OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // MSVC++ requires this to be set before any other includes to get M_PI. | 5 // MSVC++ requires this to be set before any other includes to get M_PI. |
6 #define _USE_MATH_DEFINES | 6 #define _USE_MATH_DEFINES |
7 | 7 |
8 #include "ui/events/gesture_detection/gesture_detector.h" | 8 #include "ui/events/gesture_detection/gesture_detector.h" |
9 | 9 |
10 #include <cmath> | 10 #include <cmath> |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
48 touch_slop(8), | 48 touch_slop(8), |
49 double_tap_slop(100), | 49 double_tap_slop(100), |
50 minimum_fling_velocity(50), | 50 minimum_fling_velocity(50), |
51 maximum_fling_velocity(8000), | 51 maximum_fling_velocity(8000), |
52 swipe_enabled(false), | 52 swipe_enabled(false), |
53 minimum_swipe_velocity(20), | 53 minimum_swipe_velocity(20), |
54 maximum_swipe_deviation_angle(20.f), | 54 maximum_swipe_deviation_angle(20.f), |
55 two_finger_tap_enabled(false), | 55 two_finger_tap_enabled(false), |
56 two_finger_tap_max_separation(300), | 56 two_finger_tap_max_separation(300), |
57 two_finger_tap_timeout(base::TimeDelta::FromMilliseconds(700)), | 57 two_finger_tap_timeout(base::TimeDelta::FromMilliseconds(700)), |
58 velocity_tracker_strategy(VelocityTracker::Strategy::STRATEGY_DEFAULT) { | 58 single_tap_repeat_length(1), |
59 } | 59 velocity_tracker_strategy(VelocityTracker::Strategy::STRATEGY_DEFAULT) {} |
60 | 60 |
61 GestureDetector::Config::~Config() {} | 61 GestureDetector::Config::~Config() {} |
62 | 62 |
63 class GestureDetector::TimeoutGestureHandler { | 63 class GestureDetector::TimeoutGestureHandler { |
64 public: | 64 public: |
65 TimeoutGestureHandler(const Config& config, GestureDetector* gesture_detector) | 65 TimeoutGestureHandler(const Config& config, GestureDetector* gesture_detector) |
66 : gesture_detector_(gesture_detector) { | 66 : gesture_detector_(gesture_detector) { |
67 DCHECK(config.showpress_timeout <= config.longpress_timeout); | 67 DCHECK(config.showpress_timeout <= config.longpress_timeout); |
68 | 68 |
69 timeout_callbacks_[SHOW_PRESS] = &GestureDetector::OnShowPressTimeout; | 69 timeout_callbacks_[SHOW_PRESS] = &GestureDetector::OnShowPressTimeout; |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 min_fling_velocity_(1), | 122 min_fling_velocity_(1), |
123 max_fling_velocity_(1), | 123 max_fling_velocity_(1), |
124 min_swipe_velocity_(0), | 124 min_swipe_velocity_(0), |
125 min_swipe_direction_component_ratio_(0), | 125 min_swipe_direction_component_ratio_(0), |
126 still_down_(false), | 126 still_down_(false), |
127 defer_confirm_single_tap_(false), | 127 defer_confirm_single_tap_(false), |
128 always_in_tap_region_(false), | 128 always_in_tap_region_(false), |
129 always_in_bigger_tap_region_(false), | 129 always_in_bigger_tap_region_(false), |
130 two_finger_tap_allowed_for_gesture_(false), | 130 two_finger_tap_allowed_for_gesture_(false), |
131 is_double_tapping_(false), | 131 is_double_tapping_(false), |
| 132 single_tap_count_(1), |
| 133 single_tap_repeat_length_(1), |
132 last_focus_x_(0), | 134 last_focus_x_(0), |
133 last_focus_y_(0), | 135 last_focus_y_(0), |
134 down_focus_x_(0), | 136 down_focus_x_(0), |
135 down_focus_y_(0), | 137 down_focus_y_(0), |
136 longpress_enabled_(true), | 138 longpress_enabled_(true), |
137 showpress_enabled_(true), | 139 showpress_enabled_(true), |
138 swipe_enabled_(false), | 140 swipe_enabled_(false), |
139 two_finger_tap_enabled_(false), | 141 two_finger_tap_enabled_(false), |
140 velocity_tracker_(config.velocity_tracker_strategy) { | 142 velocity_tracker_(config.velocity_tracker_strategy) { |
141 DCHECK(listener_); | 143 DCHECK(listener_); |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
227 handled = HandleSwipeIfNeeded(ev, vx_total / count, vy_total / count); | 229 handled = HandleSwipeIfNeeded(ev, vx_total / count, vy_total / count); |
228 | 230 |
229 if (two_finger_tap_allowed_for_gesture_ && ev.GetPointerCount() == 2 && | 231 if (two_finger_tap_allowed_for_gesture_ && ev.GetPointerCount() == 2 && |
230 (ev.GetEventTime() - secondary_pointer_down_event_->GetEventTime() <= | 232 (ev.GetEventTime() - secondary_pointer_down_event_->GetEventTime() <= |
231 two_finger_tap_timeout_)) { | 233 two_finger_tap_timeout_)) { |
232 handled = listener_->OnTwoFingerTap(*current_down_event_, ev); | 234 handled = listener_->OnTwoFingerTap(*current_down_event_, ev); |
233 } | 235 } |
234 two_finger_tap_allowed_for_gesture_ = false; | 236 two_finger_tap_allowed_for_gesture_ = false; |
235 } break; | 237 } break; |
236 | 238 |
237 case MotionEvent::ACTION_DOWN: | 239 case MotionEvent::ACTION_DOWN: { |
| 240 bool maybe_double_tapping = |
| 241 current_down_event_ && previous_up_event_ && |
| 242 IsConsideredDoubleTap(*current_down_event_, *previous_up_event_, ev); |
238 if (double_tap_listener_) { | 243 if (double_tap_listener_) { |
| 244 single_tap_count_ = 1; |
239 bool had_tap_message = timeout_handler_->HasTimeout(TAP); | 245 bool had_tap_message = timeout_handler_->HasTimeout(TAP); |
240 if (had_tap_message) | 246 if (had_tap_message) |
241 timeout_handler_->StopTimeout(TAP); | 247 timeout_handler_->StopTimeout(TAP); |
242 if (current_down_event_ && previous_up_event_ && had_tap_message && | 248 if (maybe_double_tapping && had_tap_message) { |
243 IsConsideredDoubleTap( | |
244 *current_down_event_, *previous_up_event_, ev)) { | |
245 // This is a second tap. | 249 // This is a second tap. |
246 is_double_tapping_ = true; | 250 is_double_tapping_ = true; |
247 // Give a callback with the first tap of the double-tap. | 251 // Give a callback with the first tap of the double-tap. |
248 handled |= double_tap_listener_->OnDoubleTap(*current_down_event_); | 252 handled |= double_tap_listener_->OnDoubleTap(*current_down_event_); |
249 // Give a callback with down event of the double-tap. | 253 // Give a callback with down event of the double-tap. |
250 handled |= double_tap_listener_->OnDoubleTapEvent(ev); | 254 handled |= double_tap_listener_->OnDoubleTapEvent(ev); |
251 } else { | 255 } else { |
252 // This is a first tap. | 256 // This is a first tap. |
253 DCHECK(double_tap_timeout_ > base::TimeDelta()); | 257 DCHECK(double_tap_timeout_ > base::TimeDelta()); |
254 timeout_handler_->StartTimeout(TAP); | 258 timeout_handler_->StartTimeout(TAP); |
255 } | 259 } |
| 260 } else if (maybe_double_tapping) { |
| 261 single_tap_count_ = 1 + (single_tap_count_ % single_tap_repeat_length_); |
256 } | 262 } |
257 | 263 |
258 down_focus_x_ = last_focus_x_ = focus_x; | 264 down_focus_x_ = last_focus_x_ = focus_x; |
259 down_focus_y_ = last_focus_y_ = focus_y; | 265 down_focus_y_ = last_focus_y_ = focus_y; |
260 current_down_event_ = ev.Clone(); | 266 current_down_event_ = ev.Clone(); |
261 | 267 |
262 secondary_pointer_down_event_.reset(); | 268 secondary_pointer_down_event_.reset(); |
263 always_in_tap_region_ = true; | 269 always_in_tap_region_ = true; |
264 always_in_bigger_tap_region_ = true; | 270 always_in_bigger_tap_region_ = true; |
265 still_down_ = true; | 271 still_down_ = true; |
266 defer_confirm_single_tap_ = false; | 272 defer_confirm_single_tap_ = false; |
267 two_finger_tap_allowed_for_gesture_ = two_finger_tap_enabled_; | 273 two_finger_tap_allowed_for_gesture_ = two_finger_tap_enabled_; |
268 | 274 |
269 // Always start the SHOW_PRESS timer before the LONG_PRESS timer to ensure | 275 // Always start the SHOW_PRESS timer before the LONG_PRESS timer to ensure |
270 // proper timeout ordering. | 276 // proper timeout ordering. |
271 if (showpress_enabled_) | 277 if (showpress_enabled_) |
272 timeout_handler_->StartTimeout(SHOW_PRESS); | 278 timeout_handler_->StartTimeout(SHOW_PRESS); |
273 if (longpress_enabled_) | 279 if (longpress_enabled_) |
274 timeout_handler_->StartTimeout(LONG_PRESS); | 280 timeout_handler_->StartTimeout(LONG_PRESS); |
275 handled |= listener_->OnDown(ev); | 281 handled |= listener_->OnDown(ev); |
276 break; | 282 } break; |
277 | 283 |
278 case MotionEvent::ACTION_MOVE: | 284 case MotionEvent::ACTION_MOVE: |
279 { | 285 { |
280 const float scroll_x = last_focus_x_ - focus_x; | 286 const float scroll_x = last_focus_x_ - focus_x; |
281 const float scroll_y = last_focus_y_ - focus_y; | 287 const float scroll_y = last_focus_y_ - focus_y; |
282 if (is_double_tapping_) { | 288 if (is_double_tapping_) { |
283 // Give the move events of the double-tap. | 289 // Give the move events of the double-tap. |
284 DCHECK(double_tap_listener_); | 290 DCHECK(double_tap_listener_); |
285 handled |= double_tap_listener_->OnDoubleTapEvent(ev); | 291 handled |= double_tap_listener_->OnDoubleTapEvent(ev); |
286 } else if (always_in_tap_region_) { | 292 } else if (always_in_tap_region_) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 break; | 342 break; |
337 | 343 |
338 case MotionEvent::ACTION_UP: | 344 case MotionEvent::ACTION_UP: |
339 still_down_ = false; | 345 still_down_ = false; |
340 { | 346 { |
341 if (is_double_tapping_) { | 347 if (is_double_tapping_) { |
342 // Finally, give the up event of the double-tap. | 348 // Finally, give the up event of the double-tap. |
343 DCHECK(double_tap_listener_); | 349 DCHECK(double_tap_listener_); |
344 handled |= double_tap_listener_->OnDoubleTapEvent(ev); | 350 handled |= double_tap_listener_->OnDoubleTapEvent(ev); |
345 } else if (always_in_tap_region_) { | 351 } else if (always_in_tap_region_) { |
346 handled = listener_->OnSingleTapUp(ev); | 352 handled = listener_->OnSingleTapUp(ev, single_tap_count_); |
347 if (defer_confirm_single_tap_ && double_tap_listener_ != NULL) { | 353 if (defer_confirm_single_tap_ && double_tap_listener_ != NULL) { |
348 double_tap_listener_->OnSingleTapConfirmed(ev); | 354 double_tap_listener_->OnSingleTapConfirmed(ev); |
349 } | 355 } |
350 } else { | 356 } else { |
351 | 357 single_tap_count_ = 1; |
352 // A fling must travel the minimum tap distance. | 358 // A fling must travel the minimum tap distance. |
353 const int pointer_id = ev.GetPointerId(0); | 359 const int pointer_id = ev.GetPointerId(0); |
354 velocity_tracker_.ComputeCurrentVelocity(1000, max_fling_velocity_); | 360 velocity_tracker_.ComputeCurrentVelocity(1000, max_fling_velocity_); |
355 const float velocity_y = velocity_tracker_.GetYVelocity(pointer_id); | 361 const float velocity_y = velocity_tracker_.GetYVelocity(pointer_id); |
356 const float velocity_x = velocity_tracker_.GetXVelocity(pointer_id); | 362 const float velocity_x = velocity_tracker_.GetXVelocity(pointer_id); |
357 | 363 |
358 if ((std::abs(velocity_y) > min_fling_velocity_) || | 364 if ((std::abs(velocity_y) > min_fling_velocity_) || |
359 (std::abs(velocity_x) > min_fling_velocity_)) { | 365 (std::abs(velocity_x) > min_fling_velocity_)) { |
360 handled = listener_->OnFling( | 366 handled = listener_->OnFling( |
361 *current_down_event_, ev, velocity_x, velocity_y); | 367 *current_down_event_, ev, velocity_x, velocity_y); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
421 DCHECK_LE(config.maximum_swipe_deviation_angle, 45); | 427 DCHECK_LE(config.maximum_swipe_deviation_angle, 45); |
422 const float maximum_swipe_deviation_angle = | 428 const float maximum_swipe_deviation_angle = |
423 std::min(45.f, std::max(0.001f, config.maximum_swipe_deviation_angle)); | 429 std::min(45.f, std::max(0.001f, config.maximum_swipe_deviation_angle)); |
424 min_swipe_direction_component_ratio_ = | 430 min_swipe_direction_component_ratio_ = |
425 1.f / tan(maximum_swipe_deviation_angle * kDegreesToRadians); | 431 1.f / tan(maximum_swipe_deviation_angle * kDegreesToRadians); |
426 | 432 |
427 two_finger_tap_enabled_ = config.two_finger_tap_enabled; | 433 two_finger_tap_enabled_ = config.two_finger_tap_enabled; |
428 two_finger_tap_distance_square_ = config.two_finger_tap_max_separation * | 434 two_finger_tap_distance_square_ = config.two_finger_tap_max_separation * |
429 config.two_finger_tap_max_separation; | 435 config.two_finger_tap_max_separation; |
430 two_finger_tap_timeout_ = config.two_finger_tap_timeout; | 436 two_finger_tap_timeout_ = config.two_finger_tap_timeout; |
| 437 |
| 438 DCHECK_GE(config.single_tap_repeat_length, 1); |
| 439 single_tap_repeat_length_ = config.single_tap_repeat_length; |
431 } | 440 } |
432 | 441 |
433 void GestureDetector::OnShowPressTimeout() { | 442 void GestureDetector::OnShowPressTimeout() { |
434 listener_->OnShowPress(*current_down_event_); | 443 listener_->OnShowPress(*current_down_event_); |
435 } | 444 } |
436 | 445 |
437 void GestureDetector::OnLongPressTimeout() { | 446 void GestureDetector::OnLongPressTimeout() { |
438 timeout_handler_->StopTimeout(TAP); | 447 timeout_handler_->StopTimeout(TAP); |
439 defer_confirm_single_tap_ = false; | 448 defer_confirm_single_tap_ = false; |
440 listener_->OnLongPress(*current_down_event_); | 449 listener_->OnLongPress(*current_down_event_); |
(...skipping 15 matching lines...) Expand all Loading... |
456 velocity_tracker_.Clear(); | 465 velocity_tracker_.Clear(); |
457 still_down_ = false; | 466 still_down_ = false; |
458 } | 467 } |
459 | 468 |
460 void GestureDetector::CancelTaps() { | 469 void GestureDetector::CancelTaps() { |
461 timeout_handler_->Stop(); | 470 timeout_handler_->Stop(); |
462 is_double_tapping_ = false; | 471 is_double_tapping_ = false; |
463 always_in_tap_region_ = false; | 472 always_in_tap_region_ = false; |
464 always_in_bigger_tap_region_ = false; | 473 always_in_bigger_tap_region_ = false; |
465 defer_confirm_single_tap_ = false; | 474 defer_confirm_single_tap_ = false; |
| 475 single_tap_count_ = 1; |
466 } | 476 } |
467 | 477 |
468 bool GestureDetector::IsConsideredDoubleTap( | 478 bool GestureDetector::IsConsideredDoubleTap( |
469 const MotionEvent& first_down, | 479 const MotionEvent& first_down, |
470 const MotionEvent& first_up, | 480 const MotionEvent& first_up, |
471 const MotionEvent& second_down) const { | 481 const MotionEvent& second_down) const { |
472 if (!always_in_bigger_tap_region_) | 482 if (!always_in_bigger_tap_region_) |
473 return false; | 483 return false; |
474 | 484 |
475 const base::TimeDelta delta_time = | 485 const base::TimeDelta delta_time = |
(...skipping 27 matching lines...) Expand all Loading... |
503 return false; | 513 return false; |
504 | 514 |
505 if (vx_abs > vy_abs) | 515 if (vx_abs > vy_abs) |
506 vy = 0; | 516 vy = 0; |
507 else | 517 else |
508 vx = 0; | 518 vx = 0; |
509 return listener_->OnSwipe(*current_down_event_, up, vx, vy); | 519 return listener_->OnSwipe(*current_down_event_, up, vx, vy); |
510 } | 520 } |
511 | 521 |
512 } // namespace ui | 522 } // namespace ui |
OLD | NEW |