Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(28)

Side by Side Diff: ui/events/gesture_detection/gesture_detector.cc

Issue 1358263002: [Android] Support double-tap selection (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix contextual search Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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_interval(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
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 is_down_candidate_for_repeated_single_tap_(false),
133 current_single_tap_repeat_count_(0),
134 single_tap_repeat_interval_(1),
132 last_focus_x_(0), 135 last_focus_x_(0),
133 last_focus_y_(0), 136 last_focus_y_(0),
134 down_focus_x_(0), 137 down_focus_x_(0),
135 down_focus_y_(0), 138 down_focus_y_(0),
136 longpress_enabled_(true), 139 longpress_enabled_(true),
137 showpress_enabled_(true), 140 showpress_enabled_(true),
138 swipe_enabled_(false), 141 swipe_enabled_(false),
139 two_finger_tap_enabled_(false), 142 two_finger_tap_enabled_(false),
140 velocity_tracker_(config.velocity_tracker_strategy) { 143 velocity_tracker_(config.velocity_tracker_strategy) {
141 DCHECK(listener_); 144 DCHECK(listener_);
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
227 handled = HandleSwipeIfNeeded(ev, vx_total / count, vy_total / count); 230 handled = HandleSwipeIfNeeded(ev, vx_total / count, vy_total / count);
228 231
229 if (two_finger_tap_allowed_for_gesture_ && ev.GetPointerCount() == 2 && 232 if (two_finger_tap_allowed_for_gesture_ && ev.GetPointerCount() == 2 &&
230 (ev.GetEventTime() - secondary_pointer_down_event_->GetEventTime() <= 233 (ev.GetEventTime() - secondary_pointer_down_event_->GetEventTime() <=
231 two_finger_tap_timeout_)) { 234 two_finger_tap_timeout_)) {
232 handled = listener_->OnTwoFingerTap(*current_down_event_, ev); 235 handled = listener_->OnTwoFingerTap(*current_down_event_, ev);
233 } 236 }
234 two_finger_tap_allowed_for_gesture_ = false; 237 two_finger_tap_allowed_for_gesture_ = false;
235 } break; 238 } break;
236 239
237 case MotionEvent::ACTION_DOWN: 240 case MotionEvent::ACTION_DOWN: {
241 bool is_repeated_tap =
242 current_down_event_ && previous_up_event_ &&
243 IsRepeatedTap(*current_down_event_, *previous_up_event_, ev);
238 if (double_tap_listener_) { 244 if (double_tap_listener_) {
245 is_down_candidate_for_repeated_single_tap_ = false;
239 bool had_tap_message = timeout_handler_->HasTimeout(TAP); 246 bool had_tap_message = timeout_handler_->HasTimeout(TAP);
240 if (had_tap_message) 247 if (had_tap_message)
241 timeout_handler_->StopTimeout(TAP); 248 timeout_handler_->StopTimeout(TAP);
242 if (current_down_event_ && previous_up_event_ && had_tap_message && 249 if (is_repeated_tap && had_tap_message) {
243 IsConsideredDoubleTap(
244 *current_down_event_, *previous_up_event_, ev)) {
245 // This is a second tap. 250 // This is a second tap.
246 is_double_tapping_ = true; 251 is_double_tapping_ = true;
247 // Give a callback with the first tap of the double-tap. 252 // Give a callback with the first tap of the double-tap.
248 handled |= double_tap_listener_->OnDoubleTap(*current_down_event_); 253 handled |= double_tap_listener_->OnDoubleTap(*current_down_event_);
249 // Give a callback with down event of the double-tap. 254 // Give a callback with down event of the double-tap.
250 handled |= double_tap_listener_->OnDoubleTapEvent(ev); 255 handled |= double_tap_listener_->OnDoubleTapEvent(ev);
251 } else { 256 } else {
252 // This is a first tap. 257 // This is a first tap.
253 DCHECK(double_tap_timeout_ > base::TimeDelta()); 258 DCHECK(double_tap_timeout_ > base::TimeDelta());
254 timeout_handler_->StartTimeout(TAP); 259 timeout_handler_->StartTimeout(TAP);
255 } 260 }
261 } else {
262 is_down_candidate_for_repeated_single_tap_ = is_repeated_tap;
256 } 263 }
257 264
258 down_focus_x_ = last_focus_x_ = focus_x; 265 down_focus_x_ = last_focus_x_ = focus_x;
259 down_focus_y_ = last_focus_y_ = focus_y; 266 down_focus_y_ = last_focus_y_ = focus_y;
260 current_down_event_ = ev.Clone(); 267 current_down_event_ = ev.Clone();
261 268
262 secondary_pointer_down_event_.reset(); 269 secondary_pointer_down_event_.reset();
263 always_in_tap_region_ = true; 270 always_in_tap_region_ = true;
264 always_in_bigger_tap_region_ = true; 271 always_in_bigger_tap_region_ = true;
265 still_down_ = true; 272 still_down_ = true;
266 defer_confirm_single_tap_ = false; 273 defer_confirm_single_tap_ = false;
267 two_finger_tap_allowed_for_gesture_ = two_finger_tap_enabled_; 274 two_finger_tap_allowed_for_gesture_ = two_finger_tap_enabled_;
268 275
269 // Always start the SHOW_PRESS timer before the LONG_PRESS timer to ensure 276 // Always start the SHOW_PRESS timer before the LONG_PRESS timer to ensure
270 // proper timeout ordering. 277 // proper timeout ordering.
271 if (showpress_enabled_) 278 if (showpress_enabled_)
272 timeout_handler_->StartTimeout(SHOW_PRESS); 279 timeout_handler_->StartTimeout(SHOW_PRESS);
273 if (longpress_enabled_) 280 if (longpress_enabled_)
274 timeout_handler_->StartTimeout(LONG_PRESS); 281 timeout_handler_->StartTimeout(LONG_PRESS);
275 handled |= listener_->OnDown(ev); 282 handled |= listener_->OnDown(ev);
276 break; 283 } break;
277 284
278 case MotionEvent::ACTION_MOVE: 285 case MotionEvent::ACTION_MOVE:
279 { 286 {
280 const float scroll_x = last_focus_x_ - focus_x; 287 const float scroll_x = last_focus_x_ - focus_x;
281 const float scroll_y = last_focus_y_ - focus_y; 288 const float scroll_y = last_focus_y_ - focus_y;
282 if (is_double_tapping_) { 289 if (is_double_tapping_) {
283 // Give the move events of the double-tap. 290 // Give the move events of the double-tap.
284 DCHECK(double_tap_listener_); 291 DCHECK(double_tap_listener_);
285 handled |= double_tap_listener_->OnDoubleTapEvent(ev); 292 handled |= double_tap_listener_->OnDoubleTapEvent(ev);
286 } else if (always_in_tap_region_) { 293 } else if (always_in_tap_region_) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
336 break; 343 break;
337 344
338 case MotionEvent::ACTION_UP: 345 case MotionEvent::ACTION_UP:
339 still_down_ = false; 346 still_down_ = false;
340 { 347 {
341 if (is_double_tapping_) { 348 if (is_double_tapping_) {
342 // Finally, give the up event of the double-tap. 349 // Finally, give the up event of the double-tap.
343 DCHECK(double_tap_listener_); 350 DCHECK(double_tap_listener_);
344 handled |= double_tap_listener_->OnDoubleTapEvent(ev); 351 handled |= double_tap_listener_->OnDoubleTapEvent(ev);
345 } else if (always_in_tap_region_) { 352 } else if (always_in_tap_region_) {
346 handled = listener_->OnSingleTapUp(ev); 353 if (is_down_candidate_for_repeated_single_tap_) {
354 current_single_tap_repeat_count_ =
355 (1 + current_single_tap_repeat_count_) %
356 single_tap_repeat_interval_;
357 } else {
358 current_single_tap_repeat_count_ = 0;
359 }
360 handled = listener_->OnSingleTapUp(
361 ev, 1 + current_single_tap_repeat_count_);
347 if (defer_confirm_single_tap_ && double_tap_listener_ != NULL) { 362 if (defer_confirm_single_tap_ && double_tap_listener_ != NULL) {
348 double_tap_listener_->OnSingleTapConfirmed(ev); 363 double_tap_listener_->OnSingleTapConfirmed(ev);
349 } 364 }
350 } else { 365 } else {
351 366 current_single_tap_repeat_count_ = 0;
352 // A fling must travel the minimum tap distance. 367 // A fling must travel the minimum tap distance.
353 const int pointer_id = ev.GetPointerId(0); 368 const int pointer_id = ev.GetPointerId(0);
354 velocity_tracker_.ComputeCurrentVelocity(1000, max_fling_velocity_); 369 velocity_tracker_.ComputeCurrentVelocity(1000, max_fling_velocity_);
355 const float velocity_y = velocity_tracker_.GetYVelocity(pointer_id); 370 const float velocity_y = velocity_tracker_.GetYVelocity(pointer_id);
356 const float velocity_x = velocity_tracker_.GetXVelocity(pointer_id); 371 const float velocity_x = velocity_tracker_.GetXVelocity(pointer_id);
357 372
358 if ((std::abs(velocity_y) > min_fling_velocity_) || 373 if ((std::abs(velocity_y) > min_fling_velocity_) ||
359 (std::abs(velocity_x) > min_fling_velocity_)) { 374 (std::abs(velocity_x) > min_fling_velocity_)) {
360 handled = listener_->OnFling( 375 handled = listener_->OnFling(
361 *current_down_event_, ev, velocity_x, velocity_y); 376 *current_down_event_, ev, velocity_x, velocity_y);
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
421 DCHECK_LE(config.maximum_swipe_deviation_angle, 45); 436 DCHECK_LE(config.maximum_swipe_deviation_angle, 45);
422 const float maximum_swipe_deviation_angle = 437 const float maximum_swipe_deviation_angle =
423 std::min(45.f, std::max(0.001f, config.maximum_swipe_deviation_angle)); 438 std::min(45.f, std::max(0.001f, config.maximum_swipe_deviation_angle));
424 min_swipe_direction_component_ratio_ = 439 min_swipe_direction_component_ratio_ =
425 1.f / tan(maximum_swipe_deviation_angle * kDegreesToRadians); 440 1.f / tan(maximum_swipe_deviation_angle * kDegreesToRadians);
426 441
427 two_finger_tap_enabled_ = config.two_finger_tap_enabled; 442 two_finger_tap_enabled_ = config.two_finger_tap_enabled;
428 two_finger_tap_distance_square_ = config.two_finger_tap_max_separation * 443 two_finger_tap_distance_square_ = config.two_finger_tap_max_separation *
429 config.two_finger_tap_max_separation; 444 config.two_finger_tap_max_separation;
430 two_finger_tap_timeout_ = config.two_finger_tap_timeout; 445 two_finger_tap_timeout_ = config.two_finger_tap_timeout;
446
447 DCHECK_GE(config.single_tap_repeat_interval, 1);
448 single_tap_repeat_interval_ = config.single_tap_repeat_interval;
431 } 449 }
432 450
433 void GestureDetector::OnShowPressTimeout() { 451 void GestureDetector::OnShowPressTimeout() {
434 listener_->OnShowPress(*current_down_event_); 452 listener_->OnShowPress(*current_down_event_);
435 } 453 }
436 454
437 void GestureDetector::OnLongPressTimeout() { 455 void GestureDetector::OnLongPressTimeout() {
438 timeout_handler_->StopTimeout(TAP); 456 timeout_handler_->StopTimeout(TAP);
439 defer_confirm_single_tap_ = false; 457 defer_confirm_single_tap_ = false;
440 listener_->OnLongPress(*current_down_event_); 458 listener_->OnLongPress(*current_down_event_);
(...skipping 15 matching lines...) Expand all
456 velocity_tracker_.Clear(); 474 velocity_tracker_.Clear();
457 still_down_ = false; 475 still_down_ = false;
458 } 476 }
459 477
460 void GestureDetector::CancelTaps() { 478 void GestureDetector::CancelTaps() {
461 timeout_handler_->Stop(); 479 timeout_handler_->Stop();
462 is_double_tapping_ = false; 480 is_double_tapping_ = false;
463 always_in_tap_region_ = false; 481 always_in_tap_region_ = false;
464 always_in_bigger_tap_region_ = false; 482 always_in_bigger_tap_region_ = false;
465 defer_confirm_single_tap_ = false; 483 defer_confirm_single_tap_ = false;
484 is_down_candidate_for_repeated_single_tap_ = false;
485 current_single_tap_repeat_count_ = 0;
466 } 486 }
467 487
468 bool GestureDetector::IsConsideredDoubleTap( 488 bool GestureDetector::IsRepeatedTap(const MotionEvent& first_down,
469 const MotionEvent& first_down, 489 const MotionEvent& first_up,
470 const MotionEvent& first_up, 490 const MotionEvent& second_down) const {
471 const MotionEvent& second_down) const {
472 if (!always_in_bigger_tap_region_) 491 if (!always_in_bigger_tap_region_)
473 return false; 492 return false;
474 493
475 const base::TimeDelta delta_time = 494 const base::TimeDelta delta_time =
476 second_down.GetEventTime() - first_up.GetEventTime(); 495 second_down.GetEventTime() - first_up.GetEventTime();
477 if (delta_time < double_tap_min_time_ || delta_time > double_tap_timeout_) 496 if (delta_time > double_tap_timeout_)
497 return false;
498
499 // Only use the min time when in double-tap detection mode. For repeated
500 // single taps the risk of accidental repeat detection (e.g., from fingernail
501 // interference) is minimal.
502 if (double_tap_listener_ && delta_time < double_tap_min_time_)
478 return false; 503 return false;
479 504
480 const float delta_x = first_down.GetX() - second_down.GetX(); 505 const float delta_x = first_down.GetX() - second_down.GetX();
481 const float delta_y = first_down.GetY() - second_down.GetY(); 506 const float delta_y = first_down.GetY() - second_down.GetY();
482 return (delta_x * delta_x + delta_y * delta_y < double_tap_slop_square_); 507 return (delta_x * delta_x + delta_y * delta_y < double_tap_slop_square_);
483 } 508 }
484 509
485 bool GestureDetector::HandleSwipeIfNeeded(const MotionEvent& up, 510 bool GestureDetector::HandleSwipeIfNeeded(const MotionEvent& up,
486 float vx, 511 float vx,
487 float vy) { 512 float vy) {
(...skipping 15 matching lines...) Expand all
503 return false; 528 return false;
504 529
505 if (vx_abs > vy_abs) 530 if (vx_abs > vy_abs)
506 vy = 0; 531 vy = 0;
507 else 532 else
508 vx = 0; 533 vx = 0;
509 return listener_->OnSwipe(*current_down_event_, up, vx, vy); 534 return listener_->OnSwipe(*current_down_event_, up, vx, vy);
510 } 535 }
511 536
512 } // namespace ui 537 } // namespace ui
OLDNEW
« no previous file with comments | « ui/events/gesture_detection/gesture_detector.h ('k') | ui/events/gesture_detection/gesture_listeners.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698