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 #include "ui/events/gesture_detection/gesture_provider.h" | 5 #include "ui/events/gesture_detection/gesture_provider.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 | 8 |
9 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
10 #include "base/debug/trace_event.h" | 10 #include "base/debug/trace_event.h" |
11 #include "ui/events/event_constants.h" | 11 #include "ui/events/event_constants.h" |
12 #include "ui/events/gesture_detection/gesture_event_data.h" | 12 #include "ui/events/gesture_detection/gesture_event_data.h" |
13 #include "ui/events/gesture_detection/motion_event.h" | 13 #include "ui/events/gesture_detection/motion_event.h" |
| 14 #include "ui/gfx/geometry/point_f.h" |
14 | 15 |
15 namespace ui { | 16 namespace ui { |
16 namespace { | 17 namespace { |
17 | 18 |
18 // Double-tap drag zoom sensitivity (speed). | 19 // Double-tap drag zoom sensitivity (speed). |
19 const float kDoubleTapDragZoomSpeed = 0.005f; | 20 const float kDoubleTapDragZoomSpeed = 0.005f; |
20 | 21 |
21 const char* GetMotionEventActionName(MotionEvent::Action action) { | 22 const char* GetMotionEventActionName(MotionEvent::Action action) { |
22 switch (action) { | 23 switch (action) { |
23 case MotionEvent::ACTION_POINTER_DOWN: | 24 case MotionEvent::ACTION_POINTER_DOWN: |
24 return "ACTION_POINTER_DOWN"; | 25 return "ACTION_POINTER_DOWN"; |
25 case MotionEvent::ACTION_POINTER_UP: | 26 case MotionEvent::ACTION_POINTER_UP: |
26 return "ACTION_POINTER_UP"; | 27 return "ACTION_POINTER_UP"; |
27 case MotionEvent::ACTION_DOWN: | 28 case MotionEvent::ACTION_DOWN: |
28 return "ACTION_DOWN"; | 29 return "ACTION_DOWN"; |
29 case MotionEvent::ACTION_UP: | 30 case MotionEvent::ACTION_UP: |
30 return "ACTION_UP"; | 31 return "ACTION_UP"; |
31 case MotionEvent::ACTION_CANCEL: | 32 case MotionEvent::ACTION_CANCEL: |
32 return "ACTION_CANCEL"; | 33 return "ACTION_CANCEL"; |
33 case MotionEvent::ACTION_MOVE: | 34 case MotionEvent::ACTION_MOVE: |
34 return "ACTION_MOVE"; | 35 return "ACTION_MOVE"; |
35 } | 36 } |
36 return ""; | 37 return ""; |
37 } | 38 } |
38 | 39 |
39 gfx::RectF GetBoundingBox(const MotionEvent& event) { | |
40 // Can't use gfx::RectF::Union, as it ignores touches with a radius of 0. | |
41 float left = std::numeric_limits<float>::max(); | |
42 float top = std::numeric_limits<float>::max(); | |
43 float right = -std::numeric_limits<float>::max(); | |
44 float bottom = -std::numeric_limits<float>::max(); | |
45 for (size_t i = 0; i < event.GetPointerCount(); ++i) { | |
46 float diameter = event.GetTouchMajor(i); | |
47 float x = event.GetX(i) - diameter / 2; | |
48 float y = event.GetY(i) - diameter / 2; | |
49 left = std::min(left, x); | |
50 right = std::max(right, x + diameter); | |
51 top = std::min(top, y); | |
52 bottom = std::max(bottom, y + diameter); | |
53 } | |
54 return gfx::RectF(left, top, right - left, bottom - top); | |
55 } | |
56 | |
57 GestureEventData CreateGesture(const GestureEventDetails& details, | |
58 int motion_event_id, | |
59 MotionEvent::ToolType primary_tool_type, | |
60 base::TimeTicks time, | |
61 float x, | |
62 float y, | |
63 float raw_x, | |
64 float raw_y, | |
65 size_t touch_point_count, | |
66 const gfx::RectF& bounding_box) { | |
67 return GestureEventData(details, | |
68 motion_event_id, | |
69 primary_tool_type, | |
70 time, | |
71 x, | |
72 y, | |
73 raw_x, | |
74 raw_y, | |
75 touch_point_count, | |
76 bounding_box); | |
77 } | |
78 | |
79 GestureEventData CreateGesture(EventType type, | |
80 int motion_event_id, | |
81 MotionEvent::ToolType primary_tool_type, | |
82 base::TimeTicks time, | |
83 float x, | |
84 float y, | |
85 float raw_x, | |
86 float raw_y, | |
87 size_t touch_point_count, | |
88 const gfx::RectF& bounding_box) { | |
89 return GestureEventData(GestureEventDetails(type, 0, 0), | |
90 motion_event_id, | |
91 primary_tool_type, | |
92 time, | |
93 x, | |
94 y, | |
95 raw_x, | |
96 raw_y, | |
97 touch_point_count, | |
98 bounding_box); | |
99 } | |
100 | |
101 GestureEventData CreateGesture(const GestureEventDetails& details, | |
102 const MotionEvent& event) { | |
103 return GestureEventData(details, | |
104 event.GetId(), | |
105 event.GetToolType(), | |
106 event.GetEventTime(), | |
107 event.GetX(), | |
108 event.GetY(), | |
109 event.GetRawX(), | |
110 event.GetRawY(), | |
111 event.GetPointerCount(), | |
112 GetBoundingBox(event)); | |
113 } | |
114 | |
115 GestureEventData CreateGesture(EventType type, const MotionEvent& event) { | |
116 return CreateGesture(GestureEventDetails(type, 0, 0), event); | |
117 } | |
118 | |
119 GestureEventData CreateTapGesture(EventType type, const MotionEvent& event) { | |
120 // Set the tap count to 1 even for ET_GESTURE_DOUBLE_TAP, in order to be | |
121 // consistent with double tap behavior on a mobile viewport. See | |
122 // crbug.com/234986 for context. | |
123 return CreateGesture(GestureEventDetails(type, 1, 0), event); | |
124 } | |
125 | |
126 gfx::RectF ClampBoundingBox(const gfx::RectF& bounds, | 40 gfx::RectF ClampBoundingBox(const gfx::RectF& bounds, |
127 float min_length, | 41 float min_length, |
128 float max_length) { | 42 float max_length) { |
129 float width = bounds.width(); | 43 float width = bounds.width(); |
130 float height = bounds.height(); | 44 float height = bounds.height(); |
131 if (min_length) { | 45 if (min_length) { |
132 width = std::max(min_length, width); | 46 width = std::max(min_length, width); |
133 height = std::max(min_length, height); | 47 height = std::max(min_length, height); |
134 } | 48 } |
135 if (max_length) { | 49 if (max_length) { |
(...skipping 30 matching lines...) Expand all Loading... |
166 GestureListenerImpl(const GestureProvider::Config& config, | 80 GestureListenerImpl(const GestureProvider::Config& config, |
167 GestureProviderClient* client) | 81 GestureProviderClient* client) |
168 : config_(config), | 82 : config_(config), |
169 client_(client), | 83 client_(client), |
170 gesture_detector_(config.gesture_detector_config, this, this), | 84 gesture_detector_(config.gesture_detector_config, this, this), |
171 scale_gesture_detector_(config.scale_gesture_detector_config, this), | 85 scale_gesture_detector_(config.scale_gesture_detector_config, this), |
172 snap_scroll_controller_(config.display), | 86 snap_scroll_controller_(config.display), |
173 ignore_multitouch_zoom_events_(false), | 87 ignore_multitouch_zoom_events_(false), |
174 ignore_single_tap_(false), | 88 ignore_single_tap_(false), |
175 pinch_event_sent_(false), | 89 pinch_event_sent_(false), |
176 scroll_event_sent_(false) {} | 90 scroll_event_sent_(false), |
| 91 max_diameter_before_show_press_(0), |
| 92 show_press_event_sent_(false) {} |
177 | 93 |
178 void OnTouchEvent(const MotionEvent& event) { | 94 void OnTouchEvent(const MotionEvent& event) { |
179 const bool in_scale_gesture = IsScaleGestureDetectionInProgress(); | 95 const bool in_scale_gesture = IsScaleGestureDetectionInProgress(); |
180 snap_scroll_controller_.SetSnapScrollingMode(event, in_scale_gesture); | 96 snap_scroll_controller_.SetSnapScrollingMode(event, in_scale_gesture); |
181 if (in_scale_gesture) | 97 if (in_scale_gesture) |
182 SetIgnoreSingleTap(true); | 98 SetIgnoreSingleTap(true); |
183 | 99 |
184 const MotionEvent::Action action = event.GetAction(); | 100 const MotionEvent::Action action = event.GetAction(); |
185 if (action == MotionEvent::ACTION_DOWN) { | 101 if (action == MotionEvent::ACTION_DOWN) { |
186 current_down_time_ = event.GetEventTime(); | 102 current_down_time_ = event.GetEventTime(); |
187 current_longpress_time_ = base::TimeTicks(); | 103 current_longpress_time_ = base::TimeTicks(); |
188 ignore_single_tap_ = false; | 104 ignore_single_tap_ = false; |
189 scroll_event_sent_ = false; | 105 scroll_event_sent_ = false; |
190 pinch_event_sent_ = false; | 106 pinch_event_sent_ = false; |
| 107 show_press_event_sent_ = false; |
191 gesture_detector_.set_longpress_enabled(true); | 108 gesture_detector_.set_longpress_enabled(true); |
| 109 tap_down_point_ = gfx::PointF(event.GetX(), event.GetY()); |
| 110 max_diameter_before_show_press_ = event.GetTouchMajor(); |
192 } | 111 } |
193 | 112 |
194 gesture_detector_.OnTouchEvent(event); | 113 gesture_detector_.OnTouchEvent(event); |
195 scale_gesture_detector_.OnTouchEvent(event); | 114 scale_gesture_detector_.OnTouchEvent(event); |
196 | 115 |
197 if (action == MotionEvent::ACTION_UP || | 116 if (action == MotionEvent::ACTION_UP || |
198 action == MotionEvent::ACTION_CANCEL) { | 117 action == MotionEvent::ACTION_CANCEL) { |
199 // Note: This call will have no effect if a fling was just generated, as | 118 // Note: This call will have no effect if a fling was just generated, as |
200 // |Fling()| will have already signalled an end to touch-scrolling. | 119 // |Fling()| will have already signalled an end to touch-scrolling. |
201 if (scroll_event_sent_) | 120 if (scroll_event_sent_) |
202 Send(CreateGesture(ET_GESTURE_SCROLL_END, event)); | 121 Send(CreateGesture(ET_GESTURE_SCROLL_END, event)); |
203 current_down_time_ = base::TimeTicks(); | 122 current_down_time_ = base::TimeTicks(); |
| 123 } else if (action == MotionEvent::ACTION_MOVE) { |
| 124 if (!show_press_event_sent_ && !scroll_event_sent_) { |
| 125 max_diameter_before_show_press_ = |
| 126 std::max(max_diameter_before_show_press_, event.GetTouchMajor()); |
| 127 } |
204 } | 128 } |
205 } | 129 } |
206 | 130 |
207 void Send(GestureEventData gesture) { | 131 void Send(GestureEventData gesture) { |
208 DCHECK(!gesture.time.is_null()); | 132 DCHECK(!gesture.time.is_null()); |
209 // The only valid events that should be sent without an active touch | 133 // The only valid events that should be sent without an active touch |
210 // sequence are SHOW_PRESS and TAP, potentially triggered by the double-tap | 134 // sequence are SHOW_PRESS and TAP, potentially triggered by the double-tap |
211 // delay timing out. | 135 // delay timing out. |
212 DCHECK(!current_down_time_.is_null() || gesture.type() == ET_GESTURE_TAP || | 136 DCHECK(!current_down_time_.is_null() || gesture.type() == ET_GESTURE_TAP || |
213 gesture.type() == ET_GESTURE_SHOW_PRESS || | 137 gesture.type() == ET_GESTURE_SHOW_PRESS || |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
290 if (!pinch_event_sent_) { | 214 if (!pinch_event_sent_) { |
291 Send(CreateGesture(ET_GESTURE_PINCH_BEGIN, | 215 Send(CreateGesture(ET_GESTURE_PINCH_BEGIN, |
292 e.GetId(), | 216 e.GetId(), |
293 e.GetToolType(), | 217 e.GetToolType(), |
294 detector.GetEventTime(), | 218 detector.GetEventTime(), |
295 detector.GetFocusX(), | 219 detector.GetFocusX(), |
296 detector.GetFocusY(), | 220 detector.GetFocusY(), |
297 detector.GetFocusX() + e.GetRawOffsetX(), | 221 detector.GetFocusX() + e.GetRawOffsetX(), |
298 detector.GetFocusY() + e.GetRawOffsetY(), | 222 detector.GetFocusY() + e.GetRawOffsetY(), |
299 e.GetPointerCount(), | 223 e.GetPointerCount(), |
300 GetBoundingBox(e))); | 224 GetBoundingBox(e, ET_GESTURE_PINCH_BEGIN))); |
301 } | 225 } |
302 | 226 |
303 if (std::abs(detector.GetCurrentSpan() - detector.GetPreviousSpan()) < | 227 if (std::abs(detector.GetCurrentSpan() - detector.GetPreviousSpan()) < |
304 config_.scale_gesture_detector_config.min_pinch_update_span_delta) { | 228 config_.scale_gesture_detector_config.min_pinch_update_span_delta) { |
305 return false; | 229 return false; |
306 } | 230 } |
307 | 231 |
308 float scale = detector.GetScaleFactor(); | 232 float scale = detector.GetScaleFactor(); |
309 if (scale == 1) | 233 if (scale == 1) |
310 return true; | 234 return true; |
(...skipping 13 matching lines...) Expand all Loading... |
324 GestureEventDetails pinch_details(ET_GESTURE_PINCH_UPDATE, scale, 0); | 248 GestureEventDetails pinch_details(ET_GESTURE_PINCH_UPDATE, scale, 0); |
325 Send(CreateGesture(pinch_details, | 249 Send(CreateGesture(pinch_details, |
326 e.GetId(), | 250 e.GetId(), |
327 e.GetToolType(), | 251 e.GetToolType(), |
328 detector.GetEventTime(), | 252 detector.GetEventTime(), |
329 detector.GetFocusX(), | 253 detector.GetFocusX(), |
330 detector.GetFocusY(), | 254 detector.GetFocusY(), |
331 detector.GetFocusX() + e.GetRawOffsetX(), | 255 detector.GetFocusX() + e.GetRawOffsetX(), |
332 detector.GetFocusY() + e.GetRawOffsetY(), | 256 detector.GetFocusY() + e.GetRawOffsetY(), |
333 e.GetPointerCount(), | 257 e.GetPointerCount(), |
334 GetBoundingBox(e))); | 258 GetBoundingBox(e, pinch_details.type()))); |
335 return true; | 259 return true; |
336 } | 260 } |
337 | 261 |
338 // GestureDetector::GestureListener implementation. | 262 // GestureDetector::GestureListener implementation. |
339 virtual bool OnDown(const MotionEvent& e) OVERRIDE { | 263 virtual bool OnDown(const MotionEvent& e) OVERRIDE { |
340 GestureEventDetails tap_details(ET_GESTURE_TAP_DOWN, 0, 0); | 264 GestureEventDetails tap_details(ET_GESTURE_TAP_DOWN, 0, 0); |
341 Send(CreateGesture(tap_details, e)); | 265 Send(CreateGesture(tap_details, e)); |
342 | 266 |
343 // Return true to indicate that we want to handle touch. | 267 // Return true to indicate that we want to handle touch. |
344 return true; | 268 return true; |
(...skipping 29 matching lines...) Expand all Loading... |
374 // used to determine which layer the scroll should affect. | 298 // used to determine which layer the scroll should affect. |
375 Send(CreateGesture(scroll_details, | 299 Send(CreateGesture(scroll_details, |
376 e2.GetId(), | 300 e2.GetId(), |
377 e2.GetToolType(), | 301 e2.GetToolType(), |
378 e2.GetEventTime(), | 302 e2.GetEventTime(), |
379 e1.GetX(), | 303 e1.GetX(), |
380 e1.GetY(), | 304 e1.GetY(), |
381 e1.GetRawX(), | 305 e1.GetRawX(), |
382 e1.GetRawY(), | 306 e1.GetRawY(), |
383 e2.GetPointerCount(), | 307 e2.GetPointerCount(), |
384 GetBoundingBox(e2))); | 308 GetBoundingBox(e2, scroll_details.type()))); |
385 DCHECK(scroll_event_sent_); | 309 DCHECK(scroll_event_sent_); |
386 } | 310 } |
387 | 311 |
388 snap_scroll_controller_.UpdateSnapScrollMode(distance_x, distance_y); | 312 snap_scroll_controller_.UpdateSnapScrollMode(distance_x, distance_y); |
389 if (snap_scroll_controller_.IsSnappingScrolls()) { | 313 if (snap_scroll_controller_.IsSnappingScrolls()) { |
390 if (snap_scroll_controller_.IsSnapHorizontal()) | 314 if (snap_scroll_controller_.IsSnapHorizontal()) |
391 distance_y = 0; | 315 distance_y = 0; |
392 else | 316 else |
393 distance_x = 0; | 317 distance_x = 0; |
394 } | 318 } |
395 | 319 |
396 if (distance_x || distance_y) { | 320 if (distance_x || distance_y) { |
397 const gfx::RectF bounding_box = GetBoundingBox(e2); | 321 GestureEventDetails scroll_details( |
| 322 ET_GESTURE_SCROLL_UPDATE, -distance_x, -distance_y); |
| 323 const gfx::RectF bounding_box = GetBoundingBox(e2, scroll_details.type()); |
398 const gfx::PointF center = bounding_box.CenterPoint(); | 324 const gfx::PointF center = bounding_box.CenterPoint(); |
399 const gfx::PointF raw_center = | 325 const gfx::PointF raw_center = |
400 center + gfx::Vector2dF(e2.GetRawOffsetX(), e2.GetRawOffsetY()); | 326 center + gfx::Vector2dF(e2.GetRawOffsetX(), e2.GetRawOffsetY()); |
401 GestureEventDetails scroll_details( | |
402 ET_GESTURE_SCROLL_UPDATE, -distance_x, -distance_y); | |
403 Send(CreateGesture(scroll_details, | 327 Send(CreateGesture(scroll_details, |
404 e2.GetId(), | 328 e2.GetId(), |
405 e2.GetToolType(), | 329 e2.GetToolType(), |
406 e2.GetEventTime(), | 330 e2.GetEventTime(), |
407 center.x(), | 331 center.x(), |
408 center.y(), | 332 center.y(), |
409 raw_center.x(), | 333 raw_center.x(), |
410 raw_center.y(), | 334 raw_center.y(), |
411 e2.GetPointerCount(), | 335 e2.GetPointerCount(), |
412 bounding_box)); | 336 bounding_box)); |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
462 ET_GESTURE_TWO_FINGER_TAP, e1.GetTouchMajor(), e1.GetTouchMajor()); | 386 ET_GESTURE_TWO_FINGER_TAP, e1.GetTouchMajor(), e1.GetTouchMajor()); |
463 Send(CreateGesture(two_finger_tap_details, | 387 Send(CreateGesture(two_finger_tap_details, |
464 e2.GetId(), | 388 e2.GetId(), |
465 e2.GetToolType(), | 389 e2.GetToolType(), |
466 e2.GetEventTime(), | 390 e2.GetEventTime(), |
467 e1.GetX(), | 391 e1.GetX(), |
468 e1.GetY(), | 392 e1.GetY(), |
469 e1.GetRawX(), | 393 e1.GetRawX(), |
470 e1.GetRawY(), | 394 e1.GetRawY(), |
471 e2.GetPointerCount(), | 395 e2.GetPointerCount(), |
472 GetBoundingBox(e2))); | 396 GetBoundingBox(e2, two_finger_tap_details.type()))); |
473 return true; | 397 return true; |
474 } | 398 } |
475 | 399 |
476 virtual void OnShowPress(const MotionEvent& e) OVERRIDE { | 400 virtual void OnShowPress(const MotionEvent& e) OVERRIDE { |
477 GestureEventDetails show_press_details(ET_GESTURE_SHOW_PRESS, 0, 0); | 401 GestureEventDetails show_press_details(ET_GESTURE_SHOW_PRESS, 0, 0); |
| 402 show_press_event_sent_ = true; |
478 Send(CreateGesture(show_press_details, e)); | 403 Send(CreateGesture(show_press_details, e)); |
479 } | 404 } |
480 | 405 |
481 virtual bool OnSingleTapUp(const MotionEvent& e) OVERRIDE { | 406 virtual bool OnSingleTapUp(const MotionEvent& e) OVERRIDE { |
482 // This is a hack to address the issue where user hovers | 407 // This is a hack to address the issue where user hovers |
483 // over a link for longer than double_tap_timeout_, then | 408 // over a link for longer than double_tap_timeout_, then |
484 // OnSingleTapConfirmed() is not triggered. But we still | 409 // OnSingleTapConfirmed() is not triggered. But we still |
485 // want to trigger the tap event at UP. So we override | 410 // want to trigger the tap event at UP. So we override |
486 // OnSingleTapUp() in this case. This assumes singleTapUp | 411 // OnSingleTapUp() in this case. This assumes singleTapUp |
487 // gets always called before singleTapConfirmed. | 412 // gets always called before singleTapConfirmed. |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
549 return false; | 474 return false; |
550 } | 475 } |
551 | 476 |
552 virtual void OnLongPress(const MotionEvent& e) OVERRIDE { | 477 virtual void OnLongPress(const MotionEvent& e) OVERRIDE { |
553 DCHECK(!IsDoubleTapInProgress()); | 478 DCHECK(!IsDoubleTapInProgress()); |
554 SetIgnoreSingleTap(true); | 479 SetIgnoreSingleTap(true); |
555 GestureEventDetails long_press_details(ET_GESTURE_LONG_PRESS, 0, 0); | 480 GestureEventDetails long_press_details(ET_GESTURE_LONG_PRESS, 0, 0); |
556 Send(CreateGesture(long_press_details, e)); | 481 Send(CreateGesture(long_press_details, e)); |
557 } | 482 } |
558 | 483 |
| 484 GestureEventData CreateGesture(const GestureEventDetails& details, |
| 485 int motion_event_id, |
| 486 MotionEvent::ToolType primary_tool_type, |
| 487 base::TimeTicks time, |
| 488 float x, |
| 489 float y, |
| 490 float raw_x, |
| 491 float raw_y, |
| 492 size_t touch_point_count, |
| 493 const gfx::RectF& bounding_box) { |
| 494 return GestureEventData(details, |
| 495 motion_event_id, |
| 496 primary_tool_type, |
| 497 time, |
| 498 x, |
| 499 y, |
| 500 raw_x, |
| 501 raw_y, |
| 502 touch_point_count, |
| 503 bounding_box); |
| 504 } |
| 505 |
| 506 GestureEventData CreateGesture(EventType type, |
| 507 int motion_event_id, |
| 508 MotionEvent::ToolType primary_tool_type, |
| 509 base::TimeTicks time, |
| 510 float x, |
| 511 float y, |
| 512 float raw_x, |
| 513 float raw_y, |
| 514 size_t touch_point_count, |
| 515 const gfx::RectF& bounding_box) { |
| 516 return GestureEventData(GestureEventDetails(type, 0, 0), |
| 517 motion_event_id, |
| 518 primary_tool_type, |
| 519 time, |
| 520 x, |
| 521 y, |
| 522 raw_x, |
| 523 raw_y, |
| 524 touch_point_count, |
| 525 bounding_box); |
| 526 } |
| 527 |
| 528 GestureEventData CreateGesture(const GestureEventDetails& details, |
| 529 const MotionEvent& event) { |
| 530 return GestureEventData(details, |
| 531 event.GetId(), |
| 532 event.GetToolType(), |
| 533 event.GetEventTime(), |
| 534 event.GetX(), |
| 535 event.GetY(), |
| 536 event.GetRawX(), |
| 537 event.GetRawY(), |
| 538 event.GetPointerCount(), |
| 539 GetBoundingBox(event, details.type())); |
| 540 } |
| 541 |
| 542 GestureEventData CreateGesture(EventType type, const MotionEvent& event) { |
| 543 return CreateGesture(GestureEventDetails(type, 0, 0), event); |
| 544 } |
| 545 |
| 546 GestureEventData CreateTapGesture(EventType type, const MotionEvent& event) { |
| 547 // Set the tap count to 1 even for ET_GESTURE_DOUBLE_TAP, in order to be |
| 548 // consistent with double tap behavior on a mobile viewport. See |
| 549 // crbug.com/234986 for context. |
| 550 return CreateGesture(GestureEventDetails(type, 1, 0), event); |
| 551 } |
| 552 |
| 553 gfx::RectF GetBoundingBox(const MotionEvent& event, EventType type) { |
| 554 // Can't use gfx::RectF::Union, as it ignores touches with a radius of 0. |
| 555 float left = std::numeric_limits<float>::max(); |
| 556 float top = std::numeric_limits<float>::max(); |
| 557 float right = -std::numeric_limits<float>::max(); |
| 558 float bottom = -std::numeric_limits<float>::max(); |
| 559 for (size_t i = 0; i < event.GetPointerCount(); ++i) { |
| 560 float x, y, diameter; |
| 561 // Only for the show press and tap events, the bounding box is calculated |
| 562 // based on the touch start point and the maximum diameter before the |
| 563 // show press event is sent. |
| 564 if (type == ET_GESTURE_SHOW_PRESS || type == ET_GESTURE_TAP || |
| 565 type == ET_GESTURE_TAP_UNCONFIRMED) { |
| 566 DCHECK_EQ(0U, i); |
| 567 diameter = max_diameter_before_show_press_; |
| 568 x = tap_down_point_.x(); |
| 569 y = tap_down_point_.y(); |
| 570 } else { |
| 571 diameter = event.GetTouchMajor(i); |
| 572 x = event.GetX(i); |
| 573 y = event.GetY(i); |
| 574 } |
| 575 x = x - diameter / 2; |
| 576 y = y - diameter / 2; |
| 577 left = std::min(left, x); |
| 578 right = std::max(right, x + diameter); |
| 579 top = std::min(top, y); |
| 580 bottom = std::max(bottom, y + diameter); |
| 581 } |
| 582 return gfx::RectF(left, top, right - left, bottom - top); |
| 583 } |
| 584 |
559 void SetDoubleTapEnabled(bool enabled) { | 585 void SetDoubleTapEnabled(bool enabled) { |
560 DCHECK(!IsDoubleTapInProgress()); | 586 DCHECK(!IsDoubleTapInProgress()); |
561 gesture_detector_.SetDoubleTapListener(enabled ? this : NULL); | 587 gesture_detector_.SetDoubleTapListener(enabled ? this : NULL); |
562 } | 588 } |
563 | 589 |
564 void SetMultiTouchZoomEnabled(bool enabled) { | 590 void SetMultiTouchZoomEnabled(bool enabled) { |
565 // Note that returning false from |OnScaleBegin()| or |OnScale()| prevents | 591 // Note that returning false from |OnScaleBegin()| or |OnScale()| prevents |
566 // the detector from emitting further scale updates for the current touch | 592 // the detector from emitting further scale updates for the current touch |
567 // sequence. Thus, if multitouch events are enabled in the middle of a | 593 // sequence. Thus, if multitouch events are enabled in the middle of a |
568 // gesture, it will only take effect with the next gesture. | 594 // gesture, it will only take effect with the next gesture. |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
614 // TODO(klobag): This is to avoid a bug in GestureDetector. With multi-touch, | 640 // TODO(klobag): This is to avoid a bug in GestureDetector. With multi-touch, |
615 // always_in_tap_region_ is not reset. So when the last finger is up, | 641 // always_in_tap_region_ is not reset. So when the last finger is up, |
616 // |OnSingleTapUp()| will be mistakenly fired. | 642 // |OnSingleTapUp()| will be mistakenly fired. |
617 bool ignore_single_tap_; | 643 bool ignore_single_tap_; |
618 | 644 |
619 // Tracks whether {PINCH|SCROLL}_BEGIN events have been forwarded for the | 645 // Tracks whether {PINCH|SCROLL}_BEGIN events have been forwarded for the |
620 // current touch sequence. | 646 // current touch sequence. |
621 bool pinch_event_sent_; | 647 bool pinch_event_sent_; |
622 bool scroll_event_sent_; | 648 bool scroll_event_sent_; |
623 | 649 |
| 650 // Only track the maximum diameter before the show press event has been |
| 651 // sent and a tap must still be possible for this touch sequence. |
| 652 float max_diameter_before_show_press_; |
| 653 |
| 654 gfx::PointF tap_down_point_; |
| 655 |
| 656 // Tracks whether an ET_GESTURE_SHOW_PRESS event has been sent for this touch |
| 657 // sequence. |
| 658 bool show_press_event_sent_; |
| 659 |
624 DISALLOW_COPY_AND_ASSIGN(GestureListenerImpl); | 660 DISALLOW_COPY_AND_ASSIGN(GestureListenerImpl); |
625 }; | 661 }; |
626 | 662 |
627 // GestureProvider | 663 // GestureProvider |
628 | 664 |
629 GestureProvider::GestureProvider(const Config& config, | 665 GestureProvider::GestureProvider(const Config& config, |
630 GestureProviderClient* client) | 666 GestureProviderClient* client) |
631 : double_tap_support_for_page_(true), | 667 : double_tap_support_for_page_(true), |
632 double_tap_support_for_platform_(true), | 668 double_tap_support_for_platform_(true), |
633 gesture_begin_end_types_enabled_(config.gesture_begin_end_types_enabled) { | 669 gesture_begin_end_types_enabled_(config.gesture_begin_end_types_enabled) { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
697 // events. | 733 // events. |
698 return current_down_event_ || event.GetAction() == MotionEvent::ACTION_DOWN || | 734 return current_down_event_ || event.GetAction() == MotionEvent::ACTION_DOWN || |
699 event.GetAction() == MotionEvent::ACTION_CANCEL; | 735 event.GetAction() == MotionEvent::ACTION_CANCEL; |
700 } | 736 } |
701 | 737 |
702 void GestureProvider::OnTouchEventHandlingBegin(const MotionEvent& event) { | 738 void GestureProvider::OnTouchEventHandlingBegin(const MotionEvent& event) { |
703 switch (event.GetAction()) { | 739 switch (event.GetAction()) { |
704 case MotionEvent::ACTION_DOWN: | 740 case MotionEvent::ACTION_DOWN: |
705 current_down_event_ = event.Clone(); | 741 current_down_event_ = event.Clone(); |
706 if (gesture_begin_end_types_enabled_) | 742 if (gesture_begin_end_types_enabled_) |
707 gesture_listener_->Send(CreateGesture(ET_GESTURE_BEGIN, event)); | 743 gesture_listener_->Send( |
| 744 gesture_listener_->CreateGesture(ET_GESTURE_BEGIN, event)); |
708 break; | 745 break; |
709 case MotionEvent::ACTION_POINTER_DOWN: | 746 case MotionEvent::ACTION_POINTER_DOWN: |
710 if (gesture_begin_end_types_enabled_) { | 747 if (gesture_begin_end_types_enabled_) { |
711 const int action_index = event.GetActionIndex(); | 748 const int action_index = event.GetActionIndex(); |
712 gesture_listener_->Send(CreateGesture(ET_GESTURE_BEGIN, | 749 gesture_listener_->Send(gesture_listener_->CreateGesture( |
713 event.GetId(), | 750 ET_GESTURE_BEGIN, |
714 event.GetToolType(), | 751 event.GetId(), |
715 event.GetEventTime(), | 752 event.GetToolType(), |
716 event.GetX(action_index), | 753 event.GetEventTime(), |
717 event.GetY(action_index), | 754 event.GetX(action_index), |
718 event.GetRawX(action_index), | 755 event.GetY(action_index), |
719 event.GetRawY(action_index), | 756 event.GetRawX(action_index), |
720 event.GetPointerCount(), | 757 event.GetRawY(action_index), |
721 GetBoundingBox(event))); | 758 event.GetPointerCount(), |
| 759 gesture_listener_->GetBoundingBox(event, ET_GESTURE_BEGIN))); |
722 } | 760 } |
723 break; | 761 break; |
724 case MotionEvent::ACTION_POINTER_UP: | 762 case MotionEvent::ACTION_POINTER_UP: |
725 case MotionEvent::ACTION_UP: | 763 case MotionEvent::ACTION_UP: |
726 case MotionEvent::ACTION_CANCEL: | 764 case MotionEvent::ACTION_CANCEL: |
727 case MotionEvent::ACTION_MOVE: | 765 case MotionEvent::ACTION_MOVE: |
728 break; | 766 break; |
729 } | 767 } |
730 } | 768 } |
731 | 769 |
732 void GestureProvider::OnTouchEventHandlingEnd(const MotionEvent& event) { | 770 void GestureProvider::OnTouchEventHandlingEnd(const MotionEvent& event) { |
733 switch (event.GetAction()) { | 771 switch (event.GetAction()) { |
734 case MotionEvent::ACTION_UP: | 772 case MotionEvent::ACTION_UP: |
735 case MotionEvent::ACTION_CANCEL: { | 773 case MotionEvent::ACTION_CANCEL: { |
736 if (gesture_begin_end_types_enabled_) | 774 if (gesture_begin_end_types_enabled_) |
737 gesture_listener_->Send(CreateGesture(ET_GESTURE_END, event)); | 775 gesture_listener_->Send( |
| 776 gesture_listener_->CreateGesture(ET_GESTURE_END, event)); |
738 | 777 |
739 current_down_event_.reset(); | 778 current_down_event_.reset(); |
740 | 779 |
741 UpdateDoubleTapDetectionSupport(); | 780 UpdateDoubleTapDetectionSupport(); |
742 break; | 781 break; |
743 } | 782 } |
744 case MotionEvent::ACTION_POINTER_UP: | 783 case MotionEvent::ACTION_POINTER_UP: |
745 if (gesture_begin_end_types_enabled_) | 784 if (gesture_begin_end_types_enabled_) |
746 gesture_listener_->Send(CreateGesture(ET_GESTURE_END, event)); | 785 gesture_listener_->Send( |
| 786 gesture_listener_->CreateGesture(ET_GESTURE_END, event)); |
747 break; | 787 break; |
748 case MotionEvent::ACTION_DOWN: | 788 case MotionEvent::ACTION_DOWN: |
749 case MotionEvent::ACTION_POINTER_DOWN: | 789 case MotionEvent::ACTION_POINTER_DOWN: |
750 case MotionEvent::ACTION_MOVE: | 790 case MotionEvent::ACTION_MOVE: |
751 break; | 791 break; |
752 } | 792 } |
753 } | 793 } |
754 | 794 |
755 void GestureProvider::UpdateDoubleTapDetectionSupport() { | 795 void GestureProvider::UpdateDoubleTapDetectionSupport() { |
756 // The GestureDetector requires that any provided DoubleTapListener remain | 796 // The GestureDetector requires that any provided DoubleTapListener remain |
757 // attached to it for the duration of a touch sequence. Defer any potential | 797 // attached to it for the duration of a touch sequence. Defer any potential |
758 // null'ing of the listener until the sequence has ended. | 798 // null'ing of the listener until the sequence has ended. |
759 if (current_down_event_) | 799 if (current_down_event_) |
760 return; | 800 return; |
761 | 801 |
762 const bool double_tap_enabled = | 802 const bool double_tap_enabled = |
763 double_tap_support_for_page_ && double_tap_support_for_platform_; | 803 double_tap_support_for_page_ && double_tap_support_for_platform_; |
764 gesture_listener_->SetDoubleTapEnabled(double_tap_enabled); | 804 gesture_listener_->SetDoubleTapEnabled(double_tap_enabled); |
765 } | 805 } |
766 | 806 |
767 } // namespace ui | 807 } // namespace ui |
OLD | NEW |