diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2017-09-11 14:10:51 +0200 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@qt.io> | 2017-09-11 15:37:50 +0000 |
commit | 47b3b1b10246cad6709c0cd99f02208dbaf6b7c0 (patch) | |
tree | 8c82a376bb3d4ef5bdc9460124e291f0c993447d /src | |
parent | fae076941bf49f13f5911ced9dd00151b4572212 (diff) |
don't re-deliver events to an item which already filtered
That is, if the filtering parent intercepts an event (returns true
from childMouseEventFilter), it does not also need direct delivery of
the same event.
Change-Id: I24003f72875b309fa10b2d316916c5f86702cb57
Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 24 | ||||
-rw-r--r-- | src/quick/items/qquickwindow_p.h | 3 |
2 files changed, 16 insertions, 11 deletions
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 023fa6f9f0..bd1a5076fd 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -2232,6 +2232,7 @@ void QQuickWindowPrivate::deliverPointerEvent(QQuickPointerEvent *event) // the usecase a bit evil, but we at least don't want to lose events. ++pointerEventRecursionGuard; + skipDelivery.clear(); if (event->asPointerMouseEvent()) { deliverMouseEvent(event->asPointerMouseEvent()); } else if (event->asPointerTouchEvent()) { @@ -2426,7 +2427,6 @@ bool QQuickWindowPrivate::deliverPressOrReleaseEvent(QQuickPointerEvent *event, } } - QVarLengthArray<QQuickItem *> filteredItems; for (QQuickItem *item : targetItems) { if (!handlersOnly && sendFilteredPointerEvent(event, item)) { if (event->isAccepted()) { @@ -2434,15 +2434,12 @@ bool QQuickWindowPrivate::deliverPressOrReleaseEvent(QQuickPointerEvent *event, event->point(i)->setAccepted(); return true; } - filteredItems << item; + skipDelivery.append(item); } - // Do not deliverMatchingPointsTo any item for which the parent-filter already intercepted the event - if (filteredItems.contains(item)) - continue; - // Do not deliverMatchingPointsTo any item which already had a chance to filter - // e.g. if Flickable has filtered events from one of its children, it does not need normal delivery - if (hasFiltered.contains(item)) + // Do not deliverMatchingPointsTo any item for which the filtering parent already intercepted the event, + // nor to any item which already had a chance to filter. + if (skipDelivery.contains(item)) continue; deliverMatchingPointsToItem(item, event, handlersOnly); if (event->allPointsAccepted()) @@ -2743,8 +2740,11 @@ bool QQuickWindowPrivate::sendFilteredPointerEventImpl(QQuickPointerEvent *event if (receiver->acceptedMouseButtons()) { QPointF localPos = receiver->mapFromScene(pme->point(0)->scenePosition()); QMouseEvent *me = pme->asMouseEvent(localPos); - if (filteringParent->childMouseEventFilter(receiver, me)) + if (filteringParent->childMouseEventFilter(receiver, me)) { + qCDebug(DBG_MOUSE) << "mouse event intercepted by childMouseEventFilter of " << filteringParent; + skipDelivery.append(filteringParent); filtered = true; + } } } else if (QQuickPointerTouchEvent *pte = event->asPointerTouchEvent()) { #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) @@ -2760,6 +2760,7 @@ bool QQuickWindowPrivate::sendFilteredPointerEventImpl(QQuickPointerEvent *event QVarLengthArray<QPair<QQuickPointerHandler *, QQuickEventPoint *>, 32> passiveGrabsToCancel; if (filteringParent->childMouseEventFilter(receiver, filteringParentTouchEvent.data())) { qCDebug(DBG_TOUCH) << "touch event intercepted by childMouseEventFilter of " << filteringParent; + skipDelivery.append(filteringParent); filteringParent->grabMouse(); for (auto point: qAsConst(filteringParentTouchEvent->touchPoints())) { auto pointerEventPoint = pte->pointById(point.id()); @@ -2804,6 +2805,7 @@ bool QQuickWindowPrivate::sendFilteredPointerEventImpl(QQuickPointerEvent *event touchMouseDevice = event->device(); if (filteringParent->childMouseEventFilter(receiver, mouseEvent.data())) { qCDebug(DBG_TOUCH) << "touch event intercepted as synth mouse event by childMouseEventFilter of " << filteringParent; + skipDelivery.append(filteringParent); if (t != QEvent::MouseButtonRelease) { qCDebug(DBG_TOUCH_TARGET) << "TP (mouse)" << hex << tp.id() << "->" << filteringParent; pointerEventInstance(touchMouseDevice)->pointById(tp.id())->setGrabberItem(filteringParent); @@ -2851,8 +2853,10 @@ bool QQuickWindowPrivate::sendFilteredMouseEvent(QEvent *event, QQuickItem *rece bool filtered = false; if (filteringParentPrivate->filtersChildMouseEvents && !hasFiltered.contains(filteringParent)) { hasFiltered.append(filteringParent); - if (filteringParent->childMouseEventFilter(receiver, event)) + if (filteringParent->childMouseEventFilter(receiver, event)) { filtered = true; + skipDelivery.append(filteringParent); + } qCDebug(DBG_MOUSE_TARGET) << "for" << receiver << filteringParent << "childMouseEventFilter ->" << filtered; } diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h index 831c8c8d88..0399b26f62 100644 --- a/src/quick/items/qquickwindow_p.h +++ b/src/quick/items/qquickwindow_p.h @@ -227,7 +227,8 @@ public: QList<QSGNode *> cleanupNodeList; QVector<QQuickItem *> itemsToPolish; - QVector<QQuickItem *> hasFiltered; // during event delivery, the items for which childMouseEventFilter was already called + QVector<QQuickItem *> hasFiltered; // during event delivery to a single receiver, the filtering parents for which childMouseEventFilter was already called + QVector<QQuickItem *> skipDelivery; // during delivery of one event to all receivers, Items to which we know delivery is no longer necessary qreal devicePixelRatio; QMetaObject::Connection physicalDpiChangedConnection; |