diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2017-01-20 11:41:23 +0100 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@qt.io> | 2017-02-16 18:54:34 +0000 |
commit | 7042cfd9cb1b552c5fd753b6912439ce604eb1a0 (patch) | |
tree | bf9fe8a1e397b7748c45599383356dd45d4892e6 | |
parent | 87e74766d33bf364e42839d73e6b8b5e9cd39a07 (diff) |
allow stealing grab from handlers; notify passive grabbers when stolen
Now if a Button with a TapHandler is pressed and has only a passive
grab, Flickable can take the exclusive grab, and it notifies the
TapHandler so that the button can go back to released state.
This reverts parts of commit e2fd141372335f917c2d216051abb00d8b15f87c
such that more of tst_PointerHandlers is working the same as it was
before we started adding the passive grab concept.
Change-Id: I88970716fcbbfb066a313fcefb233cf9263da944
Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 38 | ||||
-rw-r--r-- | tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp | 27 | ||||
-rw-r--r-- | tests/manual/pointer/flickableWithHandlers.qml | 2 |
3 files changed, 44 insertions, 23 deletions
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 4bd63b3cf8..669e521b7f 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -746,21 +746,28 @@ void QQuickWindowPrivate::setMouseGrabber(QQuickItem *grabber) if (q->mouseGrabberItem() == grabber) return; - qCDebug(DBG_MOUSE_TARGET) << "grabber" << q->mouseGrabberItem() << "->" << grabber; QQuickItem *oldGrabber = q->mouseGrabberItem(); + qCDebug(DBG_MOUSE_TARGET) << "grabber" << oldGrabber << "->" << grabber; if (grabber && touchMouseId != -1 && touchMouseDevice) { // update the touch item for mouse touch id to the new grabber qCDebug(DBG_TOUCH_TARGET) << "TP (mouse)" << touchMouseId << "->" << q->mouseGrabberItem(); auto point = touchMouseDevice->pointerEvent()->pointById(touchMouseId); - if (point) + if (point) { point->setGrabberItem(grabber); + for (auto handler : point->passiveGrabbers()) + point->cancelPassiveGrab(handler); + } } else { QQuickPointerEvent *event = QQuickPointerDevice::genericMouseDevice()->pointerEvent(); Q_ASSERT(event->pointCount() == 1); - event->point(0)->setGrabberItem(grabber); + auto point = event->point(0); + point->setGrabberItem(grabber); + for (auto handler : point->passiveGrabbers()) + point->cancelPassiveGrab(handler); } + if (oldGrabber) { QEvent e(QEvent::UngrabMouse); QSet<QQuickItem *> hasFiltered; @@ -1679,7 +1686,8 @@ void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEven // if the grabber is not an Item, it must be a PointerHandler auto handler = point->grabberPointerHandler(); pointerEvent->localize(handler->parentItem()); - handler->handlePointerEvent(pointerEvent); + if (!sendFilteredPointerEvent(pointerEvent, handler->parentItem())) + handler->handlePointerEvent(pointerEvent); if (mouseIsReleased) { point->setGrabberPointerHandler(nullptr, true); point->clearPassiveGrabbers(); @@ -1698,18 +1706,21 @@ void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEven for (auto handler : point->passiveGrabbers()) { // a null pointer in passiveGrabbers is unlikely, unless the grabbing handler was deleted dynamically if (Q_LIKELY(handler) && !eventDeliveryTargets.contains(handler)) { - handler->handlePointerEvent(pointerEvent); + if (!sendFilteredPointerEvent(pointerEvent, handler->parentItem())) + handler->handlePointerEvent(pointerEvent); eventDeliveryTargets.append(handler); } } // If some points weren't grabbed, deliver to non-grabber PointerHandlers in reverse paint order - if (!pointerEvent->allPointsGrabbed()) { + if (!pointerEvent->allPointsGrabbed() && pointerEvent->buttons()) { QVector<QQuickItem *> targetItems = pointerTargets(contentItem, point->scenePos(), false); for (QQuickItem *item : targetItems) { QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item); pointerEvent->localize(item); - if (itemPrivate->handlePointerEvent(pointerEvent, true)) // avoid re-delivering to grabbers - delivered = true; + if (!sendFilteredPointerEvent(pointerEvent, item)) { + if (itemPrivate->handlePointerEvent(pointerEvent, true)) // avoid re-delivering to grabbers + delivered = true; + } if (point->grabber()) break; } @@ -2311,6 +2322,8 @@ void QQuickWindowPrivate::deliverUpdatedTouchPoints(QQuickPointerTouchEvent *eve QQuickEventPoint *point = event->point(i); for (auto handler : point->passiveGrabbers()) { if (Q_LIKELY(handler) && !eventDeliveryTargets.contains(handler)) { + if (sendFilteredPointerEvent(event, handler->parentItem())) + return; handler->handlePointerEvent(event); eventDeliveryTargets.append(handler); } @@ -2682,6 +2695,7 @@ bool QQuickWindowPrivate::sendFilteredPointerEvent(QQuickPointerEvent *event, QQ } } } else if (QQuickPointerTouchEvent *pte = event->asPointerTouchEvent()) { + QVarLengthArray<QPair<QQuickPointerHandler *, QQuickEventPoint *>, 32> passiveGrabsToCancel; for (QPair<QQuickItem *,QQuickItem *> itemAndParent : filteringParentItems) { QQuickItem *item = receiver ? receiver : itemAndParent.first; QQuickItem *filteringParent = itemAndParent.second; @@ -2730,6 +2744,12 @@ bool QQuickWindowPrivate::sendFilteredPointerEvent(QQuickPointerEvent *event, QQ touchMouseDevice = event->device(); touchMouseDevice->pointerEvent()->pointById(tp.id())->setGrabberItem(filteringParent); filteringParent->grabMouse(); + auto pointerEventPoint = pte->pointById(tp.id()); + for (auto handler : pointerEventPoint->passiveGrabbers()) { + QPair<QQuickPointerHandler *, QQuickEventPoint *> grab(handler, pointerEventPoint); + if (!passiveGrabsToCancel.contains(grab)) + passiveGrabsToCancel.append(grab); + } } ret = true; } @@ -2739,6 +2759,8 @@ bool QQuickWindowPrivate::sendFilteredPointerEvent(QQuickPointerEvent *event, QQ } } } + for (auto grab : passiveGrabsToCancel) + grab.second->cancelPassiveGrab(grab.first); } return ret; } diff --git a/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp b/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp index 5282fb8a6c..736555c378 100644 --- a/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp +++ b/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp @@ -403,12 +403,12 @@ void tst_PointerHandlers::mouseEventDelivery() // Do not accept anything QPoint p1 = QPoint(20, 20); QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1); - QCOMPARE(eventItem1->eventList.size(), 3); + QCOMPARE(eventItem1->eventList.size(), 2); p1 += QPoint(10, 0); QTest::mouseMove(window, p1); - QCOMPARE(eventItem1->eventList.size(), 4); + QCOMPARE(eventItem1->eventList.size(), 3); QTest::mouseRelease(window, Qt::LeftButton); - QCOMPARE(eventItem1->eventList.size(), 4); + QCOMPARE(eventItem1->eventList.size(), 3); eventItem1->eventList.clear(); // wait to avoid getting a double click event @@ -420,10 +420,9 @@ void tst_PointerHandlers::mouseEventDelivery() eventItem1->setAcceptedMouseButtons(Qt::LeftButton); p1 = QPoint(20, 20); QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1); - QCOMPARE(eventItem1->eventList.size(), 3); + QCOMPARE(eventItem1->eventList.size(), 2); QCOMPARE(eventItem1->eventList.at(0).type, QEvent::Pointer); - QCOMPARE(eventItem1->eventList.at(1).type, QEvent::Pointer); - QCOMPARE(eventItem1->eventList.at(2).type, QEvent::MouseButtonPress); + QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress); QCOMPARE(window->mouseGrabberItem(), eventItem1); QPointF localPos = eventItem1->mapFromScene(p1); @@ -435,12 +434,12 @@ void tst_PointerHandlers::mouseEventDelivery() p1 += QPoint(10, 0); QTest::mouseMove(window, p1); - QCOMPARE(eventItem1->eventList.size(), 4); - QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseMove); + QCOMPARE(eventItem1->eventList.size(), 3); + QCOMPARE(eventItem1->eventList.at(2).type, QEvent::MouseMove); QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1); - QCOMPARE(eventItem1->eventList.size(), 6); - QCOMPARE(eventItem1->eventList.at(4).type, QEvent::MouseButtonRelease); - QCOMPARE(eventItem1->eventList.at(5).type, QEvent::UngrabMouse); + QCOMPARE(eventItem1->eventList.size(), 5); + QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseButtonRelease); + QCOMPARE(eventItem1->eventList.at(4).type, QEvent::UngrabMouse); eventItem1->eventList.clear(); // wait to avoid getting a double click event @@ -452,14 +451,14 @@ void tst_PointerHandlers::mouseEventDelivery() eventItem1->grabPointer = true; p1 = QPoint(20, 20); QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1); - QTRY_COMPARE(eventItem1->eventList.size(), 2); + QTRY_COMPARE(eventItem1->eventList.size(), 1); QCOMPARE(eventItem1->eventList.at(0).type, QEvent::Pointer); p1 += QPoint(10, 0); QTest::mouseMove(window, p1); - QCOMPARE(eventItem1->eventList.size(), 3); + QCOMPARE(eventItem1->eventList.size(), 2); QCOMPARE(eventItem1->eventList.at(1).type, QEvent::Pointer); QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1); - QCOMPARE(eventItem1->eventList.size(), 4); + QCOMPARE(eventItem1->eventList.size(), 3); QCOMPARE(eventItem1->eventList.at(2).type, QEvent::Pointer); eventItem1->eventList.clear(); diff --git a/tests/manual/pointer/flickableWithHandlers.qml b/tests/manual/pointer/flickableWithHandlers.qml index 59e8661aac..822ca7dc8a 100644 --- a/tests/manual/pointer/flickableWithHandlers.qml +++ b/tests/manual/pointer/flickableWithHandlers.qml @@ -44,7 +44,7 @@ import "content" Rectangle { id: root - width: 300 + width: 400 height: 400 objectName: "root" color: "#222222" |