1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the test suite of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
43 #include <QtTest/QtTest>
44 #include <QtTest/qtesttouch.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>
59 static QPointF mapToGlobal(const QPointF &pt, QGraphicsItem *item, QGraphicsView *view)
61 return view->viewport()->mapToGlobal(view->mapFromScene(item->mapToScene(pt)));
64 class CustomGesture : public QGesture
68 static Qt::GestureType GestureType;
70 CustomGesture(QObject *parent = 0)
71 : QGesture(parent), serial(0)
77 static const int SerialMaybeThreshold;
78 static const int SerialStartedThreshold;
79 static const int SerialFinishedThreshold;
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;
86 class CustomEvent : public QEvent
91 explicit CustomEvent(int serial_ = 0)
92 : QEvent(QEvent::Type(CustomEvent::EventType)),
93 serial(serial_), hasHotSpot(false)
101 int CustomEvent::EventType = 0;
103 class CustomGestureRecognizer : public QGestureRecognizer
106 static bool ConsumeEvents;
108 CustomGestureRecognizer()
110 if (!CustomEvent::EventType)
111 CustomEvent::EventType = QEvent::registerEventType();
114 QGesture* create(QObject *)
116 return new CustomGesture;
119 QGestureRecognizer::Result recognize(QGesture *state, QObject*, QEvent *event)
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;
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;
137 result = QGestureRecognizer::CancelGesture;
140 return QGestureRecognizer::Ignore;
143 void reset(QGesture *state)
145 CustomGesture *g = static_cast<CustomGesture *>(state);
147 QGestureRecognizer::reset(state);
150 bool CustomGestureRecognizer::ConsumeEvents = false;
152 // same as CustomGestureRecognizer but triggers early without the maybe state
153 class CustomContinuousGestureRecognizer : public QGestureRecognizer
156 CustomContinuousGestureRecognizer()
158 if (!CustomEvent::EventType)
159 CustomEvent::EventType = QEvent::registerEventType();
162 QGesture* create(QObject *)
164 return new CustomGesture;
167 QGestureRecognizer::Result recognize(QGesture *state, QObject*, QEvent *event)
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;
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;
181 result = QGestureRecognizer::CancelGesture;
184 return QGestureRecognizer::Ignore;
187 void reset(QGesture *state)
189 CustomGesture *g = static_cast<CustomGesture *>(state);
191 QGestureRecognizer::reset(state);
195 class GestureWidget : public QWidget
199 GestureWidget(const char *name = 0, QWidget *parent = 0)
203 setObjectName(QLatin1String(name));
205 acceptGestureOverride = false;
209 customEventsReceived = 0;
210 gestureEventsReceived = 0;
211 gestureOverrideEventsReceived = 0;
213 overrideEvents.clear();
214 ignoredGestures.clear();
217 int customEventsReceived;
218 int gestureEventsReceived;
219 int gestureOverrideEventsReceived;
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;
236 } events, overrideEvents;
238 bool acceptGestureOverride;
239 QSet<Qt::GestureType> ignoredGestures;
242 bool event(QEvent *event)
244 Events *eventsPtr = 0;
245 if (event->type() == QEvent::Gesture) {
246 QGestureEvent *e = static_cast<QGestureEvent*>(event);
247 ++gestureEventsReceived;
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)
258 QGestureEvent *e = static_cast<QGestureEvent*>(event);
259 QList<QGesture*> gestures = e->gestures();
260 foreach(QGesture *g, gestures) {
261 eventsPtr->all << g->gestureType();
263 case Qt::GestureStarted:
264 emit gestureStarted(e->type(), g);
265 eventsPtr->started << g->gestureType();
267 case Qt::GestureUpdated:
268 emit gestureUpdated(e->type(), g);
269 eventsPtr->updated << g->gestureType();
271 case Qt::GestureFinished:
272 emit gestureFinished(e->type(), g);
273 eventsPtr->finished << g->gestureType();
275 case Qt::GestureCanceled:
276 emit gestureCanceled(e->type(), g);
277 eventsPtr->canceled << g->gestureType();
280 qWarning() << "Unknown GestureState enum value:" << static_cast<int>(g->state());
283 } else if (event->type() == CustomEvent::EventType) {
284 ++customEventsReceived;
286 return QWidget::event(event);
292 void gestureStarted(QEvent::Type, QGesture *);
293 void gestureUpdated(QEvent::Type, QGesture *);
294 void gestureFinished(QEvent::Type, QGesture *);
295 void gestureCanceled(QEvent::Type, QGesture *);
298 void deleteThis() { delete this; }
301 // TODO rename to sendGestureSequence
302 static void sendCustomGesture(CustomEvent *event, QObject *object, QGraphicsScene *scene = 0)
304 QPointer<QObject> receiver(object);
305 for (int i = CustomGesture::SerialMaybeThreshold;
306 i <= CustomGesture::SerialFinishedThreshold && receiver; ++i) {
309 scene->sendEvent(qobject_cast<QGraphicsObject *>(object), event);
311 QApplication::sendEvent(object, event);
315 class tst_Gestures : public QObject
321 virtual ~tst_Gestures();
325 void cleanupTestCase();
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();
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();
365 tst_Gestures::tst_Gestures()
369 tst_Gestures::~tst_Gestures()
373 void tst_Gestures::initTestCase()
375 CustomGesture::GestureType = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
376 QVERIFY(CustomGesture::GestureType != Qt::GestureType(0));
377 QVERIFY(CustomGesture::GestureType != Qt::CustomGesture);
380 void tst_Gestures::cleanupTestCase()
382 QGestureRecognizer::unregisterRecognizer(CustomGesture::GestureType);
385 void tst_Gestures::init()
389 void tst_Gestures::cleanup()
393 void tst_Gestures::customGesture()
395 GestureWidget widget;
396 widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
398 QVERIFY(QTest::qWaitForWindowExposed(&widget));
401 event.hotSpot = widget.mapToGlobal(QPoint(5,5));
402 event.hasHotSpot = true;
403 sendCustomGesture(&event, &widget);
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);
419 void tst_Gestures::consumeEventHint()
421 GestureWidget widget;
422 widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
424 CustomGestureRecognizer::ConsumeEvents = true;
426 sendCustomGesture(&event, &widget);
427 CustomGestureRecognizer::ConsumeEvents = false;
429 QCOMPARE(widget.customEventsReceived, 0);
432 void tst_Gestures::autoCancelingGestures()
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.
439 for (int i = CustomGesture::SerialMaybeThreshold;
440 i < CustomGesture::SerialStartedThreshold; ++i) {
442 QApplication::sendEvent(&widget, &ev);
444 // wait long enough so the gesture manager will cancel the gesture
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);
452 void tst_Gestures::gestureOverChild()
454 GestureWidget widget("widget");
455 QVBoxLayout *l = new QVBoxLayout(&widget);
456 GestureWidget *child = new GestureWidget("child");
459 widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
462 sendCustomGesture(&event, child);
464 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
465 static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
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);
474 // enable gestures over the children
475 widget.grabGesture(CustomGesture::GestureType);
480 sendCustomGesture(&event, child);
482 QCOMPARE(child->customEventsReceived, TotalCustomEventsCount);
483 QCOMPARE(widget.customEventsReceived, 0);
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);
497 void tst_Gestures::multipleWidgetOnlyGestureInTree()
499 GestureWidget parent("parent");
500 QVBoxLayout *l = new QVBoxLayout(&parent);
501 GestureWidget *child = new GestureWidget("child");
504 parent.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
505 child->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
507 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
508 static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
510 // sending events to the child and making sure there is no conflict
512 sendCustomGesture(&event, child);
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);
524 // same for the parent widget
525 sendCustomGesture(&event, &parent);
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);
535 void tst_Gestures::conflictingGestures()
537 GestureWidget parent("parent");
538 QVBoxLayout *l = new QVBoxLayout(&parent);
539 GestureWidget *child = new GestureWidget("child");
542 parent.grabGesture(CustomGesture::GestureType);
543 child->grabGesture(CustomGesture::GestureType);
545 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
547 // child accepts the override, parent will not receive anything
548 parent.acceptGestureOverride = false;
549 child->acceptGestureOverride = true;
551 // sending events to the child and making sure there is no conflict
553 sendCustomGesture(&event, child);
555 QCOMPARE(child->gestureOverrideEventsReceived, 1);
556 QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount);
557 QCOMPARE(parent.gestureOverrideEventsReceived, 0);
558 QCOMPARE(parent.gestureEventsReceived, 0);
563 // parent accepts the override
564 parent.acceptGestureOverride = true;
565 child->acceptGestureOverride = false;
567 // sending events to the child and making sure there is no conflict
568 sendCustomGesture(&event, child);
570 QCOMPARE(child->gestureOverrideEventsReceived, 1);
571 QCOMPARE(child->gestureEventsReceived, 0);
572 QCOMPARE(parent.gestureOverrideEventsReceived, 1);
573 QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount);
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;
585 // sending events to the child and making sure there is no conflict
586 sendCustomGesture(&event, child);
588 QCOMPARE(child->gestureOverrideEventsReceived, 1);
589 QCOMPARE(child->gestureEventsReceived, 1);
590 QCOMPARE(parent.gestureOverrideEventsReceived, 1);
591 QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount);
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;
602 // sending events to the child and making sure there is no conflict
603 sendCustomGesture(&event, child);
605 QCOMPARE(child->gestureOverrideEventsReceived, 1);
606 QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount);
607 QCOMPARE(parent.gestureOverrideEventsReceived, 1);
608 QCOMPARE(parent.gestureEventsReceived, 1);
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;
620 // sending events to the child and making sure there is no conflict
621 sendCustomGesture(&event, child);
623 QCOMPARE(child->gestureOverrideEventsReceived, 1);
624 QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount);
625 QCOMPARE(parent.gestureOverrideEventsReceived, 1);
626 QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount);
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);
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);
645 QGestureRecognizer::unregisterRecognizer(ContinuousGesture);
648 void tst_Gestures::finishedWithoutStarted()
650 GestureWidget widget;
651 widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
653 // the gesture will claim it finished, but it was never started.
655 ev.serial = CustomGesture::SerialFinishedThreshold;
656 QApplication::sendEvent(&widget, &ev);
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);
668 void tst_Gestures::unknownGesture()
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);
676 sendCustomGesture(&event, &widget);
678 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
680 QCOMPARE(widget.gestureEventsReceived, TotalGestureEventsCount);
683 static const QColor InstanceColors[] = {
684 Qt::blue, Qt::red, Qt::green, Qt::gray, Qt::yellow
687 class GestureItem : public QGraphicsObject
690 static int InstanceCount;
692 GestureItem(const char *name = 0)
694 instanceNumber = InstanceCount++;
696 setObjectName(QLatin1String(name));
699 size = QRectF(0, 0, 100, 100);
700 customEventsReceived = 0;
701 gestureEventsReceived = 0;
702 gestureOverrideEventsReceived = 0;
704 overrideEvents.clear();
705 acceptGestureOverride = false;
714 int customEventsReceived;
715 int gestureEventsReceived;
716 int gestureOverrideEventsReceived;
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;
733 } events, overrideEvents;
735 bool acceptGestureOverride;
736 QSet<Qt::GestureType> ignoredGestures;
737 QSet<Qt::GestureType> ignoredStartedGestures;
738 QSet<Qt::GestureType> ignoredUpdatedGestures;
739 QSet<Qt::GestureType> ignoredFinishedGestures;
746 customEventsReceived = 0;
747 gestureEventsReceived = 0;
748 gestureOverrideEventsReceived = 0;
750 overrideEvents.clear();
751 ignoredGestures.clear();
752 ignoredStartedGestures.clear();
753 ignoredUpdatedGestures.clear();
754 ignoredFinishedGestures.clear();
757 QRectF boundingRect() const
761 void paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
763 QColor color = InstanceColors[instanceNumber % (sizeof(InstanceColors)/sizeof(InstanceColors[0]))];
764 p->fillRect(boundingRect(), color);
767 bool event(QEvent *event)
769 Events *eventsPtr = 0;
770 if (event->type() == QEvent::Gesture) {
771 ++gestureEventsReceived;
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()))
782 case Qt::GestureUpdated:
783 if (ignoredUpdatedGestures.contains(g->gestureType()))
786 case Qt::GestureFinished:
787 if (ignoredFinishedGestures.contains(g->gestureType()))
794 } else if (event->type() == QEvent::GestureOverride) {
795 ++gestureOverrideEventsReceived;
796 eventsPtr = &overrideEvents;
797 if (acceptGestureOverride)
801 QGestureEvent *e = static_cast<QGestureEvent*>(event);
802 QList<QGesture*> gestures = e->gestures();
803 foreach(QGesture *g, gestures) {
804 eventsPtr->all << g->gestureType();
806 case Qt::GestureStarted:
807 eventsPtr->started << g->gestureType();
808 emit gestureStarted(e->type(), g);
810 case Qt::GestureUpdated:
811 eventsPtr->updated << g->gestureType();
812 emit gestureUpdated(e->type(), g);
814 case Qt::GestureFinished:
815 eventsPtr->finished << g->gestureType();
816 emit gestureFinished(e->type(), g);
818 case Qt::GestureCanceled:
819 eventsPtr->canceled << g->gestureType();
820 emit gestureCanceled(e->type(), g);
823 qWarning() << "Unknown GestureState enum value:" << static_cast<int>(g->state());
826 } else if (event->type() == CustomEvent::EventType) {
827 ++customEventsReceived;
829 return QGraphicsObject::event(event);
835 void gestureStarted(QEvent::Type, QGesture *);
836 void gestureUpdated(QEvent::Type, QGesture *);
837 void gestureFinished(QEvent::Type, QGesture *);
838 void gestureCanceled(QEvent::Type, QGesture *);
841 // some arguments for the slots below:
842 QGraphicsScene *scene;
845 void deleteThis() { delete this; }
846 void addSelfToScene(QEvent::Type eventType, QGesture *)
848 if (eventType == QEvent::Gesture) {
849 disconnect(sender(), 0, this, SLOT(addSelfToScene(QEvent::Type,QGesture*)));
850 scene->addItem(this);
854 int GestureItem::InstanceCount = 0;
856 void tst_Gestures::graphicsItemGesture()
858 QGraphicsScene scene;
859 QGraphicsView view(&scene);
860 view.setWindowFlags(Qt::X11BypassWindowManagerHint);
862 GestureItem *item = new GestureItem("item");
864 item->setPos(100, 100);
867 QVERIFY(QTest::qWaitForWindowExposed(&view));
868 view.ensureVisible(scene.sceneRect());
870 item->grabGesture(CustomGesture::GestureType);
872 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
873 static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
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);
883 QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
884 QCOMPARE(item->gestureEventsReceived, 0);
885 QCOMPARE(item->gestureOverrideEventsReceived, 0);
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);
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);
907 // send gesture to the item which ignores it.
908 item->ignoredGestures << CustomGesture::GestureType;
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);
918 void tst_Gestures::graphicsView()
920 QGraphicsScene scene;
921 QGraphicsView view(&scene);
922 view.setWindowFlags(Qt::X11BypassWindowManagerHint);
924 GestureItem *item = new GestureItem("item");
926 item->setPos(100, 100);
929 QVERIFY(QTest::qWaitForWindowExposed(&view));
930 view.ensureVisible(scene.sceneRect());
932 item->grabGesture(CustomGesture::GestureType);
934 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
935 static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
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);
943 QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
944 QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount);
945 QCOMPARE(item->gestureOverrideEventsReceived, 0);
947 // change the viewport and try again
948 QWidget *newViewport = new QWidget;
949 view.setViewport(newViewport);
952 sendCustomGesture(&event, item, &scene);
954 QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
955 QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount);
956 QCOMPARE(item->gestureOverrideEventsReceived, 0);
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);
966 // first without a gesture
967 sendCustomGesture(&event, item, &newScene);
969 QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
970 QCOMPARE(item->gestureEventsReceived, 0);
971 QCOMPARE(item->gestureOverrideEventsReceived, 0);
973 // then grab the gesture and try again
975 item->grabGesture(CustomGesture::GestureType);
976 sendCustomGesture(&event, item, &newScene);
978 QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
979 QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount);
980 QCOMPARE(item->gestureOverrideEventsReceived, 0);
983 void tst_Gestures::graphicsItemTreeGesture()
985 QGraphicsScene scene;
986 QGraphicsView view(&scene);
987 view.setWindowFlags(Qt::X11BypassWindowManagerHint);
989 GestureItem *item1 = new GestureItem("item1");
990 item1->setPos(100, 100);
991 item1->size = QRectF(0, 0, 350, 200);
992 scene.addItem(item1);
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);
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);
1005 QVERIFY(QTest::qWaitForWindowExposed(&view));
1006 view.ensureVisible(scene.sceneRect());
1008 item1->grabGesture(CustomGesture::GestureType);
1010 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1013 event.hotSpot = mapToGlobal(QPointF(10, 10), item1_child1, &view);
1014 event.hasHotSpot = true;
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);
1025 item1->reset(); item1_child1->reset(); item1_child2->reset();
1027 item1_child1->grabGesture(CustomGesture::GestureType);
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);
1040 void tst_Gestures::explicitGraphicsObjectTarget()
1042 QGraphicsScene scene;
1043 QGraphicsView view(&scene);
1044 view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1046 GestureItem *item1 = new GestureItem("item1");
1047 scene.addItem(item1);
1048 item1->setPos(100, 100);
1049 item1->setZValue(1);
1051 GestureItem *item2 = new GestureItem("item2");
1052 scene.addItem(item2);
1053 item2->setPos(100, 100);
1054 item2->setZValue(5);
1056 GestureItem *item2_child1 = new GestureItem("item2_child1");
1057 scene.addItem(item2_child1);
1058 item2_child1->setParentItem(item2);
1059 item2_child1->setPos(10, 10);
1062 QVERIFY(QTest::qWaitForWindowExposed(&view));
1063 view.ensureVisible(scene.sceneRect());
1065 item1->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
1066 item2->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
1067 item2_child1->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
1069 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1071 // sending events to item1, but the hotSpot is set to item2
1073 event.hotSpot = mapToGlobal(QPointF(15, 15), item2, &view);
1074 event.hasHotSpot = true;
1076 sendCustomGesture(&event, item1, &scene);
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);
1093 void tst_Gestures::gestureOverChildGraphicsItem()
1095 QGraphicsScene scene;
1096 QGraphicsView view(&scene);
1097 view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1099 GestureItem *item0 = new GestureItem("item0");
1100 scene.addItem(item0);
1101 item0->setPos(0, 0);
1102 item0->grabGesture(CustomGesture::GestureType);
1103 item0->setZValue(1);
1105 GestureItem *item1 = new GestureItem("item1");
1106 scene.addItem(item1);
1107 item1->setPos(100, 100);
1108 item1->setZValue(5);
1110 GestureItem *item2 = new GestureItem("item2");
1111 scene.addItem(item2);
1112 item2->setPos(100, 100);
1113 item2->setZValue(10);
1115 GestureItem *item2_child1 = new GestureItem("item2_child1");
1116 scene.addItem(item2_child1);
1117 item2_child1->setParentItem(item2);
1118 item2_child1->setPos(0, 0);
1121 QVERIFY(QTest::qWaitForWindowExposed(&view));
1122 view.ensureVisible(scene.sceneRect());
1124 item1->grabGesture(CustomGesture::GestureType);
1126 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1127 static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
1130 event.hotSpot = mapToGlobal(QPointF(10, 10), item2_child1, &view);
1131 event.hasHotSpot = true;
1132 sendCustomGesture(&event, item0, &scene);
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);
1142 item0->reset(); item1->reset(); item2->reset(); item2_child1->reset();
1143 item2->grabGesture(CustomGesture::GestureType);
1144 item2->ignoredGestures << CustomGesture::GestureType;
1146 event.hotSpot = mapToGlobal(QPointF(10, 10), item2_child1, &view);
1147 event.hasHotSpot = true;
1148 sendCustomGesture(&event, item0, &scene);
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);
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;
1162 event.hotSpot = mapToGlobal(QPointF(10, 10), item2_child1, &view);
1163 event.hasHotSpot = true;
1164 sendCustomGesture(&event, item0, &scene);
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);
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);
1179 event.hotSpot = mapToGlobal(QPointF(10, 10), item2_child1, &view);
1180 event.hasHotSpot = true;
1181 sendCustomGesture(&event, item0, &scene);
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);
1191 void tst_Gestures::twoGesturesOnDifferentLevel()
1193 GestureWidget parent("parent");
1194 QVBoxLayout *l = new QVBoxLayout(&parent);
1195 GestureWidget *child = new GestureWidget("child");
1196 l->addWidget(child);
1198 Qt::GestureType SecondGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1200 parent.grabGesture(CustomGesture::GestureType);
1201 child->grabGesture(SecondGesture);
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);
1210 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1211 static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
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);
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);
1226 QGestureRecognizer::unregisterRecognizer(SecondGesture);
1229 void tst_Gestures::multipleGesturesInTree()
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);
1237 Qt::GestureType FirstGesture = CustomGesture::GestureType;
1238 Qt::GestureType SecondGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1239 Qt::GestureType ThirdGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
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);
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;
1259 sendCustomGesture(&event, D);
1261 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
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);
1268 QCOMPARE(C->overrideEvents.all.count(FirstGesture), 1);
1269 QCOMPARE(C->overrideEvents.all.count(SecondGesture), 1);
1270 QCOMPARE(C->overrideEvents.all.count(ThirdGesture), 1);
1272 QCOMPARE(B->overrideEvents.all.count(FirstGesture), 0);
1273 QCOMPARE(B->overrideEvents.all.count(SecondGesture), 1);
1274 QCOMPARE(B->overrideEvents.all.count(ThirdGesture), 1);
1276 QCOMPARE(A->overrideEvents.all.count(FirstGesture), 1);
1277 QCOMPARE(A->overrideEvents.all.count(SecondGesture), 0);
1278 QCOMPARE(A->overrideEvents.all.count(ThirdGesture), 1);
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);
1285 QCOMPARE(C->events.all.count(FirstGesture), TotalGestureEventsCount);
1286 QCOMPARE(C->events.all.count(SecondGesture), TotalGestureEventsCount);
1287 QCOMPARE(C->events.all.count(ThirdGesture), TotalGestureEventsCount);
1289 QCOMPARE(B->events.all.count(FirstGesture), 0);
1290 QCOMPARE(B->events.all.count(SecondGesture), TotalGestureEventsCount);
1291 QCOMPARE(B->events.all.count(ThirdGesture), TotalGestureEventsCount);
1293 QCOMPARE(A->events.all.count(FirstGesture), TotalGestureEventsCount);
1294 QCOMPARE(A->events.all.count(SecondGesture), 0);
1295 QCOMPARE(A->events.all.count(ThirdGesture), TotalGestureEventsCount);
1297 QGestureRecognizer::unregisterRecognizer(SecondGesture);
1298 QGestureRecognizer::unregisterRecognizer(ThirdGesture);
1301 void tst_Gestures::multipleGesturesInComplexTree()
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);
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);
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);
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;
1340 sendCustomGesture(&event, D);
1342 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
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);
1349 QCOMPARE(C->overrideEvents.all.count(FirstGesture), 1);
1350 QCOMPARE(C->overrideEvents.all.count(SecondGesture), 1);
1351 QCOMPARE(C->overrideEvents.all.count(ThirdGesture), 1);
1353 QCOMPARE(B->overrideEvents.all.count(FirstGesture), 0);
1354 QCOMPARE(B->overrideEvents.all.count(SecondGesture), 1);
1355 QCOMPARE(B->overrideEvents.all.count(ThirdGesture), 1);
1357 QCOMPARE(A->overrideEvents.all.count(FirstGesture), 1);
1358 QCOMPARE(A->overrideEvents.all.count(SecondGesture), 0);
1359 QCOMPARE(A->overrideEvents.all.count(ThirdGesture), 1);
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);
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);
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);
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);
1394 QGestureRecognizer::unregisterRecognizer(SecondGesture);
1395 QGestureRecognizer::unregisterRecognizer(ThirdGesture);
1396 QGestureRecognizer::unregisterRecognizer(FourthGesture);
1397 QGestureRecognizer::unregisterRecognizer(FifthGesture);
1398 QGestureRecognizer::unregisterRecognizer(SixthGesture);
1399 QGestureRecognizer::unregisterRecognizer(SeventhGesture);
1402 void tst_Gestures::testMapToScene()
1405 QList<QGesture*> list;
1407 QGestureEvent event(list);
1408 QCOMPARE(event.mapToGraphicsScene(gesture.hotSpot()), QPointF()); // not set, can't do much
1410 QGraphicsScene scene;
1411 QGraphicsView view(&scene);
1412 view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1414 GestureItem *item0 = new GestureItem;
1415 scene.addItem(item0);
1416 item0->setPos(14, 16);
1418 view.show(); // need to show to give it a global coordinate
1419 QVERIFY(QTest::qWaitForWindowExposed(&view));
1420 view.ensureVisible(scene.sceneRect());
1422 QPoint origin = view.mapToGlobal(QPoint());
1423 event.setWidget(view.viewport());
1425 QCOMPARE(event.mapToGraphicsScene(origin + QPoint(100, 200)), view.mapToScene(QPoint(100, 200)));
1428 void tst_Gestures::ungrabGesture() // a method on QWidget
1430 class MockGestureWidget : public GestureWidget {
1432 MockGestureWidget(const char *name = 0, QWidget *parent = 0)
1433 : GestureWidget(name, parent) { }
1436 QSet<QGesture*> gestures;
1438 bool event(QEvent *event)
1440 if (event->type() == QEvent::Gesture) {
1441 QGestureEvent *gestureEvent = static_cast<QGestureEvent*>(event);
1443 foreach (QGesture *g, gestureEvent->gestures())
1446 return GestureWidget::event(event);
1450 MockGestureWidget parent("A");
1451 MockGestureWidget *a = &parent;
1452 MockGestureWidget *b = new MockGestureWidget("B", a);
1454 a->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
1455 b->grabGesture(CustomGesture::GestureType);
1456 b->ignoredGestures << CustomGesture::GestureType;
1459 // sending an event will cause the QGesture objects to be instantiated for the widgets
1460 sendCustomGesture(&event, b);
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);
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);
1475 a->gestures.clear();
1476 // sending an event will cause the QGesture objects to be instantiated for the widget
1477 sendCustomGesture(&event, a);
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());
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());
1489 a->gestures.clear();
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);
1499 void tst_Gestures::unregisterRecognizer() // a method on QApplication
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.
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)
1514 void tst_Gestures::autoCancelGestures()
1516 class MockWidget : public GestureWidget {
1518 MockWidget(const char *name) : GestureWidget(name), badGestureEvents(0) { }
1520 bool event(QEvent *event)
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);
1528 return GestureWidget::event(event);
1531 int badGestureEvents;
1534 const Qt::GestureType secondGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
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);
1542 parent.grabGesture(CustomGesture::GestureType);
1543 child->grabGesture(secondGesture);
1545 QVERIFY(QTest::qWaitForWindowExposed(&parent));
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.
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);
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);
1569 void tst_Gestures::autoCancelGestures2()
1571 class MockItem : public GestureItem {
1573 MockItem(const char *name) : GestureItem(name), badGestureEvents(0) { }
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);
1582 return GestureItem::event(event);
1585 int badGestureEvents;
1588 const Qt::GestureType secondGesture = QGestureRecognizer ::registerRecognizer(new CustomGestureRecognizer);
1590 QGraphicsScene scene;
1591 QGraphicsView view(&scene);
1592 view.setWindowFlags(Qt::X11BypassWindowManagerHint);
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);
1604 QVERIFY(QTest::qWaitForWindowExposed(&view));
1605 view.ensureVisible(scene.sceneRect());
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);
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);
1624 void tst_Gestures::graphicsViewParentPropagation()
1626 QGraphicsScene scene;
1627 QGraphicsView view(&scene);
1628 view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1630 GestureItem *item0 = new GestureItem("item0");
1631 scene.addItem(item0);
1632 item0->setPos(0, 0);
1633 item0->grabGesture(CustomGesture::GestureType);
1634 item0->setZValue(1);
1636 GestureItem *item1 = new GestureItem("item1");
1637 scene.addItem(item1);
1638 item1->setPos(0, 0);
1639 item1->setZValue(5);
1641 GestureItem *item1_c1 = new GestureItem("item1_child1");
1642 item1_c1->setParentItem(item1);
1643 item1_c1->setPos(0, 0);
1645 GestureItem *item1_c1_c1 = new GestureItem("item1_child1_child1");
1646 item1_c1_c1->setParentItem(item1_c1);
1647 item1_c1_c1->setPos(0, 0);
1650 QVERIFY(QTest::qWaitForWindowExposed(&view));
1651 view.ensureVisible(scene.sceneRect());
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);
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;
1667 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1670 event.hotSpot = mapToGlobal(QPointF(10, 10), item1_c1, &view);
1671 event.hasHotSpot = true;
1672 sendCustomGesture(&event, item0, &scene);
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);
1684 void tst_Gestures::panelPropagation()
1686 QGraphicsScene scene;
1687 QGraphicsView view(&scene);
1688 view.setWindowFlags(Qt::X11BypassWindowManagerHint);
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);
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);
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);
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);
1720 QVERIFY(QTest::qWaitForWindowExposed(&view));
1721 view.ensureVisible(scene.sceneRect());
1723 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1724 static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
1727 event.hotSpot = mapToGlobal(QPointF(5, 5), item1_child1_child1, &view);
1728 event.hasHotSpot = true;
1729 sendCustomGesture(&event, item0, &scene);
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);
1740 item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset();
1742 event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view);
1743 event.hasHotSpot = true;
1744 sendCustomGesture(&event, item1, &scene);
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);
1755 item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset();
1756 // try with a modal panel
1757 item1_child1->setPanelModality(QGraphicsItem::PanelModal);
1759 event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view);
1760 event.hasHotSpot = true;
1761 sendCustomGesture(&event, item1, &scene);
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);
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);
1777 event.hotSpot = mapToGlobal(QPointF(5, 5), item0, &view);
1778 event.hasHotSpot = true;
1779 sendCustomGesture(&event, item1, &scene);
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);
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);
1794 event.hotSpot = mapToGlobal(QPointF(5, 5), item0, &view);
1795 event.hasHotSpot = true;
1796 sendCustomGesture(&event, item0, &scene);
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);
1808 void tst_Gestures::panelStacksBehindParent()
1810 QGraphicsScene scene;
1811 QGraphicsView view(&scene);
1812 view.setWindowFlags(Qt::X11BypassWindowManagerHint);
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);
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);
1831 QVERIFY(QTest::qWaitForWindowExposed(&view));
1832 view.ensureVisible(scene.sceneRect());
1834 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1837 event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view);
1838 event.hasHotSpot = true;
1839 sendCustomGesture(&event, item1, &scene);
1841 QCOMPARE(item1->gestureEventsReceived, 0);
1842 QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1843 QCOMPARE(panel->gestureEventsReceived, TotalGestureEventsCount);
1844 QCOMPARE(panel->gestureOverrideEventsReceived, 0);
1847 void tst_Gestures::deleteGestureTargetWidget()
1851 void tst_Gestures::deleteGestureTargetItem_data()
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");
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());
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;
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;
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;
1888 void tst_Gestures::deleteGestureTargetItem()
1890 QFETCH(bool, propagateUpdateGesture);
1891 QFETCH(QString, emitter);
1892 QFETCH(QString, receiver);
1893 QFETCH(QByteArray, signalName);
1894 QFETCH(QByteArray, slotName);
1896 QGraphicsScene scene;
1897 QGraphicsView view(&scene);
1898 view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1900 GestureItem *item1 = new GestureItem("item1");
1901 item1->grabGesture(CustomGesture::GestureType);
1902 item1->setZValue(2);
1903 scene.addItem(item1);
1905 GestureItem *item2 = new GestureItem("item2");
1906 item2->grabGesture(CustomGesture::GestureType);
1907 item2->setZValue(5);
1908 scene.addItem(item2);
1910 QMap<QString, GestureItem *> items;
1911 items.insert(item1->objectName(), item1);
1912 items.insert(item2->objectName(), item2);
1915 QVERIFY(QTest::qWaitForWindowExposed(&view));
1916 view.ensureVisible(scene.sceneRect());
1918 if (propagateUpdateGesture)
1919 item2->ignoredUpdatedGestures << CustomGesture::GestureType;
1920 connect(items.value(emitter, 0), signalName, items.value(receiver, 0), slotName);
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";
1927 event.hotSpot = mapToGlobal(QPointF(5, 5), item2, &view);
1928 event.hasHotSpot = true;
1929 sendCustomGesture(&event, item1, &scene);
1932 class GraphicsView : public QGraphicsView
1935 GraphicsView(QGraphicsScene *scene, QWidget *parent = 0)
1936 : QGraphicsView(scene, parent)
1940 using QGraphicsView::setViewportMargins;
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()
1948 QGraphicsScene scene;
1949 GraphicsView view(&scene);
1950 view.setViewportMargins(10,20,15,25);
1951 view.setWindowFlags(Qt::X11BypassWindowManagerHint);
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);
1960 QVERIFY(QTest::qWaitForWindowExposed(&view));
1961 view.ensureVisible(scene.sceneRect());
1964 event.hotSpot = mapToGlobal(item1->boundingRect().center(), item1, &view);
1965 event.hasHotSpot = true;
1966 sendCustomGesture(&event, item1, &scene);
1967 QVERIFY(item1->gestureEventsReceived != 0);
1970 void tst_Gestures::partialGesturePropagation()
1972 QGraphicsScene scene;
1973 QGraphicsView view(&scene);
1974 view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1976 GestureItem *item1 = new GestureItem("item1");
1977 item1->grabGesture(CustomGesture::GestureType);
1978 item1->setZValue(8);
1979 scene.addItem(item1);
1981 GestureItem *item2 = new GestureItem("item2[partial]");
1982 item2->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures);
1983 item2->setZValue(6);
1984 scene.addItem(item2);
1986 GestureItem *item3 = new GestureItem("item3");
1987 item3->grabGesture(CustomGesture::GestureType);
1988 item3->setZValue(4);
1989 scene.addItem(item3);
1991 GestureItem *item4 = new GestureItem("item4[partial]");
1992 item4->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures);
1993 item4->setZValue(2);
1994 scene.addItem(item4);
1997 QVERIFY(QTest::qWaitForWindowExposed(&view));
1998 view.ensureVisible(scene.sceneRect());
2000 item1->ignoredUpdatedGestures << CustomGesture::GestureType;
2003 event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view);
2004 event.hasHotSpot = true;
2005 sendCustomGesture(&event, item1, &scene);
2007 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
2009 QCOMPARE(item1->gestureOverrideEventsReceived, 1);
2010 QCOMPARE(item2->gestureOverrideEventsReceived, 1);
2011 QCOMPARE(item3->gestureOverrideEventsReceived, 1);
2012 QCOMPARE(item4->gestureOverrideEventsReceived, 1);
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);
2020 class WinNativePan : public QPanGesture {
2025 class Pan : public QPanGesture {
2030 class CustomPan : public QPanGesture {
2035 // Recognizer for active gesture triggers on mouse press
2036 class PanRecognizer : public QGestureRecognizer {
2038 enum PanType { Platform, Default, Custom };
2040 PanRecognizer(int id) : m_id(id) {}
2041 QGesture *create(QObject *) {
2043 case Platform: return new WinNativePan();
2044 case Default: return new Pan();
2045 default: return new CustomPan();
2049 Result recognize(QGesture *, QObject *, QEvent *) { return QGestureRecognizer::Ignore; }
2054 void tst_Gestures::testQGestureRecognizerCleanup()
2056 // Clean first the current recognizers in QGManager
2057 QGestureRecognizer::unregisterRecognizer(Qt::PanGesture);
2059 // v-- Qt singleton QGManager initialization
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;
2069 // ^-- Qt singleton QGManager initialization
2071 // Here, application code would start
2073 // Create QGV (has a QAScrollArea, which uses Qt::PanGesture)
2074 QMainWindow *w = new QMainWindow;
2075 QGraphicsView *v = new QGraphicsView();
2076 w->setCentralWidget(v);
2078 // Unregister Qt recognizers
2079 QGestureRecognizer::unregisterRecognizer(Qt::PanGesture);
2081 // Register a custom Pan recognizer
2082 //QGestureRecognizer::registerRecognizer(new PanRecognizer(PanRecognizer::Custom));
2085 QVERIFY(QTest::qWaitForWindowExposed(w));
2089 class ReuseCanceledGesturesRecognizer : public QGestureRecognizer
2093 RmbAndCancelAllType,
2097 ReuseCanceledGesturesRecognizer(Type type) : m_type(type) {}
2099 QGesture *create(QObject *) {
2100 QGesture *g = new QGesture;
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);
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;
2117 case QEvent::MouseButtonRelease:
2118 if (me->button() == mouseButton && gesture->state() > Qt::NoGesture)
2119 return QGestureRecognizer::FinishGesture;
2123 return QGestureRecognizer::Ignore;
2129 class ReuseCanceledGesturesWidget : public QGraphicsWidget
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)
2139 bool event(QEvent *event) {
2140 if (event->type() == QEvent::Gesture) {
2141 QGesture *gesture = static_cast<QGestureEvent*>(event)->gesture(m_gestureType);
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;
2153 if (event->type() == QEvent::GraphicsSceneMousePress) {
2156 return QGraphicsWidget::event(event);
2159 int started() { return m_started; }
2160 int updated() { return m_updated; }
2161 int finished() { return m_finished; }
2162 int canceled() { return m_canceled; }
2165 Qt::GestureType m_gestureType;
2172 void tst_Gestures::testReuseCanceledGestures()
2174 Qt::GestureType cancellingGestureTypeId = QGestureRecognizer::registerRecognizer(
2175 new ReuseCanceledGesturesRecognizer(ReuseCanceledGesturesRecognizer::RmbAndCancelAllType));
2176 Qt::GestureType tapGestureTypeId = QGestureRecognizer::registerRecognizer(
2177 new ReuseCanceledGesturesRecognizer(ReuseCanceledGesturesRecognizer::LmbType));
2180 mw.setWindowFlags(Qt::X11BypassWindowManagerHint);
2181 QGraphicsView *gv = new QGraphicsView(&mw);
2182 QGraphicsScene *scene = new QGraphicsScene;
2184 gv->setScene(scene);
2185 scene->setSceneRect(0,0,100,100);
2187 // Create container and add to the scene
2188 ReuseCanceledGesturesWidget *container = new ReuseCanceledGesturesWidget;
2189 container->grabGesture(cancellingGestureTypeId); // << container grabs canceling gesture
2191 // Create widget and add to the scene
2192 ReuseCanceledGesturesWidget *target = new ReuseCanceledGesturesWidget(tapGestureTypeId, container);
2193 target->grabGesture(tapGestureTypeId);
2195 container->setGeometry(scene->sceneRect());
2197 scene->addItem(container);
2199 mw.setCentralWidget(gv);
2201 // Viewport needs to grab all gestures that widgets in scene grab
2202 gv->viewport()->grabGesture(cancellingGestureTypeId);
2203 gv->viewport()->grabGesture(tapGestureTypeId);
2206 QVERIFY(QTest::qWaitForWindowExposed(&mw));
2208 QPoint targetPos(gv->mapFromScene(target->mapToScene(target->rect().center())));
2209 targetPos = gv->viewport()->mapFromParent(targetPos);
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);
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
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);
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);
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);
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);
2253 void tst_Gestures::conflictingGesturesInGraphicsView()
2255 QGraphicsScene scene;
2256 GraphicsView view(&scene);
2257 view.setWindowFlags(Qt::X11BypassWindowManagerHint);
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);
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);
2272 QVERIFY(QTest::qWaitForWindowExposed(&view));
2273 view.ensureVisible(scene.sceneRect());
2275 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
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);
2290 item1->reset(); item2->reset();
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);
2303 item1->reset(); item2->reset();
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);
2312 QCOMPARE(item2->gestureOverrideEventsReceived, 1);
2313 QCOMPARE(item2->gestureEventsReceived, 0);
2314 QCOMPARE(item1->gestureOverrideEventsReceived, 1);
2315 QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
2318 class NoConsumeWidgetBug13501 :public QWidget
2322 bool event(QEvent *e) {
2323 if(e->type() == QEvent::Gesture) {
2326 return QWidget::event(e);
2330 void tst_Gestures::bug_13501_gesture_not_accepted()
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);
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);
2345 QTEST_MAIN(tst_Gestures)
2346 #include "tst_gestures.moc"