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. 4 5#include "content/renderer/input/input_handler_proxy.h" 6 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" 19 20using blink::WebActiveWheelFlingParameters; 21using blink::WebFloatPoint; 22using blink::WebFloatSize; 23using blink::WebGestureEvent; 24using blink::WebInputEvent; 25using blink::WebMouseWheelEvent; 26using blink::WebPoint; 27using blink::WebSize; 28using blink::WebTouchEvent; 29using blink::WebTouchPoint; 30 31namespace content { 32namespace { 33 34class MockInputHandler : public cc::InputHandler { 35 public: 36 MockInputHandler() {} 37 virtual ~MockInputHandler() {} 38 39 MOCK_METHOD0(PinchGestureBegin, void()); 40 MOCK_METHOD2(PinchGestureUpdate, 41 void(float magnify_delta, gfx::Point anchor)); 42 MOCK_METHOD0(PinchGestureEnd, void()); 43 44 MOCK_METHOD0(ScheduleAnimation, void()); 45 46 MOCK_METHOD2(ScrollBegin, 47 ScrollStatus(gfx::Point viewport_point, 48 cc::InputHandler::ScrollInputType type)); 49 MOCK_METHOD2(ScrollBy, 50 bool(gfx::Point viewport_point, gfx::Vector2dF scroll_delta)); 51 MOCK_METHOD2(ScrollVerticallyByPage, 52 bool(gfx::Point viewport_point, 53 cc::ScrollDirection direction)); 54 MOCK_METHOD0(ScrollEnd, void()); 55 MOCK_METHOD0(FlingScrollBegin, cc::InputHandler::ScrollStatus()); 56 57 virtual scoped_ptr<cc::SwapPromiseMonitor> 58 CreateLatencyInfoSwapPromiseMonitor(ui::LatencyInfo* latency) OVERRIDE { 59 return scoped_ptr<cc::SwapPromiseMonitor>(); 60 } 61 62 virtual void BindToClient(cc::InputHandlerClient* client) OVERRIDE {} 63 64 virtual void StartPageScaleAnimation(gfx::Vector2d target_offset, 65 bool anchor_point, 66 float page_scale, 67 base::TimeDelta duration) OVERRIDE {} 68 69 virtual void NotifyCurrentFlingVelocity(gfx::Vector2dF velocity) OVERRIDE {} 70 virtual void MouseMoveAt(gfx::Point mouse_position) OVERRIDE {} 71 72 MOCK_METHOD1(HaveTouchEventHandlersAt, 73 bool(gfx::Point point)); 74 75 virtual void SetRootLayerScrollOffsetDelegate( 76 cc::LayerScrollOffsetDelegate* root_layer_scroll_offset_delegate) 77 OVERRIDE {} 78 79 virtual void OnRootLayerDelegatedScrollOffsetChanged() OVERRIDE {} 80 81 DISALLOW_COPY_AND_ASSIGN(MockInputHandler); 82}; 83 84// A simple WebGestureCurve implementation that flings at a constant velocity 85// indefinitely. 86class FakeWebGestureCurve : public blink::WebGestureCurve { 87 public: 88 FakeWebGestureCurve(const blink::WebFloatPoint& velocity, 89 const blink::WebSize& cumulative_scroll) 90 : velocity_(velocity), cumulative_scroll_(cumulative_scroll) {} 91 92 virtual ~FakeWebGestureCurve() {} 93 94 // Returns false if curve has finished and can no longer be applied. 95 virtual bool apply(double time, blink::WebGestureCurveTarget* target) { 96 blink::WebSize displacement(velocity_.x * time, velocity_.y * time); 97 blink::WebFloatSize increment( 98 displacement.width - cumulative_scroll_.width, 99 displacement.height - cumulative_scroll_.height); 100 cumulative_scroll_ = displacement; 101 // scrollBy() could delete this curve if the animation is over, so don't 102 // touch any member variables after making that call. 103 target->scrollBy(increment); 104 return true; 105 } 106 107 private: 108 blink::WebFloatPoint velocity_; 109 blink::WebSize cumulative_scroll_; 110 111 DISALLOW_COPY_AND_ASSIGN(FakeWebGestureCurve); 112}; 113 114class MockInputHandlerProxyClient 115 : public content::InputHandlerProxyClient { 116 public: 117 MockInputHandlerProxyClient() {} 118 virtual ~MockInputHandlerProxyClient() {} 119 120 virtual void WillShutdown() OVERRIDE {} 121 122 MOCK_METHOD1(TransferActiveWheelFlingAnimation, 123 void(const WebActiveWheelFlingParameters&)); 124 125 virtual blink::WebGestureCurve* CreateFlingAnimationCurve( 126 int deviceSource, 127 const WebFloatPoint& velocity, 128 const WebSize& cumulative_scroll) OVERRIDE { 129 return new FakeWebGestureCurve(velocity, cumulative_scroll); 130 } 131 132 virtual void DidOverscroll(const cc::DidOverscrollParams& params) {} 133 134 private: 135 DISALLOW_COPY_AND_ASSIGN(MockInputHandlerProxyClient); 136}; 137 138class InputHandlerProxyTest : public testing::Test { 139 public: 140 InputHandlerProxyTest() 141 : expected_disposition_(InputHandlerProxy::DID_HANDLE) { 142 input_handler_.reset( 143 new content::InputHandlerProxy(&mock_input_handler_)); 144 input_handler_->SetClient(&mock_client_); 145 } 146 147 ~InputHandlerProxyTest() { 148 input_handler_.reset(); 149 } 150 151// This is defined as a macro because when an expectation is not satisfied the 152// only output you get 153// out of gmock is the line number that set the expectation. 154#define VERIFY_AND_RESET_MOCKS() \ 155 do { \ 156 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); \ 157 testing::Mock::VerifyAndClearExpectations(&mock_client_); \ 158 } while (false) 159 160 protected: 161 testing::StrictMock<MockInputHandler> mock_input_handler_; 162 scoped_ptr<content::InputHandlerProxy> input_handler_; 163 testing::StrictMock<MockInputHandlerProxyClient> mock_client_; 164 WebGestureEvent gesture_; 165 166 InputHandlerProxy::EventDisposition expected_disposition_; 167}; 168 169TEST_F(InputHandlerProxyTest, MouseWheelByPageMainThread) { 170 expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE; 171 WebMouseWheelEvent wheel; 172 wheel.type = WebInputEvent::MouseWheel; 173 wheel.scrollByPage = true; 174 175 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(wheel)); 176 testing::Mock::VerifyAndClearExpectations(&mock_client_); 177} 178 179TEST_F(InputHandlerProxyTest, GestureScrollStarted) { 180 // We shouldn't send any events to the widget for this gesture. 181 expected_disposition_ = InputHandlerProxy::DID_HANDLE; 182 VERIFY_AND_RESET_MOCKS(); 183 184 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) 185 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); 186 187 gesture_.type = WebInputEvent::GestureScrollBegin; 188 EXPECT_EQ(expected_disposition_,input_handler_->HandleInputEvent(gesture_)); 189 190 // The event should not be marked as handled if scrolling is not possible. 191 expected_disposition_ = InputHandlerProxy::DROP_EVENT; 192 VERIFY_AND_RESET_MOCKS(); 193 194 gesture_.type = WebInputEvent::GestureScrollUpdate; 195 gesture_.data.scrollUpdate.deltaY = 196 -40; // -Y means scroll down - i.e. in the +Y direction. 197 EXPECT_CALL(mock_input_handler_, 198 ScrollBy(testing::_, 199 testing::Property(&gfx::Vector2dF::y, testing::Gt(0)))) 200 .WillOnce(testing::Return(false)); 201 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 202 203 // Mark the event as handled if scroll happens. 204 expected_disposition_ = InputHandlerProxy::DID_HANDLE; 205 VERIFY_AND_RESET_MOCKS(); 206 207 gesture_.type = WebInputEvent::GestureScrollUpdate; 208 gesture_.data.scrollUpdate.deltaY = 209 -40; // -Y means scroll down - i.e. in the +Y direction. 210 EXPECT_CALL(mock_input_handler_, 211 ScrollBy(testing::_, 212 testing::Property(&gfx::Vector2dF::y, testing::Gt(0)))) 213 .WillOnce(testing::Return(true)); 214 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 215 216 VERIFY_AND_RESET_MOCKS(); 217 218 gesture_.type = WebInputEvent::GestureScrollEnd; 219 gesture_.data.scrollUpdate.deltaY = 0; 220 EXPECT_CALL(mock_input_handler_, ScrollEnd()); 221 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 222} 223 224TEST_F(InputHandlerProxyTest, GestureScrollOnMainThread) { 225 // We should send all events to the widget for this gesture. 226 expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE; 227 VERIFY_AND_RESET_MOCKS(); 228 229 EXPECT_CALL(mock_input_handler_, ScrollBegin(::testing::_, ::testing::_)) 230 .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread)); 231 232 gesture_.type = WebInputEvent::GestureScrollBegin; 233 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 234 235 VERIFY_AND_RESET_MOCKS(); 236 237 gesture_.type = WebInputEvent::GestureScrollUpdate; 238 gesture_.data.scrollUpdate.deltaY = 40; 239 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 240 241 VERIFY_AND_RESET_MOCKS(); 242 243 gesture_.type = WebInputEvent::GestureScrollEnd; 244 gesture_.data.scrollUpdate.deltaY = 0; 245 EXPECT_CALL(mock_input_handler_, ScrollEnd()).WillOnce(testing::Return()); 246 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 247} 248 249TEST_F(InputHandlerProxyTest, GestureScrollIgnored) { 250 // We shouldn't handle the GestureScrollBegin. 251 // Instead, we should get a DROP_EVENT result, indicating 252 // that we could determine that there's nothing that could scroll or otherwise 253 // react to this gesture sequence and thus we should drop the whole gesture 254 // sequence on the floor, except for the ScrollEnd. 255 expected_disposition_ = InputHandlerProxy::DROP_EVENT; 256 VERIFY_AND_RESET_MOCKS(); 257 258 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) 259 .WillOnce(testing::Return(cc::InputHandler::ScrollIgnored)); 260 261 gesture_.type = WebInputEvent::GestureScrollBegin; 262 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 263 264 expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE; 265 gesture_.type = WebInputEvent::GestureScrollEnd; 266 EXPECT_CALL(mock_input_handler_, ScrollEnd()).WillOnce(testing::Return()); 267 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 268} 269 270TEST_F(InputHandlerProxyTest, GesturePinch) { 271 // We shouldn't send any events to the widget for this gesture. 272 expected_disposition_ = InputHandlerProxy::DID_HANDLE; 273 VERIFY_AND_RESET_MOCKS(); 274 275 gesture_.type = WebInputEvent::GesturePinchBegin; 276 EXPECT_CALL(mock_input_handler_, PinchGestureBegin()); 277 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 278 279 VERIFY_AND_RESET_MOCKS(); 280 281 gesture_.type = WebInputEvent::GesturePinchUpdate; 282 gesture_.data.pinchUpdate.scale = 1.5; 283 gesture_.x = 7; 284 gesture_.y = 13; 285 EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(1.5, gfx::Point(7, 13))); 286 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 287 288 VERIFY_AND_RESET_MOCKS(); 289 290 gesture_.type = WebInputEvent::GesturePinchUpdate; 291 gesture_.data.pinchUpdate.scale = 0.5; 292 gesture_.x = 9; 293 gesture_.y = 6; 294 EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(.5, gfx::Point(9, 6))); 295 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 296 297 VERIFY_AND_RESET_MOCKS(); 298 299 gesture_.type = WebInputEvent::GesturePinchEnd; 300 EXPECT_CALL(mock_input_handler_, PinchGestureEnd()); 301 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 302} 303 304TEST_F(InputHandlerProxyTest, GesturePinchAfterScrollOnMainThread) { 305 // Scrolls will start by being sent to the main thread. 306 expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE; 307 VERIFY_AND_RESET_MOCKS(); 308 309 EXPECT_CALL(mock_input_handler_, ScrollBegin(::testing::_, ::testing::_)) 310 .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread)); 311 312 gesture_.type = WebInputEvent::GestureScrollBegin; 313 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 314 315 VERIFY_AND_RESET_MOCKS(); 316 317 gesture_.type = WebInputEvent::GestureScrollUpdate; 318 gesture_.data.scrollUpdate.deltaY = 40; 319 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 320 321 // However, after the pinch gesture starts, they should go to the impl 322 // thread. 323 expected_disposition_ = InputHandlerProxy::DID_HANDLE; 324 VERIFY_AND_RESET_MOCKS(); 325 326 gesture_.type = WebInputEvent::GesturePinchBegin; 327 EXPECT_CALL(mock_input_handler_, PinchGestureBegin()); 328 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 329 330 VERIFY_AND_RESET_MOCKS(); 331 332 gesture_.type = WebInputEvent::GesturePinchUpdate; 333 gesture_.data.pinchUpdate.scale = 1.5; 334 gesture_.x = 7; 335 gesture_.y = 13; 336 EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(1.5, gfx::Point(7, 13))); 337 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 338 339 VERIFY_AND_RESET_MOCKS(); 340 341 gesture_.type = WebInputEvent::GestureScrollUpdate; 342 gesture_.data.scrollUpdate.deltaY = 343 -40; // -Y means scroll down - i.e. in the +Y direction. 344 EXPECT_CALL(mock_input_handler_, 345 ScrollBy(testing::_, 346 testing::Property(&gfx::Vector2dF::y, testing::Gt(0)))) 347 .WillOnce(testing::Return(true)); 348 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 349 350 VERIFY_AND_RESET_MOCKS(); 351 352 gesture_.type = WebInputEvent::GesturePinchUpdate; 353 gesture_.data.pinchUpdate.scale = 0.5; 354 gesture_.x = 9; 355 gesture_.y = 6; 356 EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(.5, gfx::Point(9, 6))); 357 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 358 359 VERIFY_AND_RESET_MOCKS(); 360 361 gesture_.type = WebInputEvent::GesturePinchEnd; 362 EXPECT_CALL(mock_input_handler_, PinchGestureEnd()); 363 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 364 365 // After the pinch gesture ends, they should go to back to the main 366 // thread. 367 expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE; 368 VERIFY_AND_RESET_MOCKS(); 369 370 gesture_.type = WebInputEvent::GestureScrollEnd; 371 gesture_.data.scrollUpdate.deltaY = 0; 372 EXPECT_CALL(mock_input_handler_, ScrollEnd()) 373 .WillOnce(testing::Return()); 374 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 375} 376 377TEST_F(InputHandlerProxyTest, GestureFlingStartedTouchpad) { 378 // We shouldn't send any events to the widget for this gesture. 379 expected_disposition_ = InputHandlerProxy::DID_HANDLE; 380 VERIFY_AND_RESET_MOCKS(); 381 382 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) 383 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); 384 EXPECT_CALL(mock_input_handler_, ScrollEnd()); 385 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); 386 387 gesture_.type = WebInputEvent::GestureFlingStart; 388 gesture_.data.flingStart.velocityX = 10; 389 gesture_.sourceDevice = WebGestureEvent::Touchpad; 390 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 391 392 VERIFY_AND_RESET_MOCKS(); 393 394 // Verify that a GestureFlingCancel during an animation cancels it. 395 gesture_.type = WebInputEvent::GestureFlingCancel; 396 gesture_.sourceDevice = WebGestureEvent::Touchpad; 397 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 398} 399 400TEST_F(InputHandlerProxyTest, GestureFlingOnMainThreadTouchpad) { 401 // We should send all events to the widget for this gesture. 402 expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE; 403 VERIFY_AND_RESET_MOCKS(); 404 405 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) 406 .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread)); 407 408 gesture_.type = WebInputEvent::GestureFlingStart; 409 gesture_.sourceDevice = WebGestureEvent::Touchpad; 410 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 411 412 // Since we returned ScrollStatusOnMainThread from scrollBegin, ensure the 413 // input handler knows it's scrolling off the impl thread 414 ASSERT_FALSE(input_handler_->gesture_scroll_on_impl_thread_for_testing()); 415 416 VERIFY_AND_RESET_MOCKS(); 417 418 // Even if we didn't start a fling ourselves, we still need to send the cancel 419 // event to the widget. 420 gesture_.type = WebInputEvent::GestureFlingCancel; 421 gesture_.sourceDevice = WebGestureEvent::Touchpad; 422 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 423} 424 425TEST_F(InputHandlerProxyTest, GestureFlingIgnoredTouchpad) { 426 expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE; 427 VERIFY_AND_RESET_MOCKS(); 428 429 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) 430 .WillOnce(testing::Return(cc::InputHandler::ScrollIgnored)); 431 432 gesture_.type = WebInputEvent::GestureFlingStart; 433 gesture_.sourceDevice = WebGestureEvent::Touchpad; 434 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 435 436 expected_disposition_ = InputHandlerProxy::DROP_EVENT; 437 VERIFY_AND_RESET_MOCKS(); 438 439 // Since the previous fling was ignored, we should also be dropping the next 440 // fling_cancel. 441 gesture_.type = WebInputEvent::GestureFlingCancel; 442 gesture_.sourceDevice = WebGestureEvent::Touchpad; 443 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 444} 445 446TEST_F(InputHandlerProxyTest, GestureFlingAnimatesTouchpad) { 447 // We shouldn't send any events to the widget for this gesture. 448 expected_disposition_ = InputHandlerProxy::DID_HANDLE; 449 VERIFY_AND_RESET_MOCKS(); 450 451 // On the fling start, we should schedule an animation but not actually start 452 // scrolling. 453 gesture_.type = WebInputEvent::GestureFlingStart; 454 WebFloatPoint fling_delta = WebFloatPoint(1000, 0); 455 WebPoint fling_point = WebPoint(7, 13); 456 WebPoint fling_global_point = WebPoint(17, 23); 457 int modifiers = 7; 458 gesture_.data.flingStart.velocityX = fling_delta.x; 459 gesture_.data.flingStart.velocityY = fling_delta.y; 460 gesture_.sourceDevice = WebGestureEvent::Touchpad; 461 gesture_.x = fling_point.x; 462 gesture_.y = fling_point.y; 463 gesture_.globalX = fling_global_point.x; 464 gesture_.globalY = fling_global_point.y; 465 gesture_.modifiers = modifiers; 466 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); 467 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) 468 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); 469 EXPECT_CALL(mock_input_handler_, ScrollEnd()); 470 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 471 472 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); 473 // The first animate call should let us pick up an animation start time, but 474 // we shouldn't actually move anywhere just yet. The first frame after the 475 // fling start will typically include the last scroll from the gesture that 476 // lead to the scroll (either wheel or gesture scroll), so there should be no 477 // visible hitch. 478 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); 479 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) 480 .Times(0); 481 base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10); 482 input_handler_->Animate(time); 483 484 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); 485 486 // The second call should start scrolling in the -X direction. 487 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); 488 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) 489 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); 490 EXPECT_CALL(mock_input_handler_, 491 ScrollBy(testing::_, 492 testing::Property(&gfx::Vector2dF::x, testing::Lt(0)))) 493 .WillOnce(testing::Return(true)); 494 EXPECT_CALL(mock_input_handler_, ScrollEnd()); 495 time += base::TimeDelta::FromMilliseconds(100); 496 input_handler_->Animate(time); 497 498 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); 499 500 // Let's say on the third call we hit a non-scrollable region. We should abort 501 // the fling and not scroll. 502 // We also should pass the current fling parameters out to the client so the 503 // rest of the fling can be 504 // transferred to the main thread. 505 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); 506 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) 507 .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread)); 508 EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::_)).Times(0); 509 EXPECT_CALL(mock_input_handler_, ScrollEnd()).Times(0); 510 // Expected wheel fling animation parameters: 511 // *) fling_delta and fling_point should match the original GestureFlingStart 512 // event 513 // *) startTime should be 10 to match the time parameter of the first 514 // Animate() call after the GestureFlingStart 515 // *) cumulativeScroll depends on the curve, but since we've animated in the 516 // -X direction the X value should be < 0 517 EXPECT_CALL( 518 mock_client_, 519 TransferActiveWheelFlingAnimation(testing::AllOf( 520 testing::Field(&WebActiveWheelFlingParameters::delta, 521 testing::Eq(fling_delta)), 522 testing::Field(&WebActiveWheelFlingParameters::point, 523 testing::Eq(fling_point)), 524 testing::Field(&WebActiveWheelFlingParameters::globalPoint, 525 testing::Eq(fling_global_point)), 526 testing::Field(&WebActiveWheelFlingParameters::modifiers, 527 testing::Eq(modifiers)), 528 testing::Field(&WebActiveWheelFlingParameters::startTime, 529 testing::Eq(10)), 530 testing::Field(&WebActiveWheelFlingParameters::cumulativeScroll, 531 testing::Field(&WebSize::width, testing::Gt(0)))))); 532 time += base::TimeDelta::FromMilliseconds(100); 533 input_handler_->Animate(time); 534 535 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); 536 testing::Mock::VerifyAndClearExpectations(&mock_client_); 537 538 // Since we've aborted the fling, the next animation should be a no-op and 539 // should not result in another 540 // frame being requested. 541 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()).Times(0); 542 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) 543 .Times(0); 544 time += base::TimeDelta::FromMilliseconds(100); 545 input_handler_->Animate(time); 546 547 // Since we've transferred the fling to the main thread, we need to pass the 548 // next GestureFlingCancel to the main 549 // thread as well. 550 expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE; 551 gesture_.type = WebInputEvent::GestureFlingCancel; 552 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 553} 554 555TEST_F(InputHandlerProxyTest, GestureFlingTransferResetsTouchpad) { 556 // We shouldn't send any events to the widget for this gesture. 557 expected_disposition_ = InputHandlerProxy::DID_HANDLE; 558 VERIFY_AND_RESET_MOCKS(); 559 560 // Start a gesture fling in the -X direction with zero Y movement. 561 gesture_.type = WebInputEvent::GestureFlingStart; 562 WebFloatPoint fling_delta = WebFloatPoint(1000, 0); 563 WebPoint fling_point = WebPoint(7, 13); 564 WebPoint fling_global_point = WebPoint(17, 23); 565 int modifiers = 1; 566 gesture_.data.flingStart.velocityX = fling_delta.x; 567 gesture_.data.flingStart.velocityY = fling_delta.y; 568 gesture_.sourceDevice = WebGestureEvent::Touchpad; 569 gesture_.x = fling_point.x; 570 gesture_.y = fling_point.y; 571 gesture_.globalX = fling_global_point.x; 572 gesture_.globalY = fling_global_point.y; 573 gesture_.modifiers = modifiers; 574 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); 575 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) 576 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); 577 EXPECT_CALL(mock_input_handler_, ScrollEnd()); 578 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 579 580 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); 581 582 // Start the fling animation at time 10. This shouldn't actually scroll, just 583 // establish a start time. 584 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); 585 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) 586 .Times(0); 587 base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10); 588 input_handler_->Animate(time); 589 590 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); 591 592 // The second call should start scrolling in the -X direction. 593 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); 594 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) 595 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); 596 EXPECT_CALL(mock_input_handler_, 597 ScrollBy(testing::_, 598 testing::Property(&gfx::Vector2dF::x, testing::Lt(0)))) 599 .WillOnce(testing::Return(true)); 600 EXPECT_CALL(mock_input_handler_, ScrollEnd()); 601 time += base::TimeDelta::FromMilliseconds(100); 602 input_handler_->Animate(time); 603 604 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); 605 606 // Let's say on the third call we hit a non-scrollable region. We should abort 607 // the fling and not scroll. 608 // We also should pass the current fling parameters out to the client so the 609 // rest of the fling can be 610 // transferred to the main thread. 611 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); 612 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) 613 .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread)); 614 EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::_)).Times(0); 615 EXPECT_CALL(mock_input_handler_, ScrollEnd()).Times(0); 616 617 // Expected wheel fling animation parameters: 618 // *) fling_delta and fling_point should match the original GestureFlingStart 619 // event 620 // *) startTime should be 10 to match the time parameter of the first 621 // Animate() call after the GestureFlingStart 622 // *) cumulativeScroll depends on the curve, but since we've animated in the 623 // -X direction the X value should be < 0 624 EXPECT_CALL( 625 mock_client_, 626 TransferActiveWheelFlingAnimation(testing::AllOf( 627 testing::Field(&WebActiveWheelFlingParameters::delta, 628 testing::Eq(fling_delta)), 629 testing::Field(&WebActiveWheelFlingParameters::point, 630 testing::Eq(fling_point)), 631 testing::Field(&WebActiveWheelFlingParameters::globalPoint, 632 testing::Eq(fling_global_point)), 633 testing::Field(&WebActiveWheelFlingParameters::modifiers, 634 testing::Eq(modifiers)), 635 testing::Field(&WebActiveWheelFlingParameters::startTime, 636 testing::Eq(10)), 637 testing::Field(&WebActiveWheelFlingParameters::cumulativeScroll, 638 testing::Field(&WebSize::width, testing::Gt(0)))))); 639 time += base::TimeDelta::FromMilliseconds(100); 640 input_handler_->Animate(time); 641 642 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); 643 testing::Mock::VerifyAndClearExpectations(&mock_client_); 644 645 // Since we've aborted the fling, the next animation should be a no-op and 646 // should not result in another 647 // frame being requested. 648 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()).Times(0); 649 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) 650 .Times(0); 651 time += base::TimeDelta::FromMilliseconds(100); 652 input_handler_->Animate(time); 653 654 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); 655 656 // Since we've transferred the fling to the main thread, we need to pass the 657 // next GestureFlingCancel to the main 658 // thread as well. 659 expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE; 660 gesture_.type = WebInputEvent::GestureFlingCancel; 661 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 662 663 VERIFY_AND_RESET_MOCKS(); 664 input_handler_->MainThreadHasStoppedFlinging(); 665 666 // Start a second gesture fling, this time in the +Y direction with no X. 667 gesture_.type = WebInputEvent::GestureFlingStart; 668 fling_delta = WebFloatPoint(0, -1000); 669 fling_point = WebPoint(95, 87); 670 fling_global_point = WebPoint(32, 71); 671 modifiers = 2; 672 gesture_.data.flingStart.velocityX = fling_delta.x; 673 gesture_.data.flingStart.velocityY = fling_delta.y; 674 gesture_.sourceDevice = WebGestureEvent::Touchpad; 675 gesture_.x = fling_point.x; 676 gesture_.y = fling_point.y; 677 gesture_.globalX = fling_global_point.x; 678 gesture_.globalY = fling_global_point.y; 679 gesture_.modifiers = modifiers; 680 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); 681 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) 682 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); 683 EXPECT_CALL(mock_input_handler_, ScrollEnd()); 684 expected_disposition_ = InputHandlerProxy::DID_HANDLE; 685 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 686 687 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); 688 689 // Start the second fling animation at time 30. 690 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); 691 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) 692 .Times(0); 693 time = base::TimeTicks() + base::TimeDelta::FromSeconds(30); 694 input_handler_->Animate(time); 695 696 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); 697 698 // Tick the second fling once normally. 699 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); 700 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) 701 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); 702 EXPECT_CALL(mock_input_handler_, 703 ScrollBy(testing::_, 704 testing::Property(&gfx::Vector2dF::y, testing::Gt(0)))) 705 .WillOnce(testing::Return(true)); 706 EXPECT_CALL(mock_input_handler_, ScrollEnd()); 707 time += base::TimeDelta::FromMilliseconds(100); 708 input_handler_->Animate(time); 709 710 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); 711 712 // Then abort the second fling. 713 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); 714 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) 715 .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread)); 716 EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::_)).Times(0); 717 EXPECT_CALL(mock_input_handler_, ScrollEnd()).Times(0); 718 719 // We should get parameters from the second fling, nothing from the first 720 // fling should "leak". 721 EXPECT_CALL( 722 mock_client_, 723 TransferActiveWheelFlingAnimation(testing::AllOf( 724 testing::Field(&WebActiveWheelFlingParameters::delta, 725 testing::Eq(fling_delta)), 726 testing::Field(&WebActiveWheelFlingParameters::point, 727 testing::Eq(fling_point)), 728 testing::Field(&WebActiveWheelFlingParameters::globalPoint, 729 testing::Eq(fling_global_point)), 730 testing::Field(&WebActiveWheelFlingParameters::modifiers, 731 testing::Eq(modifiers)), 732 testing::Field(&WebActiveWheelFlingParameters::startTime, 733 testing::Eq(30)), 734 testing::Field(&WebActiveWheelFlingParameters::cumulativeScroll, 735 testing::Field(&WebSize::height, testing::Lt(0)))))); 736 time += base::TimeDelta::FromMilliseconds(100); 737 input_handler_->Animate(time); 738} 739 740TEST_F(InputHandlerProxyTest, GestureFlingStartedTouchscreen) { 741 // We shouldn't send any events to the widget for this gesture. 742 expected_disposition_ = InputHandlerProxy::DID_HANDLE; 743 VERIFY_AND_RESET_MOCKS(); 744 745 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) 746 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); 747 gesture_.type = WebInputEvent::GestureScrollBegin; 748 gesture_.sourceDevice = WebGestureEvent::Touchscreen; 749 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 750 751 VERIFY_AND_RESET_MOCKS(); 752 753 EXPECT_CALL(mock_input_handler_, FlingScrollBegin()) 754 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); 755 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); 756 757 gesture_.type = WebInputEvent::GestureFlingStart; 758 gesture_.data.flingStart.velocityX = 10; 759 gesture_.sourceDevice = WebGestureEvent::Touchscreen; 760 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 761 762 VERIFY_AND_RESET_MOCKS(); 763 764 EXPECT_CALL(mock_input_handler_, ScrollEnd()); 765 766 // Verify that a GestureFlingCancel during an animation cancels it. 767 gesture_.type = WebInputEvent::GestureFlingCancel; 768 gesture_.sourceDevice = WebGestureEvent::Touchscreen; 769 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 770} 771 772TEST_F(InputHandlerProxyTest, GestureFlingOnMainThreadTouchscreen) { 773 // We should send all events to the widget for this gesture. 774 expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE; 775 VERIFY_AND_RESET_MOCKS(); 776 777 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) 778 .WillOnce(testing::Return(cc::InputHandler::ScrollOnMainThread)); 779 780 gesture_.type = WebInputEvent::GestureScrollBegin; 781 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 782 783 VERIFY_AND_RESET_MOCKS(); 784 785 EXPECT_CALL(mock_input_handler_, FlingScrollBegin()).Times(0); 786 787 gesture_.type = WebInputEvent::GestureFlingStart; 788 gesture_.sourceDevice = WebGestureEvent::Touchscreen; 789 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 790 791 VERIFY_AND_RESET_MOCKS(); 792 793 // Even if we didn't start a fling ourselves, we still need to send the cancel 794 // event to the widget. 795 gesture_.type = WebInputEvent::GestureFlingCancel; 796 gesture_.sourceDevice = WebGestureEvent::Touchscreen; 797 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 798} 799 800TEST_F(InputHandlerProxyTest, GestureFlingIgnoredTouchscreen) { 801 expected_disposition_ = InputHandlerProxy::DID_HANDLE; 802 VERIFY_AND_RESET_MOCKS(); 803 804 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) 805 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); 806 807 gesture_.type = WebInputEvent::GestureScrollBegin; 808 gesture_.sourceDevice = WebGestureEvent::Touchscreen; 809 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 810 811 expected_disposition_ = InputHandlerProxy::DROP_EVENT; 812 VERIFY_AND_RESET_MOCKS(); 813 814 EXPECT_CALL(mock_input_handler_, FlingScrollBegin()) 815 .WillOnce(testing::Return(cc::InputHandler::ScrollIgnored)); 816 817 gesture_.type = WebInputEvent::GestureFlingStart; 818 gesture_.sourceDevice = WebGestureEvent::Touchscreen; 819 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 820 821 VERIFY_AND_RESET_MOCKS(); 822 823 // Even if we didn't start a fling ourselves, we still need to send the cancel 824 // event to the widget. 825 gesture_.type = WebInputEvent::GestureFlingCancel; 826 gesture_.sourceDevice = WebGestureEvent::Touchscreen; 827 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 828} 829 830TEST_F(InputHandlerProxyTest, GestureFlingAnimatesTouchscreen) { 831 // We shouldn't send any events to the widget for this gesture. 832 expected_disposition_ = InputHandlerProxy::DID_HANDLE; 833 VERIFY_AND_RESET_MOCKS(); 834 835 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) 836 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); 837 838 gesture_.type = WebInputEvent::GestureScrollBegin; 839 gesture_.sourceDevice = WebGestureEvent::Touchscreen; 840 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 841 842 VERIFY_AND_RESET_MOCKS(); 843 844 // On the fling start, we should schedule an animation but not actually start 845 // scrolling. 846 gesture_.type = WebInputEvent::GestureFlingStart; 847 WebFloatPoint fling_delta = WebFloatPoint(1000, 0); 848 WebPoint fling_point = WebPoint(7, 13); 849 WebPoint fling_global_point = WebPoint(17, 23); 850 int modifiers = 7; 851 gesture_.data.flingStart.velocityX = fling_delta.x; 852 gesture_.data.flingStart.velocityY = fling_delta.y; 853 gesture_.sourceDevice = WebGestureEvent::Touchscreen; 854 gesture_.x = fling_point.x; 855 gesture_.y = fling_point.y; 856 gesture_.globalX = fling_global_point.x; 857 gesture_.globalY = fling_global_point.y; 858 gesture_.modifiers = modifiers; 859 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); 860 EXPECT_CALL(mock_input_handler_, FlingScrollBegin()) 861 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); 862 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 863 864 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); 865 // The first animate call should let us pick up an animation start time, but 866 // we shouldn't actually move anywhere just yet. The first frame after the 867 // fling start will typically include the last scroll from the gesture that 868 // lead to the scroll (either wheel or gesture scroll), so there should be no 869 // visible hitch. 870 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); 871 base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10); 872 input_handler_->Animate(time); 873 874 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); 875 876 // The second call should start scrolling in the -X direction. 877 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); 878 EXPECT_CALL(mock_input_handler_, 879 ScrollBy(testing::_, 880 testing::Property(&gfx::Vector2dF::x, testing::Lt(0)))) 881 .WillOnce(testing::Return(true)); 882 time += base::TimeDelta::FromMilliseconds(100); 883 input_handler_->Animate(time); 884 885 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); 886 887 EXPECT_CALL(mock_input_handler_, ScrollEnd()); 888 gesture_.type = WebInputEvent::GestureFlingCancel; 889 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 890} 891 892TEST_F(InputHandlerProxyTest, GestureFlingWithValidTimestamp) { 893 // We shouldn't send any events to the widget for this gesture. 894 expected_disposition_ = InputHandlerProxy::DID_HANDLE; 895 VERIFY_AND_RESET_MOCKS(); 896 897 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) 898 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); 899 900 gesture_.type = WebInputEvent::GestureScrollBegin; 901 gesture_.sourceDevice = WebGestureEvent::Touchscreen; 902 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 903 904 VERIFY_AND_RESET_MOCKS(); 905 906 // On the fling start, we should schedule an animation but not actually start 907 // scrolling. 908 base::TimeDelta startTimeOffset = base::TimeDelta::FromMilliseconds(10); 909 gesture_.type = WebInputEvent::GestureFlingStart; 910 WebFloatPoint fling_delta = WebFloatPoint(1000, 0); 911 WebPoint fling_point = WebPoint(7, 13); 912 WebPoint fling_global_point = WebPoint(17, 23); 913 int modifiers = 7; 914 gesture_.timeStampSeconds = startTimeOffset.InSecondsF(); 915 gesture_.data.flingStart.velocityX = fling_delta.x; 916 gesture_.data.flingStart.velocityY = fling_delta.y; 917 gesture_.sourceDevice = WebGestureEvent::Touchscreen; 918 gesture_.x = fling_point.x; 919 gesture_.y = fling_point.y; 920 gesture_.globalX = fling_global_point.x; 921 gesture_.globalY = fling_global_point.y; 922 gesture_.modifiers = modifiers; 923 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); 924 EXPECT_CALL(mock_input_handler_, FlingScrollBegin()) 925 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); 926 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 927 928 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); 929 // With a valid time stamp, the first animate call should skip start time 930 // initialization and immediately begin scroll update production. This reduces 931 // the likelihood of a hitch between the scroll preceding the fling and 932 // the first scroll generated by the fling. 933 // Scrolling should start in the -X direction. 934 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); 935 EXPECT_CALL(mock_input_handler_, 936 ScrollBy(testing::_, 937 testing::Property(&gfx::Vector2dF::x, testing::Lt(0)))) 938 .WillOnce(testing::Return(true)); 939 base::TimeTicks time = base::TimeTicks() + 2 * startTimeOffset; 940 input_handler_->Animate(time); 941 942 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); 943 944 EXPECT_CALL(mock_input_handler_, ScrollEnd()); 945 gesture_.type = WebInputEvent::GestureFlingCancel; 946 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 947} 948 949TEST_F(InputHandlerProxyTest, 950 GestureScrollOnImplThreadFlagClearedAfterFling) { 951 // We shouldn't send any events to the widget for this gesture. 952 expected_disposition_ = InputHandlerProxy::DID_HANDLE; 953 VERIFY_AND_RESET_MOCKS(); 954 955 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) 956 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); 957 958 gesture_.type = WebInputEvent::GestureScrollBegin; 959 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 960 961 // After sending a GestureScrollBegin, the member variable 962 // |gesture_scroll_on_impl_thread_| should be true. 963 EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing()); 964 965 expected_disposition_ = InputHandlerProxy::DID_HANDLE; 966 VERIFY_AND_RESET_MOCKS(); 967 968 // On the fling start, we should schedule an animation but not actually start 969 // scrolling. 970 gesture_.type = WebInputEvent::GestureFlingStart; 971 WebFloatPoint fling_delta = WebFloatPoint(1000, 0); 972 WebPoint fling_point = WebPoint(7, 13); 973 WebPoint fling_global_point = WebPoint(17, 23); 974 int modifiers = 7; 975 gesture_.data.flingStart.velocityX = fling_delta.x; 976 gesture_.data.flingStart.velocityY = fling_delta.y; 977 gesture_.sourceDevice = WebGestureEvent::Touchscreen; 978 gesture_.x = fling_point.x; 979 gesture_.y = fling_point.y; 980 gesture_.globalX = fling_global_point.x; 981 gesture_.globalY = fling_global_point.y; 982 gesture_.modifiers = modifiers; 983 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); 984 EXPECT_CALL(mock_input_handler_, FlingScrollBegin()) 985 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); 986 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 987 988 // |gesture_scroll_on_impl_thread_| should still be true after 989 // a GestureFlingStart is sent. 990 EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing()); 991 992 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); 993 // The first animate call should let us pick up an animation start time, but 994 // we shouldn't actually move anywhere just yet. The first frame after the 995 // fling start will typically include the last scroll from the gesture that 996 // lead to the scroll (either wheel or gesture scroll), so there should be no 997 // visible hitch. 998 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); 999 base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10); 1000 input_handler_->Animate(time); 1001 1002 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); 1003 1004 // The second call should start scrolling in the -X direction. 1005 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); 1006 EXPECT_CALL(mock_input_handler_, 1007 ScrollBy(testing::_, 1008 testing::Property(&gfx::Vector2dF::x, testing::Lt(0)))) 1009 .WillOnce(testing::Return(true)); 1010 time += base::TimeDelta::FromMilliseconds(100); 1011 input_handler_->Animate(time); 1012 1013 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); 1014 1015 EXPECT_CALL(mock_input_handler_, ScrollEnd()); 1016 gesture_.type = WebInputEvent::GestureFlingCancel; 1017 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 1018 1019 // |gesture_scroll_on_impl_thread_| should be false once 1020 // the fling has finished (note no GestureScrollEnd has been sent). 1021 EXPECT_TRUE(!input_handler_->gesture_scroll_on_impl_thread_for_testing()); 1022} 1023 1024TEST_F(InputHandlerProxyTest, GestureFlingStopsAtContentEdge) { 1025 // We shouldn't send any events to the widget for this gesture. 1026 expected_disposition_ = InputHandlerProxy::DID_HANDLE; 1027 VERIFY_AND_RESET_MOCKS(); 1028 1029 // On the fling start, we should schedule an animation but not actually start 1030 // scrolling. 1031 gesture_.type = WebInputEvent::GestureFlingStart; 1032 WebFloatPoint fling_delta = WebFloatPoint(1000, 1000); 1033 gesture_.data.flingStart.velocityX = fling_delta.x; 1034 gesture_.data.flingStart.velocityY = fling_delta.y; 1035 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); 1036 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) 1037 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); 1038 EXPECT_CALL(mock_input_handler_, ScrollEnd()); 1039 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); 1040 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); 1041 1042 // The first animate doesn't cause any scrolling. 1043 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); 1044 base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10); 1045 input_handler_->Animate(time); 1046 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); 1047 1048 // The second animate starts scrolling in the positive X and Y directions. 1049 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); 1050 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) 1051 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); 1052 EXPECT_CALL(mock_input_handler_, 1053 ScrollBy(testing::_, 1054 testing::Property(&gfx::Vector2dF::y, testing::Lt(0)))) 1055 .WillOnce(testing::Return(true)); 1056 EXPECT_CALL(mock_input_handler_, ScrollEnd()); 1057 time += base::TimeDelta::FromMilliseconds(100); 1058 input_handler_->Animate(time); 1059 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); 1060 1061 // Simulate hitting the bottom content edge. 1062 cc::DidOverscrollParams overscroll_params; 1063 overscroll_params.accumulated_overscroll = gfx::Vector2dF(0, 100); 1064 overscroll_params.current_fling_velocity = gfx::Vector2dF(0, 10); 1065 input_handler_->DidOverscroll(overscroll_params); 1066 1067 // The next call to animate will no longer scroll vertically. 1068 EXPECT_CALL(mock_input_handler_, ScheduleAnimation()); 1069 EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) 1070 .WillOnce(testing::Return(cc::InputHandler::ScrollStarted)); 1071 EXPECT_CALL(mock_input_handler_, 1072 ScrollBy(testing::_, 1073 testing::Property(&gfx::Vector2dF::y, testing::Eq(0)))) 1074 .WillOnce(testing::Return(true)); 1075 EXPECT_CALL(mock_input_handler_, ScrollEnd()); 1076 time += base::TimeDelta::FromMilliseconds(100); 1077 input_handler_->Animate(time); 1078 testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); 1079} 1080 1081TEST_F(InputHandlerProxyTest, MultiTouchPointHitTestNegative) { 1082 // None of the three touch points fall in the touch region. So the event 1083 // should be dropped. 1084 expected_disposition_ = InputHandlerProxy::DROP_EVENT; 1085 VERIFY_AND_RESET_MOCKS(); 1086 1087 EXPECT_CALL(mock_input_handler_, 1088 HaveTouchEventHandlersAt( 1089 testing::Property(&gfx::Point::x, testing::Gt(0)))) 1090 .WillOnce(testing::Return(false)); 1091 EXPECT_CALL(mock_input_handler_, 1092 HaveTouchEventHandlersAt( 1093 testing::Property(&gfx::Point::x, testing::Lt(0)))) 1094 .WillOnce(testing::Return(false)); 1095 1096 WebTouchEvent touch; 1097 touch.type = WebInputEvent::TouchStart; 1098 1099 touch.touchesLength = 3; 1100 touch.touches[0].state = WebTouchPoint::StateStationary; 1101 touch.touches[0].screenPosition = WebPoint(); 1102 touch.touches[0].position = WebPoint(); 1103 1104 touch.touches[1].state = WebTouchPoint::StatePressed; 1105 touch.touches[1].screenPosition = WebPoint(10, 10); 1106 touch.touches[1].position = WebPoint(10, 10); 1107 1108 touch.touches[2].state = WebTouchPoint::StatePressed; 1109 touch.touches[2].screenPosition = WebPoint(-10, 10); 1110 touch.touches[2].position = WebPoint(-10, 10); 1111 1112 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(touch)); 1113} 1114 1115TEST_F(InputHandlerProxyTest, MultiTouchPointHitTestPositive) { 1116 // One of the touch points is on a touch-region. So the event should be sent 1117 // to the main thread. 1118 expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE; 1119 VERIFY_AND_RESET_MOCKS(); 1120 1121 EXPECT_CALL(mock_input_handler_, 1122 HaveTouchEventHandlersAt( 1123 testing::Property(&gfx::Point::x, testing::Eq(0)))) 1124 .WillOnce(testing::Return(false)); 1125 EXPECT_CALL(mock_input_handler_, 1126 HaveTouchEventHandlersAt( 1127 testing::Property(&gfx::Point::x, testing::Gt(0)))) 1128 .WillOnce(testing::Return(true)); 1129 // Since the second touch point hits a touch-region, there should be no 1130 // hit-testing for the third touch point. 1131 1132 WebTouchEvent touch; 1133 touch.type = WebInputEvent::TouchStart; 1134 1135 touch.touchesLength = 3; 1136 touch.touches[0].state = WebTouchPoint::StatePressed; 1137 touch.touches[0].screenPosition = WebPoint(); 1138 touch.touches[0].position = WebPoint(); 1139 1140 touch.touches[1].state = WebTouchPoint::StatePressed; 1141 touch.touches[1].screenPosition = WebPoint(10, 10); 1142 touch.touches[1].position = WebPoint(10, 10); 1143 1144 touch.touches[2].state = WebTouchPoint::StatePressed; 1145 touch.touches[2].screenPosition = WebPoint(-10, 10); 1146 touch.touches[2].position = WebPoint(-10, 10); 1147 1148 EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(touch)); 1149} 1150 1151} // namespace 1152} // namespace content 1153