• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <map>
6 #include <set>
7 
8 #include <gtest/gtest.h>  // for FRIEND_TEST
9 
10 #include "include/finger_metrics.h"
11 #include "include/gestures.h"
12 #include "include/interpreter.h"
13 #include "include/macros.h"
14 #include "include/prop_registry.h"
15 #include "include/tracer.h"
16 
17 #ifndef GESTURES_IMMEDIATE_INTERPRETER_H_
18 #define GESTURES_IMMEDIATE_INTERPRETER_H_
19 
20 namespace gestures {
21 
22 typedef std::set<short> FingerMap;
23 
24 // This interpreter keeps some memory of the past and, for each incoming
25 // frame of hardware state, immediately determines the gestures to the best
26 // of its abilities.
27 
28 class ImmediateInterpreter;
29 class MultitouchMouseInterpreter;
30 
31 class TapRecord {
32   FRIEND_TEST(ImmediateInterpreterTest, TapRecordTest);
33  public:
TapRecord(const ImmediateInterpreter * immediate_interpreter)34   explicit TapRecord(const ImmediateInterpreter* immediate_interpreter)
35       : immediate_interpreter_(immediate_interpreter),
36         t5r2_(false),
37         t5r2_touched_size_(0),
38         t5r2_released_size_(0),
39         fingers_below_max_age_(true) {}
40   void Update(const HardwareState& hwstate,
41               const HardwareState& prev_hwstate,
42               const std::set<short>& added,
43               const std::set<short>& removed,
44               const std::set<short>& dead);
45   void Clear();
46 
47   // if any gesturing fingers are moving
48   bool Moving(const HardwareState& hwstate, const float dist_max) const;
49   bool Motionless(const HardwareState& hwstate,
50                   const HardwareState& prev_hwstate,
51                   const float max_speed) const;
52 
53   bool TapBegan() const;  // if a tap has begun
54   bool TapComplete() const;  // is a completed tap
55   // return GESTURES_BUTTON_* value or 0, if tap was too light
56   int TapType() const;
57   // If any contact has met the minimum pressure threshold
58   bool MinTapPressureMet() const;
59   bool FingersBelowMaxAge() const;
60  private:
61   void NoteTouch(short the_id, const FingerState& fs);  // Adds to touched_
62   void NoteRelease(short the_id);  // Adds to released_
63   void Remove(short the_id);  // Removes from touched_ and released_
64 
65   float CotapMinPressure() const;
66 
67   std::map<short, FingerState> touched_;
68   std::set<short> released_;
69   // At least one finger must meet the minimum pressure requirement during a
70   // tap. This set contains the fingers that have.
71   std::set<short> min_tap_pressure_met_;
72   // All fingers must meet the cotap pressure, which is half of the min tap
73   // pressure.
74   std::set<short> min_cotap_pressure_met_;
75   // Used to fetch properties
76   const ImmediateInterpreter* immediate_interpreter_;
77   // T5R2: For these pads, we try to track individual IDs, but if we get an
78   // input event with insufficient data, we switch into T5R2 mode, where we
79   // just track the number of contacts. We still maintain the non-T5R2 records
80   // which are useful for tracking if contacts move a lot.
81   // The following are for T5R2 mode:
82   bool t5r2_;  // if set, use T5R2 hacks
83   unsigned short t5r2_touched_size_;  // number of contacts that have arrived
84   unsigned short t5r2_released_size_;  // number of contacts that have left
85   // Whether all the fingers have age less than "Tap Maximum Finger Age".
86   bool fingers_below_max_age_;
87 };
88 
89 struct ScrollEvent {
90   float dx, dy, dt;
91   static ScrollEvent Add(const ScrollEvent& evt_a, const ScrollEvent& evt_b);
92 };
93 class ScrollEventBuffer {
94  public:
ScrollEventBuffer(size_t size)95   explicit ScrollEventBuffer(size_t size)
96       : buf_(new ScrollEvent[size]), max_size_(size), size_(0), head_(0) {}
97   void Insert(float dx, float dy, float dt);
98   void Clear();
Size()99   size_t Size() const { return size_; }
100   // 0 is newest, 1 is next newest, ..., size_ - 1 is oldest.
101   const ScrollEvent& Get(size_t offset) const;
102   // For efficiency, returns dist_sq and time of the last num_events events in
103   // the buffer, from which speed can be computed.
104   void GetSpeedSq(size_t num_events, float* dist_sq, float* dt) const;
105 
106  private:
107   std::unique_ptr<ScrollEvent[]> buf_;
108   size_t max_size_;
109   size_t size_;
110   size_t head_;
111   DISALLOW_COPY_AND_ASSIGN(ScrollEventBuffer);
112 };
113 
114 // Circular buffer for storing a rolling backlog of events for analysis
115 // as well as accessor functions for using the buffer's contents.
116 class HardwareStateBuffer {
117  public:
118   explicit HardwareStateBuffer(size_t size);
119   ~HardwareStateBuffer();
120 
Size()121   size_t Size() const { return size_; }
122 
123   void Reset(size_t max_finger_cnt);
124 
125   // Does a deep copy of state into states_
126   void PushState(const HardwareState& state);
127   // Pops most recently pushed state
128   void PopState();
129 
Get(size_t idx)130   const HardwareState* Get(size_t idx) const {
131     return &states_[(idx + newest_index_) % size_];
132   }
133 
Get(size_t idx)134   HardwareState* Get(size_t idx) {
135     return const_cast<HardwareState*>(
136         const_cast<const HardwareStateBuffer*>(this)->Get(idx));
137   }
138 
139  private:
140   std::unique_ptr<HardwareState[]> states_;
141   size_t newest_index_;
142   size_t size_;
143   size_t max_finger_cnt_;
144   DISALLOW_COPY_AND_ASSIGN(HardwareStateBuffer);
145 };
146 
147 struct Point {
PointPoint148   Point() : x_(0.0), y_(0.0) {}
PointPoint149   Point(float x, float y) : x_(x), y_(y) {}
150   bool operator==(const Point& that) const {
151     return x_ == that.x_ && y_ == that.y_;
152   }
153   bool operator!=(const Point& that) const { return !((*this) == that); }
154   float x_, y_;
155 };
156 
157 // Helper class for compute scroll and fling.
158 class ScrollManager {
159   FRIEND_TEST(ImmediateInterpreterTest, FlingDepthTest);
160   FRIEND_TEST(ImmediateInterpreterTest, ScrollManagerTest);
161   FRIEND_TEST(MultitouchMouseInterpreterTest, SimpleTest);
162 
163  public:
164   explicit ScrollManager(PropRegistry* prop_reg);
~ScrollManager()165   ~ScrollManager() {}
166 
167   // Returns true if a finger's movement should be suppressed based on
168   // max_stationary_move_* properties below.
169   bool SuppressStationaryFingerMovement(const FingerState& fs,
170                                         const FingerState& prev,
171                                         stime_t dt);
172 
173   // Looking at this finger and the previous ones within a small window
174   // and returns true iff this finger is stationary and the pressure is
175   // changing so quickly that we expect it's arriving on the pad or
176   // departing.
177   bool StationaryFingerPressureChangingSignificantly(
178       const HardwareStateBuffer& state_buffer,
179       const FingerState& current) const;
180 
181   // Compute a scroll and fill result.  Return false when something goes wrong.
182   bool FillResultScroll(const HardwareStateBuffer& state_buffer,
183                      const FingerMap& prev_gs_fingers,
184                      const FingerMap& gs_fingers,
185                      GestureType prev_gesture_type,
186                      const Gesture& prev_result,
187                      Gesture* result,
188                      ScrollEventBuffer* scroll_buffer);
189 
190   // Compute a fling and fill result.
191   void FillResultFling(const HardwareStateBuffer& state_buffer,
192                     const ScrollEventBuffer& scroll_buffer,
193                     Gesture* result);
194 
195   // Update ScrollEventBuffer when the current gesture type is not scroll.
196   void UpdateScrollEventBuffer(GestureType gesture_type,
197                                ScrollEventBuffer* scroll_buffer) const;
198 
ResetSameFingerState()199   void ResetSameFingerState() {
200     stationary_start_positions_.clear();
201   }
202 
203   // Set to true when a scroll or move is blocked b/c of high pressure
204   // change or small movement. Cleared when a normal scroll or move
205   // goes through.
206   bool prev_result_suppress_finger_movement_;
207 
208  private:
209   // Set to true when generating a non-zero scroll gesture. Reset to false
210   // when a fling is generated.
211   bool did_generate_scroll_;
212 
213   // Returns the number of most recent event events in the scroll_buffer_ that
214   // should be considered for fling. If it returns 0, there should be no fling.
215   size_t ScrollEventsForFlingCount(const ScrollEventBuffer& scroll_buffer)
216     const;
217 
218   // Returns a ScrollEvent that contains velocity estimates for x and y based
219   // on an N-point linear regression.
220   void RegressScrollVelocity(const ScrollEventBuffer& scroll_buffer,
221                              int count, ScrollEvent* out) const;
222 
223   std::map<short, Point> stationary_start_positions_;
224 
225   // In addition to checking for large pressure changes when moving
226   // slow, we can suppress all motion under a certain speed, unless
227   // the total distance exceeds a threshold.
228   DoubleProperty max_stationary_move_speed_;
229   DoubleProperty max_stationary_move_speed_hysteresis_;
230   DoubleProperty max_stationary_move_suppress_distance_;
231 
232   // A finger must change in pressure by less than this per second to trigger
233   // motion.
234   DoubleProperty max_pressure_change_;
235   // If a contact crosses max_pressure_change_, motion continues to be blocked
236   // until the pressure change per second goes below
237   // max_pressure_change_hysteresis_.
238   DoubleProperty max_pressure_change_hysteresis_;
239   // Try to look over a period up to this length of time when looking for large
240   // pressure change.
241   DoubleProperty max_pressure_change_duration_;
242   // A fast-swiping finger may generate rapidly changing pressure and we should
243   // not report a high pressure change in this case.  This is the maximum
244   // speed [mm/s] for which we may consider a finger stationary.
245   DoubleProperty max_stationary_speed_;
246 
247   // y| V  /
248   //  |   /  D   _-
249   //  |  /    _-'
250   //  | /  _-'
251   //  |/_-'   H
252   //  |'____________x
253   // The above quadrant of a cartesian plane shows the angles where we snap
254   // scrolling to vertical or horizontal. Very Vertical or Horizontal scrolls
255   // are snapped, while Diagonal scrolls are not. The two properties below
256   // are the slopes for the two lines.
257   DoubleProperty vertical_scroll_snap_slope_;
258   DoubleProperty horizontal_scroll_snap_slope_;
259 
260   // Depth of recent scroll event buffer used to compute Fling velocity.
261   // For most systems this will be 3.  However, for systems that use 2x
262   // interpolation, this should be 6, to ensure that the scroll events for 3
263   // actual hardware states are used.
264   IntProperty fling_buffer_depth_;
265   // Some platforms report fingers as perfectly stationary for a few frames
266   // before they report lift off. We don't include these non-movement
267   // frames in the scroll buffer, because that would suppress fling.
268   // Platforms with this property should set
269   // fling_buffer_suppress_zero_length_scrolls_ to non-zero.
270   BoolProperty fling_buffer_suppress_zero_length_scrolls_;
271   // When computing a fling, if the fling buffer has an average speed under
272   // this threshold, we do not perform a fling. Units are mm/sec.
273   DoubleProperty fling_buffer_min_avg_speed_;
274 };
275 
276 // Helper class for computing the button type of multi-finger clicks.
277 class FingerButtonClick {
278  public:
279   // Describes the three classes of fingers we deal with while determining
280   // the type of physical button clicks.
281   enum FingerClickStatus {
282     // A 'recent' finger has recently touched down on the touchpad.
283     STATUS_RECENT,
284     // A 'cold' finger has already been on the touchpad for a while,
285     // but has not been moved.
286     STATUS_COLD,
287     // A 'hot' finger has been moved since it touched down.
288     STATUS_HOT
289   };
290 
291   explicit FingerButtonClick(const ImmediateInterpreter* interpreter);
~FingerButtonClick()292   ~FingerButtonClick() {};
293 
294   // Processes the HardwareState finger data. Categorizes fingers into one of
295   // the FingerClickStatus and sort them according to their original timestamps.
296   // Returns true if further analysis is needed. Returns false in trivial cases
297   // where one is safe to use the HardwareState button data directly.
298   bool Update(const HardwareState& hwstate, stime_t button_down_time);
299 
300   // Returns which button type corresponds to which touch count (e.g. 2f = right
301   // click, 3f = middle click).
302   int GetButtonTypeForTouchCount(int touch_count) const;
303 
304   // All these following button type evaluation functions are guaranteed to
305   // return a button but the caller must ensure that the requirements are met.
306   //
307   // Evaluates the button type for the 2f case. Needs at least 2 fingers.
308   int EvaluateTwoFingerButtonType();
309 
310   // Evaluates the button type for >=3f cases. Needs at least 3 fingers.
311   int EvaluateThreeOrMoreFingerButtonType();
312 
313   // Evaluates the button type using finger locations.
314   int EvaluateButtonTypeUsingFigureLocation();
315 
num_fingers()316   int num_fingers() const { return num_fingers_; }
num_recent()317   int num_recent() const { return num_recent_; }
num_cold()318   int num_cold() const { return num_cold_; }
num_hot()319   int num_hot() const { return num_hot_; }
320 
321  private:
322   // Used to fetch properties and other finger status.
323   const ImmediateInterpreter* interpreter_;
324 
325   // Fingers that we are considering for determining the button type.
326   FingerState const * fingers_[4];
327 
328   // FingerClickStatus of each finger.
329   FingerClickStatus fingers_status_[4];
330 
331   // Number of fingers we are considering.
332   int num_fingers_;
333 
334   // Number of fingers of each kind.
335   int num_recent_;
336   int num_cold_;
337   int num_hot_;
338 };
339 
340 class ImmediateInterpreter : public Interpreter, public PropertyDelegate {
341   FRIEND_TEST(ImmediateInterpreterTest, AmbiguousPalmCoScrollTest);
342   FRIEND_TEST(ImmediateInterpreterTest, AvoidAccidentalPinchTest);
343   FRIEND_TEST(ImmediateInterpreterTest, ChangeTimeoutTest);
344   FRIEND_TEST(ImmediateInterpreterTest, ClickTest);
345   FRIEND_TEST(ImmediateInterpreterTest, FlingDepthTest);
346   FRIEND_TEST(ImmediateInterpreterTest, GetGesturingFingersTest);
347   FRIEND_TEST(ImmediateInterpreterTest, PalmAtEdgeTest);
348   FRIEND_TEST(ImmediateInterpreterTest, PalmReevaluateTest);
349   FRIEND_TEST(ImmediateInterpreterTest, PalmTest);
350   FRIEND_TEST(ImmediateInterpreterTest, PinchTests);
351   FRIEND_TEST(ImmediateInterpreterTest, ScrollResetTapTest);
352   FRIEND_TEST(ImmediateInterpreterTest, ScrollThenFalseTapTest);
353   FRIEND_TEST(ImmediateInterpreterTest, SemiMtActiveAreaTest);
354   FRIEND_TEST(ImmediateInterpreterTest, SemiMtNoPinchTest);
355   FRIEND_TEST(ImmediateInterpreterTest, StationaryPalmTest);
356   FRIEND_TEST(ImmediateInterpreterTest, SwipeTest);
357   FRIEND_TEST(ImmediateInterpreterTest, TapRecordTest);
358   FRIEND_TEST(ImmediateInterpreterTest, TapToClickEnableTest);
359   FRIEND_TEST(ImmediateInterpreterTest, TapToClickKeyboardTest);
360   FRIEND_TEST(ImmediateInterpreterTest, TapToClickLowPressureBeginOrEndTest);
361   FRIEND_TEST(ImmediateInterpreterTest, TapToClickStateMachineTest);
362   FRIEND_TEST(ImmediateInterpreterTest, ThumbRetainReevaluateTest);
363   FRIEND_TEST(ImmediateInterpreterTest, ThumbRetainTest);
364   FRIEND_TEST(ImmediateInterpreterTest, WarpedFingersTappingTest);
365   FRIEND_TEST(ImmediateInterpreterTest, ZeroClickInitializationTest);
366   friend class TapRecord;
367   friend class FingerButtonClick;
368 
369  public:
370   enum TapToClickState {
371     kTtcIdle,
372     kTtcFirstTapBegan,
373     kTtcTapComplete,
374     kTtcSubsequentTapBegan,
375     kTtcDrag,
376     kTtcDragRelease,
377     kTtcDragRetouch
378   };
379 
380   ImmediateInterpreter(PropRegistry* prop_reg, Tracer* tracer);
~ImmediateInterpreter()381   virtual ~ImmediateInterpreter() {}
382 
383  protected:
384   virtual void SyncInterpretImpl(HardwareState* hwstate, stime_t* timeout);
385 
386   virtual void HandleTimerImpl(stime_t now, stime_t* timeout);
387 
388   virtual void Initialize(const HardwareProperties* hwprops,
389                           Metrics* metrics, MetricsProperties* mprops,
390                           GestureConsumer* consumer);
391 
392  public:
tap_to_click_state()393   TapToClickState tap_to_click_state() const { return tap_to_click_state_; }
394 
tap_min_pressure()395   float tap_min_pressure() const { return tap_min_pressure_.val_; }
396 
tap_max_finger_age()397   stime_t tap_max_finger_age() const { return tap_max_finger_age_.val_; }
398 
finger_origin_timestamp(short finger_id)399   stime_t finger_origin_timestamp(short finger_id) const {
400     return origin_timestamps_.at(finger_id);
401   }
402 
403  private:
404   // Reset the member variables corresponding to same-finger state and
405   // updates changed_time_ to |now|.
406   void ResetSameFingersState(const HardwareState& hwstate);
407 
408   // Reset the member variables which track old timestamps.  Called when the
409   // clock changes backward.
410   void ResetTime();
411 
412   // Sets pointing_.
413   void UpdatePointingFingers(const HardwareState& hwstate);
414 
415   // Gets the hardware button type (RIGHT, LEFT) based on the
416   // first finger's position.
417   int GetButtonTypeFromPosition(const HardwareState& hwstate);
418 
419   // Returns the square of the distance that this contact has travelled since
420   // fingers changed (origin=false) or since they touched down (origin=true).
421   // If permit_warp is true, we ignore the GESTURES_FINGER_WARP_X/Y flags
422   // unless the more strict GESTURES_FINGER_WARP_TELEPORTATION flag is set.
423   float DistanceTravelledSq(const FingerState& fs,
424                             bool origin,
425                             bool permit_warp = false) const;
426 
427   // Returns the vector that this finger has travelled since
428   // fingers changed (origin=false) or since they touched down (origin=true).
429   // If permit_warp is true, we ignore the GESTURES_FINGER_WARP_X/Y flags
430   // unless the more strict GESTURES_FINGER_WARP_TELEPORTATION flag is set.
431   Point FingerTraveledVector(const FingerState& fs,
432                              bool origin,
433                              bool permit_warp = false) const;
434 
435   // Returns true if there is a potential for pinch zoom but still it's too
436   // early to decide. In this case, there shouldn't be any move or scroll
437   // event.
438   bool EarlyZoomPotential(const HardwareState& hwstate) const;
439 
440   // Returns true if there are two fingers moving in opposite directions.
441   // Moreover, this function makes sure that fingers moving direction hasn't
442   // changed recently.
443   bool ZoomFingersAreConsistent(const HardwareStateBuffer& state_buffer) const;
444 
445   // Returns true if the given finger is moving sufficiently upwards to be
446   // considered the bottom finger of an inward pinch.
447   bool InwardPinch(const HardwareStateBuffer& state_buffer,
448                    const FingerState& fs) const;
449 
450   // Returns Cos(A) where A is the angle between the move vector of two fingers
451   float FingersAngle(const FingerState* before1, const FingerState* before2,
452                      const FingerState* curr1, const FingerState* curr2) const;
453 
454   // Returns true if fingers are not moving in opposite directions.
455   bool ScrollAngle(const FingerState& finger1, const FingerState& finger2);
456 
457   // Returns the square of distance between two fingers.
458   // Returns -1 if not exactly two fingers are present.
459   float TwoFingerDistanceSq(const HardwareState& hwstate) const;
460 
461   // Returns the square of distance between two given fingers.
462   // Returns -1 if fingers don't present in the hwstate.
463   float TwoSpecificFingerDistanceSq(const HardwareState& hwstate,
464                                     const FingerMap& fingers) const;
465 
466   // Updates thumb_ below.
467   void UpdateThumbState(const HardwareState& hwstate);
468 
469   // Returns true iff the keyboard has been recently used.
470   bool KeyboardRecentlyUsed(stime_t now) const;
471 
472   // Updates non_gs_fingers based on a new hardware state. Removes missing and
473   // newly moving fingers from non_gs_fingers.
474   void UpdateNonGsFingers(const HardwareState& hwstate);
475 
476   // Gets the finger or fingers we should consider for gestures.
477   // Currently, it fetches the (up to) two fingers closest to the keyboard
478   // that are not palms. There is one exception: for t5r2 pads with > 2
479   // fingers present, we return all fingers.
480   FingerMap GetGesturingFingers(const HardwareState& hwstate) const;
481 
482   // Updates current_gesture_type_ based on passed-in hwstate and
483   // considering the passed in fingers as gesturing.
484   // Returns the finger(s) that are performing the gesture in
485   // active_gs_fingers.
486   void UpdateCurrentGestureType(const HardwareState& hwstate,
487                                 const FingerMap& gs_fingers,
488                                 FingerMap* active_gs_fingers);
489 
490   // Checks if gesture_type is one of kGestureTypeScroll, kGestureTypeSwipe, or
491   // kGestureTypeFourFingerSwipe
492   bool IsScrollOrSwipe(const GestureType gesture_type);
493 
494   // Checks if a scroll or swipe has ended, and replaces current_gesture_type_
495   // with the appropriate finger lift gesture.
496   void GenerateFingerLiftGesture();
497 
498   // Sorts the fingers referred to in finger_ids (whose details are in hwstate)
499   // according to prodimity and places the sorted range into out_sorted_ids.
500   // The sort first finds the two closes points and includes them first.
501   // Then, it finds the point closest to any included point, repeating until
502   // all points are included.
503   static void SortFingersByProximity(
504       const FingerMap& finger_ids,
505       const HardwareState& hwstate,
506       vector<short, kMaxGesturingFingers>* out_sorted_ids);
507 
508   // If the finger is likely to be a palm and that its contact size/pressure
509   // is diminishing/increasing, we suppress the cursor movement. A real
510   // intentional 1f cursor move near the touchpad boundary usually has a
511   // stationary finger contact size/pressure.
512   bool PalmIsArrivingOrDeparting(const FingerState& finger) const;
513 
514   // Check if a finger is close to any known thumb. Can be used to detect some
515   // thumb split cases.
516   bool IsTooCloseToThumb(const FingerState& finger) const;
517 
518   // If the fingers are near each other in location and pressure and might
519   // to be part of a 2-finger action, returns true. The function can also
520   // be used to check whether the gesture is a left or a right button click
521   // with the parameter checking_button_type.
522   bool TwoFingersGesturing(const FingerState& finger1,
523                            const FingerState& finger2,
524                            bool check_button_type) const;
525 
526   // Given that TwoFingersGesturing returns true for 2 fingers,
527   // This will further look to see if it's really 2 finger scroll or not.
528   // Returns the current state (move or scroll) or kGestureTypeNull if
529   // unknown.
530   GestureType GetTwoFingerGestureType(const FingerState& finger1,
531                                       const FingerState& finger2);
532 
533   // Check for a pinch gesture and update the state machine for detection.
534   // If a pinch was detected it will return true. False otherwise.
535   // To reset the state machine call with reset=true
536   bool UpdatePinchState(const HardwareState& hwstate, bool reset,
537                         const FingerMap& gs_fingers);
538 
539   // Returns a gesture assuming that at least one of the fingers performing
540   // current_gesture_type has left
541   GestureType GetFingerLiftGesture(GestureType current_gesture_type);
542 
543   // Returns the current multi-finger gesture, or kGestureTypeNull if no gesture
544   // should be produced. num_fingers can be 3 or 4.
545   GestureType GetMultiFingerGestureType(const FingerState* const fingers[],
546                                         const int num_fingers);
547 
548   const char* TapToClickStateName(TapToClickState state);
549 
550   stime_t TimeoutForTtcState(TapToClickState state);
551 
552   void SetTapToClickState(TapToClickState state,
553                           stime_t now);
554 
555   void UpdateTapGesture(const HardwareState* hwstate,
556                         const FingerMap& gs_fingers,
557                         const bool same_fingers,
558                         stime_t now,
559                         stime_t* timeout);
560 
561   void UpdateTapState(const HardwareState* hwstate,
562                       const FingerMap& gs_fingers,
563                       const bool same_fingers,
564                       stime_t now,
565                       unsigned* buttons_down,
566                       unsigned* buttons_up,
567                       stime_t* timeout);
568 
569   // Returns true iff the given finger is too close to any other finger to
570   // realistically be doing a tap gesture.
571   bool FingerTooCloseToTap(const HardwareState& hwstate, const FingerState& fs);
572 
573   // Returns true iff finger is in the bottom, dampened zone of the pad
574   bool FingerInDampenedZone(const FingerState& finger) const;
575 
576   // Called when fingers have changed to fill start_positions_
577   // and origin_positions_.
578   void FillStartPositions(const HardwareState& hwstate);
579 
580   // Fills the origin_* member variables.
581   void FillOriginInfo(const HardwareState& hwstate);
582 
583   // Fills moving_ with any moving fingers.
584   FingerMap UpdateMovingFingers(const HardwareState& hwstate);
585 
586   // Update started_moving_time_ to now if any gesturing fingers started moving.
587   void UpdateStartedMovingTime(stime_t now,
588                                const FingerMap& gs_fingers,
589                                const FingerMap& newly_moving_fingers);
590 
591   // Updates the internal button state based on the passed in |hwstate|.
592   // Can optionally request a timeout by setting *timeout.
593   void UpdateButtons(const HardwareState& hwstate, stime_t* timeout);
594 
595   // Called when the timeout is fired for UpdateButtons.
596   void UpdateButtonsTimeout(stime_t now);
597 
598   // By looking at |hwstate| and internal state, determins if a button down
599   // at this time would correspond to a left/middle/right click. Returns
600   // GESTURES_BUTTON_{LEFT,MIDDLE,RIGHT}.
601   int EvaluateButtonType(const HardwareState& hwstate,
602                          stime_t button_down_time);
603 
604   // Precondition: current_mode_ is set to the mode based on |hwstate|.
605   // Computes the resulting gesture, storing it in result_.
606   void FillResultGesture(const HardwareState& hwstate,
607                          const FingerMap& fingers);
608 
609   virtual void IntWasWritten(IntProperty* prop);
610 
611   // Fingers which are prohibited from ever tapping.
612   std::set<short> tap_dead_fingers_;
613 
614   // Active gs fingers are the subset of gs_fingers that are actually performing
615   // a gesture
616   FingerMap prev_active_gs_fingers_;
617 
618   // Fingers that would be considered as possibly gesturing, but others fingers
619   // did the gesturing.
620   FingerMap non_gs_fingers_;
621 
622   FingerMap prev_gs_fingers_;
623   FingerMap prev_tap_gs_fingers_;
624   HardwareProperties hw_props_;
625   Gesture result_;
626   Gesture prev_result_;
627 
628   // Time when a contact arrived. Persists even when fingers change.
629   std::map<short, stime_t> origin_timestamps_;
630 
631   // Total distance travelled by a finger since the origin_timestamps_.
632   std::map<short, float> distance_walked_;
633 
634   // Button data
635   // Which button we are going to send/have sent for the physical btn press
636   int button_type_;  // left, middle, or right
637 
638   FingerButtonClick finger_button_click_;
639 
640   // If we have sent button down for the currently down button
641   bool sent_button_down_;
642 
643   // If we haven't sent a button down by this time, send one
644   stime_t button_down_timeout_;
645 
646   // When fingers change, we record the time
647   stime_t changed_time_;
648 
649   // When gesturing fingers move after change, we record the time.
650   stime_t started_moving_time_;
651   // Record which fingers have started moving already.
652   std::set<short> moving_;
653 
654   // When different fingers are gesturing, we record the time
655   stime_t gs_changed_time_;
656 
657   // When fingers leave, we record the time
658   stime_t finger_leave_time_;
659 
660   // When fingers change, we keep track of where they started.
661   // Map: Finger ID -> (x, y) coordinate
662   std::map<short, Point> start_positions_;
663 
664   // Keep track of finger position from when three fingers began moving in the
665   // same direction.
666   // Map: Finger ID -> (x, y) coordinate
667   std::map<short, Point> three_finger_swipe_start_positions_;
668 
669   // Keep track of finger position from when four fingers began moving in the
670   // same direction.
671   // Map: Finger ID -> (x, y) coordinate
672   std::map<short, Point> four_finger_swipe_start_positions_;
673 
674   // We keep track of where each finger started when they touched.
675   // Map: Finger ID -> (x, y) coordinate.
676   std::map<short, Point> origin_positions_;
677 
678   // tracking ids of known fingers that are not palms, nor thumbs.
679   std::set<short> pointing_;
680   // tracking ids of known non-palms. But might be thumbs.
681   std::set<short> fingers_;
682   // contacts believed to be thumbs, and when they were inserted into the map
683   std::map<short, stime_t> thumb_;
684   // Timer of the evaluation period for contacts believed to be thumbs.
685   std::map<short, stime_t> thumb_eval_timer_;
686 
687   // once a moving finger is determined lock onto this one for cursor movement.
688   short moving_finger_id_;
689 
690   // Tap-to-click
691   // The current state:
692   TapToClickState tap_to_click_state_;
693 
694   // When we entered the state:
695   stime_t tap_to_click_state_entered_;
696 
697   TapRecord tap_record_;
698 
699   // Record time when the finger showed motion (uses different motion detection
700   // than last_movement_timestamp_)
701   stime_t tap_drag_last_motion_time_;
702 
703   // True when the finger was stationary for a while during tap to drag
704   bool tap_drag_finger_was_stationary_;
705 
706   // Time when the last motion (scroll, movement) occurred
707   stime_t last_movement_timestamp_;
708 
709   bool swipe_is_vertical_;
710 
711   // If we are currently pointing, scrolling, etc.
712   GestureType current_gesture_type_;
713   // Previous value of current_gesture_type_
714   GestureType prev_gesture_type_;
715 
716   // Cache for distance between fingers at previous pinch gesture event, or
717   // start of pinch detection
718   float pinch_prev_distance_sq_;
719 
720   HardwareStateBuffer state_buffer_;
721   ScrollEventBuffer scroll_buffer_;
722 
723   FingerMetrics* finger_metrics_;
724   std::unique_ptr<FingerMetrics> test_finger_metrics_;
725 
726   // There are three pinch guess states before locking:
727   //   pinch_guess_start_ == -1: No definite guess made about pinch
728   //   pinch_guess_start_ > 0:
729   //     pinch_guess_ == true:  Guess there is a pinch
730   //     pinch_guess_ == false: Guess there is no pinch
731 
732   // When guessing a pinch gesture. Do we guess pinch (true) or no-pinch?
733   bool pinch_guess_;
734   // Time when pinch guess was made. -1 if no guess has been made yet.
735   stime_t pinch_guess_start_;
736   // True when the pinch decision has been locked.
737   bool pinch_locked_;
738   // Pinch status: GESTURES_ZOOM_START, _UPDATE, or _END
739   unsigned pinch_status_;
740   // Direction of previous pinch update:
741   //   0: No previous update
742   //   1: Outward
743   //  -1: Inward
744   int pinch_prev_direction_;
745   // Timestamp of previous pinch update
746   float pinch_prev_time_;
747 
748   // Keeps track of if there was a finger seen during a physical click
749   bool finger_seen_shortly_after_button_down_;
750 
751   bool is_haptic_pad_;
752 
753   // See keyboard_touched_* properties
754   stime_t keyboard_touched_;
755 
756   ScrollManager scroll_manager_;
757 
758   // Properties
759 
760   // Is Tap-To-Click enabled
761   BoolProperty tap_enable_;
762   // Allows Tap-To-Click to be paused
763   BoolProperty tap_paused_;
764   // General time limit [s] for tap gestures
765   DoubleProperty tap_timeout_;
766   // General time limit [s] for time between taps.
767   DoubleProperty inter_tap_timeout_;
768   // Time [s] before a tap gets recognized as a drag.
769   DoubleProperty tap_drag_delay_;
770   // Time [s] it takes to stop dragging when you let go of the touchpad
771   DoubleProperty tap_drag_timeout_;
772   // True if tap dragging is enabled. With it disbled we can respond quickly
773   // to tap clicks.
774   BoolProperty tap_drag_enable_;
775   // True if drag lock is enabled
776   BoolProperty drag_lock_enable_;
777   // Time [s] the finger has to be stationary to be considered dragging
778   DoubleProperty tap_drag_stationary_time_;
779   // Distance [mm] a finger can move and still register a tap
780   DoubleProperty tap_move_dist_;
781   // Minimum pressure a finger must have for it to click when tap to click is on
782   DoubleProperty tap_min_pressure_;
783   // Maximum distance [mm] per frame that a finger can move and still be
784   // considered stationary.
785   DoubleProperty tap_max_movement_;
786   // Maximum finger age for a finger to trigger tap.
787   DoubleProperty tap_max_finger_age_;
788   // If three finger click should be enabled. This is a temporary flag so that
789   // we can deploy this feature behind a file while we work out the bugs.
790   BoolProperty three_finger_click_enable_;
791   // If zero finger click should be enabled. On some platforms, bending the
792   // case may accidentally cause a physical click.  This supresses all clicks
793   // that do not have at least 1 finger detected on the touchpad.
794   BoolProperty zero_finger_click_enable_;
795   // If T5R2 should support three-finger click/tap, which can in some situations
796   // be unreliable.
797   BoolProperty t5r2_three_finger_click_enable_;
798   // Distance [mm] a finger must move after fingers change to count as real
799   // motion
800   DoubleProperty change_move_distance_;
801   // Speed [mm/s] a finger must move to lock on to that finger
802   DoubleProperty move_lock_speed_;
803   // Distance [mm] a finger must move to report that movement
804   DoubleProperty move_report_distance_;
805   // Time [s] to block movement after number or identify of fingers change
806   DoubleProperty change_timeout_;
807   // Time [s] to wait before locking on to a gesture
808   DoubleProperty evaluation_timeout_;
809   // Time [s] to wait before deciding if the pinch zoom is happening.
810   DoubleProperty pinch_evaluation_timeout_;
811   // Time [s] to wait before decide if a thumb is doing a pinch
812   DoubleProperty thumb_pinch_evaluation_timeout_;
813   // Minimum movement that a thumb should have to be a gesturing finger.
814   DoubleProperty thumb_pinch_min_movement_;
815   // If the ratio of gesturing fingers movement to thumb movement is greater
816   // than this number, then we can't have pinch with thumb.
817   DoubleProperty thumb_pinch_movement_ratio_;
818   // Ratio of Distance_sq * Time * Time for two fingers. This measure is used
819   // to compare the slow movement of two fingers.
820   DoubleProperty thumb_slow_pinch_similarity_ratio_;
821   // If a thumb arrives at the same time as the other fingers, the
822   // thumb_pinch_evaluation_timeout_ is multiplied by this factor
823   DoubleProperty thumb_pinch_delay_factor_;
824   // Minimum movement that fingers must have before we consider their
825   // relative direction. If the movement is smaller than this number, it
826   // will considered as noise.
827   DoubleProperty minimum_movement_direction_detection_;
828   // A finger in the damp zone must move at least this much as much as
829   // the other finger to count toward a gesture. Should be between 0 and 1.
830   DoubleProperty damp_scroll_min_movement_factor_;
831   // If two fingers have a pressure difference greater than diff thresh and
832   // the larger is more than diff factor times the smaller, we assume the
833   // larger is a thumb.
834   DoubleProperty two_finger_pressure_diff_thresh_;
835   DoubleProperty two_finger_pressure_diff_factor_;
836   // Click-and-drags are sometimes wrongly classified as right-clicks if the
837   // physical-clicking finger arrives at the pad later than or at roughly the
838   // same time of the other finger. To distinguish between the two cases, we
839   // use the pressure difference and the fingers' relative positions.
840   DoubleProperty click_drag_pressure_diff_thresh_;
841   DoubleProperty click_drag_pressure_diff_factor_;
842   // Mininum slope of the line connecting two fingers that can qualify a click-
843   // and-drag gesture.
844   DoubleProperty click_drag_min_slope_;
845   // If a large contact moves more than this much times the lowest-pressure
846   // contact, consider it not to be a thumb.
847   DoubleProperty thumb_movement_factor_;
848   // If a large contact moves faster than this much times the lowest-pressure
849   // contact, consider it not to be a thumb.
850   DoubleProperty thumb_speed_factor_;
851   // This much time after fingers change, stop allowing contacts classified
852   // as thumb to be classified as non-thumb.
853   DoubleProperty thumb_eval_timeout_;
854   // If thumb is doing an inward pinch, the thresholds for distance and speed
855   // that thumb needs to move to be a gesturing finger are multiplied by this
856   // factor
857   DoubleProperty thumb_pinch_threshold_ratio_;
858   // If a finger is recognized as thumb, it has only this much time to change
859   // its status and perform a click
860   DoubleProperty thumb_click_prevention_timeout_;
861   // Consider scroll vs pointing if finger moves at least this distance [mm]
862   DoubleProperty two_finger_scroll_distance_thresh_;
863   // Consider move if there is no scroll and one finger moves at least this
864   // distance [mm]
865   DoubleProperty two_finger_move_distance_thresh_;
866   // Minimum distance [mm] one of the three fingers must move to perform a
867   // swipe gesture.
868   DoubleProperty three_finger_swipe_distance_thresh_;
869   // Minimum distance [mm] one of the four fingers must move to perform a
870   // four finger swipe gesture.
871   DoubleProperty four_finger_swipe_distance_thresh_;
872   // Minimum ratio between least and most moving finger to perform a
873   // three finger swipe gesture.
874   DoubleProperty three_finger_swipe_distance_ratio_;
875   // Minimum ratio between least and most moving finger to perform a
876   // four finger swipe gesture.
877   DoubleProperty four_finger_swipe_distance_ratio_;
878   // If three-finger swipe should be enabled
879   BoolProperty three_finger_swipe_enable_;
880   // Height [mm] of the bottom zone
881   DoubleProperty bottom_zone_size_;
882   // Time [s] to after button down to evaluate number of fingers for a click
883   DoubleProperty button_evaluation_timeout_;
884   // Time [s] to evaluate number of fingers for a click after a new touch has
885   // been registered
886   DoubleProperty button_finger_timeout_;
887   // Distance [mm] a finger can move to still be considered for a button click
888   DoubleProperty button_move_dist_;
889   // Distance [mm] a finger can be away from it's expected location to be
890   // considered part of the same finger group
891   DoubleProperty button_max_dist_from_expected_;
892   // Flag to enable the right click on the right side of the hardware button
893   BoolProperty button_right_click_zone_enable_;
894   // The size of the right click zone on the right side of the hardware button
895   DoubleProperty button_right_click_zone_size_;
896   // Timeval of time when keyboard was last touched. After the low one is set,
897   // the two are converted into an stime_t and stored in keyboard_touched_.
898   IntProperty keyboard_touched_timeval_high_;  // seconds
899   IntProperty keyboard_touched_timeval_low_;  // microseconds
900   // During this timeout, which is time [s] since the keyboard has been used,
901   // we are extra aggressive in palm detection. If this time is > 10s apart
902   // from now (either before or after), it's disregarded. We disregard old
903   // values b/c they no longer apply. Because of delays in other interpreters
904   // (LooaheadInterpreter), it's possible to get "future" keyboard used times.
905   // We wouldn't want a single bad future value to stop all tap-to-click, so
906   // we sanity check.
907   DoubleProperty keyboard_palm_prevent_timeout_;
908   // Motion (pointer movement, scroll) must halt for this length of time [s]
909   // before a tap can generate a click.
910   DoubleProperty motion_tap_prevent_timeout_;
911   // A finger must be at least this far from other fingers when it taps [mm].
912   DoubleProperty tapping_finger_min_separation_;
913 
914   // Sum of squares of movement [mm] that is considered as noise during pinch
915   // detection
916   DoubleProperty pinch_noise_level_sq_;
917   // Minimal distance [mm] fingers have to move to indicate a pinch gesture.
918   DoubleProperty pinch_guess_min_movement_;
919   // Minimal distance [mm] a thumb have to move to do a pinch gesture.
920   DoubleProperty pinch_thumb_min_movement_;
921   // Minimal distance [mm] fingers have to move to lock a pinch gesture.
922   DoubleProperty pinch_certain_min_movement_;
923   // Minimum Cos(A) that is acceptable for an inward pinch zoom, where A
924   // is the angle between the lower finger and a vertical vector directed
925   // from top to bottom.
926   DoubleProperty inward_pinch_min_angle_;
927   // Maximum Cos(A) to perform a pinch zoom, where A is the angle between
928   // two fingers.
929   DoubleProperty pinch_zoom_max_angle_;
930   // Minimum Cos(A) to perform a scroll gesture when pinch is enabled,
931   // where A is the angle between two fingers.
932   DoubleProperty scroll_min_angle_;
933   // Minimum movement ratio between fingers before we call it a consistent move
934   // for a pinch.
935   DoubleProperty pinch_guess_consistent_mov_ratio_;
936   // Minimum number of touch events needed to start a pinch zoom
937   IntProperty pinch_zoom_min_events_;
938   // If a pinch is determined quickly we use the original landing position to
939   // determing original pinch width. But if they landed too long ago we use the
940   // pinch width at detection. Inverse of time in seconds.
941   DoubleProperty pinch_initial_scale_time_inv_;
942   // Resolution of pinch events: minimum change in squared pinch scale required
943   // to send a pinch update.
944   DoubleProperty pinch_res_;
945   // Change in squared pinch scale required to send a pinch update after fingers
946   // stay stationary.
947   DoubleProperty pinch_stationary_res_;
948   // Time fingers should remain motionless before being treated as stationary.
949   DoubleProperty pinch_stationary_time_;
950   // Change in squared pinch scale required to send a pinch update after fingers
951   // change direction.
952   DoubleProperty pinch_hysteresis_res_;
953   // Temporary flag to turn pinch on/off while we tune it.
954   BoolProperty pinch_enable_;
955 
956   // Short start time diff of fingers for a two-finger click that indicates
957   // a right click
958   DoubleProperty right_click_start_time_diff_;
959   // Second finger comes down for a while then button clicks down that indicates
960   // a right click
961   DoubleProperty right_click_second_finger_age_;
962   // Suppress moves with a speed more than this much times the previous speed.
963   DoubleProperty quick_acceleration_factor_;
964 };
965 
966 bool AnyGesturingFingerLeft(const HardwareState& state,
967                             const FingerMap& prev_gs_fingers);
968 
969 }  // namespace gestures
970 
971 #endif  // GESTURES_IMMEDIATE_INTERPRETER_H_
972