Revision control

Copy as Markdown

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