From 43233652e753ffa2b97a8b6d56ae53bb02cbad6b Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Tue, 9 Feb 2010 10:50:27 +0100 Subject: Implemented GraphicsView Panel support for gestures. Events should not propagate outside the panel. Also when delivering gesture events we should respect panels modality. Task-number: QTBUG-7451 Reviewed-by: Mikko Harju Reviewed-by: Bradley T. Hughes --- src/gui/graphicsview/qgraphicsscene.cpp | 20 ++-- tests/auto/gestures/tst_gestures.cpp | 171 +++++++++++++++++++++++++++++++- 2 files changed, 183 insertions(+), 8 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 66707fc..96d2435 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5902,13 +5902,21 @@ void QGraphicsScenePrivate::getGestureTargets(const QSet &gestures, QList items = itemsAtPosition(screenPos, QPointF(), viewport); QList result; for (int j = 0; j < items.size(); ++j) { - QGraphicsObject *item = items.at(j)->toGraphicsObject(); - if (!item) - continue; - QGraphicsItemPrivate *d = item->QGraphicsItem::d_func(); - if (d->gestureContext.contains(gestureType)) { - result.append(item); + QGraphicsItem *item = items.at(j); + + // Check if the item is blocked by a modal panel and use it as + // a target instead of this item. + (void) item->isBlockedByModalPanel(&item); + + if (QGraphicsObject *itemobj = item->toGraphicsObject()) { + QGraphicsItemPrivate *d = item->d_func(); + if (d->gestureContext.contains(gestureType)) { + result.append(itemobj); + } } + // Don't propagate through panels. + if (item->isPanel()) + break; } DEBUG() << "QGraphicsScenePrivate::getGestureTargets:" << gesture << result; diff --git a/tests/auto/gestures/tst_gestures.cpp b/tests/auto/gestures/tst_gestures.cpp index 952136b..986227d 100644 --- a/tests/auto/gestures/tst_gestures.cpp +++ b/tests/auto/gestures/tst_gestures.cpp @@ -333,6 +333,8 @@ private slots: void unregisterRecognizer(); void autoCancelGestures(); void autoCancelGestures2(); + void panelPropagation(); + void panelStacksBehindParent(); }; tst_Gestures::tst_Gestures() @@ -1457,9 +1459,7 @@ void tst_Gestures::autoCancelGestures2() event.serial = CustomGesture::SerialStartedThreshold; event.hasHotSpot = true; event.hotSpot = mapToGlobal(QPointF(5, 5), child, &view); - // qDebug() << event.hotSpot; scene.sendEvent(child, &event); - //QEventLoop().exec(); QCOMPARE(parent->events.all.count(), 1); QCOMPARE(child->events.started.count(), 1); QCOMPARE(child->events.canceled.count(), 1); @@ -1471,5 +1471,172 @@ void tst_Gestures::autoCancelGestures2() QCOMPARE(parent->events.all.count(), 2); } +void tst_Gestures::panelPropagation() +{ + QGraphicsScene scene; + QGraphicsView view(&scene); + view.setWindowFlags(Qt::X11BypassWindowManagerHint); + + GestureItem *item0 = new GestureItem("item0"); + scene.addItem(item0); + item0->setPos(0, 0); + item0->size = QRectF(0, 0, 200, 200); + item0->grabGesture(CustomGesture::GestureType); + item0->setZValue(1); + + GestureItem *item1 = new GestureItem("item1"); + item1->grabGesture(CustomGesture::GestureType); + scene.addItem(item1); + item1->setPos(10, 10); + item1->size = QRectF(0, 0, 180, 180); + item1->setZValue(2); + + GestureItem *item1_child1 = new GestureItem("item1_child1[panel]"); + item1_child1->setFlags(QGraphicsItem::ItemIsPanel); + item1_child1->setParentItem(item1); + item1_child1->grabGesture(CustomGesture::GestureType); + item1_child1->setPos(10, 10); + item1_child1->size = QRectF(0, 0, 160, 160); + item1_child1->setZValue(5); + + GestureItem *item1_child1_child1 = new GestureItem("item1_child1_child1"); + item1_child1_child1->setParentItem(item1_child1); + item1_child1_child1->grabGesture(CustomGesture::GestureType); + item1_child1_child1->setPos(10, 10); + item1_child1_child1->size = QRectF(0, 0, 140, 140); + item1_child1_child1->setZValue(10); + + view.show(); + 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; + + CustomEvent event; + event.hotSpot = mapToGlobal(QPointF(5, 5), item1_child1_child1, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item0, &scene); + + QCOMPARE(item0->customEventsReceived, TotalCustomEventsCount); + QCOMPARE(item1_child1_child1->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 1); + QCOMPARE(item1_child1->gestureOverrideEventsReceived, 1); + QCOMPARE(item1->gestureEventsReceived, 0); + QCOMPARE(item1->gestureOverrideEventsReceived, 0); + QCOMPARE(item0->gestureEventsReceived, 0); + QCOMPARE(item0->gestureOverrideEventsReceived, 0); + + item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset(); + + event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item1, &scene); + + QCOMPARE(item1_child1_child1->gestureEventsReceived, 0); + QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0); + QCOMPARE(item1_child1->gestureEventsReceived, 0); + QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0); + QCOMPARE(item1->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item1->gestureOverrideEventsReceived, 1); + QCOMPARE(item0->gestureEventsReceived, 0); + QCOMPARE(item0->gestureOverrideEventsReceived, 1); + + item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset(); + // try with a modal panel + item1_child1->setPanelModality(QGraphicsItem::PanelModal); + + event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item1, &scene); + + QCOMPARE(item1_child1_child1->gestureEventsReceived, 0); + QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0); + QCOMPARE(item1_child1->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0); + QCOMPARE(item1->gestureEventsReceived, 0); + QCOMPARE(item1->gestureOverrideEventsReceived, 0); + QCOMPARE(item0->gestureEventsReceived, 0); + QCOMPARE(item0->gestureOverrideEventsReceived, 0); + + item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset(); + // try with a modal panel, however set the hotspot to be outside of the + // panel and its parent + item1_child1->setPanelModality(QGraphicsItem::PanelModal); + + event.hotSpot = mapToGlobal(QPointF(5, 5), item0, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item1, &scene); + + QCOMPARE(item1_child1_child1->gestureEventsReceived, 0); + QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0); + QCOMPARE(item1_child1->gestureEventsReceived, 0); + QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0); + QCOMPARE(item1->gestureEventsReceived, 0); + QCOMPARE(item1->gestureOverrideEventsReceived, 0); + QCOMPARE(item0->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item0->gestureOverrideEventsReceived, 0); + + item0->reset(); item1->reset(); item1_child1->reset(); item1_child1_child1->reset(); + // try with a scene modal panel + item1_child1->setPanelModality(QGraphicsItem::SceneModal); + + event.hotSpot = mapToGlobal(QPointF(5, 5), item0, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item0, &scene); + + QCOMPARE(item1_child1_child1->gestureEventsReceived, 0); + QCOMPARE(item1_child1_child1->gestureOverrideEventsReceived, 0); + QCOMPARE(item1_child1->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(item1_child1->gestureOverrideEventsReceived, 0); + QCOMPARE(item1->gestureEventsReceived, 0); + QCOMPARE(item1->gestureOverrideEventsReceived, 0); + QCOMPARE(item0->gestureEventsReceived, 0); + QCOMPARE(item0->gestureOverrideEventsReceived, 0); +} + +void tst_Gestures::panelStacksBehindParent() +{ + QGraphicsScene scene; + QGraphicsView view(&scene); + view.setWindowFlags(Qt::X11BypassWindowManagerHint); + + GestureItem *item1 = new GestureItem("item1"); + item1->grabGesture(CustomGesture::GestureType); + scene.addItem(item1); + item1->setPos(10, 10); + item1->size = QRectF(0, 0, 180, 180); + item1->setZValue(2); + + GestureItem *panel = new GestureItem("panel"); + panel->setFlags(QGraphicsItem::ItemIsPanel | QGraphicsItem::ItemStacksBehindParent); + panel->setPanelModality(QGraphicsItem::PanelModal); + panel->setParentItem(item1); + panel->grabGesture(CustomGesture::GestureType); + panel->setPos(-10, -10); + panel->size = QRectF(0, 0, 200, 200); + panel->setZValue(5); + + view.show(); + 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; + event.hotSpot = mapToGlobal(QPointF(5, 5), item1, &view); + event.hasHotSpot = true; + sendCustomGesture(&event, item1, &scene); + + QCOMPARE(item1->gestureEventsReceived, 0); + QCOMPARE(item1->gestureOverrideEventsReceived, 0); + QCOMPARE(panel->gestureEventsReceived, TotalGestureEventsCount); + QCOMPARE(panel->gestureOverrideEventsReceived, 0); +} + QTEST_MAIN(tst_Gestures) #include "tst_gestures.moc" -- cgit v0.12 From 49228260b8a70a8177c5eb89b73ed6f3a07b7cc9 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Thu, 11 Feb 2010 15:24:48 +0100 Subject: Ignore touch and gesture events when excluding input events When asked to exclude input events when processing events in the event dispatcher we should also exclude touch and gesture events on Windows and Mac. Reviewed-by: Bradley T. Hughes --- src/corelib/kernel/qeventdispatcher_win.cpp | 11 +++++++++++ src/gui/kernel/qeventdispatcher_mac.mm | 8 ++++++++ 2 files changed, 19 insertions(+) diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index cbc87f3..93becc8 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -68,6 +68,14 @@ extern uint qGlobalPostedEventsCount(); # define QS_RAWINPUT 0x0400 #endif +#ifndef WM_TOUCH +# define WM_TOUCH 0x0240 +#endif +#ifndef WM_GESTURE +# define WM_GESTURE 0x0119 +# define WM_GESTURENOTIFY 0x011A +#endif + enum { WM_QT_SOCKETNOTIFIER = WM_USER, WM_QT_SENDPOSTEDEVENTS = WM_USER + 1, @@ -714,6 +722,9 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) && msg.message <= WM_MOUSELAST) || msg.message == WM_MOUSEWHEEL || msg.message == WM_MOUSEHWHEEL + || msg.message == WM_TOUCH + || msg.message == WM_GESTURE + || msg.message == WM_GESTURENOTIFY || msg.message == WM_CLOSE)) { // queue user input events for later processing haveMessage = false; diff --git a/src/gui/kernel/qeventdispatcher_mac.mm b/src/gui/kernel/qeventdispatcher_mac.mm index c7c7caf..0b3d62f 100644 --- a/src/gui/kernel/qeventdispatcher_mac.mm +++ b/src/gui/kernel/qeventdispatcher_mac.mm @@ -492,6 +492,14 @@ static bool IsMouseOrKeyEvent( NSEvent* event ) case NSOtherMouseDown: case NSOtherMouseUp: case NSOtherMouseDragged: +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 + case NSEventTypeGesture: // touch events + case NSEventTypeMagnify: + case NSEventTypeSwipe: + case NSEventTypeRotate: + case NSEventTypeBeginGesture: + case NSEventTypeEndGesture: +#endif result = true; break; -- cgit v0.12