nixos/preload: init
[NixPkgs.git] / nixos / modules / services / hardware / triggerhappy.nix
blob54eac70643ffccd85fdedcb0231277a692888979
1 { config, lib, pkgs, ... }:
3 with lib;
5 let
7   cfg = config.services.triggerhappy;
9   socket = "/run/thd.socket";
11   configFile = pkgs.writeText "triggerhappy.conf" ''
12     ${concatMapStringsSep "\n"
13       ({ keys, event, cmd, ... }:
14         ''${concatMapStringsSep "+" (x: "KEY_" + x) keys} ${toString { press = 1; hold = 2; release = 0; }.${event}} ${cmd}''
15       )
16       cfg.bindings}
17     ${cfg.extraConfig}
18   '';
20   bindingCfg = { ... }: {
21     options = {
23       keys = mkOption {
24         type = types.listOf types.str;
25         description = lib.mdDoc "List of keys to match.  Key names as defined in linux/input-event-codes.h";
26       };
28       event = mkOption {
29         type = types.enum ["press" "hold" "release"];
30         default = "press";
31         description = lib.mdDoc "Event to match.";
32       };
34       cmd = mkOption {
35         type = types.str;
36         description = lib.mdDoc "What to run.";
37       };
39     };
40   };
46   ###### interface
48   options = {
50     services.triggerhappy = {
52       enable = mkOption {
53         type = types.bool;
54         default = false;
55         description = lib.mdDoc ''
56           Whether to enable the {command}`triggerhappy` hotkey daemon.
57         '';
58       };
60       user = mkOption {
61         type = types.str;
62         default = "nobody";
63         example = "root";
64         description = lib.mdDoc ''
65           User account under which {command}`triggerhappy` runs.
66         '';
67       };
69       bindings = mkOption {
70         type = types.listOf (types.submodule bindingCfg);
71         default = [];
72         example = lib.literalExpression ''
73           [ { keys = ["PLAYPAUSE"];  cmd = "''${pkgs.mpc-cli}/bin/mpc -q toggle"; } ]
74         '';
75         description = lib.mdDoc ''
76           Key bindings for {command}`triggerhappy`.
77         '';
78       };
80       extraConfig = mkOption {
81         type = types.lines;
82         default = "";
83         description = lib.mdDoc ''
84           Literal contents to append to the end of {command}`triggerhappy` configuration file.
85         '';
86       };
88     };
90   };
93   ###### implementation
95   config = mkIf cfg.enable {
97     systemd.sockets.triggerhappy = {
98       description = "Triggerhappy Socket";
99       wantedBy = [ "sockets.target" ];
100       socketConfig.ListenDatagram = socket;
101     };
103     systemd.services.triggerhappy = {
104       wantedBy = [ "multi-user.target" ];
105       description = "Global hotkey daemon";
106       serviceConfig = {
107         ExecStart = "${pkgs.triggerhappy}/bin/thd ${optionalString (cfg.user != "root") "--user ${cfg.user}"} --socket ${socket} --triggers ${configFile} --deviceglob /dev/input/event*";
108       };
109     };
111     services.udev.packages = lib.singleton (pkgs.writeTextFile {
112       name = "triggerhappy-udev-rules";
113       destination = "/etc/udev/rules.d/61-triggerhappy.rules";
114       text = ''
115         ACTION=="add", SUBSYSTEM=="input", KERNEL=="event[0-9]*", ATTRS{name}!="triggerhappy", \
116           RUN+="${pkgs.triggerhappy}/bin/th-cmd --socket ${socket} --passfd --udev"
117       '';
118     });
120   };