gtk: add cursor theme configuration (#2481)

* gtk: add cursor theme configuration

- Added the `cursorTheme` under the gtk module.
- Added tests for the gtk3 settings file generation, and renamed
  the gtk2 unit test expected file for clarity.
- Added guard against generating a blank `gtk.css` when `cfg.extraCss`
  is empty.
- Replaced `concatMapStrings` calls with `concatStringsSep`. The library function
  `concatMapStrings` generates an intemediate list which is then passed to
  `concatStringsSep`, As we are not performing other transformation except
  the addition of newlines, a direct call to `concatStringsSep` is sufficient.
- Updated description of examples to be more general "~/.config" -> "$XDG_CONFIG_HOME".
- Update helper functions `toGtk3Ini` and `formatGtk2Option` to use the library
  function `boolToString` and escape the separator in the key name.

* xcursor: delegate GTK cursor settings to gtk.cursorTheme

- Added deprecation warning for GTK settings in the `xsession.cursorTheme` module.
- Modified config section to use `gtk.cursorTheme` for GTK cursor settings.
This commit is contained in:
polykernel 2022-03-17 15:30:48 -04:00 committed by GitHub
parent 970b57fd3c
commit e01facc340
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 125 additions and 30 deletions

View file

@ -11,23 +11,19 @@ let
toGtk3Ini = generators.toINI { toGtk3Ini = generators.toINI {
mkKeyValue = key: value: mkKeyValue = key: value:
let let value' = if isBool value then boolToString value else toString value;
value' = if isBool value then in "${escape [ "=" ] key}=${value'}";
(if value then "true" else "false")
else
toString value;
in "${key}=${value'}";
}; };
formatGtk2Option = n: v: formatGtk2Option = n: v:
let let
v' = if isBool v then v' = if isBool v then
(if v then "true" else "false") boolToString value
else if isString v then else if isString v then
''"${v}"'' ''"${v}"''
else else
toString v; toString v;
in "${n} = ${v'}"; in "${escape [ "=" ] n} = ${v'}";
themeType = types.submodule { themeType = types.submodule {
options = { options = {
@ -50,6 +46,57 @@ let
}; };
}; };
iconThemeType = types.submodule {
options = {
package = mkOption {
type = types.nullOr types.package;
default = null;
example = literalExpression "pkgs.adwaita-icon-theme";
description = ''
Package providing the icon theme. This package will be installed
to your profile. If <literal>null</literal> then the theme
is assumed to already be available in your profile.
'';
};
name = mkOption {
type = types.str;
example = "Adwaita";
description = "The name of the icon theme within the package.";
};
};
};
cursorThemeType = types.submodule {
options = {
package = mkOption {
type = types.nullOr types.package;
default = null;
example = literalExpression "pkgs.vanilla-dmz";
description = ''
Package providing the cursor theme. This package will be installed
to your profile. If <literal>null</literal> then the theme
is assumed to already be available in your profile.
'';
};
name = mkOption {
type = types.str;
example = "Vanilla-DMZ";
description = "The name of the cursor theme within the package.";
};
size = mkOption {
type = types.nullOr types.int;
default = null;
example = 16;
description = ''
The size of the cursor.
'';
};
};
};
in { in {
meta.maintainers = [ maintainers.rycee ]; meta.maintainers = [ maintainers.rycee ];
@ -71,8 +118,14 @@ in {
''; '';
}; };
cursorTheme = mkOption {
type = types.nullOr cursorThemeType;
default = null;
description = "The cursor theme to use.";
};
iconTheme = mkOption { iconTheme = mkOption {
type = types.nullOr themeType; type = types.nullOr iconThemeType;
default = null; default = null;
description = "The icon theme to use."; description = "The icon theme to use.";
}; };
@ -116,7 +169,7 @@ in {
}; };
extraConfig = mkOption { extraConfig = mkOption {
type = with types; attrsOf (either bool (either int str)); type = with types; attrsOf (oneOf [ bool int str ]);
default = { }; default = { };
example = { example = {
gtk-cursor-blink = false; gtk-cursor-blink = false;
@ -156,7 +209,7 @@ in {
}; };
config = mkIf cfg.enable (let config = mkIf cfg.enable (let
ini = optionalAttrs (cfg.font != null) { gtkIni = optionalAttrs (cfg.font != null) {
gtk-font-name = let gtk-font-name = let
fontSize = fontSize =
optionalString (cfg.font.size != null) " ${toString cfg.font.size}"; optionalString (cfg.font.size != null) " ${toString cfg.font.size}";
@ -164,6 +217,11 @@ in {
} // optionalAttrs (cfg.theme != null) { gtk-theme-name = cfg.theme.name; } } // optionalAttrs (cfg.theme != null) { gtk-theme-name = cfg.theme.name; }
// optionalAttrs (cfg.iconTheme != null) { // optionalAttrs (cfg.iconTheme != null) {
gtk-icon-theme-name = cfg.iconTheme.name; gtk-icon-theme-name = cfg.iconTheme.name;
} // optionalAttrs (cfg.cursorTheme != null) {
gtk-cursor-theme-name = cfg.cursorTheme.name;
} // optionalAttrs
(cfg.cursorTheme != null && cfg.cursorTheme.size != null) {
gtk-cursor-theme-size = cfg.cursorTheme.size;
}; };
dconfIni = optionalAttrs (cfg.font != null) { dconfIni = optionalAttrs (cfg.font != null) {
@ -174,31 +232,41 @@ in {
} // optionalAttrs (cfg.theme != null) { gtk-theme = cfg.theme.name; } } // optionalAttrs (cfg.theme != null) { gtk-theme = cfg.theme.name; }
// optionalAttrs (cfg.iconTheme != null) { // optionalAttrs (cfg.iconTheme != null) {
icon-theme = cfg.iconTheme.name; icon-theme = cfg.iconTheme.name;
} // optionalAttrs (cfg.cursorTheme != null) {
cursor-theme = cfg.cursorTheme.name;
} // optionalAttrs
(cfg.cursorTheme != null && cfg.cursorTheme.size != null) {
cursor-size = cfg.cursorTheme.size;
}; };
optionalPackage = opt: optionalPackage = opt:
optional (opt != null && opt.package != null) opt.package; optional (opt != null && opt.package != null) opt.package;
in { in {
home.packages = optionalPackage cfg.font ++ optionalPackage cfg.theme home.packages = concatMap optionalPackage [
++ optionalPackage cfg.iconTheme; cfg.font
cfg.theme
cfg.iconTheme
cfg.cursorTheme
];
home.file.${cfg2.configLocation}.text = home.file.${cfg2.configLocation}.text =
concatMapStrings (l: l + "\n") (mapAttrsToList formatGtk2Option ini) concatStringsSep "\n" (mapAttrsToList formatGtk2Option gtkIni)
+ cfg2.extraConfig; + cfg2.extraConfig;
home.sessionVariables.GTK2_RC_FILES = cfg2.configLocation; home.sessionVariables.GTK2_RC_FILES = cfg2.configLocation;
xdg.configFile."gtk-3.0/settings.ini".text = xdg.configFile."gtk-3.0/settings.ini".text =
toGtk3Ini { Settings = ini // cfg3.extraConfig; }; toGtk3Ini { Settings = gtkIni // cfg3.extraConfig; };
xdg.configFile."gtk-3.0/gtk.css".text = cfg3.extraCss; xdg.configFile."gtk-3.0/gtk.css" =
mkIf (cfg3.extraCss != "") { text = cfg3.extraCss; };
xdg.configFile."gtk-3.0/bookmarks" = mkIf (cfg3.bookmarks != [ ]) { xdg.configFile."gtk-3.0/bookmarks" = mkIf (cfg3.bookmarks != [ ]) {
text = concatMapStrings (l: l + "\n") cfg3.bookmarks; text = concatStringsSep "\n" cfg3.bookmarks;
}; };
xdg.configFile."gtk-4.0/settings.ini".text = xdg.configFile."gtk-4.0/settings.ini".text =
toGtk3Ini { Settings = ini // cfg4.extraConfig; }; toGtk3Ini { Settings = gtkIni // cfg4.extraConfig; };
dconf.settings."org/gnome/desktop/interface" = dconfIni; dconf.settings."org/gnome/desktop/interface" = dconfIni;
}); });

View file

@ -60,6 +60,11 @@ in {
platforms.linux) platforms.linux)
]; ];
warnings = [''
GTK cursor settings will no longer be handled in the xsession.pointerCursor module in future.
Please use gtk.cursorTheme for GTK cursor settings instead.
''];
home.packages = [ cfg.package ]; home.packages = [ cfg.package ];
xsession.initExtra = '' xsession.initExtra = ''
@ -73,15 +78,8 @@ in {
"Xcursor.size" = cfg.size; "Xcursor.size" = cfg.size;
}; };
gtk.gtk2.extraConfig = '' # TODO: deprecate after next version release.
gtk-cursor-theme-name="${cfg.name}" gtk.cursorTheme = { inherit (cfg) package name size; };
gtk-cursor-theme-size=${toString cfg.size}
'';
gtk.gtk3.extraConfig = {
"gtk-cursor-theme-name" = cfg.name;
"gtk-cursor-theme-size" = cfg.size;
};
# Set name in icons theme, for compatibility with AwesomeWM etc. See: # Set name in icons theme, for compatibility with AwesomeWM etc. See:
# https://github.com/nix-community/home-manager/issues/2081 # https://github.com/nix-community/home-manager/issues/2081

View file

@ -1,5 +1,6 @@
{ {
gtk2-basic-config = ./gtk2-basic-config.nix; gtk2-basic-config = ./gtk2-basic-config.nix;
gtk2-config-file-location = ./gtk2-config-file-location.nix; gtk2-config-file-location = ./gtk2-config-file-location.nix;
gtk3-basic-settings = ./gtk3-basic-settings.nix;
} }

View file

@ -13,9 +13,10 @@ with lib;
nmt.script = '' nmt.script = ''
assertFileExists home-files/.gtkrc-2.0 assertFileExists home-files/.gtkrc-2.0
assertFileContent home-files/.gtkrc-2.0 ${
./gtk-basic-config-expected.conf assertFileContent home-files/.gtkrc-2.0 \
} ${./gtk2-basic-config-expected.conf}
assertFileRegex home-path/etc/profile.d/hm-session-vars.sh \ assertFileRegex home-path/etc/profile.d/hm-session-vars.sh \
'GTK2_RC_FILES=.*/.gtkrc-2.0' 'GTK2_RC_FILES=.*/.gtkrc-2.0'
''; '';

View file

@ -0,0 +1,3 @@
[Settings]
gtk-cursor-blink=false
gtk-recent-files-limit=20

View file

@ -0,0 +1,24 @@
{ config, lib, pkgs, ... }:
with lib;
{
config = {
gtk = {
enable = true;
gtk3.extraConfig = {
gtk-cursor-blink = false;
gtk-recent-files-limit = 20;
};
};
test.stubs.dconf = { };
nmt.script = ''
assertPathExists home-files/.config/gtk-3.0
assertFileContent home-files/.config/gtk-3.0/settings.ini \
${./gtk3-basic-settings-expected.ini}
'';
};
}