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. Fixes: QTBUG-133332 Change-Id: Ifa9ee4fdfa64b2768337e2d90b7bbaac5f3fcd70 Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io> (cherry picked from commit 3252e1808c12c21f27bb4844a1497d18587a64b5) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
parent
38c76f704b
commit
ccf61c3480
@ -2686,7 +2686,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);
|
||||||
}
|
}
|
||||||
|
@ -291,6 +291,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
|
||||||
@ -6754,6 +6755,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