nixos/preload: init
[NixPkgs.git] / nixos / modules / services / hardware / actkbd.nix
blob1718d179bf5eb36b7b02170592f7d67dc5982ef2
1 { config, lib, pkgs, ... }:
3 with lib;
5 let
7   cfg = config.services.actkbd;
9   configFile = pkgs.writeText "actkbd.conf" ''
10     ${concatMapStringsSep "\n"
11       ({ keys, events, attributes, command, ... }:
12         ''${concatMapStringsSep "+" toString keys}:${concatStringsSep "," events}:${concatStringsSep "," attributes}:${command}''
13       )
14       cfg.bindings}
15     ${cfg.extraConfig}
16   '';
18   bindingCfg = { ... }: {
19     options = {
21       keys = mkOption {
22         type = types.listOf types.int;
23         description = lib.mdDoc "List of keycodes to match.";
24       };
26       events = mkOption {
27         type = types.listOf (types.enum ["key" "rep" "rel"]);
28         default = [ "key" ];
29         description = lib.mdDoc "List of events to match.";
30       };
32       attributes = mkOption {
33         type = types.listOf types.str;
34         default = [ "exec" ];
35         description = lib.mdDoc "List of attributes.";
36       };
38       command = mkOption {
39         type = types.str;
40         default = "";
41         description = lib.mdDoc "What to run.";
42       };
44     };
45   };
51   ###### interface
53   options = {
55     services.actkbd = {
57       enable = mkOption {
58         type = types.bool;
59         default = false;
60         description = lib.mdDoc ''
61           Whether to enable the {command}`actkbd` key mapping daemon.
63           Turning this on will start an {command}`actkbd`
64           instance for every evdev input that has at least one key
65           (which is okay even for systems with tiny memory footprint,
66           since actkbd normally uses \<100 bytes of memory per
67           instance).
69           This allows binding keys globally without the need for e.g.
70           X11.
71         '';
72       };
74       bindings = mkOption {
75         type = types.listOf (types.submodule bindingCfg);
76         default = [];
77         example = lib.literalExpression ''
78           [ { keys = [ 113 ]; events = [ "key" ]; command = "''${pkgs.alsa-utils}/bin/amixer -q set Master toggle"; }
79           ]
80         '';
81         description = lib.mdDoc ''
82           Key bindings for {command}`actkbd`.
84           See {command}`actkbd` {file}`README` for documentation.
86           The example shows a piece of what {option}`sound.mediaKeys.enable` does when enabled.
87         '';
88       };
90       extraConfig = mkOption {
91         type = types.lines;
92         default = "";
93         description = lib.mdDoc ''
94           Literal contents to append to the end of actkbd configuration file.
95         '';
96       };
98     };
100   };
103   ###### implementation
105   config = mkIf cfg.enable {
107     services.udev.packages = lib.singleton (pkgs.writeTextFile {
108       name = "actkbd-udev-rules";
109       destination = "/etc/udev/rules.d/61-actkbd.rules";
110       text = ''
111         ACTION=="add", SUBSYSTEM=="input", KERNEL=="event[0-9]*", ENV{ID_INPUT_KEY}=="1", TAG+="systemd", ENV{SYSTEMD_WANTS}+="actkbd@$env{DEVNAME}.service"
112       '';
113     });
115     systemd.services."actkbd@" = {
116       enable = true;
117       restartIfChanged = true;
118       unitConfig = {
119         Description = "actkbd on %I";
120         ConditionPathExists = "%I";
121       };
122       serviceConfig = {
123         Type = "forking";
124         ExecStart = "${pkgs.actkbd}/bin/actkbd -D -c ${configFile} -d %I";
125       };
126     };
128     # For testing
129     environment.systemPackages = [ pkgs.actkbd ];
131   };