Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(168)

Side by Side Diff: content/browser/renderer_host/input/gesture_event_queue_unittest.cc

Issue 120513005: [Android] Perform eager gesture recognition on MotionEvents (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Findbugs fix Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/basictypes.h"
6 #include "base/logging.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "content/browser/renderer_host/input/gesture_event_queue.h"
9 #include "content/common/input/synthetic_web_input_event_builders.h"
10 #include "testing/gtest/include/gtest/gtest.h"
11 #include "third_party/WebKit/public/web/WebInputEvent.h"
12
13 using blink::WebGestureEvent;
14 using blink::WebInputEvent;
15 using blink::WebTouchEvent;
16 using blink::WebTouchPoint;
17
18 namespace content {
19
20 class GestureEventQueueTest : public testing::Test,
21 public GestureEventQueueClient {
22 public:
23 GestureEventQueueTest() : sent_gesture_count_(0) {}
24
25 virtual ~GestureEventQueueTest() {}
26
27 // testing::Test
28 virtual void SetUp() OVERRIDE {
29 queue_.reset(new GestureEventQueue(this));
30 }
31
32 virtual void TearDown() OVERRIDE {
33 queue_.reset();
34 }
35
36 // GestureEventQueueClient
37 virtual void ForwardGestureEvent(const WebGestureEvent& event) OVERRIDE {
38 ++sent_gesture_count_;
39 last_gesture_event_ = event;
40 }
41
42 protected:
43 typedef std::vector<WebGestureEvent> Gestures;
44
45 void SendTouchGestures() {
46 GestureEventPacket gesture_packet;
47 std::swap(gesture_packet, gesture_packet_);
48 SendTouchGestures(touch_event_, gesture_packet);
49 touch_event_.ResetPoints();
50 }
51
52 void SendTouchGestures(const WebTouchEvent& touch,
53 const GestureEventPacket& packet) {
54 GestureEventPacket touch_packet = GestureEventPacket::FromTouch(touch);
55 for (size_t i = 0; i < packet.gesture_count(); ++i)
56 touch_packet.Push(packet.gesture(i));
57 queue_->OnGestureEventPacket(touch_packet);
58 }
59
60 void SendGesture(GestureEventPacket::GestureSource source,
61 const WebGestureEvent& gesture) {
62 queue_->OnGestureEventPacket(
63 GestureEventPacket::FromGesture(source, gesture));
64 }
65
66 void SendTimeoutGesture(const WebGestureEvent& gesture) {
67 SendGesture(GestureEventPacket::TOUCH_TIMEOUT, gesture);
68 }
69
70 void SendSyntheticGesture(const WebGestureEvent& gesture) {
71 SendGesture(GestureEventPacket::SYNTHETIC, gesture);
72 }
73
74 void SendTouchEventACK(InputEventAckState ack_result) {
75 queue_->OnTouchEventAck(ack_result);
76 }
77
78 void PushGesture(const WebGestureEvent& gesture) {
79 gesture_packet_.Push(gesture);
80 }
81
82 void PushGesture(WebInputEvent::Type type) {
83 DCHECK(WebInputEvent::isGestureEventType(type));
84 PushGesture(CreateGesture(type));
85 }
86
87 void PressTouchPoint(int x, int y) {
88 touch_event_.PressPoint(x, y);
89 SendTouchGestures();
90 }
91
92 void MoveTouchPoint(int index, int x, int y) {
93 touch_event_.MovePoint(index, x, y);
94 SendTouchGestures();
95 }
96
97 void MoveTouchPoints(int index0, int x0, int y0, int index1, int x1, int y1) {
98 touch_event_.MovePoint(index0, x0, y0);
99 touch_event_.MovePoint(index1, x1, y1);
100 SendTouchGestures();
101 }
102
103 void ReleaseTouchPoint(int index) {
104 touch_event_.ReleasePoint(index);
105 SendTouchGestures();
106 }
107
108 void CancelTouchPoint(int index) {
109 touch_event_.CancelPoint(index);
110 SendTouchGestures();
111 }
112
113 size_t GetAndResetSentGestureCount() {
114 size_t count = sent_gesture_count_;
115 sent_gesture_count_ = 0;
116 return count;
117 }
118
119 const WebGestureEvent& sent_gesture() const {
120 return last_gesture_event_;
121 }
122
123 static WebGestureEvent CreateGesture(WebInputEvent::Type type) {
124 return SyntheticWebGestureEventBuilder::Build(
125 type, WebGestureEvent::Touchscreen);
126 }
127
128 private:
129
130 scoped_ptr<GestureEventQueue> queue_;
131 SyntheticWebTouchEvent touch_event_;
132 GestureEventPacket gesture_packet_;
133 size_t sent_gesture_count_;
134 WebTouchEvent last_touch_event_;
135 WebGestureEvent last_gesture_event_;
136 };
137
138 TEST_F(GestureEventQueueTest, SequenceDispositionTransitionsProperly) {
139 InputEventAckState expected_acks[5][5] = {
140 // From INPUT_EVENT_ACK_STATE_UNKNOWN
141 { INPUT_EVENT_ACK_STATE_UNKNOWN,
142 INPUT_EVENT_ACK_STATE_CONSUMED,
143 INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
144 INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
145 INPUT_EVENT_ACK_STATE_IGNORED },
146
147 // From INPUT_EVENT_ACK_STATE_CONSUMED
148 { INPUT_EVENT_ACK_STATE_CONSUMED,
149 INPUT_EVENT_ACK_STATE_CONSUMED,
150 INPUT_EVENT_ACK_STATE_CONSUMED,
151 INPUT_EVENT_ACK_STATE_CONSUMED,
152 INPUT_EVENT_ACK_STATE_CONSUMED },
153
154 // From INPUT_EVENT_ACK_STATE_NOT_CONSUMED
155 { INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
156 INPUT_EVENT_ACK_STATE_CONSUMED,
157 INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
158 INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
159 INPUT_EVENT_ACK_STATE_NOT_CONSUMED },
160
161 // From INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS
162 { INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
163 INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
164 INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
165 INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
166 INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS },
167
168 // From INPUT_EVENT_ACK_STATE_IGNORED
169 { INPUT_EVENT_ACK_STATE_IGNORED,
170 INPUT_EVENT_ACK_STATE_IGNORED,
171 INPUT_EVENT_ACK_STATE_IGNORED,
172 INPUT_EVENT_ACK_STATE_IGNORED,
173 INPUT_EVENT_ACK_STATE_IGNORED }
174 };
175
176 for (size_t ack_i = 0; ack_i < arraysize(expected_acks); ++ack_i) {
177 for (size_t ack_j = 0; ack_j < arraysize(expected_acks[ack_i]); ++ack_j) {
178 InputEventAckState ack_old = static_cast<InputEventAckState>(ack_i);
179 InputEventAckState ack_new = static_cast<InputEventAckState>(ack_j);
180 EXPECT_EQ(expected_acks[ack_i][ack_j],
181 GestureEventQueue::GetMostRestrictiveState(ack_old, ack_new));
182 }
183 }
184 }
185
186 TEST_F(GestureEventQueueTest, BasicNoGestures) {
187 PressTouchPoint(1, 1);
188 EXPECT_EQ(0U, GetAndResetSentGestureCount());
189
190 MoveTouchPoint(0, 2, 2);
191 EXPECT_EQ(0U, GetAndResetSentGestureCount());
192
193 // No gestures should be dispatched by the ack, as the queued packets
194 // contained no gestures.
195 SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
196 EXPECT_EQ(0U, GetAndResetSentGestureCount());
197
198 // Release the touch gesture.
199 ReleaseTouchPoint(0);
200 SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
201 SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
202 EXPECT_EQ(0U, GetAndResetSentGestureCount());
203 }
204
205 TEST_F(GestureEventQueueTest, BasicGestures) {
206 // An unconsumed touch's gesture should be sent.
207 PushGesture(WebInputEvent::GestureScrollBegin);
208 PressTouchPoint(1, 1);
209 EXPECT_EQ(0U, GetAndResetSentGestureCount());
210 SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
211 EXPECT_EQ(1U, GetAndResetSentGestureCount());
212 EXPECT_EQ(WebInputEvent::GestureScrollBegin, sent_gesture().type);
213
214 // Multiple gestures can be queued for a single event.
215 PushGesture(WebInputEvent::GestureFlingStart);
216 PushGesture(WebInputEvent::GestureFlingCancel);
217 MoveTouchPoint(0, 1, 1);
218 EXPECT_EQ(0U, GetAndResetSentGestureCount());
219 SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
220 EXPECT_EQ(2U, GetAndResetSentGestureCount());
221 EXPECT_EQ(WebInputEvent::GestureFlingCancel, sent_gesture().type);
222
223 // A consumed touch's gesture should not be sent.
224 PushGesture(WebInputEvent::GestureFlingStart);
225 PushGesture(WebInputEvent::GestureFlingCancel);
226 ReleaseTouchPoint(0);
227 EXPECT_EQ(0U, GetAndResetSentGestureCount());
228 SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
229 EXPECT_EQ(0U, GetAndResetSentGestureCount());
230 }
231
232 TEST_F(GestureEventQueueTest, ConsumedThenNotConsumed) {
233 // A consumed touch's gesture should not be sent.
234 PushGesture(WebInputEvent::GestureScrollBegin);
235 PressTouchPoint(1, 1);
236 SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
237 EXPECT_EQ(0U, GetAndResetSentGestureCount());
238
239 // Event if the subsequent touch is not consumed, continue dropping gestures.
240 PushGesture(WebInputEvent::GestureScrollUpdate);
241 MoveTouchPoint(0, 2, 2);
242 SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
243 EXPECT_EQ(0U, GetAndResetSentGestureCount());
244
245 // Event if the subsequent touch had no consumer, continue dropping gestures.
246 PushGesture(WebInputEvent::GestureFlingStart);
247 ReleaseTouchPoint(0);
248 SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
249 EXPECT_EQ(0U, GetAndResetSentGestureCount());
250 }
251
252 TEST_F(GestureEventQueueTest, NotConsumedThenNoConsumer) {
253 // An unconsumed touch's gesture should be sent.
254 PushGesture(WebInputEvent::GestureScrollBegin);
255 PressTouchPoint(1, 1);
256 SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
257 EXPECT_EQ(1U, GetAndResetSentGestureCount());
258
259 // If the subsequent touch has no consumer (e.g., a secondary pointer is
260 // pressed but not on a touch handling rect), send the gesture.
261 PushGesture(WebInputEvent::GesturePinchBegin);
262 PressTouchPoint(2, 2);
263 SendTouchEventACK(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
264 EXPECT_EQ(1U, GetAndResetSentGestureCount());
265
266 // If the subsequent touch is consumed, then the remaining gesture sequence
267 // should be dropped, regardless of subsequent touch ack disposition.
268 PushGesture(WebInputEvent::GestureScrollUpdate);
269 PushGesture(WebInputEvent::GesturePinchUpdate);
270 MoveTouchPoint(0, 2, 2);
271 SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
272 EXPECT_EQ(0U, GetAndResetSentGestureCount());
273
274 PushGesture(WebInputEvent::GesturePinchEnd);
275 ReleaseTouchPoint(1);
276 SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
277 EXPECT_EQ(0U, GetAndResetSentGestureCount());
278
279 PushGesture(WebInputEvent::GestureScrollEnd);
280 ReleaseTouchPoint(0);
281 SendTouchEventACK(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
282 EXPECT_EQ(0U, GetAndResetSentGestureCount());
283 }
284
285 TEST_F(GestureEventQueueTest, MultipleTouchSequences) {
286 // Queue two touch-to-gestures sequences.
287 PushGesture(WebInputEvent::GestureFlingStart);
288 PressTouchPoint(1, 1);
289 PushGesture(WebInputEvent::GestureFlingCancel);
290 ReleaseTouchPoint(0);
291 PushGesture(WebInputEvent::GestureFlingStart);
292 PressTouchPoint(1, 1);
293 PushGesture(WebInputEvent::GestureFlingCancel);
294 ReleaseTouchPoint(0);
295
296 // The first gesture sequence should not be allowed.
297 SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
298 SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
299 EXPECT_EQ(0U, GetAndResetSentGestureCount());
300
301 // The subsequent sequence should "reset" allowance.
302 SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
303 SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
304 EXPECT_EQ(2U, GetAndResetSentGestureCount());
305 }
306
307 TEST_F(GestureEventQueueTest, FlingCancelledOnNewTouchSequence) {
308 // Simulate a fling start that is sent.
309 PressTouchPoint(1, 1);
310 SendTouchEventACK(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
311 PushGesture(WebInputEvent::GestureFlingStart);
312 ReleaseTouchPoint(0);
313 SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
314 EXPECT_EQ(1U, GetAndResetSentGestureCount());
315 EXPECT_EQ(WebInputEvent::GestureFlingStart, sent_gesture().type);
316
317 // A new touch seqeuence should cancel the outstanding fling.
318 PressTouchPoint(1, 1);
319 ReleaseTouchPoint(0);
320 SendTouchEventACK(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
321 EXPECT_EQ(1U, GetAndResetSentGestureCount());
322 EXPECT_EQ(WebInputEvent::GestureFlingCancel, sent_gesture().type);
323 }
324
325 TEST_F(GestureEventQueueTest, FlingNotCancelledIfGFCEventReceived) {
326 // Simulate a fling that is started then cancelled.
327 PushGesture(WebInputEvent::GestureFlingStart);
328 PressTouchPoint(1, 1);
329 SendTouchEventACK(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
330 PushGesture(WebInputEvent::GestureFlingCancel);
331 ReleaseTouchPoint(0);
332 SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
333 EXPECT_EQ(2U, GetAndResetSentGestureCount());
334 EXPECT_EQ(WebInputEvent::GestureFlingCancel, sent_gesture().type);
335
336 // A new touch sequence will not inject a GestureFlingCancel, as the fling
337 // has already been cancelled.
338 PressTouchPoint(1, 1);
339 ReleaseTouchPoint(0);
340 SendTouchEventACK(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
341 EXPECT_EQ(0U, GetAndResetSentGestureCount());
342 }
343
344 TEST_F(GestureEventQueueTest, TapCancelledWhenScrollBegins) {
345 PushGesture(WebInputEvent::GestureTapDown);
346 PressTouchPoint(1, 1);
347 SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
348 EXPECT_EQ(1U, GetAndResetSentGestureCount());
349 EXPECT_EQ(WebInputEvent::GestureTapDown, sent_gesture().type);
350
351 // If the subsequent touch turns into a scroll, the tap should be cancelled.
352 PushGesture(WebInputEvent::GestureScrollBegin);
353 MoveTouchPoint(0, 2, 2);
354 SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
355 EXPECT_EQ(2U, GetAndResetSentGestureCount());
356 EXPECT_EQ(WebInputEvent::GestureScrollBegin, sent_gesture().type);
357 }
358
359 TEST_F(GestureEventQueueTest, TapCancelledWhenTouchConsumed) {
360 PushGesture(WebInputEvent::GestureTapDown);
361 PressTouchPoint(1, 1);
362 SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
363 EXPECT_EQ(1U, GetAndResetSentGestureCount());
364 EXPECT_EQ(WebInputEvent::GestureTapDown, sent_gesture().type);
365
366 // If the subsequent touch is consumed, the tap should be cancelled.
367 PushGesture(WebInputEvent::GestureScrollBegin);
368 MoveTouchPoint(0, 2, 2);
369 SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
370 EXPECT_EQ(1U, GetAndResetSentGestureCount());
371 EXPECT_EQ(WebInputEvent::GestureTapCancel, sent_gesture().type);
372 }
373
374 TEST_F(GestureEventQueueTest, TapNotCancelledIfTapEndingEventReceived) {
375 PushGesture(WebInputEvent::GestureTapDown);
376 PressTouchPoint(1, 1);
377 PressTouchPoint(2, 2);
378 SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
379 SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
380 EXPECT_EQ(1U, GetAndResetSentGestureCount());
381 EXPECT_EQ(WebInputEvent::GestureTapDown, sent_gesture().type);
382
383 PushGesture(WebInputEvent::GestureTap);
384 ReleaseTouchPoint(1);
385 SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
386 EXPECT_EQ(1U, GetAndResetSentGestureCount());
387 EXPECT_EQ(WebInputEvent::GestureTap, sent_gesture().type);
388
389 // The tap should not be cancelled as it was terminated by a |GestureTap|.
390 ReleaseTouchPoint(0);
391 SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
392 EXPECT_EQ(0U, GetAndResetSentGestureCount());
393 }
394
395 TEST_F(GestureEventQueueTest, TimeoutGestures) {
396 // If the sequence is allowed, and there are no preceding gestures, the
397 // timeout gestures should be forwarded immediately.
398 PressTouchPoint(1, 1);
399 SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
400 EXPECT_EQ(0U, GetAndResetSentGestureCount());
401
402 SendTimeoutGesture(CreateGesture(WebInputEvent::GestureShowPress));
403 EXPECT_EQ(1U, GetAndResetSentGestureCount());
404 EXPECT_EQ(WebInputEvent::GestureShowPress, sent_gesture().type);
405 SendTimeoutGesture(CreateGesture(WebInputEvent::GestureLongPress));
406 EXPECT_EQ(1U, GetAndResetSentGestureCount());
407 EXPECT_EQ(WebInputEvent::GestureLongPress, sent_gesture().type);
408 ReleaseTouchPoint(0);
409 SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
410
411 // If the sequence is disallowed, and there are no preceding gestures, the
412 // timeout gestures should be dropped immediately.
413 PressTouchPoint(1, 1);
414 SendTouchEventACK(INPUT_EVENT_ACK_STATE_CONSUMED);
415 EXPECT_EQ(0U, GetAndResetSentGestureCount());
416
417 SendTimeoutGesture(CreateGesture(WebInputEvent::GestureShowPress));
418 EXPECT_EQ(0U, GetAndResetSentGestureCount());
419 ReleaseTouchPoint(0);
420 SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
421
422 // If the sequence has a pending ack, the timeout gestures should
423 // remain queued until the ack is received.
424 PressTouchPoint(1, 1);
425 EXPECT_EQ(0U, GetAndResetSentGestureCount());
426
427 SendTimeoutGesture(CreateGesture(WebInputEvent::GestureLongPress));
428 EXPECT_EQ(0U, GetAndResetSentGestureCount());
429
430 SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
431 EXPECT_EQ(1U, GetAndResetSentGestureCount());
432 EXPECT_EQ(WebInputEvent::GestureLongPress, sent_gesture().type);
433 }
434
435 TEST_F(GestureEventQueueTest, SyntheticGestures) {
436 // Synthetic gestures without an associated touch event should be
437 // forwarded immediately if there are no preceding gestures.
438 SendSyntheticGesture(CreateGesture(WebInputEvent::GesturePinchBegin));
439 SendSyntheticGesture(CreateGesture(WebInputEvent::GesturePinchUpdate));
440 SendSyntheticGesture(CreateGesture(WebInputEvent::GesturePinchEnd));
441 EXPECT_EQ(3U, GetAndResetSentGestureCount());
442 EXPECT_EQ(WebInputEvent::GesturePinchEnd, sent_gesture().type);
443
444 // Queue a blocking touch gesture.
445 PushGesture(WebInputEvent::GestureFlingStart);
446 PressTouchPoint(1, 1);
447 ASSERT_EQ(0U, GetAndResetSentGestureCount());
448
449 // Subsequent synthetic events should only be forwarded after the
450 // touch-derived gesture has been dispatched.
451 SendSyntheticGesture(CreateGesture(WebInputEvent::GesturePinchBegin));
452 SendSyntheticGesture(CreateGesture(WebInputEvent::GesturePinchUpdate));
453 SendSyntheticGesture(CreateGesture(WebInputEvent::GesturePinchEnd));
454 EXPECT_EQ(0U, GetAndResetSentGestureCount());
455
456 // Dispatching the queued gesture should unblock the synthetic gestures.
457 SendTouchEventACK(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
458 EXPECT_EQ(4U, GetAndResetSentGestureCount());
459 EXPECT_EQ(WebInputEvent::GesturePinchEnd, sent_gesture().type);
460 }
461
462 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698