File indexing completed on 2024-04-14 05:20:40
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 QString ConfigValueProvider::soundThemeName() const 0129 { 0130 KConfigGroup configGroup = kdeglobalsConfig->group(QStringLiteral("Sounds")); 0131 return configGroup.readEntry(QStringLiteral("Theme"), QStringLiteral("ocean")); 0132 } 0133 0134 bool ConfigValueProvider::eventSoundsEnabled() const 0135 { 0136 KConfigGroup configGroup = kdeglobalsConfig->group(QStringLiteral("Sounds")); 0137 return configGroup.readEntry(QStringLiteral("Enable"), true); 0138 } 0139 0140 int ConfigValueProvider::cursorSize() const 0141 { 0142 KConfigGroup configGroup = inputConfig->group(QStringLiteral("Mouse")); 0143 return configGroup.readEntry(QStringLiteral("cursorSize"), 24); 0144 } 0145 0146 bool ConfigValueProvider::iconsOnButtons() const 0147 { 0148 KConfigGroup configGroup = kdeglobalsConfig->group(QStringLiteral("KDE")); 0149 return configGroup.readEntry(QStringLiteral("ShowIconsOnPushButtons"), true); 0150 } 0151 0152 bool ConfigValueProvider::iconsInMenus() const 0153 { 0154 KConfigGroup configGroup = kdeglobalsConfig->group(QStringLiteral("KDE")); 0155 return configGroup.readEntry(QStringLiteral("ShowIconsInMenuItems"), true); 0156 } 0157 0158 int ConfigValueProvider::toolbarStyle() const 0159 { 0160 KConfigGroup configGroup = kdeglobalsConfig->group(QStringLiteral("Toolbar style")); 0161 QString kdeConfigValue = configGroup.readEntry(QStringLiteral("ToolButtonStyle"), "TextBesideIcon"); 0162 0163 if (kdeConfigValue == QStringLiteral("NoText")) { 0164 return GtkToolbarStyle::GTK_TOOLBAR_ICONS; 0165 } else if (kdeConfigValue == QStringLiteral("TextOnly")) { 0166 return GtkToolbarStyle::GTK_TOOLBAR_TEXT; 0167 } else if (kdeConfigValue == QStringLiteral("TextBesideIcon")) { 0168 return GtkToolbarStyle::GTK_TOOLBAR_BOTH_HORIZ; 0169 } else { 0170 return GtkToolbarStyle::GTK_TOOLBAR_BOTH; 0171 } 0172 } 0173 0174 bool ConfigValueProvider::scrollbarBehavior() const 0175 { 0176 KConfigGroup configGroup = kdeglobalsConfig->group(QStringLiteral("KDE")); 0177 bool kdeConfigValue = configGroup.readEntry(QStringLiteral("ScrollbarLeftClickNavigatesByPage"), false); 0178 return !kdeConfigValue; // GTK setting is inverted 0179 } 0180 0181 bool ConfigValueProvider::preferDarkTheme() const 0182 { 0183 KConfigGroup colorsConfigGroup = kdeglobalsConfig->group(QStringLiteral("Colors:Window")); 0184 QColor windowBackgroundColor = colorsConfigGroup.readEntry(QStringLiteral("BackgroundNormal"), QColor(239, 240, 241)); 0185 const int windowBackgroundGray = qGray(windowBackgroundColor.rgb()); 0186 0187 // We use heuristic to determine if current color scheme is dark or not 0188 return windowBackgroundGray < 192; 0189 } 0190 0191 QStringList ConfigValueProvider::windowDecorationsButtonsImages() const 0192 { 0193 static const QList<QString> buttonTypes{ 0194 QStringLiteral("close"), 0195 QStringLiteral("maximize"), 0196 QStringLiteral("maximized"), 0197 QStringLiteral("minimize"), 0198 }; 0199 0200 static const QList<QString> buttonStates{ 0201 // Focused titlebars 0202 QStringLiteral("normal"), 0203 QStringLiteral("active"), // aka pressed 0204 QStringLiteral("hover"), 0205 // Unfocused titlebars 0206 QStringLiteral("backdrop-normal"), 0207 QStringLiteral("backdrop-active"), 0208 QStringLiteral("backdrop-hover"), 0209 }; 0210 0211 KConfigGroup decorationGroup = kwinConfig->group(QStringLiteral("org.kde.kdecoration2")); 0212 const QString themeName = decorationGroup.readEntry(QStringLiteral("theme"), QStringLiteral("Breeze")); 0213 0214 auto decorationPainter = DecorationPainter::fromThemeName(themeName); 0215 QStringList decorationsImages{}; 0216 0217 for (const auto &buttonType : buttonTypes) { 0218 for (const auto &buttonState : buttonStates) { 0219 QSvgGenerator svgGenerator{}; 0220 0221 QString filePath = generatedCSDTempPath.filePath(QStringLiteral("%1-%2.svg").arg(buttonType, buttonState)); 0222 0223 svgGenerator.setFileName(filePath); 0224 svgGenerator.setViewBox(DecorationPainter::ButtonGeometry); 0225 0226 QPainter painter{&svgGenerator}; 0227 decorationPainter->paintButton(painter, buttonType, buttonState); 0228 painter.end(); 0229 0230 decorationsImages.append(filePath); 0231 } 0232 } 0233 0234 return decorationsImages; 0235 } 0236 0237 QString ConfigValueProvider::windowDecorationsButtonsOrder() const 0238 { 0239 KConfigGroup configGroup = kwinConfig->group(QStringLiteral("org.kde.kdecoration2")); 0240 QString buttonsOnLeftKdeConfigValue = configGroup.readEntry(QStringLiteral("ButtonsOnLeft"), "MS"); 0241 QString buttonsOnRightKdeConfigValue = configGroup.readEntry(QStringLiteral("ButtonsOnRight"), "HIAX"); 0242 0243 QString buttonsOnLeftInGtkNotation = windowDecorationButtonsOrderInGtkNotation(buttonsOnLeftKdeConfigValue); 0244 QString buttonsOnRightInGtkNotation = windowDecorationButtonsOrderInGtkNotation(buttonsOnRightKdeConfigValue); 0245 0246 return buttonsOnLeftInGtkNotation + QStringLiteral(":") + buttonsOnRightInGtkNotation; 0247 } 0248 0249 bool ConfigValueProvider::enableAnimations() const 0250 { 0251 KConfigGroup generalCfg = kdeglobalsConfig->group(QStringLiteral("KDE")); 0252 const qreal animationSpeedModifier = qMax(0.0, generalCfg.readEntry("AnimationDurationFactor", 1.0)); 0253 0254 return !qFuzzyIsNull(animationSpeedModifier); 0255 } 0256 0257 int ConfigValueProvider::doubleClickInterval() const 0258 { 0259 KConfigGroup generalCfg = kdeglobalsConfig->group("KDE"); 0260 return generalCfg.readEntry("DoubleClickInterval", 400); 0261 } 0262 0263 QMap<QString, QColor> ConfigValueProvider::colors() const 0264 { 0265 using KCS = KColorScheme; 0266 0267 // Color Schemes Collection 0268 QHash<QString, QHash<QString, KCS>> csc{ 0269 {QStringLiteral("active"), 0270 { 0271 {QStringLiteral("view"), KCS(QPalette::Active, KCS::View)}, 0272 {QStringLiteral("window"), KCS(QPalette::Active, KCS::Window)}, 0273 {QStringLiteral("button"), KCS(QPalette::Active, KCS::Button)}, 0274 {QStringLiteral("selection"), KCS(QPalette::Active, KCS::Selection)}, 0275 {QStringLiteral("tooltip"), KCS(QPalette::Active, KCS::Tooltip)}, 0276 {QStringLiteral("complementary"), KCS(QPalette::Active, KCS::Complementary)}, 0277 {QStringLiteral("header"), KCS(QPalette::Active, KCS::Header)}, 0278 }}, 0279 {QStringLiteral("inactive"), 0280 { 0281 {QStringLiteral("view"), KCS(QPalette::Inactive, KCS::View)}, 0282 {QStringLiteral("window"), KCS(QPalette::Inactive, KCS::Window)}, 0283 {QStringLiteral("button"), KCS(QPalette::Inactive, KCS::Button)}, 0284 {QStringLiteral("selection"), KCS(QPalette::Inactive, KCS::Selection)}, 0285 {QStringLiteral("tooltip"), KCS(QPalette::Inactive, KCS::Tooltip)}, 0286 {QStringLiteral("complementary"), KCS(QPalette::Inactive, KCS::Complementary)}, 0287 {QStringLiteral("header"), KCS(QPalette::Inactive, KCS::Header)}, 0288 }}, 0289 {QStringLiteral("disabled"), 0290 { 0291 {QStringLiteral("view"), KCS(QPalette::Disabled, KCS::View)}, 0292 {QStringLiteral("window"), KCS(QPalette::Disabled, KCS::Window)}, 0293 {QStringLiteral("button"), KCS(QPalette::Disabled, KCS::Button)}, 0294 {QStringLiteral("selection"), KCS(QPalette::Disabled, KCS::Selection)}, 0295 {QStringLiteral("tooltip"), KCS(QPalette::Disabled, KCS::Tooltip)}, 0296 {QStringLiteral("complementary"), KCS(QPalette::Disabled, KCS::Complementary)}, 0297 {QStringLiteral("header"), KCS(QPalette::Disabled, KCS::Header)}, 0298 }}, 0299 }; 0300 0301 // Color mixing 0302 QColor windowForegroundColor = csc["active"]["window"].foreground(KCS::NormalText).color(); 0303 QColor windowBackgroundColor = csc["active"]["window"].background(KCS::NormalBackground).color(); 0304 QColor bordersColor = KColorUtils::mix(windowBackgroundColor, windowForegroundColor, 0.25); 0305 0306 QColor inactiveWindowForegroundColor = csc["inactive"]["window"].foreground(KCS::NormalText).color(); 0307 QColor inactiveWindowBackgroundColor = csc["inactive"]["window"].background(KCS::NormalBackground).color(); 0308 QColor inactiveBordersColor = KColorUtils::mix(inactiveWindowBackgroundColor, inactiveWindowForegroundColor, 0.25); 0309 0310 QColor disabledWindowForegroundColor = csc["disabled"]["window"].foreground(KCS::NormalText).color(); 0311 QColor disabledWindowBackgroundColor = csc["disabled"]["window"].background(KCS::NormalBackground).color(); 0312 QColor disabledBordersColor = KColorUtils::mix(disabledWindowBackgroundColor, disabledWindowForegroundColor, 0.25); 0313 0314 QColor unfocusedDisabledWindowForegroundColor = csc["disabled"]["window"].foreground(KCS::NormalText).color(); 0315 QColor unfocusedDisabledWindowBackgroundColor = csc["disabled"]["window"].background(KCS::NormalBackground).color(); 0316 QColor unfocusedDisabledBordersColor = KColorUtils::mix(unfocusedDisabledWindowBackgroundColor, unfocusedDisabledWindowForegroundColor, 0.25); 0317 0318 QColor tooltipForegroundColor = csc["active"]["tooltip"].foreground(KCS::NormalText).color(); 0319 QColor tooltipBackgroundColor = csc["active"]["tooltip"].background(KCS::NormalBackground).color(); 0320 QColor tooltipBorderColor = KColorUtils::mix(tooltipBackgroundColor, tooltipForegroundColor, 0.25); 0321 0322 KConfigGroup windowManagerConfig = kdeglobalsConfig->group(QStringLiteral("WM")); 0323 0324 QMap<QString, QColor> result = { 0325 /* 0326 * Normal (Non Backdrop, Non Insensitive) 0327 */ 0328 0329 // General Colors 0330 {"theme_fg_color_breeze", csc["active"]["window"].foreground(KCS::NormalText).color()}, 0331 {"theme_bg_color_breeze", csc["active"]["window"].background(KCS::NormalBackground).color()}, 0332 {"theme_text_color_breeze", csc["active"]["view"].foreground(KCS::NormalText).color()}, 0333 {"theme_base_color_breeze", csc["active"]["view"].background(KCS::NormalBackground).color()}, 0334 {"theme_view_hover_decoration_color_breeze", csc["active"]["view"].decoration(KCS::HoverColor).color()}, 0335 {"theme_hovering_selected_bg_color_breeze", csc["active"]["selection"].decoration(KCS::HoverColor).color()}, 0336 {"theme_selected_bg_color_breeze", csc["active"]["selection"].background(KCS::NormalBackground).color()}, 0337 {"theme_selected_fg_color_breeze", csc["active"]["selection"].foreground(KCS::NormalText).color()}, 0338 {"theme_view_active_decoration_color_breeze", csc["active"]["view"].decoration(KCS::HoverColor).color()}, 0339 0340 // Button Colors 0341 {"theme_button_background_normal_breeze", csc["active"]["button"].background(KCS::NormalBackground).color()}, 0342 {"theme_button_decoration_hover_breeze", csc["active"]["button"].decoration(KCS::HoverColor).color()}, 0343 {"theme_button_decoration_focus_breeze", csc["active"]["button"].decoration(KCS::FocusColor).color()}, 0344 {"theme_button_foreground_normal_breeze", csc["active"]["button"].foreground(KCS::NormalText).color()}, 0345 {"theme_button_foreground_active_breeze", csc["active"]["selection"].foreground(KCS::NormalText).color()}, 0346 0347 // Misc Colors 0348 {"borders_breeze", bordersColor}, 0349 {"warning_color_breeze", csc["active"]["view"].foreground(KCS::NeutralText).color()}, 0350 {"success_color_breeze", csc["active"]["view"].foreground(KCS::PositiveText).color()}, 0351 {"error_color_breeze", csc["active"]["view"].foreground(KCS::NegativeText).color()}, 0352 0353 /* 0354 * Backdrop (Inactive) 0355 */ 0356 0357 // General 0358 {"theme_unfocused_fg_color_breeze", csc["inactive"]["window"].foreground(KCS::NormalText).color()}, 0359 {"theme_unfocused_text_color_breeze", csc["inactive"]["view"].foreground(KCS::NormalText).color()}, 0360 {"theme_unfocused_bg_color_breeze", csc["inactive"]["window"].background(KCS::NormalBackground).color()}, 0361 {"theme_unfocused_base_color_breeze", csc["inactive"]["view"].background(KCS::NormalBackground).color()}, 0362 {"theme_unfocused_selected_bg_color_alt_breeze", csc["inactive"]["selection"].background(KCS::NormalBackground).color()}, 0363 {"theme_unfocused_selected_bg_color_breeze", csc["inactive"]["selection"].background(KCS::NormalBackground).color()}, 0364 {"theme_unfocused_selected_fg_color_breeze", csc["inactive"]["selection"].foreground(KCS::NormalText).color()}, 0365 0366 // Button 0367 {"theme_button_background_backdrop_breeze", csc["inactive"]["button"].background(KCS::NormalBackground).color()}, 0368 {"theme_button_decoration_hover_backdrop_breeze", csc["inactive"]["button"].decoration(KCS::HoverColor).color()}, 0369 {"theme_button_decoration_focus_backdrop_breeze", csc["inactive"]["button"].decoration(KCS::FocusColor).color()}, 0370 {"theme_button_foreground_backdrop_breeze", csc["inactive"]["button"].foreground(KCS::NormalText).color()}, 0371 {"theme_button_foreground_active_backdrop_breeze", csc["inactive"]["selection"].foreground(KCS::NormalText).color()}, 0372 0373 // Misc Colors 0374 {"unfocused_borders_breeze", inactiveBordersColor}, 0375 {"warning_color_backdrop_breeze", csc["inactive"]["view"].foreground(KCS::NeutralText).color()}, 0376 {"success_color_backdrop_breeze", csc["inactive"]["view"].foreground(KCS::PositiveText).color()}, 0377 {"error_color_backdrop_breeze", csc["inactive"]["view"].foreground(KCS::NegativeText).color()}, 0378 0379 /* 0380 * Insensitive (Disabled) 0381 */ 0382 0383 // General 0384 {"insensitive_fg_color_breeze", csc["disabled"]["window"].foreground(KCS::NormalText).color()}, 0385 {"insensitive_base_fg_color_breeze", csc["disabled"]["view"].foreground(KCS::NormalText).color()}, 0386 {"insensitive_bg_color_breeze", csc["disabled"]["window"].background(KCS::NormalBackground).color()}, 0387 {"insensitive_base_color_breeze", csc["disabled"]["view"].background(KCS::NormalBackground).color()}, 0388 {"insensitive_selected_bg_color_breeze", csc["disabled"]["selection"].background(KCS::NormalBackground).color()}, 0389 {"insensitive_selected_fg_color_breeze", csc["disabled"]["selection"].foreground(KCS::NormalText).color()}, 0390 0391 // Button 0392 {"theme_button_background_insensitive_breeze", csc["disabled"]["button"].background(KCS::NormalBackground).color()}, 0393 {"theme_button_decoration_hover_insensitive_breeze", csc["disabled"]["button"].decoration(KCS::HoverColor).color()}, 0394 {"theme_button_decoration_focus_insensitive_breeze", csc["disabled"]["button"].decoration(KCS::FocusColor).color()}, 0395 {"theme_button_foreground_insensitive_breeze", csc["disabled"]["button"].foreground(KCS::NormalText).color()}, 0396 {"theme_button_foreground_active_insensitive_breeze", csc["disabled"]["selection"].foreground(KCS::NormalText).color()}, 0397 0398 // Misc Colors 0399 {"insensitive_borders_breeze", disabledBordersColor}, 0400 {"warning_color_insensitive_breeze", csc["disabled"]["view"].foreground(KCS::NeutralText).color()}, 0401 {"success_color_insensitive_breeze", csc["disabled"]["view"].foreground(KCS::PositiveText).color()}, 0402 {"error_color_insensitive_breeze", csc["disabled"]["view"].foreground(KCS::NegativeText).color()}, 0403 0404 /* 0405 * Insensitive Backdrop (Inactive Disabled) 0406 * These pretty much have the same appearance as regular inactive colors, 0407 * but they're separate in case we decide to make them different in the future. 0408 */ 0409 0410 // General 0411 {"insensitive_unfocused_fg_color_breeze", csc["disabled"]["window"].foreground(KCS::NormalText).color()}, 0412 {"theme_unfocused_view_text_color_breeze", csc["disabled"]["view"].foreground(KCS::NormalText).color()}, 0413 {"insensitive_unfocused_bg_color_breeze", csc["disabled"]["window"].background(KCS::NormalBackground).color()}, 0414 {"theme_unfocused_view_bg_color_breeze", csc["disabled"]["view"].background(KCS::NormalBackground).color()}, 0415 {"insensitive_unfocused_selected_bg_color_breeze", csc["disabled"]["selection"].background(KCS::NormalBackground).color()}, 0416 {"insensitive_unfocused_selected_fg_color_breeze", csc["disabled"]["selection"].foreground(KCS::NormalText).color()}, 0417 0418 // Button 0419 {"theme_button_background_backdrop_insensitive_breeze", csc["disabled"]["button"].background(KCS::NormalBackground).color()}, 0420 {"theme_button_decoration_hover_backdrop_insensitive_breeze", csc["disabled"]["button"].decoration(KCS::HoverColor).color()}, 0421 {"theme_button_decoration_focus_backdrop_insensitive_breeze", csc["disabled"]["button"].decoration(KCS::FocusColor).color()}, 0422 {"theme_button_foreground_backdrop_insensitive_breeze", csc["disabled"]["button"].foreground(KCS::NormalText).color()}, 0423 {"theme_button_foreground_active_backdrop_insensitive_breeze", csc["disabled"]["selection"].foreground(KCS::NormalText).color()}, 0424 0425 // Misc Colors 0426 {"unfocused_insensitive_borders_breeze", unfocusedDisabledBordersColor}, 0427 {"warning_color_insensitive_backdrop_breeze", csc["disabled"]["view"].foreground(KCS::NeutralText).color()}, 0428 {"success_color_insensitive_backdrop_breeze", csc["disabled"]["view"].foreground(KCS::PositiveText).color()}, 0429 {"error_color_insensitive_backdrop_breeze", csc["disabled"]["view"].foreground(KCS::NegativeText).color()}, 0430 0431 /* 0432 * Ignorant Colors (These colors do not care about backdrop or insensitive states) 0433 */ 0434 0435 {"link_color_breeze", csc["active"]["view"].foreground(KCS::LinkText).color()}, 0436 {"link_visited_color_breeze", csc["active"]["view"].foreground(KCS::VisitedText).color()}, 0437 0438 {"tooltip_text_breeze", tooltipForegroundColor}, 0439 {"tooltip_background_breeze", tooltipBackgroundColor}, 0440 {"tooltip_border_breeze", tooltipBorderColor}, 0441 0442 {"content_view_bg_breeze", csc["active"]["view"].background(KCS::NormalBackground).color()}, 0443 0444 }; 0445 // Handle Headers (menu bars and some of toolbars) 0446 if (KCS::isColorSetSupported(kdeglobalsConfig, KCS::Header)) { 0447 // If we have a separate Header color set, use it for both titlebar and header coloring... 0448 result.insert({{"theme_header_background_breeze", csc["active"]["header"].background().color()}, 0449 {"theme_header_foreground_breeze", csc["active"]["header"].foreground().color()}, 0450 {"theme_header_background_light_breeze", csc["active"]["window"].background().color()}, 0451 {"theme_header_foreground_backdrop_breeze", csc["inactive"]["header"].foreground().color()}, 0452 {"theme_header_background_backdrop_breeze", csc["inactive"]["header"].background().color()}, 0453 {"theme_header_foreground_insensitive_breeze", csc["inactive"]["header"].foreground().color()}, 0454 {"theme_header_foreground_insensitive_backdrop_breeze", csc["inactive"]["header"].foreground().color()}, 0455 0456 {"theme_titlebar_background_breeze", csc["active"]["header"].background().color()}, 0457 {"theme_titlebar_foreground_breeze", csc["active"]["header"].foreground().color()}, 0458 {"theme_titlebar_background_light_breeze", csc["active"]["window"].background().color()}, 0459 {"theme_titlebar_foreground_backdrop_breeze", csc["inactive"]["header"].foreground().color()}, 0460 {"theme_titlebar_background_backdrop_breeze", csc["inactive"]["header"].background().color()}, 0461 {"theme_titlebar_foreground_insensitive_breeze", csc["inactive"]["header"].foreground().color()}, 0462 {"theme_titlebar_foreground_insensitive_backdrop_breeze", csc["inactive"]["header"].foreground().color()}}); 0463 } else { 0464 //... if we don't we'll use regular window colors for headerbar and WM group for a titlebar 0465 result.insert({ 0466 {"theme_header_background_breeze", csc["active"]["window"].background().color()}, 0467 {"theme_header_foreground_breeze", csc["active"]["window"].foreground().color()}, 0468 {"theme_header_background_light_breeze", csc["active"]["window"].background().color()}, 0469 {"theme_header_foreground_backdrop_breeze", csc["inactive"]["window"].foreground().color()}, 0470 {"theme_header_background_backdrop_breeze", csc["inactive"]["window"].background().color()}, 0471 {"theme_header_foreground_insensitive_breeze", csc["inactive"]["window"].foreground().color()}, 0472 {"theme_header_foreground_insensitive_backdrop_breeze", csc["inactive"]["window"].foreground().color()}, 0473 0474 {"theme_titlebar_background_breeze", windowManagerConfig.readEntry("activeBackground", QColor())}, 0475 {"theme_titlebar_foreground_breeze", windowManagerConfig.readEntry("activeForeground", QColor())}, 0476 {"theme_titlebar_background_light_breeze", csc["active"]["window"].background(KCS::NormalBackground).color()}, 0477 {"theme_titlebar_foreground_backdrop_breeze", windowManagerConfig.readEntry("inactiveForeground", QColor())}, 0478 {"theme_titlebar_background_backdrop_breeze", windowManagerConfig.readEntry("inactiveBackground", QColor())}, 0479 {"theme_titlebar_foreground_insensitive_breeze", windowManagerConfig.readEntry("inactiveForeground", QColor())}, 0480 {"theme_titlebar_foreground_insensitive_backdrop_breeze", windowManagerConfig.readEntry("inactiveForeground", QColor())}, 0481 }); 0482 } 0483 0484 return result; 0485 } 0486 0487 double ConfigValueProvider::x11GlobalScaleFactor() const 0488 { 0489 double scaleFactor; 0490 0491 if (KWindowSystem::isPlatformX11()) { 0492 KConfigGroup configGroup = kdeglobalsConfig->group(QStringLiteral("KScreen")); 0493 scaleFactor = configGroup.readEntry(QStringLiteral("ScaleFactor"), 1.0); 0494 } else { 0495 KConfigGroup xwaylandGroup = kwinConfig->group(QStringLiteral("Xwayland")); 0496 scaleFactor = xwaylandGroup.readEntry(QStringLiteral("Scale"), 1.0); 0497 } 0498 0499 return std::clamp(scaleFactor, 1.0, double(MAX_GDK_SCALE)); 0500 } 0501 0502 int ConfigValueProvider::fontDpi() const 0503 { 0504 KConfigGroup configGroup = fontsConfig->group(QStringLiteral("General")); 0505 int fontDpi = 96; // On wayland we want to enforce a scale of one for the fonts as we'll use wayland scaling 0506 0507 if (KWindowSystem::isPlatformX11()) { 0508 fontDpi = configGroup.readEntry(QStringLiteral("forceFontDPI"), 0); 0509 } 0510 0511 if (fontDpi <= 0) { 0512 return 0; 0513 } 0514 0515 return std::clamp(fontDpi, MIN_FONT_DPI, MAX_FONT_DPI); 0516 } 0517 0518 QString ConfigValueProvider::windowDecorationButtonsOrderInGtkNotation(const QString &kdeConfigValue) const 0519 { 0520 QString gtkNotation; 0521 0522 for (const QChar &buttonAbbreviation : kdeConfigValue) { 0523 if (buttonAbbreviation == 'X') { 0524 gtkNotation += QStringLiteral("close,"); 0525 } else if (buttonAbbreviation == 'I') { 0526 gtkNotation += QStringLiteral("minimize,"); 0527 } else if (buttonAbbreviation == 'A') { 0528 gtkNotation += QStringLiteral("maximize,"); 0529 } else if (buttonAbbreviation == 'M') { 0530 gtkNotation += QStringLiteral("icon,"); 0531 } 0532 } 0533 gtkNotation.chop(1); 0534 0535 return gtkNotation; 0536 }