diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,8 @@ find_package(Qt5 REQUIRED NO_MODULE COMPONENTS DBus) find_package(KF5CoreAddons REQUIRED) find_package(KF5Config REQUIRED) +find_package(KF5ConfigWidgets REQUIRED) +find_package(KF5GuiAddons REQUIRED) find_package(KF5IconThemes REQUIRED) find_package(KF5DBusAddons REQUIRED) find_package(PkgConfig REQUIRED) diff --git a/kconf_update/CMakeLists.txt b/kconf_update/CMakeLists.txt --- a/kconf_update/CMakeLists.txt +++ b/kconf_update/CMakeLists.txt @@ -9,6 +9,8 @@ PRIVATE Qt5::Core KF5::ConfigCore + KF5::ConfigWidgets + KF5::GuiAddons PkgConfig::GIO PkgConfig::GObject ) diff --git a/kded/CMakeLists.txt b/kded/CMakeLists.txt --- a/kded/CMakeLists.txt +++ b/kded/CMakeLists.txt @@ -19,12 +19,15 @@ ) target_link_libraries(gtkconfig + PUBLIC Qt5::DBus KF5::CoreAddons KF5::ConfigCore + KF5::ConfigWidgets KF5::DBusAddons KF5::IconThemes PkgConfig::GTK+3 + KF5::GuiAddons PkgConfig::GIO PkgConfig::GObject ) diff --git a/kded/configeditor.h b/kded/configeditor.h --- a/kded/configeditor.h +++ b/kded/configeditor.h @@ -22,6 +22,7 @@ #include #include +class QColor; class QFile; class QVariant; @@ -34,11 +35,17 @@ void setGtk3ConfigValueSettingsIni(const QString ¶mName, const QVariant ¶mValue); void setGtk3ConfigValueXSettingsd(const QString ¶mName, const QVariant ¶mValue); + void setGtk3Colors(const QMap &colorsDefinitions); + QString gtk2ConfigValue(const QString& paramName); QString gtk3ConfigValueSettingsIni(const QString& paramName); void removeLegacyGtk2Strings(); + void addGtkModule(const QString &moduleName); + + void addImportStatementToGtkCssUserFile(); + void modifyColorsCssFile(const QMap &colorsDefinitions); void replaceValueInGtkrcContents(QString >krcContents, const QString ¶mName, const QVariant ¶mValue); void replaceValueInXSettingsdContents(QString &xSettingsdContents, const QString ¶mName, const QVariant ¶mValue); diff --git a/kded/configeditor.cpp b/kded/configeditor.cpp --- a/kded/configeditor.cpp +++ b/kded/configeditor.cpp @@ -18,15 +18,20 @@ * along with this program. If not, see . */ -#include +#include #include #include #include #include #include +#include +#include +#include #include #include +#include +#include #include #include @@ -102,6 +107,14 @@ reloadGtk2Apps(); } +void ConfigEditor::setGtk3Colors(const QMap &colorsDefinitions) +{ + addImportStatementToGtkCssUserFile(); + modifyColorsCssFile(colorsDefinitions); + addGtkModule(QStringLiteral("colorreload-gtk-module")); +} + + QString ConfigEditor::gtk2ConfigValue(const QString& paramName) { QString gtkrcPath = QDir::homePath() + QStringLiteral("/.gtkrc-2.0"); @@ -159,6 +172,51 @@ reloadGtk2Apps(); } +void ConfigEditor::addGtkModule(const QString& moduleName) +{ + const QString currentModulesString = gtk3ConfigValueSettingsIni(QStringLiteral("gtk-modules")); + + if (currentModulesString.contains(moduleName)) { + return; + } + + if (currentModulesString.isEmpty()) { // No modules + setGtk3ConfigValueSettingsIni(QStringLiteral("gtk-modules"), moduleName); + } else { + setGtk3ConfigValueSettingsIni(QStringLiteral("gtk-modules"), QStringLiteral("%1:%2").arg(currentModulesString, moduleName)); + } +} + +void ConfigEditor::addImportStatementToGtkCssUserFile() +{ + QString gtkCssPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QStringLiteral("/gtk-3.0/gtk.css"); + QFile gtkCss(gtkCssPath); + + if (gtkCss.open(QIODevice::ReadWrite)) { + QByteArray gtkCssContents = gtkCss.readAll(); + + static const QByteArray importStatement = QByteArrayLiteral("@import 'colors.css';"); + if (!gtkCssContents.contains(importStatement)) { + QTextStream gtkCssStream(>kCss); + gtkCssStream << importStatement; + } + } +} + +void ConfigEditor::modifyColorsCssFile(const QMap &colorsDefinitions) +{ + QString colorsCssPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation) + QStringLiteral("/gtk-3.0/colors.css"); + QFile colorsCss(colorsCssPath); + + if (colorsCss.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + QTextStream colorsCssStream(&colorsCss); + + for (auto it = colorsDefinitions.cbegin(); it != colorsDefinitions.cend(); it++) { + colorsCssStream << QStringLiteral("@define-color %1 %2;\n").arg(it.key(), it.value().name()); + } + } +} + QString ConfigEditor::readFileContents(QFile &file) { if (file.open(QIODevice::ReadWrite | QIODevice::Text)) { diff --git a/kded/configvalueprovider.h b/kded/configvalueprovider.h --- a/kded/configvalueprovider.h +++ b/kded/configvalueprovider.h @@ -40,6 +40,7 @@ bool preferDarkTheme() const; QString windowDecorationsButtonsOrder() const; bool enableAnimations() const; + QMap colors() const; private: QString fontStyleHelper(const QFont &font) const; diff --git a/kded/configvalueprovider.cpp b/kded/configvalueprovider.cpp --- a/kded/configvalueprovider.cpp +++ b/kded/configvalueprovider.cpp @@ -21,11 +21,15 @@ #include #include #include +#include +#include #include #include #include #include +#include +#include #include @@ -190,6 +194,201 @@ return !qFuzzyIsNull(animationSpeedModifier); } +QMap ConfigValueProvider::colors() const +{ + using KCS = KColorScheme; + + // Color Schemes Collection + QHash> csc { + {QStringLiteral("active"), { + {QStringLiteral("view"), KCS(QPalette::Active, KCS::View)}, + {QStringLiteral("window"), KCS(QPalette::Active, KCS::Window)}, + {QStringLiteral("button"), KCS(QPalette::Active, KCS::Button)}, + {QStringLiteral("selection"), KCS(QPalette::Active, KCS::Selection)}, + {QStringLiteral("tooltip"), KCS(QPalette::Active, KCS::Tooltip)}, + {QStringLiteral("complementary"), KCS(QPalette::Active, KCS::Complementary)}, + }}, + {QStringLiteral("inactive"), { + {QStringLiteral("view"), KCS(QPalette::Inactive, KCS::View)}, + {QStringLiteral("window"), KCS(QPalette::Inactive, KCS::Window)}, + {QStringLiteral("button"), KCS(QPalette::Inactive, KCS::Button)}, + {QStringLiteral("selection"), KCS(QPalette::Inactive, KCS::Selection)}, + {QStringLiteral("tooltip"), KCS(QPalette::Inactive, KCS::Tooltip)}, + {QStringLiteral("complementary"), KCS(QPalette::Inactive, KCS::Complementary)}, + }}, + {QStringLiteral("inactive"), { + {QStringLiteral("view"), KCS(QPalette::Disabled, KCS::View)}, + {QStringLiteral("window"), KCS(QPalette::Disabled, KCS::Window)}, + {QStringLiteral("button"), KCS(QPalette::Disabled, KCS::Button)}, + {QStringLiteral("selection"), KCS(QPalette::Disabled, KCS::Selection)}, + {QStringLiteral("tooltip"), KCS(QPalette::Disabled, KCS::Tooltip)}, + {QStringLiteral("complementary"), KCS(QPalette::Disabled, KCS::Complementary)}, + }}, + }; + + // Color mixing + QColor windowForegroundColor = csc["active"]["window"].foreground(KCS::NormalText).color(); + QColor windowBackgroundColor = csc["active"]["window"].background(KCS::NormalBackground).color(); + QColor bordersColor = KColorUtils::mix(windowBackgroundColor, windowForegroundColor, 0.25); + + QColor inactiveWindowForegroundColor = csc["inactive"]["window"].foreground(KCS::NormalText).color(); + QColor inactiveWindowBackgroundColor = csc["inactive"]["window"].background(KCS::NormalBackground).color(); + QColor inactiveBordersColor = KColorUtils::mix(inactiveWindowBackgroundColor, inactiveWindowForegroundColor, 0.25); + + QColor disabledWindowForegroundColor = csc["disabled"]["window"].foreground(KCS::NormalText).color(); + QColor disabledWindowBackgroundColor = csc["disabled"]["window"].background(KCS::NormalBackground).color(); + QColor disabledBordersColor = KColorUtils::mix(disabledWindowBackgroundColor, disabledWindowForegroundColor, 0.25); + + QColor unfocusedDisabledWindowForegroundColor = csc["disabled"]["window"].foreground(KCS::NormalText).color(); + QColor unfocusedDisabledWindowBackgroundColor = csc["disabled"]["window"].background(KCS::NormalBackground).color(); + QColor unfocusedDisabledBordersColor = KColorUtils::mix(unfocusedDisabledWindowBackgroundColor, unfocusedDisabledWindowForegroundColor, 0.25); + + QColor tooltipForegroundColor = csc["active"]["tooltip"].foreground(KCS::NormalText).color(); + QColor tooltipBackgroundColor = csc["active"]["tooltip"].background(KCS::NormalBackground).color(); + QColor tooltipBorderColor = KColorUtils::mix(tooltipBackgroundColor, tooltipForegroundColor, 0.25); + + KConfigGroup windowManagerConfig = kdeglobalsConfig->group(QStringLiteral("WM")); + + return { + /* + * Normal (Non Backdrop, Non Insensitive) + */ + + // General Colors + { "theme_fg_color_breeze", csc["active"]["window"].foreground(KCS::NormalText).color()}, + { "theme_bg_color_breeze", csc["active"]["window"].background(KCS::NormalBackground).color()}, + { "theme_text_color_breeze", csc["active"]["view"].foreground(KCS::NormalText).color()}, + { "theme_base_color_breeze", csc["active"]["view"].background(KCS::NormalBackground).color()}, + { "theme_view_hover_decoration_color_breeze", csc["active"]["view"].decoration(KCS::HoverColor).color()}, + { "theme_hovering_selected_bg_color_breeze", csc["active"]["selection"].decoration(KCS::HoverColor).color()}, + { "theme_selected_bg_color_breeze", csc["active"]["selection"].background(KCS::NormalBackground).color()}, + { "theme_selected_fg_color_breeze", csc["active"]["selection"].foreground(KCS::NormalText).color()}, + { "theme_view_active_decoration_color_breeze", csc["active"]["view"].decoration(KCS::HoverColor).color()}, + + // Button Colors + { "theme_button_background_normal_breeze", csc["active"]["button"].background(KCS::NormalBackground).color()}, + { "theme_button_decoration_hover_breeze", csc["active"]["button"].decoration(KCS::HoverColor).color()}, + { "theme_button_decoration_focus_breeze", csc["active"]["button"].decoration(KCS::FocusColor).color()}, + { "theme_button_foreground_normal_breeze", csc["active"]["button"].foreground(KCS::NormalText).color()}, + { "theme_button_foreground_active_breeze", csc["active"]["selection"].foreground(KCS::NormalText).color()}, + + + // Misc Colors + { "borders_breeze", bordersColor}, + { "warning_color_breeze", csc["active"]["view"].foreground(KCS::NeutralText).color()}, + { "success_color_breeze", csc["active"]["view"].foreground(KCS::PositiveText).color()}, + { "error_color_breeze", csc["active"]["view"].foreground(KCS::NegativeText).color()}, + + /* + * Backdrop (Inactive) + */ + + // General + { "theme_unfocused_fg_color_breeze", csc["inactive"]["window"].foreground(KCS::NormalText).color()}, + { "theme_unfocused_text_color_breeze", csc["inactive"]["view"].foreground(KCS::NormalText).color()}, + { "theme_unfocused_bg_color_breeze", csc["inactive"]["window"].background(KCS::NormalBackground).color()}, + { "theme_unfocused_base_color_breeze", csc["inactive"]["view"].background(KCS::NormalBackground).color()}, + { "theme_unfocused_selected_bg_color_alt_breeze", csc["inactive"]["selection"].background(KCS::NormalBackground).color()}, + { "theme_unfocused_selected_bg_color_breeze", csc["inactive"]["selection"].background(KCS::NormalBackground).color()}, + { "theme_unfocused_selected_fg_color_breeze", csc["inactive"]["selection"].foreground(KCS::NormalText).color()}, + + // Button + { "theme_button_background_backdrop_breeze", csc["inactive"]["button"].background(KCS::NormalBackground).color()}, + { "theme_button_decoration_hover_backdrop_breeze", csc["inactive"]["button"].decoration(KCS::HoverColor).color()}, + { "theme_button_decoration_focus_backdrop_breeze", csc["inactive"]["button"].decoration(KCS::FocusColor).color()}, + { "theme_button_foreground_backdrop_breeze", csc["inactive"]["button"].foreground(KCS::NormalText).color()}, + { "theme_button_foreground_active_backdrop_breeze", csc["inactive"]["selection"].foreground(KCS::NormalText).color()}, + + // Misc Colors + { "unfocused_borders_breeze", inactiveBordersColor}, + { "warning_color_backdrop_breeze", csc["inactive"]["view"].foreground(KCS::NeutralText).color()}, + { "success_color_backdrop_breeze", csc["inactive"]["view"].foreground(KCS::PositiveText).color()}, + { "error_color_backdrop_breeze", csc["inactive"]["view"].foreground(KCS::NegativeText).color()}, + + /* + * Insensitive (Disabled) + */ + + // General + { "insensitive_fg_color_breeze",csc["disabled"]["window"].foreground(KCS::NormalText).color()}, + { "insensitive_base_fg_color_breeze", csc["disabled"]["view"].foreground(KCS::NormalText).color()}, + { "insensitive_bg_color_breeze", csc["disabled"]["window"].background(KCS::NormalBackground).color()}, + { "insensitive_base_color_breeze", csc["disabled"]["view"].background(KCS::NormalBackground).color()}, + { "insensitive_selected_bg_color_breeze", csc["disabled"]["selection"].background(KCS::NormalBackground).color()}, + { "insensitive_selected_fg_color_breeze", csc["disabled"]["selection"].foreground(KCS::NormalText).color()}, + + // Button + { "theme_button_background_insensitive_breeze", csc["disabled"]["button"].background(KCS::NormalBackground).color()}, + { "theme_button_decoration_hover_insensitive_breeze", csc["disabled"]["button"].decoration(KCS::HoverColor).color()}, + { "theme_button_decoration_focus_insensitive_breeze", csc["disabled"]["button"].decoration(KCS::FocusColor).color()}, + { "theme_button_foreground_insensitive_breeze", csc["disabled"]["button"].foreground(KCS::NormalText).color()}, + { "theme_button_foreground_active_insensitive_breeze", csc["disabled"]["selection"].foreground(KCS::NormalText).color()}, + + // Misc Colors + { "insensitive_borders_breeze", disabledBordersColor}, + { "warning_color_insensitive_breeze", csc["disabled"]["view"].foreground(KCS::NeutralText).color()}, + { "success_color_insensitive_breeze", csc["disabled"]["view"].foreground(KCS::PositiveText).color()}, + { "error_color_insensitive_breeze", csc["disabled"]["view"].foreground(KCS::NegativeText).color()}, + + /* + * Insensitive Backdrop (Inactive Disabled) + * These pretty much have the same appearance as regular inactive colors, + * but they're separate in case we decide to make them different in the future. + */ + + // General + { "insensitive_unfocused_fg_color_breeze",csc["disabled"]["window"].foreground(KCS::NormalText).color()}, + { "theme_unfocused_view_text_color_breeze", csc["disabled"]["view"].foreground(KCS::NormalText).color()}, + { "insensitive_unfocused_bg_color_breeze", csc["disabled"]["window"].background(KCS::NormalBackground).color()}, + { "theme_unfocused_view_bg_color_breeze", csc["disabled"]["view"].background(KCS::NormalBackground).color()}, + { "insensitive_unfocused_selected_bg_color_breeze", csc["disabled"]["selection"].background(KCS::NormalBackground).color()}, + { "insensitive_unfocused_selected_fg_color_breeze", csc["disabled"]["selection"].foreground(KCS::NormalText).color()}, + + // Button + { "theme_button_background_backdrop_insensitive_breeze", csc["disabled"]["button"].background(KCS::NormalBackground).color()}, + { "theme_button_decoration_hover_backdrop_insensitive_breeze", csc["disabled"]["button"].decoration(KCS::HoverColor).color()}, + { "theme_button_decoration_focus_backdrop_insensitive_breeze", csc["disabled"]["button"].decoration(KCS::FocusColor).color()}, + { "theme_button_foreground_backdrop_insensitive_breeze", csc["disabled"]["button"].foreground(KCS::NormalText).color()}, + { "theme_button_foreground_active_backdrop_insensitive_breeze", csc["disabled"]["selection"].foreground(KCS::NormalText).color()}, + + // Misc Colors + { "unfocused_insensitive_borders_breeze", unfocusedDisabledBordersColor}, + { "warning_color_insensitive_backdrop_breeze", csc["disabled"]["view"].foreground(KCS::NeutralText).color()}, + { "success_color_insensitive_backdrop_breeze", csc["disabled"]["view"].foreground(KCS::PositiveText).color()}, + { "error_color_insensitive_backdrop_breeze", csc["disabled"]["view"].foreground(KCS::NegativeText).color()}, + + /* + * Ignorant Colors (These colors do not care about backdrop or insensitive states) + */ + + { "link_color_breeze", csc["active"]["view"].foreground(KCS::LinkText).color()}, + { "link_visited_color_breeze", csc["active"]["view"].foreground(KCS::VisitedText).color()}, + + { "tooltip_text_breeze", tooltipForegroundColor}, + { "tooltip_background_breeze", tooltipBackgroundColor}, + { "tooltip_border_breeze", tooltipBorderColor}, + + { "content_view_bg_breeze", csc["active"]["view"].background(KCS::NormalBackground).color()}, + + { "theme_titlebar_background_breeze", windowManagerConfig.readEntry("activeBackground", QColor())}, + { "theme_titlebar_foreground_breeze", windowManagerConfig.readEntry("activeForeground", QColor())}, + { "theme_titlebar_background_light_breeze", csc["active"]["window"].background(KCS::NormalBackground).color()}, + { "theme_titlebar_foreground_backdrop_breeze", windowManagerConfig.readEntry("inactiveForeground", QColor())}, + { "theme_titlebar_background_backdrop_breeze", windowManagerConfig.readEntry("inactiveBackground", QColor())}, + { "theme_titlebar_foreground_insensitive_breeze", windowManagerConfig.readEntry("inactiveForeground", QColor())}, + { "theme_titlebar_foreground_insensitive_backdrop_breeze", windowManagerConfig.readEntry("inactiveForeground", QColor())}, + + // Titlebar colors + { "theme_titlebar_background_breeze", windowManagerConfig.readEntry("activeBackground", QColor())}, + { "theme_titlebar_foreground_breeze", windowManagerConfig.readEntry("activeForeground", QColor())}, + { "theme_titlebar_background_light_breeze", csc["active"]["window"].background(KCS::NormalBackground).color()}, + { "theme_titlebar_foreground_backdrop_breeze", windowManagerConfig.readEntry("inactiveForeground", QColor())}, + { "theme_titlebar_background_backdrop_breeze", windowManagerConfig.readEntry("inactiveBackground", QColor())}, + { "theme_titlebar_foreground_insensitive_breeze", windowManagerConfig.readEntry("inactiveForeground", QColor())}, + { "theme_titlebar_foreground_insensitive_backdrop_breeze", windowManagerConfig.readEntry("inactiveForeground", QColor())}, + }; +} + QString ConfigValueProvider::windowDecorationButtonsOrderInGtkNotation(const QString &kdeConfigValue) const { QString gtkNotation; diff --git a/kded/gtkconfig.h b/kded/gtkconfig.h --- a/kded/gtkconfig.h +++ b/kded/gtkconfig.h @@ -47,6 +47,7 @@ void setDarkThemePreference() const; void setWindowDecorationsButtonsOrder() const; void setEnableAnimations() const; + void setColors() const; void applyAllSettings() const; diff --git a/kded/gtkconfig.cpp b/kded/gtkconfig.cpp --- a/kded/gtkconfig.cpp +++ b/kded/gtkconfig.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include "gtkconfig.h" #include "configvalueprovider.h" @@ -176,6 +177,12 @@ ConfigEditor::setGtk3ConfigValueXSettingsd(QStringLiteral("Gtk/EnableAnimations"), enableAnimations); } +void GtkConfig::setColors() const +{ + const QMap colors = configValueProvider->colors(); + ConfigEditor::setGtk3Colors(colors); +} + void GtkConfig::applyAllSettings() const { setFont(); @@ -188,6 +195,7 @@ setDarkThemePreference(); setWindowDecorationsButtonsOrder(); setEnableAnimations(); + setColors(); } void GtkConfig::onKdeglobalsSettingsChange(const KConfigGroup &group, const QByteArrayList &names) const @@ -214,6 +222,7 @@ setFont(); } if (names.contains(QByteArrayLiteral("ColorScheme"))) { + setColors(); setDarkThemePreference(); } } else if (group.name() == QStringLiteral("Toolbar style")) {