diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2017-08-23 12:55:00 +0200 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@qt.io> | 2017-08-24 09:52:23 +0000 |
commit | 780e11cf38a98cd32b6a5aa44dbb4cbf0f5d5ff8 (patch) | |
tree | cdb6b9c2afb9c00f4808d96bcedac53c48295839 /src/quick/items | |
parent | 4003b9cf9c3998bbf6654c9eb808657b4d55568b (diff) |
Restore filtering behavior
We cannot cull pairs from filteringParentItems ahead of time on the
basis of not visiting the same parent twice, because we don't know
which child will get the press event. Skipping parents which have
already seen the event once MUST be done during event delivery, as it
was done before 9b5fc80af28580e9672792dd511d876a93947882
But another behavior difference is that the same parent can filter
twice, if it's filtering the same event on behalf of a different item.
For example:
ListView
delegate: Rectangle
MouseArea
Text
If you click on the text, the MouseArea can filter for the Text,
then ListView filters for the Text. Nobody accepts. So we try to
deliver to the MouseArea; and then ListView filters again, this time
for the MouseArea.
So we need to go back to interleaving regular delivery and
parent-filtering to get back to the behavior we had in 5.9. It's not
the same if we try to do all the parent-filtering first, and then all
the regular delivery afterwards.
Revises and reverts parts of 1b0c9b46ce13b0f9c533f18fb420ff10ad56e4f6
Done-with: Jan Arve Sæther
Task-number: QTBUG-62412
Task-number: QTBUG-62549
Task-number: QTBUG-62628
Task-number: QTBUG-62631
Change-Id: Id0bf64cb54668cc0eecfba01746a00ed7ea0359f
Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
Diffstat (limited to 'src/quick/items')
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 32 | ||||
-rw-r--r-- | src/quick/items/qquickwindow_p.h | 2 |
2 files changed, 22 insertions, 12 deletions
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index c03b362ab8..44bcda027f 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -2425,17 +2425,25 @@ bool QQuickWindowPrivate::deliverPressOrReleaseEvent(QQuickPointerEvent *event, } } - if (allowChildEventFiltering && !handlersOnly) { + if (allowChildEventFiltering && !handlersOnly) updateFilteringParentItems(targetItems); - QQuickItem *filteredItem; - if (sendFilteredPointerEvent(event, nullptr, &filteredItem)) { - if (event->isAccepted()) + + QVarLengthArray<QQuickItem *> filteredItems; + for (QQuickItem *item : targetItems) { + if (sendFilteredPointerEvent(event, item)) { + if (event->isAccepted()) { + for (int i = 0; i < event->pointCount(); ++i) + event->point(i)->setAccepted(); return true; - targetItems.removeAll(filteredItem); + } + while (!filteringParentItems.isEmpty() && filteringParentItems.first().first == item) + filteringParentItems.removeFirst(); + filteredItems << item; } - } - for (QQuickItem *item: targetItems) { + // Do not deliverMatchingPointsTo any item for which the parent-filter already intercepted the event + if (filteredItems.contains(item)) + continue; deliverMatchingPointsToItem(item, event, handlersOnly); if (event->allPointsAccepted()) break; @@ -2755,23 +2763,25 @@ void QQuickWindowPrivate::updateFilteringParentItems(const QVector<QQuickItem *> } } -bool QQuickWindowPrivate::sendFilteredPointerEvent(QQuickPointerEvent *event, QQuickItem *receiver, QQuickItem **itemThatFiltered) +bool QQuickWindowPrivate::sendFilteredPointerEvent(QQuickPointerEvent *event, QQuickItem *receiver) { if (!allowChildEventFiltering) return false; bool ret = false; + QVarLengthArray<QQuickItem *> filteringParentsToSkip; if (QQuickPointerMouseEvent *pme = event->asPointerMouseEvent()) { for (QPair<QQuickItem *,QQuickItem *> itemAndParent : filteringParentItems) { QQuickItem *item = receiver ? receiver : itemAndParent.first; QQuickItem *filteringParent = itemAndParent.second; if (item == filteringParent) continue; // a filtering item never needs to filter for itself + if (filteringParentsToSkip.contains(filteringParent)) + continue; QPointF localPos = item->mapFromScene(pme->point(0)->scenePos()); QMouseEvent *me = pme->asMouseEvent(localPos); - if (filteringParent->childMouseEventFilter(item, me)) { - if (itemThatFiltered) *itemThatFiltered = item; + if (filteringParent->childMouseEventFilter(item, me)) ret = true; - } + filteringParentsToSkip.append(filteringParent); } } else if (QQuickPointerTouchEvent *pte = event->asPointerTouchEvent()) { QVarLengthArray<QPair<QQuickPointerHandler *, QQuickEventPoint *>, 32> passiveGrabsToCancel; diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h index 837ef11d25..36b2c57e5c 100644 --- a/src/quick/items/qquickwindow_p.h +++ b/src/quick/items/qquickwindow_p.h @@ -148,7 +148,7 @@ public: static QMouseEvent *cloneMouseEvent(QMouseEvent *event, QPointF *transformedLocalPos = 0); void deliverMouseEvent(QQuickPointerMouseEvent *pointerEvent); bool sendFilteredMouseEvent(QQuickItem *, QQuickItem *, QEvent *, QSet<QQuickItem *> *); - bool sendFilteredPointerEvent(QQuickPointerEvent *event, QQuickItem *receiver, QQuickItem **itemThatFiltered = 0); + bool sendFilteredPointerEvent(QQuickPointerEvent *event, QQuickItem *receiver); #if QT_CONFIG(wheelevent) bool deliverWheelEvent(QQuickItem *, QWheelEvent *); #endif |