WindowContainer: Decouple contained window from parent on window change

We get the parentWindowChanged() callback when the window the container
item is in is going away, or the container is moved out of the window.

We need to decouple the contained window from the item's window at that
point, as otherwise the item's window will take the contained window
down with it if its destroyed before the container, which doesn't match
the semantics of the window container ultimately managing the window.

Change-Id: Ie4640d1e30677a8559a1ba6f19d1eb2aecc87d80
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
(cherry picked from commit 768145ffee)
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
Tor Arne Vestbø 2023-12-22 17:04:03 +01:00
parent 77e3cc7b36
commit 3df0ac24c3
2 changed files with 45 additions and 1 deletions

View File

@ -555,7 +555,28 @@ void QQuickWindowContainer::parentWindowChanged(QQuickWindow *parentWindow)
{
qCDebug(lcWindowContainer) << this << "parent window changed to" << parentWindow;
polish();
Q_D(QQuickWindowContainer);
if (!parentWindow) {
// We have been removed from the window we were part of,
// possibly because the window is going away. We need to
// make sure the contained window is no longer a child of
// former window, as otherwise it will be wiped out along
// with it. We can't wait for updatePolish() to do that
// as polish has no effect when an item is not part of a
// window.
if (d->window) {
// The window should already be destroyed from the
// call to releaseResources(), which is part of the
// removal of an item from a scene, but just in case
// we do it here as well.
d->window->destroy();
d->window->setParent(nullptr);
}
} else {
polish();
}
}
bool QQuickWindowContainerPrivate::transformChanged(QQuickItem *transformedItem)

View File

@ -33,6 +33,7 @@ private slots:
void basicFunctionality();
void windowDestroyed();
void windowLifetimeFollowsContainer();
private:
std::unique_ptr<QQmlApplicationEngine> m_engine;
@ -104,6 +105,28 @@ void tst_QQuickWindowContainer::windowDestroyed()
QCOMPARE(spy.size(), 2);
}
void tst_QQuickWindowContainer::windowLifetimeFollowsContainer()
{
QWindow window;
QPointer<QWindow> windowGuard = &window;
QQuickWindowContainer container;
container.setContainedWindow(&window);
{
QQuickWindow quickWindow;
container.setParentItem(quickWindow.contentItem());
quickWindow.show();
QVERIFY(QQuickTest::qWaitForPolish(&quickWindow));
QCOMPARE(window.parent(), &quickWindow);
// Decouple container from Quick window
container.setParentItem(nullptr);
}
QVERIFY(windowGuard);
}
QTEST_MAIN(tst_QQuickWindowContainer)
#include "tst_qquickwindowcontainer.moc"