aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquickwindow.cpp
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2017-04-03 11:37:03 +0200
committerShawn Rutledge <shawn.rutledge@qt.io>2017-05-22 19:12:12 +0000
commit48011c2dfeb83b4fe717034d4b3c353714fead48 (patch)
tree836196ff3c97c7085b5c9e7a4be052ad02759b33 /src/quick/items/qquickwindow.cpp
parenta09b2f6fcd087e849f4e766a03c1ab47ae49d0d7 (diff)
Start over with event delivery when touchpoint releases occur
The new rule is that when the number of touchpoints changes, we start over with event delivery as if the touch had just begun, to give more opportunities to hand off processing from one item or handler to another. And MultiPointTouchArea can now handle the handoff: for example in tests/manual/pointer/pinchDragFlingMPTA.qml when the user is pressing three fingers, the PinchHandler is active; when the user then lifts one finger, the MPTA can resume handling the two remaining touchpoints as if they were just pressed. The change in QQuickMultiPointerHandler::wantsPointerEvent is both a behavior change and an optimization: released points aren't eligible; but if some points are released, then pressed, updated and stationary points are all eligible. And, figure this out without looping over the points twice. Change-Id: I26b7593de8e72b471adfec4a4482dd87a8288442 Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
Diffstat (limited to 'src/quick/items/qquickwindow.cpp')
-rw-r--r--src/quick/items/qquickwindow.cpp38
1 files changed, 24 insertions, 14 deletions
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 9c889d54f5..e4eed8454c 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -1703,18 +1703,17 @@ void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEven
bool delivered = false;
if (pointerEvent->isPressEvent()) {
// send initial press
- delivered = deliverPressEvent(pointerEvent);
+ delivered = deliverPressOrReleaseEvent(pointerEvent);
} else if (pointerEvent->device()->type() == QQuickPointerDevice::Mouse) {
// if this is an update or release from an actual mouse,
// and the point wasn't grabbed, deliver only to PointerHandlers:
// passive grabbers first, then the rest
- QVector<QQuickPointerHandler *> &eventDeliveryTargets = pointerEvent->device()->eventDeliveryTargets();
+ const QVector<QQuickPointerHandler *> &eventDeliveryTargets = pointerEvent->device()->eventDeliveryTargets();
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)) {
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
@@ -2266,9 +2265,11 @@ void QQuickWindowPrivate::deliverTouchEvent(QQuickPointerTouchEvent *event)
qCDebug(DBG_TOUCH) << " - delivering" << event->asTouchEvent();
if (event->isPressEvent())
- deliverPressEvent(event);
+ deliverPressOrReleaseEvent(event);
if (!event->allUpdatedPointsAccepted())
deliverUpdatedTouchPoints(event);
+ if (event->isReleaseEvent())
+ deliverPressOrReleaseEvent(event, true);
// Remove released points from itemForTouchPointId
bool allReleased = true;
@@ -2322,7 +2323,7 @@ void QQuickWindowPrivate::deliverUpdatedTouchPoints(QQuickPointerTouchEvent *eve
int pointCount = event->pointCount();
// Deliver to each eventpoint's passive grabbers (but don't visit any handler more than once)
- QVector<QQuickPointerHandler *> &eventDeliveryTargets = event->device()->eventDeliveryTargets();
+ const QVector<QQuickPointerHandler *> &eventDeliveryTargets = event->device()->eventDeliveryTargets();
for (int i = 0; i < pointCount; ++i) {
QQuickEventPoint *point = event->point(i);
for (auto handler : point->passiveGrabbers()) {
@@ -2330,7 +2331,6 @@ void QQuickWindowPrivate::deliverUpdatedTouchPoints(QQuickPointerTouchEvent *eve
if (sendFilteredPointerEvent(event, handler->parentItem()))
return;
handler->handlePointerEvent(event);
- eventDeliveryTargets.append(handler);
}
}
}
@@ -2363,8 +2363,8 @@ void QQuickWindowPrivate::deliverUpdatedTouchPoints(QQuickPointerTouchEvent *eve
}
}
-// Deliver newly pressed touch points
-bool QQuickWindowPrivate::deliverPressEvent(QQuickPointerEvent *event)
+// Deliver an event containing newly pressed or released touch points
+bool QQuickWindowPrivate::deliverPressOrReleaseEvent(QQuickPointerEvent *event, bool handlersOnly)
{
int pointCount = event->pointCount();
QVector<QQuickItem *> targetItems;
@@ -2372,6 +2372,8 @@ bool QQuickWindowPrivate::deliverPressEvent(QQuickPointerEvent *event)
for (int i = 0; i < pointCount; ++i) {
auto point = event->point(i);
point->setAccepted(false); // because otherwise touchEventForItem will ignore it
+ if (point->grabberPointerHandler() && point->state() == QQuickEventPoint::Released)
+ point->setGrabberPointerHandler(nullptr, true);
QVector<QQuickItem *> targetItemsForPoint = pointerTargets(contentItem, point->scenePos(), !isTouchEvent, isTouchEvent);
if (targetItems.count()) {
targetItems = mergePointerTargets(targetItems, targetItemsForPoint);
@@ -2380,14 +2382,14 @@ bool QQuickWindowPrivate::deliverPressEvent(QQuickPointerEvent *event)
}
}
- if (allowChildEventFiltering) {
+ if (allowChildEventFiltering && !handlersOnly) {
updateFilteringParentItems(targetItems);
if (sendFilteredPointerEvent(event, nullptr))
return true;
}
for (QQuickItem *item: targetItems) {
- deliverMatchingPointsToItem(item, event);
+ deliverMatchingPointsToItem(item, event, handlersOnly);
if (event->allPointsAccepted())
break;
}
@@ -2395,7 +2397,7 @@ bool QQuickWindowPrivate::deliverPressEvent(QQuickPointerEvent *event)
return event->allPointsAccepted();
}
-void QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QQuickPointerEvent *pointerEvent)
+void QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QQuickPointerEvent *pointerEvent, bool handlersOnly)
{
Q_Q(QQuickWindow);
QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
@@ -2403,7 +2405,15 @@ void QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QQuickPo
// Let the Item's handlers (if any) have the event first.
itemPrivate->handlePointerEvent(pointerEvent);
- if (pointerEvent->allPointsAccepted())
+ if (handlersOnly)
+ return;
+ if (pointerEvent->allPointsAccepted() && !pointerEvent->isReleaseEvent())
+ return;
+
+ // If all points are released and the item is not the grabber, it doesn't get the event.
+ // But if at least one point is still pressed, we might be in a potential gesture-takeover scenario.
+ if (pointerEvent->isReleaseEvent() && !pointerEvent->isUpdateEvent()
+ && !pointerEvent->exclusiveGrabbers().contains(item))
return;
// TODO: unite this mouse point delivery with the synthetic mouse event below
@@ -2464,11 +2474,11 @@ void QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QQuickPo
if (eventAccepted) {
// If the touch was accepted (regardless by whom or in what form),
// update accepted new points.
- bool isPress = pointerEvent->isPressEvent();
+ bool isPressOrRelease = pointerEvent->isPressEvent() || pointerEvent->isReleaseEvent();
for (auto point: qAsConst(touchEvent->touchPoints())) {
auto pointerEventPoint = ptEvent->pointById(point.id());
pointerEventPoint->setAccepted();
- if (isPress)
+ if (isPressOrRelease)
pointerEventPoint->setGrabberItem(item);
}
} else {