main
 1{lib, ...}: {
 2  den.aspects.desktop.aesthetic.cursor = {
 3    settings.host = {
 4      name = lib.mkOption {
 5        type = lib.types.nullOr lib.types.str;
 6        # default = null;
 7        default = "Bibata-Modern-Classic";
 8      };
 9      package = lib.mkOption {
10        type = lib.types.nullOr (lib.types.functionTo lib.types.package);
11        # default = null;
12        default = pkgs: pkgs.bibata-cursors;
13      };
14      size = lib.mkOption {
15        type = lib.types.ints.positive;
16        default = 24;
17      };
18    };
19
20    nixos = {host, ...}: let
21      cfg = host.settings.desktop.aesthetic.cursor;
22      allOrNothing = (cfg.name != null) == (cfg.package != null);
23    in {
24      assertions = [
25        {
26          assertion = allOrNothing;
27          message = "desktop.aesthetic.cursor: name/package/size must be set all or none.";
28        }
29      ];
30
31      environment.variables = {
32        XCURSOR_SIZE = toString cfg.size;
33      };
34    };
35
36    provides.to-users.hjem = {
37      host,
38      pkgs,
39      config,
40      ...
41    }: let
42      cfg = host.settings.desktop.aesthetic.cursor;
43
44      defaultIndexThemePackage = pkgs.writeTextFile {
45        name = "index.theme";
46        destination = "/share/icons/default/index.theme";
47        # Set name in icons theme, for compatibility with AwesomeWM etc. See:
48        # https://github.com/nix-community/home-manager/issues/2081
49        # https://wiki.archlinux.org/title/Cursor_themes#XDG_specification
50        text = ''
51          [Icon Theme]
52          Name=Default
53          Comment=Default Cursor Theme
54          Inherits=${cfg.name}
55        '';
56      };
57    in
58      lib.optionalAttrs (cfg.package != null && cfg.name != null) {
59        packages = [
60          (cfg.package pkgs)
61          defaultIndexThemePackage
62        ];
63
64        environment.sessionVariables = {
65          XCURSOR_THEME = cfg.name;
66          XCURSOR_SIZE = toString cfg.size;
67          XCURSOR_PATH = "${config.xdg.data.directory}/icons";
68        };
69
70        xdg.data.files = {
71          "icons/default/index.theme".source = "${defaultIndexThemePackage}/share/icons/default/index.theme";
72          "icons/${cfg.name}".source = "${cfg.package pkgs}/share/icons/${cfg.name}";
73        };
74        files = {
75          ".icons/default/index.theme".source = "${defaultIndexThemePackage}/share/icons/default/index.theme";
76          ".icons/${cfg.name}".source = "${cfg.package pkgs}/share/icons/${cfg.name}";
77          ".Xresources".text = ''
78            Xcursor.size: ${toString cfg.size}
79            Xcursor.theme: ${cfg.name}
80          '';
81        };
82      };
83  };
84}