diff options
author | ccameron <ccameron@chromium.org> | 2014-11-06 19:18:50 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-11-07 03:19:02 +0000 |
commit | 36d091feca1a3621430a61091ff2a527972a8e79 (patch) | |
tree | 3286e93b1b78c07b05b8031166fdad02f0c7993e | |
parent | a4a32af218cf03ac89db4a27d12681f8a1ba9108 (diff) | |
download | chromium_src-36d091feca1a3621430a61091ff2a527972a8e79.zip chromium_src-36d091feca1a3621430a61091ff2a527972a8e79.tar.gz chromium_src-36d091feca1a3621430a61091ff2a527972a8e79.tar.bz2 |
Return overscroll data from cc::InputHandler::ScrollBy
Whether or not a cc::InputHandler::ScrollBy resulted in some scrolling
happening is returned as a bool from the function, but whether or not
all of the input scroll delta was used is made available through a callback
to the cc::InputHandlerClient::DidOverscroll function. All of this information
should be made available in the return value.
Make ScrollBy return a struct that contains information about if a scroll
happened, if an overscroll happened, and how much of an overscroll
happened.
The overscroll effect on Mac will require knowledge of exactly what
happened with scroll (was there any extra overscroll, etc) at the point
where the scroll is attempted.
BUG=133097
Review URL: https://codereview.chromium.org/701343002
Cr-Commit-Position: refs/heads/master@{#303172}
-rw-r--r-- | cc/BUILD.gn | 1 | ||||
-rw-r--r-- | cc/cc.gyp | 1 | ||||
-rw-r--r-- | cc/input/input_handler.cc | 13 | ||||
-rw-r--r-- | cc/input/input_handler.h | 36 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_impl.cc | 20 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_impl.h | 5 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_impl_unittest.cc | 166 | ||||
-rw-r--r-- | cc/trees/layer_tree_host_unittest_scroll.cc | 7 | ||||
-rw-r--r-- | content/renderer/input/input_handler_proxy.cc | 49 | ||||
-rw-r--r-- | content/renderer/input/input_handler_proxy.h | 9 | ||||
-rw-r--r-- | content/renderer/input/input_handler_proxy_unittest.cc | 181 |
11 files changed, 320 insertions, 168 deletions
diff --git a/cc/BUILD.gn b/cc/BUILD.gn index 9b417f0..e9ef9e2 100644 --- a/cc/BUILD.gn +++ b/cc/BUILD.gn @@ -112,6 +112,7 @@ component("cc") { "debug/unittest_only_benchmark.h", "debug/unittest_only_benchmark_impl.cc", "debug/unittest_only_benchmark_impl.h", + "input/input_handler.cc", "input/input_handler.h", "input/page_scale_animation.cc", "input/page_scale_animation.h", @@ -140,6 +140,7 @@ 'debug/unittest_only_benchmark.h', 'debug/unittest_only_benchmark_impl.cc', 'debug/unittest_only_benchmark_impl.h', + 'input/input_handler.cc', 'input/input_handler.h', 'input/page_scale_animation.cc', 'input/page_scale_animation.h', diff --git a/cc/input/input_handler.cc b/cc/input/input_handler.cc new file mode 100644 index 0000000..336d0d4 --- /dev/null +++ b/cc/input/input_handler.cc @@ -0,0 +1,13 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "cc/input/input_handler.h" + +namespace cc { + +InputHandlerScrollResult::InputHandlerScrollResult() + : did_scroll(false), did_overscroll_root(false) { +} + +} // namespace cc diff --git a/cc/input/input_handler.h b/cc/input/input_handler.h index b3205a8..7a9c991 100644 --- a/cc/input/input_handler.h +++ b/cc/input/input_handler.h @@ -6,6 +6,7 @@ #define CC_INPUT_INPUT_HANDLER_H_ #include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" #include "base/time/time.h" #include "cc/base/cc_export.h" #include "cc/base/swap_promise_monitor.h" @@ -24,6 +25,21 @@ namespace cc { class LayerScrollOffsetDelegate; +struct CC_EXPORT InputHandlerScrollResult { + InputHandlerScrollResult(); + // Did any layer scroll as a result this ScrollBy call? + bool did_scroll; + // Was any of the scroll delta argument to this ScrollBy call not used? + bool did_overscroll_root; + // The total overscroll that has been accumulated by all ScrollBy calls that + // have had overscroll since the last ScrollBegin call. This resets upon a + // ScrollBy with no overscroll. + gfx::Vector2dF accumulated_root_overscroll; + // The amount of the scroll delta argument to this ScrollBy call that was not + // used for scrolling. + gfx::Vector2dF unused_scroll_delta; +}; + class CC_EXPORT InputHandlerClient { public: virtual ~InputHandlerClient() {} @@ -32,13 +48,6 @@ class CC_EXPORT InputHandlerClient { virtual void Animate(base::TimeTicks time) = 0; virtual void MainThreadHasStoppedFlinging() = 0; - // Called when scroll deltas reaching the root scrolling layer go unused. - // The accumulated overscroll is scoped by the most recent call to - // InputHandler::ScrollBegin. - virtual void DidOverscroll(const gfx::PointF& causal_event_viewport_point, - const gfx::Vector2dF& accumulated_overscroll, - const gfx::Vector2dF& latest_overscroll_delta) = 0; - protected: InputHandlerClient() {} @@ -85,15 +94,16 @@ class CC_EXPORT InputHandler { // should be in viewport (logical pixel) coordinates. Otherwise they are in // scrolling layer's (logical pixel) space. If there is no room to move the // layer in the requested direction, its first ancestor layer that can be - // scrolled will be moved instead. If no layer can be moved in the requested - // direction at all, then false is returned. If any layer is moved, then - // true is returned. + // scrolled will be moved instead. The return value's |did_scroll| field is + // set to false if no layer can be moved in the requested direction at all, + // and set to true if any layer is moved. // If the scroll delta hits the root layer, and the layer can no longer move, // the root overscroll accumulated within this ScrollBegin() scope is reported - // to the client. + // in the return value's |accumulated_overscroll| field. // Should only be called if ScrollBegin() returned ScrollStarted. - virtual bool ScrollBy(const gfx::Point& viewport_point, - const gfx::Vector2dF& scroll_delta) = 0; + virtual InputHandlerScrollResult ScrollBy( + const gfx::Point& viewport_point, + const gfx::Vector2dF& scroll_delta) = 0; virtual bool ScrollVerticallyByPage(const gfx::Point& viewport_point, ScrollDirection direction) = 0; diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index d2041ac..00be57f 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc @@ -2638,11 +2638,12 @@ bool LayerTreeHostImpl::ShouldTopControlsConsumeScroll( return false; } -bool LayerTreeHostImpl::ScrollBy(const gfx::Point& viewport_point, - const gfx::Vector2dF& scroll_delta) { +InputHandlerScrollResult LayerTreeHostImpl::ScrollBy( + const gfx::Point& viewport_point, + const gfx::Vector2dF& scroll_delta) { TRACE_EVENT0("cc", "LayerTreeHostImpl::ScrollBy"); if (!CurrentlyScrollingLayer()) - return false; + return InputHandlerScrollResult(); gfx::Vector2dF pending_delta = scroll_delta; gfx::Vector2dF unused_root_delta; @@ -2763,15 +2764,14 @@ bool LayerTreeHostImpl::ScrollBy(const gfx::Point& viewport_point, accumulated_root_overscroll_.set_x(0); if (did_scroll_y) accumulated_root_overscroll_.set_y(0); - accumulated_root_overscroll_ += unused_root_delta; - bool did_overscroll = !unused_root_delta.IsZero(); - if (did_overscroll && input_handler_client_) { - input_handler_client_->DidOverscroll( - viewport_point, accumulated_root_overscroll_, unused_root_delta); - } - return did_scroll_content || did_scroll_top_controls; + InputHandlerScrollResult scroll_result; + scroll_result.did_scroll = did_scroll_content || did_scroll_top_controls; + scroll_result.did_overscroll_root = !unused_root_delta.IsZero(); + scroll_result.accumulated_root_overscroll = accumulated_root_overscroll_; + scroll_result.unused_scroll_delta = unused_root_delta; + return scroll_result; } // This implements scrolling by page as described here: diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h index 157fe00..2309ef7 100644 --- a/cc/trees/layer_tree_host_impl.h +++ b/cc/trees/layer_tree_host_impl.h @@ -136,8 +136,9 @@ class CC_EXPORT LayerTreeHostImpl InputHandler::ScrollStatus ScrollAnimated( const gfx::Point& viewport_point, const gfx::Vector2dF& scroll_delta) override; - bool ScrollBy(const gfx::Point& viewport_point, - const gfx::Vector2dF& scroll_delta) override; + InputHandlerScrollResult ScrollBy( + const gfx::Point& viewport_point, + const gfx::Vector2dF& scroll_delta) override; bool ScrollVerticallyByPage(const gfx::Point& viewport_point, ScrollDirection direction) override; void SetRootLayerScrollOffsetDelegate( diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index 9395639..45d636a 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc @@ -777,27 +777,40 @@ TEST_F(LayerTreeHostImplTest, ScrollByReturnsCorrectValue) { host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture)); // Trying to scroll to the left/top will not succeed. - EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0))); - EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10))); - EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10))); + EXPECT_FALSE( + host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll); + EXPECT_FALSE( + host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll); + EXPECT_FALSE( + host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll); // Scrolling to the right/bottom will succeed. - EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0))); - EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10))); - EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10))); + EXPECT_TRUE( + host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)).did_scroll); + EXPECT_TRUE( + host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll); + EXPECT_TRUE( + host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 10)).did_scroll); // Scrolling to left/top will now succeed. - EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0))); - EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10))); - EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10))); + EXPECT_TRUE( + host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll); + EXPECT_TRUE( + host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)).did_scroll); + EXPECT_TRUE( + host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, -10)).did_scroll); // Scrolling diagonally against an edge will succeed. - EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10))); - EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0))); - EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10))); + EXPECT_TRUE( + host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -10)).did_scroll); + EXPECT_TRUE( + host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 0)).did_scroll); + EXPECT_TRUE( + host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-10, 10)).did_scroll); // Trying to scroll more than the available space will also succeed. - EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000))); + EXPECT_TRUE( + host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(5000, 5000)).did_scroll); } TEST_F(LayerTreeHostImplTest, ScrollVerticallyByPageReturnsCorrectValue) { @@ -3710,6 +3723,7 @@ TEST_F(LayerTreeHostImplTest, } TEST_F(LayerTreeHostImplTest, OverscrollRoot) { + InputHandlerScrollResult scroll_result; SetupScrollAndContentsLayers(gfx::Size(100, 100)); host_impl_->SetViewportSize(gfx::Size(50, 50)); host_impl_->active_tree()->SetPageScaleFactorAndLimits(1.f, 0.5f, 4.f); @@ -3719,38 +3733,105 @@ TEST_F(LayerTreeHostImplTest, OverscrollRoot) { // In-bounds scrolling does not affect overscroll. EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->ScrollBegin(gfx::Point(), InputHandler::Wheel)); - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)); + scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)); + EXPECT_TRUE(scroll_result.did_scroll); + EXPECT_FALSE(scroll_result.did_overscroll_root); + EXPECT_EQ(gfx::Vector2dF(), scroll_result.unused_scroll_delta); EXPECT_EQ(gfx::Vector2dF(), host_impl_->accumulated_root_overscroll()); // Overscroll events are reflected immediately. - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50)); + scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 50)); + EXPECT_TRUE(scroll_result.did_scroll); + EXPECT_TRUE(scroll_result.did_overscroll_root); + EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result.unused_scroll_delta); EXPECT_EQ(gfx::Vector2dF(0, 10), host_impl_->accumulated_root_overscroll()); + EXPECT_EQ(scroll_result.accumulated_root_overscroll, + host_impl_->accumulated_root_overscroll()); // In-bounds scrolling resets accumulated overscroll for the scrolled axes. - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50)); + scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -50)); + EXPECT_TRUE(scroll_result.did_scroll); + EXPECT_FALSE(scroll_result.did_overscroll_root); + EXPECT_EQ(gfx::Vector2dF(), scroll_result.unused_scroll_delta); EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll()); - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)); + EXPECT_EQ(scroll_result.accumulated_root_overscroll, + host_impl_->accumulated_root_overscroll()); + + scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -10)); + EXPECT_FALSE(scroll_result.did_scroll); + EXPECT_TRUE(scroll_result.did_overscroll_root); + EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta); EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll()); - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)); + EXPECT_EQ(scroll_result.accumulated_root_overscroll, + host_impl_->accumulated_root_overscroll()); + + scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, 0)); + EXPECT_TRUE(scroll_result.did_scroll); + EXPECT_FALSE(scroll_result.did_overscroll_root); + EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result.unused_scroll_delta); EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll()); - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0)); + EXPECT_EQ(scroll_result.accumulated_root_overscroll, + host_impl_->accumulated_root_overscroll()); + + scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(-15, 0)); + EXPECT_TRUE(scroll_result.did_scroll); + EXPECT_TRUE(scroll_result.did_overscroll_root); + EXPECT_EQ(gfx::Vector2dF(-5, 0), scroll_result.unused_scroll_delta); EXPECT_EQ(gfx::Vector2dF(-5, -10), host_impl_->accumulated_root_overscroll()); - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60)); + EXPECT_EQ(scroll_result.accumulated_root_overscroll, + host_impl_->accumulated_root_overscroll()); + + scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 60)); + EXPECT_TRUE(scroll_result.did_scroll); + EXPECT_TRUE(scroll_result.did_overscroll_root); + EXPECT_EQ(gfx::Vector2dF(0, 10), scroll_result.unused_scroll_delta); EXPECT_EQ(gfx::Vector2dF(-5, 10), host_impl_->accumulated_root_overscroll()); - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60)); + EXPECT_EQ(scroll_result.accumulated_root_overscroll, + host_impl_->accumulated_root_overscroll()); + + scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(10, -60)); + EXPECT_TRUE(scroll_result.did_scroll); + EXPECT_TRUE(scroll_result.did_overscroll_root); + EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta); EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll()); + EXPECT_EQ(scroll_result.accumulated_root_overscroll, + host_impl_->accumulated_root_overscroll()); // Overscroll accumulates within the scope of ScrollBegin/ScrollEnd as long // as no scroll occurs. - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20)); + scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20)); + EXPECT_FALSE(scroll_result.did_scroll); + EXPECT_TRUE(scroll_result.did_overscroll_root); + EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result.unused_scroll_delta); EXPECT_EQ(gfx::Vector2dF(0, -30), host_impl_->accumulated_root_overscroll()); - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20)); + EXPECT_EQ(scroll_result.accumulated_root_overscroll, + host_impl_->accumulated_root_overscroll()); + + scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20)); + EXPECT_FALSE(scroll_result.did_scroll); + EXPECT_TRUE(scroll_result.did_overscroll_root); + EXPECT_EQ(gfx::Vector2dF(0, -20), scroll_result.unused_scroll_delta); EXPECT_EQ(gfx::Vector2dF(0, -50), host_impl_->accumulated_root_overscroll()); + EXPECT_EQ(scroll_result.accumulated_root_overscroll, + host_impl_->accumulated_root_overscroll()); + // Overscroll resets on valid scroll. - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)); + scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)); + EXPECT_TRUE(scroll_result.did_scroll); + EXPECT_FALSE(scroll_result.did_overscroll_root); + EXPECT_EQ(gfx::Vector2dF(0, 0), scroll_result.unused_scroll_delta); EXPECT_EQ(gfx::Vector2dF(0, 0), host_impl_->accumulated_root_overscroll()); - host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20)); + EXPECT_EQ(scroll_result.accumulated_root_overscroll, + host_impl_->accumulated_root_overscroll()); + + scroll_result = host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, -20)); + EXPECT_TRUE(scroll_result.did_scroll); + EXPECT_TRUE(scroll_result.did_overscroll_root); + EXPECT_EQ(gfx::Vector2dF(0, -10), scroll_result.unused_scroll_delta); EXPECT_EQ(gfx::Vector2dF(0, -10), host_impl_->accumulated_root_overscroll()); + EXPECT_EQ(scroll_result.accumulated_root_overscroll, + host_impl_->accumulated_root_overscroll()); + host_impl_->ScrollEnd(); } @@ -6554,7 +6635,7 @@ TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) { gfx::Vector2d scroll_delta(0, -2); EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture)); - EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta)); + EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll); // The grand child should have scrolled up to its limit. scroll_info = host_impl_->ProcessScrollDeltas(); @@ -6564,7 +6645,7 @@ TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) { // The child should have received the bubbled delta, but the locked // scrolling layer should remain set as the grand child. - EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta)); + EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll); scroll_info = host_impl_->ProcessScrollDeltas(); ASSERT_EQ(2u, scroll_info->scrolls.size()); ExpectContains(*scroll_info, grand_child->id(), scroll_delta); @@ -6574,7 +6655,7 @@ TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) { // The first |ScrollBy| after the fling should re-lock the scrolling // layer to the first layer that scrolled, which is the child. EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->FlingScrollBegin()); - EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta)); + EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll); EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child); // The child should have scrolled up to its limit. @@ -6584,7 +6665,7 @@ TEST_F(LayerTreeHostImplTest, TouchFlingShouldLockToFirstScrolledLayer) { ExpectContains(*scroll_info, child->id(), scroll_delta + scroll_delta); // As the locked layer is at it's limit, no further scrolling can occur. - EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta)); + EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), scroll_delta).did_scroll); EXPECT_EQ(host_impl_->CurrentlyScrollingLayer(), child); host_impl_->ScrollEnd(); } @@ -6982,7 +7063,8 @@ TEST_F(LayerTreeHostImplTest, SimpleSwapPromiseMonitor) { // Scrolling normally should not trigger any forwarding. EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture)); - EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10))); + EXPECT_TRUE( + host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll); host_impl_->ScrollEnd(); EXPECT_EQ(0, set_needs_commit_count); @@ -6994,7 +7076,8 @@ TEST_F(LayerTreeHostImplTest, SimpleSwapPromiseMonitor) { scroll_layer->SetHaveScrollEventHandlers(true); EXPECT_EQ(InputHandler::ScrollStarted, host_impl_->ScrollBegin(gfx::Point(), InputHandler::Gesture)); - EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10))); + EXPECT_TRUE( + host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, 10)).did_scroll); host_impl_->ScrollEnd(); EXPECT_EQ(0, set_needs_commit_count); @@ -7049,7 +7132,8 @@ TEST_F(LayerTreeHostImplWithTopControlsTest, ScrollHandledByTopControls) { // Scroll just the top controls and verify that the scroll succeeds. const float residue = 10; float offset = top_controls_height_ - residue; - EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset))); + EXPECT_TRUE( + host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll); EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset()); EXPECT_EQ(gfx::Vector2dF().ToString(), scroll_layer->TotalScrollOffset().ToString()); @@ -7057,7 +7141,8 @@ TEST_F(LayerTreeHostImplWithTopControlsTest, ScrollHandledByTopControls) { // Scroll across the boundary const float content_scroll = 20; offset = residue + content_scroll; - EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset))); + EXPECT_TRUE( + host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll); EXPECT_EQ(-top_controls_height_, host_impl_->top_controls_manager()->ControlsTopOffset()); EXPECT_EQ(gfx::Vector2dF(0, content_scroll).ToString(), @@ -7065,7 +7150,8 @@ TEST_F(LayerTreeHostImplWithTopControlsTest, ScrollHandledByTopControls) { // Now scroll back to the top of the content offset = -content_scroll; - EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset))); + EXPECT_TRUE( + host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll); EXPECT_EQ(-top_controls_height_, host_impl_->top_controls_manager()->ControlsTopOffset()); EXPECT_EQ(gfx::Vector2dF().ToString(), @@ -7073,13 +7159,15 @@ TEST_F(LayerTreeHostImplWithTopControlsTest, ScrollHandledByTopControls) { // And scroll the top controls completely into view offset = -top_controls_height_; - EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset))); + EXPECT_TRUE( + host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll); EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset()); EXPECT_EQ(gfx::Vector2dF().ToString(), scroll_layer->TotalScrollOffset().ToString()); // And attempt to scroll past the end - EXPECT_FALSE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset))); + EXPECT_FALSE( + host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll); EXPECT_EQ(0, host_impl_->top_controls_manager()->ControlsTopOffset()); EXPECT_EQ(gfx::Vector2dF().ToString(), scroll_layer->TotalScrollOffset().ToString()); @@ -7103,7 +7191,8 @@ TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAtOrigin) { // Scroll the top controls partially. const float residue = 35; float offset = top_controls_height_ - residue; - EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset))); + EXPECT_TRUE( + host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll); EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset()); EXPECT_EQ(gfx::Vector2dF().ToString(), scroll_layer->TotalScrollOffset().ToString()); @@ -7171,7 +7260,8 @@ TEST_F(LayerTreeHostImplWithTopControlsTest, TopControlsAnimationAfterScroll) { // Scroll the top controls partially. const float residue = 15; float offset = top_controls_height_ - residue; - EXPECT_TRUE(host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset))); + EXPECT_TRUE( + host_impl_->ScrollBy(gfx::Point(), gfx::Vector2d(0, offset)).did_scroll); EXPECT_EQ(-offset, host_impl_->top_controls_manager()->ControlsTopOffset()); EXPECT_EQ(gfx::Vector2dF(0, initial_scroll_offset).ToString(), scroll_layer->TotalScrollOffset().ToString()); diff --git a/cc/trees/layer_tree_host_unittest_scroll.cc b/cc/trees/layer_tree_host_unittest_scroll.cc index e922f21..8e7d220 100644 --- a/cc/trees/layer_tree_host_unittest_scroll.cc +++ b/cc/trees/layer_tree_host_unittest_scroll.cc @@ -1091,13 +1091,6 @@ class ThreadCheckingInputHandlerClient : public InputHandlerClient { *received_stop_flinging_ = true; } - void DidOverscroll(const gfx::PointF& causal_event_viewport_point, - const gfx::Vector2dF& accumulated_overscroll, - const gfx::Vector2dF& latest_overscroll_delta) override { - if (!task_runner_->BelongsToCurrentThread()) - ADD_FAILURE() << "DidOverscroll called on wrong thread"; - } - private: base::SingleThreadTaskRunner* task_runner_; bool* received_stop_flinging_; diff --git a/content/renderer/input/input_handler_proxy.cc b/content/renderer/input/input_handler_proxy.cc index d9a34ad..44b6139 100644 --- a/content/renderer/input/input_handler_proxy.cc +++ b/content/renderer/input/input_handler_proxy.cc @@ -238,11 +238,13 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleInputEvent( -wheel_event.deltaX, "deltaY", -wheel_event.deltaY); - bool did_scroll = input_handler_->ScrollBy( - gfx::Point(wheel_event.x, wheel_event.y), - gfx::Vector2dF(-wheel_event.deltaX, -wheel_event.deltaY)); + gfx::Point scroll_point(wheel_event.x, wheel_event.y); + gfx::Vector2dF scroll_delta(-wheel_event.deltaX, -wheel_event.deltaY); + cc::InputHandlerScrollResult scroll_result = input_handler_->ScrollBy( + scroll_point, scroll_delta); + HandleOverscroll(scroll_point, scroll_result); input_handler_->ScrollEnd(); - return did_scroll ? DID_HANDLE : DROP_EVENT; + return scroll_result.did_scroll ? DID_HANDLE : DROP_EVENT; } case cc::InputHandler::ScrollIgnored: // TODO(jamesr): This should be DROP_EVENT, but in cases where we fail @@ -297,11 +299,13 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleInputEvent( const WebGestureEvent& gesture_event = *static_cast<const WebGestureEvent*>(&event); - bool did_scroll = input_handler_->ScrollBy( - gfx::Point(gesture_event.x, gesture_event.y), - gfx::Vector2dF(-gesture_event.data.scrollUpdate.deltaX, - -gesture_event.data.scrollUpdate.deltaY)); - return did_scroll ? DID_HANDLE : DROP_EVENT; + gfx::Point scroll_point(gesture_event.x, gesture_event.y); + gfx::Vector2dF scroll_delta(-gesture_event.data.scrollUpdate.deltaX, + -gesture_event.data.scrollUpdate.deltaY); + cc::InputHandlerScrollResult scroll_result = input_handler_->ScrollBy( + scroll_point, scroll_delta); + HandleOverscroll(scroll_point, scroll_result); + return scroll_result.did_scroll ? DID_HANDLE : DROP_EVENT; } else if (event.type == WebInputEvent::GestureScrollEnd) { #ifndef NDEBUG DCHECK(expect_scroll_update_end_); @@ -645,22 +649,23 @@ void InputHandlerProxy::MainThreadHasStoppedFlinging() { client_->DidStopFlinging(); } -void InputHandlerProxy::DidOverscroll( - const gfx::PointF& causal_event_viewport_point, - const gfx::Vector2dF& accumulated_overscroll, - const gfx::Vector2dF& latest_overscroll_delta) { +void InputHandlerProxy::HandleOverscroll( + const gfx::Point& causal_event_viewport_point, + const cc::InputHandlerScrollResult& scroll_result) { DCHECK(client_); + if (!scroll_result.did_overscroll_root) + return; TRACE_EVENT2("input", "InputHandlerProxy::DidOverscroll", "dx", - latest_overscroll_delta.x(), + scroll_result.unused_scroll_delta.x(), "dy", - latest_overscroll_delta.y()); + scroll_result.unused_scroll_delta.y()); DidOverscrollParams params; - params.accumulated_overscroll = accumulated_overscroll; - params.latest_overscroll_delta = latest_overscroll_delta; + params.accumulated_overscroll = scroll_result.accumulated_root_overscroll; + params.latest_overscroll_delta = scroll_result.unused_scroll_delta; params.current_fling_velocity = ToClientScrollIncrement(current_fling_velocity_); params.causal_event_viewport_point = causal_event_viewport_point; @@ -795,11 +800,13 @@ bool InputHandlerProxy::scrollBy(const WebFloatSize& increment, case blink::WebGestureDeviceTouchpad: did_scroll = TouchpadFlingScroll(clipped_increment); break; - case blink::WebGestureDeviceTouchscreen: + case blink::WebGestureDeviceTouchscreen: { clipped_increment = ToClientScrollIncrement(clipped_increment); - did_scroll = input_handler_->ScrollBy(fling_parameters_.point, - clipped_increment); - break; + cc::InputHandlerScrollResult scroll_result = input_handler_->ScrollBy( + fling_parameters_.point, clipped_increment); + HandleOverscroll(fling_parameters_.point, scroll_result); + did_scroll = scroll_result.did_scroll; + } break; } if (did_scroll) { diff --git a/content/renderer/input/input_handler_proxy.h b/content/renderer/input/input_handler_proxy.h index 3507551..39f4346 100644 --- a/content/renderer/input/input_handler_proxy.h +++ b/content/renderer/input/input_handler_proxy.h @@ -7,6 +7,7 @@ #include "base/basictypes.h" #include "base/containers/hash_tables.h" +#include "base/gtest_prod_util.h" #include "base/memory/scoped_ptr.h" #include "cc/input/input_handler.h" #include "content/common/content_export.h" @@ -45,9 +46,6 @@ class CONTENT_EXPORT InputHandlerProxy void WillShutdown() override; void Animate(base::TimeTicks time) override; void MainThreadHasStoppedFlinging() override; - void DidOverscroll(const gfx::PointF& causal_event_viewport_point, - const gfx::Vector2dF& accumulated_overscroll, - const gfx::Vector2dF& latest_overscroll_delta) override; // blink::WebGestureCurveTarget implementation. virtual bool scrollBy(const blink::WebFloatSize& offset, @@ -80,6 +78,11 @@ class CONTENT_EXPORT InputHandlerProxy // Returns true if we actually had an active fling to cancel. bool CancelCurrentFlingWithoutNotifyingClient(); + // Used to send overscroll messages to the browser. + void HandleOverscroll( + const gfx::Point& causal_event_viewport_point, + const cc::InputHandlerScrollResult& scroll_result); + scoped_ptr<blink::WebGestureCurve> fling_curve_; // Parameters for the active fling animation, stored in case we need to // transfer it out later. diff --git a/content/renderer/input/input_handler_proxy_unittest.cc b/content/renderer/input/input_handler_proxy_unittest.cc index 59f3efd..49fa56a 100644 --- a/content/renderer/input/input_handler_proxy_unittest.cc +++ b/content/renderer/input/input_handler_proxy_unittest.cc @@ -90,8 +90,9 @@ class MockInputHandler : public cc::InputHandler { ScrollStatus(const gfx::Point& viewport_point, const gfx::Vector2dF& scroll_delta)); MOCK_METHOD2(ScrollBy, - bool(const gfx::Point& viewport_point, - const gfx::Vector2dF& scroll_delta)); + cc::InputHandlerScrollResult( + const gfx::Point& viewport_point, + const gfx::Vector2dF& scroll_delta)); MOCK_METHOD2(ScrollVerticallyByPage, bool(const gfx::Point& viewport_point, cc::ScrollDirection direction)); @@ -207,6 +208,8 @@ class InputHandlerProxyTest : public testing::Test { : expected_disposition_(InputHandlerProxy::DID_HANDLE) { input_handler_.reset( new content::InputHandlerProxy(&mock_input_handler_, &mock_client_)); + scroll_result_did_scroll_.did_scroll = true; + scroll_result_did_not_scroll_.did_scroll = false; } ~InputHandlerProxyTest() { @@ -264,8 +267,9 @@ class InputHandlerProxyTest : public testing::Test { scoped_ptr<content::InputHandlerProxy> input_handler_; testing::StrictMock<MockInputHandlerProxyClient> mock_client_; WebGestureEvent gesture_; - InputHandlerProxy::EventDisposition expected_disposition_; + cc::InputHandlerScrollResult scroll_result_did_scroll_; + cc::InputHandlerScrollResult scroll_result_did_not_scroll_; }; TEST_F(InputHandlerProxyTest, MouseWheelByPageMainThread) { @@ -309,7 +313,7 @@ TEST_F(InputHandlerProxyTest, GestureScrollStarted) { EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::y, testing::Gt(0)))) - .WillOnce(testing::Return(false)); + .WillOnce(testing::Return(scroll_result_did_not_scroll_)); EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); // Mark the event as handled if scroll happens. @@ -322,7 +326,7 @@ TEST_F(InputHandlerProxyTest, GestureScrollStarted) { EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::y, testing::Gt(0)))) - .WillOnce(testing::Return(true)); + .WillOnce(testing::Return(scroll_result_did_scroll_)); EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); VERIFY_AND_RESET_MOCKS(); @@ -456,7 +460,7 @@ TEST_F(InputHandlerProxyTest, GesturePinchAfterScrollOnMainThread) { EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::y, testing::Gt(0)))) - .WillOnce(testing::Return(true)); + .WillOnce(testing::Return(scroll_result_did_scroll_)); EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); VERIFY_AND_RESET_MOCKS(); @@ -601,7 +605,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingAnimatesTouchpad) { EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Lt(0)))) - .WillOnce(testing::Return(true)); + .WillOnce(testing::Return(scroll_result_did_scroll_)); EXPECT_CALL(mock_input_handler_, ScrollEnd()); time += base::TimeDelta::FromMilliseconds(100); input_handler_->Animate(time); @@ -704,7 +708,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingTransferResetsTouchpad) { EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Lt(0)))) - .WillOnce(testing::Return(true)); + .WillOnce(testing::Return(scroll_result_did_scroll_)); EXPECT_CALL(mock_input_handler_, ScrollEnd()); time += base::TimeDelta::FromMilliseconds(100); input_handler_->Animate(time); @@ -805,7 +809,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingTransferResetsTouchpad) { EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::y, testing::Gt(0)))) - .WillOnce(testing::Return(true)); + .WillOnce(testing::Return(scroll_result_did_scroll_)); EXPECT_CALL(mock_input_handler_, ScrollEnd()); time += base::TimeDelta::FromMilliseconds(100); input_handler_->Animate(time); @@ -977,7 +981,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingAnimatesTouchscreen) { EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Lt(0)))) - .WillOnce(testing::Return(true)); + .WillOnce(testing::Return(scroll_result_did_scroll_)); time += base::TimeDelta::FromMilliseconds(100); input_handler_->Animate(time); @@ -1031,7 +1035,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingWithValidTimestamp) { EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Lt(0)))) - .WillOnce(testing::Return(true)); + .WillOnce(testing::Return(scroll_result_did_scroll_)); time += dt; input_handler_->Animate(time); @@ -1094,7 +1098,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingWithInvalidTimestamp) { EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Lt(0)))) - .WillOnce(testing::Return(true)); + .WillOnce(testing::Return(scroll_result_did_scroll_)); time += base::TimeDelta::FromMilliseconds(10); input_handler_->Animate(time); @@ -1161,7 +1165,7 @@ TEST_F(InputHandlerProxyTest, EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Lt(0)))) - .WillOnce(testing::Return(true)); + .WillOnce(testing::Return(scroll_result_did_scroll_)); time += base::TimeDelta::FromMilliseconds(100); input_handler_->Animate(time); @@ -1187,10 +1191,10 @@ TEST_F(InputHandlerProxyTest, GestureFlingStopsAtContentEdge) { WebFloatPoint fling_delta = WebFloatPoint(100, 100); gesture_.data.flingStart.velocityX = fling_delta.x; gesture_.data.flingStart.velocityY = fling_delta.y; - EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); EXPECT_CALL(mock_input_handler_, ScrollEnd()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); @@ -1201,35 +1205,48 @@ TEST_F(InputHandlerProxyTest, GestureFlingStopsAtContentEdge) { testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); // The second animate starts scrolling in the positive X and Y directions. - EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::y, testing::Lt(0)))) - .WillOnce(testing::Return(true)); + .WillOnce(testing::Return(scroll_result_did_scroll_)); EXPECT_CALL(mock_input_handler_, ScrollEnd()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); time += base::TimeDelta::FromMilliseconds(100); input_handler_->Animate(time); testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); - // Simulate hitting the bottom content edge. - gfx::Vector2dF accumulated_overscroll(0, 100); - gfx::Vector2dF latest_overscroll_delta(0, 10); - gfx::PointF scroll_point(10, 0); + // The third animate overscrolls in the positive Y direction but scrolls + // somewhat. + cc::InputHandlerScrollResult overscroll; + overscroll.did_scroll = true; + overscroll.did_overscroll_root = true; + overscroll.accumulated_root_overscroll = gfx::Vector2dF(0, 100); + overscroll.unused_scroll_delta = gfx::Vector2dF(0, 10); + EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) + .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); + EXPECT_CALL(mock_input_handler_, + ScrollBy(testing::_, + testing::Property(&gfx::Vector2dF::y, testing::Lt(0)))) + .WillOnce(testing::Return(overscroll)); EXPECT_CALL( mock_client_, DidOverscroll(testing::AllOf( - testing::Field(&DidOverscrollParams::accumulated_overscroll, - testing::Eq(accumulated_overscroll)), - testing::Field(&DidOverscrollParams::latest_overscroll_delta, - testing::Eq(latest_overscroll_delta)), - testing::Field(&DidOverscrollParams::current_fling_velocity, - testing::Property(&gfx::Vector2dF::y, testing::Lt(0))), - testing::Field(&DidOverscrollParams::causal_event_viewport_point, - testing::Eq(scroll_point))))); - input_handler_->DidOverscroll( - scroll_point, accumulated_overscroll, latest_overscroll_delta); + testing::Field( + &DidOverscrollParams::accumulated_overscroll, + testing::Eq(overscroll.accumulated_root_overscroll)), + testing::Field( + &DidOverscrollParams::latest_overscroll_delta, + testing::Eq(overscroll.unused_scroll_delta)), + testing::Field( + &DidOverscrollParams::current_fling_velocity, + testing::Property(&gfx::Vector2dF::y, testing::Lt(0)))))); + EXPECT_CALL(mock_input_handler_, ScrollEnd()); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); + time += base::TimeDelta::FromMilliseconds(100); + input_handler_->Animate(time); + testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); // The next call to animate will no longer scroll vertically. EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); @@ -1238,7 +1255,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingStopsAtContentEdge) { EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::y, testing::Eq(0)))) - .WillOnce(testing::Return(true)); + .WillOnce(testing::Return(scroll_result_did_scroll_)); EXPECT_CALL(mock_input_handler_, ScrollEnd()); time += base::TimeDelta::FromMilliseconds(100); input_handler_->Animate(time); @@ -1293,7 +1310,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingNotCancelledBySmallTimeDelta) { EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Lt(0)))) - .WillOnce(testing::Return(false)); + .WillOnce(testing::Return(scroll_result_did_not_scroll_)); time += base::TimeDelta::FromMicroseconds(5); input_handler_->Animate(time); @@ -1314,7 +1331,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingNotCancelledBySmallTimeDelta) { EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Lt(1)))) - .WillOnce(testing::Return(false)); + .WillOnce(testing::Return(scroll_result_did_not_scroll_)); time += base::TimeDelta::FromMilliseconds(100); input_handler_->Animate(time); @@ -1323,6 +1340,10 @@ TEST_F(InputHandlerProxyTest, GestureFlingNotCancelledBySmallTimeDelta) { } TEST_F(InputHandlerProxyTest, GestureFlingCancelledAfterBothAxesStopScrolling) { + cc::InputHandlerScrollResult overscroll; + overscroll.did_scroll = true; + overscroll.did_overscroll_root = true; + // We shouldn't send any events to the widget for this gesture. expected_disposition_ = InputHandlerProxy::DID_HANDLE; VERIFY_AND_RESET_MOCKS(); @@ -1357,61 +1378,73 @@ TEST_F(InputHandlerProxyTest, GestureFlingCancelledAfterBothAxesStopScrolling) { EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::y, testing::Lt(0)))) - .WillOnce(testing::Return(true)); + .WillOnce(testing::Return(scroll_result_did_scroll_)); time += base::TimeDelta::FromMilliseconds(10); input_handler_->Animate(time); testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); - // Simulate hitting the bottom content edge. - gfx::Vector2dF accumulated_overscroll(0, 100); - gfx::Vector2dF latest_overscroll_delta(0, 100); - gfx::PointF scroll_point(10, -50); + // The third animate hits the bottom content edge. + overscroll.accumulated_root_overscroll = gfx::Vector2dF(0, 100); + overscroll.unused_scroll_delta = gfx::Vector2dF(0, 100); + EXPECT_CALL(mock_input_handler_, + ScrollBy(testing::_, + testing::Property(&gfx::Vector2dF::y, testing::Lt(0)))) + .WillOnce(testing::Return(overscroll)); EXPECT_CALL( mock_client_, DidOverscroll(testing::AllOf( - testing::Field(&DidOverscrollParams::accumulated_overscroll, - testing::Eq(accumulated_overscroll)), - testing::Field(&DidOverscrollParams::latest_overscroll_delta, - testing::Eq(latest_overscroll_delta)), - testing::Field(&DidOverscrollParams::current_fling_velocity, - testing::Property(&gfx::Vector2dF::y, testing::Lt(0))), - testing::Field(&DidOverscrollParams::causal_event_viewport_point, - testing::Eq(scroll_point))))); - input_handler_->DidOverscroll( - scroll_point, accumulated_overscroll, latest_overscroll_delta); + testing::Field( + &DidOverscrollParams::accumulated_overscroll, + testing::Eq(overscroll.accumulated_root_overscroll)), + testing::Field( + &DidOverscrollParams::latest_overscroll_delta, + testing::Eq(overscroll.unused_scroll_delta)), + testing::Field( + &DidOverscrollParams::current_fling_velocity, + testing::Property(&gfx::Vector2dF::y, testing::Lt(0)))))); + EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); + time += base::TimeDelta::FromMilliseconds(10); + input_handler_->Animate(time); + testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); // The next call to animate will no longer scroll vertically. EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()); EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::y, testing::Eq(0)))) - .WillOnce(testing::Return(true)); + .WillOnce(testing::Return(scroll_result_did_scroll_)); time += base::TimeDelta::FromMilliseconds(10); input_handler_->Animate(time); testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); - // Simulate hitting the right content edge. - accumulated_overscroll = gfx::Vector2dF(100, 100); - latest_overscroll_delta = gfx::Vector2dF(100, 0); - scroll_point = gfx::PointF(50, 0); + // The next call will hit the right edge. + overscroll.accumulated_root_overscroll = gfx::Vector2dF(100, 100); + overscroll.unused_scroll_delta = gfx::Vector2dF(100, 0); + EXPECT_CALL(mock_input_handler_, + ScrollBy(testing::_, + testing::Property(&gfx::Vector2dF::x, testing::Lt(0)))) + .WillOnce(testing::Return(overscroll)); EXPECT_CALL( mock_client_, DidOverscroll(testing::AllOf( - testing::Field(&DidOverscrollParams::accumulated_overscroll, - testing::Eq(accumulated_overscroll)), - testing::Field(&DidOverscrollParams::latest_overscroll_delta, - testing::Eq(latest_overscroll_delta)), - testing::Field(&DidOverscrollParams::current_fling_velocity, - testing::Property(&gfx::Vector2dF::x, testing::Lt(0))), - testing::Field(&DidOverscrollParams::causal_event_viewport_point, - testing::Eq(scroll_point))))); - input_handler_->DidOverscroll( - scroll_point, accumulated_overscroll, latest_overscroll_delta); + testing::Field( + &DidOverscrollParams::accumulated_overscroll, + testing::Eq(overscroll.accumulated_root_overscroll)), + testing::Field( + &DidOverscrollParams::latest_overscroll_delta, + testing::Eq(overscroll.unused_scroll_delta)), + testing::Field( + &DidOverscrollParams::current_fling_velocity, + testing::Property(&gfx::Vector2dF::x, testing::Lt(0)))))); + EXPECT_CALL(mock_input_handler_, ScrollEnd()); + time += base::TimeDelta::FromMilliseconds(10); + input_handler_->Animate(time); + testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + // The next call to animate will no longer scroll horizontally or vertically, // and the fling should be cancelled. EXPECT_CALL(mock_input_handler_, SetNeedsAnimate()).Times(0); EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::_)).Times(0); - EXPECT_CALL(mock_input_handler_, ScrollEnd()); time += base::TimeDelta::FromMilliseconds(10); input_handler_->Animate(time); testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); @@ -1575,7 +1608,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingWithNegativeTimeDelta) { EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Lt(0)))) - .WillOnce(testing::Return(true)); + .WillOnce(testing::Return(scroll_result_did_scroll_)); input_handler_->Animate(time + base::TimeDelta::FromMilliseconds(1)); @@ -1622,7 +1655,7 @@ TEST_F(InputHandlerProxyTest, FlingBoost) { ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Eq(expected_delta)))) - .WillOnce(testing::Return(true)); + .WillOnce(testing::Return(scroll_result_did_scroll_)); input_handler_->Animate(time); last_animate_time = time; @@ -1646,7 +1679,7 @@ TEST_F(InputHandlerProxyTest, FlingBoost) { ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Eq(expected_delta)))) - .WillOnce(testing::Return(true)); + .WillOnce(testing::Return(scroll_result_did_scroll_)); input_handler_->Animate(time); last_animate_time = time; @@ -1672,7 +1705,7 @@ TEST_F(InputHandlerProxyTest, FlingBoost) { ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Eq(expected_delta)))) - .WillOnce(testing::Return(true)); + .WillOnce(testing::Return(scroll_result_did_scroll_)); input_handler_->Animate(time); last_animate_time = time; @@ -1698,7 +1731,7 @@ TEST_F(InputHandlerProxyTest, FlingBoost) { ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Eq(expected_delta)))) - .WillOnce(testing::Return(true)); + .WillOnce(testing::Return(scroll_result_did_scroll_)); input_handler_->Animate(time); last_animate_time = time; @@ -1824,7 +1857,7 @@ TEST_F(InputHandlerProxyTest, NoFlingBoostIfFlingInDifferentDirection) { ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::y, testing::Eq(expected_delta)))) - .WillOnce(testing::Return(true)); + .WillOnce(testing::Return(scroll_result_did_scroll_)); input_handler_->Animate(time); VERIFY_AND_RESET_MOCKS(); @@ -1869,7 +1902,7 @@ TEST_F(InputHandlerProxyTest, NoFlingBoostIfScrollInDifferentDirection) { ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Eq(fling_delta.x)))) - .WillOnce(testing::Return(true)); + .WillOnce(testing::Return(scroll_result_did_scroll_)); EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); VERIFY_AND_RESET_MOCKS(); @@ -1909,7 +1942,7 @@ TEST_F(InputHandlerProxyTest, NoFlingBoostIfFlingTooSlow) { ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Eq(expected_delta)))) - .WillOnce(testing::Return(true)); + .WillOnce(testing::Return(scroll_result_did_scroll_)); input_handler_->Animate(time); VERIFY_AND_RESET_MOCKS(); @@ -1951,7 +1984,7 @@ TEST_F(InputHandlerProxyTest, FlingBoostTerminatedDuringScrollSequence) { ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Eq(expected_delta)))) - .WillOnce(testing::Return(false)); + .WillOnce(testing::Return(scroll_result_did_not_scroll_)); EXPECT_CALL(mock_input_handler_, ScrollEnd()); EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); @@ -1970,7 +2003,7 @@ TEST_F(InputHandlerProxyTest, FlingBoostTerminatedDuringScrollSequence) { ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Eq(expected_delta)))) - .WillOnce(testing::Return(true)); + .WillOnce(testing::Return(scroll_result_did_scroll_)); EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); VERIFY_AND_RESET_MOCKS(); |