Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kde: enable custom decorations #772

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open

Conversation

rkuklik
Copy link
Contributor

@rkuklik rkuklik commented Jan 11, 2025

Hi.

Fixing Plasma activation in #708 worked bit too well. Every time the theme is applied, it resets all custom theming options. I noticed this with decorations, so I added a new option to override org.kde.breeze with custom string.

I also took the liberty of refactoring the module a bit. To improve module maintenance, I mainly reduced the scope of with expressions and improve color handling.

@rkuklik
Copy link
Contributor Author

rkuklik commented Jan 11, 2025

I am bit unsure why nixfmt fails, perhaps there is a version mismatch (I used one from newest nixos-unstable).

@trueNAHO
Copy link
Collaborator

trueNAHO commented Jan 12, 2025

I am bit unsure why nixfmt fails, perhaps there is a version mismatch (I used one from newest nixos-unstable).

We are using the new nixfmt-rfc-style formatter, which is not the same as the older nixfmt formatter.

If the behavior of nixfmt-rfc-style recently changed, we might first have to update the nixpkgs input and re-apply nixfmt-rfc-style in a seperate PR. I will look into this once I have more time (probably in two days).

@rkuklik
Copy link
Contributor Author

rkuklik commented Jan 12, 2025

That is the one I used, nixfmt nixpkgs-unstable-2024-12-04 to be precise. I can reformat the code, but I would say that it is not necessary, if the style updates in the near future.

@trueNAHO
Copy link
Collaborator

For reference, the following patch should make the CI pass:

diff --git a/modules/kde/hm.nix b/modules/kde/hm.nix
index 92878a3..44f643c 100644
--- a/modules/kde/hm.nix
+++ b/modules/kde/hm.nix
@@ -33,7 +33,9 @@ let
     types
     ;

-  formatValue = value: if isBool value then if value then "true" else "false" else toString value;
+  formatValue =
+    value:
+    if isBool value then if value then "true" else "false" else toString value;

   formatSection =
     path: data:
@@ -45,7 +47,9 @@ let
       directChildren = partitioned.right;
       indirectChildren = partitioned.wrong;
     in
-    optional (directChildren != [ ]) header ++ directChildren ++ flatten indirectChildren;
+    optional (directChildren != [ ]) header
+    ++ directChildren
+    ++ flatten indirectChildren;

   formatLines =
     path: data:
@@ -72,7 +76,9 @@ let
   # PascalCase is the standard naming for color scheme files. Schemes named
   # in kebab-case will load when selected manually, but don't work with a
   # look and feel package.
-  colorschemeSlug = concatStrings (filter isString (builtins.split "[^a-zA-Z]" colors.scheme));
+  colorschemeSlug = concatStrings (
+    filter isString (builtins.split "[^a-zA-Z]" colors.scheme)
+  );

   colorEffect = {
     ColorEffect = 0;
@@ -326,29 +332,31 @@ in
     };
   };

-  config = mkIf (config.stylix.enable && cfg.enable && pkgs.stdenv.hostPlatform.isLinux) {
-    home = {
-      packages = [ themePackage ];
-
-      # This activation entry will run the theme activator when the homeConfiguration is activated
-      activation.stylixLookAndFeel = hm.dag.entryAfter [ "writeBoundary" ] ''
-        ${activator} || verboseEcho \
-          "Stylix KDE theme setting failed. Note that it only works in an already running Plasma session."
-      '';
-    };
-
-    xdg = {
-      systemDirs.config = [ "${configPackage}" ];
-
-      # This desktop entry will run the theme activator when a new Plasma session is started
-      # Note: This doesn't run again if a new homeConfiguration is activated from a running Plasma session
-      configFile."autostart/stylix-activator.desktop".text = ''
-        [Desktop Entry]
-        Type=Application
-        Exec=${activator}
-        Name=Stylix Activator
-        X-KDE-AutostartScript=true
-      '';
-    };
-  };
+  config =
+    mkIf (config.stylix.enable && cfg.enable && pkgs.stdenv.hostPlatform.isLinux)
+      {
+        home = {
+          packages = [ themePackage ];
+
+          # This activation entry will run the theme activator when the homeConfiguration is activated
+          activation.stylixLookAndFeel = hm.dag.entryAfter [ "writeBoundary" ] ''
+            ${activator} || verboseEcho \
+              "Stylix KDE theme setting failed. Note that it only works in an already running Plasma session."
+          '';
+        };
+
+        xdg = {
+          systemDirs.config = [ "${configPackage}" ];
+
+          # This desktop entry will run the theme activator when a new Plasma session is started
+          # Note: This doesn't run again if a new homeConfiguration is activated from a running Plasma session
+          configFile."autostart/stylix-activator.desktop".text = ''
+            [Desktop Entry]
+            Type=Application
+            Exec=${activator}
+            Name=Stylix Activator
+            X-KDE-AutostartScript=true
+          '';
+        };
+      };
 }

I will resolve this issue when I have more time.

@rkuklik
Copy link
Contributor Author

rkuklik commented Jan 12, 2025

Thank you.

I will resolve this issue when I have more time.

Do you mean the formatting CI, this PR or both? I am unsure whether I should reformat the code, leave it as is for later or help with anything else.

Copy link
Collaborator

@trueNAHO trueNAHO left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is that your code is not formated with --width=80:

stylix/flake.nix

Lines 122 to 125 in 2985ee9

nixfmt-rfc-style = {
enable = true;
settings.width = 80;
};

For reference, the current CI command is:

/nix/store/lch913ar0a3w3f6d63crf5vfvpckddk1-nixfmt-unstable-2024-12-04/bin/nixfmt --width=80

If you do not mind the pre-commit hooks (there is currently no developer shell variant without them, although this could be trivially added), feel free to use the developer shells:

# Development environment
To enter the developer shell, run:
```console
nix develop
```
To automatically enter the developer shell upon entering the project directory
with [`direnv`](https://direnv.net), run:
```console
direnv allow
```

I can reformat the code, but I would say that it is not necessary, if the style updates in the near future. [...] I am unsure whether I should reformat the code, leave it as is for later or help with anything else.

Properly format the code, since the CI already uses the latest nixfmt-unstable-2024-12-04.

@rkuklik
Copy link
Contributor Author

rkuklik commented Jan 18, 2025

Thank you very much for your help and sorry for the trouble.

modules/kde/hm.nix Outdated Show resolved Hide resolved
modules/kde/hm.nix Outdated Show resolved Hide resolved
modules/kde/hm.nix Show resolved Hide resolved
modules/kde/hm.nix Show resolved Hide resolved
modules/kde/hm.nix Outdated Show resolved Hide resolved
Copy link
Owner

@danth danth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having this be configurable seems reasonable.

(Although org.kde.breeze is the KDE default, it's important that this setting is included in our Look and Feel package, as otherwise it may not be reset when switching from a different package. So we can't just remove it.)

It might be a good idea to add a note that alternative window decorations might not be compatible with the Stylix theme.

modules/kde/hm.nix Outdated Show resolved Hide resolved
@rkuklik rkuklik requested a review from trueNAHO January 25, 2025 20:38
Copy link
Collaborator

@trueNAHO trueNAHO left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since I am unable to push to your branch (maybe because it is your master branch) consider applying the following patches:

From d14877df0af8720dc5dc0888f63008ddb2d4c413 Mon Sep 17 00:00:00 2001
From: NAHO <90870942+trueNAHO@users.noreply.github.com>
Date: Sun, 26 Jan 2025 21:01:13 +0100
Subject: [PATCH 1/2] kde: revert non-essential changes

Revert all changes that are non-essential to adding the new
stylix.targets.kde.decorations option. This simplifies the patch, making
it easier to understand, backport, and potentially revert.

Despite the KDE module benefiting from a clean-up, it might be better to
postpone this to a follow-up PR. Note that initiating this follow-up PR
is essentially reverting this commit.
---
 modules/kde/hm.nix | 144 ++++++++++++++++++++-------------------------
 1 file changed, 64 insertions(+), 80 deletions(-)

diff --git a/modules/kde/hm.nix b/modules/kde/hm.nix
index 1684ce3..ec33913 100644
--- a/modules/kde/hm.nix
+++ b/modules/kde/hm.nix
@@ -4,17 +4,19 @@
   lib,
   ...
 }:
+
+with config.stylix.fonts;
+with config.lib.stylix.colors;
+
 let
   cfg = config.stylix.targets.kde;

-  inherit (config.lib.stylix)
-    colors
-    mkEnableTarget
-    ;
-
   formatValue =
     value:
-    if lib.isBool value then if value then "true" else "false" else toString value;
+    if builtins.isBool value then
+      if value then "true" else "false"
+    else
+      builtins.toString value;

   formatSection =
     path: data:
@@ -22,7 +24,7 @@ let
       header = lib.concatStrings (map (p: "[${p}]") path);
       formatChild = name: formatLines (path ++ [ name ]);
       children = lib.mapAttrsToList formatChild data;
-      partitioned = lib.partition lib.isString children;
+      partitioned = lib.partition builtins.isString children;
       directChildren = partitioned.right;
       indirectChildren = partitioned.wrong;
     in
@@ -32,9 +34,9 @@ let

   formatLines =
     path: data:
-    if lib.isAttrs data then
+    if builtins.isAttrs data then
       if data ? _immutable then
-        if lib.isAttrs data.value then
+        if builtins.isAttrs data.value then
           formatSection (path ++ [ "$i" ]) data.value
         else
           "${lib.last path}[$i]=${formatValue data.value}"
@@ -56,7 +58,7 @@ let
   # in kebab-case will load when selected manually, but don't work with a
   # look and feel package.
   colorschemeSlug = lib.concatStrings (
-    lib.filter lib.isString (builtins.split "[^a-zA-Z]" colors.scheme)
+    builtins.filter builtins.isString (builtins.split "[^a-zA-Z]" scheme)
   );

   colorEffect = {
@@ -68,76 +70,52 @@ let
     IntensityAmount = 0;
   };

-  mkColorTriple =
-    name:
-    lib.concatStringsSep "," (
-      map (color: colors."${name}-rgb-${color}") [
-        "r"
-        "g"
-        "b"
-      ]
-    );
-
-  mkColorMapping =
-    num:
-    let
-      hex = "base0${lib.toHexString num}";
-    in
-    {
-      name = hex;
-      value = mkColorTriple hex;
-    };
-
-  colors' = lib.listToAttrs (map mkColorMapping (lib.range 0 15));
-
-  kdecolors = with colors'; {
-    BackgroundNormal = base00;
-    BackgroundAlternate = base01;
-    DecorationFocus = base0D;
-    DecorationHover = base0D;
-    ForegroundNormal = base05;
-    ForegroundActive = base05;
-    ForegroundInactive = base05;
-    ForegroundLink = base05;
-    ForegroundVisited = base05;
-    ForegroundNegative = base08;
-    ForegroundNeutral = base0D;
-    ForegroundPositive = base0B;
+  colors = {
+    BackgroundNormal = "${base00-rgb-r},${base00-rgb-g},${base00-rgb-b}";
+    BackgroundAlternate = "${base01-rgb-r},${base01-rgb-g},${base01-rgb-b}";
+    DecorationFocus = "${base0D-rgb-r},${base0D-rgb-g},${base0D-rgb-b}";
+    DecorationHover = "${base0D-rgb-r},${base0D-rgb-g},${base0D-rgb-b}";
+    ForegroundNormal = "${base05-rgb-r},${base05-rgb-g},${base05-rgb-b}";
+    ForegroundActive = "${base05-rgb-r},${base05-rgb-g},${base05-rgb-b}";
+    ForegroundInactive = "${base05-rgb-r},${base05-rgb-g},${base05-rgb-b}";
+    ForegroundLink = "${base05-rgb-r},${base05-rgb-g},${base05-rgb-b}";
+    ForegroundVisited = "${base05-rgb-r},${base05-rgb-g},${base05-rgb-b}";
+    ForegroundNegative = "${base08-rgb-r},${base08-rgb-g},${base08-rgb-b}";
+    ForegroundNeutral = "${base0D-rgb-r},${base0D-rgb-g},${base0D-rgb-b}";
+    ForegroundPositive = "${base0B-rgb-r},${base0B-rgb-g},${base0B-rgb-b}";
   };

   colorscheme = {
     General = {
       ColorScheme = colorschemeSlug;
-      Name = colors.scheme;
+      Name = scheme;
     };

     "ColorEffects:Disabled" = colorEffect;
     "ColorEffects:Inactive" = colorEffect;

-    "Colors:Window" = kdecolors;
-    "Colors:View" = kdecolors;
-    "Colors:Button" = kdecolors;
-    "Colors:Tooltip" = kdecolors;
-    "Colors:Complementary" = kdecolors;
-    "Colors:Selection" =
-      kdecolors
-      // (with colors'; {
-        BackgroundNormal = base0D;
-        BackgroundAlternate = base0D;
-        ForegroundNormal = base00;
-        ForegroundActive = base00;
-        ForegroundInactive = base00;
-        ForegroundLink = base00;
-        ForegroundVisited = base00;
-      });
-
-    WM = with colors'; {
-      activeBlend = base0A;
-      activeBackground = base00;
-      activeForeground = base05;
-      inactiveBlend = base03;
-      inactiveBackground = base00;
-      inactiveForeground = base05;
+    "Colors:Window" = colors;
+    "Colors:View" = colors;
+    "Colors:Button" = colors;
+    "Colors:Tooltip" = colors;
+    "Colors:Complementary" = colors;
+    "Colors:Selection" = colors // {
+      BackgroundNormal = "${base0D-rgb-r},${base0D-rgb-g},${base0D-rgb-b}";
+      BackgroundAlternate = "${base0D-rgb-r},${base0D-rgb-g},${base0D-rgb-b}";
+      ForegroundNormal = "${base00-rgb-r},${base00-rgb-g},${base00-rgb-b}";
+      ForegroundActive = "${base00-rgb-r},${base00-rgb-g},${base00-rgb-b}";
+      ForegroundInactive = "${base00-rgb-r},${base00-rgb-g},${base00-rgb-b}";
+      ForegroundLink = "${base00-rgb-r},${base00-rgb-g},${base00-rgb-b}";
+      ForegroundVisited = "${base00-rgb-r},${base00-rgb-g},${base00-rgb-b}";
+    };
+
+    WM = {
+      activeBlend = "${base0A-rgb-r},${base0A-rgb-g},${base0A-rgb-b}";
+      activeBackground = "${base00-rgb-r},${base00-rgb-g},${base00-rgb-b}";
+      activeForeground = "${base05-rgb-r},${base05-rgb-g},${base05-rgb-b}";
+      inactiveBlend = "${base03-rgb-r},${base03-rgb-g},${base03-rgb-b}";
+      inactiveBackground = "${base00-rgb-r},${base00-rgb-g},${base00-rgb-b}";
+      inactiveForeground = "${base05-rgb-r},${base05-rgb-g},${base05-rgb-b}";
     };
   };

@@ -234,7 +212,7 @@ let
   kdeglobals = {
     KDE.LookAndFeelPackage = makeImmutable "stylix";

-    General = with config.stylix.fonts; rec {
+    General = rec {
       font = makeImmutable "${sansSerif.name},${toString sizes.applications},-1,5,50,0,0,0,0,0";
       fixed = makeImmutable "${monospace.name},${toString sizes.terminal},-1,5,50,0,0,0,0,0";
       desktopFont = makeImmutable "${sansSerif.name},${toString sizes.desktop},-1,5,50,0,0,0,0,0";
@@ -273,28 +251,33 @@ let
   # might be installed, and look there. The ideal solution would require
   # changes to KDE to make it possible to update the wallpaper through
   # config files alone.
-  activator' = pkgs.writeShellScriptBin "stylix-activate-kde" ''
+  activator = pkgs.writeShellScriptBin "stylix-set-kde-wallpaper" ''
     set -eu
-    get_exe() {
+    global_path() {
       for directory in /run/current-system/sw/bin /usr/bin /bin; do
         if [[ -f "$directory/$1" ]]; then
           printf '%s\n' "$directory/$1"
           return 0
         fi
       done
-      echo "Skipping `$1`: command not found"
+
       return 1
     }

-    if wallpaper_image="$(get_exe plasma-apply-wallpaperimage)"; then
+    if wallpaper_image="$(global_path plasma-apply-wallpaperimage)"; then
       "$wallpaper_image" "${themePackage}/share/wallpapers/stylix"
+    else
+      echo "Skipping plasma-apply-wallpaperimage: command not found"
     fi

-    if look_and_feel="$(get_exe plasma-apply-lookandfeel)"; then
+    if look_and_feel="$(global_path plasma-apply-lookandfeel)"; then
       "$look_and_feel" --apply stylix
+    else
+      echo "Skipping plasma-apply-lookandfeel: command not found"
     fi
   '';
-  activator = lib.getExe activator';
+
+  activateDocs = "https://stylix.danth.me/options/hm.html#stylixtargetskdeservice";
 in
 {
   options.stylix.targets.kde = {
@@ -320,9 +303,10 @@ in
           packages = [ themePackage ];

           # This activation entry will run the theme activator when the homeConfiguration is activated
+          # Note: This only works in an already running Plasma session.
           activation.stylixLookAndFeel = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
-            ${activator} || verboseEcho \
-              "Stylix KDE theme setting failed. This only works in a running Plasma session."
+            ${lib.getExe activator} || verboseEcho \
+              "KDE theme setting failed. See `${activateDocs}`"
           '';
         };

@@ -334,7 +318,7 @@ in
           configFile."autostart/stylix-activator.desktop".text = ''
             [Desktop Entry]
             Type=Application
-            Exec=${activator}
+            Exec=${lib.getExe activator}
             Name=Stylix Activator
             X-KDE-AutostartScript=true
           '';
--
2.47.0
From 83df9fcc1535ef6c1be97118d5a73fcc761ff867 Mon Sep 17 00:00:00 2001
From: NAHO <90870942+trueNAHO@users.noreply.github.com>
Date: Sun, 26 Jan 2025 21:20:21 +0100
Subject: [PATCH 2/2] kde: adapt decorations description and leverage warnings

Adapt the stylix.targets.kde.decorations description and elevate its
limitation notice into a warning.
---
 modules/kde/hm.nix | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/modules/kde/hm.nix b/modules/kde/hm.nix
index ec33913..eefb018 100644
--- a/modules/kde/hm.nix
+++ b/modules/kde/hm.nix
@@ -287,10 +287,11 @@ in
       type = lib.types.str;
       default = "org.kde.breeze";
       description = ''
-        The library for the window decorations theme. Decorations other than default
-        `org.kde.breeze` may not be compatible with stylix. To view all available
-        values, see the `library` key in the `org.kde.kdecoration2` section of `$HOME/.config/kwinrc`
-        after imperatively applying the window decoration via the System Settings app.
+        The library for the window decorations theme.
+
+        To list all available decorations, see the `library` key in the
+        `org.kde.kdecoration2` section of `$HOME/.config/kwinrc` after
+        imperatively applying the window decoration via the System Settings app.
       '';
     };
   };
@@ -299,6 +300,10 @@ in
     lib.mkIf
       (config.stylix.enable && cfg.enable && pkgs.stdenv.hostPlatform.isLinux)
       {
+        warnings =
+          lib.optional (cfg.decorations != "org.kde.breeze")
+            "stylix: kde: config.stylix.targets.kde.decorations other than 'org.kde.breeze' may be incompatible: ${config.stylix.targets.kde.decorations}";
+
         home = {
           packages = [ themePackage ];

--
2.47.0

Should the limitation notice be a warning or just mentioned in the description? I assume that if most stylix.targets.kde.decorations values work that this warning would be mostly annoying.

@rkuklik
Copy link
Contributor Author

rkuklik commented Jan 26, 2025

This is just going in circles. I mostly agree with the second change (apart from the warning, any user going through the hassle of changing the decorations will most likely know where they created potentially breaking change in the config). But the first change simply takes all we have iterated on (with changes suggested in this PR) and removes it.

I can split this into two PR's, if there isn't any other change you would like apart from the second patch. I noticed that you squash the changes when merging, so should I just apply the patches (with minor warning inside docs) and after merging open a new PR?

Since I am unable to push to your branch (maybe because it is your master branch) consider applying the following patches:

You should be able to, GH tells me that users with write access to danth/stylix can add new commits to your master branch. That's wierd.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants