1 // Copyright 2013 The ChromiumOS Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <map> 6 #include <set> 7 8 #include <gtest/gtest.h> // for FRIEND_TEST 9 10 #include "include/filter_interpreter.h" 11 #include "include/finger_metrics.h" 12 #include "include/gestures.h" 13 #include "include/prop_registry.h" 14 #include "include/tracer.h" 15 16 #ifndef GESTURES_FINGER_MERGE_FILTER_INTERPRETER_H_ 17 #define GESTURES_FINGER_MERGE_FILTER_INTERPRETER_H_ 18 19 namespace gestures { 20 21 // This interpreter mainly detects finger merging and mark the merging 22 // finger(s) with a new flag GESTURE_FINGER_MERGE. The flag can be used 23 // in immediateinterpreter to suppress cursor jumps/moves caused by the 24 // merging/merged finger(s). 25 26 class FingerMergeFilterInterpreter : public FilterInterpreter { 27 FRIEND_TEST(FingerMergeFilterInterpreterTest, SimpleTest); 28 29 public: 30 FingerMergeFilterInterpreter(PropRegistry* prop_reg, Interpreter* next, 31 Tracer* tracer); ~FingerMergeFilterInterpreter()32 virtual ~FingerMergeFilterInterpreter() {} 33 34 protected: 35 virtual void SyncInterpretImpl(HardwareState& hwstate, stime_t* timeout); 36 37 private: 38 // Detects finger merge and appends GESTURE_FINGER_MERGE flag for a merged 39 // finger or close fingers 40 void UpdateFingerMergeState(const HardwareState& hwstate); 41 42 bool IsSuspiciousAngle(const FingerState& fs) const; 43 44 struct Start { 45 float position_x; 46 float position_y; 47 stime_t start_time; 48 bool operator==(const Start& that) const { 49 return position_x == that.position_x && 50 position_y == that.position_y && 51 start_time == that.start_time; 52 } 53 bool operator!=(const Start& that) const { 54 return !(*this == that); 55 } 56 }; 57 58 // Info about each contact's initial state 59 std::map<short, Start> start_info_; 60 61 std::set<short> merge_tracking_ids_; 62 63 // Fingers that should never merge, as we've determined they aren't a merge 64 std::set<short> never_merge_ids_; 65 66 std::map<short, float> prev_x_displacement_; 67 std::map<short, float> prev2_x_displacement_; 68 69 // Flag to turn on/off the finger merge filter 70 BoolProperty finger_merge_filter_enable_; 71 72 // Distance threshold for close fingers 73 DoubleProperty merge_distance_threshold_; 74 75 // Maximum pressure value of a merged finger candidate 76 DoubleProperty max_pressure_threshold_; 77 78 // Min pressure of a merged finger candidate 79 DoubleProperty min_pressure_threshold_; 80 81 // Minimum touch major of a merged finger candidate 82 DoubleProperty min_major_threshold_; 83 84 // More criteria for filtering out false positives: 85 // The touch major of a merged finger could be merged_major_pressure_ratio_ 86 // times of its pressure value at least or a merged finger could have a 87 // very high touch major 88 DoubleProperty merged_major_pressure_ratio_; 89 DoubleProperty merged_major_threshold_; 90 91 // We require that when a finger has displaced in the X direction more than 92 // x_jump_min_displacement_, the next frame it must be at 93 // x_jump_max_displacement_, else it's not considered a merged finger. 94 DoubleProperty x_jump_min_displacement_; 95 DoubleProperty x_jump_max_displacement_; 96 97 // If a contact has displaced from the start position more than 98 // suspicious_angle_min_displacement_, we require it to be at a particular 99 // angle relative to the start position. 100 DoubleProperty suspicious_angle_min_displacement_; 101 102 // If a contact exceeds any of these (movement in a direction or age), 103 // it is not marked as a merged contact. 104 DoubleProperty max_x_move_; 105 DoubleProperty max_y_move_; 106 DoubleProperty max_age_; 107 }; 108 109 } 110 111 #endif 112