aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquickwindow.cpp
diff options
context:
space:
mode:
authorVolker Hilsheimer <volker.hilsheimer@qt.io>2023-04-18 14:55:48 +0200
committerVolker Hilsheimer <volker.hilsheimer@qt.io>2023-07-02 21:43:48 +0200
commitf21f1d47e901dcf2d7b37815ada97c6317331a62 (patch)
treef1ee6af8da24f95abd13fd9f07f733313d0a9a65 /src/quick/items/qquickwindow.cpp
parent1fc968c51350b509ea016fbf539978f8f3889a25 (diff)
Overlay: clean up grabbers on touch release
The overlay installs itself as an event filter on the QQuickWindow, passes the event on to the delivery agent directly, and eats the event. This bypasses regular event processing in QQuickWindow::Event, including the clearing of any grabs when an event point is released. This leaves handlers in an inconsistent state. To fix this, factor the clean-up routine out into a separate function that the overlay can call at the end of processing. Add a test project for QQuickOverlay. Not making it a QML test as there are no qml files yet, and no need to unit-test this behavior with all styles. Pick-to: 6.5 6.6 Fixes: QTBUG-110328 Change-Id: Iebe7a252de9919d4958dcda405d24e716353764a Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Diffstat (limited to 'src/quick/items/qquickwindow.cpp')
-rw-r--r--src/quick/items/qquickwindow.cpp56
1 files changed, 36 insertions, 20 deletions
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 08648ee4f6..c04813d13a 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -1324,6 +1324,41 @@ QObject *QQuickWindow::focusObject() const
return const_cast<QQuickWindow*>(this);
}
+/*!
+ \internal
+
+ Clears all exclusive and passive grabs for the points in \a pointerEvent.
+
+ We never allow any kind of grab to persist after release, unless we're waiting
+ for a synth event from QtGui (as with most tablet events), so for points that
+ are fully released, the grab is cleared.
+
+ Called when QQuickWindow::event dispatches events, or when the QQuickOverlay
+ has filtered an event so that it bypasses normal delivery.
+*/
+void QQuickWindowPrivate::clearGrabbers(QPointerEvent *pointerEvent)
+{
+ if (pointerEvent->isEndEvent()
+ && !(QQuickDeliveryAgentPrivate::isTabletEvent(pointerEvent)
+ && (qApp->testAttribute(Qt::AA_SynthesizeMouseForUnhandledTabletEvents)
+ || QWindowSystemInterfacePrivate::TabletEvent::platformSynthesizesMouse))) {
+ if (pointerEvent->isSinglePointEvent()) {
+ if (static_cast<QSinglePointEvent *>(pointerEvent)->buttons() == Qt::NoButton) {
+ auto &firstPt = pointerEvent->point(0);
+ pointerEvent->setExclusiveGrabber(firstPt, nullptr);
+ pointerEvent->clearPassiveGrabbers(firstPt);
+ }
+ } else {
+ for (auto &point : pointerEvent->points()) {
+ if (point.state() == QEventPoint::State::Released) {
+ pointerEvent->setExclusiveGrabber(point, nullptr);
+ pointerEvent->clearPassiveGrabbers(point);
+ }
+ }
+ }
+ }
+}
+
/*! \reimp */
bool QQuickWindow::event(QEvent *event)
{
@@ -1466,26 +1501,7 @@ bool QQuickWindow::event(QEvent *event)
// or fix QTBUG-90851 so that the event always has points?
bool ret = (da && da->event(event));
- // failsafe: never allow any kind of grab to persist after release,
- // unless we're waiting for a synth event from QtGui (as with most tablet events)
- if (pe->isEndEvent() && !(QQuickDeliveryAgentPrivate::isTabletEvent(pe) &&
- (qApp->testAttribute(Qt::AA_SynthesizeMouseForUnhandledTabletEvents) ||
- QWindowSystemInterfacePrivate::TabletEvent::platformSynthesizesMouse))) {
- if (pe->isSinglePointEvent()) {
- if (static_cast<QSinglePointEvent *>(pe)->buttons() == Qt::NoButton) {
- auto &firstPt = pe->point(0);
- pe->setExclusiveGrabber(firstPt, nullptr);
- pe->clearPassiveGrabbers(firstPt);
- }
- } else {
- for (auto &point : pe->points()) {
- if (point.state() == QEventPoint::State::Released) {
- pe->setExclusiveGrabber(point, nullptr);
- pe->clearPassiveGrabbers(point);
- }
- }
- }
- }
+ d->clearGrabbers(pe);
if (ret)
return true;