Fix crash when windowcontainer is used in a dockwidget
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 <ulf.hermann@digia.com> Reviewed-by: Jørgen Lind <jorgen.lind@digia.com>
This commit is contained in:
parent
16ad93af49
commit
54b8c27e03
@ -53,6 +53,7 @@
|
||||
#include <qpa/qplatformintegration.h>
|
||||
#include "QtGui/private/qwindow_p.h"
|
||||
#include "QtGui/private/qguiapplication_p.h"
|
||||
#include <private/qwindowcontainer_p.h>
|
||||
|
||||
#include <qpa/qplatformcursor.h>
|
||||
#include <QtGui/QGuiApplication>
|
||||
@ -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;
|
||||
|
@ -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 *>(QWidgetPrivate::get(toplevel));
|
||||
tld->createTLExtra();
|
||||
tld->createTLSysExtra();
|
||||
Q_ASSERT(toplevel->windowHandle());
|
||||
}
|
||||
d->window->setParent(toplevel->windowHandle());
|
||||
d->updateGeometry();
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -46,6 +46,8 @@
|
||||
#include <qwindow.h>
|
||||
#include <qwidget.h>
|
||||
|
||||
#include <qdockwidget.h>
|
||||
#include <qmainwindow.h>
|
||||
|
||||
|
||||
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"
|
||||
|
Loading…
Reference in New Issue
Block a user