File indexing completed on 2024-04-28 16:44:30

0001 /*
0002  * SPDX-FileCopyrightText: 2019 Mikhail Zolotukhin <zomial@protonmail.com>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0005  */
0006 
0007 #include <QColor>
0008 #include <QDir>
0009 #include <QFont>
0010 #include <QList>
0011 #include <QMap>
0012 #include <QString>
0013 #include <QSvgGenerator>
0014 
0015 #include <KColorScheme>
0016 #include <KColorUtils>
0017 #include <KConfig>
0018 #include <KConfigGroup>
0019 #include <KWindowSystem>
0020 
0021 #include <gtk/gtk.h>
0022 
0023 #include <algorithm>
0024 
0025 #include "configvalueprovider.h"
0026 #include "decorationpainter.h"
0027 
0028 constexpr int MAX_GDK_SCALE = 5;
0029 
0030 constexpr int DEFAULT_DPI = 96;
0031 constexpr int MIN_FONT_DPI = DEFAULT_DPI / 2;
0032 constexpr int MAX_FONT_DPI = DEFAULT_DPI * 5;
0033 
0034 ConfigValueProvider::ConfigValueProvider()
0035     : kdeglobalsConfig(KSharedConfig::openConfig())
0036     , fontsConfig(KSharedConfig::openConfig(QStringLiteral("kcmfonts")))
0037     , inputConfig(KSharedConfig::openConfig(QStringLiteral("kcminputrc")))
0038     , kwinConfig(KSharedConfig::openConfig(QStringLiteral("kwinrc")))
0039     , generatedCSDTempPath(QDir::tempPath() + QStringLiteral("/plasma-csd-generator"))
0040 {
0041 }
0042 
0043 QString ConfigValueProvider::fontName() const
0044 {
0045     static const QFont defaultFont(QStringLiteral("Noto Sans"), 10);
0046 
0047     KConfigGroup configGroup = kdeglobalsConfig->group(QStringLiteral("General"));
0048     QString fontAsString = configGroup.readEntry(QStringLiteral("font"), defaultFont.toString());
0049     static QFont font;
0050     font.fromString(fontAsString);
0051     const QString fontStyle = fontStyleHelper(font);
0052     return font.family() + QStringLiteral(", ") + fontStyle + ' ' + QString::number(font.pointSize());
0053 }
0054 
0055 QString ConfigValueProvider::fontStyleHelper(const QFont &font) const
0056 {
0057     // BUG: 333146
0058     // Since Qt sometimes gives us wrong font style name,
0059     // we ought to use this big helper function to construct
0060     // the style ourselves. Some fonts will not work
0061     auto weight = font.weight();
0062     QString result;
0063     if (weight > QFont::Normal) {
0064         if (weight >= QFont::Black) {
0065             result = QStringLiteral("Black");
0066         } else if (weight >= QFont::ExtraBold) {
0067             result = QStringLiteral("Extra Bold");
0068         } else if (weight >= QFont::Bold) {
0069             result = QStringLiteral("Bold");
0070         } else if (weight >= QFont::DemiBold) {
0071             result = QStringLiteral("Demi Bold");
0072         } else if (weight >= QFont::Medium) {
0073             result = QStringLiteral("Medium");
0074         }
0075     } else {
0076         if (weight <= QFont::Thin) {
0077             result = QStringLiteral("Thin");
0078         } else if (weight <= QFont::ExtraLight) {
0079             result = QStringLiteral("Extra Light");
0080         } else if (weight <= QFont::Light) {
0081             result = QStringLiteral("Light");
0082         }
0083     }
0084 
0085     auto style = font.style();
0086     if (style == QFont::StyleItalic) {
0087         result += QLatin1Char(' ') + QStringLiteral("Italic");
0088     } else if (style == QFont::StyleOblique) {
0089         result += QLatin1Char(' ') + QStringLiteral("Oblique");
0090     }
0091 
0092     auto stretch = font.stretch();
0093     if (stretch == QFont::UltraCondensed) {
0094         result += QLatin1Char(' ') + QStringLiteral("UltraCondensed");
0095     } else if (stretch == QFont::ExtraCondensed) {
0096         result += QLatin1Char(' ') + QStringLiteral("ExtraCondensed");
0097     } else if (stretch == QFont::Condensed) {
0098         result += QLatin1Char(' ') + QStringLiteral("Condensed");
0099     } else if (stretch == QFont::SemiCondensed) {
0100         result += QLatin1Char(' ') + QStringLiteral("SemiCondensed");
0101     } else if (stretch == QFont::Unstretched) {
0102         result += QLatin1Char(' ') + QStringLiteral("Unstretched");
0103     } else if (stretch == QFont::SemiExpanded) {
0104         result += QLatin1Char(' ') + QStringLiteral("SemiExpanded");
0105     } else if (stretch == QFont::Expanded) {
0106         result += QLatin1Char(' ') + QStringLiteral("Expanded");
0107     } else if (stretch == QFont::ExtraExpanded) {
0108         result += QLatin1Char(' ') + QStringLiteral("ExtraExpanded");
0109     } else if (stretch == QFont::UltraExpanded) {
0110         result += QLatin1Char(' ') + QStringLiteral("UltraExpanded");
0111     }
0112 
0113     return result.simplified();
0114 }
0115 
0116 QString ConfigValueProvider::iconThemeName() const
0117 {
0118     KConfigGroup configGroup = kdeglobalsConfig->group(QStringLiteral("Icons"));
0119     return configGroup.readEntry(QStringLiteral("Theme"), QStringLiteral("breeze"));
0120 }
0121 
0122 QString ConfigValueProvider::cursorThemeName() const
0123 {
0124     KConfigGroup configGroup = inputConfig->group(QStringLiteral("Mouse"));
0125     return configGroup.readEntry(QStringLiteral("cursorTheme"), QStringLiteral("breeze_cursors"));
0126 }
0127 
0128 int ConfigValueProvider::cursorSize() const
0129 {
0130     KConfigGroup configGroup = inputConfig->group(QStringLiteral("Mouse"));
0131     return configGroup.readEntry(QStringLiteral("cursorSize"), 24);
0132 }
0133 
0134 bool ConfigValueProvider::iconsOnButtons() const
0135 {
0136     KConfigGroup configGroup = kdeglobalsConfig->group(QStringLiteral("KDE"));
0137     return configGroup.readEntry(QStringLiteral("ShowIconsOnPushButtons"), true);
0138 }
0139 
0140 bool ConfigValueProvider::iconsInMenus() const
0141 {
0142     KConfigGroup configGroup = kdeglobalsConfig->group(QStringLiteral("KDE"));
0143     return configGroup.readEntry(QStringLiteral("ShowIconsInMenuItems"), true);
0144 }
0145 
0146 int ConfigValueProvider::toolbarStyle() const
0147 {
0148     KConfigGroup configGroup = kdeglobalsConfig->group(QStringLiteral("Toolbar style"));
0149     QString kdeConfigValue = configGroup.readEntry(QStringLiteral("ToolButtonStyle"), "TextBesideIcon");
0150 
0151     if (kdeConfigValue == QStringLiteral("NoText")) {
0152         return GtkToolbarStyle::GTK_TOOLBAR_ICONS;
0153     } else if (kdeConfigValue == QStringLiteral("TextOnly")) {
0154         return GtkToolbarStyle::GTK_TOOLBAR_TEXT;
0155     } else if (kdeConfigValue == QStringLiteral("TextBesideIcon")) {
0156         return GtkToolbarStyle::GTK_TOOLBAR_BOTH_HORIZ;
0157     } else {
0158         return GtkToolbarStyle::GTK_TOOLBAR_BOTH;
0159     }
0160 }
0161 
0162 bool ConfigValueProvider::scrollbarBehavior() const
0163 {
0164     KConfigGroup configGroup = kdeglobalsConfig->group(QStringLiteral("KDE"));
0165     bool kdeConfigValue = configGroup.readEntry(QStringLiteral("ScrollbarLeftClickNavigatesByPage"), true);
0166     return !kdeConfigValue; // GTK setting is inverted
0167 }
0168 
0169 bool ConfigValueProvider::preferDarkTheme() const
0170 {
0171     KConfigGroup colorsConfigGroup = kdeglobalsConfig->group(QStringLiteral("Colors:Window"));
0172     QColor windowBackgroundColor = colorsConfigGroup.readEntry(QStringLiteral("BackgroundNormal"), QColor(239, 240, 241));
0173     const int windowBackgroundGray = qGray(windowBackgroundColor.rgb());
0174 
0175     // We use heuristic to determine if current color scheme is dark or not
0176     return windowBackgroundGray < 192;
0177 }
0178 
0179 QStringList ConfigValueProvider::windowDecorationsButtonsImages() const
0180 {
0181     static const QVector<QString> buttonTypes{
0182         QStringLiteral("close"),
0183         QStringLiteral("maximize"),
0184         QStringLiteral("maximized"),
0185         QStringLiteral("minimize"),
0186     };
0187 
0188     static const QVector<QString> buttonStates{
0189         // Focused titlebars
0190         QStringLiteral("normal"),
0191         QStringLiteral("active"), // aka pressed
0192         QStringLiteral("hover"),
0193         // Unfocused titlebars
0194         QStringLiteral("backdrop-normal"),
0195         QStringLiteral("backdrop-active"),
0196         QStringLiteral("backdrop-hover"),
0197     };
0198 
0199     KConfigGroup decorationGroup = kwinConfig->group(QStringLiteral("org.kde.kdecoration2"));
0200     const QString themeName = decorationGroup.readEntry(QStringLiteral("theme"), QStringLiteral("Breeze"));
0201 
0202     auto decorationPainter = DecorationPainter::fromThemeName(themeName);
0203     QStringList decorationsImages{};
0204 
0205     for (const auto &buttonType : buttonTypes) {
0206         for (const auto &buttonState : buttonStates) {
0207             QSvgGenerator svgGenerator{};
0208 
0209             QString filePath = generatedCSDTempPath.filePath(QStringLiteral("%1-%2.svg").arg(buttonType, buttonState));
0210 
0211             svgGenerator.setFileName(filePath);
0212             svgGenerator.setViewBox(DecorationPainter::ButtonGeometry);
0213 
0214             QPainter painter{&svgGenerator};
0215             decorationPainter->paintButton(painter, buttonType, buttonState);
0216             painter.end();
0217 
0218             decorationsImages.append(filePath);
0219         }
0220     }
0221 
0222     return decorationsImages;
0223 }
0224 
0225 QString ConfigValueProvider::windowDecorationsButtonsOrder() const
0226 {
0227     KConfigGroup configGroup = kwinConfig->group(QStringLiteral("org.kde.kdecoration2"));
0228     QString buttonsOnLeftKdeConfigValue = configGroup.readEntry(QStringLiteral("ButtonsOnLeft"), "MS");
0229     QString buttonsOnRightKdeConfigValue = configGroup.readEntry(QStringLiteral("ButtonsOnRight"), "HIAX");
0230 
0231     QString buttonsOnLeftInGtkNotation = windowDecorationButtonsOrderInGtkNotation(buttonsOnLeftKdeConfigValue);
0232     QString buttonsOnRightInGtkNotation = windowDecorationButtonsOrderInGtkNotation(buttonsOnRightKdeConfigValue);
0233 
0234     return buttonsOnLeftInGtkNotation + QStringLiteral(":") + buttonsOnRightInGtkNotation;
0235 }
0236 
0237 bool ConfigValueProvider::enableAnimations() const
0238 {
0239     KConfigGroup generalCfg = kdeglobalsConfig->group(QStringLiteral("KDE"));
0240     const qreal animationSpeedModifier = qMax(0.0, generalCfg.readEntry("AnimationDurationFactor", 1.0));
0241 
0242     return !qFuzzyIsNull(animationSpeedModifier);
0243 }
0244 
0245 QMap<QString, QColor> ConfigValueProvider::colors() const
0246 {
0247     using KCS = KColorScheme;
0248 
0249     // Color Schemes Collection
0250     QHash<QString, QHash<QString, KCS>> csc{
0251         {QStringLiteral("active"),
0252          {
0253              {QStringLiteral("view"), KCS(QPalette::Active, KCS::View)},
0254              {QStringLiteral("window"), KCS(QPalette::Active, KCS::Window)},
0255              {QStringLiteral("button"), KCS(QPalette::Active, KCS::Button)},
0256              {QStringLiteral("selection"), KCS(QPalette::Active, KCS::Selection)},
0257              {QStringLiteral("tooltip"), KCS(QPalette::Active, KCS::Tooltip)},
0258              {QStringLiteral("complementary"), KCS(QPalette::Active, KCS::Complementary)},
0259              {QStringLiteral("header"), KCS(QPalette::Active, KCS::Header)},
0260          }},
0261         {QStringLiteral("inactive"),
0262          {
0263              {QStringLiteral("view"), KCS(QPalette::Inactive, KCS::View)},
0264              {QStringLiteral("window"), KCS(QPalette::Inactive, KCS::Window)},
0265              {QStringLiteral("button"), KCS(QPalette::Inactive, KCS::Button)},
0266              {QStringLiteral("selection"), KCS(QPalette::Inactive, KCS::Selection)},
0267              {QStringLiteral("tooltip"), KCS(QPalette::Inactive, KCS::Tooltip)},
0268              {QStringLiteral("complementary"), KCS(QPalette::Inactive, KCS::Complementary)},
0269              {QStringLiteral("header"), KCS(QPalette::Inactive, KCS::Header)},
0270          }},
0271         {QStringLiteral("disabled"),
0272          {
0273              {QStringLiteral("view"), KCS(QPalette::Disabled, KCS::View)},
0274              {QStringLiteral("window"), KCS(QPalette::Disabled, KCS::Window)},
0275              {QStringLiteral("button"), KCS(QPalette::Disabled, KCS::Button)},
0276              {QStringLiteral("selection"), KCS(QPalette::Disabled, KCS::Selection)},
0277              {QStringLiteral("tooltip"), KCS(QPalette::Disabled, KCS::Tooltip)},
0278              {QStringLiteral("complementary"), KCS(QPalette::Disabled, KCS::Complementary)},
0279              {QStringLiteral("header"), KCS(QPalette::Disabled, KCS::Header)},
0280          }},
0281     };
0282 
0283     // Color mixing
0284     QColor windowForegroundColor = csc["active"]["window"].foreground(KCS::NormalText).color();
0285     QColor windowBackgroundColor = csc["active"]["window"].background(KCS::NormalBackground).color();
0286     QColor bordersColor = KColorUtils::mix(windowBackgroundColor, windowForegroundColor, 0.25);
0287 
0288     QColor inactiveWindowForegroundColor = csc["inactive"]["window"].foreground(KCS::NormalText).color();
0289     QColor inactiveWindowBackgroundColor = csc["inactive"]["window"].background(KCS::NormalBackground).color();
0290     QColor inactiveBordersColor = KColorUtils::mix(inactiveWindowBackgroundColor, inactiveWindowForegroundColor, 0.25);
0291 
0292     QColor disabledWindowForegroundColor = csc["disabled"]["window"].foreground(KCS::NormalText).color();
0293     QColor disabledWindowBackgroundColor = csc["disabled"]["window"].background(KCS::NormalBackground).color();
0294     QColor disabledBordersColor = KColorUtils::mix(disabledWindowBackgroundColor, disabledWindowForegroundColor, 0.25);
0295 
0296     QColor unfocusedDisabledWindowForegroundColor = csc["disabled"]["window"].foreground(KCS::NormalText).color();
0297     QColor unfocusedDisabledWindowBackgroundColor = csc["disabled"]["window"].background(KCS::NormalBackground).color();
0298     QColor unfocusedDisabledBordersColor = KColorUtils::mix(unfocusedDisabledWindowBackgroundColor, unfocusedDisabledWindowForegroundColor, 0.25);
0299 
0300     QColor tooltipForegroundColor = csc["active"]["tooltip"].foreground(KCS::NormalText).color();
0301     QColor tooltipBackgroundColor = csc["active"]["tooltip"].background(KCS::NormalBackground).color();
0302     QColor tooltipBorderColor = KColorUtils::mix(tooltipBackgroundColor, tooltipForegroundColor, 0.25);
0303 
0304     KConfigGroup windowManagerConfig = kdeglobalsConfig->group(QStringLiteral("WM"));
0305 
0306     QMap<QString, QColor> result = {
0307         /*
0308          * Normal (Non Backdrop, Non Insensitive)
0309          */
0310 
0311         // General Colors
0312         {"theme_fg_color_breeze", csc["active"]["window"].foreground(KCS::NormalText).color()},
0313         {"theme_bg_color_breeze", csc["active"]["window"].background(KCS::NormalBackground).color()},
0314         {"theme_text_color_breeze", csc["active"]["view"].foreground(KCS::NormalText).color()},
0315         {"theme_base_color_breeze", csc["active"]["view"].background(KCS::NormalBackground).color()},
0316         {"theme_view_hover_decoration_color_breeze", csc["active"]["view"].decoration(KCS::HoverColor).color()},
0317         {"theme_hovering_selected_bg_color_breeze", csc["active"]["selection"].decoration(KCS::HoverColor).color()},
0318         {"theme_selected_bg_color_breeze", csc["active"]["selection"].background(KCS::NormalBackground).color()},
0319         {"theme_selected_fg_color_breeze", csc["active"]["selection"].foreground(KCS::NormalText).color()},
0320         {"theme_view_active_decoration_color_breeze", csc["active"]["view"].decoration(KCS::HoverColor).color()},
0321 
0322         // Button Colors
0323         {"theme_button_background_normal_breeze", csc["active"]["button"].background(KCS::NormalBackground).color()},
0324         {"theme_button_decoration_hover_breeze", csc["active"]["button"].decoration(KCS::HoverColor).color()},
0325         {"theme_button_decoration_focus_breeze", csc["active"]["button"].decoration(KCS::FocusColor).color()},
0326         {"theme_button_foreground_normal_breeze", csc["active"]["button"].foreground(KCS::NormalText).color()},
0327         {"theme_button_foreground_active_breeze", csc["active"]["selection"].foreground(KCS::NormalText).color()},
0328 
0329         // Misc Colors
0330         {"borders_breeze", bordersColor},
0331         {"warning_color_breeze", csc["active"]["view"].foreground(KCS::NeutralText).color()},
0332         {"success_color_breeze", csc["active"]["view"].foreground(KCS::PositiveText).color()},
0333         {"error_color_breeze", csc["active"]["view"].foreground(KCS::NegativeText).color()},
0334 
0335         /*
0336          * Backdrop (Inactive)
0337          */
0338 
0339         // General
0340         {"theme_unfocused_fg_color_breeze", csc["inactive"]["window"].foreground(KCS::NormalText).color()},
0341         {"theme_unfocused_text_color_breeze", csc["inactive"]["view"].foreground(KCS::NormalText).color()},
0342         {"theme_unfocused_bg_color_breeze", csc["inactive"]["window"].background(KCS::NormalBackground).color()},
0343         {"theme_unfocused_base_color_breeze", csc["inactive"]["view"].background(KCS::NormalBackground).color()},
0344         {"theme_unfocused_selected_bg_color_alt_breeze", csc["inactive"]["selection"].background(KCS::NormalBackground).color()},
0345         {"theme_unfocused_selected_bg_color_breeze", csc["inactive"]["selection"].background(KCS::NormalBackground).color()},
0346         {"theme_unfocused_selected_fg_color_breeze", csc["inactive"]["selection"].foreground(KCS::NormalText).color()},
0347 
0348         // Button
0349         {"theme_button_background_backdrop_breeze", csc["inactive"]["button"].background(KCS::NormalBackground).color()},
0350         {"theme_button_decoration_hover_backdrop_breeze", csc["inactive"]["button"].decoration(KCS::HoverColor).color()},
0351         {"theme_button_decoration_focus_backdrop_breeze", csc["inactive"]["button"].decoration(KCS::FocusColor).color()},
0352         {"theme_button_foreground_backdrop_breeze", csc["inactive"]["button"].foreground(KCS::NormalText).color()},
0353         {"theme_button_foreground_active_backdrop_breeze", csc["inactive"]["selection"].foreground(KCS::NormalText).color()},
0354 
0355         // Misc Colors
0356         {"unfocused_borders_breeze", inactiveBordersColor},
0357         {"warning_color_backdrop_breeze", csc["inactive"]["view"].foreground(KCS::NeutralText).color()},
0358         {"success_color_backdrop_breeze", csc["inactive"]["view"].foreground(KCS::PositiveText).color()},
0359         {"error_color_backdrop_breeze", csc["inactive"]["view"].foreground(KCS::NegativeText).color()},
0360 
0361         /*
0362          * Insensitive (Disabled)
0363          */
0364 
0365         // General
0366         {"insensitive_fg_color_breeze", csc["disabled"]["window"].foreground(KCS::NormalText).color()},
0367         {"insensitive_base_fg_color_breeze", csc["disabled"]["view"].foreground(KCS::NormalText).color()},
0368         {"insensitive_bg_color_breeze", csc["disabled"]["window"].background(KCS::NormalBackground).color()},
0369         {"insensitive_base_color_breeze", csc["disabled"]["view"].background(KCS::NormalBackground).color()},
0370         {"insensitive_selected_bg_color_breeze", csc["disabled"]["selection"].background(KCS::NormalBackground).color()},
0371         {"insensitive_selected_fg_color_breeze", csc["disabled"]["selection"].foreground(KCS::NormalText).color()},
0372 
0373         // Button
0374         {"theme_button_background_insensitive_breeze", csc["disabled"]["button"].background(KCS::NormalBackground).color()},
0375         {"theme_button_decoration_hover_insensitive_breeze", csc["disabled"]["button"].decoration(KCS::HoverColor).color()},
0376         {"theme_button_decoration_focus_insensitive_breeze", csc["disabled"]["button"].decoration(KCS::FocusColor).color()},
0377         {"theme_button_foreground_insensitive_breeze", csc["disabled"]["button"].foreground(KCS::NormalText).color()},
0378         {"theme_button_foreground_active_insensitive_breeze", csc["disabled"]["selection"].foreground(KCS::NormalText).color()},
0379 
0380         // Misc Colors
0381         {"insensitive_borders_breeze", disabledBordersColor},
0382         {"warning_color_insensitive_breeze", csc["disabled"]["view"].foreground(KCS::NeutralText).color()},
0383         {"success_color_insensitive_breeze", csc["disabled"]["view"].foreground(KCS::PositiveText).color()},
0384         {"error_color_insensitive_breeze", csc["disabled"]["view"].foreground(KCS::NegativeText).color()},
0385 
0386         /*
0387          * Insensitive Backdrop (Inactive Disabled)
0388          * These pretty much have the same appearance as regular inactive colors,
0389          * but they're separate in case we decide to make them different in the future.
0390          */
0391 
0392         // General
0393         {"insensitive_unfocused_fg_color_breeze", csc["disabled"]["window"].foreground(KCS::NormalText).color()},
0394         {"theme_unfocused_view_text_color_breeze", csc["disabled"]["view"].foreground(KCS::NormalText).color()},
0395         {"insensitive_unfocused_bg_color_breeze", csc["disabled"]["window"].background(KCS::NormalBackground).color()},
0396         {"theme_unfocused_view_bg_color_breeze", csc["disabled"]["view"].background(KCS::NormalBackground).color()},
0397         {"insensitive_unfocused_selected_bg_color_breeze", csc["disabled"]["selection"].background(KCS::NormalBackground).color()},
0398         {"insensitive_unfocused_selected_fg_color_breeze", csc["disabled"]["selection"].foreground(KCS::NormalText).color()},
0399 
0400         // Button
0401         {"theme_button_background_backdrop_insensitive_breeze", csc["disabled"]["button"].background(KCS::NormalBackground).color()},
0402         {"theme_button_decoration_hover_backdrop_insensitive_breeze", csc["disabled"]["button"].decoration(KCS::HoverColor).color()},
0403         {"theme_button_decoration_focus_backdrop_insensitive_breeze", csc["disabled"]["button"].decoration(KCS::FocusColor).color()},
0404         {"theme_button_foreground_backdrop_insensitive_breeze", csc["disabled"]["button"].foreground(KCS::NormalText).color()},
0405         {"theme_button_foreground_active_backdrop_insensitive_breeze", csc["disabled"]["selection"].foreground(KCS::NormalText).color()},
0406 
0407         // Misc Colors
0408         {"unfocused_insensitive_borders_breeze", unfocusedDisabledBordersColor},
0409         {"warning_color_insensitive_backdrop_breeze", csc["disabled"]["view"].foreground(KCS::NeutralText).color()},
0410         {"success_color_insensitive_backdrop_breeze", csc["disabled"]["view"].foreground(KCS::PositiveText).color()},
0411         {"error_color_insensitive_backdrop_breeze", csc["disabled"]["view"].foreground(KCS::NegativeText).color()},
0412 
0413         /*
0414          * Ignorant Colors (These colors do not care about backdrop or insensitive states)
0415          */
0416 
0417         {"link_color_breeze", csc["active"]["view"].foreground(KCS::LinkText).color()},
0418         {"link_visited_color_breeze", csc["active"]["view"].foreground(KCS::VisitedText).color()},
0419 
0420         {"tooltip_text_breeze", tooltipForegroundColor},
0421         {"tooltip_background_breeze", tooltipBackgroundColor},
0422         {"tooltip_border_breeze", tooltipBorderColor},
0423 
0424         {"content_view_bg_breeze", csc["active"]["view"].background(KCS::NormalBackground).color()},
0425 
0426     };
0427     // Handle Headers (menu bars and some of toolbars)
0428     if (KCS::isColorSetSupported(kdeglobalsConfig, KCS::Header)) {
0429         // If we have a separate Header color set, use it for both titlebar and header coloring...
0430         result.insert({{"theme_header_background_breeze", csc["active"]["header"].background().color()},
0431                        {"theme_header_foreground_breeze", csc["active"]["header"].foreground().color()},
0432                        {"theme_header_background_light_breeze", csc["active"]["window"].background().color()},
0433                        {"theme_header_foreground_backdrop_breeze", csc["inactive"]["header"].foreground().color()},
0434                        {"theme_header_background_backdrop_breeze", csc["inactive"]["header"].background().color()},
0435                        {"theme_header_foreground_insensitive_breeze", csc["inactive"]["header"].foreground().color()},
0436                        {"theme_header_foreground_insensitive_backdrop_breeze", csc["inactive"]["header"].foreground().color()},
0437 
0438                        {"theme_titlebar_background_breeze", csc["active"]["header"].background().color()},
0439                        {"theme_titlebar_foreground_breeze", csc["active"]["header"].foreground().color()},
0440                        {"theme_titlebar_background_light_breeze", csc["active"]["window"].background().color()},
0441                        {"theme_titlebar_foreground_backdrop_breeze", csc["inactive"]["header"].foreground().color()},
0442                        {"theme_titlebar_background_backdrop_breeze", csc["inactive"]["header"].background().color()},
0443                        {"theme_titlebar_foreground_insensitive_breeze", csc["inactive"]["header"].foreground().color()},
0444                        {"theme_titlebar_foreground_insensitive_backdrop_breeze", csc["inactive"]["header"].foreground().color()}});
0445     } else {
0446         //... if we don't we'll use regular window colors for headerbar and WM group for a titlebar
0447         result.insert({
0448             {"theme_header_background_breeze", csc["active"]["window"].background().color()},
0449             {"theme_header_foreground_breeze", csc["active"]["window"].foreground().color()},
0450             {"theme_header_background_light_breeze", csc["active"]["window"].background().color()},
0451             {"theme_header_foreground_backdrop_breeze", csc["inactive"]["window"].foreground().color()},
0452             {"theme_header_background_backdrop_breeze", csc["inactive"]["window"].background().color()},
0453             {"theme_header_foreground_insensitive_breeze", csc["inactive"]["window"].foreground().color()},
0454             {"theme_header_foreground_insensitive_backdrop_breeze", csc["inactive"]["window"].foreground().color()},
0455 
0456             {"theme_titlebar_background_breeze", windowManagerConfig.readEntry("activeBackground", QColor())},
0457             {"theme_titlebar_foreground_breeze", windowManagerConfig.readEntry("activeForeground", QColor())},
0458             {"theme_titlebar_background_light_breeze", csc["active"]["window"].background(KCS::NormalBackground).color()},
0459             {"theme_titlebar_foreground_backdrop_breeze", windowManagerConfig.readEntry("inactiveForeground", QColor())},
0460             {"theme_titlebar_background_backdrop_breeze", windowManagerConfig.readEntry("inactiveBackground", QColor())},
0461             {"theme_titlebar_foreground_insensitive_breeze", windowManagerConfig.readEntry("inactiveForeground", QColor())},
0462             {"theme_titlebar_foreground_insensitive_backdrop_breeze", windowManagerConfig.readEntry("inactiveForeground", QColor())},
0463         });
0464     }
0465 
0466     return result;
0467 }
0468 
0469 double ConfigValueProvider::x11GlobalScaleFactor() const
0470 {
0471     double scaleFactor;
0472 
0473     if (KWindowSystem::isPlatformX11()) {
0474         KConfigGroup configGroup = kdeglobalsConfig->group(QStringLiteral("KScreen"));
0475         scaleFactor = configGroup.readEntry(QStringLiteral("ScaleFactor"), 1.0);
0476     } else {
0477         KConfigGroup xwaylandGroup = kwinConfig->group(QStringLiteral("Xwayland"));
0478         scaleFactor = xwaylandGroup.readEntry(QStringLiteral("Scale"), 1.0);
0479     }
0480 
0481     return std::clamp(scaleFactor, 1.0, double(MAX_GDK_SCALE));
0482 }
0483 
0484 int ConfigValueProvider::fontDpi() const
0485 {
0486     KConfigGroup configGroup = fontsConfig->group(QStringLiteral("General"));
0487     int fontDpi = 0;
0488 
0489     if (KWindowSystem::isPlatformX11()) {
0490         fontDpi = configGroup.readEntry(QStringLiteral("forceFontDPI"), 0);
0491     } else {
0492         fontDpi = configGroup.readEntry(QStringLiteral("forceFontDPIWayland"), 0);
0493     }
0494 
0495     if (fontDpi <= 0) {
0496         return 0;
0497     }
0498 
0499     return std::clamp(fontDpi, MIN_FONT_DPI, MAX_FONT_DPI);
0500 }
0501 
0502 QString ConfigValueProvider::windowDecorationButtonsOrderInGtkNotation(const QString &kdeConfigValue) const
0503 {
0504     QString gtkNotation;
0505 
0506     for (const QChar &buttonAbbreviation : kdeConfigValue) {
0507         if (buttonAbbreviation == 'X') {
0508             gtkNotation += QStringLiteral("close,");
0509         } else if (buttonAbbreviation == 'I') {
0510             gtkNotation += QStringLiteral("minimize,");
0511         } else if (buttonAbbreviation == 'A') {
0512             gtkNotation += QStringLiteral("maximize,");
0513         } else if (buttonAbbreviation == 'M') {
0514             gtkNotation += QStringLiteral("icon,");
0515         }
0516     }
0517     gtkNotation.chop(1);
0518 
0519     return gtkNotation;
0520 }