| Index: content/browser/renderer_host/input/gesture_event_queue_unittest.cc
|
| diff --git a/content/browser/renderer_host/input/gesture_event_queue_unittest.cc b/content/browser/renderer_host/input/gesture_event_queue_unittest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..7eac31c17c8b3ffd79b1cba369e4603b8bd415fb
|
| --- /dev/null
|
| +++ b/content/browser/renderer_host/input/gesture_event_queue_unittest.cc
|
| @@ -0,0 +1,313 @@
|
| +// Copyright 2013 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 "base/basictypes.h"
|
| +#include "base/logging.h"
|
| +#include "base/memory/scoped_ptr.h"
|
| +#include "content/browser/renderer_host/input/touch_to_gesture_queue.h"
|
| +#include "content/common/input/synthetic_web_input_event_builders.h"
|
| +#include "testing/gtest/include/gtest/gtest.h"
|
| +#include "third_party/WebKit/public/web/WebInputEvent.h"
|
| +
|
| +using blink::WebGestureEvent;
|
| +using blink::WebInputEvent;
|
| +using blink::WebTouchEvent;
|
| +using blink::WebTouchPoint;
|
| +
|
| +namespace content {
|
| +namespace {
|
| +const size_t kDefaultTouchTimeoutDelayMs = 10;
|
| +}
|
| +
|
| +class TouchToGestureQueueTest : public testing::Test,
|
| + public TouchToGestureQueueClient {
|
| + public:
|
| + TouchToGestureQueueTest()
|
| + : sent_touch_count_(0),
|
| + sent_gesture_count_(0) {}
|
| +
|
| + virtual ~TouchToGestureQueueTest() {}
|
| +
|
| + // testing::Test
|
| + virtual void SetUp() OVERRIDE {
|
| + queue_.reset(new TouchToGestureQueue(this));
|
| + }
|
| +
|
| + virtual void TearDown() OVERRIDE {
|
| + queue_.reset();
|
| + }
|
| +
|
| + // TouchEventQueueClient
|
| + virtual void ForwardTouchEvent(const WebTouchEvent& event) OVERRIDE {
|
| + ++sent_touch_count_;
|
| + last_touch_event_ = event;
|
| + if (sync_ack_result_)
|
| + SendTouchEventACK(*sync_ack_result_.Pass());
|
| + }
|
| +
|
| + virtual void ForwardGestureEvent(const WebGestureEvent& event) OVERRIDE {
|
| + ++sent_gesture_count_;
|
| + last_gesture_event_ = event;
|
| + }
|
| +
|
| + protected:
|
| + typedef std::vector<WebGestureEvent> Gestures;
|
| +
|
| + void SendTouchEventWithGestures() {
|
| + Gestures gestures;
|
| + gestures.swap(gestures_);
|
| + SendTouchEventWithGestures(touch_event_, gestures);
|
| + touch_event_.ResetPoints();
|
| + }
|
| +
|
| + void SendTouchEventWithGestures(const WebTouchEvent& touch,
|
| + const Gestures& gestures) {
|
| + queue_->OnTouchEventHandlingBegin(touch);
|
| + for (size_t i = 0; i < gestures.size(); ++i)
|
| + queue_->OnGestureEvent(gestures[i]);
|
| + queue_->OnTouchEventHandlingEnd();
|
| + }
|
| +
|
| + void SendGesture(const WebGestureEvent& gesture) {
|
| + queue_->OnGestureEvent(gesture);
|
| + }
|
| +
|
| + void SendTouchEventACK(InputEventAckState ack_result) {
|
| + queue_->OnTouchEventAck(ack_result);
|
| + }
|
| +
|
| + void SetSyncAckResult(InputEventAckState sync_ack_result) {
|
| + sync_ack_result_.reset(new InputEventAckState(sync_ack_result));
|
| + }
|
| +
|
| + void PushGesture(const WebGestureEvent& gesture) {
|
| + gestures_.push_back(gesture);
|
| + }
|
| +
|
| + void PushGesture(WebInputEvent::Type type) {
|
| + DCHECK(WebInputEvent::isGestureEventType(type));
|
| + PushGesture(CreateGesture(type));
|
| + }
|
| +
|
| + void PressTouchPoint(int x, int y) {
|
| + touch_event_.PressPoint(x, y);
|
| + SendTouchEventWithGestures();
|
| + }
|
| +
|
| + void MoveTouchPoint(int index, int x, int y) {
|
| + touch_event_.MovePoint(index, x, y);
|
| + SendTouchEventWithGestures();
|
| + }
|
| +
|
| + void MoveTouchPoints(int index0, int x0, int y0, int index1, int x1, int y1) {
|
| + touch_event_.MovePoint(index0, x0, y0);
|
| + touch_event_.MovePoint(index1, x1, y1);
|
| + SendTouchEventWithGestures();
|
| + }
|
| +
|
| + void ReleaseTouchPoint(int index) {
|
| + touch_event_.ReleasePoint(index);
|
| + SendTouchEventWithGestures();
|
| + }
|
| +
|
| + void CancelTouchPoint(int index) {
|
| + touch_event_.CancelPoint(index);
|
| + SendTouchEventWithGestures();
|
| + }
|
| +
|
| + size_t GetAndResetSentTouchCount() {
|
| + size_t count = sent_touch_count_;
|
| + sent_touch_count_ = 0;
|
| + return count;
|
| + }
|
| +
|
| + size_t GetAndResetSentGestureCount() {
|
| + size_t count = sent_gesture_count_;
|
| + sent_gesture_count_ = 0;
|
| + return count;
|
| + }
|
| +
|
| + const WebTouchEvent& sent_touch() const {
|
| + return last_touch_event_;
|
| + }
|
| +
|
| + const WebGestureEvent& sent_gesture() const {
|
| + return last_gesture_event_;
|
| + }
|
| +
|
| + static WebGestureEvent CreateGesture(WebInputEvent::Type type) {
|
| + return SyntheticWebGestureEventBuilder::Build(
|
| + type, WebGestureEvent::Touchscreen);
|
| + }
|
| +
|
| + private:
|
| +
|
| + scoped_ptr<TouchToGestureQueue> queue_;
|
| + SyntheticWebTouchEvent touch_event_;
|
| + Gestures gestures_;
|
| + size_t sent_touch_count_;
|
| + size_t sent_gesture_count_;
|
| + WebTouchEvent last_touch_event_;
|
| + WebGestureEvent last_gesture_event_;
|
| + scoped_ptr<InputEventAckState> sync_ack_result_;
|
| +};
|
| +
|
| +TEST_F(TouchToGestureQueueTest, BasicNoGestures) {
|
| + PressTouchPoint(1, 1);
|
| + EXPECT_EQ(1U, GetAndResetSentTouchCount());
|
| + EXPECT_EQ(0U, GetAndResetSentGestureCount());
|
| + EXPECT_EQ(WebInputEvent::TouchStart, sent_touch().type);
|
| +
|
| + // Touch events are always forwarded immediately.
|
| + MoveTouchPoint(0, 2, 2);
|
| + EXPECT_EQ(1U, GetAndResetSentTouchCount());
|
| + EXPECT_EQ(0U, GetAndResetSentGestureCount());
|
| + EXPECT_EQ(WebInputEvent::TouchMove, sent_touch().type);
|
| +
|
| + // No gestures should be dispatched by the ack, as none were queued.
|
| + SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
|
| + EXPECT_EQ(0U, GetAndResetSentTouchCount());
|
| + EXPECT_EQ(0U, GetAndResetSentGestureCount());
|
| +
|
| + // Release the touch gesture.
|
| + ReleaseTouchPoint(0);
|
| + EXPECT_EQ(1U, GetAndResetSentTouchCount());
|
| + EXPECT_EQ(0U, GetAndResetSentGestureCount());
|
| + EXPECT_EQ(WebInputEvent::TouchEnd, sent_touch().type);
|
| +}
|
| +
|
| +TEST_F(TouchToGestureQueueTest, BasicGestures) {
|
| + // An unconsumed touch's gesture should be sent.
|
| + PushGesture(WebInputEvent::GestureScrollBegin);
|
| + PressTouchPoint(1, 1);
|
| + EXPECT_EQ(1U, GetAndResetSentTouchCount());
|
| + EXPECT_EQ(0U, GetAndResetSentGestureCount());
|
| + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
|
| + EXPECT_EQ(1U, GetAndResetSentGestureCount());
|
| + EXPECT_EQ(WebInputEvent::GestureScrollBegin, sent_gesture().type);
|
| +
|
| + // Multiple gestures can be queued for a single event.
|
| + PushGesture(WebInputEvent::GestureFlingStart);
|
| + PushGesture(WebInputEvent::GestureFlingCancel);
|
| + MoveTouchPoint(0, 1, 1);
|
| + EXPECT_EQ(1U, GetAndResetSentTouchCount());
|
| + EXPECT_EQ(0U, GetAndResetSentGestureCount());
|
| + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
|
| + EXPECT_EQ(2U, GetAndResetSentGestureCount());
|
| + EXPECT_EQ(WebInputEvent::GestureFlingCancel, sent_gesture().type);
|
| +
|
| + // A consumed touch's gesture should not be sent.
|
| + PushGesture(WebInputEvent::GestureFlingStart);
|
| + PushGesture(WebInputEvent::GestureFlingCancel);
|
| + ReleaseTouchPoint(0);
|
| + EXPECT_EQ(1U, GetAndResetSentTouchCount());
|
| + EXPECT_EQ(0U, GetAndResetSentGestureCount());
|
| + SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
|
| + EXPECT_EQ(0U, GetAndResetSentGestureCount());
|
| +}
|
| +
|
| +TEST_F(TouchToGestureQueueTest, ConsumedThenNotConsumed) {
|
| + // A consumed touch's gesture should not be sent.
|
| + PushGesture(WebInputEvent::GestureScrollBegin);
|
| + PressTouchPoint(1, 1);
|
| + EXPECT_EQ(1U, GetAndResetSentTouchCount());
|
| + SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
|
| + EXPECT_EQ(0U, GetAndResetSentGestureCount());
|
| +
|
| + // Event if the subsequent touch is not consumed, continue dropping gestures.
|
| + PushGesture(WebInputEvent::GestureScrollUpdate);
|
| + MoveTouchPoint(0, 2, 2);
|
| + EXPECT_EQ(1U, GetAndResetSentTouchCount());
|
| + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
|
| + EXPECT_EQ(0U, GetAndResetSentGestureCount());
|
| +
|
| + // Event if the subsequent touch had no consumer, continue dropping gestures.
|
| + PushGesture(WebInputEvent::GestureFlingStart);
|
| + ReleaseTouchPoint(0);
|
| + EXPECT_EQ(1U, GetAndResetSentTouchCount());
|
| + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
|
| + EXPECT_EQ(0U, GetAndResetSentGestureCount());
|
| +}
|
| +
|
| +TEST_F(TouchToGestureQueueTest, NotConsumedThenNoConsumer) {
|
| + // An unconsumed touch's gesture should be sent.
|
| + PushGesture(WebInputEvent::GestureScrollBegin);
|
| + PressTouchPoint(1, 1);
|
| + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
|
| + EXPECT_EQ(1U, GetAndResetSentTouchCount());
|
| + EXPECT_EQ(1U, GetAndResetSentGestureCount());
|
| +
|
| + // If the subsequent touch has no consumer, send the gesture.
|
| + PushGesture(WebInputEvent::GestureScrollEnd);
|
| + MoveTouchPoint(0, 2, 2);
|
| + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
|
| + EXPECT_EQ(1U, GetAndResetSentTouchCount());
|
| + EXPECT_EQ(1U, GetAndResetSentGestureCount());
|
| +
|
| + // Even if the subsequent touch was consumed, continue sending gestures.
|
| + PushGesture(WebInputEvent::GestureFlingStart);
|
| + PushGesture(WebInputEvent::GestureFlingCancel);
|
| + MoveTouchPoint(0, 2, 2);
|
| + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
|
| + EXPECT_EQ(1U, GetAndResetSentTouchCount());
|
| + EXPECT_EQ(2U, GetAndResetSentGestureCount());
|
| +}
|
| +
|
| +TEST_F(TouchToGestureQueueTest, MultipleTouchSequences) {
|
| + // Queue two touch-to-gestures sequences.
|
| + PushGesture(WebInputEvent::GestureFlingStart);
|
| + PressTouchPoint(1, 1);
|
| + PushGesture(WebInputEvent::GestureFlingCancel);
|
| + ReleaseTouchPoint(0);
|
| + PushGesture(WebInputEvent::GestureFlingStart);
|
| + PressTouchPoint(1, 1);
|
| + PushGesture(WebInputEvent::GestureFlingCancel);
|
| + ReleaseTouchPoint(0);
|
| + EXPECT_EQ(4U, GetAndResetSentTouchCount());
|
| +
|
| + // The first gesture sequence should not be allowed.
|
| + SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
|
| + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
|
| + EXPECT_EQ(0U, GetAndResetSentGestureCount());
|
| +
|
| + // The subsequent sequence should "reset" allowance.
|
| + // The first gesture sequence should not be allowed.
|
| + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
|
| + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
|
| + EXPECT_EQ(2U, GetAndResetSentGestureCount());
|
| +}
|
| +
|
| +TEST_F(TouchToGestureQueueTest, TimeoutGestures) {}
|
| +
|
| +TEST_F(TouchToGestureQueueTest, GestureFlingCancel) {}
|
| +
|
| +TEST_F(TouchToGestureQueueTest, GestureTapCancel) {}
|
| +
|
| +TEST_F(TouchToGestureQueueTest, SyntheticGestures) {
|
| + // Non-timeout gestures without an associated touch event should be
|
| + // forwarded immediately.
|
| + SendGesture(CreateGesture(WebInputEvent::GesturePinchBegin));
|
| + SendGesture(CreateGesture(WebInputEvent::GesturePinchUpdate));
|
| + SendGesture(CreateGesture(WebInputEvent::GesturePinchEnd));
|
| + EXPECT_EQ(3U, GetAndResetSentGestureCount());
|
| + EXPECT_EQ(WebInputEvent::GesturePinchEnd, sent_gesture().type);
|
| +
|
| + PushGesture(WebInputEvent::GestureFlingStart);
|
| + PressTouchPoint(1, 1);
|
| +
|
| + // Even if there's a queued gesture, synthetic events should be forwarded
|
| + // immediately.
|
| + SendGesture(CreateGesture(WebInputEvent::GesturePinchBegin));
|
| + SendGesture(CreateGesture(WebInputEvent::GesturePinchUpdate));
|
| + SendGesture(CreateGesture(WebInputEvent::GesturePinchEnd));
|
| + EXPECT_EQ(3U, GetAndResetSentGestureCount());
|
| + EXPECT_EQ(WebInputEvent::GesturePinchEnd, sent_gesture().type);
|
| +
|
| + // The queued gesture should be dispatched as usual.
|
| + SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
|
| + EXPECT_EQ(1U, GetAndResetSentGestureCount());
|
| + EXPECT_EQ(WebInputEvent::GestureFlingStart, sent_gesture().type);
|
| +}
|
| +
|
| +} // namespace content
|
|
|