ctucx.git: nixfiles

ctucx' nixfiles

1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 
40 
41 
42 
43 
44 
45 
46 
47 
48 
49 
50 
51 
52 
53 
54 
55 
56 
57 
58 
59 
60 
61 
62 
63 
64 
65 
66 
67 
68 
69 
70 
71 
72 
73 
74 
75 
76 
77 
78 
79 
80 
81 
82 
83 
84 
85 
86 
87 
88 
89 
90 
91 
92 
93 
94 
95 
96 
97 
98 
99 
100 
101 
102 
103 
104 
105 
106 
{ config, lib, pkgs, ... }:

with lib;

let
  cfg = config.hidutil;

  # convert hex to int with nix!
  hexToDec = hex: (builtins.fromTOML "a = 0x${removePrefix "0x" hex}").a;

in {
  ###### interface
  options = {
    hidutil = {

      enable = mkEnableOption "Enable key remapping powered by hidutil";

      remapKeys = mkOption {
        type = types.listOf (types.submodule {
          options = {

            VendorID = mkOption {
              type    = types.nullOr types.str;
              default = null;
            };

            ProductID = mkOption {
              type    = types.nullOr types.str;
              default = null;
            };

            LocationID = mkOption {
              type    = types.nullOr types.str;
              default = null;
            };

            UserKeyMapping = mkOption {
              type = types.listOf (types.submodule {
                options = {
                  HIDKeyboardModifierMappingSrc = mkOption {
                    type = types.int;
                  };
                  HIDKeyboardModifierMappingDst = mkOption {
                    type = types.int;
                  };
                };
              });
            };

          };
        });
        default = [];
      };

    };
  };

  ###### implementation
  config = mkIf cfg.enable {

    launchd.user.agents = builtins.listToAttrs (
      lib.remove "skip" (
        lib.forEach cfg.remapKeys (
          entry: (if (entry.LocationID != null) then "skip" else {
            name  = "activateUserKeyMapping-${entry.VendorID}:${entry.ProductID}";
            value.serviceConfig = {
              Disabled          = if (entry.VendorID != "5ac" && entry.ProductID != "281") then false else true;
              Label             = "org.nixos.activateUserKeyMapping-${entry.VendorID}:${entry.ProductID}";

              ProgramArguments  = [
                "${pkgs.XPCEventStreamHandler}/bin/xpc_set_event_stream_handler"
                "${pkgs.writeScript "hidutil" ''
                  #!/usr/bin/env bash
                  osascript -e 'display notification "Load UserKeyMapping for ${entry.VendorID}:${entry.ProductID}" with title "hidutil"'
                  hidutil property --matching '{"VendorID":0x${entry.VendorID},"ProductID":0x${entry.ProductID}' --set '{"UserKeyMapping":${builtins.toJSON entry.UserKeyMapping}}'  > /dev/null
                ''}"
              ];

              LaunchEvents = {
                "com.apple.iokit.matching" = {
                  "com.apple.device-attach" = {
                    IOMatchLaunchStream = true;
                    IOProviderClass     = "IOUSBDevice";
                    idVendor            = hexToDec entry.VendorID;
                    idProduct           = hexToDec entry.ProductID;
                  };
                };
              };
            };
          })
        )
      )
    );

    system.activationScripts.keyboard.text = ''
      # Configuring keyboard
      echo "configuring keyboard..." >&2
      ${lib.concatStringsSep "\n" (lib.forEach cfg.remapKeys (entry: (if entry.LocationID != null then
        "hidutil property --matching '{\"LocationID\":0x${entry.LocationID}}' --set '{\"UserKeyMapping\":${builtins.toJSON entry.UserKeyMapping}}' > /dev/null"
      else
        "hidutil property --matching '{\"VendorID\":0x${entry.VendorID},\"ProductID\":0x${entry.ProductID}}' --set '{\"UserKeyMapping\":${builtins.toJSON entry.UserKeyMapping}}' > /dev/null"
      )))}
    '';

  };
}