Index: content/renderer/gpu/input_handler_proxy_unittest.cc |
diff --git a/content/renderer/gpu/input_handler_proxy_unittest.cc b/content/renderer/gpu/input_handler_proxy_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..f1a6e6779afdd8c830359568fb66ed735717801b |
--- /dev/null |
+++ b/content/renderer/gpu/input_handler_proxy_unittest.cc |
@@ -0,0 +1,995 @@ |
+// Copyright (c) 2013 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 "content/renderer/gpu/input_handler_proxy.h" |
+ |
+#include "base/basictypes.h" |
+#include "base/memory/scoped_ptr.h" |
+#include "content/renderer/gpu/input_handler_proxy_client.h" |
+#include "testing/gmock/include/gmock/gmock.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+#include "third_party/WebKit/Source/Platform/chromium/public/WebFloatPoint.h" |
+#include "third_party/WebKit/Source/Platform/chromium/public/WebFloatSize.h" |
+#include "third_party/WebKit/Source/Platform/chromium/public/WebGestureCurve.h" |
+#include "third_party/WebKit/Source/Platform/chromium/public/WebPoint.h" |
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h" |
+ |
+using WebKit::WebActiveWheelFlingParameters; |
+using WebKit::WebFloatPoint; |
+using WebKit::WebFloatSize; |
+using WebKit::WebGestureEvent; |
+using WebKit::WebInputEvent; |
+using WebKit::WebMouseWheelEvent; |
+using WebKit::WebPoint; |
+using WebKit::WebSize; |
+ |
+namespace { |
+ |
+class MockInputHandler : public cc::InputHandler { |
+ public: |
+ MockInputHandler() {} |
+ virtual ~MockInputHandler() {} |
+ |
+ MOCK_METHOD0(PinchGestureBegin, void()); |
+ MOCK_METHOD2(PinchGestureUpdate, |
+ void(float magnify_delta, gfx::Point anchor)); |
+ MOCK_METHOD0(PinchGestureEnd, void()); |
+ |
+ MOCK_METHOD0(ScheduleAnimation, void()); |
+ |
+ MOCK_METHOD2(ScrollBegin, |
+ ScrollStatus(gfx::Point viewport_point, |
+ cc::InputHandler::ScrollInputType type)); |
+ MOCK_METHOD2(ScrollBy, |
+ bool(gfx::Point viewport_point, gfx::Vector2dF scroll_delta)); |
+ MOCK_METHOD2(ScrollVerticallyByPage, |
+ bool(gfx::Point viewport_point, |
+ WebKit::WebScrollbar::ScrollDirection direction)); |
+ MOCK_METHOD0(ScrollEnd, void()); |
+ MOCK_METHOD0(FlingScrollBegin, cc::InputHandler::ScrollStatus()); |
+ |
+ MOCK_METHOD1(DidReceiveLastInputEventForVSync, void(base::TimeTicks time)); |
+ |
+ virtual void BindToClient(cc::InputHandlerClient* client) OVERRIDE {} |
+ |
+ virtual void StartPageScaleAnimation(gfx::Vector2d target_offset, |
+ bool anchor_point, |
+ float page_scale, |
+ base::TimeTicks start_time, |
+ base::TimeDelta duration) OVERRIDE {} |
+ |
+ virtual void NotifyCurrentFlingVelocity(gfx::Vector2dF velocity) OVERRIDE {} |
+ |
+ virtual bool HaveTouchEventHandlersAt(gfx::Point point) OVERRIDE { |
+ return false; |
+ } |
+ |
+ virtual void SetRootLayerScrollOffsetDelegate( |
+ cc::LayerScrollOffsetDelegate* root_layer_scroll_offset_delegate) |
+ OVERRIDE {} |
+ |
+ virtual void OnRootLayerDelegatedScrollOffsetChanged() OVERRIDE {} |
+ |
+ DISALLOW_COPY_AND_ASSIGN(MockInputHandler); |
+}; |
+ |
+// A simple WebGestureCurve implementation that flings at a constant velocity |
+// indefinitely. |
+class FakeWebGestureCurve : public WebKit::WebGestureCurve { |
+ public: |
+ FakeWebGestureCurve(const WebKit::WebFloatPoint& velocity, |
+ const WebKit::WebSize& cumulative_scroll) |
+ : velocity_(velocity), cumulative_scroll_(cumulative_scroll) {} |
+ |
+ virtual ~FakeWebGestureCurve() {} |
+ |
+ // Returns false if curve has finished and can no longer be applied. |
+ virtual bool apply(double time, WebKit::WebGestureCurveTarget* target) { |
+ WebKit::WebSize displacement(velocity_.x * time, velocity_.y * time); |
+ WebKit::WebFloatSize increment( |
+ displacement.width - cumulative_scroll_.width, |
+ displacement.height - cumulative_scroll_.height); |
+ cumulative_scroll_ = displacement; |
+ // scrollBy() could delete this curve if the animation is over, so don't |
+ // touch any member variables after making that call. |
+ target->scrollBy(increment); |
+ return true; |
+ } |
+ |
+ private: |
+ WebKit::WebFloatPoint velocity_; |
+ WebKit::WebSize cumulative_scroll_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(FakeWebGestureCurve); |
+}; |
+ |
+class MockInputHandlerProxyClient |
+ : public content::InputHandlerProxyClient { |
+ public: |
+ MockInputHandlerProxyClient() {} |
+ virtual ~MockInputHandlerProxyClient() {} |
+ |
+ virtual void WillShutdown() OVERRIDE {} |
+ |
+ MOCK_METHOD0(DidHandleInputEvent, void()); |
+ MOCK_METHOD1(DidNotHandleInputEvent, void(bool send_to_widget)); |
+ |
+ MOCK_METHOD1(TransferActiveWheelFlingAnimation, |
+ void(const WebActiveWheelFlingParameters&)); |
+ |
+ virtual WebKit::WebGestureCurve* CreateFlingAnimationCurve( |
+ int deviceSource, |
+ const WebFloatPoint& velocity, |
+ const WebSize& cumulative_scroll) OVERRIDE { |
+ return new FakeWebGestureCurve(velocity, cumulative_scroll); |
+ } |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(MockInputHandlerProxyClient); |
+}; |
+ |
+class InputHandlerProxyTest : public testing::Test { |
+ public: |
+ InputHandlerProxyTest() : expected_disposition_(DidHandle) { |
+ input_handler_.reset( |
+ new content::InputHandlerProxy(&mock_input_handler_)); |
+ input_handler_->SetClient(&mock_client_); |
+ } |
+ |
+ ~InputHandlerProxyTest() { |
+ input_handler_.reset(); |
+ } |
+ |
+// This is defined as a macro because when an expectation is not satisfied the |
+// only output you get |
+// out of gmock is the line number that set the expectation. |
+#define VERIFY_AND_RESET_MOCKS() \ |
+ do { \ |
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); \ |
+ testing::Mock::VerifyAndClearExpectations(&mock_client_); \ |
+ switch (expected_disposition_) { \ |
+ case DidHandle: \ |
+ /* If we expect to handle events, we shouldn't get any */ \ |
+ /* DidNotHandleInputEvent() calls with any parameter. */ \ |
+ EXPECT_CALL(mock_client_, DidNotHandleInputEvent(::testing::_)) \ |
+ .Times(0); \ |
+ EXPECT_CALL(mock_client_, DidHandleInputEvent()); \ |
+ break; \ |
+ case DidNotHandle: \ |
+ /* If we aren't expecting to handle events, we shouldn't call */ \ |
+ /* DidHandleInputEvent(). */ \ |
+ EXPECT_CALL(mock_client_, DidHandleInputEvent()).Times(0); \ |
+ EXPECT_CALL(mock_client_, DidNotHandleInputEvent(false)).Times(0); \ |
+ EXPECT_CALL(mock_client_, DidNotHandleInputEvent(true)); \ |
+ break; \ |
+ case DropEvent: \ |
+ /* If we're expecting to drop, we shouldn't get any didHandle..() */ \ |
+ /* or DidNotHandleInputEvent(true) calls. */ \ |
+ EXPECT_CALL(mock_client_, DidHandleInputEvent()).Times(0); \ |
+ EXPECT_CALL(mock_client_, DidNotHandleInputEvent(true)).Times(0); \ |
+ EXPECT_CALL(mock_client_, DidNotHandleInputEvent(false)); \ |
+ break; \ |
+ } \ |
+ } while (false) |
+ |
+ protected: |
+ testing::StrictMock<MockInputHandler> mock_input_handler_; |
+ scoped_ptr<content::InputHandlerProxy> input_handler_; |
+ testing::StrictMock<MockInputHandlerProxyClient> mock_client_; |
+ WebGestureEvent gesture_; |
+ |
+ enum ExpectedDisposition { |
+ DidHandle, |
+ DidNotHandle, |
+ DropEvent |
+ }; |
+ ExpectedDisposition expected_disposition_; |
+}; |
+ |
+TEST_F(InputHandlerProxyTest, MouseWheelByPageMainThread) { |
+ WebMouseWheelEvent wheel; |
+ wheel.type = WebInputEvent::MouseWheel; |
+ wheel.scrollByPage = true; |
+ |
+ EXPECT_CALL(mock_client_, DidNotHandleInputEvent(true)).Times(1); |
+ input_handler_->HandleInputEvent(wheel); |
+ testing::Mock::VerifyAndClearExpectations(&mock_client_); |
+} |
+ |
+TEST_F(InputHandlerProxyTest, GestureScrollStarted) { |
+ // We shouldn't send any events to the widget for this gesture. |
+ expected_disposition_ = DidHandle; |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) |
+ .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); |
+ |
+ gesture_.type = WebInputEvent::GestureScrollBegin; |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ // The event should not be marked as handled if scrolling is not possible. |
+ expected_disposition_ = DropEvent; |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ gesture_.type = WebInputEvent::GestureScrollUpdate; |
+ gesture_.data.scrollUpdate.deltaY = |
+ -40; // -Y means scroll down - i.e. in the +Y direction. |
+ EXPECT_CALL(mock_input_handler_, |
+ ScrollBy(testing::_, |
+ testing::Property(&gfx::Vector2dF::y, testing::Gt(0)))) |
+ .WillOnce(testing::Return(false)); |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ // Mark the event as handled if scroll happens. |
+ expected_disposition_ = DidHandle; |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ gesture_.type = WebInputEvent::GestureScrollUpdate; |
+ gesture_.data.scrollUpdate.deltaY = |
+ -40; // -Y means scroll down - i.e. in the +Y direction. |
+ EXPECT_CALL(mock_input_handler_, |
+ ScrollBy(testing::_, |
+ testing::Property(&gfx::Vector2dF::y, testing::Gt(0)))) |
+ .WillOnce(testing::Return(true)); |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ gesture_.type = WebInputEvent::GestureScrollEnd; |
+ gesture_.data.scrollUpdate.deltaY = 0; |
+ EXPECT_CALL(mock_input_handler_, ScrollEnd()); |
+ input_handler_->HandleInputEvent(gesture_); |
+} |
+ |
+TEST_F(InputHandlerProxyTest, GestureScrollOnMainThread) { |
+ // We should send all events to the widget for this gesture. |
+ expected_disposition_ = DidNotHandle; |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(::testing::_, ::testing::_)) |
+ .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread)); |
+ |
+ gesture_.type = WebInputEvent::GestureScrollBegin; |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ gesture_.type = WebInputEvent::GestureScrollUpdate; |
+ gesture_.data.scrollUpdate.deltaY = 40; |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ gesture_.type = WebInputEvent::GestureScrollEnd; |
+ gesture_.data.scrollUpdate.deltaY = 0; |
+ input_handler_->HandleInputEvent(gesture_); |
+} |
+ |
+TEST_F(InputHandlerProxyTest, GestureScrollIgnored) { |
+ // We shouldn't handle the GestureScrollBegin. |
+ // Instead, we should get one DidNotHandleInputEvent(false) call per |
+ // HandleInputEvent(), indicating that we could determine that there's nothing |
+ // that could scroll or otherwise react to this gesture sequence and thus we |
+ // should drop the whole gesture sequence on the floor. |
+ expected_disposition_ = DropEvent; |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) |
+ .WillOnce(testing::Return(cc::InputHandler::ScrollIgnored)); |
+ |
+ gesture_.type = WebInputEvent::GestureScrollBegin; |
+ input_handler_->HandleInputEvent(gesture_); |
+} |
+ |
+TEST_F(InputHandlerProxyTest, GesturePinch) { |
+ // We shouldn't send any events to the widget for this gesture. |
+ expected_disposition_ = DidHandle; |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ gesture_.type = WebInputEvent::GesturePinchBegin; |
+ EXPECT_CALL(mock_input_handler_, PinchGestureBegin()); |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ gesture_.type = WebInputEvent::GesturePinchUpdate; |
+ gesture_.data.pinchUpdate.scale = 1.5; |
+ gesture_.x = 7; |
+ gesture_.y = 13; |
+ EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(1.5, gfx::Point(7, 13))); |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ gesture_.type = WebInputEvent::GesturePinchUpdate; |
+ gesture_.data.pinchUpdate.scale = 0.5; |
+ gesture_.x = 9; |
+ gesture_.y = 6; |
+ EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(.5, gfx::Point(9, 6))); |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ gesture_.type = WebInputEvent::GesturePinchEnd; |
+ EXPECT_CALL(mock_input_handler_, PinchGestureEnd()); |
+ input_handler_->HandleInputEvent(gesture_); |
+} |
+ |
+TEST_F(InputHandlerProxyTest, GesturePinchAfterScrollOnMainThread) { |
+ // Scrolls will start by being sent to the main thread. |
+ expected_disposition_ = DidNotHandle; |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(::testing::_, ::testing::_)) |
+ .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread)); |
+ |
+ gesture_.type = WebInputEvent::GestureScrollBegin; |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ gesture_.type = WebInputEvent::GestureScrollUpdate; |
+ gesture_.data.scrollUpdate.deltaY = 40; |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ // However, after the pinch gesture starts, they should go to the impl |
+ // thread. |
+ expected_disposition_ = DidHandle; |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ gesture_.type = WebInputEvent::GesturePinchBegin; |
+ EXPECT_CALL(mock_input_handler_, PinchGestureBegin()); |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ gesture_.type = WebInputEvent::GesturePinchUpdate; |
+ gesture_.data.pinchUpdate.scale = 1.5; |
+ gesture_.x = 7; |
+ gesture_.y = 13; |
+ EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(1.5, gfx::Point(7, 13))); |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ gesture_.type = WebInputEvent::GestureScrollUpdate; |
+ gesture_.data.scrollUpdate.deltaY = |
+ -40; // -Y means scroll down - i.e. in the +Y direction. |
+ EXPECT_CALL(mock_input_handler_, |
+ ScrollBy(testing::_, |
+ testing::Property(&gfx::Vector2dF::y, testing::Gt(0)))) |
+ .WillOnce(testing::Return(true)); |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ gesture_.type = WebInputEvent::GesturePinchUpdate; |
+ gesture_.data.pinchUpdate.scale = 0.5; |
+ gesture_.x = 9; |
+ gesture_.y = 6; |
+ EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(.5, gfx::Point(9, 6))); |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ gesture_.type = WebInputEvent::GesturePinchEnd; |
+ EXPECT_CALL(mock_input_handler_, PinchGestureEnd()); |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ // After the pinch gesture ends, they should go to back to the main |
+ // thread. |
+ expected_disposition_ = DidNotHandle; |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ gesture_.type = WebInputEvent::GestureScrollEnd; |
+ gesture_.data.scrollUpdate.deltaY = 0; |
+ input_handler_->HandleInputEvent(gesture_); |
+} |
+ |
+TEST_F(InputHandlerProxyTest, GestureFlingStartedTouchpad) { |
+ // We shouldn't send any events to the widget for this gesture. |
+ expected_disposition_ = DidHandle; |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ 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_, ScheduleAnimation()); |
+ |
+ gesture_.type = WebInputEvent::GestureFlingStart; |
+ gesture_.data.flingStart.velocityX = 10; |
+ gesture_.sourceDevice = WebGestureEvent::Touchpad; |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ // Verify that a GestureFlingCancel during an animation cancels it. |
+ gesture_.type = WebInputEvent::GestureFlingCancel; |
+ gesture_.sourceDevice = WebGestureEvent::Touchpad; |
+ input_handler_->HandleInputEvent(gesture_); |
+} |
+ |
+TEST_F(InputHandlerProxyTest, GestureFlingOnMainThreadTouchpad) { |
+ // We should send all events to the widget for this gesture. |
+ expected_disposition_ = DidNotHandle; |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) |
+ .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread)); |
+ |
+ gesture_.type = WebInputEvent::GestureFlingStart; |
+ gesture_.sourceDevice = WebGestureEvent::Touchpad; |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ // Since we returned ScrollStatusOnMainThread from scrollBegin, ensure the |
+ // input handler knows it's scrolling off the impl thread |
+ ASSERT_FALSE(input_handler_->gesture_scroll_on_impl_thread_for_testing()); |
+ |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ // Even if we didn't start a fling ourselves, we still need to send the cancel |
+ // event to the widget. |
+ gesture_.type = WebInputEvent::GestureFlingCancel; |
+ gesture_.sourceDevice = WebGestureEvent::Touchpad; |
+ input_handler_->HandleInputEvent(gesture_); |
+} |
+ |
+TEST_F(InputHandlerProxyTest, GestureFlingIgnoredTouchpad) { |
+ expected_disposition_ = DidNotHandle; |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) |
+ .WillOnce(testing::Return(cc::InputHandler::ScrollIgnored)); |
+ |
+ gesture_.type = WebInputEvent::GestureFlingStart; |
+ gesture_.sourceDevice = WebGestureEvent::Touchpad; |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ expected_disposition_ = DropEvent; |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ // Since the previous fling was ignored, we should also be dropping the next |
+ // fling_cancel. |
+ gesture_.type = WebInputEvent::GestureFlingCancel; |
+ gesture_.sourceDevice = WebGestureEvent::Touchpad; |
+ input_handler_->HandleInputEvent(gesture_); |
+} |
+ |
+TEST_F(InputHandlerProxyTest, GestureFlingAnimatesTouchpad) { |
+ // We shouldn't send any events to the widget for this gesture. |
+ expected_disposition_ = DidHandle; |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ // On the fling start, we should schedule an animation but not actually start |
+ // scrolling. |
+ gesture_.type = WebInputEvent::GestureFlingStart; |
+ WebFloatPoint fling_delta = WebFloatPoint(1000, 0); |
+ WebPoint fling_point = WebPoint(7, 13); |
+ WebPoint fling_global_point = WebPoint(17, 23); |
+ int modifiers = 7; |
+ gesture_.data.flingStart.velocityX = fling_delta.x; |
+ gesture_.data.flingStart.velocityY = fling_delta.y; |
+ gesture_.sourceDevice = WebGestureEvent::Touchpad; |
+ gesture_.x = fling_point.x; |
+ gesture_.y = fling_point.y; |
+ gesture_.globalX = fling_global_point.x; |
+ gesture_.globalY = fling_global_point.y; |
+ gesture_.modifiers = modifiers; |
+ EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); |
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) |
+ .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); |
+ EXPECT_CALL(mock_input_handler_, ScrollEnd()); |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); |
+ // The first animate call should let us pick up an animation start time, but |
+ // we shouldn't actually move anywhere just yet. The first frame after the |
+ // fling start will typically include the last scroll from the gesture that |
+ // lead to the scroll (either wheel or gesture scroll), so there should be no |
+ // visible hitch. |
+ EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); |
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) |
+ .Times(0); |
+ base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10); |
+ input_handler_->Animate(time); |
+ |
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); |
+ |
+ // The second call should start scrolling in the -X direction. |
+ EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); |
+ 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::x, testing::Lt(0)))) |
+ .WillOnce(testing::Return(true)); |
+ EXPECT_CALL(mock_input_handler_, ScrollEnd()); |
+ time += base::TimeDelta::FromMilliseconds(100); |
+ input_handler_->Animate(time); |
+ |
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); |
+ |
+ // Let's say on the third call we hit a non-scrollable region. We should abort |
+ // the fling and not scroll. |
+ // We also should pass the current fling parameters out to the client so the |
+ // rest of the fling can be |
+ // transferred to the main thread. |
+ EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); |
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) |
+ .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread)); |
+ EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::_)).Times(0); |
+ EXPECT_CALL(mock_input_handler_, ScrollEnd()).Times(0); |
+ // Expected wheel fling animation parameters: |
+ // *) fling_delta and fling_point should match the original GestureFlingStart |
+ // event |
+ // *) startTime should be 10 to match the time parameter of the first |
+ // Animate() call after the GestureFlingStart |
+ // *) cumulativeScroll depends on the curve, but since we've animated in the |
+ // -X direction the X value should be < 0 |
+ EXPECT_CALL( |
+ mock_client_, |
+ TransferActiveWheelFlingAnimation(testing::AllOf( |
+ testing::Field(&WebActiveWheelFlingParameters::delta, |
+ testing::Eq(fling_delta)), |
+ testing::Field(&WebActiveWheelFlingParameters::point, |
+ testing::Eq(fling_point)), |
+ testing::Field(&WebActiveWheelFlingParameters::globalPoint, |
+ testing::Eq(fling_global_point)), |
+ testing::Field(&WebActiveWheelFlingParameters::modifiers, |
+ testing::Eq(modifiers)), |
+ testing::Field(&WebActiveWheelFlingParameters::startTime, |
+ testing::Eq(10)), |
+ testing::Field(&WebActiveWheelFlingParameters::cumulativeScroll, |
+ testing::Field(&WebSize::width, testing::Gt(0)))))); |
+ time += base::TimeDelta::FromMilliseconds(100); |
+ input_handler_->Animate(time); |
+ |
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); |
+ testing::Mock::VerifyAndClearExpectations(&mock_client_); |
+ |
+ // Since we've aborted the fling, the next animation should be a no-op and |
+ // should not result in another |
+ // frame being requested. |
+ EXPECT_CALL(mock_input_handler_, ScheduleAnimation()).Times(0); |
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) |
+ .Times(0); |
+ time += base::TimeDelta::FromMilliseconds(100); |
+ input_handler_->Animate(time); |
+ |
+ // Since we've transferred the fling to the main thread, we need to pass the |
+ // next GestureFlingCancel to the main |
+ // thread as well. |
+ EXPECT_CALL(mock_client_, DidNotHandleInputEvent(true)); |
+ gesture_.type = WebInputEvent::GestureFlingCancel; |
+ input_handler_->HandleInputEvent(gesture_); |
+} |
+ |
+TEST_F(InputHandlerProxyTest, GestureFlingTransferResetsTouchpad) { |
+ // We shouldn't send any events to the widget for this gesture. |
+ expected_disposition_ = DidHandle; |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ // Start a gesture fling in the -X direction with zero Y movement. |
+ gesture_.type = WebInputEvent::GestureFlingStart; |
+ WebFloatPoint fling_delta = WebFloatPoint(1000, 0); |
+ WebPoint fling_point = WebPoint(7, 13); |
+ WebPoint fling_global_point = WebPoint(17, 23); |
+ int modifiers = 1; |
+ gesture_.data.flingStart.velocityX = fling_delta.x; |
+ gesture_.data.flingStart.velocityY = fling_delta.y; |
+ gesture_.sourceDevice = WebGestureEvent::Touchpad; |
+ gesture_.x = fling_point.x; |
+ gesture_.y = fling_point.y; |
+ gesture_.globalX = fling_global_point.x; |
+ gesture_.globalY = fling_global_point.y; |
+ gesture_.modifiers = modifiers; |
+ EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); |
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) |
+ .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); |
+ EXPECT_CALL(mock_input_handler_, ScrollEnd()); |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); |
+ |
+ // Start the fling animation at time 10. This shouldn't actually scroll, just |
+ // establish a start time. |
+ EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); |
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) |
+ .Times(0); |
+ base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10); |
+ input_handler_->Animate(time); |
+ |
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); |
+ |
+ // The second call should start scrolling in the -X direction. |
+ EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); |
+ 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::x, testing::Lt(0)))) |
+ .WillOnce(testing::Return(true)); |
+ EXPECT_CALL(mock_input_handler_, ScrollEnd()); |
+ time += base::TimeDelta::FromMilliseconds(100); |
+ input_handler_->Animate(time); |
+ |
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); |
+ |
+ // Let's say on the third call we hit a non-scrollable region. We should abort |
+ // the fling and not scroll. |
+ // We also should pass the current fling parameters out to the client so the |
+ // rest of the fling can be |
+ // transferred to the main thread. |
+ EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); |
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) |
+ .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread)); |
+ EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::_)).Times(0); |
+ EXPECT_CALL(mock_input_handler_, ScrollEnd()).Times(0); |
+ |
+ // Expected wheel fling animation parameters: |
+ // *) fling_delta and fling_point should match the original GestureFlingStart |
+ // event |
+ // *) startTime should be 10 to match the time parameter of the first |
+ // Animate() call after the GestureFlingStart |
+ // *) cumulativeScroll depends on the curve, but since we've animated in the |
+ // -X direction the X value should be < 0 |
+ EXPECT_CALL( |
+ mock_client_, |
+ TransferActiveWheelFlingAnimation(testing::AllOf( |
+ testing::Field(&WebActiveWheelFlingParameters::delta, |
+ testing::Eq(fling_delta)), |
+ testing::Field(&WebActiveWheelFlingParameters::point, |
+ testing::Eq(fling_point)), |
+ testing::Field(&WebActiveWheelFlingParameters::globalPoint, |
+ testing::Eq(fling_global_point)), |
+ testing::Field(&WebActiveWheelFlingParameters::modifiers, |
+ testing::Eq(modifiers)), |
+ testing::Field(&WebActiveWheelFlingParameters::startTime, |
+ testing::Eq(10)), |
+ testing::Field(&WebActiveWheelFlingParameters::cumulativeScroll, |
+ testing::Field(&WebSize::width, testing::Gt(0)))))); |
+ time += base::TimeDelta::FromMilliseconds(100); |
+ input_handler_->Animate(time); |
+ |
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); |
+ testing::Mock::VerifyAndClearExpectations(&mock_client_); |
+ |
+ // Since we've aborted the fling, the next animation should be a no-op and |
+ // should not result in another |
+ // frame being requested. |
+ EXPECT_CALL(mock_input_handler_, ScheduleAnimation()).Times(0); |
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) |
+ .Times(0); |
+ time += base::TimeDelta::FromMilliseconds(100); |
+ input_handler_->Animate(time); |
+ |
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); |
+ |
+ // Since we've transferred the fling to the main thread, we need to pass the |
+ // next GestureFlingCancel to the main |
+ // thread as well. |
+ EXPECT_CALL(mock_client_, DidNotHandleInputEvent(true)); |
+ gesture_.type = WebInputEvent::GestureFlingCancel; |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ VERIFY_AND_RESET_MOCKS(); |
+ input_handler_->MainThreadHasStoppedFlinging(); |
+ |
+ // Start a second gesture fling, this time in the +Y direction with no X. |
+ gesture_.type = WebInputEvent::GestureFlingStart; |
+ fling_delta = WebFloatPoint(0, -1000); |
+ fling_point = WebPoint(95, 87); |
+ fling_global_point = WebPoint(32, 71); |
+ modifiers = 2; |
+ gesture_.data.flingStart.velocityX = fling_delta.x; |
+ gesture_.data.flingStart.velocityY = fling_delta.y; |
+ gesture_.sourceDevice = WebGestureEvent::Touchpad; |
+ gesture_.x = fling_point.x; |
+ gesture_.y = fling_point.y; |
+ gesture_.globalX = fling_global_point.x; |
+ gesture_.globalY = fling_global_point.y; |
+ gesture_.modifiers = modifiers; |
+ EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); |
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) |
+ .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); |
+ EXPECT_CALL(mock_input_handler_, ScrollEnd()); |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); |
+ |
+ // Start the second fling animation at time 30. |
+ EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); |
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) |
+ .Times(0); |
+ time = base::TimeTicks() + base::TimeDelta::FromSeconds(30); |
+ input_handler_->Animate(time); |
+ |
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); |
+ |
+ // Tick the second fling once normally. |
+ EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); |
+ 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::Gt(0)))) |
+ .WillOnce(testing::Return(true)); |
+ EXPECT_CALL(mock_input_handler_, ScrollEnd()); |
+ time += base::TimeDelta::FromMilliseconds(100); |
+ input_handler_->Animate(time); |
+ |
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); |
+ |
+ // Then abort the second fling. |
+ EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); |
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) |
+ .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread)); |
+ EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::_)).Times(0); |
+ EXPECT_CALL(mock_input_handler_, ScrollEnd()).Times(0); |
+ |
+ // We should get parameters from the second fling, nothing from the first |
+ // fling should "leak". |
+ EXPECT_CALL( |
+ mock_client_, |
+ TransferActiveWheelFlingAnimation(testing::AllOf( |
+ testing::Field(&WebActiveWheelFlingParameters::delta, |
+ testing::Eq(fling_delta)), |
+ testing::Field(&WebActiveWheelFlingParameters::point, |
+ testing::Eq(fling_point)), |
+ testing::Field(&WebActiveWheelFlingParameters::globalPoint, |
+ testing::Eq(fling_global_point)), |
+ testing::Field(&WebActiveWheelFlingParameters::modifiers, |
+ testing::Eq(modifiers)), |
+ testing::Field(&WebActiveWheelFlingParameters::startTime, |
+ testing::Eq(30)), |
+ testing::Field(&WebActiveWheelFlingParameters::cumulativeScroll, |
+ testing::Field(&WebSize::height, testing::Lt(0)))))); |
+ time += base::TimeDelta::FromMilliseconds(100); |
+ input_handler_->Animate(time); |
+} |
+ |
+TEST_F(InputHandlerProxyTest, GestureFlingStartedTouchscreen) { |
+ // We shouldn't send any events to the widget for this gesture. |
+ expected_disposition_ = DidHandle; |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) |
+ .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); |
+ gesture_.type = WebInputEvent::GestureScrollBegin; |
+ gesture_.sourceDevice = WebGestureEvent::Touchscreen; |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ EXPECT_CALL(mock_input_handler_, FlingScrollBegin()) |
+ .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); |
+ EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); |
+ |
+ gesture_.type = WebInputEvent::GestureFlingStart; |
+ gesture_.data.flingStart.velocityX = 10; |
+ gesture_.sourceDevice = WebGestureEvent::Touchscreen; |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ EXPECT_CALL(mock_input_handler_, ScrollEnd()); |
+ |
+ // Verify that a GestureFlingCancel during an animation cancels it. |
+ gesture_.type = WebInputEvent::GestureFlingCancel; |
+ gesture_.sourceDevice = WebGestureEvent::Touchscreen; |
+ input_handler_->HandleInputEvent(gesture_); |
+} |
+ |
+TEST_F(InputHandlerProxyTest, GestureFlingOnMainThreadTouchscreen) { |
+ // We should send all events to the widget for this gesture. |
+ expected_disposition_ = DidNotHandle; |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) |
+ .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread)); |
+ |
+ gesture_.type = WebInputEvent::GestureScrollBegin; |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ EXPECT_CALL(mock_input_handler_, FlingScrollBegin()).Times(0); |
+ |
+ gesture_.type = WebInputEvent::GestureFlingStart; |
+ gesture_.sourceDevice = WebGestureEvent::Touchscreen; |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ // Even if we didn't start a fling ourselves, we still need to send the cancel |
+ // event to the widget. |
+ gesture_.type = WebInputEvent::GestureFlingCancel; |
+ gesture_.sourceDevice = WebGestureEvent::Touchscreen; |
+ input_handler_->HandleInputEvent(gesture_); |
+} |
+ |
+TEST_F(InputHandlerProxyTest, GestureFlingIgnoredTouchscreen) { |
+ expected_disposition_ = DidHandle; |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) |
+ .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); |
+ |
+ gesture_.type = WebInputEvent::GestureScrollBegin; |
+ gesture_.sourceDevice = WebGestureEvent::Touchscreen; |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ expected_disposition_ = DropEvent; |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ EXPECT_CALL(mock_input_handler_, FlingScrollBegin()) |
+ .WillOnce(testing::Return(cc::InputHandler::ScrollIgnored)); |
+ |
+ gesture_.type = WebInputEvent::GestureFlingStart; |
+ gesture_.sourceDevice = WebGestureEvent::Touchscreen; |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ // Even if we didn't start a fling ourselves, we still need to send the cancel |
+ // event to the widget. |
+ gesture_.type = WebInputEvent::GestureFlingCancel; |
+ gesture_.sourceDevice = WebGestureEvent::Touchscreen; |
+ input_handler_->HandleInputEvent(gesture_); |
+} |
+ |
+TEST_F(InputHandlerProxyTest, GestureFlingAnimatesTouchscreen) { |
+ // We shouldn't send any events to the widget for this gesture. |
+ expected_disposition_ = DidHandle; |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) |
+ .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); |
+ |
+ gesture_.type = WebInputEvent::GestureScrollBegin; |
+ gesture_.sourceDevice = WebGestureEvent::Touchscreen; |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ // On the fling start, we should schedule an animation but not actually start |
+ // scrolling. |
+ gesture_.type = WebInputEvent::GestureFlingStart; |
+ WebFloatPoint fling_delta = WebFloatPoint(1000, 0); |
+ WebPoint fling_point = WebPoint(7, 13); |
+ WebPoint fling_global_point = WebPoint(17, 23); |
+ int modifiers = 7; |
+ gesture_.data.flingStart.velocityX = fling_delta.x; |
+ gesture_.data.flingStart.velocityY = fling_delta.y; |
+ gesture_.sourceDevice = WebGestureEvent::Touchscreen; |
+ gesture_.x = fling_point.x; |
+ gesture_.y = fling_point.y; |
+ gesture_.globalX = fling_global_point.x; |
+ gesture_.globalY = fling_global_point.y; |
+ gesture_.modifiers = modifiers; |
+ EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); |
+ EXPECT_CALL(mock_input_handler_, FlingScrollBegin()) |
+ .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); |
+ // The first animate call should let us pick up an animation start time, but |
+ // we shouldn't actually move anywhere just yet. The first frame after the |
+ // fling start will typically include the last scroll from the gesture that |
+ // lead to the scroll (either wheel or gesture scroll), so there should be no |
+ // visible hitch. |
+ EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); |
+ base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10); |
+ input_handler_->Animate(time); |
+ |
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); |
+ |
+ // The second call should start scrolling in the -X direction. |
+ EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); |
+ EXPECT_CALL(mock_input_handler_, |
+ ScrollBy(testing::_, |
+ testing::Property(&gfx::Vector2dF::x, testing::Lt(0)))) |
+ .WillOnce(testing::Return(true)); |
+ time += base::TimeDelta::FromMilliseconds(100); |
+ input_handler_->Animate(time); |
+ |
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); |
+ |
+ EXPECT_CALL(mock_client_, DidHandleInputEvent()); |
+ EXPECT_CALL(mock_input_handler_, ScrollEnd()); |
+ gesture_.type = WebInputEvent::GestureFlingCancel; |
+ input_handler_->HandleInputEvent(gesture_); |
+} |
+ |
+TEST_F(InputHandlerProxyTest, |
+ GestureScrollOnImplThreadFlagClearedAfterFling) { |
+ // We shouldn't send any events to the widget for this gesture. |
+ expected_disposition_ = DidHandle; |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) |
+ .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); |
+ |
+ gesture_.type = WebInputEvent::GestureScrollBegin; |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ // After sending a GestureScrollBegin, the member variable |
+ // |gesture_scroll_on_impl_thread_| should be true. |
+ EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing()); |
+ |
+ expected_disposition_ = DidHandle; |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ // On the fling start, we should schedule an animation but not actually start |
+ // scrolling. |
+ gesture_.type = WebInputEvent::GestureFlingStart; |
+ WebFloatPoint fling_delta = WebFloatPoint(1000, 0); |
+ WebPoint fling_point = WebPoint(7, 13); |
+ WebPoint fling_global_point = WebPoint(17, 23); |
+ int modifiers = 7; |
+ gesture_.data.flingStart.velocityX = fling_delta.x; |
+ gesture_.data.flingStart.velocityY = fling_delta.y; |
+ gesture_.sourceDevice = WebGestureEvent::Touchscreen; |
+ gesture_.x = fling_point.x; |
+ gesture_.y = fling_point.y; |
+ gesture_.globalX = fling_global_point.x; |
+ gesture_.globalY = fling_global_point.y; |
+ gesture_.modifiers = modifiers; |
+ EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); |
+ EXPECT_CALL(mock_input_handler_, FlingScrollBegin()) |
+ .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ // |gesture_scroll_on_impl_thread_| should still be true after |
+ // a GestureFlingStart is sent. |
+ EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing()); |
+ |
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); |
+ // The first animate call should let us pick up an animation start time, but |
+ // we shouldn't actually move anywhere just yet. The first frame after the |
+ // fling start will typically include the last scroll from the gesture that |
+ // lead to the scroll (either wheel or gesture scroll), so there should be no |
+ // visible hitch. |
+ EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); |
+ base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10); |
+ input_handler_->Animate(time); |
+ |
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); |
+ |
+ // The second call should start scrolling in the -X direction. |
+ EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); |
+ EXPECT_CALL(mock_input_handler_, |
+ ScrollBy(testing::_, |
+ testing::Property(&gfx::Vector2dF::x, testing::Lt(0)))) |
+ .WillOnce(testing::Return(true)); |
+ time += base::TimeDelta::FromMilliseconds(100); |
+ input_handler_->Animate(time); |
+ |
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); |
+ |
+ EXPECT_CALL(mock_client_, DidHandleInputEvent()); |
+ EXPECT_CALL(mock_input_handler_, ScrollEnd()); |
+ gesture_.type = WebInputEvent::GestureFlingCancel; |
+ input_handler_->HandleInputEvent(gesture_); |
+ |
+ // |gesture_scroll_on_impl_thread_| should be false once |
+ // the fling has finished (note no GestureScrollEnd has been sent). |
+ EXPECT_TRUE(!input_handler_->gesture_scroll_on_impl_thread_for_testing()); |
+} |
+ |
+TEST_F(InputHandlerProxyTest, LastInputEventForVSync) { |
+ expected_disposition_ = DropEvent; |
+ VERIFY_AND_RESET_MOCKS(); |
+ |
+ gesture_.type = WebInputEvent::GestureFlingCancel; |
+ gesture_.timeStampSeconds = 1234; |
+ base::TimeTicks time = |
+ base::TimeTicks() + |
+ base::TimeDelta::FromSeconds(gesture_.timeStampSeconds); |
+ gesture_.modifiers |= WebInputEvent::IsLastInputEventForCurrentVSync; |
+ EXPECT_CALL(mock_input_handler_, DidReceiveLastInputEventForVSync(time)); |
+ input_handler_->HandleInputEvent(gesture_); |
+} |
+ |
+} // namespace |