#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "cc/base/swap_promise_monitor.h"
+#include "content/common/input/did_overscroll_params.h"
#include "content/renderer/input/input_handler_proxy_client.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using blink::WebActiveWheelFlingParameters;
using blink::WebFloatPoint;
using blink::WebFloatSize;
+using blink::WebGestureDevice;
using blink::WebGestureEvent;
using blink::WebInputEvent;
+using blink::WebKeyboardEvent;
using blink::WebMouseWheelEvent;
using blink::WebPoint;
using blink::WebSize;
namespace content {
namespace {
+double InSecondsF(const base::TimeTicks& time) {
+ return (time - base::TimeTicks()).InSecondsF();
+}
+
+WebGestureEvent CreateFling(base::TimeTicks timestamp,
+ WebGestureDevice source_device,
+ WebFloatPoint velocity,
+ WebPoint point,
+ WebPoint global_point,
+ int modifiers) {
+ WebGestureEvent fling;
+ fling.type = WebInputEvent::GestureFlingStart;
+ fling.sourceDevice = source_device;
+ fling.timeStampSeconds = (timestamp - base::TimeTicks()).InSecondsF();
+ fling.data.flingStart.velocityX = velocity.x;
+ fling.data.flingStart.velocityY = velocity.y;
+ fling.x = point.x;
+ fling.y = point.y;
+ fling.globalX = global_point.x;
+ fling.globalY = global_point.y;
+ fling.modifiers = modifiers;
+ return fling;
+}
+
+WebGestureEvent CreateFling(WebGestureDevice source_device,
+ WebFloatPoint velocity,
+ WebPoint point,
+ WebPoint global_point,
+ int modifiers) {
+ return CreateFling(base::TimeTicks(),
+ source_device,
+ velocity,
+ point,
+ global_point,
+ modifiers);
+}
+
class MockInputHandler : public cc::InputHandler {
public:
MockInputHandler() {}
MOCK_METHOD0(PinchGestureBegin, void());
MOCK_METHOD2(PinchGestureUpdate,
- void(float magnify_delta, gfx::Point anchor));
+ void(float magnify_delta, const gfx::Point& anchor));
MOCK_METHOD0(PinchGestureEnd, void());
- MOCK_METHOD0(ScheduleAnimation, void());
+ MOCK_METHOD0(SetNeedsAnimate, void());
MOCK_METHOD2(ScrollBegin,
- ScrollStatus(gfx::Point viewport_point,
+ ScrollStatus(const gfx::Point& viewport_point,
cc::InputHandler::ScrollInputType type));
+ MOCK_METHOD2(ScrollAnimated,
+ ScrollStatus(const gfx::Point& viewport_point,
+ const gfx::Vector2dF& scroll_delta));
MOCK_METHOD2(ScrollBy,
- bool(gfx::Point viewport_point,
+ bool(const gfx::Point& viewport_point,
const gfx::Vector2dF& scroll_delta));
MOCK_METHOD2(ScrollVerticallyByPage,
- bool(gfx::Point viewport_point,
+ bool(const gfx::Point& viewport_point,
cc::ScrollDirection direction));
MOCK_METHOD0(ScrollEnd, void());
MOCK_METHOD0(FlingScrollBegin, cc::InputHandler::ScrollStatus());
virtual void BindToClient(cc::InputHandlerClient* client) OVERRIDE {}
- virtual void StartPageScaleAnimation(gfx::Vector2d target_offset,
+ virtual void StartPageScaleAnimation(const gfx::Vector2d& target_offset,
bool anchor_point,
float page_scale,
base::TimeDelta duration) OVERRIDE {}
- virtual void NotifyCurrentFlingVelocity(
- const gfx::Vector2dF& velocity) OVERRIDE {}
- virtual void MouseMoveAt(gfx::Point mouse_position) OVERRIDE {}
+ virtual void MouseMoveAt(const gfx::Point& mouse_position) OVERRIDE {}
- MOCK_METHOD1(HaveTouchEventHandlersAt,
- bool(gfx::Point point));
+ MOCK_METHOD2(IsCurrentlyScrollingLayerAt,
+ bool(const gfx::Point& point,
+ cc::InputHandler::ScrollInputType type));
+
+ MOCK_METHOD1(HaveTouchEventHandlersAt, bool(const gfx::Point& point));
virtual void SetRootLayerScrollOffsetDelegate(
cc::LayerScrollOffsetDelegate* root_layer_scroll_offset_delegate)
// indefinitely.
class FakeWebGestureCurve : public blink::WebGestureCurve {
public:
- FakeWebGestureCurve(const blink::WebFloatPoint& velocity,
- const blink::WebSize& cumulative_scroll)
+ FakeWebGestureCurve(const blink::WebFloatSize& velocity,
+ const blink::WebFloatSize& 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, blink::WebGestureCurveTarget* target) {
- blink::WebSize displacement(velocity_.x * time, velocity_.y * time);
+ blink::WebFloatSize displacement(velocity_.width * time,
+ velocity_.height * time);
blink::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;
+ return target->scrollBy(increment, velocity_);
}
private:
- blink::WebFloatPoint velocity_;
- blink::WebSize cumulative_scroll_;
+ blink::WebFloatSize velocity_;
+ blink::WebFloatSize cumulative_scroll_;
DISALLOW_COPY_AND_ASSIGN(FakeWebGestureCurve);
};
void(const WebActiveWheelFlingParameters&));
virtual blink::WebGestureCurve* CreateFlingAnimationCurve(
- int deviceSource,
+ WebGestureDevice deviceSource,
const WebFloatPoint& velocity,
const WebSize& cumulative_scroll) OVERRIDE {
- return new FakeWebGestureCurve(velocity, cumulative_scroll);
+ return new FakeWebGestureCurve(
+ blink::WebFloatSize(velocity.x, velocity.y),
+ blink::WebFloatSize(cumulative_scroll.width, cumulative_scroll.height));
}
- virtual void DidOverscroll(const cc::DidOverscrollParams& params) OVERRIDE {}
+ MOCK_METHOD1(DidOverscroll, void(const DidOverscrollParams&));
virtual void DidStopFlinging() OVERRIDE {}
+ virtual void DidReceiveInputEvent() OVERRIDE {}
private:
DISALLOW_COPY_AND_ASSIGN(MockInputHandlerProxyClient);
};
+class MockInputHandlerProxyClientWithDidReceiveInputEvent
+ : public MockInputHandlerProxyClient {
+ public:
+ MockInputHandlerProxyClientWithDidReceiveInputEvent() {}
+ virtual ~MockInputHandlerProxyClientWithDidReceiveInputEvent() {}
+
+ MOCK_METHOD0(DidReceiveInputEvent, void());
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockInputHandlerProxyClientWithDidReceiveInputEvent);
+};
+
+WebTouchPoint CreateWebTouchPoint(WebTouchPoint::State state, float x,
+ float y) {
+ WebTouchPoint point;
+ point.state = state;
+ point.screenPosition = WebFloatPoint(x, y);
+ point.position = WebFloatPoint(x, y);
+ return point;
+}
+
class InputHandlerProxyTest : public testing::Test {
public:
InputHandlerProxyTest()
: expected_disposition_(InputHandlerProxy::DID_HANDLE) {
input_handler_.reset(
- new content::InputHandlerProxy(&mock_input_handler_));
- input_handler_->SetClient(&mock_client_);
+ new content::InputHandlerProxy(&mock_input_handler_, &mock_client_));
}
~InputHandlerProxyTest() {
testing::Mock::VerifyAndClearExpectations(&mock_client_); \
} while (false)
+ void StartFling(base::TimeTicks timestamp,
+ WebGestureDevice source_device,
+ WebFloatPoint velocity,
+ WebPoint position) {
+ expected_disposition_ = InputHandlerProxy::DID_HANDLE;
+ VERIFY_AND_RESET_MOCKS();
+
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
+ gesture_.type = WebInputEvent::GestureScrollBegin;
+ gesture_.sourceDevice = source_device;
+ EXPECT_EQ(expected_disposition_,
+ 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_, SetNeedsAnimate());
+
+ gesture_ =
+ CreateFling(timestamp, source_device, velocity, position, position, 0);
+ EXPECT_EQ(expected_disposition_,
+ input_handler_->HandleInputEvent(gesture_));
+
+ VERIFY_AND_RESET_MOCKS();
+ }
+
+ void CancelFling(base::TimeTicks timestamp) {
+ gesture_.timeStampSeconds = InSecondsF(timestamp);
+ gesture_.type = WebInputEvent::GestureFlingCancel;
+ EXPECT_EQ(expected_disposition_,
+ input_handler_->HandleInputEvent(gesture_));
+
+ VERIFY_AND_RESET_MOCKS();
+ }
+
protected:
testing::StrictMock<MockInputHandler> mock_input_handler_;
scoped_ptr<content::InputHandlerProxy> input_handler_;
testing::Mock::VerifyAndClearExpectations(&mock_client_);
}
+TEST_F(InputHandlerProxyTest, MouseWheelWithCtrl) {
+ expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
+ WebMouseWheelEvent wheel;
+ wheel.type = WebInputEvent::MouseWheel;
+ wheel.modifiers = WebInputEvent::ControlKey;
+
+ EXPECT_EQ(expected_disposition_, 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_ = InputHandlerProxy::DID_HANDLE;
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());
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
gesture_.type = WebInputEvent::GestureFlingStart;
gesture_.data.flingStart.velocityX = 10;
- gesture_.sourceDevice = WebGestureEvent::Touchpad;
+ gesture_.sourceDevice = blink::WebGestureDeviceTouchpad;
EXPECT_EQ(expected_disposition_, 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;
+ gesture_.sourceDevice = blink::WebGestureDeviceTouchpad;
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
}
.WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread));
gesture_.type = WebInputEvent::GestureFlingStart;
- gesture_.sourceDevice = WebGestureEvent::Touchpad;
+ gesture_.sourceDevice = blink::WebGestureDeviceTouchpad;
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
// Since we returned ScrollStatusOnMainThread from scrollBegin, ensure the
// 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;
+ gesture_.sourceDevice = blink::WebGestureDeviceTouchpad;
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
}
.WillOnce(testing::Return(cc::InputHandler::ScrollIgnored));
gesture_.type = WebInputEvent::GestureFlingStart;
- gesture_.sourceDevice = WebGestureEvent::Touchpad;
+ gesture_.sourceDevice = blink::WebGestureDeviceTouchpad;
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
expected_disposition_ = InputHandlerProxy::DROP_EVENT;
// Since the previous fling was ignored, we should also be dropping the next
// fling_cancel.
gesture_.type = WebInputEvent::GestureFlingCancel;
- gesture_.sourceDevice = WebGestureEvent::Touchpad;
+ gesture_.sourceDevice = blink::WebGestureDeviceTouchpad;
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
}
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());
+ // Note that for trackpad, wheel events with the Control modifier are
+ // special (reserved for zoom), so don't set that here.
+ int modifiers = WebInputEvent::ShiftKey | WebInputEvent::AltKey;
+ gesture_ = CreateFling(blink::WebGestureDeviceTouchpad,
+ fling_delta,
+ fling_point,
+ fling_global_point,
+ modifiers);
+ 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());
// 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_, SetNeedsAnimate());
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
.Times(0);
base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10);
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_, SetNeedsAnimate());
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
.WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
EXPECT_CALL(mock_input_handler_,
// 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);
// 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_, SetNeedsAnimate()).Times(0);
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
.Times(0);
time += base::TimeDelta::FromMilliseconds(100);
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());
+ // Note that for trackpad, wheel events with the Control modifier are
+ // special (reserved for zoom), so don't set that here.
+ int modifiers = WebInputEvent::ShiftKey | WebInputEvent::AltKey;
+ gesture_ = CreateFling(blink::WebGestureDeviceTouchpad,
+ fling_delta,
+ fling_point,
+ fling_global_point,
+ modifiers);
+ 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());
// 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_, SetNeedsAnimate());
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
.Times(0);
base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10);
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_, SetNeedsAnimate());
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
.WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
EXPECT_CALL(mock_input_handler_,
// 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);
// 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_, SetNeedsAnimate()).Times(0);
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
.Times(0);
time += base::TimeDelta::FromMilliseconds(100);
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());
+ modifiers = WebInputEvent::AltKey;
+ gesture_ = CreateFling(blink::WebGestureDeviceTouchpad,
+ fling_delta,
+ fling_point,
+ fling_global_point,
+ modifiers);
+ 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());
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_, SetNeedsAnimate());
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
.Times(0);
time = base::TimeTicks() + base::TimeDelta::FromSeconds(30);
testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
// Tick the second fling once normally.
- EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
+ 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_,
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_, ScrollBegin(testing::_, testing::_))
.WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
gesture_.type = WebInputEvent::GestureScrollBegin;
- gesture_.sourceDevice = WebGestureEvent::Touchscreen;
+ gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
EXPECT_EQ(expected_disposition_, 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());
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
gesture_.type = WebInputEvent::GestureFlingStart;
gesture_.data.flingStart.velocityX = 10;
- gesture_.sourceDevice = WebGestureEvent::Touchscreen;
+ gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
VERIFY_AND_RESET_MOCKS();
// Verify that a GestureFlingCancel during an animation cancels it.
gesture_.type = WebInputEvent::GestureFlingCancel;
- gesture_.sourceDevice = WebGestureEvent::Touchscreen;
+ gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
}
EXPECT_CALL(mock_input_handler_, FlingScrollBegin()).Times(0);
gesture_.type = WebInputEvent::GestureFlingStart;
- gesture_.sourceDevice = WebGestureEvent::Touchscreen;
+ gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
EXPECT_EQ(expected_disposition_, 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;
+ gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
}
.WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
gesture_.type = WebInputEvent::GestureScrollBegin;
- gesture_.sourceDevice = WebGestureEvent::Touchscreen;
+ gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
expected_disposition_ = InputHandlerProxy::DROP_EVENT;
.WillOnce(testing::Return(cc::InputHandler::ScrollIgnored));
gesture_.type = WebInputEvent::GestureFlingStart;
- gesture_.sourceDevice = WebGestureEvent::Touchscreen;
+ gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
EXPECT_EQ(expected_disposition_, 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;
+ gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
}
.WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
gesture_.type = WebInputEvent::GestureScrollBegin;
- gesture_.sourceDevice = WebGestureEvent::Touchscreen;
+ gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
EXPECT_EQ(expected_disposition_, 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);
+ WebFloatPoint fling_delta = WebFloatPoint(100, 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());
+ // Note that for touchscreen the control modifier is not special.
+ int modifiers = WebInputEvent::ControlKey;
+ gesture_ = CreateFling(blink::WebGestureDeviceTouchscreen,
+ fling_delta,
+ fling_point,
+ fling_global_point,
+ modifiers);
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
.WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
// 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_, SetNeedsAnimate());
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_, SetNeedsAnimate());
EXPECT_CALL(mock_input_handler_,
ScrollBy(testing::_,
testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
.WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
gesture_.type = WebInputEvent::GestureScrollBegin;
- gesture_.sourceDevice = WebGestureEvent::Touchscreen;
+ gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
VERIFY_AND_RESET_MOCKS();
// On the fling start, we should schedule an animation but not actually start
// scrolling.
- base::TimeDelta startTimeOffset = base::TimeDelta::FromMilliseconds(10);
+ base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10);
+ base::TimeTicks time = base::TimeTicks() + dt;
+ WebFloatPoint fling_delta = WebFloatPoint(100, 0);
+ WebPoint fling_point = WebPoint(7, 13);
+ WebPoint fling_global_point = WebPoint(17, 23);
+ int modifiers = WebInputEvent::ControlKey;
+ gesture_ = CreateFling(time,
+ blink::WebGestureDeviceTouchscreen,
+ fling_delta,
+ fling_point,
+ fling_global_point,
+ modifiers);
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
+ EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
+ .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
+ // With a valid time stamp, the first animate call should skip start time
+ // initialization and immediately begin scroll update production. This reduces
+ // the likelihood of a hitch between the scroll preceding the fling and
+ // the first scroll generated by the fling.
+ // Scrolling should start in the -X direction.
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
+ EXPECT_CALL(mock_input_handler_,
+ ScrollBy(testing::_,
+ testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
+ .WillOnce(testing::Return(true));
+ time += dt;
+ input_handler_->Animate(time);
+
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
+
+ EXPECT_CALL(mock_input_handler_, ScrollEnd());
+ gesture_.type = WebInputEvent::GestureFlingCancel;
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+}
+
+TEST_F(InputHandlerProxyTest, GestureFlingWithInvalidTimestamp) {
+ // We shouldn't send any events to the widget for this gesture.
+ expected_disposition_ = InputHandlerProxy::DID_HANDLE;
+ VERIFY_AND_RESET_MOCKS();
+
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
+
+ gesture_.type = WebInputEvent::GestureScrollBegin;
+ gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ VERIFY_AND_RESET_MOCKS();
+
+ // On the fling start, we should schedule an animation but not actually start
+ // scrolling.
+ base::TimeDelta start_time_offset = base::TimeDelta::FromMilliseconds(10);
gesture_.type = WebInputEvent::GestureFlingStart;
- WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
+ WebFloatPoint fling_delta = WebFloatPoint(100, 0);
WebPoint fling_point = WebPoint(7, 13);
WebPoint fling_global_point = WebPoint(17, 23);
- int modifiers = 7;
- gesture_.timeStampSeconds = startTimeOffset.InSecondsF();
+ int modifiers = WebInputEvent::ControlKey;
+ gesture_.timeStampSeconds = start_time_offset.InSecondsF();
gesture_.data.flingStart.velocityX = fling_delta.x;
gesture_.data.flingStart.velocityY = fling_delta.y;
- gesture_.sourceDevice = WebGestureEvent::Touchscreen;
+ gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
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_, SetNeedsAnimate());
EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
.WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
- // With a valid time stamp, the first animate call should skip start time
- // initialization and immediately begin scroll update production. This reduces
- // the likelihood of a hitch between the scroll preceding the fling and
- // the first scroll generated by the fling.
- // Scrolling should start in the -X direction.
- EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
+ // Event though a time stamp was provided for the fling event, it will be
+ // ignored as its too far in the past relative to the first animate call's
+ // timestamp.
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
+ base::TimeTicks time =
+ base::TimeTicks() + start_time_offset + base::TimeDelta::FromSeconds(1);
+ input_handler_->Animate(time);
+
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
+
+ // Further animation ticks should update the fling as usual.
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
EXPECT_CALL(mock_input_handler_,
ScrollBy(testing::_,
testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
.WillOnce(testing::Return(true));
- base::TimeTicks time = base::TimeTicks() + 2 * startTimeOffset;
+ time += base::TimeDelta::FromMilliseconds(10);
input_handler_->Animate(time);
testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
// On the fling start, we should schedule an animation but not actually start
// scrolling.
- gesture_.type = WebInputEvent::GestureFlingStart;
- WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
+ WebFloatPoint fling_delta = WebFloatPoint(100, 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());
+ int modifiers = WebInputEvent::ControlKey | WebInputEvent::AltKey;
+ gesture_ = CreateFling(blink::WebGestureDeviceTouchscreen,
+ fling_delta,
+ fling_point,
+ fling_global_point,
+ modifiers);
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
.WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
// 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_, SetNeedsAnimate());
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_, SetNeedsAnimate());
EXPECT_CALL(mock_input_handler_,
ScrollBy(testing::_,
testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
// On the fling start, we should schedule an animation but not actually start
// scrolling.
gesture_.type = WebInputEvent::GestureFlingStart;
- WebFloatPoint fling_delta = WebFloatPoint(1000, 1000);
+ 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_, ScheduleAnimation());
+ 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());
testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
// The first animate doesn't cause any scrolling.
- EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10);
input_handler_->Animate(time);
testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
// The second animate starts scrolling in the positive X and Y directions.
- EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
+ 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_,
testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
// Simulate hitting the bottom content edge.
- cc::DidOverscrollParams overscroll_params;
- overscroll_params.accumulated_overscroll = gfx::Vector2dF(0, 100);
- overscroll_params.current_fling_velocity = gfx::Vector2dF(0, 10);
- input_handler_->DidOverscroll(overscroll_params);
+ gfx::Vector2dF accumulated_overscroll(0, 100);
+ gfx::Vector2dF latest_overscroll_delta(0, 10);
+ gfx::PointF scroll_point(10, 0);
+ 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);
// The next call to animate will no longer scroll vertically.
- EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
+ 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_,
testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
}
+TEST_F(InputHandlerProxyTest, GestureFlingNotCancelledBySmallTimeDelta) {
+ // We shouldn't send any events to the widget for this gesture.
+ expected_disposition_ = InputHandlerProxy::DID_HANDLE;
+ VERIFY_AND_RESET_MOCKS();
+
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
+
+ gesture_.type = WebInputEvent::GestureScrollBegin;
+ gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ VERIFY_AND_RESET_MOCKS();
+
+ // On the fling start, we should schedule an animation but not actually start
+ // scrolling.
+ base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10);
+ base::TimeTicks time = base::TimeTicks() + dt;
+ WebFloatPoint fling_delta = WebFloatPoint(100, 0);
+ WebPoint fling_point = WebPoint(7, 13);
+ WebPoint fling_global_point = WebPoint(17, 23);
+ int modifiers = WebInputEvent::ControlKey;
+ gesture_ = CreateFling(time,
+ blink::WebGestureDeviceTouchscreen,
+ fling_delta,
+ fling_point,
+ fling_global_point,
+ modifiers);
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
+ EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
+ .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
+ // With an animation timestamp equivalent to the starting timestamp, the
+ // animation will simply be rescheduled.
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
+ input_handler_->Animate(time);
+
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
+ EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
+
+ // A small time delta should not stop the fling, even if the client
+ // reports no scrolling.
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
+ EXPECT_CALL(mock_input_handler_,
+ ScrollBy(testing::_,
+ testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
+ .WillOnce(testing::Return(false));
+ time += base::TimeDelta::FromMicroseconds(5);
+ input_handler_->Animate(time);
+
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
+ EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
+
+ // A time delta of zero should not stop the fling, and neither should it
+ // trigger scrolling on the client.
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
+ input_handler_->Animate(time);
+
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
+ EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
+
+ // Lack of movement on the client, with a non-trivial scroll delta, should
+ // terminate the fling.
+ EXPECT_CALL(mock_input_handler_, ScrollEnd());
+ EXPECT_CALL(mock_input_handler_,
+ ScrollBy(testing::_,
+ testing::Property(&gfx::Vector2dF::x, testing::Lt(1))))
+ .WillOnce(testing::Return(false));
+ time += base::TimeDelta::FromMilliseconds(100);
+ input_handler_->Animate(time);
+
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
+ EXPECT_FALSE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
+}
+
TEST_F(InputHandlerProxyTest, GestureFlingCancelledAfterBothAxesStopScrolling) {
// We shouldn't send any events to the widget for this gesture.
expected_disposition_ = InputHandlerProxy::DID_HANDLE;
EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
.WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
gesture_.type = WebInputEvent::GestureScrollBegin;
- gesture_.sourceDevice = WebGestureEvent::Touchscreen;
+ gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
// On the fling start, we should schedule an animation but not actually start
// scrolling.
gesture_.type = WebInputEvent::GestureFlingStart;
- WebFloatPoint fling_delta = WebFloatPoint(1000, 1000);
+ 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_, FlingScrollBegin())
.WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
- EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
// The first animate doesn't cause any scrolling.
- EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10);
input_handler_->Animate(time);
testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
// The second animate starts scrolling in the positive X and Y directions.
- EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
EXPECT_CALL(mock_input_handler_,
ScrollBy(testing::_,
testing::Property(&gfx::Vector2dF::y, testing::Lt(0))))
testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
// Simulate hitting the bottom content edge.
- cc::DidOverscrollParams overscroll_params;
- overscroll_params.accumulated_overscroll = gfx::Vector2dF(0, 100);
- input_handler_->DidOverscroll(overscroll_params);
+ gfx::Vector2dF accumulated_overscroll(0, 100);
+ gfx::Vector2dF latest_overscroll_delta(0, 100);
+ gfx::PointF scroll_point(10, -50);
+ 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);
// The next call to animate will no longer scroll vertically.
- EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
EXPECT_CALL(mock_input_handler_,
ScrollBy(testing::_,
testing::Property(&gfx::Vector2dF::y, testing::Eq(0))))
testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
// Simulate hitting the right content edge.
- overscroll_params.accumulated_overscroll = gfx::Vector2dF(100, 100);
- input_handler_->DidOverscroll(overscroll_params);
-
+ accumulated_overscroll = gfx::Vector2dF(100, 100);
+ latest_overscroll_delta = gfx::Vector2dF(100, 0);
+ scroll_point = gfx::PointF(50, 0);
+ 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);
// The next call to animate will no longer scroll horizontally or vertically,
// and the fling should be cancelled.
- EXPECT_CALL(mock_input_handler_, ScheduleAnimation()).Times(0);
+ 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);
touch.type = WebInputEvent::TouchStart;
touch.touchesLength = 3;
- touch.touches[0].state = WebTouchPoint::StateStationary;
- touch.touches[0].screenPosition = WebPoint();
- touch.touches[0].position = WebPoint();
-
- touch.touches[1].state = WebTouchPoint::StatePressed;
- touch.touches[1].screenPosition = WebPoint(10, 10);
- touch.touches[1].position = WebPoint(10, 10);
-
- touch.touches[2].state = WebTouchPoint::StatePressed;
- touch.touches[2].screenPosition = WebPoint(-10, 10);
- touch.touches[2].position = WebPoint(-10, 10);
-
+ touch.touches[0] = CreateWebTouchPoint(WebTouchPoint::StateStationary, 0, 0);
+ touch.touches[1] = CreateWebTouchPoint(WebTouchPoint::StatePressed, 10, 10);
+ touch.touches[2] = CreateWebTouchPoint(WebTouchPoint::StatePressed, -10, 10);
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(touch));
}
touch.type = WebInputEvent::TouchStart;
touch.touchesLength = 3;
- touch.touches[0].state = WebTouchPoint::StatePressed;
- touch.touches[0].screenPosition = WebPoint();
- touch.touches[0].position = WebPoint();
+ touch.touches[0] = CreateWebTouchPoint(WebTouchPoint::StatePressed, 0, 0);
+ touch.touches[1] = CreateWebTouchPoint(WebTouchPoint::StatePressed, 10, 10);
+ touch.touches[2] = CreateWebTouchPoint(WebTouchPoint::StatePressed, -10, 10);
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(touch));
+}
- touch.touches[1].state = WebTouchPoint::StatePressed;
- touch.touches[1].screenPosition = WebPoint(10, 10);
- touch.touches[1].position = WebPoint(10, 10);
+TEST_F(InputHandlerProxyTest, GestureFlingCancelledByKeyboardEvent) {
+ // We shouldn't send any events to the widget for this gesture.
+ expected_disposition_ = InputHandlerProxy::DID_HANDLE;
+ VERIFY_AND_RESET_MOCKS();
+
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
+ gesture_.type = WebInputEvent::GestureScrollBegin;
+ gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+ EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
- touch.touches[2].state = WebTouchPoint::StatePressed;
- touch.touches[2].screenPosition = WebPoint(-10, 10);
- touch.touches[2].position = WebPoint(-10, 10);
+ // Keyboard events received during a scroll should have no effect.
+ WebKeyboardEvent key_event;
+ key_event.type = WebInputEvent::KeyDown;
+ EXPECT_EQ(InputHandlerProxy::DID_NOT_HANDLE,
+ input_handler_->HandleInputEvent(key_event));
+ EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(touch));
+ // On the fling start, animation should be scheduled, but no scrolling occurs.
+ gesture_.type = WebInputEvent::GestureFlingStart;
+ 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_, FlingScrollBegin())
+ .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+ EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
+
+ // Keyboard events received during a fling should cancel the active fling.
+ EXPECT_CALL(mock_input_handler_, ScrollEnd());
+ EXPECT_EQ(InputHandlerProxy::DID_NOT_HANDLE,
+ input_handler_->HandleInputEvent(key_event));
+ EXPECT_FALSE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
+
+ // The call to animate should have no effect, as the fling was cancelled.
+ base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10);
+ input_handler_->Animate(time);
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
+
+ // A fling cancel should be dropped, as there is nothing to cancel.
+ gesture_.type = WebInputEvent::GestureFlingCancel;
+ EXPECT_EQ(InputHandlerProxy::DROP_EVENT,
+ input_handler_->HandleInputEvent(gesture_));
+ EXPECT_FALSE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
+}
+
+TEST_F(InputHandlerProxyTest, GestureFlingWithNegativeTimeDelta) {
+ // We shouldn't send any events to the widget for this gesture.
+ expected_disposition_ = InputHandlerProxy::DID_HANDLE;
+ VERIFY_AND_RESET_MOCKS();
+
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
+
+ gesture_.type = WebInputEvent::GestureScrollBegin;
+ gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ VERIFY_AND_RESET_MOCKS();
+
+ // On the fling start, we should schedule an animation but not actually start
+ // scrolling.
+ base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10);
+ base::TimeTicks time = base::TimeTicks() + dt;
+ WebFloatPoint fling_delta = WebFloatPoint(100, 0);
+ WebPoint fling_point = WebPoint(7, 13);
+ WebPoint fling_global_point = WebPoint(17, 23);
+ int modifiers = WebInputEvent::ControlKey;
+ gesture_ = CreateFling(time,
+ blink::WebGestureDeviceTouchscreen,
+ fling_delta,
+ fling_point,
+ fling_global_point,
+ modifiers);
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
+ EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
+ .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
+
+ // If we get a negative time delta, that is, the Animation tick time happens
+ // before the fling's start time then we should *not* try scrolling and
+ // instead reset the fling start time.
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
+ EXPECT_CALL(mock_input_handler_,
+ ScrollBy(testing::_,
+ testing::_)).Times(0);
+ time -= base::TimeDelta::FromMilliseconds(5);
+ input_handler_->Animate(time);
+
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
+
+ // The first call should have reset the start time so subsequent calls should
+ // generate scroll events.
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
+ EXPECT_CALL(mock_input_handler_,
+ ScrollBy(testing::_,
+ testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
+ .WillOnce(testing::Return(true));
+
+ input_handler_->Animate(time + base::TimeDelta::FromMilliseconds(1));
+
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
+
+ EXPECT_CALL(mock_input_handler_, ScrollEnd());
+ gesture_.type = WebInputEvent::GestureFlingCancel;
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+}
+
+TEST_F(InputHandlerProxyTest, FlingBoost) {
+ base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10);
+ base::TimeTicks time = base::TimeTicks() + dt;
+ base::TimeTicks last_animate_time = time;
+ WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
+ WebPoint fling_point = WebPoint(7, 13);
+ StartFling(
+ time, blink::WebGestureDeviceTouchscreen, fling_delta, fling_point);
+
+ // Now cancel the fling. The fling cancellation should be deferred to allow
+ // fling boosting events to arrive.
+ time += dt;
+ CancelFling(time);
+
+ // The GestureScrollBegin should be swallowed by the fling if it hits the same
+ // scrolling layer.
+ EXPECT_CALL(mock_input_handler_,
+ IsCurrentlyScrollingLayerAt(testing::_, testing::_))
+ .WillOnce(testing::Return(true));
+
+ time += dt;
+ gesture_.timeStampSeconds = InSecondsF(time);
+ gesture_.type = WebInputEvent::GestureScrollBegin;
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ VERIFY_AND_RESET_MOCKS();
+
+ // Animate calls within the deferred cancellation window should continue.
+ time += dt;
+ float expected_delta =
+ (time - last_animate_time).InSecondsF() * -fling_delta.x;
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
+ EXPECT_CALL(mock_input_handler_,
+ ScrollBy(testing::_,
+ testing::Property(&gfx::Vector2dF::x,
+ testing::Eq(expected_delta))))
+ .WillOnce(testing::Return(true));
+ input_handler_->Animate(time);
+ last_animate_time = time;
+
+ VERIFY_AND_RESET_MOCKS();
+
+ // GestureScrollUpdates in the same direction and at sufficient speed should
+ // be swallowed by the fling.
+ time += dt;
+ gesture_.timeStampSeconds = InSecondsF(time);
+ gesture_.type = WebInputEvent::GestureScrollUpdate;
+ gesture_.data.scrollUpdate.deltaX = fling_delta.x;
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ VERIFY_AND_RESET_MOCKS();
+
+ // Animate calls within the deferred cancellation window should continue.
+ time += dt;
+ expected_delta = (time - last_animate_time).InSecondsF() * -fling_delta.x;
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
+ EXPECT_CALL(mock_input_handler_,
+ ScrollBy(testing::_,
+ testing::Property(&gfx::Vector2dF::x,
+ testing::Eq(expected_delta))))
+ .WillOnce(testing::Return(true));
+ input_handler_->Animate(time);
+ last_animate_time = time;
+
+ VERIFY_AND_RESET_MOCKS();
+
+ // GestureFlingStart in the same direction and at sufficient speed should
+ // boost the active fling.
+
+ gesture_ = CreateFling(time,
+ blink::WebGestureDeviceTouchscreen,
+ fling_delta,
+ fling_point,
+ fling_point,
+ 0);
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+ VERIFY_AND_RESET_MOCKS();
+
+ time += dt;
+ // Note we get *2x* as much delta because 2 flings have combined.
+ expected_delta = 2 * (time - last_animate_time).InSecondsF() * -fling_delta.x;
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
+ EXPECT_CALL(mock_input_handler_,
+ ScrollBy(testing::_,
+ testing::Property(&gfx::Vector2dF::x,
+ testing::Eq(expected_delta))))
+ .WillOnce(testing::Return(true));
+ input_handler_->Animate(time);
+ last_animate_time = time;
+
+ VERIFY_AND_RESET_MOCKS();
+
+ // Repeated GestureFlingStarts should accumulate.
+
+ CancelFling(time);
+ gesture_ = CreateFling(time,
+ blink::WebGestureDeviceTouchscreen,
+ fling_delta,
+ fling_point,
+ fling_point,
+ 0);
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+ VERIFY_AND_RESET_MOCKS();
+
+ time += dt;
+ // Note we get *3x* as much delta because 3 flings have combined.
+ expected_delta = 3 * (time - last_animate_time).InSecondsF() * -fling_delta.x;
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
+ EXPECT_CALL(mock_input_handler_,
+ ScrollBy(testing::_,
+ testing::Property(&gfx::Vector2dF::x,
+ testing::Eq(expected_delta))))
+ .WillOnce(testing::Return(true));
+ input_handler_->Animate(time);
+ last_animate_time = time;
+
+ VERIFY_AND_RESET_MOCKS();
+
+ // GestureFlingCancel should terminate the fling if no boosting gestures are
+ // received within the timeout window.
+
+ time += dt;
+ gesture_.timeStampSeconds = InSecondsF(time);
+ gesture_.type = WebInputEvent::GestureFlingCancel;
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ VERIFY_AND_RESET_MOCKS();
+
+ time += base::TimeDelta::FromMilliseconds(100);
+ EXPECT_CALL(mock_input_handler_, ScrollEnd());
+ input_handler_->Animate(time);
+
+ VERIFY_AND_RESET_MOCKS();
+}
+
+TEST_F(InputHandlerProxyTest, NoFlingBoostIfScrollTargetsDifferentLayer) {
+ base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10);
+ base::TimeTicks time = base::TimeTicks() + dt;
+ WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
+ WebPoint fling_point = WebPoint(7, 13);
+ StartFling(
+ time, blink::WebGestureDeviceTouchscreen, fling_delta, fling_point);
+
+ // Cancel the fling. The fling cancellation should be deferred to allow
+ // fling boosting events to arrive.
+ time += dt;
+ CancelFling(time);
+
+ // If the GestureScrollBegin targets a different layer, the fling should be
+ // cancelled and the scroll should be handled as usual.
+ EXPECT_CALL(mock_input_handler_,
+ IsCurrentlyScrollingLayerAt(testing::_, testing::_))
+ .WillOnce(testing::Return(false));
+ EXPECT_CALL(mock_input_handler_, ScrollEnd());
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
+
+ time += dt;
+ gesture_.timeStampSeconds = InSecondsF(time);
+ gesture_.type = WebInputEvent::GestureScrollBegin;
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ VERIFY_AND_RESET_MOCKS();
+}
+
+TEST_F(InputHandlerProxyTest, NoFlingBoostIfScrollDelayed) {
+ base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10);
+ base::TimeTicks time = base::TimeTicks() + dt;
+ WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
+ WebPoint fling_point = WebPoint(7, 13);
+ StartFling(
+ time, blink::WebGestureDeviceTouchscreen, fling_delta, fling_point);
+
+ // Cancel the fling. The fling cancellation should be deferred to allow
+ // fling boosting events to arrive.
+ time += dt;
+ CancelFling(time);
+
+ // The GestureScrollBegin should be swallowed by the fling if it hits the same
+ // scrolling layer.
+ EXPECT_CALL(mock_input_handler_,
+ IsCurrentlyScrollingLayerAt(testing::_, testing::_))
+ .WillOnce(testing::Return(true));
+
+ time += dt;
+ gesture_.timeStampSeconds = InSecondsF(time);
+ gesture_.type = WebInputEvent::GestureScrollBegin;
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ VERIFY_AND_RESET_MOCKS();
+
+ // If no GestureScrollUpdate or GestureFlingStart is received within the
+ // timeout window, the fling should be cancelled and scrolling should resume.
+ time += base::TimeDelta::FromMilliseconds(100);
+ EXPECT_CALL(mock_input_handler_, ScrollEnd());
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
+ input_handler_->Animate(time);
+
+ VERIFY_AND_RESET_MOCKS();
+}
+
+TEST_F(InputHandlerProxyTest, NoFlingBoostIfFlingInDifferentDirection) {
+ base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10);
+ base::TimeTicks time = base::TimeTicks() + dt;
+ WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
+ WebPoint fling_point = WebPoint(7, 13);
+ StartFling(
+ time, blink::WebGestureDeviceTouchscreen, fling_delta, fling_point);
+
+ // Cancel the fling. The fling cancellation should be deferred to allow
+ // fling boosting events to arrive.
+ time += dt;
+ CancelFling(time);
+
+ // If the new fling is orthogonal to the existing fling, no boosting should
+ // take place, with the new fling replacing the old.
+ WebFloatPoint orthogonal_fling_delta =
+ WebFloatPoint(fling_delta.y, -fling_delta.x);
+ gesture_ = CreateFling(time,
+ blink::WebGestureDeviceTouchscreen,
+ orthogonal_fling_delta,
+ fling_point,
+ fling_point,
+ 0);
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ VERIFY_AND_RESET_MOCKS();
+
+ // Note that the new fling delta uses the orthogonal, unboosted fling
+ // velocity.
+ time += dt;
+ float expected_delta = dt.InSecondsF() * -orthogonal_fling_delta.y;
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
+ EXPECT_CALL(mock_input_handler_,
+ ScrollBy(testing::_,
+ testing::Property(&gfx::Vector2dF::y,
+ testing::Eq(expected_delta))))
+ .WillOnce(testing::Return(true));
+ input_handler_->Animate(time);
+
+ VERIFY_AND_RESET_MOCKS();
+}
+
+TEST_F(InputHandlerProxyTest, NoFlingBoostIfScrollInDifferentDirection) {
+ base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10);
+ base::TimeTicks time = base::TimeTicks() + dt;
+ WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
+ WebPoint fling_point = WebPoint(7, 13);
+ StartFling(
+ time, blink::WebGestureDeviceTouchscreen, fling_delta, fling_point);
+
+ // Cancel the fling. The fling cancellation should be deferred to allow
+ // fling boosting events to arrive.
+ time += dt;
+ CancelFling(time);
+
+ // The GestureScrollBegin should be swallowed by the fling if it hits the same
+ // scrolling layer.
+ EXPECT_CALL(mock_input_handler_,
+ IsCurrentlyScrollingLayerAt(testing::_, testing::_))
+ .WillOnce(testing::Return(true));
+
+ time += dt;
+ gesture_.timeStampSeconds = InSecondsF(time);
+ gesture_.type = WebInputEvent::GestureScrollBegin;
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ VERIFY_AND_RESET_MOCKS();
+
+ // If the GestureScrollUpdate is in a different direction than the fling,
+ // the fling should be cancelled and scrolling should resume.
+ time += dt;
+ gesture_.timeStampSeconds = InSecondsF(time);
+ gesture_.type = WebInputEvent::GestureScrollUpdate;
+ gesture_.data.scrollUpdate.deltaX = -fling_delta.x;
+ EXPECT_CALL(mock_input_handler_, ScrollEnd());
+ 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::Eq(fling_delta.x))))
+ .WillOnce(testing::Return(true));
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ VERIFY_AND_RESET_MOCKS();
+}
+
+TEST_F(InputHandlerProxyTest, NoFlingBoostIfFlingTooSlow) {
+ base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10);
+ base::TimeTicks time = base::TimeTicks() + dt;
+ WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
+ WebPoint fling_point = WebPoint(7, 13);
+ StartFling(
+ time, blink::WebGestureDeviceTouchscreen, fling_delta, fling_point);
+
+ // Cancel the fling. The fling cancellation should be deferred to allow
+ // fling boosting events to arrive.
+ time += dt;
+ CancelFling(time);
+
+ // If the new fling is too slow, no boosting should take place, with the new
+ // fling replacing the old.
+ WebFloatPoint small_fling_delta = WebFloatPoint(100, 0);
+ gesture_ = CreateFling(time,
+ blink::WebGestureDeviceTouchscreen,
+ small_fling_delta,
+ fling_point,
+ fling_point,
+ 0);
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ VERIFY_AND_RESET_MOCKS();
+
+ // Note that the new fling delta uses the *slow*, unboosted fling velocity.
+ time += dt;
+ float expected_delta = dt.InSecondsF() * -small_fling_delta.x;
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimate());
+ EXPECT_CALL(mock_input_handler_,
+ ScrollBy(testing::_,
+ testing::Property(&gfx::Vector2dF::x,
+ testing::Eq(expected_delta))))
+ .WillOnce(testing::Return(true));
+ input_handler_->Animate(time);
+
+ VERIFY_AND_RESET_MOCKS();
+}
+
+TEST_F(InputHandlerProxyTest, FlingBoostTerminatedDuringScrollSequence) {
+ base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10);
+ base::TimeTicks time = base::TimeTicks() + dt;
+ base::TimeTicks last_animate_time = time;
+ WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
+ WebPoint fling_point = WebPoint(7, 13);
+ StartFling(
+ time, blink::WebGestureDeviceTouchscreen, fling_delta, fling_point);
+
+ // Now cancel the fling. The fling cancellation should be deferred to allow
+ // fling boosting events to arrive.
+ time += dt;
+ CancelFling(time);
+
+ // The GestureScrollBegin should be swallowed by the fling.
+ time += dt;
+ gesture_.timeStampSeconds = InSecondsF(time);
+ gesture_.type = WebInputEvent::GestureScrollBegin;
+ EXPECT_CALL(mock_input_handler_,
+ IsCurrentlyScrollingLayerAt(testing::_, testing::_))
+ .WillOnce(testing::Return(true));
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ VERIFY_AND_RESET_MOCKS();
+
+ // Now animate the fling to completion (in this case, the fling should
+ // terminate because the input handler reports a failed scroll). As the fling
+ // was cancelled during an active scroll sequence, a synthetic
+ // GestureScrollBegin should be processed, resuming the scroll.
+ time += dt;
+ float expected_delta =
+ (time - last_animate_time).InSecondsF() * -fling_delta.x;
+ EXPECT_CALL(mock_input_handler_,
+ ScrollBy(testing::_,
+ testing::Property(&gfx::Vector2dF::x,
+ testing::Eq(expected_delta))))
+ .WillOnce(testing::Return(false));
+ EXPECT_CALL(mock_input_handler_, ScrollEnd());
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
+ input_handler_->Animate(time);
+
+ VERIFY_AND_RESET_MOCKS();
+
+ // Subsequent GestureScrollUpdates after the cancelled, boosted fling should
+ // cause scrolling as usual.
+ time += dt;
+ expected_delta = 7.3f;
+ gesture_.timeStampSeconds = InSecondsF(time);
+ gesture_.type = WebInputEvent::GestureScrollUpdate;
+ gesture_.data.scrollUpdate.deltaX = -expected_delta;
+ EXPECT_CALL(mock_input_handler_,
+ ScrollBy(testing::_,
+ testing::Property(&gfx::Vector2dF::x,
+ testing::Eq(expected_delta))))
+ .WillOnce(testing::Return(true));
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ VERIFY_AND_RESET_MOCKS();
+
+ // GestureScrollEnd should terminate the resumed scroll properly.
+ time += dt;
+ gesture_.timeStampSeconds = InSecondsF(time);
+ gesture_.type = WebInputEvent::GestureScrollEnd;
+ EXPECT_CALL(mock_input_handler_, ScrollEnd());
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ VERIFY_AND_RESET_MOCKS();
+}
+
+TEST_F(InputHandlerProxyTest, DidReceiveInputEvent) {
+ testing::StrictMock<
+ MockInputHandlerProxyClientWithDidReceiveInputEvent> mock_client;
+ input_handler_.reset(
+ new content::InputHandlerProxy(&mock_input_handler_, &mock_client));
+
+ // Note the type of input event isn't important.
+ WebMouseWheelEvent wheel;
+ wheel.type = WebInputEvent::MouseWheel;
+ wheel.scrollByPage = true;
+
+ EXPECT_CALL(mock_client, DidReceiveInputEvent());
+
+ input_handler_->HandleInputEvent(wheel);
+ testing::Mock::VerifyAndClearExpectations(&mock_client);
}
} // namespace