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