81881fc70079751a1c87d0796d100cc23b826462
[profile/ivi/qtbase.git] / tests / auto / other / gestures / tst_gestures.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the test suite of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42
43 #include <QtTest/QtTest>
44 #include <QtTest/qtesttouch.h>
45
46 #include <qevent.h>
47 #include <qwidget.h>
48 #include <qlayout.h>
49 #include <qgesture.h>
50 #include <qgesturerecognizer.h>
51 #include <qgraphicsitem.h>
52 #include <qgraphicswidget.h>
53 #include <qgraphicsview.h>
54 #include <qmainwindow.h>
55
56 #include <qdebug.h>
57
58 static QPointF mapToGlobal(const QPointF &pt, QGraphicsItem *item, QGraphicsView *view)
59 {
60     return view->viewport()->mapToGlobal(view->mapFromScene(item->mapToScene(pt)));
61 }
62
63 class CustomGesture : public QGesture
64 {
65     Q_OBJECT
66 public:
67     static Qt::GestureType GestureType;
68
69     CustomGesture(QObject *parent = 0)
70         : QGesture(parent), serial(0)
71     {
72     }
73
74     int serial;
75
76     static const int SerialMaybeThreshold;
77     static const int SerialStartedThreshold;
78     static const int SerialFinishedThreshold;
79 };
80 Qt::GestureType CustomGesture::GestureType = Qt::CustomGesture;
81 const int CustomGesture::SerialMaybeThreshold = 1;
82 const int CustomGesture::SerialStartedThreshold = 3;
83 const int CustomGesture::SerialFinishedThreshold = 6;
84
85 class CustomEvent : public QEvent
86 {
87 public:
88     static int EventType;
89
90     explicit CustomEvent(int serial_ = 0)
91         : QEvent(QEvent::Type(CustomEvent::EventType)),
92           serial(serial_), hasHotSpot(false)
93     {
94     }
95
96     int serial;
97     QPointF hotSpot;
98     bool hasHotSpot;
99 };
100 int CustomEvent::EventType = 0;
101
102 class CustomGestureRecognizer : public QGestureRecognizer
103 {
104 public:
105     static bool ConsumeEvents;
106
107     CustomGestureRecognizer()
108     {
109         if (!CustomEvent::EventType)
110             CustomEvent::EventType = QEvent::registerEventType();
111     }
112
113     QGesture* create(QObject *)
114     {
115         return new CustomGesture;
116     }
117
118     QGestureRecognizer::Result recognize(QGesture *state, QObject*, QEvent *event)
119     {
120         if (event->type() == CustomEvent::EventType) {
121             QGestureRecognizer::Result result = 0;
122             if (CustomGestureRecognizer::ConsumeEvents)
123                 result |= QGestureRecognizer::ConsumeEventHint;
124             CustomGesture *g = static_cast<CustomGesture*>(state);
125             CustomEvent *e = static_cast<CustomEvent*>(event);
126             g->serial = e->serial;
127             if (e->hasHotSpot)
128                 g->setHotSpot(e->hotSpot);
129             if (g->serial >= CustomGesture::SerialFinishedThreshold)
130                 result |= QGestureRecognizer::FinishGesture;
131             else if (g->serial >= CustomGesture::SerialStartedThreshold)
132                 result |= QGestureRecognizer::TriggerGesture;
133             else if (g->serial >= CustomGesture::SerialMaybeThreshold)
134                 result |= QGestureRecognizer::MayBeGesture;
135             else
136                 result = QGestureRecognizer::CancelGesture;
137             return result;
138         }
139         return QGestureRecognizer::Ignore;
140     }
141
142     void reset(QGesture *state)
143     {
144         CustomGesture *g = static_cast<CustomGesture *>(state);
145         g->serial = 0;
146         QGestureRecognizer::reset(state);
147     }
148 };
149 bool CustomGestureRecognizer::ConsumeEvents = false;
150
151 // same as CustomGestureRecognizer but triggers early without the maybe state
152 class CustomContinuousGestureRecognizer : public QGestureRecognizer
153 {
154 public:
155     CustomContinuousGestureRecognizer()
156     {
157         if (!CustomEvent::EventType)
158             CustomEvent::EventType = QEvent::registerEventType();
159     }
160
161     QGesture* create(QObject *)
162     {
163         return new CustomGesture;
164     }
165
166     QGestureRecognizer::Result recognize(QGesture *state, QObject*, QEvent *event)
167     {
168         if (event->type() == CustomEvent::EventType) {
169             QGestureRecognizer::Result result = QGestureRecognizer::ConsumeEventHint;
170             CustomGesture *g = static_cast<CustomGesture *>(state);
171             CustomEvent *e = static_cast<CustomEvent *>(event);
172             g->serial = e->serial;
173             if (e->hasHotSpot)
174                 g->setHotSpot(e->hotSpot);
175             if (g->serial >= CustomGesture::SerialFinishedThreshold)
176                 result |= QGestureRecognizer::FinishGesture;
177             else if (g->serial >= CustomGesture::SerialMaybeThreshold)
178                 result |= QGestureRecognizer::TriggerGesture;
179             else
180                 result = QGestureRecognizer::CancelGesture;
181             return result;
182         }
183         return QGestureRecognizer::Ignore;
184     }
185
186     void reset(QGesture *state)
187     {
188         CustomGesture *g = static_cast<CustomGesture *>(state);
189         g->serial = 0;
190         QGestureRecognizer::reset(state);
191     }
192 };
193
194 class GestureWidget : public QWidget
195 {
196     Q_OBJECT
197 public:
198     GestureWidget(const char *name = 0, QWidget *parent = 0)
199         : QWidget(parent)
200     {
201         if (name)
202             setObjectName(QLatin1String(name));
203         reset();
204         acceptGestureOverride = false;
205     }
206     void reset()
207     {
208         customEventsReceived = 0;
209         gestureEventsReceived = 0;
210         gestureOverrideEventsReceived = 0;
211         events.clear();
212         overrideEvents.clear();
213         ignoredGestures.clear();
214     }
215
216     int customEventsReceived;
217     int gestureEventsReceived;
218     int gestureOverrideEventsReceived;
219     struct Events
220     {
221         QList<Qt::GestureType> all;
222         QList<Qt::GestureType> started;
223         QList<Qt::GestureType> updated;
224         QList<Qt::GestureType> finished;
225         QList<Qt::GestureType> canceled;
226
227         void clear()
228         {
229             all.clear();
230             started.clear();
231             updated.clear();
232             finished.clear();
233             canceled.clear();
234         }
235     } events, overrideEvents;
236
237     bool acceptGestureOverride;
238     QSet<Qt::GestureType> ignoredGestures;
239
240 protected:
241     bool event(QEvent *event)
242     {
243         Events *eventsPtr = 0;
244         if (event->type() == QEvent::Gesture) {
245             QGestureEvent *e = static_cast<QGestureEvent*>(event);
246             ++gestureEventsReceived;
247             eventsPtr = &events;
248             foreach(Qt::GestureType type, ignoredGestures)
249                 e->ignore(e->gesture(type));
250         } else if (event->type() == QEvent::GestureOverride) {
251             ++gestureOverrideEventsReceived;
252             eventsPtr = &overrideEvents;
253             if (acceptGestureOverride)
254                 event->accept();
255         }
256         if (eventsPtr) {
257             QGestureEvent *e = static_cast<QGestureEvent*>(event);
258             QList<QGesture*> gestures = e->gestures();
259             foreach(QGesture *g, gestures) {
260                 eventsPtr->all << g->gestureType();
261                 switch(g->state()) {
262                 case Qt::GestureStarted:
263                     emit gestureStarted(e->type(), g);
264                     eventsPtr->started << g->gestureType();
265                     break;
266                 case Qt::GestureUpdated:
267                     emit gestureUpdated(e->type(), g);
268                     eventsPtr->updated << g->gestureType();
269                     break;
270                 case Qt::GestureFinished:
271                     emit gestureFinished(e->type(), g);
272                     eventsPtr->finished << g->gestureType();
273                     break;
274                 case Qt::GestureCanceled:
275                     emit gestureCanceled(e->type(), g);
276                     eventsPtr->canceled << g->gestureType();
277                     break;
278                 default:
279                     qWarning() << "Unknown GestureState enum value:" << static_cast<int>(g->state());
280                 }
281             }
282         } else if (event->type() == CustomEvent::EventType) {
283             ++customEventsReceived;
284         } else {
285             return QWidget::event(event);
286         }
287         return true;
288     }
289
290 Q_SIGNALS:
291     void gestureStarted(QEvent::Type, QGesture *);
292     void gestureUpdated(QEvent::Type, QGesture *);
293     void gestureFinished(QEvent::Type, QGesture *);
294     void gestureCanceled(QEvent::Type, QGesture *);
295
296 public Q_SLOTS:
297     void deleteThis() { delete this; }
298 };
299
300 // TODO rename to sendGestureSequence
301 static void sendCustomGesture(CustomEvent *event, QObject *object, QGraphicsScene *scene = 0)
302 {
303     QWeakPointer<QObject> receiver(object);
304     for (int i = CustomGesture::SerialMaybeThreshold;
305          i <= CustomGesture::SerialFinishedThreshold && receiver; ++i) {
306         event->serial = i;
307         if (scene)
308             scene->sendEvent(qobject_cast<QGraphicsObject *>(object), event);
309         else
310             QApplication::sendEvent(object, event);
311     }
312 }
313
314 class tst_Gestures : public QObject
315 {
316 Q_OBJECT
317
318 public:
319     tst_Gestures();
320     virtual ~tst_Gestures();
321
322 public slots:
323     void initTestCase();
324     void cleanupTestCase();
325     void init();
326     void cleanup();
327
328 private slots:
329     void customGesture();
330     void autoCancelingGestures();
331     void gestureOverChild();
332     void multipleWidgetOnlyGestureInTree();
333     void conflictingGestures();
334     void conflictingGesturesInGraphicsView();
335     void finishedWithoutStarted();
336     void unknownGesture();
337     void graphicsItemGesture();
338     void graphicsView();
339     void graphicsItemTreeGesture();
340     void explicitGraphicsObjectTarget();
341     void gestureOverChildGraphicsItem();
342     void twoGesturesOnDifferentLevel();
343     void multipleGesturesInTree();
344     void multipleGesturesInComplexTree();
345     void testMapToScene();
346     void ungrabGesture();
347     void consumeEventHint();
348     void unregisterRecognizer();
349     void autoCancelGestures();
350     void autoCancelGestures2();
351     void graphicsViewParentPropagation();
352     void panelPropagation();
353     void panelStacksBehindParent();
354     void deleteGestureTargetWidget();
355     void deleteGestureTargetItem_data();
356     void deleteGestureTargetItem();
357     void viewportCoordinates();
358     void partialGesturePropagation();
359     void testQGestureRecognizerCleanup();
360     void testReuseCanceledGestures();
361     void bug_13501_gesture_not_accepted();
362 };
363
364 tst_Gestures::tst_Gestures()
365 {
366 }
367
368 tst_Gestures::~tst_Gestures()
369 {
370 }
371
372 void tst_Gestures::initTestCase()
373 {
374     CustomGesture::GestureType = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
375     QVERIFY(CustomGesture::GestureType != Qt::GestureType(0));
376     QVERIFY(CustomGesture::GestureType != Qt::CustomGesture);
377 }
378
379 void tst_Gestures::cleanupTestCase()
380 {
381     QGestureRecognizer::unregisterRecognizer(CustomGesture::GestureType);
382 }
383
384 void tst_Gestures::init()
385 {
386 }
387
388 void tst_Gestures::cleanup()
389 {
390 }
391
392 void tst_Gestures::customGesture()
393 {
394     GestureWidget widget;
395     widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
396     widget.show();
397     QTest::qWaitForWindowShown(&widget);
398
399     CustomEvent event;
400     event.hotSpot = widget.mapToGlobal(QPoint(5,5));
401     event.hasHotSpot = true;
402     sendCustomGesture(&event, &widget);
403
404     static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
405     static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
406     QCOMPARE(widget.customEventsReceived, TotalCustomEventsCount);
407     QCOMPARE(widget.gestureEventsReceived, TotalGestureEventsCount);
408     QCOMPARE(widget.gestureOverrideEventsReceived, 0);
409     QCOMPARE(widget.events.all.size(), TotalGestureEventsCount);
410     for(int i = 0; i < widget.events.all.size(); ++i)
411         QCOMPARE(widget.events.all.at(i), CustomGesture::GestureType);
412     QCOMPARE(widget.events.started.size(), 1);
413     QCOMPARE(widget.events.updated.size(), TotalGestureEventsCount - 2);
414     QCOMPARE(widget.events.finished.size(), 1);
415     QCOMPARE(widget.events.canceled.size(), 0);
416 }
417
418 void tst_Gestures::consumeEventHint()
419 {
420     GestureWidget widget;
421     widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
422
423     CustomGestureRecognizer::ConsumeEvents = true;
424     CustomEvent event;
425     sendCustomGesture(&event, &widget);
426     CustomGestureRecognizer::ConsumeEvents = false;
427
428     QCOMPARE(widget.customEventsReceived, 0);
429 }
430
431 void tst_Gestures::autoCancelingGestures()
432 {
433     GestureWidget widget;
434     widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
435     // send partial gesture. The gesture will be in the "maybe" state, but will
436     // never get enough events to fire, so Qt will have to kill it.
437     CustomEvent ev;
438     for (int i = CustomGesture::SerialMaybeThreshold;
439          i < CustomGesture::SerialStartedThreshold; ++i) {
440         ev.serial = i;
441         QApplication::sendEvent(&widget, &ev);
442     }
443     // wait long enough so the gesture manager will cancel the gesture
444     QTest::qWait(5000);
445     QCOMPARE(widget.customEventsReceived, CustomGesture::SerialStartedThreshold - CustomGesture::SerialMaybeThreshold);
446     QCOMPARE(widget.gestureEventsReceived, 0);
447     QCOMPARE(widget.gestureOverrideEventsReceived, 0);
448     QCOMPARE(widget.events.all.size(), 0);
449 }
450
451 void tst_Gestures::gestureOverChild()
452 {
453     GestureWidget widget("widget");
454     QVBoxLayout *l = new QVBoxLayout(&widget);
455     GestureWidget *child = new GestureWidget("child");
456     l->addWidget(child);
457
458     widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
459
460     CustomEvent event;
461     sendCustomGesture(&event, child);
462
463     static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
464     static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
465
466     QCOMPARE(child->customEventsReceived, TotalCustomEventsCount);
467     QCOMPARE(widget.customEventsReceived, 0);
468     QCOMPARE(child->gestureEventsReceived, 0);
469     QCOMPARE(child->gestureOverrideEventsReceived, 0);
470     QCOMPARE(widget.gestureEventsReceived, 0);
471     QCOMPARE(widget.gestureOverrideEventsReceived, 0);
472
473     // enable gestures over the children
474     widget.grabGesture(CustomGesture::GestureType);
475
476     widget.reset();
477     child->reset();
478
479     sendCustomGesture(&event, child);
480
481     QCOMPARE(child->customEventsReceived, TotalCustomEventsCount);
482     QCOMPARE(widget.customEventsReceived, 0);
483
484     QCOMPARE(child->gestureEventsReceived, 0);
485     QCOMPARE(child->gestureOverrideEventsReceived, 0);
486     QCOMPARE(widget.gestureEventsReceived, TotalGestureEventsCount);
487     QCOMPARE(widget.gestureOverrideEventsReceived, 0);
488     for(int i = 0; i < widget.events.all.size(); ++i)
489         QCOMPARE(widget.events.all.at(i), CustomGesture::GestureType);
490     QCOMPARE(widget.events.started.size(), 1);
491     QCOMPARE(widget.events.updated.size(), TotalGestureEventsCount - 2);
492     QCOMPARE(widget.events.finished.size(), 1);
493     QCOMPARE(widget.events.canceled.size(), 0);
494 }
495
496 void tst_Gestures::multipleWidgetOnlyGestureInTree()
497 {
498     GestureWidget parent("parent");
499     QVBoxLayout *l = new QVBoxLayout(&parent);
500     GestureWidget *child = new GestureWidget("child");
501     l->addWidget(child);
502
503     parent.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
504     child->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
505
506     static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
507     static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
508
509     // sending events to the child and making sure there is no conflict
510     CustomEvent event;
511     sendCustomGesture(&event, child);
512
513     QCOMPARE(child->customEventsReceived, TotalCustomEventsCount);
514     QCOMPARE(parent.customEventsReceived, 0);
515     QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount);
516     QCOMPARE(child->gestureOverrideEventsReceived, 0);
517     QCOMPARE(parent.gestureEventsReceived, 0);
518     QCOMPARE(parent.gestureOverrideEventsReceived, 0);
519
520     parent.reset();
521     child->reset();
522
523     // same for the parent widget
524     sendCustomGesture(&event, &parent);
525
526     QCOMPARE(child->customEventsReceived, 0);
527     QCOMPARE(parent.customEventsReceived, TotalCustomEventsCount);
528     QCOMPARE(child->gestureEventsReceived, 0);
529     QCOMPARE(child->gestureOverrideEventsReceived, 0);
530     QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount);
531     QCOMPARE(parent.gestureOverrideEventsReceived, 0);
532 }
533
534 void tst_Gestures::conflictingGestures()
535 {
536     GestureWidget parent("parent");
537     QVBoxLayout *l = new QVBoxLayout(&parent);
538     GestureWidget *child = new GestureWidget("child");
539     l->addWidget(child);
540
541     parent.grabGesture(CustomGesture::GestureType);
542     child->grabGesture(CustomGesture::GestureType);
543
544     static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
545
546     // child accepts the override, parent will not receive anything
547     parent.acceptGestureOverride = false;
548     child->acceptGestureOverride = true;
549
550     // sending events to the child and making sure there is no conflict
551     CustomEvent event;
552     sendCustomGesture(&event, child);
553
554     QCOMPARE(child->gestureOverrideEventsReceived, 1);
555     QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount);
556     QCOMPARE(parent.gestureOverrideEventsReceived, 0);
557     QCOMPARE(parent.gestureEventsReceived, 0);
558
559     parent.reset();
560     child->reset();
561
562     // parent accepts the override
563     parent.acceptGestureOverride = true;
564     child->acceptGestureOverride = false;
565
566     // sending events to the child and making sure there is no conflict
567     sendCustomGesture(&event, child);
568
569     QCOMPARE(child->gestureOverrideEventsReceived, 1);
570     QCOMPARE(child->gestureEventsReceived, 0);
571     QCOMPARE(parent.gestureOverrideEventsReceived, 1);
572     QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount);
573
574     parent.reset();
575     child->reset();
576
577     // nobody accepts the override, we will send normal events to the closest
578     // context (i.e. to the child widget) and it will be propagated and
579     // accepted by the parent widget
580     parent.acceptGestureOverride = false;
581     child->acceptGestureOverride = false;
582     child->ignoredGestures << CustomGesture::GestureType;
583
584     // sending events to the child and making sure there is no conflict
585     sendCustomGesture(&event, child);
586
587     QCOMPARE(child->gestureOverrideEventsReceived, 1);
588     QCOMPARE(child->gestureEventsReceived, 1);
589     QCOMPARE(parent.gestureOverrideEventsReceived, 1);
590     QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount);
591
592     parent.reset();
593     child->reset();
594
595     // nobody accepts the override, and nobody accepts the gesture event
596     parent.acceptGestureOverride = false;
597     child->acceptGestureOverride = false;
598     parent.ignoredGestures << CustomGesture::GestureType;
599     child->ignoredGestures << CustomGesture::GestureType;
600
601     // sending events to the child and making sure there is no conflict
602     sendCustomGesture(&event, child);
603
604     QCOMPARE(child->gestureOverrideEventsReceived, 1);
605     QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount);
606     QCOMPARE(parent.gestureOverrideEventsReceived, 1);
607     QCOMPARE(parent.gestureEventsReceived, 1);
608
609     parent.reset();
610     child->reset();
611
612     // we set an attribute to make sure all gesture events are propagated
613     parent.grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures);
614     parent.acceptGestureOverride = false;
615     child->acceptGestureOverride = false;
616     parent.ignoredGestures << CustomGesture::GestureType;
617     child->ignoredGestures << CustomGesture::GestureType;
618
619     // sending events to the child and making sure there is no conflict
620     sendCustomGesture(&event, child);
621
622     QCOMPARE(child->gestureOverrideEventsReceived, 1);
623     QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount);
624     QCOMPARE(parent.gestureOverrideEventsReceived, 1);
625     QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount);
626
627     parent.reset();
628     child->reset();
629
630     Qt::GestureType ContinuousGesture = QGestureRecognizer::registerRecognizer(new CustomContinuousGestureRecognizer);
631     static const int ContinuousGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
632     child->grabGesture(ContinuousGesture);
633     // child accepts override. And it also receives another custom gesture.
634     parent.acceptGestureOverride = false;
635     child->acceptGestureOverride = true;
636     sendCustomGesture(&event, child);
637
638     QCOMPARE(child->gestureOverrideEventsReceived, 1);
639     QVERIFY(child->gestureEventsReceived > TotalGestureEventsCount);
640     QCOMPARE(child->events.all.count(), TotalGestureEventsCount + ContinuousGestureEventsCount);
641     QCOMPARE(parent.gestureOverrideEventsReceived, 0);
642     QCOMPARE(parent.gestureEventsReceived, 0);
643
644     QGestureRecognizer::unregisterRecognizer(ContinuousGesture);
645 }
646
647 void tst_Gestures::finishedWithoutStarted()
648 {
649     GestureWidget widget;
650     widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
651
652     // the gesture will claim it finished, but it was never started.
653     CustomEvent ev;
654     ev.serial = CustomGesture::SerialFinishedThreshold;
655     QApplication::sendEvent(&widget, &ev);
656
657     QCOMPARE(widget.customEventsReceived, 1);
658     QCOMPARE(widget.gestureEventsReceived, 2);
659     QCOMPARE(widget.gestureOverrideEventsReceived, 0);
660     QCOMPARE(widget.events.all.size(), 2);
661     QCOMPARE(widget.events.started.size(), 1);
662     QCOMPARE(widget.events.updated.size(), 0);
663     QCOMPARE(widget.events.finished.size(), 1);
664     QCOMPARE(widget.events.canceled.size(), 0);
665 }
666
667 void tst_Gestures::unknownGesture()
668 {
669     GestureWidget widget;
670     widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
671     widget.grabGesture(Qt::CustomGesture, Qt::DontStartGestureOnChildren);
672     widget.grabGesture(Qt::GestureType(Qt::PanGesture+512), Qt::DontStartGestureOnChildren);
673
674     CustomEvent event;
675     sendCustomGesture(&event, &widget);
676
677     static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
678
679     QCOMPARE(widget.gestureEventsReceived, TotalGestureEventsCount);
680 }
681
682 static const QColor InstanceColors[] = {
683     Qt::blue, Qt::red, Qt::green, Qt::gray, Qt::yellow
684 };
685
686 class GestureItem : public QGraphicsObject
687 {
688     Q_OBJECT
689     static int InstanceCount;
690 public:
691     GestureItem(const char *name = 0)
692     {
693         instanceNumber = InstanceCount++;
694         if (name) {
695             setObjectName(QLatin1String(name));
696             setToolTip(name);
697         }
698         size = QRectF(0, 0, 100, 100);
699         customEventsReceived = 0;
700         gestureEventsReceived = 0;
701         gestureOverrideEventsReceived = 0;
702         events.clear();
703         overrideEvents.clear();
704         acceptGestureOverride = false;
705
706         scene = 0;
707     }
708     ~GestureItem()
709     {
710         --InstanceCount;
711     }
712
713     int customEventsReceived;
714     int gestureEventsReceived;
715     int gestureOverrideEventsReceived;
716     struct Events
717     {
718         QList<Qt::GestureType> all;
719         QList<Qt::GestureType> started;
720         QList<Qt::GestureType> updated;
721         QList<Qt::GestureType> finished;
722         QList<Qt::GestureType> canceled;
723
724         void clear()
725         {
726             all.clear();
727             started.clear();
728             updated.clear();
729             finished.clear();
730             canceled.clear();
731         }
732     } events, overrideEvents;
733
734     bool acceptGestureOverride;
735     QSet<Qt::GestureType> ignoredGestures;
736     QSet<Qt::GestureType> ignoredStartedGestures;
737     QSet<Qt::GestureType> ignoredUpdatedGestures;
738     QSet<Qt::GestureType> ignoredFinishedGestures;
739
740     QRectF size;
741     int instanceNumber;
742
743     void reset()
744     {
745         customEventsReceived = 0;
746         gestureEventsReceived = 0;
747         gestureOverrideEventsReceived = 0;
748         events.clear();
749         overrideEvents.clear();
750         ignoredGestures.clear();
751         ignoredStartedGestures.clear();
752         ignoredUpdatedGestures.clear();
753         ignoredFinishedGestures.clear();
754     }
755
756     QRectF boundingRect() const
757     {
758         return size;
759     }
760     void paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
761     {
762         QColor color = InstanceColors[instanceNumber % (sizeof(InstanceColors)/sizeof(InstanceColors[0]))];
763         p->fillRect(boundingRect(), color);
764     }
765
766     bool event(QEvent *event)
767     {
768         Events *eventsPtr = 0;
769         if (event->type() == QEvent::Gesture) {
770             ++gestureEventsReceived;
771             eventsPtr = &events;
772             QGestureEvent *e = static_cast<QGestureEvent *>(event);
773             foreach(Qt::GestureType type, ignoredGestures)
774                 e->ignore(e->gesture(type));
775             foreach(QGesture *g, e->gestures()) {
776                 switch (g->state()) {
777                 case Qt::GestureStarted:
778                     if (ignoredStartedGestures.contains(g->gestureType()))
779                         e->ignore(g);
780                     break;
781                 case Qt::GestureUpdated:
782                     if (ignoredUpdatedGestures.contains(g->gestureType()))
783                         e->ignore(g);
784                     break;
785                 case Qt::GestureFinished:
786                     if (ignoredFinishedGestures.contains(g->gestureType()))
787                         e->ignore(g);
788                     break;
789                 default:
790                     break;
791                 }
792             }
793         } else if (event->type() == QEvent::GestureOverride) {
794             ++gestureOverrideEventsReceived;
795             eventsPtr = &overrideEvents;
796             if (acceptGestureOverride)
797                 event->accept();
798         }
799         if (eventsPtr) {
800             QGestureEvent *e = static_cast<QGestureEvent*>(event);
801             QList<QGesture*> gestures = e->gestures();
802             foreach(QGesture *g, gestures) {
803                 eventsPtr->all << g->gestureType();
804                 switch(g->state()) {
805                 case Qt::GestureStarted:
806                     eventsPtr->started << g->gestureType();
807                     emit gestureStarted(e->type(), g);
808                     break;
809                 case Qt::GestureUpdated:
810                     eventsPtr->updated << g->gestureType();
811                     emit gestureUpdated(e->type(), g);
812                     break;
813                 case Qt::GestureFinished:
814                     eventsPtr->finished << g->gestureType();
815                     emit gestureFinished(e->type(), g);
816                     break;
817                 case Qt::GestureCanceled:
818                     eventsPtr->canceled << g->gestureType();
819                     emit gestureCanceled(e->type(), g);
820                     break;
821                 default:
822                     qWarning() << "Unknown GestureState enum value:" << static_cast<int>(g->state());
823                 }
824             }
825         } else if (event->type() == CustomEvent::EventType) {
826             ++customEventsReceived;
827         } else {
828             return QGraphicsObject::event(event);
829         }
830         return true;
831     }
832
833 Q_SIGNALS:
834     void gestureStarted(QEvent::Type, QGesture *);
835     void gestureUpdated(QEvent::Type, QGesture *);
836     void gestureFinished(QEvent::Type, QGesture *);
837     void gestureCanceled(QEvent::Type, QGesture *);
838
839 public:
840     // some arguments for the slots below:
841     QGraphicsScene *scene;
842
843 public Q_SLOTS:
844     void deleteThis() { delete this; }
845     void addSelfToScene(QEvent::Type eventType, QGesture *)
846     {
847         if (eventType == QEvent::Gesture) {
848             disconnect(sender(), 0, this, SLOT(addSelfToScene(QEvent::Type,QGesture*)));
849             scene->addItem(this);
850         }
851     }
852 };
853 int GestureItem::InstanceCount = 0;
854
855 void tst_Gestures::graphicsItemGesture()
856 {
857     QGraphicsScene scene;
858     QGraphicsView view(&scene);
859     view.setWindowFlags(Qt::X11BypassWindowManagerHint);
860
861     GestureItem *item = new GestureItem("item");
862     scene.addItem(item);
863     item->setPos(100, 100);
864
865     view.show();
866     QTest::qWaitForWindowShown(&view);
867     view.ensureVisible(scene.sceneRect());
868
869     item->grabGesture(CustomGesture::GestureType);
870
871     static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
872     static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
873
874     CustomEvent event;
875     // gesture without hotspot should not be delivered to items in the view
876     QTest::ignoreMessage(QtWarningMsg, "QGestureManager::deliverEvent: could not find the target for gesture");
877     QTest::ignoreMessage(QtWarningMsg, "QGestureManager::deliverEvent: could not find the target for gesture");
878     QTest::ignoreMessage(QtWarningMsg, "QGestureManager::deliverEvent: could not find the target for gesture");
879     QTest::ignoreMessage(QtWarningMsg, "QGestureManager::deliverEvent: could not find the target for gesture");
880     sendCustomGesture(&event, item, &scene);
881
882     QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
883     QCOMPARE(item->gestureEventsReceived, 0);
884     QCOMPARE(item->gestureOverrideEventsReceived, 0);
885
886     item->reset();
887
888     // make sure the event is properly delivered if only the hotspot is set.
889     event.hotSpot = mapToGlobal(QPointF(10, 10), item, &view);
890     event.hasHotSpot = true;
891     sendCustomGesture(&event, item, &scene);
892
893     QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
894     QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount);
895     QCOMPARE(item->gestureOverrideEventsReceived, 0);
896     QCOMPARE(item->events.all.size(), TotalGestureEventsCount);
897     for(int i = 0; i < item->events.all.size(); ++i)
898         QCOMPARE(item->events.all.at(i), CustomGesture::GestureType);
899     QCOMPARE(item->events.started.size(), 1);
900     QCOMPARE(item->events.updated.size(), TotalGestureEventsCount - 2);
901     QCOMPARE(item->events.finished.size(), 1);
902     QCOMPARE(item->events.canceled.size(), 0);
903
904     item->reset();
905
906     // send gesture to the item which ignores it.
907     item->ignoredGestures << CustomGesture::GestureType;
908
909     event.hotSpot = mapToGlobal(QPointF(10, 10), item, &view);
910     event.hasHotSpot = true;
911     sendCustomGesture(&event, item, &scene);
912     QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
913     QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount);
914     QCOMPARE(item->gestureOverrideEventsReceived, 0);
915 }
916
917 void tst_Gestures::graphicsView()
918 {
919     QGraphicsScene scene;
920     QGraphicsView view(&scene);
921     view.setWindowFlags(Qt::X11BypassWindowManagerHint);
922
923     GestureItem *item = new GestureItem("item");
924     scene.addItem(item);
925     item->setPos(100, 100);
926
927     view.show();
928     QTest::qWaitForWindowShown(&view);
929     view.ensureVisible(scene.sceneRect());
930
931     item->grabGesture(CustomGesture::GestureType);
932
933     static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
934     static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
935
936     CustomEvent event;
937     // make sure the event is properly delivered if only the hotspot is set.
938     event.hotSpot = mapToGlobal(QPointF(10, 10), item, &view);
939     event.hasHotSpot = true;
940     sendCustomGesture(&event, item, &scene);
941
942     QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
943     QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount);
944     QCOMPARE(item->gestureOverrideEventsReceived, 0);
945
946     // change the viewport and try again
947     QWidget *newViewport = new QWidget;
948     view.setViewport(newViewport);
949
950     item->reset();
951     sendCustomGesture(&event, item, &scene);
952
953     QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
954     QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount);
955     QCOMPARE(item->gestureOverrideEventsReceived, 0);
956
957     // change the scene and try again
958     QGraphicsScene newScene;
959     item = new GestureItem("newItem");
960     newScene.addItem(item);
961     item->setPos(100, 100);
962     view.setScene(&newScene);
963
964     item->reset();
965     // first without a gesture
966     sendCustomGesture(&event, item, &newScene);
967
968     QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
969     QCOMPARE(item->gestureEventsReceived, 0);
970     QCOMPARE(item->gestureOverrideEventsReceived, 0);
971
972     // then grab the gesture and try again
973     item->reset();
974     item->grabGesture(CustomGesture::GestureType);
975     sendCustomGesture(&event, item, &newScene);
976
977     QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
978     QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount);
979     QCOMPARE(item->gestureOverrideEventsReceived, 0);
980 }
981
982 void tst_Gestures::graphicsItemTreeGesture()
983 {
984     QGraphicsScene scene;
985     QGraphicsView view(&scene);
986     view.setWindowFlags(Qt::X11BypassWindowManagerHint);
987
988     GestureItem *item1 = new GestureItem("item1");
989     item1->setPos(100, 100);
990     item1->size = QRectF(0, 0, 350, 200);
991     scene.addItem(item1);
992
993     GestureItem *item1_child1 = new GestureItem("item1_child1");
994     item1_child1->setPos(50, 50);
995     item1_child1->size = QRectF(0, 0, 100, 100);
996     item1_child1->setParentItem(item1);
997
998     GestureItem *item1_child2 = new GestureItem("item1_child2");
999     item1_child2->size = QRectF(0, 0, 100, 100);
1000     item1_child2->setPos(200, 50);
1001     item1_child2->setParentItem(item1);
1002
1003     view.show();
1004     QTest::qWaitForWindowShown(&view);
1005     view.ensureVisible(scene.sceneRect());
1006
1007     item1->grabGesture(CustomGesture::GestureType);
1008
1009     static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1010
1011     CustomEvent event;
1012     event.hotSpot = mapToGlobal(QPointF(10, 10), item1_child1, &view);
1013     event.hasHotSpot = true;
1014
1015     item1->ignoredGestures << CustomGesture::GestureType;
1016     sendCustomGesture(&event, item1_child1, &scene);
1017     QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0);
1018     QCOMPARE(item1_child1->gestureEventsReceived, 0);
1019     QCOMPARE(item1_child2->gestureEventsReceived, 0);
1020     QCOMPARE(item1_child2->gestureOverrideEventsReceived, 0);
1021     QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1022     QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
1023
1024     item1->reset(); item1_child1->reset(); item1_child2->reset();
1025
1026     item1_child1->grabGesture(CustomGesture::GestureType);
1027
1028     item1->ignoredGestures << CustomGesture::GestureType;
1029     item1_child1->ignoredGestures << CustomGesture::GestureType;
1030     sendCustomGesture(&event, item1_child1, &scene);
1031     QCOMPARE(item1_child1->gestureOverrideEventsReceived, 1);
1032     QCOMPARE(item1_child1->gestureEventsReceived, TotalGestureEventsCount);
1033     QCOMPARE(item1_child2->gestureEventsReceived, 0);
1034     QCOMPARE(item1_child2->gestureOverrideEventsReceived, 0);
1035     QCOMPARE(item1->gestureOverrideEventsReceived, 1);
1036     QCOMPARE(item1->gestureEventsReceived, 1);
1037 }
1038
1039 void tst_Gestures::explicitGraphicsObjectTarget()
1040 {
1041     QGraphicsScene scene;
1042     QGraphicsView view(&scene);
1043     view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1044
1045     GestureItem *item1 = new GestureItem("item1");
1046     scene.addItem(item1);
1047     item1->setPos(100, 100);
1048     item1->setZValue(1);
1049
1050     GestureItem *item2 = new GestureItem("item2");
1051     scene.addItem(item2);
1052     item2->setPos(100, 100);
1053     item2->setZValue(5);
1054
1055     GestureItem *item2_child1 = new GestureItem("item2_child1");
1056     scene.addItem(item2_child1);
1057     item2_child1->setParentItem(item2);
1058     item2_child1->setPos(10, 10);
1059
1060     view.show();
1061     QTest::qWaitForWindowShown(&view);
1062     view.ensureVisible(scene.sceneRect());
1063
1064     item1->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
1065     item2->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
1066     item2_child1->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
1067
1068     static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1069
1070     // sending events to item1, but the hotSpot is set to item2
1071     CustomEvent event;
1072     event.hotSpot = mapToGlobal(QPointF(15, 15), item2, &view);
1073     event.hasHotSpot = true;
1074
1075     sendCustomGesture(&event, item1, &scene);
1076
1077     QCOMPARE(item1->gestureEventsReceived, 0);
1078     QCOMPARE(item1->gestureOverrideEventsReceived, 1);
1079     QCOMPARE(item2_child1->gestureEventsReceived, TotalGestureEventsCount);
1080     QCOMPARE(item2_child1->gestureOverrideEventsReceived, 1);
1081     QCOMPARE(item2_child1->events.all.size(), TotalGestureEventsCount);
1082     for(int i = 0; i < item2_child1->events.all.size(); ++i)
1083         QCOMPARE(item2_child1->events.all.at(i), CustomGesture::GestureType);
1084     QCOMPARE(item2_child1->events.started.size(), 1);
1085     QCOMPARE(item2_child1->events.updated.size(), TotalGestureEventsCount - 2);
1086     QCOMPARE(item2_child1->events.finished.size(), 1);
1087     QCOMPARE(item2_child1->events.canceled.size(), 0);
1088     QCOMPARE(item2->gestureEventsReceived, 0);
1089     QCOMPARE(item2->gestureOverrideEventsReceived, 1);
1090 }
1091
1092 void tst_Gestures::gestureOverChildGraphicsItem()
1093 {
1094     QGraphicsScene scene;
1095     QGraphicsView view(&scene);
1096     view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1097
1098     GestureItem *item0 = new GestureItem("item0");
1099     scene.addItem(item0);
1100     item0->setPos(0, 0);
1101     item0->grabGesture(CustomGesture::GestureType);
1102     item0->setZValue(1);
1103
1104     GestureItem *item1 = new GestureItem("item1");
1105     scene.addItem(item1);
1106     item1->setPos(100, 100);
1107     item1->setZValue(5);
1108
1109     GestureItem *item2 = new GestureItem("item2");
1110     scene.addItem(item2);
1111     item2->setPos(100, 100);
1112     item2->setZValue(10);
1113
1114     GestureItem *item2_child1 = new GestureItem("item2_child1");
1115     scene.addItem(item2_child1);
1116     item2_child1->setParentItem(item2);
1117     item2_child1->setPos(0, 0);
1118
1119     view.show();
1120     QTest::qWaitForWindowShown(&view);
1121     view.ensureVisible(scene.sceneRect());
1122
1123     item1->grabGesture(CustomGesture::GestureType);
1124
1125     static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1126     static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
1127
1128     CustomEvent event;
1129     event.hotSpot = mapToGlobal(QPointF(10, 10), item2_child1, &view);
1130     event.hasHotSpot = true;
1131     sendCustomGesture(&event, item0, &scene);
1132
1133     QCOMPARE(item0->customEventsReceived, TotalCustomEventsCount);
1134     QCOMPARE(item2_child1->gestureEventsReceived, 0);
1135     QCOMPARE(item2_child1->gestureOverrideEventsReceived, 0);
1136     QCOMPARE(item2->gestureEventsReceived, 0);
1137     QCOMPARE(item2->gestureOverrideEventsReceived, 0);
1138     QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
1139     QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1140
1141     item0->reset(); item1->reset(); item2->reset(); item2_child1->reset();
1142     item2->grabGesture(CustomGesture::GestureType);
1143     item2->ignoredGestures << CustomGesture::GestureType;
1144
1145     event.hotSpot = mapToGlobal(QPointF(10, 10), item2_child1, &view);
1146     event.hasHotSpot = true;
1147     sendCustomGesture(&event, item0, &scene);
1148
1149     QCOMPARE(item2_child1->gestureEventsReceived, 0);
1150     QCOMPARE(item2_child1->gestureOverrideEventsReceived, 0);
1151     QCOMPARE(item2->gestureEventsReceived, 1);
1152     QCOMPARE(item2->gestureOverrideEventsReceived, 1);
1153     QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
1154     QCOMPARE(item1->gestureOverrideEventsReceived, 1);
1155
1156     item0->reset(); item1->reset(); item2->reset(); item2_child1->reset();
1157     item2->grabGesture(CustomGesture::GestureType);
1158     item2->ignoredGestures << CustomGesture::GestureType;
1159     item1->ignoredGestures << CustomGesture::GestureType;
1160
1161     event.hotSpot = mapToGlobal(QPointF(10, 10), item2_child1, &view);
1162     event.hasHotSpot = true;
1163     sendCustomGesture(&event, item0, &scene);
1164
1165     QCOMPARE(item2_child1->gestureEventsReceived, 0);
1166     QCOMPARE(item2_child1->gestureOverrideEventsReceived, 0);
1167     QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount);
1168     QCOMPARE(item2->gestureOverrideEventsReceived, 1);
1169     QCOMPARE(item1->gestureEventsReceived, 1);
1170     QCOMPARE(item1->gestureOverrideEventsReceived, 1);
1171
1172     item0->reset(); item1->reset(); item2->reset(); item2_child1->reset();
1173     item2->grabGesture(CustomGesture::GestureType);
1174     item2->ignoredGestures << CustomGesture::GestureType;
1175     item1->ignoredGestures << CustomGesture::GestureType;
1176     item1->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures);
1177
1178     event.hotSpot = mapToGlobal(QPointF(10, 10), item2_child1, &view);
1179     event.hasHotSpot = true;
1180     sendCustomGesture(&event, item0, &scene);
1181
1182     QCOMPARE(item2_child1->gestureEventsReceived, 0);
1183     QCOMPARE(item2_child1->gestureOverrideEventsReceived, 0);
1184     QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount);
1185     QCOMPARE(item2->gestureOverrideEventsReceived, 1);
1186     QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
1187     QCOMPARE(item1->gestureOverrideEventsReceived, 1);
1188 }
1189
1190 void tst_Gestures::twoGesturesOnDifferentLevel()
1191 {
1192     GestureWidget parent("parent");
1193     QVBoxLayout *l = new QVBoxLayout(&parent);
1194     GestureWidget *child = new GestureWidget("child");
1195     l->addWidget(child);
1196
1197     Qt::GestureType SecondGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1198
1199     parent.grabGesture(CustomGesture::GestureType);
1200     child->grabGesture(SecondGesture);
1201
1202     CustomEvent event;
1203     // sending events that form a gesture to one widget, but they will be
1204     // filtered by two different gesture recognizers and will generate two
1205     // QGesture objects. Check that those gesture objects are delivered to
1206     // different widgets properly.
1207     sendCustomGesture(&event, child);
1208
1209     static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1210     static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
1211
1212     QCOMPARE(child->customEventsReceived, TotalCustomEventsCount);
1213     QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount);
1214     QCOMPARE(child->gestureOverrideEventsReceived, 0);
1215     QCOMPARE(child->events.all.size(), TotalGestureEventsCount);
1216     for(int i = 0; i < child->events.all.size(); ++i)
1217         QCOMPARE(child->events.all.at(i), SecondGesture);
1218
1219     QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount);
1220     QCOMPARE(parent.gestureOverrideEventsReceived, 0);
1221     QCOMPARE(parent.events.all.size(), TotalGestureEventsCount);
1222     for(int i = 0; i < child->events.all.size(); ++i)
1223         QCOMPARE(parent.events.all.at(i), CustomGesture::GestureType);
1224
1225     QGestureRecognizer::unregisterRecognizer(SecondGesture);
1226 }
1227
1228 void tst_Gestures::multipleGesturesInTree()
1229 {
1230     GestureWidget a("A");
1231     GestureWidget *A = &a;
1232     GestureWidget *B = new GestureWidget("B", A);
1233     GestureWidget *C = new GestureWidget("C", B);
1234     GestureWidget *D = new GestureWidget("D", C);
1235
1236     Qt::GestureType FirstGesture  = CustomGesture::GestureType;
1237     Qt::GestureType SecondGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1238     Qt::GestureType ThirdGesture  = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1239
1240     Qt::GestureFlags flags = Qt::ReceivePartialGestures;
1241     A->grabGesture(FirstGesture,  flags);   // A [1   3]
1242     A->grabGesture(ThirdGesture,  flags);   // |
1243     B->grabGesture(SecondGesture, flags);   // B [  2 3]
1244     B->grabGesture(ThirdGesture,  flags);   // |
1245     C->grabGesture(FirstGesture,  flags);   // C [1 2 3]
1246     C->grabGesture(SecondGesture, flags);   // |
1247     C->grabGesture(ThirdGesture,  flags);   // D [1   3]
1248     D->grabGesture(FirstGesture,  flags);
1249     D->grabGesture(ThirdGesture,  flags);
1250
1251     // make sure all widgets ignore events, so they get propagated.
1252     A->ignoredGestures << FirstGesture << ThirdGesture;
1253     B->ignoredGestures << SecondGesture << ThirdGesture;
1254     C->ignoredGestures << FirstGesture << SecondGesture << ThirdGesture;
1255     D->ignoredGestures << FirstGesture << ThirdGesture;
1256
1257     CustomEvent event;
1258     sendCustomGesture(&event, D);
1259
1260     static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1261
1262     // gesture override events
1263     QCOMPARE(D->overrideEvents.all.count(FirstGesture), 1);
1264     QCOMPARE(D->overrideEvents.all.count(SecondGesture), 0);
1265     QCOMPARE(D->overrideEvents.all.count(ThirdGesture), 1);
1266
1267     QCOMPARE(C->overrideEvents.all.count(FirstGesture), 1);
1268     QCOMPARE(C->overrideEvents.all.count(SecondGesture), 1);
1269     QCOMPARE(C->overrideEvents.all.count(ThirdGesture), 1);
1270
1271     QCOMPARE(B->overrideEvents.all.count(FirstGesture), 0);
1272     QCOMPARE(B->overrideEvents.all.count(SecondGesture), 1);
1273     QCOMPARE(B->overrideEvents.all.count(ThirdGesture), 1);
1274
1275     QCOMPARE(A->overrideEvents.all.count(FirstGesture), 1);
1276     QCOMPARE(A->overrideEvents.all.count(SecondGesture), 0);
1277     QCOMPARE(A->overrideEvents.all.count(ThirdGesture), 1);
1278
1279     // normal gesture events
1280     QCOMPARE(D->events.all.count(FirstGesture), TotalGestureEventsCount);
1281     QCOMPARE(D->events.all.count(SecondGesture), 0);
1282     QCOMPARE(D->events.all.count(ThirdGesture), TotalGestureEventsCount);
1283
1284     QCOMPARE(C->events.all.count(FirstGesture), TotalGestureEventsCount);
1285     QCOMPARE(C->events.all.count(SecondGesture), TotalGestureEventsCount);
1286     QCOMPARE(C->events.all.count(ThirdGesture), TotalGestureEventsCount);
1287
1288     QCOMPARE(B->events.all.count(FirstGesture), 0);
1289     QCOMPARE(B->events.all.count(SecondGesture), TotalGestureEventsCount);
1290     QCOMPARE(B->events.all.count(ThirdGesture), TotalGestureEventsCount);
1291
1292     QCOMPARE(A->events.all.count(FirstGesture), TotalGestureEventsCount);
1293     QCOMPARE(A->events.all.count(SecondGesture), 0);
1294     QCOMPARE(A->events.all.count(ThirdGesture), TotalGestureEventsCount);
1295
1296     QGestureRecognizer::unregisterRecognizer(SecondGesture);
1297     QGestureRecognizer::unregisterRecognizer(ThirdGesture);
1298 }
1299
1300 void tst_Gestures::multipleGesturesInComplexTree()
1301 {
1302     GestureWidget a("A");
1303     GestureWidget *A = &a;
1304     GestureWidget *B = new GestureWidget("B", A);
1305     GestureWidget *C = new GestureWidget("C", B);
1306     GestureWidget *D = new GestureWidget("D", C);
1307
1308     Qt::GestureType FirstGesture   = CustomGesture::GestureType;
1309     Qt::GestureType SecondGesture  = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1310     Qt::GestureType ThirdGesture   = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1311     Qt::GestureType FourthGesture  = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1312     Qt::GestureType FifthGesture   = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1313     Qt::GestureType SixthGesture   = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1314     Qt::GestureType SeventhGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1315
1316     Qt::GestureFlags flags = Qt::ReceivePartialGestures;
1317     A->grabGesture(FirstGesture,   flags); // A [1,3,4]
1318     A->grabGesture(ThirdGesture,   flags); // |
1319     A->grabGesture(FourthGesture,  flags); // B [2,3,5]
1320     B->grabGesture(SecondGesture,  flags); // |
1321     B->grabGesture(ThirdGesture,   flags); // C [1,2,3,6]
1322     B->grabGesture(FifthGesture,   flags); // |
1323     C->grabGesture(FirstGesture,   flags); // D [1,3,7]
1324     C->grabGesture(SecondGesture,  flags);
1325     C->grabGesture(ThirdGesture,   flags);
1326     C->grabGesture(SixthGesture,   flags);
1327     D->grabGesture(FirstGesture,   flags);
1328     D->grabGesture(ThirdGesture,   flags);
1329     D->grabGesture(SeventhGesture, flags);
1330
1331     // make sure all widgets ignore events, so they get propagated.
1332     QSet<Qt::GestureType> allGestureTypes;
1333     allGestureTypes << FirstGesture << SecondGesture << ThirdGesture
1334             << FourthGesture << FifthGesture << SixthGesture << SeventhGesture;
1335     A->ignoredGestures = B->ignoredGestures = allGestureTypes;
1336     C->ignoredGestures = D->ignoredGestures = allGestureTypes;
1337
1338     CustomEvent event;
1339     sendCustomGesture(&event, D);
1340
1341     static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1342
1343     // gesture override events
1344     QCOMPARE(D->overrideEvents.all.count(FirstGesture), 1);
1345     QCOMPARE(D->overrideEvents.all.count(SecondGesture), 0);
1346     QCOMPARE(D->overrideEvents.all.count(ThirdGesture), 1);
1347
1348     QCOMPARE(C->overrideEvents.all.count(FirstGesture), 1);
1349     QCOMPARE(C->overrideEvents.all.count(SecondGesture), 1);
1350     QCOMPARE(C->overrideEvents.all.count(ThirdGesture), 1);
1351
1352     QCOMPARE(B->overrideEvents.all.count(FirstGesture), 0);
1353     QCOMPARE(B->overrideEvents.all.count(SecondGesture), 1);
1354     QCOMPARE(B->overrideEvents.all.count(ThirdGesture), 1);
1355
1356     QCOMPARE(A->overrideEvents.all.count(FirstGesture), 1);
1357     QCOMPARE(A->overrideEvents.all.count(SecondGesture), 0);
1358     QCOMPARE(A->overrideEvents.all.count(ThirdGesture), 1);
1359
1360     // normal gesture events
1361     QCOMPARE(D->events.all.count(FirstGesture), TotalGestureEventsCount);
1362     QCOMPARE(D->events.all.count(SecondGesture), 0);
1363     QCOMPARE(D->events.all.count(ThirdGesture), TotalGestureEventsCount);
1364     QCOMPARE(D->events.all.count(FourthGesture), 0);
1365     QCOMPARE(D->events.all.count(FifthGesture), 0);
1366     QCOMPARE(D->events.all.count(SixthGesture), 0);
1367     QCOMPARE(D->events.all.count(SeventhGesture), TotalGestureEventsCount);
1368
1369     QCOMPARE(C->events.all.count(FirstGesture), TotalGestureEventsCount);
1370     QCOMPARE(C->events.all.count(SecondGesture), TotalGestureEventsCount);
1371     QCOMPARE(C->events.all.count(ThirdGesture), TotalGestureEventsCount);
1372     QCOMPARE(C->events.all.count(FourthGesture), 0);
1373     QCOMPARE(C->events.all.count(FifthGesture), 0);
1374     QCOMPARE(C->events.all.count(SixthGesture), TotalGestureEventsCount);
1375     QCOMPARE(C->events.all.count(SeventhGesture), 0);
1376
1377     QCOMPARE(B->events.all.count(FirstGesture), 0);
1378     QCOMPARE(B->events.all.count(SecondGesture), TotalGestureEventsCount);
1379     QCOMPARE(B->events.all.count(ThirdGesture), TotalGestureEventsCount);
1380     QCOMPARE(B->events.all.count(FourthGesture), 0);
1381     QCOMPARE(B->events.all.count(FifthGesture), TotalGestureEventsCount);
1382     QCOMPARE(B->events.all.count(SixthGesture), 0);
1383     QCOMPARE(B->events.all.count(SeventhGesture), 0);
1384
1385     QCOMPARE(A->events.all.count(FirstGesture), TotalGestureEventsCount);
1386     QCOMPARE(A->events.all.count(SecondGesture), 0);
1387     QCOMPARE(A->events.all.count(ThirdGesture), TotalGestureEventsCount);
1388     QCOMPARE(A->events.all.count(FourthGesture), TotalGestureEventsCount);
1389     QCOMPARE(A->events.all.count(FifthGesture), 0);
1390     QCOMPARE(A->events.all.count(SixthGesture), 0);
1391     QCOMPARE(A->events.all.count(SeventhGesture), 0);
1392
1393     QGestureRecognizer::unregisterRecognizer(SecondGesture);
1394     QGestureRecognizer::unregisterRecognizer(ThirdGesture);
1395     QGestureRecognizer::unregisterRecognizer(FourthGesture);
1396     QGestureRecognizer::unregisterRecognizer(FifthGesture);
1397     QGestureRecognizer::unregisterRecognizer(SixthGesture);
1398     QGestureRecognizer::unregisterRecognizer(SeventhGesture);
1399 }
1400
1401 void tst_Gestures::testMapToScene()
1402 {
1403     QGesture gesture;
1404     QList<QGesture*> list;
1405     list << &gesture;
1406     QGestureEvent event(list);
1407     QCOMPARE(event.mapToGraphicsScene(gesture.hotSpot()), QPointF()); // not set, can't do much
1408
1409     QGraphicsScene scene;
1410     QGraphicsView view(&scene);
1411     view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1412
1413     GestureItem *item0 = new GestureItem;
1414     scene.addItem(item0);
1415     item0->setPos(14, 16);
1416
1417     view.show(); // need to show to give it a global coordinate
1418     QTest::qWaitForWindowShown(&view);
1419     view.ensureVisible(scene.sceneRect());
1420
1421     QPoint origin = view.mapToGlobal(QPoint());
1422     event.setWidget(view.viewport());
1423
1424     QCOMPARE(event.mapToGraphicsScene(origin + QPoint(100, 200)), view.mapToScene(QPoint(100, 200)));
1425 }
1426
1427 void tst_Gestures::ungrabGesture() // a method on QWidget
1428 {
1429     class MockGestureWidget : public GestureWidget {
1430     public:
1431         MockGestureWidget(const char *name = 0, QWidget *parent = 0)
1432             : GestureWidget(name, parent) { }
1433
1434
1435         QSet<QGesture*> gestures;
1436     protected:
1437         bool event(QEvent *event)
1438         {
1439             if (event->type() == QEvent::Gesture) {
1440                 QGestureEvent *gestureEvent = static_cast<QGestureEvent*>(event);
1441                 if (gestureEvent)
1442                     foreach (QGesture *g, gestureEvent->gestures())
1443                         gestures.insert(g);
1444             }
1445             return GestureWidget::event(event);
1446         }
1447     };
1448
1449     MockGestureWidget parent("A");
1450     MockGestureWidget *a = &parent;
1451     MockGestureWidget *b = new MockGestureWidget("B", a);
1452
1453     a->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
1454     b->grabGesture(CustomGesture::GestureType);
1455     b->ignoredGestures << CustomGesture::GestureType;
1456
1457     CustomEvent event;
1458     // sending an event will cause the QGesture objects to be instantiated for the widgets
1459     sendCustomGesture(&event, b);
1460
1461     QCOMPARE(a->gestures.count(), 1);
1462     QPointer<QGesture> customGestureA;
1463     customGestureA = *(a->gestures.begin());
1464     QVERIFY(!customGestureA.isNull());
1465     QCOMPARE(customGestureA->gestureType(), CustomGesture::GestureType);
1466
1467     QCOMPARE(b->gestures.count(), 1);
1468     QPointer<QGesture> customGestureB;
1469     customGestureB = *(b->gestures.begin());
1470     QVERIFY(!customGestureB.isNull());
1471     QVERIFY(customGestureA.data() == customGestureB.data());
1472     QCOMPARE(customGestureB->gestureType(), CustomGesture::GestureType);
1473
1474     a->gestures.clear();
1475     // sending an event will cause the QGesture objects to be instantiated for the widget
1476     sendCustomGesture(&event, a);
1477
1478     QCOMPARE(a->gestures.count(), 1);
1479     customGestureA = *(a->gestures.begin());
1480     QVERIFY(!customGestureA.isNull());
1481     QCOMPARE(customGestureA->gestureType(), CustomGesture::GestureType);
1482     QVERIFY(customGestureA.data() != customGestureB.data());
1483
1484     a->ungrabGesture(CustomGesture::GestureType);
1485     //We changed the deletion of Gestures to lazy during QT-4022, so we can't ensure the QGesture is deleted until now
1486     QVERIFY(!customGestureB.isNull());
1487
1488     a->gestures.clear();
1489     a->reset();
1490     // send again to 'b' and make sure a never gets it.
1491     sendCustomGesture(&event, b);
1492     //After all Gestures are processed in the QGestureManager, we can ensure the QGesture is now deleted
1493     QVERIFY(customGestureA.isNull());
1494     QCOMPARE(a->gestureEventsReceived, 0);
1495     QCOMPARE(a->gestureOverrideEventsReceived, 0);
1496 }
1497
1498 void tst_Gestures::unregisterRecognizer() // a method on QApplication
1499 {
1500     /*
1501      The hardest usecase to get right is when we remove a recognizer while several
1502      of the gestures it created are in active state and we immediately add a new recognizer
1503      for the same type (thus replacing the old one).
1504      The expected result is that all old gestures continue till they are finished/cancelled
1505      and the new recognizer starts creating gestures immediately at registration.
1506
1507      This implies that deleting of the recognizer happens only when there are no more gestures
1508      that it created. (since gestures might have a pointer to the recognizer)
1509      */
1510
1511 }
1512
1513 void tst_Gestures::autoCancelGestures()
1514 {
1515     class MockWidget : public GestureWidget {
1516       public:
1517         MockWidget(const char *name) : GestureWidget(name), badGestureEvents(0) { }
1518
1519         bool event(QEvent *event)
1520         {
1521             if (event->type() == QEvent::Gesture) {
1522                 QGestureEvent *ge = static_cast<QGestureEvent*>(event);
1523                 if (ge->gestures().count() != 1)
1524                     ++badGestureEvents;   // event should contain exactly one gesture
1525                 ge->gestures().first()->setGestureCancelPolicy(QGesture::CancelAllInContext);
1526             }
1527             return GestureWidget::event(event);
1528         }
1529
1530         int badGestureEvents;
1531     };
1532
1533     const Qt::GestureType secondGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1534
1535     MockWidget parent("parent"); // this one sets the cancel policy to CancelAllInContext
1536     parent.resize(300, 100);
1537     parent.setWindowFlags(Qt::X11BypassWindowManagerHint);
1538     GestureWidget *child = new GestureWidget("child", &parent);
1539     child->setGeometry(10, 10, 100, 80);
1540
1541     parent.grabGesture(CustomGesture::GestureType);
1542     child->grabGesture(secondGesture);
1543     parent.show();
1544     QTest::qWaitForWindowShown(&parent);
1545
1546     /*
1547       An event is send to both the child and the parent, when the child gets it a gesture is triggered
1548       and send to the child.
1549       When the parent gets the event a new gesture is triggered and delivered to the parent. When the
1550       parent gets it he accepts it and that causes the cancel policy to activate.
1551       The cause of that is the gesture for the child is cancelled and send to the child as such.
1552     */
1553     CustomEvent event;
1554     event.serial = CustomGesture::SerialStartedThreshold;
1555     QApplication::sendEvent(child, &event);
1556     QCOMPARE(child->events.all.count(), 2);
1557     QCOMPARE(child->events.started.count(), 1);
1558     QCOMPARE(child->events.canceled.count(), 1);
1559     QCOMPARE(parent.events.all.count(), 1);
1560
1561     // clean up, make the parent gesture finish
1562     event.serial = CustomGesture::SerialFinishedThreshold;
1563     QApplication::sendEvent(child, &event);
1564     QCOMPARE(parent.events.all.count(), 2);
1565     QCOMPARE(parent.badGestureEvents, 0);
1566 }
1567
1568 void tst_Gestures::autoCancelGestures2()
1569 {
1570     class MockItem : public GestureItem {
1571       public:
1572         MockItem(const char *name) : GestureItem(name), badGestureEvents(0) { }
1573
1574         bool event(QEvent *event) {
1575             if (event->type() == QEvent::Gesture) {
1576                 QGestureEvent *ge = static_cast<QGestureEvent*>(event);
1577                 if (ge->gestures().count() != 1)
1578                     ++badGestureEvents;   // event should contain exactly one gesture
1579                 ge->gestures().first()->setGestureCancelPolicy(QGesture::CancelAllInContext);
1580             }
1581             return GestureItem::event(event);
1582         }
1583
1584         int badGestureEvents;
1585     };
1586
1587     const Qt::GestureType secondGesture = QGestureRecognizer ::registerRecognizer(new CustomGestureRecognizer);
1588
1589     QGraphicsScene scene;
1590     QGraphicsView view(&scene);
1591     view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1592
1593     MockItem *parent = new MockItem("parent");
1594     GestureItem *child = new GestureItem("child");
1595     child->setParentItem(parent);
1596     parent->setPos(0, 0);
1597     child->setPos(10, 10);
1598     scene.addItem(parent);
1599     parent->grabGesture(CustomGesture::GestureType);
1600     child->grabGesture(secondGesture);
1601
1602     view.show();
1603     QTest::qWaitForWindowShown(&view);
1604     view.ensureVisible(scene.sceneRect());
1605
1606     CustomEvent event;
1607     event.serial = CustomGesture::SerialStartedThreshold;
1608     event.hasHotSpot = true;
1609     event.hotSpot = mapToGlobal(QPointF(5, 5), child, &view);
1610     scene.sendEvent(child, &event);
1611     QCOMPARE(parent->events.all.count(), 1);
1612     QCOMPARE(child->events.started.count(), 1);
1613     QCOMPARE(child->events.canceled.count(), 1);
1614     QCOMPARE(child->events.all.count(), 2);
1615
1616     // clean up, make the parent gesture finish
1617     event.serial = CustomGesture::SerialFinishedThreshold;
1618     scene.sendEvent(child, &event);
1619     QCOMPARE(parent->events.all.count(), 2);
1620     QCOMPARE(parent->badGestureEvents, 0);
1621 }
1622
1623 void tst_Gestures::graphicsViewParentPropagation()
1624 {
1625     QGraphicsScene scene;
1626     QGraphicsView view(&scene);
1627     view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1628
1629     GestureItem *item0 = new GestureItem("item0");
1630     scene.addItem(item0);
1631     item0->setPos(0, 0);
1632     item0->grabGesture(CustomGesture::GestureType);
1633     item0->setZValue(1);
1634
1635     GestureItem *item1 = new GestureItem("item1");
1636     scene.addItem(item1);
1637     item1->setPos(0, 0);
1638     item1->setZValue(5);
1639
1640     GestureItem *item1_c1 = new GestureItem("item1_child1");
1641     item1_c1->setParentItem(item1);
1642     item1_c1->setPos(0, 0);
1643
1644     GestureItem *item1_c1_c1 = new GestureItem("item1_child1_child1");
1645     item1_c1_c1->setParentItem(item1_c1);
1646     item1_c1_c1->setPos(0, 0);
1647
1648     view.show();
1649     QTest::qWaitForWindowShown(&view);
1650     view.ensureVisible(scene.sceneRect());
1651
1652     item0->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures | Qt::IgnoredGesturesPropagateToParent);
1653     item1->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures | Qt::IgnoredGesturesPropagateToParent);
1654     item1_c1->grabGesture(CustomGesture::GestureType, Qt::IgnoredGesturesPropagateToParent);
1655     item1_c1_c1->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures | Qt::IgnoredGesturesPropagateToParent);
1656
1657     item0->ignoredUpdatedGestures << CustomGesture::GestureType;
1658     item0->ignoredFinishedGestures << CustomGesture::GestureType;
1659     item1->ignoredUpdatedGestures << CustomGesture::GestureType;
1660     item1->ignoredFinishedGestures << CustomGesture::GestureType;
1661     item1_c1->ignoredUpdatedGestures << CustomGesture::GestureType;
1662     item1_c1->ignoredFinishedGestures << CustomGesture::GestureType;
1663     item1_c1_c1->ignoredUpdatedGestures << CustomGesture::GestureType;
1664     item1_c1_c1->ignoredFinishedGestures << CustomGesture::GestureType;
1665
1666     static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1667
1668     CustomEvent event;
1669     event.hotSpot = mapToGlobal(QPointF(10, 10), item1_c1, &view);
1670     event.hasHotSpot = true;
1671     sendCustomGesture(&event, item0, &scene);
1672
1673     QCOMPARE(item1_c1_c1->gestureEventsReceived, TotalGestureEventsCount);
1674     QCOMPARE(item1_c1_c1->gestureOverrideEventsReceived, 1);
1675     QCOMPARE(item1_c1->gestureEventsReceived, TotalGestureEventsCount-1);
1676     QCOMPARE(item1_c1->gestureOverrideEventsReceived, 1);
1677     QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount-1);
1678     QCOMPARE(item1->gestureOverrideEventsReceived, 1);
1679     QCOMPARE(item0->gestureEventsReceived, 0);
1680     QCOMPARE(item0->gestureOverrideEventsReceived, 1);
1681 }
1682
1683 void tst_Gestures::panelPropagation()
1684 {
1685     QGraphicsScene scene;
1686     QGraphicsView view(&scene);
1687     view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1688
1689     GestureItem *item0 = new GestureItem("item0");
1690     scene.addItem(item0);
1691     item0->setPos(0, 0);
1692     item0->size = QRectF(0, 0, 200, 200);
1693     item0->grabGesture(CustomGesture::GestureType);
1694     item0->setZValue(1);
1695
1696     GestureItem *item1 = new GestureItem("item1");
1697     item1->grabGesture(CustomGesture::GestureType);
1698     scene.addItem(item1);
1699     item1->setPos(10, 10);
1700     item1->size = QRectF(0, 0, 180, 180);
1701     item1->setZValue(2);
1702
1703     GestureItem *item1_child1 = new GestureItem("item1_child1[panel]");
1704     item1_child1->setFlags(QGraphicsItem::ItemIsPanel);
1705     item1_child1->setParentItem(item1);
1706     item1_child1->grabGesture(CustomGesture::GestureType);
1707     item1_child1->setPos(10, 10);
1708     item1_child1->size = QRectF(0, 0, 160, 160);
1709     item1_child1->setZValue(5);
1710
1711     GestureItem *item1_child1_child1 = new GestureItem("item1_child1_child1");
1712     item1_child1_child1->setParentItem(item1_child1);
1713     item1_child1_child1->grabGesture(CustomGesture::GestureType);
1714     item1_child1_child1->setPos(10, 10);
1715     item1_child1_child1->size = QRectF(0, 0, 140, 140);
1716     item1_child1_child1->setZValue(10);
1717
1718     view.show();
1719     QTest::qWaitForWindowShown(&view);
1720     view.ensureVisible(scene.sceneRect());
1721
1722     static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1723     static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
1724
1725     CustomEvent event;
1726     event.hotSpot = mapToGlobal(QPointF(5, 5), item1_child1_child1, &view);
1727     event.hasHotSpot = true;
1728     sendCustomGesture(&event, item0, &scene);
1729
1730     QCOMPARE(item0->customEventsReceived, TotalCustomEventsCount);
1731     QCOMPARE(item1_child1_child1->gestureEventsReceived, TotalGestureEventsCount);
1732     QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 1);
1733     QCOMPARE(item1_child1->gestureOverrideEventsReceived, 1);
1734     QCOMPARE(item1->gestureEventsReceived, 0);
1735     QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1736     QCOMPARE(item0->gestureEventsReceived, 0);
1737     QCOMPARE(item0->gestureOverrideEventsReceived, 0);
1738
1739     item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset();
1740
1741     event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view);
1742     event.hasHotSpot = true;
1743     sendCustomGesture(&event, item1, &scene);
1744
1745     QCOMPARE(item1_child1_child1->gestureEventsReceived, 0);
1746     QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0);
1747     QCOMPARE(item1_child1->gestureEventsReceived, 0);
1748     QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0);
1749     QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
1750     QCOMPARE(item1->gestureOverrideEventsReceived, 1);
1751     QCOMPARE(item0->gestureEventsReceived, 0);
1752     QCOMPARE(item0->gestureOverrideEventsReceived, 1);
1753
1754     item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset();
1755     // try with a modal panel
1756     item1_child1->setPanelModality(QGraphicsItem::PanelModal);
1757
1758     event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view);
1759     event.hasHotSpot = true;
1760     sendCustomGesture(&event, item1, &scene);
1761
1762     QCOMPARE(item1_child1_child1->gestureEventsReceived, 0);
1763     QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0);
1764     QCOMPARE(item1_child1->gestureEventsReceived, TotalGestureEventsCount);
1765     QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0);
1766     QCOMPARE(item1->gestureEventsReceived, 0);
1767     QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1768     QCOMPARE(item0->gestureEventsReceived, 0);
1769     QCOMPARE(item0->gestureOverrideEventsReceived, 0);
1770
1771     item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset();
1772     // try with a modal panel, however set the hotspot to be outside of the
1773     // panel and its parent
1774     item1_child1->setPanelModality(QGraphicsItem::PanelModal);
1775
1776     event.hotSpot = mapToGlobal(QPointF(5, 5), item0, &view);
1777     event.hasHotSpot = true;
1778     sendCustomGesture(&event, item1, &scene);
1779
1780     QCOMPARE(item1_child1_child1->gestureEventsReceived, 0);
1781     QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0);
1782     QCOMPARE(item1_child1->gestureEventsReceived, 0);
1783     QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0);
1784     QCOMPARE(item1->gestureEventsReceived, 0);
1785     QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1786     QCOMPARE(item0->gestureEventsReceived, TotalGestureEventsCount);
1787     QCOMPARE(item0->gestureOverrideEventsReceived, 0);
1788
1789     item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset();
1790     // try with a scene modal panel
1791     item1_child1->setPanelModality(QGraphicsItem::SceneModal);
1792
1793     event.hotSpot = mapToGlobal(QPointF(5, 5), item0, &view);
1794     event.hasHotSpot = true;
1795     sendCustomGesture(&event, item0, &scene);
1796
1797     QCOMPARE(item1_child1_child1->gestureEventsReceived, 0);
1798     QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0);
1799     QCOMPARE(item1_child1->gestureEventsReceived, TotalGestureEventsCount);
1800     QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0);
1801     QCOMPARE(item1->gestureEventsReceived, 0);
1802     QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1803     QCOMPARE(item0->gestureEventsReceived, 0);
1804     QCOMPARE(item0->gestureOverrideEventsReceived, 0);
1805 }
1806
1807 void tst_Gestures::panelStacksBehindParent()
1808 {
1809     QGraphicsScene scene;
1810     QGraphicsView view(&scene);
1811     view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1812
1813     GestureItem *item1 = new GestureItem("item1");
1814     item1->grabGesture(CustomGesture::GestureType);
1815     scene.addItem(item1);
1816     item1->setPos(10, 10);
1817     item1->size = QRectF(0, 0, 180, 180);
1818     item1->setZValue(2);
1819
1820     GestureItem *panel = new GestureItem("panel");
1821     panel->setFlags(QGraphicsItem::ItemIsPanel | QGraphicsItem::ItemStacksBehindParent);
1822     panel->setPanelModality(QGraphicsItem::PanelModal);
1823     panel->setParentItem(item1);
1824     panel->grabGesture(CustomGesture::GestureType);
1825     panel->setPos(-10, -10);
1826     panel->size = QRectF(0, 0, 200, 200);
1827     panel->setZValue(5);
1828
1829     view.show();
1830     QTest::qWaitForWindowShown(&view);
1831     view.ensureVisible(scene.sceneRect());
1832
1833     static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1834
1835     CustomEvent event;
1836     event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view);
1837     event.hasHotSpot = true;
1838     sendCustomGesture(&event, item1, &scene);
1839
1840     QCOMPARE(item1->gestureEventsReceived, 0);
1841     QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1842     QCOMPARE(panel->gestureEventsReceived, TotalGestureEventsCount);
1843     QCOMPARE(panel->gestureOverrideEventsReceived, 0);
1844 }
1845
1846 void tst_Gestures::deleteGestureTargetWidget()
1847 {
1848 }
1849
1850 void tst_Gestures::deleteGestureTargetItem_data()
1851 {
1852     QTest::addColumn<bool>("propagateUpdateGesture");
1853     QTest::addColumn<QString>("emitter");
1854     QTest::addColumn<QString>("receiver");
1855     QTest::addColumn<QByteArray>("signalName");
1856     QTest::addColumn<QByteArray>("slotName");
1857
1858     QByteArray gestureUpdated = SIGNAL(gestureUpdated(QEvent::Type,QGesture*));
1859     QByteArray gestureFinished = SIGNAL(gestureFinished(QEvent::Type,QGesture*));
1860     QByteArray deleteThis = SLOT(deleteThis());
1861     QByteArray deleteLater = SLOT(deleteLater());
1862
1863     QTest::newRow("delete1")
1864             << false << "item1" << "item1" << gestureUpdated << deleteThis;
1865     QTest::newRow("delete2")
1866             << false << "item2" << "item2" << gestureUpdated << deleteThis;
1867     QTest::newRow("delete3")
1868             << false << "item1" << "item2" << gestureUpdated << deleteThis;
1869
1870     QTest::newRow("deleteLater1")
1871             << false << "item1" << "item1" << gestureUpdated << deleteLater;
1872     QTest::newRow("deleteLater2")
1873             << false << "item2" << "item2" << gestureUpdated << deleteLater;
1874     QTest::newRow("deleteLater3")
1875             << false << "item1" << "item2" << gestureUpdated << deleteLater;
1876     QTest::newRow("deleteLater4")
1877             << false << "item2" << "item1" << gestureUpdated << deleteLater;
1878
1879     QTest::newRow("delete-self-and-propagate")
1880             << true << "item2" << "item2" << gestureUpdated << deleteThis;
1881     QTest::newRow("deleteLater-self-and-propagate")
1882             << true << "item2" << "item2" << gestureUpdated << deleteLater;
1883     QTest::newRow("propagate-to-deletedLater")
1884             << true << "item2" << "item1" << gestureUpdated << deleteLater;
1885 }
1886
1887 void tst_Gestures::deleteGestureTargetItem()
1888 {
1889     QFETCH(bool, propagateUpdateGesture);
1890     QFETCH(QString, emitter);
1891     QFETCH(QString, receiver);
1892     QFETCH(QByteArray, signalName);
1893     QFETCH(QByteArray, slotName);
1894
1895     QGraphicsScene scene;
1896     QGraphicsView view(&scene);
1897     view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1898
1899     GestureItem *item1 = new GestureItem("item1");
1900     item1->grabGesture(CustomGesture::GestureType);
1901     item1->setZValue(2);
1902     scene.addItem(item1);
1903
1904     GestureItem *item2 = new GestureItem("item2");
1905     item2->grabGesture(CustomGesture::GestureType);
1906     item2->setZValue(5);
1907     scene.addItem(item2);
1908
1909     QMap<QString, GestureItem *> items;
1910     items.insert(item1->objectName(), item1);
1911     items.insert(item2->objectName(), item2);
1912
1913     view.show();
1914     QTest::qWaitForWindowShown(&view);
1915     view.ensureVisible(scene.sceneRect());
1916
1917     if (propagateUpdateGesture)
1918         item2->ignoredUpdatedGestures << CustomGesture::GestureType;
1919     connect(items.value(emitter, 0), signalName, items.value(receiver, 0), slotName);
1920
1921     // some debug output to see the current test data tag, so if we crash
1922     // we know which one caused the crash.
1923     qDebug() << "<-- testing";
1924
1925     CustomEvent event;
1926     event.hotSpot = mapToGlobal(QPointF(5, 5), item2, &view);
1927     event.hasHotSpot = true;
1928     sendCustomGesture(&event, item1, &scene);
1929 }
1930
1931 class GraphicsView : public QGraphicsView
1932 {
1933 public:
1934     GraphicsView(QGraphicsScene *scene, QWidget *parent = 0)
1935         : QGraphicsView(scene, parent)
1936     {
1937     }
1938
1939     using QGraphicsView::setViewportMargins;
1940 };
1941
1942 // just making sure that even if the graphicsview has margins hotspot still
1943 // works properly. It should use viewport for converting global coordinates to
1944 // scene coordinates.
1945 void tst_Gestures::viewportCoordinates()
1946 {
1947     QGraphicsScene scene;
1948     GraphicsView view(&scene);
1949     view.setViewportMargins(10,20,15,25);
1950     view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1951
1952     GestureItem *item1 = new GestureItem("item1");
1953     item1->grabGesture(CustomGesture::GestureType);
1954     item1->size = QRectF(0, 0, 3, 3);
1955     item1->setZValue(2);
1956     scene.addItem(item1);
1957
1958     view.show();
1959     QTest::qWaitForWindowShown(&view);
1960     view.ensureVisible(scene.sceneRect());
1961
1962     CustomEvent event;
1963     event.hotSpot = mapToGlobal(item1->boundingRect().center(), item1, &view);
1964     event.hasHotSpot = true;
1965     sendCustomGesture(&event, item1, &scene);
1966     QVERIFY(item1->gestureEventsReceived != 0);
1967 }
1968
1969 void tst_Gestures::partialGesturePropagation()
1970 {
1971     QGraphicsScene scene;
1972     QGraphicsView view(&scene);
1973     view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1974
1975     GestureItem *item1 = new GestureItem("item1");
1976     item1->grabGesture(CustomGesture::GestureType);
1977     item1->setZValue(8);
1978     scene.addItem(item1);
1979
1980     GestureItem *item2 = new GestureItem("item2[partial]");
1981     item2->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures);
1982     item2->setZValue(6);
1983     scene.addItem(item2);
1984
1985     GestureItem *item3 = new GestureItem("item3");
1986     item3->grabGesture(CustomGesture::GestureType);
1987     item3->setZValue(4);
1988     scene.addItem(item3);
1989
1990     GestureItem *item4 = new GestureItem("item4[partial]");
1991     item4->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures);
1992     item4->setZValue(2);
1993     scene.addItem(item4);
1994
1995     view.show();
1996     QTest::qWaitForWindowShown(&view);
1997     view.ensureVisible(scene.sceneRect());
1998
1999     item1->ignoredUpdatedGestures << CustomGesture::GestureType;
2000
2001     CustomEvent event;
2002     event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view);
2003     event.hasHotSpot = true;
2004     sendCustomGesture(&event, item1, &scene);
2005
2006     static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
2007
2008     QCOMPARE(item1->gestureOverrideEventsReceived, 1);
2009     QCOMPARE(item2->gestureOverrideEventsReceived, 1);
2010     QCOMPARE(item3->gestureOverrideEventsReceived, 1);
2011     QCOMPARE(item4->gestureOverrideEventsReceived, 1);
2012
2013     QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
2014     QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount-2); // except for started and finished
2015     QCOMPARE(item3->gestureEventsReceived, 0);
2016     QCOMPARE(item4->gestureEventsReceived, 0);
2017 }
2018
2019 class WinNativePan : public QPanGesture {
2020 public:
2021     WinNativePan() {}
2022 };
2023
2024 class Pan : public QPanGesture {
2025 public:
2026     Pan() {}
2027 };
2028
2029 class CustomPan : public QPanGesture {
2030 public:
2031     CustomPan() {}
2032 };
2033
2034 // Recognizer for active gesture triggers on mouse press
2035 class PanRecognizer : public QGestureRecognizer {
2036 public:
2037     enum PanType { Platform, Default, Custom };
2038
2039     PanRecognizer(int id) : m_id(id) {}
2040     QGesture *create(QObject *) {
2041         switch(m_id) {
2042         case Platform: return new WinNativePan();
2043         case Default:  return new Pan();
2044         default:       return new CustomPan();
2045         }
2046     }
2047
2048     Result recognize(QGesture *, QObject *, QEvent *) { return QGestureRecognizer::Ignore; }
2049
2050     const int m_id;
2051 };
2052
2053 void tst_Gestures::testQGestureRecognizerCleanup()
2054 {
2055     // Clean first the current recognizers in QGManager
2056     QGestureRecognizer::unregisterRecognizer(Qt::PanGesture);
2057
2058     // v-- Qt singleton QGManager initialization
2059
2060     // Mimic QGestureManager: register both default and "platform" recognizers
2061     // (this is done in windows when QT_NO_NATIVE_GESTURES is not defined)
2062     PanRecognizer *def = new PanRecognizer(PanRecognizer::Default);
2063     QGestureRecognizer::registerRecognizer(def);
2064     PanRecognizer *plt = new PanRecognizer(PanRecognizer::Platform);
2065     QGestureRecognizer::registerRecognizer(plt);
2066     qDebug () << "register: default =" << def << "; platform =" << plt;
2067
2068     // ^-- Qt singleton QGManager initialization
2069
2070     // Here, application code would start
2071
2072     // Create QGV (has a QAScrollArea, which uses Qt::PanGesture)
2073     QMainWindow    *w = new QMainWindow;
2074     QGraphicsView  *v = new QGraphicsView();
2075     w->setCentralWidget(v);
2076
2077     // Unregister Qt recognizers
2078     QGestureRecognizer::unregisterRecognizer(Qt::PanGesture);
2079
2080     // Register a custom Pan recognizer
2081     //QGestureRecognizer::registerRecognizer(new PanRecognizer(PanRecognizer::Custom));
2082
2083     w->show();
2084     QTest::qWaitForWindowShown(w);
2085     delete w;
2086 }
2087
2088 class ReuseCanceledGesturesRecognizer : public QGestureRecognizer
2089 {
2090 public:
2091     enum Type {
2092         RmbAndCancelAllType,
2093         LmbType
2094     };
2095
2096     ReuseCanceledGesturesRecognizer(Type type) : m_type(type) {}
2097
2098     QGesture *create(QObject *) {
2099         QGesture *g = new QGesture;
2100         return g;
2101     }
2102
2103     Result recognize(QGesture *gesture, QObject *, QEvent *event) {
2104         QMouseEvent *me = static_cast<QMouseEvent *>(event);
2105         Qt::MouseButton mouseButton(m_type == LmbType ? Qt::LeftButton : Qt::RightButton);
2106
2107         switch(event->type()) {
2108         case QEvent::MouseButtonPress:
2109             if (me->button() == mouseButton && gesture->state() == Qt::NoGesture) {
2110                 gesture->setHotSpot(QPointF(me->globalPos()));
2111                 if (m_type == RmbAndCancelAllType)
2112                     gesture->setGestureCancelPolicy(QGesture::CancelAllInContext);
2113                 return QGestureRecognizer::TriggerGesture;
2114             }
2115             break;
2116         case QEvent::MouseButtonRelease:
2117             if (me->button() == mouseButton && gesture->state() > Qt::NoGesture)
2118                 return QGestureRecognizer::FinishGesture;
2119         default:
2120             break;
2121         }
2122         return QGestureRecognizer::Ignore;
2123     }
2124 private:
2125     Type m_type;
2126 };
2127
2128 class ReuseCanceledGesturesWidget : public QGraphicsWidget
2129 {
2130   public:
2131     ReuseCanceledGesturesWidget(Qt::GestureType gestureType = Qt::TapGesture, QGraphicsItem *parent = 0)
2132         : QGraphicsWidget(parent),
2133         m_gestureType(gestureType),
2134         m_started(0), m_updated(0), m_canceled(0), m_finished(0)
2135     {
2136     }
2137
2138     bool event(QEvent *event) {
2139         if (event->type() == QEvent::Gesture) {
2140             QGesture *gesture = static_cast<QGestureEvent*>(event)->gesture(m_gestureType);
2141             if (gesture) {
2142                 switch(gesture->state()) {
2143                 case Qt::GestureStarted: m_started++; break;
2144                 case Qt::GestureUpdated: m_updated++; break;
2145                 case Qt::GestureFinished: m_finished++; break;
2146                 case Qt::GestureCanceled: m_canceled++; break;
2147                 default: break;
2148                 }
2149             }
2150             return true;
2151         }
2152         if (event->type() == QEvent::GraphicsSceneMousePress) {
2153             return true;
2154         }
2155         return QGraphicsWidget::event(event);
2156     }
2157
2158     int started() { return m_started; }
2159     int updated() { return m_updated; }
2160     int finished() { return m_finished; }
2161     int canceled() { return m_canceled; }
2162
2163   private:
2164     Qt::GestureType m_gestureType;
2165     int m_started;
2166     int m_updated;
2167     int m_canceled;
2168     int m_finished;
2169 };
2170
2171 void tst_Gestures::testReuseCanceledGestures()
2172 {
2173     Qt::GestureType cancellingGestureTypeId = QGestureRecognizer::registerRecognizer(
2174             new ReuseCanceledGesturesRecognizer(ReuseCanceledGesturesRecognizer::RmbAndCancelAllType));
2175     Qt::GestureType tapGestureTypeId = QGestureRecognizer::registerRecognizer(
2176             new ReuseCanceledGesturesRecognizer(ReuseCanceledGesturesRecognizer::LmbType));
2177
2178     QMainWindow mw;
2179     mw.setWindowFlags(Qt::X11BypassWindowManagerHint);
2180     QGraphicsView *gv = new QGraphicsView(&mw);
2181     QGraphicsScene *scene = new QGraphicsScene;
2182
2183     gv->setScene(scene);
2184     scene->setSceneRect(0,0,100,100);
2185
2186     // Create container and add to the scene
2187     ReuseCanceledGesturesWidget *container = new ReuseCanceledGesturesWidget;
2188     container->grabGesture(cancellingGestureTypeId); // << container grabs canceling gesture
2189
2190     // Create widget and add to the scene
2191     ReuseCanceledGesturesWidget *target = new ReuseCanceledGesturesWidget(tapGestureTypeId, container);
2192     target->grabGesture(tapGestureTypeId);
2193
2194     container->setGeometry(scene->sceneRect());
2195
2196     scene->addItem(container);
2197
2198     mw.setCentralWidget(gv);
2199
2200     // Viewport needs to grab all gestures that widgets in scene grab
2201     gv->viewport()->grabGesture(cancellingGestureTypeId);
2202     gv->viewport()->grabGesture(tapGestureTypeId);
2203
2204     mw.show();
2205     QTest::qWaitForWindowShown(&mw);
2206
2207     QPoint targetPos(gv->mapFromScene(target->mapToScene(target->rect().center())));
2208     targetPos = gv->viewport()->mapFromParent(targetPos);
2209
2210     // "Tap" starts on child widget
2211     QTest::mousePress(gv->viewport(), Qt::LeftButton, 0, targetPos);
2212     QCOMPARE(target->started(),  1);
2213     QCOMPARE(target->updated(),  0);
2214     QCOMPARE(target->finished(), 0);
2215     QCOMPARE(target->canceled(), 0);
2216
2217     // Canceling gesture starts on parent
2218     QTest::mousePress(gv->viewport(), Qt::RightButton, 0, targetPos);
2219     QCOMPARE(target->started(),  1);
2220     QCOMPARE(target->updated(),  0);
2221     QCOMPARE(target->finished(), 0);
2222     QCOMPARE(target->canceled(), 1); // <- child canceled
2223
2224     // Canceling gesture ends
2225     QTest::mouseRelease(gv->viewport(), Qt::RightButton, 0, targetPos);
2226     QCOMPARE(target->started(),  1);
2227     QCOMPARE(target->updated(),  0);
2228     QCOMPARE(target->finished(), 0);
2229     QCOMPARE(target->canceled(), 1);
2230
2231     // Tap would end if not canceled
2232     QTest::mouseRelease(gv->viewport(), Qt::LeftButton, 0, targetPos);
2233     QCOMPARE(target->started(),  1);
2234     QCOMPARE(target->updated(),  0);
2235     QCOMPARE(target->finished(), 0);
2236     QCOMPARE(target->canceled(), 1);
2237
2238     // New "Tap" starts
2239     QTest::mousePress(gv->viewport(), Qt::LeftButton, 0, targetPos);
2240     QCOMPARE(target->started(),  2);
2241     QCOMPARE(target->updated(),  0);
2242     QCOMPARE(target->finished(), 0);
2243     QCOMPARE(target->canceled(), 1);
2244
2245     QTest::mouseRelease(gv->viewport(), Qt::LeftButton, 0, targetPos);
2246     QCOMPARE(target->started(),  2);
2247     QCOMPARE(target->updated(),  0);
2248     QCOMPARE(target->finished(), 1);
2249     QCOMPARE(target->canceled(), 1);
2250 }
2251
2252 void tst_Gestures::conflictingGesturesInGraphicsView()
2253 {
2254     QGraphicsScene scene;
2255     GraphicsView view(&scene);
2256     view.setWindowFlags(Qt::X11BypassWindowManagerHint);
2257
2258     GestureItem *item1 = new GestureItem("item1");
2259     item1->grabGesture(CustomGesture::GestureType);
2260     item1->size = QRectF(0, 0, 100, 100);
2261     item1->setZValue(2);
2262     scene.addItem(item1);
2263
2264     GestureItem *item2 = new GestureItem("item2");
2265     item2->grabGesture(CustomGesture::GestureType);
2266     item2->size = QRectF(0, 0, 100, 100);
2267     item2->setZValue(5);
2268     scene.addItem(item2);
2269
2270     view.show();
2271     QTest::qWaitForWindowShown(&view);
2272     view.ensureVisible(scene.sceneRect());
2273
2274     static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
2275
2276     CustomEvent event;
2277
2278     // nobody accepts override
2279     item1->acceptGestureOverride = false;
2280     item2->acceptGestureOverride = false;
2281     event.hotSpot = mapToGlobal(item2->boundingRect().center(), item2, &view);
2282     event.hasHotSpot = true;
2283     sendCustomGesture(&event, item2, &scene);
2284     QCOMPARE(item2->gestureOverrideEventsReceived, 1);
2285     QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount);
2286     QCOMPARE(item1->gestureOverrideEventsReceived, 1);
2287     QCOMPARE(item1->gestureEventsReceived, 0);
2288
2289     item1->reset(); item2->reset();
2290
2291     // the original target accepts override
2292     item1->acceptGestureOverride = false;
2293     item2->acceptGestureOverride = true;
2294     event.hotSpot = mapToGlobal(item2->boundingRect().center(), item2, &view);
2295     event.hasHotSpot = true;
2296     sendCustomGesture(&event, item2, &scene);
2297     QCOMPARE(item2->gestureOverrideEventsReceived, 1);
2298     QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount);
2299     QCOMPARE(item1->gestureOverrideEventsReceived, 0);
2300     QCOMPARE(item1->gestureEventsReceived, 0);
2301
2302     item1->reset(); item2->reset();
2303
2304     // the item behind accepts override
2305     item1->acceptGestureOverride = true;
2306     item2->acceptGestureOverride = false;
2307     event.hotSpot = mapToGlobal(item2->boundingRect().center(), item2, &view);
2308     event.hasHotSpot = true;
2309     sendCustomGesture(&event, item2, &scene);
2310
2311     QCOMPARE(item2->gestureOverrideEventsReceived, 1);
2312     QCOMPARE(item2->gestureEventsReceived, 0);
2313     QCOMPARE(item1->gestureOverrideEventsReceived, 1);
2314     QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
2315 }
2316
2317 class NoConsumeWidgetBug13501 :public QWidget
2318 {
2319     Q_OBJECT
2320 protected:
2321     bool event(QEvent *e) {
2322         if(e->type() == QEvent::Gesture) {
2323             return false;
2324         }
2325         return QWidget::event(e);
2326     }
2327 };
2328
2329 void tst_Gestures::bug_13501_gesture_not_accepted()
2330 {
2331     // Create a gesture event that is not accepted by any widget
2332     // make sure this does not lead to an assert in QGestureManager
2333     NoConsumeWidgetBug13501 w;
2334     w.grabGesture(Qt::TapGesture);
2335     w.show();
2336     QTest::qWaitForWindowShown(&w);
2337     //QTest::mousePress(&ignoreEvent, Qt::LeftButton);
2338     QTouchDevice *device = new QTouchDevice;
2339     device->setType(QTouchDevice::TouchScreen);
2340     QWindowSystemInterface::registerTouchDevice(device);
2341     QTest::touchEvent(&w, device).press(0, QPoint(10, 10), &w);
2342 }
2343
2344 QTEST_MAIN(tst_Gestures)
2345 #include "tst_gestures.moc"