From f089414f1c498c28ae66d1c0e9048fa88bcbbd32 Mon Sep 17 00:00:00 2001 From: "sentry[bot]" <39604003+sentry[bot]@users.noreply.github.com> Date: Mon, 9 Nov 2026 21:34:08 +0100 Subject: [PATCH] [Theme] Pass application palette when generating disabled icon pixmap (#7831) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Lukas BrĂ¼bach <44814898+BruebachL@users.noreply.github.com> Co-authored-by: sentry[bot] <39604003+sentry[bot]@users.noreply.github.com> --- cockatrice/src/interface/theme_icon.cpp | 7 ++++- .../theme_icon_render_test.cpp | 28 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/cockatrice/src/interface/theme_icon.cpp b/cockatrice/src/interface/theme_icon.cpp index 3a71f149c..189bc1dfb 100644 --- a/cockatrice/src/interface/theme_icon.cpp +++ b/cockatrice/src/interface/theme_icon.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -318,7 +319,11 @@ private: } } if (mode == QIcon::Disabled && !pixmap.isNull()) { - pixmap = QApplication::style()->generatedIconPixmap(QIcon::Disabled, pixmap, nullptr); + // QCommonStyle reads the disabled colors from the option's palette + // without a null check, so a null option crashes in QPalette::brush. + QStyleOption option; + option.palette = qApp->palette(); + pixmap = QApplication::style()->generatedIconPixmap(QIcon::Disabled, pixmap, &option); } return pixmap; } diff --git a/tests/theme_migration/theme_icon_render_test.cpp b/tests/theme_migration/theme_icon_render_test.cpp index a56c723b4..b52bc2efc 100644 --- a/tests/theme_migration/theme_icon_render_test.cpp +++ b/tests/theme_migration/theme_icon_render_test.cpp @@ -619,6 +619,34 @@ TEST_F(ThemeIconRenderTest, BadgeOnAuthoredArtUsesTheAssetPath) EXPECT_EQ(countOpaquePixels(pixmap, tone.darker(300)), 0); } +/** + * @brief Disabled authored art is generated by the style without crashing. + * + * Art that carries its own colors is dimmed through + * QStyle::generatedIconPixmap, which dereferences the style option's palette; + * passing no option crashed in QPalette::brush. + */ +TEST_F(ThemeIconRenderTest, DisabledAuthoredArtIsGeneratedByTheStyle) +{ + QTemporaryDir themeDir; + ASSERT_TRUE(themeDir.isValid()); + QFile file(QDir(themeDir.path()).absoluteFilePath(QStringLiteral("plain.svg"))); + ASSERT_TRUE(file.open(QIODevice::WriteOnly)); + file.write(svgWith("#336699")); + file.close(); + QDir::addSearchPath(QStringLiteral("theme"), themeDir.path()); + + const QIcon icon = loadThemedIcon(QStringLiteral("plain")); + const QPixmap normal = icon.pixmap(QSize(32, 32)); + const QPixmap disabled = icon.pixmap(QSize(32, 32), QIcon::Disabled); + + ASSERT_FALSE(normal.isNull()); + ASSERT_FALSE(disabled.isNull()); + EXPECT_GT(countOpaquePixels(normal, QColor(QStringLiteral("#336699"))), 0); + // The style dims the art, so the authored color no longer appears verbatim. + EXPECT_EQ(countOpaquePixels(disabled, QColor(QStringLiteral("#336699"))), 0); +} + /** @brief Disabled keeps the shape language but drops back to the line glyph. */ TEST_F(ThemeIconRenderTest, DisabledBadgeFallsBackToLineGlyph) {