Fix crash when reparenting window container

QWindowContainer assumed that a widget could never change from
native to non-native. This is not a fact when the window container
is reparented to toplevel and back. In this case, usesNativeWidgets
would be stuck at true, and parentWasChanged() would go down the
native widget path, triggering an assert.

The solution is to always recalculate the usesNativeWidgets bool.

Task-number: QTBUG-63168
Change-Id: I88178259878ace9eb5de2ee45ff5e69b170da71c
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
Reviewed-by: Błażej Szczygieł <spaz16@wp.pl>
This commit is contained in:
Paul Olav Tvete 2017-09-26 18:08:25 +02:00
parent e96c56c740
commit ff2e9a17e7
2 changed files with 30 additions and 2 deletions

View File

@ -89,7 +89,7 @@ public:
void updateUsesNativeWidgets() void updateUsesNativeWidgets()
{ {
if (usesNativeWidgets || window->parent() == 0) if (window->parent() == 0)
return; return;
Q_Q(QWindowContainer); Q_Q(QWindowContainer);
if (q->internalWinId()) { if (q->internalWinId()) {
@ -97,6 +97,7 @@ public:
usesNativeWidgets = true; usesNativeWidgets = true;
return; return;
} }
bool nativeWidgetSet = false;
QWidget *p = q->parentWidget(); QWidget *p = q->parentWidget();
while (p) { while (p) {
if (false if (false
@ -108,11 +109,12 @@ public:
#endif #endif
) { ) {
q->winId(); q->winId();
usesNativeWidgets = true; nativeWidgetSet = true;
break; break;
} }
p = p->parentWidget(); p = p->parentWidget();
} }
usesNativeWidgets = nativeWidgetSet;
} }
void markParentChain() { void markParentChain() {

View File

@ -74,6 +74,7 @@ private slots:
void testOwnership(); void testOwnership();
void testBehindTheScenesDeletion(); void testBehindTheScenesDeletion();
void testUnparenting(); void testUnparenting();
void testUnparentReparent();
void testActivation(); void testActivation();
void testAncestorChange(); void testAncestorChange();
void testDockWidget(); void testDockWidget();
@ -241,6 +242,31 @@ void tst_QWindowContainer::testUnparenting()
QVERIFY(!window->isVisible()); QVERIFY(!window->isVisible());
} }
void tst_QWindowContainer::testUnparentReparent()
{
QWidget root;
QWindow *window = new QWindow();
QScopedPointer<QWidget> container(QWidget::createWindowContainer(window, &root));
container->setWindowTitle(QTest::currentTestFunction());
container->setGeometry(m_availableGeometry.x() + 100, m_availableGeometry.y() + 100, 200, 100);
root.show();
QVERIFY(QTest::qWaitForWindowExposed(&root));
QTRY_VERIFY(window->isVisible());
container->setParent(nullptr);
QTRY_VERIFY(!window->isVisible());
container->show();
QVERIFY(QTest::qWaitForWindowExposed(window));
QTRY_VERIFY(window->isVisible());
container->setParent(&root); // This should not crash (QTBUG-63168)
}
void tst_QWindowContainer::testAncestorChange() void tst_QWindowContainer::testAncestorChange()
{ {
QWidget root; QWidget root;