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

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

Issue 243403002: Add multi-finger swipe detection to GestureDetector (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Test three finger swipe Created 6 years, 8 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 #include "ui/events/gesture_detection/gesture_detector.h" 5 #include "ui/events/gesture_detection/gesture_detector.h"
6 6
7 #include <cmath> 7 #include <cmath>
8 8
9 #include "base/timer/timer.h" 9 #include "base/timer/timer.h"
10 #include "ui/events/gesture_detection/motion_event.h" 10 #include "ui/events/gesture_detection/motion_event.h"
(...skipping 22 matching lines...) Expand all
33 33
34 // Note: These constants were taken directly from the default (unscaled) 34 // Note: These constants were taken directly from the default (unscaled)
35 // versions found in Android's ViewConfiguration. 35 // versions found in Android's ViewConfiguration.
36 GestureDetector::Config::Config() 36 GestureDetector::Config::Config()
37 : longpress_timeout(base::TimeDelta::FromMilliseconds(500)), 37 : longpress_timeout(base::TimeDelta::FromMilliseconds(500)),
38 showpress_timeout(base::TimeDelta::FromMilliseconds(180)), 38 showpress_timeout(base::TimeDelta::FromMilliseconds(180)),
39 double_tap_timeout(base::TimeDelta::FromMilliseconds(300)), 39 double_tap_timeout(base::TimeDelta::FromMilliseconds(300)),
40 touch_slop(8), 40 touch_slop(8),
41 double_tap_slop(100), 41 double_tap_slop(100),
42 minimum_fling_velocity(50), 42 minimum_fling_velocity(50),
43 maximum_fling_velocity(8000) {} 43 maximum_fling_velocity(8000),
44 swipe_enabled(false),
45 minimum_swipe_velocity(20),
46 minimum_swipe_direction_ratio(3) {
47 }
44 48
45 GestureDetector::Config::~Config() {} 49 GestureDetector::Config::~Config() {}
46 50
47 bool GestureDetector::SimpleGestureListener::OnDown(const MotionEvent& e) { 51 bool GestureDetector::SimpleGestureListener::OnDown(const MotionEvent& e) {
48 return false; 52 return false;
49 } 53 }
50 54
51 void GestureDetector::SimpleGestureListener::OnShowPress(const MotionEvent& e) { 55 void GestureDetector::SimpleGestureListener::OnShowPress(const MotionEvent& e) {
52 } 56 }
53 57
(...skipping 13 matching lines...) Expand all
67 return false; 71 return false;
68 } 72 }
69 73
70 bool GestureDetector::SimpleGestureListener::OnFling(const MotionEvent& e1, 74 bool GestureDetector::SimpleGestureListener::OnFling(const MotionEvent& e1,
71 const MotionEvent& e2, 75 const MotionEvent& e2,
72 float velocity_x, 76 float velocity_x,
73 float velocity_y) { 77 float velocity_y) {
74 return false; 78 return false;
75 } 79 }
76 80
81 bool GestureDetector::SimpleGestureListener::OnSwipe(const MotionEvent& e1,
82 const MotionEvent& e2,
83 float velocity_x,
84 float velocity_y) {
85 return false;
86 }
87
77 bool GestureDetector::SimpleGestureListener::OnSingleTapConfirmed( 88 bool GestureDetector::SimpleGestureListener::OnSingleTapConfirmed(
78 const MotionEvent& e) { 89 const MotionEvent& e) {
79 return false; 90 return false;
80 } 91 }
81 92
82 bool GestureDetector::SimpleGestureListener::OnDoubleTap(const MotionEvent& e) { 93 bool GestureDetector::SimpleGestureListener::OnDoubleTap(const MotionEvent& e) {
83 return false; 94 return false;
84 } 95 }
85 96
86 bool GestureDetector::SimpleGestureListener::OnDoubleTapEvent( 97 bool GestureDetector::SimpleGestureListener::OnDoubleTapEvent(
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 still_down_(false), 162 still_down_(false),
152 defer_confirm_single_tap_(false), 163 defer_confirm_single_tap_(false),
153 in_longpress_(false), 164 in_longpress_(false),
154 always_in_tap_region_(false), 165 always_in_tap_region_(false),
155 always_in_bigger_tap_region_(false), 166 always_in_bigger_tap_region_(false),
156 is_double_tapping_(false), 167 is_double_tapping_(false),
157 last_focus_x_(0), 168 last_focus_x_(0),
158 last_focus_y_(0), 169 last_focus_y_(0),
159 down_focus_x_(0), 170 down_focus_x_(0),
160 down_focus_y_(0), 171 down_focus_y_(0),
161 is_longpress_enabled_(true) { 172 longpress_enabled_(true) {
162 DCHECK(listener_); 173 DCHECK(listener_);
163 Init(config); 174 Init(config);
164 } 175 }
165 176
166 GestureDetector::~GestureDetector() {} 177 GestureDetector::~GestureDetector() {}
167 178
168 bool GestureDetector::OnTouchEvent(const MotionEvent& ev) { 179 bool GestureDetector::OnTouchEvent(const MotionEvent& ev) {
169 const MotionEvent::Action action = ev.GetAction(); 180 const MotionEvent::Action action = ev.GetAction();
170 181
171 velocity_tracker_.AddMovement(ev); 182 velocity_tracker_.AddMovement(ev);
(...skipping 27 matching lines...) Expand all
199 case MotionEvent::ACTION_POINTER_UP: 210 case MotionEvent::ACTION_POINTER_UP:
200 down_focus_x_ = last_focus_x_ = focus_x; 211 down_focus_x_ = last_focus_x_ = focus_x;
201 down_focus_y_ = last_focus_y_ = focus_y; 212 down_focus_y_ = last_focus_y_ = focus_y;
202 213
203 // Check the dot product of current velocities. 214 // Check the dot product of current velocities.
204 // If the pointer that left was opposing another velocity vector, clear. 215 // If the pointer that left was opposing another velocity vector, clear.
205 velocity_tracker_.ComputeCurrentVelocity(1000, max_fling_velocity_); 216 velocity_tracker_.ComputeCurrentVelocity(1000, max_fling_velocity_);
206 { 217 {
207 const int up_index = ev.GetActionIndex(); 218 const int up_index = ev.GetActionIndex();
208 const int id1 = ev.GetPointerId(up_index); 219 const int id1 = ev.GetPointerId(up_index);
209 const float x1 = velocity_tracker_.GetXVelocity(id1); 220 const float vx1 = velocity_tracker_.GetXVelocity(id1);
tdresser 2014/04/22 15:27:16 I was envisioning adding an independent object to
210 const float y1 = velocity_tracker_.GetYVelocity(id1); 221 const float vy1 = velocity_tracker_.GetYVelocity(id1);
222 float vx_total = vx1;
223 float vy_total = vy1;
211 for (int i = 0; i < count; i++) { 224 for (int i = 0; i < count; i++) {
212 if (i == up_index) 225 if (i == up_index)
213 continue; 226 continue;
214 227
215 const int id2 = ev.GetPointerId(i); 228 const int id2 = ev.GetPointerId(i);
216 const float x = x1 * velocity_tracker_.GetXVelocity(id2); 229 const float vx2 = velocity_tracker_.GetXVelocity(id2);
217 const float y = y1 * velocity_tracker_.GetYVelocity(id2); 230 const float vy2 = velocity_tracker_.GetYVelocity(id2);
218 231 const float dot = vx1 * vx2 + vy1 * vy2;
219 const float dot = x + y;
220 if (dot < 0) { 232 if (dot < 0) {
233 vx_total = 0;
234 vy_total = 0;
221 velocity_tracker_.Clear(); 235 velocity_tracker_.Clear();
222 break; 236 break;
223 } 237 }
238 vx_total += vx2;
239 vy_total += vy2;
240 }
241
242 if (swipe_enabled_ && (vx_total || vy_total)) {
243 float vx = vx_total / count;
244 float vy = vy_total / count;
245 float vx_abs = std::abs(vx);
246 float vy_abs = std::abs(vy);
247
248 if (vx_abs < min_swipe_velocity_)
249 vx_abs = vx = 0;
250 if (vy_abs < min_swipe_velocity_)
251 vy_abs = vy = 0;
252
253 // Note that the ratio will be 0 if both velocites are below the min.
254 float ratio = vx_abs > vy_abs ? vx_abs / std::max(vy_abs, 0.001f)
255 : vy_abs / std::max(vx_abs, 0.001f);
256 if (ratio > min_swipe_direction_ratio_) {
257 if (vx_abs > vy_abs)
258 vy = 0;
259 else
260 vx = 0;
261
262 handled = listener_->OnSwipe(*current_down_event_, ev, vx, vy);
263 }
224 } 264 }
225 } 265 }
226 break; 266 break;
227 267
228 case MotionEvent::ACTION_DOWN: 268 case MotionEvent::ACTION_DOWN:
229 if (double_tap_listener_) { 269 if (double_tap_listener_) {
230 bool had_tap_message = timeout_handler_->HasTimeout(TAP); 270 bool had_tap_message = timeout_handler_->HasTimeout(TAP);
231 if (had_tap_message) 271 if (had_tap_message)
232 timeout_handler_->StopTimeout(TAP); 272 timeout_handler_->StopTimeout(TAP);
233 if (current_down_event_ && previous_up_event_ && had_tap_message && 273 if (current_down_event_ && previous_up_event_ && had_tap_message &&
(...skipping 18 matching lines...) Expand all
252 292
253 always_in_tap_region_ = true; 293 always_in_tap_region_ = true;
254 always_in_bigger_tap_region_ = true; 294 always_in_bigger_tap_region_ = true;
255 still_down_ = true; 295 still_down_ = true;
256 in_longpress_ = false; 296 in_longpress_ = false;
257 defer_confirm_single_tap_ = false; 297 defer_confirm_single_tap_ = false;
258 298
259 // Always start the SHOW_PRESS timer before the LONG_PRESS timer to ensure 299 // Always start the SHOW_PRESS timer before the LONG_PRESS timer to ensure
260 // proper timeout ordering. 300 // proper timeout ordering.
261 timeout_handler_->StartTimeout(SHOW_PRESS); 301 timeout_handler_->StartTimeout(SHOW_PRESS);
262 if (is_longpress_enabled_) 302 if (longpress_enabled_)
263 timeout_handler_->StartTimeout(LONG_PRESS); 303 timeout_handler_->StartTimeout(LONG_PRESS);
264 handled |= listener_->OnDown(ev); 304 handled |= listener_->OnDown(ev);
265 break; 305 break;
266 306
267 case MotionEvent::ACTION_MOVE: 307 case MotionEvent::ACTION_MOVE:
268 if (in_longpress_) 308 if (in_longpress_)
269 break; 309 break;
270 310
271 { 311 {
272 const float scroll_x = last_focus_x_ - focus_x; 312 const float scroll_x = last_focus_x_ - focus_x;
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 410
371 const float touch_slop = config.touch_slop + kSlopEpsilon; 411 const float touch_slop = config.touch_slop + kSlopEpsilon;
372 const float double_tap_touch_slop = touch_slop; 412 const float double_tap_touch_slop = touch_slop;
373 const float double_tap_slop = config.double_tap_slop + kSlopEpsilon; 413 const float double_tap_slop = config.double_tap_slop + kSlopEpsilon;
374 touch_slop_square_ = touch_slop * touch_slop; 414 touch_slop_square_ = touch_slop * touch_slop;
375 double_tap_touch_slop_square_ = double_tap_touch_slop * double_tap_touch_slop; 415 double_tap_touch_slop_square_ = double_tap_touch_slop * double_tap_touch_slop;
376 double_tap_slop_square_ = double_tap_slop * double_tap_slop; 416 double_tap_slop_square_ = double_tap_slop * double_tap_slop;
377 double_tap_timeout_ = config.double_tap_timeout; 417 double_tap_timeout_ = config.double_tap_timeout;
378 min_fling_velocity_ = config.minimum_fling_velocity; 418 min_fling_velocity_ = config.minimum_fling_velocity;
379 max_fling_velocity_ = config.maximum_fling_velocity; 419 max_fling_velocity_ = config.maximum_fling_velocity;
420 swipe_enabled_ = config.swipe_enabled;
421 min_swipe_velocity_ = config.minimum_swipe_velocity;
422 min_swipe_direction_ratio_ = config.minimum_swipe_direction_ratio;
380 } 423 }
381 424
382 void GestureDetector::OnShowPressTimeout() { 425 void GestureDetector::OnShowPressTimeout() {
383 listener_->OnShowPress(*current_down_event_); 426 listener_->OnShowPress(*current_down_event_);
384 } 427 }
385 428
386 void GestureDetector::OnLongPressTimeout() { 429 void GestureDetector::OnLongPressTimeout() {
387 timeout_handler_->StopTimeout(TAP); 430 timeout_handler_->StopTimeout(TAP);
388 defer_confirm_single_tap_ = false; 431 defer_confirm_single_tap_ = false;
389 in_longpress_ = listener_->OnLongPress(*current_down_event_); 432 in_longpress_ = listener_->OnLongPress(*current_down_event_);
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 if (second_down.GetEventTime() - first_up.GetEventTime() > 471 if (second_down.GetEventTime() - first_up.GetEventTime() >
429 double_tap_timeout_) 472 double_tap_timeout_)
430 return false; 473 return false;
431 474
432 const float delta_x = first_down.GetX() - second_down.GetX(); 475 const float delta_x = first_down.GetX() - second_down.GetX();
433 const float delta_y = first_down.GetY() - second_down.GetY(); 476 const float delta_y = first_down.GetY() - second_down.GetY();
434 return (delta_x * delta_x + delta_y * delta_y < double_tap_slop_square_); 477 return (delta_x * delta_x + delta_y * delta_y < double_tap_slop_square_);
435 } 478 }
436 479
437 } // namespace ui 480 } // namespace ui
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698