summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Dzyubenko <denis.dzyubenko@nokia.com>2009-10-15 21:00:24 +0200
committerDenis Dzyubenko <denis.dzyubenko@nokia.com>2009-10-22 16:59:18 +0200
commit0b61c5e284462376afab15ac9189d759b859ec46 (patch)
treed959820f8e4f3664d45ee971fee508422ab116ee
parentc5c1b878891b5ace5a71b95ea62229e26722fdba (diff)
Improving gesture event delivery for widgets.
Reviewed-by: trustme
-rw-r--r--src/gui/kernel/qapplication.cpp1
-rw-r--r--src/gui/kernel/qevent.h2
-rw-r--r--src/gui/kernel/qgesturemanager.cpp214
-rw-r--r--src/gui/kernel/qgesturemanager_p.h12
-rw-r--r--tests/auto/gestures/tst_gestures.cpp184
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"