1 // Copyright 2012 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 <set> 6 #include <gtest/gtest.h> // for FRIEND_TEST 7 8 #include "include/filter_interpreter.h" 9 #include "include/finger_metrics.h" 10 #include "include/gestures.h" 11 #include "include/prop_registry.h" 12 #include "include/tracer.h" 13 14 #ifndef GESTURES_SPLIT_CORRECTING_FILTER_INTERPRETER_H_ 15 #define GESTURES_SPLIT_CORRECTING_FILTER_INTERPRETER_H_ 16 17 namespace gestures { 18 19 // This interepreter corrects problems that can occur with some touchpads. 20 // Currently, it corrects for the case where a large finger can erroneously 21 // "split" into two contacts. It works around this by looking for a contact 22 // to seemingly split into two, and fakes that the split didn't occur. 23 24 // This struct tracks an unmerged contact. By default the output and input 25 // IDs will be the same value, however after merge cycles, that may no longer 26 // be the case. 27 struct UnmergedContact { UnmergedContactUnmergedContact28 UnmergedContact() : input_id(-1) {} ValidUnmergedContact29 bool Valid() const { return input_id != -1; } InvalidateUnmergedContact30 void Invalidate() { input_id = -1; } 31 short input_id; 32 short output_id; 33 float position_x; 34 float position_y; 35 }; 36 37 // Tracks two input contacts that are being combined into one output contact 38 // because we believe they are actually two parts of the same real contact. 39 struct MergedContact { MergedContactMergedContact40 MergedContact() : output_id(-1) {} ValidMergedContact41 bool Valid() const { return output_id != -1; } InvalidateMergedContact42 void Invalidate() { output_id = -1; } 43 FingerState input_fingers[2]; // initial state 44 short output_id; 45 }; 46 47 class SplitCorrectingFilterInterpreter : public FilterInterpreter { 48 FRIEND_TEST(SplitCorrectingFilterInterpreterTest, DistFromPointToLineTest); 49 public: 50 // Takes ownership of |next|: 51 SplitCorrectingFilterInterpreter(PropRegistry* prop_reg, Interpreter* next, 52 Tracer* tracer); ~SplitCorrectingFilterInterpreter()53 virtual ~SplitCorrectingFilterInterpreter() {} 54 Enable()55 void Enable() { enabled_.val_ = 1; } 56 57 protected: 58 virtual void SyncInterpretImpl(HardwareState& hwstate, stime_t* timeout); 59 60 private: 61 void RemoveMissingUnmergedContacts(const HardwareState& hwstate); 62 void MergeFingers(const HardwareState& hwstate); 63 void UnmergeFingers(const HardwareState& hwstate); 64 void UpdateUnmergedLocations(const HardwareState& hwstate); 65 66 // Given a line that goes through (x0, y0) and (x1, y1), and a separate 67 // point, compute the square of the smallest distance from the point to the 68 // line. 69 static float DistSqFromPointToLine(float line_x_0, float line_y_0, 70 float line_x_1, float line_y_1, 71 float point_x, float point_y); 72 73 // Based on merged_ and unmeged_, updates the current hwstate. 74 void UpdateHwState(HardwareState& hwstate) const; 75 // Tests to see if new_contact, when paired w/ existing_contact 76 // are a good match for the unmerged contact, merge_recipient. 77 // new_contact is the current state of the finger in merge_recipient. 78 // Returns < 0 if this is not a good match, or an error value if it's good. 79 // The smaller the error, the better. 80 float AreMergePair(const FingerState& existing_contact, 81 const FingerState& new_contact, 82 const UnmergedContact& merge_recipient) const; 83 84 void AppendMergedContact(const FingerState& input_a, 85 const FingerState& input_b, 86 short output_id); 87 void AppendUnmergedContact(const FingerState& fs, short output_id); 88 89 const UnmergedContact* FindUnmerged(short input_id) const; 90 const MergedContact* FindMerged(short input_id) const; 91 92 static void JoinFingerState(FingerState* in_out, 93 const FingerState& newfinger); 94 static void RemoveFingerStateFromHardwareState(HardwareState& hs, 95 FingerState* fs); 96 97 // Sets last_tracking_ids_ to the ids in the passed hwstate. 98 void SetLastTrackingIds(const HardwareState& hwstate); 99 100 // Dumps internal state and hwstate. 101 void Dump(const HardwareState& hwstate) const; 102 103 std::set<short> last_tracking_ids_; 104 UnmergedContact unmerged_[kMaxFingers]; 105 MergedContact merged_[kMaxFingers / 2 + 1]; 106 107 // We only enable on non-T5R2 pads 108 BoolProperty enabled_; 109 110 // Contacts must be separated by less than this amount to be considered for 111 // merging. 112 DoubleProperty merge_max_separation_; 113 // The most [mm] that a finger in a merged contact can move before we break 114 // out and unmerge. 115 DoubleProperty merge_max_movement_; 116 // When merging, we expect that the two fingers that appear are on either 117 // side of the old merged contact from last frame, and that the angle from 118 // the old merged contact, to the new finger with the same id, to the new 119 // finger with a new ID has a max angle. This angle then computes the max 120 // ratio of: (distance from new ID point to line defined by old and new 121 // contacts that have the same ID) / (length from new ID point to old ID point 122 // in newer frame). 123 DoubleProperty merge_max_ratio_; 124 }; 125 126 } // namespace gestures 127 128 #endif // GESTURES_SPLIT_CORRECTING_FILTER_INTERPRETER_H_ 129