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;
|
extra->style = newStyle;
|
||||||
|
|
||||||
// repolish
|
// repolish
|
||||||
if (polished && q->windowType() != Qt::Desktop) {
|
if (polished && q->windowType() != Qt::Desktop && oldStyle != q->style()) {
|
||||||
oldStyle->unpolish(q);
|
oldStyle->unpolish(q);
|
||||||
q->style()->polish(q);
|
q->style()->polish(q);
|
||||||
}
|
}
|
||||||
|
@ -292,6 +292,7 @@ private slots:
|
|||||||
void setLocale();
|
void setLocale();
|
||||||
void propagateLocale();
|
void propagateLocale();
|
||||||
void deleteStyle();
|
void deleteStyle();
|
||||||
|
void dontCrashOnSetStyle();
|
||||||
void multipleToplevelFocusCheck();
|
void multipleToplevelFocusCheck();
|
||||||
void setFocus();
|
void setFocus();
|
||||||
#ifndef QT_NO_CURSOR
|
#ifndef QT_NO_CURSOR
|
||||||
@ -6795,6 +6796,37 @@ void tst_QWidget::deleteStyle()
|
|||||||
QCoreApplication::processEvents();
|
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
|
class TopLevelFocusCheck: public QWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
Loading…
x
Reference in New Issue
Block a user