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" |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 36 float y, | 36 float y, |
| 37 const GestureEventDetails& details) { | 37 const GestureEventDetails& details) { |
| 38 return GestureEventData(type, time, x, y, details); | 38 return GestureEventData(type, time, x, y, details); |
| 39 } | 39 } |
| 40 | 40 |
| 41 GestureEventData CreateGesture(EventType type, | 41 GestureEventData CreateGesture(EventType type, |
| 42 base::TimeTicks time, | 42 base::TimeTicks time, |
| 43 float x, | 43 float x, |
| 44 float y) { | 44 float y) { |
| 45 return GestureEventData(type, time, x, y); | 45 return GestureEventData(type, time, x, y); |
| 46 } | 46 } |
| 47 | 47 |
| 48 GestureEventData CreateGesture(EventType type, | 48 GestureEventData CreateGesture(EventType type, |
| 49 const MotionEvent& event, | 49 const MotionEvent& event, |
| 50 const GestureEventDetails& details) { | 50 const GestureEventDetails& details) { |
| 51 return CreateGesture( | 51 return CreateGesture( |
| 52 type, event.GetEventTime(), event.GetX(), event.GetY(), details); | 52 type, event.GetEventTime(), event.GetX(), event.GetY(), details); |
| 53 } | 53 } |
| 54 | 54 |
| 55 GestureEventData CreateGesture(EventType type, | 55 GestureEventData CreateGesture(EventType type, |
| 56 const MotionEvent& event) { | 56 const MotionEvent& event) { |
| 57 return CreateGesture(type, event.GetEventTime(), event.GetX(), event.GetY()); | 57 return CreateGesture(type, event.GetEventTime(), event.GetX(), event.GetY()); |
| 58 } | 58 } |
| 59 | 59 |
| 60 float Round(float f) { | |
| 61 return (f > 0.f) ? std::floor(f + 0.5f) : std::ceil(f - 0.5f); | |
| 62 } | |
| 63 | |
| 64 GestureEventDetails CreateTapGestureDetails(EventType type, | 60 GestureEventDetails CreateTapGestureDetails(EventType type, |
| 65 const MotionEvent& event) { | 61 const MotionEvent& event) { |
| 66 // Set the tap count to 1 even for ET_GESTURE_DOUBLE_TAP, in order to be | 62 // Set the tap count to 1 even for ET_GESTURE_DOUBLE_TAP, in order to be |
| 67 // consistent with double tap behavior on a mobile viewport. See | 63 // consistent with double tap behavior on a mobile viewport. See |
| 68 // crbug.com/234986 for context. | 64 // crbug.com/234986 for context. |
| 69 GestureEventDetails tap_details(type, 1, 0); | 65 GestureEventDetails tap_details(type, 1, 0); |
| 70 tap_details.set_bounding_box( | 66 tap_details.set_bounding_box( |
| 71 gfx::RectF(event.GetTouchMajor(), event.GetTouchMajor())); | 67 gfx::RectF(event.GetTouchMajor(), event.GetTouchMajor())); |
| 72 return tap_details; | 68 return tap_details; |
| 73 } | 69 } |
| 74 | 70 |
| 75 } // namespace | 71 } // namespace |
| 76 | 72 |
| 77 // GestureProvider:::Config | 73 // GestureProvider:::Config |
| 78 | 74 |
| 79 GestureProvider::Config::Config() : disable_click_delay(false) {} | 75 GestureProvider::Config::Config() : disable_click_delay(false) {} |
| 80 | 76 |
| 81 GestureProvider::Config::~Config() {} | 77 GestureProvider::Config::~Config() {} |
| 82 | 78 |
| 83 // GestureProvider::ScaleGestureListener | 79 // GestureProvider::ScaleGestureListener |
| 84 | 80 |
| 85 class GestureProvider::ScaleGestureListenerImpl | 81 class GestureProvider::ScaleGestureListenerImpl |
| 86 : public ScaleGestureDetector::ScaleGestureListener { | 82 : public ScaleGestureDetector::ScaleGestureListener { |
| 87 public: | 83 public: |
| 88 ScaleGestureListenerImpl(const ScaleGestureDetector::Config& config, | 84 ScaleGestureListenerImpl(const ScaleGestureDetector::Config& config, |
| 85 float device_scale_factor, | |
| 89 GestureProvider* provider) | 86 GestureProvider* provider) |
| 90 : scale_gesture_detector_(config, this), | 87 : scale_gesture_detector_(config, this), |
| 91 provider_(provider), | 88 provider_(provider), |
| 92 ignore_detector_events_(false), | 89 px_to_dp_(1.0f / device_scale_factor), |
| 90 ignore_multitouch_events_(false), | |
| 93 pinch_event_sent_(false) {} | 91 pinch_event_sent_(false) {} |
| 94 | 92 |
| 95 bool OnTouchEvent(const MotionEvent& event) { | 93 bool OnTouchEvent(const MotionEvent& event) { |
| 96 // TODO: Need to deal with multi-touch transition. | 94 // TODO: Need to deal with multi-touch transition. |
| 97 const bool in_scale_gesture = IsScaleGestureDetectionInProgress(); | 95 const bool in_scale_gesture = IsScaleGestureDetectionInProgress(); |
| 98 bool handled = scale_gesture_detector_.OnTouchEvent(event); | 96 bool handled = scale_gesture_detector_.OnTouchEvent(event); |
| 99 if (!in_scale_gesture && | 97 if (!in_scale_gesture && |
| 100 (event.GetAction() == MotionEvent::ACTION_UP || | 98 (event.GetAction() == MotionEvent::ACTION_UP || |
| 101 event.GetAction() == MotionEvent::ACTION_CANCEL)) { | 99 event.GetAction() == MotionEvent::ACTION_CANCEL)) { |
| 102 return false; | 100 return false; |
| 103 } | 101 } |
| 104 return handled; | 102 return handled; |
| 105 } | 103 } |
| 106 | 104 |
| 107 // ScaleGestureDetector::ScaleGestureListener implementation. | 105 // ScaleGestureDetector::ScaleGestureListener implementation. |
| 108 virtual bool OnScaleBegin(const ScaleGestureDetector& detector) OVERRIDE { | 106 virtual bool OnScaleBegin(const ScaleGestureDetector& detector) OVERRIDE { |
| 109 if (ignore_detector_events_) | 107 if (ignore_multitouch_events_ && !detector.InDoubleTapMode()) |
| 110 return false; | 108 return false; |
| 111 pinch_event_sent_ = false; | 109 pinch_event_sent_ = false; |
| 112 return true; | 110 return true; |
| 113 } | 111 } |
| 114 | 112 |
| 115 virtual void OnScaleEnd(const ScaleGestureDetector& detector) OVERRIDE { | 113 virtual void OnScaleEnd(const ScaleGestureDetector& detector) OVERRIDE { |
| 116 if (!pinch_event_sent_) | 114 if (!pinch_event_sent_) |
| 117 return; | 115 return; |
| 118 provider_->Send( | 116 provider_->Send( |
| 119 CreateGesture(ET_GESTURE_PINCH_END, detector.GetEventTime(), 0, 0)); | 117 CreateGesture(ET_GESTURE_PINCH_END, detector.GetEventTime(), 0, 0)); |
| 120 pinch_event_sent_ = false; | 118 pinch_event_sent_ = false; |
| 121 } | 119 } |
| 122 | 120 |
| 123 virtual bool OnScale(const ScaleGestureDetector& detector) OVERRIDE { | 121 virtual bool OnScale(const ScaleGestureDetector& detector) OVERRIDE { |
| 124 if (ignore_detector_events_) | 122 if (ignore_multitouch_events_ && !detector.InDoubleTapMode()) |
| 125 return false; | 123 return false; |
| 126 if (!pinch_event_sent_) { | 124 if (!pinch_event_sent_) { |
| 127 pinch_event_sent_ = true; | 125 pinch_event_sent_ = true; |
| 128 provider_->Send(CreateGesture(ET_GESTURE_PINCH_BEGIN, | 126 provider_->Send(CreateGesture(ET_GESTURE_PINCH_BEGIN, |
| 129 detector.GetEventTime(), | 127 detector.GetEventTime(), |
| 130 detector.GetFocusX(), | 128 detector.GetFocusX(), |
| 131 detector.GetFocusY())); | 129 detector.GetFocusY())); |
| 132 } | 130 } |
| 133 GestureEventDetails pinch_details( | 131 |
| 134 ET_GESTURE_PINCH_UPDATE, detector.GetScaleFactor(), 0); | 132 float scale = detector.GetScaleFactor(); |
| 133 if (scale == 1) | |
| 134 return true; | |
| 135 | |
| 136 if (detector.InDoubleTapMode()) { | |
| 137 // Relative changes in the double-tap scale factor computed by |detector| | |
| 138 // diminish as the touch moves away from the original double-tap focus. | |
| 139 // Instead, compute a scale factor delta invariant to the distance, where | |
| 140 // the scale delta remains constant if the touch velocity is constant. | |
| 141 float dy = | |
| 142 (detector.GetCurrentSpanY() - detector.GetPreviousSpanY()) * 0.5f; | |
| 143 scale = std::pow(scale > 1 ? 1.0f + kDoubleTapDragZoomSpeed | |
| 144 : 1.0f - kDoubleTapDragZoomSpeed, | |
| 145 std::abs(dy * px_to_dp_)); | |
|
tdresser
2014/04/03 17:53:30
Do we have any justification for why Chromium and
jdduke (slow)
2014/04/03 19:28:01
I don't, but I can find out.
| |
| 146 } | |
| 147 GestureEventDetails pinch_details(ET_GESTURE_PINCH_UPDATE, scale, 0); | |
| 135 provider_->Send(CreateGesture(ET_GESTURE_PINCH_UPDATE, | 148 provider_->Send(CreateGesture(ET_GESTURE_PINCH_UPDATE, |
| 136 detector.GetEventTime(), | 149 detector.GetEventTime(), |
| 137 detector.GetFocusX(), | 150 detector.GetFocusX(), |
| 138 detector.GetFocusY(), | 151 detector.GetFocusY(), |
| 139 pinch_details)); | 152 pinch_details)); |
| 140 return true; | 153 return true; |
| 141 } | 154 } |
| 142 | 155 |
| 143 bool IsScaleGestureDetectionInProgress() const { | 156 void SetDoubleTapSupportEnabled(bool enabled) { |
|
tdresser
2014/04/03 17:53:30
Maybe just "SetDoubleTapEnabled"?
jdduke (slow)
2014/04/03 19:28:01
Done.
| |
| 144 return !ignore_detector_events_ && scale_gesture_detector_.IsInProgress(); | 157 DCHECK(!IsDoubleTapInProgress()); |
| 158 scale_gesture_detector_.SetQuickScaleEnabled(enabled); | |
| 145 } | 159 } |
| 146 | 160 |
| 147 void set_ignore_detector_events(bool value) { | 161 void SetMultiTouchSupportEnabled(bool value) { |
| 148 // Note that returning false from OnScaleBegin / OnScale makes the | 162 // Note that returning false from OnScaleBegin / OnScale makes the |
| 149 // gesture detector not to emit further scaling notifications | 163 // gesture detector not to emit further scaling notifications |
| 150 // related to this gesture. Thus, if detector events are enabled in | 164 // related to this gesture. Thus, if detector events are enabled in |
| 151 // the middle of the gesture, we don't need to do anything. | 165 // the middle of the gesture, we don't need to do anything. |
| 152 ignore_detector_events_ = value; | 166 ignore_multitouch_events_ = value; |
| 167 } | |
| 168 | |
| 169 bool IsDoubleTapInProgress() const { | |
| 170 return IsScaleGestureDetectionInProgress() && InDoubleTapMode(); | |
| 171 } | |
| 172 | |
| 173 bool IsScaleGestureDetectionInProgress() const { | |
| 174 return scale_gesture_detector_.IsInProgress(); | |
| 153 } | 175 } |
| 154 | 176 |
| 155 private: | 177 private: |
| 178 bool InDoubleTapMode() const { | |
| 179 return scale_gesture_detector_.InDoubleTapMode(); | |
| 180 } | |
| 181 | |
| 156 ScaleGestureDetector scale_gesture_detector_; | 182 ScaleGestureDetector scale_gesture_detector_; |
| 157 | 183 |
| 158 GestureProvider* const provider_; | 184 GestureProvider* const provider_; |
| 159 | 185 |
| 186 // TODO(jdduke): Remove this when all MotionEvent's use DIPs. | |
| 187 const float px_to_dp_; | |
| 188 | |
| 160 // Completely silence scaling events. Used in WebView when zoom support | 189 // Completely silence scaling events. Used in WebView when zoom support |
| 161 // is turned off. | 190 // is turned off. |
| 162 bool ignore_detector_events_; | 191 bool ignore_multitouch_events_; |
|
tdresser
2014/04/03 17:53:30
The comment and the variable name don't line up he
jdduke (slow)
2014/04/03 19:28:01
Oops yeah didn't notice the comment, thanks.
| |
| 163 | 192 |
| 164 // Whether any pinch zoom event has been sent to native. | 193 // Whether any pinch zoom event has been sent to native. |
| 165 bool pinch_event_sent_; | 194 bool pinch_event_sent_; |
| 166 | 195 |
| 167 DISALLOW_COPY_AND_ASSIGN(ScaleGestureListenerImpl); | 196 DISALLOW_COPY_AND_ASSIGN(ScaleGestureListenerImpl); |
| 168 }; | 197 }; |
| 169 | 198 |
| 170 // GestureProvider::GestureListener | 199 // GestureProvider::GestureListener |
| 171 | 200 |
| 172 class GestureProvider::GestureListenerImpl | 201 class GestureProvider::GestureListenerImpl |
| 173 : public GestureDetector::GestureListener, | 202 : public GestureDetector::GestureListener, |
| 174 public GestureDetector::DoubleTapListener { | 203 public GestureDetector::DoubleTapListener { |
| 175 public: | 204 public: |
| 176 GestureListenerImpl( | 205 GestureListenerImpl( |
| 177 const GestureDetector::Config& gesture_detector_config, | 206 const GestureDetector::Config& gesture_detector_config, |
| 178 const SnapScrollController::Config& snap_scroll_controller_config, | 207 const SnapScrollController::Config& snap_scroll_controller_config, |
| 179 bool disable_click_delay, | 208 bool disable_click_delay, |
| 180 GestureProvider* provider) | 209 GestureProvider* provider) |
| 181 : gesture_detector_(gesture_detector_config, this, this), | 210 : gesture_detector_(gesture_detector_config, this, this), |
| 182 snap_scroll_controller_(snap_scroll_controller_config), | 211 snap_scroll_controller_(snap_scroll_controller_config), |
| 183 provider_(provider), | 212 provider_(provider), |
| 184 px_to_dp_(1.0f / snap_scroll_controller_config.device_scale_factor), | |
| 185 disable_click_delay_(disable_click_delay), | 213 disable_click_delay_(disable_click_delay), |
| 186 scaled_touch_slop_(gesture_detector_config.scaled_touch_slop), | 214 scaled_touch_slop_(gesture_detector_config.scaled_touch_slop), |
| 187 scaled_touch_slop_square_(scaled_touch_slop_ * scaled_touch_slop_), | 215 scaled_touch_slop_square_(scaled_touch_slop_ * scaled_touch_slop_), |
| 188 double_tap_timeout_(gesture_detector_config.double_tap_timeout), | 216 double_tap_timeout_(gesture_detector_config.double_tap_timeout), |
| 189 ignore_single_tap_(false), | 217 ignore_single_tap_(false), |
| 190 seen_first_scroll_event_(false), | 218 seen_first_scroll_event_(false), |
| 191 double_tap_mode_(DOUBLE_TAP_MODE_NONE), | |
| 192 double_tap_y_(0), | |
| 193 double_tap_support_enabled_(true), | |
| 194 double_tap_drag_zoom_anchor_x_(0), | |
| 195 double_tap_drag_zoom_anchor_y_(0), | |
| 196 last_raw_x_(0), | 219 last_raw_x_(0), |
| 197 last_raw_y_(0), | 220 last_raw_y_(0), |
| 198 accumulated_scroll_error_x_(0), | 221 accumulated_scroll_error_x_(0), |
| 199 accumulated_scroll_error_y_(0) { | 222 accumulated_scroll_error_y_(0) {} |
| 200 UpdateDoubleTapListener(); | |
| 201 } | |
| 202 | 223 |
| 203 virtual ~GestureListenerImpl() {} | 224 virtual ~GestureListenerImpl() {} |
| 204 | 225 |
| 205 bool OnTouchEvent(const MotionEvent& e, | 226 bool OnTouchEvent(const MotionEvent& e, |
| 206 bool is_scale_gesture_detection_in_progress) { | 227 bool is_scale_gesture_detection_in_progress) { |
| 207 snap_scroll_controller_.SetSnapScrollingMode( | 228 snap_scroll_controller_.SetSnapScrollingMode( |
| 208 e, is_scale_gesture_detection_in_progress); | 229 e, is_scale_gesture_detection_in_progress); |
| 209 | 230 |
| 210 if (is_scale_gesture_detection_in_progress) | 231 if (is_scale_gesture_detection_in_progress) |
| 211 SetIgnoreSingleTap(true); | 232 SetIgnoreSingleTap(true); |
| 212 | 233 |
| 213 if (e.GetAction() == MotionEvent::ACTION_POINTER_DOWN || | 234 if (e.GetAction() == MotionEvent::ACTION_DOWN) |
| 214 e.GetAction() == MotionEvent::ACTION_CANCEL) { | |
| 215 EndDoubleTapDragIfNecessary(e); | |
| 216 } else if (e.GetAction() == MotionEvent::ACTION_DOWN) { | |
| 217 gesture_detector_.set_is_longpress_enabled(true); | 235 gesture_detector_.set_is_longpress_enabled(true); |
| 218 } | |
| 219 | 236 |
| 220 return gesture_detector_.OnTouchEvent(e); | 237 return gesture_detector_.OnTouchEvent(e); |
| 221 } | 238 } |
| 222 | 239 |
| 223 // GestureDetector::GestureListener implementation. | 240 // GestureDetector::GestureListener implementation. |
| 224 virtual bool OnDown(const MotionEvent& e) OVERRIDE { | 241 virtual bool OnDown(const MotionEvent& e) OVERRIDE { |
| 225 current_down_time_ = e.GetEventTime(); | 242 current_down_time_ = e.GetEventTime(); |
| 226 ignore_single_tap_ = false; | 243 ignore_single_tap_ = false; |
| 227 seen_first_scroll_event_ = false; | 244 seen_first_scroll_event_ = false; |
| 228 last_raw_x_ = e.GetRawX(); | 245 last_raw_x_ = e.GetRawX(); |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 336 } | 353 } |
| 337 // This is a hack to address the issue where user hovers | 354 // This is a hack to address the issue where user hovers |
| 338 // over a link for longer than double_tap_timeout_, then | 355 // over a link for longer than double_tap_timeout_, then |
| 339 // OnSingleTapConfirmed() is not triggered. But we still | 356 // OnSingleTapConfirmed() is not triggered. But we still |
| 340 // want to trigger the tap event at UP. So we override | 357 // want to trigger the tap event at UP. So we override |
| 341 // OnSingleTapUp() in this case. This assumes singleTapUp | 358 // OnSingleTapUp() in this case. This assumes singleTapUp |
| 342 // gets always called before singleTapConfirmed. | 359 // gets always called before singleTapConfirmed. |
| 343 if (!ignore_single_tap_) { | 360 if (!ignore_single_tap_) { |
| 344 if (e.GetEventTime() - current_down_time_ > double_tap_timeout_) { | 361 if (e.GetEventTime() - current_down_time_ > double_tap_timeout_) { |
| 345 return OnSingleTapConfirmed(e); | 362 return OnSingleTapConfirmed(e); |
| 346 } else if (IsDoubleTapDisabled() || disable_click_delay_) { | 363 } else if (!IsDoubleTapEnabled() || disable_click_delay_) { |
| 347 // If double-tap has been disabled, there is no need to wait | 364 // If double-tap has been disabled, there is no need to wait |
| 348 // for the double-tap timeout. | 365 // for the double-tap timeout. |
| 349 return OnSingleTapConfirmed(e); | 366 return OnSingleTapConfirmed(e); |
| 350 } else { | 367 } else { |
| 351 // Notify Blink about this tapUp event anyway, when none of the above | 368 // Notify Blink about this tapUp event anyway, when none of the above |
| 352 // conditions applied. | 369 // conditions applied. |
| 353 provider_->Send(CreateGesture( | 370 provider_->Send(CreateGesture( |
| 354 ET_GESTURE_TAP_UNCONFIRMED, | 371 ET_GESTURE_TAP_UNCONFIRMED, |
| 355 e, | 372 e, |
| 356 CreateTapGestureDetails(ET_GESTURE_TAP_UNCONFIRMED, e))); | 373 CreateTapGestureDetails(ET_GESTURE_TAP_UNCONFIRMED, e))); |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 374 provider_->Send(CreateGesture( | 391 provider_->Send(CreateGesture( |
| 375 ET_GESTURE_TAP, e, CreateTapGestureDetails(ET_GESTURE_TAP, e))); | 392 ET_GESTURE_TAP, e, CreateTapGestureDetails(ET_GESTURE_TAP, e))); |
| 376 return true; | 393 return true; |
| 377 } | 394 } |
| 378 | 395 |
| 379 virtual bool OnDoubleTap(const MotionEvent& e) OVERRIDE { return false; } | 396 virtual bool OnDoubleTap(const MotionEvent& e) OVERRIDE { return false; } |
| 380 | 397 |
| 381 virtual bool OnDoubleTapEvent(const MotionEvent& e) OVERRIDE { | 398 virtual bool OnDoubleTapEvent(const MotionEvent& e) OVERRIDE { |
| 382 switch (e.GetAction()) { | 399 switch (e.GetAction()) { |
| 383 case MotionEvent::ACTION_DOWN: | 400 case MotionEvent::ACTION_DOWN: |
| 384 // Note that this will be called before the corresponding |onDown()| | |
| 385 // of the same ACTION_DOWN event. Thus, the preceding TAP_DOWN | |
| 386 // should be cancelled prior to sending a new one (in |onDown()|). | |
| 387 double_tap_drag_zoom_anchor_x_ = e.GetX(); | |
| 388 double_tap_drag_zoom_anchor_y_ = e.GetY(); | |
| 389 double_tap_mode_ = DOUBLE_TAP_MODE_DRAG_DETECTION_IN_PROGRESS; | |
| 390 // If a long-press fires during a double-tap, the GestureDetector | |
| 391 // will stop feeding MotionEvents to |onDoubleTapEvent()|, | |
| 392 // preventing double-tap drag zoom. Long press detection will be | |
| 393 // re-enabled on the next ACTION_DOWN. | |
| 394 gesture_detector_.set_is_longpress_enabled(false); | 401 gesture_detector_.set_is_longpress_enabled(false); |
| 395 break; | 402 break; |
| 396 case MotionEvent::ACTION_MOVE: | |
| 397 if (double_tap_mode_ == DOUBLE_TAP_MODE_DRAG_DETECTION_IN_PROGRESS) { | |
| 398 float distance_x = double_tap_drag_zoom_anchor_x_ - e.GetX(); | |
| 399 float distance_y = double_tap_drag_zoom_anchor_y_ - e.GetY(); | |
| 400 | 403 |
| 401 // Begin double-tap drag zoom mode if the move distance is | |
| 402 // further than the threshold. | |
| 403 if (IsDistanceGreaterThanTouchSlop(distance_x, distance_y)) { | |
| 404 GestureEventDetails scroll_details( | |
| 405 ET_GESTURE_SCROLL_BEGIN, -distance_x, -distance_y); | |
| 406 provider_->Send( | |
| 407 CreateGesture(ET_GESTURE_SCROLL_BEGIN, e, scroll_details)); | |
| 408 provider_->Send( | |
| 409 CreateGesture(ET_GESTURE_PINCH_BEGIN, | |
| 410 e.GetEventTime(), | |
| 411 Round(double_tap_drag_zoom_anchor_x_), | |
| 412 Round(double_tap_drag_zoom_anchor_y_))); | |
| 413 double_tap_mode_ = DOUBLE_TAP_MODE_DRAG_ZOOM; | |
| 414 } | |
| 415 } else if (double_tap_mode_ == DOUBLE_TAP_MODE_DRAG_ZOOM) { | |
| 416 provider_->Send(CreateGesture(ET_GESTURE_SCROLL_UPDATE, e)); | |
| 417 | |
| 418 float dy = double_tap_y_ - e.GetY(); | |
| 419 float scale = std::pow(dy > 0 ? 1.0f - kDoubleTapDragZoomSpeed | |
| 420 : 1.0f + kDoubleTapDragZoomSpeed, | |
| 421 std::abs(dy * px_to_dp_)); | |
| 422 GestureEventDetails pinch_details(ET_GESTURE_PINCH_UPDATE, scale, 0); | |
| 423 provider_->Send(CreateGesture(ET_GESTURE_PINCH_UPDATE, | |
| 424 e.GetEventTime(), | |
| 425 Round(double_tap_drag_zoom_anchor_x_), | |
| 426 Round(double_tap_drag_zoom_anchor_y_), | |
| 427 pinch_details)); | |
| 428 } | |
| 429 break; | |
| 430 case MotionEvent::ACTION_UP: | 404 case MotionEvent::ACTION_UP: |
| 431 if (double_tap_mode_ != DOUBLE_TAP_MODE_DRAG_ZOOM) { | 405 if (!provider_->IsPinchInProgress()) { |
| 432 // Normal double-tap gesture. | |
| 433 provider_->Send( | 406 provider_->Send( |
| 434 CreateGesture(ET_GESTURE_DOUBLE_TAP, | 407 CreateGesture(ET_GESTURE_DOUBLE_TAP, |
| 435 e, | 408 e, |
| 436 CreateTapGestureDetails(ET_GESTURE_DOUBLE_TAP, e))); | 409 CreateTapGestureDetails(ET_GESTURE_DOUBLE_TAP, e))); |
| 410 return true; | |
| 437 } | 411 } |
| 438 EndDoubleTapDragIfNecessary(e); | |
| 439 break; | |
| 440 case MotionEvent::ACTION_CANCEL: | |
| 441 EndDoubleTapDragIfNecessary(e); | |
| 442 break; | 412 break; |
| 443 default: | 413 default: |
| 444 NOTREACHED() << "Invalid double-tap event."; | |
| 445 break; | 414 break; |
| 446 } | 415 } |
| 447 double_tap_y_ = e.GetY(); | 416 return false; |
| 448 return true; | |
| 449 } | 417 } |
| 450 | 418 |
| 451 virtual bool OnLongPress(const MotionEvent& e) OVERRIDE { | 419 virtual bool OnLongPress(const MotionEvent& e) OVERRIDE { |
| 452 DCHECK(!IsDoubleTapInProgress()); | 420 DCHECK(!IsDoubleTapInProgress()); |
| 453 SetIgnoreSingleTap(true); | 421 SetIgnoreSingleTap(true); |
| 454 | 422 |
| 455 GestureEventDetails long_press_details(ET_GESTURE_LONG_PRESS, 0, 0); | 423 GestureEventDetails long_press_details(ET_GESTURE_LONG_PRESS, 0, 0); |
| 456 long_press_details.set_bounding_box( | 424 long_press_details.set_bounding_box( |
| 457 gfx::RectF(e.GetTouchMajor(), e.GetTouchMajor())); | 425 gfx::RectF(e.GetTouchMajor(), e.GetTouchMajor())); |
| 458 provider_->Send( | 426 provider_->Send( |
| 459 CreateGesture(ET_GESTURE_LONG_PRESS, e, long_press_details)); | 427 CreateGesture(ET_GESTURE_LONG_PRESS, e, long_press_details)); |
| 460 | 428 |
| 461 // Returning true puts the GestureDetector in "longpress" mode, disabling | 429 // Returning true puts the GestureDetector in "longpress" mode, disabling |
| 462 // further scrolling. This is undesirable, as it is quite common for a | 430 // further scrolling. This is undesirable, as it is quite common for a |
| 463 // longpress gesture to fire on content that won't trigger a context menu. | 431 // longpress gesture to fire on content that won't trigger a context menu. |
| 464 return false; | 432 return false; |
| 465 } | 433 } |
| 466 | 434 |
| 467 void SetDoubleTapSupportForPlatformEnabled(bool enabled) { | 435 void SetDoubleTapSupportEnabled(bool enabled) { |
| 468 DCHECK(!IsDoubleTapInProgress()); | 436 DCHECK(!IsDoubleTapInProgress()); |
| 469 DoubleTapMode double_tap_mode = | 437 if (enabled) { |
| 470 enabled ? DOUBLE_TAP_MODE_NONE : DOUBLE_TAP_MODE_DISABLED; | 438 gesture_detector_.set_doubletap_listener(this); |
| 471 if (double_tap_mode_ == double_tap_mode) | 439 } else { |
| 472 return; | 440 // TODO(jdduke): Send GESTURE_TAP if GESTURE_TAP_UNCONFIRMED already sent. |
| 473 double_tap_mode_ = double_tap_mode; | 441 gesture_detector_.set_doubletap_listener(NULL); |
| 474 UpdateDoubleTapListener(); | 442 } |
| 475 } | |
| 476 | |
| 477 void SetDoubleTapSupportForPageEnabled(bool enabled) { | |
| 478 if (double_tap_support_enabled_ == enabled) | |
| 479 return; | |
| 480 double_tap_support_enabled_ = enabled; | |
| 481 UpdateDoubleTapListener(); | |
| 482 } | |
| 483 | |
| 484 bool IsDoubleTapDisabled() const { | |
| 485 return double_tap_mode_ == DOUBLE_TAP_MODE_DISABLED || | |
| 486 !double_tap_support_enabled_; | |
| 487 } | 443 } |
| 488 | 444 |
| 489 bool IsClickDelayDisabled() const { return disable_click_delay_; } | 445 bool IsClickDelayDisabled() const { return disable_click_delay_; } |
| 490 | 446 |
| 491 bool IsDoubleTapInProgress() const { | 447 bool IsDoubleTapInProgress() const { |
| 492 return double_tap_mode_ != DOUBLE_TAP_MODE_DISABLED && | 448 return gesture_detector_.is_double_tapping(); |
| 493 double_tap_mode_ != DOUBLE_TAP_MODE_NONE; | |
| 494 } | 449 } |
| 495 | 450 |
| 496 private: | 451 private: |
| 497 enum DoubleTapMode { | |
| 498 DOUBLE_TAP_MODE_NONE, | |
| 499 DOUBLE_TAP_MODE_DRAG_DETECTION_IN_PROGRESS, | |
| 500 DOUBLE_TAP_MODE_DRAG_ZOOM, | |
| 501 DOUBLE_TAP_MODE_DISABLED | |
| 502 }; | |
| 503 | |
| 504 bool IsPointOutsideCurrentSlopRegion(float x, float y) const { | 452 bool IsPointOutsideCurrentSlopRegion(float x, float y) const { |
| 505 return IsDistanceGreaterThanTouchSlop(last_raw_x_ - x, last_raw_y_ - y); | 453 return IsDistanceGreaterThanTouchSlop(last_raw_x_ - x, last_raw_y_ - y); |
| 506 } | 454 } |
| 507 | 455 |
| 508 bool IsDistanceGreaterThanTouchSlop(float distance_x, | 456 bool IsDistanceGreaterThanTouchSlop(float distance_x, |
| 509 float distance_y) const { | 457 float distance_y) const { |
| 510 return distance_x * distance_x + distance_y * distance_y > | 458 return distance_x * distance_x + distance_y * distance_y > |
| 511 scaled_touch_slop_square_; | 459 scaled_touch_slop_square_; |
| 512 } | 460 } |
| 513 | 461 |
| 514 void SetIgnoreSingleTap(bool value) { ignore_single_tap_ = value; } | 462 void SetIgnoreSingleTap(bool value) { ignore_single_tap_ = value; } |
| 515 | 463 |
| 516 void EndDoubleTapDragIfNecessary(const MotionEvent& event) { | 464 bool IsDoubleTapEnabled() const { |
| 517 if (!IsDoubleTapInProgress()) | 465 return gesture_detector_.has_doubletap_listener(); |
| 518 return; | |
| 519 if (double_tap_mode_ == DOUBLE_TAP_MODE_DRAG_ZOOM) { | |
| 520 provider_->Send(CreateGesture(ET_GESTURE_PINCH_END, event)); | |
| 521 provider_->Send(CreateGesture(ET_GESTURE_SCROLL_END, event)); | |
| 522 } | |
| 523 double_tap_mode_ = DOUBLE_TAP_MODE_NONE; | |
| 524 UpdateDoubleTapListener(); | |
| 525 } | |
| 526 | |
| 527 void UpdateDoubleTapListener() { | |
| 528 if (IsDoubleTapDisabled()) { | |
| 529 // Defer nulling the DoubleTapListener until the double-tap gesture is | |
| 530 // complete. | |
| 531 if (IsDoubleTapInProgress()) | |
| 532 return; | |
| 533 gesture_detector_.set_doubletap_listener(NULL); | |
| 534 } else { | |
| 535 gesture_detector_.set_doubletap_listener(this); | |
| 536 } | |
| 537 } | 466 } |
| 538 | 467 |
| 539 GestureDetector gesture_detector_; | 468 GestureDetector gesture_detector_; |
| 540 SnapScrollController snap_scroll_controller_; | 469 SnapScrollController snap_scroll_controller_; |
| 541 | 470 |
| 542 GestureProvider* const provider_; | 471 GestureProvider* const provider_; |
| 543 | 472 |
| 544 const float px_to_dp_; | |
| 545 | |
| 546 // Whether the click delay should always be disabled by sending clicks for | 473 // Whether the click delay should always be disabled by sending clicks for |
| 547 // double-tap gestures. | 474 // double-tap gestures. |
| 548 const bool disable_click_delay_; | 475 const bool disable_click_delay_; |
| 549 | 476 |
| 550 const int scaled_touch_slop_; | 477 const int scaled_touch_slop_; |
| 551 | 478 |
| 552 // Cache of square of the scaled touch slop so we don't have to calculate it | 479 // Cache of square of the scaled touch slop so we don't have to calculate it |
| 553 // on every touch. | 480 // on every touch. |
| 554 const int scaled_touch_slop_square_; | 481 const int scaled_touch_slop_square_; |
| 555 | 482 |
| 556 const base::TimeDelta double_tap_timeout_; | 483 const base::TimeDelta double_tap_timeout_; |
| 557 | 484 |
| 558 base::TimeTicks current_down_time_; | 485 base::TimeTicks current_down_time_; |
| 559 | 486 |
| 560 // TODO(klobag): This is to avoid a bug in GestureDetector. With multi-touch, | 487 // TODO(klobag): This is to avoid a bug in GestureDetector. With multi-touch, |
| 561 // always_in_tap_region_ is not reset. So when the last finger is up, | 488 // always_in_tap_region_ is not reset. So when the last finger is up, |
| 562 // OnSingleTapUp() will be mistakenly fired. | 489 // OnSingleTapUp() will be mistakenly fired. |
| 563 bool ignore_single_tap_; | 490 bool ignore_single_tap_; |
| 564 | 491 |
| 565 // Used to remove the touch slop from the initial scroll event in a scroll | 492 // Used to remove the touch slop from the initial scroll event in a scroll |
| 566 // gesture. | 493 // gesture. |
| 567 bool seen_first_scroll_event_; | 494 bool seen_first_scroll_event_; |
| 568 | 495 |
| 569 // Indicate current double-tap mode state. | |
| 570 int double_tap_mode_; | |
| 571 | |
| 572 // On double-tap this will store the y coordinates of the touch. | |
| 573 float double_tap_y_; | |
| 574 | |
| 575 // The page's viewport and scale sometimes allow us to disable double-tap | |
| 576 // gesture detection, | |
| 577 // according to the logic in ContentViewCore.onRenderCoordinatesUpdated(). | |
| 578 bool double_tap_support_enabled_; | |
| 579 | |
| 580 // x, y coordinates for an Anchor on double-tap drag zoom. | |
| 581 float double_tap_drag_zoom_anchor_x_; | |
| 582 float double_tap_drag_zoom_anchor_y_; | |
| 583 | |
| 584 // Used to track the last rawX/Y coordinates for moves. This gives absolute | 496 // Used to track the last rawX/Y coordinates for moves. This gives absolute |
| 585 // scroll distance. | 497 // scroll distance. |
| 586 // Useful for full screen tracking. | 498 // Useful for full screen tracking. |
| 587 float last_raw_x_; | 499 float last_raw_x_; |
| 588 float last_raw_y_; | 500 float last_raw_y_; |
| 589 | 501 |
| 590 // Used to track the accumulated scroll error over time. This is used to | 502 // Used to track the accumulated scroll error over time. This is used to |
| 591 // remove the | 503 // remove the |
| 592 // rounding error we introduced by passing integers to webkit. | 504 // rounding error we introduced by passing integers to webkit. |
| 593 float accumulated_scroll_error_x_; | 505 float accumulated_scroll_error_x_; |
| 594 float accumulated_scroll_error_y_; | 506 float accumulated_scroll_error_y_; |
| 595 | 507 |
| 596 DISALLOW_COPY_AND_ASSIGN(GestureListenerImpl); | 508 DISALLOW_COPY_AND_ASSIGN(GestureListenerImpl); |
| 597 }; | 509 }; |
| 598 | 510 |
| 599 // GestureProvider | 511 // GestureProvider |
| 600 | 512 |
| 601 GestureProvider::GestureProvider(const Config& config, | 513 GestureProvider::GestureProvider(const Config& config, |
| 602 GestureProviderClient* client) | 514 GestureProviderClient* client) |
| 603 : client_(client), | 515 : client_(client), |
| 604 needs_show_press_event_(false), | 516 needs_show_press_event_(false), |
| 605 needs_tap_ending_event_(false), | 517 needs_tap_ending_event_(false), |
| 606 touch_scroll_in_progress_(false), | 518 touch_scroll_in_progress_(false), |
| 607 pinch_in_progress_(false) { | 519 pinch_in_progress_(false), |
| 520 double_tap_support_for_page_(true), | |
| 521 double_tap_support_for_platform_(true) { | |
| 608 DCHECK(client); | 522 DCHECK(client); |
| 609 InitGestureDetectors(config); | 523 InitGestureDetectors(config); |
| 610 } | 524 } |
| 611 | 525 |
| 612 GestureProvider::~GestureProvider() {} | 526 GestureProvider::~GestureProvider() {} |
| 613 | 527 |
| 614 bool GestureProvider::OnTouchEvent(const MotionEvent& event) { | 528 bool GestureProvider::OnTouchEvent(const MotionEvent& event) { |
| 615 TRACE_EVENT1("input", "GestureProvider::OnTouchEvent", | 529 TRACE_EVENT1("input", "GestureProvider::OnTouchEvent", |
| 616 "action", GetMotionEventActionName(event.GetAction())); | 530 "action", GetMotionEventActionName(event.GetAction())); |
| 617 if (!CanHandle(event)) | 531 if (!CanHandle(event)) |
| 618 return false; | 532 return false; |
| 619 | 533 |
| 620 const bool was_touch_scrolling_ = touch_scroll_in_progress_; | |
| 621 const bool in_scale_gesture = | 534 const bool in_scale_gesture = |
| 622 scale_gesture_listener_->IsScaleGestureDetectionInProgress(); | 535 scale_gesture_listener_->IsScaleGestureDetectionInProgress(); |
| 623 | 536 |
| 624 if (event.GetAction() == MotionEvent::ACTION_DOWN) { | 537 if (event.GetAction() == MotionEvent::ACTION_DOWN) { |
| 625 current_down_event_ = event.Clone(); | 538 current_down_event_ = event.Clone(); |
| 626 touch_scroll_in_progress_ = false; | 539 touch_scroll_in_progress_ = false; |
| 627 needs_show_press_event_ = true; | 540 needs_show_press_event_ = true; |
| 628 current_longpress_time_ = base::TimeTicks(); | 541 current_longpress_time_ = base::TimeTicks(); |
| 629 SendTapCancelIfNecessary(event); | 542 SendTapCancelIfNecessary(event); |
| 630 } | 543 } |
| 631 | 544 |
| 632 bool handled = gesture_listener_->OnTouchEvent(event, in_scale_gesture); | 545 bool handled = gesture_listener_->OnTouchEvent(event, in_scale_gesture); |
| 633 handled |= scale_gesture_listener_->OnTouchEvent(event); | 546 handled |= scale_gesture_listener_->OnTouchEvent(event); |
| 634 | 547 |
| 635 if (event.GetAction() == MotionEvent::ACTION_UP || | 548 if (event.GetAction() == MotionEvent::ACTION_UP || |
| 636 event.GetAction() == MotionEvent::ACTION_CANCEL) { | 549 event.GetAction() == MotionEvent::ACTION_CANCEL) { |
| 637 // "Last finger raised" could be an end to movement, but it should | 550 // Note: This call will have no effect if a fling was just generated, as |
| 638 // only terminate scrolling if the event did not cause a fling. | 551 // |Fling()| will have already signalled an end to touch-scrolling. |
| 639 if (was_touch_scrolling_ && !handled) | 552 EndTouchScrollIfNecessary(event.GetEventTime(), true); |
| 640 EndTouchScrollIfNecessary(event.GetEventTime(), true); | |
| 641 | 553 |
| 642 // We shouldn't necessarily cancel a tap on ACTION_UP, as the double-tap | 554 // We shouldn't necessarily cancel a tap on ACTION_UP, as the double-tap |
| 643 // timeout may yet trigger a SINGLE_TAP. | 555 // timeout may yet trigger a SINGLE_TAP. |
| 644 if (event.GetAction() == MotionEvent::ACTION_CANCEL) | 556 if (event.GetAction() == MotionEvent::ACTION_CANCEL) |
| 645 SendTapCancelIfNecessary(event); | 557 SendTapCancelIfNecessary(event); |
| 646 | 558 |
| 559 UpdateDoubleTapDetectionSupport(); | |
| 560 | |
| 647 current_down_event_.reset(); | 561 current_down_event_.reset(); |
| 648 } | 562 } |
| 649 | 563 |
| 650 return true; | 564 return true; |
| 651 } | 565 } |
| 652 | 566 |
| 653 void GestureProvider::ResetGestureDetectors() { | 567 void GestureProvider::ResetGestureDetectors() { |
| 654 if (!current_down_event_) | 568 if (!current_down_event_) |
| 655 return; | 569 return; |
| 656 scoped_ptr<MotionEvent> cancel_event = current_down_event_->Cancel(); | 570 scoped_ptr<MotionEvent> cancel_event = current_down_event_->Cancel(); |
| 657 gesture_listener_->OnTouchEvent(*cancel_event, false); | 571 gesture_listener_->OnTouchEvent(*cancel_event, false); |
| 658 scale_gesture_listener_->OnTouchEvent(*cancel_event); | 572 scale_gesture_listener_->OnTouchEvent(*cancel_event); |
| 659 } | 573 } |
| 660 | 574 |
| 661 void GestureProvider::SetMultiTouchSupportEnabled(bool enabled) { | 575 void GestureProvider::SetMultiTouchSupportEnabled(bool enabled) { |
| 662 scale_gesture_listener_->set_ignore_detector_events(!enabled); | 576 scale_gesture_listener_->SetMultiTouchSupportEnabled(!enabled); |
| 663 } | 577 } |
| 664 | 578 |
| 665 void GestureProvider::SetDoubleTapSupportForPlatformEnabled(bool enabled) { | 579 void GestureProvider::SetDoubleTapSupportForPlatformEnabled(bool enabled) { |
| 666 gesture_listener_->SetDoubleTapSupportForPlatformEnabled(enabled); | 580 double_tap_support_for_platform_ = enabled; |
| 581 UpdateDoubleTapDetectionSupport(); | |
| 667 } | 582 } |
| 668 | 583 |
| 669 void GestureProvider::SetDoubleTapSupportForPageEnabled(bool enabled) { | 584 void GestureProvider::SetDoubleTapSupportForPageEnabled(bool enabled) { |
| 670 gesture_listener_->SetDoubleTapSupportForPageEnabled(enabled); | 585 double_tap_support_for_page_ = enabled; |
| 586 UpdateDoubleTapDetectionSupport(); | |
| 671 } | 587 } |
| 672 | 588 |
| 673 bool GestureProvider::IsScrollInProgress() const { | 589 bool GestureProvider::IsScrollInProgress() const { |
| 674 // TODO(wangxianzhu): Also return true when fling is active once the UI knows | 590 // TODO(wangxianzhu): Also return true when fling is active once the UI knows |
| 675 // exactly when the fling ends. | 591 // exactly when the fling ends. |
| 676 return touch_scroll_in_progress_; | 592 return touch_scroll_in_progress_; |
| 677 } | 593 } |
| 678 | 594 |
| 679 bool GestureProvider::IsPinchInProgress() const { return pinch_in_progress_; } | 595 bool GestureProvider::IsPinchInProgress() const { return pinch_in_progress_; } |
| 680 | 596 |
| 681 bool GestureProvider::IsDoubleTapInProgress() const { | 597 bool GestureProvider::IsDoubleTapInProgress() const { |
| 682 return gesture_listener_->IsDoubleTapInProgress(); | 598 return gesture_listener_->IsDoubleTapInProgress() || |
| 599 scale_gesture_listener_->IsDoubleTapInProgress(); | |
| 600 } | |
| 601 | |
| 602 bool GestureProvider::IsDoubleTapSupportedEnabled() const { | |
| 603 return double_tap_support_for_page_ && double_tap_support_for_platform_; | |
| 683 } | 604 } |
| 684 | 605 |
| 685 bool GestureProvider::IsClickDelayDisabled() const { | 606 bool GestureProvider::IsClickDelayDisabled() const { |
| 686 return gesture_listener_->IsClickDelayDisabled(); | 607 return gesture_listener_->IsClickDelayDisabled(); |
| 687 } | 608 } |
| 688 | 609 |
| 689 void GestureProvider::InitGestureDetectors(const Config& config) { | 610 void GestureProvider::InitGestureDetectors(const Config& config) { |
| 690 TRACE_EVENT0("input", "GestureProvider::InitGestureDetectors"); | 611 TRACE_EVENT0("input", "GestureProvider::InitGestureDetectors"); |
| 691 gesture_listener_.reset( | 612 gesture_listener_.reset( |
| 692 new GestureListenerImpl(config.gesture_detector_config, | 613 new GestureListenerImpl(config.gesture_detector_config, |
| 693 config.snap_scroll_controller_config, | 614 config.snap_scroll_controller_config, |
| 694 config.disable_click_delay, | 615 config.disable_click_delay, |
| 695 this)); | 616 this)); |
| 696 | 617 |
| 697 scale_gesture_listener_.reset( | 618 scale_gesture_listener_.reset(new ScaleGestureListenerImpl( |
| 698 new ScaleGestureListenerImpl(config.scale_gesture_detector_config, this)); | 619 config.scale_gesture_detector_config, |
| 620 config.snap_scroll_controller_config.device_scale_factor, | |
| 621 this)); | |
| 622 | |
| 623 UpdateDoubleTapDetectionSupport(); | |
| 699 } | 624 } |
| 700 | 625 |
| 701 bool GestureProvider::CanHandle(const MotionEvent& event) const { | 626 bool GestureProvider::CanHandle(const MotionEvent& event) const { |
| 702 return event.GetAction() == MotionEvent::ACTION_DOWN || current_down_event_; | 627 return event.GetAction() == MotionEvent::ACTION_DOWN || current_down_event_; |
| 703 } | 628 } |
| 704 | 629 |
| 705 void GestureProvider::Fling(base::TimeTicks time, | 630 void GestureProvider::Fling(base::TimeTicks time, |
| 706 float x, | 631 float x, |
| 707 float y, | 632 float y, |
| 708 float velocity_x, | 633 float velocity_x, |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 769 current_longpress_time_ = base::TimeTicks(); | 694 current_longpress_time_ = base::TimeTicks(); |
| 770 break; | 695 break; |
| 771 case ET_GESTURE_SCROLL_BEGIN: | 696 case ET_GESTURE_SCROLL_BEGIN: |
| 772 touch_scroll_in_progress_ = true; | 697 touch_scroll_in_progress_ = true; |
| 773 SendTapCancelIfNecessary(*current_down_event_); | 698 SendTapCancelIfNecessary(*current_down_event_); |
| 774 break; | 699 break; |
| 775 case ET_GESTURE_SCROLL_END: | 700 case ET_GESTURE_SCROLL_END: |
| 776 touch_scroll_in_progress_ = false; | 701 touch_scroll_in_progress_ = false; |
| 777 break; | 702 break; |
| 778 case ET_GESTURE_PINCH_BEGIN: | 703 case ET_GESTURE_PINCH_BEGIN: |
| 704 if (!touch_scroll_in_progress_) | |
| 705 Send(CreateGesture( | |
| 706 ET_GESTURE_SCROLL_BEGIN, gesture.time, gesture.x, gesture.y)); | |
| 779 pinch_in_progress_ = true; | 707 pinch_in_progress_ = true; |
| 780 break; | 708 break; |
| 781 case ET_GESTURE_PINCH_END: | 709 case ET_GESTURE_PINCH_END: |
| 782 pinch_in_progress_ = false; | 710 pinch_in_progress_ = false; |
| 783 break; | 711 break; |
| 784 default: | 712 default: |
| 785 break; | 713 break; |
| 786 }; | 714 }; |
| 787 | 715 |
| 788 client_->OnGestureEvent(gesture); | 716 client_->OnGestureEvent(gesture); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 811 | 739 |
| 812 void GestureProvider::EndTouchScrollIfNecessary(base::TimeTicks time, | 740 void GestureProvider::EndTouchScrollIfNecessary(base::TimeTicks time, |
| 813 bool send_scroll_end_event) { | 741 bool send_scroll_end_event) { |
| 814 if (!touch_scroll_in_progress_) | 742 if (!touch_scroll_in_progress_) |
| 815 return; | 743 return; |
| 816 touch_scroll_in_progress_ = false; | 744 touch_scroll_in_progress_ = false; |
| 817 if (send_scroll_end_event) | 745 if (send_scroll_end_event) |
| 818 Send(CreateGesture(ET_GESTURE_SCROLL_END, time, 0, 0)); | 746 Send(CreateGesture(ET_GESTURE_SCROLL_END, time, 0, 0)); |
| 819 } | 747 } |
| 820 | 748 |
| 749 void GestureProvider::UpdateDoubleTapDetectionSupport() { | |
| 750 if (IsDoubleTapInProgress()) | |
| 751 return; | |
| 752 | |
| 753 const bool supports_double_tap = IsDoubleTapSupportedEnabled(); | |
| 754 gesture_listener_->SetDoubleTapSupportEnabled(supports_double_tap); | |
| 755 scale_gesture_listener_->SetDoubleTapSupportEnabled(supports_double_tap); | |
| 756 } | |
| 757 | |
| 821 } // namespace ui | 758 } // namespace ui |
| OLD | NEW |