QQuickWindow: disconnect incoming signals in dtor to avoid assert

qtbase commit 92a65fdac69d7773b114584f1637946622cf4f72 changed what
happened when deleting a QWindow with child windows: they are now
deleted earlier, from ~QWindow rather than from ~QObject.

As a consequence, if the deletion of the child window triggers any
signal (such as QSGRenderContext::invalidated), the parent window
now receives it (while before, the code in ~QObject would disconnect
the parent window from all senders).

Fixed by explicit disconnects, using a std::array of
QMetaObject::Connections, like in QSortFilterProxyModel for instance.

Task-number: QTBUG-140170
Pick-to: 6.10 6.10.0
Change-Id: Id2c402d3121c8a3e6962cfed0afe1e90f5f14b3f
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
David Faure 2025-09-15 20:13:23 +02:00
parent 5ab3da9daf
commit a346f6d0f3
2 changed files with 13 additions and 7 deletions

View File

@ -817,14 +817,16 @@ void QQuickWindowPrivate::init(QQuickWindow *c, QQuickRenderControl *control)
animationController.reset(new QQuickAnimatorController(q));
QObject::connect(context, &QSGRenderContext::initialized, q, &QQuickWindow::sceneGraphInitialized, Qt::DirectConnection);
QObject::connect(context, &QSGRenderContext::invalidated, q, &QQuickWindow::sceneGraphInvalidated, Qt::DirectConnection);
QObject::connect(context, &QSGRenderContext::invalidated, q, &QQuickWindow::cleanupSceneGraph, Qt::DirectConnection);
connections = {
QObject::connect(context, &QSGRenderContext::initialized, q, &QQuickWindow::sceneGraphInitialized, Qt::DirectConnection),
QObject::connect(context, &QSGRenderContext::invalidated, q, &QQuickWindow::sceneGraphInvalidated, Qt::DirectConnection),
QObject::connect(context, &QSGRenderContext::invalidated, q, &QQuickWindow::cleanupSceneGraph, Qt::DirectConnection),
QObject::connect(q, &QQuickWindow::focusObjectChanged, q, &QQuickWindow::activeFocusItemChanged);
QObject::connect(q, &QQuickWindow::screenChanged, q, &QQuickWindow::handleScreenChanged);
QObject::connect(qApp, &QGuiApplication::applicationStateChanged, q, &QQuickWindow::handleApplicationStateChanged);
QObject::connect(q, &QQuickWindow::frameSwapped, q, &QQuickWindow::runJobsAfterSwap, Qt::DirectConnection);
QObject::connect(q, &QQuickWindow::focusObjectChanged, q, &QQuickWindow::activeFocusItemChanged),
QObject::connect(q, &QQuickWindow::screenChanged, q, &QQuickWindow::handleScreenChanged),
QObject::connect(qApp, &QGuiApplication::applicationStateChanged, q, &QQuickWindow::handleApplicationStateChanged),
QObject::connect(q, &QQuickWindow::frameSwapped, q, &QQuickWindow::runJobsAfterSwap, Qt::DirectConnection),
};
if (QQmlInspectorService *service = QQmlDebugConnector::service<QQmlInspectorService>())
service->addWindow(q);
@ -1213,6 +1215,9 @@ QQuickWindow::~QQuickWindow()
// have their destructors loaded while they the library is still
// loaded into memory.
QQuickPixmap::purgeCache();
for (const QMetaObject::Connection &connection : d->connections)
disconnect(connection);
}
#if QT_CONFIG(quick_shadereffect)

View File

@ -194,6 +194,7 @@ public:
qreal lastReportedItemDevicePixelRatio;
QMetaObject::Connection physicalDpiChangedConnection;
std::array<QMetaObject::Connection, 7> connections;
void updateDirtyNodes();
void cleanupNodes();