aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2016-12-05 12:20:31 +0100
committerShawn Rutledge <shawn.rutledge@qt.io>2017-02-10 20:25:02 +0000
commit34d17ce0243ffad278ac7cf57804bf150524940a (patch)
treec714bc459d25a646fef9a84b7a931c553f9c0cfb
parentf3cf71bae2e4bdc83ffa661d7273f6709b006615 (diff)
prioritize delivery to passive grabbers
Change-Id: I445c53ea74e26318aa1193a963cbcae601b0f76d Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
-rw-r--r--src/quick/items/qquickwindow.cpp74
1 files changed, 51 insertions, 23 deletions
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 457d59ea39..10144e6eb9 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -1693,15 +1693,27 @@ void QQuickWindowPrivate::deliverMouseEvent(QQuickPointerMouseEvent *pointerEven
delivered = deliverPressEvent(pointerEvent, &hasFiltered);
} 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 non-grabber PointerHandlers
- 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 (point->grabber())
- break;
+ // and the point wasn't grabbed, deliver only to PointerHandlers:
+ // passive grabbers first, then the rest
+ 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)) {
+ handler->handlePointerEvent(pointerEvent);
+ eventDeliveryTargets.append(handler);
+ }
+ }
+ // If some points weren't grabbed, deliver to non-grabber PointerHandlers in reverse paint order
+ if (!pointerEvent->allPointsGrabbed()) {
+ 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 (point->grabber())
+ break;
+ }
}
}
@@ -2293,26 +2305,42 @@ bool QQuickWindowPrivate::deliverUpdatedTouchPoints(QQuickPointerTouchEvent *eve
// If some points weren't grabbed, deliver only to non-grabber PointerHandlers
if (!event->allPointsGrabbed()) {
- QVector<QQuickItem *> targetItems;
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();
for (int i = 0; i < pointCount; ++i) {
QQuickEventPoint *point = event->point(i);
- QVector<QQuickItem *> targetItemsForPoint = pointerTargets(contentItem, point->scenePos(), false);
- if (targetItems.count()) {
- targetItems = mergePointerTargets(targetItems, targetItemsForPoint);
- } else {
- targetItems = targetItemsForPoint;
+ for (auto handler : point->passiveGrabbers()) {
+ if (Q_LIKELY(handler) && !eventDeliveryTargets.contains(handler)) {
+ handler->handlePointerEvent(event);
+ eventDeliveryTargets.append(handler);
+ }
}
}
- for (QQuickItem *item: targetItems) {
- if (grabbers.contains(item))
- continue;
- QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
- event->localize(item);
- itemPrivate->handlePointerEvent(event, true); // avoid re-delivering to grabbers
- if (event->allPointsGrabbed())
- break;
+ // If some points weren't grabbed, deliver to non-grabber PointerHandlers in reverse paint order
+ if (!event->allPointsGrabbed()) {
+ QVector<QQuickItem *> targetItems;
+ for (int i = 0; i < pointCount; ++i) {
+ QQuickEventPoint *point = event->point(i);
+ QVector<QQuickItem *> targetItemsForPoint = pointerTargets(contentItem, point->scenePos(), false);
+ if (targetItems.count()) {
+ targetItems = mergePointerTargets(targetItems, targetItemsForPoint);
+ } else {
+ targetItems = targetItemsForPoint;
+ }
+ }
+
+ for (QQuickItem *item: targetItems) {
+ if (grabbers.contains(item))
+ continue;
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+ event->localize(item);
+ itemPrivate->handlePointerEvent(event, true); // avoid re-delivering to grabbers
+ if (event->allPointsGrabbed())
+ break;
+ }
}
}