Defer QPlatformWindow creation on setVisible(true) if parent hasn't been created
When a child QWindow is shown by calling setVisible(true), we don't need to create the platform window immediately if the parent window hasn't been created yet. We defer creation until the parent is created, or we're re-parented into a created parent or made top level. This optimization is more important now that we create the full parent hierarchy once we decide that we need to create a child QWindow. Change-Id: Ia4f0430f0d3709a12f41f6473c1cea6b0ef3c9cd Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com>
This commit is contained in:
parent
ac27f9a83e
commit
73c86fcb40
@ -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<QWindow *>(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<QWindow *>(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();
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user