Index: content/browser/renderer_host/render_widget_host_view_event_handler.cc |
diff --git a/content/browser/renderer_host/render_widget_host_view_event_handler.cc b/content/browser/renderer_host/render_widget_host_view_event_handler.cc |
index 980a6780b411c34b8988b6bb93bf7d1c3dd833a0..b3dbf5266e0b7c070cd7b94e5b6678d8f0aa8d4f 100644 |
--- a/content/browser/renderer_host/render_widget_host_view_event_handler.cc |
+++ b/content/browser/renderer_host/render_widget_host_view_event_handler.cc |
@@ -336,8 +336,12 @@ void RenderWidgetHostViewEventHandler::OnMouseEvent(ui::MouseEvent* event) { |
blink::WebMouseWheelEvent mouse_wheel_event = |
ui::MakeWebMouseWheelEvent(static_cast<ui::MouseWheelEvent&>(*event), |
base::Bind(&GetScreenLocationFromEvent)); |
+ |
if (mouse_wheel_event.delta_x != 0 || mouse_wheel_event.delta_y != 0) { |
- if (ShouldRouteEvent(event)) { |
+ bool should_route_event = ShouldRouteEvent(event); |
+ if (host_view_->wheel_scroll_latching_enabled()) |
+ AddPhaseAndScheduleEndEvent(mouse_wheel_event, should_route_event); |
+ if (should_route_event) { |
host_->delegate()->GetInputEventRouter()->RouteMouseWheelEvent( |
host_view_, &mouse_wheel_event, *event->latency()); |
} else { |
@@ -388,7 +392,7 @@ void RenderWidgetHostViewEventHandler::OnMouseEvent(ui::MouseEvent* event) { |
void RenderWidgetHostViewEventHandler::OnScrollEvent(ui::ScrollEvent* event) { |
TRACE_EVENT0("input", "RenderWidgetHostViewBase::OnScrollEvent"); |
- |
+ bool should_route_event = ShouldRouteEvent(event); |
if (event->type() == ui::ET_SCROLL) { |
#if !defined(OS_WIN) |
// TODO(ananta) |
@@ -404,7 +408,9 @@ void RenderWidgetHostViewEventHandler::OnScrollEvent(ui::ScrollEvent* event) { |
gesture_event.y = event->y(); |
blink::WebMouseWheelEvent mouse_wheel_event = ui::MakeWebMouseWheelEvent( |
*event, base::Bind(&GetScreenLocationFromEvent)); |
- if (ShouldRouteEvent(event)) { |
+ if (host_view_->wheel_scroll_latching_enabled()) |
+ AddPhaseAndScheduleEndEvent(mouse_wheel_event, should_route_event); |
+ if (should_route_event) { |
host_->delegate()->GetInputEventRouter()->RouteGestureEvent( |
host_view_, &gesture_event, |
ui::LatencyInfo(ui::SourceEventType::WHEEL)); |
@@ -419,15 +425,19 @@ void RenderWidgetHostViewEventHandler::OnScrollEvent(ui::ScrollEvent* event) { |
event->type() == ui::ET_SCROLL_FLING_CANCEL) { |
blink::WebGestureEvent gesture_event = ui::MakeWebGestureEvent( |
*event, base::Bind(&GetScreenLocationFromEvent)); |
- if (ShouldRouteEvent(event)) { |
+ if (should_route_event) { |
host_->delegate()->GetInputEventRouter()->RouteGestureEvent( |
host_view_, &gesture_event, |
ui::LatencyInfo(ui::SourceEventType::WHEEL)); |
} else { |
host_->ForwardGestureEvent(gesture_event); |
} |
- if (event->type() == ui::ET_SCROLL_FLING_START) |
+ if (event->type() == ui::ET_SCROLL_FLING_START) { |
RecordAction(base::UserMetricsAction("TrackpadScrollFling")); |
+ // Stop the timer to avoid sending a synthetic wheel event with |
+ // kPhaseEnded. |
+ mouse_wheel_end_dispatch_timer_.Stop(); |
+ } |
} |
event->SetHandled(); |
@@ -519,18 +529,32 @@ void RenderWidgetHostViewEventHandler::OnGestureEvent(ui::GestureEvent* event) { |
} |
if (gesture.GetType() != blink::WebInputEvent::kUndefined) { |
+ if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN) { |
+ RecordAction(base::UserMetricsAction("TouchscreenScroll")); |
+ |
+ if (mouse_wheel_end_dispatch_timer_.IsRunning()) { |
+ // If there is a current scroll going on and a new scroll that isn't |
+ // wheel based send a synthetic wheel event with kPhaseEnded to cancel |
+ // the current scroll. |
+ base::Closure task = mouse_wheel_end_dispatch_timer_.user_task(); |
+ mouse_wheel_end_dispatch_timer_.Stop(); |
+ task.Run(); |
+ } |
+ } else if (event->type() == ui::ET_GESTURE_SCROLL_END) { |
+ // Make sure that the next wheel event will have phase = |kPhaseBegan|. |
+ // This is for maintaining the correct phase info when some of the wheel |
+ // events get ignored while a touchscreen scroll is going on. |
+ mouse_wheel_end_dispatch_timer_.Stop(); |
+ } else if (event->type() == ui::ET_SCROLL_FLING_START) { |
+ RecordAction(base::UserMetricsAction("TouchscreenScrollFling")); |
+ } |
+ |
if (ShouldRouteEvent(event)) { |
host_->delegate()->GetInputEventRouter()->RouteGestureEvent( |
host_view_, &gesture, *event->latency()); |
} else { |
host_->ForwardGestureEventWithLatencyInfo(gesture, *event->latency()); |
} |
- |
- if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN) { |
- RecordAction(base::UserMetricsAction("TouchscreenScroll")); |
- } else if (event->type() == ui::ET_SCROLL_FLING_START) { |
- RecordAction(base::UserMetricsAction("TouchscreenScrollFling")); |
- } |
} |
// If a gesture is not processed by the webpage, then WebKit processes it |
@@ -887,4 +911,51 @@ void RenderWidgetHostViewEventHandler::ProcessTouchEvent( |
host_->ForwardTouchEventWithLatencyInfo(event, latency); |
} |
+void RenderWidgetHostViewEventHandler::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 { |
+ ProcessMouseWheelEvent(mouse_wheel_event, |
+ ui::LatencyInfo(ui::SourceEventType::WHEEL)); |
+ } |
+} |
+ |
+void RenderWidgetHostViewEventHandler::AddPhaseAndScheduleEndEvent( |
+ blink::WebMouseWheelEvent& mouse_wheel_event, |
+ bool should_route_event) { |
+ DCHECK(mouse_wheel_event.phase == blink::WebMouseWheelEvent::kPhaseNone && |
+ mouse_wheel_event.momentum_phase == |
+ blink::WebMouseWheelEvent::kPhaseNone); |
tdresser
2017/05/19 16:17:33
I'd split this into two DCHECKs, as it'll be easie
sahel
2017/05/19 17:39:16
Done.
|
+ |
+ if (!mouse_wheel_end_dispatch_timer_.IsRunning()) { |
+ mouse_wheel_event.phase = blink::WebMouseWheelEvent::kPhaseBegan; |
+ mouse_wheel_end_dispatch_timer_.Start( |
+ FROM_HERE, |
+ base::TimeDelta::FromMilliseconds( |
+ kDefaultMouseWheelLatchingTransactionMs), |
+ base::Bind(&RenderWidgetHostViewEventHandler:: |
+ SendSyntheticWheelEventWithPhaseEnded, |
+ base::Unretained(this), mouse_wheel_event, |
+ should_route_event)); |
+ } else { |
+ 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(); |
+ } |
+} |
+ |
} // namespace content |