diff options
author | jdduke <jdduke@chromium.org> | 2015-02-26 08:16:18 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-02-26 16:17:24 +0000 |
commit | dfb809f04aa38b0fc0a6ce8c69649377b83a20df (patch) | |
tree | c28ec3663a9e16c9287851cf5b325449518d0e25 | |
parent | cab20570232799a8c60e988469cd2676b7a57010 (diff) | |
download | chromium_src-dfb809f04aa38b0fc0a6ce8c69649377b83a20df.zip chromium_src-dfb809f04aa38b0fc0a6ce8c69649377b83a20df.tar.gz chromium_src-dfb809f04aa38b0fc0a6ce8c69649377b83a20df.tar.bz2 |
Always forward touch events to the TouchEventQueue
There's currently a shortcut that the RWHView can take with touch events
when there is no registered touch handler. This avoids the overhead
of passing the touch to the InputRouter/TouchEventQueue, but the
predicate for conditionally forwarding the events is racy. This can lead
to scenarios where a touch event stream is interrupted and the
pipeline only sees a partial touch sequence.
As the cost of always forwarding the events is relatively small, remove
this optimization entirely, instead relying on the TouchEventQueue to
filter events as appropriate.
BUG=461583
Review URL: https://codereview.chromium.org/954973003
Cr-Commit-Position: refs/heads/master@{#318243}
11 files changed, 57 insertions, 91 deletions
diff --git a/content/browser/renderer_host/input/input_router.h b/content/browser/renderer_host/input/input_router.h index 96b68c3..dde441a 100644 --- a/content/browser/renderer_host/input/input_router.h +++ b/content/browser/renderer_host/input/input_router.h @@ -50,11 +50,6 @@ class InputRouter : public IPC::Listener { // Returns the oldest queued or in-flight keyboard event sent to the router. virtual const NativeWebKeyboardEvent* GetLastKeyboardEvent() const = 0; - // Returns |true| if the caller should immediately forward touch events to the - // router. When |false|, the caller can forego sending touch events, and - // instead consume them directly. - virtual bool ShouldForwardTouchEvent() const = 0; - // Allow the router to make more informed input handling decisions based on // the current view. enum ViewFlags { diff --git a/content/browser/renderer_host/input/input_router_impl.cc b/content/browser/renderer_host/input/input_router_impl.cc index 8714548..54bf892 100644 --- a/content/browser/renderer_host/input/input_router_impl.cc +++ b/content/browser/renderer_host/input/input_router_impl.cc @@ -237,12 +237,6 @@ const NativeWebKeyboardEvent* InputRouterImpl::GetLastKeyboardEvent() const { return &key_queue_.front(); } -bool InputRouterImpl::ShouldForwardTouchEvent() const { - // Always send a touch event if the renderer has a touch-event handler or - // there are pending touch events. - return touch_event_queue_.has_handlers() || !touch_event_queue_.empty(); -} - void InputRouterImpl::OnViewUpdated(int view_flags) { current_view_flags_ = view_flags; diff --git a/content/browser/renderer_host/input/input_router_impl.h b/content/browser/renderer_host/input/input_router_impl.h index 11ebdf5..e869640 100644 --- a/content/browser/renderer_host/input/input_router_impl.h +++ b/content/browser/renderer_host/input/input_router_impl.h @@ -68,7 +68,6 @@ class CONTENT_EXPORT InputRouterImpl const GestureEventWithLatencyInfo& gesture_event) override; void SendTouchEvent(const TouchEventWithLatencyInfo& touch_event) override; const NativeWebKeyboardEvent* GetLastKeyboardEvent() const override; - bool ShouldForwardTouchEvent() const override; void OnViewUpdated(int view_flags) override; bool HasPendingEvents() const override; diff --git a/content/browser/renderer_host/input/input_router_impl_unittest.cc b/content/browser/renderer_host/input/input_router_impl_unittest.cc index d285cef..ec62671 100644 --- a/content/browser/renderer_host/input/input_router_impl_unittest.cc +++ b/content/browser/renderer_host/input/input_router_impl_unittest.cc @@ -818,8 +818,6 @@ TEST_F(InputRouterImplTest, TouchEventQueueFlush) { EXPECT_EQ(0U, GetSentMessageCountAndResetSink()); EXPECT_TRUE(TouchEventQueueEmpty()); - EXPECT_TRUE(input_router_->ShouldForwardTouchEvent()); - // Send a touch-press event. PressTouchPoint(1, 1); SendTouchEvent(); @@ -834,14 +832,12 @@ TEST_F(InputRouterImplTest, TouchEventQueueFlush) { EXPECT_FALSE(client_->has_touch_handler()); EXPECT_EQ(0U, GetSentMessageCountAndResetSink()); EXPECT_FALSE(TouchEventQueueEmpty()); - EXPECT_TRUE(input_router_->ShouldForwardTouchEvent()); // After the ack, the touch-event queue should be empty, and none of the // flushed touch-events should have been sent to the renderer. SendInputEventACK(WebInputEvent::TouchStart, INPUT_EVENT_ACK_STATE_CONSUMED); EXPECT_EQ(0U, GetSentMessageCountAndResetSink()); EXPECT_TRUE(TouchEventQueueEmpty()); - EXPECT_FALSE(input_router_->ShouldForwardTouchEvent()); } #if defined(USE_AURA) @@ -851,7 +847,6 @@ TEST_F(InputRouterImplTest, AckedTouchEventState) { input_router_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true)); EXPECT_EQ(0U, GetSentMessageCountAndResetSink()); EXPECT_TRUE(TouchEventQueueEmpty()); - EXPECT_TRUE(input_router_->ShouldForwardTouchEvent()); // Send a bunch of events, and make sure the ACKed events are correct. ScopedVector<ui::TouchEvent> expected_events; diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index 717e2c0..b2b8dca 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc @@ -1902,17 +1902,6 @@ bool RenderWidgetHostImpl::IgnoreInputEvents() const { return ignore_input_events_ || process_->IgnoreInputEvents(); } -bool RenderWidgetHostImpl::ShouldForwardTouchEvent() const { - // It's important that the emulator sees a complete native touch stream, - // allowing it to perform touch filtering as appropriate. - // TODO(dgozman): Remove when touch stream forwarding issues resolved, see - // crbug.com/375940. - if (touch_emulator_ && touch_emulator_->enabled()) - return true; - - return input_router_->ShouldForwardTouchEvent(); -} - void RenderWidgetHostImpl::StartUserGesture() { OnUserGesture(); } diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h index 3516a0c..4d7d0f9 100644 --- a/content/browser/renderer_host/render_widget_host_impl.h +++ b/content/browser/renderer_host/render_widget_host_impl.h @@ -380,9 +380,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl // |ignore_input_events_| or |process_->IgnoreInputEvents()| is true. bool IgnoreInputEvents() const; - // Event queries delegated to the |input_router_|. - bool ShouldForwardTouchEvent() const; - bool has_touch_handler() const { return has_touch_handler_; } // Notification that the user has made some kind of input that could diff --git a/content/browser/renderer_host/render_widget_host_unittest.cc b/content/browser/renderer_host/render_widget_host_unittest.cc index ea9d84e..121bbf3 100644 --- a/content/browser/renderer_host/render_widget_host_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_unittest.cc @@ -100,7 +100,6 @@ class MockInputRouter : public InputRouter { NOTREACHED(); return NULL; } - bool ShouldForwardTouchEvent() const override { return true; } void OnViewUpdated(int view_flags) override {} bool HasPendingEvents() const override { return false; } diff --git a/content/browser/renderer_host/render_widget_host_view_android.cc b/content/browser/renderer_host/render_widget_host_view_android.cc index cc6ab4e..339fec9 100644 --- a/content/browser/renderer_host/render_widget_host_view_android.cc +++ b/content/browser/renderer_host/render_widget_host_view_android.cc @@ -810,19 +810,15 @@ bool RenderWidgetHostViewAndroid::OnTouchEvent( if (stylus_text_selector_.OnTouchEvent(event)) return true; - auto result = gesture_provider_.OnTouchEvent(event); + ui::FilteredGestureProvider::TouchHandlingResult result = + gesture_provider_.OnTouchEvent(event); if (!result.succeeded) return false; - if (host_->ShouldForwardTouchEvent()) { - blink::WebTouchEvent web_event = - CreateWebTouchEventFromMotionEvent(event, result.did_generate_scroll); - host_->ForwardTouchEventWithLatencyInfo(web_event, - CreateLatencyInfo(web_event)); - } else { - const bool event_consumed = false; - gesture_provider_.OnAsyncTouchEventAck(event_consumed); - } + blink::WebTouchEvent web_event = + CreateWebTouchEventFromMotionEvent(event, result.did_generate_scroll); + host_->ForwardTouchEventWithLatencyInfo(web_event, + CreateLatencyInfo(web_event)); // Send a proactive BeginFrame on the next vsync to reduce latency. // This is good enough as long as the first touch event has Begin semantics diff --git a/content/browser/renderer_host/render_widget_host_view_aura.cc b/content/browser/renderer_host/render_widget_host_view_aura.cc index 63c1609..71d03da 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc @@ -2067,18 +2067,12 @@ void RenderWidgetHostViewAura::OnTouchEvent(ui::TouchEvent* event) { pointer_state_, event->may_cause_scrolling()); pointer_state_.CleanupRemovedTouchPoints(*event); - // Forward the touch event only if a touch point was updated, and - // there's a touch-event handler in the page, and no other - // touch-event is in the queue. It is important to always mark - // events as being handled asynchronously if there is a touch-event - // handler in the page, or some touch-event is already in the queue, - // even if no point has been updated. This ensures that this event - // does not get processed by the gesture recognizer before events - // currently awaiting dispatch in the touch queue. - if (host_->ShouldForwardTouchEvent()) { - event->DisableSynchronousHandling(); - host_->ForwardTouchEventWithLatencyInfo(touch_event, *event->latency()); - } + // It is important to always mark events as being handled asynchronously when + // they are forwarded. This ensures that the current event does not get + // processed by the gesture recognizer before events currently awaiting + // dispatch in the touch queue. + event->DisableSynchronousHandling(); + host_->ForwardTouchEventWithLatencyInfo(touch_event, *event->latency()); } void RenderWidgetHostViewAura::OnGestureEvent(ui::GestureEvent* event) { diff --git a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc index 9a6042d..50ca24c 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc @@ -448,6 +448,28 @@ class RenderWidgetHostViewAuraTest : public testing::Test { widget_host_->OnMessageReceived(response); } + size_t GetSentMessageCountAndResetSink() { + size_t count = sink_->message_count(); + sink_->ClearMessages(); + return count; + } + + void AckLastSentInputEventIfNecessary(InputEventAckState ack_result) { + if (!sink_->message_count()) + return; + + InputMsg_HandleInputEvent::Param params; + if (!InputMsg_HandleInputEvent::Read( + sink_->GetMessageAt(sink_->message_count() - 1), ¶ms)) { + return; + } + + if (WebInputEventTraits::IgnoresAckDisposition(*get<0>(params))) + return; + + SendInputEventACK(get<0>(params)->type, ack_result); + } + protected: // If true, then calls RWH::Shutdown() instead of deleting RWH. bool widget_host_uses_shutdown_to_destroy_; @@ -693,28 +715,6 @@ class RenderWidgetHostViewAuraOverscrollTest SendTouchEvent(); } - size_t GetSentMessageCountAndResetSink() { - size_t count = sink_->message_count(); - sink_->ClearMessages(); - return count; - } - - void AckLastSentInputEventIfNecessary(InputEventAckState ack_result) { - if (!sink_->message_count()) - return; - - InputMsg_HandleInputEvent::Param params; - if (!InputMsg_HandleInputEvent::Read( - sink_->GetMessageAt(sink_->message_count() - 1), ¶ms)) { - return; - } - - if (WebInputEventTraits::IgnoresAckDisposition(*get<0>(params))) - return; - - SendInputEventACK(get<0>(params)->type, ack_result); - } - SyntheticWebTouchEvent touch_event_; scoped_ptr<TestOverscrollDelegate> overscroll_delegate_; @@ -1021,10 +1021,10 @@ TEST_F(RenderWidgetHostViewAuraTest, FinishCompositionByMouse) { TEST_F(RenderWidgetHostViewAuraTest, TouchEventState) { view_->InitAsChild(NULL); view_->Show(); + GetSentMessageCountAndResetSink(); // Start with no touch-event handler in the renderer. widget_host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, false)); - EXPECT_FALSE(widget_host_->ShouldForwardTouchEvent()); ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(30, 30), @@ -1039,8 +1039,11 @@ TEST_F(RenderWidgetHostViewAuraTest, TouchEventState) { 0, ui::EventTimeForNow()); + // The touch events should get forwared from the view, but they should not + // reach the renderer. view_->OnTouchEvent(&press); - EXPECT_FALSE(press.handled()); + EXPECT_EQ(0U, GetSentMessageCountAndResetSink()); + EXPECT_TRUE(press.synchronous_handling_disabled()); EXPECT_EQ(blink::WebInputEvent::TouchStart, view_->touch_event_->type); EXPECT_TRUE(view_->touch_event_->cancelable); EXPECT_EQ(1U, view_->touch_event_->touchesLength); @@ -1048,7 +1051,8 @@ TEST_F(RenderWidgetHostViewAuraTest, TouchEventState) { view_->touch_event_->touches[0].state); view_->OnTouchEvent(&move); - EXPECT_FALSE(move.handled()); + EXPECT_EQ(0U, GetSentMessageCountAndResetSink()); + EXPECT_TRUE(press.synchronous_handling_disabled()); EXPECT_EQ(blink::WebInputEvent::TouchMove, view_->touch_event_->type); EXPECT_TRUE(view_->touch_event_->cancelable); EXPECT_EQ(1U, view_->touch_event_->touchesLength); @@ -1056,16 +1060,17 @@ TEST_F(RenderWidgetHostViewAuraTest, TouchEventState) { view_->touch_event_->touches[0].state); view_->OnTouchEvent(&release); - EXPECT_FALSE(release.handled()); + EXPECT_EQ(0U, GetSentMessageCountAndResetSink()); + EXPECT_TRUE(press.synchronous_handling_disabled()); EXPECT_EQ(nullptr, view_->touch_event_); // Now install some touch-event handlers and do the same steps. The touch // events should now be consumed. However, the touch-event state should be // updated as before. widget_host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true)); - EXPECT_TRUE(widget_host_->ShouldForwardTouchEvent()); view_->OnTouchEvent(&press); + EXPECT_EQ(1U, GetSentMessageCountAndResetSink()); EXPECT_TRUE(press.synchronous_handling_disabled()); EXPECT_EQ(blink::WebInputEvent::TouchStart, view_->touch_event_->type); EXPECT_TRUE(view_->touch_event_->cancelable); @@ -1093,19 +1098,18 @@ TEST_F(RenderWidgetHostViewAuraTest, TouchEventState) { view_->touch_event_->touches[0].state); widget_host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, false)); - EXPECT_TRUE(widget_host_->ShouldForwardTouchEvent()); // Ack'ing the outstanding event should flush the pending touch queue. InputHostMsg_HandleInputEvent_ACK_Params ack; ack.type = blink::WebInputEvent::TouchStart; ack.state = INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS; widget_host_->OnMessageReceived(InputHostMsg_HandleInputEvent_ACK(0, ack)); - EXPECT_FALSE(widget_host_->ShouldForwardTouchEvent()); + EXPECT_EQ(0U, GetSentMessageCountAndResetSink()); ui::TouchEvent move2(ui::ET_TOUCH_MOVED, gfx::Point(20, 20), 0, base::Time::NowFromSystemTime() - base::Time()); view_->OnTouchEvent(&move2); - EXPECT_FALSE(move2.handled()); + EXPECT_TRUE(press.synchronous_handling_disabled()); EXPECT_EQ(blink::WebInputEvent::TouchMove, view_->touch_event_->type); EXPECT_EQ(1U, view_->touch_event_->touchesLength); EXPECT_EQ(blink::WebTouchPoint::StateMoved, @@ -1114,7 +1118,7 @@ TEST_F(RenderWidgetHostViewAuraTest, TouchEventState) { ui::TouchEvent release2(ui::ET_TOUCH_RELEASED, gfx::Point(20, 20), 0, base::Time::NowFromSystemTime() - base::Time()); view_->OnTouchEvent(&release2); - EXPECT_FALSE(release2.handled()); + EXPECT_TRUE(press.synchronous_handling_disabled()); EXPECT_EQ(nullptr, view_->touch_event_); } @@ -1125,7 +1129,6 @@ TEST_F(RenderWidgetHostViewAuraTest, TouchEventSyncAsync) { view_->Show(); widget_host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true)); - EXPECT_TRUE(widget_host_->ShouldForwardTouchEvent()); ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(30, 30), @@ -3102,9 +3105,9 @@ TEST_F(RenderWidgetHostViewAuraTest, InvalidEventsHaveSyncHandlingDisabled) { view_->InitAsChild(NULL); view_->Show(); + GetSentMessageCountAndResetSink(); widget_host_->OnMessageReceived(ViewHostMsg_HasTouchEventHandlers(0, true)); - EXPECT_TRUE(widget_host_->ShouldForwardTouchEvent()); ui::TouchEvent press(ui::ET_TOUCH_PRESSED, gfx::Point(30, 30), 0, ui::EventTimeForNow()); @@ -3113,11 +3116,16 @@ TEST_F(RenderWidgetHostViewAuraTest, ui::TouchEvent invalid_move(ui::ET_TOUCH_MOVED, gfx::Point(30, 30), 1, ui::EventTimeForNow()); - view_->OnTouchEvent(&press); - view_->OnTouchEvent(&invalid_move); // Valid press is handled asynchronously. + view_->OnTouchEvent(&press); EXPECT_TRUE(press.synchronous_handling_disabled()); - // Invalid move is handled synchronously, but is consumed. + EXPECT_EQ(1U, GetSentMessageCountAndResetSink()); + AckLastSentInputEventIfNecessary(INPUT_EVENT_ACK_STATE_CONSUMED); + + // Invalid move is handled synchronously, but is consumed. It should not + // be forwarded to the renderer. + view_->OnTouchEvent(&invalid_move); + EXPECT_EQ(0U, GetSentMessageCountAndResetSink()); EXPECT_FALSE(invalid_move.synchronous_handling_disabled()); EXPECT_TRUE(invalid_move.stopped_propagation()); } diff --git a/ui/events/gesture_detection/filtered_gesture_provider.h b/ui/events/gesture_detection/filtered_gesture_provider.h index 5f937c1..21b9a96 100644 --- a/ui/events/gesture_detection/filtered_gesture_provider.h +++ b/ui/events/gesture_detection/filtered_gesture_provider.h @@ -29,7 +29,7 @@ class GESTURE_DETECTION_EXPORT FilteredGestureProvider // True if |event| was both valid and successfully handled by the // gesture provider. Otherwise, false, in which case the caller should drop - // |event| and cease furthe propagation. + // |event| and cease further propagation. bool succeeded; // Whether |event| produced scrolling motion, either the start of a scroll, |