diff --git a/src/widgets/kernel/qwindowcontainer.cpp b/src/widgets/kernel/qwindowcontainer.cpp index 847058e5b21..072a0bc5fa2 100644 --- a/src/widgets/kernel/qwindowcontainer.cpp +++ b/src/widgets/kernel/qwindowcontainer.cpp @@ -191,6 +191,7 @@ QWindowContainer::QWindowContainer(QWindow *embeddedWindow, QWidget *parent, Qt: d->fakeParent.setObjectName(windowName + "ContainerFakeParent"_L1); d->window->setParent(&d->fakeParent); + d->window->parent()->installEventFilter(this); d->window->setFlag(Qt::SubWindow); setAcceptDrops(true); @@ -239,6 +240,26 @@ void QWindowContainer::focusWindowChanged(QWindow *focusWindow) } } +/*! + \internal + */ + +bool QWindowContainer::eventFilter(QObject *o, QEvent *e) +{ + Q_D(QWindowContainer); + if (!d->window) + return false; + + if (e->type() == QEvent::ChildRemoved) { + QChildEvent *ce = static_cast(e); + if (ce->child() == d->window) { + o->removeEventFilter(this); + d->window = nullptr; + } + } + return false; +} + /*! \internal */ @@ -251,12 +272,6 @@ bool QWindowContainer::event(QEvent *e) QEvent::Type type = e->type(); switch (type) { - case QEvent::ChildRemoved: { - QChildEvent *ce = static_cast(e); - if (ce->child() == d->window) - d->window = nullptr; - break; - } // The only thing we are interested in is making sure our sizes stay // in sync, so do a catch-all case. case QEvent::Resize: @@ -271,10 +286,13 @@ bool QWindowContainer::event(QEvent *e) case QEvent::Show: d->updateUsesNativeWidgets(); if (d->isStillAnOrphan()) { + d->window->parent()->removeEventFilter(this); d->window->setParent(d->usesNativeWidgets ? windowHandle() : window()->windowHandle()); d->fakeParent.destroy(); + if (d->window->parent()) + d->window->parent()->installEventFilter(this); } if (d->window->parent()) { d->markParentChain(); @@ -345,7 +363,10 @@ static void qwindowcontainer_traverse(QWidget *parent, qwindowcontainer_traverse void QWindowContainer::toplevelAboutToBeDestroyed(QWidget *parent) { if (QWindowContainerPrivate *d = QWindowContainerPrivate::get(parent)) { + if (d->window->parent()) + d->window->parent()->removeEventFilter(parent); d->window->setParent(&d->fakeParent); + d->window->parent()->installEventFilter(parent); } qwindowcontainer_traverse(parent, toplevelAboutToBeDestroyed); } @@ -363,7 +384,9 @@ void QWindowContainer::parentWasChanged(QWidget *parent) tld->createTLSysExtra(); Q_ASSERT(toplevel->windowHandle()); } + d->window->parent()->removeEventFilter(parent); d->window->setParent(toplevel->windowHandle()); + toplevel->windowHandle()->installEventFilter(parent); d->fakeParent.destroy(); d->updateGeometry(); } diff --git a/src/widgets/kernel/qwindowcontainer_p.h b/src/widgets/kernel/qwindowcontainer_p.h index e8944191e6a..8dc5c64af4f 100644 --- a/src/widgets/kernel/qwindowcontainer_p.h +++ b/src/widgets/kernel/qwindowcontainer_p.h @@ -40,6 +40,7 @@ public: protected: bool event(QEvent *ev) override; + bool eventFilter(QObject *, QEvent *ev) override; private slots: void focusWindowChanged(QWindow *focusWindow); diff --git a/tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp b/tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp index 8d0f84ca60e..19c9606d79d 100644 --- a/tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp +++ b/tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp @@ -50,6 +50,7 @@ private slots: void testOwnership(); void testBehindTheScenesDeletion(); void testUnparenting(); + void testReparenting(); void testUnparentReparent(); void testActivation(); void testAncestorChange(); @@ -206,12 +207,12 @@ void tst_QWindowContainer::testActivation() void tst_QWindowContainer::testUnparenting() { - QWindow *window = new QWindow(); + QPointer window(new QWindow()); QScopedPointer container(QWidget::createWindowContainer(window)); container->setWindowTitle(QTest::currentTestFunction()); container->setGeometry(m_availableGeometry.x() + 100, m_availableGeometry.y() + 100, 200, 100); - window->setParent(0); + window->setParent(nullptr); container->show(); @@ -219,6 +220,26 @@ void tst_QWindowContainer::testUnparenting() // Window should not be made visible by container.. QVERIFY(!window->isVisible()); + + container.reset(); + QVERIFY(window); + delete window; +} + +void tst_QWindowContainer::testReparenting() +{ + QPointer window1(new QWindow()); + QScopedPointer window2(new QWindow()); + QScopedPointer container(QWidget::createWindowContainer(window1)); + + window1->setParent(window2.data()); + + // Not deleted with container + container.reset(); + QVERIFY(window1); + // but deleted with new parent + window2.reset(); + QVERIFY(!window1); } void tst_QWindowContainer::testUnparentReparent()