| 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 |  |