1 | // Copyright (C) 2024 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #include "qquickfluentwinui3theme_p.h" |
5 | |
6 | #include <QtCore/qoperatingsystemversion.h> |
7 | #include <QtGui/private/qguiapplication_p.h> |
8 | #include <QtGui/qpa/qplatformtheme.h> |
9 | #include <QtGui/qguiapplication.h> |
10 | #include <QtGui/qstylehints.h> |
11 | #include <QtGui/qcolor.h> |
12 | #include <QtGui/qfontdatabase.h> |
13 | #include <QtQuickTemplates2/private/qquicktheme_p.h> |
14 | |
15 | QT_BEGIN_NAMESPACE |
16 | |
17 | // If on a Windows11 or above, the platform theme will be used to populate the palette |
18 | // We need to fallback to hardcoded colors when using the style on other platforms, |
19 | // that's why we need the following |
20 | // The colors for Windows 11 are taken from the official WinUI3 Figma style at |
21 | // https://www.figma.com/community/file/1159947337437047524 |
22 | // Try to keep these consistent with the widget windows11 style |
23 | enum WinUI3Color { |
24 | solidBackground, // Solid background color used for the bottom most layer |
25 | acrylicBackgroundDefault, // Acrylic background for popups/tooltips |
26 | textPrimary, // Color for UI labels and static text |
27 | textSecondary, // Color for text in pressed controls |
28 | textDisabled, // Color for disabled text |
29 | textOnAccentPrimary, // Color of text on controls filled in accent color |
30 | textOnAccentSecondary, // Color of text on sunken controls in accent color |
31 | textOnAccentDisabled, // Color of text on disabled controls in accent color |
32 | controlDefault, // Color for standard controls |
33 | controlDisabled, // Color for disabled controls |
34 | controlStrokeDefault, // Color for gradient stops in elevations (pressed or disabled state) |
35 | controlStrokeSecondary, // Color for gradient stops in elevations |
36 | controlStrokeAccentDefault, // Color for gradient stops in elevations for accent controls |
37 | controlStrokeAccentSecondary, // Color for gradient stops in elevations for accent controls |
38 | accentDefault, // Default color for accent fills on controls |
39 | accentDisabled, // Default color for accent fills on disabled controls |
40 | accentSecondary, // Color for accent fills on hovered controls |
41 | }; |
42 | |
43 | const static QColor WINUI3ColorsLight [] { |
44 | QColor(0xF3,0xF3,0xF3,0xFF), //solidBackgroundColor |
45 | QColor(0xFC,0xFC,0xFC,0xFF), //acrylicBackgroundDefault |
46 | QColor(0x00,0x00,0x00,0xE4), //textPrimary |
47 | QColor(0x00,0x00,0x00,0x9E), //textSecondary |
48 | QColor(0x00,0x00,0x00,0x5C), //textDisabled |
49 | QColor(0xFF,0xFF,0xFF,0xFF), //textOnAccentPrimary |
50 | QColor(0xFF,0xFF,0xFF,0x7F), //textOnAccentSecondary |
51 | QColor(0xFF,0xFF,0xFF,0xFF), //textOnAccentDisabled |
52 | QColor(0xFF,0xFF,0xFF,0xB3), //controlDefault |
53 | QColor(0xF9,0xF9,0xF9,0x4D), //controlDisabled |
54 | QColor(0x00,0x00,0x00,0x0F), //controlStrokeDefault |
55 | QColor(0x00,0x00,0x00,0x29), //controlStrokeSecondary |
56 | QColor(0xFF,0xFF,0xFF,0x14), //controlStrokeAccentDefault |
57 | QColor(0x00,0x00,0x00,0x66), //controlStrokeAccentSecondary |
58 | QColor(0x00,0x5F,0xB8,0xFF), //accentDefault |
59 | QColor(0x00,0x00,0x00,0x37), //accentDisabled |
60 | QColor(0x00,0x5F,0xB8,0xE6), //accentSecondary |
61 | }; |
62 | |
63 | const static QColor WINUI3ColorsDark[] { |
64 | QColor(0x20,0x20,0x20,0xFF), //solidBackgroundColor |
65 | QColor(0x2C,0x2C,0x2C,0xFF), //acrylicBackgroundDefault |
66 | QColor(0xFF,0xFF,0xFF,0xFF), //textPrimary |
67 | QColor(0xFF,0xFF,0xFF,0xC5), //textSecondary |
68 | QColor(0xFF,0xFF,0xFF,0x5D), //textDisabled |
69 | QColor(0x00,0x00,0x00,0xFF), //textOnAccentPrimary |
70 | QColor(0x00,0x00,0x00,0x80), //textOnAccentSecondary |
71 | QColor(0xFF,0xFF,0xFF,0x87), //textOnAccentDisabled |
72 | QColor(0xFF,0xFF,0xFF,0x0F), //controlDefault |
73 | QColor(0xFF,0xFF,0xFF,0x11), //controlDisabled |
74 | QColor(0xFF,0xFF,0xFF,0x12), //controlStrokeDefault |
75 | QColor(0xFF,0xFF,0xFF,0x18), //controlStrokeSecondary |
76 | QColor(0xFF,0xFF,0xFF,0x14), //controlStrokeAccentDefault |
77 | QColor(0x00,0x00,0x00,0x23), //controlStrokeAccentSecondary |
78 | QColor(0x60,0xCD,0xFF,0xFF), //accentDefault |
79 | QColor(0xFF,0xFF,0xFF,0x28), //accentDisabled |
80 | QColor(0x60,0xCD,0xFF,0xE6) // accentSecondary |
81 | }; |
82 | |
83 | const static QColor* WINUI3Colors[] { |
84 | WINUI3ColorsLight, |
85 | WINUI3ColorsDark |
86 | }; |
87 | |
88 | static void populateSystemPalette(QPalette &palette) |
89 | { |
90 | const auto colorSchemeIndex = QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Light ? 0 : 1; |
91 | |
92 | palette.setColor(acg: QPalette::All, acr: QPalette::Window, acolor: WINUI3Colors[colorSchemeIndex][solidBackground]); |
93 | |
94 | palette.setColor(acg: QPalette::All, acr: QPalette::WindowText, acolor: WINUI3Colors[colorSchemeIndex][textPrimary]); |
95 | palette.setColor(acg: QPalette::Disabled, acr: QPalette::WindowText, acolor: WINUI3Colors[colorSchemeIndex][textDisabled]); |
96 | |
97 | palette.setColor(acg: QPalette::All, acr: QPalette::Text, acolor: WINUI3Colors[colorSchemeIndex][textPrimary]); |
98 | palette.setColor(acg: QPalette::Disabled, acr: QPalette::Text, acolor: WINUI3Colors[colorSchemeIndex][textDisabled]); |
99 | |
100 | palette.setColor(acg: QPalette::All, acr: QPalette::PlaceholderText, acolor: WINUI3Colors[colorSchemeIndex][textSecondary]); |
101 | palette.setColor(acg: QPalette::Disabled, acr: QPalette::PlaceholderText, acolor: WINUI3Colors[colorSchemeIndex][textDisabled]); |
102 | |
103 | palette.setColor(acg: QPalette::All, acr: QPalette::Button, acolor: WINUI3Colors[colorSchemeIndex][controlDefault]); |
104 | palette.setColor(acg: QPalette::Disabled, acr: QPalette::Button, acolor: WINUI3Colors[colorSchemeIndex][controlDisabled]); |
105 | palette.setColor(acg: QPalette::All, acr: QPalette::ButtonText, acolor: WINUI3Colors[colorSchemeIndex][textPrimary]); |
106 | palette.setColor(acg: QPalette::Disabled, acr: QPalette::ButtonText, acolor: WINUI3Colors[colorSchemeIndex][textDisabled]); |
107 | |
108 | palette.setColor(acg: QPalette::All, acr: QPalette::ToolTipBase, acolor: WINUI3Colors[colorSchemeIndex][acrylicBackgroundDefault]); |
109 | palette.setColor(acg: QPalette::All, acr: QPalette::ToolTipText, acolor: WINUI3Colors[colorSchemeIndex][textPrimary]); |
110 | palette.setColor(acg: QPalette::Disabled, acr: QPalette::ToolTipText, acolor: WINUI3Colors[colorSchemeIndex][textDisabled]); |
111 | |
112 | palette.setColor(acg: QPalette::Disabled, acr: QPalette::Accent, acolor: WINUI3Colors[colorSchemeIndex][accentDisabled]); |
113 | palette.setColor(acg: QPalette::Disabled, acr: QPalette::Highlight, acolor: WINUI3Colors[colorSchemeIndex][accentDisabled]); |
114 | |
115 | palette.setColor(acg: QPalette::All, acr: QPalette::HighlightedText, acolor: Qt::white); |
116 | |
117 | palette.setColor(acg: QPalette::All, acr: QPalette::Light, acolor: WINUI3Colors[colorSchemeIndex][controlStrokeAccentDefault]); |
118 | palette.setColor(acg: QPalette::All, acr: QPalette::Midlight, acolor: WINUI3Colors[colorSchemeIndex][controlStrokeDefault]); |
119 | palette.setColor(acg: QPalette::All, acr: QPalette::Dark, acolor: WINUI3Colors[colorSchemeIndex][controlStrokeSecondary]); |
120 | palette.setColor(acg: QPalette::All, acr: QPalette::Mid, acolor: WINUI3Colors[colorSchemeIndex][controlStrokeAccentSecondary]); |
121 | } |
122 | |
123 | static void populateThemeFont(QQuickTheme *theme) |
124 | { |
125 | QFont systemFont; |
126 | QFont toolBarFont; |
127 | QFont toolTipFont; |
128 | |
129 | const QLatin1String segoeUiFamilyName("Segoe UI Variable" ); |
130 | if (QFontDatabase::families().contains(str: segoeUiFamilyName)) { |
131 | const QFont segoeFont(segoeUiFamilyName); |
132 | const QStringList families{segoeFont.family()}; |
133 | systemFont.setFamilies(families); |
134 | toolBarFont.setFamilies(families); |
135 | } |
136 | systemFont.setWeight(QFont::Weight::Normal); |
137 | toolBarFont.setWeight(QFont::Weight::Normal); |
138 | toolTipFont.setWeight(QFont::Weight::Normal); |
139 | |
140 | systemFont.setPixelSize(14); |
141 | toolBarFont.setPixelSize(12); |
142 | toolTipFont.setPixelSize(12); |
143 | |
144 | theme->setFont(scope: QQuickTheme::System, font: systemFont); |
145 | theme->setFont(scope: QQuickTheme::ToolBar, font: toolBarFont); |
146 | theme->setFont(scope: QQuickTheme::ToolTip, font: toolTipFont); |
147 | } |
148 | |
149 | void QQuickFluentWinUI3Theme::updatePalette(QPalette &palette) |
150 | { |
151 | populateSystemPalette(palette); |
152 | } |
153 | |
154 | void QQuickFluentWinUI3Theme::initialize(QQuickTheme *theme) |
155 | { |
156 | populateThemeFont(theme); |
157 | QPalette systemPalette; |
158 | updatePalette(palette&: systemPalette); |
159 | |
160 | if (auto platformTheme = QGuiApplicationPrivate::platformTheme()) { |
161 | const auto platformPalette = platformTheme->palette(); |
162 | if (platformPalette) |
163 | // style palette takes precedence over platform's theme |
164 | systemPalette = systemPalette.resolve(other: *platformPalette); |
165 | } |
166 | |
167 | { |
168 | const auto colorSchemeIndex = QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Light ? 0 : 1; |
169 | if (!systemPalette.isBrushSet(cg: QPalette::Active, cr: QPalette::Accent)) |
170 | systemPalette.setColor(acg: QPalette::Active, acr: QPalette::Accent, acolor: WINUI3Colors[colorSchemeIndex][accentDefault]); |
171 | |
172 | systemPalette.setColor(acg: QPalette::Active, acr: QPalette::Highlight, acolor: systemPalette.accent().color()); |
173 | systemPalette.setColor(acg: QPalette::Inactive, acr: QPalette::Accent, acolor: systemPalette.accent().color()); |
174 | systemPalette.setColor(acg: QPalette::Inactive, acr: QPalette::Highlight, acolor: systemPalette.highlight().color()); |
175 | } |
176 | |
177 | // Finally QGuiApp::palette() should take precedence over style palette |
178 | systemPalette = QGuiApplication::palette().resolve(other: systemPalette); |
179 | theme->setPalette(scope: QQuickTheme::System, palette: systemPalette); |
180 | } |
181 | |
182 | QT_END_NAMESPACE |
183 | |