| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "content/browser/renderer_host/input/gesture_event_queue.h" |
| |
| #include <stddef.h> |
| |
| #include <memory> |
| #include <utility> |
| #include <vector> |
| |
| #include "base/location.h" |
| #include "base/logging.h" |
| #include "base/message_loop/message_loop.h" |
| #include "base/run_loop.h" |
| #include "base/single_thread_task_runner.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "base/test/scoped_task_environment.h" |
| #include "base/threading/thread_task_runner_handle.h" |
| #include "base/time/time.h" |
| #include "content/browser/renderer_host/input/touchpad_tap_suppression_controller.h" |
| #include "content/common/input/input_event_ack_state.h" |
| #include "content/common/input/synthetic_web_input_event_builders.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/WebKit/public/platform/WebInputEvent.h" |
| #include "ui/events/blink/blink_features.h" |
| |
| using base::TimeDelta; |
| using blink::WebGestureDevice; |
| using blink::WebGestureEvent; |
| using blink::WebInputEvent; |
| |
| namespace content { |
| |
| class GestureEventQueueTest : public testing::Test, |
| public GestureEventQueueClient, |
| public TouchpadTapSuppressionControllerClient { |
| public: |
| GestureEventQueueTest() : GestureEventQueueTest(false) {} |
| |
| GestureEventQueueTest(bool enable_compositor_event_queue) |
| : scoped_task_environment_( |
| base::test::ScopedTaskEnvironment::MainThreadType::UI), |
| acked_gesture_event_count_(0), |
| sent_gesture_event_count_(0) { |
| if (enable_compositor_event_queue) |
| feature_list_.InitAndEnableFeature(features::kVsyncAlignedInputEvents); |
| else |
| feature_list_.InitAndDisableFeature(features::kVsyncAlignedInputEvents); |
| } |
| |
| ~GestureEventQueueTest() override {} |
| |
| // testing::Test |
| void SetUp() override { |
| queue_.reset(new GestureEventQueue(this, this, DefaultConfig())); |
| } |
| |
| void TearDown() override { |
| // Process all pending tasks to avoid leaks. |
| RunUntilIdle(); |
| queue_.reset(); |
| } |
| |
| // GestureEventQueueClient |
| void SendGestureEventImmediately( |
| const GestureEventWithLatencyInfo& event) override { |
| ++sent_gesture_event_count_; |
| if (sync_ack_result_) { |
| std::unique_ptr<InputEventAckState> ack_result = |
| std::move(sync_ack_result_); |
| SendInputEventACK(event.event.GetType(), *ack_result); |
| } |
| } |
| |
| void OnGestureEventAck(const GestureEventWithLatencyInfo& event, |
| InputEventAckState ack_result) override { |
| ++acked_gesture_event_count_; |
| last_acked_event_ = event.event; |
| if (sync_followup_event_) { |
| auto sync_followup_event = std::move(sync_followup_event_); |
| SimulateGestureEvent(*sync_followup_event); |
| } |
| } |
| |
| // TouchpadTapSuppressionControllerClient |
| void SendMouseEventImmediately( |
| const MouseEventWithLatencyInfo& event) override {} |
| |
| protected: |
| static GestureEventQueue::Config DefaultConfig() { |
| return GestureEventQueue::Config(); |
| } |
| |
| void SetUpForDebounce(int interval_ms) { |
| queue()->set_debounce_interval_time_ms_for_testing(interval_ms); |
| } |
| |
| void SimulateGestureEvent(const WebGestureEvent& gesture) { |
| queue()->QueueEvent(GestureEventWithLatencyInfo(gesture)); |
| } |
| |
| void SimulateGestureEvent(WebInputEvent::Type type, |
| WebGestureDevice sourceDevice) { |
| SimulateGestureEvent( |
| SyntheticWebGestureEventBuilder::Build(type, sourceDevice)); |
| } |
| |
| void SimulateGestureScrollUpdateEvent(float dX, float dY, int modifiers) { |
| SimulateGestureEvent(SyntheticWebGestureEventBuilder::BuildScrollUpdate( |
| dX, dY, modifiers, blink::kWebGestureDeviceTouchscreen)); |
| } |
| |
| void SimulateGesturePinchUpdateEvent(float scale, |
| float anchorX, |
| float anchorY, |
| int modifiers) { |
| SimulateGestureEvent(SyntheticWebGestureEventBuilder::BuildPinchUpdate( |
| scale, anchorX, anchorY, modifiers, |
| blink::kWebGestureDeviceTouchscreen)); |
| } |
| |
| void SimulateGestureFlingStartEvent(float velocityX, |
| float velocityY, |
| WebGestureDevice sourceDevice) { |
| SimulateGestureEvent( |
| SyntheticWebGestureEventBuilder::BuildFling(velocityX, |
| velocityY, |
| sourceDevice)); |
| } |
| |
| void SendInputEventACK(WebInputEvent::Type type, |
| InputEventAckState ack) { |
| queue()->ProcessGestureAck(ack, type, ui::LatencyInfo()); |
| } |
| |
| void RunUntilIdle() { base::RunLoop().RunUntilIdle(); } |
| |
| size_t GetAndResetSentGestureEventCount() { |
| size_t count = sent_gesture_event_count_; |
| sent_gesture_event_count_ = 0; |
| return count; |
| } |
| |
| size_t GetAndResetAckedGestureEventCount() { |
| size_t count = acked_gesture_event_count_; |
| acked_gesture_event_count_ = 0; |
| return count; |
| } |
| |
| const WebGestureEvent& last_acked_event() const { |
| return last_acked_event_; |
| } |
| |
| void set_synchronous_ack(InputEventAckState ack_result) { |
| sync_ack_result_.reset(new InputEventAckState(ack_result)); |
| } |
| |
| void set_sync_followup_event(WebInputEvent::Type type, |
| WebGestureDevice sourceDevice) { |
| sync_followup_event_.reset(new WebGestureEvent( |
| SyntheticWebGestureEventBuilder::Build(type, sourceDevice))); |
| } |
| |
| unsigned GestureEventQueueSize() { |
| return queue()->coalesced_gesture_events_.size(); |
| } |
| |
| WebGestureEvent GestureEventSecondFromLastQueueEvent() { |
| return queue()->coalesced_gesture_events_.at( |
| GestureEventQueueSize() - 2).event; |
| } |
| |
| WebGestureEvent GestureEventLastQueueEvent() { |
| return queue()->coalesced_gesture_events_.back().event; |
| } |
| |
| unsigned GestureEventDebouncingQueueSize() { |
| return queue()->debouncing_deferral_queue_.size(); |
| } |
| |
| WebGestureEvent GestureEventQueueEventAt(int i) { |
| return queue()->coalesced_gesture_events_.at(i).event; |
| } |
| |
| bool ScrollingInProgress() { |
| return queue()->scrolling_in_progress_; |
| } |
| |
| bool FlingInProgress() { return queue()->fling_in_progress_; } |
| |
| bool WillIgnoreNextACK() { |
| return queue()->ignore_next_ack_; |
| } |
| |
| GestureEventQueue* queue() const { |
| return queue_.get(); |
| } |
| |
| private: |
| base::test::ScopedTaskEnvironment scoped_task_environment_; |
| std::unique_ptr<GestureEventQueue> queue_; |
| size_t acked_gesture_event_count_; |
| size_t sent_gesture_event_count_; |
| WebGestureEvent last_acked_event_; |
| std::unique_ptr<InputEventAckState> sync_ack_result_; |
| std::unique_ptr<WebGestureEvent> sync_followup_event_; |
| base::test::ScopedFeatureList feature_list_; |
| }; |
| |
| #if GTEST_HAS_PARAM_TEST |
| // This is for tests that are to be run for all source devices. |
| class GestureEventQueueWithSourceTest |
| : public GestureEventQueueTest, |
| public testing::WithParamInterface<WebGestureDevice> {}; |
| #endif // GTEST_HAS_PARAM_TEST |
| |
| class GestureEventQueueWithCompositorEventQueueTest |
| : public GestureEventQueueTest { |
| public: |
| GestureEventQueueWithCompositorEventQueueTest() |
| : GestureEventQueueTest(true) {} |
| }; |
| |
| TEST_F(GestureEventQueueTest, CoalescesScrollGestureEvents) { |
| // Test coalescing of only GestureScrollUpdate events. |
| // Simulate gesture events. |
| |
| // Sent. |
| SimulateGestureEvent(WebInputEvent::kGestureScrollBegin, |
| blink::kWebGestureDeviceTouchscreen); |
| EXPECT_EQ(1U, GetAndResetSentGestureEventCount()); |
| |
| // Enqueued. |
| SimulateGestureScrollUpdateEvent(8, -5, 0); |
| |
| // Make sure that the queue contains what we think it should. |
| WebGestureEvent merged_event = GestureEventLastQueueEvent(); |
| EXPECT_EQ(2U, GestureEventQueueSize()); |
| EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, merged_event.GetType()); |
| EXPECT_EQ(blink::kWebGestureDeviceTouchscreen, merged_event.source_device); |
| |
| // Coalesced. |
| SimulateGestureScrollUpdateEvent(8, -6, 0); |
| |
| // Check that coalescing updated the correct values. |
| merged_event = GestureEventLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, merged_event.GetType()); |
| EXPECT_EQ(0, merged_event.GetModifiers()); |
| EXPECT_EQ(16, merged_event.data.scroll_update.delta_x); |
| EXPECT_EQ(-11, merged_event.data.scroll_update.delta_y); |
| EXPECT_EQ(blink::kWebGestureDeviceTouchscreen, merged_event.source_device); |
| |
| // Enqueued. |
| SimulateGestureScrollUpdateEvent(8, -7, 1); |
| |
| // Check that we didn't wrongly coalesce. |
| merged_event = GestureEventLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, merged_event.GetType()); |
| EXPECT_EQ(1, merged_event.GetModifiers()); |
| EXPECT_EQ(blink::kWebGestureDeviceTouchscreen, merged_event.source_device); |
| |
| // Different. |
| SimulateGestureEvent(WebInputEvent::kGestureScrollEnd, |
| blink::kWebGestureDeviceTouchscreen); |
| |
| // Check that only the first event was sent. |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| |
| // Check that the ACK sends the second message. |
| SendInputEventACK(WebInputEvent::kGestureScrollBegin, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| RunUntilIdle(); |
| EXPECT_EQ(1U, GetAndResetAckedGestureEventCount()); |
| EXPECT_EQ(1U, GetAndResetSentGestureEventCount()); |
| |
| // Ack for queued coalesced event. |
| SendInputEventACK(WebInputEvent::kGestureScrollUpdate, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| RunUntilIdle(); |
| EXPECT_EQ(1U, GetAndResetAckedGestureEventCount()); |
| EXPECT_EQ(1U, GetAndResetSentGestureEventCount()); |
| |
| // Ack for queued uncoalesced event. |
| SendInputEventACK(WebInputEvent::kGestureScrollUpdate, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| RunUntilIdle(); |
| EXPECT_EQ(1U, GetAndResetAckedGestureEventCount()); |
| EXPECT_EQ(1U, GetAndResetSentGestureEventCount()); |
| |
| // After the final ack, the queue should be empty. |
| SendInputEventACK(WebInputEvent::kGestureScrollEnd, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| RunUntilIdle(); |
| EXPECT_EQ(1U, GetAndResetAckedGestureEventCount()); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| } |
| |
| TEST_F(GestureEventQueueTest, |
| DoesNotCoalesceScrollGestureEventsFromDifferentDevices) { |
| // Test that GestureScrollUpdate events from Touchscreen and Touchpad do not |
| // coalesce. |
| |
| // Sent. |
| SimulateGestureEvent(WebInputEvent::kGestureScrollBegin, |
| blink::kWebGestureDeviceTouchscreen); |
| EXPECT_EQ(1U, GetAndResetSentGestureEventCount()); |
| |
| // Enqueued. |
| SimulateGestureScrollUpdateEvent(8, -5, 0); |
| |
| // Make sure that the queue contains what we think it should. |
| EXPECT_EQ(2U, GestureEventQueueSize()); |
| EXPECT_EQ(blink::kWebGestureDeviceTouchscreen, |
| GestureEventLastQueueEvent().source_device); |
| |
| // Coalesced. |
| SimulateGestureScrollUpdateEvent(8, -6, 0); |
| EXPECT_EQ(2U, GestureEventQueueSize()); |
| EXPECT_EQ(blink::kWebGestureDeviceTouchscreen, |
| GestureEventLastQueueEvent().source_device); |
| |
| // Enqueued. |
| SimulateGestureEvent(WebInputEvent::kGestureScrollUpdate, |
| blink::kWebGestureDeviceTouchpad); |
| EXPECT_EQ(3U, GestureEventQueueSize()); |
| EXPECT_EQ(blink::kWebGestureDeviceTouchpad, |
| GestureEventLastQueueEvent().source_device); |
| |
| // Coalesced. |
| SimulateGestureEvent(WebInputEvent::kGestureScrollUpdate, |
| blink::kWebGestureDeviceTouchpad); |
| EXPECT_EQ(3U, GestureEventQueueSize()); |
| EXPECT_EQ(blink::kWebGestureDeviceTouchpad, |
| GestureEventLastQueueEvent().source_device); |
| |
| // Enqueued. |
| SimulateGestureScrollUpdateEvent(8, -7, 0); |
| EXPECT_EQ(4U, GestureEventQueueSize()); |
| EXPECT_EQ(blink::kWebGestureDeviceTouchscreen, |
| GestureEventLastQueueEvent().source_device); |
| } |
| |
| TEST_F(GestureEventQueueTest, CoalescesScrollAndPinchEvents) { |
| // Test coalescing of only GestureScrollUpdate events. |
| // Simulate gesture events. |
| |
| // Sent. |
| SimulateGestureEvent(WebInputEvent::kGestureScrollBegin, |
| blink::kWebGestureDeviceTouchscreen); |
| |
| // Sent. |
| SimulateGestureEvent(WebInputEvent::kGesturePinchBegin, |
| blink::kWebGestureDeviceTouchscreen); |
| |
| // Enqueued. |
| SimulateGestureScrollUpdateEvent(8, -4, 1); |
| |
| // Make sure that the queue contains what we think it should. |
| WebGestureEvent merged_event = GestureEventLastQueueEvent(); |
| EXPECT_EQ(3U, GestureEventQueueSize()); |
| EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, merged_event.GetType()); |
| |
| // Coalesced without changing event order. Note anchor at (60, 60). Anchoring |
| // from a point that is not the origin should still give us the right scroll. |
| SimulateGesturePinchUpdateEvent(1.5, 60, 60, 1); |
| EXPECT_EQ(4U, GestureEventQueueSize()); |
| merged_event = GestureEventLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGesturePinchUpdate, merged_event.GetType()); |
| EXPECT_EQ(1.5, merged_event.data.pinch_update.scale); |
| EXPECT_EQ(1, merged_event.GetModifiers()); |
| EXPECT_EQ(blink::kWebGestureDeviceTouchscreen, merged_event.source_device); |
| merged_event = GestureEventSecondFromLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, merged_event.GetType()); |
| EXPECT_EQ(8, merged_event.data.scroll_update.delta_x); |
| EXPECT_EQ(-4, merged_event.data.scroll_update.delta_y); |
| EXPECT_EQ(1, merged_event.GetModifiers()); |
| EXPECT_EQ(blink::kWebGestureDeviceTouchscreen, merged_event.source_device); |
| |
| // Enqueued. |
| SimulateGestureScrollUpdateEvent(6, -3, 1); |
| |
| // Check whether coalesced correctly. |
| EXPECT_EQ(4U, GestureEventQueueSize()); |
| merged_event = GestureEventLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGesturePinchUpdate, merged_event.GetType()); |
| EXPECT_EQ(1.5, merged_event.data.pinch_update.scale); |
| EXPECT_EQ(1, merged_event.GetModifiers()); |
| EXPECT_EQ(blink::kWebGestureDeviceTouchscreen, merged_event.source_device); |
| merged_event = GestureEventSecondFromLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, merged_event.GetType()); |
| EXPECT_EQ(12, merged_event.data.scroll_update.delta_x); |
| EXPECT_EQ(-6, merged_event.data.scroll_update.delta_y); |
| EXPECT_EQ(1, merged_event.GetModifiers()); |
| EXPECT_EQ(blink::kWebGestureDeviceTouchscreen, merged_event.source_device); |
| |
| // Enqueued. |
| SimulateGesturePinchUpdateEvent(2, 60, 60, 1); |
| |
| // Check whether coalesced correctly. |
| EXPECT_EQ(4U, GestureEventQueueSize()); |
| merged_event = GestureEventLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGesturePinchUpdate, merged_event.GetType()); |
| EXPECT_EQ(3, merged_event.data.pinch_update.scale); |
| EXPECT_EQ(1, merged_event.GetModifiers()); |
| EXPECT_EQ(blink::kWebGestureDeviceTouchscreen, merged_event.source_device); |
| merged_event = GestureEventSecondFromLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, merged_event.GetType()); |
| EXPECT_EQ(12, merged_event.data.scroll_update.delta_x); |
| EXPECT_EQ(-6, merged_event.data.scroll_update.delta_y); |
| EXPECT_EQ(1, merged_event.GetModifiers()); |
| EXPECT_EQ(blink::kWebGestureDeviceTouchscreen, merged_event.source_device); |
| |
| // Enqueued. |
| SimulateGesturePinchUpdateEvent(2, 60, 60, 1); |
| |
| // Check whether coalesced correctly. |
| EXPECT_EQ(4U, GestureEventQueueSize()); |
| merged_event = GestureEventLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGesturePinchUpdate, merged_event.GetType()); |
| EXPECT_EQ(6, merged_event.data.pinch_update.scale); |
| EXPECT_EQ(1, merged_event.GetModifiers()); |
| EXPECT_EQ(blink::kWebGestureDeviceTouchscreen, merged_event.source_device); |
| merged_event = GestureEventSecondFromLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, merged_event.GetType()); |
| EXPECT_EQ(12, merged_event.data.scroll_update.delta_x); |
| EXPECT_EQ(-6, merged_event.data.scroll_update.delta_y); |
| EXPECT_EQ(1, merged_event.GetModifiers()); |
| EXPECT_EQ(blink::kWebGestureDeviceTouchscreen, merged_event.source_device); |
| |
| // Check that only the first event was sent. |
| EXPECT_EQ(1U, GetAndResetSentGestureEventCount()); |
| |
| // Check that the ACK sends the second message. |
| SendInputEventACK(WebInputEvent::kGestureScrollBegin, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| RunUntilIdle(); |
| EXPECT_EQ(1U, GetAndResetSentGestureEventCount()); |
| |
| // Enqueued. |
| SimulateGestureScrollUpdateEvent(6, -6, 1); |
| |
| // Check whether coalesced correctly. |
| EXPECT_EQ(3U, GestureEventQueueSize()); |
| merged_event = GestureEventLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGesturePinchUpdate, merged_event.GetType()); |
| EXPECT_EQ(6, merged_event.data.pinch_update.scale); |
| EXPECT_EQ(1, merged_event.GetModifiers()); |
| EXPECT_EQ(blink::kWebGestureDeviceTouchscreen, merged_event.source_device); |
| merged_event = GestureEventSecondFromLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, merged_event.GetType()); |
| EXPECT_EQ(13, merged_event.data.scroll_update.delta_x); |
| EXPECT_EQ(-7, merged_event.data.scroll_update.delta_y); |
| EXPECT_EQ(1, merged_event.GetModifiers()); |
| EXPECT_EQ(blink::kWebGestureDeviceTouchscreen, merged_event.source_device); |
| |
| // At this point ACKs shouldn't be getting ignored. |
| EXPECT_FALSE(WillIgnoreNextACK()); |
| |
| // Check that the ACK sends both scroll and pinch updates. |
| SendInputEventACK(WebInputEvent::kGesturePinchBegin, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| RunUntilIdle(); |
| EXPECT_EQ(2U, GetAndResetSentGestureEventCount()); |
| |
| // The next ACK should be getting ignored. |
| EXPECT_TRUE(WillIgnoreNextACK()); |
| |
| // Enqueued. |
| SimulateGestureScrollUpdateEvent(1, -1, 1); |
| |
| // Check whether coalesced correctly. |
| EXPECT_EQ(3U, GestureEventQueueSize()); |
| merged_event = GestureEventLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, merged_event.GetType()); |
| EXPECT_EQ(1, merged_event.data.scroll_update.delta_x); |
| EXPECT_EQ(-1, merged_event.data.scroll_update.delta_y); |
| EXPECT_EQ(1, merged_event.GetModifiers()); |
| EXPECT_EQ(blink::kWebGestureDeviceTouchscreen, merged_event.source_device); |
| merged_event = GestureEventSecondFromLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGesturePinchUpdate, merged_event.GetType()); |
| EXPECT_EQ(6, merged_event.data.pinch_update.scale); |
| EXPECT_EQ(1, merged_event.GetModifiers()); |
| EXPECT_EQ(blink::kWebGestureDeviceTouchscreen, merged_event.source_device); |
| |
| // Enqueued. |
| SimulateGestureScrollUpdateEvent(2, -2, 1); |
| |
| // Coalescing scrolls should still work. |
| EXPECT_EQ(3U, GestureEventQueueSize()); |
| merged_event = GestureEventLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, merged_event.GetType()); |
| EXPECT_EQ(3, merged_event.data.scroll_update.delta_x); |
| EXPECT_EQ(-3, merged_event.data.scroll_update.delta_y); |
| EXPECT_EQ(1, merged_event.GetModifiers()); |
| EXPECT_EQ(blink::kWebGestureDeviceTouchscreen, merged_event.source_device); |
| merged_event = GestureEventSecondFromLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGesturePinchUpdate, merged_event.GetType()); |
| EXPECT_EQ(6, merged_event.data.pinch_update.scale); |
| EXPECT_EQ(1, merged_event.GetModifiers()); |
| EXPECT_EQ(blink::kWebGestureDeviceTouchscreen, merged_event.source_device); |
| |
| // Enqueued. |
| SimulateGesturePinchUpdateEvent(0.5, 60, 60, 1); |
| |
| // Check whether coalesced correctly. |
| EXPECT_EQ(4U, GestureEventQueueSize()); |
| merged_event = GestureEventLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGesturePinchUpdate, merged_event.GetType()); |
| EXPECT_EQ(0.5, merged_event.data.pinch_update.scale); |
| EXPECT_EQ(1, merged_event.GetModifiers()); |
| EXPECT_EQ(blink::kWebGestureDeviceTouchscreen, merged_event.source_device); |
| merged_event = GestureEventSecondFromLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, merged_event.GetType()); |
| EXPECT_EQ(3, merged_event.data.scroll_update.delta_x); |
| EXPECT_EQ(-3, merged_event.data.scroll_update.delta_y); |
| EXPECT_EQ(1, merged_event.GetModifiers()); |
| EXPECT_EQ(blink::kWebGestureDeviceTouchscreen, merged_event.source_device); |
| |
| // Check that the ACK gets ignored. |
| SendInputEventACK(WebInputEvent::kGestureScrollUpdate, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, last_acked_event().GetType()); |
| RunUntilIdle(); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| // The flag should have been flipped back to false. |
| EXPECT_FALSE(WillIgnoreNextACK()); |
| |
| // Enqueued. |
| SimulateGestureScrollUpdateEvent(2, -2, 2); |
| |
| // Shouldn't coalesce with different modifiers. |
| EXPECT_EQ(4U, GestureEventQueueSize()); |
| merged_event = GestureEventLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, merged_event.GetType()); |
| EXPECT_EQ(2, merged_event.data.scroll_update.delta_x); |
| EXPECT_EQ(-2, merged_event.data.scroll_update.delta_y); |
| EXPECT_EQ(2, merged_event.GetModifiers()); |
| EXPECT_EQ(blink::kWebGestureDeviceTouchscreen, merged_event.source_device); |
| merged_event = GestureEventSecondFromLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGesturePinchUpdate, merged_event.GetType()); |
| EXPECT_EQ(0.5, merged_event.data.pinch_update.scale); |
| EXPECT_EQ(1, merged_event.GetModifiers()); |
| EXPECT_EQ(blink::kWebGestureDeviceTouchscreen, merged_event.source_device); |
| |
| // Check that the ACK sends the next scroll pinch pair. |
| SendInputEventACK(WebInputEvent::kGesturePinchUpdate, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| EXPECT_EQ(WebInputEvent::kGesturePinchUpdate, last_acked_event().GetType()); |
| RunUntilIdle(); |
| EXPECT_EQ(2U, GetAndResetSentGestureEventCount()); |
| |
| // Check that the ACK sends the second message. |
| SendInputEventACK(WebInputEvent::kGestureScrollUpdate, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, last_acked_event().GetType()); |
| RunUntilIdle(); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| |
| // Check that the ACK sends the second event. |
| SendInputEventACK(WebInputEvent::kGesturePinchUpdate, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| EXPECT_EQ(WebInputEvent::kGesturePinchUpdate, last_acked_event().GetType()); |
| RunUntilIdle(); |
| EXPECT_EQ(1U, GetAndResetSentGestureEventCount()); |
| |
| // Check that the queue is empty after ACK and no events get sent. |
| SendInputEventACK(WebInputEvent::kGestureScrollUpdate, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, last_acked_event().GetType()); |
| RunUntilIdle(); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(0U, GestureEventQueueSize()); |
| } |
| |
| TEST_F(GestureEventQueueTest, CoalescesMultiplePinchEventSequences) { |
| // Simulate a pinch sequence. |
| SimulateGestureEvent(WebInputEvent::kGestureScrollBegin, |
| blink::kWebGestureDeviceTouchscreen); |
| SimulateGestureEvent(WebInputEvent::kGesturePinchBegin, |
| blink::kWebGestureDeviceTouchscreen); |
| |
| SimulateGestureScrollUpdateEvent(8, -4, 1); |
| // Make sure that the queue contains what we think it should. |
| WebGestureEvent merged_event = GestureEventLastQueueEvent(); |
| size_t expected_events_in_queue = 3; |
| EXPECT_EQ(expected_events_in_queue, GestureEventQueueSize()); |
| EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, merged_event.GetType()); |
| |
| // Coalesced without changing event order. Note anchor at (60, 60). Anchoring |
| // from a point that is not the origin should still give us the right scroll. |
| SimulateGesturePinchUpdateEvent(1.5, 60, 60, 1); |
| EXPECT_EQ(++expected_events_in_queue, GestureEventQueueSize()); |
| merged_event = GestureEventLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGesturePinchUpdate, merged_event.GetType()); |
| EXPECT_EQ(1.5, merged_event.data.pinch_update.scale); |
| EXPECT_EQ(1, merged_event.GetModifiers()); |
| merged_event = GestureEventSecondFromLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, merged_event.GetType()); |
| EXPECT_EQ(8, merged_event.data.scroll_update.delta_x); |
| EXPECT_EQ(-4, merged_event.data.scroll_update.delta_y); |
| EXPECT_EQ(1, merged_event.GetModifiers()); |
| |
| // Enqueued. |
| SimulateGestureScrollUpdateEvent(6, -3, 1); |
| |
| // Check whether coalesced correctly. |
| EXPECT_EQ(expected_events_in_queue, GestureEventQueueSize()); |
| merged_event = GestureEventLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGesturePinchUpdate, merged_event.GetType()); |
| EXPECT_EQ(1.5, merged_event.data.pinch_update.scale); |
| EXPECT_EQ(1, merged_event.GetModifiers()); |
| merged_event = GestureEventSecondFromLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, merged_event.GetType()); |
| EXPECT_EQ(12, merged_event.data.scroll_update.delta_x); |
| EXPECT_EQ(-6, merged_event.data.scroll_update.delta_y); |
| EXPECT_EQ(1, merged_event.GetModifiers()); |
| |
| // Now start another sequence before the previous sequence has been ack'ed. |
| SimulateGestureEvent(WebInputEvent::kGesturePinchEnd, |
| blink::kWebGestureDeviceTouchscreen); |
| SimulateGestureEvent(WebInputEvent::kGestureScrollEnd, |
| blink::kWebGestureDeviceTouchscreen); |
| SimulateGestureEvent(WebInputEvent::kGestureScrollBegin, |
| blink::kWebGestureDeviceTouchscreen); |
| SimulateGestureEvent(WebInputEvent::kGesturePinchBegin, |
| blink::kWebGestureDeviceTouchscreen); |
| |
| SimulateGestureScrollUpdateEvent(8, -4, 1); |
| // Make sure that the queue contains what we think it should. |
| expected_events_in_queue += 5; |
| merged_event = GestureEventLastQueueEvent(); |
| EXPECT_EQ(expected_events_in_queue, GestureEventQueueSize()); |
| EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, merged_event.GetType()); |
| |
| // Coalesced without changing event order. Note anchor at (60, 60). Anchoring |
| // from a point that is not the origin should still give us the right scroll. |
| SimulateGesturePinchUpdateEvent(1.5, 30, 30, 1); |
| EXPECT_EQ(++expected_events_in_queue, GestureEventQueueSize()); |
| merged_event = GestureEventLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGesturePinchUpdate, merged_event.GetType()); |
| EXPECT_EQ(1.5, merged_event.data.pinch_update.scale); |
| EXPECT_EQ(1, merged_event.GetModifiers()); |
| merged_event = GestureEventSecondFromLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, merged_event.GetType()); |
| EXPECT_EQ(8, merged_event.data.scroll_update.delta_x); |
| EXPECT_EQ(-4, merged_event.data.scroll_update.delta_y); |
| EXPECT_EQ(1, merged_event.GetModifiers()); |
| |
| // Enqueued. |
| SimulateGestureScrollUpdateEvent(6, -3, 1); |
| |
| // Check whether coalesced correctly. |
| EXPECT_EQ(expected_events_in_queue, GestureEventQueueSize()); |
| merged_event = GestureEventLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGesturePinchUpdate, merged_event.GetType()); |
| EXPECT_EQ(1.5, merged_event.data.pinch_update.scale); |
| EXPECT_EQ(1, merged_event.GetModifiers()); |
| merged_event = GestureEventSecondFromLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, merged_event.GetType()); |
| EXPECT_EQ(12, merged_event.data.scroll_update.delta_x); |
| EXPECT_EQ(-6, merged_event.data.scroll_update.delta_y); |
| EXPECT_EQ(1, merged_event.GetModifiers()); |
| } |
| |
| TEST_F(GestureEventQueueTest, CoalescesPinchSequencesWithEarlyAck) { |
| SimulateGestureEvent(WebInputEvent::kGestureScrollBegin, |
| blink::kWebGestureDeviceTouchscreen); |
| SendInputEventACK(WebInputEvent::kGestureScrollBegin, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| |
| SimulateGestureEvent(WebInputEvent::kGesturePinchBegin, |
| blink::kWebGestureDeviceTouchscreen); |
| SendInputEventACK(WebInputEvent::kGesturePinchBegin, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| // ScrollBegin and PinchBegin have been sent |
| EXPECT_EQ(2U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(0U, GestureEventQueueSize()); |
| |
| SimulateGestureScrollUpdateEvent(5, 5, 1); |
| EXPECT_EQ(1U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, |
| GestureEventLastQueueEvent().GetType()); |
| EXPECT_EQ(1U, GestureEventQueueSize()); |
| |
| SimulateGesturePinchUpdateEvent(2, 60, 60, 1); |
| EXPECT_EQ(1U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(WebInputEvent::kGesturePinchUpdate, |
| GestureEventLastQueueEvent().GetType()); |
| EXPECT_EQ(2U, GestureEventQueueSize()); |
| |
| SimulateGesturePinchUpdateEvent(3, 60, 60, 1); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(WebInputEvent::kGesturePinchUpdate, |
| GestureEventLastQueueEvent().GetType()); |
| EXPECT_EQ(3U, GestureEventQueueSize()); |
| |
| SimulateGestureScrollUpdateEvent(5, 5, 1); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| // The coalesced pinch/scroll pair will have been re-arranged, with the |
| // pinch following the scroll. |
| EXPECT_EQ(WebInputEvent::kGesturePinchUpdate, |
| GestureEventLastQueueEvent().GetType()); |
| EXPECT_EQ(4U, GestureEventQueueSize()); |
| |
| SimulateGesturePinchUpdateEvent(4, 60, 60, 1); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(4U, GestureEventQueueSize()); |
| |
| SendInputEventACK(WebInputEvent::kGestureScrollUpdate, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(3U, GestureEventQueueSize()); |
| |
| SendInputEventACK(WebInputEvent::kGesturePinchUpdate, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| EXPECT_EQ(2U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(2U, GestureEventQueueSize()); |
| EXPECT_EQ(2.f, last_acked_event().data.pinch_update.scale); |
| |
| SendInputEventACK(WebInputEvent::kGestureScrollUpdate, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, last_acked_event().GetType()); |
| |
| SendInputEventACK(WebInputEvent::kGesturePinchUpdate, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| EXPECT_EQ(WebInputEvent::kGesturePinchUpdate, last_acked_event().GetType()); |
| EXPECT_EQ(3.f * 4.f, last_acked_event().data.pinch_update.scale); |
| |
| EXPECT_EQ(0U, GestureEventQueueSize()); |
| } |
| |
| TEST_F(GestureEventQueueTest, |
| DoesNotCoalescePinchGestureEventsWithDifferentModifiers) { |
| // Insert an event to force queueing of gestures. |
| SimulateGestureEvent(WebInputEvent::kGestureTapCancel, |
| blink::kWebGestureDeviceTouchscreen); |
| EXPECT_EQ(1U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(1U, GestureEventQueueSize()); |
| |
| SimulateGestureScrollUpdateEvent(5, 5, 1); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(2U, GestureEventQueueSize()); |
| |
| SimulateGesturePinchUpdateEvent(3, 60, 60, 1); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(3U, GestureEventQueueSize()); |
| |
| SimulateGestureScrollUpdateEvent(10, 15, 1); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(3U, GestureEventQueueSize()); |
| |
| SimulateGesturePinchUpdateEvent(4, 60, 60, 1); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(3U, GestureEventQueueSize()); |
| |
| // Using different modifiers should prevent coalescing. |
| SimulateGesturePinchUpdateEvent(5, 60, 60, 2); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(4U, GestureEventQueueSize()); |
| |
| SimulateGesturePinchUpdateEvent(6, 60, 60, 3); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(5U, GestureEventQueueSize()); |
| |
| SendInputEventACK(WebInputEvent::kGestureTapCancel, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| EXPECT_EQ(2U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(4U, GestureEventQueueSize()); |
| |
| SendInputEventACK(WebInputEvent::kGestureScrollUpdate, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, last_acked_event().GetType()); |
| EXPECT_EQ(3U, GestureEventQueueSize()); |
| |
| SendInputEventACK(WebInputEvent::kGesturePinchUpdate, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| EXPECT_EQ(WebInputEvent::kGesturePinchUpdate, last_acked_event().GetType()); |
| EXPECT_EQ(3.f * 4.f, last_acked_event().data.pinch_update.scale); |
| EXPECT_EQ(2U, GestureEventQueueSize()); |
| EXPECT_EQ(1U, GetAndResetSentGestureEventCount()); |
| |
| SendInputEventACK(WebInputEvent::kGesturePinchUpdate, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| EXPECT_EQ(WebInputEvent::kGesturePinchUpdate, last_acked_event().GetType()); |
| EXPECT_EQ(5.f, last_acked_event().data.pinch_update.scale); |
| EXPECT_EQ(1U, GestureEventQueueSize()); |
| EXPECT_EQ(1U, GetAndResetSentGestureEventCount()); |
| |
| SendInputEventACK(WebInputEvent::kGesturePinchUpdate, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| EXPECT_EQ(WebInputEvent::kGesturePinchUpdate, last_acked_event().GetType()); |
| EXPECT_EQ(6.f, last_acked_event().data.pinch_update.scale); |
| EXPECT_EQ(0U, GestureEventQueueSize()); |
| } |
| |
| TEST_F(GestureEventQueueTest, CoalescesScrollAndPinchEventsIdentity) { |
| // Insert an event to force queueing of gestures. |
| SimulateGestureEvent(WebInputEvent::kGestureTapCancel, |
| blink::kWebGestureDeviceTouchscreen); |
| EXPECT_EQ(1U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(1U, GestureEventQueueSize()); |
| |
| // Ensure that coalescing yields an identity transform for any pinch/scroll |
| // pair combined with its inverse. |
| SimulateGestureScrollUpdateEvent(5, 5, 1); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(2U, GestureEventQueueSize()); |
| |
| SimulateGesturePinchUpdateEvent(5, 10, 10, 1); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(3U, GestureEventQueueSize()); |
| |
| SimulateGesturePinchUpdateEvent(.2f, 10, 10, 1); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(3U, GestureEventQueueSize()); |
| |
| SimulateGestureScrollUpdateEvent(-5, -5, 1); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(3U, GestureEventQueueSize()); |
| |
| SendInputEventACK(WebInputEvent::kGestureTapCancel, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| EXPECT_EQ(2U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(2U, GestureEventQueueSize()); |
| |
| SendInputEventACK(WebInputEvent::kGestureScrollUpdate, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, last_acked_event().GetType()); |
| EXPECT_EQ(0.f, last_acked_event().data.scroll_update.delta_x); |
| EXPECT_EQ(0.f, last_acked_event().data.scroll_update.delta_y); |
| |
| SendInputEventACK(WebInputEvent::kGesturePinchUpdate, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| EXPECT_EQ(WebInputEvent::kGesturePinchUpdate, last_acked_event().GetType()); |
| EXPECT_EQ(1.f, last_acked_event().data.pinch_update.scale); |
| EXPECT_EQ(0U, GestureEventQueueSize()); |
| |
| // Insert an event to force queueing of gestures. |
| SimulateGestureEvent(WebInputEvent::kGestureTapCancel, |
| blink::kWebGestureDeviceTouchscreen); |
| EXPECT_EQ(1U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(1U, GestureEventQueueSize()); |
| |
| // Ensure that coalescing yields an identity transform for any pinch/scroll |
| // pair combined with its inverse. |
| SimulateGesturePinchUpdateEvent(2, 10, 10, 1); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(2U, GestureEventQueueSize()); |
| |
| SimulateGestureScrollUpdateEvent(20, 20, 1); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(3U, GestureEventQueueSize()); |
| |
| SimulateGesturePinchUpdateEvent(0.5f, 20, 20, 1); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(3U, GestureEventQueueSize()); |
| |
| SimulateGestureScrollUpdateEvent(-5, -5, 1); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(3U, GestureEventQueueSize()); |
| |
| SendInputEventACK(WebInputEvent::kGestureTapCancel, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| EXPECT_EQ(2U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(2U, GestureEventQueueSize()); |
| |
| SendInputEventACK(WebInputEvent::kGestureScrollUpdate, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, last_acked_event().GetType()); |
| EXPECT_EQ(0.f, last_acked_event().data.scroll_update.delta_x); |
| EXPECT_EQ(0.f, last_acked_event().data.scroll_update.delta_y); |
| |
| SendInputEventACK(WebInputEvent::kGesturePinchUpdate, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| EXPECT_EQ(WebInputEvent::kGesturePinchUpdate, last_acked_event().GetType()); |
| EXPECT_EQ(1.f, last_acked_event().data.pinch_update.scale); |
| } |
| |
| // Tests a single event with an synchronous ack. |
| TEST_F(GestureEventQueueTest, SimpleSyncAck) { |
| set_synchronous_ack(INPUT_EVENT_ACK_STATE_CONSUMED); |
| SimulateGestureEvent(WebInputEvent::kGestureTapDown, |
| blink::kWebGestureDeviceTouchscreen); |
| EXPECT_EQ(1U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(0U, GestureEventQueueSize()); |
| EXPECT_EQ(1U, GetAndResetAckedGestureEventCount()); |
| } |
| |
| // Tests an event with an synchronous ack which enqueues an additional event. |
| TEST_F(GestureEventQueueTest, SyncAckQueuesEvent) { |
| std::unique_ptr<WebGestureEvent> queued_event; |
| set_synchronous_ack(INPUT_EVENT_ACK_STATE_CONSUMED); |
| set_sync_followup_event(WebInputEvent::kGestureShowPress, |
| blink::kWebGestureDeviceTouchscreen); |
| // This event enqueues the show press event. |
| SimulateGestureEvent(WebInputEvent::kGestureTapDown, |
| blink::kWebGestureDeviceTouchscreen); |
| EXPECT_EQ(2U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(1U, GestureEventQueueSize()); |
| EXPECT_EQ(1U, GetAndResetAckedGestureEventCount()); |
| |
| SendInputEventACK(WebInputEvent::kGestureShowPress, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(0U, GestureEventQueueSize()); |
| EXPECT_EQ(1U, GetAndResetAckedGestureEventCount()); |
| } |
| |
| // Tests an event with an async ack followed by an event with a sync ack. |
| TEST_F(GestureEventQueueTest, AsyncThenSyncAck) { |
| SimulateGestureEvent(WebInputEvent::kGestureTapDown, |
| blink::kWebGestureDeviceTouchscreen); |
| |
| EXPECT_EQ(1U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(1U, GestureEventQueueSize()); |
| EXPECT_EQ(0U, GetAndResetAckedGestureEventCount()); |
| |
| SimulateGestureEvent(WebInputEvent::kGestureScrollBegin, |
| blink::kWebGestureDeviceTouchscreen); |
| set_synchronous_ack(INPUT_EVENT_ACK_STATE_CONSUMED); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(2U, GestureEventQueueSize()); |
| EXPECT_EQ(0U, GetAndResetAckedGestureEventCount()); |
| |
| SendInputEventACK(WebInputEvent::kGestureTapDown, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| EXPECT_EQ(1U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(0U, GestureEventQueueSize()); |
| EXPECT_EQ(2U, GetAndResetAckedGestureEventCount()); |
| } |
| |
| TEST_F(GestureEventQueueTest, CoalescesScrollAndPinchEventWithSyncAck) { |
| // Simulate a pinch sequence. |
| SimulateGestureEvent(WebInputEvent::kGestureScrollBegin, |
| blink::kWebGestureDeviceTouchscreen); |
| EXPECT_EQ(1U, GetAndResetSentGestureEventCount()); |
| SimulateGestureEvent(WebInputEvent::kGesturePinchBegin, |
| blink::kWebGestureDeviceTouchscreen); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| |
| SimulateGestureScrollUpdateEvent(8, -4, 1); |
| // Make sure that the queue contains what we think it should. |
| WebGestureEvent merged_event = GestureEventLastQueueEvent(); |
| EXPECT_EQ(3U, GestureEventQueueSize()); |
| EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, merged_event.GetType()); |
| |
| // Coalesced without changing event order. Note anchor at (60, 60). Anchoring |
| // from a point that is not the origin should still give us the right scroll. |
| SimulateGesturePinchUpdateEvent(1.5, 60, 60, 1); |
| EXPECT_EQ(4U, GestureEventQueueSize()); |
| |
| SendInputEventACK(WebInputEvent::kGestureScrollBegin, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| EXPECT_EQ(1U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(3U, GestureEventQueueSize()); |
| |
| // Ack the PinchBegin, and schedule a synchronous ack for GestureScrollUpdate. |
| set_synchronous_ack(INPUT_EVENT_ACK_STATE_CONSUMED); |
| SendInputEventACK(WebInputEvent::kGesturePinchBegin, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| |
| // Both GestureScrollUpdate and GesturePinchUpdate should have been sent. |
| EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, last_acked_event().GetType()); |
| EXPECT_EQ(1U, GestureEventQueueSize()); |
| EXPECT_EQ(2U, GetAndResetSentGestureEventCount()); |
| |
| // Ack the final GesturePinchUpdate. |
| SendInputEventACK(WebInputEvent::kGesturePinchUpdate, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| EXPECT_EQ(WebInputEvent::kGesturePinchUpdate, last_acked_event().GetType()); |
| EXPECT_EQ(0U, GestureEventQueueSize()); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| } |
| |
| #if GTEST_HAS_PARAM_TEST |
| TEST_P(GestureEventQueueWithSourceTest, GestureFlingCancelsFiltered) { |
| WebGestureDevice source_device = GetParam(); |
| |
| // GFC without previous GFS is dropped. |
| SimulateGestureEvent(WebInputEvent::kGestureFlingCancel, source_device); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(0U, GestureEventQueueSize()); |
| |
| // GFC after previous GFS is dispatched and acked. |
| SimulateGestureFlingStartEvent(0, -10, source_device); |
| EXPECT_TRUE(FlingInProgress()); |
| SendInputEventACK(WebInputEvent::kGestureFlingStart, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| RunUntilIdle(); |
| EXPECT_EQ(1U, GetAndResetAckedGestureEventCount()); |
| SimulateGestureEvent(WebInputEvent::kGestureFlingCancel, source_device); |
| EXPECT_FALSE(FlingInProgress()); |
| EXPECT_EQ(2U, GetAndResetSentGestureEventCount()); |
| SendInputEventACK(WebInputEvent::kGestureFlingCancel, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| RunUntilIdle(); |
| EXPECT_EQ(1U, GetAndResetAckedGestureEventCount()); |
| EXPECT_EQ(0U, GestureEventQueueSize()); |
| |
| // GFC before previous GFS is acked. |
| SimulateGestureFlingStartEvent(0, -10, source_device); |
| EXPECT_TRUE(FlingInProgress()); |
| SimulateGestureEvent(WebInputEvent::kGestureFlingCancel, source_device); |
| EXPECT_FALSE(FlingInProgress()); |
| EXPECT_EQ(1U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(2U, GestureEventQueueSize()); |
| |
| // Advance state realistically. |
| SendInputEventACK(WebInputEvent::kGestureFlingStart, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| RunUntilIdle(); |
| EXPECT_EQ(1U, GetAndResetSentGestureEventCount()); |
| SendInputEventACK(WebInputEvent::kGestureFlingCancel, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| RunUntilIdle(); |
| EXPECT_EQ(2U, GetAndResetAckedGestureEventCount()); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(0U, GestureEventQueueSize()); |
| |
| // GFS is added to the queue if another event is pending |
| SimulateGestureScrollUpdateEvent(8, -7, 0); |
| SimulateGestureFlingStartEvent(0, -10, source_device); |
| EXPECT_EQ(2U, GestureEventQueueSize()); |
| EXPECT_EQ(1U, GetAndResetSentGestureEventCount()); |
| WebGestureEvent merged_event = GestureEventLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGestureFlingStart, merged_event.GetType()); |
| EXPECT_TRUE(FlingInProgress()); |
| EXPECT_EQ(2U, GestureEventQueueSize()); |
| |
| // GFS in queue means that a GFC is added to the queue |
| SimulateGestureEvent(WebInputEvent::kGestureFlingCancel, source_device); |
| merged_event =GestureEventLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGestureFlingCancel, merged_event.GetType()); |
| EXPECT_FALSE(FlingInProgress()); |
| EXPECT_EQ(3U, GestureEventQueueSize()); |
| |
| // Adding a second GFC is dropped. |
| SimulateGestureEvent(WebInputEvent::kGestureFlingCancel, source_device); |
| EXPECT_FALSE(FlingInProgress()); |
| EXPECT_EQ(3U, GestureEventQueueSize()); |
| |
| // Adding another GFS will add it to the queue. |
| SimulateGestureFlingStartEvent(0, -10, source_device); |
| merged_event = GestureEventLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGestureFlingStart, merged_event.GetType()); |
| EXPECT_TRUE(FlingInProgress()); |
| EXPECT_EQ(4U, GestureEventQueueSize()); |
| |
| // GFS in queue means that a GFC is added to the queue |
| SimulateGestureEvent(WebInputEvent::kGestureFlingCancel, source_device); |
| merged_event = GestureEventLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGestureFlingCancel, merged_event.GetType()); |
| EXPECT_FALSE(FlingInProgress()); |
| EXPECT_EQ(5U, GestureEventQueueSize()); |
| |
| // Adding another GFC with a GFC already there is dropped. |
| SimulateGestureEvent(WebInputEvent::kGestureFlingCancel, source_device); |
| merged_event = GestureEventLastQueueEvent(); |
| EXPECT_EQ(WebInputEvent::kGestureFlingCancel, merged_event.GetType()); |
| EXPECT_FALSE(FlingInProgress()); |
| EXPECT_EQ(5U, GestureEventQueueSize()); |
| } |
| |
| INSTANTIATE_TEST_CASE_P(AllSources, |
| GestureEventQueueWithSourceTest, |
| testing::Values(blink::kWebGestureDeviceTouchscreen, |
| blink::kWebGestureDeviceTouchpad)); |
| #endif // GTEST_HAS_PARAM_TEST |
| |
| // Test that a GestureScrollEnd | GestureFlingStart are deferred during the |
| // debounce interval, that Scrolls are not and that the deferred events are |
| // sent after that timer fires. |
| TEST_F(GestureEventQueueTest, DebounceDefersFollowingGestureEvents) { |
| SetUpForDebounce(3); |
| |
| SimulateGestureEvent(WebInputEvent::kGestureScrollUpdate, |
| blink::kWebGestureDeviceTouchscreen); |
| EXPECT_EQ(1U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(1U, GestureEventQueueSize()); |
| EXPECT_EQ(0U, GestureEventDebouncingQueueSize()); |
| EXPECT_TRUE(ScrollingInProgress()); |
| |
| SimulateGestureEvent(WebInputEvent::kGestureScrollUpdate, |
| blink::kWebGestureDeviceTouchscreen); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(2U, GestureEventQueueSize()); |
| EXPECT_EQ(0U, GestureEventDebouncingQueueSize()); |
| EXPECT_TRUE(ScrollingInProgress()); |
| |
| SimulateGestureEvent(WebInputEvent::kGestureScrollEnd, |
| blink::kWebGestureDeviceTouchscreen); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(2U, GestureEventQueueSize()); |
| EXPECT_EQ(1U, GestureEventDebouncingQueueSize()); |
| |
| SimulateGestureFlingStartEvent(0, 10, blink::kWebGestureDeviceTouchscreen); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(2U, GestureEventQueueSize()); |
| EXPECT_EQ(2U, GestureEventDebouncingQueueSize()); |
| |
| SimulateGestureEvent(WebInputEvent::kGestureTapDown, |
| blink::kWebGestureDeviceTouchscreen); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(2U, GestureEventQueueSize()); |
| EXPECT_EQ(3U, GestureEventDebouncingQueueSize()); |
| |
| base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(), |
| TimeDelta::FromMilliseconds(5)); |
| base::RunLoop().Run(); |
| |
| // The deferred events are correctly queued in coalescing queue. |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(5U, GestureEventQueueSize()); |
| EXPECT_EQ(0U, GestureEventDebouncingQueueSize()); |
| EXPECT_FALSE(ScrollingInProgress()); |
| |
| // Verify that the coalescing queue contains the correct events. |
| WebInputEvent::Type expected[] = { |
| WebInputEvent::kGestureScrollUpdate, WebInputEvent::kGestureScrollUpdate, |
| WebInputEvent::kGestureScrollEnd, WebInputEvent::kGestureFlingStart}; |
| |
| for (unsigned i = 0; i < sizeof(expected) / sizeof(WebInputEvent::Type); |
| i++) { |
| WebGestureEvent merged_event = GestureEventQueueEventAt(i); |
| EXPECT_EQ(expected[i], merged_event.GetType()); |
| } |
| } |
| |
| // Test that non-scroll events are deferred while scrolling during the debounce |
| // interval and are discarded if a GestureScrollUpdate event arrives before the |
| // interval end. |
| TEST_F(GestureEventQueueTest, DebounceDropsDeferredEvents) { |
| SetUpForDebounce(3); |
| |
| EXPECT_FALSE(ScrollingInProgress()); |
| |
| SimulateGestureEvent(WebInputEvent::kGestureScrollUpdate, |
| blink::kWebGestureDeviceTouchscreen); |
| EXPECT_EQ(1U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(1U, GestureEventQueueSize()); |
| EXPECT_EQ(0U, GestureEventDebouncingQueueSize()); |
| EXPECT_TRUE(ScrollingInProgress()); |
| |
| // This event should get discarded. |
| SimulateGestureEvent(WebInputEvent::kGestureScrollEnd, |
| blink::kWebGestureDeviceTouchscreen); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(1U, GestureEventQueueSize()); |
| EXPECT_EQ(1U, GestureEventDebouncingQueueSize()); |
| |
| SimulateGestureEvent(WebInputEvent::kGestureScrollUpdate, |
| blink::kWebGestureDeviceTouchscreen); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(2U, GestureEventQueueSize()); |
| EXPECT_EQ(0U, GestureEventDebouncingQueueSize()); |
| EXPECT_TRUE(ScrollingInProgress()); |
| |
| // Verify that the coalescing queue contains the correct events. |
| WebInputEvent::Type expected[] = {WebInputEvent::kGestureScrollUpdate, |
| WebInputEvent::kGestureScrollUpdate}; |
| |
| for (unsigned i = 0; i < sizeof(expected) / sizeof(WebInputEvent::Type); |
| i++) { |
| WebGestureEvent merged_event = GestureEventQueueEventAt(i); |
| EXPECT_EQ(expected[i], merged_event.GetType()); |
| } |
| } |
| |
| TEST_F(GestureEventQueueTest, CoalescesSyntheticScrollBeginEndEvents) { |
| // Test coalescing of only GestureScrollBegin/End events. |
| SimulateGestureEvent(WebInputEvent::kGestureScrollUpdate, |
| blink::kWebGestureDeviceTouchpad); |
| EXPECT_EQ(1U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(1U, GestureEventQueueSize()); |
| |
| WebGestureEvent synthetic_end = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::kGestureScrollEnd, blink::kWebGestureDeviceTouchpad); |
| synthetic_end.data.scroll_end.synthetic = true; |
| |
| SimulateGestureEvent(synthetic_end); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(2U, GestureEventQueueSize()); |
| |
| // Synthetic begin will remove the unsent synthetic end. |
| WebGestureEvent synthetic_begin = SyntheticWebGestureEventBuilder::Build( |
| WebInputEvent::kGestureScrollBegin, blink::kWebGestureDeviceTouchpad); |
| synthetic_begin.data.scroll_begin.synthetic = true; |
| |
| SimulateGestureEvent(synthetic_begin); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(1U, GestureEventQueueSize()); |
| } |
| |
| TEST_F(GestureEventQueueWithCompositorEventQueueTest, |
| MultipleGesturesInFlight) { |
| // Simulate a pinch sequence, events should be forwarded immediately. |
| SimulateGestureEvent(WebInputEvent::kGestureScrollBegin, |
| blink::kWebGestureDeviceTouchscreen); |
| EXPECT_EQ(1U, GetAndResetSentGestureEventCount()); |
| SimulateGestureEvent(WebInputEvent::kGesturePinchBegin, |
| blink::kWebGestureDeviceTouchscreen); |
| EXPECT_EQ(1U, GetAndResetSentGestureEventCount()); |
| |
| SimulateGestureScrollUpdateEvent(8, -4, 1); |
| EXPECT_EQ(1U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(3U, GestureEventQueueSize()); |
| EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, |
| GestureEventLastQueueEvent().GetType()); |
| |
| // Simulate 2 pinch update events. |
| SimulateGesturePinchUpdateEvent(1.5, 60, 60, 1); |
| EXPECT_EQ(4U, GestureEventQueueSize()); |
| SimulateGesturePinchUpdateEvent(1.3, 60, 60, 1); |
| // Events should be forwarded immediately instead of being coalesced. |
| EXPECT_EQ(5U, GestureEventQueueSize()); |
| EXPECT_EQ(2U, GetAndResetSentGestureEventCount()); |
| EXPECT_EQ(WebInputEvent::kGesturePinchUpdate, |
| GestureEventLastQueueEvent().GetType()); |
| |
| SendInputEventACK(WebInputEvent::kGestureScrollBegin, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| EXPECT_EQ(4U, GestureEventQueueSize()); |
| |
| SendInputEventACK(WebInputEvent::kGesturePinchBegin, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| SendInputEventACK(WebInputEvent::kGestureScrollUpdate, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| |
| // Both GestureScrollUpdate and GesturePinchUpdate should have been sent. |
| EXPECT_EQ(WebInputEvent::kGestureScrollUpdate, last_acked_event().GetType()); |
| EXPECT_EQ(2U, GestureEventQueueSize()); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| |
| // Ack the last 2 GesturePinchUpdate events. |
| SendInputEventACK(WebInputEvent::kGesturePinchUpdate, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| SendInputEventACK(WebInputEvent::kGesturePinchUpdate, |
| INPUT_EVENT_ACK_STATE_CONSUMED); |
| EXPECT_EQ(WebInputEvent::kGesturePinchUpdate, last_acked_event().GetType()); |
| EXPECT_EQ(0U, GestureEventQueueSize()); |
| EXPECT_EQ(0U, GetAndResetSentGestureEventCount()); |
| } |
| |
| } // namespace content |