QWidget: don't re-polish when style did not change
Don't call style->unpolish()/polish() when the old and new style did not change which might happen when setting a style sheet as this might create an infinite loop and the style (re)sets some window attribute. Bailing out early is not an option here as newStyle might be a nullptr so q->style() will fall back to the application default style. Pick-to: 6.9 Fixes: QTBUG-133332 Change-Id: Ifa9ee4fdfa64b2768337e2d90b7bbaac5f3fcd70 Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
This commit is contained in:
parent
263f06ae8b
commit
3252e1808c
@ -2676,7 +2676,7 @@ void QWidgetPrivate::setStyle_helper(QStyle *newStyle, bool propagate)
|
||||
extra->style = newStyle;
|
||||
|
||||
// repolish
|
||||
if (polished && q->windowType() != Qt::Desktop) {
|
||||
if (polished && q->windowType() != Qt::Desktop && oldStyle != q->style()) {
|
||||
oldStyle->unpolish(q);
|
||||
q->style()->polish(q);
|
||||
}
|
||||
|
@ -292,6 +292,7 @@ private slots:
|
||||
void setLocale();
|
||||
void propagateLocale();
|
||||
void deleteStyle();
|
||||
void dontCrashOnSetStyle();
|
||||
void multipleToplevelFocusCheck();
|
||||
void setFocus();
|
||||
#ifndef QT_NO_CURSOR
|
||||
@ -6795,6 +6796,37 @@ void tst_QWidget::deleteStyle()
|
||||
QCoreApplication::processEvents();
|
||||
}
|
||||
|
||||
class TestStyle : public QCommonStyle
|
||||
{
|
||||
void polish(QWidget *w) override
|
||||
{
|
||||
w->setWindowFlag(Qt::NoDropShadowWindowHint, true);
|
||||
}
|
||||
void unpolish(QWidget *w) override
|
||||
{
|
||||
w->setWindowFlag(Qt::NoDropShadowWindowHint, false);
|
||||
}
|
||||
};
|
||||
|
||||
void tst_QWidget::dontCrashOnSetStyle()
|
||||
{
|
||||
const auto oldStyleName = qApp->style()->name();
|
||||
const auto resetStyleHelper = qScopeGuard([&] {
|
||||
qApp->setStyleSheet({});
|
||||
qApp->setStyle(QStyleFactory::create(oldStyleName));
|
||||
});
|
||||
{
|
||||
qApp->setStyle(new TestStyle);
|
||||
qApp->setStyleSheet("blub");
|
||||
QComboBox w;
|
||||
w.show();
|
||||
QVERIFY(QTest::qWaitForWindowExposed(&w));
|
||||
// this created an infinite loop / stack overflow inside setStyle_helper()
|
||||
// directly call polish instead waiting for the polish event
|
||||
qApp->style()->polish(&w);
|
||||
}
|
||||
}
|
||||
|
||||
class TopLevelFocusCheck: public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
Loading…
x
Reference in New Issue
Block a user