summaryrefslogtreecommitdiffstats
path: root/src/widgets/kernel/qwidgetwindow.cpp
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@qt.io>2024-01-31 16:26:18 +0100
committerTor Arne Vestbø <tor.arne.vestbo@qt.io>2024-02-01 15:28:56 +0100
commit5ba0982b2879a1a4c13bf97467b8e5ad296e57a2 (patch)
tree15dd7be460cc36d18e25a63e161b0c2388620536 /src/widgets/kernel/qwidgetwindow.cpp
parentf85c988980f73398762d4bd5c1a8a1799d182bdd (diff)
Don't set ExplicitShowHide on children when showing parent widget
As a result of using QWidget::setVisible to show the child widgets we would end up also setting ExplicitShowHide. This is not in line with the intent of ExplicitShowHide, which is to flag a widget as explicitly shown/hidden by the developer, which in turn prevents Qt Widgets from toggling WState_Hidden when the widget is reparented. By using QWidgetPrivate::setVisible instead, we can show the child without setting ExplicitShowHide. As side effect of this is that we no longer reset WA_WState_Hidden from QWidgetWindowPrivate::setVisible(). This is an issue when the setVisible call comes as a result of destroying the QWidgetWindow, as that is an implicit hide, and should not result in the widget having WA_WState_Hidden. QWidget handles this case in hideChildren by not calling QWidgetPrivate::setVisible -- instead doing its own reset of WA_WState_Visible. We don't want to untangle this just yet, so as a workaround we detect that the widget is already !isVisible(), thanks to hideChildren having hidden it, and then skip the call to QWidgetPrivate::setVisible that results from QWindow::destroy(). Task-number: QTBUG-121398 Pick-to: 6.7 Change-Id: Ib5b4d9c84f0569124c5f3ca2169cabff18934e2d Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
Diffstat (limited to 'src/widgets/kernel/qwidgetwindow.cpp')
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp48
1 files changed, 26 insertions, 22 deletions
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index 26f1afbca6..d80eb3346b 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -41,32 +41,36 @@ public:
Q_Q(QWidgetWindow);
qCDebug(lcWidgetShowHide) << "Setting visibility of" << q->widget()
<< "to" << visible << "via QWidgetWindowPrivate";
+
if (QWidget *widget = q->widget()) {
- // Check if the widget was already hidden, as this indicates it was done
- // 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 (wasExplicitShowHide) {
- widget->setAttribute(Qt::WA_WState_ExplicitShowHide, wasExplicitShowHide);
- widget->setAttribute(Qt::WA_WState_Hidden, wasHidden);
+ // If the widget's visible state is already matching the new QWindow
+ // visible state we assume the widget has already synced up.
+ if (visible != widget->isVisible()) {
+ // Check if the widget was already hidden, as this indicates it was done
+ // 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 (wasExplicitShowHide) {
+ widget->setAttribute(Qt::WA_WState_ExplicitShowHide, wasExplicitShowHide);
+ widget->setAttribute(Qt::WA_WState_Hidden, wasHidden);
+ }
}
+ }
- // The call to QWidgetPrivate::setVisible() above will normally
- // recurse back into QWidgetWindow::setNativeWindowVisibility()
- // to update the QWindow state, but during QWidget::destroy()
- // this is not the case, as Qt::WA_WState_Created has been
- // unset by the time we check if we should call hide_helper().
- // We don't want to change the QWidget logic, as that has
- // other side effects, so as a targeted fix we sync up the
- // visibility here if needed.
- if (q->isVisible() != visible)
- QWindowPrivate::setVisible(visible);
- } else {
+ // If we end up calling QWidgetPrivate::setVisible() above, we will
+ // in most cases recurse back into setNativeWindowVisibility() to
+ // update the QWindow state. But during QWidget::destroy() this is
+ // not the case, as Qt::WA_WState_Created has been unset by the time
+ // we check if we should call hide_helper(). We handle this case, as
+ // well as the cases where we don't call QWidgetPrivate::setVisible(),
+ // by syncing up the QWindow state here if needed.
+ if (q->isVisible() != visible)
QWindowPrivate::setVisible(visible);
- }
}
QWindow *eventReceiver() override {