summaryrefslogtreecommitdiffstats
path: root/content/renderer/input
diff options
context:
space:
mode:
authorkhushalsagar <khushalsagar@chromium.org>2015-11-23 14:50:36 -0800
committerCommit bot <commit-bot@chromium.org>2015-11-23 22:51:42 +0000
commit3a8d056562f51c44bbbf8a1b7dd670af4d058350 (patch)
treee93a16aa0a9bc971abf92c10fe5da0e3d0b87e9e /content/renderer/input
parente7325fc3acb3de298d65726950c4e040b7ac9ab4 (diff)
downloadchromium_src-3a8d056562f51c44bbbf8a1b7dd670af4d058350.zip
chromium_src-3a8d056562f51c44bbbf8a1b7dd670af4d058350.tar.gz
chromium_src-3a8d056562f51c44bbbf8a1b7dd670af4d058350.tar.bz2
Move content/renderer input handling for web input events to ui.
The InputHandlerProxy in content/renderer implements the logic for sending the intercepted web input events to the compositor. Move this logic to ui to be used by mus/blimp. BUG=550531 Review URL: https://codereview.chromium.org/1415953004 Cr-Commit-Position: refs/heads/master@{#361207}
Diffstat (limited to 'content/renderer/input')
-rw-r--r--content/renderer/input/input_event_filter.cc4
-rw-r--r--content/renderer/input/input_event_filter.h9
-rw-r--r--content/renderer/input/input_handler_manager.cc8
-rw-r--r--content/renderer/input/input_handler_manager_client.h7
-rw-r--r--content/renderer/input/input_handler_proxy.cc1048
-rw-r--r--content/renderer/input/input_handler_proxy.h189
-rw-r--r--content/renderer/input/input_handler_proxy_client.h49
-rw-r--r--content/renderer/input/input_handler_proxy_unittest.cc2478
-rw-r--r--content/renderer/input/input_handler_wrapper.cc17
-rw-r--r--content/renderer/input/input_handler_wrapper.h23
-rw-r--r--content/renderer/input/input_scroll_elasticity_controller.cc410
-rw-r--r--content/renderer/input/input_scroll_elasticity_controller.h148
-rw-r--r--content/renderer/input/input_scroll_elasticity_controller_unittest.cc387
-rw-r--r--content/renderer/input/synchronous_input_handler_proxy.h73
14 files changed, 52 insertions, 4798 deletions
diff --git a/content/renderer/input/input_event_filter.cc b/content/renderer/input/input_event_filter.cc
index 6b648c7..0647685 100644
--- a/content/renderer/input/input_event_filter.cc
+++ b/content/renderer/input/input_event_filter.cc
@@ -17,6 +17,7 @@
#include "content/public/common/content_switches.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_sender.h"
+#include "ui/events/blink/synchronous_input_handler_proxy.h"
#include "ui/gfx/geometry/vector2d_f.h"
using blink::WebInputEvent;
@@ -57,7 +58,8 @@ void InputEventFilter::SetBoundHandler(const Handler& handler) {
void InputEventFilter::DidAddInputHandler(
int routing_id,
- SynchronousInputHandlerProxy* synchronous_input_handler_proxy) {
+ ui::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 2f87d57..e2d18f3 100644
--- a/content/renderer/input/input_event_filter.h
+++ b/content/renderer/input/input_event_filter.h
@@ -20,8 +20,8 @@ namespace base {
class SingleThreadTaskRunner;
}
-namespace cc {
-class InputHandler;
+namespace ui {
+class SynchronousInputHandlerProxy;
}
namespace IPC {
@@ -39,8 +39,6 @@ class Sender;
namespace content {
-class SynchronousInputHandlerProxy;
-
class CONTENT_EXPORT InputEventFilter : public InputHandlerManagerClient,
public IPC::MessageFilter {
public:
@@ -62,7 +60,8 @@ class CONTENT_EXPORT InputEventFilter : public InputHandlerManagerClient,
void SetBoundHandler(const Handler& handler) override;
void DidAddInputHandler(
int routing_id,
- SynchronousInputHandlerProxy* synchronous_input_handler_proxy) override;
+ ui::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_handler_manager.cc b/content/renderer/input/input_handler_manager.cc
index cbc9a15..85f229d 100644
--- a/content/renderer/input/input_handler_manager.cc
+++ b/content/renderer/input/input_handler_manager.cc
@@ -11,12 +11,14 @@
#include "base/trace_event/trace_event.h"
#include "cc/input/input_handler.h"
#include "components/scheduler/renderer/renderer_scheduler.h"
+#include "content/common/input/web_input_event_traits.h"
#include "content/renderer/input/input_event_filter.h"
#include "content/renderer/input/input_handler_manager_client.h"
#include "content/renderer/input/input_handler_wrapper.h"
-#include "content/renderer/input/input_scroll_elasticity_controller.h"
+#include "ui/events/blink/input_handler_proxy.h"
using blink::WebInputEvent;
+using ui::InputHandlerProxy;
using scheduler::RendererScheduler;
namespace content {
@@ -137,6 +139,8 @@ InputEventAckState InputHandlerManager::HandleInputEvent(
const WebInputEvent* input_event,
ui::LatencyInfo* latency_info) {
DCHECK(task_runner_->BelongsToCurrentThread());
+ TRACE_EVENT1("input,benchmark", "InputHandlerManager::HandleInputEvent",
+ "type", WebInputEventTraits::GetName(input_event->type));
auto it = input_handlers_.find(routing_id);
if (it == input_handlers_.end()) {
@@ -146,6 +150,8 @@ InputEventAckState InputHandlerManager::HandleInputEvent(
return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
}
+ TRACE_EVENT1("input", "InputHandlerManager::HandleInputEvent",
+ "result", "EventSentToInputHandlerProxy");
InputHandlerProxy* proxy = it->second->input_handler_proxy();
InputEventAckState input_event_ack_state = InputEventDispositionToAck(
proxy->HandleInputEventWithLatencyInfo(*input_event, latency_info));
diff --git a/content/renderer/input/input_handler_manager_client.h b/content/renderer/input/input_handler_manager_client.h
index 61cc5e6..9455af3 100644
--- a/content/renderer/input/input_handler_manager_client.h
+++ b/content/renderer/input/input_handler_manager_client.h
@@ -24,9 +24,12 @@ namespace blink {
class WebInputEvent;
}
+namespace ui {
+class SynchronousInputHandlerProxy;
+}
+
namespace content {
struct DidOverscrollParams;
-class SynchronousInputHandlerProxy;
class CONTENT_EXPORT InputHandlerManagerClient {
public:
@@ -46,7 +49,7 @@ class CONTENT_EXPORT InputHandlerManagerClient {
// Called from the compositor thread.
virtual void DidAddInputHandler(
int routing_id,
- SynchronousInputHandlerProxy* synchronous_handler) = 0;
+ ui::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
deleted file mode 100644
index 255492f..0000000
--- a/content/renderer/input/input_handler_proxy.cc
+++ /dev/null
@@ -1,1048 +0,0 @@
-// Copyright 2013 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.
-
-#include "content/renderer/input/input_handler_proxy.h"
-
-#include <algorithm>
-
-#include "base/auto_reset.h"
-#include "base/command_line.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/metrics/histogram.h"
-#include "base/single_thread_task_runner.h"
-#include "base/thread_task_runner_handle.h"
-#include "base/trace_event/trace_event.h"
-#include "content/common/input/did_overscroll_params.h"
-#include "content/common/input/web_input_event_traits.h"
-#include "content/public/common/content_switches.h"
-#include "content/renderer/input/input_handler_proxy_client.h"
-#include "content/renderer/input/input_scroll_elasticity_controller.h"
-#include "third_party/WebKit/public/platform/Platform.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
-#include "ui/events/latency_info.h"
-#include "ui/gfx/geometry/point_conversions.h"
-
-using blink::WebFloatPoint;
-using blink::WebFloatSize;
-using blink::WebGestureEvent;
-using blink::WebInputEvent;
-using blink::WebMouseEvent;
-using blink::WebMouseWheelEvent;
-using blink::WebPoint;
-using blink::WebTouchEvent;
-using blink::WebTouchPoint;
-
-namespace {
-
-// Maximum time between a fling event's timestamp and the first |Animate| call
-// for the fling curve to use the fling timestamp as the initial animation time.
-// Two frames allows a minor delay between event creation and the first animate.
-const double kMaxSecondsFromFlingTimestampToFirstAnimate = 2. / 60.;
-
-// Threshold for determining whether a fling scroll delta should have caused the
-// client to scroll.
-const float kScrollEpsilon = 0.1f;
-
-// Minimum fling velocity required for the active fling and new fling for the
-// two to accumulate.
-const double kMinBoostFlingSpeedSquare = 350. * 350.;
-
-// Minimum velocity for the active touch scroll to preserve (boost) an active
-// fling for which cancellation has been deferred.
-const double kMinBoostTouchScrollSpeedSquare = 150 * 150.;
-
-// Timeout window after which the active fling will be cancelled if no animation
-// ticks, scrolls or flings of sufficient velocity relative to the current fling
-// are received. The default value on Android native views is 40ms, but we use a
-// slightly increased value to accomodate small IPC message delays.
-const double kFlingBoostTimeoutDelaySeconds = 0.05;
-
-gfx::Vector2dF ToClientScrollIncrement(const WebFloatSize& increment) {
- return gfx::Vector2dF(-increment.width, -increment.height);
-}
-
-double InSecondsF(const base::TimeTicks& time) {
- return (time - base::TimeTicks()).InSecondsF();
-}
-
-bool ShouldSuppressScrollForFlingBoosting(
- const gfx::Vector2dF& current_fling_velocity,
- const WebGestureEvent& scroll_update_event,
- double time_since_last_boost_event,
- double time_since_last_fling_animate) {
- DCHECK_EQ(WebInputEvent::GestureScrollUpdate, scroll_update_event.type);
-
- gfx::Vector2dF dx(scroll_update_event.data.scrollUpdate.deltaX,
- scroll_update_event.data.scrollUpdate.deltaY);
- if (gfx::DotProduct(current_fling_velocity, dx) <= 0)
- return false;
-
- if (time_since_last_fling_animate > kFlingBoostTimeoutDelaySeconds)
- return false;
-
- if (time_since_last_boost_event < 0.001)
- return true;
-
- // TODO(jdduke): Use |scroll_update_event.data.scrollUpdate.velocity{X,Y}|.
- // The scroll must be of sufficient velocity to maintain the active fling.
- const gfx::Vector2dF scroll_velocity =
- gfx::ScaleVector2d(dx, 1. / time_since_last_boost_event);
- if (scroll_velocity.LengthSquared() < kMinBoostTouchScrollSpeedSquare)
- return false;
-
- return true;
-}
-
-bool ShouldBoostFling(const gfx::Vector2dF& current_fling_velocity,
- const WebGestureEvent& fling_start_event) {
- DCHECK_EQ(WebInputEvent::GestureFlingStart, fling_start_event.type);
-
- gfx::Vector2dF new_fling_velocity(
- fling_start_event.data.flingStart.velocityX,
- fling_start_event.data.flingStart.velocityY);
-
- if (gfx::DotProduct(current_fling_velocity, new_fling_velocity) <= 0)
- return false;
-
- if (current_fling_velocity.LengthSquared() < kMinBoostFlingSpeedSquare)
- return false;
-
- if (new_fling_velocity.LengthSquared() < kMinBoostFlingSpeedSquare)
- return false;
-
- return true;
-}
-
-WebGestureEvent ObtainGestureScrollBegin(const WebGestureEvent& event) {
- WebGestureEvent scroll_begin_event = event;
- scroll_begin_event.type = WebInputEvent::GestureScrollBegin;
- scroll_begin_event.data.scrollBegin.deltaXHint = 0;
- scroll_begin_event.data.scrollBegin.deltaYHint = 0;
- return scroll_begin_event;
-}
-
-void ReportInputEventLatencyUma(const WebInputEvent& event,
- const ui::LatencyInfo& latency_info) {
- if (!(event.type == WebInputEvent::GestureScrollBegin ||
- event.type == WebInputEvent::GestureScrollUpdate ||
- event.type == WebInputEvent::GesturePinchBegin ||
- event.type == WebInputEvent::GesturePinchUpdate ||
- event.type == WebInputEvent::GestureFlingStart)) {
- return;
- }
-
- ui::LatencyInfo::LatencyMap::const_iterator it =
- latency_info.latency_components().find(std::make_pair(
- ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0));
-
- if (it == latency_info.latency_components().end())
- return;
-
- base::TimeDelta delta = base::TimeTicks::Now() - it->second.event_time;
- for (size_t i = 0; i < it->second.event_count; ++i) {
- switch (event.type) {
- case blink::WebInputEvent::GestureScrollBegin:
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "Event.Latency.RendererImpl.GestureScrollBegin",
- delta.InMicroseconds(), 1, 1000000, 100);
- break;
- case blink::WebInputEvent::GestureScrollUpdate:
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- // So named for historical reasons.
- "Event.Latency.RendererImpl.GestureScroll2",
- delta.InMicroseconds(), 1, 1000000, 100);
- break;
- case blink::WebInputEvent::GesturePinchBegin:
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "Event.Latency.RendererImpl.GesturePinchBegin",
- delta.InMicroseconds(), 1, 1000000, 100);
- break;
- case blink::WebInputEvent::GesturePinchUpdate:
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "Event.Latency.RendererImpl.GesturePinchUpdate",
- delta.InMicroseconds(), 1, 1000000, 100);
- break;
- case blink::WebInputEvent::GestureFlingStart:
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "Event.Latency.RendererImpl.GestureFlingStart",
- delta.InMicroseconds(), 1, 1000000, 100);
- break;
- default:
- NOTREACHED();
- break;
- }
- }
-}
-
-} // namespace
-
-namespace content {
-
-InputHandlerProxy::InputHandlerProxy(cc::InputHandler* input_handler,
- InputHandlerProxyClient* client)
- : 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
- gesture_scroll_on_impl_thread_(false),
- gesture_pinch_on_impl_thread_(false),
- fling_may_be_active_on_main_thread_(false),
- disallow_horizontal_fling_scroll_(false),
- disallow_vertical_fling_scroll_(false),
- has_fling_animation_started_(false),
- uma_latency_reporting_enabled_(base::TimeTicks::IsHighResolution()) {
- DCHECK(client);
- input_handler_->BindToClient(this);
- smooth_scroll_enabled_ = base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableSmoothScrolling);
- cc::ScrollElasticityHelper* scroll_elasticity_helper =
- input_handler_->CreateScrollElasticityHelper();
- if (scroll_elasticity_helper) {
- scroll_elasticity_controller_.reset(
- new InputScrollElasticityController(scroll_elasticity_helper));
- }
-}
-
-InputHandlerProxy::~InputHandlerProxy() {}
-
-void InputHandlerProxy::WillShutdown() {
- scroll_elasticity_controller_.reset();
- input_handler_ = NULL;
- client_->WillShutdown();
-}
-
-InputHandlerProxy::EventDisposition
-InputHandlerProxy::HandleInputEventWithLatencyInfo(
- const WebInputEvent& event,
- ui::LatencyInfo* latency_info) {
- DCHECK(input_handler_);
-
- if (uma_latency_reporting_enabled_)
- ReportInputEventLatencyUma(event, *latency_info);
-
- TRACE_EVENT_WITH_FLOW1("input,benchmark",
- "LatencyInfo.Flow",
- TRACE_ID_DONT_MANGLE(latency_info->trace_id()),
- TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
- "step", "HandleInputEventImpl");
-
- scoped_ptr<cc::SwapPromiseMonitor> latency_info_swap_promise_monitor =
- input_handler_->CreateLatencyInfoSwapPromiseMonitor(latency_info);
- InputHandlerProxy::EventDisposition disposition = HandleInputEvent(event);
- return disposition;
-}
-
-InputHandlerProxy::EventDisposition InputHandlerProxy::HandleInputEvent(
- const WebInputEvent& event) {
- DCHECK(input_handler_);
- TRACE_EVENT1("input,benchmark", "InputHandlerProxy::HandleInputEvent",
- "type", WebInputEventTraits::GetName(event.type));
-
- if (FilterInputEventForFlingBoosting(event))
- return DID_HANDLE;
-
- switch (event.type) {
- case WebInputEvent::MouseWheel:
- return HandleMouseWheel(static_cast<const WebMouseWheelEvent&>(event));
-
- case WebInputEvent::GestureScrollBegin:
- return HandleGestureScrollBegin(
- static_cast<const WebGestureEvent&>(event));
-
- case WebInputEvent::GestureScrollUpdate:
- return HandleGestureScrollUpdate(
- static_cast<const WebGestureEvent&>(event));
-
- case WebInputEvent::GestureScrollEnd:
- return HandleGestureScrollEnd(static_cast<const WebGestureEvent&>(event));
-
- case WebInputEvent::GesturePinchBegin: {
- DCHECK(!gesture_pinch_on_impl_thread_);
- const WebGestureEvent& gesture_event =
- static_cast<const WebGestureEvent&>(event);
- if (gesture_event.sourceDevice == blink::WebGestureDeviceTouchpad &&
- input_handler_->HaveWheelEventHandlersAt(
- gfx::Point(gesture_event.x, gesture_event.y))) {
- return DID_NOT_HANDLE;
- } else {
- input_handler_->PinchGestureBegin();
- gesture_pinch_on_impl_thread_ = true;
- return DID_HANDLE;
- }
- }
-
- case WebInputEvent::GesturePinchEnd:
- if (gesture_pinch_on_impl_thread_) {
- gesture_pinch_on_impl_thread_ = false;
- input_handler_->PinchGestureEnd();
- return DID_HANDLE;
- } else {
- return DID_NOT_HANDLE;
- }
-
- case WebInputEvent::GesturePinchUpdate: {
- if (gesture_pinch_on_impl_thread_) {
- const WebGestureEvent& gesture_event =
- static_cast<const WebGestureEvent&>(event);
- if (gesture_event.data.pinchUpdate.zoomDisabled)
- return DROP_EVENT;
- input_handler_->PinchGestureUpdate(
- gesture_event.data.pinchUpdate.scale,
- gfx::Point(gesture_event.x, gesture_event.y));
- return DID_HANDLE;
- } else {
- return DID_NOT_HANDLE;
- }
- }
-
- case WebInputEvent::GestureFlingStart:
- return HandleGestureFlingStart(
- *static_cast<const WebGestureEvent*>(&event));
-
- case WebInputEvent::GestureFlingCancel:
- if (CancelCurrentFling())
- return DID_HANDLE;
- else if (!fling_may_be_active_on_main_thread_)
- return DROP_EVENT;
- return DID_NOT_HANDLE;
-
- case WebInputEvent::TouchStart:
- return HandleTouchStart(static_cast<const WebTouchEvent&>(event));
-
- case WebInputEvent::MouseMove: {
- const WebMouseEvent& mouse_event =
- static_cast<const WebMouseEvent&>(event);
- // TODO(tony): Ignore when mouse buttons are down?
- // TODO(davemoore): This should never happen, but bug #326635 showed some
- // surprising crashes.
- CHECK(input_handler_);
- input_handler_->MouseMoveAt(gfx::Point(mouse_event.x, mouse_event.y));
- return DID_NOT_HANDLE;
- }
-
- default:
- if (WebInputEvent::isKeyboardEventType(event.type)) {
- // Only call |CancelCurrentFling()| if a fling was active, as it will
- // otherwise disrupt an in-progress touch scroll.
- if (fling_curve_)
- CancelCurrentFling();
- }
- break;
- }
-
- return DID_NOT_HANDLE;
-}
-
-InputHandlerProxy::EventDisposition InputHandlerProxy::HandleMouseWheel(
- const WebMouseWheelEvent& wheel_event) {
- InputHandlerProxy::EventDisposition result = DID_NOT_HANDLE;
- cc::InputHandlerScrollResult scroll_result;
-
- // TODO(ccameron): The rail information should be pushed down into
- // InputHandler.
- gfx::Vector2dF scroll_delta(
- wheel_event.railsMode != WebInputEvent::RailsModeVertical
- ? -wheel_event.deltaX
- : 0,
- wheel_event.railsMode != WebInputEvent::RailsModeHorizontal
- ? -wheel_event.deltaY
- : 0);
-
- if (wheel_event.scrollByPage) {
- // TODO(jamesr): We don't properly handle scroll by page in the compositor
- // thread, so punt it to the main thread. http://crbug.com/236639
- result = DID_NOT_HANDLE;
- } else if (!wheel_event.canScroll) {
- // Wheel events with |canScroll| == false will not trigger scrolling,
- // only event handlers. Forward to the main thread.
- result = DID_NOT_HANDLE;
- } else if (smooth_scroll_enabled_ && !wheel_event.hasPreciseScrollingDeltas) {
- cc::InputHandler::ScrollStatus scroll_status =
- input_handler_->ScrollAnimated(gfx::Point(wheel_event.x, wheel_event.y),
- scroll_delta);
- switch (scroll_status) {
- case cc::InputHandler::SCROLL_STARTED:
- result = DID_HANDLE;
- break;
- case cc::InputHandler::SCROLL_IGNORED:
- result = DROP_EVENT;
- break;
- default:
- result = DID_NOT_HANDLE;
- break;
- }
- } else {
- cc::InputHandler::ScrollStatus scroll_status = input_handler_->ScrollBegin(
- gfx::Point(wheel_event.x, wheel_event.y), cc::InputHandler::WHEEL);
- switch (scroll_status) {
- case cc::InputHandler::SCROLL_STARTED: {
- TRACE_EVENT_INSTANT2("input",
- "InputHandlerProxy::handle_input wheel scroll",
- TRACE_EVENT_SCOPE_THREAD, "deltaX",
- scroll_delta.x(), "deltaY", scroll_delta.y());
- gfx::Point scroll_point(wheel_event.x, wheel_event.y);
- scroll_result = input_handler_->ScrollBy(scroll_point, scroll_delta);
- HandleOverscroll(scroll_point, scroll_result);
- input_handler_->ScrollEnd();
- result = scroll_result.did_scroll ? DID_HANDLE : DROP_EVENT;
- break;
- }
- case cc::InputHandler::SCROLL_IGNORED:
- // TODO(jamesr): This should be DROP_EVENT, but in cases where we fail
- // to properly sync scrollability it's safer to send the event to the
- // main thread. Change back to DROP_EVENT once we have synchronization
- // bugs sorted out.
- result = DID_NOT_HANDLE;
- break;
- case cc::InputHandler::SCROLL_UNKNOWN:
- case cc::InputHandler::SCROLL_ON_MAIN_THREAD:
- result = DID_NOT_HANDLE;
- break;
- case cc::InputHandler::ScrollStatusCount:
- NOTREACHED();
- break;
- }
- }
-
- // Send the event and its disposition to the elasticity controller to update
- // the over-scroll animation. If the event is to be handled on the main
- // thread, the event and its disposition will be sent to the elasticity
- // controller after being handled on the main thread.
- if (scroll_elasticity_controller_ && result != DID_NOT_HANDLE) {
- // Note that the call to the elasticity controller is made asynchronously,
- // to minimize divergence between main thread and impl thread event
- // handling paths.
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(&InputScrollElasticityController::ObserveWheelEventAndResult,
- scroll_elasticity_controller_->GetWeakPtr(), wheel_event,
- scroll_result));
- }
- return result;
-}
-
-InputHandlerProxy::EventDisposition InputHandlerProxy::HandleGestureScrollBegin(
- const WebGestureEvent& gesture_event) {
- if (gesture_scroll_on_impl_thread_)
- CancelCurrentFling();
-
-#ifndef NDEBUG
- DCHECK(!expect_scroll_update_end_);
- expect_scroll_update_end_ = true;
-#endif
- cc::InputHandler::ScrollStatus scroll_status;
- if (gesture_event.data.scrollBegin.targetViewport) {
- scroll_status = input_handler_->RootScrollBegin(cc::InputHandler::GESTURE);
- } else {
- scroll_status = input_handler_->ScrollBegin(
- gfx::Point(gesture_event.x, gesture_event.y),
- cc::InputHandler::GESTURE);
- }
- UMA_HISTOGRAM_ENUMERATION("Renderer4.CompositorScrollHitTestResult",
- scroll_status,
- cc::InputHandler::ScrollStatusCount);
- switch (scroll_status) {
- case cc::InputHandler::SCROLL_STARTED:
- TRACE_EVENT_INSTANT0("input",
- "InputHandlerProxy::handle_input gesture scroll",
- TRACE_EVENT_SCOPE_THREAD);
- gesture_scroll_on_impl_thread_ = true;
- return DID_HANDLE;
- case cc::InputHandler::SCROLL_UNKNOWN:
- case cc::InputHandler::SCROLL_ON_MAIN_THREAD:
- return DID_NOT_HANDLE;
- case cc::InputHandler::SCROLL_IGNORED:
- return DROP_EVENT;
- case cc::InputHandler::ScrollStatusCount:
- NOTREACHED();
- break;
- }
- return DID_NOT_HANDLE;
-}
-
-InputHandlerProxy::EventDisposition
-InputHandlerProxy::HandleGestureScrollUpdate(
- const WebGestureEvent& gesture_event) {
-#ifndef NDEBUG
- DCHECK(expect_scroll_update_end_);
-#endif
-
- if (!gesture_scroll_on_impl_thread_ && !gesture_pinch_on_impl_thread_)
- return DID_NOT_HANDLE;
-
- gfx::Point scroll_point(gesture_event.x, gesture_event.y);
- gfx::Vector2dF scroll_delta(-gesture_event.data.scrollUpdate.deltaX,
- -gesture_event.data.scrollUpdate.deltaY);
- cc::InputHandlerScrollResult scroll_result = input_handler_->ScrollBy(
- scroll_point, scroll_delta);
- HandleOverscroll(scroll_point, scroll_result);
- return scroll_result.did_scroll ? DID_HANDLE : DROP_EVENT;
-}
-
-InputHandlerProxy::EventDisposition InputHandlerProxy::HandleGestureScrollEnd(
- const WebGestureEvent& gesture_event) {
-#ifndef NDEBUG
- DCHECK(expect_scroll_update_end_);
- expect_scroll_update_end_ = false;
-#endif
- input_handler_->ScrollEnd();
- if (!gesture_scroll_on_impl_thread_)
- return DID_NOT_HANDLE;
- gesture_scroll_on_impl_thread_ = false;
- return DID_HANDLE;
-}
-
-InputHandlerProxy::EventDisposition InputHandlerProxy::HandleGestureFlingStart(
- const WebGestureEvent& gesture_event) {
- cc::InputHandler::ScrollStatus scroll_status =
- cc::InputHandler::SCROLL_ON_MAIN_THREAD;
- switch (gesture_event.sourceDevice) {
- case blink::WebGestureDeviceTouchpad:
- if (gesture_event.data.flingStart.targetViewport) {
- scroll_status = input_handler_->RootScrollBegin(
- cc::InputHandler::NON_BUBBLING_GESTURE);
- } else {
- scroll_status = input_handler_->ScrollBegin(
- gfx::Point(gesture_event.x, gesture_event.y),
- cc::InputHandler::NON_BUBBLING_GESTURE);
- }
- break;
- case blink::WebGestureDeviceTouchscreen:
- if (!gesture_scroll_on_impl_thread_)
- scroll_status = cc::InputHandler::SCROLL_ON_MAIN_THREAD;
- else
- scroll_status = input_handler_->FlingScrollBegin();
- break;
- case blink::WebGestureDeviceUninitialized:
- NOTREACHED();
- return DID_NOT_HANDLE;
- }
-
-#ifndef NDEBUG
- expect_scroll_update_end_ = false;
-#endif
-
- switch (scroll_status) {
- case cc::InputHandler::SCROLL_STARTED: {
- if (gesture_event.sourceDevice == blink::WebGestureDeviceTouchpad)
- input_handler_->ScrollEnd();
-
- const float vx = gesture_event.data.flingStart.velocityX;
- const float vy = gesture_event.data.flingStart.velocityY;
- current_fling_velocity_ = gfx::Vector2dF(vx, vy);
- DCHECK(!current_fling_velocity_.IsZero());
- fling_curve_.reset(client_->CreateFlingAnimationCurve(
- gesture_event.sourceDevice,
- WebFloatPoint(vx, vy),
- blink::WebSize()));
- disallow_horizontal_fling_scroll_ = !vx;
- disallow_vertical_fling_scroll_ = !vy;
- TRACE_EVENT_ASYNC_BEGIN2("input,benchmark",
- "InputHandlerProxy::HandleGestureFling::started",
- this, "vx", vx, "vy", vy);
- // Note that the timestamp will only be used to kickstart the animation if
- // its sufficiently close to the timestamp of the first call |Animate()|.
- has_fling_animation_started_ = false;
- fling_parameters_.startTime = gesture_event.timeStampSeconds;
- fling_parameters_.delta = WebFloatPoint(vx, vy);
- fling_parameters_.point = WebPoint(gesture_event.x, gesture_event.y);
- fling_parameters_.globalPoint =
- WebPoint(gesture_event.globalX, gesture_event.globalY);
- fling_parameters_.modifiers = gesture_event.modifiers;
- fling_parameters_.sourceDevice = gesture_event.sourceDevice;
- RequestAnimation();
- return DID_HANDLE;
- }
- case cc::InputHandler::SCROLL_UNKNOWN:
- case cc::InputHandler::SCROLL_ON_MAIN_THREAD: {
- TRACE_EVENT_INSTANT0("input",
- "InputHandlerProxy::HandleGestureFling::"
- "scroll_on_main_thread",
- TRACE_EVENT_SCOPE_THREAD);
- gesture_scroll_on_impl_thread_ = false;
- fling_may_be_active_on_main_thread_ = true;
- return DID_NOT_HANDLE;
- }
- case cc::InputHandler::SCROLL_IGNORED: {
- TRACE_EVENT_INSTANT0(
- "input",
- "InputHandlerProxy::HandleGestureFling::ignored",
- TRACE_EVENT_SCOPE_THREAD);
- gesture_scroll_on_impl_thread_ = false;
- if (gesture_event.sourceDevice == blink::WebGestureDeviceTouchpad) {
- // We still pass the curve to the main thread if there's nothing
- // scrollable, in case something
- // registers a handler before the curve is over.
- return DID_NOT_HANDLE;
- }
- return DROP_EVENT;
- }
- case cc::InputHandler::ScrollStatusCount:
- NOTREACHED();
- break;
- }
- return DID_NOT_HANDLE;
-}
-
-InputHandlerProxy::EventDisposition InputHandlerProxy::HandleTouchStart(
- const blink::WebTouchEvent& touch_event) {
- for (size_t i = 0; i < touch_event.touchesLength; ++i) {
- if (touch_event.touches[i].state != WebTouchPoint::StatePressed)
- continue;
- if (input_handler_->DoTouchEventsBlockScrollAt(
- gfx::Point(touch_event.touches[i].position.x,
- touch_event.touches[i].position.y))) {
- // TODO(rbyers): We should consider still sending the touch events to
- // main asynchronously (crbug.com/455539).
- return DID_NOT_HANDLE;
- }
- }
- return DROP_EVENT;
-}
-
-bool InputHandlerProxy::FilterInputEventForFlingBoosting(
- const WebInputEvent& event) {
- if (!WebInputEvent::isGestureEventType(event.type))
- return false;
-
- if (!fling_curve_) {
- DCHECK(!deferred_fling_cancel_time_seconds_);
- return false;
- }
-
- const WebGestureEvent& gesture_event =
- static_cast<const WebGestureEvent&>(event);
- if (gesture_event.type == WebInputEvent::GestureFlingCancel) {
- if (gesture_event.data.flingCancel.preventBoosting)
- return false;
-
- if (current_fling_velocity_.LengthSquared() < kMinBoostFlingSpeedSquare)
- return false;
-
- TRACE_EVENT_INSTANT0("input",
- "InputHandlerProxy::FlingBoostStart",
- TRACE_EVENT_SCOPE_THREAD);
- deferred_fling_cancel_time_seconds_ =
- event.timeStampSeconds + kFlingBoostTimeoutDelaySeconds;
- return true;
- }
-
- // A fling is either inactive or is "free spinning", i.e., has yet to be
- // interrupted by a touch gesture, in which case there is nothing to filter.
- if (!deferred_fling_cancel_time_seconds_)
- return false;
-
- // Gestures from a different source should immediately interrupt the fling.
- if (gesture_event.sourceDevice != fling_parameters_.sourceDevice) {
- CancelCurrentFling();
- return false;
- }
-
- switch (gesture_event.type) {
- case WebInputEvent::GestureTapCancel:
- case WebInputEvent::GestureTapDown:
- return false;
-
- case WebInputEvent::GestureScrollBegin:
- if (!input_handler_->IsCurrentlyScrollingLayerAt(
- gfx::Point(gesture_event.x, gesture_event.y),
- fling_parameters_.sourceDevice == blink::WebGestureDeviceTouchpad
- ? cc::InputHandler::NON_BUBBLING_GESTURE
- : cc::InputHandler::GESTURE)) {
- CancelCurrentFling();
- return false;
- }
-
- // TODO(jdduke): Use |gesture_event.data.scrollBegin.delta{X,Y}Hint| to
- // determine if the ScrollBegin should immediately cancel the fling.
- ExtendBoostedFlingTimeout(gesture_event);
- return true;
-
- case WebInputEvent::GestureScrollUpdate: {
- const double time_since_last_boost_event =
- event.timeStampSeconds - last_fling_boost_event_.timeStampSeconds;
- const double time_since_last_fling_animate = std::max(
- 0.0, event.timeStampSeconds - InSecondsF(last_fling_animate_time_));
- if (ShouldSuppressScrollForFlingBoosting(current_fling_velocity_,
- gesture_event,
- time_since_last_boost_event,
- time_since_last_fling_animate)) {
- ExtendBoostedFlingTimeout(gesture_event);
- return true;
- }
-
- CancelCurrentFling();
- return false;
- }
-
- case WebInputEvent::GestureScrollEnd:
- // Clear the last fling boost event *prior* to fling cancellation,
- // preventing insertion of a synthetic GestureScrollBegin.
- last_fling_boost_event_ = WebGestureEvent();
- CancelCurrentFling();
- return true;
-
- case WebInputEvent::GestureFlingStart: {
- DCHECK_EQ(fling_parameters_.sourceDevice, gesture_event.sourceDevice);
-
- bool fling_boosted =
- fling_parameters_.modifiers == gesture_event.modifiers &&
- ShouldBoostFling(current_fling_velocity_, gesture_event);
-
- gfx::Vector2dF new_fling_velocity(
- gesture_event.data.flingStart.velocityX,
- gesture_event.data.flingStart.velocityY);
- DCHECK(!new_fling_velocity.IsZero());
-
- if (fling_boosted)
- current_fling_velocity_ += new_fling_velocity;
- else
- current_fling_velocity_ = new_fling_velocity;
-
- WebFloatPoint velocity(current_fling_velocity_.x(),
- current_fling_velocity_.y());
- deferred_fling_cancel_time_seconds_ = 0;
- disallow_horizontal_fling_scroll_ = !velocity.x;
- disallow_vertical_fling_scroll_ = !velocity.y;
- last_fling_boost_event_ = WebGestureEvent();
- fling_curve_.reset(client_->CreateFlingAnimationCurve(
- gesture_event.sourceDevice,
- velocity,
- blink::WebSize()));
- fling_parameters_.startTime = gesture_event.timeStampSeconds;
- fling_parameters_.delta = velocity;
- fling_parameters_.point = WebPoint(gesture_event.x, gesture_event.y);
- fling_parameters_.globalPoint =
- WebPoint(gesture_event.globalX, gesture_event.globalY);
-
- TRACE_EVENT_INSTANT2("input",
- fling_boosted ? "InputHandlerProxy::FlingBoosted"
- : "InputHandlerProxy::FlingReplaced",
- TRACE_EVENT_SCOPE_THREAD,
- "vx",
- current_fling_velocity_.x(),
- "vy",
- current_fling_velocity_.y());
-
- // The client expects balanced calls between a consumed GestureFlingStart
- // and |DidStopFlinging()|.
- client_->DidStopFlinging();
- return true;
- }
-
- default:
- // All other types of gestures (taps, presses, etc...) will complete the
- // deferred fling cancellation.
- CancelCurrentFling();
- return false;
- }
-}
-
-void InputHandlerProxy::ExtendBoostedFlingTimeout(
- const blink::WebGestureEvent& event) {
- TRACE_EVENT_INSTANT0("input",
- "InputHandlerProxy::ExtendBoostedFlingTimeout",
- TRACE_EVENT_SCOPE_THREAD);
- deferred_fling_cancel_time_seconds_ =
- event.timeStampSeconds + kFlingBoostTimeoutDelaySeconds;
- last_fling_boost_event_ = event;
-}
-
-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(!input_handler_->IsCurrentlyScrollingInnerViewport() ||
- allow_root_animate_);
-
- if (scroll_elasticity_controller_)
- scroll_elasticity_controller_->Animate(time);
-
- if (!fling_curve_)
- return;
-
- last_fling_animate_time_ = time;
- double monotonic_time_sec = InSecondsF(time);
-
- if (deferred_fling_cancel_time_seconds_ &&
- monotonic_time_sec > deferred_fling_cancel_time_seconds_) {
- CancelCurrentFling();
- return;
- }
-
- client_->DidAnimateForInput();
-
- if (!has_fling_animation_started_) {
- has_fling_animation_started_ = true;
- // Guard against invalid, future or sufficiently stale start times, as there
- // are no guarantees fling event and animation timestamps are compatible.
- if (!fling_parameters_.startTime ||
- monotonic_time_sec <= fling_parameters_.startTime ||
- monotonic_time_sec >= fling_parameters_.startTime +
- kMaxSecondsFromFlingTimestampToFirstAnimate) {
- fling_parameters_.startTime = monotonic_time_sec;
- RequestAnimation();
- return;
- }
- }
-
- bool fling_is_active =
- fling_curve_->apply(monotonic_time_sec - fling_parameters_.startTime,
- this);
-
- if (disallow_vertical_fling_scroll_ && disallow_horizontal_fling_scroll_)
- fling_is_active = false;
-
- if (fling_is_active) {
- RequestAnimation();
- } else {
- TRACE_EVENT_INSTANT0("input",
- "InputHandlerProxy::animate::flingOver",
- TRACE_EVENT_SCOPE_THREAD);
- CancelCurrentFling();
- }
-}
-
-void InputHandlerProxy::MainThreadHasStoppedFlinging() {
- fling_may_be_active_on_main_thread_ = false;
- client_->DidStopFlinging();
-}
-
-void InputHandlerProxy::ReconcileElasticOverscrollAndRootScroll() {
- if (scroll_elasticity_controller_)
- scroll_elasticity_controller_->ReconcileStretchAndScroll();
-}
-
-void InputHandlerProxy::UpdateRootLayerStateForSynchronousInputHandler(
- const gfx::ScrollOffset& total_scroll_offset,
- const gfx::ScrollOffset& max_scroll_offset,
- const gfx::SizeF& scrollable_size,
- float page_scale_factor,
- float min_page_scale_factor,
- float max_page_scale_factor) {
- if (synchronous_input_handler_) {
- synchronous_input_handler_->UpdateRootLayerState(
- total_scroll_offset, max_scroll_offset, scrollable_size,
- page_scale_factor, min_page_scale_factor, max_page_scale_factor);
- }
-}
-
-void InputHandlerProxy::SetOnlySynchronouslyAnimateRootFlings(
- SynchronousInputHandler* synchronous_input_handler) {
- allow_root_animate_ = !synchronous_input_handler;
- synchronous_input_handler_ = synchronous_input_handler;
- if (synchronous_input_handler_)
- input_handler_->RequestUpdateForSynchronousInputHandler();
-}
-
-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(synchronous_input_handler_);
- DCHECK(!allow_root_animate_);
- base::AutoReset<bool> reset(&allow_root_animate_, true);
- Animate(time);
-}
-
-void InputHandlerProxy::SynchronouslySetRootScrollOffset(
- const gfx::ScrollOffset& root_offset) {
- DCHECK(synchronous_input_handler_);
- input_handler_->SetSynchronousInputHandlerRootScrollOffset(root_offset);
-}
-
-void InputHandlerProxy::HandleOverscroll(
- const gfx::Point& causal_event_viewport_point,
- const cc::InputHandlerScrollResult& scroll_result) {
- DCHECK(client_);
- if (!scroll_result.did_overscroll_root)
- return;
-
- TRACE_EVENT2("input",
- "InputHandlerProxy::DidOverscroll",
- "dx",
- scroll_result.unused_scroll_delta.x(),
- "dy",
- scroll_result.unused_scroll_delta.y());
-
- DidOverscrollParams params;
- params.accumulated_overscroll = scroll_result.accumulated_root_overscroll;
- params.latest_overscroll_delta = scroll_result.unused_scroll_delta;
- params.current_fling_velocity =
- ToClientScrollIncrement(current_fling_velocity_);
- params.causal_event_viewport_point = gfx::PointF(causal_event_viewport_point);
-
- if (fling_curve_) {
- static const int kFlingOverscrollThreshold = 1;
- disallow_horizontal_fling_scroll_ |=
- std::abs(params.accumulated_overscroll.x()) >=
- kFlingOverscrollThreshold;
- disallow_vertical_fling_scroll_ |=
- std::abs(params.accumulated_overscroll.y()) >=
- kFlingOverscrollThreshold;
- }
-
- client_->DidOverscroll(params);
-}
-
-bool InputHandlerProxy::CancelCurrentFling() {
- if (CancelCurrentFlingWithoutNotifyingClient()) {
- client_->DidStopFlinging();
- return true;
- }
- return false;
-}
-
-bool InputHandlerProxy::CancelCurrentFlingWithoutNotifyingClient() {
- bool had_fling_animation = fling_curve_;
- if (had_fling_animation &&
- fling_parameters_.sourceDevice == blink::WebGestureDeviceTouchscreen) {
- input_handler_->ScrollEnd();
- TRACE_EVENT_ASYNC_END0(
- "input",
- "InputHandlerProxy::HandleGestureFling::started",
- this);
- }
-
- TRACE_EVENT_INSTANT1("input",
- "InputHandlerProxy::CancelCurrentFling",
- TRACE_EVENT_SCOPE_THREAD,
- "had_fling_animation",
- had_fling_animation);
- fling_curve_.reset();
- has_fling_animation_started_ = false;
- gesture_scroll_on_impl_thread_ = false;
- current_fling_velocity_ = gfx::Vector2dF();
- fling_parameters_ = blink::WebActiveWheelFlingParameters();
-
- if (deferred_fling_cancel_time_seconds_) {
- deferred_fling_cancel_time_seconds_ = 0;
-
- WebGestureEvent last_fling_boost_event = last_fling_boost_event_;
- last_fling_boost_event_ = WebGestureEvent();
- if (last_fling_boost_event.type == WebInputEvent::GestureScrollBegin ||
- last_fling_boost_event.type == WebInputEvent::GestureScrollUpdate) {
- // Synthesize a GestureScrollBegin, as the original was suppressed.
- HandleInputEvent(ObtainGestureScrollBegin(last_fling_boost_event));
- }
- }
-
- 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_->IsCurrentlyScrollingInnerViewport())
- synchronous_input_handler_->SetNeedsSynchronousAnimateInput();
- else
- input_handler_->SetNeedsAnimateInput();
-}
-
-bool InputHandlerProxy::TouchpadFlingScroll(
- const WebFloatSize& increment) {
- WebMouseWheelEvent synthetic_wheel;
- synthetic_wheel.type = WebInputEvent::MouseWheel;
- synthetic_wheel.deltaX = increment.width;
- synthetic_wheel.deltaY = increment.height;
- synthetic_wheel.hasPreciseScrollingDeltas = true;
- synthetic_wheel.x = fling_parameters_.point.x;
- synthetic_wheel.y = fling_parameters_.point.y;
- synthetic_wheel.globalX = fling_parameters_.globalPoint.x;
- synthetic_wheel.globalY = fling_parameters_.globalPoint.y;
- synthetic_wheel.modifiers = fling_parameters_.modifiers;
-
- InputHandlerProxy::EventDisposition disposition =
- HandleInputEvent(synthetic_wheel);
- switch (disposition) {
- case DID_HANDLE:
- return true;
- case DROP_EVENT:
- break;
- case DID_NOT_HANDLE:
- TRACE_EVENT_INSTANT0("input",
- "InputHandlerProxy::scrollBy::AbortFling",
- TRACE_EVENT_SCOPE_THREAD);
- // If we got a DID_NOT_HANDLE, that means we need to deliver wheels on the
- // main thread. In this case we need to schedule a commit and transfer the
- // fling curve over to the main thread and run the rest of the wheels from
- // there. This can happen when flinging a page that contains a scrollable
- // subarea that we can't scroll on the thread if the fling starts outside
- // the subarea but then is flung "under" the pointer.
- client_->TransferActiveWheelFlingAnimation(fling_parameters_);
- fling_may_be_active_on_main_thread_ = true;
- CancelCurrentFlingWithoutNotifyingClient();
- break;
- }
-
- return false;
-}
-
-bool InputHandlerProxy::scrollBy(const WebFloatSize& increment,
- const WebFloatSize& velocity) {
- WebFloatSize clipped_increment;
- WebFloatSize clipped_velocity;
- if (!disallow_horizontal_fling_scroll_) {
- clipped_increment.width = increment.width;
- clipped_velocity.width = velocity.width;
- }
- if (!disallow_vertical_fling_scroll_) {
- clipped_increment.height = increment.height;
- clipped_velocity.height = velocity.height;
- }
-
- current_fling_velocity_ = clipped_velocity;
-
- // Early out if the increment is zero, but avoid early terimination if the
- // velocity is still non-zero.
- if (clipped_increment == WebFloatSize())
- return clipped_velocity != WebFloatSize();
-
- TRACE_EVENT2("input",
- "InputHandlerProxy::scrollBy",
- "x",
- clipped_increment.width,
- "y",
- clipped_increment.height);
-
- bool did_scroll = false;
-
- switch (fling_parameters_.sourceDevice) {
- case blink::WebGestureDeviceTouchpad:
- did_scroll = TouchpadFlingScroll(clipped_increment);
- break;
- case blink::WebGestureDeviceTouchscreen: {
- clipped_increment = ToClientScrollIncrement(clipped_increment);
- cc::InputHandlerScrollResult scroll_result = input_handler_->ScrollBy(
- fling_parameters_.point, clipped_increment);
- HandleOverscroll(fling_parameters_.point, scroll_result);
- did_scroll = scroll_result.did_scroll;
- } break;
- case blink::WebGestureDeviceUninitialized:
- NOTREACHED();
- return false;
- }
-
- if (did_scroll) {
- fling_parameters_.cumulativeScroll.width += clipped_increment.width;
- fling_parameters_.cumulativeScroll.height += clipped_increment.height;
- }
-
- // It's possible the provided |increment| is sufficiently small as to not
- // trigger a scroll, e.g., with a trivial time delta between fling updates.
- // Return true in this case to prevent early fling termination.
- if (std::abs(clipped_increment.width) < kScrollEpsilon &&
- std::abs(clipped_increment.height) < kScrollEpsilon)
- return true;
-
- return did_scroll;
-}
-
-} // namespace content
diff --git a/content/renderer/input/input_handler_proxy.h b/content/renderer/input/input_handler_proxy.h
deleted file mode 100644
index d234511..0000000
--- a/content/renderer/input/input_handler_proxy.h
+++ /dev/null
@@ -1,189 +0,0 @@
-// Copyright 2013 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_INPUT_HANDLER_PROXY_H_
-#define CONTENT_RENDERER_INPUT_INPUT_HANDLER_PROXY_H_
-
-#include "base/basictypes.h"
-#include "base/containers/hash_tables.h"
-#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"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
-
-namespace content {
-
-namespace test {
-class InputHandlerProxyTest;
-}
-
-class InputHandlerProxyClient;
-class InputScrollElasticityController;
-
-// This class is a proxy between the content input event filtering and the
-// compositor's input handling logic. InputHandlerProxy instances live entirely
-// on the compositor thread. Each InputHandler instance handles input events
-// 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,
- InputHandlerProxyClient* client);
- ~InputHandlerProxy() override;
-
- InputScrollElasticityController* scroll_elasticity_controller() {
- return scroll_elasticity_controller_.get();
- }
-
- enum EventDisposition {
- DID_HANDLE,
- DID_NOT_HANDLE,
- DROP_EVENT
- };
- EventDisposition HandleInputEventWithLatencyInfo(
- const blink::WebInputEvent& event,
- ui::LatencyInfo* latency_info);
- EventDisposition HandleInputEvent(const blink::WebInputEvent& event);
-
- // cc::InputHandlerClient implementation.
- void WillShutdown() override;
- void Animate(base::TimeTicks time) override;
- void MainThreadHasStoppedFlinging() override;
- void ReconcileElasticOverscrollAndRootScroll() override;
- void UpdateRootLayerStateForSynchronousInputHandler(
- const gfx::ScrollOffset& total_scroll_offset,
- const gfx::ScrollOffset& max_scroll_offset,
- const gfx::SizeF& scrollable_size,
- float page_scale_factor,
- float min_page_scale_factor,
- float max_page_scale_factor) override;
-
- // SynchronousInputHandlerProxy implementation.
- void SetOnlySynchronouslyAnimateRootFlings(
- SynchronousInputHandler* synchronous_input_handler) override;
- void SynchronouslyAnimate(base::TimeTicks time) override;
- void SynchronouslySetRootScrollOffset(
- const gfx::ScrollOffset& root_offset) override;
-
- // blink::WebGestureCurveTarget implementation.
- bool scrollBy(const blink::WebFloatSize& offset,
- const blink::WebFloatSize& velocity) override;
-
- bool gesture_scroll_on_impl_thread_for_testing() const {
- return gesture_scroll_on_impl_thread_;
- }
-
- private:
- friend class test::InputHandlerProxyTest;
-
- // Helper functions for handling more complicated input events.
- EventDisposition HandleMouseWheel(
- const blink::WebMouseWheelEvent& event);
- EventDisposition HandleGestureScrollBegin(
- const blink::WebGestureEvent& event);
- EventDisposition HandleGestureScrollUpdate(
- const blink::WebGestureEvent& event);
- EventDisposition HandleGestureScrollEnd(
- const blink::WebGestureEvent& event);
- EventDisposition HandleGestureFlingStart(
- const blink::WebGestureEvent& event);
- EventDisposition HandleTouchStart(
- const blink::WebTouchEvent& event);
-
- // Returns true if the event should be suppressed due to to an active,
- // boost-enabled fling, in which case further processing should cease.
- bool FilterInputEventForFlingBoosting(const blink::WebInputEvent& event);
-
- // Schedule a time in the future after which a boost-enabled fling will
- // terminate without further momentum from the user (see |Animate()|).
- void ExtendBoostedFlingTimeout(const blink::WebGestureEvent& event);
-
- // Returns true if we scrolled by the increment.
- bool TouchpadFlingScroll(const blink::WebFloatSize& increment);
-
- // Returns true if we actually had an active fling to cancel, also notifying
- // the client that the fling has ended. Note that if a boosted fling is active
- // and suppressing an active scroll sequence, a synthetic GestureScrollBegin
- // will be injected to resume scrolling.
- bool CancelCurrentFling();
-
- // 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,
- const cc::InputHandlerScrollResult& scroll_result);
-
- scoped_ptr<blink::WebGestureCurve> fling_curve_;
- // Parameters for the active fling animation, stored in case we need to
- // transfer it out later.
- blink::WebActiveWheelFlingParameters fling_parameters_;
-
- InputHandlerProxyClient* client_;
- cc::InputHandler* input_handler_;
-
- // Time at which an active fling should expire due to a deferred cancellation
- // event. A call to |Animate()| after this time will end the fling.
- double deferred_fling_cancel_time_seconds_;
-
- // The last event that extended the lifetime of the boosted fling. If the
- // event was a scroll gesture, a GestureScrollBegin will be inserted if the
- // 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
- bool gesture_scroll_on_impl_thread_;
- bool gesture_pinch_on_impl_thread_;
- // This is always false when there are no flings on the main thread, but
- // conservative in the sense that we might not be actually flinging when it is
- // true.
- bool fling_may_be_active_on_main_thread_;
- // The axes on which the current fling is allowed to scroll. If a given fling
- // has overscrolled on a particular axis, further fling scrolls on that axis
- // will be disabled.
- bool disallow_horizontal_fling_scroll_;
- bool disallow_vertical_fling_scroll_;
-
- // Whether an active fling has seen an |Animate()| call. This is useful for
- // determining if the fling start time should be re-initialized.
- bool has_fling_animation_started_;
-
- // Non-zero only within the scope of |scrollBy|.
- gfx::Vector2dF current_fling_velocity_;
-
- // Used to animate rubber-band over-scroll effect on Mac.
- scoped_ptr<InputScrollElasticityController> scroll_elasticity_controller_;
-
- bool smooth_scroll_enabled_;
-
- bool uma_latency_reporting_enabled_;
-
- base::TimeTicks last_fling_animate_time_;
-
- DISALLOW_COPY_AND_ASSIGN(InputHandlerProxy);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_INPUT_INPUT_HANDLER_PROXY_H_
diff --git a/content/renderer/input/input_handler_proxy_client.h b/content/renderer/input/input_handler_proxy_client.h
deleted file mode 100644
index 53b4bc9..0000000
--- a/content/renderer/input/input_handler_proxy_client.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2013 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_INPUT_HANDLER_PROXY_CLIENT_H_
-#define CONTENT_RENDERER_INPUT_INPUT_HANDLER_PROXY_CLIENT_H_
-
-namespace blink {
-class WebGestureCurve;
-struct WebActiveWheelFlingParameters;
-struct WebFloatPoint;
-struct WebSize;
-}
-
-namespace content {
-
-struct DidOverscrollParams;
-
-// All callbacks invoked from the compositor thread.
-class InputHandlerProxyClient {
- public:
- // Called just before the InputHandlerProxy shuts down.
- virtual void WillShutdown() = 0;
-
- // Transfers an active wheel fling animation initiated by a previously
- // handled input event out to the client.
- virtual void TransferActiveWheelFlingAnimation(
- const blink::WebActiveWheelFlingParameters& params) = 0;
-
- // Creates a new fling animation curve instance for device |device_source|
- // with |velocity| and already scrolled |cumulative_scroll| pixels.
- virtual blink::WebGestureCurve* CreateFlingAnimationCurve(
- blink::WebGestureDevice device_source,
- const blink::WebFloatPoint& velocity,
- const blink::WebSize& cumulative_scroll) = 0;
-
- virtual void DidOverscroll(const DidOverscrollParams& params) = 0;
-
- virtual void DidStopFlinging() = 0;
-
- virtual void DidAnimateForInput() = 0;
-
- protected:
- virtual ~InputHandlerProxyClient() {}
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_INPUT_INPUT_HANDLER_PROXY_CLIENT_H_
diff --git a/content/renderer/input/input_handler_proxy_unittest.cc b/content/renderer/input/input_handler_proxy_unittest.cc
deleted file mode 100644
index aee95d8..0000000
--- a/content/renderer/input/input_handler_proxy_unittest.cc
+++ /dev/null
@@ -1,2478 +0,0 @@
-// Copyright 2013 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.
-
-#include "content/renderer/input/input_handler_proxy.h"
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "cc/trees/swap_promise_monitor.h"
-#include "content/common/input/did_overscroll_params.h"
-#include "content/renderer/input/input_handler_proxy_client.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/platform/WebFloatPoint.h"
-#include "third_party/WebKit/public/platform/WebFloatSize.h"
-#include "third_party/WebKit/public/platform/WebGestureCurve.h"
-#include "third_party/WebKit/public/platform/WebPoint.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
-#include "ui/events/latency_info.h"
-#include "ui/gfx/geometry/scroll_offset.h"
-#include "ui/gfx/geometry/size_f.h"
-
-using blink::WebActiveWheelFlingParameters;
-using blink::WebFloatPoint;
-using blink::WebFloatSize;
-using blink::WebGestureDevice;
-using blink::WebGestureEvent;
-using blink::WebInputEvent;
-using blink::WebKeyboardEvent;
-using blink::WebMouseWheelEvent;
-using blink::WebPoint;
-using blink::WebSize;
-using blink::WebTouchEvent;
-using blink::WebTouchPoint;
-using testing::Field;
-
-namespace content {
-namespace test {
-
-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();
-}
-
-WebGestureEvent CreateFling(base::TimeTicks timestamp,
- WebGestureDevice source_device,
- WebFloatPoint velocity,
- WebPoint point,
- WebPoint global_point,
- int modifiers) {
- WebGestureEvent fling;
- fling.type = WebInputEvent::GestureFlingStart;
- fling.sourceDevice = source_device;
- fling.timeStampSeconds = (timestamp - base::TimeTicks()).InSecondsF();
- fling.data.flingStart.velocityX = velocity.x;
- fling.data.flingStart.velocityY = velocity.y;
- fling.x = point.x;
- fling.y = point.y;
- fling.globalX = global_point.x;
- fling.globalY = global_point.y;
- fling.modifiers = modifiers;
- return fling;
-}
-
-WebGestureEvent CreateFling(WebGestureDevice source_device,
- WebFloatPoint velocity,
- WebPoint point,
- WebPoint global_point,
- int modifiers) {
- return CreateFling(base::TimeTicks(),
- source_device,
- velocity,
- point,
- global_point,
- modifiers);
-}
-
-class MockInputHandler : public cc::InputHandler {
- public:
- MockInputHandler() {}
- ~MockInputHandler() override {}
-
- MOCK_METHOD0(PinchGestureBegin, void());
- MOCK_METHOD2(PinchGestureUpdate,
- void(float magnify_delta, const gfx::Point& anchor));
- MOCK_METHOD0(PinchGestureEnd, void());
-
- MOCK_METHOD0(SetNeedsAnimateInput, void());
-
- MOCK_METHOD2(ScrollBegin,
- ScrollStatus(const gfx::Point& viewport_point,
- cc::InputHandler::ScrollInputType type));
- MOCK_METHOD1(RootScrollBegin,
- ScrollStatus(cc::InputHandler::ScrollInputType type));
- MOCK_METHOD2(ScrollAnimated,
- ScrollStatus(const gfx::Point& viewport_point,
- const gfx::Vector2dF& scroll_delta));
- MOCK_METHOD2(ScrollBy,
- cc::InputHandlerScrollResult(
- const gfx::Point& viewport_point,
- const gfx::Vector2dF& scroll_delta));
- MOCK_METHOD2(ScrollVerticallyByPage,
- bool(const gfx::Point& viewport_point,
- cc::ScrollDirection direction));
- MOCK_METHOD0(ScrollEnd, void());
- MOCK_METHOD0(FlingScrollBegin, cc::InputHandler::ScrollStatus());
-
- scoped_ptr<cc::SwapPromiseMonitor> CreateLatencyInfoSwapPromiseMonitor(
- ui::LatencyInfo* latency) override {
- return scoped_ptr<cc::SwapPromiseMonitor>();
- }
-
- cc::ScrollElasticityHelper* CreateScrollElasticityHelper() override {
- return NULL;
- }
-
- void BindToClient(cc::InputHandlerClient* client) override {}
-
- void MouseMoveAt(const gfx::Point& mouse_position) override {}
-
- 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));
-
- MOCK_METHOD0(RequestUpdateForSynchronousInputHandler, void());
- MOCK_METHOD1(SetSynchronousInputHandlerRootScrollOffset,
- void(const gfx::ScrollOffset& root_offset));
-
- bool IsCurrentlyScrollingInnerViewport() 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());
- MOCK_METHOD6(UpdateRootLayerState,
- void(const gfx::ScrollOffset& total_scroll_offset,
- const gfx::ScrollOffset& max_scroll_offset,
- const gfx::SizeF& scrollable_size,
- float page_scale_factor,
- float min_page_scale_factor,
- float max_page_scale_factor));
-};
-
-// A simple WebGestureCurve implementation that flings at a constant velocity
-// indefinitely.
-class FakeWebGestureCurve : public blink::WebGestureCurve {
- public:
- FakeWebGestureCurve(const blink::WebFloatSize& velocity,
- const blink::WebFloatSize& cumulative_scroll)
- : velocity_(velocity), cumulative_scroll_(cumulative_scroll) {}
-
- ~FakeWebGestureCurve() override {}
-
- // Returns false if curve has finished and can no longer be applied.
- bool apply(double time, blink::WebGestureCurveTarget* target) override {
- blink::WebFloatSize displacement(velocity_.width * time,
- velocity_.height * time);
- blink::WebFloatSize increment(
- displacement.width - cumulative_scroll_.width,
- displacement.height - cumulative_scroll_.height);
- cumulative_scroll_ = displacement;
- // scrollBy() could delete this curve if the animation is over, so don't
- // touch any member variables after making that call.
- return target->scrollBy(increment, velocity_);
- }
-
- private:
- blink::WebFloatSize velocity_;
- blink::WebFloatSize cumulative_scroll_;
-
- DISALLOW_COPY_AND_ASSIGN(FakeWebGestureCurve);
-};
-
-class MockInputHandlerProxyClient
- : public content::InputHandlerProxyClient {
- public:
- MockInputHandlerProxyClient() {}
- ~MockInputHandlerProxyClient() override {}
-
- void WillShutdown() override {}
-
- MOCK_METHOD1(TransferActiveWheelFlingAnimation,
- void(const WebActiveWheelFlingParameters&));
-
- blink::WebGestureCurve* CreateFlingAnimationCurve(
- WebGestureDevice deviceSource,
- const WebFloatPoint& velocity,
- const WebSize& cumulative_scroll) override {
- return new FakeWebGestureCurve(
- blink::WebFloatSize(velocity.x, velocity.y),
- blink::WebFloatSize(cumulative_scroll.width, cumulative_scroll.height));
- }
-
- MOCK_METHOD1(DidOverscroll, void(const DidOverscrollParams&));
- void DidStopFlinging() override {}
- void DidAnimateForInput() override {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockInputHandlerProxyClient);
-};
-
-class MockInputHandlerProxyClientWithDidAnimateForInput
- : public MockInputHandlerProxyClient {
- public:
- MockInputHandlerProxyClientWithDidAnimateForInput() {}
- ~MockInputHandlerProxyClientWithDidAnimateForInput() override {}
-
- MOCK_METHOD0(DidAnimateForInput, void());
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockInputHandlerProxyClientWithDidAnimateForInput);
-};
-
-WebTouchPoint CreateWebTouchPoint(WebTouchPoint::State state, float x,
- float y) {
- WebTouchPoint point;
- point.state = state;
- point.screenPosition = WebFloatPoint(x, y);
- point.position = WebFloatPoint(x, y);
- return point;
-}
-
-} // namespace
-
-class InputHandlerProxyTest
- : public testing::Test,
- public testing::WithParamInterface<InputHandlerProxyTestType> {
- public:
- InputHandlerProxyTest()
- : 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_) {
- EXPECT_CALL(mock_input_handler_,
- RequestUpdateForSynchronousInputHandler())
- .Times(1);
- input_handler_->SetOnlySynchronouslyAnimateRootFlings(
- &mock_synchronous_input_handler_);
- }
-
- mock_input_handler_.set_is_scrolling_root(synchronous_root_scroll_);
-
- // Set a default device so tests don't always have to set this.
- gesture_.sourceDevice = blink::WebGestureDeviceTouchpad;
- }
-
- ~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_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,
- WebPoint position) {
- expected_disposition_ = InputHandlerProxy::DID_HANDLE;
- VERIFY_AND_RESET_MOCKS();
-
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
- gesture_.type = WebInputEvent::GestureScrollBegin;
- gesture_.sourceDevice = source_device;
- EXPECT_EQ(expected_disposition_,
- input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
- EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
-
- gesture_ =
- CreateFling(timestamp, source_device, velocity, position, position, 0);
- EXPECT_EQ(expected_disposition_,
- input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
- }
-
- void CancelFling(base::TimeTicks timestamp) {
- gesture_.timeStampSeconds = InSecondsF(timestamp);
- gesture_.type = WebInputEvent::GestureFlingCancel;
- EXPECT_EQ(expected_disposition_,
- input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
- }
-
- void SetSmoothScrollEnabled(bool value) {
- input_handler_->smooth_scroll_enabled_ = value;
- }
-
- 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_;
- InputHandlerProxy::EventDisposition expected_disposition_;
- cc::InputHandlerScrollResult scroll_result_did_scroll_;
- cc::InputHandlerScrollResult scroll_result_did_not_scroll_;
-};
-
-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));
- VERIFY_AND_RESET_MOCKS();
-}
-
-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));
- VERIFY_AND_RESET_MOCKS();
-}
-
-TEST_P(InputHandlerProxyTest, MouseWheelWithPreciseScrollingDeltas) {
- SetSmoothScrollEnabled(true);
- expected_disposition_ = InputHandlerProxy::DID_HANDLE;
- WebMouseWheelEvent wheel;
- wheel.type = WebInputEvent::MouseWheel;
-
- VERIFY_AND_RESET_MOCKS();
-
- // Smooth scroll because hasPreciseScrollingDeltas is set to false.
- wheel.hasPreciseScrollingDeltas = false;
- EXPECT_CALL(mock_input_handler_, ScrollAnimated(::testing::_, ::testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(wheel));
-
- VERIFY_AND_RESET_MOCKS();
-
- // No smooth scroll because hasPreciseScrollingDeltas is set to true.
- wheel.hasPreciseScrollingDeltas = true;
- EXPECT_CALL(mock_input_handler_, ScrollBegin(::testing::_, ::testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
- EXPECT_CALL(mock_input_handler_, ScrollBy(::testing::_, ::testing::_))
- .WillOnce(testing::Return(scroll_result_did_scroll_));
- EXPECT_CALL(mock_input_handler_, ScrollEnd());
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(wheel));
-
- VERIFY_AND_RESET_MOCKS();
-}
-
-TEST_P(InputHandlerProxyTest, MouseWheelScrollIgnored) {
- SetSmoothScrollEnabled(true);
- expected_disposition_ = InputHandlerProxy::DROP_EVENT;
- WebMouseWheelEvent wheel;
- wheel.type = WebInputEvent::MouseWheel;
-
- EXPECT_CALL(mock_input_handler_, ScrollAnimated(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_IGNORED));
-
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(wheel));
- VERIFY_AND_RESET_MOCKS();
-}
-
-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();
-
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
-
- gesture_.type = WebInputEvent::GestureScrollBegin;
- EXPECT_EQ(expected_disposition_,input_handler_->HandleInputEvent(gesture_));
-
- // The event should not be marked as handled if scrolling is not possible.
- expected_disposition_ = InputHandlerProxy::DROP_EVENT;
- VERIFY_AND_RESET_MOCKS();
-
- gesture_.type = WebInputEvent::GestureScrollUpdate;
- gesture_.data.scrollUpdate.deltaY =
- -40; // -Y means scroll down - i.e. in the +Y direction.
- EXPECT_CALL(mock_input_handler_,
- ScrollBy(testing::_,
- testing::Property(&gfx::Vector2dF::y, testing::Gt(0))))
- .WillOnce(testing::Return(scroll_result_did_not_scroll_));
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- // Mark the event as handled if scroll happens.
- expected_disposition_ = InputHandlerProxy::DID_HANDLE;
- VERIFY_AND_RESET_MOCKS();
-
- gesture_.type = WebInputEvent::GestureScrollUpdate;
- gesture_.data.scrollUpdate.deltaY =
- -40; // -Y means scroll down - i.e. in the +Y direction.
- EXPECT_CALL(mock_input_handler_,
- ScrollBy(testing::_,
- testing::Property(&gfx::Vector2dF::y, testing::Gt(0))))
- .WillOnce(testing::Return(scroll_result_did_scroll_));
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- gesture_.type = WebInputEvent::GestureScrollEnd;
- gesture_.data.scrollUpdate.deltaY = 0;
- EXPECT_CALL(mock_input_handler_, ScrollEnd());
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-}
-
-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();
-
- EXPECT_CALL(mock_input_handler_, ScrollBegin(::testing::_, ::testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_ON_MAIN_THREAD));
-
- gesture_.type = WebInputEvent::GestureScrollBegin;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- gesture_.type = WebInputEvent::GestureScrollUpdate;
- gesture_.data.scrollUpdate.deltaY = 40;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- gesture_.type = WebInputEvent::GestureScrollEnd;
- gesture_.data.scrollUpdate.deltaY = 0;
- EXPECT_CALL(mock_input_handler_, ScrollEnd()).WillOnce(testing::Return());
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-}
-
-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
- // react to this gesture sequence and thus we should drop the whole gesture
- // sequence on the floor, except for the ScrollEnd.
- expected_disposition_ = InputHandlerProxy::DROP_EVENT;
- VERIFY_AND_RESET_MOCKS();
-
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_IGNORED));
-
- gesture_.type = WebInputEvent::GestureScrollBegin;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
- gesture_.type = WebInputEvent::GestureScrollEnd;
- EXPECT_CALL(mock_input_handler_, ScrollEnd()).WillOnce(testing::Return());
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-}
-
-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();
-
- EXPECT_CALL(mock_input_handler_, RootScrollBegin(testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
-
- gesture_.type = WebInputEvent::GestureScrollBegin;
- gesture_.data.scrollBegin.targetViewport = true;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-}
-
-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();
-
- gesture_.type = WebInputEvent::GesturePinchBegin;
- EXPECT_CALL(mock_input_handler_, HaveWheelEventHandlersAt(testing::_))
- .WillOnce(testing::Return(false));
- EXPECT_CALL(mock_input_handler_, PinchGestureBegin());
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- gesture_.type = WebInputEvent::GesturePinchUpdate;
- gesture_.data.pinchUpdate.scale = 1.5;
- gesture_.x = 7;
- gesture_.y = 13;
- EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(1.5, gfx::Point(7, 13)));
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- gesture_.type = WebInputEvent::GesturePinchUpdate;
- gesture_.data.pinchUpdate.scale = 0.5;
- gesture_.data.pinchUpdate.zoomDisabled = true;
- gesture_.x = 9;
- gesture_.y = 6;
- EXPECT_EQ(InputHandlerProxy::DROP_EVENT,
- input_handler_->HandleInputEvent(gesture_));
- gesture_.data.pinchUpdate.zoomDisabled = false;
-
- VERIFY_AND_RESET_MOCKS();
-
- gesture_.type = WebInputEvent::GesturePinchUpdate;
- gesture_.data.pinchUpdate.scale = 0.5;
- gesture_.x = 9;
- gesture_.y = 6;
- EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(.5, gfx::Point(9, 6)));
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- gesture_.type = WebInputEvent::GesturePinchEnd;
- EXPECT_CALL(mock_input_handler_, PinchGestureEnd());
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-}
-
-TEST_P(InputHandlerProxyTest, GesturePinchWithWheelHandler) {
- // We will send the synthetic wheel event to the widget.
- expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
- VERIFY_AND_RESET_MOCKS();
-
- gesture_.type = WebInputEvent::GesturePinchBegin;
- EXPECT_CALL(mock_input_handler_, HaveWheelEventHandlersAt(testing::_))
- .WillOnce(testing::Return(true));
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- gesture_.type = WebInputEvent::GesturePinchUpdate;
- gesture_.data.pinchUpdate.scale = 1.5;
- gesture_.x = 7;
- gesture_.y = 13;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- gesture_.type = WebInputEvent::GesturePinchUpdate;
- gesture_.data.pinchUpdate.scale = 0.5;
- gesture_.x = 9;
- gesture_.y = 6;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- gesture_.type = WebInputEvent::GesturePinchEnd;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-}
-
-TEST_P(InputHandlerProxyTest, GesturePinchAfterScrollOnMainThread) {
- // Scrolls will start by being sent to the main thread.
- expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
- VERIFY_AND_RESET_MOCKS();
-
- EXPECT_CALL(mock_input_handler_, ScrollBegin(::testing::_, ::testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_ON_MAIN_THREAD));
-
- gesture_.type = WebInputEvent::GestureScrollBegin;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- gesture_.type = WebInputEvent::GestureScrollUpdate;
- gesture_.data.scrollUpdate.deltaY = 40;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- // However, after the pinch gesture starts, they should go to the impl
- // thread.
- expected_disposition_ = InputHandlerProxy::DID_HANDLE;
- VERIFY_AND_RESET_MOCKS();
-
- gesture_.type = WebInputEvent::GesturePinchBegin;
- EXPECT_CALL(mock_input_handler_, HaveWheelEventHandlersAt(testing::_))
- .WillOnce(testing::Return(false));
- EXPECT_CALL(mock_input_handler_, PinchGestureBegin());
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- gesture_.type = WebInputEvent::GesturePinchUpdate;
- gesture_.data.pinchUpdate.scale = 1.5;
- gesture_.x = 7;
- gesture_.y = 13;
- EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(1.5, gfx::Point(7, 13)));
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- gesture_.type = WebInputEvent::GestureScrollUpdate;
- gesture_.data.scrollUpdate.deltaY =
- -40; // -Y means scroll down - i.e. in the +Y direction.
- EXPECT_CALL(mock_input_handler_,
- ScrollBy(testing::_,
- testing::Property(&gfx::Vector2dF::y, testing::Gt(0))))
- .WillOnce(testing::Return(scroll_result_did_scroll_));
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- gesture_.type = WebInputEvent::GesturePinchUpdate;
- gesture_.data.pinchUpdate.scale = 0.5;
- gesture_.x = 9;
- gesture_.y = 6;
- EXPECT_CALL(mock_input_handler_, PinchGestureUpdate(.5, gfx::Point(9, 6)));
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- gesture_.type = WebInputEvent::GesturePinchEnd;
- EXPECT_CALL(mock_input_handler_, PinchGestureEnd());
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- // After the pinch gesture ends, they should go to back to the main
- // thread.
- expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
- VERIFY_AND_RESET_MOCKS();
-
- gesture_.type = WebInputEvent::GestureScrollEnd;
- gesture_.data.scrollUpdate.deltaY = 0;
- EXPECT_CALL(mock_input_handler_, ScrollEnd())
- .WillOnce(testing::Return());
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-}
-
-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();
-
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
- EXPECT_CALL(mock_input_handler_, ScrollEnd());
- EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
-
- gesture_.type = WebInputEvent::GestureFlingStart;
- gesture_.data.flingStart.velocityX = 10;
- gesture_.sourceDevice = blink::WebGestureDeviceTouchpad;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- // Verify that a GestureFlingCancel during an animation cancels it.
- gesture_.type = WebInputEvent::GestureFlingCancel;
- gesture_.sourceDevice = blink::WebGestureDeviceTouchpad;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-}
-
-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();
-
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_ON_MAIN_THREAD));
-
- gesture_.type = WebInputEvent::GestureFlingStart;
- gesture_.sourceDevice = blink::WebGestureDeviceTouchpad;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- // Since we returned ScrollStatusOnMainThread from scrollBegin, ensure the
- // input handler knows it's scrolling off the impl thread
- ASSERT_FALSE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
-
- VERIFY_AND_RESET_MOCKS();
-
- // Even if we didn't start a fling ourselves, we still need to send the cancel
- // event to the widget.
- gesture_.type = WebInputEvent::GestureFlingCancel;
- gesture_.sourceDevice = blink::WebGestureDeviceTouchpad;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-}
-
-TEST_P(InputHandlerProxyTest, GestureFlingIgnoredTouchpad) {
- expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
- VERIFY_AND_RESET_MOCKS();
-
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_IGNORED));
-
- gesture_.type = WebInputEvent::GestureFlingStart;
- gesture_.sourceDevice = blink::WebGestureDeviceTouchpad;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- expected_disposition_ = InputHandlerProxy::DROP_EVENT;
- VERIFY_AND_RESET_MOCKS();
-
- // Since the previous fling was ignored, we should also be dropping the next
- // fling_cancel.
- gesture_.type = WebInputEvent::GestureFlingCancel;
- gesture_.sourceDevice = blink::WebGestureDeviceTouchpad;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-}
-
-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();
-
- // On the fling start, we should schedule an animation but not actually start
- // scrolling.
- gesture_.type = WebInputEvent::GestureFlingStart;
- WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
- WebPoint fling_point = WebPoint(7, 13);
- WebPoint fling_global_point = WebPoint(17, 23);
- // Note that for trackpad, wheel events with the Control modifier are
- // special (reserved for zoom), so don't set that here.
- int modifiers = WebInputEvent::ShiftKey | WebInputEvent::AltKey;
- gesture_ = CreateFling(blink::WebGestureDeviceTouchpad,
- fling_delta,
- fling_point,
- fling_global_point,
- modifiers);
- 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_));
-
- 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_SET_NEEDS_ANIMATE_INPUT(1);
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .Times(0);
- base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10);
- Animate(time);
-
- VERIFY_AND_RESET_MOCKS();
-
- // The second call should start scrolling in the -X direction.
- 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_,
- ScrollBy(testing::_,
- testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
- .WillOnce(testing::Return(scroll_result_did_scroll_));
- EXPECT_CALL(mock_input_handler_, ScrollEnd());
- time += base::TimeDelta::FromMilliseconds(100);
- Animate(time);
-
- 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.
- // We also should pass the current fling parameters out to the client so the
- // rest of the fling can be
- // transferred to the main thread.
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_ON_MAIN_THREAD));
- EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::_)).Times(0);
- EXPECT_CALL(mock_input_handler_, ScrollEnd()).Times(0);
- // Expected wheel fling animation parameters:
- // *) fling_delta and fling_point should match the original GestureFlingStart
- // event
- // *) startTime should be 10 to match the time parameter of the first
- // Animate() call after the GestureFlingStart
- // *) cumulativeScroll depends on the curve, but since we've animated in the
- // -X direction the X value should be < 0
- EXPECT_CALL(
- mock_client_,
- TransferActiveWheelFlingAnimation(testing::AllOf(
- testing::Field(&WebActiveWheelFlingParameters::delta,
- testing::Eq(fling_delta)),
- testing::Field(&WebActiveWheelFlingParameters::point,
- testing::Eq(fling_point)),
- testing::Field(&WebActiveWheelFlingParameters::globalPoint,
- testing::Eq(fling_global_point)),
- testing::Field(&WebActiveWheelFlingParameters::modifiers,
- testing::Eq(modifiers)),
- testing::Field(&WebActiveWheelFlingParameters::startTime,
- testing::Eq(10)),
- testing::Field(&WebActiveWheelFlingParameters::cumulativeScroll,
- testing::Field(&WebSize::width, testing::Gt(0))))));
- time += base::TimeDelta::FromMilliseconds(100);
- Animate(time);
-
- 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_SET_NEEDS_ANIMATE_INPUT(0);
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .Times(0);
- time += base::TimeDelta::FromMilliseconds(100);
- Animate(time);
-
- // Since we've transferred the fling to the main thread, we need to pass the
- // next GestureFlingCancel to the main
- // thread as well.
- expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
- gesture_.type = WebInputEvent::GestureFlingCancel;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-}
-
-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();
-
- // Start a gesture fling in the -X direction with zero Y movement.
- WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
- WebPoint fling_point = WebPoint(7, 13);
- WebPoint fling_global_point = WebPoint(17, 23);
- // Note that for trackpad, wheel events with the Control modifier are
- // special (reserved for zoom), so don't set that here.
- int modifiers = WebInputEvent::ShiftKey | WebInputEvent::AltKey;
- gesture_ = CreateFling(blink::WebGestureDeviceTouchpad,
- fling_delta,
- fling_point,
- fling_global_point,
- modifiers);
- 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_));
-
- VERIFY_AND_RESET_MOCKS();
-
- // Start the fling animation at time 10. This shouldn't actually scroll, just
- // establish a start time.
- 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);
- Animate(time);
-
- VERIFY_AND_RESET_MOCKS();
-
- // The second call should start scrolling in the -X direction.
- 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_,
- ScrollBy(testing::_,
- testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
- .WillOnce(testing::Return(scroll_result_did_scroll_));
- EXPECT_CALL(mock_input_handler_, ScrollEnd());
- time += base::TimeDelta::FromMilliseconds(100);
- Animate(time);
-
- 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.
- // We also should pass the current fling parameters out to the client so the
- // rest of the fling can be
- // transferred to the main thread.
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_ON_MAIN_THREAD));
- EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::_)).Times(0);
- EXPECT_CALL(mock_input_handler_, ScrollEnd()).Times(0);
-
- // Expected wheel fling animation parameters:
- // *) fling_delta and fling_point should match the original GestureFlingStart
- // event
- // *) startTime should be 10 to match the time parameter of the first
- // Animate() call after the GestureFlingStart
- // *) cumulativeScroll depends on the curve, but since we've animated in the
- // -X direction the X value should be < 0
- EXPECT_CALL(
- mock_client_,
- TransferActiveWheelFlingAnimation(testing::AllOf(
- testing::Field(&WebActiveWheelFlingParameters::delta,
- testing::Eq(fling_delta)),
- testing::Field(&WebActiveWheelFlingParameters::point,
- testing::Eq(fling_point)),
- testing::Field(&WebActiveWheelFlingParameters::globalPoint,
- testing::Eq(fling_global_point)),
- testing::Field(&WebActiveWheelFlingParameters::modifiers,
- testing::Eq(modifiers)),
- testing::Field(&WebActiveWheelFlingParameters::startTime,
- testing::Eq(10)),
- testing::Field(&WebActiveWheelFlingParameters::cumulativeScroll,
- testing::Field(&WebSize::width, testing::Gt(0))))));
- time += base::TimeDelta::FromMilliseconds(100);
- Animate(time);
-
- 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_SET_NEEDS_ANIMATE_INPUT(0);
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .Times(0);
- time += base::TimeDelta::FromMilliseconds(100);
- Animate(time);
-
- VERIFY_AND_RESET_MOCKS();
-
- // Since we've transferred the fling to the main thread, we need to pass the
- // next GestureFlingCancel to the main
- // thread as well.
- expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
- gesture_.type = WebInputEvent::GestureFlingCancel;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
- input_handler_->MainThreadHasStoppedFlinging();
-
- // Start a second gesture fling, this time in the +Y direction with no X.
- fling_delta = WebFloatPoint(0, -1000);
- fling_point = WebPoint(95, 87);
- fling_global_point = WebPoint(32, 71);
- modifiers = WebInputEvent::AltKey;
- gesture_ = CreateFling(blink::WebGestureDeviceTouchpad,
- fling_delta,
- fling_point,
- fling_global_point,
- modifiers);
- 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_));
-
- VERIFY_AND_RESET_MOCKS();
-
- // Start the second fling animation at time 30.
- EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .Times(0);
- time = base::TimeTicks() + base::TimeDelta::FromSeconds(30);
- Animate(time);
-
- VERIFY_AND_RESET_MOCKS();
-
- // Tick the second fling once normally.
- 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_,
- ScrollBy(testing::_,
- testing::Property(&gfx::Vector2dF::y, testing::Gt(0))))
- .WillOnce(testing::Return(scroll_result_did_scroll_));
- EXPECT_CALL(mock_input_handler_, ScrollEnd());
- time += base::TimeDelta::FromMilliseconds(100);
- Animate(time);
-
- VERIFY_AND_RESET_MOCKS();
-
- // Then abort the second fling.
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_ON_MAIN_THREAD));
- EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::_)).Times(0);
- EXPECT_CALL(mock_input_handler_, ScrollEnd()).Times(0);
-
- // We should get parameters from the second fling, nothing from the first
- // fling should "leak".
- EXPECT_CALL(
- mock_client_,
- TransferActiveWheelFlingAnimation(testing::AllOf(
- testing::Field(&WebActiveWheelFlingParameters::delta,
- testing::Eq(fling_delta)),
- testing::Field(&WebActiveWheelFlingParameters::point,
- testing::Eq(fling_point)),
- testing::Field(&WebActiveWheelFlingParameters::globalPoint,
- testing::Eq(fling_global_point)),
- testing::Field(&WebActiveWheelFlingParameters::modifiers,
- testing::Eq(modifiers)),
- testing::Field(&WebActiveWheelFlingParameters::startTime,
- testing::Eq(30)),
- testing::Field(&WebActiveWheelFlingParameters::cumulativeScroll,
- testing::Field(&WebSize::height, testing::Lt(0))))));
- time += base::TimeDelta::FromMilliseconds(100);
- Animate(time);
-
- VERIFY_AND_RESET_MOCKS();
-}
-
-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();
-
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
- gesture_.type = WebInputEvent::GestureScrollBegin;
- gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
- EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
-
- gesture_.type = WebInputEvent::GestureFlingStart;
- gesture_.data.flingStart.velocityX = 10;
- gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- EXPECT_CALL(mock_input_handler_, ScrollEnd());
-
- // Verify that a GestureFlingCancel during an animation cancels it.
- gesture_.type = WebInputEvent::GestureFlingCancel;
- gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-}
-
-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();
-
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_ON_MAIN_THREAD));
-
- gesture_.type = WebInputEvent::GestureScrollBegin;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- EXPECT_CALL(mock_input_handler_, FlingScrollBegin()).Times(0);
-
- gesture_.type = WebInputEvent::GestureFlingStart;
- gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- // Even if we didn't start a fling ourselves, we still need to send the cancel
- // event to the widget.
- gesture_.type = WebInputEvent::GestureFlingCancel;
- gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-}
-
-TEST_P(InputHandlerProxyTest, GestureFlingIgnoredTouchscreen) {
- expected_disposition_ = InputHandlerProxy::DID_HANDLE;
- VERIFY_AND_RESET_MOCKS();
-
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
-
- gesture_.type = WebInputEvent::GestureScrollBegin;
- gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- expected_disposition_ = InputHandlerProxy::DROP_EVENT;
- VERIFY_AND_RESET_MOCKS();
-
- // Flings ignored by the InputHandler should be dropped, signalling the end
- // of the touch scroll sequence.
- EXPECT_CALL(mock_input_handler_, FlingScrollBegin())
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_IGNORED));
-
- gesture_.type = WebInputEvent::GestureFlingStart;
- gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- // Subsequent scrolls should behave normally, even without an intervening
- // GestureFlingCancel, as the original GestureFlingStart was dropped.
- expected_disposition_ = InputHandlerProxy::DID_HANDLE;
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
- gesture_.type = WebInputEvent::GestureScrollBegin;
- gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-}
-
-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();
-
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
-
- gesture_.type = WebInputEvent::GestureScrollBegin;
- gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- // On the fling start, we should schedule an animation but not actually start
- // scrolling.
- WebFloatPoint fling_delta = WebFloatPoint(100, 0);
- WebPoint fling_point = WebPoint(7, 13);
- WebPoint fling_global_point = WebPoint(17, 23);
- // Note that for touchscreen the control modifier is not special.
- int modifiers = WebInputEvent::ControlKey;
- gesture_ = CreateFling(blink::WebGestureDeviceTouchscreen,
- fling_delta,
- fling_point,
- fling_global_point,
- modifiers);
- 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_));
-
- 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_SET_NEEDS_ANIMATE_INPUT(1);
- base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10);
- Animate(time);
-
- VERIFY_AND_RESET_MOCKS();
-
- // The second call should start scrolling in the -X direction.
- 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);
- Animate(time);
-
- VERIFY_AND_RESET_MOCKS();
-
- EXPECT_CALL(mock_input_handler_, ScrollEnd());
- gesture_.type = WebInputEvent::GestureFlingCancel;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-}
-
-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();
-
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
-
- gesture_.type = WebInputEvent::GestureScrollBegin;
- gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- // On the fling start, we should schedule an animation but not actually start
- // scrolling.
- base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10);
- base::TimeTicks time = base::TimeTicks() + dt;
- WebFloatPoint fling_delta = WebFloatPoint(100, 0);
- WebPoint fling_point = WebPoint(7, 13);
- WebPoint fling_global_point = WebPoint(17, 23);
- int modifiers = WebInputEvent::ControlKey;
- gesture_ = CreateFling(time,
- blink::WebGestureDeviceTouchscreen,
- fling_delta,
- fling_point,
- fling_global_point,
- modifiers);
- 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_));
-
- 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_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;
- Animate(time);
-
- VERIFY_AND_RESET_MOCKS();
-
- EXPECT_CALL(mock_input_handler_, ScrollEnd());
- gesture_.type = WebInputEvent::GestureFlingCancel;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-}
-
-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();
-
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
-
- gesture_.type = WebInputEvent::GestureScrollBegin;
- gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- // On the fling start, we should schedule an animation but not actually start
- // scrolling.
- base::TimeDelta start_time_offset = base::TimeDelta::FromMilliseconds(10);
- gesture_.type = WebInputEvent::GestureFlingStart;
- WebFloatPoint fling_delta = WebFloatPoint(100, 0);
- WebPoint fling_point = WebPoint(7, 13);
- WebPoint fling_global_point = WebPoint(17, 23);
- int modifiers = WebInputEvent::ControlKey;
- gesture_.timeStampSeconds = start_time_offset.InSecondsF();
- gesture_.data.flingStart.velocityX = fling_delta.x;
- gesture_.data.flingStart.velocityY = fling_delta.y;
- gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
- gesture_.x = fling_point.x;
- gesture_.y = fling_point.y;
- gesture_.globalX = fling_global_point.x;
- gesture_.globalY = fling_global_point.y;
- gesture_.modifiers = modifiers;
- 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_));
-
- 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_SET_NEEDS_ANIMATE_INPUT(1);
- base::TimeTicks time =
- base::TimeTicks() + start_time_offset + base::TimeDelta::FromSeconds(1);
- Animate(time);
-
- VERIFY_AND_RESET_MOCKS();
-
- // Further animation ticks should update the fling as usual.
- 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);
- Animate(time);
-
- VERIFY_AND_RESET_MOCKS();
-
- EXPECT_CALL(mock_input_handler_, ScrollEnd());
- gesture_.type = WebInputEvent::GestureFlingCancel;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-}
-
-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();
-
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
-
- gesture_.type = WebInputEvent::GestureScrollBegin;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- // After sending a GestureScrollBegin, the member variable
- // |gesture_scroll_on_impl_thread_| should be true.
- EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
-
- expected_disposition_ = InputHandlerProxy::DID_HANDLE;
- VERIFY_AND_RESET_MOCKS();
-
- // On the fling start, we should schedule an animation but not actually start
- // scrolling.
- WebFloatPoint fling_delta = WebFloatPoint(100, 0);
- WebPoint fling_point = WebPoint(7, 13);
- WebPoint fling_global_point = WebPoint(17, 23);
- int modifiers = WebInputEvent::ControlKey | WebInputEvent::AltKey;
- gesture_ = CreateFling(blink::WebGestureDeviceTouchscreen,
- fling_delta,
- fling_point,
- fling_global_point,
- modifiers);
- 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_));
-
- // |gesture_scroll_on_impl_thread_| should still be true after
- // a GestureFlingStart is sent.
- EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
-
- 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_SET_NEEDS_ANIMATE_INPUT(1);
- base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10);
- Animate(time);
-
- VERIFY_AND_RESET_MOCKS();
-
- // The second call should start scrolling in the -X direction.
- 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);
- Animate(time);
-
- VERIFY_AND_RESET_MOCKS();
-
- EXPECT_CALL(mock_input_handler_, ScrollEnd());
- gesture_.type = WebInputEvent::GestureFlingCancel;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- // |gesture_scroll_on_impl_thread_| should be false once
- // the fling has finished (note no GestureScrollEnd has been sent).
- EXPECT_TRUE(!input_handler_->gesture_scroll_on_impl_thread_for_testing());
-
- VERIFY_AND_RESET_MOCKS();
-}
-
-TEST_P(InputHandlerProxyTest,
- BeginScrollWhenGestureScrollOnImplThreadFlagIsSet) {
- // We shouldn't send any events to the widget for this gesture.
- expected_disposition_ = InputHandlerProxy::DID_HANDLE;
- VERIFY_AND_RESET_MOCKS();
-
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
-
- gesture_.type = WebInputEvent::GestureScrollBegin;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- // After sending a GestureScrollBegin, the member variable
- // |gesture_scroll_on_impl_thread_| should be true.
- EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
-
- expected_disposition_ = InputHandlerProxy::DID_HANDLE;
- VERIFY_AND_RESET_MOCKS();
-
- // On the fling start, we should schedule an animation but not actually start
- // scrolling.
- WebFloatPoint fling_delta = WebFloatPoint(100, 0);
- WebPoint fling_point = WebPoint(7, 13);
- WebPoint fling_global_point = WebPoint(17, 23);
- int modifiers = WebInputEvent::ControlKey | WebInputEvent::AltKey;
- gesture_ = CreateFling(blink::WebGestureDeviceTouchscreen, fling_delta,
- fling_point, fling_global_point, modifiers);
- 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_));
-
- // |gesture_scroll_on_impl_thread_| should still be true after
- // a GestureFlingStart is sent.
- EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
-
- 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.
- EXPECT_CALL(mock_input_handler_, ScrollEnd());
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
-
- gesture_.type = WebInputEvent::GestureScrollBegin;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- // After sending a GestureScrollBegin, the member variable
- // |gesture_scroll_on_impl_thread_| should be true.
- EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
- VERIFY_AND_RESET_MOCKS();
-}
-
-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();
-
- // On the fling start, we should schedule an animation but not actually start
- // scrolling.
- 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_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
- EXPECT_CALL(mock_input_handler_, ScrollEnd());
- EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
- VERIFY_AND_RESET_MOCKS();
-
- // The first animate doesn't cause any scrolling.
- EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
- base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10);
- 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::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
- EXPECT_CALL(mock_input_handler_,
- ScrollBy(testing::_,
- testing::Property(&gfx::Vector2dF::y, testing::Lt(0))))
- .WillOnce(testing::Return(scroll_result_did_scroll_));
- EXPECT_CALL(mock_input_handler_, ScrollEnd());
- EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
- time += base::TimeDelta::FromMilliseconds(100);
- Animate(time);
- VERIFY_AND_RESET_MOCKS();
-
- // The third animate overscrolls in the positive Y direction but scrolls
- // somewhat.
- cc::InputHandlerScrollResult overscroll;
- overscroll.did_scroll = true;
- overscroll.did_overscroll_root = true;
- overscroll.accumulated_root_overscroll = gfx::Vector2dF(0, 100);
- overscroll.unused_scroll_delta = gfx::Vector2dF(0, 10);
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
- EXPECT_CALL(mock_input_handler_,
- ScrollBy(testing::_,
- testing::Property(&gfx::Vector2dF::y, testing::Lt(0))))
- .WillOnce(testing::Return(overscroll));
- EXPECT_CALL(
- mock_client_,
- DidOverscroll(testing::AllOf(
- testing::Field(
- &DidOverscrollParams::accumulated_overscroll,
- testing::Eq(overscroll.accumulated_root_overscroll)),
- testing::Field(
- &DidOverscrollParams::latest_overscroll_delta,
- testing::Eq(overscroll.unused_scroll_delta)),
- testing::Field(
- &DidOverscrollParams::current_fling_velocity,
- testing::Property(&gfx::Vector2dF::y, testing::Lt(0))))));
- EXPECT_CALL(mock_input_handler_, ScrollEnd());
- EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
- time += base::TimeDelta::FromMilliseconds(100);
- Animate(time);
- VERIFY_AND_RESET_MOCKS();
-
- // The next call to animate will no longer scroll vertically.
- 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_,
- ScrollBy(testing::_,
- testing::Property(&gfx::Vector2dF::y, testing::Eq(0))))
- .WillOnce(testing::Return(scroll_result_did_scroll_));
- EXPECT_CALL(mock_input_handler_, ScrollEnd());
- time += base::TimeDelta::FromMilliseconds(100);
- Animate(time);
- VERIFY_AND_RESET_MOCKS();
-}
-
-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();
-
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
-
- gesture_.type = WebInputEvent::GestureScrollBegin;
- gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- // On the fling start, we should schedule an animation but not actually start
- // scrolling.
- base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10);
- base::TimeTicks time = base::TimeTicks() + dt;
- WebFloatPoint fling_delta = WebFloatPoint(100, 0);
- WebPoint fling_point = WebPoint(7, 13);
- WebPoint fling_global_point = WebPoint(17, 23);
- int modifiers = WebInputEvent::ControlKey;
- gesture_ = CreateFling(time,
- blink::WebGestureDeviceTouchscreen,
- fling_delta,
- fling_point,
- fling_global_point,
- modifiers);
- 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_));
-
- VERIFY_AND_RESET_MOCKS();
- // With an animation timestamp equivalent to the starting timestamp, the
- // animation will simply be rescheduled.
- EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
- Animate(time);
-
- 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_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);
- Animate(time);
-
- 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_SET_NEEDS_ANIMATE_INPUT(1);
- Animate(time);
-
- 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
- // terminate the fling.
- EXPECT_CALL(mock_input_handler_, ScrollEnd());
- EXPECT_CALL(mock_input_handler_,
- ScrollBy(testing::_,
- testing::Property(&gfx::Vector2dF::x, testing::Lt(1))))
- .WillOnce(testing::Return(scroll_result_did_not_scroll_));
- time += base::TimeDelta::FromMilliseconds(100);
- Animate(time);
-
- VERIFY_AND_RESET_MOCKS();
- EXPECT_FALSE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
-}
-
-TEST_P(InputHandlerProxyTest, GestureFlingCancelledAfterBothAxesStopScrolling) {
- cc::InputHandlerScrollResult overscroll;
- overscroll.did_scroll = true;
- overscroll.did_overscroll_root = true;
-
- // We shouldn't send any events to the widget for this gesture.
- expected_disposition_ = InputHandlerProxy::DID_HANDLE;
- VERIFY_AND_RESET_MOCKS();
-
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
- gesture_.type = WebInputEvent::GestureScrollBegin;
- gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
- VERIFY_AND_RESET_MOCKS();
-
- // On the fling start, we should schedule an animation but not actually start
- // scrolling.
- 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_, FlingScrollBegin())
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
- EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
- VERIFY_AND_RESET_MOCKS();
-
- // The first animate doesn't cause any scrolling.
- EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
- base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10);
- Animate(time);
- VERIFY_AND_RESET_MOCKS();
-
- // The second animate starts scrolling in the positive X and Y directions.
- 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);
- Animate(time);
- VERIFY_AND_RESET_MOCKS();
-
- // The third animate hits the bottom content edge.
- overscroll.accumulated_root_overscroll = gfx::Vector2dF(0, 100);
- overscroll.unused_scroll_delta = gfx::Vector2dF(0, 100);
- EXPECT_CALL(mock_input_handler_,
- ScrollBy(testing::_,
- testing::Property(&gfx::Vector2dF::y, testing::Lt(0))))
- .WillOnce(testing::Return(overscroll));
- EXPECT_CALL(
- mock_client_,
- DidOverscroll(testing::AllOf(
- testing::Field(
- &DidOverscrollParams::accumulated_overscroll,
- testing::Eq(overscroll.accumulated_root_overscroll)),
- testing::Field(
- &DidOverscrollParams::latest_overscroll_delta,
- testing::Eq(overscroll.unused_scroll_delta)),
- testing::Field(
- &DidOverscrollParams::current_fling_velocity,
- testing::Property(&gfx::Vector2dF::y, testing::Lt(0))))));
- EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
- time += base::TimeDelta::FromMilliseconds(10);
- Animate(time);
- VERIFY_AND_RESET_MOCKS();
-
- // The next call to animate will no longer scroll vertically.
- 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);
- Animate(time);
- VERIFY_AND_RESET_MOCKS();
-
- // The next call will hit the right edge.
- overscroll.accumulated_root_overscroll = gfx::Vector2dF(100, 100);
- overscroll.unused_scroll_delta = gfx::Vector2dF(100, 0);
- EXPECT_CALL(mock_input_handler_,
- ScrollBy(testing::_,
- testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))
- .WillOnce(testing::Return(overscroll));
- EXPECT_CALL(
- mock_client_,
- DidOverscroll(testing::AllOf(
- testing::Field(
- &DidOverscrollParams::accumulated_overscroll,
- testing::Eq(overscroll.accumulated_root_overscroll)),
- testing::Field(
- &DidOverscrollParams::latest_overscroll_delta,
- testing::Eq(overscroll.unused_scroll_delta)),
- testing::Field(
- &DidOverscrollParams::current_fling_velocity,
- testing::Property(&gfx::Vector2dF::x, testing::Lt(0))))));
- EXPECT_CALL(mock_input_handler_, ScrollEnd());
- time += base::TimeDelta::FromMilliseconds(10);
- 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_SET_NEEDS_ANIMATE_INPUT(0);
- EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::_)).Times(0);
- time += base::TimeDelta::FromMilliseconds(10);
- Animate(time);
- VERIFY_AND_RESET_MOCKS();
- EXPECT_FALSE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
-}
-
-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;
- VERIFY_AND_RESET_MOCKS();
-
- EXPECT_CALL(mock_input_handler_,
- DoTouchEventsBlockScrollAt(
- testing::Property(&gfx::Point::x, testing::Gt(0))))
- .WillOnce(testing::Return(false));
- EXPECT_CALL(mock_input_handler_,
- DoTouchEventsBlockScrollAt(
- testing::Property(&gfx::Point::x, testing::Lt(0))))
- .WillOnce(testing::Return(false));
-
- WebTouchEvent touch;
- touch.type = WebInputEvent::TouchStart;
-
- touch.touchesLength = 3;
- touch.touches[0] = CreateWebTouchPoint(WebTouchPoint::StateStationary, 0, 0);
- touch.touches[1] = CreateWebTouchPoint(WebTouchPoint::StatePressed, 10, 10);
- touch.touches[2] = CreateWebTouchPoint(WebTouchPoint::StatePressed, -10, 10);
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(touch));
-
- VERIFY_AND_RESET_MOCKS();
-}
-
-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;
- VERIFY_AND_RESET_MOCKS();
-
- EXPECT_CALL(mock_input_handler_,
- DoTouchEventsBlockScrollAt(
- testing::Property(&gfx::Point::x, testing::Eq(0))))
- .WillOnce(testing::Return(false));
- EXPECT_CALL(mock_input_handler_,
- DoTouchEventsBlockScrollAt(
- testing::Property(&gfx::Point::x, testing::Gt(0))))
- .WillOnce(testing::Return(true));
- // Since the second touch point hits a touch-region, there should be no
- // hit-testing for the third touch point.
-
- WebTouchEvent touch;
- touch.type = WebInputEvent::TouchStart;
-
- touch.touchesLength = 3;
- touch.touches[0] = CreateWebTouchPoint(WebTouchPoint::StatePressed, 0, 0);
- touch.touches[1] = CreateWebTouchPoint(WebTouchPoint::StatePressed, 10, 10);
- touch.touches[2] = CreateWebTouchPoint(WebTouchPoint::StatePressed, -10, 10);
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(touch));
-
- VERIFY_AND_RESET_MOCKS();
-}
-
-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();
-
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
- gesture_.type = WebInputEvent::GestureScrollBegin;
- gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
- EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
- VERIFY_AND_RESET_MOCKS();
-
- // Keyboard events received during a scroll should have no effect.
- WebKeyboardEvent key_event;
- key_event.type = WebInputEvent::KeyDown;
- EXPECT_EQ(InputHandlerProxy::DID_NOT_HANDLE,
- input_handler_->HandleInputEvent(key_event));
- EXPECT_TRUE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
- VERIFY_AND_RESET_MOCKS();
-
- // On the fling start, animation should be scheduled, but no scrolling occurs.
- 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_, FlingScrollBegin())
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
- 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());
- 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());
- 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);
- Animate(time);
- VERIFY_AND_RESET_MOCKS();
-
- // A fling cancel should be dropped, as there is nothing to cancel.
- gesture_.type = WebInputEvent::GestureFlingCancel;
- EXPECT_EQ(InputHandlerProxy::DROP_EVENT,
- input_handler_->HandleInputEvent(gesture_));
- EXPECT_FALSE(input_handler_->gesture_scroll_on_impl_thread_for_testing());
-}
-
-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();
-
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
-
- gesture_.type = WebInputEvent::GestureScrollBegin;
- gesture_.sourceDevice = blink::WebGestureDeviceTouchscreen;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- // On the fling start, we should schedule an animation but not actually start
- // scrolling.
- base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10);
- base::TimeTicks time = base::TimeTicks() + dt;
- WebFloatPoint fling_delta = WebFloatPoint(100, 0);
- WebPoint fling_point = WebPoint(7, 13);
- WebPoint fling_global_point = WebPoint(17, 23);
- int modifiers = WebInputEvent::ControlKey;
- gesture_ = CreateFling(time,
- blink::WebGestureDeviceTouchscreen,
- fling_delta,
- fling_point,
- fling_global_point,
- modifiers);
- 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_));
-
- 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_SET_NEEDS_ANIMATE_INPUT(1);
- EXPECT_CALL(mock_input_handler_,
- ScrollBy(testing::_,
- testing::_)).Times(0);
- time -= base::TimeDelta::FromMilliseconds(5);
- Animate(time);
-
- VERIFY_AND_RESET_MOCKS();
-
- // The first call should have reset the start time so subsequent calls should
- // generate scroll events.
- 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_));
-
- Animate(time + base::TimeDelta::FromMilliseconds(1));
-
- VERIFY_AND_RESET_MOCKS();
-
- EXPECT_CALL(mock_input_handler_, ScrollEnd());
- gesture_.type = WebInputEvent::GestureFlingCancel;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-}
-
-TEST_P(InputHandlerProxyTest, FlingBoost) {
- base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10);
- base::TimeTicks time = base::TimeTicks() + dt;
- base::TimeTicks last_animate_time = time;
- WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
- WebPoint fling_point = WebPoint(7, 13);
- StartFling(
- time, blink::WebGestureDeviceTouchscreen, fling_delta, fling_point);
-
- // Now cancel the fling. The fling cancellation should be deferred to allow
- // fling boosting events to arrive.
- time += dt;
- CancelFling(time);
-
- // The GestureScrollBegin should be swallowed by the fling if it hits the same
- // scrolling layer.
- EXPECT_CALL(mock_input_handler_,
- IsCurrentlyScrollingLayerAt(testing::_, testing::_))
- .WillOnce(testing::Return(true));
-
- time += dt;
- gesture_.timeStampSeconds = InSecondsF(time);
- gesture_.type = WebInputEvent::GestureScrollBegin;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- // Animate calls within the deferred cancellation window should continue.
- time += dt;
- float expected_delta =
- (time - last_animate_time).InSecondsF() * -fling_delta.x;
- 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_));
- Animate(time);
- last_animate_time = time;
-
- VERIFY_AND_RESET_MOCKS();
-
- // GestureScrollUpdates in the same direction and at sufficient speed should
- // be swallowed by the fling.
- time += dt;
- gesture_.timeStampSeconds = InSecondsF(time);
- gesture_.type = WebInputEvent::GestureScrollUpdate;
- gesture_.data.scrollUpdate.deltaX = fling_delta.x;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- // Animate calls within the deferred cancellation window should continue.
- time += dt;
- expected_delta = (time - last_animate_time).InSecondsF() * -fling_delta.x;
- 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_));
- Animate(time);
- last_animate_time = time;
-
- VERIFY_AND_RESET_MOCKS();
-
- // GestureFlingStart in the same direction and at sufficient speed should
- // boost the active fling.
-
- gesture_ = CreateFling(time,
- blink::WebGestureDeviceTouchscreen,
- fling_delta,
- fling_point,
- fling_point,
- 0);
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
- VERIFY_AND_RESET_MOCKS();
-
- 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_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_));
- Animate(time);
- last_animate_time = time;
-
- VERIFY_AND_RESET_MOCKS();
-
- // Repeated GestureFlingStarts should accumulate.
-
- CancelFling(time);
- gesture_ = CreateFling(time,
- blink::WebGestureDeviceTouchscreen,
- fling_delta,
- fling_point,
- fling_point,
- 0);
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
- VERIFY_AND_RESET_MOCKS();
-
- 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_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_));
- Animate(time);
- last_animate_time = time;
-
- VERIFY_AND_RESET_MOCKS();
-
- // GestureFlingCancel should terminate the fling if no boosting gestures are
- // received within the timeout window.
-
- time += dt;
- gesture_.timeStampSeconds = InSecondsF(time);
- gesture_.type = WebInputEvent::GestureFlingCancel;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- time += base::TimeDelta::FromMilliseconds(100);
- EXPECT_CALL(mock_input_handler_, ScrollEnd());
- Animate(time);
-
- VERIFY_AND_RESET_MOCKS();
-}
-
-TEST_P(InputHandlerProxyTest, NoFlingBoostIfScrollTargetsDifferentLayer) {
- base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10);
- base::TimeTicks time = base::TimeTicks() + dt;
- WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
- WebPoint fling_point = WebPoint(7, 13);
- StartFling(
- time, blink::WebGestureDeviceTouchscreen, fling_delta, fling_point);
-
- // Cancel the fling. The fling cancellation should be deferred to allow
- // fling boosting events to arrive.
- time += dt;
- CancelFling(time);
-
- // If the GestureScrollBegin targets a different layer, the fling should be
- // cancelled and the scroll should be handled as usual.
- EXPECT_CALL(mock_input_handler_,
- IsCurrentlyScrollingLayerAt(testing::_, testing::_))
- .WillOnce(testing::Return(false));
- EXPECT_CALL(mock_input_handler_, ScrollEnd());
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
-
- time += dt;
- gesture_.timeStampSeconds = InSecondsF(time);
- gesture_.type = WebInputEvent::GestureScrollBegin;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-}
-
-TEST_P(InputHandlerProxyTest, NoFlingBoostIfScrollDelayed) {
- base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10);
- base::TimeTicks time = base::TimeTicks() + dt;
- WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
- WebPoint fling_point = WebPoint(7, 13);
- StartFling(
- time, blink::WebGestureDeviceTouchscreen, fling_delta, fling_point);
-
- // Cancel the fling. The fling cancellation should be deferred to allow
- // fling boosting events to arrive.
- time += dt;
- CancelFling(time);
-
- // The GestureScrollBegin should be swallowed by the fling if it hits the same
- // scrolling layer.
- EXPECT_CALL(mock_input_handler_,
- IsCurrentlyScrollingLayerAt(testing::_, testing::_))
- .WillOnce(testing::Return(true));
-
- time += dt;
- gesture_.timeStampSeconds = InSecondsF(time);
- gesture_.type = WebInputEvent::GestureScrollBegin;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- // If no GestureScrollUpdate or GestureFlingStart is received within the
- // timeout window, the fling should be cancelled and scrolling should resume.
- time += base::TimeDelta::FromMilliseconds(100);
- EXPECT_CALL(mock_input_handler_, ScrollEnd());
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
- Animate(time);
-
- VERIFY_AND_RESET_MOCKS();
-}
-
-TEST_P(InputHandlerProxyTest, NoFlingBoostIfNotAnimated) {
- base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10);
- base::TimeTicks time = base::TimeTicks() + dt;
- WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
- WebPoint fling_point = WebPoint(7, 13);
- StartFling(
- time, blink::WebGestureDeviceTouchscreen, fling_delta, fling_point);
-
- // Animate fling once.
- time += dt;
- EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::_))
- .WillOnce(testing::Return(scroll_result_did_scroll_));
- 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.
- time += base::TimeDelta::FromMilliseconds(100);
- CancelFling(time);
-
- // The GestureScrollBegin should be swallowed by the fling if it hits the same
- // scrolling layer.
- EXPECT_CALL(mock_input_handler_,
- IsCurrentlyScrollingLayerAt(testing::_, testing::_))
- .WillOnce(testing::Return(true));
-
- time += dt;
- gesture_.timeStampSeconds = InSecondsF(time);
- gesture_.type = WebInputEvent::GestureScrollBegin;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- // Should exit scroll bosting on GestureScrollUpdate due to long delay
- // since last animate. Cancel old fling and start new scroll.
- gesture_.type = WebInputEvent::GestureScrollUpdate;
- gesture_.data.scrollUpdate.deltaY = -40;
- EXPECT_CALL(mock_input_handler_, ScrollEnd());
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
- EXPECT_CALL(mock_input_handler_, ScrollBy(testing::_, testing::_))
- .WillOnce(testing::Return(scroll_result_did_scroll_));
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-}
-
-TEST_P(InputHandlerProxyTest, NoFlingBoostIfFlingInDifferentDirection) {
- base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10);
- base::TimeTicks time = base::TimeTicks() + dt;
- WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
- WebPoint fling_point = WebPoint(7, 13);
- StartFling(
- time, blink::WebGestureDeviceTouchscreen, fling_delta, fling_point);
-
- // Cancel the fling. The fling cancellation should be deferred to allow
- // fling boosting events to arrive.
- time += dt;
- CancelFling(time);
-
- // If the new fling is orthogonal to the existing fling, no boosting should
- // take place, with the new fling replacing the old.
- WebFloatPoint orthogonal_fling_delta =
- WebFloatPoint(fling_delta.y, -fling_delta.x);
- gesture_ = CreateFling(time,
- blink::WebGestureDeviceTouchscreen,
- orthogonal_fling_delta,
- fling_point,
- fling_point,
- 0);
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- // Note that the new fling delta uses the orthogonal, unboosted fling
- // velocity.
- time += dt;
- float expected_delta = dt.InSecondsF() * -orthogonal_fling_delta.y;
- 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_));
- Animate(time);
-
- VERIFY_AND_RESET_MOCKS();
-}
-
-TEST_P(InputHandlerProxyTest, NoFlingBoostIfScrollInDifferentDirection) {
- base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10);
- base::TimeTicks time = base::TimeTicks() + dt;
- WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
- WebPoint fling_point = WebPoint(7, 13);
- StartFling(
- time, blink::WebGestureDeviceTouchscreen, fling_delta, fling_point);
-
- // Cancel the fling. The fling cancellation should be deferred to allow
- // fling boosting events to arrive.
- time += dt;
- CancelFling(time);
-
- // The GestureScrollBegin should be swallowed by the fling if it hits the same
- // scrolling layer.
- EXPECT_CALL(mock_input_handler_,
- IsCurrentlyScrollingLayerAt(testing::_, testing::_))
- .WillOnce(testing::Return(true));
-
- time += dt;
- gesture_.timeStampSeconds = InSecondsF(time);
- gesture_.type = WebInputEvent::GestureScrollBegin;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- // If the GestureScrollUpdate is in a different direction than the fling,
- // the fling should be cancelled and scrolling should resume.
- time += dt;
- gesture_.timeStampSeconds = InSecondsF(time);
- gesture_.type = WebInputEvent::GestureScrollUpdate;
- gesture_.data.scrollUpdate.deltaX = -fling_delta.x;
- EXPECT_CALL(mock_input_handler_, ScrollEnd());
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
- EXPECT_CALL(mock_input_handler_,
- ScrollBy(testing::_,
- testing::Property(&gfx::Vector2dF::x,
- testing::Eq(fling_delta.x))))
- .WillOnce(testing::Return(scroll_result_did_scroll_));
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-}
-
-TEST_P(InputHandlerProxyTest, NoFlingBoostIfFlingTooSlow) {
- base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10);
- base::TimeTicks time = base::TimeTicks() + dt;
- WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
- WebPoint fling_point = WebPoint(7, 13);
- StartFling(
- time, blink::WebGestureDeviceTouchscreen, fling_delta, fling_point);
-
- // Cancel the fling. The fling cancellation should be deferred to allow
- // fling boosting events to arrive.
- time += dt;
- CancelFling(time);
-
- // If the new fling is too slow, no boosting should take place, with the new
- // fling replacing the old.
- WebFloatPoint small_fling_delta = WebFloatPoint(100, 0);
- gesture_ = CreateFling(time,
- blink::WebGestureDeviceTouchscreen,
- small_fling_delta,
- fling_point,
- fling_point,
- 0);
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- // Note that the new fling delta uses the *slow*, unboosted fling velocity.
- time += dt;
- float expected_delta = dt.InSecondsF() * -small_fling_delta.x;
- 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_));
- Animate(time);
-
- VERIFY_AND_RESET_MOCKS();
-}
-
-TEST_P(InputHandlerProxyTest, NoFlingBoostIfPreventBoostingFlagIsSet) {
- base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10);
- base::TimeTicks time = base::TimeTicks() + dt;
- WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
- WebPoint fling_point = WebPoint(7, 13);
-
- StartFling(
- time, blink::WebGestureDeviceTouchscreen, fling_delta, fling_point);
-
- EXPECT_CALL(mock_input_handler_, ScrollEnd());
-
- // Cancel the fling. The fling cancellation should not be deferred because of
- // prevent boosting flag set.
- gesture_.data.flingCancel.preventBoosting = true;
- time += dt;
- CancelFling(time);
-
- // VERIFY_AND_RESET_MOCKS already called by CancelFling
-}
-
-TEST_P(InputHandlerProxyTest, FlingBoostTerminatedDuringScrollSequence) {
- base::TimeDelta dt = base::TimeDelta::FromMilliseconds(10);
- base::TimeTicks time = base::TimeTicks() + dt;
- base::TimeTicks last_animate_time = time;
- WebFloatPoint fling_delta = WebFloatPoint(1000, 0);
- WebPoint fling_point = WebPoint(7, 13);
- StartFling(
- time, blink::WebGestureDeviceTouchscreen, fling_delta, fling_point);
-
- // Now cancel the fling. The fling cancellation should be deferred to allow
- // fling boosting events to arrive.
- time += dt;
- CancelFling(time);
-
- // The GestureScrollBegin should be swallowed by the fling.
- time += dt;
- gesture_.timeStampSeconds = InSecondsF(time);
- gesture_.type = WebInputEvent::GestureScrollBegin;
- EXPECT_CALL(mock_input_handler_,
- IsCurrentlyScrollingLayerAt(testing::_, testing::_))
- .WillOnce(testing::Return(true));
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- // Now animate the fling to completion (in this case, the fling should
- // terminate because the input handler reports a failed scroll). As the fling
- // was cancelled during an active scroll sequence, a synthetic
- // GestureScrollBegin should be processed, resuming the scroll.
- time += dt;
- float expected_delta =
- (time - last_animate_time).InSecondsF() * -fling_delta.x;
- EXPECT_CALL(mock_input_handler_,
- ScrollBy(testing::_,
- testing::Property(&gfx::Vector2dF::x,
- testing::Eq(expected_delta))))
- .WillOnce(testing::Return(scroll_result_did_not_scroll_));
- EXPECT_CALL(mock_input_handler_, ScrollEnd());
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(cc::InputHandler::SCROLL_STARTED));
- Animate(time);
-
- VERIFY_AND_RESET_MOCKS();
-
- // Subsequent GestureScrollUpdates after the cancelled, boosted fling should
- // cause scrolling as usual.
- time += dt;
- expected_delta = 7.3f;
- gesture_.timeStampSeconds = InSecondsF(time);
- gesture_.type = WebInputEvent::GestureScrollUpdate;
- gesture_.data.scrollUpdate.deltaX = -expected_delta;
- EXPECT_CALL(mock_input_handler_,
- ScrollBy(testing::_,
- testing::Property(&gfx::Vector2dF::x,
- testing::Eq(expected_delta))))
- .WillOnce(testing::Return(scroll_result_did_scroll_));
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-
- // GestureScrollEnd should terminate the resumed scroll properly.
- time += dt;
- gesture_.timeStampSeconds = InSecondsF(time);
- gesture_.type = WebInputEvent::GestureScrollEnd;
- EXPECT_CALL(mock_input_handler_, ScrollEnd());
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
-
- VERIFY_AND_RESET_MOCKS();
-}
-
-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_) {
- EXPECT_CALL(mock_input_handler_, RequestUpdateForSynchronousInputHandler())
- .Times(1);
- 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_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_));
- VERIFY_AND_RESET_MOCKS();
-
- EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
- EXPECT_CALL(mock_client, DidAnimateForInput());
- base::TimeTicks time = base::TimeTicks() + base::TimeDelta::FromSeconds(10);
- Animate(time);
-
- VERIFY_AND_RESET_MOCKS();
-}
-
-TEST(SynchronousInputHandlerProxyTest, StartupShutdown) {
- testing::StrictMock<MockInputHandler> mock_input_handler;
- testing::StrictMock<MockInputHandlerProxyClient> mock_client;
- testing::StrictMock<MockSynchronousInputHandler>
- mock_synchronous_input_handler;
- content::InputHandlerProxy proxy(&mock_input_handler, &mock_client);
-
- // When adding a SynchronousInputHandler, immediately request an
- // UpdateRootLayerStateForSynchronousInputHandler() call.
- EXPECT_CALL(mock_input_handler, RequestUpdateForSynchronousInputHandler())
- .Times(1);
- proxy.SetOnlySynchronouslyAnimateRootFlings(&mock_synchronous_input_handler);
-
- testing::Mock::VerifyAndClearExpectations(&mock_input_handler);
- testing::Mock::VerifyAndClearExpectations(&mock_client);
- testing::Mock::VerifyAndClearExpectations(&mock_synchronous_input_handler);
-
- EXPECT_CALL(mock_input_handler, RequestUpdateForSynchronousInputHandler())
- .Times(0);
- proxy.SetOnlySynchronouslyAnimateRootFlings(nullptr);
-
- testing::Mock::VerifyAndClearExpectations(&mock_input_handler);
- testing::Mock::VerifyAndClearExpectations(&mock_client);
- testing::Mock::VerifyAndClearExpectations(&mock_synchronous_input_handler);
-}
-
-TEST(SynchronousInputHandlerProxyTest, UpdateRootLayerState) {
- testing::NiceMock<MockInputHandler> mock_input_handler;
- testing::StrictMock<MockInputHandlerProxyClient> mock_client;
- testing::StrictMock<MockSynchronousInputHandler>
- mock_synchronous_input_handler;
- content::InputHandlerProxy proxy(&mock_input_handler, &mock_client);
-
- proxy.SetOnlySynchronouslyAnimateRootFlings(&mock_synchronous_input_handler);
-
- // When adding a SynchronousInputHandler, immediately request an
- // UpdateRootLayerStateForSynchronousInputHandler() call.
- EXPECT_CALL(
- mock_synchronous_input_handler,
- UpdateRootLayerState(gfx::ScrollOffset(1, 2), gfx::ScrollOffset(3, 4),
- gfx::SizeF(5, 6), 7, 8, 9))
- .Times(1);
- proxy.UpdateRootLayerStateForSynchronousInputHandler(
- gfx::ScrollOffset(1, 2), gfx::ScrollOffset(3, 4), gfx::SizeF(5, 6), 7, 8,
- 9);
-
- testing::Mock::VerifyAndClearExpectations(&mock_input_handler);
- testing::Mock::VerifyAndClearExpectations(&mock_client);
- testing::Mock::VerifyAndClearExpectations(&mock_synchronous_input_handler);
-}
-
-TEST(SynchronousInputHandlerProxyTest, SetOffset) {
- testing::NiceMock<MockInputHandler> mock_input_handler;
- testing::StrictMock<MockInputHandlerProxyClient> mock_client;
- testing::StrictMock<MockSynchronousInputHandler>
- mock_synchronous_input_handler;
- content::InputHandlerProxy proxy(&mock_input_handler, &mock_client);
-
- proxy.SetOnlySynchronouslyAnimateRootFlings(&mock_synchronous_input_handler);
-
- EXPECT_CALL(mock_input_handler, SetSynchronousInputHandlerRootScrollOffset(
- gfx::ScrollOffset(5, 6)));
- proxy.SynchronouslySetRootScrollOffset(gfx::ScrollOffset(5, 6));
-
- testing::Mock::VerifyAndClearExpectations(&mock_input_handler);
- testing::Mock::VerifyAndClearExpectations(&mock_client);
- testing::Mock::VerifyAndClearExpectations(&mock_synchronous_input_handler);
-}
-
-INSTANTIATE_TEST_CASE_P(AnimateInput,
- InputHandlerProxyTest,
- testing::ValuesIn(test_types));
-} // namespace test
-} // namespace content
diff --git a/content/renderer/input/input_handler_wrapper.cc b/content/renderer/input/input_handler_wrapper.cc
index d5596bd..5995d99 100644
--- a/content/renderer/input/input_handler_wrapper.cc
+++ b/content/renderer/input/input_handler_wrapper.cc
@@ -4,7 +4,10 @@
#include "content/renderer/input/input_handler_wrapper.h"
+#include "base/command_line.h"
#include "base/location.h"
+#include "content/common/input/did_overscroll_params.h"
+#include "content/public/common/content_switches.h"
#include "content/renderer/input/input_event_filter.h"
#include "content/renderer/input/input_handler_manager.h"
#include "third_party/WebKit/public/platform/Platform.h"
@@ -23,6 +26,9 @@ InputHandlerWrapper::InputHandlerWrapper(
main_task_runner_(main_task_runner),
render_view_impl_(render_view_impl) {
DCHECK(input_handler);
+ input_handler_proxy_.set_smooth_scroll_enabled(
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableSmoothScrolling));
}
InputHandlerWrapper::~InputHandlerWrapper() {
@@ -47,7 +53,16 @@ blink::WebGestureCurve* InputHandlerWrapper::CreateFlingAnimationCurve(
deviceSource, velocity, cumulative_scroll);
}
-void InputHandlerWrapper::DidOverscroll(const DidOverscrollParams& params) {
+void InputHandlerWrapper::DidOverscroll(
+ const gfx::Vector2dF& accumulated_overscroll,
+ const gfx::Vector2dF& latest_overscroll_delta,
+ const gfx::Vector2dF& current_fling_velocity,
+ const gfx::PointF& causal_event_viewport_point) {
+ DidOverscrollParams params;
+ params.accumulated_overscroll = accumulated_overscroll;
+ params.latest_overscroll_delta = latest_overscroll_delta;
+ params.current_fling_velocity = current_fling_velocity;
+ params.causal_event_viewport_point = causal_event_viewport_point;
input_handler_manager_->DidOverscroll(routing_id_, params);
}
diff --git a/content/renderer/input/input_handler_wrapper.h b/content/renderer/input/input_handler_wrapper.h
index 5c925d0..69ff5c67 100644
--- a/content/renderer/input/input_handler_wrapper.h
+++ b/content/renderer/input/input_handler_wrapper.h
@@ -8,13 +8,18 @@
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
#include "content/renderer/input/input_handler_manager.h"
-#include "content/renderer/input/input_handler_proxy.h"
-#include "content/renderer/input/input_handler_proxy_client.h"
+#include "ui/events/blink/input_handler_proxy.h"
+#include "ui/events/blink/input_handler_proxy_client.h"
+
+namespace ui {
+class InputHandlerProxy;
+class InputHandlerProxyClient;
+}
namespace content {
// This class lives on the compositor thread.
-class InputHandlerWrapper : public InputHandlerProxyClient {
+class InputHandlerWrapper : public ui::InputHandlerProxyClient {
public:
InputHandlerWrapper(
InputHandlerManager* input_handler_manager,
@@ -25,7 +30,9 @@ class InputHandlerWrapper : public InputHandlerProxyClient {
~InputHandlerWrapper() override;
int routing_id() const { return routing_id_; }
- InputHandlerProxy* input_handler_proxy() { return &input_handler_proxy_; }
+ ui::InputHandlerProxy* input_handler_proxy() {
+ return &input_handler_proxy_;
+ }
// InputHandlerProxyClient implementation.
void WillShutdown() override;
@@ -35,14 +42,18 @@ class InputHandlerWrapper : public InputHandlerProxyClient {
blink::WebGestureDevice deviceSource,
const blink::WebFloatPoint& velocity,
const blink::WebSize& cumulativeScroll) override;
- void DidOverscroll(const DidOverscrollParams& params) override;
+ void DidOverscroll(
+ const gfx::Vector2dF& accumulated_overscroll,
+ const gfx::Vector2dF& latest_overscroll_delta,
+ const gfx::Vector2dF& current_fling_velocity,
+ const gfx::PointF& causal_event_viewport_point) override;
void DidStopFlinging() override;
void DidAnimateForInput() override;
private:
InputHandlerManager* input_handler_manager_;
int routing_id_;
- InputHandlerProxy input_handler_proxy_;
+ ui::InputHandlerProxy input_handler_proxy_;
scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
// Can only be accessed on the main thread.
diff --git a/content/renderer/input/input_scroll_elasticity_controller.cc b/content/renderer/input/input_scroll_elasticity_controller.cc
deleted file mode 100644
index 00d078f..0000000
--- a/content/renderer/input/input_scroll_elasticity_controller.cc
+++ /dev/null
@@ -1,410 +0,0 @@
-// Copyright 2014 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.
-
-#include "content/renderer/input/input_scroll_elasticity_controller.h"
-
-#include <math.h>
-
-#include "base/bind.h"
-#include "cc/input/input_handler.h"
-#include "ui/gfx/geometry/vector2d_conversions.h"
-
-// InputScrollElasticityController is based on
-// WebKit/Source/platform/mac/InputScrollElasticityController.mm
-/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-namespace content {
-
-namespace {
-
-const float kScrollVelocityZeroingTimeout = 0.10f;
-const float kRubberbandMinimumRequiredDeltaBeforeStretch = 10;
-
-const float kRubberbandStiffness = 20;
-const float kRubberbandAmplitude = 0.31f;
-const float kRubberbandPeriod = 1.6f;
-
-// For these functions which compute the stretch amount, always return a
-// rounded value, instead of a floating-point value. The reason for this is
-// that Blink's scrolling can become erratic with fractional scroll amounts (in
-// particular, if you have a scroll offset of 0.5, Blink will never actually
-// bring that value back to 0, which breaks the logic used to determine if a
-// layer is pinned in a direction).
-
-gfx::Vector2d StretchAmountForTimeDelta(const gfx::Vector2dF& initial_position,
- const gfx::Vector2dF& initial_velocity,
- float elapsed_time) {
- // Compute the stretch amount at a given time after some initial conditions.
- // Do this by first computing an intermediary position given the initial
- // position, initial velocity, time elapsed, and no external forces. Then
- // take the intermediary position and damp it towards zero by multiplying
- // against a negative exponential.
- float amplitude = kRubberbandAmplitude;
- float period = kRubberbandPeriod;
- float critical_dampening_factor =
- expf((-elapsed_time * kRubberbandStiffness) / period);
-
- return gfx::ToRoundedVector2d(gfx::ScaleVector2d(
- initial_position +
- gfx::ScaleVector2d(initial_velocity, elapsed_time * amplitude),
- critical_dampening_factor));
-}
-
-gfx::Vector2d StretchAmountForReboundDelta(const gfx::Vector2dF& delta) {
- float stiffness = std::max(kRubberbandStiffness, 1.0f);
- return gfx::ToRoundedVector2d(gfx::ScaleVector2d(delta, 1.0f / stiffness));
-}
-
-gfx::Vector2d StretchScrollForceForStretchAmount(const gfx::Vector2dF& delta) {
- return gfx::ToRoundedVector2d(
- gfx::ScaleVector2d(delta, kRubberbandStiffness));
-}
-
-} // namespace
-
-InputScrollElasticityController::InputScrollElasticityController(
- cc::ScrollElasticityHelper* helper)
- : helper_(helper),
- state_(kStateInactive),
- momentum_animation_reset_at_next_frame_(false),
- weak_factory_(this) {
-}
-
-InputScrollElasticityController::~InputScrollElasticityController() {
-}
-
-base::WeakPtr<InputScrollElasticityController>
-InputScrollElasticityController::GetWeakPtr() {
- if (helper_)
- return weak_factory_.GetWeakPtr();
- return base::WeakPtr<InputScrollElasticityController>();
-}
-
-void InputScrollElasticityController::ObserveWheelEventAndResult(
- const blink::WebMouseWheelEvent& wheel_event,
- const cc::InputHandlerScrollResult& scroll_result) {
- // We should only get PhaseMayBegin or PhaseBegan events while in the
- // Inactive or MomentumAnimated states, but in case we get bad input (e.g,
- // abbreviated by tab-switch), always re-set the state to ActiveScrolling
- // when those events are received.
- if (wheel_event.phase == blink::WebMouseWheelEvent::PhaseMayBegin ||
- wheel_event.phase == blink::WebMouseWheelEvent::PhaseBegan) {
- scroll_velocity = gfx::Vector2dF();
- last_scroll_event_timestamp_ = base::TimeTicks();
- state_ = kStateActiveScroll;
- pending_overscroll_delta_ = gfx::Vector2dF();
- return;
- }
-
- gfx::Vector2dF event_delta(-wheel_event.deltaX, -wheel_event.deltaY);
- base::TimeTicks event_timestamp =
- base::TimeTicks() +
- base::TimeDelta::FromSecondsD(wheel_event.timeStampSeconds);
- switch (state_) {
- case kStateInactive: {
- // The PhaseMayBegin and PhaseBegan cases are handled at the top of the
- // function.
- if (wheel_event.momentumPhase == blink::WebMouseWheelEvent::PhaseBegan)
- state_ = kStateMomentumScroll;
- break;
- }
- case kStateActiveScroll:
- if (wheel_event.phase == blink::WebMouseWheelEvent::PhaseChanged) {
- UpdateVelocity(event_delta, event_timestamp);
- Overscroll(event_delta, scroll_result.unused_scroll_delta);
- } else if (wheel_event.phase == blink::WebMouseWheelEvent::PhaseEnded ||
- wheel_event.phase ==
- blink::WebMouseWheelEvent::PhaseCancelled) {
- if (helper_->StretchAmount().IsZero()) {
- EnterStateInactive();
- } else {
- EnterStateMomentumAnimated(event_timestamp);
- }
- }
- break;
- case kStateMomentumScroll:
- if (wheel_event.momentumPhase ==
- blink::WebMouseWheelEvent::PhaseChanged) {
- UpdateVelocity(event_delta, event_timestamp);
- Overscroll(event_delta, scroll_result.unused_scroll_delta);
- if (!helper_->StretchAmount().IsZero()) {
- EnterStateMomentumAnimated(event_timestamp);
- }
- } else if (wheel_event.momentumPhase ==
- blink::WebMouseWheelEvent::PhaseEnded) {
- EnterStateInactive();
- }
- case kStateMomentumAnimated:
- // The PhaseMayBegin and PhaseBegan cases are handled at the top of the
- // function.
- break;
- }
-}
-
-void InputScrollElasticityController::UpdateVelocity(
- const gfx::Vector2dF& event_delta,
- const base::TimeTicks& event_timestamp) {
- float time_delta =
- (event_timestamp - last_scroll_event_timestamp_).InSecondsF();
- if (time_delta < kScrollVelocityZeroingTimeout && time_delta > 0) {
- scroll_velocity = gfx::Vector2dF(event_delta.x() / time_delta,
- event_delta.y() / time_delta);
- } else {
- scroll_velocity = gfx::Vector2dF();
- }
- last_scroll_event_timestamp_ = event_timestamp;
-}
-
-void InputScrollElasticityController::Overscroll(
- const gfx::Vector2dF& input_delta,
- const gfx::Vector2dF& overscroll_delta) {
- // The effect can be dynamically disabled by setting disallowing user
- // scrolling. When disabled, disallow active or momentum overscrolling, but
- // allow any current overscroll to animate back.
- if (!helper_->IsUserScrollable())
- return;
-
- gfx::Vector2dF adjusted_overscroll_delta =
- pending_overscroll_delta_ + overscroll_delta;
- pending_overscroll_delta_ = gfx::Vector2dF();
-
- // Only allow one direction to overscroll at a time, and slightly prefer
- // scrolling vertically by applying the equal case to delta_y.
- if (fabsf(input_delta.y()) >= fabsf(input_delta.x()))
- adjusted_overscroll_delta.set_x(0);
- else
- adjusted_overscroll_delta.set_y(0);
-
- // Don't allow overscrolling in a direction where scrolling is possible.
- if (!PinnedHorizontally(adjusted_overscroll_delta.x()))
- adjusted_overscroll_delta.set_x(0);
- if (!PinnedVertically(adjusted_overscroll_delta.y())) {
- adjusted_overscroll_delta.set_y(0);
- }
-
- // Require a minimum of 10 units of overscroll before starting the rubber-band
- // stretch effect, so that small stray motions don't trigger it. If that
- // minimum isn't met, save what remains in |pending_overscroll_delta_| for
- // the next event.
- gfx::Vector2dF old_stretch_amount = helper_->StretchAmount();
- gfx::Vector2dF stretch_scroll_force_delta;
- if (old_stretch_amount.x() != 0 ||
- fabsf(adjusted_overscroll_delta.x()) >=
- kRubberbandMinimumRequiredDeltaBeforeStretch) {
- stretch_scroll_force_delta.set_x(adjusted_overscroll_delta.x());
- } else {
- pending_overscroll_delta_.set_x(adjusted_overscroll_delta.x());
- }
- if (old_stretch_amount.y() != 0 ||
- fabsf(adjusted_overscroll_delta.y()) >=
- kRubberbandMinimumRequiredDeltaBeforeStretch) {
- stretch_scroll_force_delta.set_y(adjusted_overscroll_delta.y());
- } else {
- pending_overscroll_delta_.set_y(adjusted_overscroll_delta.y());
- }
-
- // Update the stretch amount according to the spring equations.
- if (stretch_scroll_force_delta.IsZero())
- return;
- stretch_scroll_force_ += stretch_scroll_force_delta;
- gfx::Vector2dF new_stretch_amount =
- StretchAmountForReboundDelta(stretch_scroll_force_);
- helper_->SetStretchAmount(new_stretch_amount);
-}
-
-void InputScrollElasticityController::EnterStateInactive() {
- DCHECK_NE(kStateInactive, state_);
- DCHECK(helper_->StretchAmount().IsZero());
- state_ = kStateInactive;
- stretch_scroll_force_ = gfx::Vector2dF();
-}
-
-void InputScrollElasticityController::EnterStateMomentumAnimated(
- const base::TimeTicks& triggering_event_timestamp) {
- DCHECK_NE(kStateMomentumAnimated, state_);
- state_ = kStateMomentumAnimated;
-
- momentum_animation_start_time_ = triggering_event_timestamp;
- momentum_animation_initial_stretch_ = helper_->StretchAmount();
- momentum_animation_initial_velocity_ = scroll_velocity;
- momentum_animation_reset_at_next_frame_ = false;
-
- // Similarly to the logic in Overscroll, prefer vertical scrolling to
- // horizontal scrolling.
- if (fabsf(momentum_animation_initial_velocity_.y()) >=
- fabsf(momentum_animation_initial_velocity_.x()))
- momentum_animation_initial_velocity_.set_x(0);
-
- if (!CanScrollHorizontally())
- momentum_animation_initial_velocity_.set_x(0);
-
- if (!CanScrollVertically())
- momentum_animation_initial_velocity_.set_y(0);
-
- helper_->RequestAnimate();
-}
-
-void InputScrollElasticityController::Animate(base::TimeTicks time) {
- if (state_ != kStateMomentumAnimated)
- return;
-
- if (momentum_animation_reset_at_next_frame_) {
- momentum_animation_start_time_ = time;
- momentum_animation_initial_stretch_ = helper_->StretchAmount();
- momentum_animation_initial_velocity_ = gfx::Vector2dF();
- momentum_animation_reset_at_next_frame_ = false;
- }
-
- float time_delta =
- std::max((time - momentum_animation_start_time_).InSecondsF(), 0.0);
-
- gfx::Vector2dF old_stretch_amount = helper_->StretchAmount();
- gfx::Vector2dF new_stretch_amount = StretchAmountForTimeDelta(
- momentum_animation_initial_stretch_, momentum_animation_initial_velocity_,
- time_delta);
- gfx::Vector2dF stretch_delta = new_stretch_amount - old_stretch_amount;
-
- // If the new stretch amount is near zero, set it directly to zero and enter
- // the inactive state.
- if (fabs(new_stretch_amount.x()) < 1 && fabs(new_stretch_amount.y()) < 1) {
- helper_->SetStretchAmount(gfx::Vector2dF());
- EnterStateInactive();
- return;
- }
-
- // If we are not pinned in the direction of the delta, then the delta is only
- // allowed to decrease the existing stretch -- it cannot increase a stretch
- // until it is pinned.
- if (!PinnedHorizontally(stretch_delta.x())) {
- if (stretch_delta.x() > 0 && old_stretch_amount.x() < 0)
- stretch_delta.set_x(std::min(stretch_delta.x(), -old_stretch_amount.x()));
- else if (stretch_delta.x() < 0 && old_stretch_amount.x() > 0)
- stretch_delta.set_x(std::max(stretch_delta.x(), -old_stretch_amount.x()));
- else
- stretch_delta.set_x(0);
- }
- if (!PinnedVertically(stretch_delta.y())) {
- if (stretch_delta.y() > 0 && old_stretch_amount.y() < 0)
- stretch_delta.set_y(std::min(stretch_delta.y(), -old_stretch_amount.y()));
- else if (stretch_delta.y() < 0 && old_stretch_amount.y() > 0)
- stretch_delta.set_y(std::max(stretch_delta.y(), -old_stretch_amount.y()));
- else
- stretch_delta.set_y(0);
- }
- new_stretch_amount = old_stretch_amount + stretch_delta;
-
- stretch_scroll_force_ =
- StretchScrollForceForStretchAmount(new_stretch_amount);
- helper_->SetStretchAmount(new_stretch_amount);
- helper_->RequestAnimate();
-}
-
-bool InputScrollElasticityController::PinnedHorizontally(
- float direction) const {
- gfx::ScrollOffset scroll_offset = helper_->ScrollOffset();
- gfx::ScrollOffset max_scroll_offset = helper_->MaxScrollOffset();
- if (direction < 0)
- return scroll_offset.x() <= 0;
- if (direction > 0)
- return scroll_offset.x() >= max_scroll_offset.x();
- return false;
-}
-
-bool InputScrollElasticityController::PinnedVertically(float direction) const {
- gfx::ScrollOffset scroll_offset = helper_->ScrollOffset();
- gfx::ScrollOffset max_scroll_offset = helper_->MaxScrollOffset();
- if (direction < 0)
- return scroll_offset.y() <= 0;
- if (direction > 0)
- return scroll_offset.y() >= max_scroll_offset.y();
- return false;
-}
-
-bool InputScrollElasticityController::CanScrollHorizontally() const {
- return helper_->MaxScrollOffset().x() > 0;
-}
-
-bool InputScrollElasticityController::CanScrollVertically() const {
- return helper_->MaxScrollOffset().y() > 0;
-}
-
-void InputScrollElasticityController::ReconcileStretchAndScroll() {
- gfx::Vector2dF stretch = helper_->StretchAmount();
- if (stretch.IsZero())
- return;
-
- gfx::ScrollOffset scroll_offset = helper_->ScrollOffset();
- gfx::ScrollOffset max_scroll_offset = helper_->MaxScrollOffset();
-
- // Compute stretch_adjustment which will be added to |stretch| and subtracted
- // from the |scroll_offset|.
- gfx::Vector2dF stretch_adjustment;
- if (stretch.x() < 0 && scroll_offset.x() > 0) {
- stretch_adjustment.set_x(
- std::min(-stretch.x(), static_cast<float>(scroll_offset.x())));
- }
- if (stretch.x() > 0 && scroll_offset.x() < max_scroll_offset.x()) {
- stretch_adjustment.set_x(std::max(
- -stretch.x(),
- static_cast<float>(scroll_offset.x() - max_scroll_offset.x())));
- }
- if (stretch.y() < 0 && scroll_offset.y() > 0) {
- stretch_adjustment.set_y(
- std::min(-stretch.y(), static_cast<float>(scroll_offset.y())));
- }
- if (stretch.y() > 0 && scroll_offset.y() < max_scroll_offset.y()) {
- stretch_adjustment.set_y(std::max(
- -stretch.y(),
- static_cast<float>(scroll_offset.y() - max_scroll_offset.y())));
- }
-
- if (stretch_adjustment.IsZero())
- return;
-
- gfx::Vector2dF new_stretch_amount = stretch + stretch_adjustment;
- helper_->ScrollBy(-stretch_adjustment);
- helper_->SetStretchAmount(new_stretch_amount);
-
- // Update the internal state for the active scroll or animation to avoid
- // discontinuities.
- switch (state_) {
- case kStateActiveScroll:
- stretch_scroll_force_ =
- StretchScrollForceForStretchAmount(new_stretch_amount);
- break;
- case kStateMomentumAnimated:
- momentum_animation_reset_at_next_frame_ = true;
- break;
- default:
- // These cases should not be hit because the stretch must be zero in the
- // Inactive and MomentumScroll states.
- NOTREACHED();
- break;
- }
-}
-
-} // namespace content
diff --git a/content/renderer/input/input_scroll_elasticity_controller.h b/content/renderer/input/input_scroll_elasticity_controller.h
deleted file mode 100644
index c60a86e..0000000
--- a/content/renderer/input/input_scroll_elasticity_controller.h
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright 2014 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_INPUT_SCROLL_ELASTICITY_CONTROLLER_H_
-#define CONTENT_RENDERER_INPUT_INPUT_SCROLL_ELASTICITY_CONTROLLER_H_
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "cc/input/scroll_elasticity_helper.h"
-#include "content/common/content_export.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
-
-// InputScrollElasticityController is based on
-// WebKit/Source/platform/mac/ScrollElasticityController.h
-/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-namespace cc {
-struct InputHandlerScrollResult;
-} // namespace cc
-
-namespace content {
-
-class CONTENT_EXPORT InputScrollElasticityController {
- public:
- explicit InputScrollElasticityController(cc::ScrollElasticityHelper* helper);
- virtual ~InputScrollElasticityController();
-
- base::WeakPtr<InputScrollElasticityController> GetWeakPtr();
-
- // Update the overscroll state based a wheel event that has been processed.
- // Note that this assumes that all events are coming from a single input
- // device. If the user simultaneously uses multiple input devices, Cocoa may
- // not correctly pass all the gesture begin and end events. In this case,
- // this class may disregard some scrolls that come in at unexpected times.
- void ObserveWheelEventAndResult(
- const blink::WebMouseWheelEvent& wheel_event,
- const cc::InputHandlerScrollResult& scroll_result);
- void Animate(base::TimeTicks time);
-
- void ReconcileStretchAndScroll();
-
- private:
- enum State {
- // The initial state, during which the overscroll amount is zero and
- // there are no active or momentum scroll events coming in. This state
- // is briefly returned to between the active and momentum phases of a
- // scroll (if there is no overscroll).
- kStateInactive,
- // The state between receiving PhaseBegan/MayBegin and PhaseEnd/Cancelled,
- // corresponding to the period during which the user has fingers on the
- // trackpad. The overscroll amount is updated as input events are received.
- // When PhaseEnd is received, the state transitions to Inactive if there is
- // no overscroll and MomentumAnimated if there is non-zero overscroll.
- kStateActiveScroll,
- // The state between receiving a momentum PhaseBegan and PhaseEnd, while
- // there is no overscroll. The overscroll amount is updated as input events
- // are received. If the overscroll is ever non-zero then the state
- // immediately transitions to kStateMomentumAnimated.
- kStateMomentumScroll,
- // The state while the overscroll amount is updated by an animation. If
- // the user places fingers on the trackpad (a PhaseMayBegin is received)
- // then the state transition to kStateActiveScroll. Otherwise the state
- // transitions to Inactive when the overscroll amount becomes zero.
- kStateMomentumAnimated,
- };
-
- void UpdateVelocity(const gfx::Vector2dF& event_delta,
- const base::TimeTicks& event_timestamp);
- void Overscroll(const gfx::Vector2dF& input_delta,
- const gfx::Vector2dF& overscroll_delta);
- void EnterStateMomentumAnimated(
- const base::TimeTicks& triggering_event_timestamp);
- void EnterStateInactive();
-
- // Returns true if |direction| is pointing in a direction in which it is not
- // possible to scroll any farther horizontally (or vertically). It is only in
- // this circumstance that an overscroll in that direction may begin.
- bool PinnedHorizontally(float direction) const;
- bool PinnedVertically(float direction) const;
- // Whether or not the content of the page is scrollable horizontaly (or
- // vertically).
- bool CanScrollHorizontally() const;
- bool CanScrollVertically() const;
-
- cc::ScrollElasticityHelper* helper_;
- State state_;
-
- // If there is no overscroll, require a minimum overscroll delta before
- // starting the rubber-band effect. Track the amount of scrolling that has
- // has occurred but has not yet caused rubber-band stretching in
- // |pending_overscroll_delta_|.
- gfx::Vector2dF pending_overscroll_delta_;
-
- // Maintain a calculation of the velocity of the scroll, based on the input
- // scroll delta divide by the time between input events. Track this velocity
- // in |scroll_velocity| and the previous input event timestamp for finite
- // differencing in |last_scroll_event_timestamp_|.
- gfx::Vector2dF scroll_velocity;
- base::TimeTicks last_scroll_event_timestamp_;
-
- // The force of the rubber-band spring. This is equal to the cumulative sum
- // of all overscroll offsets since entering a non-Inactive state. This is
- // reset to zero only when entering the Inactive state.
- gfx::Vector2dF stretch_scroll_force_;
-
- // Momentum animation state. This state is valid only while the state is
- // MomentumAnimated, and is initialized in EnterStateMomentumAnimated.
- base::TimeTicks momentum_animation_start_time_;
- gfx::Vector2dF momentum_animation_initial_stretch_;
- gfx::Vector2dF momentum_animation_initial_velocity_;
-
- // This is set in response to a scroll (most likely programmatic) occuring
- // while animating the momentum phase. In this case, re-set the initial
- // velocity, stretch, and start time at the next frame (this is the same
- // behavior as would happen if the scroll were caused by an active scroll).
- bool momentum_animation_reset_at_next_frame_;
-
- base::WeakPtrFactory<InputScrollElasticityController> weak_factory_;
- DISALLOW_COPY_AND_ASSIGN(InputScrollElasticityController);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_INPUT_INPUT_SCROLL_ELASTICITY_CONTROLLER_H_
diff --git a/content/renderer/input/input_scroll_elasticity_controller_unittest.cc b/content/renderer/input/input_scroll_elasticity_controller_unittest.cc
deleted file mode 100644
index fa2c7f1..0000000
--- a/content/renderer/input/input_scroll_elasticity_controller_unittest.cc
+++ /dev/null
@@ -1,387 +0,0 @@
-// Copyright 2014 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.
-
-#include "cc/input/input_handler.h"
-#include "content/renderer/input/input_scroll_elasticity_controller.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
-
-namespace content {
-namespace {
-
-enum Phase {
- PhaseNone = blink::WebMouseWheelEvent::PhaseNone,
- PhaseBegan = blink::WebMouseWheelEvent::PhaseBegan,
- PhaseStationary = blink::WebMouseWheelEvent::PhaseStationary,
- PhaseChanged = blink::WebMouseWheelEvent::PhaseChanged,
- PhaseEnded = blink::WebMouseWheelEvent::PhaseEnded,
- PhaseCancelled = blink::WebMouseWheelEvent::PhaseCancelled,
- PhaseMayBegin = blink::WebMouseWheelEvent::PhaseMayBegin,
-};
-
-class MockScrollElasticityHelper : public cc::ScrollElasticityHelper {
- public:
- MockScrollElasticityHelper()
- : is_user_scrollable_(true),
- set_stretch_amount_count_(0),
- request_animate_count_(0) {}
- ~MockScrollElasticityHelper() override {}
-
- // cc::ScrollElasticityHelper implementation:
- bool IsUserScrollable() const override { return is_user_scrollable_; }
- gfx::Vector2dF StretchAmount() const override { return stretch_amount_; }
- void SetStretchAmount(const gfx::Vector2dF& stretch_amount) override {
- set_stretch_amount_count_ += 1;
- stretch_amount_ = stretch_amount;
- }
- gfx::ScrollOffset ScrollOffset() const override { return scroll_offset_; }
- gfx::ScrollOffset MaxScrollOffset() const override {
- return max_scroll_offset_;
- }
- void ScrollBy(const gfx::Vector2dF& delta) override {
- scroll_offset_ += gfx::ScrollOffset(delta);
- }
- void RequestAnimate() override { request_animate_count_ += 1; }
-
- // Counters for number of times functions were called.
- int request_animate_count() const { return request_animate_count_; }
- int set_stretch_amount_count() const { return set_stretch_amount_count_; }
-
- void SetScrollOffsetAndMaxScrollOffset(
- const gfx::ScrollOffset& scroll_offset,
- const gfx::ScrollOffset& max_scroll_offset) {
- scroll_offset_ = scroll_offset;
- max_scroll_offset_ = max_scroll_offset;
- }
- void SetUserScrollable(bool is_user_scrollable) {
- is_user_scrollable_ = is_user_scrollable;
- }
-
- private:
- bool is_user_scrollable_;
- gfx::Vector2dF stretch_amount_;
- int set_stretch_amount_count_;
- int request_animate_count_;
-
- gfx::ScrollOffset scroll_offset_;
- gfx::ScrollOffset max_scroll_offset_;
-};
-
-class ScrollElasticityControllerTest : public testing::Test {
- public:
- ScrollElasticityControllerTest()
- : controller_(&helper_),
- input_event_count_(0),
- current_time_(base::TimeTicks::FromInternalValue(100000000ull)) {}
- ~ScrollElasticityControllerTest() override {}
-
- void SendMouseWheelEvent(
- Phase phase,
- Phase momentum_phase,
- const gfx::Vector2dF& event_delta = gfx::Vector2dF(),
- const gfx::Vector2dF& overscroll_delta = gfx::Vector2dF()) {
- blink::WebMouseWheelEvent event;
- event.phase = static_cast<blink::WebMouseWheelEvent::Phase>(phase);
- event.momentumPhase =
- static_cast<blink::WebMouseWheelEvent::Phase>(momentum_phase);
- event.deltaX = -event_delta.x();
- event.deltaY = -event_delta.y();
- TickCurrentTime();
- event.timeStampSeconds = (current_time_ - base::TimeTicks()).InSecondsF();
-
- cc::InputHandlerScrollResult scroll_result;
- scroll_result.did_overscroll_root = !overscroll_delta.IsZero();
- scroll_result.unused_scroll_delta = overscroll_delta;
-
- controller_.ObserveWheelEventAndResult(event, scroll_result);
- input_event_count_ += 1;
- }
-
- const base::TimeTicks& TickCurrentTime() {
- current_time_ += base::TimeDelta::FromSecondsD(1 / 60.f);
- return current_time_;
- }
- void TickCurrentTimeAndAnimate() {
- TickCurrentTime();
- controller_.Animate(current_time_);
- }
-
- MockScrollElasticityHelper helper_;
- InputScrollElasticityController controller_;
- int input_event_count_;
- base::TimeTicks current_time_;
-};
-
-// Verify that stretching only occurs in one axis at a time, and that it
-// is biased to the Y axis.
-TEST_F(ScrollElasticityControllerTest, Axis) {
- helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(0, 0),
- gfx::ScrollOffset(0, 0));
-
- // If we push equally in the X and Y directions, we should see a stretch only
- // in the Y direction.
- SendMouseWheelEvent(PhaseBegan, PhaseNone);
- SendMouseWheelEvent(PhaseChanged, PhaseNone, gfx::Vector2dF(10, 10),
- gfx::Vector2dF(10, 10));
- EXPECT_EQ(1, helper_.set_stretch_amount_count());
- EXPECT_EQ(0.f, helper_.StretchAmount().x());
- EXPECT_LT(0.f, helper_.StretchAmount().y());
- helper_.SetStretchAmount(gfx::Vector2dF());
- EXPECT_EQ(2, helper_.set_stretch_amount_count());
- SendMouseWheelEvent(PhaseEnded, PhaseNone);
- EXPECT_EQ(0, helper_.request_animate_count());
-
- // If we push more in the X direction than the Y direction, we should see a
- // stretch only in the X direction. This decision should be based on the
- // input delta, not the actual overscroll delta.
- SendMouseWheelEvent(PhaseBegan, PhaseNone);
- SendMouseWheelEvent(PhaseChanged, PhaseNone, gfx::Vector2dF(-25, 10),
- gfx::Vector2dF(-25, 40));
- EXPECT_EQ(3, helper_.set_stretch_amount_count());
- EXPECT_GT(0.f, helper_.StretchAmount().x());
- EXPECT_EQ(0.f, helper_.StretchAmount().y());
- helper_.SetStretchAmount(gfx::Vector2dF());
- EXPECT_EQ(4, helper_.set_stretch_amount_count());
- SendMouseWheelEvent(PhaseEnded, PhaseNone);
- EXPECT_EQ(0, helper_.request_animate_count());
-}
-
-// Verify that we need a total overscroll delta of at least 10 in a pinned
-// direction before we start stretching.
-TEST_F(ScrollElasticityControllerTest, MinimumDeltaBeforeStretch) {
- // We should not start stretching while we are not pinned in the direction
- // of the scroll (even if there is an overscroll delta). We have to wait for
- // the regular scroll to eat all of the events.
- helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(5, 5),
- gfx::ScrollOffset(10, 10));
- SendMouseWheelEvent(PhaseMayBegin, PhaseNone);
- SendMouseWheelEvent(PhaseBegan, PhaseNone);
- SendMouseWheelEvent(PhaseChanged, PhaseNone, gfx::Vector2dF(0, 10),
- gfx::Vector2dF(0, 10));
- SendMouseWheelEvent(PhaseChanged, PhaseNone, gfx::Vector2dF(0, 10),
- gfx::Vector2dF(0, 10));
- EXPECT_EQ(0, helper_.set_stretch_amount_count());
-
- // Now pin the -X and +Y direction. The first event will not generate a
- // stretch
- // because it is below the delta threshold of 10.
- helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(0, 10),
- gfx::ScrollOffset(10, 10));
- SendMouseWheelEvent(PhaseChanged, PhaseNone, gfx::Vector2dF(0, 10),
- gfx::Vector2dF(0, 8));
- EXPECT_EQ(0, helper_.set_stretch_amount_count());
-
- // Make the next scroll be in the -X direction more than the +Y direction,
- // which will erase the memory of the previous unused delta of 8.
- SendMouseWheelEvent(PhaseChanged, PhaseNone, gfx::Vector2dF(-10, 5),
- gfx::Vector2dF(-8, 10));
- EXPECT_EQ(0, helper_.set_stretch_amount_count());
-
- // Now push against the pinned +Y direction again by 8. We reset the
- // previous delta, so this will not generate a stretch.
- SendMouseWheelEvent(PhaseChanged, PhaseNone, gfx::Vector2dF(0, 10),
- gfx::Vector2dF(0, 8));
- EXPECT_EQ(0, helper_.set_stretch_amount_count());
-
- // Push against +Y by another 8. This gets us above the delta threshold of
- // 10, so we should now have had the stretch set, and it should be in the
- // +Y direction. The scroll in the -X direction should have been forgotten.
- SendMouseWheelEvent(PhaseChanged, PhaseNone, gfx::Vector2dF(0, 10),
- gfx::Vector2dF(0, 8));
- EXPECT_EQ(1, helper_.set_stretch_amount_count());
- EXPECT_EQ(0.f, helper_.StretchAmount().x());
- EXPECT_LT(0.f, helper_.StretchAmount().y());
-
- // End the gesture. Because there is a non-zero stretch, we should be in the
- // animated state, and should have had a frame requested.
- EXPECT_EQ(0, helper_.request_animate_count());
- SendMouseWheelEvent(PhaseEnded, PhaseNone);
- EXPECT_EQ(1, helper_.request_animate_count());
-}
-
-// Verify that an stretch caused by a momentum scroll will switch to the
-// animating mode, where input events are ignored, and the stretch is updated
-// while animating.
-TEST_F(ScrollElasticityControllerTest, MomentumAnimate) {
- // Do an active scroll, then switch to the momentum phase and scroll for a
- // bit.
- helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(5, 5),
- gfx::ScrollOffset(10, 10));
- SendMouseWheelEvent(PhaseBegan, PhaseNone);
- SendMouseWheelEvent(PhaseChanged, PhaseNone, gfx::Vector2dF(0, -80),
- gfx::Vector2dF(0, 0));
- SendMouseWheelEvent(PhaseChanged, PhaseNone, gfx::Vector2dF(0, -80),
- gfx::Vector2dF(0, 0));
- SendMouseWheelEvent(PhaseChanged, PhaseNone, gfx::Vector2dF(0, -80),
- gfx::Vector2dF(0, 0));
- SendMouseWheelEvent(PhaseEnded, PhaseNone);
- SendMouseWheelEvent(PhaseNone, PhaseBegan);
- SendMouseWheelEvent(PhaseNone, PhaseChanged, gfx::Vector2dF(0, -80),
- gfx::Vector2dF(0, 0));
- SendMouseWheelEvent(PhaseNone, PhaseChanged, gfx::Vector2dF(0, -80),
- gfx::Vector2dF(0, 0));
- SendMouseWheelEvent(PhaseNone, PhaseChanged, gfx::Vector2dF(0, -80),
- gfx::Vector2dF(0, 0));
- EXPECT_EQ(0, helper_.set_stretch_amount_count());
-
- // Hit the -Y edge and overscroll slightly, but not enough to go over the
- // threshold to cause a stretch.
- helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(5, 0),
- gfx::ScrollOffset(10, 10));
- SendMouseWheelEvent(PhaseNone, PhaseChanged, gfx::Vector2dF(0, -80),
- gfx::Vector2dF(0, -8));
- EXPECT_EQ(0, helper_.set_stretch_amount_count());
- EXPECT_EQ(0, helper_.request_animate_count());
-
- // Take another step, this time going over the threshold. This should update
- // the stretch amount, and then switch to the animating mode.
- SendMouseWheelEvent(PhaseNone, PhaseChanged, gfx::Vector2dF(0, -80),
- gfx::Vector2dF(0, -80));
- EXPECT_EQ(1, helper_.set_stretch_amount_count());
- EXPECT_EQ(1, helper_.request_animate_count());
- EXPECT_GT(-1.f, helper_.StretchAmount().y());
-
- // Subsequent momentum events should do nothing.
- SendMouseWheelEvent(PhaseNone, PhaseChanged, gfx::Vector2dF(0, -80),
- gfx::Vector2dF(0, -80));
- SendMouseWheelEvent(PhaseNone, PhaseChanged, gfx::Vector2dF(0, -80),
- gfx::Vector2dF(0, -80));
- SendMouseWheelEvent(PhaseNone, PhaseEnded, gfx::Vector2dF(0, -80),
- gfx::Vector2dF(0, -80));
- EXPECT_EQ(1, helper_.set_stretch_amount_count());
- EXPECT_EQ(1, helper_.request_animate_count());
-
- // Subsequent animate events should update the stretch amount and request
- // another frame.
- TickCurrentTimeAndAnimate();
- EXPECT_EQ(2, helper_.set_stretch_amount_count());
- EXPECT_EQ(2, helper_.request_animate_count());
- EXPECT_GT(-1.f, helper_.StretchAmount().y());
-
- // Touching the trackpad (a PhaseMayBegin event) should disable animation.
- SendMouseWheelEvent(PhaseMayBegin, PhaseNone);
- TickCurrentTimeAndAnimate();
- EXPECT_EQ(2, helper_.set_stretch_amount_count());
- EXPECT_EQ(2, helper_.request_animate_count());
-
- // Releasing the trackpad should re-enable animation.
- SendMouseWheelEvent(PhaseCancelled, PhaseNone);
- EXPECT_EQ(2, helper_.set_stretch_amount_count());
- EXPECT_EQ(3, helper_.request_animate_count());
- TickCurrentTimeAndAnimate();
- EXPECT_EQ(3, helper_.set_stretch_amount_count());
- EXPECT_EQ(4, helper_.request_animate_count());
-
- // Keep animating frames until the stretch returns to rest.
- int stretch_count = 3;
- int animate_count = 4;
- while (1) {
- TickCurrentTimeAndAnimate();
- if (helper_.StretchAmount().IsZero()) {
- stretch_count += 1;
- EXPECT_EQ(stretch_count, helper_.set_stretch_amount_count());
- EXPECT_EQ(animate_count, helper_.request_animate_count());
- break;
- }
- stretch_count += 1;
- animate_count += 1;
- EXPECT_EQ(stretch_count, helper_.set_stretch_amount_count());
- EXPECT_EQ(animate_count, helper_.request_animate_count());
- }
-
- // After coming to rest, no subsequent animate calls change anything.
- TickCurrentTimeAndAnimate();
- EXPECT_EQ(stretch_count, helper_.set_stretch_amount_count());
- EXPECT_EQ(animate_count, helper_.request_animate_count());
-}
-
-// Verify that an stretch opposing a scroll is correctly resolved.
-TEST_F(ScrollElasticityControllerTest, ReconcileStretchAndScroll) {
- SendMouseWheelEvent(PhaseBegan, PhaseNone);
-
- // Verify completely knocking out the scroll in the -Y direction.
- helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(5, 5),
- gfx::ScrollOffset(10, 10));
- helper_.SetStretchAmount(gfx::Vector2dF(0, -10));
- controller_.ReconcileStretchAndScroll();
- EXPECT_EQ(helper_.StretchAmount(), gfx::Vector2dF(0, -5));
- EXPECT_EQ(helper_.ScrollOffset(), gfx::ScrollOffset(5, 0));
-
- // Verify partially knocking out the scroll in the -Y direction.
- helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(5, 8),
- gfx::ScrollOffset(10, 10));
- helper_.SetStretchAmount(gfx::Vector2dF(0, -5));
- controller_.ReconcileStretchAndScroll();
- EXPECT_EQ(helper_.StretchAmount(), gfx::Vector2dF(0, 0));
- EXPECT_EQ(helper_.ScrollOffset(), gfx::ScrollOffset(5, 3));
-
- // Verify completely knocking out the scroll in the +X direction.
- helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(5, 5),
- gfx::ScrollOffset(10, 10));
- helper_.SetStretchAmount(gfx::Vector2dF(10, 0));
- controller_.ReconcileStretchAndScroll();
- EXPECT_EQ(helper_.StretchAmount(), gfx::Vector2dF(5, 0));
- EXPECT_EQ(helper_.ScrollOffset(), gfx::ScrollOffset(10, 5));
-
- // Verify partially knocking out the scroll in the +X and +Y directions.
- helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(2, 3),
- gfx::ScrollOffset(10, 10));
- helper_.SetStretchAmount(gfx::Vector2dF(5, 5));
- controller_.ReconcileStretchAndScroll();
- EXPECT_EQ(helper_.StretchAmount(), gfx::Vector2dF(0, 0));
- EXPECT_EQ(helper_.ScrollOffset(), gfx::ScrollOffset(7, 8));
-}
-
-// Verify that stretching only happens when the area is user scrollable.
-TEST_F(ScrollElasticityControllerTest, UserScrollableRequiredForStretch) {
- helper_.SetScrollOffsetAndMaxScrollOffset(gfx::ScrollOffset(0, 0),
- gfx::ScrollOffset(10, 10));
- gfx::Vector2dF delta(0, -15);
-
- // Do an active scroll, and ensure that the stretch amount doesn't change,
- // and also that the stretch amount isn't even ever changed.
- helper_.SetUserScrollable(false);
- SendMouseWheelEvent(PhaseBegan, PhaseNone);
- SendMouseWheelEvent(PhaseChanged, PhaseNone, delta, delta);
- SendMouseWheelEvent(PhaseChanged, PhaseNone, delta, delta);
- SendMouseWheelEvent(PhaseEnded, PhaseNone);
- EXPECT_EQ(helper_.StretchAmount(), gfx::Vector2dF(0, 0));
- EXPECT_EQ(0, helper_.set_stretch_amount_count());
- SendMouseWheelEvent(PhaseNone, PhaseBegan);
- SendMouseWheelEvent(PhaseNone, PhaseChanged, delta, delta);
- SendMouseWheelEvent(PhaseNone, PhaseChanged, delta, delta);
- SendMouseWheelEvent(PhaseNone, PhaseEnded);
- EXPECT_EQ(helper_.StretchAmount(), gfx::Vector2dF(0, 0));
- EXPECT_EQ(0, helper_.set_stretch_amount_count());
-
- // Re-enable user scrolling and ensure that stretching is re-enabled.
- helper_.SetUserScrollable(true);
- SendMouseWheelEvent(PhaseBegan, PhaseNone);
- SendMouseWheelEvent(PhaseChanged, PhaseNone, delta, delta);
- SendMouseWheelEvent(PhaseChanged, PhaseNone, delta, delta);
- SendMouseWheelEvent(PhaseEnded, PhaseNone);
- EXPECT_NE(helper_.StretchAmount(), gfx::Vector2dF(0, 0));
- EXPECT_GT(helper_.set_stretch_amount_count(), 0);
- SendMouseWheelEvent(PhaseNone, PhaseBegan);
- SendMouseWheelEvent(PhaseNone, PhaseChanged, delta, delta);
- SendMouseWheelEvent(PhaseNone, PhaseChanged, delta, delta);
- SendMouseWheelEvent(PhaseNone, PhaseEnded);
- EXPECT_NE(helper_.StretchAmount(), gfx::Vector2dF(0, 0));
- EXPECT_GT(helper_.set_stretch_amount_count(), 0);
-
- // Disable user scrolling and tick the timer until the stretch goes back
- // to zero. Ensure that the return to zero doesn't happen immediately.
- helper_.SetUserScrollable(false);
- int ticks_to_zero = 0;
- while (1) {
- TickCurrentTimeAndAnimate();
- if (helper_.StretchAmount().IsZero())
- break;
- ticks_to_zero += 1;
- }
- EXPECT_GT(ticks_to_zero, 3);
-}
-
-} // namespace
-} // namespace content
diff --git a/content/renderer/input/synchronous_input_handler_proxy.h b/content/renderer/input/synchronous_input_handler_proxy.h
deleted file mode 100644
index 3bf3990..0000000
--- a/content/renderer/input/synchronous_input_handler_proxy.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// 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"
-#include "content/common/content_export.h"
-
-namespace gfx {
-class ScrollOffset;
-class SizeF;
-}
-
-namespace content {
-
-class CONTENT_EXPORT SynchronousInputHandler {
- public:
- virtual ~SynchronousInputHandler() {}
-
- // 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;
-
- // Informs the Android WebView embedder of the current root scroll and page
- // scale state.
- virtual void UpdateRootLayerState(
- const gfx::ScrollOffset& total_scroll_offset,
- const gfx::ScrollOffset& max_scroll_offset,
- const gfx::SizeF& scrollable_size,
- float page_scale_factor,
- float min_page_scale_factor,
- float max_page_scale_factor) = 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:
- virtual ~SynchronousInputHandlerProxy() {}
-
- // 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;
-
- // Called when the synchronous input handler wants to change the root scroll
- // offset. Since it has the final say, this overrides values from compositor-
- // controlled behaviour. After the offset is applied, the
- // SynchronousInputHandler should be given back the result in case it differs
- // from what was sent.
- virtual void SynchronouslySetRootScrollOffset(
- const gfx::ScrollOffset& root_offset) = 0;
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_INPUT_SYNCHRONOUS_INPUT_HANDLER_PROXY_H_