xref: /aosp_15_r20/external/libchrome-gestures/include/finger_metrics.h (revision aed3e5085e770be5b69ce25295ecf6ddf906af95)
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