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/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 |