// Copyright 2012 The ChromiumOS Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef GESTURES_FINGER_METRICS_H_ #define GESTURES_FINGER_METRICS_H_ #include #include #include "include/gestures.h" #include "include/prop_registry.h" namespace gestures { static const size_t kMaxFingers = 10; static const size_t kMaxGesturingFingers = 4; static const size_t kMaxTapFingers = 10; // A datastructure describing a 2D vector in the mathematical sense. struct Vector2 { Vector2() : x(0), y(0) {} Vector2(float x, float y) : x(x), y(y) {} Vector2(const Vector2& other) : x(other.x), y(other.y) {} explicit Vector2(const FingerState& state) : x(state.position_x), y(state.position_y) {} Vector2 Sub(const Vector2& other) { return Vector2(x - other.x, y - other.y); } Vector2 Add(const Vector2& other) { return Vector2(x + other.x, y + other.y); } float MagSq() const { return x * x + y * y; } float Mag() const { return sqrtf(MagSq()); } bool operator==(const Vector2& that) const { return x == that.x && y == that.y; } bool operator!=(const Vector2& that) const { return !(*this == that); } float x; float y; }; extern Vector2 Add(const Vector2& left, const Vector2& right); extern Vector2 Sub(const Vector2& left, const Vector2& right); extern float Dot(const Vector2& left, const Vector2& right); class MetricsProperties { public: explicit MetricsProperties(PropRegistry* prop_reg); // Maximum distance [mm] two fingers may be separated and still be eligible // for a two-finger gesture (e.g., scroll / tap / click). These define an // ellipse with horizontal and vertical axes lengths (think: radii). DoubleProperty two_finger_close_horizontal_distance_thresh; DoubleProperty two_finger_close_vertical_distance_thresh; }; // This class describes a finger and derives additional metrics that // are useful for gesture recognition. // In contrast to a FingerState an instance of this class has the // lifetime of the duration the finger touches the touchpad. This allows // metrics to be derived from the history of a finger. class FingerMetrics { public: FingerMetrics(); explicit FingerMetrics(short tracking_id); FingerMetrics(short tracking_id, stime_t timestamp); FingerMetrics(const FingerState& state, stime_t timestamp); // Update the finger metrics from a FingerState. // gesture_start: true if fingers have been added or removed during this // sync. void Update(const FingerState& state, stime_t timestamp, bool gesture_start); short tracking_id() const { return tracking_id_; } // current position Vector2 position() const { return position_; } // position delta between current and last frame Vector2 delta() const { return delta_; } // origin is the time and position where the finger first touched Vector2 origin_position() const { return origin_position_; } stime_t origin_time() const { return origin_time_; } Vector2 origin_delta() const { return Sub(position_, origin_position_); } // start is the time and postion where the fingers were located // when the last of all current fingers touched (i.e. the gesture started) Vector2 start_position() const { return start_position_; } stime_t start_time() const { return start_time_; } Vector2 start_delta() const { return Sub(position_, start_position_); } // instances with the same tracking id are considered equal. bool operator==(const FingerMetrics& other) const { return other.tracking_id() == tracking_id_; } private: short tracking_id_; Vector2 position_; Vector2 delta_; Vector2 origin_position_; Vector2 start_position_; stime_t origin_time_; stime_t start_time_; }; // The Metrics class is a container for FingerMetrics and additional // metrics that are based on the interaction of multiple fingers. // It is responsible for keeping the FingerMetrics instances updated // with the latest FingerStates. class Metrics { public: Metrics(MetricsProperties* properties); bool CloseEnoughToGesture(const Vector2& pos_a, const Vector2& pos_b) const; // A collection of FingerMetrics describing the current hardware state. // The collection is sorted to yield the oldest finger first. std::vector& fingers() { return fingers_; } // Find a FingerMetrics instance by it's tracking id. // Returns nullptr if not found. FingerMetrics* GetFinger(short tracking_id) { return const_cast( const_cast(this)->GetFinger(tracking_id)); } const FingerMetrics* GetFinger(short tracking_id) const; FingerMetrics* GetFinger(const FingerState& state); const FingerMetrics* GetFinger(const FingerState& state) const; // Update the collection of FingerMetrics using information from 'hwstate'. void Update(const HardwareState& hwstate); // Clear all finger information void Clear(); // Set the origin timestamp for a particular finger for testing purposes. // Prefer calling Update with a whole HardwareState instead. // TODO(b/307933752): remove this method once its last usage (in // TapToClickStateMachineTest::check_hwstates) is removed. void SetFingerOriginTimestampForTesting(short tracking_id, stime_t time); private: std::vector fingers_; MetricsProperties* properties_; std::unique_ptr own_properties_; }; } // namespace gestures #endif // GESTURES_FINGER_METRICS_H_