aboutsummaryrefslogtreecommitdiffstats
path: root/src/quickcontrols/fluentwinui3/qquickfluentwinui3theme.cpp
blob: d1daea0823e486fc149aef1d0d5b5fac64b4ee82 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
// Qt-Security score:significant reason:default

#include "qquickfluentwinui3theme_p.h"

#include <QtCore/qoperatingsystemversion.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/qpa/qplatformtheme.h>
#include <QtGui/qguiapplication.h>
#include <QtGui/qstylehints.h>
#include <QtGui/QAccessibilityHints>
#include <QtGui/qcolor.h>
#include <QtGui/qfontdatabase.h>
#include <QtQuickTemplates2/private/qquicktheme_p.h>

QT_BEGIN_NAMESPACE

// If on a Windows11 or above, the platform theme will be used to populate the palette
// We need to fallback to hardcoded colors when using the style on other platforms,
// that's why we need the following
// The colors for Windows 11 are taken from the official WinUI3 Figma style at
// https://www.figma.com/community/file/1159947337437047524
// Try to keep these consistent with the widget windows11 style
enum WinUI3Color {
    solidBackground,                    // Solid background color used for the bottom most layer
    acrylicBackgroundDefault,           // Acrylic background for popups/tooltips
    textPrimary,                        // Color for UI labels and static text
    textSecondary,                      // Color for text in pressed controls
    textDisabled,                       // Color for disabled text
    textOnAccentPrimary,                // Color of text on controls filled in accent color
    textOnAccentSecondary,              // Color of text on sunken controls in accent color
    textOnAccentDisabled,               // Color of text on disabled controls in accent color
    controlDefault,                     // Color for standard controls
    controlDisabled,                    // Color for disabled controls
    controlStrokeDefault,               // Color for gradient stops in elevations (pressed or disabled state)
    controlStrokeSecondary,             // Color for gradient stops in elevations
    controlStrokeAccentDefault,         // Color for gradient stops in elevations for accent controls
    controlStrokeAccentSecondary,       // Color for gradient stops in elevations for accent controls
    accentDefault,                      // Default color for accent fills on controls
    accentDisabled,                     // Default color for accent fills on disabled controls
    accentSecondary,                    // Color for accent fills on hovered controls
    inputActive,                        // Color for active text input backgrounds
};

const static QColor WINUI3ColorsLight [] {
    QColor(0xF3,0xF3,0xF3,0xFF), //solidBackgroundColor
    QColor(0xFC,0xFC,0xFC,0xFF), //acrylicBackgroundDefault
    QColor(0x00,0x00,0x00,0xE4), //textPrimary
    QColor(0x00,0x00,0x00,0x9E), //textSecondary
    QColor(0x00,0x00,0x00,0x5C), //textDisabled
    QColor(0xFF,0xFF,0xFF,0xFF), //textOnAccentPrimary
    QColor(0xFF,0xFF,0xFF,0x7F), //textOnAccentSecondary
    QColor(0xFF,0xFF,0xFF,0xFF), //textOnAccentDisabled
    QColor(0xFF,0xFF,0xFF,0xB3), //controlDefault
    QColor(0xF9,0xF9,0xF9,0x4D), //controlDisabled
    QColor(0x00,0x00,0x00,0x0F), //controlStrokeDefault
    QColor(0x00,0x00,0x00,0x29), //controlStrokeSecondary
    QColor(0xFF,0xFF,0xFF,0x14), //controlStrokeAccentDefault
    QColor(0x00,0x00,0x00,0x66), //controlStrokeAccentSecondary
    QColor(0x00,0x5F,0xB8,0xFF), //accentDefault
    QColor(0x00,0x00,0x00,0x37), //accentDisabled
    QColor(0x00,0x5F,0xB8,0xE6), //accentSecondary
    QColor(0xFF,0xFF,0xFF,0xFF)  //inputActive
};

const static QColor WINUI3ColorsDark[] {
    QColor(0x20,0x20,0x20,0xFF), //solidBackgroundColor
    QColor(0x2C,0x2C,0x2C,0xFF), //acrylicBackgroundDefault
    QColor(0xFF,0xFF,0xFF,0xFF), //textPrimary
    QColor(0xFF,0xFF,0xFF,0xC5), //textSecondary
    QColor(0xFF,0xFF,0xFF,0x5D), //textDisabled
    QColor(0x00,0x00,0x00,0xFF), //textOnAccentPrimary
    QColor(0x00,0x00,0x00,0x80), //textOnAccentSecondary
    QColor(0xFF,0xFF,0xFF,0x87), //textOnAccentDisabled
    QColor(0xFF,0xFF,0xFF,0x0F), //controlDefault
    QColor(0xFF,0xFF,0xFF,0x11), //controlDisabled
    QColor(0xFF,0xFF,0xFF,0x12), //controlStrokeDefault
    QColor(0xFF,0xFF,0xFF,0x18), //controlStrokeSecondary
    QColor(0xFF,0xFF,0xFF,0x14), //controlStrokeAccentDefault
    QColor(0x00,0x00,0x00,0x23), //controlStrokeAccentSecondary
    QColor(0x60,0xCD,0xFF,0xFF), //accentDefault
    QColor(0xFF,0xFF,0xFF,0x28), //accentDisabled
    QColor(0x60,0xCD,0xFF,0xE6), // accentSecondary
    QColor(0x1E,0x1E,0x1E,0xB3)  // inputActive
};

const static QColor* WINUI3Colors[] {
    WINUI3ColorsLight,
    WINUI3ColorsDark
};

// Function to populate the palette with WinUI3 theme-specific colors
static void populateWinUI3Palette(QPalette &palette)
{
    const auto colorSchemeIndex = QGuiApplication::styleHints()->colorScheme() == Qt::ColorScheme::Light ? 0 : 1;

    palette.setColor(QPalette::All, QPalette::Window, WINUI3Colors[colorSchemeIndex][solidBackground]);

    palette.setColor(QPalette::All, QPalette::Base, WINUI3Colors[colorSchemeIndex][controlDefault]);
    palette.setColor(QPalette::Active, QPalette::Base, WINUI3Colors[colorSchemeIndex][inputActive]);
    palette.setColor(QPalette::Disabled, QPalette::Base, WINUI3Colors[colorSchemeIndex][controlDisabled]);

    palette.setColor(QPalette::All, QPalette::WindowText, WINUI3Colors[colorSchemeIndex][textPrimary]);
    palette.setColor(QPalette::Disabled, QPalette::WindowText, WINUI3Colors[colorSchemeIndex][textDisabled]);

    palette.setColor(QPalette::All, QPalette::Text, WINUI3Colors[colorSchemeIndex][textPrimary]);
    palette.setColor(QPalette::Disabled, QPalette::Text, WINUI3Colors[colorSchemeIndex][textDisabled]);

    palette.setColor(QPalette::All, QPalette::PlaceholderText, WINUI3Colors[colorSchemeIndex][textSecondary]);
    palette.setColor(QPalette::Disabled, QPalette::PlaceholderText, WINUI3Colors[colorSchemeIndex][textDisabled]);

    palette.setColor(QPalette::All, QPalette::Button, WINUI3Colors[colorSchemeIndex][controlDefault]);
    palette.setColor(QPalette::Disabled, QPalette::Button, WINUI3Colors[colorSchemeIndex][controlDisabled]);
    palette.setColor(QPalette::All, QPalette::ButtonText, WINUI3Colors[colorSchemeIndex][textPrimary]);
    palette.setColor(QPalette::Disabled, QPalette::ButtonText, WINUI3Colors[colorSchemeIndex][textDisabled]);

    palette.setColor(QPalette::All, QPalette::ToolTipBase, WINUI3Colors[colorSchemeIndex][acrylicBackgroundDefault]);
    palette.setColor(QPalette::All, QPalette::ToolTipText, WINUI3Colors[colorSchemeIndex][textPrimary]);
    palette.setColor(QPalette::Disabled, QPalette::ToolTipText, WINUI3Colors[colorSchemeIndex][textDisabled]);

    palette.setColor(QPalette::Disabled, QPalette::Accent, WINUI3Colors[colorSchemeIndex][accentDisabled]);
    palette.setColor(QPalette::Disabled, QPalette::Highlight, WINUI3Colors[colorSchemeIndex][accentDisabled]);

    palette.setColor(QPalette::All, QPalette::HighlightedText, Qt::white);

    palette.setColor(QPalette::All, QPalette::Light, WINUI3Colors[colorSchemeIndex][controlStrokeAccentDefault]);
    palette.setColor(QPalette::All, QPalette::Midlight, WINUI3Colors[colorSchemeIndex][controlStrokeDefault]);
    palette.setColor(QPalette::All, QPalette::Dark, WINUI3Colors[colorSchemeIndex][controlStrokeSecondary]);
    palette.setColor(QPalette::All, QPalette::Mid, WINUI3Colors[colorSchemeIndex][controlStrokeAccentSecondary]);
}

static void populateWinUI3Fonts(QQuickTheme *theme)
{
    QFont systemFont;
    QFont toolBarFont;
    QFont toolTipFont;

    const QLatin1String segoeUiFamilyName("Segoe UI Variable");
    if (QFontDatabase::families().contains(segoeUiFamilyName)) {
        const QFont segoeFont(segoeUiFamilyName);
        const QStringList families{segoeFont.family()};
        systemFont.setFamilies(families);
        toolBarFont.setFamilies(families);
    }
    systemFont.setWeight(QFont::Weight::Normal);
    toolBarFont.setWeight(QFont::Weight::Normal);
    toolTipFont.setWeight(QFont::Weight::Normal);

    systemFont.setPixelSize(14);
    toolBarFont.setPixelSize(12);
    toolTipFont.setPixelSize(12);

    theme->setFont(QQuickTheme::System, systemFont);
    theme->setFont(QQuickTheme::ToolBar, toolBarFont);
    theme->setFont(QQuickTheme::ToolTip, toolTipFont);
}

QPalette QQuickFluentWinUI3Theme::initializeDefaultPalette()
{
    QPalette palette;

    const auto *styleHints = QGuiApplication::styleHints();
    const auto highContrastTheme = styleHints->accessibility()->contrastPreference() == Qt::ContrastPreference::HighContrast;
    // HighContrast themes use system colors only
    if (!highContrastTheme) {
        populateWinUI3Palette(palette);

        // Resolve against the platform palette
        if (auto platformTheme = QGuiApplicationPrivate::platformTheme()) {
            const auto platformPalette = platformTheme->palette();
            if (platformPalette)
                palette = palette.resolve(*platformPalette);
        }
        const auto colorSchemeIndex = styleHints->colorScheme() == Qt::ColorScheme::Light ? 0 : 1;
        // Ensure specific roles are set
        if (!palette.isBrushSet(QPalette::Active, QPalette::Accent))
            palette.setColor(QPalette::Active, QPalette::Accent, WINUI3Colors[colorSchemeIndex][accentDefault]);

        if (!palette.isBrushSet(QPalette::Inactive, QPalette::Highlight))
            palette.setColor(QPalette::Inactive, QPalette::Highlight, palette.accent().color());

        palette.setColor(QPalette::Disabled, QPalette::Accent, WINUI3Colors[colorSchemeIndex][accentDisabled]);
        palette.setColor(QPalette::Disabled, QPalette::Highlight, WINUI3Colors[colorSchemeIndex][accentDisabled]);
    }
    // WinUI3 sets the inactive accent color to the same as the active one
    palette.setColor(QPalette::Inactive, QPalette::Accent, palette.accent().color());
    palette.setColor(QPalette::Inactive, QPalette::Highlight, palette.highlight().color());

    // Finally QGuiApp::palette() should take precedence over style palette
    palette = QGuiApplication::palette().resolve(palette);

    return palette;
}

void QQuickFluentWinUI3Theme::initialize(QQuickTheme *theme)
{
    populateWinUI3Fonts(theme);

    QPalette systemPalette = initializeDefaultPalette();
    theme->setPalette(QQuickTheme::System, systemPalette);
}

QT_END_NAMESPACE