diff options
author | Denis Dzyubenko <denis.dzyubenko@nokia.com> | 2009-10-15 21:00:24 +0200 |
---|---|---|
committer | Denis Dzyubenko <denis.dzyubenko@nokia.com> | 2009-10-22 16:59:18 +0200 |
commit | 0b61c5e284462376afab15ac9189d759b859ec46 (patch) | |
tree | d959820f8e4f3664d45ee971fee508422ab116ee | |
parent | c5c1b878891b5ace5a71b95ea62229e26722fdba (diff) |
Improving gesture event delivery for widgets.
Reviewed-by: trustme
-rw-r--r-- | src/gui/kernel/qapplication.cpp | 1 | ||||
-rw-r--r-- | src/gui/kernel/qevent.h | 2 | ||||
-rw-r--r-- | src/gui/kernel/qgesturemanager.cpp | 214 | ||||
-rw-r--r-- | src/gui/kernel/qgesturemanager_p.h | 12 | ||||
-rw-r--r-- | tests/auto/gestures/tst_gestures.cpp | 184 |
5 files changed, 324 insertions, 89 deletions
diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index aee8afc125..af1c1c8196 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -4204,6 +4204,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) w = w->parentWidget(); } gestureEvent->m_accept = eventAccepted; + gestureEvent->gestures_ = allGestures; } else { res = d->notify_helper(receiver, e); } diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index 6cba5fb67c..1ba2d41949 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -856,6 +856,8 @@ public: private: QList<QGesture *> gestures_; QWidget *widget_; + + friend class QApplication; }; QT_END_NAMESPACE diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp index 8928d1ca2b..f8e1e49f97 100644 --- a/src/gui/kernel/qgesturemanager.cpp +++ b/src/gui/kernel/qgesturemanager.cpp @@ -122,7 +122,7 @@ QGesture *QGestureManager::getState(QObject *object, Qt::GestureType type) Q_ASSERT(qobject_cast<QGraphicsObject *>(object)); } - QWeakPointer<QGesture> state = + QGesture *state = objectGestures.value(QGestureManager::ObjectGesture(object, type)); if (!state) { QGestureRecognizer *recognizer = recognizers.value(type); @@ -130,21 +130,25 @@ QGesture *QGestureManager::getState(QObject *object, Qt::GestureType type) state = recognizer->createGesture(object); if (!state) return 0; - if (state.data()->gestureType() == Qt::CustomGesture) { + if (state->gestureType() == Qt::CustomGesture) { // if the recognizer didn't fill in the gesture type, then this // is a custom gesture with autogenerated it and we fill it. - state.data()->d_func()->gestureType = type; + state->d_func()->gestureType = type; +#if defined(GESTURE_DEBUG) + state->setObjectName(QString::number((int)type)); +#endif } objectGestures.insert(QGestureManager::ObjectGesture(object, type), state); - gestureToRecognizer[state.data()] = recognizer; + gestureToRecognizer[state] = recognizer; + gestureOwners[state] = object; } } - return state.data(); + return state; } bool QGestureManager::filterEventThroughContexts(const QMap<QObject *, Qt::GestureType> &contexts, - QObject *receiver, QEvent *event) + QEvent *event) { QSet<QGesture *> triggeredGestures; QSet<QGesture *> finishedGestures; @@ -152,6 +156,9 @@ bool QGestureManager::filterEventThroughContexts(const QMap<QObject *, QSet<QGesture *> canceledGestures; QSet<QGesture *> notGestures; + // TODO: sort contexts by the gesture type and check if one of the contexts + // is already active. + // filter the event through recognizers typedef QMap<QObject *, Qt::GestureType>::const_iterator ContextIterator; for (ContextIterator cit = contexts.begin(), ce = contexts.end(); cit != ce; ++cit) { @@ -237,7 +244,7 @@ bool QGestureManager::filterEventThroughContexts(const QMap<QObject *, foreach (QGesture *gesture, notStarted) gesture->d_func()->state = Qt::GestureStarted; QSet<QGesture *> undeliveredGestures; - deliverEvents(notStarted, receiver, &undeliveredGestures); + deliverEvents(notStarted, &undeliveredGestures); finishedGestures -= undeliveredGestures; } @@ -274,7 +281,7 @@ bool QGestureManager::filterEventThroughContexts(const QMap<QObject *, QSet<QGesture *> undeliveredGestures; deliverEvents(startedGestures+triggeredGestures+finishedGestures+canceledGestures, - receiver, &undeliveredGestures); + &undeliveredGestures); activeGestures -= undeliveredGestures; @@ -292,38 +299,47 @@ bool QGestureManager::filterEventThroughContexts(const QMap<QObject *, bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event) { + QSet<Qt::GestureType> types; QMap<QObject *, Qt::GestureType> contexts; QWidget *w = receiver; + typedef QMap<Qt::GestureType, Qt::GestureContext>::const_iterator ContextIterator; if (!w->d_func()->gestureContext.isEmpty()) { - typedef QMap<Qt::GestureType, Qt::GestureContext>::const_iterator ContextIterator; for(ContextIterator it = w->d_func()->gestureContext.begin(), e = w->d_func()->gestureContext.end(); it != e; ++it) { + types.insert(it.key()); contexts.insertMulti(w, it.key()); } } // find all gesture contexts for the widget tree - w = w->parentWidget(); + w = w->isWindow() ? 0 : w->parentWidget(); while (w) { - typedef QMap<Qt::GestureType, Qt::GestureContext>::const_iterator ContextIterator; for (ContextIterator it = w->d_func()->gestureContext.begin(), e = w->d_func()->gestureContext.end(); it != e; ++it) { - if (it.value() == Qt::WidgetWithChildrenGesture) - contexts.insertMulti(w, it.key()); + if (it.value() == Qt::WidgetWithChildrenGesture) { + if (!types.contains(it.key())) { + types.insert(it.key()); + contexts.insertMulti(w, it.key()); + } + } } + if (w->isWindow()) + break; w = w->parentWidget(); } - return filterEventThroughContexts(contexts , receiver, event); + return filterEventThroughContexts(contexts, event); } -bool QGestureManager::filterEvent(QGraphicsObject *graphicsObject, QEvent *event) +bool QGestureManager::filterEvent(QGraphicsObject *receiver, QEvent *event) { + QSet<Qt::GestureType> types; QMap<QObject *, Qt::GestureType> contexts; - QGraphicsObject *item = graphicsObject; + QGraphicsObject *item = receiver; if (!item->QGraphicsItem::d_func()->gestureContext.isEmpty()) { typedef QMap<Qt::GestureType, Qt::GestureContext>::const_iterator ContextIterator; for(ContextIterator it = item->QGraphicsItem::d_func()->gestureContext.begin(), e = item->QGraphicsItem::d_func()->gestureContext.end(); it != e; ++it) { + types.insert(it.key()); contexts.insertMulti(item, it.key()); } } @@ -334,55 +350,110 @@ bool QGestureManager::filterEvent(QGraphicsObject *graphicsObject, QEvent *event typedef QMap<Qt::GestureType, Qt::GestureContext>::const_iterator ContextIterator; for (ContextIterator it = item->QGraphicsItem::d_func()->gestureContext.begin(), e = item->QGraphicsItem::d_func()->gestureContext.end(); it != e; ++it) { - if (it.value() == Qt::ItemWithChildrenGesture) - contexts.insertMulti(item, it.key()); + if (it.value() == Qt::ItemWithChildrenGesture) { + if (!types.contains(it.key())) + contexts.insertMulti(item, it.key()); + } } item = item->parentObject(); } - return filterEventThroughContexts(contexts, graphicsObject, event); + return filterEventThroughContexts(contexts, event); } bool QGestureManager::filterEvent(QGesture *state, QEvent *event) { QMap<QObject *, Qt::GestureType> contexts; contexts.insert(state, state->gestureType()); - return filterEventThroughContexts(contexts, 0, event); + return filterEventThroughContexts(contexts, event); +} + +void QGestureManager::getGestureTargets(const QSet<QGesture*> &gestures, + QMap<QWidget *, QList<QGesture *> > *conflicts, + QMap<QWidget *, QList<QGesture *> > *normal) +{ + typedef QHash<Qt::GestureType, QHash<QWidget *, QGesture *> > GestureByTypes; + GestureByTypes gestureByTypes; + + // sort gestures by types + foreach (QGesture *gesture, gestures) { + QWidget *receiver = gestureTargets.value(gesture, 0); + Q_ASSERT(receiver); + gestureByTypes[gesture->gestureType()].insert(receiver, gesture); + } + + // for each gesture type + foreach (Qt::GestureType type, gestureByTypes.keys()) { + QHash<QWidget *, QGesture *> gestures = gestureByTypes.value(type); + foreach (QWidget *widget, gestures.keys()) { + QWidget *w = widget->parentWidget(); + while (w) { + QMap<Qt::GestureType, Qt::GestureContext>::const_iterator it + = w->d_func()->gestureContext.find(type); + if (it != w->d_func()->gestureContext.end()) { + // i.e. 'w' listens to gesture 'type' + Qt::GestureContext context = it.value(); + if (context == Qt::WidgetWithChildrenGesture && w != widget) { + // conflicting gesture! + (*conflicts)[widget].append(gestures[widget]); + break; + } + } + if (w->isWindow()) { + w = 0; + break; + } + w = w->parentWidget(); + } + if (!w) + (*normal)[widget].append(gestures[widget]); + } + } } -void QGestureManager::deliverEvents(const QSet<QGesture*> &gestures, - QObject *lastReceiver, +void QGestureManager::deliverEvents(const QSet<QGesture *> &gestures, QSet<QGesture *> *undeliveredGestures) { if (gestures.isEmpty()) return; - // group gestures by widgets - typedef QMap<QObject *, QList<QGesture *> > GesturesPerReceiver; - GesturesPerReceiver groupedGestures; - // for conflicted gestures the key is always the innermost widget (i.e. the child) - GesturesPerReceiver conflictedGestures; - typedef QMultiHash<QWidget *, QGesture *> WidgetMultiGestures; - WidgetMultiGestures widgetMultiGestures; + typedef QMap<QWidget *, QList<QGesture *> > GesturesPerWidget; + GesturesPerWidget conflictedGestures; + GesturesPerWidget normalStartedGestures; - foreach (QGesture *gesture, gestures) { - QObject *target = gestureTargets.value(gesture, 0); + QSet<QGesture *> startedGestures; + // first figure out the initial receivers of gestures + for (QSet<QGesture *>::const_iterator it = gestures.begin(), + e = gestures.end(); it != e; ++it) { + QGesture *gesture = *it; + QWidget *target = gestureTargets.value(gesture, 0); if (!target) { + // the gesture has just started and doesn't have a target yet. Q_ASSERT(gesture->state() == Qt::GestureStarted); if (gesture->hasHotSpot()) { - // guess the target using the hotspot of the gesture + // guess the target widget using the hotspot of the gesture QPoint pt = gesture->hotSpot().toPoint(); if (QWidget *w = qApp->topLevelAt(pt)) { target = w->childAt(w->mapFromGlobal(pt)); } + } else { + // or use the context of the gesture + QObject *context = gestureOwners.value(gesture, 0); + if (context->isWidgetType()) + target = static_cast<QWidget *>(context); } - if (!target) - target = lastReceiver; + if (target) + gestureTargets.insert(gesture, target); } + + Qt::GestureType gestureType = gesture->gestureType(); + Q_ASSERT(gestureType != Qt::CustomGesture); + if (target) { - gestureTargets.insert(gesture, target); - if (target->isWidgetType()) - widgetMultiGestures.insert(static_cast<QWidget *>(target), gesture); - groupedGestures[target].append(gesture); + if (gesture->state() == Qt::GestureStarted) { + startedGestures.insert(gesture); + } else { + normalStartedGestures[target].append(gesture); + } } else { qWarning() << "QGestureManager::deliverEvent: could not find the target for gesture" << gesture->gestureType(); @@ -390,56 +461,44 @@ void QGestureManager::deliverEvents(const QSet<QGesture*> &gestures, } } - typedef WidgetMultiGestures::const_iterator WidgetMultiGesturesIterator; - for (WidgetMultiGesturesIterator it = widgetMultiGestures.begin(), - e = widgetMultiGestures.end(); it != e; ++it) { - QWidget *widget1 = it.key(); - QGesture *gesture1 = it.value(); - WidgetMultiGesturesIterator cit = it; - for (++cit; cit != e; ++cit) { - QWidget *widget2 = cit.key(); - QGesture *gesture2 = cit.value(); - if (gesture1->gestureType() != gesture2->gestureType()) - continue; - // TODO: ugly, rewrite this. - if ((widget1 && widget2 && widget2->isAncestorOf(widget1))) { - groupedGestures[widget2].removeOne(gesture2); - groupedGestures[widget1].removeOne(gesture1); - conflictedGestures[widget1].append(gesture1); - } else if ((widget1 && widget2 && widget1->isAncestorOf(widget2))) { - groupedGestures[widget2].removeOne(gesture2); - groupedGestures[widget1].removeOne(gesture1); - conflictedGestures[widget2].append(gesture2); - } - } - } - - DEBUG() << "deliverEvents: conflicted =" << conflictedGestures.values() - << " grouped =" << groupedGestures.values(); + getGestureTargets(startedGestures, &conflictedGestures, &normalStartedGestures); + DEBUG() << "QGestureManager::deliverEvents:" + << "\nstarted: " << startedGestures + << "\nconflicted: " << conflictedGestures + << "\nnormal: " << normalStartedGestures + << "\n"; // if there are conflicting gestures, send the GestureOverride event - for (GesturesPerReceiver::const_iterator it = conflictedGestures.begin(), + for (GesturesPerWidget::const_iterator it = conflictedGestures.begin(), e = conflictedGestures.end(); it != e; ++it) { + QWidget *receiver = it.key(); + QList<QGesture *> gestures = it.value(); DEBUG() << "QGestureManager::deliverEvents: sending GestureOverride to" - << it.key() - << " gestures:" << it.value(); - QGestureEvent event(it.value()); + << receiver + << "gestures:" << gestures; + QGestureEvent event(gestures); event.t = QEvent::GestureOverride; event.ignore(); - QApplication::sendEvent(it.key(), &event); + QApplication::sendEvent(receiver, &event); if (!event.isAccepted()) { - // nobody accepted the GestureOverride, put it back to deliver to - // the closest context (i.e. to the inner-most widget). - DEBUG() <<" override was not accepted"; - groupedGestures[it.key()].append(it.value()); + // nobody accepted the GestureOverride, put gestures that were not + // accepted back to deliver as usual + QList<QGesture *> &gestures = normalStartedGestures[receiver]; + foreach(QGesture *gesture, event.allGestures()) { + if (!event.isAccepted(gesture)) { + DEBUG() << "override event wasn't accepted. putting back:" << gesture; + gestures.append(gesture); + } + } } } - for (GesturesPerReceiver::const_iterator it = groupedGestures.begin(), - e = groupedGestures.end(); it != e; ++it) { + // delivering gestures that are not in conflicted state + for (GesturesPerWidget::const_iterator it = normalStartedGestures.begin(), + e = normalStartedGestures.end(); it != e; ++it) { if (!it.value().isEmpty()) { DEBUG() << "QGestureManager::deliverEvents: sending to" << it.key() - << " gestures:" << it.value(); + << "gestures:" << it.value(); QGestureEvent event(it.value()); QApplication::sendEvent(it.key(), &event); } @@ -457,7 +516,8 @@ void QGestureManager::timerEvent(QTimerEvent *event) timer.stop(); QGesture *gesture = it.key(); it = maybeGestures.erase(it); - DEBUG() << "QGestureManager::timerEvent: gesture stopped due to timeout:" << gesture; + DEBUG() << "QGestureManager::timerEvent: gesture stopped due to timeout:" + << gesture; QGestureRecognizer *recognizer = gestureToRecognizer.value(gesture, 0); if (recognizer) recognizer->reset(gesture); diff --git a/src/gui/kernel/qgesturemanager_p.h b/src/gui/kernel/qgesturemanager_p.h index 5fc02ab133..f0e72252bd 100644 --- a/src/gui/kernel/qgesturemanager_p.h +++ b/src/gui/kernel/qgesturemanager_p.h @@ -82,7 +82,7 @@ public: protected: void timerEvent(QTimerEvent *event); bool filterEventThroughContexts(const QMap<QObject *, Qt::GestureType> &contexts, - QObject *receiver, QEvent *event); + QEvent *event); private: QMultiMap<Qt::GestureType, QGestureRecognizer *> recognizers; @@ -114,16 +114,20 @@ private: } }; - QMap<ObjectGesture, QWeakPointer<QGesture> > objectGestures; + QMap<ObjectGesture, QGesture *> objectGestures; QMap<QGesture *, QGestureRecognizer *> gestureToRecognizer; + QHash<QGesture *, QObject *> gestureOwners; - QHash<QGesture *, QObject *> gestureTargets; + QHash<QGesture *, QWidget *> gestureTargets; int lastCustomGestureId; QGesture *getState(QObject *widget, Qt::GestureType gesture); - void deliverEvents(const QSet<QGesture *> &gestures, QObject *lastReceiver, + void deliverEvents(const QSet<QGesture *> &gestures, QSet<QGesture *> *undeliveredGestures); + void getGestureTargets(const QSet<QGesture*> &gestures, + QMap<QWidget *, QList<QGesture *> > *conflicts, + QMap<QWidget *, QList<QGesture *> > *normal); }; QT_END_NAMESPACE diff --git a/tests/auto/gestures/tst_gestures.cpp b/tests/auto/gestures/tst_gestures.cpp index a5e66cffa6..4d072bcff8 100644 --- a/tests/auto/gestures/tst_gestures.cpp +++ b/tests/auto/gestures/tst_gestures.cpp @@ -148,7 +148,8 @@ class GestureWidget : public QWidget { Q_OBJECT public: - GestureWidget(const char *name = 0) + GestureWidget(const char *name = 0, QWidget *parent = 0) + : QWidget(parent) { if (name) setObjectName(QLatin1String(name)); @@ -186,14 +187,18 @@ public: } events, overrideEvents; bool acceptGestureOverride; + QSet<Qt::GestureType> ignoredGestures; protected: bool event(QEvent *event) { Events *eventsPtr = 0; if (event->type() == QEvent::Gesture) { + QGestureEvent *e = static_cast<QGestureEvent*>(event); ++gestureEventsReceived; eventsPtr = &events; + foreach(Qt::GestureType type, ignoredGestures) + e->ignore(e->gesture(type)); } else if (event->type() == QEvent::GestureOverride) { ++gestureOverrideEventsReceived; eventsPtr = &overrideEvents; @@ -268,7 +273,9 @@ private slots: void graphicsItemGesture(); void explicitGraphicsObjectTarget(); void gestureOverChildGraphicsItem(); - void multipleGestures(); + void twoGesturesOnDifferentLevel(); + void multipleGesturesInTree(); + void multipleGesturesInComplexTree(); }; tst_Gestures::tst_Gestures() @@ -442,7 +449,7 @@ void tst_Gestures::conflictingGestures() CustomEvent event; sendCustomGesture(&event, child); - QCOMPARE(child->gestureOverrideEventsReceived, TotalGestureEventsCount); + QCOMPARE(child->gestureOverrideEventsReceived, 1); QCOMPARE(child->gestureEventsReceived, 0); QCOMPARE(parent.gestureOverrideEventsReceived, 0); QCOMPARE(parent.gestureEventsReceived, 0); @@ -457,9 +464,9 @@ void tst_Gestures::conflictingGestures() // sending events to the child and making sure there is no conflict sendCustomGesture(&event, child); - QCOMPARE(child->gestureOverrideEventsReceived, TotalGestureEventsCount); + QCOMPARE(child->gestureOverrideEventsReceived, 1); QCOMPARE(child->gestureEventsReceived, 0); - QCOMPARE(parent.gestureOverrideEventsReceived, TotalGestureEventsCount); + QCOMPARE(parent.gestureOverrideEventsReceived, 1); QCOMPARE(parent.gestureEventsReceived, 0); parent.reset(); @@ -472,9 +479,9 @@ void tst_Gestures::conflictingGestures() // sending events to the child and making sure there is no conflict sendCustomGesture(&event, child); - QCOMPARE(child->gestureOverrideEventsReceived, TotalGestureEventsCount); + QCOMPARE(child->gestureOverrideEventsReceived, 1); QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount); - QCOMPARE(parent.gestureOverrideEventsReceived, TotalGestureEventsCount); + QCOMPARE(parent.gestureOverrideEventsReceived, 1); QCOMPARE(parent.gestureEventsReceived, 0); } @@ -782,7 +789,7 @@ void tst_Gestures::gestureOverChildGraphicsItem() QCOMPARE(item1->gestureOverrideEventsReceived, TotalGestureEventsCount); } -void tst_Gestures::multipleGestures() +void tst_Gestures::twoGesturesOnDifferentLevel() { GestureWidget parent("parent"); QVBoxLayout *l = new QVBoxLayout(&parent); @@ -818,5 +825,166 @@ void tst_Gestures::multipleGestures() QCOMPARE(parent.events.all.at(i), CustomGesture::GestureType); } +void tst_Gestures::multipleGesturesInTree() +{ + GestureWidget a("A"); + GestureWidget *A = &a; + GestureWidget *B = new GestureWidget("B", A); + GestureWidget *C = new GestureWidget("C", B); + GestureWidget *D = new GestureWidget("D", C); + + Qt::GestureType FirstGesture = CustomGesture::GestureType; + Qt::GestureType SecondGesture = qApp->registerGestureRecognizer(new CustomGestureRecognizer); + Qt::GestureType ThirdGesture = qApp->registerGestureRecognizer(new CustomGestureRecognizer); + + A->grabGesture(FirstGesture, Qt::WidgetWithChildrenGesture); // A [1 3] + A->grabGesture(ThirdGesture, Qt::WidgetWithChildrenGesture); // | + B->grabGesture(SecondGesture, Qt::WidgetWithChildrenGesture); // B [ 2 3] + B->grabGesture(ThirdGesture, Qt::WidgetWithChildrenGesture); // | + C->grabGesture(FirstGesture, Qt::WidgetWithChildrenGesture); // C [1 2 3] + C->grabGesture(SecondGesture, Qt::WidgetWithChildrenGesture); // | + C->grabGesture(ThirdGesture, Qt::WidgetWithChildrenGesture); // D [1 3] + D->grabGesture(FirstGesture, Qt::WidgetWithChildrenGesture); + D->grabGesture(ThirdGesture, Qt::WidgetWithChildrenGesture); + + // make sure all widgets ignore events, so they get propagated. + A->ignoredGestures << FirstGesture << ThirdGesture; + B->ignoredGestures << SecondGesture << ThirdGesture; + C->ignoredGestures << FirstGesture << SecondGesture << ThirdGesture; + D->ignoredGestures << FirstGesture << ThirdGesture; + + CustomEvent event; + sendCustomGesture(&event, D); + + static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; + + // gesture override events + QCOMPARE(D->overrideEvents.all.count(FirstGesture), 1); + QCOMPARE(D->overrideEvents.all.count(SecondGesture), 0); + QCOMPARE(D->overrideEvents.all.count(ThirdGesture), 1); + + QCOMPARE(C->overrideEvents.all.count(FirstGesture), 1); + QCOMPARE(C->overrideEvents.all.count(SecondGesture), 1); + QCOMPARE(C->overrideEvents.all.count(ThirdGesture), 1); + + QCOMPARE(B->overrideEvents.all.count(FirstGesture), 0); + QCOMPARE(B->overrideEvents.all.count(SecondGesture), 1); + QCOMPARE(B->overrideEvents.all.count(ThirdGesture), 1); + + QCOMPARE(A->overrideEvents.all.count(FirstGesture), 1); + QCOMPARE(A->overrideEvents.all.count(SecondGesture), 0); + QCOMPARE(A->overrideEvents.all.count(ThirdGesture), 1); + + // normal gesture events + QCOMPARE(D->events.all.count(FirstGesture), TotalGestureEventsCount); + QCOMPARE(D->events.all.count(SecondGesture), 0); + QCOMPARE(D->events.all.count(ThirdGesture), TotalGestureEventsCount); + + QCOMPARE(C->events.all.count(FirstGesture), TotalGestureEventsCount); + QCOMPARE(C->events.all.count(SecondGesture), TotalGestureEventsCount); + QCOMPARE(C->events.all.count(ThirdGesture), TotalGestureEventsCount); + + QCOMPARE(B->events.all.count(FirstGesture), 0); + QCOMPARE(B->events.all.count(SecondGesture), TotalGestureEventsCount); + QCOMPARE(B->events.all.count(ThirdGesture), TotalGestureEventsCount); + + QCOMPARE(A->events.all.count(FirstGesture), TotalGestureEventsCount); + QCOMPARE(A->events.all.count(SecondGesture), 0); + QCOMPARE(A->events.all.count(ThirdGesture), TotalGestureEventsCount); +} + +void tst_Gestures::multipleGesturesInComplexTree() +{ + GestureWidget a("A"); + GestureWidget *A = &a; + GestureWidget *B = new GestureWidget("B", A); + GestureWidget *C = new GestureWidget("C", B); + GestureWidget *D = new GestureWidget("D", C); + + Qt::GestureType FirstGesture = CustomGesture::GestureType; + Qt::GestureType SecondGesture = qApp->registerGestureRecognizer(new CustomGestureRecognizer); + Qt::GestureType ThirdGesture = qApp->registerGestureRecognizer(new CustomGestureRecognizer); + Qt::GestureType FourthGesture = qApp->registerGestureRecognizer(new CustomGestureRecognizer); + Qt::GestureType FifthGesture = qApp->registerGestureRecognizer(new CustomGestureRecognizer); + Qt::GestureType SixthGesture = qApp->registerGestureRecognizer(new CustomGestureRecognizer); + Qt::GestureType SeventhGesture = qApp->registerGestureRecognizer(new CustomGestureRecognizer); + + A->grabGesture(FirstGesture, Qt::WidgetWithChildrenGesture); // A [1,3,4] + A->grabGesture(ThirdGesture, Qt::WidgetWithChildrenGesture); // | + A->grabGesture(FourthGesture, Qt::WidgetWithChildrenGesture); // B [2,3,5] + B->grabGesture(SecondGesture, Qt::WidgetWithChildrenGesture); // | + B->grabGesture(ThirdGesture, Qt::WidgetWithChildrenGesture); // C [1,2,3,6] + B->grabGesture(FifthGesture, Qt::WidgetWithChildrenGesture); // | + C->grabGesture(FirstGesture, Qt::WidgetWithChildrenGesture); // D [1,3,7] + C->grabGesture(SecondGesture, Qt::WidgetWithChildrenGesture); + C->grabGesture(ThirdGesture, Qt::WidgetWithChildrenGesture); + C->grabGesture(SixthGesture, Qt::WidgetWithChildrenGesture); + D->grabGesture(FirstGesture, Qt::WidgetWithChildrenGesture); + D->grabGesture(ThirdGesture, Qt::WidgetWithChildrenGesture); + D->grabGesture(SeventhGesture, Qt::WidgetWithChildrenGesture); + + // make sure all widgets ignore events, so they get propagated. + QSet<Qt::GestureType> allGestureTypes; + allGestureTypes << FirstGesture << SecondGesture << ThirdGesture + << FourthGesture << FifthGesture << SixthGesture << SeventhGesture; + A->ignoredGestures = B->ignoredGestures = allGestureTypes; + C->ignoredGestures = D->ignoredGestures = allGestureTypes; + + CustomEvent event; + sendCustomGesture(&event, D); + + static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; + + // gesture override events + QCOMPARE(D->overrideEvents.all.count(FirstGesture), 1); + QCOMPARE(D->overrideEvents.all.count(SecondGesture), 0); + QCOMPARE(D->overrideEvents.all.count(ThirdGesture), 1); + + QCOMPARE(C->overrideEvents.all.count(FirstGesture), 1); + QCOMPARE(C->overrideEvents.all.count(SecondGesture), 1); + QCOMPARE(C->overrideEvents.all.count(ThirdGesture), 1); + + QCOMPARE(B->overrideEvents.all.count(FirstGesture), 0); + QCOMPARE(B->overrideEvents.all.count(SecondGesture), 1); + QCOMPARE(B->overrideEvents.all.count(ThirdGesture), 1); + + QCOMPARE(A->overrideEvents.all.count(FirstGesture), 1); + QCOMPARE(A->overrideEvents.all.count(SecondGesture), 0); + QCOMPARE(A->overrideEvents.all.count(ThirdGesture), 1); + + // normal gesture events + QCOMPARE(D->events.all.count(FirstGesture), TotalGestureEventsCount); + QCOMPARE(D->events.all.count(SecondGesture), 0); + QCOMPARE(D->events.all.count(ThirdGesture), TotalGestureEventsCount); + QCOMPARE(D->events.all.count(FourthGesture), 0); + QCOMPARE(D->events.all.count(FifthGesture), 0); + QCOMPARE(D->events.all.count(SixthGesture), 0); + QCOMPARE(D->events.all.count(SeventhGesture), TotalGestureEventsCount); + + QCOMPARE(C->events.all.count(FirstGesture), TotalGestureEventsCount); + QCOMPARE(C->events.all.count(SecondGesture), TotalGestureEventsCount); + QCOMPARE(C->events.all.count(ThirdGesture), TotalGestureEventsCount); + QCOMPARE(C->events.all.count(FourthGesture), 0); + QCOMPARE(C->events.all.count(FifthGesture), 0); + QCOMPARE(C->events.all.count(SixthGesture), TotalGestureEventsCount); + QCOMPARE(C->events.all.count(SeventhGesture), 0); + + QCOMPARE(B->events.all.count(FirstGesture), 0); + QCOMPARE(B->events.all.count(SecondGesture), TotalGestureEventsCount); + QCOMPARE(B->events.all.count(ThirdGesture), TotalGestureEventsCount); + QCOMPARE(B->events.all.count(FourthGesture), 0); + QCOMPARE(B->events.all.count(FifthGesture), TotalGestureEventsCount); + QCOMPARE(B->events.all.count(SixthGesture), 0); + QCOMPARE(B->events.all.count(SeventhGesture), 0); + + QCOMPARE(A->events.all.count(FirstGesture), TotalGestureEventsCount); + QCOMPARE(A->events.all.count(SecondGesture), 0); + QCOMPARE(A->events.all.count(ThirdGesture), TotalGestureEventsCount); + QCOMPARE(A->events.all.count(FourthGesture), TotalGestureEventsCount); + QCOMPARE(A->events.all.count(FifthGesture), 0); + QCOMPARE(A->events.all.count(SixthGesture), 0); + QCOMPARE(A->events.all.count(SeventhGesture), 0); +} + QTEST_MAIN(tst_Gestures) #include "tst_gestures.moc" |