diff options
author | jdduke@chromium.org <jdduke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-03 22:37:07 +0000 |
---|---|---|
committer | jdduke@chromium.org <jdduke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-04-03 22:37:07 +0000 |
commit | d3114ed736edf6d02303101cd7bec7d86852fbc5 (patch) | |
tree | df068c8e64136215b08900ee84531a4151d2c0b5 /ui/events | |
parent | fa6f3e8cf3db2a69816f98b79679cc9a68b6c1b6 (diff) | |
download | chromium_src-d3114ed736edf6d02303101cd7bec7d86852fbc5.zip chromium_src-d3114ed736edf6d02303101cd7bec7d86852fbc5.tar.gz chromium_src-d3114ed736edf6d02303101cd7bec7d86852fbc5.tar.bz2 |
Adopt "QuickScale" double-tap drag zoom code in the GestureProvider
QuickScale, aka double-tap drag zoom, was added in KitKat on Android. However,
the corresponding code in ScaleGestureDetector went unused by Chromium in the
old Java-based gesture detection pipeline. Remove the current custom code for
double-tap drag zoom, adopting the implementation in ScaleGestureDetector.
Note that we maintain one slight difference with the Android platform: instead
of diminishing the relative scale delta as the drag focus deiviates from the
anchor, continue using a distance-invariant scale delta computation.
BUG=332418,359615
Review URL: https://codereview.chromium.org/200623003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@261552 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/events')
8 files changed, 148 insertions, 233 deletions
diff --git a/ui/events/gesture_detection/gesture_config_helper_android.cc b/ui/events/gesture_detection/gesture_config_helper_android.cc index db46068..96aa7a6 100644 --- a/ui/events/gesture_detection/gesture_config_helper_android.cc +++ b/ui/events/gesture_detection/gesture_config_helper_android.cc @@ -37,9 +37,7 @@ ScaleGestureDetector::Config DefaultScaleGestureDetectorConfig() { ScaleGestureDetector::Config config; config.gesture_detector_config = DefaultGestureDetectorConfig(); - // TODO(jdduke): Enable "quick scale" on the ScaleGestureDetector, and remove - // corresponding double tap drag zoom code from GestureProvider, crbug/331092. - config.quick_scale_enabled = false; + config.quick_scale_enabled = true; config.min_scaling_touch_major = ViewConfiguration::GetMinScalingTouchMajorInPixels(); config.min_scaling_span = ViewConfiguration::GetMinScalingSpanInPixels(); diff --git a/ui/events/gesture_detection/gesture_config_helper_aura.cc b/ui/events/gesture_detection/gesture_config_helper_aura.cc index 4229600..3096db6 100644 --- a/ui/events/gesture_detection/gesture_config_helper_aura.cc +++ b/ui/events/gesture_detection/gesture_config_helper_aura.cc @@ -34,7 +34,6 @@ ScaleGestureDetector::Config DefaultScaleGestureDetectorConfig() { ScaleGestureDetector::Config config; config.gesture_detector_config = DefaultGestureDetectorConfig(); - config.quick_scale_enabled = false; config.min_scaling_touch_major = GestureConfiguration::default_radius() / 2; config.min_scaling_span = GestureConfiguration::min_distance_for_pinch_scroll_in_pixels(); diff --git a/ui/events/gesture_detection/gesture_detector.h b/ui/events/gesture_detection/gesture_detector.h index ff60905..29a004a 100644 --- a/ui/events/gesture_detection/gesture_detector.h +++ b/ui/events/gesture_detection/gesture_detector.h @@ -88,6 +88,10 @@ class GestureDetector { double_tap_listener_ = double_tap_listener; } + bool has_doubletap_listener() const { return double_tap_listener_ != NULL; } + + bool is_double_tapping() const { return is_double_tapping_; } + void set_is_longpress_enabled(bool is_longpress_enabled) { is_longpress_enabled_ = is_longpress_enabled; } diff --git a/ui/events/gesture_detection/gesture_provider.cc b/ui/events/gesture_detection/gesture_provider.cc index 4deeba2..eb1794d 100644 --- a/ui/events/gesture_detection/gesture_provider.cc +++ b/ui/events/gesture_detection/gesture_provider.cc @@ -43,7 +43,7 @@ GestureEventData CreateGesture(EventType type, float x, float y) { return GestureEventData(type, time, x, y); - } +} GestureEventData CreateGesture(EventType type, const MotionEvent& event, @@ -57,10 +57,6 @@ GestureEventData CreateGesture(EventType type, return CreateGesture(type, event.GetEventTime(), event.GetX(), event.GetY()); } -float Round(float f) { - return (f > 0.f) ? std::floor(f + 0.5f) : std::ceil(f - 0.5f); -} - GestureEventDetails CreateTapGestureDetails(EventType type, const MotionEvent& event) { // Set the tap count to 1 even for ET_GESTURE_DOUBLE_TAP, in order to be @@ -86,10 +82,12 @@ class GestureProvider::ScaleGestureListenerImpl : public ScaleGestureDetector::ScaleGestureListener { public: ScaleGestureListenerImpl(const ScaleGestureDetector::Config& config, + float device_scale_factor, GestureProvider* provider) : scale_gesture_detector_(config, this), provider_(provider), - ignore_detector_events_(false), + px_to_dp_(1.0f / device_scale_factor), + ignore_multitouch_events_(false), pinch_event_sent_(false) {} bool OnTouchEvent(const MotionEvent& event) { @@ -106,7 +104,7 @@ class GestureProvider::ScaleGestureListenerImpl // ScaleGestureDetector::ScaleGestureListener implementation. virtual bool OnScaleBegin(const ScaleGestureDetector& detector) OVERRIDE { - if (ignore_detector_events_) + if (ignore_multitouch_events_ && !detector.InDoubleTapMode()) return false; pinch_event_sent_ = false; return true; @@ -121,7 +119,7 @@ class GestureProvider::ScaleGestureListenerImpl } virtual bool OnScale(const ScaleGestureDetector& detector) OVERRIDE { - if (ignore_detector_events_) + if (ignore_multitouch_events_ && !detector.InDoubleTapMode()) return false; if (!pinch_event_sent_) { pinch_event_sent_ = true; @@ -130,8 +128,24 @@ class GestureProvider::ScaleGestureListenerImpl detector.GetFocusX(), detector.GetFocusY())); } - GestureEventDetails pinch_details( - ET_GESTURE_PINCH_UPDATE, detector.GetScaleFactor(), 0); + + float scale = detector.GetScaleFactor(); + if (scale == 1) + return true; + + if (detector.InDoubleTapMode()) { + // Relative changes in the double-tap scale factor computed by |detector| + // diminish as the touch moves away from the original double-tap focus. + // For historical reasons, Chrome has instead adopted a scale factor + // computation that is invariant to the focal distance, where + // the scale delta remains constant if the touch velocity is constant. + float dy = + (detector.GetCurrentSpanY() - detector.GetPreviousSpanY()) * 0.5f; + scale = std::pow(scale > 1 ? 1.0f + kDoubleTapDragZoomSpeed + : 1.0f - kDoubleTapDragZoomSpeed, + std::abs(dy * px_to_dp_)); + } + GestureEventDetails pinch_details(ET_GESTURE_PINCH_UPDATE, scale, 0); provider_->Send(CreateGesture(ET_GESTURE_PINCH_UPDATE, detector.GetEventTime(), detector.GetFocusX(), @@ -140,26 +154,42 @@ class GestureProvider::ScaleGestureListenerImpl return true; } - bool IsScaleGestureDetectionInProgress() const { - return !ignore_detector_events_ && scale_gesture_detector_.IsInProgress(); + void SetDoubleTapEnabled(bool enabled) { + DCHECK(!IsDoubleTapInProgress()); + scale_gesture_detector_.SetQuickScaleEnabled(enabled); } - void set_ignore_detector_events(bool value) { + void SetMultiTouchEnabled(bool value) { // Note that returning false from OnScaleBegin / OnScale makes the // gesture detector not to emit further scaling notifications // related to this gesture. Thus, if detector events are enabled in // the middle of the gesture, we don't need to do anything. - ignore_detector_events_ = value; + ignore_multitouch_events_ = value; + } + + bool IsDoubleTapInProgress() const { + return IsScaleGestureDetectionInProgress() && InDoubleTapMode(); + } + + bool IsScaleGestureDetectionInProgress() const { + return scale_gesture_detector_.IsInProgress(); } private: + bool InDoubleTapMode() const { + return scale_gesture_detector_.InDoubleTapMode(); + } + ScaleGestureDetector scale_gesture_detector_; GestureProvider* const provider_; - // Completely silence scaling events. Used in WebView when zoom support - // is turned off. - bool ignore_detector_events_; + // TODO(jdduke): Remove this when all MotionEvent's use DIPs. + const float px_to_dp_; + + // Completely silence multi-touch (pinch) scaling events. Used in WebView when + // zoom support is turned off. + bool ignore_multitouch_events_; // Whether any pinch zoom event has been sent to native. bool pinch_event_sent_; @@ -181,24 +211,16 @@ class GestureProvider::GestureListenerImpl : gesture_detector_(gesture_detector_config, this, this), snap_scroll_controller_(snap_scroll_controller_config), provider_(provider), - px_to_dp_(1.0f / snap_scroll_controller_config.device_scale_factor), disable_click_delay_(disable_click_delay), scaled_touch_slop_(gesture_detector_config.scaled_touch_slop), scaled_touch_slop_square_(scaled_touch_slop_ * scaled_touch_slop_), double_tap_timeout_(gesture_detector_config.double_tap_timeout), ignore_single_tap_(false), seen_first_scroll_event_(false), - double_tap_mode_(DOUBLE_TAP_MODE_NONE), - double_tap_y_(0), - double_tap_support_enabled_(true), - double_tap_drag_zoom_anchor_x_(0), - double_tap_drag_zoom_anchor_y_(0), last_raw_x_(0), last_raw_y_(0), accumulated_scroll_error_x_(0), - accumulated_scroll_error_y_(0) { - UpdateDoubleTapListener(); - } + accumulated_scroll_error_y_(0) {} virtual ~GestureListenerImpl() {} @@ -210,12 +232,8 @@ class GestureProvider::GestureListenerImpl if (is_scale_gesture_detection_in_progress) SetIgnoreSingleTap(true); - if (e.GetAction() == MotionEvent::ACTION_POINTER_DOWN || - e.GetAction() == MotionEvent::ACTION_CANCEL) { - EndDoubleTapDragIfNecessary(e); - } else if (e.GetAction() == MotionEvent::ACTION_DOWN) { + if (e.GetAction() == MotionEvent::ACTION_DOWN) gesture_detector_.set_is_longpress_enabled(true); - } return gesture_detector_.OnTouchEvent(e); } @@ -343,7 +361,7 @@ class GestureProvider::GestureListenerImpl if (!ignore_single_tap_) { if (e.GetEventTime() - current_down_time_ > double_tap_timeout_) { return OnSingleTapConfirmed(e); - } else if (IsDoubleTapDisabled() || disable_click_delay_) { + } else if (!IsDoubleTapEnabled() || disable_click_delay_) { // If double-tap has been disabled, there is no need to wait // for the double-tap timeout. return OnSingleTapConfirmed(e); @@ -381,71 +399,23 @@ class GestureProvider::GestureListenerImpl virtual bool OnDoubleTapEvent(const MotionEvent& e) OVERRIDE { switch (e.GetAction()) { case MotionEvent::ACTION_DOWN: - // Note that this will be called before the corresponding |onDown()| - // of the same ACTION_DOWN event. Thus, the preceding TAP_DOWN - // should be cancelled prior to sending a new one (in |onDown()|). - double_tap_drag_zoom_anchor_x_ = e.GetX(); - double_tap_drag_zoom_anchor_y_ = e.GetY(); - double_tap_mode_ = DOUBLE_TAP_MODE_DRAG_DETECTION_IN_PROGRESS; - // If a long-press fires during a double-tap, the GestureDetector - // will stop feeding MotionEvents to |onDoubleTapEvent()|, - // preventing double-tap drag zoom. Long press detection will be - // re-enabled on the next ACTION_DOWN. gesture_detector_.set_is_longpress_enabled(false); break; - case MotionEvent::ACTION_MOVE: - if (double_tap_mode_ == DOUBLE_TAP_MODE_DRAG_DETECTION_IN_PROGRESS) { - float distance_x = double_tap_drag_zoom_anchor_x_ - e.GetX(); - float distance_y = double_tap_drag_zoom_anchor_y_ - e.GetY(); - - // Begin double-tap drag zoom mode if the move distance is - // further than the threshold. - if (IsDistanceGreaterThanTouchSlop(distance_x, distance_y)) { - GestureEventDetails scroll_details( - ET_GESTURE_SCROLL_BEGIN, -distance_x, -distance_y); - provider_->Send( - CreateGesture(ET_GESTURE_SCROLL_BEGIN, e, scroll_details)); - provider_->Send( - CreateGesture(ET_GESTURE_PINCH_BEGIN, - e.GetEventTime(), - Round(double_tap_drag_zoom_anchor_x_), - Round(double_tap_drag_zoom_anchor_y_))); - double_tap_mode_ = DOUBLE_TAP_MODE_DRAG_ZOOM; - } - } else if (double_tap_mode_ == DOUBLE_TAP_MODE_DRAG_ZOOM) { - provider_->Send(CreateGesture(ET_GESTURE_SCROLL_UPDATE, e)); - - float dy = double_tap_y_ - e.GetY(); - float scale = std::pow(dy > 0 ? 1.0f - kDoubleTapDragZoomSpeed - : 1.0f + kDoubleTapDragZoomSpeed, - std::abs(dy * px_to_dp_)); - GestureEventDetails pinch_details(ET_GESTURE_PINCH_UPDATE, scale, 0); - provider_->Send(CreateGesture(ET_GESTURE_PINCH_UPDATE, - e.GetEventTime(), - Round(double_tap_drag_zoom_anchor_x_), - Round(double_tap_drag_zoom_anchor_y_), - pinch_details)); - } - break; + case MotionEvent::ACTION_UP: - if (double_tap_mode_ != DOUBLE_TAP_MODE_DRAG_ZOOM) { - // Normal double-tap gesture. + if (!provider_->IsPinchInProgress() && + !provider_->IsScrollInProgress()) { provider_->Send( CreateGesture(ET_GESTURE_DOUBLE_TAP, e, CreateTapGestureDetails(ET_GESTURE_DOUBLE_TAP, e))); + return true; } - EndDoubleTapDragIfNecessary(e); - break; - case MotionEvent::ACTION_CANCEL: - EndDoubleTapDragIfNecessary(e); break; default: - NOTREACHED() << "Invalid double-tap event."; break; } - double_tap_y_ = e.GetY(); - return true; + return false; } virtual bool OnLongPress(const MotionEvent& e) OVERRIDE { @@ -464,43 +434,23 @@ class GestureProvider::GestureListenerImpl return false; } - void SetDoubleTapSupportForPlatformEnabled(bool enabled) { + void SetDoubleTapEnabled(bool enabled) { DCHECK(!IsDoubleTapInProgress()); - DoubleTapMode double_tap_mode = - enabled ? DOUBLE_TAP_MODE_NONE : DOUBLE_TAP_MODE_DISABLED; - if (double_tap_mode_ == double_tap_mode) - return; - double_tap_mode_ = double_tap_mode; - UpdateDoubleTapListener(); - } - - void SetDoubleTapSupportForPageEnabled(bool enabled) { - if (double_tap_support_enabled_ == enabled) - return; - double_tap_support_enabled_ = enabled; - UpdateDoubleTapListener(); - } - - bool IsDoubleTapDisabled() const { - return double_tap_mode_ == DOUBLE_TAP_MODE_DISABLED || - !double_tap_support_enabled_; + if (enabled) { + gesture_detector_.set_doubletap_listener(this); + } else { + // TODO(jdduke): Send GESTURE_TAP if GESTURE_TAP_UNCONFIRMED already sent. + gesture_detector_.set_doubletap_listener(NULL); + } } bool IsClickDelayDisabled() const { return disable_click_delay_; } bool IsDoubleTapInProgress() const { - return double_tap_mode_ != DOUBLE_TAP_MODE_DISABLED && - double_tap_mode_ != DOUBLE_TAP_MODE_NONE; + return gesture_detector_.is_double_tapping(); } private: - enum DoubleTapMode { - DOUBLE_TAP_MODE_NONE, - DOUBLE_TAP_MODE_DRAG_DETECTION_IN_PROGRESS, - DOUBLE_TAP_MODE_DRAG_ZOOM, - DOUBLE_TAP_MODE_DISABLED - }; - bool IsPointOutsideCurrentSlopRegion(float x, float y) const { return IsDistanceGreaterThanTouchSlop(last_raw_x_ - x, last_raw_y_ - y); } @@ -513,27 +463,8 @@ class GestureProvider::GestureListenerImpl void SetIgnoreSingleTap(bool value) { ignore_single_tap_ = value; } - void EndDoubleTapDragIfNecessary(const MotionEvent& event) { - if (!IsDoubleTapInProgress()) - return; - if (double_tap_mode_ == DOUBLE_TAP_MODE_DRAG_ZOOM) { - provider_->Send(CreateGesture(ET_GESTURE_PINCH_END, event)); - provider_->Send(CreateGesture(ET_GESTURE_SCROLL_END, event)); - } - double_tap_mode_ = DOUBLE_TAP_MODE_NONE; - UpdateDoubleTapListener(); - } - - void UpdateDoubleTapListener() { - if (IsDoubleTapDisabled()) { - // Defer nulling the DoubleTapListener until the double-tap gesture is - // complete. - if (IsDoubleTapInProgress()) - return; - gesture_detector_.set_doubletap_listener(NULL); - } else { - gesture_detector_.set_doubletap_listener(this); - } + bool IsDoubleTapEnabled() const { + return gesture_detector_.has_doubletap_listener(); } GestureDetector gesture_detector_; @@ -541,8 +472,6 @@ class GestureProvider::GestureListenerImpl GestureProvider* const provider_; - const float px_to_dp_; - // Whether the click delay should always be disabled by sending clicks for // double-tap gestures. const bool disable_click_delay_; @@ -566,21 +495,6 @@ class GestureProvider::GestureListenerImpl // gesture. bool seen_first_scroll_event_; - // Indicate current double-tap mode state. - int double_tap_mode_; - - // On double-tap this will store the y coordinates of the touch. - float double_tap_y_; - - // The page's viewport and scale sometimes allow us to disable double-tap - // gesture detection, - // according to the logic in ContentViewCore.onRenderCoordinatesUpdated(). - bool double_tap_support_enabled_; - - // x, y coordinates for an Anchor on double-tap drag zoom. - float double_tap_drag_zoom_anchor_x_; - float double_tap_drag_zoom_anchor_y_; - // Used to track the last rawX/Y coordinates for moves. This gives absolute // scroll distance. // Useful for full screen tracking. @@ -604,7 +518,9 @@ GestureProvider::GestureProvider(const Config& config, needs_show_press_event_(false), needs_tap_ending_event_(false), touch_scroll_in_progress_(false), - pinch_in_progress_(false) { + pinch_in_progress_(false), + double_tap_support_for_page_(true), + double_tap_support_for_platform_(true) { DCHECK(client); InitGestureDetectors(config); } @@ -617,7 +533,6 @@ bool GestureProvider::OnTouchEvent(const MotionEvent& event) { if (!CanHandle(event)) return false; - const bool was_touch_scrolling_ = touch_scroll_in_progress_; const bool in_scale_gesture = scale_gesture_listener_->IsScaleGestureDetectionInProgress(); @@ -634,16 +549,17 @@ bool GestureProvider::OnTouchEvent(const MotionEvent& event) { if (event.GetAction() == MotionEvent::ACTION_UP || event.GetAction() == MotionEvent::ACTION_CANCEL) { - // "Last finger raised" could be an end to movement, but it should - // only terminate scrolling if the event did not cause a fling. - if (was_touch_scrolling_ && !handled) - EndTouchScrollIfNecessary(event.GetEventTime(), true); + // Note: This call will have no effect if a fling was just generated, as + // |Fling()| will have already signalled an end to touch-scrolling. + EndTouchScrollIfNecessary(event.GetEventTime(), true); // We shouldn't necessarily cancel a tap on ACTION_UP, as the double-tap // timeout may yet trigger a SINGLE_TAP. if (event.GetAction() == MotionEvent::ACTION_CANCEL) SendTapCancelIfNecessary(event); + UpdateDoubleTapDetectionSupport(); + current_down_event_.reset(); } @@ -659,15 +575,17 @@ void GestureProvider::ResetGestureDetectors() { } void GestureProvider::SetMultiTouchSupportEnabled(bool enabled) { - scale_gesture_listener_->set_ignore_detector_events(!enabled); + scale_gesture_listener_->SetMultiTouchEnabled(!enabled); } void GestureProvider::SetDoubleTapSupportForPlatformEnabled(bool enabled) { - gesture_listener_->SetDoubleTapSupportForPlatformEnabled(enabled); + double_tap_support_for_platform_ = enabled; + UpdateDoubleTapDetectionSupport(); } void GestureProvider::SetDoubleTapSupportForPageEnabled(bool enabled) { - gesture_listener_->SetDoubleTapSupportForPageEnabled(enabled); + double_tap_support_for_page_ = enabled; + UpdateDoubleTapDetectionSupport(); } bool GestureProvider::IsScrollInProgress() const { @@ -679,7 +597,12 @@ bool GestureProvider::IsScrollInProgress() const { bool GestureProvider::IsPinchInProgress() const { return pinch_in_progress_; } bool GestureProvider::IsDoubleTapInProgress() const { - return gesture_listener_->IsDoubleTapInProgress(); + return gesture_listener_->IsDoubleTapInProgress() || + scale_gesture_listener_->IsDoubleTapInProgress(); +} + +bool GestureProvider::IsDoubleTapSupported() const { + return double_tap_support_for_page_ && double_tap_support_for_platform_; } bool GestureProvider::IsClickDelayDisabled() const { @@ -694,8 +617,12 @@ void GestureProvider::InitGestureDetectors(const Config& config) { config.disable_click_delay, this)); - scale_gesture_listener_.reset( - new ScaleGestureListenerImpl(config.scale_gesture_detector_config, this)); + scale_gesture_listener_.reset(new ScaleGestureListenerImpl( + config.scale_gesture_detector_config, + config.snap_scroll_controller_config.device_scale_factor, + this)); + + UpdateDoubleTapDetectionSupport(); } bool GestureProvider::CanHandle(const MotionEvent& event) const { @@ -776,6 +703,9 @@ void GestureProvider::Send(const GestureEventData& gesture) { touch_scroll_in_progress_ = false; break; case ET_GESTURE_PINCH_BEGIN: + if (!touch_scroll_in_progress_) + Send(CreateGesture( + ET_GESTURE_SCROLL_BEGIN, gesture.time, gesture.x, gesture.y)); pinch_in_progress_ = true; break; case ET_GESTURE_PINCH_END: @@ -818,4 +748,13 @@ void GestureProvider::EndTouchScrollIfNecessary(base::TimeTicks time, Send(CreateGesture(ET_GESTURE_SCROLL_END, time, 0, 0)); } +void GestureProvider::UpdateDoubleTapDetectionSupport() { + if (IsDoubleTapInProgress()) + return; + + const bool supports_double_tap = IsDoubleTapSupported(); + gesture_listener_->SetDoubleTapEnabled(supports_double_tap); + scale_gesture_listener_->SetDoubleTapEnabled(supports_double_tap); +} + } // namespace ui diff --git a/ui/events/gesture_detection/gesture_provider.h b/ui/events/gesture_detection/gesture_provider.h index d854219..fce5926 100644 --- a/ui/events/gesture_detection/gesture_provider.h +++ b/ui/events/gesture_detection/gesture_provider.h @@ -66,9 +66,13 @@ class GESTURE_DETECTION_EXPORT GestureProvider { // forwarded and detection is still active). bool IsPinchInProgress() const; - // Whether a double tap-gesture is in-progress. + // Whether a double-tap gesture is in-progress (either double-tap or + // double-tap drag zoom). bool IsDoubleTapInProgress() const; + // Whether double-tap gesture detection is supported. + bool IsDoubleTapSupported() const; + // Whether the tap gesture delay is explicitly disabled (independent of // whether double-tap is supported), see |Config.disable_click_delay|. bool IsClickDelayDisabled() const; @@ -93,6 +97,7 @@ class GESTURE_DETECTION_EXPORT GestureProvider { bool SendLongTapIfNecessary(const MotionEvent& event); void EndTouchScrollIfNecessary(base::TimeTicks time, bool send_scroll_end_event); + void UpdateDoubleTapDetectionSupport(); GestureProviderClient* const client_; @@ -120,6 +125,10 @@ class GESTURE_DETECTION_EXPORT GestureProvider { bool touch_scroll_in_progress_; bool pinch_in_progress_; + // Whether double-tap gesture detection is currently supported. + bool double_tap_support_for_page_; + bool double_tap_support_for_platform_; + // Keeps track of the current GESTURE_LONG_PRESS event. If a context menu is // opened after a GESTURE_LONG_PRESS, this is used to insert a // GESTURE_TAP_CANCEL for removing any ::active styling. diff --git a/ui/events/gesture_detection/gesture_provider_unittest.cc b/ui/events/gesture_detection/gesture_provider_unittest.cc index 1be9ec7..85ced8e 100644 --- a/ui/events/gesture_detection/gesture_provider_unittest.cc +++ b/ui/events/gesture_detection/gesture_provider_unittest.cc @@ -405,7 +405,7 @@ TEST_F(GestureProviderTest, DoubleTap) { EXPECT_EQ(1, double_tap.details.tap_count()); } -TEST_F(GestureProviderTest, DoubleTapDragZoom) { +TEST_F(GestureProviderTest, DoubleTapDragZoomBasic) { const base::TimeTicks down_time_1 = TimeTicks::Now(); const base::TimeTicks down_time_2 = down_time_1 + kOneMicrosecond * 2; @@ -431,75 +431,31 @@ TEST_F(GestureProviderTest, DoubleTapDragZoom) { kFakeCoordY + 100); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); EXPECT_TRUE(HasReceivedGesture(ET_GESTURE_SCROLL_BEGIN)); - const GestureEventData* scroll_begin_gesture = GetActiveScrollBeginEvent(); - ASSERT_TRUE(!!scroll_begin_gesture); - EXPECT_EQ(0, scroll_begin_gesture->details.scroll_x_hint()); - EXPECT_EQ(100, scroll_begin_gesture->details.scroll_y_hint()); - EXPECT_EQ(ET_GESTURE_PINCH_BEGIN, GetMostRecentGestureEventType()); + ASSERT_EQ(ET_GESTURE_PINCH_BEGIN, GetMostRecentGestureEventType()); event = ObtainMotionEvent(down_time_2 + kOneMicrosecond * 2, MotionEvent::ACTION_MOVE, kFakeCoordX, kFakeCoordY + 200); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); - EXPECT_TRUE(HasReceivedGesture(ET_GESTURE_SCROLL_UPDATE)); - EXPECT_EQ(ET_GESTURE_PINCH_UPDATE, GetMostRecentGestureEventType()); + ASSERT_EQ(ET_GESTURE_PINCH_UPDATE, GetMostRecentGestureEventType()); + EXPECT_LT(1.f, GetMostRecentGestureEvent().details.scale()); event = ObtainMotionEvent(down_time_2 + kOneMicrosecond * 3, - MotionEvent::ACTION_UP, - kFakeCoordX, - kFakeCoordY + 200); - EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); - EXPECT_TRUE(HasReceivedGesture(ET_GESTURE_PINCH_END)); - EXPECT_EQ(ET_GESTURE_SCROLL_END, GetMostRecentGestureEventType()); -} - -TEST_F(GestureProviderTest, DoubleTapDragZoomCancelledOnSecondaryPointerDown) { - const base::TimeTicks down_time_1 = TimeTicks::Now(); - const base::TimeTicks down_time_2 = down_time_1 + kOneMicrosecond * 2; - - MockMotionEvent event = - ObtainMotionEvent(down_time_1, MotionEvent::ACTION_DOWN); - EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); - EXPECT_EQ(ET_GESTURE_TAP_DOWN, GetMostRecentGestureEventType()); - - event = ObtainMotionEvent(down_time_1 + kOneMicrosecond, - MotionEvent::ACTION_UP); - gesture_provider_->OnTouchEvent(event); - EXPECT_EQ(ET_GESTURE_TAP_UNCONFIRMED, GetMostRecentGestureEventType()); - - event = ObtainMotionEvent(down_time_2, MotionEvent::ACTION_DOWN); - EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); - EXPECT_EQ(ET_GESTURE_TAP_DOWN, GetMostRecentGestureEventType()); - EXPECT_TRUE(HasReceivedGesture(ET_GESTURE_TAP_CANCEL)); - - event = ObtainMotionEvent(down_time_2 + kOneMicrosecond, MotionEvent::ACTION_MOVE, kFakeCoordX, - kFakeCoordY - 30); + kFakeCoordY + 100); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); - EXPECT_TRUE(HasReceivedGesture(ET_GESTURE_SCROLL_BEGIN)); - EXPECT_EQ(ET_GESTURE_PINCH_BEGIN, GetMostRecentGestureEventType()); + ASSERT_EQ(ET_GESTURE_PINCH_UPDATE, GetMostRecentGestureEventType()); + EXPECT_GT(1.f, GetMostRecentGestureEvent().details.scale()); - event = ObtainMotionEvent(down_time_2 + kOneMicrosecond * 2, - MotionEvent::ACTION_POINTER_DOWN, + event = ObtainMotionEvent(down_time_2 + kOneMicrosecond * 4, + MotionEvent::ACTION_UP, kFakeCoordX, - kFakeCoordY - 30, - kFakeCoordX + 50, - kFakeCoordY + 50); - gesture_provider_->OnTouchEvent(event); + kFakeCoordY - 200); + EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); EXPECT_TRUE(HasReceivedGesture(ET_GESTURE_PINCH_END)); EXPECT_EQ(ET_GESTURE_SCROLL_END, GetMostRecentGestureEventType()); - const size_t gesture_count = GetReceivedGestureCount(); - - event = ObtainMotionEvent(down_time_2 + kOneMicrosecond * 3, - MotionEvent::ACTION_POINTER_UP, - kFakeCoordX, - kFakeCoordY - 30, - kFakeCoordX + 50, - kFakeCoordY + 50); - gesture_provider_->OnTouchEvent(event); - EXPECT_EQ(gesture_count, GetReceivedGestureCount()); } // Generate a scroll gesture and verify that the resulting scroll motion event @@ -932,8 +888,8 @@ TEST_F(GestureProviderTest, FixedPageScaleDuringDoubleTapDragZoom) { kFakeCoordX, kFakeCoordY + 200); EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); - EXPECT_TRUE(HasReceivedGesture(ET_GESTURE_SCROLL_UPDATE)); EXPECT_EQ(ET_GESTURE_PINCH_UPDATE, GetMostRecentGestureEventType()); + EXPECT_LT(1.f, GetMostRecentGestureEvent().details.scale()); event = ObtainMotionEvent(down_time_2 + kOneMicrosecond * 3, MotionEvent::ACTION_UP, kFakeCoordX, @@ -1010,20 +966,30 @@ TEST_F(GestureProviderTest, PinchZoom) { secondary_coord_x += 5 * scaled_touch_slop; secondary_coord_y += 5 * scaled_touch_slop; - event = ObtainMotionEvent(event_time, MotionEvent::ACTION_MOVE, kFakeCoordX, kFakeCoordY, secondary_coord_x, secondary_coord_y); - EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); EXPECT_TRUE(HasReceivedGesture(ET_GESTURE_PINCH_BEGIN)); EXPECT_TRUE(HasReceivedGesture(ET_GESTURE_SCROLL_BEGIN)); - EXPECT_TRUE(HasReceivedGesture(ET_GESTURE_PINCH_UPDATE)); EXPECT_TRUE(HasReceivedGesture(ET_GESTURE_SCROLL_UPDATE)); + secondary_coord_x += 2 * scaled_touch_slop; + secondary_coord_y += 2 * scaled_touch_slop; + event = ObtainMotionEvent(event_time, + MotionEvent::ACTION_MOVE, + kFakeCoordX, + kFakeCoordY, + secondary_coord_x, + secondary_coord_y); + EXPECT_TRUE(gesture_provider_->OnTouchEvent(event)); + EXPECT_TRUE(HasReceivedGesture(ET_GESTURE_SCROLL_UPDATE)); + EXPECT_EQ(ET_GESTURE_PINCH_UPDATE, GetMostRecentGestureEventType()); + EXPECT_LT(1.f, GetMostRecentGestureEvent().details.scale()); + event = ObtainMotionEvent(event_time, MotionEvent::ACTION_POINTER_UP, kFakeCoordX, diff --git a/ui/events/gesture_detection/scale_gesture_detector.cc b/ui/events/gesture_detection/scale_gesture_detector.cc index 782f3dd..ea46448 100644 --- a/ui/events/gesture_detection/scale_gesture_detector.cc +++ b/ui/events/gesture_detection/scale_gesture_detector.cc @@ -26,7 +26,7 @@ const float kScaleFactor = .5f; // Note: These constants were taken directly from the default (unscaled) // versions found in Android's ViewConfiguration. ScaleGestureDetector::Config::Config() - : quick_scale_enabled(false), + : quick_scale_enabled(true), min_scaling_touch_major(48), min_scaling_span(200) {} @@ -245,6 +245,10 @@ bool ScaleGestureDetector::IsQuickScaleEnabled() const { bool ScaleGestureDetector::IsInProgress() const { return in_progress_; } +bool ScaleGestureDetector::InDoubleTapMode() const { + return double_tap_mode_ == DOUBLE_TAP_MODE_IN_PROGRESS; +} + float ScaleGestureDetector::GetFocusX() const { return focus_x_; } float ScaleGestureDetector::GetFocusY() const { return focus_y_; } @@ -360,8 +364,4 @@ void ScaleGestureDetector::ClearTouchHistory() { touch_history_last_accepted_time_ = base::TimeTicks(); } -bool ScaleGestureDetector::InDoubleTapMode() const { - return double_tap_mode_ == DOUBLE_TAP_MODE_IN_PROGRESS; -} - } // namespace ui diff --git a/ui/events/gesture_detection/scale_gesture_detector.h b/ui/events/gesture_detection/scale_gesture_detector.h index 9e84ca5..bd8086a 100644 --- a/ui/events/gesture_detection/scale_gesture_detector.h +++ b/ui/events/gesture_detection/scale_gesture_detector.h @@ -71,6 +71,7 @@ class ScaleGestureDetector : public GestureDetector::SimpleGestureListener { void SetQuickScaleEnabled(bool scales); bool IsQuickScaleEnabled() const; bool IsInProgress() const; + bool InDoubleTapMode() const; float GetFocusX() const; float GetFocusY() const; float GetCurrentSpan() const; @@ -93,7 +94,6 @@ class ScaleGestureDetector : public GestureDetector::SimpleGestureListener { // some hardware/driver combos. Smooth out to get kinder, gentler behavior. void AddTouchHistory(const MotionEvent& ev); void ClearTouchHistory(); - bool InDoubleTapMode() const; ScaleGestureListener* const listener_; |