summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordanakj <danakj@chromium.org>2015-09-09 14:36:16 -0700
committerCommit bot <commit-bot@chromium.org>2015-09-09 21:37:01 +0000
commite9f830c3b57371a0b3d090f48be2545a58eba3d6 (patch)
tree273dd1a308ceeb80d66cc96fab9d6e7ebdfa0f97
parenta2c9f2ae93b9920f1ddeb01042e9b1a431106e71 (diff)
downloadchromium_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}
-rw-r--r--android_webview/browser/browser_view_renderer.cc16
-rw-r--r--android_webview/browser/browser_view_renderer.h7
-rw-r--r--cc/input/input_handler.h6
-rw-r--r--cc/input/layer_scroll_offset_delegate.h5
-rw-r--r--cc/trees/layer_tree_host_impl.cc74
-rw-r--r--cc/trees/layer_tree_host_impl.h8
-rw-r--r--cc/trees/layer_tree_host_impl_unittest.cc15
-rw-r--r--content/browser/android/in_process/synchronous_compositor_impl.cc38
-rw-r--r--content/browser/android/in_process/synchronous_compositor_impl.h12
-rw-r--r--content/browser/android/in_process/synchronous_compositor_registry.cc17
-rw-r--r--content/browser/android/in_process/synchronous_compositor_registry.h5
-rw-r--r--content/browser/android/in_process/synchronous_input_event_filter.cc5
-rw-r--r--content/browser/android/in_process/synchronous_input_event_filter.h6
-rw-r--r--content/content_renderer.gypi1
-rw-r--r--content/public/browser/android/synchronous_compositor.h4
-rw-r--r--content/public/browser/android/synchronous_compositor_client.h3
-rw-r--r--content/public/test/test_synchronous_compositor_android.h1
-rw-r--r--content/renderer/input/input_event_filter.cc7
-rw-r--r--content/renderer/input/input_event_filter.h12
-rw-r--r--content/renderer/input/input_event_filter_unittest.cc4
-rw-r--r--content/renderer/input/input_handler_manager.cc9
-rw-r--r--content/renderer/input/input_handler_manager_client.h7
-rw-r--r--content/renderer/input/input_handler_proxy.cc38
-rw-r--r--content/renderer/input/input_handler_proxy.h18
-rw-r--r--content/renderer/input/input_handler_proxy_unittest.cc483
-rw-r--r--content/renderer/input/synchronous_input_handler_proxy.h45
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_