From 28ad286c3e2df7e391d4e5cbe41958c9be12d900 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Fri, 14 May 2010 11:27:47 +0200 Subject: Gestures in GraphicsView do not require a viewport to subscribe to gestures. When a graphicsitem subscribes to a gesture the viewport is implicitly subscribed to it as well. Task-number: QTBUG-9849 Reviewed-by: Olivier Goffart Reviewed-by: Mikko Harju --- src/gui/graphicsview/qgraphicsitem.cpp | 14 +++--- src/gui/graphicsview/qgraphicsscene.cpp | 29 ++++++++++++ src/gui/graphicsview/qgraphicsscene.h | 1 + src/gui/graphicsview/qgraphicsscene_p.h | 3 ++ src/gui/graphicsview/qgraphicsview.cpp | 5 ++ tests/auto/gestures/tst_gestures.cpp | 83 ++++++++++++++++++++++++++------- 6 files changed, 110 insertions(+), 25 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 5e0d46f..04d9075 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -7650,9 +7650,10 @@ QGraphicsObject::QGraphicsObject(QGraphicsItemPrivate &dd, QGraphicsItem *parent */ void QGraphicsObject::grabGesture(Qt::GestureType gesture, Qt::GestureFlags flags) { - QGraphicsItemPrivate * const d = QGraphicsItem::d_func(); - d->gestureContext.insert(gesture, flags); - (void)QGestureManager::instance(); // create a gesture manager + bool contains = QGraphicsItem::d_ptr->gestureContext.contains(gesture); + QGraphicsItem::d_ptr->gestureContext.insert(gesture, flags); + if (!contains && QGraphicsItem::d_ptr->scene) + QGraphicsItem::d_ptr->scene->d_func()->grabGesture(this, gesture); } /*! @@ -7662,11 +7663,8 @@ void QGraphicsObject::grabGesture(Qt::GestureType gesture, Qt::GestureFlags flag */ void QGraphicsObject::ungrabGesture(Qt::GestureType gesture) { - QGraphicsItemPrivate * const d = QGraphicsItem::d_func(); - if (d->gestureContext.remove(gesture)) { - QGestureManager *manager = QGestureManager::instance(); - manager->cleanupCachedGestures(this, gesture); - } + if (QGraphicsItem::d_ptr->gestureContext.remove(gesture) && QGraphicsItem::d_ptr->scene) + QGraphicsItem::d_ptr->scene->d_func()->ungrabGesture(this, gesture); } /*! Updates the item's micro focus. This is slot for convenience. diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 9b7cf12..b7e2fda 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -710,6 +710,9 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item) cachedTargetItems.removeOne(dummy); cachedItemGestures.remove(dummy); cachedAlreadyDeliveredGestures.remove(dummy); + + foreach (Qt::GestureType gesture, item->d_ptr->gestureContext.keys()) + ungrabGesture(item, gesture); } /*! @@ -2595,6 +2598,9 @@ void QGraphicsScene::addItem(QGraphicsItem *item) d->enableTouchEventsOnViews(); } + foreach (Qt::GestureType gesture, item->d_ptr->gestureContext.keys()) + d->grabGesture(item, gesture); + // Update selection lists if (item->isSelected()) d->selectedItems << item; @@ -5609,6 +5615,8 @@ bool QGraphicsScene::sendEvent(QGraphicsItem *item, QEvent *event) void QGraphicsScenePrivate::addView(QGraphicsView *view) { views << view; + foreach (Qt::GestureType gesture, grabbedGestures.keys()) + view->viewport()->grabGesture(gesture); } void QGraphicsScenePrivate::removeView(QGraphicsView *view) @@ -6306,6 +6314,27 @@ void QGraphicsScenePrivate::cancelGesturesForChildren(QGesture *original) } } +void QGraphicsScenePrivate::grabGesture(QGraphicsItem *, Qt::GestureType gesture) +{ + (void)QGestureManager::instance(); // create a gesture manager + if (!grabbedGestures[gesture]++) { + foreach (QGraphicsView *view, views) + view->viewport()->grabGesture(gesture); + } +} + +void QGraphicsScenePrivate::ungrabGesture(QGraphicsItem *item, Qt::GestureType gesture) +{ + // we know this can only be an object + Q_ASSERT(item->d_ptr->isObject); + QGraphicsObject *obj = static_cast(item); + QGestureManager::instance()->cleanupCachedGestures(obj, gesture); + if (!--grabbedGestures[gesture]) { + foreach (QGraphicsView *view, views) + view->viewport()->ungrabGesture(gesture); + } +} + QT_END_NAMESPACE #include "moc_qgraphicsscene.cpp" diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h index e5b15ef..c34a303 100644 --- a/src/gui/graphicsview/qgraphicsscene.h +++ b/src/gui/graphicsview/qgraphicsscene.h @@ -302,6 +302,7 @@ private: Q_PRIVATE_SLOT(d_func(), void _q_updateScenePosDescendants()) friend class QGraphicsItem; friend class QGraphicsItemPrivate; + friend class QGraphicsObject; friend class QGraphicsView; friend class QGraphicsViewPrivate; friend class QGraphicsWidget; diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 77bf450..8ad2a0a 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -302,6 +302,7 @@ public: QHash > cachedItemGestures; QHash > cachedAlreadyDeliveredGestures; QHash gestureTargets; + QHash grabbedGestures; void gestureEventHandler(QGestureEvent *event); void gestureTargetsAtHotSpots(const QSet &gestures, Qt::GestureFlag flag, @@ -310,6 +311,8 @@ public: QSet *normal = 0, QSet *conflicts = 0); void cancelGesturesForChildren(QGesture *original); + void grabGesture(QGraphicsItem *, Qt::GestureType gesture); + void ungrabGesture(QGraphicsItem *, Qt::GestureType gesture); void updateInputMethodSensitivityInViews(); diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index d2964ca..9dfcd2c 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -2688,6 +2688,11 @@ void QGraphicsView::setupViewport(QWidget *widget) if (d->scene && !d->scene->d_func()->allItemsIgnoreTouchEvents) widget->setAttribute(Qt::WA_AcceptTouchEvents); + if (d->scene) { + foreach (Qt::GestureType gesture, d->scene->d_func()->grabbedGestures.keys()) + widget->grabGesture(gesture); + } + widget->setAcceptDrops(acceptDrops()); } diff --git a/tests/auto/gestures/tst_gestures.cpp b/tests/auto/gestures/tst_gestures.cpp index dfadf48..4a9f1d1 100644 --- a/tests/auto/gestures/tst_gestures.cpp +++ b/tests/auto/gestures/tst_gestures.cpp @@ -336,6 +336,7 @@ private slots: void finishedWithoutStarted(); void unknownGesture(); void graphicsItemGesture(); + void graphicsView(); void graphicsItemTreeGesture(); void explicitGraphicsObjectTarget(); void gestureOverChildGraphicsItem(); @@ -859,7 +860,6 @@ void tst_Gestures::graphicsItemGesture() QTest::qWaitForWindowShown(&view); view.ensureVisible(scene.sceneRect()); - view.viewport()->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); item->grabGesture(CustomGesture::GestureType); static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; @@ -908,6 +908,71 @@ void tst_Gestures::graphicsItemGesture() QCOMPARE(item->gestureOverrideEventsReceived, 0); } +void tst_Gestures::graphicsView() +{ + QGraphicsScene scene; + QGraphicsView view(&scene); + view.setWindowFlags(Qt::X11BypassWindowManagerHint); + + GestureItem *item = new GestureItem("item"); + scene.addItem(item); + item->setPos(100, 100); + + view.show(); + QTest::qWaitForWindowShown(&view); + view.ensureVisible(scene.sceneRect()); + + item->grabGesture(CustomGesture::GestureType); + + static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; + static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1; + + CustomEvent event; + // make sure the event is properly delivered if only the hotspot is set. + event.hotSpot = mapToGlobal(QPointF(10, 10), item, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item, &scene); + + QCOMPARE(item->customEventsReceived, TotalCustomEventsCount); + QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item->gestureOverrideEventsReceived, 0); + + // change the viewport and try again + QWidget *newViewport = new QWidget; + view.setViewport(newViewport); + + item->reset(); + sendCustomGesture(&event, item, &scene); + + QCOMPARE(item->customEventsReceived, TotalCustomEventsCount); + QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item->gestureOverrideEventsReceived, 0); + + // change the scene and try again + QGraphicsScene newScene; + item = new GestureItem("newItem"); + newScene.addItem(item); + item->setPos(100, 100); + view.setScene(&newScene); + + item->reset(); + // first without a gesture + sendCustomGesture(&event, item, &newScene); + + QCOMPARE(item->customEventsReceived, TotalCustomEventsCount); + QCOMPARE(item->gestureEventsReceived, 0); + QCOMPARE(item->gestureOverrideEventsReceived, 0); + + // then grab the gesture and try again + item->reset(); + item->grabGesture(CustomGesture::GestureType); + sendCustomGesture(&event, item, &newScene); + + QCOMPARE(item->customEventsReceived, TotalCustomEventsCount); + QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item->gestureOverrideEventsReceived, 0); +} + void tst_Gestures::graphicsItemTreeGesture() { QGraphicsScene scene; @@ -933,7 +998,6 @@ void tst_Gestures::graphicsItemTreeGesture() QTest::qWaitForWindowShown(&view); view.ensureVisible(scene.sceneRect()); - view.viewport()->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); item1->grabGesture(CustomGesture::GestureType); static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; @@ -991,7 +1055,6 @@ void tst_Gestures::explicitGraphicsObjectTarget() QTest::qWaitForWindowShown(&view); view.ensureVisible(scene.sceneRect()); - view.viewport()->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); item1->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); item2->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); item2_child1->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); @@ -1051,7 +1114,6 @@ void tst_Gestures::gestureOverChildGraphicsItem() QTest::qWaitForWindowShown(&view); view.ensureVisible(scene.sceneRect()); - view.viewport()->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); item1->grabGesture(CustomGesture::GestureType); static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; @@ -1519,8 +1581,6 @@ void tst_Gestures::autoCancelGestures2() parent->setPos(0, 0); child->setPos(10, 10); scene.addItem(parent); - view.viewport()->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); - view.viewport()->grabGesture(secondGesture, Qt::DontStartGestureOnChildren); parent->grabGesture(CustomGesture::GestureType); child->grabGesture(secondGesture); @@ -1573,7 +1633,6 @@ void tst_Gestures::graphicsViewParentPropagation() QTest::qWaitForWindowShown(&view); view.ensureVisible(scene.sceneRect()); - view.viewport()->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); item0->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures | Qt::IgnoredGesturesPropagateToParent); item1->grabGesture(CustomGesture::GestureType, Qt::ReceivePartialGestures | Qt::IgnoredGesturesPropagateToParent); item1_c1->grabGesture(CustomGesture::GestureType, Qt::IgnoredGesturesPropagateToParent); @@ -1644,8 +1703,6 @@ void tst_Gestures::panelPropagation() QTest::qWaitForWindowShown(&view); view.ensureVisible(scene.sceneRect()); - view.viewport()->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); - static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1; @@ -1757,8 +1814,6 @@ void tst_Gestures::panelStacksBehindParent() QTest::qWaitForWindowShown(&view); view.ensureVisible(scene.sceneRect()); - view.viewport()->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); - static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1; CustomEvent event; @@ -1843,8 +1898,6 @@ void tst_Gestures::deleteGestureTargetItem() QTest::qWaitForWindowShown(&view); view.ensureVisible(scene.sceneRect()); - view.viewport()->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); - if (propagateUpdateGesture) item2->ignoredUpdatedGestures << CustomGesture::GestureType; connect(items.value(emitter, 0), signalName, items.value(receiver, 0), slotName); @@ -1890,8 +1943,6 @@ void tst_Gestures::viewportCoordinates() QTest::qWaitForWindowShown(&view); view.ensureVisible(scene.sceneRect()); - view.viewport()->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); - CustomEvent event; event.hotSpot = mapToGlobal(item1->boundingRect().center(), item1, &view); event.hasHotSpot = true; @@ -1929,8 +1980,6 @@ void tst_Gestures::partialGesturePropagation() QTest::qWaitForWindowShown(&view); view.ensureVisible(scene.sceneRect()); - view.viewport()->grabGesture(CustomGesture::GestureType, Qt::DontStartGestureOnChildren); - item1->ignoredUpdatedGestures << CustomGesture::GestureType; CustomEvent event; -- cgit v0.12