on fcccc72 help sign in
unity8/tests/libs/UbuntuGestures/tst_TouchRegistry.cpp
803 lines 31 kB history raw
1/*
2 * Copyright (C) 2014 Canonical, Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
17#include <QtTest>
18#include <QSet>
19#include <QTouchEvent>
21#include <Timer.h>
22#include <TouchOwnershipEvent.h>
23#include <TouchRegistry.h>
24#include <UnownedTouchEvent.h>
26using namespace UbuntuGestures;
28class TouchMemento {
29public:
30 TouchMemento(const QTouchEvent *touchEvent);
31 Qt::TouchPointStates touchPointStates;
32 QList<QTouchEvent::TouchPoint> touchPoints;
34 bool containsTouchWithId(int touchId) const;
35};
37class DummyCandidate : public QQuickItem
39 Q_OBJECT
40public:
41 bool event(QEvent *e) override;
42 QSet<int> ownedTouches;
43 QSet<int> lostTouches;
44 QList<TouchMemento> unownedTouchEvents;
45};
47class tst_TouchRegistry : public QObject
49 Q_OBJECT
50public:
51 tst_TouchRegistry() : QObject(0) { }
52private Q_SLOTS:
53 void initTestCase() {} // will be called before the first test function is executed
54 void cleanupTestCase() {} // will be called after the last test function was executed.
56 void init() {} // called right before each and every test function is executed
57 void cleanup() {} // called right after each and every test function is executed
59 void requestWithNoCandidates();
60 void lateCandidateRequestGetsNothing();
61 void lateCandidateGestOwnershipOnceEarlyCandidateQuits();
62 void dispatchesTouchEventsToCandidates();
63 void dispatchesTouchEventsToWatchers();
64 void keepDispatchingToWatchersAfterLastCandidateGivesUp();
65 void candidatesAndWatchers_1();
66 void candidatesAndWatchers_2();
67 void rejectingTouchfterItsEnd();
68 void removeOldUndecidedCandidates();
69};
71void tst_TouchRegistry::requestWithNoCandidates()
73 TouchRegistry touchRegistry;
74 DummyCandidate candidate;
76 {
77 QList<QTouchEvent::TouchPoint> touchPoints;
78 touchPoints.append(QTouchEvent::TouchPoint(0));
79 touchPoints[0].setState(Qt::TouchPointPressed);
80 QTouchEvent touchEvent(QEvent::TouchBegin,
81 0 /* device */,
82 Qt::NoModifier,
83 Qt::TouchPointPressed,
84 touchPoints);
85 touchRegistry.update(&touchEvent);
86 }
88 touchRegistry.requestTouchOwnership(0, &candidate);
90 QVERIFY(candidate.ownedTouches.contains(0));
93void tst_TouchRegistry::lateCandidateRequestGetsNothing()
95 TouchRegistry touchRegistry;
96 DummyCandidate earlyCandidate;
97 earlyCandidate.setObjectName("early");
98 DummyCandidate lateCandidate;
99 lateCandidate.setObjectName("late");
101 {
102 QList<QTouchEvent::TouchPoint> touchPoints;
103 touchPoints.append(QTouchEvent::TouchPoint(0));
104 touchPoints[0].setState(Qt::TouchPointPressed);
105 QTouchEvent touchEvent(QEvent::TouchBegin,
106 0 /* device */,
107 Qt::NoModifier,
108 Qt::TouchPointPressed,
109 touchPoints);
110 touchRegistry.update(&touchEvent);
111 }
113 touchRegistry.addCandidateOwnerForTouch(0, &earlyCandidate);
114 touchRegistry.addCandidateOwnerForTouch(0, &lateCandidate);
116 QVERIFY(earlyCandidate.ownedTouches.isEmpty());
117 QVERIFY(lateCandidate.ownedTouches.isEmpty());
119 touchRegistry.requestTouchOwnership(0, &lateCandidate);
121 QVERIFY(earlyCandidate.ownedTouches.isEmpty());
122 QVERIFY(lateCandidate.ownedTouches.isEmpty());
124 touchRegistry.requestTouchOwnership(0, &earlyCandidate);
126 QVERIFY(earlyCandidate.ownedTouches.contains(0));
127 QVERIFY(lateCandidate.ownedTouches.isEmpty());
130void tst_TouchRegistry::lateCandidateGestOwnershipOnceEarlyCandidateQuits()
132 TouchRegistry touchRegistry;
133 DummyCandidate earlyCandidate;
134 DummyCandidate lateCandidate;
136 {
137 QList<QTouchEvent::TouchPoint> touchPoints;
138 touchPoints.append(QTouchEvent::TouchPoint(0));
139 touchPoints[0].setState(Qt::TouchPointPressed);
140 QTouchEvent touchEvent(QEvent::TouchBegin,
141 0 /* device */,
142 Qt::NoModifier,
143 Qt::TouchPointPressed,
144 touchPoints);
145 touchRegistry.update(&touchEvent);
146 }
148 touchRegistry.addCandidateOwnerForTouch(0, &earlyCandidate);
149 touchRegistry.addCandidateOwnerForTouch(0, &lateCandidate);
151 QVERIFY(earlyCandidate.ownedTouches.isEmpty());
152 QVERIFY(lateCandidate.ownedTouches.isEmpty());
154 touchRegistry.requestTouchOwnership(0, &lateCandidate);
156 QVERIFY(earlyCandidate.ownedTouches.isEmpty());
157 QVERIFY(lateCandidate.ownedTouches.isEmpty());
159 touchRegistry.removeCandidateOwnerForTouch(0, &earlyCandidate);
161 QVERIFY(earlyCandidate.ownedTouches.isEmpty());
162 QVERIFY(lateCandidate.ownedTouches.contains(0));
165void tst_TouchRegistry::dispatchesTouchEventsToCandidates()
167 TouchRegistry touchRegistry;
168 QQuickItem rootItem;
170 DummyCandidate candidate0;
171 candidate0.setObjectName("0");
172 candidate0.setParentItem(&rootItem);
173 candidate0.setX(1);
174 candidate0.setY(2);
176 DummyCandidate candidate1;
177 candidate1.setObjectName("1");
178 candidate0.setParentItem(&rootItem);
179 candidate1.setX(3);
180 candidate1.setY(4);
182 {
183 QList<QTouchEvent::TouchPoint> touchPoints;
184 touchPoints.append(QTouchEvent::TouchPoint(0));
185 touchPoints[0].setState(Qt::TouchPointPressed);
186 touchPoints[0].setRect(QRect(10, 10, 0, 0));
187 QTouchEvent touchEvent(QEvent::TouchBegin,
188 0 /* device */,
189 Qt::NoModifier,
190 Qt::TouchPointPressed,
191 touchPoints);
192 touchRegistry.update(&touchEvent);
193 }
195 touchRegistry.addCandidateOwnerForTouch(0, &candidate0);
197 {
198 QList<QTouchEvent::TouchPoint> touchPoints;
199 touchPoints.append(QTouchEvent::TouchPoint(0));
200 touchPoints[0].setState(Qt::TouchPointMoved);
201 touchPoints[0].setRect(QRect(11, 11, 0, 0));
202 touchPoints.append(QTouchEvent::TouchPoint(1));
203 touchPoints[1].setState(Qt::TouchPointPressed);
204 touchPoints[1].setRect(QRect(20, 20, 0, 0));
205 QTouchEvent touchEvent(QEvent::TouchUpdate,
206 0 /* device */,
207 Qt::NoModifier,
208 Qt::TouchPointPressed | Qt::TouchPointMoved,
209 touchPoints);
210 touchRegistry.update(&touchEvent);
211 }
213 // candidate0 should have received an update on the touch he's interested on.
214 QCOMPARE(candidate0.unownedTouchEvents.count(), 1);
215 // make sure only touch 0 is there (i.e. no mention of touch 1)
216 QCOMPARE(candidate0.unownedTouchEvents[0].touchPoints.count(), 1);
217 QCOMPARE(candidate0.unownedTouchEvents[0].touchPoints[0].id(), 0);
218 // Check that the points local coordinates have been mapped to candidate0's coordinate system.
219 QCOMPARE(candidate0.unownedTouchEvents[0].touchPoints[0].rect().x(), 11 - candidate0.x());
220 QCOMPARE(candidate0.unownedTouchEvents[0].touchPoints[0].rect().y(), 11 - candidate0.y());
222 touchRegistry.addCandidateOwnerForTouch(1, &candidate1);
224 {
225 QList<QTouchEvent::TouchPoint> touchPoints;
226 touchPoints.append(QTouchEvent::TouchPoint(0));
227 touchPoints[0].setState(Qt::TouchPointMoved);
228 touchPoints[0].setRect(QRect(12, 12, 0, 0));
229 touchPoints.append(QTouchEvent::TouchPoint(1));
230 touchPoints[1].setState(Qt::TouchPointMoved);
231 touchPoints[1].setRect(QRect(21, 21, 0, 0));
232 QTouchEvent touchEvent(QEvent::TouchUpdate,
233 0 /* device */,
234 Qt::NoModifier,
235 Qt::TouchPointPressed | Qt::TouchPointMoved,
236 touchPoints);
237 touchRegistry.update(&touchEvent);
238 }
240 // candidate0 gets updates only for touch 0 and
241 // candidate1 gets updates only for touch 1
243 QCOMPARE(candidate0.unownedTouchEvents.count(), 2);
244 QCOMPARE(candidate0.unownedTouchEvents[1].touchPoints.count(), 1);
245 QCOMPARE(candidate0.unownedTouchEvents[1].touchPoints[0].id(), 0);
247 QCOMPARE(candidate1.unownedTouchEvents.count(), 1);
248 QCOMPARE(candidate1.unownedTouchEvents[0].touchPoints.count(), 1);
249 QCOMPARE(candidate1.unownedTouchEvents[0].touchPoints[0].id(), 1);
252void tst_TouchRegistry::dispatchesTouchEventsToWatchers()
254 TouchRegistry touchRegistry;
255 QQuickItem rootItem;
257 DummyCandidate watcher;
258 watcher.setObjectName("watcher");
259 watcher.setParentItem(&rootItem);
260 watcher.setX(1);
261 watcher.setY(2);
263 {
264 QList<QTouchEvent::TouchPoint> touchPoints;
265 touchPoints.append(QTouchEvent::TouchPoint(0));
266 touchPoints[0].setState(Qt::TouchPointPressed);
267 touchPoints[0].setRect(QRect(10, 10, 0, 0));
268 QTouchEvent touchEvent(QEvent::TouchBegin,
269 0 /* device */,
270 Qt::NoModifier,
271 Qt::TouchPointPressed,
272 touchPoints);
273 touchRegistry.update(&touchEvent);
274 }
276 touchRegistry.addTouchWatcher(0, &watcher);
278 {
279 QList<QTouchEvent::TouchPoint> touchPoints;
280 touchPoints.append(QTouchEvent::TouchPoint(0));
281 touchPoints[0].setState(Qt::TouchPointMoved);
282 touchPoints[0].setRect(QRect(11, 11, 0, 0));
283 touchPoints.append(QTouchEvent::TouchPoint(1));
284 touchPoints[1].setState(Qt::TouchPointPressed);
285 touchPoints[1].setRect(QRect(20, 20, 0, 0));
286 QTouchEvent touchEvent(QEvent::TouchUpdate,
287 0 /* device */,
288 Qt::NoModifier,
289 Qt::TouchPointPressed | Qt::TouchPointMoved,
290 touchPoints);
291 touchRegistry.update(&touchEvent);
292 }
294 // watcher should have received an update on the touch he's interested on.
295 QCOMPARE(watcher.unownedTouchEvents.count(), 1);
296 // make sure only touch 0 is there (i.e. no mention of touch 1)
297 QCOMPARE(watcher.unownedTouchEvents[0].touchPoints.count(), 1);
298 QCOMPARE(watcher.unownedTouchEvents[0].touchPoints[0].id(), 0);
299 // Check that the points local coordinates have been mapped to watcher's coordinate system.
300 QCOMPARE(watcher.unownedTouchEvents[0].touchPoints[0].rect().x(), 11 - watcher.x());
301 QCOMPARE(watcher.unownedTouchEvents[0].touchPoints[0].rect().y(), 11 - watcher.y());
303 {
304 QList<QTouchEvent::TouchPoint> touchPoints;
305 touchPoints.append(QTouchEvent::TouchPoint(0));
306 touchPoints[0].setState(Qt::TouchPointMoved);
307 touchPoints[0].setRect(QRect(12, 12, 0, 0));
308 touchPoints.append(QTouchEvent::TouchPoint(1));
309 touchPoints[1].setState(Qt::TouchPointMoved);
310 touchPoints[1].setRect(QRect(21, 21, 0, 0));
311 QTouchEvent touchEvent(QEvent::TouchUpdate,
312 0 /* device */,
313 Qt::NoModifier,
314 Qt::TouchPointPressed | Qt::TouchPointMoved,
315 touchPoints);
316 touchRegistry.update(&touchEvent);
317 }
319 // watcher gets updates only for touch 0
321 QCOMPARE(watcher.unownedTouchEvents.count(), 2);
322 QCOMPARE(watcher.unownedTouchEvents[1].touchPoints.count(), 1);
323 QCOMPARE(watcher.unownedTouchEvents[1].touchPoints[0].id(), 0);
326void tst_TouchRegistry::keepDispatchingToWatchersAfterLastCandidateGivesUp()
328 TouchRegistry touchRegistry;
329 DummyCandidate item;
331 {
332 QList<QTouchEvent::TouchPoint> touchPoints;
333 touchPoints.append(QTouchEvent::TouchPoint(0));
334 touchPoints[0].setState(Qt::TouchPointPressed);
335 QTouchEvent touchEvent(QEvent::TouchBegin,
336 0 /* device */,
337 Qt::NoModifier,
338 Qt::TouchPointPressed,
339 touchPoints);
340 touchRegistry.update(&touchEvent);
341 }
343 touchRegistry.addCandidateOwnerForTouch(0, &item);
345 {
346 QList<QTouchEvent::TouchPoint> touchPoints;
347 touchPoints.append(QTouchEvent::TouchPoint(0));
348 touchPoints[0].setState(Qt::TouchPointMoved);
349 touchPoints.append(QTouchEvent::TouchPoint(1));
350 touchPoints[1].setState(Qt::TouchPointPressed);
351 QTouchEvent touchEvent(QEvent::TouchUpdate,
352 0 /* device */,
353 Qt::NoModifier,
354 Qt::TouchPointPressed | Qt::TouchPointMoved,
355 touchPoints);
356 touchRegistry.update(&touchEvent);
357 }
359 QCOMPARE(item.unownedTouchEvents.count(), 1);
360 QCOMPARE(item.unownedTouchEvents[0].touchPoints.count(), 1);
361 QCOMPARE(item.unownedTouchEvents[0].touchPoints[0].id(), 0);
362 item.unownedTouchEvents.clear();
364 touchRegistry.addTouchWatcher(1, &item);
366 {
367 QList<QTouchEvent::TouchPoint> touchPoints;
368 touchPoints.append(QTouchEvent::TouchPoint(0));
369 touchPoints[0].setState(Qt::TouchPointMoved);
370 touchPoints.append(QTouchEvent::TouchPoint(1));
371 touchPoints[1].setState(Qt::TouchPointMoved);
372 QTouchEvent touchEvent(QEvent::TouchUpdate,
373 0 /* device */,
374 Qt::NoModifier,
375 Qt::TouchPointMoved,
376 touchPoints);
377 touchRegistry.update(&touchEvent);
378 }
380 QCOMPARE(item.unownedTouchEvents.count(), 1);
381 QCOMPARE(item.unownedTouchEvents[0].touchPoints.count(), 2);
382 QVERIFY(item.unownedTouchEvents[0].containsTouchWithId(0));
383 QVERIFY(item.unownedTouchEvents[0].containsTouchWithId(1));
384 item.unownedTouchEvents.clear();
386 {
387 QList<QTouchEvent::TouchPoint> touchPoints;
388 touchPoints.append(QTouchEvent::TouchPoint(0));
389 touchPoints[0].setState(Qt::TouchPointReleased);
390 touchPoints.append(QTouchEvent::TouchPoint(1));
391 touchPoints[1].setState(Qt::TouchPointMoved);
392 QTouchEvent touchEvent(QEvent::TouchUpdate,
393 0 /* device */,
394 Qt::NoModifier,
395 Qt::TouchPointReleased | Qt::TouchPointMoved,
396 touchPoints);
397 touchRegistry.update(&touchEvent);
398 }
400 QCOMPARE(item.unownedTouchEvents.count(), 1);
401 QCOMPARE(item.unownedTouchEvents[0].touchPoints.count(), 2);
402 QVERIFY(item.unownedTouchEvents[0].containsTouchWithId(0));
403 QVERIFY(item.unownedTouchEvents[0].containsTouchWithId(1));
404 item.unownedTouchEvents.clear();
406 touchRegistry.removeCandidateOwnerForTouch(0, &item);
408 {
409 QList<QTouchEvent::TouchPoint> touchPoints;
410 touchPoints.append(QTouchEvent::TouchPoint(1));
411 touchPoints[0].setState(Qt::TouchPointReleased);
412 QTouchEvent touchEvent(QEvent::TouchEnd,
413 0 /* device */,
414 Qt::NoModifier,
415 Qt::TouchPointReleased,
416 touchPoints);
417 touchRegistry.update(&touchEvent);
418 }
420 QCOMPARE(item.unownedTouchEvents.count(), 1);
421 QCOMPARE(item.unownedTouchEvents[0].touchPoints.count(), 1);
422 QVERIFY(item.unownedTouchEvents[0].containsTouchWithId(1));
423 item.unownedTouchEvents.clear();
425 QVERIFY(touchRegistry.m_touchInfoPool.isEmpty());
428/*
429 Regression test that reproduces a problematic scenario that came up during manual testing.
430 It reproduces the interaction between TouchRegistry and a DirectionalDragArea
431 */
432void tst_TouchRegistry::candidatesAndWatchers_1()
434 TouchRegistry touchRegistry;
435 DummyCandidate item;
437 {
438 QList<QTouchEvent::TouchPoint> touchPoints;
439 touchPoints.append(QTouchEvent::TouchPoint(0));
440 touchPoints[0].setState(Qt::TouchPointPressed);
441 QTouchEvent touchEvent(QEvent::TouchBegin,
442 0 /* device */,
443 Qt::NoModifier,
444 Qt::TouchPointPressed,
445 touchPoints);
446 touchRegistry.update(&touchEvent);
447 }
449 touchRegistry.addCandidateOwnerForTouch(0, &item);
451 {
452 QList<QTouchEvent::TouchPoint> touchPoints;
453 touchPoints.append(QTouchEvent::TouchPoint(0));
454 touchPoints[0].setState(Qt::TouchPointMoved);
455 touchPoints.append(QTouchEvent::TouchPoint(1));
456 touchPoints[1].setState(Qt::TouchPointPressed);
457 QTouchEvent touchEvent(QEvent::TouchUpdate,
458 0 /* device */,
459 Qt::NoModifier,
460 Qt::TouchPointPressed | Qt::TouchPointMoved,
461 touchPoints);
462 touchRegistry.update(&touchEvent);
463 }
465 touchRegistry.addTouchWatcher(1, &item);
467 touchRegistry.removeCandidateOwnerForTouch(0, &item);
469 touchRegistry.addTouchWatcher(0, &item);
471 {
472 QList<QTouchEvent::TouchPoint> touchPoints;
473 touchPoints.append(QTouchEvent::TouchPoint(0));
474 touchPoints[0].setState(Qt::TouchPointReleased);
475 touchPoints.append(QTouchEvent::TouchPoint(1));
476 touchPoints[1].setState(Qt::TouchPointMoved);
477 QTouchEvent touchEvent(QEvent::TouchUpdate,
478 0 /* device */,
479 Qt::NoModifier,
480 Qt::TouchPointReleased | Qt::TouchPointMoved,
481 touchPoints);
482 touchRegistry.update(&touchEvent);
483 }
485 {
486 QList<QTouchEvent::TouchPoint> touchPoints;
487 touchPoints.append(QTouchEvent::TouchPoint(1));
488 touchPoints[0].setState(Qt::TouchPointReleased);
489 QTouchEvent touchEvent(QEvent::TouchEnd,
490 0 /* device */,
491 Qt::NoModifier,
492 Qt::TouchPointReleased,
493 touchPoints);
494 touchRegistry.update(&touchEvent);
495 }
497 QVERIFY(touchRegistry.m_touchInfoPool.isEmpty());
499 item.unownedTouchEvents.clear();
501 {
502 QList<QTouchEvent::TouchPoint> touchPoints;
503 touchPoints.append(QTouchEvent::TouchPoint(0));
504 touchPoints[0].setState(Qt::TouchPointPressed);
505 QTouchEvent touchEvent(QEvent::TouchBegin,
506 0 /* device */,
507 Qt::NoModifier,
508 Qt::TouchPointPressed,
509 touchPoints);
510 touchRegistry.update(&touchEvent);
511 }
513 // Haven't made any subscription for that new touch 0.
514 QCOMPARE(item.unownedTouchEvents.count(), 0);
517/*
518 Regression test that reproduces a problematic scenario that came up during manual testing.
519 It reproduces the interaction between TouchRegistry, DirectionalDragArea and a TouchGate.
520 */
521void tst_TouchRegistry::candidatesAndWatchers_2()
523 TouchRegistry touchRegistry;
525 DummyCandidate directionalDragArea;
526 directionalDragArea.setObjectName("DirectionalDragArea");
528 DummyCandidate touchGate;
529 touchGate.setObjectName("TouchGate");
531 // [DDA] 1298 TouchBegin (id:0, state:pressed, scenePos:(147,1023))
532 {
533 QList<QTouchEvent::TouchPoint> touchPoints;
534 touchPoints.append(QTouchEvent::TouchPoint(0));
535 touchPoints[0].setState(Qt::TouchPointPressed);
536 QTouchEvent touchEvent(QEvent::TouchBegin,
537 0 /* device */,
538 Qt::NoModifier,
539 Qt::TouchPointPressed,
540 touchPoints);
541 touchRegistry.update(&touchEvent);
542 }
544 // [TouchRegistry] addCandidateOwnerForTouch id 0 candidate DirectionalDragArea
545 touchRegistry.addCandidateOwnerForTouch(0, &directionalDragArea);
547 // [TouchRegistry] requestTouchOwnership id 0 candidate TouchGate
548 touchRegistry.requestTouchOwnership(0, &touchGate);
550 //[TouchRegistry] got TouchUpdate (id:0, state:moved, scenePos:(147,1023)) (id:1, state:pressed, scenePos:(327,792))
551 {
552 QList<QTouchEvent::TouchPoint> touchPoints;
553 touchPoints.append(QTouchEvent::TouchPoint(0));
554 touchPoints[0].setState(Qt::TouchPointMoved);
555 touchPoints.append(QTouchEvent::TouchPoint(1));
556 touchPoints[1].setState(Qt::TouchPointPressed);
557 QTouchEvent touchEvent(QEvent::TouchUpdate,
558 0 /* device */,
559 Qt::NoModifier,
560 Qt::TouchPointPressed | Qt::TouchPointMoved,
561 touchPoints);
562 touchRegistry.update(&touchEvent);
563 }
565 // [TouchRegistry] addTouchWatcher id 1 watcher DirectionalDragArea
566 touchRegistry.addTouchWatcher(1, &directionalDragArea);
568 // [TouchRegistry] removeCandidateOwnerForTouch id 0 candidate DirectionalDragArea
569 touchRegistry.removeCandidateOwnerForTouch(0, &directionalDragArea);
571 //[TouchRegistry] sending TouchWonershipEvent(id = 0 gained) to candidate TouchGate
572 QCOMPARE(touchGate.ownedTouches.count(), 1);
573 QVERIFY(touchGate.ownedTouches.contains(0));
575 // [TouchRegistry] addTouchWatcher id 0 watcher DirectionalDragArea
576 touchRegistry.addTouchWatcher(0, &directionalDragArea);
578 // [TouchRegistry] requestTouchOwnership id 1 candidate TouchGate
579 touchRegistry.requestTouchOwnership(1, &touchGate);
581 //[TouchRegistry] sending TouchWonershipEvent(id = 1 gained) to candidate TouchGate
582 QCOMPARE(touchGate.ownedTouches.count(), 2);
583 QVERIFY(touchGate.ownedTouches.contains(1));
585 directionalDragArea.unownedTouchEvents.clear();
586 touchGate.unownedTouchEvents.clear();
588 //[TouchRegistry] got TouchUpdate (id:0, state:moved, scenePos:(148,1025)) (id:1, state:moved, scenePos:(329,795))
589 {
590 QList<QTouchEvent::TouchPoint> touchPoints;
591 touchPoints.append(QTouchEvent::TouchPoint(0));
592 touchPoints[0].setState(Qt::TouchPointMoved);
593 touchPoints.append(QTouchEvent::TouchPoint(1));
594 touchPoints[1].setState(Qt::TouchPointMoved);
595 QTouchEvent touchEvent(QEvent::TouchUpdate,
596 0 /* device */,
597 Qt::NoModifier,
598 Qt::TouchPointMoved,
599 touchPoints);
600 touchRegistry.update(&touchEvent);
601 }
603 //vvvvv DDA Watchers are being ignored from now on vvvvvvv
605 QCOMPARE(directionalDragArea.unownedTouchEvents.count(), 1);
606 QCOMPARE(directionalDragArea.unownedTouchEvents.first().touchPoints.count(), 2);
607 QVERIFY(directionalDragArea.unownedTouchEvents.first().containsTouchWithId(0));
608 QVERIFY(directionalDragArea.unownedTouchEvents.first().containsTouchWithId(1));
610 QVERIFY(touchGate.unownedTouchEvents.isEmpty());
612 directionalDragArea.unownedTouchEvents.clear();
614 //[TouchRegistry] got TouchUpdate (id:0, state:moved, scenePos:(151,1029)) (id:1, state:released, scenePos:(329,795))
615 {
616 QList<QTouchEvent::TouchPoint> touchPoints;
617 touchPoints.append(QTouchEvent::TouchPoint(0));
618 touchPoints[0].setState(Qt::TouchPointMoved);
619 touchPoints.append(QTouchEvent::TouchPoint(1));
620 touchPoints[1].setState(Qt::TouchPointReleased);
621 QTouchEvent touchEvent(QEvent::TouchUpdate,
622 0 /* device */,
623 Qt::NoModifier,
624 Qt::TouchPointMoved | Qt::TouchPointReleased,
625 touchPoints);
626 touchRegistry.update(&touchEvent);
627 }
629 QCOMPARE(directionalDragArea.unownedTouchEvents.count(), 1);
630 QCOMPARE(directionalDragArea.unownedTouchEvents.first().touchPoints.count(), 2);
631 QVERIFY(directionalDragArea.unownedTouchEvents.first().containsTouchWithId(0));
632 QVERIFY(directionalDragArea.unownedTouchEvents.first().containsTouchWithId(1));
634 QVERIFY(touchGate.unownedTouchEvents.isEmpty());
636 directionalDragArea.unownedTouchEvents.clear();
638 //[TouchRegistry] got TouchEnd (id:0, state:released, scenePos:(157,1034))
639 {
640 QList<QTouchEvent::TouchPoint> touchPoints;
641 touchPoints.append(QTouchEvent::TouchPoint(0));
642 touchPoints[0].setState(Qt::TouchPointReleased);
643 QTouchEvent touchEvent(QEvent::TouchEnd,
644 0 /* device */,
645 Qt::NoModifier,
646 Qt::TouchPointReleased,
647 touchPoints);
648 touchRegistry.update(&touchEvent);
649 }
651 QCOMPARE(directionalDragArea.unownedTouchEvents.count(), 1);
652 QCOMPARE(directionalDragArea.unownedTouchEvents.first().touchPoints.count(), 1);
653 QVERIFY(directionalDragArea.unownedTouchEvents.first().containsTouchWithId(0));
655 QVERIFY(touchGate.unownedTouchEvents.isEmpty());
658void tst_TouchRegistry::rejectingTouchfterItsEnd()
660 TouchRegistry touchRegistry;
661 DummyCandidate earlyCandidate;
662 DummyCandidate lateCandidate;
664 {
665 QList<QTouchEvent::TouchPoint> touchPoints;
666 touchPoints.append(QTouchEvent::TouchPoint(0));
667 touchPoints[0].setState(Qt::TouchPointPressed);
668 QTouchEvent touchEvent(QEvent::TouchBegin,
669 0 /* device */,
670 Qt::NoModifier,
671 Qt::TouchPointPressed,
672 touchPoints);
673 touchRegistry.update(&touchEvent);
674 }
676 touchRegistry.addCandidateOwnerForTouch(0, &earlyCandidate);
677 touchRegistry.addCandidateOwnerForTouch(0, &lateCandidate);
679 QVERIFY(earlyCandidate.ownedTouches.isEmpty());
680 QVERIFY(lateCandidate.ownedTouches.isEmpty());
682 touchRegistry.requestTouchOwnership(0, &lateCandidate);
684 QVERIFY(earlyCandidate.ownedTouches.isEmpty());
685 QVERIFY(lateCandidate.ownedTouches.isEmpty());
687 {
688 QList<QTouchEvent::TouchPoint> touchPoints;
689 touchPoints.append(QTouchEvent::TouchPoint(0));
690 touchPoints[0].setState(Qt::TouchPointReleased);
691 QTouchEvent touchEvent(QEvent::TouchEnd,
692 0 /* device */,
693 Qt::NoModifier,
694 Qt::TouchPointPressed,
695 touchPoints);
696 touchRegistry.update(&touchEvent);
697 }
699 QVERIFY(earlyCandidate.ownedTouches.isEmpty());
700 QVERIFY(lateCandidate.ownedTouches.isEmpty());
702 touchRegistry.removeCandidateOwnerForTouch(0, &earlyCandidate);
704 QCOMPARE(lateCandidate.ownedTouches.count(), 1);
705 QCOMPARE(lateCandidate.ownedTouches.contains(0), 1);
707 // Check that there's no trace left of touch 0 as we no longer need to keep tabs on it.
708 QVERIFY(!touchRegistry.findTouchInfo(0));
711void tst_TouchRegistry::removeOldUndecidedCandidates()
713 FakeTimerFactory *fakeTimerFactory = new FakeTimerFactory;
714 TouchRegistry *touchRegistry = new TouchRegistry(nullptr, fakeTimerFactory);
716 DummyCandidate undecidedCandidate;
717 undecidedCandidate.setObjectName("undecided");
719 DummyCandidate candidateThatWantsTouch;
720 candidateThatWantsTouch.setObjectName("wantsTouch");
722 {
723 QList<QTouchEvent::TouchPoint> touchPoints;
724 touchPoints.append(QTouchEvent::TouchPoint(0));
725 touchPoints[0].setState(Qt::TouchPointPressed);
726 QTouchEvent touchEvent(QEvent::TouchBegin,
727 0 /* device */,
728 Qt::NoModifier,
729 Qt::TouchPointPressed,
730 touchPoints);
731 touchRegistry->update(&touchEvent);
732 }
734 touchRegistry->addCandidateOwnerForTouch(0, &undecidedCandidate);
736 touchRegistry->requestTouchOwnership(0, &candidateThatWantsTouch);
738 QVERIFY(undecidedCandidate.ownedTouches.isEmpty());
739 QVERIFY(undecidedCandidate.lostTouches.isEmpty());
740 QVERIFY(candidateThatWantsTouch.ownedTouches.isEmpty());
741 QVERIFY(candidateThatWantsTouch.lostTouches.isEmpty());
743 // Simulate that enough time has passed to cause the CandidateInactivityTimer to timeout,
744 // making TouchRegistry consider that undecidedCantidate defaulted.
745 fakeTimerFactory->makeRunningTimersTimeout();
747 QVERIFY(undecidedCandidate.ownedTouches.isEmpty());
748 QVERIFY(undecidedCandidate.lostTouches.contains(0));
749 QVERIFY(candidateThatWantsTouch.ownedTouches.contains(0));
750 QVERIFY(candidateThatWantsTouch.lostTouches.isEmpty());
752 delete touchRegistry;
755////////////// TouchMemento //////////
757TouchMemento::TouchMemento(const QTouchEvent *touchEvent)
758 : touchPointStates(touchEvent->touchPointStates()), touchPoints(touchEvent->touchPoints())
762bool TouchMemento::containsTouchWithId(int touchId) const
764 for (int i = 0; i < touchPoints.count(); ++i) {
765 if (touchPoints.at(i).id() == touchId) {
766 return true;
767 }
768 }
769 return false;
772////////////// DummyCandidate //////////
774bool DummyCandidate::event(QEvent *e)
776 if (e->type() == TouchOwnershipEvent::touchOwnershipEventType()) {
777 TouchOwnershipEvent *touchOwnershipEvent = static_cast<TouchOwnershipEvent *>(e);
779 // NB: Cannot use QVERIFY here because the macro doesn't return a boolean and is
780 // meant for use only directly in the body of a test function
781 if (ownedTouches.contains(touchOwnershipEvent->touchId()))
782 qFatal("Sent ownership event for a touch that is already owned.");
783 if (lostTouches.contains(touchOwnershipEvent->touchId()))
784 qFatal("Sent ownership event for a touch that has already been lost.");
786 if (touchOwnershipEvent->gained()) {
787 ownedTouches.insert(touchOwnershipEvent->touchId());
788 } else {
789 lostTouches.insert(touchOwnershipEvent->touchId());
790 }
791 return true;
792 } else if (e->type() == UnownedTouchEvent::unownedTouchEventType()) {
793 UnownedTouchEvent *unownedTouchEvent = static_cast<UnownedTouchEvent *>(e);
794 unownedTouchEvents.append(TouchMemento(unownedTouchEvent->touchEvent()));
795 return true;
796 } else {
797 return QObject::event(e);
798 }
801QTEST_GUILESS_MAIN(tst_TouchRegistry)
803#include "tst_TouchRegistry.moc"