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