| Index: ui/aura/gestures/gesture_recognizer_unittest.cc
|
| diff --git a/ui/aura/gestures/gesture_recognizer_unittest.cc b/ui/aura/gestures/gesture_recognizer_unittest.cc
|
| index f7d1a4288ad95666b1c97a77ceca15628cfbacc3..23cbfbde3fd9500fb99a7f3ecb45e50acde46948 100644
|
| --- a/ui/aura/gestures/gesture_recognizer_unittest.cc
|
| +++ b/ui/aura/gestures/gesture_recognizer_unittest.cc
|
| @@ -337,7 +337,8 @@ class QueueTouchEventDelegate : public GestureEventConsumeDelegate {
|
| explicit QueueTouchEventDelegate(WindowEventDispatcher* dispatcher)
|
| : window_(NULL),
|
| dispatcher_(dispatcher),
|
| - queue_events_(true) {
|
| + queue_events_(true),
|
| + synchronous_ack_for_next_event_(AckState::PENDING) {
|
| }
|
| ~QueueTouchEventDelegate() override {
|
| while(!queue_.empty()) {
|
| @@ -347,10 +348,18 @@ class QueueTouchEventDelegate : public GestureEventConsumeDelegate {
|
| }
|
|
|
| void OnTouchEvent(ui::TouchEvent* event) override {
|
| - if (queue_events_) {
|
| - queue_.push(new ui::TouchEvent(*event, window_, window_));
|
| - event->StopPropagation();
|
| + event->DisableSynchronousHandling();
|
| + if (synchronous_ack_for_next_event_ != AckState::PENDING) {
|
| + ui::GestureRecognizer::Get()->AckSyncTouchEvent(
|
| + event->unique_event_id(),
|
| + synchronous_ack_for_next_event_ == AckState::CONSUMED
|
| + ? ui::ER_CONSUMED
|
| + : ui::ER_UNHANDLED,
|
| + window_);
|
| + synchronous_ack_for_next_event_ = AckState::PENDING;
|
| }
|
| + if (queue_events_)
|
| + queue_.push(new ui::TouchEvent(*event, window_, window_));
|
| }
|
|
|
| void ReceivedAck() {
|
| @@ -363,8 +372,19 @@ class QueueTouchEventDelegate : public GestureEventConsumeDelegate {
|
|
|
| void set_window(Window* w) { window_ = w; }
|
| void set_queue_events(bool queue) { queue_events_ = queue; }
|
| + void set_synchronous_ack_for_next_event(bool consumed) {
|
| + DCHECK(synchronous_ack_for_next_event_ == AckState::PENDING);
|
| + synchronous_ack_for_next_event_ =
|
| + consumed ? AckState::CONSUMED : AckState::UNCONSUMED;
|
| + }
|
|
|
| private:
|
| + enum class AckState {
|
| + PENDING,
|
| + CONSUMED,
|
| + UNCONSUMED,
|
| + };
|
| +
|
| void ReceivedAckImpl(bool prevent_defaulted) {
|
| scoped_ptr<ui::TouchEvent> event(queue_.front());
|
| dispatcher_->ProcessedTouchEvent(event.get(), window_,
|
| @@ -376,6 +396,7 @@ class QueueTouchEventDelegate : public GestureEventConsumeDelegate {
|
| Window* window_;
|
| WindowEventDispatcher* dispatcher_;
|
| bool queue_events_;
|
| + AckState synchronous_ack_for_next_event_;
|
|
|
| DISALLOW_COPY_AND_ASSIGN(QueueTouchEventDelegate);
|
| };
|
| @@ -4247,7 +4268,7 @@ TEST_F(GestureRecognizerTest, GestureEventSmallPinchEnabled) {
|
|
|
| // Tests that delaying the ack of a touch release doesn't trigger a long press
|
| // gesture.
|
| -TEST_F(GestureRecognizerTest, DISABLED_EagerGestureDetection) {
|
| +TEST_F(GestureRecognizerTest, EagerGestureDetection) {
|
| scoped_ptr<QueueTouchEventDelegate> delegate(
|
| new QueueTouchEventDelegate(host()->dispatcher()));
|
| TimedEvents tes;
|
| @@ -4280,9 +4301,9 @@ TEST_F(GestureRecognizerTest, DISABLED_EagerGestureDetection) {
|
| EXPECT_FALSE(delegate->long_press());
|
| }
|
|
|
| -// This tests crbug.com/405519, in which events which the gesture detector
|
| -// ignores cause future events to also be thrown away.
|
| -TEST_F(GestureRecognizerTest, IgnoredEventsDontPreventFutureEvents) {
|
| +// This tests crbug.com/405519, in which touch events which the gesture detector
|
| +// ignores interfere with gesture recognition.
|
| +TEST_F(GestureRecognizerTest, IgnoredEventsDontBreakGestureRecognition) {
|
| scoped_ptr<QueueTouchEventDelegate> delegate(
|
| new QueueTouchEventDelegate(host()->dispatcher()));
|
| TimedEvents tes;
|
| @@ -4315,9 +4336,12 @@ TEST_F(GestureRecognizerTest, IgnoredEventsDontPreventFutureEvents) {
|
| ui::ET_GESTURE_SCROLL_UPDATE);
|
|
|
| delegate->Reset();
|
| +
|
| + // Send a valid event, but don't ack it.
|
| ui::TouchEvent move2(
|
| ui::ET_TOUCH_MOVED, gfx::Point(65, 202), kTouchId1, tes.Now());
|
| DispatchEventUsingWindowDispatcher(&move2);
|
| + EXPECT_0_EVENTS(delegate->events());
|
|
|
| // Send a touchmove event at the same location as the previous touchmove
|
| // event. This shouldn't do anything.
|
| @@ -4325,9 +4349,88 @@ TEST_F(GestureRecognizerTest, IgnoredEventsDontPreventFutureEvents) {
|
| ui::ET_TOUCH_MOVED, gfx::Point(65, 202), kTouchId1, tes.Now());
|
| DispatchEventUsingWindowDispatcher(&move3);
|
|
|
| + // Ack the previous valid event. The intermediary invalid event shouldn't
|
| + // interfere.
|
| delegate->ReceivedAck();
|
| EXPECT_1_EVENT(delegate->events(), ui::ET_GESTURE_SCROLL_UPDATE);
|
| }
|
|
|
| +// Tests that an event stream can have a mix of sync and async acks.
|
| +TEST_F(GestureRecognizerTest,
|
| + MixedSyncAndAsyncAcksDontCauseOutOfOrderDispatch) {
|
| + scoped_ptr<QueueTouchEventDelegate> delegate(
|
| + new QueueTouchEventDelegate(host()->dispatcher()));
|
| + TimedEvents tes;
|
| + const int kWindowWidth = 300;
|
| + const int kWindowHeight = 400;
|
| + const int kTouchId1 = 3;
|
| + gfx::Rect bounds(0, 0, kWindowWidth, kWindowHeight);
|
| + scoped_ptr<aura::Window> window(CreateTestWindowWithDelegate(
|
| + delegate.get(), -1234, bounds, root_window()));
|
| + delegate->set_window(window.get());
|
| +
|
| + // Start a scroll gesture.
|
| + ui::TouchEvent press1(
|
| + ui::ET_TOUCH_PRESSED, gfx::Point(0, 0), kTouchId1, tes.Now());
|
| + DispatchEventUsingWindowDispatcher(&press1);
|
| + delegate->ReceivedAck();
|
| +
|
| + ui::TouchEvent move1(
|
| + ui::ET_TOUCH_MOVED, gfx::Point(100, 100), kTouchId1, tes.Now());
|
| + DispatchEventUsingWindowDispatcher(&move1);
|
| + delegate->ReceivedAck();
|
| +
|
| + delegate->Reset();
|
| + // Dispatch a synchronously consumed touch move, which should be ignored.
|
| + delegate->set_synchronous_ack_for_next_event(true);
|
| + ui::TouchEvent move2(ui::ET_TOUCH_MOVED, gfx::Point(200, 200), kTouchId1,
|
| + tes.Now());
|
| + DispatchEventUsingWindowDispatcher(&move2);
|
| + EXPECT_0_EVENTS(delegate->events());
|
| +
|
| + // Dispatch a touch move, but don't ack it.
|
| + ui::TouchEvent move3(ui::ET_TOUCH_MOVED, gfx::Point(300, 300), kTouchId1,
|
| + tes.Now());
|
| + DispatchEventUsingWindowDispatcher(&move3);
|
| +
|
| + // Dispatch two synchronously consumed touch moves, which should be ignored.
|
| + delegate->set_synchronous_ack_for_next_event(true);
|
| + ui::TouchEvent move4(
|
| + ui::ET_TOUCH_MOVED, gfx::Point(400, 400), kTouchId1, tes.Now());
|
| + DispatchEventUsingWindowDispatcher(&move4);
|
| +
|
| + delegate->set_synchronous_ack_for_next_event(true);
|
| + ui::TouchEvent move5(
|
| + ui::ET_TOUCH_MOVED, gfx::Point(500, 500), kTouchId1, tes.Now());
|
| + DispatchEventUsingWindowDispatcher(&move5);
|
| +
|
| + EXPECT_0_EVENTS(delegate->events());
|
| + EXPECT_EQ(100, delegate->bounding_box().x());
|
| + // Ack the pending touch move, and ensure the most recent gesture event
|
| + // used its co-ordinates.
|
| + delegate->ReceivedAck();
|
| + EXPECT_EQ(300, delegate->bounding_box().x());
|
| + EXPECT_1_EVENT(delegate->events(), ui::ET_GESTURE_SCROLL_UPDATE);
|
| +
|
| + // Dispatch a touch move, but don't ack it.
|
| + delegate->Reset();
|
| + ui::TouchEvent move6(ui::ET_TOUCH_MOVED, gfx::Point(600, 600), kTouchId1,
|
| + tes.Now());
|
| + DispatchEventUsingWindowDispatcher(&move6);
|
| +
|
| + // Dispatch a synchronously unconsumed touch move.
|
| + delegate->set_synchronous_ack_for_next_event(false);
|
| + ui::TouchEvent move7(
|
| + ui::ET_TOUCH_MOVED, gfx::Point(700, 700), kTouchId1, tes.Now());
|
| + DispatchEventUsingWindowDispatcher(&move7);
|
| +
|
| + // The synchronous ack is stuck behind the pending touch move.
|
| + EXPECT_0_EVENTS(delegate->events());
|
| +
|
| + delegate->ReceivedAck();
|
| + EXPECT_2_EVENTS(delegate->events(), ui::ET_GESTURE_SCROLL_UPDATE,
|
| + ui::ET_GESTURE_SCROLL_UPDATE);
|
| +}
|
| +
|
| } // namespace test
|
| } // namespace aura
|
|
|