From 54b8c27e03d04c1e5cd35f75d5c0a8111240eb74 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Fri, 15 Nov 2013 11:26:38 +0100 Subject: Fix crash when windowcontainer is used in a dockwidget MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The dockwidget's toplevel window would be a parent of the container's window when floating. When plugged back into the mainwindow the dockwidget's window is destroyed and the container's window along with it. Added a function toplevelAboutToBeDestroyed to unparent the containers window before this happens so parentWasChanged will work correctly. Change-Id: I06679cfb3a8fa3834c0db0be5973c012b8277275 Reviewed-by: Ulf Hermann Reviewed-by: Jørgen Lind --- src/widgets/kernel/qwidget_qpa.cpp | 6 ++++- src/widgets/kernel/qwindowcontainer.cpp | 19 +++++++++++--- src/widgets/kernel/qwindowcontainer_p.h | 1 + .../qwindowcontainer/tst_qwindowcontainer.cpp | 29 ++++++++++++++++++++++ 4 files changed, 51 insertions(+), 4 deletions(-) diff --git a/src/widgets/kernel/qwidget_qpa.cpp b/src/widgets/kernel/qwidget_qpa.cpp index 18045e3b09..3c4985591e 100644 --- a/src/widgets/kernel/qwidget_qpa.cpp +++ b/src/widgets/kernel/qwidget_qpa.cpp @@ -53,6 +53,7 @@ #include #include "QtGui/private/qwindow_p.h" #include "QtGui/private/qguiapplication_p.h" +#include #include #include @@ -267,8 +268,11 @@ void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f) bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide); // Reparenting toplevel to child - if (wasCreated && !(f & Qt::Window) && (oldFlags & Qt::Window) && !q->testAttribute(Qt::WA_NativeWindow)) + if (wasCreated && !(f & Qt::Window) && (oldFlags & Qt::Window) && !q->testAttribute(Qt::WA_NativeWindow)) { + if (extra && extra->hasWindowContainer) + QWindowContainer::toplevelAboutToBeDestroyed(q); q->destroy(); + } adjustFlags(f, q); data.window_flags = f; diff --git a/src/widgets/kernel/qwindowcontainer.cpp b/src/widgets/kernel/qwindowcontainer.cpp index 6914f64f8e..7c319c5095 100644 --- a/src/widgets/kernel/qwindowcontainer.cpp +++ b/src/widgets/kernel/qwindowcontainer.cpp @@ -300,15 +300,28 @@ static void qwindowcontainer_traverse(QWidget *parent, qwindowcontainer_traverse } } +void QWindowContainer::toplevelAboutToBeDestroyed(QWidget *parent) +{ + if (QWindowContainerPrivate *d = QWindowContainerPrivate::get(parent)) { + d->window->setParent(&d->fakeParent); + } + qwindowcontainer_traverse(parent, toplevelAboutToBeDestroyed); +} + void QWindowContainer::parentWasChanged(QWidget *parent) { if (QWindowContainerPrivate *d = QWindowContainerPrivate::get(parent)) { if (d->window->parent()) { d->updateUsesNativeWidgets(); d->markParentChain(); - d->window->setParent(d->usesNativeWidgets - ? parent->windowHandle() - : parent->window()->windowHandle()); + QWidget *toplevel = d->usesNativeWidgets ? parent : parent->window(); + if (!toplevel->windowHandle()) { + QWidgetPrivate *tld = static_cast(QWidgetPrivate::get(toplevel)); + tld->createTLExtra(); + tld->createTLSysExtra(); + Q_ASSERT(toplevel->windowHandle()); + } + d->window->setParent(toplevel->windowHandle()); d->updateGeometry(); } } diff --git a/src/widgets/kernel/qwindowcontainer_p.h b/src/widgets/kernel/qwindowcontainer_p.h index e2446bef42..a21f9bd35a 100644 --- a/src/widgets/kernel/qwindowcontainer_p.h +++ b/src/widgets/kernel/qwindowcontainer_p.h @@ -57,6 +57,7 @@ public: explicit QWindowContainer(QWindow *embeddedWindow, QWidget *parent = 0, Qt::WindowFlags f = 0); ~QWindowContainer(); + static void toplevelAboutToBeDestroyed(QWidget *parent); static void parentWasChanged(QWidget *parent); static void parentWasMoved(QWidget *parent); static void parentWasRaised(QWidget *parent); diff --git a/tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp b/tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp index c17a03e058..cd6433bbe7 100644 --- a/tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp +++ b/tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp @@ -46,6 +46,8 @@ #include #include +#include +#include class Window : public QWindow @@ -80,6 +82,7 @@ private slots: void testUnparenting(); void testActivation(); void testAncestorChange(); + void testDockWidget(); }; @@ -278,6 +281,7 @@ void tst_QWindowContainer::testAncestorChange() newRoot->setGeometry(100, 100, 200, 200); newRoot->show(); QVERIFY(QTest::qWaitForWindowExposed(newRoot)); + QCOMPARE(newRoot->windowHandle(), window->parent()); // newRoot // + right // + container @@ -285,6 +289,31 @@ void tst_QWindowContainer::testAncestorChange() QCOMPARE(window->geometry(), QRect(100, 0, 100, 100)); } + +void tst_QWindowContainer::testDockWidget() +{ + QMainWindow mainWindow; + mainWindow.resize(200, 200); + + QDockWidget *dock = new QDockWidget(); + QWindow *window = new QWindow(); + QWidget *container = QWidget::createWindowContainer(window); + dock->setWidget(container); + mainWindow.addDockWidget(Qt::RightDockWidgetArea, dock); + + mainWindow.show(); + QVERIFY(QTest::qWaitForWindowExposed(&mainWindow)); + QVERIFY(window->parent() == mainWindow.window()->windowHandle()); + + QTest::qWait(1000); + dock->setFloating(true); + QTRY_VERIFY(window->parent() != mainWindow.window()->windowHandle()); + + QTest::qWait(1000); + dock->setFloating(false); + QTRY_VERIFY(window->parent() == mainWindow.window()->windowHandle()); +} + QTEST_MAIN(tst_QWindowContainer) #include "tst_qwindowcontainer.moc" -- cgit v1.2.3