Index: content/browser/renderer_host/input/mouse_wheel_phase_handler.cc |
diff --git a/content/browser/renderer_host/input/mouse_wheel_phase_handler.cc b/content/browser/renderer_host/input/mouse_wheel_phase_handler.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..318561b07fc0c9f57481e8b794926de90f1bc3ee |
--- /dev/null |
+++ b/content/browser/renderer_host/input/mouse_wheel_phase_handler.cc |
@@ -0,0 +1,99 @@ |
+// Copyright 2017 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/browser/renderer_host/input/mouse_wheel_phase_handler.h" |
+ |
+#include "content/browser/renderer_host/render_widget_host_impl.h" |
+#include "content/browser/renderer_host/render_widget_host_input_event_router.h" |
+#include "content/browser/renderer_host/render_widget_host_view_base.h" |
+ |
+namespace content { |
+MouseWheelPhaseHandler::MouseWheelPhaseHandler( |
+ RenderWidgetHostImpl* const host, |
+ RenderWidgetHostViewBase* const host_view) |
+ : host_(RenderWidgetHostImpl::From(host)), host_view_(host_view) {} |
+ |
+void MouseWheelPhaseHandler::AddPhaseIfNeededAndScheduleEndEvent( |
+ blink::WebMouseWheelEvent& mouse_wheel_event, |
+ bool should_route_event) { |
+ bool has_phase = |
+ mouse_wheel_event.phase != blink::WebMouseWheelEvent::kPhaseNone || |
+ mouse_wheel_event.momentum_phase != blink::WebMouseWheelEvent::kPhaseNone; |
+ if (has_phase) { |
+ if (mouse_wheel_event.phase == blink::WebMouseWheelEvent::kPhaseEnded) { |
+ // Don't send the wheel end event immediately, start a timer instead to |
+ // see whether momentum phase of the scrolling starts or not. |
+ ScheduleMouseWheelEndDispatching(mouse_wheel_event, should_route_event); |
+ } else if (mouse_wheel_event.phase == |
+ blink::WebMouseWheelEvent::kPhaseBegan) { |
+ // A new scrolling sequence has started, send the pending wheel end |
+ // event to end the previous scrolling sequence. |
+ DispatchPendingWheelEndEvent(); |
+ } else if (mouse_wheel_event.momentum_phase == |
+ blink::WebMouseWheelEvent::kPhaseBegan) { |
+ // Momentum phase has started, drop the pending wheel end event to make |
+ // sure that no wheel end event will be sent during the momentum phase |
+ // of scrolling. |
+ IgnorePendingWheelEndEvent(); |
+ } |
+ } else { // !has_phase |
+ if (!mouse_wheel_end_dispatch_timer_.IsRunning()) { |
+ mouse_wheel_event.phase = blink::WebMouseWheelEvent::kPhaseBegan; |
+ ScheduleMouseWheelEndDispatching(mouse_wheel_event, should_route_event); |
+ } else { // mouse_wheel_end_dispatch_timer_.IsRunning() |
+ bool non_zero_delta = |
+ mouse_wheel_event.delta_x || mouse_wheel_event.delta_y; |
+ mouse_wheel_event.phase = |
+ non_zero_delta ? blink::WebMouseWheelEvent::kPhaseChanged |
+ : blink::WebMouseWheelEvent::kPhaseStationary; |
+ mouse_wheel_end_dispatch_timer_.Reset(); |
+ } |
+ } |
+} |
+ |
+void MouseWheelPhaseHandler::DispatchPendingWheelEndEvent() { |
+ if (!mouse_wheel_end_dispatch_timer_.IsRunning()) |
+ return; |
+ |
+ base::Closure task = mouse_wheel_end_dispatch_timer_.user_task(); |
+ mouse_wheel_end_dispatch_timer_.Stop(); |
+ task.Run(); |
+} |
+ |
+void MouseWheelPhaseHandler::IgnorePendingWheelEndEvent() { |
+ mouse_wheel_end_dispatch_timer_.Stop(); |
+} |
+ |
+void MouseWheelPhaseHandler::SendSyntheticWheelEventWithPhaseEnded( |
+ blink::WebMouseWheelEvent last_mouse_wheel_event, |
+ bool should_route_event) { |
+ DCHECK(host_view_->wheel_scroll_latching_enabled()); |
+ blink::WebMouseWheelEvent mouse_wheel_event = last_mouse_wheel_event; |
+ mouse_wheel_event.delta_x = 0; |
+ mouse_wheel_event.delta_y = 0; |
+ mouse_wheel_event.phase = blink::WebMouseWheelEvent::kPhaseEnded; |
+ mouse_wheel_event.dispatch_type = |
+ blink::WebInputEvent::DispatchType::kEventNonBlocking; |
+ if (should_route_event) { |
+ host_->delegate()->GetInputEventRouter()->RouteMouseWheelEvent( |
+ host_view_, &mouse_wheel_event, |
+ ui::LatencyInfo(ui::SourceEventType::WHEEL)); |
+ } else { |
+ host_view_->ProcessMouseWheelEvent( |
+ mouse_wheel_event, ui::LatencyInfo(ui::SourceEventType::WHEEL)); |
+ } |
+} |
+ |
+void MouseWheelPhaseHandler::ScheduleMouseWheelEndDispatching( |
+ blink::WebMouseWheelEvent wheel_event, |
+ bool should_route_event) { |
+ mouse_wheel_end_dispatch_timer_.Start( |
+ FROM_HERE, |
+ base::TimeDelta::FromMilliseconds( |
+ kDefaultMouseWheelLatchingTransactionMs), |
+ base::Bind(&MouseWheelPhaseHandler::SendSyntheticWheelEventWithPhaseEnded, |
+ base::Unretained(this), wheel_event, should_route_event)); |
+} |
+ |
+} // namespace content |