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 | |
parent | 2e7330f5797c90b4461d638fc839a7ab92906d30 (diff) | |
download | qtdeclarative-d68419faf424df2492425baca789742f1a239af3.tar.gz |
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>
-rw-r--r-- | src/quick/items/qquickitem.cpp | 11 | ||||
-rw-r--r-- | src/quick/items/qquickitem.h | 1 | ||||
-rw-r--r-- | src/quick/items/qquickmousearea.cpp | 6 | ||||
-rw-r--r-- | src/quick/items/qquickmousearea_p.h | 1 | ||||
-rw-r--r-- | src/quick/items/qquickwindow.cpp | 40 | ||||
-rw-r--r-- | src/quick/items/qquickwindow_p.h | 1 |
6 files changed, 38 insertions, 22 deletions
diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 5dcc191053..fa2f388fe6 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -4226,17 +4226,6 @@ bool QQuickItem::childMouseEventFilter(QQuickItem *item, QEvent *event) return false; } -/*! - \internal - */ -void QQuickItem::windowDeactivateEvent() -{ - const auto children = childItems(); - for (QQuickItem* item : children) { - item->windowDeactivateEvent(); - } -} - #if QT_CONFIG(im) /*! This method is only relevant for input items. diff --git a/src/quick/items/qquickitem.h b/src/quick/items/qquickitem.h index 7b72b6032d..c7bc2f54c3 100644 --- a/src/quick/items/qquickitem.h +++ b/src/quick/items/qquickitem.h @@ -449,7 +449,6 @@ protected: virtual void dropEvent(QDropEvent *); #endif virtual bool childMouseEventFilter(QQuickItem *, QEvent *); - virtual void windowDeactivateEvent(); virtual QSGNode *updatePaintNode(QSGNode *, UpdatePaintNodeData *); virtual void releaseResources(); diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp index b306c0ddf4..6e7688a734 100644 --- a/src/quick/items/qquickmousearea.cpp +++ b/src/quick/items/qquickmousearea.cpp @@ -1038,12 +1038,6 @@ void QQuickMouseArea::timerEvent(QTimerEvent *event) } } -void QQuickMouseArea::windowDeactivateEvent() -{ - ungrabMouse(); - QQuickItem::windowDeactivateEvent(); -} - void QQuickMouseArea::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) { Q_D(QQuickMouseArea); diff --git a/src/quick/items/qquickmousearea_p.h b/src/quick/items/qquickmousearea_p.h index c368f43b30..e0f7397f06 100644 --- a/src/quick/items/qquickmousearea_p.h +++ b/src/quick/items/qquickmousearea_p.h @@ -180,7 +180,6 @@ protected: #endif bool childMouseEventFilter(QQuickItem *i, QEvent *e) override; void timerEvent(QTimerEvent *event) override; - void windowDeactivateEvent() override; void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override; void itemChange(ItemChange change, const ItemChangeData& value) override; 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()) { diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h index 18a43487c1..6e4d24da85 100644 --- a/src/quick/items/qquickwindow_p.h +++ b/src/quick/items/qquickwindow_p.h @@ -187,6 +187,7 @@ public: bool compressTouchEvent(QTouchEvent *); void flushFrameSynchronousEvents(); void deliverDelayedTouchEvent(); + void handleWindowDeactivate(); // utility functions that used to be in QQuickPointerEvent et al. bool allUpdatedPointsAccepted(const QPointerEvent *ev); |