at 23.11-pre 3.0 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 7 cfg = config.services.triggerhappy; 8 9 socket = "/run/thd.socket"; 10 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 ''; 19 20 bindingCfg = { ... }: { 21 options = { 22 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 }; 27 28 event = mkOption { 29 type = types.enum ["press" "hold" "release"]; 30 default = "press"; 31 description = lib.mdDoc "Event to match."; 32 }; 33 34 cmd = mkOption { 35 type = types.str; 36 description = lib.mdDoc "What to run."; 37 }; 38 39 }; 40 }; 41 42in 43 44{ 45 46 ###### interface 47 48 options = { 49 50 services.triggerhappy = { 51 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 }; 59 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 }; 68 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 }; 79 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 }; 87 88 }; 89 90 }; 91 92 93 ###### implementation 94 95 config = mkIf cfg.enable { 96 97 systemd.sockets.triggerhappy = { 98 description = "Triggerhappy Socket"; 99 wantedBy = [ "sockets.target" ]; 100 socketConfig.ListenDatagram = socket; 101 }; 102 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 }; 110 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 }); 119 120 }; 121 122}