diff options
author | danakj <danakj@chromium.org> | 2015-09-09 14:36:16 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-09-09 21:37:01 +0000 |
commit | e9f830c3b57371a0b3d090f48be2545a58eba3d6 (patch) | |
tree | 273dd1a308ceeb80d66cc96fab9d6e7ebdfa0f97 | |
parent | a2c9f2ae93b9920f1ddeb01042e9b1a431106e71 (diff) | |
download | chromium_src-e9f830c3b57371a0b3d090f48be2545a58eba3d6.zip chromium_src-e9f830c3b57371a0b3d090f48be2545a58eba3d6.tar.gz chromium_src-e9f830c3b57371a0b3d090f48be2545a58eba3d6.tar.bz2 |
Move the AnimateInput paths for WebView around to not path through cc.
They don't need to go through cc, so let's not and this lets cc reason
about when/how things happen better.
Adds 2 new interfaces:
- SynchronousInputHandlerProxy. A limited view of the InputHandlerProxy
given out to WebView to control animating timing. It lets WebView call
SynchronouslyAnimate() to do animations. And if cc tried to also animate,
we'd hit a DCHECK.
- SynchronousInputHandler. An interface given to the InputHandlerProxy
as an alternate place to handle requests for animation. When it's
present animate requests go there instead of the usual InputHandler.
R=boliu, enne, hush, jdduke, sievers
BUG=522658
CQ_INCLUDE_TRYBOTS=tryserver.blink:linux_blink_rel
Review URL: https://codereview.chromium.org/1307203003
Cr-Commit-Position: refs/heads/master@{#348014}
26 files changed, 513 insertions, 333 deletions
diff --git a/android_webview/browser/browser_view_renderer.cc b/android_webview/browser/browser_view_renderer.cc index 5a20d63..ec7dc08 100644 --- a/android_webview/browser/browser_view_renderer.cc +++ b/android_webview/browser/browser_view_renderer.cc @@ -418,13 +418,10 @@ void BrowserViewRenderer::OnDetachedFromWindow() { } void BrowserViewRenderer::OnComputeScroll(base::TimeTicks animation_time) { - if (pending_fling_animation_.is_null()) + if (!compositor_) return; TRACE_EVENT0("android_webview", "BrowserViewRenderer::OnComputeScroll"); - DCHECK(!pending_fling_animation_.is_null()); - AnimationCallback animation = pending_fling_animation_; - pending_fling_animation_.Reset(); - animation.Run(animation_time); + compositor_->OnComputeScroll(animation_time); } void BrowserViewRenderer::ReleaseHardware() { @@ -615,15 +612,6 @@ BrowserViewRenderer::RootLayerStateAsValue( return state; } -void BrowserViewRenderer::SetNeedsAnimateScroll( - const AnimationCallback& scroll_animation) { - pending_fling_animation_ = scroll_animation; - // No need to reschedule the fallback tick here because the compositor is - // fine with the animation not being ticked. The invalidate could happen some - // time later, or not at all. - client_->PostInvalidate(); -} - void BrowserViewRenderer::DidOverscroll(gfx::Vector2dF accumulated_overscroll, gfx::Vector2dF latest_overscroll_delta, gfx::Vector2dF current_fling_velocity) { diff --git a/android_webview/browser/browser_view_renderer.h b/android_webview/browser/browser_view_renderer.h index d0fc03e..dc0d3c5 100644 --- a/android_webview/browser/browser_view_renderer.h +++ b/android_webview/browser/browser_view_renderer.h @@ -108,8 +108,6 @@ class BrowserViewRenderer : public content::SynchronousCompositorClient { float page_scale_factor, float min_page_scale_factor, float max_page_scale_factor) override; - void SetNeedsAnimateScroll( - const AnimationCallback& scroll_animation) override; void DidOverscroll(gfx::Vector2dF accumulated_overscroll, gfx::Vector2dF latest_overscroll_delta, gfx::Vector2dF current_fling_velocity) override; @@ -182,11 +180,6 @@ class BrowserViewRenderer : public content::SynchronousCompositorClient { gfx::Size size_; - // Used to drive a fling animation as requested by the compositor. This acts - // as a single-shot animation; the compositor will continually post an - // animation callback as long as they're required. - AnimationCallback pending_fling_animation_; - // Current scroll offset in CSS pixels. gfx::Vector2dF scroll_offset_dip_; diff --git a/cc/input/input_handler.h b/cc/input/input_handler.h index 4852bdc..67a2c57 100644 --- a/cc/input/input_handler.h +++ b/cc/input/input_handler.h @@ -143,9 +143,13 @@ class CC_EXPORT InputHandler { // Request another callback to InputHandlerClient::Animate(). virtual void SetNeedsAnimateInput() = 0; + // If there is a scroll active, this reports whether the scroll is on the + // root layer, or on some other sublayer. + virtual bool IsCurrentlyScrollingRoot() const = 0; + // Whether the layer under |viewport_point| is the currently scrolling layer. virtual bool IsCurrentlyScrollingLayerAt(const gfx::Point& viewport_point, - ScrollInputType type) = 0; + ScrollInputType type) const = 0; virtual bool HaveWheelEventHandlersAt(const gfx::Point& viewport_point) = 0; diff --git a/cc/input/layer_scroll_offset_delegate.h b/cc/input/layer_scroll_offset_delegate.h index a0c0e0d..afd6e4b 100644 --- a/cc/input/layer_scroll_offset_delegate.h +++ b/cc/input/layer_scroll_offset_delegate.h @@ -44,11 +44,6 @@ class LayerScrollOffsetDelegate { float min_page_scale_factor, float max_page_scale_factor) = 0; - // This is called by the compositor when a fling hitting the root layer - // requires a scheduled animation update. - typedef base::Callback<void(base::TimeTicks)> AnimationCallback; - virtual void SetNeedsAnimate(const AnimationCallback& animation) = 0; - protected: LayerScrollOffsetDelegate() {} virtual ~LayerScrollOffsetDelegate() {} diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc index 9770aac..b15226a 100644 --- a/cc/trees/layer_tree_host_impl.cc +++ b/cc/trees/layer_tree_host_impl.cc @@ -405,16 +405,23 @@ bool LayerTreeHostImpl::CanDraw() const { } void LayerTreeHostImpl::Animate() { + DCHECK(proxy_->IsImplThread()); base::TimeTicks monotonic_time = CurrentBeginFrameArgs().frame_time; // mithro(TODO): Enable these checks. // DCHECK(!current_begin_frame_tracker_.HasFinished()); // DCHECK(monotonic_time == current_begin_frame_tracker_.Current().frame_time) // << "Called animate with unknown frame time!?"; - if (!root_layer_scroll_offset_delegate_ || - (CurrentlyScrollingLayer() != InnerViewportScrollLayer() && - CurrentlyScrollingLayer() != OuterViewportScrollLayer())) - AnimateInput(monotonic_time); + + if (input_handler_client_) { + // This animates fling scrolls. But on Android WebView root flings are + // controlled by the application, so the compositor does not animate them. + bool ignore_fling = + settings_.ignore_root_layer_flings && IsCurrentlyScrollingRoot(); + if (!ignore_fling) + input_handler_client_->Animate(monotonic_time); + } + AnimatePageScale(monotonic_time); AnimateLayers(monotonic_time); AnimateScrollbars(monotonic_time); @@ -474,25 +481,24 @@ void LayerTreeHostImpl::StartPageScaleAnimation( } void LayerTreeHostImpl::SetNeedsAnimateInput() { - if (root_layer_scroll_offset_delegate_ && - (CurrentlyScrollingLayer() == InnerViewportScrollLayer() || - CurrentlyScrollingLayer() == OuterViewportScrollLayer())) { - if (root_layer_animation_callback_.is_null()) { - root_layer_animation_callback_ = - base::Bind(&LayerTreeHostImpl::AnimateInput, AsWeakPtr()); - } - root_layer_scroll_offset_delegate_->SetNeedsAnimate( - root_layer_animation_callback_); - return; - } - + DCHECK_IMPLIES(IsCurrentlyScrollingRoot(), + !settings_.ignore_root_layer_flings); SetNeedsAnimate(); } +bool LayerTreeHostImpl::IsCurrentlyScrollingRoot() const { + LayerImpl* scrolling_layer = CurrentlyScrollingLayer(); + if (!scrolling_layer) + return false; + return scrolling_layer == InnerViewportScrollLayer() || + scrolling_layer == OuterViewportScrollLayer(); +} + bool LayerTreeHostImpl::IsCurrentlyScrollingLayerAt( const gfx::Point& viewport_point, - InputHandler::ScrollInputType type) { - if (!CurrentlyScrollingLayer()) + InputHandler::ScrollInputType type) const { + LayerImpl* scrolling_layer_impl = CurrentlyScrollingLayer(); + if (!scrolling_layer_impl) return false; gfx::PointF device_viewport_point = @@ -502,20 +508,20 @@ bool LayerTreeHostImpl::IsCurrentlyScrollingLayerAt( active_tree_->FindLayerThatIsHitByPoint(device_viewport_point); bool scroll_on_main_thread = false; - LayerImpl* scrolling_layer_impl = FindScrollLayerForDeviceViewportPoint( + LayerImpl* test_layer_impl = FindScrollLayerForDeviceViewportPoint( device_viewport_point, type, layer_impl, &scroll_on_main_thread, NULL); - if (!scrolling_layer_impl) + if (!test_layer_impl) return false; - if (CurrentlyScrollingLayer() == scrolling_layer_impl) + if (scrolling_layer_impl == test_layer_impl) return true; // For active scrolling state treat the inner/outer viewports interchangeably. - if ((CurrentlyScrollingLayer() == InnerViewportScrollLayer() && - scrolling_layer_impl == OuterViewportScrollLayer()) || - (CurrentlyScrollingLayer() == OuterViewportScrollLayer() && - scrolling_layer_impl == InnerViewportScrollLayer())) { + if ((scrolling_layer_impl == InnerViewportScrollLayer() && + test_layer_impl == OuterViewportScrollLayer()) || + (scrolling_layer_impl == OuterViewportScrollLayer() && + test_layer_impl == InnerViewportScrollLayer())) { return true; } @@ -1824,12 +1830,11 @@ LayerImpl* LayerTreeHostImpl::CurrentlyScrollingLayer() const { bool LayerTreeHostImpl::IsActivelyScrolling() const { if (!CurrentlyScrollingLayer()) return false; - if (root_layer_scroll_offset_delegate_ && - (CurrentlyScrollingLayer() == InnerViewportScrollLayer() || - CurrentlyScrollingLayer() == OuterViewportScrollLayer())) { - // ScrollDelegate cannot determine current scroll, so assume no. + // On Android WebView root flings are controlled by the application, + // so the compositor does not animate them and can't tell if they + // are actually animating. So assume there are none. + if (settings_.ignore_root_layer_flings && IsCurrentlyScrollingRoot()) return false; - } return did_lock_scrolling_layer_; } @@ -2773,8 +2778,9 @@ void LayerTreeHostImpl::OnRootLayerDelegatedScrollOffsetChanged() { DCHECK(root_layer_scroll_offset_delegate_); active_tree_->DistributeRootScrollOffset(); client_->SetNeedsCommitOnImplThread(); - SetNeedsRedraw(); active_tree_->set_needs_update_draw_properties(); + // No need to SetNeedsRedraw, this is for WebView and every frame has redraw + // requested by the WebView embedder already. } void LayerTreeHostImpl::ClearCurrentlyScrollingLayer() { @@ -2998,12 +3004,6 @@ void LayerTreeHostImpl::ScrollViewportBy(gfx::Vector2dF scroll_delta) { InnerViewportScrollLayer()->ScrollBy(unused_delta); } -void LayerTreeHostImpl::AnimateInput(base::TimeTicks monotonic_time) { - DCHECK(proxy_->IsImplThread()); - if (input_handler_client_) - input_handler_client_->Animate(monotonic_time); -} - void LayerTreeHostImpl::AnimatePageScale(base::TimeTicks monotonic_time) { if (!page_scale_animation_) return; diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h index e66a1ff..424cc53 100644 --- a/cc/trees/layer_tree_host_impl.h +++ b/cc/trees/layer_tree_host_impl.h @@ -189,8 +189,10 @@ class CC_EXPORT LayerTreeHostImpl float page_scale, base::TimeDelta duration); void SetNeedsAnimateInput() override; - bool IsCurrentlyScrollingLayerAt(const gfx::Point& viewport_point, - InputHandler::ScrollInputType type) override; + bool IsCurrentlyScrollingRoot() const override; + bool IsCurrentlyScrollingLayerAt( + const gfx::Point& viewport_point, + InputHandler::ScrollInputType type) const override; bool HaveWheelEventHandlersAt(const gfx::Point& viewport_point) override; bool DoTouchEventsBlockScrollAt(const gfx::Point& viewport_port) override; scoped_ptr<SwapPromiseMonitor> CreateLatencyInfoSwapPromiseMonitor( @@ -642,7 +644,6 @@ class CC_EXPORT LayerTreeHostImpl LayerImpl* scrolling_layer_impl, InputHandler::ScrollInputType type); - void AnimateInput(base::TimeTicks monotonic_time); void AnimatePageScale(base::TimeTicks monotonic_time); void AnimateScrollbars(base::TimeTicks monotonic_time); void AnimateTopControls(base::TimeTicks monotonic_time); @@ -742,7 +743,6 @@ class CC_EXPORT LayerTreeHostImpl // The optional delegate for the root layer scroll offset. LayerScrollOffsetDelegate* root_layer_scroll_offset_delegate_; - LayerScrollOffsetDelegate::AnimationCallback root_layer_animation_callback_; const LayerTreeSettings settings_; LayerTreeDebugState debug_state_; diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index 74d0a9c..a28b646 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc @@ -4499,8 +4499,7 @@ class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate { TestScrollOffsetDelegate() : page_scale_factor_(0.f), min_page_scale_factor_(-1.f), - max_page_scale_factor_(-1.f), - needs_animate_(false) {} + max_page_scale_factor_(-1.f) {} ~TestScrollOffsetDelegate() override {} @@ -4508,10 +4507,6 @@ class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate { return getter_return_value_; } - void SetNeedsAnimate(const AnimationCallback&) override { - needs_animate_ = true; - } - void UpdateRootLayerState(const gfx::ScrollOffset& total_scroll_offset, const gfx::ScrollOffset& max_scroll_offset, const gfx::SizeF& scrollable_size, @@ -4530,12 +4525,6 @@ class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate { set_getter_return_value(last_set_scroll_offset_); } - bool GetAndResetNeedsAnimate() { - bool needs_animate = needs_animate_; - needs_animate_ = false; - return needs_animate; - } - gfx::ScrollOffset last_set_scroll_offset() { return last_set_scroll_offset_; } @@ -4572,10 +4561,8 @@ class TestScrollOffsetDelegate : public LayerScrollOffsetDelegate { float page_scale_factor_; float min_page_scale_factor_; float max_page_scale_factor_; - bool needs_animate_; }; -// TODO(jdduke): Test root fling animation. TEST_F(LayerTreeHostImplTest, RootLayerScrollOffsetDelegation) { TestScrollOffsetDelegate scroll_delegate; host_impl_->SetViewportSize(gfx::Size(10, 20)); diff --git a/content/browser/android/in_process/synchronous_compositor_impl.cc b/content/browser/android/in_process/synchronous_compositor_impl.cc index a952650..a64971e 100644 --- a/content/browser/android/in_process/synchronous_compositor_impl.cc +++ b/content/browser/android/in_process/synchronous_compositor_impl.cc @@ -83,6 +83,7 @@ SynchronousCompositorImpl::SynchronousCompositorImpl(WebContents* contents) registered_with_client_(false), is_active_(true), renderer_needs_begin_frames_(false), + need_animate_input_(false), weak_ptr_factory_(this) { DCHECK(contents); DCHECK_NE(routing_id_, MSG_ROUTING_NONE); @@ -132,6 +133,10 @@ void SynchronousCompositorImpl::RegisterWithClient() { // Setting the delegate causes UpdateRootLayerState immediately so do it // after setting the client. input_handler_->SetRootLayerScrollOffsetDelegate(this); + // This disables the input system from animating inputs autonomously, instead + // routing all input animations through the SynchronousInputHandler, which is + // |this| class. + synchronous_input_handler_proxy_->SetOnlySynchronouslyAnimateRootFlings(this); } // static @@ -150,17 +155,20 @@ void SynchronousCompositor::SetUseIpcCommandBuffer() { void SynchronousCompositorImpl::DidInitializeRendererObjects( SynchronousCompositorOutputSurface* output_surface, SynchronousCompositorExternalBeginFrameSource* begin_frame_source, - cc::InputHandler* input_handler) { + cc::InputHandler* input_handler, + SynchronousInputHandlerProxy* synchronous_input_handler_proxy) { DCHECK(!output_surface_); DCHECK(!begin_frame_source_); DCHECK(output_surface); DCHECK(begin_frame_source); DCHECK(compositor_client_); DCHECK(input_handler); + DCHECK(synchronous_input_handler_proxy); output_surface_ = output_surface; begin_frame_source_ = begin_frame_source; input_handler_ = input_handler; + synchronous_input_handler_proxy_ = synchronous_input_handler_proxy; output_surface_->SetCompositor(this); begin_frame_source_->SetCompositor(this); @@ -184,6 +192,8 @@ void SynchronousCompositorImpl::DidDestroyRendererObjects() { input_handler_ = nullptr; begin_frame_source_ = nullptr; output_surface_ = nullptr; + // Don't propogate this signal from one renderer to the next. + need_animate_input_ = false; } scoped_ptr<cc::CompositorFrame> SynchronousCompositorImpl::DemandDrawHw( @@ -275,6 +285,14 @@ void SynchronousCompositorImpl::SetIsActive(bool is_active) { UpdateNeedsBeginFrames(); } +void SynchronousCompositorImpl::OnComputeScroll( + base::TimeTicks animation_time) { + if (need_animate_input_) { + synchronous_input_handler_proxy_->SynchronouslyAnimate(animation_time); + need_animate_input_ = false; + } +} + void SynchronousCompositorImpl::OnNeedsBeginFramesChange( bool needs_begin_frames) { renderer_needs_begin_frames_ = needs_begin_frames; @@ -342,6 +360,15 @@ void SynchronousCompositorImpl::DidActivatePendingTree() { DeliverMessages(); } +void SynchronousCompositorImpl::SetNeedsSynchronousAnimateInput() { + DCHECK(CalledOnValidThread()); + DCHECK(compositor_client_); + if (!registered_with_client_) + return; + need_animate_input_ = true; + compositor_client_->PostInvalidate(); +} + gfx::ScrollOffset SynchronousCompositorImpl::GetTotalScrollOffset() { DCHECK(CalledOnValidThread()); DCHECK(compositor_client_); @@ -353,15 +380,6 @@ gfx::ScrollOffset SynchronousCompositorImpl::GetTotalScrollOffset() { compositor_client_->GetTotalRootLayerScrollOffset()); } -void SynchronousCompositorImpl::SetNeedsAnimate( - const AnimationCallback& animation) { - DCHECK(CalledOnValidThread()); - DCHECK(compositor_client_); - if (!registered_with_client_) - return; - compositor_client_->SetNeedsAnimateScroll(animation); -} - void SynchronousCompositorImpl::UpdateRootLayerState( const gfx::ScrollOffset& total_scroll_offset, const gfx::ScrollOffset& max_scroll_offset, diff --git a/content/browser/android/in_process/synchronous_compositor_impl.h b/content/browser/android/in_process/synchronous_compositor_impl.h index 26b310a..999ae11 100644 --- a/content/browser/android/in_process/synchronous_compositor_impl.h +++ b/content/browser/android/in_process/synchronous_compositor_impl.h @@ -15,6 +15,7 @@ #include "content/common/input/input_event_ack_state.h" #include "content/public/browser/android/synchronous_compositor.h" #include "content/public/browser/web_contents_user_data.h" +#include "content/renderer/input/synchronous_input_handler_proxy.h" #include "ipc/ipc_message.h" namespace cc { @@ -38,6 +39,7 @@ struct DidOverscrollParams; // from the Compositor thread. class SynchronousCompositorImpl : public cc::LayerScrollOffsetDelegate, + public SynchronousInputHandler, public SynchronousCompositor, public WebContentsUserData<SynchronousCompositorImpl> { public: @@ -53,7 +55,8 @@ class SynchronousCompositorImpl void DidInitializeRendererObjects( SynchronousCompositorOutputSurface* output_surface, SynchronousCompositorExternalBeginFrameSource* begin_frame_source, - cc::InputHandler* input_handler); + cc::InputHandler* input_handler, + SynchronousInputHandlerProxy* synchronous_input_handler_proxy); void DidDestroyRendererObjects(); // Called by SynchronousCompositorExternalBeginFrameSource. @@ -78,6 +81,10 @@ class SynchronousCompositorImpl void SetMemoryPolicy(size_t bytes_limit) override; void DidChangeRootLayerScrollOffset() override; void SetIsActive(bool is_active) override; + void OnComputeScroll(base::TimeTicks animation_time) override; + + // SynchronousInputHandler + void SetNeedsSynchronousAnimateInput() override; // LayerScrollOffsetDelegate gfx::ScrollOffset GetTotalScrollOffset() override; @@ -87,7 +94,6 @@ class SynchronousCompositorImpl float page_scale_factor, float min_page_scale_factor, float max_page_scale_factor) override; - void SetNeedsAnimate(const AnimationCallback& scroll_animation) override; void DidOverscroll(const DidOverscrollParams& params); void DidStopFlinging(); @@ -112,9 +118,11 @@ class SynchronousCompositorImpl WebContents* contents_; const int routing_id_; cc::InputHandler* input_handler_; + SynchronousInputHandlerProxy* synchronous_input_handler_proxy_; bool registered_with_client_; bool is_active_; bool renderer_needs_begin_frames_; + bool need_animate_input_; base::WeakPtrFactory<SynchronousCompositorImpl> weak_ptr_factory_; diff --git a/content/browser/android/in_process/synchronous_compositor_registry.cc b/content/browser/android/in_process/synchronous_compositor_registry.cc index 2b8bded..84c45a2 100644 --- a/content/browser/android/in_process/synchronous_compositor_registry.cc +++ b/content/browser/android/in_process/synchronous_compositor_registry.cc @@ -107,12 +107,14 @@ void SynchronousCompositorRegistry::UnregisterOutputSurface( void SynchronousCompositorRegistry::RegisterInputHandler( int routing_id, - cc::InputHandler* input_handler) { + cc::InputHandler* input_handler, + SynchronousInputHandlerProxy* synchronous_input_handler_proxy) { DCHECK(CalledOnValidThread()); DCHECK(input_handler); Entry& entry = entry_map_[routing_id]; DCHECK(!entry.input_handler); entry.input_handler = input_handler; + entry.synchronous_input_handler_proxy = synchronous_input_handler_proxy; CheckIsReady(routing_id); } @@ -131,9 +133,9 @@ void SynchronousCompositorRegistry::CheckIsReady(int routing_id) { DCHECK(entry_map_.find(routing_id) != entry_map_.end()); Entry& entry = entry_map_[routing_id]; if (entry.IsReady()) { - entry.compositor->DidInitializeRendererObjects(entry.output_surface, - entry.begin_frame_source, - entry.input_handler); + entry.compositor->DidInitializeRendererObjects( + entry.output_surface, entry.begin_frame_source, entry.input_handler, + entry.synchronous_input_handler_proxy); } } @@ -161,11 +163,12 @@ SynchronousCompositorRegistry::Entry::Entry() : compositor(nullptr), begin_frame_source(nullptr), output_surface(nullptr), - input_handler(nullptr) { -} + input_handler(nullptr), + synchronous_input_handler_proxy(nullptr) {} bool SynchronousCompositorRegistry::Entry::IsReady() { - return compositor && begin_frame_source && output_surface && input_handler; + return compositor && begin_frame_source && output_surface && input_handler && + synchronous_input_handler_proxy; } } // namespace content diff --git a/content/browser/android/in_process/synchronous_compositor_registry.h b/content/browser/android/in_process/synchronous_compositor_registry.h index 5dfdc7e..f84bb0d 100644 --- a/content/browser/android/in_process/synchronous_compositor_registry.h +++ b/content/browser/android/in_process/synchronous_compositor_registry.h @@ -17,6 +17,7 @@ namespace content { class SynchronousCompositorExternalBeginFrameSource; class SynchronousCompositorImpl; class SynchronousCompositorOutputSurface; +class SynchronousInputHandlerProxy; class SynchronousCompositorRegistry { public: @@ -40,7 +41,8 @@ class SynchronousCompositorRegistry { SynchronousCompositorOutputSurface* output_surface); void RegisterInputHandler( int routing_id, - cc::InputHandler* input_handler); + cc::InputHandler* input_handler, + SynchronousInputHandlerProxy* synchronous_input_handler_proxy); void UnregisterInputHandler(int routing_id); private: @@ -53,6 +55,7 @@ class SynchronousCompositorRegistry { SynchronousCompositorExternalBeginFrameSource* begin_frame_source; SynchronousCompositorOutputSurface* output_surface; cc::InputHandler* input_handler; + SynchronousInputHandlerProxy* synchronous_input_handler_proxy; Entry(); bool IsReady(); diff --git a/content/browser/android/in_process/synchronous_input_event_filter.cc b/content/browser/android/in_process/synchronous_input_event_filter.cc index 3a03c0d..c3669af 100644 --- a/content/browser/android/in_process/synchronous_input_event_filter.cc +++ b/content/browser/android/in_process/synchronous_input_event_filter.cc @@ -48,10 +48,11 @@ void SynchronousInputEventFilter::SetBoundHandlerOnUIThread( void SynchronousInputEventFilter::DidAddInputHandler( int routing_id, - cc::InputHandler* input_handler) { + cc::InputHandler* input_handler, + SynchronousInputHandlerProxy* synchronous_input_handler_proxy) { DCHECK_CURRENTLY_ON(BrowserThread::UI); SynchronousCompositorRegistry::GetInstance()->RegisterInputHandler( - routing_id, input_handler); + routing_id, input_handler, synchronous_input_handler_proxy); } void SynchronousInputEventFilter::DidRemoveInputHandler(int routing_id) { diff --git a/content/browser/android/in_process/synchronous_input_event_filter.h b/content/browser/android/in_process/synchronous_input_event_filter.h index 607b9a9..9174a4d 100644 --- a/content/browser/android/in_process/synchronous_input_event_filter.h +++ b/content/browser/android/in_process/synchronous_input_event_filter.h @@ -33,8 +33,10 @@ class SynchronousInputEventFilter : public InputHandlerManagerClient { // InputHandlerManagerClient implementation. void SetBoundHandler(const Handler& handler) override; - void DidAddInputHandler(int routing_id, - cc::InputHandler* input_handler) override; + void DidAddInputHandler( + int routing_id, + cc::InputHandler* input_handler, + SynchronousInputHandlerProxy* synchronous_input_handler_proxy) override; void DidRemoveInputHandler(int routing_id) override; void DidOverscroll(int routing_id, const DidOverscrollParams& params) override; diff --git a/content/content_renderer.gypi b/content/content_renderer.gypi index 0a54c9d..3f31165 100644 --- a/content/content_renderer.gypi +++ b/content/content_renderer.gypi @@ -227,6 +227,7 @@ 'renderer/input/input_scroll_elasticity_controller.h', 'renderer/input/main_thread_input_event_filter.cc', 'renderer/input/main_thread_input_event_filter.h', + 'renderer/input/synchronous_input_handler_proxy.h', 'renderer/internal_document_state_data.cc', 'renderer/internal_document_state_data.h', 'renderer/java/gin_java_bridge_dispatcher.cc', diff --git a/content/public/browser/android/synchronous_compositor.h b/content/public/browser/android/synchronous_compositor.h index 08e5770..41aa848 100644 --- a/content/public/browser/android/synchronous_compositor.h +++ b/content/public/browser/android/synchronous_compositor.h @@ -79,6 +79,10 @@ class CONTENT_EXPORT SynchronousCompositor { // starts off as inactive and needs a SetActive(true) call to begin. virtual void SetIsActive(bool is_active) = 0; + // Called by the embedder to notify that the OnComputeScroll step is happening + // and if any input animation is active, it should tick now. + virtual void OnComputeScroll(base::TimeTicks animation_time) = 0; + protected: virtual ~SynchronousCompositor() {} }; diff --git a/content/public/browser/android/synchronous_compositor_client.h b/content/public/browser/android/synchronous_compositor_client.h index 1629995..4e0ab21 100644 --- a/content/public/browser/android/synchronous_compositor_client.h +++ b/content/public/browser/android/synchronous_compositor_client.h @@ -36,9 +36,6 @@ class SynchronousCompositorClient { float min_page_scale_factor, float max_page_scale_factor) = 0; - typedef base::Callback<void(base::TimeTicks)> AnimationCallback; - virtual void SetNeedsAnimateScroll(const AnimationCallback& animation) = 0; - virtual void DidOverscroll(gfx::Vector2dF accumulated_overscroll, gfx::Vector2dF latest_overscroll_delta, gfx::Vector2dF current_fling_velocity) = 0; diff --git a/content/public/test/test_synchronous_compositor_android.h b/content/public/test/test_synchronous_compositor_android.h index 695082b..e6d442d 100644 --- a/content/public/test/test_synchronous_compositor_android.h +++ b/content/public/test/test_synchronous_compositor_android.h @@ -30,6 +30,7 @@ class CONTENT_EXPORT TestSynchronousCompositor : public SynchronousCompositor { void SetMemoryPolicy(size_t bytes_limit) override {} void DidChangeRootLayerScrollOffset() override {} void SetIsActive(bool is_active) override {} + void OnComputeScroll(base::TimeTicks animate_time) override {} private: SynchronousCompositorClient* client_; diff --git a/content/renderer/input/input_event_filter.cc b/content/renderer/input/input_event_filter.cc index 4d487bd..36476a7 100644 --- a/content/renderer/input/input_event_filter.cc +++ b/content/renderer/input/input_event_filter.cc @@ -10,7 +10,6 @@ #include "base/single_thread_task_runner.h" #include "base/thread_task_runner_handle.h" #include "base/trace_event/trace_event.h" -#include "cc/input/input_handler.h" #include "content/common/input/did_overscroll_params.h" #include "content/common/input/web_input_event_traits.h" #include "content/common/input_messages.h" @@ -56,8 +55,10 @@ void InputEventFilter::SetBoundHandler(const Handler& handler) { handler_ = handler; } -void InputEventFilter::DidAddInputHandler(int routing_id, - cc::InputHandler* input_handler) { +void InputEventFilter::DidAddInputHandler( + int routing_id, + cc::InputHandler* input_handler, + SynchronousInputHandlerProxy* synchronous_input_handler_proxy) { base::AutoLock locked(routes_lock_); routes_.insert(routing_id); } diff --git a/content/renderer/input/input_event_filter.h b/content/renderer/input/input_event_filter.h index b66cf8c..1678a79 100644 --- a/content/renderer/input/input_event_filter.h +++ b/content/renderer/input/input_event_filter.h @@ -20,6 +20,10 @@ namespace base { class SingleThreadTaskRunner; } +namespace cc { +class InputHandler; +} + namespace IPC { class Listener; class Sender; @@ -35,6 +39,8 @@ class Sender; namespace content { +class SynchronousInputHandlerProxy; + class CONTENT_EXPORT InputEventFilter : public InputHandlerManagerClient, public IPC::MessageFilter { public: @@ -54,8 +60,10 @@ class CONTENT_EXPORT InputEventFilter : public InputHandlerManagerClient, // InputHostMsg_HandleInputEvent_ACK. // void SetBoundHandler(const Handler& handler) override; - void DidAddInputHandler(int routing_id, - cc::InputHandler* input_handler) override; + void DidAddInputHandler( + int routing_id, + cc::InputHandler* input_handler, + SynchronousInputHandlerProxy* synchronous_input_handler_proxy) override; void DidRemoveInputHandler(int routing_id) override; void DidOverscroll(int routing_id, const DidOverscrollParams& params) override; diff --git a/content/renderer/input/input_event_filter_unittest.cc b/content/renderer/input/input_event_filter_unittest.cc index d9a3505..98e6326 100644 --- a/content/renderer/input/input_event_filter_unittest.cc +++ b/content/renderer/input/input_event_filter_unittest.cc @@ -165,7 +165,7 @@ TEST_F(InputEventFilterTest, Basic) { EXPECT_EQ(0U, event_recorder_.record_count()); EXPECT_EQ(0U, message_recorder_.message_count()); - filter_->DidAddInputHandler(kTestRoutingID, NULL); + filter_->DidAddInputHandler(kTestRoutingID, nullptr, nullptr); AddEventsToFilter(filter_.get(), kEvents, arraysize(kEvents)); ASSERT_EQ(arraysize(kEvents), ipc_sink_.message_count()); @@ -241,7 +241,7 @@ TEST_F(InputEventFilterTest, Basic) { } TEST_F(InputEventFilterTest, PreserveRelativeOrder) { - filter_->DidAddInputHandler(kTestRoutingID, NULL); + filter_->DidAddInputHandler(kTestRoutingID, nullptr, nullptr); event_recorder_.set_send_to_widget(true); diff --git a/content/renderer/input/input_handler_manager.cc b/content/renderer/input/input_handler_manager.cc index 98df2661..3a298e3 100644 --- a/content/renderer/input/input_handler_manager.cc +++ b/content/renderer/input/input_handler_manager.cc @@ -91,10 +91,11 @@ void InputHandlerManager::AddInputHandlerOnCompositorThread( TRACE_EVENT1("input", "InputHandlerManager::AddInputHandlerOnCompositorThread", "result", "AddingRoute"); - client_->DidAddInputHandler(routing_id, input_handler.get()); - input_handlers_.add(routing_id, make_scoped_ptr(new InputHandlerWrapper( - this, routing_id, main_task_runner, - input_handler, render_view_impl))); + scoped_ptr<InputHandlerWrapper> wrapper(new InputHandlerWrapper( + this, routing_id, main_task_runner, input_handler, render_view_impl)); + client_->DidAddInputHandler(routing_id, input_handler.get(), + wrapper->input_handler_proxy()); + input_handlers_.add(routing_id, wrapper.Pass()); } void InputHandlerManager::RemoveInputHandler(int routing_id) { diff --git a/content/renderer/input/input_handler_manager_client.h b/content/renderer/input/input_handler_manager_client.h index 8967881..a098808 100644 --- a/content/renderer/input/input_handler_manager_client.h +++ b/content/renderer/input/input_handler_manager_client.h @@ -25,6 +25,7 @@ class WebInputEvent; namespace content { struct DidOverscrollParams; +class SynchronousInputHandlerProxy; class CONTENT_EXPORT InputHandlerManagerClient { public: @@ -42,8 +43,10 @@ class CONTENT_EXPORT InputHandlerManagerClient { virtual void SetBoundHandler(const Handler& handler) = 0; // Called from the compositor thread. - virtual void DidAddInputHandler(int routing_id, - cc::InputHandler* input_handler) = 0; + virtual void DidAddInputHandler( + int routing_id, + cc::InputHandler* input_handler, + SynchronousInputHandlerProxy* synchronous_handler) = 0; virtual void DidRemoveInputHandler(int routing_id) = 0; virtual void DidOverscroll(int routing_id, const DidOverscrollParams& params) = 0; diff --git a/content/renderer/input/input_handler_proxy.cc b/content/renderer/input/input_handler_proxy.cc index 633ed8b..302c66d 100644 --- a/content/renderer/input/input_handler_proxy.cc +++ b/content/renderer/input/input_handler_proxy.cc @@ -185,6 +185,8 @@ InputHandlerProxy::InputHandlerProxy(cc::InputHandler* input_handler, : client_(client), input_handler_(input_handler), deferred_fling_cancel_time_seconds_(0), + synchronous_input_handler_(nullptr), + allow_root_animate_(true), #ifndef NDEBUG expect_scroll_update_end_(false), #endif @@ -551,7 +553,7 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleGestureFlingStart( WebPoint(gesture_event.globalX, gesture_event.globalY); fling_parameters_.modifiers = gesture_event.modifiers; fling_parameters_.sourceDevice = gesture_event.sourceDevice; - input_handler_->SetNeedsAnimateInput(); + RequestAnimation(); return DID_HANDLE; } case cc::InputHandler::SCROLL_UNKNOWN: @@ -751,6 +753,11 @@ void InputHandlerProxy::ExtendBoostedFlingTimeout( } void InputHandlerProxy::Animate(base::TimeTicks time) { + // If using synchronous animate, then only expect Animate attempts started by + // the synchronous system. Don't let the InputHandler try to Animate also. + DCHECK_IMPLIES(input_handler_->IsCurrentlyScrollingRoot(), + allow_root_animate_); + if (scroll_elasticity_controller_) scroll_elasticity_controller_->Animate(time); @@ -777,7 +784,7 @@ void InputHandlerProxy::Animate(base::TimeTicks time) { monotonic_time_sec >= fling_parameters_.startTime + kMaxSecondsFromFlingTimestampToFirstAnimate) { fling_parameters_.startTime = monotonic_time_sec; - input_handler_->SetNeedsAnimateInput(); + RequestAnimation(); return; } } @@ -790,7 +797,7 @@ void InputHandlerProxy::Animate(base::TimeTicks time) { fling_is_active = false; if (fling_is_active) { - input_handler_->SetNeedsAnimateInput(); + RequestAnimation(); } else { TRACE_EVENT_INSTANT0("input", "InputHandlerProxy::animate::flingOver", @@ -809,6 +816,21 @@ void InputHandlerProxy::ReconcileElasticOverscrollAndRootScroll() { scroll_elasticity_controller_->ReconcileStretchAndScroll(); } +void InputHandlerProxy::SetOnlySynchronouslyAnimateRootFlings( + SynchronousInputHandler* synchronous_input_handler) { + allow_root_animate_ = false; + synchronous_input_handler_ = synchronous_input_handler; +} + +void InputHandlerProxy::SynchronouslyAnimate(base::TimeTicks time) { + // When this function is used, SetOnlySynchronouslyAnimate() should have been + // previously called. IOW you should either be entirely in synchronous mode or + // not. + DCHECK(!allow_root_animate_); + base::AutoReset<bool> reset(&allow_root_animate_, true); + Animate(time); +} + void InputHandlerProxy::HandleOverscroll( const gfx::Point& causal_event_viewport_point, const cc::InputHandlerScrollResult& scroll_result) { @@ -888,6 +910,16 @@ bool InputHandlerProxy::CancelCurrentFlingWithoutNotifyingClient() { return had_fling_animation; } +void InputHandlerProxy::RequestAnimation() { + // When a SynchronousInputHandler is present, root flings should go through + // it to allow it to control when or if the root fling is animated. Non-root + // flings always go through the normal InputHandler. + if (synchronous_input_handler_ && input_handler_->IsCurrentlyScrollingRoot()) + synchronous_input_handler_->SetNeedsSynchronousAnimateInput(); + else + input_handler_->SetNeedsAnimateInput(); +} + bool InputHandlerProxy::TouchpadFlingScroll( const WebFloatSize& increment) { WebMouseWheelEvent synthetic_wheel; diff --git a/content/renderer/input/input_handler_proxy.h b/content/renderer/input/input_handler_proxy.h index 4248474..b61067c 100644 --- a/content/renderer/input/input_handler_proxy.h +++ b/content/renderer/input/input_handler_proxy.h @@ -11,6 +11,7 @@ #include "base/memory/scoped_ptr.h" #include "cc/input/input_handler.h" #include "content/common/content_export.h" +#include "content/renderer/input/synchronous_input_handler_proxy.h" #include "third_party/WebKit/public/platform/WebGestureCurve.h" #include "third_party/WebKit/public/platform/WebGestureCurveTarget.h" #include "third_party/WebKit/public/web/WebActiveWheelFlingParameters.h" @@ -27,6 +28,7 @@ class InputScrollElasticityController; // intended for a specific WebWidget. class CONTENT_EXPORT InputHandlerProxy : public cc::InputHandlerClient, + public SynchronousInputHandlerProxy, public NON_EXPORTED_BASE(blink::WebGestureCurveTarget) { public: InputHandlerProxy(cc::InputHandler* input_handler, @@ -53,6 +55,11 @@ class CONTENT_EXPORT InputHandlerProxy void MainThreadHasStoppedFlinging() override; void ReconcileElasticOverscrollAndRootScroll() override; + // SynchronousInputHandlerProxy implementation. + void SetOnlySynchronouslyAnimateRootFlings( + SynchronousInputHandler* synchronous_input_handler) override; + void SynchronouslyAnimate(base::TimeTicks time) override; + // blink::WebGestureCurveTarget implementation. virtual bool scrollBy(const blink::WebFloatSize& offset, const blink::WebFloatSize& velocity); @@ -96,6 +103,10 @@ class CONTENT_EXPORT InputHandlerProxy // Returns true if we actually had an active fling to cancel. bool CancelCurrentFlingWithoutNotifyingClient(); + // Request a frame of animation from the InputHandler or + // SynchronousInputHandler. They can provide that by calling Animate(). + void RequestAnimation(); + // Used to send overscroll messages to the browser. void HandleOverscroll( const gfx::Point& causal_event_viewport_point, @@ -118,6 +129,13 @@ class CONTENT_EXPORT InputHandlerProxy // fling terminates (via |CancelCurrentFling()|). blink::WebGestureEvent last_fling_boost_event_; + // When present, Animates are not requested to the InputHandler, but to this + // SynchronousInputHandler instead. And all Animate() calls are expected to + // happen via the SynchronouslyAnimate() call instead of coming directly from + // the InputHandler. + SynchronousInputHandler* synchronous_input_handler_; + bool allow_root_animate_; + #ifndef NDEBUG bool expect_scroll_update_end_; #endif diff --git a/content/renderer/input/input_handler_proxy_unittest.cc b/content/renderer/input/input_handler_proxy_unittest.cc index 65f6644..fea5a7f 100644 --- a/content/renderer/input/input_handler_proxy_unittest.cc +++ b/content/renderer/input/input_handler_proxy_unittest.cc @@ -35,6 +35,16 @@ using testing::Field; namespace content { namespace { +enum InputHandlerProxyTestType { + ROOT_SCROLL_NORMAL_HANDLER, + ROOT_SCROLL_SYNCHRONOUS_HANDLER, + CHILD_SCROLL_NORMAL_HANDLER, + CHILD_SCROLL_SYNCHRONOUS_HANDLER, +}; +static const InputHandlerProxyTestType test_types[] = { + ROOT_SCROLL_NORMAL_HANDLER, ROOT_SCROLL_SYNCHRONOUS_HANDLER, + CHILD_SCROLL_NORMAL_HANDLER, CHILD_SCROLL_SYNCHRONOUS_HANDLER}; + double InSecondsF(const base::TimeTicks& time) { return (time - base::TimeTicks()).InSecondsF(); } @@ -115,9 +125,9 @@ class MockInputHandler : public cc::InputHandler { void MouseMoveAt(const gfx::Point& mouse_position) override {} - MOCK_METHOD2(IsCurrentlyScrollingLayerAt, - bool(const gfx::Point& point, - cc::InputHandler::ScrollInputType type)); + MOCK_CONST_METHOD2(IsCurrentlyScrollingLayerAt, + bool(const gfx::Point& point, + cc::InputHandler::ScrollInputType type)); MOCK_METHOD1(HaveWheelEventHandlersAt, bool(const gfx::Point& point)); MOCK_METHOD1(DoTouchEventsBlockScrollAt, bool(const gfx::Point& point)); @@ -128,9 +138,19 @@ class MockInputHandler : public cc::InputHandler { void OnRootLayerDelegatedScrollOffsetChanged() override {} + bool IsCurrentlyScrollingRoot() const override { return is_scrolling_root_; } + void set_is_scrolling_root(bool is) { is_scrolling_root_ = is; } + + private: + bool is_scrolling_root_ = true; DISALLOW_COPY_AND_ASSIGN(MockInputHandler); }; +class MockSynchronousInputHandler : public content::SynchronousInputHandler { + public: + MOCK_METHOD0(SetNeedsSynchronousAnimateInput, void()); +}; + // A simple WebGestureCurve implementation that flings at a constant velocity // indefinitely. class FakeWebGestureCurve : public blink::WebGestureCurve { @@ -210,29 +230,67 @@ WebTouchPoint CreateWebTouchPoint(WebTouchPoint::State state, float x, return point; } -class InputHandlerProxyTest : public testing::Test { +class InputHandlerProxyTest + : public testing::Test, + public testing::WithParamInterface<InputHandlerProxyTestType> { public: InputHandlerProxyTest() - : expected_disposition_(InputHandlerProxy::DID_HANDLE) { + : synchronous_root_scroll_(GetParam() == ROOT_SCROLL_SYNCHRONOUS_HANDLER), + install_synchronous_handler_( + GetParam() == ROOT_SCROLL_SYNCHRONOUS_HANDLER || + GetParam() == CHILD_SCROLL_SYNCHRONOUS_HANDLER), + expected_disposition_(InputHandlerProxy::DID_HANDLE) { input_handler_.reset( new content::InputHandlerProxy(&mock_input_handler_, &mock_client_)); scroll_result_did_scroll_.did_scroll = true; scroll_result_did_not_scroll_.did_scroll = false; + + if (install_synchronous_handler_) { + input_handler_->SetOnlySynchronouslyAnimateRootFlings( + &mock_synchronous_input_handler_); + } + mock_input_handler_.set_is_scrolling_root(synchronous_root_scroll_); } ~InputHandlerProxyTest() { input_handler_.reset(); } +// This is defined as a macro so the line numbers can be traced back to the +// correct spot when it fails. +#define EXPECT_SET_NEEDS_ANIMATE_INPUT(times) \ + do { \ + if (synchronous_root_scroll_) { \ + EXPECT_CALL(mock_synchronous_input_handler_, \ + SetNeedsSynchronousAnimateInput()) \ + .Times(times); \ + EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(0); \ + } else { \ + EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(times); \ + EXPECT_CALL(mock_synchronous_input_handler_, \ + SetNeedsSynchronousAnimateInput()) \ + .Times(0); \ + } \ + } while (false) + // This is defined as a macro because when an expectation is not satisfied the -// only output you get -// out of gmock is the line number that set the expectation. -#define VERIFY_AND_RESET_MOCKS() \ - do { \ - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); \ - testing::Mock::VerifyAndClearExpectations(&mock_client_); \ +// only output you get out of gmock is the line number that set the expectation. +#define VERIFY_AND_RESET_MOCKS() \ + do { \ + testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); \ + testing::Mock::VerifyAndClearExpectations( \ + &mock_synchronous_input_handler_); \ + testing::Mock::VerifyAndClearExpectations(&mock_client_); \ } while (false) + void Animate(base::TimeTicks time) { + if (synchronous_root_scroll_) { + input_handler_->SynchronouslyAnimate(time); + } else { + input_handler_->Animate(time); + } + } + void StartFling(base::TimeTicks timestamp, WebGestureDevice source_device, WebFloatPoint velocity, @@ -251,7 +309,7 @@ class InputHandlerProxyTest : public testing::Test { EXPECT_CALL(mock_input_handler_, FlingScrollBegin()) .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED)); - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); gesture_ = CreateFling(timestamp, source_device, velocity, position, position, 0); @@ -271,7 +329,11 @@ class InputHandlerProxyTest : public testing::Test { } protected: + const bool synchronous_root_scroll_; + const bool install_synchronous_handler_; testing::StrictMock<MockInputHandler> mock_input_handler_; + testing::StrictMock<MockSynchronousInputHandler> + mock_synchronous_input_handler_; scoped_ptr<content::InputHandlerProxy> input_handler_; testing::StrictMock<MockInputHandlerProxyClient> mock_client_; WebGestureEvent gesture_; @@ -280,27 +342,27 @@ class InputHandlerProxyTest : public testing::Test { cc::InputHandlerScrollResult scroll_result_did_not_scroll_; }; -TEST_F(InputHandlerProxyTest, MouseWheelByPageMainThread) { +TEST_P(InputHandlerProxyTest, MouseWheelByPageMainThread) { expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE; WebMouseWheelEvent wheel; wheel.type = WebInputEvent::MouseWheel; wheel.scrollByPage = true; EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(wheel)); - testing::Mock::VerifyAndClearExpectations(&mock_client_); + VERIFY_AND_RESET_MOCKS(); } -TEST_F(InputHandlerProxyTest, MouseWheelWithCtrlNotScroll) { +TEST_P(InputHandlerProxyTest, MouseWheelWithCtrlNotScroll) { expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE; WebMouseWheelEvent wheel; wheel.type = WebInputEvent::MouseWheel; wheel.modifiers = WebInputEvent::ControlKey; wheel.canScroll = false; EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(wheel)); - testing::Mock::VerifyAndClearExpectations(&mock_client_); + VERIFY_AND_RESET_MOCKS(); } -TEST_F(InputHandlerProxyTest, GestureScrollStarted) { +TEST_P(InputHandlerProxyTest, GestureScrollStarted) { // We shouldn't send any events to the widget for this gesture. expected_disposition_ = InputHandlerProxy::DID_HANDLE; VERIFY_AND_RESET_MOCKS(); @@ -347,7 +409,7 @@ TEST_F(InputHandlerProxyTest, GestureScrollStarted) { VERIFY_AND_RESET_MOCKS(); } -TEST_F(InputHandlerProxyTest, GestureScrollOnMainThread) { +TEST_P(InputHandlerProxyTest, GestureScrollOnMainThread) { // We should send all events to the widget for this gesture. expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE; VERIFY_AND_RESET_MOCKS(); @@ -374,7 +436,7 @@ TEST_F(InputHandlerProxyTest, GestureScrollOnMainThread) { VERIFY_AND_RESET_MOCKS(); } -TEST_F(InputHandlerProxyTest, GestureScrollIgnored) { +TEST_P(InputHandlerProxyTest, GestureScrollIgnored) { // We shouldn't handle the GestureScrollBegin. // Instead, we should get a DROP_EVENT result, indicating // that we could determine that there's nothing that could scroll or otherwise @@ -397,7 +459,7 @@ TEST_F(InputHandlerProxyTest, GestureScrollIgnored) { VERIFY_AND_RESET_MOCKS(); } -TEST_F(InputHandlerProxyTest, GestureScrollBeginThatTargetViewport) { +TEST_P(InputHandlerProxyTest, GestureScrollBeginThatTargetViewport) { // We shouldn't send any events to the widget for this gesture. expected_disposition_ = InputHandlerProxy::DID_HANDLE; VERIFY_AND_RESET_MOCKS(); @@ -412,7 +474,7 @@ TEST_F(InputHandlerProxyTest, GestureScrollBeginThatTargetViewport) { VERIFY_AND_RESET_MOCKS(); } -TEST_F(InputHandlerProxyTest, GesturePinch) { +TEST_P(InputHandlerProxyTest, GesturePinch) { // We shouldn't send any events to the widget for this gesture. expected_disposition_ = InputHandlerProxy::DID_HANDLE; VERIFY_AND_RESET_MOCKS(); @@ -461,7 +523,7 @@ TEST_F(InputHandlerProxyTest, GesturePinch) { VERIFY_AND_RESET_MOCKS(); } -TEST_F(InputHandlerProxyTest, GesturePinchWithWheelHandler) { +TEST_P(InputHandlerProxyTest, GesturePinchWithWheelHandler) { // We will send the synthetic wheel event to the widget. expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE; VERIFY_AND_RESET_MOCKS(); @@ -493,7 +555,7 @@ TEST_F(InputHandlerProxyTest, GesturePinchWithWheelHandler) { EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); } -TEST_F(InputHandlerProxyTest, GesturePinchAfterScrollOnMainThread) { +TEST_P(InputHandlerProxyTest, GesturePinchAfterScrollOnMainThread) { // Scrolls will start by being sent to the main thread. expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE; VERIFY_AND_RESET_MOCKS(); @@ -570,7 +632,7 @@ TEST_F(InputHandlerProxyTest, GesturePinchAfterScrollOnMainThread) { VERIFY_AND_RESET_MOCKS(); } -TEST_F(InputHandlerProxyTest, GestureFlingStartedTouchpad) { +TEST_P(InputHandlerProxyTest, GestureFlingStartedTouchpad) { // We shouldn't send any events to the widget for this gesture. expected_disposition_ = InputHandlerProxy::DID_HANDLE; VERIFY_AND_RESET_MOCKS(); @@ -578,7 +640,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingStartedTouchpad) { EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED)); EXPECT_CALL(mock_input_handler_, ScrollEnd()); - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); gesture_.type = WebInputEvent::GestureFlingStart; gesture_.data.flingStart.velocityX = 10; @@ -593,7 +655,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingStartedTouchpad) { EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); } -TEST_F(InputHandlerProxyTest, GestureFlingOnMainThreadTouchpad) { +TEST_P(InputHandlerProxyTest, GestureFlingOnMainThreadTouchpad) { // We should send all events to the widget for this gesture. expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE; VERIFY_AND_RESET_MOCKS(); @@ -618,7 +680,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingOnMainThreadTouchpad) { EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); } -TEST_F(InputHandlerProxyTest, GestureFlingIgnoredTouchpad) { +TEST_P(InputHandlerProxyTest, GestureFlingIgnoredTouchpad) { expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE; VERIFY_AND_RESET_MOCKS(); @@ -639,7 +701,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingIgnoredTouchpad) { EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); } -TEST_F(InputHandlerProxyTest, GestureFlingAnimatesTouchpad) { +TEST_P(InputHandlerProxyTest, GestureFlingAnimatesTouchpad) { // We shouldn't send any events to the widget for this gesture. expected_disposition_ = InputHandlerProxy::DID_HANDLE; VERIFY_AND_RESET_MOCKS(); @@ -658,28 +720,28 @@ TEST_F(InputHandlerProxyTest, GestureFlingAnimatesTouchpad) { fling_point, fling_global_point, modifiers); - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED)); EXPECT_CALL(mock_input_handler_, ScrollEnd()); EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); // The first animate call should let us pick up an animation start time, but // we shouldn't actually move anywhere just yet. The first frame after the // fling start will typically include the last scroll from the gesture that // lead to the scroll (either wheel or gesture scroll), so there should be no // visible hitch. - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .Times(0); base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10); - input_handler_->Animate(time); + Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); // The second call should start scrolling in the -X direction. - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED)); EXPECT_CALL(mock_input_handler_, @@ -688,9 +750,9 @@ TEST_F(InputHandlerProxyTest, GestureFlingAnimatesTouchpad) { .WillOnce(testing::Return(scroll_result_did_scroll_)); EXPECT_CALL(mock_input_handler_, ScrollEnd()); time += base::TimeDelta::FromMilliseconds(100); - input_handler_->Animate(time); + Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); // Let's say on the third call we hit a non-scrollable region. We should abort // the fling and not scroll. @@ -724,19 +786,18 @@ TEST_F(InputHandlerProxyTest, GestureFlingAnimatesTouchpad) { testing::Field(&WebActiveWheelFlingParameters::cumulativeScroll, testing::Field(&WebSize::width, testing::Gt(0)))))); time += base::TimeDelta::FromMilliseconds(100); - input_handler_->Animate(time); + Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); - testing::Mock::VerifyAndClearExpectations(&mock_client_); + VERIFY_AND_RESET_MOCKS(); // Since we've aborted the fling, the next animation should be a no-op and // should not result in another // frame being requested. - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(0); + EXPECT_SET_NEEDS_ANIMATE_INPUT(0); EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .Times(0); time += base::TimeDelta::FromMilliseconds(100); - input_handler_->Animate(time); + Animate(time); // Since we've transferred the fling to the main thread, we need to pass the // next GestureFlingCancel to the main @@ -748,7 +809,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingAnimatesTouchpad) { VERIFY_AND_RESET_MOCKS(); } -TEST_F(InputHandlerProxyTest, GestureFlingTransferResetsTouchpad) { +TEST_P(InputHandlerProxyTest, GestureFlingTransferResetsTouchpad) { // We shouldn't send any events to the widget for this gesture. expected_disposition_ = InputHandlerProxy::DID_HANDLE; VERIFY_AND_RESET_MOCKS(); @@ -765,26 +826,26 @@ TEST_F(InputHandlerProxyTest, GestureFlingTransferResetsTouchpad) { fling_point, fling_global_point, modifiers); - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED)); EXPECT_CALL(mock_input_handler_, ScrollEnd()); EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); // Start the fling animation at time 10. This shouldn't actually scroll, just // establish a start time. - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .Times(0); base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10); - input_handler_->Animate(time); + Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); // The second call should start scrolling in the -X direction. - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED)); EXPECT_CALL(mock_input_handler_, @@ -793,9 +854,9 @@ TEST_F(InputHandlerProxyTest, GestureFlingTransferResetsTouchpad) { .WillOnce(testing::Return(scroll_result_did_scroll_)); EXPECT_CALL(mock_input_handler_, ScrollEnd()); time += base::TimeDelta::FromMilliseconds(100); - input_handler_->Animate(time); + Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); // Let's say on the third call we hit a non-scrollable region. We should abort // the fling and not scroll. @@ -830,21 +891,20 @@ TEST_F(InputHandlerProxyTest, GestureFlingTransferResetsTouchpad) { testing::Field(&WebActiveWheelFlingParameters::cumulativeScroll, testing::Field(&WebSize::width, testing::Gt(0)))))); time += base::TimeDelta::FromMilliseconds(100); - input_handler_->Animate(time); + Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); - testing::Mock::VerifyAndClearExpectations(&mock_client_); + VERIFY_AND_RESET_MOCKS(); // Since we've aborted the fling, the next animation should be a no-op and // should not result in another // frame being requested. - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(0); + EXPECT_SET_NEEDS_ANIMATE_INPUT(0); EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .Times(0); time += base::TimeDelta::FromMilliseconds(100); - input_handler_->Animate(time); + Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); // Since we've transferred the fling to the main thread, we need to pass the // next GestureFlingCancel to the main @@ -866,26 +926,26 @@ TEST_F(InputHandlerProxyTest, GestureFlingTransferResetsTouchpad) { fling_point, fling_global_point, modifiers); - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED)); EXPECT_CALL(mock_input_handler_, ScrollEnd()); expected_disposition_ = InputHandlerProxy::DID_HANDLE; EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); // Start the second fling animation at time 30. - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .Times(0); time = base::TimeTicks() + base::TimeDelta::FromSeconds(30); - input_handler_->Animate(time); + Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); // Tick the second fling once normally. - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED)); EXPECT_CALL(mock_input_handler_, @@ -894,9 +954,9 @@ TEST_F(InputHandlerProxyTest, GestureFlingTransferResetsTouchpad) { .WillOnce(testing::Return(scroll_result_did_scroll_)); EXPECT_CALL(mock_input_handler_, ScrollEnd()); time += base::TimeDelta::FromMilliseconds(100); - input_handler_->Animate(time); + Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); // Then abort the second fling. EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) @@ -922,12 +982,12 @@ TEST_F(InputHandlerProxyTest, GestureFlingTransferResetsTouchpad) { testing::Field(&WebActiveWheelFlingParameters::cumulativeScroll, testing::Field(&WebSize::height, testing::Lt(0)))))); time += base::TimeDelta::FromMilliseconds(100); - input_handler_->Animate(time); + Animate(time); VERIFY_AND_RESET_MOCKS(); } -TEST_F(InputHandlerProxyTest, GestureFlingStartedTouchscreen) { +TEST_P(InputHandlerProxyTest, GestureFlingStartedTouchscreen) { // We shouldn't send any events to the widget for this gesture. expected_disposition_ = InputHandlerProxy::DID_HANDLE; VERIFY_AND_RESET_MOCKS(); @@ -942,7 +1002,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingStartedTouchscreen) { EXPECT_CALL(mock_input_handler_, FlingScrollBegin()) .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED)); - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); gesture_.type = WebInputEvent::GestureFlingStart; gesture_.data.flingStart.velocityX = 10; @@ -961,7 +1021,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingStartedTouchscreen) { VERIFY_AND_RESET_MOCKS(); } -TEST_F(InputHandlerProxyTest, GestureFlingOnMainThreadTouchscreen) { +TEST_P(InputHandlerProxyTest, GestureFlingOnMainThreadTouchscreen) { // We should send all events to the widget for this gesture. expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE; VERIFY_AND_RESET_MOCKS(); @@ -989,7 +1049,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingOnMainThreadTouchscreen) { EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); } -TEST_F(InputHandlerProxyTest, GestureFlingIgnoredTouchscreen) { +TEST_P(InputHandlerProxyTest, GestureFlingIgnoredTouchscreen) { expected_disposition_ = InputHandlerProxy::DID_HANDLE; VERIFY_AND_RESET_MOCKS(); @@ -1026,7 +1086,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingIgnoredTouchscreen) { VERIFY_AND_RESET_MOCKS(); } -TEST_F(InputHandlerProxyTest, GestureFlingAnimatesTouchscreen) { +TEST_P(InputHandlerProxyTest, GestureFlingAnimatesTouchscreen) { // We shouldn't send any events to the widget for this gesture. expected_disposition_ = InputHandlerProxy::DID_HANDLE; VERIFY_AND_RESET_MOCKS(); @@ -1052,33 +1112,33 @@ TEST_F(InputHandlerProxyTest, GestureFlingAnimatesTouchscreen) { fling_point, fling_global_point, modifiers); - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, FlingScrollBegin()) .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED)); EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); // The first animate call should let us pick up an animation start time, but // we shouldn't actually move anywhere just yet. The first frame after the // fling start will typically include the last scroll from the gesture that // lead to the scroll (either wheel or gesture scroll), so there should be no // visible hitch. - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10); - input_handler_->Animate(time); + Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); // The second call should start scrolling in the -X direction. - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Lt(0)))) .WillOnce(testing::Return(scroll_result_did_scroll_)); time += base::TimeDelta::FromMilliseconds(100); - input_handler_->Animate(time); + Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); EXPECT_CALL(mock_input_handler_, ScrollEnd()); gesture_.type = WebInputEvent::GestureFlingCancel; @@ -1087,7 +1147,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingAnimatesTouchscreen) { VERIFY_AND_RESET_MOCKS(); } -TEST_F(InputHandlerProxyTest, GestureFlingWithValidTimestamp) { +TEST_P(InputHandlerProxyTest, GestureFlingWithValidTimestamp) { // We shouldn't send any events to the widget for this gesture. expected_disposition_ = InputHandlerProxy::DID_HANDLE; VERIFY_AND_RESET_MOCKS(); @@ -1115,26 +1175,26 @@ TEST_F(InputHandlerProxyTest, GestureFlingWithValidTimestamp) { fling_point, fling_global_point, modifiers); - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, FlingScrollBegin()) .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED)); EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); // With a valid time stamp, the first animate call should skip start time // initialization and immediately begin scroll update production. This reduces // the likelihood of a hitch between the scroll preceding the fling and // the first scroll generated by the fling. // Scrolling should start in the -X direction. - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Lt(0)))) .WillOnce(testing::Return(scroll_result_did_scroll_)); time += dt; - input_handler_->Animate(time); + Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); EXPECT_CALL(mock_input_handler_, ScrollEnd()); gesture_.type = WebInputEvent::GestureFlingCancel; @@ -1143,7 +1203,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingWithValidTimestamp) { VERIFY_AND_RESET_MOCKS(); } -TEST_F(InputHandlerProxyTest, GestureFlingWithInvalidTimestamp) { +TEST_P(InputHandlerProxyTest, GestureFlingWithInvalidTimestamp) { // We shouldn't send any events to the widget for this gesture. expected_disposition_ = InputHandlerProxy::DID_HANDLE; VERIFY_AND_RESET_MOCKS(); @@ -1174,32 +1234,32 @@ TEST_F(InputHandlerProxyTest, GestureFlingWithInvalidTimestamp) { gesture_.globalX = fling_global_point.x; gesture_.globalY = fling_global_point.y; gesture_.modifiers = modifiers; - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, FlingScrollBegin()) .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED)); EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); // Event though a time stamp was provided for the fling event, it will be // ignored as its too far in the past relative to the first animate call's // timestamp. - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); base::TimeTicks time = base::TimeTicks() + start_time_offset + base::TimeDelta::FromSeconds(1); - input_handler_->Animate(time); + Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); // Further animation ticks should update the fling as usual. - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Lt(0)))) .WillOnce(testing::Return(scroll_result_did_scroll_)); time += base::TimeDelta::FromMilliseconds(10); - input_handler_->Animate(time); + Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); EXPECT_CALL(mock_input_handler_, ScrollEnd()); gesture_.type = WebInputEvent::GestureFlingCancel; @@ -1208,8 +1268,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingWithInvalidTimestamp) { VERIFY_AND_RESET_MOCKS(); } -TEST_F(InputHandlerProxyTest, - GestureScrollOnImplThreadFlagClearedAfterFling) { +TEST_P(InputHandlerProxyTest, GestureScrollOnImplThreadFlagClearedAfterFling) { // We shouldn't send any events to the widget for this gesture. expected_disposition_ = InputHandlerProxy::DID_HANDLE; VERIFY_AND_RESET_MOCKS(); @@ -1238,7 +1297,7 @@ TEST_F(InputHandlerProxyTest, fling_point, fling_global_point, modifiers); - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, FlingScrollBegin()) .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED)); EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); @@ -1247,28 +1306,28 @@ TEST_F(InputHandlerProxyTest, // a GestureFlingStart is sent. EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing()); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); // The first animate call should let us pick up an animation start time, but // we shouldn't actually move anywhere just yet. The first frame after the // fling start will typically include the last scroll from the gesture that // lead to the scroll (either wheel or gesture scroll), so there should be no // visible hitch. - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10); - input_handler_->Animate(time); + Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); // The second call should start scrolling in the -X direction. - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Lt(0)))) .WillOnce(testing::Return(scroll_result_did_scroll_)); time += base::TimeDelta::FromMilliseconds(100); - input_handler_->Animate(time); + Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); EXPECT_CALL(mock_input_handler_, ScrollEnd()); gesture_.type = WebInputEvent::GestureFlingCancel; @@ -1281,7 +1340,7 @@ TEST_F(InputHandlerProxyTest, VERIFY_AND_RESET_MOCKS(); } -TEST_F(InputHandlerProxyTest, +TEST_P(InputHandlerProxyTest, BeginScrollWhenGestureScrollOnImplThreadFlagIsSet) { // We shouldn't send any events to the widget for this gesture. expected_disposition_ = InputHandlerProxy::DID_HANDLE; @@ -1308,7 +1367,7 @@ TEST_F(InputHandlerProxyTest, int modifiers = WebInputEvent::ControlKey | WebInputEvent::AltKey; gesture_ = CreateFling(blink::WebGestureDeviceTouchscreen, fling_delta, fling_point, fling_global_point, modifiers); - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, FlingScrollBegin()) .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED)); EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); @@ -1317,7 +1376,7 @@ TEST_F(InputHandlerProxyTest, // a GestureFlingStart is sent. EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing()); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); // gesture_scroll_on_impl_thread_ is still true when this scroll begins. As a // result, this scroll begin will cancel the previous fling. @@ -1334,7 +1393,7 @@ TEST_F(InputHandlerProxyTest, VERIFY_AND_RESET_MOCKS(); } -TEST_F(InputHandlerProxyTest, GestureFlingStopsAtContentEdge) { +TEST_P(InputHandlerProxyTest, GestureFlingStopsAtContentEdge) { // We shouldn't send any events to the widget for this gesture. expected_disposition_ = InputHandlerProxy::DID_HANDLE; VERIFY_AND_RESET_MOCKS(); @@ -1348,15 +1407,15 @@ TEST_F(InputHandlerProxyTest, GestureFlingStopsAtContentEdge) { EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED)); EXPECT_CALL(mock_input_handler_, ScrollEnd()); - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); // The first animate doesn't cause any scrolling. - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10); - input_handler_->Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + Animate(time); + VERIFY_AND_RESET_MOCKS(); // The second animate starts scrolling in the positive X and Y directions. EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) @@ -1366,10 +1425,10 @@ TEST_F(InputHandlerProxyTest, GestureFlingStopsAtContentEdge) { testing::Property(&gfx::Vector2dF::y, testing::Lt(0)))) .WillOnce(testing::Return(scroll_result_did_scroll_)); EXPECT_CALL(mock_input_handler_, ScrollEnd()); - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); time += base::TimeDelta::FromMilliseconds(100); - input_handler_->Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + Animate(time); + VERIFY_AND_RESET_MOCKS(); // The third animate overscrolls in the positive Y direction but scrolls // somewhat. @@ -1397,13 +1456,13 @@ TEST_F(InputHandlerProxyTest, GestureFlingStopsAtContentEdge) { &DidOverscrollParams::current_fling_velocity, testing::Property(&gfx::Vector2dF::y, testing::Lt(0)))))); EXPECT_CALL(mock_input_handler_, ScrollEnd()); - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); time += base::TimeDelta::FromMilliseconds(100); - input_handler_->Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + Animate(time); + VERIFY_AND_RESET_MOCKS(); // The next call to animate will no longer scroll vertically. - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED)); EXPECT_CALL(mock_input_handler_, @@ -1412,11 +1471,11 @@ TEST_F(InputHandlerProxyTest, GestureFlingStopsAtContentEdge) { .WillOnce(testing::Return(scroll_result_did_scroll_)); EXPECT_CALL(mock_input_handler_, ScrollEnd()); time += base::TimeDelta::FromMilliseconds(100); - input_handler_->Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + Animate(time); + VERIFY_AND_RESET_MOCKS(); } -TEST_F(InputHandlerProxyTest, GestureFlingNotCancelledBySmallTimeDelta) { +TEST_P(InputHandlerProxyTest, GestureFlingNotCancelledBySmallTimeDelta) { // We shouldn't send any events to the widget for this gesture. expected_disposition_ = InputHandlerProxy::DID_HANDLE; VERIFY_AND_RESET_MOCKS(); @@ -1444,39 +1503,39 @@ TEST_F(InputHandlerProxyTest, GestureFlingNotCancelledBySmallTimeDelta) { fling_point, fling_global_point, modifiers); - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, FlingScrollBegin()) .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED)); EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); // With an animation timestamp equivalent to the starting timestamp, the // animation will simply be rescheduled. - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); - input_handler_->Animate(time); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); + Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing()); // A small time delta should not stop the fling, even if the client // reports no scrolling. - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Lt(0)))) .WillOnce(testing::Return(scroll_result_did_not_scroll_)); time += base::TimeDelta::FromMicroseconds(5); - input_handler_->Animate(time); + Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing()); // A time delta of zero should not stop the fling, and neither should it // trigger scrolling on the client. - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); - input_handler_->Animate(time); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); + Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing()); // Lack of movement on the client, with a non-trivial scroll delta, should @@ -1487,13 +1546,13 @@ TEST_F(InputHandlerProxyTest, GestureFlingNotCancelledBySmallTimeDelta) { testing::Property(&gfx::Vector2dF::x, testing::Lt(1)))) .WillOnce(testing::Return(scroll_result_did_not_scroll_)); time += base::TimeDelta::FromMilliseconds(100); - input_handler_->Animate(time); + Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); EXPECT_FALSE(input_handler_->gesture_scroll_on_impl_thread_for_testing()); } -TEST_F(InputHandlerProxyTest, GestureFlingCancelledAfterBothAxesStopScrolling) { +TEST_P(InputHandlerProxyTest, GestureFlingCancelledAfterBothAxesStopScrolling) { cc::InputHandlerScrollResult overscroll; overscroll.did_scroll = true; overscroll.did_overscroll_root = true; @@ -1507,7 +1566,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingCancelledAfterBothAxesStopScrolling) { gesture_.type = WebInputEvent::GestureScrollBegin; gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen; EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); // On the fling start, we should schedule an animation but not actually start // scrolling. @@ -1517,25 +1576,25 @@ TEST_F(InputHandlerProxyTest, GestureFlingCancelledAfterBothAxesStopScrolling) { gesture_.data.flingStart.velocityY = fling_delta.y; EXPECT_CALL(mock_input_handler_, FlingScrollBegin()) .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED)); - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); // The first animate doesn't cause any scrolling. - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10); - input_handler_->Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + Animate(time); + VERIFY_AND_RESET_MOCKS(); // The second animate starts scrolling in the positive X and Y directions. - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::y, testing::Lt(0)))) .WillOnce(testing::Return(scroll_result_did_scroll_)); time += base::TimeDelta::FromMilliseconds(10); - input_handler_->Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + Animate(time); + VERIFY_AND_RESET_MOCKS(); // The third animate hits the bottom content edge. overscroll.accumulated_root_overscroll = gfx::Vector2dF(0, 100); @@ -1556,20 +1615,20 @@ TEST_F(InputHandlerProxyTest, GestureFlingCancelledAfterBothAxesStopScrolling) { testing::Field( &DidOverscrollParams::current_fling_velocity, testing::Property(&gfx::Vector2dF::y, testing::Lt(0)))))); - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); time += base::TimeDelta::FromMilliseconds(10); - input_handler_->Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + Animate(time); + VERIFY_AND_RESET_MOCKS(); // The next call to animate will no longer scroll vertically. - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::y, testing::Eq(0)))) .WillOnce(testing::Return(scroll_result_did_scroll_)); time += base::TimeDelta::FromMilliseconds(10); - input_handler_->Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + Animate(time); + VERIFY_AND_RESET_MOCKS(); // The next call will hit the right edge. overscroll.accumulated_root_overscroll = gfx::Vector2dF(100, 100); @@ -1592,20 +1651,20 @@ TEST_F(InputHandlerProxyTest, GestureFlingCancelledAfterBothAxesStopScrolling) { testing::Property(&gfx::Vector2dF::x, testing::Lt(0)))))); EXPECT_CALL(mock_input_handler_, ScrollEnd()); time += base::TimeDelta::FromMilliseconds(10); - input_handler_->Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + Animate(time); + VERIFY_AND_RESET_MOCKS(); // The next call to animate will no longer scroll horizontally or vertically, // and the fling should be cancelled. - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(0); + EXPECT_SET_NEEDS_ANIMATE_INPUT(0); EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::_)).Times(0); time += base::TimeDelta::FromMilliseconds(10); - input_handler_->Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + Animate(time); + VERIFY_AND_RESET_MOCKS(); EXPECT_FALSE(input_handler_->gesture_scroll_on_impl_thread_for_testing()); } -TEST_F(InputHandlerProxyTest, MultiTouchPointHitTestNegative) { +TEST_P(InputHandlerProxyTest, MultiTouchPointHitTestNegative) { // None of the three touch points fall in the touch region. So the event // should be dropped. expected_disposition_ = InputHandlerProxy::DROP_EVENT; @@ -1632,7 +1691,7 @@ TEST_F(InputHandlerProxyTest, MultiTouchPointHitTestNegative) { VERIFY_AND_RESET_MOCKS(); } -TEST_F(InputHandlerProxyTest, MultiTouchPointHitTestPositive) { +TEST_P(InputHandlerProxyTest, MultiTouchPointHitTestPositive) { // One of the touch points is on a touch-region. So the event should be sent // to the main thread. expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE; @@ -1661,7 +1720,7 @@ TEST_F(InputHandlerProxyTest, MultiTouchPointHitTestPositive) { VERIFY_AND_RESET_MOCKS(); } -TEST_F(InputHandlerProxyTest, GestureFlingCancelledByKeyboardEvent) { +TEST_P(InputHandlerProxyTest, GestureFlingCancelledByKeyboardEvent) { // We shouldn't send any events to the widget for this gesture. expected_disposition_ = InputHandlerProxy::DID_HANDLE; VERIFY_AND_RESET_MOCKS(); @@ -1672,7 +1731,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingCancelledByKeyboardEvent) { gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen; EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing()); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); // Keyboard events received during a scroll should have no effect. WebKeyboardEvent key_event; @@ -1680,7 +1739,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingCancelledByKeyboardEvent) { EXPECT_EQ(InputHandlerProxy::DID_NOT_HANDLE, input_handler_->HandleInputEvent(key_event)); EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing()); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); // On the fling start, animation should be scheduled, but no scrolling occurs. gesture_.type = WebInputEvent::GestureFlingStart; @@ -1689,22 +1748,22 @@ TEST_F(InputHandlerProxyTest, GestureFlingCancelledByKeyboardEvent) { gesture_.data.flingStart.velocityY = fling_delta.y; EXPECT_CALL(mock_input_handler_, FlingScrollBegin()) .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED)); - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing()); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); // Keyboard events received during a fling should cancel the active fling. EXPECT_CALL(mock_input_handler_, ScrollEnd()); EXPECT_EQ(InputHandlerProxy::DID_NOT_HANDLE, input_handler_->HandleInputEvent(key_event)); EXPECT_FALSE(input_handler_->gesture_scroll_on_impl_thread_for_testing()); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); // The call to animate should have no effect, as the fling was cancelled. base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10); - input_handler_->Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + Animate(time); + VERIFY_AND_RESET_MOCKS(); // A fling cancel should be dropped, as there is nothing to cancel. gesture_.type = WebInputEvent::GestureFlingCancel; @@ -1713,7 +1772,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingCancelledByKeyboardEvent) { EXPECT_FALSE(input_handler_->gesture_scroll_on_impl_thread_for_testing()); } -TEST_F(InputHandlerProxyTest, GestureFlingWithNegativeTimeDelta) { +TEST_P(InputHandlerProxyTest, GestureFlingWithNegativeTimeDelta) { // We shouldn't send any events to the widget for this gesture. expected_disposition_ = InputHandlerProxy::DID_HANDLE; VERIFY_AND_RESET_MOCKS(); @@ -1741,36 +1800,36 @@ TEST_F(InputHandlerProxyTest, GestureFlingWithNegativeTimeDelta) { fling_point, fling_global_point, modifiers); - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, FlingScrollBegin()) .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED)); EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_)); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); // If we get a negative time delta, that is, the Animation tick time happens // before the fling's start time then we should *not* try scrolling and // instead reset the fling start time. - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::_)).Times(0); time -= base::TimeDelta::FromMilliseconds(5); - input_handler_->Animate(time); + Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); // The first call should have reset the start time so subsequent calls should // generate scroll events. - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Lt(0)))) .WillOnce(testing::Return(scroll_result_did_scroll_)); - input_handler_->Animate(time + base::TimeDelta::FromMilliseconds(1)); + Animate(time + base::TimeDelta::FromMilliseconds(1)); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); + VERIFY_AND_RESET_MOCKS(); EXPECT_CALL(mock_input_handler_, ScrollEnd()); gesture_.type = WebInputEvent::GestureFlingCancel; @@ -1779,7 +1838,7 @@ TEST_F(InputHandlerProxyTest, GestureFlingWithNegativeTimeDelta) { VERIFY_AND_RESET_MOCKS(); } -TEST_F(InputHandlerProxyTest, FlingBoost) { +TEST_P(InputHandlerProxyTest, FlingBoost) { base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10); base::TimeTicks time = base::TimeTicks() + dt; base::TimeTicks last_animate_time = time; @@ -1810,13 +1869,13 @@ TEST_F(InputHandlerProxyTest, FlingBoost) { time += dt; float expected_delta = (time - last_animate_time).InSecondsF() * -fling_delta.x; - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Eq(expected_delta)))) .WillOnce(testing::Return(scroll_result_did_scroll_)); - input_handler_->Animate(time); + Animate(time); last_animate_time = time; VERIFY_AND_RESET_MOCKS(); @@ -1834,13 +1893,13 @@ TEST_F(InputHandlerProxyTest, FlingBoost) { // Animate calls within the deferred cancellation window should continue. time += dt; expected_delta = (time - last_animate_time).InSecondsF() * -fling_delta.x; - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Eq(expected_delta)))) .WillOnce(testing::Return(scroll_result_did_scroll_)); - input_handler_->Animate(time); + Animate(time); last_animate_time = time; VERIFY_AND_RESET_MOCKS(); @@ -1860,13 +1919,13 @@ TEST_F(InputHandlerProxyTest, FlingBoost) { time += dt; // Note we get *2x* as much delta because 2 flings have combined. expected_delta = 2 * (time - last_animate_time).InSecondsF() * -fling_delta.x; - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Eq(expected_delta)))) .WillOnce(testing::Return(scroll_result_did_scroll_)); - input_handler_->Animate(time); + Animate(time); last_animate_time = time; VERIFY_AND_RESET_MOCKS(); @@ -1886,13 +1945,13 @@ TEST_F(InputHandlerProxyTest, FlingBoost) { time += dt; // Note we get *3x* as much delta because 3 flings have combined. expected_delta = 3 * (time - last_animate_time).InSecondsF() * -fling_delta.x; - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Eq(expected_delta)))) .WillOnce(testing::Return(scroll_result_did_scroll_)); - input_handler_->Animate(time); + Animate(time); last_animate_time = time; VERIFY_AND_RESET_MOCKS(); @@ -1909,12 +1968,12 @@ TEST_F(InputHandlerProxyTest, FlingBoost) { time += base::TimeDelta::FromMilliseconds(100); EXPECT_CALL(mock_input_handler_, ScrollEnd()); - input_handler_->Animate(time); + Animate(time); VERIFY_AND_RESET_MOCKS(); } -TEST_F(InputHandlerProxyTest, NoFlingBoostIfScrollTargetsDifferentLayer) { +TEST_P(InputHandlerProxyTest, NoFlingBoostIfScrollTargetsDifferentLayer) { base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10); base::TimeTicks time = base::TimeTicks() + dt; WebFloatPoint fling_delta = WebFloatPoint(1000, 0); @@ -1944,7 +2003,7 @@ TEST_F(InputHandlerProxyTest, NoFlingBoostIfScrollTargetsDifferentLayer) { VERIFY_AND_RESET_MOCKS(); } -TEST_F(InputHandlerProxyTest, NoFlingBoostIfScrollDelayed) { +TEST_P(InputHandlerProxyTest, NoFlingBoostIfScrollDelayed) { base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10); base::TimeTicks time = base::TimeTicks() + dt; WebFloatPoint fling_delta = WebFloatPoint(1000, 0); @@ -1976,12 +2035,12 @@ TEST_F(InputHandlerProxyTest, NoFlingBoostIfScrollDelayed) { EXPECT_CALL(mock_input_handler_, ScrollEnd()); EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED)); - input_handler_->Animate(time); + Animate(time); VERIFY_AND_RESET_MOCKS(); } -TEST_F(InputHandlerProxyTest, NoFlingBoostIfNotAnimated) { +TEST_P(InputHandlerProxyTest, NoFlingBoostIfNotAnimated) { base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10); base::TimeTicks time = base::TimeTicks() + dt; WebFloatPoint fling_delta = WebFloatPoint(1000, 0); @@ -1993,8 +2052,8 @@ TEST_F(InputHandlerProxyTest, NoFlingBoostIfNotAnimated) { time += dt; EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::_)) .WillOnce(testing::Return(scroll_result_did_scroll_)); - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); - input_handler_->Animate(time); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); + Animate(time); // Cancel the fling after long delay of no animate. The fling cancellation // should be deferred to allow fling boosting events to arrive. @@ -2028,7 +2087,7 @@ TEST_F(InputHandlerProxyTest, NoFlingBoostIfNotAnimated) { VERIFY_AND_RESET_MOCKS(); } -TEST_F(InputHandlerProxyTest, NoFlingBoostIfFlingInDifferentDirection) { +TEST_P(InputHandlerProxyTest, NoFlingBoostIfFlingInDifferentDirection) { base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10); base::TimeTicks time = base::TimeTicks() + dt; WebFloatPoint fling_delta = WebFloatPoint(1000, 0); @@ -2059,18 +2118,18 @@ TEST_F(InputHandlerProxyTest, NoFlingBoostIfFlingInDifferentDirection) { // velocity. time += dt; float expected_delta = dt.InSecondsF() * -orthogonal_fling_delta.y; - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::y, testing::Eq(expected_delta)))) .WillOnce(testing::Return(scroll_result_did_scroll_)); - input_handler_->Animate(time); + Animate(time); VERIFY_AND_RESET_MOCKS(); } -TEST_F(InputHandlerProxyTest, NoFlingBoostIfScrollInDifferentDirection) { +TEST_P(InputHandlerProxyTest, NoFlingBoostIfScrollInDifferentDirection) { base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10); base::TimeTicks time = base::TimeTicks() + dt; WebFloatPoint fling_delta = WebFloatPoint(1000, 0); @@ -2115,7 +2174,7 @@ TEST_F(InputHandlerProxyTest, NoFlingBoostIfScrollInDifferentDirection) { VERIFY_AND_RESET_MOCKS(); } -TEST_F(InputHandlerProxyTest, NoFlingBoostIfFlingTooSlow) { +TEST_P(InputHandlerProxyTest, NoFlingBoostIfFlingTooSlow) { base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10); base::TimeTicks time = base::TimeTicks() + dt; WebFloatPoint fling_delta = WebFloatPoint(1000, 0); @@ -2144,18 +2203,18 @@ TEST_F(InputHandlerProxyTest, NoFlingBoostIfFlingTooSlow) { // Note that the new fling delta uses the *slow*, unboosted fling velocity. time += dt; float expected_delta = dt.InSecondsF() * -small_fling_delta.x; - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::Property(&gfx::Vector2dF::x, testing::Eq(expected_delta)))) .WillOnce(testing::Return(scroll_result_did_scroll_)); - input_handler_->Animate(time); + Animate(time); VERIFY_AND_RESET_MOCKS(); } -TEST_F(InputHandlerProxyTest, NoFlingBoostIfPreventBoostingFlagIsSet) { +TEST_P(InputHandlerProxyTest, NoFlingBoostIfPreventBoostingFlagIsSet) { base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10); base::TimeTicks time = base::TimeTicks() + dt; WebFloatPoint fling_delta = WebFloatPoint(1000, 0); @@ -2175,7 +2234,7 @@ TEST_F(InputHandlerProxyTest, NoFlingBoostIfPreventBoostingFlagIsSet) { // VERIFY_AND_RESET_MOCKS already called by CancelFling } -TEST_F(InputHandlerProxyTest, FlingBoostTerminatedDuringScrollSequence) { +TEST_P(InputHandlerProxyTest, FlingBoostTerminatedDuringScrollSequence) { base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10); base::TimeTicks time = base::TimeTicks() + dt; base::TimeTicks last_animate_time = time; @@ -2215,7 +2274,7 @@ TEST_F(InputHandlerProxyTest, FlingBoostTerminatedDuringScrollSequence) { EXPECT_CALL(mock_input_handler_, ScrollEnd()); EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED)); - input_handler_->Animate(time); + Animate(time); VERIFY_AND_RESET_MOCKS(); @@ -2245,32 +2304,40 @@ TEST_F(InputHandlerProxyTest, FlingBoostTerminatedDuringScrollSequence) { VERIFY_AND_RESET_MOCKS(); } -TEST_F(InputHandlerProxyTest, DidReceiveInputEvent_ForFling) { +TEST_P(InputHandlerProxyTest, DidReceiveInputEvent_ForFling) { testing::StrictMock<MockInputHandlerProxyClientWithDidAnimateForInput> mock_client; input_handler_.reset( new content::InputHandlerProxy(&mock_input_handler_, &mock_client)); + if (install_synchronous_handler_) { + input_handler_->SetOnlySynchronouslyAnimateRootFlings( + &mock_synchronous_input_handler_); + } + mock_input_handler_.set_is_scrolling_root(synchronous_root_scroll_); gesture_.type = WebInputEvent::GestureFlingStart; WebFloatPoint fling_delta = WebFloatPoint(100, 100); gesture_.data.flingStart.velocityX = fling_delta.x; gesture_.data.flingStart.velocityY = fling_delta.y; - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_)) .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED)); EXPECT_CALL(mock_input_handler_, ScrollEnd()); EXPECT_EQ(InputHandlerProxy::DID_HANDLE, input_handler_->HandleInputEvent(gesture_)); - testing::Mock::VerifyAndClearExpectations(&mock_input_handler_); - testing::Mock::VerifyAndClearExpectations(&mock_client); + VERIFY_AND_RESET_MOCKS(); - EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()); + EXPECT_SET_NEEDS_ANIMATE_INPUT(1); EXPECT_CALL(mock_client, DidAnimateForInput()); base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10); - input_handler_->Animate(time); + Animate(time); - testing::Mock::VerifyAndClearExpectations(&mock_client); + VERIFY_AND_RESET_MOCKS(); } +INSTANTIATE_TEST_CASE_P(AnimateInput, + InputHandlerProxyTest, + testing::ValuesIn(test_types)); + } // namespace } // namespace content diff --git a/content/renderer/input/synchronous_input_handler_proxy.h b/content/renderer/input/synchronous_input_handler_proxy.h new file mode 100644 index 0000000..8f84aad --- /dev/null +++ b/content/renderer/input/synchronous_input_handler_proxy.h @@ -0,0 +1,45 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CONTENT_RENDERER_INPUT_SYNCHRONOUS_INPUT_HANDLER_PROXY_H_ +#define CONTENT_RENDERER_INPUT_SYNCHRONOUS_INPUT_HANDLER_PROXY_H_ + +#include "base/time/time.h" + +namespace content { + +class CONTENT_EXPORT SynchronousInputHandler { + public: + // Informs the Android WebView embedder that a fling animation is running, and + // that it should call SynchronouslyAnimate() if it wants to execute that + // animation. The embedder/app may choose to override and ignore the + // request for animation. + virtual void SetNeedsSynchronousAnimateInput() = 0; +}; + +// Android WebView requires synchronous scrolling from the WebView application. +// This interface provides support for that behaviour. The WebView embedder will +// act as the InputHandler for controlling the timing of input (fling) +// animations. +class CONTENT_EXPORT SynchronousInputHandlerProxy { + public: + // Tell the proxy that we will control the timing of root fling animations + // from the SynchronousInputHandler. Once this is set, the InputHandler is + // not requested to Animate() the InputHandlerProxy for root layer flings. + // Instead, requests for animation will go to the SynchronousInputHandler and + // animation ticks will only come back through SynchronouslyAnimate(). + // Non-root flings are not affected. + virtual void SetOnlySynchronouslyAnimateRootFlings( + SynchronousInputHandler* synchronous_input_handler) = 0; + + // Tick input (fling) animations. This may happen out of phase with the frame + // timing, or not at all, as it is controlled by the WebView application. When + // it returns, it expects the animation scroll offsets to be visible to the + // application. + virtual void SynchronouslyAnimate(base::TimeTicks time) = 0; +}; + +} // namespace content + +#endif // CONTENT_RENDERER_INPUT_SYNCHRONOUS_INPUT_HANDLER_PROXY_H_ |