From 705dbea2a97a5c93c734784590705b29c1b1d502 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 1 Jul 2024 12:44:45 +0200 Subject: [PATCH] Call QWidget::setVisible, not QWidgetPrivate, when showing children As part of 5ba0982b2879a1a4c13bf97467b8e5ad296e57a2 we started calling QWidgetPrivate::setVisible instead of QWidget::setVisible when showing children, to avoid setting ExplicitShowHide. Unfortunately some widget subclasses wrongly override setVisible to do initialization, which resulted in these widgets not running their init code. The documentation clearly specifies to use showEvent or Polish for this use case, but to avoid a regression we temporarily set a flag that prevents QWidget::setVisible from setting the ExplicitShowHide attribute. We can not rely on simply unsetting ExplicitShowHide after our call to QWidget::setVisible, as the call might recurse into logic that checks ExplicitShowHide and wrongly determines that the show is explicit. Fixes: QTBUG-126721 Fixes: QTBUG-126218 Pick-to: 6.7 Change-Id: Ibf88340b68cb4fcb20ce3d8ec5b76de0fd2d2551 Reviewed-by: Volker Hilsheimer (cherry picked from commit fc4c6fb5f6bd6bd63b13f1f8b5b7a7289a5fd230) Reviewed-by: Qt Cherry-pick Bot --- src/widgets/kernel/qwidget.cpp | 22 +++++++++++++++++----- src/widgets/kernel/qwidget_p.h | 1 + 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index a8bc8e2185a..0cfd3ca93cc 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -153,6 +153,7 @@ QWidgetPrivate::QWidgetPrivate(int version) , usesRhiFlush(0) , childrenHiddenByWState(0) , childrenShownByExpose(0) + , dontSetExplicitShowHide(0) #if defined(Q_OS_WIN) , noPaintOnScreen(0) #endif @@ -8291,8 +8292,12 @@ void QWidget::setVisible(bool visible) if (testAttribute(Qt::WA_WState_ExplicitShowHide) && testAttribute(Qt::WA_WState_Hidden) == !visible) return; - // Remember that setVisible was called explicitly - setAttribute(Qt::WA_WState_ExplicitShowHide); + if (d->dontSetExplicitShowHide) { + d->dontSetExplicitShowHide = false; + } else { + // Remember that setVisible was called explicitly + setAttribute(Qt::WA_WState_ExplicitShowHide); + } d->setVisible(visible); } @@ -8446,10 +8451,17 @@ void QWidgetPrivate::showChildren(bool spontaneous) QShowEvent e; QApplication::sendSpontaneousEvent(widget, &e); } else { - if (widget->testAttribute(Qt::WA_WState_ExplicitShowHide)) + if (widget->testAttribute(Qt::WA_WState_ExplicitShowHide)) { widget->d_func()->show_recursive(); - else - widget->d_func()->setVisible(true); + } else { + // Call QWidget::setVisible() here, so that subclasses + // that (wrongly) override setVisible to do initialization + // will still be notified that they are made visible, but + // do so without triggering ExplicitShowHide. + widget->d_func()->dontSetExplicitShowHide = true; + widget->setVisible(true); + widget->d_func()->dontSetExplicitShowHide = false; + } } } } diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index 9fab9efa62b..b27ffdb1be6 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -733,6 +733,7 @@ public: uint usesRhiFlush : 1; uint childrenHiddenByWState : 1; uint childrenShownByExpose : 1; + uint dontSetExplicitShowHide : 1; // *************************** Focus abstraction ************************************ enum class FocusDirection {