1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/renderer/input/input_handler_proxy.h"
7 #include "base/basictypes.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "cc/base/swap_promise_monitor.h"
10 #include "content/renderer/input/input_handler_proxy_client.h"
11 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "third_party/WebKit/public/platform/WebFloatPoint.h"
14 #include "third_party/WebKit/public/platform/WebFloatSize.h"
15 #include "third_party/WebKit/public/platform/WebGestureCurve.h"
16 #include "third_party/WebKit/public/platform/WebPoint.h"
17 #include "third_party/WebKit/public/web/WebInputEvent.h"
18 #include "ui/events/latency_info.h"
20 using blink::WebActiveWheelFlingParameters;
21 using blink::WebFloatPoint;
22 using blink::WebFloatSize;
23 using blink::WebGestureEvent;
24 using blink::WebInputEvent;
25 using blink::WebMouseWheelEvent;
26 using blink::WebPoint;
28 using blink::WebTouchEvent;
29 using blink::WebTouchPoint;
34 class MockInputHandler : public cc::InputHandler {
37 virtual ~MockInputHandler() {}
39 MOCK_METHOD0(PinchGestureBegin, void());
40 MOCK_METHOD2(PinchGestureUpdate,
41 void(float magnify_delta, const gfx::Point& anchor));
42 MOCK_METHOD0(PinchGestureEnd, void());
44 MOCK_METHOD0(ScheduleAnimation, void());
46 MOCK_METHOD2(ScrollBegin,
47 ScrollStatus(const gfx::Point& viewport_point,
48 cc::InputHandler::ScrollInputType type));
49 MOCK_METHOD2(ScrollBy,
50 bool(const gfx::Point& viewport_point,
51 const gfx::Vector2dF& scroll_delta));
52 MOCK_METHOD2(ScrollVerticallyByPage,
53 bool(const gfx::Point& viewport_point,
54 cc::ScrollDirection direction));
55 MOCK_METHOD0(ScrollEnd, void());
56 MOCK_METHOD0(FlingScrollBegin, cc::InputHandler::ScrollStatus());
58 virtual scoped_ptr<cc::SwapPromiseMonitor>
59 CreateLatencyInfoSwapPromiseMonitor(ui::LatencyInfo* latency) OVERRIDE {
60 return scoped_ptr<cc::SwapPromiseMonitor>();
63 virtual void BindToClient(cc::InputHandlerClient* client) OVERRIDE {}
65 virtual void StartPageScaleAnimation(const gfx::Vector2d& target_offset,
68 base::TimeDelta duration) OVERRIDE {}
70 virtual void NotifyCurrentFlingVelocity(
71 const gfx::Vector2dF& velocity) OVERRIDE {}
72 virtual void MouseMoveAt(const gfx::Point& mouse_position) OVERRIDE {}
74 MOCK_METHOD1(HaveTouchEventHandlersAt, bool(const gfx::Point& point));
76 virtual void SetRootLayerScrollOffsetDelegate(
77 cc::LayerScrollOffsetDelegate* root_layer_scroll_offset_delegate)
80 virtual void OnRootLayerDelegatedScrollOffsetChanged() OVERRIDE {}
82 DISALLOW_COPY_AND_ASSIGN(MockInputHandler);
85 // A simple WebGestureCurve implementation that flings at a constant velocity
87 class FakeWebGestureCurve : public blink::WebGestureCurve {
89 FakeWebGestureCurve(const blink::WebFloatPoint& velocity,
90 const blink::WebSize& cumulative_scroll)
91 : velocity_(velocity), cumulative_scroll_(cumulative_scroll) {}
93 virtual ~FakeWebGestureCurve() {}
95 // Returns false if curve has finished and can no longer be applied.
96 virtual bool apply(double time, blink::WebGestureCurveTarget* target) {
97 blink::WebSize displacement(velocity_.x * time, velocity_.y * time);
98 blink::WebFloatSize increment(
99 displacement.width - cumulative_scroll_.width,
100 displacement.height - cumulative_scroll_.height);
101 cumulative_scroll_ = displacement;
102 // scrollBy() could delete this curve if the animation is over, so don't
103 // touch any member variables after making that call.
104 target->scrollBy(increment);
109 blink::WebFloatPoint velocity_;
110 blink::WebSize cumulative_scroll_;
112 DISALLOW_COPY_AND_ASSIGN(FakeWebGestureCurve);
115 class MockInputHandlerProxyClient
116 : public content::InputHandlerProxyClient {
118 MockInputHandlerProxyClient() {}
119 virtual ~MockInputHandlerProxyClient() {}
121 virtual void WillShutdown() OVERRIDE {}
123 MOCK_METHOD1(TransferActiveWheelFlingAnimation,
124 void(const WebActiveWheelFlingParameters&));
126 virtual blink::WebGestureCurve* CreateFlingAnimationCurve(
128 const WebFloatPoint& velocity,
129 const WebSize& cumulative_scroll) OVERRIDE {
130 return new FakeWebGestureCurve(velocity, cumulative_scroll);
133 virtual void DidOverscroll(const cc::DidOverscrollParams& params) OVERRIDE {}
134 virtual void DidStopFlinging() OVERRIDE {}
137 DISALLOW_COPY_AND_ASSIGN(MockInputHandlerProxyClient);
140 WebTouchPoint CreateWebTouchPoint(WebTouchPoint::State state, float x,
144 point.screenPosition = WebFloatPoint(x, y);
145 point.position = WebFloatPoint(x, y);
149 class InputHandlerProxyTest : public testing::Test {
151 InputHandlerProxyTest()
152 : expected_disposition_(InputHandlerProxy::DID_HANDLE) {
153 input_handler_.reset(
154 new content::InputHandlerProxy(&mock_input_handler_));
155 input_handler_->SetClient(&mock_client_);
158 ~InputHandlerProxyTest() {
159 input_handler_.reset();
162 // This is defined as a macro because when an expectation is not satisfied the
163 // only output you get
164 // out of gmock is the line number that set the expectation.
165 #define VERIFY_AND_RESET_MOCKS() \
167 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); \
168 testing::Mock::VerifyAndClearExpectations(&mock_client_); \
172 testing::StrictMock<MockInputHandler> mock_input_handler_;
173 scoped_ptr<content::InputHandlerProxy> input_handler_;
174 testing::StrictMock<MockInputHandlerProxyClient> mock_client_;
175 WebGestureEvent gesture_;
177 InputHandlerProxy::EventDisposition expected_disposition_;
180 TEST_F(InputHandlerProxyTest, MouseWheelByPageMainThread) {
181 expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
182 WebMouseWheelEvent wheel;
183 wheel.type = WebInputEvent::MouseWheel;
184 wheel.scrollByPage = true;
186 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(wheel));
187 testing::Mock::VerifyAndClearExpectations(&mock_client_);
190 TEST_F(InputHandlerProxyTest, MouseWheelWithCtrl) {
191 expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
192 WebMouseWheelEvent wheel;
193 wheel.type = WebInputEvent::MouseWheel;
194 wheel.modifiers = WebInputEvent::ControlKey;
196 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(wheel));
197 testing::Mock::VerifyAndClearExpectations(&mock_client_);
200 TEST_F(InputHandlerProxyTest, GestureScrollStarted) {
201 // We shouldn't send any events to the widget for this gesture.
202 expected_disposition_ = InputHandlerProxy::DID_HANDLE;
203 VERIFY_AND_RESET_MOCKS();
205 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
206 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
208 gesture_.type = WebInputEvent::GestureScrollBegin;
209 EXPECT_EQ(expected_disposition_,input_handler_->HandleInputEvent(gesture_));
211 // The event should not be marked as handled if scrolling is not possible.
212 expected_disposition_ = InputHandlerProxy::DROP_EVENT;
213 VERIFY_AND_RESET_MOCKS();
215 gesture_.type = WebInputEvent::GestureScrollUpdate;
216 gesture_.data.scrollUpdate.deltaY =
217 -40; // -Y means scroll down - i.e. in the +Y direction.
218 EXPECT_CALL(mock_input_handler_,
220 testing::Property(&gfx::Vector2dF::y, testing::Gt(0))))
221 .WillOnce(testing::Return(false));
222 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
224 // Mark the event as handled if scroll happens.
225 expected_disposition_ = InputHandlerProxy::DID_HANDLE;
226 VERIFY_AND_RESET_MOCKS();
228 gesture_.type = WebInputEvent::GestureScrollUpdate;
229 gesture_.data.scrollUpdate.deltaY =
230 -40; // -Y means scroll down - i.e. in the +Y direction.
231 EXPECT_CALL(mock_input_handler_,
233 testing::Property(&gfx::Vector2dF::y, testing::Gt(0))))
234 .WillOnce(testing::Return(true));
235 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
237 VERIFY_AND_RESET_MOCKS();
239 gesture_.type = WebInputEvent::GestureScrollEnd;
240 gesture_.data.scrollUpdate.deltaY = 0;
241 EXPECT_CALL(mock_input_handler_, ScrollEnd());
242 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
245 TEST_F(InputHandlerProxyTest, GestureScrollOnMainThread) {
246 // We should send all events to the widget for this gesture.
247 expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
248 VERIFY_AND_RESET_MOCKS();
250 EXPECT_CALL(mock_input_handler_, ScrollBegin(::testing::_, ::testing::_))
251 .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread));
253 gesture_.type = WebInputEvent::GestureScrollBegin;
254 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
256 VERIFY_AND_RESET_MOCKS();
258 gesture_.type = WebInputEvent::GestureScrollUpdate;
259 gesture_.data.scrollUpdate.deltaY = 40;
260 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
262 VERIFY_AND_RESET_MOCKS();
264 gesture_.type = WebInputEvent::GestureScrollEnd;
265 gesture_.data.scrollUpdate.deltaY = 0;
266 EXPECT_CALL(mock_input_handler_, ScrollEnd()).WillOnce(testing::Return());
267 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
270 TEST_F(InputHandlerProxyTest, GestureScrollIgnored) {
271 // We shouldn't handle the GestureScrollBegin.
272 // Instead, we should get a DROP_EVENT result, indicating
273 // that we could determine that there's nothing that could scroll or otherwise
274 // react to this gesture sequence and thus we should drop the whole gesture
275 // sequence on the floor, except for the ScrollEnd.
276 expected_disposition_ = InputHandlerProxy::DROP_EVENT;
277 VERIFY_AND_RESET_MOCKS();
279 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
280 .WillOnce(testing::Return(cc::InputHandler::ScrollIgnored));
282 gesture_.type = WebInputEvent::GestureScrollBegin;
283 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
285 expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
286 gesture_.type = WebInputEvent::GestureScrollEnd;
287 EXPECT_CALL(mock_input_handler_, ScrollEnd()).WillOnce(testing::Return());
288 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
291 TEST_F(InputHandlerProxyTest, GesturePinch) {
292 // We shouldn't send any events to the widget for this gesture.
293 expected_disposition_ = InputHandlerProxy::DID_HANDLE;
294 VERIFY_AND_RESET_MOCKS();
296 gesture_.type = WebInputEvent::GesturePinchBegin;
297 EXPECT_CALL(mock_input_handler_, PinchGestureBegin());
298 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
300 VERIFY_AND_RESET_MOCKS();
302 gesture_.type = WebInputEvent::GesturePinchUpdate;
303 gesture_.data.pinchUpdate.scale = 1.5;
306 EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(1.5, gfx::Point(7, 13)));
307 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
309 VERIFY_AND_RESET_MOCKS();
311 gesture_.type = WebInputEvent::GesturePinchUpdate;
312 gesture_.data.pinchUpdate.scale = 0.5;
315 EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(.5, gfx::Point(9, 6)));
316 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
318 VERIFY_AND_RESET_MOCKS();
320 gesture_.type = WebInputEvent::GesturePinchEnd;
321 EXPECT_CALL(mock_input_handler_, PinchGestureEnd());
322 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
325 TEST_F(InputHandlerProxyTest, GesturePinchAfterScrollOnMainThread) {
326 // Scrolls will start by being sent to the main thread.
327 expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
328 VERIFY_AND_RESET_MOCKS();
330 EXPECT_CALL(mock_input_handler_, ScrollBegin(::testing::_, ::testing::_))
331 .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread));
333 gesture_.type = WebInputEvent::GestureScrollBegin;
334 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
336 VERIFY_AND_RESET_MOCKS();
338 gesture_.type = WebInputEvent::GestureScrollUpdate;
339 gesture_.data.scrollUpdate.deltaY = 40;
340 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
342 // However, after the pinch gesture starts, they should go to the impl
344 expected_disposition_ = InputHandlerProxy::DID_HANDLE;
345 VERIFY_AND_RESET_MOCKS();
347 gesture_.type = WebInputEvent::GesturePinchBegin;
348 EXPECT_CALL(mock_input_handler_, PinchGestureBegin());
349 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
351 VERIFY_AND_RESET_MOCKS();
353 gesture_.type = WebInputEvent::GesturePinchUpdate;
354 gesture_.data.pinchUpdate.scale = 1.5;
357 EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(1.5, gfx::Point(7, 13)));
358 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
360 VERIFY_AND_RESET_MOCKS();
362 gesture_.type = WebInputEvent::GestureScrollUpdate;
363 gesture_.data.scrollUpdate.deltaY =
364 -40; // -Y means scroll down - i.e. in the +Y direction.
365 EXPECT_CALL(mock_input_handler_,
367 testing::Property(&gfx::Vector2dF::y, testing::Gt(0))))
368 .WillOnce(testing::Return(true));
369 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
371 VERIFY_AND_RESET_MOCKS();
373 gesture_.type = WebInputEvent::GesturePinchUpdate;
374 gesture_.data.pinchUpdate.scale = 0.5;
377 EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(.5, gfx::Point(9, 6)));
378 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
380 VERIFY_AND_RESET_MOCKS();
382 gesture_.type = WebInputEvent::GesturePinchEnd;
383 EXPECT_CALL(mock_input_handler_, PinchGestureEnd());
384 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
386 // After the pinch gesture ends, they should go to back to the main
388 expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
389 VERIFY_AND_RESET_MOCKS();
391 gesture_.type = WebInputEvent::GestureScrollEnd;
392 gesture_.data.scrollUpdate.deltaY = 0;
393 EXPECT_CALL(mock_input_handler_, ScrollEnd())
394 .WillOnce(testing::Return());
395 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
398 TEST_F(InputHandlerProxyTest, GestureFlingStartedTouchpad) {
399 // We shouldn't send any events to the widget for this gesture.
400 expected_disposition_ = InputHandlerProxy::DID_HANDLE;
401 VERIFY_AND_RESET_MOCKS();
403 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
404 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
405 EXPECT_CALL(mock_input_handler_, ScrollEnd());
406 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
408 gesture_.type = WebInputEvent::GestureFlingStart;
409 gesture_.data.flingStart.velocityX = 10;
410 gesture_.sourceDevice = WebGestureEvent::Touchpad;
411 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
413 VERIFY_AND_RESET_MOCKS();
415 // Verify that a GestureFlingCancel during an animation cancels it.
416 gesture_.type = WebInputEvent::GestureFlingCancel;
417 gesture_.sourceDevice = WebGestureEvent::Touchpad;
418 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
421 TEST_F(InputHandlerProxyTest, GestureFlingOnMainThreadTouchpad) {
422 // We should send all events to the widget for this gesture.
423 expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
424 VERIFY_AND_RESET_MOCKS();
426 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
427 .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread));
429 gesture_.type = WebInputEvent::GestureFlingStart;
430 gesture_.sourceDevice = WebGestureEvent::Touchpad;
431 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
433 // Since we returned ScrollStatusOnMainThread from scrollBegin, ensure the
434 // input handler knows it's scrolling off the impl thread
435 ASSERT_FALSE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
437 VERIFY_AND_RESET_MOCKS();
439 // Even if we didn't start a fling ourselves, we still need to send the cancel
440 // event to the widget.
441 gesture_.type = WebInputEvent::GestureFlingCancel;
442 gesture_.sourceDevice = WebGestureEvent::Touchpad;
443 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
446 TEST_F(InputHandlerProxyTest, GestureFlingIgnoredTouchpad) {
447 expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
448 VERIFY_AND_RESET_MOCKS();
450 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
451 .WillOnce(testing::Return(cc::InputHandler::ScrollIgnored));
453 gesture_.type = WebInputEvent::GestureFlingStart;
454 gesture_.sourceDevice = WebGestureEvent::Touchpad;
455 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
457 expected_disposition_ = InputHandlerProxy::DROP_EVENT;
458 VERIFY_AND_RESET_MOCKS();
460 // Since the previous fling was ignored, we should also be dropping the next
462 gesture_.type = WebInputEvent::GestureFlingCancel;
463 gesture_.sourceDevice = WebGestureEvent::Touchpad;
464 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
467 TEST_F(InputHandlerProxyTest, GestureFlingAnimatesTouchpad) {
468 // We shouldn't send any events to the widget for this gesture.
469 expected_disposition_ = InputHandlerProxy::DID_HANDLE;
470 VERIFY_AND_RESET_MOCKS();
472 // On the fling start, we should schedule an animation but not actually start
474 gesture_.type = WebInputEvent::GestureFlingStart;
475 WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
476 WebPoint fling_point = WebPoint(7, 13);
477 WebPoint fling_global_point = WebPoint(17, 23);
478 // Note that for trackpad, wheel events with the Control modifier are
479 // special (reserved for zoom), so don't set that here.
480 int modifiers = WebInputEvent::ShiftKey | WebInputEvent::AltKey;
481 gesture_.data.flingStart.velocityX = fling_delta.x;
482 gesture_.data.flingStart.velocityY = fling_delta.y;
483 gesture_.sourceDevice = WebGestureEvent::Touchpad;
484 gesture_.x = fling_point.x;
485 gesture_.y = fling_point.y;
486 gesture_.globalX = fling_global_point.x;
487 gesture_.globalY = fling_global_point.y;
488 gesture_.modifiers = modifiers;
489 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
490 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
491 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
492 EXPECT_CALL(mock_input_handler_, ScrollEnd());
493 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
495 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
496 // The first animate call should let us pick up an animation start time, but
497 // we shouldn't actually move anywhere just yet. The first frame after the
498 // fling start will typically include the last scroll from the gesture that
499 // lead to the scroll (either wheel or gesture scroll), so there should be no
501 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
502 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
504 base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10);
505 input_handler_->Animate(time);
507 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
509 // The second call should start scrolling in the -X direction.
510 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
511 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
512 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
513 EXPECT_CALL(mock_input_handler_,
515 testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
516 .WillOnce(testing::Return(true));
517 EXPECT_CALL(mock_input_handler_, ScrollEnd());
518 time += base::TimeDelta::FromMilliseconds(100);
519 input_handler_->Animate(time);
521 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
523 // Let's say on the third call we hit a non-scrollable region. We should abort
524 // the fling and not scroll.
525 // We also should pass the current fling parameters out to the client so the
526 // rest of the fling can be
527 // transferred to the main thread.
528 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
529 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
530 .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread));
531 EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::_)).Times(0);
532 EXPECT_CALL(mock_input_handler_, ScrollEnd()).Times(0);
533 // Expected wheel fling animation parameters:
534 // *) fling_delta and fling_point should match the original GestureFlingStart
536 // *) startTime should be 10 to match the time parameter of the first
537 // Animate() call after the GestureFlingStart
538 // *) cumulativeScroll depends on the curve, but since we've animated in the
539 // -X direction the X value should be < 0
542 TransferActiveWheelFlingAnimation(testing::AllOf(
543 testing::Field(&WebActiveWheelFlingParameters::delta,
544 testing::Eq(fling_delta)),
545 testing::Field(&WebActiveWheelFlingParameters::point,
546 testing::Eq(fling_point)),
547 testing::Field(&WebActiveWheelFlingParameters::globalPoint,
548 testing::Eq(fling_global_point)),
549 testing::Field(&WebActiveWheelFlingParameters::modifiers,
550 testing::Eq(modifiers)),
551 testing::Field(&WebActiveWheelFlingParameters::startTime,
553 testing::Field(&WebActiveWheelFlingParameters::cumulativeScroll,
554 testing::Field(&WebSize::width, testing::Gt(0))))));
555 time += base::TimeDelta::FromMilliseconds(100);
556 input_handler_->Animate(time);
558 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
559 testing::Mock::VerifyAndClearExpectations(&mock_client_);
561 // Since we've aborted the fling, the next animation should be a no-op and
562 // should not result in another
563 // frame being requested.
564 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()).Times(0);
565 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
567 time += base::TimeDelta::FromMilliseconds(100);
568 input_handler_->Animate(time);
570 // Since we've transferred the fling to the main thread, we need to pass the
571 // next GestureFlingCancel to the main
573 expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
574 gesture_.type = WebInputEvent::GestureFlingCancel;
575 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
578 TEST_F(InputHandlerProxyTest, GestureFlingTransferResetsTouchpad) {
579 // We shouldn't send any events to the widget for this gesture.
580 expected_disposition_ = InputHandlerProxy::DID_HANDLE;
581 VERIFY_AND_RESET_MOCKS();
583 // Start a gesture fling in the -X direction with zero Y movement.
584 gesture_.type = WebInputEvent::GestureFlingStart;
585 WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
586 WebPoint fling_point = WebPoint(7, 13);
587 WebPoint fling_global_point = WebPoint(17, 23);
588 // Note that for trackpad, wheel events with the Control modifier are
589 // special (reserved for zoom), so don't set that here.
590 int modifiers = WebInputEvent::ShiftKey | WebInputEvent::AltKey;
591 gesture_.data.flingStart.velocityX = fling_delta.x;
592 gesture_.data.flingStart.velocityY = fling_delta.y;
593 gesture_.sourceDevice = WebGestureEvent::Touchpad;
594 gesture_.x = fling_point.x;
595 gesture_.y = fling_point.y;
596 gesture_.globalX = fling_global_point.x;
597 gesture_.globalY = fling_global_point.y;
598 gesture_.modifiers = modifiers;
599 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
600 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
601 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
602 EXPECT_CALL(mock_input_handler_, ScrollEnd());
603 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
605 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
607 // Start the fling animation at time 10. This shouldn't actually scroll, just
608 // establish a start time.
609 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
610 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
612 base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10);
613 input_handler_->Animate(time);
615 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
617 // The second call should start scrolling in the -X direction.
618 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
619 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
620 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
621 EXPECT_CALL(mock_input_handler_,
623 testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
624 .WillOnce(testing::Return(true));
625 EXPECT_CALL(mock_input_handler_, ScrollEnd());
626 time += base::TimeDelta::FromMilliseconds(100);
627 input_handler_->Animate(time);
629 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
631 // Let's say on the third call we hit a non-scrollable region. We should abort
632 // the fling and not scroll.
633 // We also should pass the current fling parameters out to the client so the
634 // rest of the fling can be
635 // transferred to the main thread.
636 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
637 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
638 .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread));
639 EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::_)).Times(0);
640 EXPECT_CALL(mock_input_handler_, ScrollEnd()).Times(0);
642 // Expected wheel fling animation parameters:
643 // *) fling_delta and fling_point should match the original GestureFlingStart
645 // *) startTime should be 10 to match the time parameter of the first
646 // Animate() call after the GestureFlingStart
647 // *) cumulativeScroll depends on the curve, but since we've animated in the
648 // -X direction the X value should be < 0
651 TransferActiveWheelFlingAnimation(testing::AllOf(
652 testing::Field(&WebActiveWheelFlingParameters::delta,
653 testing::Eq(fling_delta)),
654 testing::Field(&WebActiveWheelFlingParameters::point,
655 testing::Eq(fling_point)),
656 testing::Field(&WebActiveWheelFlingParameters::globalPoint,
657 testing::Eq(fling_global_point)),
658 testing::Field(&WebActiveWheelFlingParameters::modifiers,
659 testing::Eq(modifiers)),
660 testing::Field(&WebActiveWheelFlingParameters::startTime,
662 testing::Field(&WebActiveWheelFlingParameters::cumulativeScroll,
663 testing::Field(&WebSize::width, testing::Gt(0))))));
664 time += base::TimeDelta::FromMilliseconds(100);
665 input_handler_->Animate(time);
667 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
668 testing::Mock::VerifyAndClearExpectations(&mock_client_);
670 // Since we've aborted the fling, the next animation should be a no-op and
671 // should not result in another
672 // frame being requested.
673 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()).Times(0);
674 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
676 time += base::TimeDelta::FromMilliseconds(100);
677 input_handler_->Animate(time);
679 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
681 // Since we've transferred the fling to the main thread, we need to pass the
682 // next GestureFlingCancel to the main
684 expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
685 gesture_.type = WebInputEvent::GestureFlingCancel;
686 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
688 VERIFY_AND_RESET_MOCKS();
689 input_handler_->MainThreadHasStoppedFlinging();
691 // Start a second gesture fling, this time in the +Y direction with no X.
692 gesture_.type = WebInputEvent::GestureFlingStart;
693 fling_delta = WebFloatPoint(0, -1000);
694 fling_point = WebPoint(95, 87);
695 fling_global_point = WebPoint(32, 71);
696 modifiers = WebInputEvent::AltKey;
697 gesture_.data.flingStart.velocityX = fling_delta.x;
698 gesture_.data.flingStart.velocityY = fling_delta.y;
699 gesture_.sourceDevice = WebGestureEvent::Touchpad;
700 gesture_.x = fling_point.x;
701 gesture_.y = fling_point.y;
702 gesture_.globalX = fling_global_point.x;
703 gesture_.globalY = fling_global_point.y;
704 gesture_.modifiers = modifiers;
705 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
706 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
707 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
708 EXPECT_CALL(mock_input_handler_, ScrollEnd());
709 expected_disposition_ = InputHandlerProxy::DID_HANDLE;
710 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
712 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
714 // Start the second fling animation at time 30.
715 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
716 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
718 time = base::TimeTicks() + base::TimeDelta::FromSeconds(30);
719 input_handler_->Animate(time);
721 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
723 // Tick the second fling once normally.
724 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
725 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
726 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
727 EXPECT_CALL(mock_input_handler_,
729 testing::Property(&gfx::Vector2dF::y, testing::Gt(0))))
730 .WillOnce(testing::Return(true));
731 EXPECT_CALL(mock_input_handler_, ScrollEnd());
732 time += base::TimeDelta::FromMilliseconds(100);
733 input_handler_->Animate(time);
735 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
737 // Then abort the second fling.
738 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
739 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
740 .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread));
741 EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::_)).Times(0);
742 EXPECT_CALL(mock_input_handler_, ScrollEnd()).Times(0);
744 // We should get parameters from the second fling, nothing from the first
745 // fling should "leak".
748 TransferActiveWheelFlingAnimation(testing::AllOf(
749 testing::Field(&WebActiveWheelFlingParameters::delta,
750 testing::Eq(fling_delta)),
751 testing::Field(&WebActiveWheelFlingParameters::point,
752 testing::Eq(fling_point)),
753 testing::Field(&WebActiveWheelFlingParameters::globalPoint,
754 testing::Eq(fling_global_point)),
755 testing::Field(&WebActiveWheelFlingParameters::modifiers,
756 testing::Eq(modifiers)),
757 testing::Field(&WebActiveWheelFlingParameters::startTime,
759 testing::Field(&WebActiveWheelFlingParameters::cumulativeScroll,
760 testing::Field(&WebSize::height, testing::Lt(0))))));
761 time += base::TimeDelta::FromMilliseconds(100);
762 input_handler_->Animate(time);
765 TEST_F(InputHandlerProxyTest, GestureFlingStartedTouchscreen) {
766 // We shouldn't send any events to the widget for this gesture.
767 expected_disposition_ = InputHandlerProxy::DID_HANDLE;
768 VERIFY_AND_RESET_MOCKS();
770 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
771 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
772 gesture_.type = WebInputEvent::GestureScrollBegin;
773 gesture_.sourceDevice = WebGestureEvent::Touchscreen;
774 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
776 VERIFY_AND_RESET_MOCKS();
778 EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
779 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
780 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
782 gesture_.type = WebInputEvent::GestureFlingStart;
783 gesture_.data.flingStart.velocityX = 10;
784 gesture_.sourceDevice = WebGestureEvent::Touchscreen;
785 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
787 VERIFY_AND_RESET_MOCKS();
789 EXPECT_CALL(mock_input_handler_, ScrollEnd());
791 // Verify that a GestureFlingCancel during an animation cancels it.
792 gesture_.type = WebInputEvent::GestureFlingCancel;
793 gesture_.sourceDevice = WebGestureEvent::Touchscreen;
794 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
797 TEST_F(InputHandlerProxyTest, GestureFlingOnMainThreadTouchscreen) {
798 // We should send all events to the widget for this gesture.
799 expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
800 VERIFY_AND_RESET_MOCKS();
802 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
803 .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread));
805 gesture_.type = WebInputEvent::GestureScrollBegin;
806 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
808 VERIFY_AND_RESET_MOCKS();
810 EXPECT_CALL(mock_input_handler_, FlingScrollBegin()).Times(0);
812 gesture_.type = WebInputEvent::GestureFlingStart;
813 gesture_.sourceDevice = WebGestureEvent::Touchscreen;
814 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
816 VERIFY_AND_RESET_MOCKS();
818 // Even if we didn't start a fling ourselves, we still need to send the cancel
819 // event to the widget.
820 gesture_.type = WebInputEvent::GestureFlingCancel;
821 gesture_.sourceDevice = WebGestureEvent::Touchscreen;
822 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
825 TEST_F(InputHandlerProxyTest, GestureFlingIgnoredTouchscreen) {
826 expected_disposition_ = InputHandlerProxy::DID_HANDLE;
827 VERIFY_AND_RESET_MOCKS();
829 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
830 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
832 gesture_.type = WebInputEvent::GestureScrollBegin;
833 gesture_.sourceDevice = WebGestureEvent::Touchscreen;
834 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
836 expected_disposition_ = InputHandlerProxy::DROP_EVENT;
837 VERIFY_AND_RESET_MOCKS();
839 EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
840 .WillOnce(testing::Return(cc::InputHandler::ScrollIgnored));
842 gesture_.type = WebInputEvent::GestureFlingStart;
843 gesture_.sourceDevice = WebGestureEvent::Touchscreen;
844 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
846 VERIFY_AND_RESET_MOCKS();
848 // Even if we didn't start a fling ourselves, we still need to send the cancel
849 // event to the widget.
850 gesture_.type = WebInputEvent::GestureFlingCancel;
851 gesture_.sourceDevice = WebGestureEvent::Touchscreen;
852 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
855 TEST_F(InputHandlerProxyTest, GestureFlingAnimatesTouchscreen) {
856 // We shouldn't send any events to the widget for this gesture.
857 expected_disposition_ = InputHandlerProxy::DID_HANDLE;
858 VERIFY_AND_RESET_MOCKS();
860 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
861 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
863 gesture_.type = WebInputEvent::GestureScrollBegin;
864 gesture_.sourceDevice = WebGestureEvent::Touchscreen;
865 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
867 VERIFY_AND_RESET_MOCKS();
869 // On the fling start, we should schedule an animation but not actually start
871 gesture_.type = WebInputEvent::GestureFlingStart;
872 WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
873 WebPoint fling_point = WebPoint(7, 13);
874 WebPoint fling_global_point = WebPoint(17, 23);
875 // Note that for touchscreen the control modifier is not special.
876 int modifiers = WebInputEvent::ControlKey;
877 gesture_.data.flingStart.velocityX = fling_delta.x;
878 gesture_.data.flingStart.velocityY = fling_delta.y;
879 gesture_.sourceDevice = WebGestureEvent::Touchscreen;
880 gesture_.x = fling_point.x;
881 gesture_.y = fling_point.y;
882 gesture_.globalX = fling_global_point.x;
883 gesture_.globalY = fling_global_point.y;
884 gesture_.modifiers = modifiers;
885 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
886 EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
887 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
888 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
890 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
891 // The first animate call should let us pick up an animation start time, but
892 // we shouldn't actually move anywhere just yet. The first frame after the
893 // fling start will typically include the last scroll from the gesture that
894 // lead to the scroll (either wheel or gesture scroll), so there should be no
896 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
897 base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10);
898 input_handler_->Animate(time);
900 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
902 // The second call should start scrolling in the -X direction.
903 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
904 EXPECT_CALL(mock_input_handler_,
906 testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
907 .WillOnce(testing::Return(true));
908 time += base::TimeDelta::FromMilliseconds(100);
909 input_handler_->Animate(time);
911 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
913 EXPECT_CALL(mock_input_handler_, ScrollEnd());
914 gesture_.type = WebInputEvent::GestureFlingCancel;
915 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
918 TEST_F(InputHandlerProxyTest, GestureFlingWithValidTimestamp) {
919 // We shouldn't send any events to the widget for this gesture.
920 expected_disposition_ = InputHandlerProxy::DID_HANDLE;
921 VERIFY_AND_RESET_MOCKS();
923 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
924 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
926 gesture_.type = WebInputEvent::GestureScrollBegin;
927 gesture_.sourceDevice = WebGestureEvent::Touchscreen;
928 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
930 VERIFY_AND_RESET_MOCKS();
932 // On the fling start, we should schedule an animation but not actually start
934 base::TimeDelta startTimeOffset = base::TimeDelta::FromMilliseconds(10);
935 gesture_.type = WebInputEvent::GestureFlingStart;
936 WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
937 WebPoint fling_point = WebPoint(7, 13);
938 WebPoint fling_global_point = WebPoint(17, 23);
939 int modifiers = WebInputEvent::ControlKey;
940 gesture_.timeStampSeconds = startTimeOffset.InSecondsF();
941 gesture_.data.flingStart.velocityX = fling_delta.x;
942 gesture_.data.flingStart.velocityY = fling_delta.y;
943 gesture_.sourceDevice = WebGestureEvent::Touchscreen;
944 gesture_.x = fling_point.x;
945 gesture_.y = fling_point.y;
946 gesture_.globalX = fling_global_point.x;
947 gesture_.globalY = fling_global_point.y;
948 gesture_.modifiers = modifiers;
949 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
950 EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
951 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
952 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
954 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
955 // With a valid time stamp, the first animate call should skip start time
956 // initialization and immediately begin scroll update production. This reduces
957 // the likelihood of a hitch between the scroll preceding the fling and
958 // the first scroll generated by the fling.
959 // Scrolling should start in the -X direction.
960 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
961 EXPECT_CALL(mock_input_handler_,
963 testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
964 .WillOnce(testing::Return(true));
965 base::TimeTicks time = base::TimeTicks() + 2 * startTimeOffset;
966 input_handler_->Animate(time);
968 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
970 EXPECT_CALL(mock_input_handler_, ScrollEnd());
971 gesture_.type = WebInputEvent::GestureFlingCancel;
972 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
975 TEST_F(InputHandlerProxyTest,
976 GestureScrollOnImplThreadFlagClearedAfterFling) {
977 // We shouldn't send any events to the widget for this gesture.
978 expected_disposition_ = InputHandlerProxy::DID_HANDLE;
979 VERIFY_AND_RESET_MOCKS();
981 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
982 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
984 gesture_.type = WebInputEvent::GestureScrollBegin;
985 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
987 // After sending a GestureScrollBegin, the member variable
988 // |gesture_scroll_on_impl_thread_| should be true.
989 EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
991 expected_disposition_ = InputHandlerProxy::DID_HANDLE;
992 VERIFY_AND_RESET_MOCKS();
994 // On the fling start, we should schedule an animation but not actually start
996 gesture_.type = WebInputEvent::GestureFlingStart;
997 WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
998 WebPoint fling_point = WebPoint(7, 13);
999 WebPoint fling_global_point = WebPoint(17, 23);
1000 int modifiers = WebInputEvent::ControlKey | WebInputEvent::AltKey;
1001 gesture_.data.flingStart.velocityX = fling_delta.x;
1002 gesture_.data.flingStart.velocityY = fling_delta.y;
1003 gesture_.sourceDevice = WebGestureEvent::Touchscreen;
1004 gesture_.x = fling_point.x;
1005 gesture_.y = fling_point.y;
1006 gesture_.globalX = fling_global_point.x;
1007 gesture_.globalY = fling_global_point.y;
1008 gesture_.modifiers = modifiers;
1009 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
1010 EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
1011 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
1012 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
1014 // |gesture_scroll_on_impl_thread_| should still be true after
1015 // a GestureFlingStart is sent.
1016 EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
1018 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
1019 // The first animate call should let us pick up an animation start time, but
1020 // we shouldn't actually move anywhere just yet. The first frame after the
1021 // fling start will typically include the last scroll from the gesture that
1022 // lead to the scroll (either wheel or gesture scroll), so there should be no
1024 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
1025 base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10);
1026 input_handler_->Animate(time);
1028 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
1030 // The second call should start scrolling in the -X direction.
1031 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
1032 EXPECT_CALL(mock_input_handler_,
1033 ScrollBy(testing::_,
1034 testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
1035 .WillOnce(testing::Return(true));
1036 time += base::TimeDelta::FromMilliseconds(100);
1037 input_handler_->Animate(time);
1039 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
1041 EXPECT_CALL(mock_input_handler_, ScrollEnd());
1042 gesture_.type = WebInputEvent::GestureFlingCancel;
1043 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
1045 // |gesture_scroll_on_impl_thread_| should be false once
1046 // the fling has finished (note no GestureScrollEnd has been sent).
1047 EXPECT_TRUE(!input_handler_->gesture_scroll_on_impl_thread_for_testing());
1050 TEST_F(InputHandlerProxyTest, GestureFlingStopsAtContentEdge) {
1051 // We shouldn't send any events to the widget for this gesture.
1052 expected_disposition_ = InputHandlerProxy::DID_HANDLE;
1053 VERIFY_AND_RESET_MOCKS();
1055 // On the fling start, we should schedule an animation but not actually start
1057 gesture_.type = WebInputEvent::GestureFlingStart;
1058 WebFloatPoint fling_delta = WebFloatPoint(1000, 1000);
1059 gesture_.data.flingStart.velocityX = fling_delta.x;
1060 gesture_.data.flingStart.velocityY = fling_delta.y;
1061 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
1062 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
1063 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
1064 EXPECT_CALL(mock_input_handler_, ScrollEnd());
1065 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
1066 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
1068 // The first animate doesn't cause any scrolling.
1069 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
1070 base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10);
1071 input_handler_->Animate(time);
1072 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
1074 // The second animate starts scrolling in the positive X and Y directions.
1075 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
1076 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
1077 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
1078 EXPECT_CALL(mock_input_handler_,
1079 ScrollBy(testing::_,
1080 testing::Property(&gfx::Vector2dF::y, testing::Lt(0))))
1081 .WillOnce(testing::Return(true));
1082 EXPECT_CALL(mock_input_handler_, ScrollEnd());
1083 time += base::TimeDelta::FromMilliseconds(100);
1084 input_handler_->Animate(time);
1085 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
1087 // Simulate hitting the bottom content edge.
1088 cc::DidOverscrollParams overscroll_params;
1089 overscroll_params.accumulated_overscroll = gfx::Vector2dF(0, 100);
1090 overscroll_params.current_fling_velocity = gfx::Vector2dF(0, 10);
1091 input_handler_->DidOverscroll(overscroll_params);
1093 // The next call to animate will no longer scroll vertically.
1094 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
1095 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
1096 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
1097 EXPECT_CALL(mock_input_handler_,
1098 ScrollBy(testing::_,
1099 testing::Property(&gfx::Vector2dF::y, testing::Eq(0))))
1100 .WillOnce(testing::Return(true));
1101 EXPECT_CALL(mock_input_handler_, ScrollEnd());
1102 time += base::TimeDelta::FromMilliseconds(100);
1103 input_handler_->Animate(time);
1104 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
1107 TEST_F(InputHandlerProxyTest, GestureFlingCancelledAfterBothAxesStopScrolling) {
1108 // We shouldn't send any events to the widget for this gesture.
1109 expected_disposition_ = InputHandlerProxy::DID_HANDLE;
1110 VERIFY_AND_RESET_MOCKS();
1112 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
1113 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
1114 gesture_.type = WebInputEvent::GestureScrollBegin;
1115 gesture_.sourceDevice = WebGestureEvent::Touchscreen;
1116 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
1117 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
1119 // On the fling start, we should schedule an animation but not actually start
1121 gesture_.type = WebInputEvent::GestureFlingStart;
1122 WebFloatPoint fling_delta = WebFloatPoint(1000, 1000);
1123 gesture_.data.flingStart.velocityX = fling_delta.x;
1124 gesture_.data.flingStart.velocityY = fling_delta.y;
1125 EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
1126 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted));
1127 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
1128 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
1129 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
1131 // The first animate doesn't cause any scrolling.
1132 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
1133 base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10);
1134 input_handler_->Animate(time);
1135 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
1137 // The second animate starts scrolling in the positive X and Y directions.
1138 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
1139 EXPECT_CALL(mock_input_handler_,
1140 ScrollBy(testing::_,
1141 testing::Property(&gfx::Vector2dF::y, testing::Lt(0))))
1142 .WillOnce(testing::Return(true));
1143 time += base::TimeDelta::FromMilliseconds(10);
1144 input_handler_->Animate(time);
1145 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
1147 // Simulate hitting the bottom content edge.
1148 cc::DidOverscrollParams overscroll_params;
1149 overscroll_params.accumulated_overscroll = gfx::Vector2dF(0, 100);
1150 input_handler_->DidOverscroll(overscroll_params);
1152 // The next call to animate will no longer scroll vertically.
1153 EXPECT_CALL(mock_input_handler_, ScheduleAnimation());
1154 EXPECT_CALL(mock_input_handler_,
1155 ScrollBy(testing::_,
1156 testing::Property(&gfx::Vector2dF::y, testing::Eq(0))))
1157 .WillOnce(testing::Return(true));
1158 time += base::TimeDelta::FromMilliseconds(10);
1159 input_handler_->Animate(time);
1160 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
1162 // Simulate hitting the right content edge.
1163 overscroll_params.accumulated_overscroll = gfx::Vector2dF(100, 100);
1164 input_handler_->DidOverscroll(overscroll_params);
1166 // The next call to animate will no longer scroll horizontally or vertically,
1167 // and the fling should be cancelled.
1168 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()).Times(0);
1169 EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::_)).Times(0);
1170 EXPECT_CALL(mock_input_handler_, ScrollEnd());
1171 time += base::TimeDelta::FromMilliseconds(10);
1172 input_handler_->Animate(time);
1173 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
1174 EXPECT_FALSE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
1177 TEST_F(InputHandlerProxyTest, MultiTouchPointHitTestNegative) {
1178 // None of the three touch points fall in the touch region. So the event
1179 // should be dropped.
1180 expected_disposition_ = InputHandlerProxy::DROP_EVENT;
1181 VERIFY_AND_RESET_MOCKS();
1183 EXPECT_CALL(mock_input_handler_,
1184 HaveTouchEventHandlersAt(
1185 testing::Property(&gfx::Point::x, testing::Gt(0))))
1186 .WillOnce(testing::Return(false));
1187 EXPECT_CALL(mock_input_handler_,
1188 HaveTouchEventHandlersAt(
1189 testing::Property(&gfx::Point::x, testing::Lt(0))))
1190 .WillOnce(testing::Return(false));
1192 WebTouchEvent touch;
1193 touch.type = WebInputEvent::TouchStart;
1195 touch.touchesLength = 3;
1196 touch.touches[0] = CreateWebTouchPoint(WebTouchPoint::StateStationary, 0, 0);
1197 touch.touches[1] = CreateWebTouchPoint(WebTouchPoint::StatePressed, 10, 10);
1198 touch.touches[2] = CreateWebTouchPoint(WebTouchPoint::StatePressed, -10, 10);
1199 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(touch));
1202 TEST_F(InputHandlerProxyTest, MultiTouchPointHitTestPositive) {
1203 // One of the touch points is on a touch-region. So the event should be sent
1204 // to the main thread.
1205 expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
1206 VERIFY_AND_RESET_MOCKS();
1208 EXPECT_CALL(mock_input_handler_,
1209 HaveTouchEventHandlersAt(
1210 testing::Property(&gfx::Point::x, testing::Eq(0))))
1211 .WillOnce(testing::Return(false));
1212 EXPECT_CALL(mock_input_handler_,
1213 HaveTouchEventHandlersAt(
1214 testing::Property(&gfx::Point::x, testing::Gt(0))))
1215 .WillOnce(testing::Return(true));
1216 // Since the second touch point hits a touch-region, there should be no
1217 // hit-testing for the third touch point.
1219 WebTouchEvent touch;
1220 touch.type = WebInputEvent::TouchStart;
1222 touch.touchesLength = 3;
1223 touch.touches[0] = CreateWebTouchPoint(WebTouchPoint::StatePressed, 0, 0);
1224 touch.touches[1] = CreateWebTouchPoint(WebTouchPoint::StatePressed, 10, 10);
1225 touch.touches[2] = CreateWebTouchPoint(WebTouchPoint::StatePressed, -10, 10);
1226 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(touch));
1230 } // namespace content