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 <volker.hilsheimer@qt.io>
(cherry picked from commit fc4c6fb5f6bd6bd63b13f1f8b5b7a7289a5fd230)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Tor Arne Vestbø 2024-07-01 12:44:45 +02:00 committed by Qt Cherry-pick Bot
parent 7b53e87bd7
commit 705dbea2a9
2 changed files with 18 additions and 5 deletions

View File

@ -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;
}
}
}
}

View File

@ -733,6 +733,7 @@ public:
uint usesRhiFlush : 1;
uint childrenHiddenByWState : 1;
uint childrenShownByExpose : 1;
uint dontSetExplicitShowHide : 1;
// *************************** Focus abstraction ************************************
enum class FocusDirection {