Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(776)

Unified Diff: content/renderer/input/input_handler_proxy.cc

Issue 1415953004: Move content/renderer input handling for web input events to ui (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « content/renderer/input/input_handler_proxy.h ('k') | content/renderer/input/input_handler_proxy_client.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: content/renderer/input/input_handler_proxy.cc
diff --git a/content/renderer/input/input_handler_proxy.cc b/content/renderer/input/input_handler_proxy.cc
deleted file mode 100644
index 255492f0d4d2556ead2a4e7d15058fe7689ea0fe..0000000000000000000000000000000000000000
--- 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
« no previous file with comments | « content/renderer/input/input_handler_proxy.h ('k') | content/renderer/input/input_handler_proxy_client.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698