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_) | |
tdresser
2014/09/08 15:52:47
I prefer adding {} when the body of a conditional
lanwei
2014/09/08 16:14:52
Done.
| |
125 max_diameter_before_show_press_ = | |
126 std::max(max_diameter_before_show_press_, event.GetTouchMajor()); | |
204 } | 127 } |
205 } | 128 } |
206 | 129 |
207 void Send(GestureEventData gesture) { | 130 void Send(GestureEventData gesture) { |
208 DCHECK(!gesture.time.is_null()); | 131 DCHECK(!gesture.time.is_null()); |
209 // The only valid events that should be sent without an active touch | 132 // 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 | 133 // sequence are SHOW_PRESS and TAP, potentially triggered by the double-tap |
211 // delay timing out. | 134 // delay timing out. |
212 DCHECK(!current_down_time_.is_null() || gesture.type() == ET_GESTURE_TAP || | 135 DCHECK(!current_down_time_.is_null() || gesture.type() == ET_GESTURE_TAP || |
213 gesture.type() == ET_GESTURE_SHOW_PRESS || | 136 gesture.type() == ET_GESTURE_SHOW_PRESS || |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
290 if (!pinch_event_sent_) { | 213 if (!pinch_event_sent_) { |
291 Send(CreateGesture(ET_GESTURE_PINCH_BEGIN, | 214 Send(CreateGesture(ET_GESTURE_PINCH_BEGIN, |
292 e.GetId(), | 215 e.GetId(), |
293 e.GetToolType(), | 216 e.GetToolType(), |
294 detector.GetEventTime(), | 217 detector.GetEventTime(), |
295 detector.GetFocusX(), | 218 detector.GetFocusX(), |
296 detector.GetFocusY(), | 219 detector.GetFocusY(), |
297 detector.GetFocusX() + e.GetRawOffsetX(), | 220 detector.GetFocusX() + e.GetRawOffsetX(), |
298 detector.GetFocusY() + e.GetRawOffsetY(), | 221 detector.GetFocusY() + e.GetRawOffsetY(), |
299 e.GetPointerCount(), | 222 e.GetPointerCount(), |
300 GetBoundingBox(e))); | 223 GetBoundingBox(e, ET_GESTURE_PINCH_BEGIN))); |
301 } | 224 } |
302 | 225 |
303 if (std::abs(detector.GetCurrentSpan() - detector.GetPreviousSpan()) < | 226 if (std::abs(detector.GetCurrentSpan() - detector.GetPreviousSpan()) < |
304 config_.scale_gesture_detector_config.min_pinch_update_span_delta) { | 227 config_.scale_gesture_detector_config.min_pinch_update_span_delta) { |
305 return false; | 228 return false; |
306 } | 229 } |
307 | 230 |
308 float scale = detector.GetScaleFactor(); | 231 float scale = detector.GetScaleFactor(); |
309 if (scale == 1) | 232 if (scale == 1) |
310 return true; | 233 return true; |
(...skipping 13 matching lines...) Expand all Loading... | |
324 GestureEventDetails pinch_details(ET_GESTURE_PINCH_UPDATE, scale, 0); | 247 GestureEventDetails pinch_details(ET_GESTURE_PINCH_UPDATE, scale, 0); |
325 Send(CreateGesture(pinch_details, | 248 Send(CreateGesture(pinch_details, |
326 e.GetId(), | 249 e.GetId(), |
327 e.GetToolType(), | 250 e.GetToolType(), |
328 detector.GetEventTime(), | 251 detector.GetEventTime(), |
329 detector.GetFocusX(), | 252 detector.GetFocusX(), |
330 detector.GetFocusY(), | 253 detector.GetFocusY(), |
331 detector.GetFocusX() + e.GetRawOffsetX(), | 254 detector.GetFocusX() + e.GetRawOffsetX(), |
332 detector.GetFocusY() + e.GetRawOffsetY(), | 255 detector.GetFocusY() + e.GetRawOffsetY(), |
333 e.GetPointerCount(), | 256 e.GetPointerCount(), |
334 GetBoundingBox(e))); | 257 GetBoundingBox(e, pinch_details.type()))); |
335 return true; | 258 return true; |
336 } | 259 } |
337 | 260 |
338 // GestureDetector::GestureListener implementation. | 261 // GestureDetector::GestureListener implementation. |
339 virtual bool OnDown(const MotionEvent& e) OVERRIDE { | 262 virtual bool OnDown(const MotionEvent& e) OVERRIDE { |
340 GestureEventDetails tap_details(ET_GESTURE_TAP_DOWN, 0, 0); | 263 GestureEventDetails tap_details(ET_GESTURE_TAP_DOWN, 0, 0); |
341 Send(CreateGesture(tap_details, e)); | 264 Send(CreateGesture(tap_details, e)); |
342 | 265 |
343 // Return true to indicate that we want to handle touch. | 266 // Return true to indicate that we want to handle touch. |
344 return true; | 267 return true; |
(...skipping 29 matching lines...) Expand all Loading... | |
374 // used to determine which layer the scroll should affect. | 297 // used to determine which layer the scroll should affect. |
375 Send(CreateGesture(scroll_details, | 298 Send(CreateGesture(scroll_details, |
376 e2.GetId(), | 299 e2.GetId(), |
377 e2.GetToolType(), | 300 e2.GetToolType(), |
378 e2.GetEventTime(), | 301 e2.GetEventTime(), |
379 e1.GetX(), | 302 e1.GetX(), |
380 e1.GetY(), | 303 e1.GetY(), |
381 e1.GetRawX(), | 304 e1.GetRawX(), |
382 e1.GetRawY(), | 305 e1.GetRawY(), |
383 e2.GetPointerCount(), | 306 e2.GetPointerCount(), |
384 GetBoundingBox(e2))); | 307 GetBoundingBox(e2, scroll_details.type()))); |
385 DCHECK(scroll_event_sent_); | 308 DCHECK(scroll_event_sent_); |
386 } | 309 } |
387 | 310 |
388 snap_scroll_controller_.UpdateSnapScrollMode(distance_x, distance_y); | 311 snap_scroll_controller_.UpdateSnapScrollMode(distance_x, distance_y); |
389 if (snap_scroll_controller_.IsSnappingScrolls()) { | 312 if (snap_scroll_controller_.IsSnappingScrolls()) { |
390 if (snap_scroll_controller_.IsSnapHorizontal()) | 313 if (snap_scroll_controller_.IsSnapHorizontal()) |
391 distance_y = 0; | 314 distance_y = 0; |
392 else | 315 else |
393 distance_x = 0; | 316 distance_x = 0; |
394 } | 317 } |
395 | 318 |
396 if (distance_x || distance_y) { | 319 if (distance_x || distance_y) { |
397 const gfx::RectF bounding_box = GetBoundingBox(e2); | 320 GestureEventDetails scroll_details( |
321 ET_GESTURE_SCROLL_UPDATE, -distance_x, -distance_y); | |
322 const gfx::RectF bounding_box = GetBoundingBox(e2, scroll_details.type()); | |
398 const gfx::PointF center = bounding_box.CenterPoint(); | 323 const gfx::PointF center = bounding_box.CenterPoint(); |
399 const gfx::PointF raw_center = | 324 const gfx::PointF raw_center = |
400 center + gfx::Vector2dF(e2.GetRawOffsetX(), e2.GetRawOffsetY()); | 325 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, | 326 Send(CreateGesture(scroll_details, |
404 e2.GetId(), | 327 e2.GetId(), |
405 e2.GetToolType(), | 328 e2.GetToolType(), |
406 e2.GetEventTime(), | 329 e2.GetEventTime(), |
407 center.x(), | 330 center.x(), |
408 center.y(), | 331 center.y(), |
409 raw_center.x(), | 332 raw_center.x(), |
410 raw_center.y(), | 333 raw_center.y(), |
411 e2.GetPointerCount(), | 334 e2.GetPointerCount(), |
412 bounding_box)); | 335 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()); | 385 ET_GESTURE_TWO_FINGER_TAP, e1.GetTouchMajor(), e1.GetTouchMajor()); |
463 Send(CreateGesture(two_finger_tap_details, | 386 Send(CreateGesture(two_finger_tap_details, |
464 e2.GetId(), | 387 e2.GetId(), |
465 e2.GetToolType(), | 388 e2.GetToolType(), |
466 e2.GetEventTime(), | 389 e2.GetEventTime(), |
467 e1.GetX(), | 390 e1.GetX(), |
468 e1.GetY(), | 391 e1.GetY(), |
469 e1.GetRawX(), | 392 e1.GetRawX(), |
470 e1.GetRawY(), | 393 e1.GetRawY(), |
471 e2.GetPointerCount(), | 394 e2.GetPointerCount(), |
472 GetBoundingBox(e2))); | 395 GetBoundingBox(e2, two_finger_tap_details.type()))); |
473 return true; | 396 return true; |
474 } | 397 } |
475 | 398 |
476 virtual void OnShowPress(const MotionEvent& e) OVERRIDE { | 399 virtual void OnShowPress(const MotionEvent& e) OVERRIDE { |
477 GestureEventDetails show_press_details(ET_GESTURE_SHOW_PRESS, 0, 0); | 400 GestureEventDetails show_press_details(ET_GESTURE_SHOW_PRESS, 0, 0); |
401 show_press_event_sent_ = true; | |
478 Send(CreateGesture(show_press_details, e)); | 402 Send(CreateGesture(show_press_details, e)); |
479 } | 403 } |
480 | 404 |
481 virtual bool OnSingleTapUp(const MotionEvent& e) OVERRIDE { | 405 virtual bool OnSingleTapUp(const MotionEvent& e) OVERRIDE { |
482 // This is a hack to address the issue where user hovers | 406 // This is a hack to address the issue where user hovers |
483 // over a link for longer than double_tap_timeout_, then | 407 // over a link for longer than double_tap_timeout_, then |
484 // OnSingleTapConfirmed() is not triggered. But we still | 408 // OnSingleTapConfirmed() is not triggered. But we still |
485 // want to trigger the tap event at UP. So we override | 409 // want to trigger the tap event at UP. So we override |
486 // OnSingleTapUp() in this case. This assumes singleTapUp | 410 // OnSingleTapUp() in this case. This assumes singleTapUp |
487 // gets always called before singleTapConfirmed. | 411 // gets always called before singleTapConfirmed. |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
549 return false; | 473 return false; |
550 } | 474 } |
551 | 475 |
552 virtual void OnLongPress(const MotionEvent& e) OVERRIDE { | 476 virtual void OnLongPress(const MotionEvent& e) OVERRIDE { |
553 DCHECK(!IsDoubleTapInProgress()); | 477 DCHECK(!IsDoubleTapInProgress()); |
554 SetIgnoreSingleTap(true); | 478 SetIgnoreSingleTap(true); |
555 GestureEventDetails long_press_details(ET_GESTURE_LONG_PRESS, 0, 0); | 479 GestureEventDetails long_press_details(ET_GESTURE_LONG_PRESS, 0, 0); |
556 Send(CreateGesture(long_press_details, e)); | 480 Send(CreateGesture(long_press_details, e)); |
557 } | 481 } |
558 | 482 |
483 GestureEventData CreateGesture(const GestureEventDetails& details, | |
484 int motion_event_id, | |
485 MotionEvent::ToolType primary_tool_type, | |
486 base::TimeTicks time, | |
487 float x, | |
488 float y, | |
489 float raw_x, | |
490 float raw_y, | |
491 size_t touch_point_count, | |
492 const gfx::RectF& bounding_box) { | |
493 return GestureEventData(details, | |
494 motion_event_id, | |
495 primary_tool_type, | |
496 time, | |
497 x, | |
498 y, | |
499 raw_x, | |
500 raw_y, | |
501 touch_point_count, | |
502 bounding_box); | |
503 } | |
504 | |
505 GestureEventData CreateGesture(EventType type, | |
506 int motion_event_id, | |
507 MotionEvent::ToolType primary_tool_type, | |
508 base::TimeTicks time, | |
509 float x, | |
510 float y, | |
511 float raw_x, | |
512 float raw_y, | |
513 size_t touch_point_count, | |
514 const gfx::RectF& bounding_box) { | |
515 return GestureEventData(GestureEventDetails(type, 0, 0), | |
516 motion_event_id, | |
517 primary_tool_type, | |
518 time, | |
519 x, | |
520 y, | |
521 raw_x, | |
522 raw_y, | |
523 touch_point_count, | |
524 bounding_box); | |
525 } | |
526 | |
527 GestureEventData CreateGesture(const GestureEventDetails& details, | |
528 const MotionEvent& event) { | |
529 return GestureEventData(details, | |
530 event.GetId(), | |
531 event.GetToolType(), | |
532 event.GetEventTime(), | |
533 event.GetX(), | |
534 event.GetY(), | |
535 event.GetRawX(), | |
536 event.GetRawY(), | |
537 event.GetPointerCount(), | |
538 GetBoundingBox(event, details.type())); | |
539 } | |
540 | |
541 GestureEventData CreateGesture(EventType type, const MotionEvent& event) { | |
542 return CreateGesture(GestureEventDetails(type, 0, 0), event); | |
543 } | |
544 | |
545 GestureEventData CreateTapGesture(EventType type, const MotionEvent& event) { | |
546 // Set the tap count to 1 even for ET_GESTURE_DOUBLE_TAP, in order to be | |
547 // consistent with double tap behavior on a mobile viewport. See | |
548 // crbug.com/234986 for context. | |
549 return CreateGesture(GestureEventDetails(type, 1, 0), event); | |
550 } | |
551 | |
552 gfx::RectF GetBoundingBox(const MotionEvent& event, EventType type) { | |
553 // Can't use gfx::RectF::Union, as it ignores touches with a radius of 0. | |
554 float left = std::numeric_limits<float>::max(); | |
555 float top = std::numeric_limits<float>::max(); | |
556 float right = -std::numeric_limits<float>::max(); | |
557 float bottom = -std::numeric_limits<float>::max(); | |
558 for (size_t i = 0; i < event.GetPointerCount(); ++i) { | |
559 float x, y, diameter; | |
560 // Only for the show press and tap events, the bounding box is calculated | |
561 // based on the touch start point and the maximum diameter before the | |
562 // show press event is sent. | |
563 if (type == ET_GESTURE_SHOW_PRESS || type == ET_GESTURE_TAP || | |
564 type == ET_GESTURE_TAP_UNCONFIRMED) { | |
565 DCHECK_EQ(0U, i); | |
566 diameter = max_diameter_before_show_press_; | |
567 x = tap_down_point_.x(); | |
568 y = tap_down_point_.y(); | |
569 } else { | |
570 diameter = event.GetTouchMajor(i); | |
571 x = event.GetX(i); | |
572 y = event.GetY(i); | |
573 } | |
574 x = x - diameter / 2; | |
575 y = y - diameter / 2; | |
576 left = std::min(left, x); | |
577 right = std::max(right, x + diameter); | |
578 top = std::min(top, y); | |
579 bottom = std::max(bottom, y + diameter); | |
580 } | |
581 return gfx::RectF(left, top, right - left, bottom - top); | |
582 } | |
583 | |
559 void SetDoubleTapEnabled(bool enabled) { | 584 void SetDoubleTapEnabled(bool enabled) { |
560 DCHECK(!IsDoubleTapInProgress()); | 585 DCHECK(!IsDoubleTapInProgress()); |
561 gesture_detector_.SetDoubleTapListener(enabled ? this : NULL); | 586 gesture_detector_.SetDoubleTapListener(enabled ? this : NULL); |
562 } | 587 } |
563 | 588 |
564 void SetMultiTouchZoomEnabled(bool enabled) { | 589 void SetMultiTouchZoomEnabled(bool enabled) { |
565 // Note that returning false from |OnScaleBegin()| or |OnScale()| prevents | 590 // Note that returning false from |OnScaleBegin()| or |OnScale()| prevents |
566 // the detector from emitting further scale updates for the current touch | 591 // the detector from emitting further scale updates for the current touch |
567 // sequence. Thus, if multitouch events are enabled in the middle of a | 592 // sequence. Thus, if multitouch events are enabled in the middle of a |
568 // gesture, it will only take effect with the next gesture. | 593 // 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, | 639 // 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, | 640 // always_in_tap_region_ is not reset. So when the last finger is up, |
616 // |OnSingleTapUp()| will be mistakenly fired. | 641 // |OnSingleTapUp()| will be mistakenly fired. |
617 bool ignore_single_tap_; | 642 bool ignore_single_tap_; |
618 | 643 |
619 // Tracks whether {PINCH|SCROLL}_BEGIN events have been forwarded for the | 644 // Tracks whether {PINCH|SCROLL}_BEGIN events have been forwarded for the |
620 // current touch sequence. | 645 // current touch sequence. |
621 bool pinch_event_sent_; | 646 bool pinch_event_sent_; |
622 bool scroll_event_sent_; | 647 bool scroll_event_sent_; |
623 | 648 |
649 // Only track the maximum diameter before the show press event has been | |
650 // sent and there must be a tap event happening afterwards. | |
tdresser
2014/09/08 15:52:47
It isn't that a tap event must happen afterwards,
lanwei
2014/09/08 16:14:52
Thanks.
Done.
| |
651 float max_diameter_before_show_press_; | |
652 | |
653 gfx::PointF tap_down_point_; | |
654 | |
655 // Tracks whether an ET_GESTURE_SHOW_PRESS event has been sent for this touch | |
656 // sequence. | |
657 bool show_press_event_sent_; | |
658 | |
624 DISALLOW_COPY_AND_ASSIGN(GestureListenerImpl); | 659 DISALLOW_COPY_AND_ASSIGN(GestureListenerImpl); |
625 }; | 660 }; |
626 | 661 |
627 // GestureProvider | 662 // GestureProvider |
628 | 663 |
629 GestureProvider::GestureProvider(const Config& config, | 664 GestureProvider::GestureProvider(const Config& config, |
630 GestureProviderClient* client) | 665 GestureProviderClient* client) |
631 : double_tap_support_for_page_(true), | 666 : double_tap_support_for_page_(true), |
632 double_tap_support_for_platform_(true), | 667 double_tap_support_for_platform_(true), |
633 gesture_begin_end_types_enabled_(config.gesture_begin_end_types_enabled) { | 668 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. | 732 // events. |
698 return current_down_event_ || event.GetAction() == MotionEvent::ACTION_DOWN || | 733 return current_down_event_ || event.GetAction() == MotionEvent::ACTION_DOWN || |
699 event.GetAction() == MotionEvent::ACTION_CANCEL; | 734 event.GetAction() == MotionEvent::ACTION_CANCEL; |
700 } | 735 } |
701 | 736 |
702 void GestureProvider::OnTouchEventHandlingBegin(const MotionEvent& event) { | 737 void GestureProvider::OnTouchEventHandlingBegin(const MotionEvent& event) { |
703 switch (event.GetAction()) { | 738 switch (event.GetAction()) { |
704 case MotionEvent::ACTION_DOWN: | 739 case MotionEvent::ACTION_DOWN: |
705 current_down_event_ = event.Clone(); | 740 current_down_event_ = event.Clone(); |
706 if (gesture_begin_end_types_enabled_) | 741 if (gesture_begin_end_types_enabled_) |
707 gesture_listener_->Send(CreateGesture(ET_GESTURE_BEGIN, event)); | 742 gesture_listener_->Send( |
743 gesture_listener_->CreateGesture(ET_GESTURE_BEGIN, event)); | |
708 break; | 744 break; |
709 case MotionEvent::ACTION_POINTER_DOWN: | 745 case MotionEvent::ACTION_POINTER_DOWN: |
710 if (gesture_begin_end_types_enabled_) { | 746 if (gesture_begin_end_types_enabled_) { |
711 const int action_index = event.GetActionIndex(); | 747 const int action_index = event.GetActionIndex(); |
712 gesture_listener_->Send(CreateGesture(ET_GESTURE_BEGIN, | 748 gesture_listener_->Send(gesture_listener_->CreateGesture( |
713 event.GetId(), | 749 ET_GESTURE_BEGIN, |
714 event.GetToolType(), | 750 event.GetId(), |
715 event.GetEventTime(), | 751 event.GetToolType(), |
716 event.GetX(action_index), | 752 event.GetEventTime(), |
717 event.GetY(action_index), | 753 event.GetX(action_index), |
718 event.GetRawX(action_index), | 754 event.GetY(action_index), |
719 event.GetRawY(action_index), | 755 event.GetRawX(action_index), |
720 event.GetPointerCount(), | 756 event.GetRawY(action_index), |
721 GetBoundingBox(event))); | 757 event.GetPointerCount(), |
758 gesture_listener_->GetBoundingBox(event, ET_GESTURE_BEGIN))); | |
722 } | 759 } |
723 break; | 760 break; |
724 case MotionEvent::ACTION_POINTER_UP: | 761 case MotionEvent::ACTION_POINTER_UP: |
725 case MotionEvent::ACTION_UP: | 762 case MotionEvent::ACTION_UP: |
726 case MotionEvent::ACTION_CANCEL: | 763 case MotionEvent::ACTION_CANCEL: |
727 case MotionEvent::ACTION_MOVE: | 764 case MotionEvent::ACTION_MOVE: |
728 break; | 765 break; |
729 } | 766 } |
730 } | 767 } |
731 | 768 |
732 void GestureProvider::OnTouchEventHandlingEnd(const MotionEvent& event) { | 769 void GestureProvider::OnTouchEventHandlingEnd(const MotionEvent& event) { |
733 switch (event.GetAction()) { | 770 switch (event.GetAction()) { |
734 case MotionEvent::ACTION_UP: | 771 case MotionEvent::ACTION_UP: |
735 case MotionEvent::ACTION_CANCEL: { | 772 case MotionEvent::ACTION_CANCEL: { |
736 if (gesture_begin_end_types_enabled_) | 773 if (gesture_begin_end_types_enabled_) |
737 gesture_listener_->Send(CreateGesture(ET_GESTURE_END, event)); | 774 gesture_listener_->Send( |
775 gesture_listener_->CreateGesture(ET_GESTURE_END, event)); | |
738 | 776 |
739 current_down_event_.reset(); | 777 current_down_event_.reset(); |
740 | 778 |
741 UpdateDoubleTapDetectionSupport(); | 779 UpdateDoubleTapDetectionSupport(); |
742 break; | 780 break; |
743 } | 781 } |
744 case MotionEvent::ACTION_POINTER_UP: | 782 case MotionEvent::ACTION_POINTER_UP: |
745 if (gesture_begin_end_types_enabled_) | 783 if (gesture_begin_end_types_enabled_) |
746 gesture_listener_->Send(CreateGesture(ET_GESTURE_END, event)); | 784 gesture_listener_->Send( |
785 gesture_listener_->CreateGesture(ET_GESTURE_END, event)); | |
747 break; | 786 break; |
748 case MotionEvent::ACTION_DOWN: | 787 case MotionEvent::ACTION_DOWN: |
749 case MotionEvent::ACTION_POINTER_DOWN: | 788 case MotionEvent::ACTION_POINTER_DOWN: |
750 case MotionEvent::ACTION_MOVE: | 789 case MotionEvent::ACTION_MOVE: |
751 break; | 790 break; |
752 } | 791 } |
753 } | 792 } |
754 | 793 |
755 void GestureProvider::UpdateDoubleTapDetectionSupport() { | 794 void GestureProvider::UpdateDoubleTapDetectionSupport() { |
756 // The GestureDetector requires that any provided DoubleTapListener remain | 795 // The GestureDetector requires that any provided DoubleTapListener remain |
757 // attached to it for the duration of a touch sequence. Defer any potential | 796 // attached to it for the duration of a touch sequence. Defer any potential |
758 // null'ing of the listener until the sequence has ended. | 797 // null'ing of the listener until the sequence has ended. |
759 if (current_down_event_) | 798 if (current_down_event_) |
760 return; | 799 return; |
761 | 800 |
762 const bool double_tap_enabled = | 801 const bool double_tap_enabled = |
763 double_tap_support_for_page_ && double_tap_support_for_platform_; | 802 double_tap_support_for_page_ && double_tap_support_for_platform_; |
764 gesture_listener_->SetDoubleTapEnabled(double_tap_enabled); | 803 gesture_listener_->SetDoubleTapEnabled(double_tap_enabled); |
765 } | 804 } |
766 | 805 |
767 } // namespace ui | 806 } // namespace ui |
OLD | NEW |