summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Ehrlicher <[email protected]>2025-01-10 16:41:54 +0100
committerChristian Ehrlicher <[email protected]>2025-05-20 21:00:41 +0200
commit3252e1808c12c21f27bb4844a1497d18587a64b5 (patch)
tree11d972f8e1509dc16edab5da5cdaa5d23bf26f6a
parent263f06ae8b5cceafe8d394c11ec89aaea175e5ac (diff)
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 <[email protected]>
-rw-r--r--src/widgets/kernel/qwidget.cpp2
-rw-r--r--tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp32
2 files changed, 33 insertions, 1 deletions
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index f36d7f094dd..0a3416a31af 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -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);
}
diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
index 5c2553ce832..2ecfd262330 100644
--- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
+++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
@@ -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