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

Unified Diff: content/renderer/gpu/input_handler_client_impl_unittest.cc

Issue 13844021: Move compositor thread input handling logic into content (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: content/renderer/gpu/input_handler_client_impl_unittest.cc
diff --git a/content/renderer/gpu/input_handler_client_impl_unittest.cc b/content/renderer/gpu/input_handler_client_impl_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..4bdad174e3a562ead945126230c3146688973c93
--- /dev/null
+++ b/content/renderer/gpu/input_handler_client_impl_unittest.cc
@@ -0,0 +1,946 @@
+// 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_client_impl.h"
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/renderer/gpu/input_handler_client_impl_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/WebInputHandler.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::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_METHOD0(FlingScrollBegin, cc::InputHandler::ScrollStatus());
+ 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_METHOD1(DidReceiveLastInputEventForVSync, void(base::TimeTicks time));
+
+ virtual void BindToClient(cc::InputHandlerClient* clent) OVERRIDE {}
danakj 2013/05/01 19:20:43 should this be MOCK and verify it is called when y
+
+ 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;
+ }
+
+ 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 MockInputHandlerClientImplClient
+ : public content::InputHandlerClientImplClient {
+ public:
+ MockInputHandlerClientImplClient() {}
+ virtual ~MockInputHandlerClientImplClient() {}
+
+ MOCK_METHOD0(willShutdown, void());
+ 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(MockInputHandlerClientImplClient);
+};
+
+class InputHandlerClientImplTest : public testing::Test {
+ public:
+ InputHandlerClientImplTest() : expected_disposition_(DidHandle) {
+ input_handler_.reset(
+ new content::InputHandlerClientImpl(&mock_input_handler_));
+ input_handler_->SetClient(&mock_client_);
+ }
+
+ ~InputHandlerClientImplTest() {
+ input_handler_->SetClient(NULL);
+ 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 (0)
danakj 2013/05/01 19:20:43 s/0/false/
+
+ protected:
+ testing::StrictMock<MockInputHandler> mock_input_handler_;
+ scoped_ptr<content::InputHandlerClientImpl> input_handler_;
+ testing::StrictMock<MockInputHandlerClientImplClient> mock_client_;
+ WebGestureEvent gesture;
danakj 2013/05/01 19:20:43 gesture_
+
+ enum ExpectedDisposition {
+ DidHandle,
+ DidNotHandle,
+ DropEvent
+ };
+ ExpectedDisposition expected_disposition_;
+};
+
+TEST_F(InputHandlerClientImplTest, 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(InputHandlerClientImplTest, 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(InputHandlerClientImplTest, 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(InputHandlerClientImplTest, 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(InputHandlerClientImplTest, 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(InputHandlerClientImplTest, 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(InputHandlerClientImplTest, 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);
+
+ 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(InputHandlerClientImplTest, 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(InputHandlerClientImplTest, 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(InputHandlerClientImplTest, 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(InputHandlerClientImplTest, 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));
+ 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(InputHandlerClientImplTest, 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::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(InputHandlerClientImplTest, GestureFlingIgnoredTouchscreen) {
+ expected_disposition_ = DropEvent;
+ 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::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(InputHandlerClientImplTest, GestureFlingAnimatesTouchscreen) {
+ // 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::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_, ScrollBegin(testing::_, testing::_))
+ .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(InputHandlerClientImplTest,
+ 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());
+
+ 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_, ScrollBegin(testing::_, testing::_))
+ .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());
+
+ 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());
+}
+
+TEST_F(InputHandlerClientImplTest, 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

Powered by Google App Engine
This is Rietveld 408576698