kde: add decorations option and polish code (#772)

Commit e0a41d3a25 ("kde: replace systemd unit with AutostartScript for
theme application (#708)") improved theme application robustness to the
point of resetting custom theming options. Adding a decorations option
allows overriding its default value without it being reset.

This change also polishes the entire module.

Link: https://github.com/danth/stylix/pull/772

Reviewed-by: NAHO <90870942+trueNAHO@users.noreply.github.com>
This commit is contained in:
rkuklik 2025-01-30 23:33:12 +01:00 committed by GitHub
parent 55418e8fc8
commit d9df2b4200
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -4,19 +4,17 @@
lib, lib,
... ...
}: }:
with config.stylix.fonts;
with config.lib.stylix.colors;
let let
cfg = config.stylix.targets.kde; cfg = config.stylix.targets.kde;
inherit (config.lib.stylix)
colors
mkEnableTarget
;
formatValue = formatValue =
value: value:
if builtins.isBool value then if lib.isBool value then if value then "true" else "false" else toString value;
if value then "true" else "false"
else
builtins.toString value;
formatSection = formatSection =
path: data: path: data:
@ -24,7 +22,7 @@ let
header = lib.concatStrings (map (p: "[${p}]") path); header = lib.concatStrings (map (p: "[${p}]") path);
formatChild = name: formatLines (path ++ [ name ]); formatChild = name: formatLines (path ++ [ name ]);
children = lib.mapAttrsToList formatChild data; children = lib.mapAttrsToList formatChild data;
partitioned = lib.partition builtins.isString children; partitioned = lib.partition lib.isString children;
directChildren = partitioned.right; directChildren = partitioned.right;
indirectChildren = partitioned.wrong; indirectChildren = partitioned.wrong;
in in
@ -34,9 +32,9 @@ let
formatLines = formatLines =
path: data: path: data:
if builtins.isAttrs data then if lib.isAttrs data then
if data ? _immutable then if data ? _immutable then
if builtins.isAttrs data.value then if lib.isAttrs data.value then
formatSection (path ++ [ "$i" ]) data.value formatSection (path ++ [ "$i" ]) data.value
else else
"${lib.last path}[$i]=${formatValue data.value}" "${lib.last path}[$i]=${formatValue data.value}"
@ -58,7 +56,7 @@ let
# in kebab-case will load when selected manually, but don't work with a # in kebab-case will load when selected manually, but don't work with a
# look and feel package. # look and feel package.
colorschemeSlug = lib.concatStrings ( colorschemeSlug = lib.concatStrings (
builtins.filter builtins.isString (builtins.split "[^a-zA-Z]" scheme) lib.filter lib.isString (builtins.split "[^a-zA-Z]" colors.scheme)
); );
colorEffect = { colorEffect = {
@ -70,52 +68,76 @@ let
IntensityAmount = 0; IntensityAmount = 0;
}; };
colors = { mkColorTriple =
BackgroundNormal = "${base00-rgb-r},${base00-rgb-g},${base00-rgb-b}"; name:
BackgroundAlternate = "${base01-rgb-r},${base01-rgb-g},${base01-rgb-b}"; lib.concatStringsSep "," (
DecorationFocus = "${base0D-rgb-r},${base0D-rgb-g},${base0D-rgb-b}"; map (color: colors."${name}-rgb-${color}") [
DecorationHover = "${base0D-rgb-r},${base0D-rgb-g},${base0D-rgb-b}"; "r"
ForegroundNormal = "${base05-rgb-r},${base05-rgb-g},${base05-rgb-b}"; "g"
ForegroundActive = "${base05-rgb-r},${base05-rgb-g},${base05-rgb-b}"; "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}"; mkColorMapping =
ForegroundNeutral = "${base0D-rgb-r},${base0D-rgb-g},${base0D-rgb-b}"; num:
ForegroundPositive = "${base0B-rgb-r},${base0B-rgb-g},${base0B-rgb-b}"; 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;
}; };
colorscheme = { colorscheme = {
General = { General = {
ColorScheme = colorschemeSlug; ColorScheme = colorschemeSlug;
Name = scheme; Name = colors.scheme;
}; };
"ColorEffects:Disabled" = colorEffect; "ColorEffects:Disabled" = colorEffect;
"ColorEffects:Inactive" = colorEffect; "ColorEffects:Inactive" = colorEffect;
"Colors:Window" = colors; "Colors:Window" = kdecolors;
"Colors:View" = colors; "Colors:View" = kdecolors;
"Colors:Button" = colors; "Colors:Button" = kdecolors;
"Colors:Tooltip" = colors; "Colors:Tooltip" = kdecolors;
"Colors:Complementary" = colors; "Colors:Complementary" = kdecolors;
"Colors:Selection" = colors // { "Colors:Selection" =
BackgroundNormal = "${base0D-rgb-r},${base0D-rgb-g},${base0D-rgb-b}"; kdecolors
BackgroundAlternate = "${base0D-rgb-r},${base0D-rgb-g},${base0D-rgb-b}"; // (with colors'; {
ForegroundNormal = "${base00-rgb-r},${base00-rgb-g},${base00-rgb-b}"; BackgroundNormal = base0D;
ForegroundActive = "${base00-rgb-r},${base00-rgb-g},${base00-rgb-b}"; BackgroundAlternate = base0D;
ForegroundInactive = "${base00-rgb-r},${base00-rgb-g},${base00-rgb-b}"; ForegroundNormal = base00;
ForegroundLink = "${base00-rgb-r},${base00-rgb-g},${base00-rgb-b}"; ForegroundActive = base00;
ForegroundVisited = "${base00-rgb-r},${base00-rgb-g},${base00-rgb-b}"; ForegroundInactive = base00;
}; ForegroundLink = base00;
ForegroundVisited = base00;
});
WM = { WM = with colors'; {
activeBlend = "${base0A-rgb-r},${base0A-rgb-g},${base0A-rgb-b}"; activeBlend = base0A;
activeBackground = "${base00-rgb-r},${base00-rgb-g},${base00-rgb-b}"; activeBackground = base00;
activeForeground = "${base05-rgb-r},${base05-rgb-g},${base05-rgb-b}"; activeForeground = base05;
inactiveBlend = "${base03-rgb-r},${base03-rgb-g},${base03-rgb-b}"; inactiveBlend = base03;
inactiveBackground = "${base00-rgb-r},${base00-rgb-g},${base00-rgb-b}"; inactiveBackground = base00;
inactiveForeground = "${base05-rgb-r},${base05-rgb-g},${base05-rgb-b}"; inactiveForeground = base05;
}; };
}; };
@ -138,7 +160,7 @@ let
}; };
lookAndFeelDefaults = { lookAndFeelDefaults = {
kwinrc."org.kde.kdecoration2".library = "org.kde.breeze"; kwinrc."org.kde.kdecoration2".library = cfg.decorations;
plasmarc.Theme.name = "default"; plasmarc.Theme.name = "default";
kdeglobals = { kdeglobals = {
@ -212,7 +234,7 @@ let
kdeglobals = { kdeglobals = {
KDE.LookAndFeelPackage = makeImmutable "stylix"; KDE.LookAndFeelPackage = makeImmutable "stylix";
General = rec { General = with config.stylix.fonts; rec {
font = makeImmutable "${sansSerif.name},${toString sizes.applications},-1,5,50,0,0,0,0,0"; 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"; 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"; desktopFont = makeImmutable "${sansSerif.name},${toString sizes.desktop},-1,5,50,0,0,0,0,0";
@ -251,36 +273,48 @@ let
# might be installed, and look there. The ideal solution would require # might be installed, and look there. The ideal solution would require
# changes to KDE to make it possible to update the wallpaper through # changes to KDE to make it possible to update the wallpaper through
# config files alone. # config files alone.
activator = pkgs.writeShellScriptBin "stylix-set-kde-wallpaper" '' activator' = pkgs.writeShellScriptBin "stylix-activate-kde" ''
set -eu set -eu
global_path() { get_exe() {
for directory in /run/current-system/sw/bin /usr/bin /bin; do for directory in /run/current-system/sw/bin /usr/bin /bin; do
if [[ -f "$directory/$1" ]]; then if [[ -f "$directory/$1" ]]; then
printf '%s\n' "$directory/$1" printf '%s\n' "$directory/$1"
return 0 return 0
fi fi
done done
echo "Skipping `$1`: command not found"
return 1 return 1
} }
if wallpaper_image="$(global_path plasma-apply-wallpaperimage)"; then if wallpaper_image="$(get_exe plasma-apply-wallpaperimage)"; then
"$wallpaper_image" "${themePackage}/share/wallpapers/stylix" "$wallpaper_image" "${themePackage}/share/wallpapers/stylix"
else
echo "Skipping plasma-apply-wallpaperimage: command not found"
fi fi
if look_and_feel="$(global_path plasma-apply-lookandfeel)"; then if look_and_feel="$(get_exe plasma-apply-lookandfeel)"; then
"$look_and_feel" --apply stylix "$look_and_feel" --apply stylix
else
echo "Skipping plasma-apply-lookandfeel: command not found"
fi fi
''; '';
activator = lib.getExe activator';
activateDocs = "https://stylix.danth.me/options/hm.html#stylixtargetskdeservice";
in in
{ {
options.stylix.targets.kde.enable = config.lib.stylix.mkEnableTarget "KDE" true; options.stylix.targets.kde = {
enable = mkEnableTarget "KDE" true;
decorations = lib.mkOption {
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 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.
'';
};
};
config = config =
lib.mkIf lib.mkIf
@ -290,10 +324,9 @@ in
packages = [ themePackage ]; packages = [ themePackage ];
# This activation entry will run the theme activator when the homeConfiguration is activated # 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" ] '' activation.stylixLookAndFeel = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
${lib.getExe activator} || verboseEcho \ ${activator} || verboseEcho \
"KDE theme setting failed. See `${activateDocs}`" "Stylix KDE theme setting failed. This only works in a running Plasma session."
''; '';
}; };
@ -305,7 +338,7 @@ in
configFile."autostart/stylix-activator.desktop".text = '' configFile."autostart/stylix-activator.desktop".text = ''
[Desktop Entry] [Desktop Entry]
Type=Application Type=Application
Exec=${lib.getExe activator} Exec=${activator}
Name=Stylix Activator Name=Stylix Activator
X-KDE-AutostartScript=true X-KDE-AutostartScript=true
''; '';