diff options
-rw-r--r-- | src/corelib/global/qnamespace.h | 12 | ||||
-rw-r--r-- | src/corelib/global/qnamespace.qdoc | 18 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsscene.cpp | 13 | ||||
-rw-r--r-- | src/gui/kernel/qapplication.cpp | 7 | ||||
-rw-r--r-- | src/gui/kernel/qgesturemanager.cpp | 16 | ||||
-rw-r--r-- | tests/auto/gestures/tst_gestures.cpp | 121 |
6 files changed, 150 insertions, 37 deletions
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index aeaca54..561ffc1 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -1715,14 +1715,19 @@ public: LastGestureType = ~0u }; - enum GestureContext + enum GestureContextFlag { WidgetGesture = 0, WidgetWithChildrenGesture = 3, - ItemGesture = WidgetGesture, - ItemWithChildrenGesture = WidgetWithChildrenGesture + ItemGesture = WidgetGesture, + ItemWithChildrenGesture = WidgetWithChildrenGesture, + + GestureContext_Mask = 0x00ff, + AcceptPartialGesturesHint = 0x0100, + GestureContextHint_Mask = 0xff00 }; + Q_DECLARE_FLAGS(GestureContext, GestureContextFlag) enum NavigationMode { @@ -1757,6 +1762,7 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::MatchFlags) Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::TextInteractionFlags) Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::InputMethodHints) Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::TouchPointStates) +Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::GestureContext) typedef bool (*qInternalCallback)(void **); diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index 3fcbe57..f2a8882 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -2917,11 +2917,11 @@ QApplication::registerGestureRecognizer() function which generates a custom gesture ID in the range of values from CustomGesture to LastGestureType. - \sa QGesture, QWidget::grabGesture() + \sa QGesture, QWidget::grabGesture(), QGraphicsObject::grabGesture() */ /*! - \enum Qt::GestureContext + \enum Qt::GestureContextFlag \since 4.6 This enum type describes the context of a gesture. @@ -2937,7 +2937,19 @@ \value ItemWithChildrenGesture Gestures can start on the item or over any of its children. - \sa QWidget::grabGesture() + \value AcceptPartialGesturesHint Allows any ignored gesture events to be + propagated to parent widgets which have specified this hint. By default + only gestures that are in the Qt::GestureStarted state are propagated and + the widget only gets the full gesture sequence starting with a gesture in + the Qt::GestureStarted state and ending with a gesture in the + Qt::GestureFinished or Qt::GestureCanceled states. + + \value GestureContext_Mask A mask for extracting the context type of the + context flags. + \value GestureContextHint_Mask A mask for extracting additional hints for + the context. + + \sa QWidget::grabGesture(), QGraphicsObject::grabGesture() */ /*! diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 9279fe3..f5bb408 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5900,7 +5900,12 @@ void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event) QGraphicsItemPrivate *gid = item->QGraphicsItem::d_func(); foreach(QGesture *g, alreadyIgnoredGestures) { - if (gid->gestureContext.contains(g->gestureType())) + QMap<Qt::GestureType, Qt::GestureContext>::iterator contextit = + gid->gestureContext.find(g->gestureType()); + bool deliver = contextit != gid->gestureContext.end() && + (g->state() == Qt::GestureStarted || + (contextit.value() & Qt::GestureContextHint_Mask) & Qt::AcceptPartialGesturesHint); + if (deliver) gestures += g; } if (gestures.isEmpty()) @@ -5913,8 +5918,12 @@ void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event) sendEvent(item, &ev); QSet<QGesture *> ignoredGestures; foreach (QGesture *g, gestures) { - if (!ev.isAccepted() && !ev.isAccepted(g)) + if (!ev.isAccepted() && !ev.isAccepted(g)) { ignoredGestures.insert(g); + } else { + if (g->state() == Qt::GestureStarted) + gestureTargets[g] = item; + } } if (!ignoredGestures.isEmpty()) { // get a list of items under the (current) hotspot of each ignored diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 06787eb..b9e7d52 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -4161,7 +4161,12 @@ bool QApplication::notify(QObject *receiver, QEvent *e) for (int i = 0; i < allGestures.size();) { QGesture *g = allGestures.at(i); Qt::GestureType type = g->gestureType(); - if (wd->gestureContext.contains(type)) { + QMap<Qt::GestureType, Qt::GestureContext>::iterator contextit = + wd->gestureContext.find(type); + bool deliver = contextit != wd->gestureContext.end() && + (g->state() == Qt::GestureStarted || w == receiver || + (contextit.value() & Qt::GestureContextHint_Mask) & Qt::AcceptPartialGesturesHint); + if (deliver) { allGestures.removeAt(i); gestures.append(g); } else { diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp index 318d4b5..e4a1eb4 100644 --- a/src/gui/kernel/qgesturemanager.cpp +++ b/src/gui/kernel/qgesturemanager.cpp @@ -448,7 +448,7 @@ bool QGestureManager::filterEvent(QWidget *receiver, QEvent *event) { for (ContextIterator it = w->d_func()->gestureContext.begin(), e = w->d_func()->gestureContext.end(); it != e; ++it) { - if (it.value() == Qt::WidgetWithChildrenGesture) { + if ((it.value() & Qt::GestureContext_Mask) == Qt::WidgetWithChildrenGesture) { if (!types.contains(it.key())) { types.insert(it.key()); contexts.insertMulti(w, it.key()); @@ -482,7 +482,7 @@ bool QGestureManager::filterEvent(QGraphicsObject *receiver, 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) { + if ((it.value() & Qt::GestureContext_Mask) == Qt::ItemWithChildrenGesture) { if (!types.contains(it.key())) { types.insert(it.key()); contexts.insertMulti(item, it.key()); @@ -525,7 +525,7 @@ void QGestureManager::getGestureTargets(const QSet<QGesture*> &gestures, = 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(); + Qt::GestureContext context = it.value() & Qt::GestureContext_Mask; if (context == Qt::WidgetWithChildrenGesture && w != widget) { // conflicting gesture! (*conflicts)[widget].append(gestures[widget]); @@ -645,6 +645,16 @@ void QGestureManager::deliverEvents(const QSet<QGesture *> &gestures, << "gestures:" << it.value(); QGestureEvent event(it.value()); QApplication::sendEvent(it.key(), &event); + bool eventAccepted = event.isAccepted(); + foreach (QGesture *gesture, event.allGestures()) { + if (gesture->state() == Qt::GestureStarted && + (eventAccepted || event.isAccepted(gesture))) { + QWidget *w = event.d_func()->targetWidgets.value(gesture->gestureType(), 0); + Q_ASSERT(w); + DEBUG() << "started gesture was delivered and accepted by" << w; + m_gestureTargets[gesture] = w; + } + } } } } diff --git a/tests/auto/gestures/tst_gestures.cpp b/tests/auto/gestures/tst_gestures.cpp index 79de823..9b2bc57 100644 --- a/tests/auto/gestures/tst_gestures.cpp +++ b/tests/auto/gestures/tst_gestures.cpp @@ -543,7 +543,9 @@ void tst_Gestures::conflictingGestures() parent.reset(); child->reset(); - // nobody accepts the override, we will send normal events to the closest context (to the child) + // nobody accepts the override, we will send normal events to the closest + // context (i.e. to the child widget) and it will be propagated and + // accepted by the parent widget parent.acceptGestureOverride = false; child->acceptGestureOverride = false; child->ignoredGestures << CustomGesture::GestureType; @@ -552,6 +554,41 @@ void tst_Gestures::conflictingGestures() sendCustomGesture(&event, child); QCOMPARE(child->gestureOverrideEventsReceived, 1); + QCOMPARE(child->gestureEventsReceived, 1); + QCOMPARE(parent.gestureOverrideEventsReceived, 1); + QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount); + + parent.reset(); + child->reset(); + + // nobody accepts the override, and nobody accepts the gesture event + parent.acceptGestureOverride = false; + child->acceptGestureOverride = false; + parent.ignoredGestures << CustomGesture::GestureType; + child->ignoredGestures << CustomGesture::GestureType; + + // sending events to the child and making sure there is no conflict + sendCustomGesture(&event, child); + + QCOMPARE(child->gestureOverrideEventsReceived, 1); + QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(parent.gestureOverrideEventsReceived, 1); + QCOMPARE(parent.gestureEventsReceived, 1); + + parent.reset(); + child->reset(); + + // we set an attribute to make sure all gesture events are propagated + parent.grabGesture(CustomGesture::GestureType, Qt::WidgetWithChildrenGesture | Qt::AcceptPartialGesturesHint); + parent.acceptGestureOverride = false; + child->acceptGestureOverride = false; + parent.ignoredGestures << CustomGesture::GestureType; + child->ignoredGestures << CustomGesture::GestureType; + + // sending events to the child and making sure there is no conflict + sendCustomGesture(&event, child); + + QCOMPARE(child->gestureOverrideEventsReceived, 1); QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount); QCOMPARE(parent.gestureOverrideEventsReceived, 1); QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount); @@ -851,7 +888,7 @@ void tst_Gestures::graphicsItemTreeGesture() QCOMPARE(item1_child2->gestureEventsReceived, 0); QCOMPARE(item1_child2->gestureOverrideEventsReceived, 0); QCOMPARE(item1->gestureOverrideEventsReceived, 1); - QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item1->gestureEventsReceived, 1); } void tst_Gestures::explicitGraphicsObjectTarget() @@ -966,7 +1003,39 @@ void tst_Gestures::gestureOverChildGraphicsItem() event.hasHotSpot = true; sendCustomGesture(&event, item0, &scene); - QCOMPARE(item0->customEventsReceived, TotalCustomEventsCount); + QCOMPARE(item2_child1->gestureEventsReceived, 0); + QCOMPARE(item2_child1->gestureOverrideEventsReceived, 0); + QCOMPARE(item2->gestureEventsReceived, 1); + QCOMPARE(item2->gestureOverrideEventsReceived, 1); + QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item1->gestureOverrideEventsReceived, 1); + + item0->reset(); item1->reset(); item2->reset(); item2_child1->reset(); + item2->grabGesture(CustomGesture::GestureType); + item2->ignoredGestures << CustomGesture::GestureType; + item1->ignoredGestures << CustomGesture::GestureType; + + event.hotSpot = mapToGlobal(QPointF(10, 10), item2_child1, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item0, &scene); + + QCOMPARE(item2_child1->gestureEventsReceived, 0); + QCOMPARE(item2_child1->gestureOverrideEventsReceived, 0); + QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item2->gestureOverrideEventsReceived, 1); + QCOMPARE(item1->gestureEventsReceived, 1); + QCOMPARE(item1->gestureOverrideEventsReceived, 1); + + item0->reset(); item1->reset(); item2->reset(); item2_child1->reset(); + item2->grabGesture(CustomGesture::GestureType); + item2->ignoredGestures << CustomGesture::GestureType; + item1->ignoredGestures << CustomGesture::GestureType; + item1->grabGesture(CustomGesture::GestureType, Qt::WidgetWithChildrenGesture | Qt::AcceptPartialGesturesHint); + + event.hotSpot = mapToGlobal(QPointF(10, 10), item2_child1, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item0, &scene); + QCOMPARE(item2_child1->gestureEventsReceived, 0); QCOMPARE(item2_child1->gestureOverrideEventsReceived, 0); QCOMPARE(item2->gestureEventsReceived, TotalGestureEventsCount); @@ -1025,15 +1094,16 @@ void tst_Gestures::multipleGesturesInTree() Qt::GestureType SecondGesture = QApplication::registerGestureRecognizer(new CustomGestureRecognizer); Qt::GestureType ThirdGesture = QApplication::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); + Qt::GestureContext context = Qt::WidgetWithChildrenGesture | Qt::AcceptPartialGesturesHint; + A->grabGesture(FirstGesture, context); // A [1 3] + A->grabGesture(ThirdGesture, context); // | + B->grabGesture(SecondGesture, context); // B [ 2 3] + B->grabGesture(ThirdGesture, context); // | + C->grabGesture(FirstGesture, context); // C [1 2 3] + C->grabGesture(SecondGesture, context); // | + C->grabGesture(ThirdGesture, context); // D [1 3] + D->grabGesture(FirstGesture, context); + D->grabGesture(ThirdGesture, context); // make sure all widgets ignore events, so they get propagated. A->ignoredGestures << FirstGesture << ThirdGesture; @@ -1100,19 +1170,20 @@ void tst_Gestures::multipleGesturesInComplexTree() Qt::GestureType SixthGesture = QApplication::registerGestureRecognizer(new CustomGestureRecognizer); Qt::GestureType SeventhGesture = QApplication::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); + Qt::GestureContext context = Qt::WidgetWithChildrenGesture | Qt::AcceptPartialGesturesHint; + A->grabGesture(FirstGesture, context); // A [1,3,4] + A->grabGesture(ThirdGesture, context); // | + A->grabGesture(FourthGesture, context); // B [2,3,5] + B->grabGesture(SecondGesture, context); // | + B->grabGesture(ThirdGesture, context); // C [1,2,3,6] + B->grabGesture(FifthGesture, context); // | + C->grabGesture(FirstGesture, context); // D [1,3,7] + C->grabGesture(SecondGesture, context); + C->grabGesture(ThirdGesture, context); + C->grabGesture(SixthGesture, context); + D->grabGesture(FirstGesture, context); + D->grabGesture(ThirdGesture, context); + D->grabGesture(SeventhGesture, context); // make sure all widgets ignore events, so they get propagated. QSet<Qt::GestureType> allGestureTypes; |