diff options
author | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2021-09-23 17:16:13 +0200 |
---|---|---|
committer | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2021-10-07 12:54:10 +0200 |
commit | 51300566ffe2ece2455e1d0479a556c5dbb3bb8e (patch) | |
tree | ce5c7886ba97437a6a77f28faf418734525434ae | |
parent | 5d174877234477a59eb29818d3cfb99fedc3e704 (diff) |
Fix closing and showing a window with a native child
Closing a window with a native child results in the native child's
QWidgetWindow being closed. That explicitly calls setVisible(false)
on the child, which will still have the ExplicitShowHide attribute
set from the initial (explicit) show. Even though we then reset
the ExplicitShowHide, the WState_Hidden attribute will still be
set, so Qt considers the window to have been hidden, and not show
it again when the parent becomes visible.
Add a test case.
Fixes: QTBUG-96286
Fixes: QTBUG-79012
Fixes: QTBUG-71519
Change-Id: I482e6d5236c959d82ce66798176b259a3176972c
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
-rw-r--r-- | src/widgets/kernel/qwidgetwindow.cpp | 7 | ||||
-rw-r--r-- | tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp | 46 |
2 files changed, 51 insertions, 2 deletions
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index 69c76112f6..e3563dc301 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -78,10 +78,13 @@ public: // explicitly and not because the parent window in this case made it hidden. // In which case do not automatically show the widget when the parent // window is shown. + const bool wasExplicitShowHide = widget->testAttribute(Qt::WA_WState_ExplicitShowHide); const bool wasHidden = widget->testAttribute(Qt::WA_WState_Hidden); QWidgetPrivate::get(widget)->setVisible(visible); - if (!wasHidden) - widget->setAttribute(Qt::WA_WState_ExplicitShowHide, false); + if (wasExplicitShowHide) { + widget->setAttribute(Qt::WA_WState_ExplicitShowHide, wasExplicitShowHide); + widget->setAttribute(Qt::WA_WState_Hidden, wasHidden); + } } else { QWindowPrivate::setVisible(visible); } diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 3f51938ce1..c4f2944afc 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -243,6 +243,7 @@ private slots: void winIdChangeEvent(); void persistentWinId(); void showNativeChild(); + void closeAndShowWithNativeChild(); void transientParent(); void qobject_castInDestroyedSlot(); @@ -4773,6 +4774,51 @@ void tst_QWidget::showNativeChild() QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); } +void tst_QWidget::closeAndShowWithNativeChild() +{ + bool dontCreateNativeWidgetSiblings = QApplication::testAttribute(Qt::AA_DontCreateNativeWidgetSiblings); + auto resetAttribute = qScopeGuard([&]{ + QApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, dontCreateNativeWidgetSiblings); + }); + QApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); + + QWidget topLevel; + QWidget *nativeChild = new QWidget; + nativeChild->setFixedSize(200, 200); + QWidget *nativeHiddenChild = new QWidget; + nativeHiddenChild->setFixedSize(200, 200); + QWidget *normalChild = new QWidget; + normalChild->setFixedSize(200, 200); + + QHBoxLayout *layout = new QHBoxLayout; + layout->addWidget(nativeChild); + layout->addWidget(nativeHiddenChild); + layout->addWidget(normalChild); + topLevel.setLayout(layout); + + nativeHiddenChild->hide(); + + topLevel.show(); + QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); + nativeChild->winId(); + const QSize originalSize = topLevel.size(); + topLevel.close(); + + // all children must have the same state + QCOMPARE(nativeChild->isHidden(), normalChild->isHidden()); + QCOMPARE(nativeChild->isVisible(), normalChild->isVisible()); + QCOMPARE(nativeChild->testAttribute(Qt::WA_WState_Visible), + normalChild->testAttribute(Qt::WA_WState_Visible)); + QCOMPARE(nativeChild->testAttribute(Qt::WA_WState_Hidden), + normalChild->testAttribute(Qt::WA_WState_Hidden)); + QCOMPARE(nativeChild->testAttribute(Qt::WA_WState_ExplicitShowHide), + normalChild->testAttribute(Qt::WA_WState_ExplicitShowHide)); + + topLevel.show(); + QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); + QCOMPARE(topLevel.size(), originalSize); +} + class ShowHideEventWidget : public QWidget { public: |