aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquickwindow.cpp
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2020-11-18 23:55:25 +0100
committerShawn Rutledge <shawn.rutledge@qt.io>2020-11-19 15:17:39 +0000
commitd68419faf424df2492425baca789742f1a239af3 (patch)
tree2b5aaf3554649f398a27737be0953d87323ecbd2 /src/quick/items/qquickwindow.cpp
parent2e7330f5797c90b4461d638fc839a7ab92906d30 (diff)
Remove QQuickItem::windowDeactivateEvent(); cancel grabs instead
When a QQuickWindow is deactivated, visiting every item in the entire scene to tell them the news isn't very efficient, especially considering that the only item that overrode this virtual function has been QQMouseArea, throughout the lifetime of Qt 5. If it's important to cancel grabs of MouseAreas, then it's equally important to cancel grabs of MultiPointTouchArea, pointer handlers, etc. It should be OK to delete the virtual function since it was never documented, and marked \internal, so hopefully no users are depending on it. The existing tst_QQuickMouseArea::pressedCanceledOnWindowDeactivate() test continues to pass, which proves that the WindowDeactivate event still has the desired effect on MouseArea. Change-Id: I0109370aba14096fb7777a83cf1b6763ac58013f Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'src/quick/items/qquickwindow.cpp')
-rw-r--r--src/quick/items/qquickwindow.cpp40
1 files changed, 37 insertions, 3 deletions
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 3721620bf2..0515a62b1e 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -849,7 +849,7 @@ void QQuickWindow::handleApplicationStateChanged(Qt::ApplicationState state)
{
Q_D(QQuickWindow);
if (state != Qt::ApplicationActive && d->contentItem)
- d->contentItem->windowDeactivateEvent();
+ d->handleWindowDeactivate();
}
/*!
@@ -1945,8 +1945,7 @@ bool QQuickWindow::event(QEvent *e)
break;
#endif
case QEvent::WindowDeactivate:
- if (d->contentItem)
- d->contentItem->windowDeactivateEvent();
+ d->handleWindowDeactivate();
break;
case QEvent::PlatformSurface:
if ((static_cast<QPlatformSurfaceEvent *>(e))->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed) {
@@ -2296,6 +2295,41 @@ void QQuickWindowPrivate::deliverDelayedTouchEvent()
deliverPointerEvent(e.data());
}
+/*! \internal
+ The handler for the QEvent::WindowDeactivate event, and also when
+ Qt::ApplicationState tells us the application is no longer active.
+ It clears all exclusive grabs of items and handlers whose window is this one,
+ for all known pointing devices.
+
+ The QEvent is not passed into this function because in the first case it's
+ just a plain QEvent with no extra data, and because the application state
+ change is delivered via a signal rather than an event.
+*/
+void QQuickWindowPrivate::handleWindowDeactivate()
+{
+ Q_Q(QQuickWindow);
+ qCDebug(DBG_FOCUS) << "deactivated" << windowTitle;
+ const auto inputDevices = QInputDevice::devices();
+ for (auto device : inputDevices) {
+ if (auto pointingDevice = qobject_cast<const QPointingDevice *>(device)) {
+ auto devPriv = QPointingDevicePrivate::get(const_cast<QPointingDevice *>(pointingDevice));
+ for (auto epd : devPriv->activePoints.values()) {
+ if (!epd.exclusiveGrabber.isNull()) {
+ bool relevant = false;
+ if (QQuickItem *item = qmlobject_cast<QQuickItem *>(epd.exclusiveGrabber.data()))
+ relevant = (item->window() == q);
+ else if (QQuickPointerHandler *handler = qmlobject_cast<QQuickPointerHandler *>(epd.exclusiveGrabber.data()))
+ relevant = (handler->parentItem()->window() == q);
+ if (relevant)
+ devPriv->setExclusiveGrabber(nullptr, epd.eventPoint, nullptr);
+ }
+ // For now, we don't clearPassiveGrabbers(), just in case passive grabs
+ // can be useful to keep monitoring the mouse even after window deactivation.
+ }
+ }
+ }
+}
+
bool QQuickWindowPrivate::allUpdatedPointsAccepted(const QPointerEvent *ev)
{
for (auto &point : ev->points()) {