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