1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// found in the LICENSE file. 4a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 55c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// MSVC++ requires this to be set before any other includes to get M_PI. 65c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#define _USE_MATH_DEFINES 75c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/events/gesture_detection/gesture_detector.h" 9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include <cmath> 11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "base/timer/timer.h" 13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/events/gesture_detection/motion_event.h" 14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace ui { 16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace { 17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 18a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// Using a small epsilon when comparing slop distances allows pixel perfect 19a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// slop determination when using fractional DIP coordinates (assuming the slop 20a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// region and DPI scale are reasonably proportioned). 21a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochconst float kSlopEpsilon = .05f; 22a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 23a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// Minimum distance a scroll must have traveled from the last scroll/focal point 24a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch// to trigger an |OnScroll| callback. 25a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochconst float kScrollEpsilon = .1f; 26a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst float kDegreesToRadians = static_cast<float>(M_PI) / 180.0f; 285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Constants used by TimeoutGestureHandler. 30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)enum TimeoutEvent { 31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) SHOW_PRESS = 0, 32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) LONG_PRESS, 33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) TAP, 34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) TIMEOUT_EVENT_COUNT 35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}; 36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} // namespace 38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Note: These constants were taken directly from the default (unscaled) 40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// versions found in Android's ViewConfiguration. 41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)GestureDetector::Config::Config() 42a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : longpress_timeout(base::TimeDelta::FromMilliseconds(500)), 43a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) showpress_timeout(base::TimeDelta::FromMilliseconds(180)), 44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) double_tap_timeout(base::TimeDelta::FromMilliseconds(300)), 45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) double_tap_min_time(base::TimeDelta::FromMilliseconds(40)), 46a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch touch_slop(8), 47a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch double_tap_slop(100), 48a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch minimum_fling_velocity(50), 495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu maximum_fling_velocity(8000), 505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu swipe_enabled(false), 515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu minimum_swipe_velocity(20), 52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) maximum_swipe_deviation_angle(20.f), 53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) two_finger_tap_enabled(false), 54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) two_finger_tap_max_separation(300), 55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) two_finger_tap_timeout(base::TimeDelta::FromMilliseconds(700)) { 565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)GestureDetector::Config::~Config() {} 59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool GestureDetector::SimpleGestureListener::OnDown(const MotionEvent& e) { 61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 62a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GestureDetector::SimpleGestureListener::OnShowPress(const MotionEvent& e) { 65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool GestureDetector::SimpleGestureListener::OnSingleTapUp( 68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const MotionEvent& e) { 69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 72116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid GestureDetector::SimpleGestureListener::OnLongPress(const MotionEvent& e) { 73a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool GestureDetector::SimpleGestureListener::OnScroll(const MotionEvent& e1, 76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const MotionEvent& e2, 77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float distance_x, 78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float distance_y) { 79a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool GestureDetector::SimpleGestureListener::OnFling(const MotionEvent& e1, 83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const MotionEvent& e2, 84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float velocity_x, 85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float velocity_y) { 86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool GestureDetector::SimpleGestureListener::OnSwipe(const MotionEvent& e1, 905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const MotionEvent& e2, 915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu float velocity_x, 925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu float velocity_y) { 935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu return false; 945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu} 955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool GestureDetector::SimpleGestureListener::OnTwoFingerTap( 97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const MotionEvent& e1, 98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const MotionEvent& e2) { 99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 102a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool GestureDetector::SimpleGestureListener::OnSingleTapConfirmed( 103a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const MotionEvent& e) { 104a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 107a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool GestureDetector::SimpleGestureListener::OnDoubleTap(const MotionEvent& e) { 108a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 110a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 111a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool GestureDetector::SimpleGestureListener::OnDoubleTapEvent( 112a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const MotionEvent& e) { 113a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class GestureDetector::TimeoutGestureHandler { 117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public: 118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) TimeoutGestureHandler(const Config& config, GestureDetector* gesture_detector) 119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : gesture_detector_(gesture_detector) { 120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(config.showpress_timeout <= config.longpress_timeout); 121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) timeout_callbacks_[SHOW_PRESS] = &GestureDetector::OnShowPressTimeout; 123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) timeout_delays_[SHOW_PRESS] = config.showpress_timeout; 124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) timeout_callbacks_[LONG_PRESS] = &GestureDetector::OnLongPressTimeout; 126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) timeout_delays_[LONG_PRESS] = 127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) config.longpress_timeout + config.showpress_timeout; 128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) timeout_callbacks_[TAP] = &GestureDetector::OnTapTimeout; 130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) timeout_delays_[TAP] = config.double_tap_timeout; 131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ~TimeoutGestureHandler() { 134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Stop(); 135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void StartTimeout(TimeoutEvent event) { 138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) timeout_timers_[event].Start(FROM_HERE, 139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) timeout_delays_[event], 140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) gesture_detector_, 141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) timeout_callbacks_[event]); 142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void StopTimeout(TimeoutEvent event) { timeout_timers_[event].Stop(); } 145a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 146a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) void Stop() { 147a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (size_t i = SHOW_PRESS; i < TIMEOUT_EVENT_COUNT; ++i) 148a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) timeout_timers_[i].Stop(); 149a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 150a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 151a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool HasTimeout(TimeoutEvent event) const { 152a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return timeout_timers_[event].IsRunning(); 153a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 154a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) private: 156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) typedef void (GestureDetector::*ReceiverMethod)(); 157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) GestureDetector* const gesture_detector_; 159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::OneShotTimer<GestureDetector> timeout_timers_[TIMEOUT_EVENT_COUNT]; 160a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ReceiverMethod timeout_callbacks_[TIMEOUT_EVENT_COUNT]; 161a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) base::TimeDelta timeout_delays_[TIMEOUT_EVENT_COUNT]; 162a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}; 163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 164a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)GestureDetector::GestureDetector( 165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const Config& config, 166a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) GestureListener* listener, 167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DoubleTapListener* optional_double_tap_listener) 168a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : timeout_handler_(new TimeoutGestureHandler(config, this)), 169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) listener_(listener), 170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) double_tap_listener_(optional_double_tap_listener), 171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) touch_slop_square_(0), 172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) double_tap_touch_slop_square_(0), 173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) double_tap_slop_square_(0), 174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) two_finger_tap_distance_square_(0), 175a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) min_fling_velocity_(1), 176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) max_fling_velocity_(1), 177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) min_swipe_velocity_(0), 178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) min_swipe_direction_component_ratio_(0), 179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) still_down_(false), 180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) defer_confirm_single_tap_(false), 181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) always_in_tap_region_(false), 182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) always_in_bigger_tap_region_(false), 183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) two_finger_tap_allowed_for_gesture_(false), 184a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) is_double_tapping_(false), 185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) last_focus_x_(0), 186a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) last_focus_y_(0), 187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) down_focus_x_(0), 188a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) down_focus_y_(0), 189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) longpress_enabled_(true), 190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) swipe_enabled_(false), 191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) two_finger_tap_enabled_(false) { 192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(listener_); 193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Init(config); 194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)GestureDetector::~GestureDetector() {} 197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 198a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool GestureDetector::OnTouchEvent(const MotionEvent& ev) { 199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const MotionEvent::Action action = ev.GetAction(); 200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 201a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) velocity_tracker_.AddMovement(ev); 202a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const bool pointer_up = action == MotionEvent::ACTION_POINTER_UP; 204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const int skip_index = pointer_up ? ev.GetActionIndex() : -1; 205a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Determine focal point. 207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) float sum_x = 0, sum_y = 0; 208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const int count = static_cast<int>(ev.GetPointerCount()); 209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (int i = 0; i < count; i++) { 210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (skip_index == i) 211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) continue; 212a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) sum_x += ev.GetX(i); 213a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) sum_y += ev.GetY(i); 214a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 215a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const int div = pointer_up ? count - 1 : count; 216a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const float focus_x = sum_x / div; 217a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const float focus_y = sum_y / div; 218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool handled = false; 220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) switch (action) { 222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case MotionEvent::ACTION_POINTER_DOWN: { 223a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) down_focus_x_ = last_focus_x_ = focus_x; 224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) down_focus_y_ = last_focus_y_ = focus_y; 225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Cancel long press and taps. 226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) CancelTaps(); 227a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!two_finger_tap_allowed_for_gesture_) 229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const int action_index = ev.GetActionIndex(); 232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const float dx = ev.GetX(action_index) - current_down_event_->GetX(); 233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const float dy = ev.GetY(action_index) - current_down_event_->GetY(); 234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (ev.GetPointerCount() == 2 && 236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) dx * dx + dy * dy < two_finger_tap_distance_square_) { 237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) secondary_pointer_down_event_ = ev.Clone(); 238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } else { 239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) two_finger_tap_allowed_for_gesture_ = false; 240cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } break; 242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) case MotionEvent::ACTION_POINTER_UP: { 244a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) down_focus_x_ = last_focus_x_ = focus_x; 245a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) down_focus_y_ = last_focus_y_ = focus_y; 246a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 247a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Check the dot product of current velocities. 248a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // If the pointer that left was opposing another velocity vector, clear. 249a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) velocity_tracker_.ComputeCurrentVelocity(1000, max_fling_velocity_); 250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const int up_index = ev.GetActionIndex(); 251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const int id1 = ev.GetPointerId(up_index); 252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const float vx1 = velocity_tracker_.GetXVelocity(id1); 253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const float vy1 = velocity_tracker_.GetYVelocity(id1); 254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float vx_total = vx1; 255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float vy_total = vy1; 256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for (int i = 0; i < count; i++) { 257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (i == up_index) 258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) continue; 259cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const int id2 = ev.GetPointerId(i); 261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const float vx2 = velocity_tracker_.GetXVelocity(id2); 262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const float vy2 = velocity_tracker_.GetYVelocity(id2); 263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const float dot = vx1 * vx2 + vy1 * vy2; 264cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (dot < 0) { 265cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) vx_total = 0; 266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) vy_total = 0; 267cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) velocity_tracker_.Clear(); 268cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 2695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 270cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) vx_total += vx2; 271cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) vy_total += vy2; 272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 2735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) handled = HandleSwipeIfNeeded(ev, vx_total / count, vy_total / count); 275cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 276cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (two_finger_tap_allowed_for_gesture_ && ev.GetPointerCount() == 2 && 277cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) (ev.GetEventTime() - secondary_pointer_down_event_->GetEventTime() <= 278cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) two_finger_tap_timeout_)) { 279cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) handled = listener_->OnTwoFingerTap(*current_down_event_, ev); 280a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 281cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) two_finger_tap_allowed_for_gesture_ = false; 282cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } break; 283a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 284a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case MotionEvent::ACTION_DOWN: 285a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (double_tap_listener_) { 286a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool had_tap_message = timeout_handler_->HasTimeout(TAP); 287a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (had_tap_message) 288a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) timeout_handler_->StopTimeout(TAP); 289a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (current_down_event_ && previous_up_event_ && had_tap_message && 290a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) IsConsideredDoubleTap( 291a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) *current_down_event_, *previous_up_event_, ev)) { 292a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // This is a second tap. 293a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) is_double_tapping_ = true; 294a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Give a callback with the first tap of the double-tap. 295a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) handled |= double_tap_listener_->OnDoubleTap(*current_down_event_); 296a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Give a callback with down event of the double-tap. 297a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) handled |= double_tap_listener_->OnDoubleTapEvent(ev); 298a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else { 299a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // This is a first tap. 300a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(double_tap_timeout_ > base::TimeDelta()); 301a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) timeout_handler_->StartTimeout(TAP); 302a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 303a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 304a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 305a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) down_focus_x_ = last_focus_x_ = focus_x; 306a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) down_focus_y_ = last_focus_y_ = focus_y; 307a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) current_down_event_ = ev.Clone(); 308a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 309cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) secondary_pointer_down_event_.reset(); 310a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) always_in_tap_region_ = true; 311a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) always_in_bigger_tap_region_ = true; 312a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) still_down_ = true; 313a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) defer_confirm_single_tap_ = false; 314cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) two_finger_tap_allowed_for_gesture_ = two_finger_tap_enabled_; 315a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 316a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Always start the SHOW_PRESS timer before the LONG_PRESS timer to ensure 317a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // proper timeout ordering. 318a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) timeout_handler_->StartTimeout(SHOW_PRESS); 3195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu if (longpress_enabled_) 320a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) timeout_handler_->StartTimeout(LONG_PRESS); 321a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) handled |= listener_->OnDown(ev); 322a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) break; 323a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 324a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case MotionEvent::ACTION_MOVE: 325a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) { 326a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const float scroll_x = last_focus_x_ - focus_x; 327a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const float scroll_y = last_focus_y_ - focus_y; 328a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (is_double_tapping_) { 329a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Give the move events of the double-tap. 33023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) DCHECK(double_tap_listener_); 331a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) handled |= double_tap_listener_->OnDoubleTapEvent(ev); 332a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else if (always_in_tap_region_) { 333a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const float delta_x = focus_x - down_focus_x_; 334a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const float delta_y = focus_y - down_focus_y_; 335a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const float distance_square = delta_x * delta_x + delta_y * delta_y; 336a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (distance_square > touch_slop_square_) { 337a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) handled = listener_->OnScroll( 338a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) *current_down_event_, ev, scroll_x, scroll_y); 339a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) last_focus_x_ = focus_x; 340a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) last_focus_y_ = focus_y; 341a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) always_in_tap_region_ = false; 342a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) timeout_handler_->Stop(); 343a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 344a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (distance_square > double_tap_touch_slop_square_) 345a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) always_in_bigger_tap_region_ = false; 346a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } else if (std::abs(scroll_x) > kScrollEpsilon || 347a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch std::abs(scroll_y) > kScrollEpsilon) { 348a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) handled = 349a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) listener_->OnScroll(*current_down_event_, ev, scroll_x, scroll_y); 350a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) last_focus_x_ = focus_x; 351a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) last_focus_y_ = focus_y; 352a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 353cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 354cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!two_finger_tap_allowed_for_gesture_) 355cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 356cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 357cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Two-finger tap should be prevented if either pointer exceeds its 358cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // (independent) slop region. 359cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const int id0 = current_down_event_->GetPointerId(0); 360cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const int ev_idx0 = ev.GetPointerId(0) == id0 ? 0 : 1; 361cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 362cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Check if the primary pointer exceeded the slop region. 363cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float dx = current_down_event_->GetX() - ev.GetX(ev_idx0); 364cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float dy = current_down_event_->GetY() - ev.GetY(ev_idx0); 365cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (dx * dx + dy * dy > touch_slop_square_) { 366cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) two_finger_tap_allowed_for_gesture_ = false; 367cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) break; 368cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 369cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (ev.GetPointerCount() == 2) { 370cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Check if the secondary pointer exceeded the slop region. 371cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const int ev_idx1 = ev_idx0 == 0 ? 1 : 0; 372cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const int idx1 = secondary_pointer_down_event_->GetActionIndex(); 373cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) dx = secondary_pointer_down_event_->GetX(idx1) - ev.GetX(ev_idx1); 374cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) dy = secondary_pointer_down_event_->GetY(idx1) - ev.GetY(ev_idx1); 375cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (dx * dx + dy * dy > touch_slop_square_) 376cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) two_finger_tap_allowed_for_gesture_ = false; 377cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 378a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 379a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) break; 380a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 381a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case MotionEvent::ACTION_UP: 382a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) still_down_ = false; 383a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) { 384a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (is_double_tapping_) { 385a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Finally, give the up event of the double-tap. 38623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) DCHECK(double_tap_listener_); 387a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) handled |= double_tap_listener_->OnDoubleTapEvent(ev); 388a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else if (always_in_tap_region_) { 389a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) handled = listener_->OnSingleTapUp(ev); 390a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (defer_confirm_single_tap_ && double_tap_listener_ != NULL) { 391a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) double_tap_listener_->OnSingleTapConfirmed(ev); 392a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 393a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } else { 394a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 395a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // A fling must travel the minimum tap distance. 396a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const int pointer_id = ev.GetPointerId(0); 397a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) velocity_tracker_.ComputeCurrentVelocity(1000, max_fling_velocity_); 398a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const float velocity_y = velocity_tracker_.GetYVelocity(pointer_id); 399a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const float velocity_x = velocity_tracker_.GetXVelocity(pointer_id); 400a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 401a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if ((std::abs(velocity_y) > min_fling_velocity_) || 402a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) (std::abs(velocity_x) > min_fling_velocity_)) { 403a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) handled = listener_->OnFling( 404a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) *current_down_event_, ev, velocity_x, velocity_y); 405a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 406cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 407cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) handled |= HandleSwipeIfNeeded(ev, velocity_x, velocity_y); 408a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 409a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 410a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) previous_up_event_ = ev.Clone(); 411a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 412a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) velocity_tracker_.Clear(); 413a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) is_double_tapping_ = false; 414a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) defer_confirm_single_tap_ = false; 415a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) timeout_handler_->StopTimeout(SHOW_PRESS); 416a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) timeout_handler_->StopTimeout(LONG_PRESS); 417a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 418a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) break; 419a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 420a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case MotionEvent::ACTION_CANCEL: 421a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Cancel(); 422a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) break; 423a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 424a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 425a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return handled; 426a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 427a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 4280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid GestureDetector::SetDoubleTapListener( 4290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DoubleTapListener* double_tap_listener) { 4300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (double_tap_listener == double_tap_listener_) 4310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return; 4320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch DCHECK(!is_double_tapping_); 4340529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4350529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // Null'ing the double-tap listener should flush an active tap timeout. 4360529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (!double_tap_listener) { 4370529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (timeout_handler_->HasTimeout(TAP)) { 4380529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch timeout_handler_->StopTimeout(TAP); 4390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch OnTapTimeout(); 4400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 4410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 4420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 4430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch double_tap_listener_ = double_tap_listener; 4440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch} 4450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch 446a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GestureDetector::Init(const Config& config) { 447a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(listener_); 448a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 449a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const float touch_slop = config.touch_slop + kSlopEpsilon; 450a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const float double_tap_touch_slop = touch_slop; 451a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const float double_tap_slop = config.double_tap_slop + kSlopEpsilon; 452a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) touch_slop_square_ = touch_slop * touch_slop; 453a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) double_tap_touch_slop_square_ = double_tap_touch_slop * double_tap_touch_slop; 454a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) double_tap_slop_square_ = double_tap_slop * double_tap_slop; 455a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) double_tap_timeout_ = config.double_tap_timeout; 456f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) double_tap_min_time_ = config.double_tap_min_time; 457f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK(double_tap_min_time_ < double_tap_timeout_); 458a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch min_fling_velocity_ = config.minimum_fling_velocity; 459a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch max_fling_velocity_ = config.maximum_fling_velocity; 4605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 4615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu swipe_enabled_ = config.swipe_enabled; 4625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu min_swipe_velocity_ = config.minimum_swipe_velocity; 4635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DCHECK_GT(config.maximum_swipe_deviation_angle, 0); 4645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu DCHECK_LE(config.maximum_swipe_deviation_angle, 45); 4655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu const float maximum_swipe_deviation_angle = 4665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu std::min(45.f, std::max(0.001f, config.maximum_swipe_deviation_angle)); 4675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu min_swipe_direction_component_ratio_ = 4685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 1.f / tan(maximum_swipe_deviation_angle * kDegreesToRadians); 469cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 470cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) two_finger_tap_enabled_ = config.two_finger_tap_enabled; 471cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) two_finger_tap_distance_square_ = config.two_finger_tap_max_separation * 472cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) config.two_finger_tap_max_separation; 473cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) two_finger_tap_timeout_ = config.two_finger_tap_timeout; 474a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 475a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 476a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GestureDetector::OnShowPressTimeout() { 477a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) listener_->OnShowPress(*current_down_event_); 478a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 479a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 480a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GestureDetector::OnLongPressTimeout() { 481a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) timeout_handler_->StopTimeout(TAP); 482a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) defer_confirm_single_tap_ = false; 483116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch listener_->OnLongPress(*current_down_event_); 484a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 485a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 486a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GestureDetector::OnTapTimeout() { 487a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!double_tap_listener_) 488a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return; 489a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!still_down_) 490a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) double_tap_listener_->OnSingleTapConfirmed(*current_down_event_); 491a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) else 492a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) defer_confirm_single_tap_ = true; 493a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 494a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 495a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GestureDetector::Cancel() { 496cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CancelTaps(); 497a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) velocity_tracker_.Clear(); 498a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) still_down_ = false; 499a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 500a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 501a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void GestureDetector::CancelTaps() { 502a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) timeout_handler_->Stop(); 503a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) is_double_tapping_ = false; 504a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) always_in_tap_region_ = false; 505a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) always_in_bigger_tap_region_ = false; 506a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) defer_confirm_single_tap_ = false; 507a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 508a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 509a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)bool GestureDetector::IsConsideredDoubleTap( 510a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const MotionEvent& first_down, 511a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const MotionEvent& first_up, 512a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const MotionEvent& second_down) const { 513a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!always_in_bigger_tap_region_) 514a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 515a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 516f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const base::TimeDelta delta_time = 517f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) second_down.GetEventTime() - first_up.GetEventTime(); 518f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (delta_time < double_tap_min_time_ || delta_time > double_tap_timeout_) 519a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 520a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 521a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const float delta_x = first_down.GetX() - second_down.GetX(); 522a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const float delta_y = first_down.GetY() - second_down.GetY(); 523a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return (delta_x * delta_x + delta_y * delta_y < double_tap_slop_square_); 524a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 525a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 526cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool GestureDetector::HandleSwipeIfNeeded(const MotionEvent& up, 527cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float vx, 528cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float vy) { 529cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!swipe_enabled_ || (!vx && !vy)) 530cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 531cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float vx_abs = std::abs(vx); 532cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float vy_abs = std::abs(vy); 533cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 534cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (vx_abs < min_swipe_velocity_) 535cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) vx_abs = vx = 0; 536cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (vy_abs < min_swipe_velocity_) 537cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) vy_abs = vy = 0; 538cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 539cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Note that the ratio will be 0 if both velocites are below the min. 540cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) float ratio = vx_abs > vy_abs ? vx_abs / std::max(vy_abs, 0.001f) 541cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) : vy_abs / std::max(vx_abs, 0.001f); 542cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 543cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (ratio < min_swipe_direction_component_ratio_) 544cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return false; 545cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 546cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (vx_abs > vy_abs) 547cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) vy = 0; 548cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) else 549cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) vx = 0; 550cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return listener_->OnSwipe(*current_down_event_, up, vx, vy); 551cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 552cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 553a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} // namespace ui 554