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