Chromium Code Reviews| 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 |