diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2021-04-13 22:21:36 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2021-04-19 16:58:33 +0000 |
commit | fb23d24e0f3d875d5451336b351ac5a9ef641ca2 (patch) | |
tree | 67764a08bbb4c64db5fa1c59f96e640e1e020aef | |
parent | 5b8cc74b2eae9ed4035ab6d32eb7fc1b3225f900 (diff) |
Clear passive grabbers on press in QQWindow not in DeliveryAgent
In case the window's main scene and a subscene both contain handlers,
and one of the handlers in the main scene takes a passive grab on press,
we don't want to lose it while we are delivering to the subscene.
For example in Qt Quick 3D's dynamictexture example, if you click on
one of the doors, the TapHandler in the View3D grabs on press;
but the door also has a 2D subscene, which allows dragging (either
dragging one yellow note item, or flicking the ListView). If you
drag, the TapHandler does not detect a tap; if you tap, nothing gets
dragged. So this is an example of a cooperative scenario involving
multiple DeliveryAgents at the same time: a passive grab can occur
in the main scene, an exclusive grab can occur in the subscene, and
they don't interfere with each other. But if we clear the passive
grab while delivering to the subscene, the TapHandler does not get
a chance to detect a tap. So we should do that only once, when
the window receives the press event.
Amends 68c103225f4e8bd6c1b18ef547108fd60f398c0f
Task-number: QTBUG-92944
Change-Id: I9f064764a17b1efe758909f61fca6658f65d43e5
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
(cherry picked from commit 48b1c59b65332b773eb51d25c422b53dbd3d6762)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 15 | ||||
-rw-r--r-- | src/quick/util/qquickdeliveryagent.cpp | 2 |
2 files changed, 12 insertions, 5 deletions
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 697e5b3410..58fa4cffa6 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -1367,6 +1367,8 @@ bool QQuickWindow::event(QEvent *e) if (!ptda) ptda = da; if (ptda) { + if (pt.state() == QEventPoint::Pressed) + pe->clearPassiveGrabbers(pt); auto danpit = deliveryAgentsNeedingPoints.find(ptda); if (danpit == deliveryAgentsNeedingPoints.end()) { deliveryAgentsNeedingPoints.insert(ptda, QList<QEventPoint>() << pt); @@ -1398,10 +1400,17 @@ bool QQuickWindow::event(QEvent *e) } if (ret) return true; - } else if (pe->pointCount() && !pe->isBeginEvent()) { + } else if (pe->pointCount()) { // single-point event - if (auto *ptda = QQuickDeliveryAgent::grabberAgent(pe, pe->points().first())) - da = ptda; + const auto &pt = pe->points().first(); + if (pt.state() == QEventPoint::Pressed) + pe->clearPassiveGrabbers(pt); + // it would be nice to just use "else" here, but + // isBeginEvent() is not quite the same check as pt.state() != Pressed + if (!pe->isBeginEvent()) { + if (auto *ptda = QQuickDeliveryAgent::grabberAgent(pe, pe->points().first())) + da = ptda; + } } // else if it has no points, it's probably a TouchCancel, and DeliveryAgent needs to handle it. // TODO should we deliver to all DAs at once then, since we don't know which one should get it? diff --git a/src/quick/util/qquickdeliveryagent.cpp b/src/quick/util/qquickdeliveryagent.cpp index 5c4b228dab..2fd5cab9a2 100644 --- a/src/quick/util/qquickdeliveryagent.cpp +++ b/src/quick/util/qquickdeliveryagent.cpp @@ -1736,8 +1736,6 @@ bool QQuickDeliveryAgentPrivate::deliverPressOrReleaseEvent(QPointerEvent *event } for (int i = 0; i < event->pointCount(); ++i) { auto &point = event->point(i); - if (point.state() == QEventPoint::Pressed) - event->clearPassiveGrabbers(point); QVector<QQuickItem *> targetItemsForPoint = pointerTargets(rootItem, event, point, !isTouch, isTouch); if (targetItems.count()) { targetItems = mergePointerTargets(targetItems, targetItemsForPoint); |