Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(135)

Side by Side Diff: ui/events/gesture_detection/gesture_provider.cc

Issue 200623003: Adopt "QuickScale" double-tap drag zoom code in the GestureProvider (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Comment Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698