Let QWindowContainer know when its top level is about to be destroyed

When the top level window that a QWindowContainer is in is about to
be destroyed the QWindowContainer must reparent the contained window
into a dummy window, as otherwise the destruction of the top level
will bring down the contained window as well.

We were notifying the window container about this situation when
the window container was moved from being a top level itself, to
being a child widget, but did not have any logic for other ways
the window container could lose its parent QWindow.

An example of this was when RHI-needs would result in recreating
the top revel with a different RHI backend.

We now have a last minute call to toplevelAboutToBeDestroyed in
QWidgetPrivate::deleteTLSysExtra().

Fixes: QTBUG-126303
Pick-to: 6.7 6.5
Change-Id: I5b14e156956ae76a8f53cac31904eaadee9e791f
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
(cherry picked from commit 006cbf658ea1f5986bbe1baafa7c146780320661)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Tor Arne Vestbø 2024-06-17 19:34:28 +02:00 committed by Qt Cherry-pick Bot
parent 94e8419ed5
commit f0f9cc602f
2 changed files with 35 additions and 0 deletions

View File

@ -1700,7 +1700,11 @@ void QWidgetPrivate::deleteSysExtra()
void QWidgetPrivate::deleteTLSysExtra()
{
Q_Q(QWidget);
if (extra && extra->topextra) {
if (extra->hasWindowContainer)
QWindowContainer::toplevelAboutToBeDestroyed(q);
delete extra->topextra->window;
extra->topextra->window = nullptr;
}

View File

@ -62,6 +62,7 @@ private slots:
void testPlatformSurfaceEvent();
void embedWidgetWindow();
void testFocus();
void parentDestroyed();
void cleanup();
private:
@ -530,6 +531,36 @@ void tst_QWindowContainer::testFocus()
QVERIFY(!lineEdit->hasFocus());
}
class CreateDestroyWidget : public QWidget
{
public:
void create() { QWidget::create(); }
void destroy() { QWidget::destroy(); }
};
void tst_QWindowContainer::parentDestroyed()
{
CreateDestroyWidget topLevel;
topLevel.setAttribute(Qt::WA_NativeWindow);
QVERIFY(topLevel.windowHandle());
QPointer<QWindow> window = new QWindow;
QWidget *container = QWidget::createWindowContainer(window.get());
container->setParent(&topLevel);
topLevel.show();
QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
QCOMPARE(window->parent(), topLevel.windowHandle());
// Destroying the widget should not wipe out the contained QWindow
topLevel.destroy();
QVERIFY(window);
// Recreating the top level should once again reparent the contained window
topLevel.show();
QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
QCOMPARE(window->parent(), topLevel.windowHandle());
}
QTEST_MAIN(tst_QWindowContainer)
#include "tst_qwindowcontainer.moc"