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