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>
58 static QPointF mapToGlobal(const QPointF &pt, QGraphicsItem *item, QGraphicsView *view)
60 return view->viewport()->mapToGlobal(view->mapFromScene(item->mapToScene(pt)));
63 class CustomGesture : public QGesture
67 static Qt::GestureType GestureType;
69 CustomGesture(QObject *parent = 0)
70 : QGesture(parent), serial(0)
76 static const int SerialMaybeThreshold;
77 static const int SerialStartedThreshold;
78 static const int SerialFinishedThreshold;
80 Qt::GestureType CustomGesture::GestureType = Qt::CustomGesture;
81 const int CustomGesture::SerialMaybeThreshold = 1;
82 const int CustomGesture::SerialStartedThreshold = 3;
83 const int CustomGesture::SerialFinishedThreshold = 6;
85 class CustomEvent : public QEvent
90 explicit CustomEvent(int serial_ = 0)
91 : QEvent(QEvent::Type(CustomEvent::EventType)),
92 serial(serial_), hasHotSpot(false)
100 int CustomEvent::EventType = 0;
102 class CustomGestureRecognizer : public QGestureRecognizer
105 static bool ConsumeEvents;
107 CustomGestureRecognizer()
109 if (!CustomEvent::EventType)
110 CustomEvent::EventType = QEvent::registerEventType();
113 QGesture* create(QObject *)
115 return new CustomGesture;
118 QGestureRecognizer::Result recognize(QGesture *state, QObject*, QEvent *event)
120 if (event->type() == CustomEvent::EventType) {
121 QGestureRecognizer::Result result = 0;
122 if (CustomGestureRecognizer::ConsumeEvents)
123 result |= QGestureRecognizer::ConsumeEventHint;
124 CustomGesture *g = static_cast<CustomGesture*>(state);
125 CustomEvent *e = static_cast<CustomEvent*>(event);
126 g->serial = e->serial;
128 g->setHotSpot(e->hotSpot);
129 if (g->serial >= CustomGesture::SerialFinishedThreshold)
130 result |= QGestureRecognizer::FinishGesture;
131 else if (g->serial >= CustomGesture::SerialStartedThreshold)
132 result |= QGestureRecognizer::TriggerGesture;
133 else if (g->serial >= CustomGesture::SerialMaybeThreshold)
134 result |= QGestureRecognizer::MayBeGesture;
136 result = QGestureRecognizer::CancelGesture;
139 return QGestureRecognizer::Ignore;
142 void reset(QGesture *state)
144 CustomGesture *g = static_cast<CustomGesture *>(state);
146 QGestureRecognizer::reset(state);
149 bool CustomGestureRecognizer::ConsumeEvents = false;
151 // same as CustomGestureRecognizer but triggers early without the maybe state
152 class CustomContinuousGestureRecognizer : public QGestureRecognizer
155 CustomContinuousGestureRecognizer()
157 if (!CustomEvent::EventType)
158 CustomEvent::EventType = QEvent::registerEventType();
161 QGesture* create(QObject *)
163 return new CustomGesture;
166 QGestureRecognizer::Result recognize(QGesture *state, QObject*, QEvent *event)
168 if (event->type() == CustomEvent::EventType) {
169 QGestureRecognizer::Result result = QGestureRecognizer::ConsumeEventHint;
170 CustomGesture *g = static_cast<CustomGesture *>(state);
171 CustomEvent *e = static_cast<CustomEvent *>(event);
172 g->serial = e->serial;
174 g->setHotSpot(e->hotSpot);
175 if (g->serial >= CustomGesture::SerialFinishedThreshold)
176 result |= QGestureRecognizer::FinishGesture;
177 else if (g->serial >= CustomGesture::SerialMaybeThreshold)
178 result |= QGestureRecognizer::TriggerGesture;
180 result = QGestureRecognizer::CancelGesture;
183 return QGestureRecognizer::Ignore;
186 void reset(QGesture *state)
188 CustomGesture *g = static_cast<CustomGesture *>(state);
190 QGestureRecognizer::reset(state);
194 class GestureWidget : public QWidget
198 GestureWidget(const char *name = 0, QWidget *parent = 0)
202 setObjectName(QLatin1String(name));
204 acceptGestureOverride = false;
208 customEventsReceived = 0;
209 gestureEventsReceived = 0;
210 gestureOverrideEventsReceived = 0;
212 overrideEvents.clear();
213 ignoredGestures.clear();
216 int customEventsReceived;
217 int gestureEventsReceived;
218 int gestureOverrideEventsReceived;
221 QList<Qt::GestureType> all;
222 QList<Qt::GestureType> started;
223 QList<Qt::GestureType> updated;
224 QList<Qt::GestureType> finished;
225 QList<Qt::GestureType> canceled;
235 } events, overrideEvents;
237 bool acceptGestureOverride;
238 QSet<Qt::GestureType> ignoredGestures;
241 bool event(QEvent *event)
243 Events *eventsPtr = 0;
244 if (event->type() == QEvent::Gesture) {
245 QGestureEvent *e = static_cast<QGestureEvent*>(event);
246 ++gestureEventsReceived;
248 foreach(Qt::GestureType type, ignoredGestures)
249 e->ignore(e->gesture(type));
250 } else if (event->type() == QEvent::GestureOverride) {
251 ++gestureOverrideEventsReceived;
252 eventsPtr = &overrideEvents;
253 if (acceptGestureOverride)
257 QGestureEvent *e = static_cast<QGestureEvent*>(event);
258 QList<QGesture*> gestures = e->gestures();
259 foreach(QGesture *g, gestures) {
260 eventsPtr->all << g->gestureType();
262 case Qt::GestureStarted:
263 emit gestureStarted(e->type(), g);
264 eventsPtr->started << g->gestureType();
266 case Qt::GestureUpdated:
267 emit gestureUpdated(e->type(), g);
268 eventsPtr->updated << g->gestureType();
270 case Qt::GestureFinished:
271 emit gestureFinished(e->type(), g);
272 eventsPtr->finished << g->gestureType();
274 case Qt::GestureCanceled:
275 emit gestureCanceled(e->type(), g);
276 eventsPtr->canceled << g->gestureType();
279 qWarning() << "Unknown GestureState enum value:" << static_cast<int>(g->state());
282 } else if (event->type() == CustomEvent::EventType) {
283 ++customEventsReceived;
285 return QWidget::event(event);
291 void gestureStarted(QEvent::Type, QGesture *);
292 void gestureUpdated(QEvent::Type, QGesture *);
293 void gestureFinished(QEvent::Type, QGesture *);
294 void gestureCanceled(QEvent::Type, QGesture *);
297 void deleteThis() { delete this; }
300 // TODO rename to sendGestureSequence
301 static void sendCustomGesture(CustomEvent *event, QObject *object, QGraphicsScene *scene = 0)
303 QWeakPointer<QObject> receiver(object);
304 for (int i = CustomGesture::SerialMaybeThreshold;
305 i <= CustomGesture::SerialFinishedThreshold && receiver; ++i) {
308 scene->sendEvent(qobject_cast<QGraphicsObject *>(object), event);
310 QApplication::sendEvent(object, event);
314 class tst_Gestures : public QObject
320 virtual ~tst_Gestures();
324 void cleanupTestCase();
329 void customGesture();
330 void autoCancelingGestures();
331 void gestureOverChild();
332 void multipleWidgetOnlyGestureInTree();
333 void conflictingGestures();
334 void conflictingGesturesInGraphicsView();
335 void finishedWithoutStarted();
336 void unknownGesture();
337 void graphicsItemGesture();
339 void graphicsItemTreeGesture();
340 void explicitGraphicsObjectTarget();
341 void gestureOverChildGraphicsItem();
342 void twoGesturesOnDifferentLevel();
343 void multipleGesturesInTree();
344 void multipleGesturesInComplexTree();
345 void testMapToScene();
346 void ungrabGesture();
347 void consumeEventHint();
348 void unregisterRecognizer();
349 void autoCancelGestures();
350 void autoCancelGestures2();
351 void graphicsViewParentPropagation();
352 void panelPropagation();
353 void panelStacksBehindParent();
354 void deleteGestureTargetWidget();
355 void deleteGestureTargetItem_data();
356 void deleteGestureTargetItem();
357 void viewportCoordinates();
358 void partialGesturePropagation();
359 void testQGestureRecognizerCleanup();
360 void testReuseCanceledGestures();
361 void bug_13501_gesture_not_accepted();
364 tst_Gestures::tst_Gestures()
368 tst_Gestures::~tst_Gestures()
372 void tst_Gestures::initTestCase()
374 CustomGesture::GestureType = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
375 QVERIFY(CustomGesture::GestureType != Qt::GestureType(0));
376 QVERIFY(CustomGesture::GestureType != Qt::CustomGesture);
379 void tst_Gestures::cleanupTestCase()
381 QGestureRecognizer::unregisterRecognizer(CustomGesture::GestureType);
384 void tst_Gestures::init()
388 void tst_Gestures::cleanup()
392 void tst_Gestures::customGesture()
394 GestureWidget widget;
395 widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
397 QTest::qWaitForWindowShown(&widget);
400 event.hotSpot = widget.mapToGlobal(QPoint(5,5));
401 event.hasHotSpot = true;
402 sendCustomGesture(&event, &widget);
404 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
405 static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
406 QCOMPARE(widget.customEventsReceived, TotalCustomEventsCount);
407 QCOMPARE(widget.gestureEventsReceived, TotalGestureEventsCount);
408 QCOMPARE(widget.gestureOverrideEventsReceived, 0);
409 QCOMPARE(widget.events.all.size(), TotalGestureEventsCount);
410 for(int i = 0; i < widget.events.all.size(); ++i)
411 QCOMPARE(widget.events.all.at(i), CustomGesture::GestureType);
412 QCOMPARE(widget.events.started.size(), 1);
413 QCOMPARE(widget.events.updated.size(), TotalGestureEventsCount - 2);
414 QCOMPARE(widget.events.finished.size(), 1);
415 QCOMPARE(widget.events.canceled.size(), 0);
418 void tst_Gestures::consumeEventHint()
420 GestureWidget widget;
421 widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
423 CustomGestureRecognizer::ConsumeEvents = true;
425 sendCustomGesture(&event, &widget);
426 CustomGestureRecognizer::ConsumeEvents = false;
428 QCOMPARE(widget.customEventsReceived, 0);
431 void tst_Gestures::autoCancelingGestures()
433 GestureWidget widget;
434 widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
435 // send partial gesture. The gesture will be in the "maybe" state, but will
436 // never get enough events to fire, so Qt will have to kill it.
438 for (int i = CustomGesture::SerialMaybeThreshold;
439 i < CustomGesture::SerialStartedThreshold; ++i) {
441 QApplication::sendEvent(&widget, &ev);
443 // wait long enough so the gesture manager will cancel the gesture
445 QCOMPARE(widget.customEventsReceived, CustomGesture::SerialStartedThreshold - CustomGesture::SerialMaybeThreshold);
446 QCOMPARE(widget.gestureEventsReceived, 0);
447 QCOMPARE(widget.gestureOverrideEventsReceived, 0);
448 QCOMPARE(widget.events.all.size(), 0);
451 void tst_Gestures::gestureOverChild()
453 GestureWidget widget("widget");
454 QVBoxLayout *l = new QVBoxLayout(&widget);
455 GestureWidget *child = new GestureWidget("child");
458 widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
461 sendCustomGesture(&event, child);
463 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
464 static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
466 QCOMPARE(child->customEventsReceived, TotalCustomEventsCount);
467 QCOMPARE(widget.customEventsReceived, 0);
468 QCOMPARE(child->gestureEventsReceived, 0);
469 QCOMPARE(child->gestureOverrideEventsReceived, 0);
470 QCOMPARE(widget.gestureEventsReceived, 0);
471 QCOMPARE(widget.gestureOverrideEventsReceived, 0);
473 // enable gestures over the children
474 widget.grabGesture(CustomGesture::GestureType);
479 sendCustomGesture(&event, child);
481 QCOMPARE(child->customEventsReceived, TotalCustomEventsCount);
482 QCOMPARE(widget.customEventsReceived, 0);
484 QCOMPARE(child->gestureEventsReceived, 0);
485 QCOMPARE(child->gestureOverrideEventsReceived, 0);
486 QCOMPARE(widget.gestureEventsReceived, TotalGestureEventsCount);
487 QCOMPARE(widget.gestureOverrideEventsReceived, 0);
488 for(int i = 0; i < widget.events.all.size(); ++i)
489 QCOMPARE(widget.events.all.at(i), CustomGesture::GestureType);
490 QCOMPARE(widget.events.started.size(), 1);
491 QCOMPARE(widget.events.updated.size(), TotalGestureEventsCount - 2);
492 QCOMPARE(widget.events.finished.size(), 1);
493 QCOMPARE(widget.events.canceled.size(), 0);
496 void tst_Gestures::multipleWidgetOnlyGestureInTree()
498 GestureWidget parent("parent");
499 QVBoxLayout *l = new QVBoxLayout(&parent);
500 GestureWidget *child = new GestureWidget("child");
503 parent.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
504 child->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
506 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
507 static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
509 // sending events to the child and making sure there is no conflict
511 sendCustomGesture(&event, child);
513 QCOMPARE(child->customEventsReceived, TotalCustomEventsCount);
514 QCOMPARE(parent.customEventsReceived, 0);
515 QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount);
516 QCOMPARE(child->gestureOverrideEventsReceived, 0);
517 QCOMPARE(parent.gestureEventsReceived, 0);
518 QCOMPARE(parent.gestureOverrideEventsReceived, 0);
523 // same for the parent widget
524 sendCustomGesture(&event, &parent);
526 QCOMPARE(child->customEventsReceived, 0);
527 QCOMPARE(parent.customEventsReceived, TotalCustomEventsCount);
528 QCOMPARE(child->gestureEventsReceived, 0);
529 QCOMPARE(child->gestureOverrideEventsReceived, 0);
530 QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount);
531 QCOMPARE(parent.gestureOverrideEventsReceived, 0);
534 void tst_Gestures::conflictingGestures()
536 GestureWidget parent("parent");
537 QVBoxLayout *l = new QVBoxLayout(&parent);
538 GestureWidget *child = new GestureWidget("child");
541 parent.grabGesture(CustomGesture::GestureType);
542 child->grabGesture(CustomGesture::GestureType);
544 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
546 // child accepts the override, parent will not receive anything
547 parent.acceptGestureOverride = false;
548 child->acceptGestureOverride = true;
550 // sending events to the child and making sure there is no conflict
552 sendCustomGesture(&event, child);
554 QCOMPARE(child->gestureOverrideEventsReceived, 1);
555 QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount);
556 QCOMPARE(parent.gestureOverrideEventsReceived, 0);
557 QCOMPARE(parent.gestureEventsReceived, 0);
562 // parent accepts the override
563 parent.acceptGestureOverride = true;
564 child->acceptGestureOverride = false;
566 // sending events to the child and making sure there is no conflict
567 sendCustomGesture(&event, child);
569 QCOMPARE(child->gestureOverrideEventsReceived, 1);
570 QCOMPARE(child->gestureEventsReceived, 0);
571 QCOMPARE(parent.gestureOverrideEventsReceived, 1);
572 QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount);
577 // nobody accepts the override, we will send normal events to the closest
578 // context (i.e. to the child widget) and it will be propagated and
579 // accepted by the parent widget
580 parent.acceptGestureOverride = false;
581 child->acceptGestureOverride = false;
582 child->ignoredGestures << CustomGesture::GestureType;
584 // sending events to the child and making sure there is no conflict
585 sendCustomGesture(&event, child);
587 QCOMPARE(child->gestureOverrideEventsReceived, 1);
588 QCOMPARE(child->gestureEventsReceived, 1);
589 QCOMPARE(parent.gestureOverrideEventsReceived, 1);
590 QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount);
595 // nobody accepts the override, and nobody accepts the gesture event
596 parent.acceptGestureOverride = false;
597 child->acceptGestureOverride = false;
598 parent.ignoredGestures << CustomGesture::GestureType;
599 child->ignoredGestures << CustomGesture::GestureType;
601 // sending events to the child and making sure there is no conflict
602 sendCustomGesture(&event, child);
604 QCOMPARE(child->gestureOverrideEventsReceived, 1);
605 QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount);
606 QCOMPARE(parent.gestureOverrideEventsReceived, 1);
607 QCOMPARE(parent.gestureEventsReceived, 1);
612 // we set an attribute to make sure all gesture events are propagated
613 parent.grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures);
614 parent.acceptGestureOverride = false;
615 child->acceptGestureOverride = false;
616 parent.ignoredGestures << CustomGesture::GestureType;
617 child->ignoredGestures << CustomGesture::GestureType;
619 // sending events to the child and making sure there is no conflict
620 sendCustomGesture(&event, child);
622 QCOMPARE(child->gestureOverrideEventsReceived, 1);
623 QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount);
624 QCOMPARE(parent.gestureOverrideEventsReceived, 1);
625 QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount);
630 Qt::GestureType ContinuousGesture = QGestureRecognizer::registerRecognizer(new CustomContinuousGestureRecognizer);
631 static const int ContinuousGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
632 child->grabGesture(ContinuousGesture);
633 // child accepts override. And it also receives another custom gesture.
634 parent.acceptGestureOverride = false;
635 child->acceptGestureOverride = true;
636 sendCustomGesture(&event, child);
638 QCOMPARE(child->gestureOverrideEventsReceived, 1);
639 QVERIFY(child->gestureEventsReceived > TotalGestureEventsCount);
640 QCOMPARE(child->events.all.count(), TotalGestureEventsCount + ContinuousGestureEventsCount);
641 QCOMPARE(parent.gestureOverrideEventsReceived, 0);
642 QCOMPARE(parent.gestureEventsReceived, 0);
644 QGestureRecognizer::unregisterRecognizer(ContinuousGesture);
647 void tst_Gestures::finishedWithoutStarted()
649 GestureWidget widget;
650 widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
652 // the gesture will claim it finished, but it was never started.
654 ev.serial = CustomGesture::SerialFinishedThreshold;
655 QApplication::sendEvent(&widget, &ev);
657 QCOMPARE(widget.customEventsReceived, 1);
658 QCOMPARE(widget.gestureEventsReceived, 2);
659 QCOMPARE(widget.gestureOverrideEventsReceived, 0);
660 QCOMPARE(widget.events.all.size(), 2);
661 QCOMPARE(widget.events.started.size(), 1);
662 QCOMPARE(widget.events.updated.size(), 0);
663 QCOMPARE(widget.events.finished.size(), 1);
664 QCOMPARE(widget.events.canceled.size(), 0);
667 void tst_Gestures::unknownGesture()
669 GestureWidget widget;
670 widget.grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
671 widget.grabGesture(Qt::CustomGesture, Qt::DontStartGestureOnChildren);
672 widget.grabGesture(Qt::GestureType(Qt::PanGesture+512), Qt::DontStartGestureOnChildren);
675 sendCustomGesture(&event, &widget);
677 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
679 QCOMPARE(widget.gestureEventsReceived, TotalGestureEventsCount);
682 static const QColor InstanceColors[] = {
683 Qt::blue, Qt::red, Qt::green, Qt::gray, Qt::yellow
686 class GestureItem : public QGraphicsObject
689 static int InstanceCount;
691 GestureItem(const char *name = 0)
693 instanceNumber = InstanceCount++;
695 setObjectName(QLatin1String(name));
698 size = QRectF(0, 0, 100, 100);
699 customEventsReceived = 0;
700 gestureEventsReceived = 0;
701 gestureOverrideEventsReceived = 0;
703 overrideEvents.clear();
704 acceptGestureOverride = false;
713 int customEventsReceived;
714 int gestureEventsReceived;
715 int gestureOverrideEventsReceived;
718 QList<Qt::GestureType> all;
719 QList<Qt::GestureType> started;
720 QList<Qt::GestureType> updated;
721 QList<Qt::GestureType> finished;
722 QList<Qt::GestureType> canceled;
732 } events, overrideEvents;
734 bool acceptGestureOverride;
735 QSet<Qt::GestureType> ignoredGestures;
736 QSet<Qt::GestureType> ignoredStartedGestures;
737 QSet<Qt::GestureType> ignoredUpdatedGestures;
738 QSet<Qt::GestureType> ignoredFinishedGestures;
745 customEventsReceived = 0;
746 gestureEventsReceived = 0;
747 gestureOverrideEventsReceived = 0;
749 overrideEvents.clear();
750 ignoredGestures.clear();
751 ignoredStartedGestures.clear();
752 ignoredUpdatedGestures.clear();
753 ignoredFinishedGestures.clear();
756 QRectF boundingRect() const
760 void paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
762 QColor color = InstanceColors[instanceNumber % (sizeof(InstanceColors)/sizeof(InstanceColors[0]))];
763 p->fillRect(boundingRect(), color);
766 bool event(QEvent *event)
768 Events *eventsPtr = 0;
769 if (event->type() == QEvent::Gesture) {
770 ++gestureEventsReceived;
772 QGestureEvent *e = static_cast<QGestureEvent *>(event);
773 foreach(Qt::GestureType type, ignoredGestures)
774 e->ignore(e->gesture(type));
775 foreach(QGesture *g, e->gestures()) {
776 switch (g->state()) {
777 case Qt::GestureStarted:
778 if (ignoredStartedGestures.contains(g->gestureType()))
781 case Qt::GestureUpdated:
782 if (ignoredUpdatedGestures.contains(g->gestureType()))
785 case Qt::GestureFinished:
786 if (ignoredFinishedGestures.contains(g->gestureType()))
793 } else if (event->type() == QEvent::GestureOverride) {
794 ++gestureOverrideEventsReceived;
795 eventsPtr = &overrideEvents;
796 if (acceptGestureOverride)
800 QGestureEvent *e = static_cast<QGestureEvent*>(event);
801 QList<QGesture*> gestures = e->gestures();
802 foreach(QGesture *g, gestures) {
803 eventsPtr->all << g->gestureType();
805 case Qt::GestureStarted:
806 eventsPtr->started << g->gestureType();
807 emit gestureStarted(e->type(), g);
809 case Qt::GestureUpdated:
810 eventsPtr->updated << g->gestureType();
811 emit gestureUpdated(e->type(), g);
813 case Qt::GestureFinished:
814 eventsPtr->finished << g->gestureType();
815 emit gestureFinished(e->type(), g);
817 case Qt::GestureCanceled:
818 eventsPtr->canceled << g->gestureType();
819 emit gestureCanceled(e->type(), g);
822 qWarning() << "Unknown GestureState enum value:" << static_cast<int>(g->state());
825 } else if (event->type() == CustomEvent::EventType) {
826 ++customEventsReceived;
828 return QGraphicsObject::event(event);
834 void gestureStarted(QEvent::Type, QGesture *);
835 void gestureUpdated(QEvent::Type, QGesture *);
836 void gestureFinished(QEvent::Type, QGesture *);
837 void gestureCanceled(QEvent::Type, QGesture *);
840 // some arguments for the slots below:
841 QGraphicsScene *scene;
844 void deleteThis() { delete this; }
845 void addSelfToScene(QEvent::Type eventType, QGesture *)
847 if (eventType == QEvent::Gesture) {
848 disconnect(sender(), 0, this, SLOT(addSelfToScene(QEvent::Type,QGesture*)));
849 scene->addItem(this);
853 int GestureItem::InstanceCount = 0;
855 void tst_Gestures::graphicsItemGesture()
857 QGraphicsScene scene;
858 QGraphicsView view(&scene);
859 view.setWindowFlags(Qt::X11BypassWindowManagerHint);
861 GestureItem *item = new GestureItem("item");
863 item->setPos(100, 100);
866 QTest::qWaitForWindowShown(&view);
867 view.ensureVisible(scene.sceneRect());
869 item->grabGesture(CustomGesture::GestureType);
871 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
872 static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
875 // gesture without hotspot should not be delivered to items in the view
876 QTest::ignoreMessage(QtWarningMsg, "QGestureManager::deliverEvent: could not find the target for gesture");
877 QTest::ignoreMessage(QtWarningMsg, "QGestureManager::deliverEvent: could not find the target for gesture");
878 QTest::ignoreMessage(QtWarningMsg, "QGestureManager::deliverEvent: could not find the target for gesture");
879 QTest::ignoreMessage(QtWarningMsg, "QGestureManager::deliverEvent: could not find the target for gesture");
880 sendCustomGesture(&event, item, &scene);
882 QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
883 QCOMPARE(item->gestureEventsReceived, 0);
884 QCOMPARE(item->gestureOverrideEventsReceived, 0);
888 // make sure the event is properly delivered if only the hotspot is set.
889 event.hotSpot = mapToGlobal(QPointF(10, 10), item, &view);
890 event.hasHotSpot = true;
891 sendCustomGesture(&event, item, &scene);
893 QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
894 QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount);
895 QCOMPARE(item->gestureOverrideEventsReceived, 0);
896 QCOMPARE(item->events.all.size(), TotalGestureEventsCount);
897 for(int i = 0; i < item->events.all.size(); ++i)
898 QCOMPARE(item->events.all.at(i), CustomGesture::GestureType);
899 QCOMPARE(item->events.started.size(), 1);
900 QCOMPARE(item->events.updated.size(), TotalGestureEventsCount - 2);
901 QCOMPARE(item->events.finished.size(), 1);
902 QCOMPARE(item->events.canceled.size(), 0);
906 // send gesture to the item which ignores it.
907 item->ignoredGestures << CustomGesture::GestureType;
909 event.hotSpot = mapToGlobal(QPointF(10, 10), item, &view);
910 event.hasHotSpot = true;
911 sendCustomGesture(&event, item, &scene);
912 QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
913 QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount);
914 QCOMPARE(item->gestureOverrideEventsReceived, 0);
917 void tst_Gestures::graphicsView()
919 QGraphicsScene scene;
920 QGraphicsView view(&scene);
921 view.setWindowFlags(Qt::X11BypassWindowManagerHint);
923 GestureItem *item = new GestureItem("item");
925 item->setPos(100, 100);
928 QTest::qWaitForWindowShown(&view);
929 view.ensureVisible(scene.sceneRect());
931 item->grabGesture(CustomGesture::GestureType);
933 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
934 static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
937 // make sure the event is properly delivered if only the hotspot is set.
938 event.hotSpot = mapToGlobal(QPointF(10, 10), item, &view);
939 event.hasHotSpot = true;
940 sendCustomGesture(&event, item, &scene);
942 QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
943 QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount);
944 QCOMPARE(item->gestureOverrideEventsReceived, 0);
946 // change the viewport and try again
947 QWidget *newViewport = new QWidget;
948 view.setViewport(newViewport);
951 sendCustomGesture(&event, item, &scene);
953 QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
954 QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount);
955 QCOMPARE(item->gestureOverrideEventsReceived, 0);
957 // change the scene and try again
958 QGraphicsScene newScene;
959 item = new GestureItem("newItem");
960 newScene.addItem(item);
961 item->setPos(100, 100);
962 view.setScene(&newScene);
965 // first without a gesture
966 sendCustomGesture(&event, item, &newScene);
968 QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
969 QCOMPARE(item->gestureEventsReceived, 0);
970 QCOMPARE(item->gestureOverrideEventsReceived, 0);
972 // then grab the gesture and try again
974 item->grabGesture(CustomGesture::GestureType);
975 sendCustomGesture(&event, item, &newScene);
977 QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
978 QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount);
979 QCOMPARE(item->gestureOverrideEventsReceived, 0);
982 void tst_Gestures::graphicsItemTreeGesture()
984 QGraphicsScene scene;
985 QGraphicsView view(&scene);
986 view.setWindowFlags(Qt::X11BypassWindowManagerHint);
988 GestureItem *item1 = new GestureItem("item1");
989 item1->setPos(100, 100);
990 item1->size = QRectF(0, 0, 350, 200);
991 scene.addItem(item1);
993 GestureItem *item1_child1 = new GestureItem("item1_child1");
994 item1_child1->setPos(50, 50);
995 item1_child1->size = QRectF(0, 0, 100, 100);
996 item1_child1->setParentItem(item1);
998 GestureItem *item1_child2 = new GestureItem("item1_child2");
999 item1_child2->size = QRectF(0, 0, 100, 100);
1000 item1_child2->setPos(200, 50);
1001 item1_child2->setParentItem(item1);
1004 QTest::qWaitForWindowShown(&view);
1005 view.ensureVisible(scene.sceneRect());
1007 item1->grabGesture(CustomGesture::GestureType);
1009 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1012 event.hotSpot = mapToGlobal(QPointF(10, 10), item1_child1, &view);
1013 event.hasHotSpot = true;
1015 item1->ignoredGestures << CustomGesture::GestureType;
1016 sendCustomGesture(&event, item1_child1, &scene);
1017 QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0);
1018 QCOMPARE(item1_child1->gestureEventsReceived, 0);
1019 QCOMPARE(item1_child2->gestureEventsReceived, 0);
1020 QCOMPARE(item1_child2->gestureOverrideEventsReceived, 0);
1021 QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1022 QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
1024 item1->reset(); item1_child1->reset(); item1_child2->reset();
1026 item1_child1->grabGesture(CustomGesture::GestureType);
1028 item1->ignoredGestures << CustomGesture::GestureType;
1029 item1_child1->ignoredGestures << CustomGesture::GestureType;
1030 sendCustomGesture(&event, item1_child1, &scene);
1031 QCOMPARE(item1_child1->gestureOverrideEventsReceived, 1);
1032 QCOMPARE(item1_child1->gestureEventsReceived, TotalGestureEventsCount);
1033 QCOMPARE(item1_child2->gestureEventsReceived, 0);
1034 QCOMPARE(item1_child2->gestureOverrideEventsReceived, 0);
1035 QCOMPARE(item1->gestureOverrideEventsReceived, 1);
1036 QCOMPARE(item1->gestureEventsReceived, 1);
1039 void tst_Gestures::explicitGraphicsObjectTarget()
1041 QGraphicsScene scene;
1042 QGraphicsView view(&scene);
1043 view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1045 GestureItem *item1 = new GestureItem("item1");
1046 scene.addItem(item1);
1047 item1->setPos(100, 100);
1048 item1->setZValue(1);
1050 GestureItem *item2 = new GestureItem("item2");
1051 scene.addItem(item2);
1052 item2->setPos(100, 100);
1053 item2->setZValue(5);
1055 GestureItem *item2_child1 = new GestureItem("item2_child1");
1056 scene.addItem(item2_child1);
1057 item2_child1->setParentItem(item2);
1058 item2_child1->setPos(10, 10);
1061 QTest::qWaitForWindowShown(&view);
1062 view.ensureVisible(scene.sceneRect());
1064 item1->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
1065 item2->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
1066 item2_child1->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
1068 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1070 // sending events to item1, but the hotSpot is set to item2
1072 event.hotSpot = mapToGlobal(QPointF(15, 15), item2, &view);
1073 event.hasHotSpot = true;
1075 sendCustomGesture(&event, item1, &scene);
1077 QCOMPARE(item1->gestureEventsReceived, 0);
1078 QCOMPARE(item1->gestureOverrideEventsReceived, 1);
1079 QCOMPARE(item2_child1->gestureEventsReceived, TotalGestureEventsCount);
1080 QCOMPARE(item2_child1->gestureOverrideEventsReceived, 1);
1081 QCOMPARE(item2_child1->events.all.size(), TotalGestureEventsCount);
1082 for(int i = 0; i < item2_child1->events.all.size(); ++i)
1083 QCOMPARE(item2_child1->events.all.at(i), CustomGesture::GestureType);
1084 QCOMPARE(item2_child1->events.started.size(), 1);
1085 QCOMPARE(item2_child1->events.updated.size(), TotalGestureEventsCount - 2);
1086 QCOMPARE(item2_child1->events.finished.size(), 1);
1087 QCOMPARE(item2_child1->events.canceled.size(), 0);
1088 QCOMPARE(item2->gestureEventsReceived, 0);
1089 QCOMPARE(item2->gestureOverrideEventsReceived, 1);
1092 void tst_Gestures::gestureOverChildGraphicsItem()
1094 QGraphicsScene scene;
1095 QGraphicsView view(&scene);
1096 view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1098 GestureItem *item0 = new GestureItem("item0");
1099 scene.addItem(item0);
1100 item0->setPos(0, 0);
1101 item0->grabGesture(CustomGesture::GestureType);
1102 item0->setZValue(1);
1104 GestureItem *item1 = new GestureItem("item1");
1105 scene.addItem(item1);
1106 item1->setPos(100, 100);
1107 item1->setZValue(5);
1109 GestureItem *item2 = new GestureItem("item2");
1110 scene.addItem(item2);
1111 item2->setPos(100, 100);
1112 item2->setZValue(10);
1114 GestureItem *item2_child1 = new GestureItem("item2_child1");
1115 scene.addItem(item2_child1);
1116 item2_child1->setParentItem(item2);
1117 item2_child1->setPos(0, 0);
1120 QTest::qWaitForWindowShown(&view);
1121 view.ensureVisible(scene.sceneRect());
1123 item1->grabGesture(CustomGesture::GestureType);
1125 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1126 static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
1129 event.hotSpot = mapToGlobal(QPointF(10, 10), item2_child1, &view);
1130 event.hasHotSpot = true;
1131 sendCustomGesture(&event, item0, &scene);
1133 QCOMPARE(item0->customEventsReceived, TotalCustomEventsCount);
1134 QCOMPARE(item2_child1->gestureEventsReceived, 0);
1135 QCOMPARE(item2_child1->gestureOverrideEventsReceived, 0);
1136 QCOMPARE(item2->gestureEventsReceived, 0);
1137 QCOMPARE(item2->gestureOverrideEventsReceived, 0);
1138 QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
1139 QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1141 item0->reset(); item1->reset(); item2->reset(); item2_child1->reset();
1142 item2->grabGesture(CustomGesture::GestureType);
1143 item2->ignoredGestures << CustomGesture::GestureType;
1145 event.hotSpot = mapToGlobal(QPointF(10, 10), item2_child1, &view);
1146 event.hasHotSpot = true;
1147 sendCustomGesture(&event, item0, &scene);
1149 QCOMPARE(item2_child1->gestureEventsReceived, 0);
1150 QCOMPARE(item2_child1->gestureOverrideEventsReceived, 0);
1151 QCOMPARE(item2->gestureEventsReceived, 1);
1152 QCOMPARE(item2->gestureOverrideEventsReceived, 1);
1153 QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
1154 QCOMPARE(item1->gestureOverrideEventsReceived, 1);
1156 item0->reset(); item1->reset(); item2->reset(); item2_child1->reset();
1157 item2->grabGesture(CustomGesture::GestureType);
1158 item2->ignoredGestures << CustomGesture::GestureType;
1159 item1->ignoredGestures << CustomGesture::GestureType;
1161 event.hotSpot = mapToGlobal(QPointF(10, 10), item2_child1, &view);
1162 event.hasHotSpot = true;
1163 sendCustomGesture(&event, item0, &scene);
1165 QCOMPARE(item2_child1->gestureEventsReceived, 0);
1166 QCOMPARE(item2_child1->gestureOverrideEventsReceived, 0);
1167 QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount);
1168 QCOMPARE(item2->gestureOverrideEventsReceived, 1);
1169 QCOMPARE(item1->gestureEventsReceived, 1);
1170 QCOMPARE(item1->gestureOverrideEventsReceived, 1);
1172 item0->reset(); item1->reset(); item2->reset(); item2_child1->reset();
1173 item2->grabGesture(CustomGesture::GestureType);
1174 item2->ignoredGestures << CustomGesture::GestureType;
1175 item1->ignoredGestures << CustomGesture::GestureType;
1176 item1->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures);
1178 event.hotSpot = mapToGlobal(QPointF(10, 10), item2_child1, &view);
1179 event.hasHotSpot = true;
1180 sendCustomGesture(&event, item0, &scene);
1182 QCOMPARE(item2_child1->gestureEventsReceived, 0);
1183 QCOMPARE(item2_child1->gestureOverrideEventsReceived, 0);
1184 QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount);
1185 QCOMPARE(item2->gestureOverrideEventsReceived, 1);
1186 QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
1187 QCOMPARE(item1->gestureOverrideEventsReceived, 1);
1190 void tst_Gestures::twoGesturesOnDifferentLevel()
1192 GestureWidget parent("parent");
1193 QVBoxLayout *l = new QVBoxLayout(&parent);
1194 GestureWidget *child = new GestureWidget("child");
1195 l->addWidget(child);
1197 Qt::GestureType SecondGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1199 parent.grabGesture(CustomGesture::GestureType);
1200 child->grabGesture(SecondGesture);
1203 // sending events that form a gesture to one widget, but they will be
1204 // filtered by two different gesture recognizers and will generate two
1205 // QGesture objects. Check that those gesture objects are delivered to
1206 // different widgets properly.
1207 sendCustomGesture(&event, child);
1209 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1210 static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
1212 QCOMPARE(child->customEventsReceived, TotalCustomEventsCount);
1213 QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount);
1214 QCOMPARE(child->gestureOverrideEventsReceived, 0);
1215 QCOMPARE(child->events.all.size(), TotalGestureEventsCount);
1216 for(int i = 0; i < child->events.all.size(); ++i)
1217 QCOMPARE(child->events.all.at(i), SecondGesture);
1219 QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount);
1220 QCOMPARE(parent.gestureOverrideEventsReceived, 0);
1221 QCOMPARE(parent.events.all.size(), TotalGestureEventsCount);
1222 for(int i = 0; i < child->events.all.size(); ++i)
1223 QCOMPARE(parent.events.all.at(i), CustomGesture::GestureType);
1225 QGestureRecognizer::unregisterRecognizer(SecondGesture);
1228 void tst_Gestures::multipleGesturesInTree()
1230 GestureWidget a("A");
1231 GestureWidget *A = &a;
1232 GestureWidget *B = new GestureWidget("B", A);
1233 GestureWidget *C = new GestureWidget("C", B);
1234 GestureWidget *D = new GestureWidget("D", C);
1236 Qt::GestureType FirstGesture = CustomGesture::GestureType;
1237 Qt::GestureType SecondGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1238 Qt::GestureType ThirdGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1240 Qt::GestureFlags flags = Qt::ReceivePartialGestures;
1241 A->grabGesture(FirstGesture, flags); // A [1 3]
1242 A->grabGesture(ThirdGesture, flags); // |
1243 B->grabGesture(SecondGesture, flags); // B [ 2 3]
1244 B->grabGesture(ThirdGesture, flags); // |
1245 C->grabGesture(FirstGesture, flags); // C [1 2 3]
1246 C->grabGesture(SecondGesture, flags); // |
1247 C->grabGesture(ThirdGesture, flags); // D [1 3]
1248 D->grabGesture(FirstGesture, flags);
1249 D->grabGesture(ThirdGesture, flags);
1251 // make sure all widgets ignore events, so they get propagated.
1252 A->ignoredGestures << FirstGesture << ThirdGesture;
1253 B->ignoredGestures << SecondGesture << ThirdGesture;
1254 C->ignoredGestures << FirstGesture << SecondGesture << ThirdGesture;
1255 D->ignoredGestures << FirstGesture << ThirdGesture;
1258 sendCustomGesture(&event, D);
1260 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1262 // gesture override events
1263 QCOMPARE(D->overrideEvents.all.count(FirstGesture), 1);
1264 QCOMPARE(D->overrideEvents.all.count(SecondGesture), 0);
1265 QCOMPARE(D->overrideEvents.all.count(ThirdGesture), 1);
1267 QCOMPARE(C->overrideEvents.all.count(FirstGesture), 1);
1268 QCOMPARE(C->overrideEvents.all.count(SecondGesture), 1);
1269 QCOMPARE(C->overrideEvents.all.count(ThirdGesture), 1);
1271 QCOMPARE(B->overrideEvents.all.count(FirstGesture), 0);
1272 QCOMPARE(B->overrideEvents.all.count(SecondGesture), 1);
1273 QCOMPARE(B->overrideEvents.all.count(ThirdGesture), 1);
1275 QCOMPARE(A->overrideEvents.all.count(FirstGesture), 1);
1276 QCOMPARE(A->overrideEvents.all.count(SecondGesture), 0);
1277 QCOMPARE(A->overrideEvents.all.count(ThirdGesture), 1);
1279 // normal gesture events
1280 QCOMPARE(D->events.all.count(FirstGesture), TotalGestureEventsCount);
1281 QCOMPARE(D->events.all.count(SecondGesture), 0);
1282 QCOMPARE(D->events.all.count(ThirdGesture), TotalGestureEventsCount);
1284 QCOMPARE(C->events.all.count(FirstGesture), TotalGestureEventsCount);
1285 QCOMPARE(C->events.all.count(SecondGesture), TotalGestureEventsCount);
1286 QCOMPARE(C->events.all.count(ThirdGesture), TotalGestureEventsCount);
1288 QCOMPARE(B->events.all.count(FirstGesture), 0);
1289 QCOMPARE(B->events.all.count(SecondGesture), TotalGestureEventsCount);
1290 QCOMPARE(B->events.all.count(ThirdGesture), TotalGestureEventsCount);
1292 QCOMPARE(A->events.all.count(FirstGesture), TotalGestureEventsCount);
1293 QCOMPARE(A->events.all.count(SecondGesture), 0);
1294 QCOMPARE(A->events.all.count(ThirdGesture), TotalGestureEventsCount);
1296 QGestureRecognizer::unregisterRecognizer(SecondGesture);
1297 QGestureRecognizer::unregisterRecognizer(ThirdGesture);
1300 void tst_Gestures::multipleGesturesInComplexTree()
1302 GestureWidget a("A");
1303 GestureWidget *A = &a;
1304 GestureWidget *B = new GestureWidget("B", A);
1305 GestureWidget *C = new GestureWidget("C", B);
1306 GestureWidget *D = new GestureWidget("D", C);
1308 Qt::GestureType FirstGesture = CustomGesture::GestureType;
1309 Qt::GestureType SecondGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1310 Qt::GestureType ThirdGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1311 Qt::GestureType FourthGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1312 Qt::GestureType FifthGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1313 Qt::GestureType SixthGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1314 Qt::GestureType SeventhGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1316 Qt::GestureFlags flags = Qt::ReceivePartialGestures;
1317 A->grabGesture(FirstGesture, flags); // A [1,3,4]
1318 A->grabGesture(ThirdGesture, flags); // |
1319 A->grabGesture(FourthGesture, flags); // B [2,3,5]
1320 B->grabGesture(SecondGesture, flags); // |
1321 B->grabGesture(ThirdGesture, flags); // C [1,2,3,6]
1322 B->grabGesture(FifthGesture, flags); // |
1323 C->grabGesture(FirstGesture, flags); // D [1,3,7]
1324 C->grabGesture(SecondGesture, flags);
1325 C->grabGesture(ThirdGesture, flags);
1326 C->grabGesture(SixthGesture, flags);
1327 D->grabGesture(FirstGesture, flags);
1328 D->grabGesture(ThirdGesture, flags);
1329 D->grabGesture(SeventhGesture, flags);
1331 // make sure all widgets ignore events, so they get propagated.
1332 QSet<Qt::GestureType> allGestureTypes;
1333 allGestureTypes << FirstGesture << SecondGesture << ThirdGesture
1334 << FourthGesture << FifthGesture << SixthGesture << SeventhGesture;
1335 A->ignoredGestures = B->ignoredGestures = allGestureTypes;
1336 C->ignoredGestures = D->ignoredGestures = allGestureTypes;
1339 sendCustomGesture(&event, D);
1341 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1343 // gesture override events
1344 QCOMPARE(D->overrideEvents.all.count(FirstGesture), 1);
1345 QCOMPARE(D->overrideEvents.all.count(SecondGesture), 0);
1346 QCOMPARE(D->overrideEvents.all.count(ThirdGesture), 1);
1348 QCOMPARE(C->overrideEvents.all.count(FirstGesture), 1);
1349 QCOMPARE(C->overrideEvents.all.count(SecondGesture), 1);
1350 QCOMPARE(C->overrideEvents.all.count(ThirdGesture), 1);
1352 QCOMPARE(B->overrideEvents.all.count(FirstGesture), 0);
1353 QCOMPARE(B->overrideEvents.all.count(SecondGesture), 1);
1354 QCOMPARE(B->overrideEvents.all.count(ThirdGesture), 1);
1356 QCOMPARE(A->overrideEvents.all.count(FirstGesture), 1);
1357 QCOMPARE(A->overrideEvents.all.count(SecondGesture), 0);
1358 QCOMPARE(A->overrideEvents.all.count(ThirdGesture), 1);
1360 // normal gesture events
1361 QCOMPARE(D->events.all.count(FirstGesture), TotalGestureEventsCount);
1362 QCOMPARE(D->events.all.count(SecondGesture), 0);
1363 QCOMPARE(D->events.all.count(ThirdGesture), TotalGestureEventsCount);
1364 QCOMPARE(D->events.all.count(FourthGesture), 0);
1365 QCOMPARE(D->events.all.count(FifthGesture), 0);
1366 QCOMPARE(D->events.all.count(SixthGesture), 0);
1367 QCOMPARE(D->events.all.count(SeventhGesture), TotalGestureEventsCount);
1369 QCOMPARE(C->events.all.count(FirstGesture), TotalGestureEventsCount);
1370 QCOMPARE(C->events.all.count(SecondGesture), TotalGestureEventsCount);
1371 QCOMPARE(C->events.all.count(ThirdGesture), TotalGestureEventsCount);
1372 QCOMPARE(C->events.all.count(FourthGesture), 0);
1373 QCOMPARE(C->events.all.count(FifthGesture), 0);
1374 QCOMPARE(C->events.all.count(SixthGesture), TotalGestureEventsCount);
1375 QCOMPARE(C->events.all.count(SeventhGesture), 0);
1377 QCOMPARE(B->events.all.count(FirstGesture), 0);
1378 QCOMPARE(B->events.all.count(SecondGesture), TotalGestureEventsCount);
1379 QCOMPARE(B->events.all.count(ThirdGesture), TotalGestureEventsCount);
1380 QCOMPARE(B->events.all.count(FourthGesture), 0);
1381 QCOMPARE(B->events.all.count(FifthGesture), TotalGestureEventsCount);
1382 QCOMPARE(B->events.all.count(SixthGesture), 0);
1383 QCOMPARE(B->events.all.count(SeventhGesture), 0);
1385 QCOMPARE(A->events.all.count(FirstGesture), TotalGestureEventsCount);
1386 QCOMPARE(A->events.all.count(SecondGesture), 0);
1387 QCOMPARE(A->events.all.count(ThirdGesture), TotalGestureEventsCount);
1388 QCOMPARE(A->events.all.count(FourthGesture), TotalGestureEventsCount);
1389 QCOMPARE(A->events.all.count(FifthGesture), 0);
1390 QCOMPARE(A->events.all.count(SixthGesture), 0);
1391 QCOMPARE(A->events.all.count(SeventhGesture), 0);
1393 QGestureRecognizer::unregisterRecognizer(SecondGesture);
1394 QGestureRecognizer::unregisterRecognizer(ThirdGesture);
1395 QGestureRecognizer::unregisterRecognizer(FourthGesture);
1396 QGestureRecognizer::unregisterRecognizer(FifthGesture);
1397 QGestureRecognizer::unregisterRecognizer(SixthGesture);
1398 QGestureRecognizer::unregisterRecognizer(SeventhGesture);
1401 void tst_Gestures::testMapToScene()
1404 QList<QGesture*> list;
1406 QGestureEvent event(list);
1407 QCOMPARE(event.mapToGraphicsScene(gesture.hotSpot()), QPointF()); // not set, can't do much
1409 QGraphicsScene scene;
1410 QGraphicsView view(&scene);
1411 view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1413 GestureItem *item0 = new GestureItem;
1414 scene.addItem(item0);
1415 item0->setPos(14, 16);
1417 view.show(); // need to show to give it a global coordinate
1418 QTest::qWaitForWindowShown(&view);
1419 view.ensureVisible(scene.sceneRect());
1421 QPoint origin = view.mapToGlobal(QPoint());
1422 event.setWidget(view.viewport());
1424 QCOMPARE(event.mapToGraphicsScene(origin + QPoint(100, 200)), view.mapToScene(QPoint(100, 200)));
1427 void tst_Gestures::ungrabGesture() // a method on QWidget
1429 class MockGestureWidget : public GestureWidget {
1431 MockGestureWidget(const char *name = 0, QWidget *parent = 0)
1432 : GestureWidget(name, parent) { }
1435 QSet<QGesture*> gestures;
1437 bool event(QEvent *event)
1439 if (event->type() == QEvent::Gesture) {
1440 QGestureEvent *gestureEvent = static_cast<QGestureEvent*>(event);
1442 foreach (QGesture *g, gestureEvent->gestures())
1445 return GestureWidget::event(event);
1449 MockGestureWidget parent("A");
1450 MockGestureWidget *a = &parent;
1451 MockGestureWidget *b = new MockGestureWidget("B", a);
1453 a->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren);
1454 b->grabGesture(CustomGesture::GestureType);
1455 b->ignoredGestures << CustomGesture::GestureType;
1458 // sending an event will cause the QGesture objects to be instantiated for the widgets
1459 sendCustomGesture(&event, b);
1461 QCOMPARE(a->gestures.count(), 1);
1462 QPointer<QGesture> customGestureA;
1463 customGestureA = *(a->gestures.begin());
1464 QVERIFY(!customGestureA.isNull());
1465 QCOMPARE(customGestureA->gestureType(), CustomGesture::GestureType);
1467 QCOMPARE(b->gestures.count(), 1);
1468 QPointer<QGesture> customGestureB;
1469 customGestureB = *(b->gestures.begin());
1470 QVERIFY(!customGestureB.isNull());
1471 QVERIFY(customGestureA.data() == customGestureB.data());
1472 QCOMPARE(customGestureB->gestureType(), CustomGesture::GestureType);
1474 a->gestures.clear();
1475 // sending an event will cause the QGesture objects to be instantiated for the widget
1476 sendCustomGesture(&event, a);
1478 QCOMPARE(a->gestures.count(), 1);
1479 customGestureA = *(a->gestures.begin());
1480 QVERIFY(!customGestureA.isNull());
1481 QCOMPARE(customGestureA->gestureType(), CustomGesture::GestureType);
1482 QVERIFY(customGestureA.data() != customGestureB.data());
1484 a->ungrabGesture(CustomGesture::GestureType);
1485 //We changed the deletion of Gestures to lazy during QT-4022, so we can't ensure the QGesture is deleted until now
1486 QVERIFY(!customGestureB.isNull());
1488 a->gestures.clear();
1490 // send again to 'b' and make sure a never gets it.
1491 sendCustomGesture(&event, b);
1492 //After all Gestures are processed in the QGestureManager, we can ensure the QGesture is now deleted
1493 QVERIFY(customGestureA.isNull());
1494 QCOMPARE(a->gestureEventsReceived, 0);
1495 QCOMPARE(a->gestureOverrideEventsReceived, 0);
1498 void tst_Gestures::unregisterRecognizer() // a method on QApplication
1501 The hardest usecase to get right is when we remove a recognizer while several
1502 of the gestures it created are in active state and we immediately add a new recognizer
1503 for the same type (thus replacing the old one).
1504 The expected result is that all old gestures continue till they are finished/cancelled
1505 and the new recognizer starts creating gestures immediately at registration.
1507 This implies that deleting of the recognizer happens only when there are no more gestures
1508 that it created. (since gestures might have a pointer to the recognizer)
1513 void tst_Gestures::autoCancelGestures()
1515 class MockWidget : public GestureWidget {
1517 MockWidget(const char *name) : GestureWidget(name), badGestureEvents(0) { }
1519 bool event(QEvent *event)
1521 if (event->type() == QEvent::Gesture) {
1522 QGestureEvent *ge = static_cast<QGestureEvent*>(event);
1523 if (ge->gestures().count() != 1)
1524 ++badGestureEvents; // event should contain exactly one gesture
1525 ge->gestures().first()->setGestureCancelPolicy(QGesture::CancelAllInContext);
1527 return GestureWidget::event(event);
1530 int badGestureEvents;
1533 const Qt::GestureType secondGesture = QGestureRecognizer::registerRecognizer(new CustomGestureRecognizer);
1535 MockWidget parent("parent"); // this one sets the cancel policy to CancelAllInContext
1536 parent.resize(300, 100);
1537 parent.setWindowFlags(Qt::X11BypassWindowManagerHint);
1538 GestureWidget *child = new GestureWidget("child", &parent);
1539 child->setGeometry(10, 10, 100, 80);
1541 parent.grabGesture(CustomGesture::GestureType);
1542 child->grabGesture(secondGesture);
1544 QTest::qWaitForWindowShown(&parent);
1547 An event is send to both the child and the parent, when the child gets it a gesture is triggered
1548 and send to the child.
1549 When the parent gets the event a new gesture is triggered and delivered to the parent. When the
1550 parent gets it he accepts it and that causes the cancel policy to activate.
1551 The cause of that is the gesture for the child is cancelled and send to the child as such.
1554 event.serial = CustomGesture::SerialStartedThreshold;
1555 QApplication::sendEvent(child, &event);
1556 QCOMPARE(child->events.all.count(), 2);
1557 QCOMPARE(child->events.started.count(), 1);
1558 QCOMPARE(child->events.canceled.count(), 1);
1559 QCOMPARE(parent.events.all.count(), 1);
1561 // clean up, make the parent gesture finish
1562 event.serial = CustomGesture::SerialFinishedThreshold;
1563 QApplication::sendEvent(child, &event);
1564 QCOMPARE(parent.events.all.count(), 2);
1565 QCOMPARE(parent.badGestureEvents, 0);
1568 void tst_Gestures::autoCancelGestures2()
1570 class MockItem : public GestureItem {
1572 MockItem(const char *name) : GestureItem(name), badGestureEvents(0) { }
1574 bool event(QEvent *event) {
1575 if (event->type() == QEvent::Gesture) {
1576 QGestureEvent *ge = static_cast<QGestureEvent*>(event);
1577 if (ge->gestures().count() != 1)
1578 ++badGestureEvents; // event should contain exactly one gesture
1579 ge->gestures().first()->setGestureCancelPolicy(QGesture::CancelAllInContext);
1581 return GestureItem::event(event);
1584 int badGestureEvents;
1587 const Qt::GestureType secondGesture = QGestureRecognizer ::registerRecognizer(new CustomGestureRecognizer);
1589 QGraphicsScene scene;
1590 QGraphicsView view(&scene);
1591 view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1593 MockItem *parent = new MockItem("parent");
1594 GestureItem *child = new GestureItem("child");
1595 child->setParentItem(parent);
1596 parent->setPos(0, 0);
1597 child->setPos(10, 10);
1598 scene.addItem(parent);
1599 parent->grabGesture(CustomGesture::GestureType);
1600 child->grabGesture(secondGesture);
1603 QTest::qWaitForWindowShown(&view);
1604 view.ensureVisible(scene.sceneRect());
1607 event.serial = CustomGesture::SerialStartedThreshold;
1608 event.hasHotSpot = true;
1609 event.hotSpot = mapToGlobal(QPointF(5, 5), child, &view);
1610 scene.sendEvent(child, &event);
1611 QCOMPARE(parent->events.all.count(), 1);
1612 QCOMPARE(child->events.started.count(), 1);
1613 QCOMPARE(child->events.canceled.count(), 1);
1614 QCOMPARE(child->events.all.count(), 2);
1616 // clean up, make the parent gesture finish
1617 event.serial = CustomGesture::SerialFinishedThreshold;
1618 scene.sendEvent(child, &event);
1619 QCOMPARE(parent->events.all.count(), 2);
1620 QCOMPARE(parent->badGestureEvents, 0);
1623 void tst_Gestures::graphicsViewParentPropagation()
1625 QGraphicsScene scene;
1626 QGraphicsView view(&scene);
1627 view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1629 GestureItem *item0 = new GestureItem("item0");
1630 scene.addItem(item0);
1631 item0->setPos(0, 0);
1632 item0->grabGesture(CustomGesture::GestureType);
1633 item0->setZValue(1);
1635 GestureItem *item1 = new GestureItem("item1");
1636 scene.addItem(item1);
1637 item1->setPos(0, 0);
1638 item1->setZValue(5);
1640 GestureItem *item1_c1 = new GestureItem("item1_child1");
1641 item1_c1->setParentItem(item1);
1642 item1_c1->setPos(0, 0);
1644 GestureItem *item1_c1_c1 = new GestureItem("item1_child1_child1");
1645 item1_c1_c1->setParentItem(item1_c1);
1646 item1_c1_c1->setPos(0, 0);
1649 QTest::qWaitForWindowShown(&view);
1650 view.ensureVisible(scene.sceneRect());
1652 item0->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures | Qt::IgnoredGesturesPropagateToParent);
1653 item1->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures | Qt::IgnoredGesturesPropagateToParent);
1654 item1_c1->grabGesture(CustomGesture::GestureType, Qt::IgnoredGesturesPropagateToParent);
1655 item1_c1_c1->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures | Qt::IgnoredGesturesPropagateToParent);
1657 item0->ignoredUpdatedGestures << CustomGesture::GestureType;
1658 item0->ignoredFinishedGestures << CustomGesture::GestureType;
1659 item1->ignoredUpdatedGestures << CustomGesture::GestureType;
1660 item1->ignoredFinishedGestures << CustomGesture::GestureType;
1661 item1_c1->ignoredUpdatedGestures << CustomGesture::GestureType;
1662 item1_c1->ignoredFinishedGestures << CustomGesture::GestureType;
1663 item1_c1_c1->ignoredUpdatedGestures << CustomGesture::GestureType;
1664 item1_c1_c1->ignoredFinishedGestures << CustomGesture::GestureType;
1666 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1669 event.hotSpot = mapToGlobal(QPointF(10, 10), item1_c1, &view);
1670 event.hasHotSpot = true;
1671 sendCustomGesture(&event, item0, &scene);
1673 QCOMPARE(item1_c1_c1->gestureEventsReceived, TotalGestureEventsCount);
1674 QCOMPARE(item1_c1_c1->gestureOverrideEventsReceived, 1);
1675 QCOMPARE(item1_c1->gestureEventsReceived, TotalGestureEventsCount-1);
1676 QCOMPARE(item1_c1->gestureOverrideEventsReceived, 1);
1677 QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount-1);
1678 QCOMPARE(item1->gestureOverrideEventsReceived, 1);
1679 QCOMPARE(item0->gestureEventsReceived, 0);
1680 QCOMPARE(item0->gestureOverrideEventsReceived, 1);
1683 void tst_Gestures::panelPropagation()
1685 QGraphicsScene scene;
1686 QGraphicsView view(&scene);
1687 view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1689 GestureItem *item0 = new GestureItem("item0");
1690 scene.addItem(item0);
1691 item0->setPos(0, 0);
1692 item0->size = QRectF(0, 0, 200, 200);
1693 item0->grabGesture(CustomGesture::GestureType);
1694 item0->setZValue(1);
1696 GestureItem *item1 = new GestureItem("item1");
1697 item1->grabGesture(CustomGesture::GestureType);
1698 scene.addItem(item1);
1699 item1->setPos(10, 10);
1700 item1->size = QRectF(0, 0, 180, 180);
1701 item1->setZValue(2);
1703 GestureItem *item1_child1 = new GestureItem("item1_child1[panel]");
1704 item1_child1->setFlags(QGraphicsItem::ItemIsPanel);
1705 item1_child1->setParentItem(item1);
1706 item1_child1->grabGesture(CustomGesture::GestureType);
1707 item1_child1->setPos(10, 10);
1708 item1_child1->size = QRectF(0, 0, 160, 160);
1709 item1_child1->setZValue(5);
1711 GestureItem *item1_child1_child1 = new GestureItem("item1_child1_child1");
1712 item1_child1_child1->setParentItem(item1_child1);
1713 item1_child1_child1->grabGesture(CustomGesture::GestureType);
1714 item1_child1_child1->setPos(10, 10);
1715 item1_child1_child1->size = QRectF(0, 0, 140, 140);
1716 item1_child1_child1->setZValue(10);
1719 QTest::qWaitForWindowShown(&view);
1720 view.ensureVisible(scene.sceneRect());
1722 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1723 static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
1726 event.hotSpot = mapToGlobal(QPointF(5, 5), item1_child1_child1, &view);
1727 event.hasHotSpot = true;
1728 sendCustomGesture(&event, item0, &scene);
1730 QCOMPARE(item0->customEventsReceived, TotalCustomEventsCount);
1731 QCOMPARE(item1_child1_child1->gestureEventsReceived, TotalGestureEventsCount);
1732 QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 1);
1733 QCOMPARE(item1_child1->gestureOverrideEventsReceived, 1);
1734 QCOMPARE(item1->gestureEventsReceived, 0);
1735 QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1736 QCOMPARE(item0->gestureEventsReceived, 0);
1737 QCOMPARE(item0->gestureOverrideEventsReceived, 0);
1739 item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset();
1741 event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view);
1742 event.hasHotSpot = true;
1743 sendCustomGesture(&event, item1, &scene);
1745 QCOMPARE(item1_child1_child1->gestureEventsReceived, 0);
1746 QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0);
1747 QCOMPARE(item1_child1->gestureEventsReceived, 0);
1748 QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0);
1749 QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
1750 QCOMPARE(item1->gestureOverrideEventsReceived, 1);
1751 QCOMPARE(item0->gestureEventsReceived, 0);
1752 QCOMPARE(item0->gestureOverrideEventsReceived, 1);
1754 item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset();
1755 // try with a modal panel
1756 item1_child1->setPanelModality(QGraphicsItem::PanelModal);
1758 event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view);
1759 event.hasHotSpot = true;
1760 sendCustomGesture(&event, item1, &scene);
1762 QCOMPARE(item1_child1_child1->gestureEventsReceived, 0);
1763 QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0);
1764 QCOMPARE(item1_child1->gestureEventsReceived, TotalGestureEventsCount);
1765 QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0);
1766 QCOMPARE(item1->gestureEventsReceived, 0);
1767 QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1768 QCOMPARE(item0->gestureEventsReceived, 0);
1769 QCOMPARE(item0->gestureOverrideEventsReceived, 0);
1771 item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset();
1772 // try with a modal panel, however set the hotspot to be outside of the
1773 // panel and its parent
1774 item1_child1->setPanelModality(QGraphicsItem::PanelModal);
1776 event.hotSpot = mapToGlobal(QPointF(5, 5), item0, &view);
1777 event.hasHotSpot = true;
1778 sendCustomGesture(&event, item1, &scene);
1780 QCOMPARE(item1_child1_child1->gestureEventsReceived, 0);
1781 QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0);
1782 QCOMPARE(item1_child1->gestureEventsReceived, 0);
1783 QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0);
1784 QCOMPARE(item1->gestureEventsReceived, 0);
1785 QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1786 QCOMPARE(item0->gestureEventsReceived, TotalGestureEventsCount);
1787 QCOMPARE(item0->gestureOverrideEventsReceived, 0);
1789 item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset();
1790 // try with a scene modal panel
1791 item1_child1->setPanelModality(QGraphicsItem::SceneModal);
1793 event.hotSpot = mapToGlobal(QPointF(5, 5), item0, &view);
1794 event.hasHotSpot = true;
1795 sendCustomGesture(&event, item0, &scene);
1797 QCOMPARE(item1_child1_child1->gestureEventsReceived, 0);
1798 QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0);
1799 QCOMPARE(item1_child1->gestureEventsReceived, TotalGestureEventsCount);
1800 QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0);
1801 QCOMPARE(item1->gestureEventsReceived, 0);
1802 QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1803 QCOMPARE(item0->gestureEventsReceived, 0);
1804 QCOMPARE(item0->gestureOverrideEventsReceived, 0);
1807 void tst_Gestures::panelStacksBehindParent()
1809 QGraphicsScene scene;
1810 QGraphicsView view(&scene);
1811 view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1813 GestureItem *item1 = new GestureItem("item1");
1814 item1->grabGesture(CustomGesture::GestureType);
1815 scene.addItem(item1);
1816 item1->setPos(10, 10);
1817 item1->size = QRectF(0, 0, 180, 180);
1818 item1->setZValue(2);
1820 GestureItem *panel = new GestureItem("panel");
1821 panel->setFlags(QGraphicsItem::ItemIsPanel | QGraphicsItem::ItemStacksBehindParent);
1822 panel->setPanelModality(QGraphicsItem::PanelModal);
1823 panel->setParentItem(item1);
1824 panel->grabGesture(CustomGesture::GestureType);
1825 panel->setPos(-10, -10);
1826 panel->size = QRectF(0, 0, 200, 200);
1827 panel->setZValue(5);
1830 QTest::qWaitForWindowShown(&view);
1831 view.ensureVisible(scene.sceneRect());
1833 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
1836 event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view);
1837 event.hasHotSpot = true;
1838 sendCustomGesture(&event, item1, &scene);
1840 QCOMPARE(item1->gestureEventsReceived, 0);
1841 QCOMPARE(item1->gestureOverrideEventsReceived, 0);
1842 QCOMPARE(panel->gestureEventsReceived, TotalGestureEventsCount);
1843 QCOMPARE(panel->gestureOverrideEventsReceived, 0);
1846 void tst_Gestures::deleteGestureTargetWidget()
1850 void tst_Gestures::deleteGestureTargetItem_data()
1852 QTest::addColumn<bool>("propagateUpdateGesture");
1853 QTest::addColumn<QString>("emitter");
1854 QTest::addColumn<QString>("receiver");
1855 QTest::addColumn<QByteArray>("signalName");
1856 QTest::addColumn<QByteArray>("slotName");
1858 QByteArray gestureUpdated = SIGNAL(gestureUpdated(QEvent::Type,QGesture*));
1859 QByteArray gestureFinished = SIGNAL(gestureFinished(QEvent::Type,QGesture*));
1860 QByteArray deleteThis = SLOT(deleteThis());
1861 QByteArray deleteLater = SLOT(deleteLater());
1863 QTest::newRow("delete1")
1864 << false << "item1" << "item1" << gestureUpdated << deleteThis;
1865 QTest::newRow("delete2")
1866 << false << "item2" << "item2" << gestureUpdated << deleteThis;
1867 QTest::newRow("delete3")
1868 << false << "item1" << "item2" << gestureUpdated << deleteThis;
1870 QTest::newRow("deleteLater1")
1871 << false << "item1" << "item1" << gestureUpdated << deleteLater;
1872 QTest::newRow("deleteLater2")
1873 << false << "item2" << "item2" << gestureUpdated << deleteLater;
1874 QTest::newRow("deleteLater3")
1875 << false << "item1" << "item2" << gestureUpdated << deleteLater;
1876 QTest::newRow("deleteLater4")
1877 << false << "item2" << "item1" << gestureUpdated << deleteLater;
1879 QTest::newRow("delete-self-and-propagate")
1880 << true << "item2" << "item2" << gestureUpdated << deleteThis;
1881 QTest::newRow("deleteLater-self-and-propagate")
1882 << true << "item2" << "item2" << gestureUpdated << deleteLater;
1883 QTest::newRow("propagate-to-deletedLater")
1884 << true << "item2" << "item1" << gestureUpdated << deleteLater;
1887 void tst_Gestures::deleteGestureTargetItem()
1889 QFETCH(bool, propagateUpdateGesture);
1890 QFETCH(QString, emitter);
1891 QFETCH(QString, receiver);
1892 QFETCH(QByteArray, signalName);
1893 QFETCH(QByteArray, slotName);
1895 QGraphicsScene scene;
1896 QGraphicsView view(&scene);
1897 view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1899 GestureItem *item1 = new GestureItem("item1");
1900 item1->grabGesture(CustomGesture::GestureType);
1901 item1->setZValue(2);
1902 scene.addItem(item1);
1904 GestureItem *item2 = new GestureItem("item2");
1905 item2->grabGesture(CustomGesture::GestureType);
1906 item2->setZValue(5);
1907 scene.addItem(item2);
1909 QMap<QString, GestureItem *> items;
1910 items.insert(item1->objectName(), item1);
1911 items.insert(item2->objectName(), item2);
1914 QTest::qWaitForWindowShown(&view);
1915 view.ensureVisible(scene.sceneRect());
1917 if (propagateUpdateGesture)
1918 item2->ignoredUpdatedGestures << CustomGesture::GestureType;
1919 connect(items.value(emitter, 0), signalName, items.value(receiver, 0), slotName);
1921 // some debug output to see the current test data tag, so if we crash
1922 // we know which one caused the crash.
1923 qDebug() << "<-- testing";
1926 event.hotSpot = mapToGlobal(QPointF(5, 5), item2, &view);
1927 event.hasHotSpot = true;
1928 sendCustomGesture(&event, item1, &scene);
1931 class GraphicsView : public QGraphicsView
1934 GraphicsView(QGraphicsScene *scene, QWidget *parent = 0)
1935 : QGraphicsView(scene, parent)
1939 using QGraphicsView::setViewportMargins;
1942 // just making sure that even if the graphicsview has margins hotspot still
1943 // works properly. It should use viewport for converting global coordinates to
1944 // scene coordinates.
1945 void tst_Gestures::viewportCoordinates()
1947 QGraphicsScene scene;
1948 GraphicsView view(&scene);
1949 view.setViewportMargins(10,20,15,25);
1950 view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1952 GestureItem *item1 = new GestureItem("item1");
1953 item1->grabGesture(CustomGesture::GestureType);
1954 item1->size = QRectF(0, 0, 3, 3);
1955 item1->setZValue(2);
1956 scene.addItem(item1);
1959 QTest::qWaitForWindowShown(&view);
1960 view.ensureVisible(scene.sceneRect());
1963 event.hotSpot = mapToGlobal(item1->boundingRect().center(), item1, &view);
1964 event.hasHotSpot = true;
1965 sendCustomGesture(&event, item1, &scene);
1966 QVERIFY(item1->gestureEventsReceived != 0);
1969 void tst_Gestures::partialGesturePropagation()
1971 QGraphicsScene scene;
1972 QGraphicsView view(&scene);
1973 view.setWindowFlags(Qt::X11BypassWindowManagerHint);
1975 GestureItem *item1 = new GestureItem("item1");
1976 item1->grabGesture(CustomGesture::GestureType);
1977 item1->setZValue(8);
1978 scene.addItem(item1);
1980 GestureItem *item2 = new GestureItem("item2[partial]");
1981 item2->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures);
1982 item2->setZValue(6);
1983 scene.addItem(item2);
1985 GestureItem *item3 = new GestureItem("item3");
1986 item3->grabGesture(CustomGesture::GestureType);
1987 item3->setZValue(4);
1988 scene.addItem(item3);
1990 GestureItem *item4 = new GestureItem("item4[partial]");
1991 item4->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures);
1992 item4->setZValue(2);
1993 scene.addItem(item4);
1996 QTest::qWaitForWindowShown(&view);
1997 view.ensureVisible(scene.sceneRect());
1999 item1->ignoredUpdatedGestures << CustomGesture::GestureType;
2002 event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view);
2003 event.hasHotSpot = true;
2004 sendCustomGesture(&event, item1, &scene);
2006 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
2008 QCOMPARE(item1->gestureOverrideEventsReceived, 1);
2009 QCOMPARE(item2->gestureOverrideEventsReceived, 1);
2010 QCOMPARE(item3->gestureOverrideEventsReceived, 1);
2011 QCOMPARE(item4->gestureOverrideEventsReceived, 1);
2013 QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
2014 QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount-2); // except for started and finished
2015 QCOMPARE(item3->gestureEventsReceived, 0);
2016 QCOMPARE(item4->gestureEventsReceived, 0);
2019 class WinNativePan : public QPanGesture {
2024 class Pan : public QPanGesture {
2029 class CustomPan : public QPanGesture {
2034 // Recognizer for active gesture triggers on mouse press
2035 class PanRecognizer : public QGestureRecognizer {
2037 enum PanType { Platform, Default, Custom };
2039 PanRecognizer(int id) : m_id(id) {}
2040 QGesture *create(QObject *) {
2042 case Platform: return new WinNativePan();
2043 case Default: return new Pan();
2044 default: return new CustomPan();
2048 Result recognize(QGesture *, QObject *, QEvent *) { return QGestureRecognizer::Ignore; }
2053 void tst_Gestures::testQGestureRecognizerCleanup()
2055 // Clean first the current recognizers in QGManager
2056 QGestureRecognizer::unregisterRecognizer(Qt::PanGesture);
2058 // v-- Qt singleton QGManager initialization
2060 // Mimic QGestureManager: register both default and "platform" recognizers
2061 // (this is done in windows when QT_NO_NATIVE_GESTURES is not defined)
2062 PanRecognizer *def = new PanRecognizer(PanRecognizer::Default);
2063 QGestureRecognizer::registerRecognizer(def);
2064 PanRecognizer *plt = new PanRecognizer(PanRecognizer::Platform);
2065 QGestureRecognizer::registerRecognizer(plt);
2066 qDebug () << "register: default =" << def << "; platform =" << plt;
2068 // ^-- Qt singleton QGManager initialization
2070 // Here, application code would start
2072 // Create QGV (has a QAScrollArea, which uses Qt::PanGesture)
2073 QMainWindow *w = new QMainWindow;
2074 QGraphicsView *v = new QGraphicsView();
2075 w->setCentralWidget(v);
2077 // Unregister Qt recognizers
2078 QGestureRecognizer::unregisterRecognizer(Qt::PanGesture);
2080 // Register a custom Pan recognizer
2081 //QGestureRecognizer::registerRecognizer(new PanRecognizer(PanRecognizer::Custom));
2084 QTest::qWaitForWindowShown(w);
2088 class ReuseCanceledGesturesRecognizer : public QGestureRecognizer
2092 RmbAndCancelAllType,
2096 ReuseCanceledGesturesRecognizer(Type type) : m_type(type) {}
2098 QGesture *create(QObject *) {
2099 QGesture *g = new QGesture;
2103 Result recognize(QGesture *gesture, QObject *, QEvent *event) {
2104 QMouseEvent *me = static_cast<QMouseEvent *>(event);
2105 Qt::MouseButton mouseButton(m_type == LmbType ? Qt::LeftButton : Qt::RightButton);
2107 switch(event->type()) {
2108 case QEvent::MouseButtonPress:
2109 if (me->button() == mouseButton && gesture->state() == Qt::NoGesture) {
2110 gesture->setHotSpot(QPointF(me->globalPos()));
2111 if (m_type == RmbAndCancelAllType)
2112 gesture->setGestureCancelPolicy(QGesture::CancelAllInContext);
2113 return QGestureRecognizer::TriggerGesture;
2116 case QEvent::MouseButtonRelease:
2117 if (me->button() == mouseButton && gesture->state() > Qt::NoGesture)
2118 return QGestureRecognizer::FinishGesture;
2122 return QGestureRecognizer::Ignore;
2128 class ReuseCanceledGesturesWidget : public QGraphicsWidget
2131 ReuseCanceledGesturesWidget(Qt::GestureType gestureType = Qt::TapGesture, QGraphicsItem *parent = 0)
2132 : QGraphicsWidget(parent),
2133 m_gestureType(gestureType),
2134 m_started(0), m_updated(0), m_canceled(0), m_finished(0)
2138 bool event(QEvent *event) {
2139 if (event->type() == QEvent::Gesture) {
2140 QGesture *gesture = static_cast<QGestureEvent*>(event)->gesture(m_gestureType);
2142 switch(gesture->state()) {
2143 case Qt::GestureStarted: m_started++; break;
2144 case Qt::GestureUpdated: m_updated++; break;
2145 case Qt::GestureFinished: m_finished++; break;
2146 case Qt::GestureCanceled: m_canceled++; break;
2152 if (event->type() == QEvent::GraphicsSceneMousePress) {
2155 return QGraphicsWidget::event(event);
2158 int started() { return m_started; }
2159 int updated() { return m_updated; }
2160 int finished() { return m_finished; }
2161 int canceled() { return m_canceled; }
2164 Qt::GestureType m_gestureType;
2171 void tst_Gestures::testReuseCanceledGestures()
2173 Qt::GestureType cancellingGestureTypeId = QGestureRecognizer::registerRecognizer(
2174 new ReuseCanceledGesturesRecognizer(ReuseCanceledGesturesRecognizer::RmbAndCancelAllType));
2175 Qt::GestureType tapGestureTypeId = QGestureRecognizer::registerRecognizer(
2176 new ReuseCanceledGesturesRecognizer(ReuseCanceledGesturesRecognizer::LmbType));
2179 mw.setWindowFlags(Qt::X11BypassWindowManagerHint);
2180 QGraphicsView *gv = new QGraphicsView(&mw);
2181 QGraphicsScene *scene = new QGraphicsScene;
2183 gv->setScene(scene);
2184 scene->setSceneRect(0,0,100,100);
2186 // Create container and add to the scene
2187 ReuseCanceledGesturesWidget *container = new ReuseCanceledGesturesWidget;
2188 container->grabGesture(cancellingGestureTypeId); // << container grabs canceling gesture
2190 // Create widget and add to the scene
2191 ReuseCanceledGesturesWidget *target = new ReuseCanceledGesturesWidget(tapGestureTypeId, container);
2192 target->grabGesture(tapGestureTypeId);
2194 container->setGeometry(scene->sceneRect());
2196 scene->addItem(container);
2198 mw.setCentralWidget(gv);
2200 // Viewport needs to grab all gestures that widgets in scene grab
2201 gv->viewport()->grabGesture(cancellingGestureTypeId);
2202 gv->viewport()->grabGesture(tapGestureTypeId);
2205 QTest::qWaitForWindowShown(&mw);
2207 QPoint targetPos(gv->mapFromScene(target->mapToScene(target->rect().center())));
2208 targetPos = gv->viewport()->mapFromParent(targetPos);
2210 // "Tap" starts on child widget
2211 QTest::mousePress(gv->viewport(), Qt::LeftButton, 0, targetPos);
2212 QCOMPARE(target->started(), 1);
2213 QCOMPARE(target->updated(), 0);
2214 QCOMPARE(target->finished(), 0);
2215 QCOMPARE(target->canceled(), 0);
2217 // Canceling gesture starts on parent
2218 QTest::mousePress(gv->viewport(), Qt::RightButton, 0, targetPos);
2219 QCOMPARE(target->started(), 1);
2220 QCOMPARE(target->updated(), 0);
2221 QCOMPARE(target->finished(), 0);
2222 QCOMPARE(target->canceled(), 1); // <- child canceled
2224 // Canceling gesture ends
2225 QTest::mouseRelease(gv->viewport(), Qt::RightButton, 0, targetPos);
2226 QCOMPARE(target->started(), 1);
2227 QCOMPARE(target->updated(), 0);
2228 QCOMPARE(target->finished(), 0);
2229 QCOMPARE(target->canceled(), 1);
2231 // Tap would end if not canceled
2232 QTest::mouseRelease(gv->viewport(), Qt::LeftButton, 0, targetPos);
2233 QCOMPARE(target->started(), 1);
2234 QCOMPARE(target->updated(), 0);
2235 QCOMPARE(target->finished(), 0);
2236 QCOMPARE(target->canceled(), 1);
2239 QTest::mousePress(gv->viewport(), Qt::LeftButton, 0, targetPos);
2240 QCOMPARE(target->started(), 2);
2241 QCOMPARE(target->updated(), 0);
2242 QCOMPARE(target->finished(), 0);
2243 QCOMPARE(target->canceled(), 1);
2245 QTest::mouseRelease(gv->viewport(), Qt::LeftButton, 0, targetPos);
2246 QCOMPARE(target->started(), 2);
2247 QCOMPARE(target->updated(), 0);
2248 QCOMPARE(target->finished(), 1);
2249 QCOMPARE(target->canceled(), 1);
2252 void tst_Gestures::conflictingGesturesInGraphicsView()
2254 QGraphicsScene scene;
2255 GraphicsView view(&scene);
2256 view.setWindowFlags(Qt::X11BypassWindowManagerHint);
2258 GestureItem *item1 = new GestureItem("item1");
2259 item1->grabGesture(CustomGesture::GestureType);
2260 item1->size = QRectF(0, 0, 100, 100);
2261 item1->setZValue(2);
2262 scene.addItem(item1);
2264 GestureItem *item2 = new GestureItem("item2");
2265 item2->grabGesture(CustomGesture::GestureType);
2266 item2->size = QRectF(0, 0, 100, 100);
2267 item2->setZValue(5);
2268 scene.addItem(item2);
2271 QTest::qWaitForWindowShown(&view);
2272 view.ensureVisible(scene.sceneRect());
2274 static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
2278 // nobody accepts override
2279 item1->acceptGestureOverride = false;
2280 item2->acceptGestureOverride = false;
2281 event.hotSpot = mapToGlobal(item2->boundingRect().center(), item2, &view);
2282 event.hasHotSpot = true;
2283 sendCustomGesture(&event, item2, &scene);
2284 QCOMPARE(item2->gestureOverrideEventsReceived, 1);
2285 QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount);
2286 QCOMPARE(item1->gestureOverrideEventsReceived, 1);
2287 QCOMPARE(item1->gestureEventsReceived, 0);
2289 item1->reset(); item2->reset();
2291 // the original target accepts override
2292 item1->acceptGestureOverride = false;
2293 item2->acceptGestureOverride = true;
2294 event.hotSpot = mapToGlobal(item2->boundingRect().center(), item2, &view);
2295 event.hasHotSpot = true;
2296 sendCustomGesture(&event, item2, &scene);
2297 QCOMPARE(item2->gestureOverrideEventsReceived, 1);
2298 QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount);
2299 QCOMPARE(item1->gestureOverrideEventsReceived, 0);
2300 QCOMPARE(item1->gestureEventsReceived, 0);
2302 item1->reset(); item2->reset();
2304 // the item behind accepts override
2305 item1->acceptGestureOverride = true;
2306 item2->acceptGestureOverride = false;
2307 event.hotSpot = mapToGlobal(item2->boundingRect().center(), item2, &view);
2308 event.hasHotSpot = true;
2309 sendCustomGesture(&event, item2, &scene);
2311 QCOMPARE(item2->gestureOverrideEventsReceived, 1);
2312 QCOMPARE(item2->gestureEventsReceived, 0);
2313 QCOMPARE(item1->gestureOverrideEventsReceived, 1);
2314 QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount);
2317 class NoConsumeWidgetBug13501 :public QWidget
2321 bool event(QEvent *e) {
2322 if(e->type() == QEvent::Gesture) {
2325 return QWidget::event(e);
2329 void tst_Gestures::bug_13501_gesture_not_accepted()
2331 // Create a gesture event that is not accepted by any widget
2332 // make sure this does not lead to an assert in QGestureManager
2333 NoConsumeWidgetBug13501 w;
2334 w.grabGesture(Qt::TapGesture);
2336 QTest::qWaitForWindowShown(&w);
2337 //QTest::mousePress(&ignoreEvent, Qt::LeftButton);
2338 QTouchDevice *device = new QTouchDevice;
2339 device->setType(QTouchDevice::TouchScreen);
2340 QWindowSystemInterface::registerTouchDevice(device);
2341 QTest::touchEvent(&w, device).press(0, QPoint(10, 10), &w);
2344 QTEST_MAIN(tst_Gestures)
2345 #include "tst_gestures.moc"