diff options
author | Christian Ehrlicher <[email protected]> | 2025-01-10 16:41:54 +0100 |
---|---|---|
committer | Christian Ehrlicher <[email protected]> | 2025-05-20 21:00:41 +0200 |
commit | 3252e1808c12c21f27bb4844a1497d18587a64b5 (patch) | |
tree | 11d972f8e1509dc16edab5da5cdaa5d23bf26f6a | |
parent | 263f06ae8b5cceafe8d394c11ec89aaea175e5ac (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.cpp | 2 | ||||
-rw-r--r-- | tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp | 32 |
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 |