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