at 17.09-beta 3.3 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 7 cfg = config.services.actkbd; 8 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 ''; 17 18 bindingCfg = { config, ... }: { 19 options = { 20 21 keys = mkOption { 22 type = types.listOf types.int; 23 description = "List of keycodes to match."; 24 }; 25 26 events = mkOption { 27 type = types.listOf (types.enum ["key" "rep" "rel"]); 28 default = [ "key" ]; 29 description = "List of events to match."; 30 }; 31 32 attributes = mkOption { 33 type = types.listOf types.str; 34 default = [ "exec" ]; 35 description = "List of attributes."; 36 }; 37 38 command = mkOption { 39 type = types.str; 40 default = ""; 41 description = "What to run."; 42 }; 43 44 }; 45 }; 46 47in 48 49{ 50 51 ###### interface 52 53 options = { 54 55 services.actkbd = { 56 57 enable = mkOption { 58 type = types.bool; 59 default = false; 60 description = '' 61 Whether to enable the <command>actkbd</command> key mapping daemon. 62 63 Turning this on will start an <command>actkbd</command> 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 &lt;100 bytes of memory per 67 instance). 68 69 This allows binding keys globally without the need for e.g. 70 X11. 71 ''; 72 }; 73 74 bindings = mkOption { 75 type = types.listOf (types.submodule bindingCfg); 76 default = []; 77 example = lib.literalExample '' 78 [ { keys = [ 113 ]; events = [ "key" ]; command = "''${pkgs.alsaUtils}/bin/amixer -q set Master toggle"; } 79 ] 80 ''; 81 description = '' 82 Key bindings for <command>actkbd</command>. 83 84 See <command>actkbd</command> <filename>README</filename> for documentation. 85 86 The example shows a piece of what <option>sound.enableMediaKeys</option> does when enabled. 87 ''; 88 }; 89 90 extraConfig = mkOption { 91 type = types.lines; 92 default = ""; 93 description = '' 94 Literal contents to append to the end of actkbd configuration file. 95 ''; 96 }; 97 98 }; 99 100 }; 101 102 103 ###### implementation 104 105 config = mkIf cfg.enable { 106 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 }); 114 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 }; 127 128 # For testing 129 environment.systemPackages = [ pkgs.actkbd ]; 130 131 }; 132 133}