diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2020-11-18 23:55:25 +0100 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@qt.io> | 2020-11-19 15:17:39 +0000 |
commit | d68419faf424df2492425baca789742f1a239af3 (patch) | |
tree | 2b5aaf3554649f398a27737be0953d87323ecbd2 /src/quick/items/qquickwindow.cpp | |
parent | 2e7330f5797c90b4461d638fc839a7ab92906d30 (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.cpp | 40 |
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()) { |