#include "content/renderer/input/input_handler_proxy.h"
#include "base/auto_reset.h"
+#include "base/command_line.h"
#include "base/debug/trace_event.h"
#include "base/logging.h"
#include "base/metrics/histogram.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 "third_party/WebKit/public/platform/Platform.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
has_fling_animation_started_(false) {
DCHECK(client);
input_handler_->BindToClient(this);
+ smooth_scroll_enabled_ = CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableSmoothScrolling);
}
InputHandlerProxy::~InputHandlerProxy() {}
SendScrollLatencyUma(event, *latency_info);
- TRACE_EVENT_FLOW_STEP0(
- "input",
- "LatencyInfo.Flow",
- TRACE_ID_DONT_MANGLE(latency_info->trace_id),
- "HanldeInputEventImpl");
+ TRACE_EVENT_FLOW_STEP0("input",
+ "LatencyInfo.Flow",
+ TRACE_ID_DONT_MANGLE(latency_info->trace_id),
+ "HandleInputEventImpl");
scoped_ptr<cc::SwapPromiseMonitor> latency_info_swap_promise_monitor =
input_handler_->CreateLatencyInfoSwapPromiseMonitor(latency_info);
// event handlers. Forward to the main thread.
return DID_NOT_HANDLE;
}
+ if (smooth_scroll_enabled_) {
+ cc::InputHandler::ScrollStatus scroll_status =
+ input_handler_->ScrollAnimated(
+ gfx::Point(wheel_event.x, wheel_event.y),
+ gfx::Vector2dF(-wheel_event.deltaX, -wheel_event.deltaY));
+ switch (scroll_status) {
+ case cc::InputHandler::ScrollStarted:
+ return DID_HANDLE;
+ case cc::InputHandler::ScrollIgnored:
+ return DROP_EVENT;
+ default:
+ return DID_NOT_HANDLE;
+ }
+ }
cc::InputHandler::ScrollStatus scroll_status = input_handler_->ScrollBegin(
gfx::Point(wheel_event.x, wheel_event.y), cc::InputHandler::Wheel);
switch (scroll_status) {
*static_cast<const WebGestureEvent*>(&event);
return HandleGestureFling(gesture_event);
} else if (event.type == WebInputEvent::GestureFlingCancel) {
- if (CancelCurrentFling(true))
+ if (CancelCurrentFling())
return DID_HANDLE;
else if (!fling_may_be_active_on_main_thread_)
return DROP_EVENT;
// Only call |CancelCurrentFling()| if a fling was active, as it will
// otherwise disrupt an in-progress touch scroll.
if (fling_curve_)
- CancelCurrentFling(true);
+ CancelCurrentFling();
} else if (event.type == WebInputEvent::MouseMove) {
const WebMouseEvent& mouse_event =
*static_cast<const WebMouseEvent*>(&event);
// Gestures from a different source should immediately interrupt the fling.
if (gesture_event.sourceDevice != fling_parameters_.sourceDevice) {
- FlingBoostCancelAndResumeScrollingIfNecessary();
+ CancelCurrentFling();
return false;
}
fling_parameters_.sourceDevice == blink::WebGestureDeviceTouchpad
? cc::InputHandler::NonBubblingGesture
: cc::InputHandler::Gesture)) {
- CancelCurrentFling(true);
+ CancelCurrentFling();
return false;
}
// TODO(jdduke): Use |gesture_event.data.scrollBegin.delta{X,Y}Hint| to
// determine if the ScrollBegin should immediately cancel the fling.
- FlingBoostExtend(gesture_event);
+ ExtendBoostedFlingTimeout(gesture_event);
return true;
case WebInputEvent::GestureScrollUpdate: {
if (ShouldSuppressScrollForFlingBoosting(current_fling_velocity_,
gesture_event,
time_since_last_boost_event)) {
- FlingBoostExtend(gesture_event);
+ ExtendBoostedFlingTimeout(gesture_event);
return true;
}
- FlingBoostCancelAndResumeScrollingIfNecessary();
+ CancelCurrentFling();
return false;
}
case WebInputEvent::GestureScrollEnd:
- CancelCurrentFling(true);
+ // 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: {
default:
// All other types of gestures (taps, presses, etc...) will complete the
// deferred fling cancellation.
- FlingBoostCancelAndResumeScrollingIfNecessary();
+ CancelCurrentFling();
return false;
}
}
-void InputHandlerProxy::FlingBoostExtend(const blink::WebGestureEvent& event) {
- TRACE_EVENT_INSTANT0(
- "input", "InputHandlerProxy::FlingBoostExtend", TRACE_EVENT_SCOPE_THREAD);
+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::FlingBoostCancelAndResumeScrollingIfNecessary() {
- TRACE_EVENT_INSTANT0(
- "input", "InputHandlerProxy::FlingBoostCancel", TRACE_EVENT_SCOPE_THREAD);
- DCHECK(deferred_fling_cancel_time_seconds_);
-
- // Note: |last_fling_boost_event_| is cleared by |CancelCurrentFling()|.
- WebGestureEvent last_fling_boost_event = last_fling_boost_event_;
-
- CancelCurrentFling(true);
-
- 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));
- }
-}
-
void InputHandlerProxy::Animate(base::TimeTicks time) {
if (!fling_curve_)
return;
if (deferred_fling_cancel_time_seconds_ &&
monotonic_time_sec > deferred_fling_cancel_time_seconds_) {
- FlingBoostCancelAndResumeScrollingIfNecessary();
+ CancelCurrentFling();
return;
}
TRACE_EVENT_INSTANT0("input",
"InputHandlerProxy::animate::flingOver",
TRACE_EVENT_SCOPE_THREAD);
- CancelCurrentFling(true);
+ CancelCurrentFling();
}
}
}
void InputHandlerProxy::DidOverscroll(
+ const gfx::PointF& causal_event_viewport_point,
const gfx::Vector2dF& accumulated_overscroll,
const gfx::Vector2dF& latest_overscroll_delta) {
DCHECK(client_);
params.latest_overscroll_delta = latest_overscroll_delta;
params.current_fling_velocity =
ToClientScrollIncrement(current_fling_velocity_);
+ params.causal_event_viewport_point = causal_event_viewport_point;
if (fling_curve_) {
static const int kFlingOverscrollThreshold = 1;
client_->DidOverscroll(params);
}
-bool InputHandlerProxy::CancelCurrentFling(
- bool send_fling_stopped_notification) {
+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) {
gesture_scroll_on_impl_thread_ = false;
current_fling_velocity_ = gfx::Vector2dF();
fling_parameters_ = blink::WebActiveWheelFlingParameters();
- deferred_fling_cancel_time_seconds_ = 0;
- last_fling_boost_event_ = WebGestureEvent();
- if (send_fling_stopped_notification && had_fling_animation)
- client_->DidStopFlinging();
+
+ 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;
}
// the subarea but then is flung "under" the pointer.
client_->TransferActiveWheelFlingAnimation(fling_parameters_);
fling_may_be_active_on_main_thread_ = true;
- CancelCurrentFling(false);
+ CancelCurrentFlingWithoutNotifyingClient();
break;
}