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 #ifndef GESTURES_FINGER_METRICS_H_ 6 #define GESTURES_FINGER_METRICS_H_ 7 8 #include <cmath> 9 #include <vector> 10 11 #include "include/gestures.h" 12 #include "include/prop_registry.h" 13 14 namespace gestures { 15 16 static const size_t kMaxFingers = 10; 17 static const size_t kMaxGesturingFingers = 4; 18 static const size_t kMaxTapFingers = 10; 19 20 // A datastructure describing a 2D vector in the mathematical sense. 21 struct Vector2 { Vector2Vector222 Vector2() : x(0), y(0) {} Vector2Vector223 Vector2(float x, float y) : x(x), y(y) {} Vector2Vector224 Vector2(const Vector2& other) : x(other.x), y(other.y) {} Vector2Vector225 explicit Vector2(const FingerState& state) : x(state.position_x), 26 y(state.position_y) {} 27 SubVector228 Vector2 Sub(const Vector2& other) { 29 return Vector2(x - other.x, y - other.y); 30 } 31 AddVector232 Vector2 Add(const Vector2& other) { 33 return Vector2(x + other.x, y + other.y); 34 } 35 MagSqVector236 float MagSq() const { 37 return x * x + y * y; 38 } MagVector239 float Mag() const { 40 return sqrtf(MagSq()); 41 } 42 bool operator==(const Vector2& that) const { 43 return x == that.x && y == that.y; 44 } 45 bool operator!=(const Vector2& that) const { 46 return !(*this == that); 47 } 48 49 float x; 50 float y; 51 }; 52 53 extern Vector2 Add(const Vector2& left, const Vector2& right); 54 extern Vector2 Sub(const Vector2& left, const Vector2& right); 55 extern float Dot(const Vector2& left, const Vector2& right); 56 57 class MetricsProperties { 58 public: 59 explicit MetricsProperties(PropRegistry* prop_reg); 60 61 // Maximum distance [mm] two fingers may be separated and still be eligible 62 // for a two-finger gesture (e.g., scroll / tap / click). These define an 63 // ellipse with horizontal and vertical axes lengths (think: radii). 64 DoubleProperty two_finger_close_horizontal_distance_thresh; 65 DoubleProperty two_finger_close_vertical_distance_thresh; 66 }; 67 68 // This class describes a finger and derives additional metrics that 69 // are useful for gesture recognition. 70 // In contrast to a FingerState an instance of this class has the 71 // lifetime of the duration the finger touches the touchpad. This allows 72 // metrics to be derived from the history of a finger. 73 class FingerMetrics { 74 public: 75 FingerMetrics(); 76 explicit FingerMetrics(short tracking_id); 77 FingerMetrics(short tracking_id, stime_t timestamp); 78 FingerMetrics(const FingerState& state, stime_t timestamp); 79 80 // Update the finger metrics from a FingerState. 81 // gesture_start: true if fingers have been added or removed during this 82 // sync. 83 void Update(const FingerState& state, stime_t timestamp, 84 bool gesture_start); 85 tracking_id()86 short tracking_id() const { return tracking_id_; } 87 88 // current position position()89 Vector2 position() const { return position_; } 90 91 // position delta between current and last frame delta()92 Vector2 delta() const { return delta_; } 93 94 // origin is the time and position where the finger first touched origin_position()95 Vector2 origin_position() const { return origin_position_; } origin_time()96 stime_t origin_time() const { return origin_time_; } origin_delta()97 Vector2 origin_delta() const { return Sub(position_, origin_position_); } 98 99 // start is the time and postion where the fingers were located 100 // when the last of all current fingers touched (i.e. the gesture started) start_position()101 Vector2 start_position() const { return start_position_; } start_time()102 stime_t start_time() const { return start_time_; } start_delta()103 Vector2 start_delta() const { return Sub(position_, start_position_); } 104 105 // instances with the same tracking id are considered equal. 106 bool operator==(const FingerMetrics& other) const { 107 return other.tracking_id() == tracking_id_; 108 } 109 110 private: 111 short tracking_id_; 112 Vector2 position_; 113 Vector2 delta_; 114 Vector2 origin_position_; 115 Vector2 start_position_; 116 stime_t origin_time_; 117 stime_t start_time_; 118 }; 119 120 // The Metrics class is a container for FingerMetrics and additional 121 // metrics that are based on the interaction of multiple fingers. 122 // It is responsible for keeping the FingerMetrics instances updated 123 // with the latest FingerStates. 124 class Metrics { 125 public: 126 Metrics(MetricsProperties* properties); 127 128 bool CloseEnoughToGesture(const Vector2& pos_a, 129 const Vector2& pos_b) const; 130 131 // A collection of FingerMetrics describing the current hardware state. 132 // The collection is sorted to yield the oldest finger first. fingers()133 std::vector<FingerMetrics>& fingers() { return fingers_; } 134 135 // Find a FingerMetrics instance by it's tracking id. 136 // Returns nullptr if not found. GetFinger(short tracking_id)137 FingerMetrics* GetFinger(short tracking_id) { 138 return const_cast<FingerMetrics*>( 139 const_cast<const Metrics*>(this)->GetFinger(tracking_id)); 140 } 141 const FingerMetrics* GetFinger(short tracking_id) const; 142 143 FingerMetrics* GetFinger(const FingerState& state); 144 const FingerMetrics* GetFinger(const FingerState& state) const; 145 146 // Update the collection of FingerMetrics using information from 'hwstate'. 147 void Update(const HardwareState& hwstate); 148 149 // Clear all finger information 150 void Clear(); 151 152 // Set the origin timestamp for a particular finger for testing purposes. 153 // Prefer calling Update with a whole HardwareState instead. 154 // TODO(b/307933752): remove this method once its last usage (in 155 // TapToClickStateMachineTest::check_hwstates) is removed. 156 void SetFingerOriginTimestampForTesting(short tracking_id, stime_t time); 157 158 private: 159 std::vector<FingerMetrics> fingers_; 160 161 MetricsProperties* properties_; 162 std::unique_ptr<MetricsProperties> own_properties_; 163 }; 164 165 } // namespace gestures 166 167 #endif // GESTURES_FINGER_METRICS_H_ 168