aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2017-01-20 11:41:23 +0100
committerShawn Rutledge <shawn.rutledge@qt.io>2017-02-16 18:54:34 +0000
commit7042cfd9cb1b552c5fd753b6912439ce604eb1a0 (patch)
treebf9fe8a1e397b7748c45599383356dd45d4892e6
parent87e74766d33bf364e42839d73e6b8b5e9cd39a07 (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.cpp38
-rw-r--r--tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp27
-rw-r--r--tests/manual/pointer/flickableWithHandlers.qml2
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"