From c5c1b878891b5ace5a71b95ea62229e26722fdba Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Wed, 14 Oct 2009 14:45:27 +0200 Subject: Fixed gesture event delivery when several gestures are triggered. When there are two different gestures are being triggered and they are supposed to be sent to different widgets, don't stop event "propagation" when the first event is successfully delivered. Reviewed-by: trustme --- src/gui/kernel/qapplication.cpp | 2 +- src/gui/kernel/qgesturemanager.cpp | 41 +++++++++++++++----------------- tests/auto/gestures/tst_gestures.cpp | 45 +++++++++++++++++++++++++++++++----- 3 files changed, 59 insertions(+), 29 deletions(-) diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 30440eb..aee8afc 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -4183,7 +4183,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) res = d->notify_helper(w, &ge); gestureEvent->spont = false; eventAccepted = ge.isAccepted(); - if (res && eventAccepted) + if (res && eventAccepted && allGestures.isEmpty()) break; if (!eventAccepted) { // ### two ways to ignore the event/gesture diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp index 4f8a911..8928d1c 100644 --- a/src/gui/kernel/qgesturemanager.cpp +++ b/src/gui/kernel/qgesturemanager.cpp @@ -361,7 +361,8 @@ void QGestureManager::deliverEvents(const QSet &gestures, GesturesPerReceiver groupedGestures; // for conflicted gestures the key is always the innermost widget (i.e. the child) GesturesPerReceiver conflictedGestures; - QMultiHash objectGestures; + typedef QMultiHash WidgetMultiGestures; + WidgetMultiGestures widgetMultiGestures; foreach (QGesture *gesture, gestures) { QObject *target = gestureTargets.value(gesture, 0); @@ -380,7 +381,7 @@ void QGestureManager::deliverEvents(const QSet &gestures, if (target) { gestureTargets.insert(gesture, target); if (target->isWidgetType()) - objectGestures.insert(target, gesture); + widgetMultiGestures.insert(static_cast(target), gesture); groupedGestures[target].append(gesture); } else { qWarning() << "QGestureManager::deliverEvent: could not find the target for gesture" @@ -389,30 +390,26 @@ void QGestureManager::deliverEvents(const QSet &gestures, } } - typedef QMultiHash::const_iterator ObjectGesturesIterator; - for (ObjectGesturesIterator it = objectGestures.begin(), - e = objectGestures.end(); it != e; ++it) { - QObject *object1 = it.key(); - QWidget *widget1 = qobject_cast(object1); - QGraphicsObject *item1 = qobject_cast(object1); + typedef WidgetMultiGestures::const_iterator WidgetMultiGesturesIterator; + for (WidgetMultiGesturesIterator it = widgetMultiGestures.begin(), + e = widgetMultiGestures.end(); it != e; ++it) { + QWidget *widget1 = it.key(); QGesture *gesture1 = it.value(); - ObjectGesturesIterator cit = it; + WidgetMultiGesturesIterator cit = it; for (++cit; cit != e; ++cit) { - QObject *object2 = cit.key(); - QWidget *widget2 = qobject_cast(object2); - QGraphicsObject *item2 = qobject_cast(object2); + QWidget *widget2 = cit.key(); QGesture *gesture2 = cit.value(); + if (gesture1->gestureType() != gesture2->gestureType()) + continue; // TODO: ugly, rewrite this. - if ((widget1 && widget2 && widget2->isAncestorOf(widget1)) || - (item1 && item2 && item2->isAncestorOf(item1))) { - groupedGestures[object2].removeOne(gesture2); - groupedGestures[object1].removeOne(gesture1); - conflictedGestures[object1].append(gesture1); - } else if ((widget1 && widget2 && widget1->isAncestorOf(widget2)) || - (item1 && item2 && item1->isAncestorOf(item2))) { - groupedGestures[object2].removeOne(gesture2); - groupedGestures[object1].removeOne(gesture1); - conflictedGestures[object2].append(gesture2); + 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); } } } diff --git a/tests/auto/gestures/tst_gestures.cpp b/tests/auto/gestures/tst_gestures.cpp index 3ce5b86..a5e66cf 100644 --- a/tests/auto/gestures/tst_gestures.cpp +++ b/tests/auto/gestures/tst_gestures.cpp @@ -105,8 +105,8 @@ class CustomGestureRecognizer : public QGestureRecognizer public: CustomGestureRecognizer() { - CustomEvent::EventType = QEvent::registerEventType(); - eventsCounter = 0; + if (!CustomEvent::EventType) + CustomEvent::EventType = QEvent::registerEventType(); } QGesture* createGesture(QObject *) @@ -123,7 +123,6 @@ public: g->serial = e->serial; if (e->hasHotSpot) g->setHotSpot(e->hotSpot); - ++eventsCounter; if (g->serial >= CustomGesture::SerialFinishedThreshold) result |= QGestureRecognizer::GestureFinished; else if (g->serial >= CustomGesture::SerialStartedThreshold) @@ -143,9 +142,6 @@ public: g->serial = 0; QGestureRecognizer::reset(state); } - - int eventsCounter; - QString name; }; class GestureWidget : public QWidget @@ -272,6 +268,7 @@ private slots: void graphicsItemGesture(); void explicitGraphicsObjectTarget(); void gestureOverChildGraphicsItem(); + void multipleGestures(); }; tst_Gestures::tst_Gestures() @@ -785,5 +782,41 @@ void tst_Gestures::gestureOverChildGraphicsItem() QCOMPARE(item1->gestureOverrideEventsReceived, TotalGestureEventsCount); } +void tst_Gestures::multipleGestures() +{ + GestureWidget parent("parent"); + QVBoxLayout *l = new QVBoxLayout(&parent); + GestureWidget *child = new GestureWidget("child"); + l->addWidget(child); + + Qt::GestureType SecondGesture = qApp->registerGestureRecognizer(new CustomGestureRecognizer); + + parent.grabGesture(CustomGesture::GestureType, Qt::WidgetWithChildrenGesture); + child->grabGesture(SecondGesture, Qt::WidgetWithChildrenGesture); + + CustomEvent event; + // sending events that form a gesture to one widget, but they will be + // filtered by two different gesture recognizers and will generate two + // QGesture objects. Check that those gesture objects are delivered to + // different widgets properly. + sendCustomGesture(&event, child); + + static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; + static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1; + + QCOMPARE(child->customEventsReceived, TotalCustomEventsCount); + QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(child->gestureOverrideEventsReceived, 0); + QCOMPARE(child->events.all.size(), TotalGestureEventsCount); + for(int i = 0; i < child->events.all.size(); ++i) + QCOMPARE(child->events.all.at(i), SecondGesture); + + QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(parent.gestureOverrideEventsReceived, 0); + QCOMPARE(parent.events.all.size(), TotalGestureEventsCount); + for(int i = 0; i < child->events.all.size(); ++i) + QCOMPARE(parent.events.all.at(i), CustomGesture::GestureType); +} + QTEST_MAIN(tst_Gestures) #include "tst_gestures.moc" -- cgit v0.12