Commit 33bd4854 authored by Kevin McNee's avatar Kevin McNee Committed by Commit Bot

Only generate a synthetic fling cancel at the start of a touchpad scroll

As part of issue 855840, we will need to hit test touchpad gesture fling
cancel events. However, we currently generate a synthetic fling cancel
before every wheel event in a scroll. This is excessive, since we have
wheel scroll latching, and would become expensive, since we would need
to hit test them all.

We now only generate a synthetic fling cancel at the beginning of a
touchpad scroll.

Bug: 855840
Change-Id: I108393814065c90cea80ba5326772a1764526ad7
Reviewed-on: https://chromium-review.googlesource.com/1138637
Commit-Queue: Kevin McNee <mcnee@chromium.org>
Reviewed-by: default avatarTimothy Dresser <tdresser@chromium.org>
Reviewed-by: default avatarSahel Sharify <sahel@chromium.org>
Cr-Commit-Position: refs/heads/master@{#576486}
parent 2b96359c
...@@ -384,6 +384,20 @@ class MockRenderWidgetHostImpl : public RenderWidgetHostImpl { ...@@ -384,6 +384,20 @@ class MockRenderWidgetHostImpl : public RenderWidgetHostImpl {
lastWheelOrTouchEventLatencyInfo = ui::LatencyInfo(ui_latency); lastWheelOrTouchEventLatencyInfo = ui::LatencyInfo(ui_latency);
} }
void ForwardGestureEventWithLatencyInfo(
const blink::WebGestureEvent& gesture_event,
const ui::LatencyInfo& ui_latency) override {
RenderWidgetHostImpl::ForwardGestureEventWithLatencyInfo(gesture_event,
ui_latency);
last_forwarded_gesture_event_ = gesture_event;
}
base::Optional<WebGestureEvent> GetAndResetLastForwardedGestureEvent() {
base::Optional<WebGestureEvent> ret;
last_forwarded_gesture_event_.swap(ret);
return ret;
}
static MockRenderWidgetHostImpl* Create(RenderWidgetHostDelegate* delegate, static MockRenderWidgetHostImpl* Create(RenderWidgetHostDelegate* delegate,
RenderProcessHost* process, RenderProcessHost* process,
int32_t routing_id) { int32_t routing_id) {
...@@ -430,6 +444,7 @@ class MockRenderWidgetHostImpl : public RenderWidgetHostImpl { ...@@ -430,6 +444,7 @@ class MockRenderWidgetHostImpl : public RenderWidgetHostImpl {
bool new_content_rendering_timeout_fired_ = false; bool new_content_rendering_timeout_fired_ = false;
std::unique_ptr<MockWidgetImpl> widget_impl_; std::unique_ptr<MockWidgetImpl> widget_impl_;
base::Optional<WebGestureEvent> last_forwarded_gesture_event_;
}; };
class TestScopedKeyboardHook : public aura::ScopedKeyboardHook { class TestScopedKeyboardHook : public aura::ScopedKeyboardHook {
...@@ -2440,6 +2455,43 @@ TEST_F(RenderWidgetHostViewAuraTest, ...@@ -2440,6 +2455,43 @@ TEST_F(RenderWidgetHostViewAuraTest,
EXPECT_EQ(blink::kWebGestureDeviceTouchscreen, gesture_event->SourceDevice()); EXPECT_EQ(blink::kWebGestureDeviceTouchscreen, gesture_event->SourceDevice());
} }
TEST_F(RenderWidgetHostViewAuraTest,
SyntheticFlingCancelAtTouchpadScrollBegin) {
ui::ScrollEvent scroll_event(ui::ET_SCROLL, gfx::Point(2, 2),
ui::EventTimeForNow(), 0, 0, 5, 0, 5, 2);
// Send the beginning scroll event. This should generate a synthetic fling
// cancel to cancel any ongoing flings before the start of this scroll.
view_->OnScrollEvent(&scroll_event);
base::RunLoop().RunUntilIdle();
base::Optional<WebGestureEvent> last_gesture =
widget_host_->GetAndResetLastForwardedGestureEvent();
ASSERT_TRUE(last_gesture);
EXPECT_EQ(WebInputEvent::kGestureFlingCancel, last_gesture->GetType());
// Consume the wheel to prevent gesture scrolls from interfering with the
// rest of the test.
MockWidgetInputHandler::MessageVector dispatched_events =
GetAndResetDispatchedMessages();
EXPECT_EQ("MouseWheel", GetMessageNames(dispatched_events));
dispatched_events[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
dispatched_events = GetAndResetDispatchedMessages();
EXPECT_EQ(0U, dispatched_events.size());
// Send a scroll update. A synthetic fling cancel has already been sent for
// this sequence, so we should not generate another.
view_->OnScrollEvent(&scroll_event);
base::RunLoop().RunUntilIdle();
last_gesture = widget_host_->GetAndResetLastForwardedGestureEvent();
EXPECT_FALSE(last_gesture);
dispatched_events = GetAndResetDispatchedMessages();
EXPECT_EQ("MouseWheel", GetMessageNames(dispatched_events));
dispatched_events[0]->ToEvent()->CallCallback(INPUT_EVENT_ACK_STATE_CONSUMED);
dispatched_events = GetAndResetDispatchedMessages();
EXPECT_EQ(0U, dispatched_events.size());
}
// Checks that touch-event state is maintained correctly for multiple touch // Checks that touch-event state is maintained correctly for multiple touch
// points. // points.
TEST_F(RenderWidgetHostViewAuraTest, MultiTouchPointsStates) { TEST_F(RenderWidgetHostViewAuraTest, MultiTouchPointsStates) {
......
...@@ -433,23 +433,29 @@ void RenderWidgetHostViewEventHandler::OnScrollEvent(ui::ScrollEvent* event) { ...@@ -433,23 +433,29 @@ void RenderWidgetHostViewEventHandler::OnScrollEvent(ui::ScrollEvent* event) {
if (event->finger_count() != 2) if (event->finger_count() != 2)
return; return;
#endif #endif
blink::WebGestureEvent gesture_event = ui::MakeWebGestureEventFlingCancel();
// Coordinates need to be transferred to the fling cancel gesture only
// for Surface-targeting to ensure that it is targeted to the correct
// RenderWidgetHost.
gesture_event.SetPositionInWidget(event->location_f());
blink::WebMouseWheelEvent mouse_wheel_event = ui::MakeWebMouseWheelEvent( blink::WebMouseWheelEvent mouse_wheel_event = ui::MakeWebMouseWheelEvent(
*event, base::Bind(&GetScreenLocationFromEvent)); *event, base::Bind(&GetScreenLocationFromEvent));
mouse_wheel_phase_handler_.AddPhaseIfNeededAndScheduleEndEvent( mouse_wheel_phase_handler_.AddPhaseIfNeededAndScheduleEndEvent(
mouse_wheel_event, should_route_event); mouse_wheel_event, should_route_event);
base::Optional<blink::WebGestureEvent> maybe_synthetic_fling_cancel;
if (mouse_wheel_event.phase == blink::WebMouseWheelEvent::kPhaseBegan) {
maybe_synthetic_fling_cancel =
ui::MakeWebGestureEventFlingCancel(mouse_wheel_event);
}
if (should_route_event) { if (should_route_event) {
host_->delegate()->GetInputEventRouter()->RouteGestureEvent( if (maybe_synthetic_fling_cancel) {
host_view_, &gesture_event, host_->delegate()->GetInputEventRouter()->RouteGestureEvent(
ui::LatencyInfo(ui::SourceEventType::WHEEL)); host_view_, &*maybe_synthetic_fling_cancel,
ui::LatencyInfo(ui::SourceEventType::WHEEL));
}
host_->delegate()->GetInputEventRouter()->RouteMouseWheelEvent( host_->delegate()->GetInputEventRouter()->RouteMouseWheelEvent(
host_view_, &mouse_wheel_event, *event->latency()); host_view_, &mouse_wheel_event, *event->latency());
} else { } else {
host_->ForwardGestureEvent(gesture_event); if (maybe_synthetic_fling_cancel) {
host_->ForwardGestureEvent(*maybe_synthetic_fling_cancel);
}
host_->ForwardWheelEventWithLatencyInfo(mouse_wheel_event, host_->ForwardWheelEventWithLatencyInfo(mouse_wheel_event,
*event->latency()); *event->latency());
} }
......
...@@ -392,11 +392,17 @@ blink::WebGestureEvent MakeWebGestureEvent( ...@@ -392,11 +392,17 @@ blink::WebGestureEvent MakeWebGestureEvent(
return gesture_event; return gesture_event;
} }
blink::WebGestureEvent MakeWebGestureEventFlingCancel() { blink::WebGestureEvent MakeWebGestureEventFlingCancel(
const blink::WebMouseWheelEvent& wheel_event) {
blink::WebGestureEvent gesture_event( blink::WebGestureEvent gesture_event(
blink::WebInputEvent::kGestureFlingCancel, blink::WebInputEvent::kGestureFlingCancel,
blink::WebInputEvent::kNoModifiers, EventTimeForNow(), blink::WebInputEvent::kNoModifiers, wheel_event.TimeStamp(),
blink::kWebGestureDeviceTouchpad); blink::kWebGestureDeviceTouchpad);
// Coordinates need to be transferred to the fling cancel gesture only
// for Surface-targeting to ensure that it is targeted to the correct
// RenderWidgetHost.
gesture_event.SetPositionInWidget(wheel_event.PositionInWidget());
gesture_event.SetPositionInScreen(wheel_event.PositionInScreen());
// All other fields are ignored on a GestureFlingCancel event. // All other fields are ignored on a GestureFlingCancel event.
return gesture_event; return gesture_event;
} }
......
...@@ -51,7 +51,8 @@ blink::WebGestureEvent MakeWebGestureEvent( ...@@ -51,7 +51,8 @@ blink::WebGestureEvent MakeWebGestureEvent(
const ScrollEvent& event, const ScrollEvent& event,
const base::Callback<gfx::PointF(const ui::LocatedEvent& event)>& const base::Callback<gfx::PointF(const ui::LocatedEvent& event)>&
screen_location_callback); screen_location_callback);
blink::WebGestureEvent MakeWebGestureEventFlingCancel(); blink::WebGestureEvent MakeWebGestureEventFlingCancel(
const blink::WebMouseWheelEvent& wheel_event);
} // namespace ui } // namespace ui
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment