Chromium Code Reviews| Index: content/browser/renderer_host/input/touch_event_queue_unittest.cc |
| diff --git a/content/browser/renderer_host/input/touch_event_queue_unittest.cc b/content/browser/renderer_host/input/touch_event_queue_unittest.cc |
| index f74d1557b37d6038f3cdb00fe60feafc9daa1cd4..f3996f7edca1c66baa08675221e5ac6225c81d5c 100644 |
| --- a/content/browser/renderer_host/input/touch_event_queue_unittest.cc |
| +++ b/content/browser/renderer_host/input/touch_event_queue_unittest.cc |
| @@ -19,6 +19,9 @@ using blink::WebTouchPoint; |
| namespace content { |
| namespace { |
| + |
| +const double MinSecondsBetweenThrottledTouchmoves = 0.2; |
| + |
| base::TimeDelta DefaultTouchTimeoutDelay() { |
| return base::TimeDelta::FromMilliseconds(1); |
| } |
| @@ -156,6 +159,10 @@ class TouchEventQueueTest : public testing::Test, |
| SendTouchEvent(); |
| } |
| + void AdvanceTouchTime(double seconds) { |
| + touch_event_.timeStampSeconds += seconds; |
| + } |
| + |
| size_t GetAndResetAckedEventCount() { |
| size_t count = acked_event_count_; |
| acked_event_count_ = 0; |
| @@ -180,14 +187,18 @@ class TouchEventQueueTest : public testing::Test, |
| queue_->SetAckTimeoutEnabled(false, base::TimeDelta()); |
| } |
| - bool IsTimeoutEnabled() { |
| + bool IsTimeoutEnabled() const { |
| return queue_->ack_timeout_enabled(); |
| } |
| - bool IsTimeoutRunning() { |
| + bool IsTimeoutRunning() const { |
| return queue_->IsTimeoutRunningForTesting(); |
| } |
| + bool HasPendingAsyncTouchMove() const { |
| + return queue_->HasPendingAsyncTouchMoveForTesting(); |
| + } |
| + |
| size_t queued_event_count() const { |
| return queue_->size(); |
| } |
| @@ -1530,8 +1541,8 @@ TEST_F(TouchEventQueueTest, SyncTouchMoveDoesntCancelTouchOnScroll) { |
| EXPECT_EQ(0U, queued_event_count()); |
| } |
| -TEST_F(TouchEventQueueTest, TouchAbsorption) { |
| - SetTouchScrollingMode(TouchEventQueue::TOUCH_SCROLLING_MODE_ABSORB_TOUCHMOVE); |
| +TEST_F(TouchEventQueueTest, AsyncTouch) { |
| + SetTouchScrollingMode(TouchEventQueue::TOUCH_SCROLLING_MODE_ASYNC_TOUCHMOVE); |
| // Queue a TouchStart. |
| PressTouchPoint(0, 1); |
| @@ -1545,6 +1556,8 @@ TEST_F(TouchEventQueueTest, TouchAbsorption) { |
| MoveTouchPoint(0, 20, 5); |
| SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); |
| + EXPECT_FALSE(HasPendingAsyncTouchMove()); |
| + EXPECT_TRUE(sent_event().cancelable); |
| EXPECT_EQ(0U, queued_event_count()); |
| EXPECT_EQ(1U, GetAndResetSentEventCount()); |
| @@ -1554,13 +1567,14 @@ TEST_F(TouchEventQueueTest, TouchAbsorption) { |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| MoveTouchPoint(0, 20, 5); |
| SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); |
| + EXPECT_TRUE(HasPendingAsyncTouchMove()); |
| EXPECT_EQ(0U, queued_event_count()); |
| EXPECT_EQ(0U, GetAndResetSentEventCount()); |
| } |
| } |
| -TEST_F(TouchEventQueueTest, TouchAbsorptionNoTouchAfterScroll) { |
| - SetTouchScrollingMode(TouchEventQueue::TOUCH_SCROLLING_MODE_ABSORB_TOUCHMOVE); |
| +TEST_F(TouchEventQueueTest, AsyncTouchThrottledAfterScroll) { |
| + SetTouchScrollingMode(TouchEventQueue::TOUCH_SCROLLING_MODE_ASYNC_TOUCHMOVE); |
| // Process a TouchStart |
| PressTouchPoint(0, 1); |
| @@ -1578,21 +1592,36 @@ TEST_F(TouchEventQueueTest, TouchAbsorptionNoTouchAfterScroll) { |
| EXPECT_EQ(1U, GetAndResetSentEventCount()); |
| EXPECT_EQ(1U, GetAndResetAckedEventCount()); |
| - // Now queue a second touchmove and verify it's not dispatched. |
| + // Now queue a second touchmove and verify it's not (yet) dispatched. |
| MoveTouchPoint(0, 0, 10); |
| SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); |
| + EXPECT_TRUE(HasPendingAsyncTouchMove()); |
| EXPECT_EQ(0U, queued_event_count()); |
| EXPECT_EQ(0U, GetAndResetSentEventCount()); |
| EXPECT_EQ(1U, GetAndResetAckedEventCount()); |
| - // But a final touchend is sent (even before any gesture events |
| - // have been ACKed). |
| + // Queuing the final touchend should flush the pending, async touchmove. |
| ReleaseTouchPoint(0); |
| + EXPECT_EQ(WebInputEvent::TouchMove, sent_event().type); |
| + EXPECT_FALSE(HasPendingAsyncTouchMove()); |
| + EXPECT_FALSE(sent_event().cancelable); |
| + EXPECT_EQ(1U, GetAndResetSentEventCount()); |
| + EXPECT_EQ(2U, queued_event_count()); |
| + |
| + // Ack the flushed, async touchmove. The ack should not reach the client, but |
| + // it should trigger sending of the (now non-cancelable) touchend. |
| SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); |
| - EXPECT_EQ(0U, queued_event_count()); |
| + EXPECT_EQ(WebInputEvent::TouchEnd, sent_event().type); |
| + EXPECT_FALSE(sent_event().cancelable); |
| EXPECT_EQ(1U, GetAndResetSentEventCount()); |
| + EXPECT_EQ(0U, GetAndResetAckedEventCount()); |
| + EXPECT_EQ(1U, queued_event_count()); |
| + |
| + // Ack the touchend. |
| + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); |
| + EXPECT_EQ(0U, queued_event_count()); |
| + EXPECT_EQ(0U, GetAndResetSentEventCount()); |
| EXPECT_EQ(1U, GetAndResetAckedEventCount()); |
| - EXPECT_EQ(WebInputEvent::TouchEnd, sent_event().type); |
| // Now mark the scroll as not consumed (which would cause future |
| // touchmoves in the active sequence to be sent if there was one). |
| @@ -1600,8 +1629,8 @@ TEST_F(TouchEventQueueTest, TouchAbsorptionNoTouchAfterScroll) { |
| INPUT_EVENT_ACK_STATE_NOT_CONSUMED); |
| // Start a new touch sequence and verify that absorption has been |
|
Rick Byers
2014/04/23 21:56:17
replace reference to "absorption" I guess...
|
| - // reset so that moves after the start of scrolling are not sent. |
| - PressTouchPoint(0, 1); |
| + // reset so that moves after the start of scrolling are throttled. |
| + PressTouchPoint(0, 0); |
| EXPECT_EQ(1U, GetAndResetSentEventCount()); |
| SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); |
| EXPECT_EQ(1U, GetAndResetAckedEventCount()); |
| @@ -1612,8 +1641,118 @@ TEST_F(TouchEventQueueTest, TouchAbsorptionNoTouchAfterScroll) { |
| EXPECT_EQ(1U, GetAndResetAckedEventCount()); |
| MoveTouchPoint(0, 0, 10); |
| SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); |
| + EXPECT_TRUE(HasPendingAsyncTouchMove()); |
| + EXPECT_EQ(0U, queued_event_count()); |
| + EXPECT_EQ(0U, GetAndResetSentEventCount()); |
| + EXPECT_EQ(1U, GetAndResetAckedEventCount()); |
| + |
|
Rick Byers
2014/04/23 21:56:17
All the additional tests below look great - cover
jdduke (slow)
2014/04/23 22:56:48
:) Yeah, I actually had a few subtle bugs caught b
|
| + // As soon as a touchmove exceeds the outer slop region it will be forwarded |
| + // immediately. |
| + MoveTouchPoint(0, 0, 20); |
| + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); |
| + EXPECT_FALSE(HasPendingAsyncTouchMove()); |
| + EXPECT_FALSE(sent_event().cancelable); |
| + EXPECT_EQ(0U, queued_event_count()); |
| + EXPECT_EQ(1U, GetAndResetSentEventCount()); |
| + EXPECT_EQ(1U, GetAndResetAckedEventCount()); |
| + |
| + // Subsequent touchmove's should be deferred. |
| + MoveTouchPoint(0, 0, 25); |
| + EXPECT_TRUE(HasPendingAsyncTouchMove()); |
| + EXPECT_EQ(0U, queued_event_count()); |
| + EXPECT_EQ(0U, GetAndResetSentEventCount()); |
| + EXPECT_EQ(1U, GetAndResetAckedEventCount()); |
| + |
| + // The pending touchmove should be flushed with the the new touchmove if |
| + // sufficient time has passed. |
| + AdvanceTouchTime(MinSecondsBetweenThrottledTouchmoves + 0.1); |
| + MoveTouchPoint(0, 0, 15); |
| + EXPECT_FALSE(HasPendingAsyncTouchMove()); |
| + EXPECT_FALSE(sent_event().cancelable); |
| + EXPECT_EQ(1U, queued_event_count()); |
| + EXPECT_EQ(1U, GetAndResetSentEventCount()); |
| + EXPECT_EQ(0U, GetAndResetAckedEventCount()); |
| + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); |
| + EXPECT_EQ(0U, queued_event_count()); |
| + EXPECT_EQ(0U, GetAndResetSentEventCount()); |
| + EXPECT_EQ(1U, GetAndResetAckedEventCount()); |
| + |
| + // Non-touchmove events should always flush any pending touchmove events. |
| + MoveTouchPoint(0, 0, 25); |
| + EXPECT_TRUE(HasPendingAsyncTouchMove()); |
| + EXPECT_EQ(0U, queued_event_count()); |
| + EXPECT_EQ(0U, GetAndResetSentEventCount()); |
| + EXPECT_EQ(1U, GetAndResetAckedEventCount()); |
| + PressTouchPoint(30, 30); |
| + EXPECT_FALSE(HasPendingAsyncTouchMove()); |
| + EXPECT_FALSE(sent_event().cancelable); |
| + EXPECT_EQ(WebInputEvent::TouchMove, sent_event().type); |
| + EXPECT_EQ(1U, GetAndResetSentEventCount()); |
| + EXPECT_EQ(2U, queued_event_count()); |
| + |
| + // Ack'ing the flushed, async touchmove will dispatch the touchstart. Note |
| + // that the flushed touchmove's ack will not reach the client (its |
| + // constituent events have already been ack'ed). |
| + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); |
| + EXPECT_FALSE(sent_event().cancelable); |
| + EXPECT_EQ(WebInputEvent::TouchStart, sent_event().type); |
| + EXPECT_EQ(1U, queued_event_count()); |
| + EXPECT_EQ(1U, GetAndResetSentEventCount()); |
| + EXPECT_EQ(0U, GetAndResetAckedEventCount()); |
| + |
| + // Ack the touchstart. |
| + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); |
| EXPECT_EQ(0U, queued_event_count()); |
| EXPECT_EQ(0U, GetAndResetSentEventCount()); |
| + EXPECT_EQ(1U, GetAndResetAckedEventCount()); |
| + |
| + // Send a secondary touchmove. |
| + MoveTouchPoint(1, 0, 25); |
| + EXPECT_TRUE(HasPendingAsyncTouchMove()); |
| + EXPECT_EQ(0U, queued_event_count()); |
| + EXPECT_EQ(0U, GetAndResetSentEventCount()); |
| + EXPECT_EQ(1U, GetAndResetAckedEventCount()); |
| + |
| + // An unconsumed scroll should resume synchronous touch handling. |
| + SendGestureEventAck(WebInputEvent::GestureScrollUpdate, |
| + INPUT_EVENT_ACK_STATE_NOT_CONSUMED); |
| + |
| + // The pending touchmove should be coalesced with the next (now synchronous) |
| + // touchmove. |
| + MoveTouchPoint(0, 0, 25); |
| + EXPECT_TRUE(sent_event().cancelable); |
| + EXPECT_FALSE(HasPendingAsyncTouchMove()); |
| + EXPECT_EQ(WebInputEvent::TouchMove, sent_event().type); |
| + EXPECT_EQ(WebTouchPoint::StateMoved, sent_event().touches[0].state); |
| + EXPECT_EQ(WebTouchPoint::StateMoved, sent_event().touches[1].state); |
| + EXPECT_EQ(1U, queued_event_count()); |
| + EXPECT_EQ(1U, GetAndResetSentEventCount()); |
| + EXPECT_EQ(0U, GetAndResetAckedEventCount()); |
| + |
| + // Subsequent touches will queue until the preceding, synchronous touches are |
| + // ack'ed. |
| + ReleaseTouchPoint(1); |
| + EXPECT_EQ(2U, queued_event_count()); |
| + ReleaseTouchPoint(0); |
| + EXPECT_EQ(3U, queued_event_count()); |
| + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); |
| + EXPECT_TRUE(sent_event().cancelable); |
| + EXPECT_EQ(WebInputEvent::TouchEnd, sent_event().type); |
| + EXPECT_EQ(2U, queued_event_count()); |
| + EXPECT_EQ(1U, GetAndResetSentEventCount()); |
| + EXPECT_EQ(1U, GetAndResetAckedEventCount()); |
| + |
| + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); |
| + EXPECT_TRUE(sent_event().cancelable); |
| + EXPECT_EQ(WebInputEvent::TouchEnd, sent_event().type); |
| + EXPECT_EQ(1U, queued_event_count()); |
| + EXPECT_EQ(1U, GetAndResetSentEventCount()); |
| + EXPECT_EQ(1U, GetAndResetAckedEventCount()); |
| + |
| + SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED); |
| + EXPECT_EQ(0U, queued_event_count()); |
| + EXPECT_EQ(0U, GetAndResetSentEventCount()); |
| + EXPECT_EQ(1U, GetAndResetAckedEventCount()); |
| } |
| } // namespace content |