aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--src/quick/items/qquickitem.cpp11
-rw-r--r--src/quick/items/qquickitem.h1
-rw-r--r--src/quick/items/qquickmousearea.cpp6
-rw-r--r--src/quick/items/qquickmousearea_p.h1
-rw-r--r--src/quick/items/qquickwindow.cpp40
-rw-r--r--src/quick/items/qquickwindow_p.h1
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);