Windows 11 style: simplify code to polish palette

There are two cases in which we let the style polish a palette:

- after merging the system palette and the style's standard palette
- or when a widget-class specific palette gets set

A style needs to know which colors of the palette it can safely
overwrite with style-specific preferences. For that to work, we
need to reset the resolve mask of the synthesized palette (first
case) to 0 before polishing. Palettes set explicitly by application
code will then have resolve bits set, and the polishing can
respect those colors and not overwrite them.

Simplify the polish() implementation then to check whether the
respective color's resolve bit is set, and only overwrite it with
the style's preferred color if the bit is clear. Move that logic
into a macro for simplification.

This amends b733d31f27 and makes
sure that colors that are set by the application explicitly don't
get overridden by the style.

Task-number: QTBUG-124490
Task-number: QTBUG-124286
Change-Id: I69e1e3da93f661ebdafee0b62adbb3d411322443
Reviewed-by: Axel Spoerl <axel.spoerl@qt.io>
bb10
Volker Hilsheimer 2024-05-02 17:57:28 +02:00
parent cee94658d6
commit 5cdac10b46
3 changed files with 43 additions and 59 deletions

View File

@ -1121,7 +1121,7 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op
rect.translate(shiftX, shiftY);
painter->setFont(toolbutton->font);
const QString text = d->toolButtonElideText(toolbutton, rect, alignment);
if (toolbutton->state & State_Raised || d->defaultPalette.buttonText() != toolbutton->palette.buttonText())
if (toolbutton->state & State_Raised || toolbutton->palette.isBrushSet(QPalette::Current, QPalette::ButtonText))
painter->setPen(QPen(toolbutton->palette.buttonText().color()));
else
painter->setPen(QPen(WINUI3Colors[colorSchemeIndex][controlTextSecondary]));
@ -1175,7 +1175,7 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op
}
tr.translate(shiftX, shiftY);
const QString text = d->toolButtonElideText(toolbutton, tr, alignment);
if (toolbutton->state & State_Raised || d->defaultPalette.buttonText() != toolbutton->palette.buttonText())
if (toolbutton->state & State_Raised || toolbutton->palette.isBrushSet(QPalette::Current, QPalette::ButtonText))
painter->setPen(QPen(toolbutton->palette.buttonText().color()));
else
painter->setPen(QPen(WINUI3Colors[colorSchemeIndex][controlTextSecondary]));
@ -2073,48 +2073,35 @@ void QWindows11Style::unpolish(QWidget *widget)
The colors for Windows 11 are taken from the official WinUI3 Figma style at
https://www.figma.com/community/file/1159947337437047524
*/
#define SET_IF_UNRESOLVED(GROUP, ROLE, VALUE) \
if (!result.isBrushSet(QPalette::Inactive, ROLE) || styleSheetChanged) \
result.setColor(GROUP, ROLE, VALUE)
static void populateLightSystemBasePalette(QPalette &result)
{
static QString oldStyleSheet;
const bool styleSheetChanged = oldStyleSheet != qApp->styleSheet();
QPalette standardPalette = QApplication::palette();
const QColor textColor = QColor(0x00,0x00,0x00,0xE4);
const QColor btnFace = QColor(0xFF,0xFF,0xFF,0xB3);
const QColor btnHighlight = result.accent().color();
const QColor btnColor = result.button().color();
if (standardPalette.color(QPalette::Highlight) == result.color(QPalette::Highlight) || styleSheetChanged)
result.setColor(QPalette::Highlight, btnHighlight);
if (standardPalette.color(QPalette::WindowText) == result.color(QPalette::WindowText) || styleSheetChanged)
result.setColor(QPalette::WindowText, textColor);
if (standardPalette.color(QPalette::Button) == result.color(QPalette::Button) || styleSheetChanged)
result.setColor(QPalette::Button, btnFace);
if (standardPalette.color(QPalette::Light) == result.color(QPalette::Light) || styleSheetChanged)
result.setColor(QPalette::Light, btnColor.lighter(150));
if (standardPalette.color(QPalette::Dark) == result.color(QPalette::Dark) || styleSheetChanged)
result.setColor(QPalette::Dark, btnColor.darker(200));
if (standardPalette.color(QPalette::Mid) == result.color(QPalette::Mid) || styleSheetChanged)
result.setColor(QPalette::Mid, btnColor.darker(150));
if (standardPalette.color(QPalette::Text) == result.color(QPalette::Text) || styleSheetChanged)
result.setColor(QPalette::Text, textColor);
if (standardPalette.color(QPalette::BrightText) != result.color(QPalette::BrightText) || styleSheetChanged)
result.setColor(QPalette::BrightText, btnHighlight);
if (standardPalette.color(QPalette::Base) == result.color(QPalette::Base) || styleSheetChanged)
result.setColor(QPalette::Base, btnFace);
if (standardPalette.color(QPalette::Window) == result.color(QPalette::Window) || styleSheetChanged)
result.setColor(QPalette::Window, QColor(0xF3,0xF3,0xF3,0xFF));
if (standardPalette.color(QPalette::ButtonText) == result.color(QPalette::ButtonText) || styleSheetChanged)
result.setColor(QPalette::ButtonText, textColor);
if (standardPalette.color(QPalette::Midlight) == result.color(QPalette::Midlight) || styleSheetChanged)
result.setColor(QPalette::Midlight, btnColor.lighter(125));
if (standardPalette.color(QPalette::Shadow) == result.color(QPalette::Shadow) || styleSheetChanged)
result.setColor(QPalette::Shadow, Qt::black);
if (standardPalette.color(QPalette::ToolTipBase) == result.color(QPalette::ToolTipBase) || styleSheetChanged)
result.setColor(QPalette::ToolTipBase, result.window().color());
if (standardPalette.color(QPalette::ToolTipText) == result.color(QPalette::ToolTipText) || styleSheetChanged)
result.setColor(QPalette::ToolTipText, result.windowText().color());
SET_IF_UNRESOLVED(QPalette::All, QPalette::Highlight, btnHighlight);
SET_IF_UNRESOLVED(QPalette::All, QPalette::WindowText, textColor);
SET_IF_UNRESOLVED(QPalette::All, QPalette::Button, btnFace);
SET_IF_UNRESOLVED(QPalette::All, QPalette::Light, btnColor.lighter(150));
SET_IF_UNRESOLVED(QPalette::All, QPalette::Dark, btnColor.darker(200));
SET_IF_UNRESOLVED(QPalette::All, QPalette::Mid, btnColor.darker(150));
SET_IF_UNRESOLVED(QPalette::All, QPalette::Text, textColor);
SET_IF_UNRESOLVED(QPalette::All, QPalette::BrightText, btnHighlight);
SET_IF_UNRESOLVED(QPalette::All, QPalette::Base, btnFace);
SET_IF_UNRESOLVED(QPalette::All, QPalette::Window, QColor(0xF3,0xF3,0xF3,0xFF));
SET_IF_UNRESOLVED(QPalette::All, QPalette::ButtonText, textColor);
SET_IF_UNRESOLVED(QPalette::All, QPalette::Midlight, btnColor.lighter(125));
SET_IF_UNRESOLVED(QPalette::All, QPalette::Shadow, Qt::black);
SET_IF_UNRESOLVED(QPalette::All, QPalette::ToolTipBase, result.window().color());
SET_IF_UNRESOLVED(QPalette::All, QPalette::ToolTipText, result.windowText().color());
if (result.midlight() == result.button())
result.setColor(QPalette::Midlight, btnColor.lighter(110));
@ -2124,38 +2111,30 @@ static void populateLightSystemBasePalette(QPalette &result)
/*!
\internal
*/
void QWindows11Style::polish(QPalette& pal)
void QWindows11Style::polish(QPalette& result)
{
Q_D(QWindows11Style);
highContrastTheme = QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Unknown;
colorSchemeIndex = QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Light ? 0 : 1;
if (!highContrastTheme && colorSchemeIndex == 0)
populateLightSystemBasePalette(pal);
populateLightSystemBasePalette(result);
if (standardPalette().color(QPalette::Inactive, QPalette::Button) == pal.color(QPalette::Inactive, QPalette::Button))
pal.setColor(QPalette::Inactive, QPalette::Button, pal.button().color());
if (standardPalette().color(QPalette::Inactive, QPalette::Window) == pal.color(QPalette::Inactive, QPalette::Window))
pal.setColor(QPalette::Inactive, QPalette::Window, pal.window().color());
if (standardPalette().color(QPalette::Inactive, QPalette::Light) == pal.color(QPalette::Inactive, QPalette::Light))
pal.setColor(QPalette::Inactive, QPalette::Light, pal.light().color());
if (standardPalette().color(QPalette::Inactive, QPalette::Dark) == pal.color(QPalette::Inactive, QPalette::Dark))
pal.setColor(QPalette::Inactive, QPalette::Dark, pal.dark().color());
if (standardPalette().color(QPalette::Inactive, QPalette::Accent) == pal.color(QPalette::Inactive, QPalette::Accent))
pal.setColor(QPalette::Inactive, QPalette::Accent, pal.accent().color());
if (standardPalette().color(QPalette::Inactive, QPalette::Highlight) == pal.color(QPalette::Inactive, QPalette::Highlight))
pal.setColor(QPalette::Inactive, QPalette::Highlight, pal.highlight().color());
if (standardPalette().color(QPalette::Inactive, QPalette::HighlightedText) == pal.color(QPalette::Inactive, QPalette::HighlightedText))
pal.setColor(QPalette::Inactive, QPalette::HighlightedText, pal.highlightedText().color());
if (standardPalette().color(QPalette::Inactive, QPalette::Text) == pal.color(QPalette::Inactive, QPalette::Text))
pal.setColor(QPalette::Inactive, QPalette::Text, pal.text().color());
if (standardPalette().color(QPalette::Inactive, QPalette::WindowText) == pal.color(QPalette::Inactive, QPalette::WindowText))
pal.setColor(QPalette::Inactive, QPalette::WindowText, pal.windowText().color());
const bool styleSheetChanged = false; // so the macro works
SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::Button, result.button().color());
SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::Window, result.window().color());
SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::Light, result.light().color());
SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::Dark, result.dark().color());
SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::Accent, result.accent().color());
SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::Highlight, result.highlight().color());
SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::HighlightedText, result.highlightedText().color());
SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::Text, result.text().color());
SET_IF_UNRESOLVED(QPalette::Inactive, QPalette::WindowText, result.windowText().color());
if (highContrastTheme)
pal.setColor(QPalette::Active, QPalette::HighlightedText, pal.windowText().color());
d->defaultPalette = pal;
result.setColor(QPalette::Active, QPalette::HighlightedText, result.windowText().color());
}
#undef SET_IF_UNRESOLVED
QT_END_NAMESPACE

View File

@ -63,7 +63,6 @@ private:
class QWindows11StylePrivate : public QWindowsVistaStylePrivate {
Q_DECLARE_PUBLIC(QWindows11Style)
QPalette defaultPalette;
};
QT_END_NAMESPACE

View File

@ -1094,6 +1094,12 @@ QPalette QApplicationPrivate::basePalette() const
if (const QPalette *themePalette = platformTheme() ? platformTheme()->palette() : nullptr)
palette = themePalette->resolve(palette);
// This palette now is Qt-generated, so reset the resolve mask. This allows
// QStyle::polish implementations to respect palettes that are user provided,
// by checking if the palette has a brush set for a color that the style might
// otherwise overwrite.
palette.setResolveMask(0);
// Finish off by letting the application style polish the palette. This will
// not result in the polished palette becoming a user-set palette, as the
// resulting base palette is only used as a fallback, with the resolve mask