diff options
author | lanwei <lanwei@chromium.org> | 2015-05-11 09:56:55 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-05-11 16:58:17 +0000 |
commit | 901538b70297c3984afc8c045381ebff5bfdaa9e (patch) | |
tree | a8d7d639dca559d1c739234cc9ae68230786c5bb | |
parent | 2117e7503ed5ee06a9e80e6e02b01786b73ed3b1 (diff) | |
download | chromium_src-901538b70297c3984afc8c045381ebff5bfdaa9e.zip chromium_src-901538b70297c3984afc8c045381ebff5bfdaa9e.tar.gz chromium_src-901538b70297c3984afc8c045381ebff5bfdaa9e.tar.bz2 |
Make sure send one WebTouchEvent ack per ui::TouchEvent
In our current code (RenderWidgetHostViewAura), we may send more than one ack
for one WebTouchEvent in the multi-touch scenario, but we should only send
one WebTouchEvent ack for each ui::TouchEvent. For touchmove and
touchcancel, we will only change the state for the actual touch point which
causes this touchevent for multi-touch.
BUG=484276
Review URL: https://codereview.chromium.org/1120293003
Cr-Commit-Position: refs/heads/master@{#329161}
-rw-r--r-- | content/browser/renderer_host/render_widget_host_view_aura.cc | 26 | ||||
-rw-r--r-- | content/browser/renderer_host/render_widget_host_view_aura_unittest.cc | 90 |
2 files changed, 111 insertions, 5 deletions
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 420f475..93a4e93 100644 --- a/content/browser/renderer_host/render_widget_host_view_aura.cc +++ b/content/browser/renderer_host/render_widget_host_view_aura.cc @@ -277,6 +277,20 @@ bool IsFractionalScaleFactor(float scale_factor) { return (scale_factor - static_cast<int>(scale_factor)) > 0; } +// Reset unchanged touch point to StateStationary for touchmove and +// touchcancel. +void MarkUnchangedTouchPointsAsStationary( + blink::WebTouchEvent* event, + int changed_touch_id) { + if (event->type == blink::WebInputEvent::TouchMove || + event->type == blink::WebInputEvent::TouchCancel) { + for (size_t i = 0; i < event->touchesLength; ++i) { + if (event->touches[i].id != changed_touch_id) + event->touches[i].state = blink::WebTouchPoint::StateStationary; + } + } +} + } // namespace // We need to watch for mouse events outside a Web Popup or its parent @@ -1278,10 +1292,14 @@ void RenderWidgetHostViewAura::ProcessAckedTouchEvent( break; } - // Only send acks for changed touches. + // Only send acks for one changed touch point. + bool sent_ack = false; for (size_t i = 0; i < touch.event.touchesLength; ++i) { - if (touch.event.touches[i].state == required_state) + if (touch.event.touches[i].state == required_state) { + DCHECK(!sent_ack); host->dispatcher()->ProcessedTouchEvent(window_, result); + sent_ack = true; + } } } @@ -2180,6 +2198,10 @@ void RenderWidgetHostViewAura::OnTouchEvent(ui::TouchEvent* event) { // processed by the gesture recognizer before events currently awaiting // dispatch in the touch queue. event->DisableSynchronousHandling(); + + // Set unchanged touch point to StateStationary for touchmove and + // touchcancel to make sure only send one ack per WebTouchEvent. + MarkUnchangedTouchPointsAsStationary(&touch_event, event->touch_id()); host_->ForwardTouchEventWithLatencyInfo(touch_event, *event->latency()); } 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 aba2b57..eb32f72 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 @@ -223,8 +223,10 @@ class FakeWindowEventDispatcher : public aura::WindowEventDispatcher { processed_touch_event_count_++; } - size_t processed_touch_event_count() { - return processed_touch_event_count_; + size_t GetAndResetProcessedTouchEventCount() { + size_t count = processed_touch_event_count_; + processed_touch_event_count_ = 0; + return count; } private: @@ -1124,6 +1126,88 @@ TEST_F(RenderWidgetHostViewAuraTest, TouchEventState) { EXPECT_EQ(nullptr, view_->touch_event_); } +// Checks that touch-event state is maintained correctly for multiple touch +// points. +TEST_F(RenderWidgetHostViewAuraTest, MultiTouchPointsStates) { + view_->InitAsFullscreen(parent_view_); + view_->Show(); + view_->UseFakeDispatcher(); + GetSentMessageCountAndResetSink(); + + ui::TouchEvent press0(ui::ET_TOUCH_PRESSED, gfx::Point(30, 30), 0, + ui::EventTimeForNow()); + + view_->OnTouchEvent(&press0); + SendInputEventACK(blink::WebInputEvent::TouchStart, + INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(blink::WebInputEvent::TouchStart, view_->touch_event_->type); + EXPECT_EQ(1U, view_->touch_event_->touchesLength); + EXPECT_EQ(1U, view_->dispatcher_->GetAndResetProcessedTouchEventCount()); + + ui::TouchEvent move0(ui::ET_TOUCH_MOVED, gfx::Point(20, 20), 0, + ui::EventTimeForNow()); + + view_->OnTouchEvent(&move0); + SendInputEventACK(blink::WebInputEvent::TouchMove, + INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(blink::WebInputEvent::TouchMove, view_->touch_event_->type); + EXPECT_EQ(1U, view_->touch_event_->touchesLength); + EXPECT_EQ(1U, view_->dispatcher_->GetAndResetProcessedTouchEventCount()); + + // For the second touchstart, only the state of the second touch point is + // StatePressed, the state of the first touch point is StateStationary. + ui::TouchEvent press1(ui::ET_TOUCH_PRESSED, gfx::Point(10, 10), 1, + ui::EventTimeForNow()); + + view_->OnTouchEvent(&press1); + SendInputEventACK(blink::WebInputEvent::TouchStart, + INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(blink::WebInputEvent::TouchStart, view_->touch_event_->type); + EXPECT_EQ(2U, view_->touch_event_->touchesLength); + EXPECT_EQ(1U, view_->dispatcher_->GetAndResetProcessedTouchEventCount()); + + // For the touchmove of second point, the state of the second touch point is + // StateMoved, the state of the first touch point is StateStationary. + ui::TouchEvent move1(ui::ET_TOUCH_MOVED, gfx::Point(30, 30), 1, + ui::EventTimeForNow()); + + view_->OnTouchEvent(&move1); + SendInputEventACK(blink::WebInputEvent::TouchMove, + INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(blink::WebInputEvent::TouchMove, view_->touch_event_->type); + EXPECT_EQ(2U, view_->touch_event_->touchesLength); + EXPECT_EQ(1U, view_->dispatcher_->GetAndResetProcessedTouchEventCount()); + + // For the touchmove of first point, the state of the first touch point is + // StateMoved, the state of the second touch point is StateStationary. + ui::TouchEvent move2(ui::ET_TOUCH_MOVED, gfx::Point(10, 10), 0, + ui::EventTimeForNow()); + + view_->OnTouchEvent(&move2); + SendInputEventACK(blink::WebInputEvent::TouchMove, + INPUT_EVENT_ACK_STATE_CONSUMED); + EXPECT_EQ(blink::WebInputEvent::TouchMove, view_->touch_event_->type); + EXPECT_EQ(2U, view_->touch_event_->touchesLength); + EXPECT_EQ(1U, view_->dispatcher_->GetAndResetProcessedTouchEventCount()); + + ui::TouchEvent cancel0(ui::ET_TOUCH_CANCELLED, gfx::Point(10, 10), 0, + ui::EventTimeForNow()); + + // For the touchcancel, only the state of the current touch point is + // StateCancelled, the state of the other touch point is StateStationary. + view_->OnTouchEvent(&cancel0); + EXPECT_EQ(blink::WebInputEvent::TouchCancel, view_-> touch_event_->type); + EXPECT_EQ(1U, view_->touch_event_->touchesLength); + EXPECT_EQ(1U, view_->dispatcher_->GetAndResetProcessedTouchEventCount()); + + ui::TouchEvent cancel1(ui::ET_TOUCH_CANCELLED, gfx::Point(30, 30), 1, + ui::EventTimeForNow()); + + view_->OnTouchEvent(&cancel1); + EXPECT_EQ(1U, view_->dispatcher_->GetAndResetProcessedTouchEventCount()); + EXPECT_EQ(nullptr, view_->touch_event_); +} + // Checks that touch-events are queued properly when there is a touch-event // handler on the page. TEST_F(RenderWidgetHostViewAuraTest, TouchEventSyncAsync) { @@ -3321,7 +3405,7 @@ TEST_F(RenderWidgetHostViewAuraTest, CorrectNumberOfAcksAreDispatched) { SendInputEventACK(blink::WebInputEvent::TouchStart, INPUT_EVENT_ACK_STATE_CONSUMED); - EXPECT_EQ(2U, view_->dispatcher_->processed_touch_event_count()); + EXPECT_EQ(2U, view_->dispatcher_->GetAndResetProcessedTouchEventCount()); } // Tests that the scroll deltas stored within the overscroll controller get |