diff options
author | Tor Arne Vestbø <tor.arne.vestbo@qt.io> | 2024-01-31 16:26:18 +0100 |
---|---|---|
committer | Tor Arne Vestbø <tor.arne.vestbo@qt.io> | 2024-02-01 15:28:56 +0100 |
commit | 5ba0982b2879a1a4c13bf97467b8e5ad296e57a2 (patch) | |
tree | 15dd7be460cc36d18e25a63e161b0c2388620536 /src/widgets/kernel/qwidgetwindow.cpp | |
parent | f85c988980f73398762d4bd5c1a8a1799d182bdd (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.cpp | 48 |
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 { |