OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/input/input_handler_proxy.h" | 5 #include "content/renderer/input/input_handler_proxy.h" |
6 | 6 |
7 #include "base/auto_reset.h" | 7 #include "base/auto_reset.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
329 *static_cast<const WebGestureEvent*>(&event); | 329 *static_cast<const WebGestureEvent*>(&event); |
330 input_handler_->PinchGestureUpdate( | 330 input_handler_->PinchGestureUpdate( |
331 gesture_event.data.pinchUpdate.scale, | 331 gesture_event.data.pinchUpdate.scale, |
332 gfx::Point(gesture_event.x, gesture_event.y)); | 332 gfx::Point(gesture_event.x, gesture_event.y)); |
333 return DID_HANDLE; | 333 return DID_HANDLE; |
334 } else if (event.type == WebInputEvent::GestureFlingStart) { | 334 } else if (event.type == WebInputEvent::GestureFlingStart) { |
335 const WebGestureEvent& gesture_event = | 335 const WebGestureEvent& gesture_event = |
336 *static_cast<const WebGestureEvent*>(&event); | 336 *static_cast<const WebGestureEvent*>(&event); |
337 return HandleGestureFling(gesture_event); | 337 return HandleGestureFling(gesture_event); |
338 } else if (event.type == WebInputEvent::GestureFlingCancel) { | 338 } else if (event.type == WebInputEvent::GestureFlingCancel) { |
339 if (CancelCurrentFling(true)) | 339 if (CancelCurrentFling()) |
340 return DID_HANDLE; | 340 return DID_HANDLE; |
341 else if (!fling_may_be_active_on_main_thread_) | 341 else if (!fling_may_be_active_on_main_thread_) |
342 return DROP_EVENT; | 342 return DROP_EVENT; |
343 } else if (event.type == WebInputEvent::TouchStart) { | 343 } else if (event.type == WebInputEvent::TouchStart) { |
344 const WebTouchEvent& touch_event = | 344 const WebTouchEvent& touch_event = |
345 *static_cast<const WebTouchEvent*>(&event); | 345 *static_cast<const WebTouchEvent*>(&event); |
346 for (size_t i = 0; i < touch_event.touchesLength; ++i) { | 346 for (size_t i = 0; i < touch_event.touchesLength; ++i) { |
347 if (touch_event.touches[i].state != WebTouchPoint::StatePressed) | 347 if (touch_event.touches[i].state != WebTouchPoint::StatePressed) |
348 continue; | 348 continue; |
349 if (input_handler_->HaveTouchEventHandlersAt( | 349 if (input_handler_->HaveTouchEventHandlersAt( |
350 gfx::Point(touch_event.touches[i].position.x, | 350 gfx::Point(touch_event.touches[i].position.x, |
351 touch_event.touches[i].position.y))) { | 351 touch_event.touches[i].position.y))) { |
352 return DID_NOT_HANDLE; | 352 return DID_NOT_HANDLE; |
353 } | 353 } |
354 } | 354 } |
355 return DROP_EVENT; | 355 return DROP_EVENT; |
356 } else if (WebInputEvent::isKeyboardEventType(event.type)) { | 356 } else if (WebInputEvent::isKeyboardEventType(event.type)) { |
357 // Only call |CancelCurrentFling()| if a fling was active, as it will | 357 // Only call |CancelCurrentFling()| if a fling was active, as it will |
358 // otherwise disrupt an in-progress touch scroll. | 358 // otherwise disrupt an in-progress touch scroll. |
359 if (fling_curve_) | 359 if (fling_curve_) |
360 CancelCurrentFling(true); | 360 CancelCurrentFling(); |
361 } else if (event.type == WebInputEvent::MouseMove) { | 361 } else if (event.type == WebInputEvent::MouseMove) { |
362 const WebMouseEvent& mouse_event = | 362 const WebMouseEvent& mouse_event = |
363 *static_cast<const WebMouseEvent*>(&event); | 363 *static_cast<const WebMouseEvent*>(&event); |
364 // TODO(tony): Ignore when mouse buttons are down? | 364 // TODO(tony): Ignore when mouse buttons are down? |
365 // TODO(davemoore): This should never happen, but bug #326635 showed some | 365 // TODO(davemoore): This should never happen, but bug #326635 showed some |
366 // surprising crashes. | 366 // surprising crashes. |
367 CHECK(input_handler_); | 367 CHECK(input_handler_); |
368 input_handler_->MouseMoveAt(gfx::Point(mouse_event.x, mouse_event.y)); | 368 input_handler_->MouseMoveAt(gfx::Point(mouse_event.x, mouse_event.y)); |
369 } | 369 } |
370 | 370 |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
478 return true; | 478 return true; |
479 } | 479 } |
480 | 480 |
481 // A fling is either inactive or is "free spinning", i.e., has yet to be | 481 // A fling is either inactive or is "free spinning", i.e., has yet to be |
482 // interrupted by a touch gesture, in which case there is nothing to filter. | 482 // interrupted by a touch gesture, in which case there is nothing to filter. |
483 if (!deferred_fling_cancel_time_seconds_) | 483 if (!deferred_fling_cancel_time_seconds_) |
484 return false; | 484 return false; |
485 | 485 |
486 // Gestures from a different source should immediately interrupt the fling. | 486 // Gestures from a different source should immediately interrupt the fling. |
487 if (gesture_event.sourceDevice != fling_parameters_.sourceDevice) { | 487 if (gesture_event.sourceDevice != fling_parameters_.sourceDevice) { |
488 FlingBoostCancelAndResumeScrollingIfNecessary(); | 488 CancelCurrentFling(); |
489 return false; | 489 return false; |
490 } | 490 } |
491 | 491 |
492 switch (gesture_event.type) { | 492 switch (gesture_event.type) { |
493 case WebInputEvent::GestureTapCancel: | 493 case WebInputEvent::GestureTapCancel: |
494 case WebInputEvent::GestureTapDown: | 494 case WebInputEvent::GestureTapDown: |
495 return false; | 495 return false; |
496 | 496 |
497 case WebInputEvent::GestureScrollBegin: | 497 case WebInputEvent::GestureScrollBegin: |
498 if (!input_handler_->IsCurrentlyScrollingLayerAt( | 498 if (!input_handler_->IsCurrentlyScrollingLayerAt( |
499 gfx::Point(gesture_event.x, gesture_event.y), | 499 gfx::Point(gesture_event.x, gesture_event.y), |
500 fling_parameters_.sourceDevice == blink::WebGestureDeviceTouchpad | 500 fling_parameters_.sourceDevice == blink::WebGestureDeviceTouchpad |
501 ? cc::InputHandler::NonBubblingGesture | 501 ? cc::InputHandler::NonBubblingGesture |
502 : cc::InputHandler::Gesture)) { | 502 : cc::InputHandler::Gesture)) { |
503 CancelCurrentFling(true); | 503 CancelCurrentFling(); |
504 return false; | 504 return false; |
505 } | 505 } |
506 | 506 |
507 // TODO(jdduke): Use |gesture_event.data.scrollBegin.delta{X,Y}Hint| to | 507 // TODO(jdduke): Use |gesture_event.data.scrollBegin.delta{X,Y}Hint| to |
508 // determine if the ScrollBegin should immediately cancel the fling. | 508 // determine if the ScrollBegin should immediately cancel the fling. |
509 FlingBoostExtend(gesture_event); | 509 ExtendBoostedFlingTimeout(gesture_event); |
510 return true; | 510 return true; |
511 | 511 |
512 case WebInputEvent::GestureScrollUpdate: { | 512 case WebInputEvent::GestureScrollUpdate: { |
513 const double time_since_last_boost_event = | 513 const double time_since_last_boost_event = |
514 event.timeStampSeconds - last_fling_boost_event_.timeStampSeconds; | 514 event.timeStampSeconds - last_fling_boost_event_.timeStampSeconds; |
515 if (ShouldSuppressScrollForFlingBoosting(current_fling_velocity_, | 515 if (ShouldSuppressScrollForFlingBoosting(current_fling_velocity_, |
516 gesture_event, | 516 gesture_event, |
517 time_since_last_boost_event)) { | 517 time_since_last_boost_event)) { |
518 FlingBoostExtend(gesture_event); | 518 ExtendBoostedFlingTimeout(gesture_event); |
519 return true; | 519 return true; |
520 } | 520 } |
521 | 521 |
522 FlingBoostCancelAndResumeScrollingIfNecessary(); | 522 CancelCurrentFling(); |
523 return false; | 523 return false; |
524 } | 524 } |
525 | 525 |
526 case WebInputEvent::GestureScrollEnd: | 526 case WebInputEvent::GestureScrollEnd: |
527 CancelCurrentFling(true); | 527 // Clear the last fling boost event *prior* to fling cancellation, |
| 528 // preventing insertion of a synthetic GestureScrollBegin. |
| 529 last_fling_boost_event_ = WebGestureEvent(); |
| 530 CancelCurrentFling(); |
528 return true; | 531 return true; |
529 | 532 |
530 case WebInputEvent::GestureFlingStart: { | 533 case WebInputEvent::GestureFlingStart: { |
531 DCHECK_EQ(fling_parameters_.sourceDevice, gesture_event.sourceDevice); | 534 DCHECK_EQ(fling_parameters_.sourceDevice, gesture_event.sourceDevice); |
532 | 535 |
533 bool fling_boosted = | 536 bool fling_boosted = |
534 fling_parameters_.modifiers == gesture_event.modifiers && | 537 fling_parameters_.modifiers == gesture_event.modifiers && |
535 ShouldBoostFling(current_fling_velocity_, gesture_event); | 538 ShouldBoostFling(current_fling_velocity_, gesture_event); |
536 | 539 |
537 gfx::Vector2dF new_fling_velocity( | 540 gfx::Vector2dF new_fling_velocity( |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
569 // The client expects balanced calls between a consumed GestureFlingStart | 572 // The client expects balanced calls between a consumed GestureFlingStart |
570 // and |DidStopFlinging()|. TODO(jdduke): Provide a count parameter to | 573 // and |DidStopFlinging()|. TODO(jdduke): Provide a count parameter to |
571 // |DidStopFlinging()| and only send after the accumulated fling ends. | 574 // |DidStopFlinging()| and only send after the accumulated fling ends. |
572 client_->DidStopFlinging(); | 575 client_->DidStopFlinging(); |
573 return true; | 576 return true; |
574 } | 577 } |
575 | 578 |
576 default: | 579 default: |
577 // All other types of gestures (taps, presses, etc...) will complete the | 580 // All other types of gestures (taps, presses, etc...) will complete the |
578 // deferred fling cancellation. | 581 // deferred fling cancellation. |
579 FlingBoostCancelAndResumeScrollingIfNecessary(); | 582 CancelCurrentFling(); |
580 return false; | 583 return false; |
581 } | 584 } |
582 } | 585 } |
583 | 586 |
584 void InputHandlerProxy::FlingBoostExtend(const blink::WebGestureEvent& event) { | 587 void InputHandlerProxy::ExtendBoostedFlingTimeout( |
585 TRACE_EVENT_INSTANT0( | 588 const blink::WebGestureEvent& event) { |
586 "input", "InputHandlerProxy::FlingBoostExtend", TRACE_EVENT_SCOPE_THREAD); | 589 TRACE_EVENT_INSTANT0("input", |
| 590 "InputHandlerProxy::ExtendBoostedFlingTimeout", |
| 591 TRACE_EVENT_SCOPE_THREAD); |
587 deferred_fling_cancel_time_seconds_ = | 592 deferred_fling_cancel_time_seconds_ = |
588 event.timeStampSeconds + kFlingBoostTimeoutDelaySeconds; | 593 event.timeStampSeconds + kFlingBoostTimeoutDelaySeconds; |
589 last_fling_boost_event_ = event; | 594 last_fling_boost_event_ = event; |
590 } | 595 } |
591 | 596 |
592 void InputHandlerProxy::FlingBoostCancelAndResumeScrollingIfNecessary() { | |
593 TRACE_EVENT_INSTANT0( | |
594 "input", "InputHandlerProxy::FlingBoostCancel", TRACE_EVENT_SCOPE_THREAD); | |
595 DCHECK(deferred_fling_cancel_time_seconds_); | |
596 | |
597 // Note: |last_fling_boost_event_| is cleared by |CancelCurrentFling()|. | |
598 WebGestureEvent last_fling_boost_event = last_fling_boost_event_; | |
599 | |
600 CancelCurrentFling(true); | |
601 | |
602 if (last_fling_boost_event.type == WebInputEvent::GestureScrollBegin || | |
603 last_fling_boost_event.type == WebInputEvent::GestureScrollUpdate) { | |
604 // Synthesize a GestureScrollBegin, as the original was suppressed. | |
605 HandleInputEvent(ObtainGestureScrollBegin(last_fling_boost_event)); | |
606 } | |
607 } | |
608 | |
609 void InputHandlerProxy::Animate(base::TimeTicks time) { | 597 void InputHandlerProxy::Animate(base::TimeTicks time) { |
610 if (!fling_curve_) | 598 if (!fling_curve_) |
611 return; | 599 return; |
612 | 600 |
613 double monotonic_time_sec = InSecondsF(time); | 601 double monotonic_time_sec = InSecondsF(time); |
614 | 602 |
615 if (deferred_fling_cancel_time_seconds_ && | 603 if (deferred_fling_cancel_time_seconds_ && |
616 monotonic_time_sec > deferred_fling_cancel_time_seconds_) { | 604 monotonic_time_sec > deferred_fling_cancel_time_seconds_) { |
617 FlingBoostCancelAndResumeScrollingIfNecessary(); | 605 CancelCurrentFling(); |
618 return; | 606 return; |
619 } | 607 } |
620 | 608 |
621 if (!has_fling_animation_started_) { | 609 if (!has_fling_animation_started_) { |
622 has_fling_animation_started_ = true; | 610 has_fling_animation_started_ = true; |
623 // Guard against invalid, future or sufficiently stale start times, as there | 611 // Guard against invalid, future or sufficiently stale start times, as there |
624 // are no guarantees fling event and animation timestamps are compatible. | 612 // are no guarantees fling event and animation timestamps are compatible. |
625 if (!fling_parameters_.startTime || | 613 if (!fling_parameters_.startTime || |
626 monotonic_time_sec <= fling_parameters_.startTime || | 614 monotonic_time_sec <= fling_parameters_.startTime || |
627 monotonic_time_sec >= fling_parameters_.startTime + | 615 monotonic_time_sec >= fling_parameters_.startTime + |
(...skipping 10 matching lines...) Expand all Loading... |
638 | 626 |
639 if (disallow_vertical_fling_scroll_ && disallow_horizontal_fling_scroll_) | 627 if (disallow_vertical_fling_scroll_ && disallow_horizontal_fling_scroll_) |
640 fling_is_active = false; | 628 fling_is_active = false; |
641 | 629 |
642 if (fling_is_active) { | 630 if (fling_is_active) { |
643 input_handler_->SetNeedsAnimate(); | 631 input_handler_->SetNeedsAnimate(); |
644 } else { | 632 } else { |
645 TRACE_EVENT_INSTANT0("input", | 633 TRACE_EVENT_INSTANT0("input", |
646 "InputHandlerProxy::animate::flingOver", | 634 "InputHandlerProxy::animate::flingOver", |
647 TRACE_EVENT_SCOPE_THREAD); | 635 TRACE_EVENT_SCOPE_THREAD); |
648 CancelCurrentFling(true); | 636 CancelCurrentFling(); |
649 } | 637 } |
650 } | 638 } |
651 | 639 |
652 void InputHandlerProxy::MainThreadHasStoppedFlinging() { | 640 void InputHandlerProxy::MainThreadHasStoppedFlinging() { |
653 fling_may_be_active_on_main_thread_ = false; | 641 fling_may_be_active_on_main_thread_ = false; |
654 client_->DidStopFlinging(); | 642 client_->DidStopFlinging(); |
655 } | 643 } |
656 | 644 |
657 void InputHandlerProxy::DidOverscroll( | 645 void InputHandlerProxy::DidOverscroll( |
658 const gfx::Vector2dF& accumulated_overscroll, | 646 const gfx::Vector2dF& accumulated_overscroll, |
(...skipping 19 matching lines...) Expand all Loading... |
678 std::abs(params.accumulated_overscroll.x()) >= | 666 std::abs(params.accumulated_overscroll.x()) >= |
679 kFlingOverscrollThreshold; | 667 kFlingOverscrollThreshold; |
680 disallow_vertical_fling_scroll_ |= | 668 disallow_vertical_fling_scroll_ |= |
681 std::abs(params.accumulated_overscroll.y()) >= | 669 std::abs(params.accumulated_overscroll.y()) >= |
682 kFlingOverscrollThreshold; | 670 kFlingOverscrollThreshold; |
683 } | 671 } |
684 | 672 |
685 client_->DidOverscroll(params); | 673 client_->DidOverscroll(params); |
686 } | 674 } |
687 | 675 |
688 bool InputHandlerProxy::CancelCurrentFling( | 676 bool InputHandlerProxy::CancelCurrentFling() { |
689 bool send_fling_stopped_notification) { | 677 if (CancelCurrentFlingWithoutNotifyingClient()) { |
| 678 client_->DidStopFlinging(); |
| 679 return true; |
| 680 } |
| 681 return false; |
| 682 } |
| 683 |
| 684 bool InputHandlerProxy::CancelCurrentFlingWithoutNotifyingClient() { |
690 bool had_fling_animation = fling_curve_; | 685 bool had_fling_animation = fling_curve_; |
691 if (had_fling_animation && | 686 if (had_fling_animation && |
692 fling_parameters_.sourceDevice == blink::WebGestureDeviceTouchscreen) { | 687 fling_parameters_.sourceDevice == blink::WebGestureDeviceTouchscreen) { |
693 input_handler_->ScrollEnd(); | 688 input_handler_->ScrollEnd(); |
694 TRACE_EVENT_ASYNC_END0( | 689 TRACE_EVENT_ASYNC_END0( |
695 "input", | 690 "input", |
696 "InputHandlerProxy::HandleGestureFling::started", | 691 "InputHandlerProxy::HandleGestureFling::started", |
697 this); | 692 this); |
698 } | 693 } |
699 | 694 |
700 TRACE_EVENT_INSTANT1("input", | 695 TRACE_EVENT_INSTANT1("input", |
701 "InputHandlerProxy::CancelCurrentFling", | 696 "InputHandlerProxy::CancelCurrentFling", |
702 TRACE_EVENT_SCOPE_THREAD, | 697 TRACE_EVENT_SCOPE_THREAD, |
703 "had_fling_animation", | 698 "had_fling_animation", |
704 had_fling_animation); | 699 had_fling_animation); |
705 fling_curve_.reset(); | 700 fling_curve_.reset(); |
706 has_fling_animation_started_ = false; | 701 has_fling_animation_started_ = false; |
707 gesture_scroll_on_impl_thread_ = false; | 702 gesture_scroll_on_impl_thread_ = false; |
708 current_fling_velocity_ = gfx::Vector2dF(); | 703 current_fling_velocity_ = gfx::Vector2dF(); |
709 fling_parameters_ = blink::WebActiveWheelFlingParameters(); | 704 fling_parameters_ = blink::WebActiveWheelFlingParameters(); |
710 deferred_fling_cancel_time_seconds_ = 0; | 705 |
711 last_fling_boost_event_ = WebGestureEvent(); | 706 if (deferred_fling_cancel_time_seconds_) { |
712 if (send_fling_stopped_notification && had_fling_animation) | 707 deferred_fling_cancel_time_seconds_ = 0; |
713 client_->DidStopFlinging(); | 708 |
| 709 WebGestureEvent last_fling_boost_event = last_fling_boost_event_; |
| 710 last_fling_boost_event_ = WebGestureEvent(); |
| 711 if (last_fling_boost_event.type == WebInputEvent::GestureScrollBegin || |
| 712 last_fling_boost_event.type == WebInputEvent::GestureScrollUpdate) { |
| 713 // Synthesize a GestureScrollBegin, as the original was suppressed. |
| 714 HandleInputEvent(ObtainGestureScrollBegin(last_fling_boost_event)); |
| 715 } |
| 716 } |
| 717 |
714 return had_fling_animation; | 718 return had_fling_animation; |
715 } | 719 } |
716 | 720 |
717 bool InputHandlerProxy::TouchpadFlingScroll( | 721 bool InputHandlerProxy::TouchpadFlingScroll( |
718 const WebFloatSize& increment) { | 722 const WebFloatSize& increment) { |
719 WebMouseWheelEvent synthetic_wheel; | 723 WebMouseWheelEvent synthetic_wheel; |
720 synthetic_wheel.type = WebInputEvent::MouseWheel; | 724 synthetic_wheel.type = WebInputEvent::MouseWheel; |
721 synthetic_wheel.deltaX = increment.width; | 725 synthetic_wheel.deltaX = increment.width; |
722 synthetic_wheel.deltaY = increment.height; | 726 synthetic_wheel.deltaY = increment.height; |
723 synthetic_wheel.hasPreciseScrollingDeltas = true; | 727 synthetic_wheel.hasPreciseScrollingDeltas = true; |
(...skipping 15 matching lines...) Expand all Loading... |
739 "InputHandlerProxy::scrollBy::AbortFling", | 743 "InputHandlerProxy::scrollBy::AbortFling", |
740 TRACE_EVENT_SCOPE_THREAD); | 744 TRACE_EVENT_SCOPE_THREAD); |
741 // If we got a DID_NOT_HANDLE, that means we need to deliver wheels on the | 745 // If we got a DID_NOT_HANDLE, that means we need to deliver wheels on the |
742 // main thread. In this case we need to schedule a commit and transfer the | 746 // main thread. In this case we need to schedule a commit and transfer the |
743 // fling curve over to the main thread and run the rest of the wheels from | 747 // fling curve over to the main thread and run the rest of the wheels from |
744 // there. This can happen when flinging a page that contains a scrollable | 748 // there. This can happen when flinging a page that contains a scrollable |
745 // subarea that we can't scroll on the thread if the fling starts outside | 749 // subarea that we can't scroll on the thread if the fling starts outside |
746 // the subarea but then is flung "under" the pointer. | 750 // the subarea but then is flung "under" the pointer. |
747 client_->TransferActiveWheelFlingAnimation(fling_parameters_); | 751 client_->TransferActiveWheelFlingAnimation(fling_parameters_); |
748 fling_may_be_active_on_main_thread_ = true; | 752 fling_may_be_active_on_main_thread_ = true; |
749 CancelCurrentFling(false); | 753 CancelCurrentFlingWithoutNotifyingClient(); |
750 break; | 754 break; |
751 } | 755 } |
752 | 756 |
753 return false; | 757 return false; |
754 } | 758 } |
755 | 759 |
756 bool InputHandlerProxy::scrollBy(const WebFloatSize& increment, | 760 bool InputHandlerProxy::scrollBy(const WebFloatSize& increment, |
757 const WebFloatSize& velocity) { | 761 const WebFloatSize& velocity) { |
758 WebFloatSize clipped_increment; | 762 WebFloatSize clipped_increment; |
759 WebFloatSize clipped_velocity; | 763 WebFloatSize clipped_velocity; |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
802 // trigger a scroll, e.g., with a trivial time delta between fling updates. | 806 // trigger a scroll, e.g., with a trivial time delta between fling updates. |
803 // Return true in this case to prevent early fling termination. | 807 // Return true in this case to prevent early fling termination. |
804 if (std::abs(clipped_increment.width) < kScrollEpsilon && | 808 if (std::abs(clipped_increment.width) < kScrollEpsilon && |
805 std::abs(clipped_increment.height) < kScrollEpsilon) | 809 std::abs(clipped_increment.height) < kScrollEpsilon) |
806 return true; | 810 return true; |
807 | 811 |
808 return did_scroll; | 812 return did_scroll; |
809 } | 813 } |
810 | 814 |
811 } // namespace content | 815 } // namespace content |
OLD | NEW |