diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index f55e7f0803..3f971d700e 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -406,13 +406,21 @@ void QWindowPrivate::create(bool recursive) QObjectList childObjects = q->children(); for (int i = 0; i < childObjects.size(); i ++) { QObject *object = childObjects.at(i); - if (object->isWindowType()) { - QWindow *window = static_cast(object); - if (recursive) - window->d_func()->create(true); - if (window->d_func()->platformWindow) - window->d_func()->platformWindow->setParent(platformWindow); - } + if (!object->isWindowType()) + continue; + + QWindow *childWindow = static_cast(object); + if (recursive) + childWindow->d_func()->create(recursive); + + // The child may have had deferred creation due to this window not being created + // at the time setVisible was called, so we re-apply the visible state, which + // may result in creating the child, and emitting the appropriate signals. + if (childWindow->isVisible()) + childWindow->setVisible(true); + + if (QPlatformWindow *childPlatformWindow = childWindow->d_func()->platformWindow) + childPlatformWindow->setParent(this->platformWindow); } QPlatformSurfaceEvent e(QPlatformSurfaceEvent::SurfaceCreated); @@ -477,14 +485,23 @@ void QWindow::setVisible(bool visible) { Q_D(QWindow); - if (d->visible == visible) + if (d->visible != visible) { + d->visible = visible; + emit visibleChanged(visible); + d->updateVisibility(); + } else if (d->platformWindow) { + // Visibility hasn't changed, and the platform window is in sync return; - d->visible = visible; - emit visibleChanged(visible); - d->updateVisibility(); + } - if (!d->platformWindow) - create(); + if (!d->platformWindow) { + // If we have a parent window, but the parent hasn't been created yet, we + // can defer creation until the parent is created or we're re-parented. + if (parent() && !parent()->handle()) + return; + else + create(); + } if (visible) { // remove posted quit events when showing a new window @@ -523,6 +540,7 @@ void QWindow::setVisible(bool visible) if (visible && (d->hasCursor || QGuiApplication::overrideCursor())) d->applyCursor(); #endif + d->platformWindow->setVisible(visible); if (!visible) { @@ -619,6 +637,12 @@ void QWindow::setParent(QWindow *parent) else d->connectToScreen(newScreen); + // If we were set visible, but not created because we were a child, and we're now + // re-parented into a created parent, or to being a top level, we need re-apply the + // visibility state, which will also create. + if (isVisible() && (!parent || parent->handle())) + setVisible(true); + if (d->platformWindow) { if (parent) parent->create(); diff --git a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp index 6f8fa3fcd1..0faace0c1a 100644 --- a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp +++ b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp @@ -60,6 +60,7 @@ class tst_QWindow: public QObject private slots: void create(); void setParent(); + void setVisible(); void eventOrderOnShow(); void resizeEventAfterResize(); void mapGlobal(); @@ -186,6 +187,51 @@ void tst_QWindow::setParent() QVERIFY2(f.handle(), "Making a created window a child of a non-created window should automatically create it"); } +void tst_QWindow::setVisible() +{ + QWindow a; + QWindow b(&a); + a.setVisible(true); + QVERIFY2(!b.handle(), "Making a top level window visible doesn't create its children"); + QVERIFY2(!b.isVisible(), "Making a top level window visible doesn't make its children visible"); + QVERIFY(QTest::qWaitForWindowExposed(&a)); + + QWindow c; + QWindow d(&c); + d.setVisible(true); + QVERIFY2(!c.handle(), "Making a child window visible doesn't create parent window if parent is hidden"); + QVERIFY2(!c.isVisible(), "Making a child window visible doesn't make its parent visible"); + + QVERIFY2(!d.handle(), "Making a child window visible doesn't create platform window if parent is hidden"); + + c.create(); + QVERIFY(c.handle()); + QVERIFY2(d.handle(), "Creating a parent window should automatically create children if they are visible"); + QVERIFY2(!c.isVisible(), "Creating a parent window should not make it visible just because it has visible children"); + + QWindow e; + QWindow f(&e); + f.setVisible(true); + QVERIFY(!f.handle()); + QVERIFY(!e.handle()); + f.setParent(0); + QVERIFY2(f.handle(), "Making a visible but not created child window top level should create it"); + QVERIFY(QTest::qWaitForWindowExposed(&f)); + + QWindow g; + QWindow h; + QWindow i(&g); + i.setVisible(true); + h.setVisible(true); + QVERIFY(QTest::qWaitForWindowExposed(&h)); + QVERIFY(!i.handle()); + QVERIFY(!g.handle()); + QVERIFY(h.handle()); + i.setParent(&h); + QVERIFY2(i.handle(), "Making a visible but not created child window child of a created window should create it"); + QVERIFY(QTest::qWaitForWindowExposed(&i)); +} + void tst_QWindow::mapGlobal() { QWindow a;