summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRichard Moe Gustavsen <richard.gustavsen@qt.io>2023-04-26 11:33:09 +0200
committerRichard Moe Gustavsen <richard.gustavsen@qt.io>2023-05-11 10:13:43 +0200
commitafcdf6cfad6db20668d22ecabca1f45d712e2383 (patch)
tree24d22f02395c38b542e0af3c7ff75053f2a7cdf2 /src
parent58961f035cac4b7b5331d4d8154889680b2ad4b9 (diff)
downloadqtdeclarative-afcdf6cfad6db20668d22ecabca1f45d712e2383.tar.gz
QQuickFlickable: avoid processing the same event twice
If Flickable has an exclusive grab (e.g if it's being dragged), and at the same time, a child has a passive grab (e.g a TapHandler inside a child of the content item), Flickable ends up getting the same pointer events twice. The reason this happens is because Flickable has a childMouseEventFilter. So the flickable will first get all the pointer events since it has an exclusive grab, just to see that the filter will receive the same events once more, as they next are delivered to the passive grabbers. The result is that Flickable will handle all pointer events (move, release etc) twice when it has en exclusive grab, which will even cause the flickable from stop flicking prematurely if the mouse release ends up outside the bounds of the flickable (because of a double call to handleReleaseEvent(), which will set stealMouse to false too early). To fix this, this patch will make sure that we don't handle any pointer events in the childMouseEventFilter if we already have an exclusive grab. After all, having an exclusive grab means that we're already getting the events the "normal" way, and shouldn't handle the same events once more. Fixes: QTBUG-104987 Change-Id: Iaed49cb860cf50ea38a70a6e546d9dcf25cce444 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Oliver Eftevaag <oliver.eftevaag@qt.io> (cherry picked from commit 1bac9de1136c8d52650199f9defefae2f1d6a1a5)
Diffstat (limited to 'src')
-rw-r--r--src/quick/items/qquickflickable.cpp12
1 files changed, 12 insertions, 0 deletions
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index 14b97e35da..fdb294cdfc 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -2537,6 +2537,18 @@ bool QQuickFlickable::filterPointerEvent(QQuickItem *receiver, QPointerEvent *ev
if (isTouch && static_cast<QTouchEvent *>(event)->touchPointStates().testFlag(QEventPoint::State::Pressed))
d->stealMouse = false;
const auto &firstPoint = event->points().first();
+
+ if (event->pointCount() == 1 && event->exclusiveGrabber(firstPoint) == this) {
+ // We have an exclusive grab (since we're e.g dragging), but at the same time, we have
+ // a child with a passive grab (which is why this filter is being called). And because
+ // of that, we end up getting the same pointer events twice; First in our own event
+ // handlers (because of the grab), then once more in here, since we filter the child.
+ // To avoid processing the event twice (e.g avoid calling handleReleaseEvent once more
+ // from below), we mark the event as filtered, and simply return.
+ event->setAccepted(true);
+ return true;
+ }
+
QPointF localPos = mapFromScene(firstPoint.scenePosition());
bool receiverDisabled = receiver && !receiver->isEnabled();
bool stealThisEvent = d->stealMouse;