Commit f34917b1 authored by Lin Jian's avatar Lin Jian Committed by pennae
Browse files

nixos/kanata: do not use path activation

Since 1.2.0, kanata handles missing keyboards well:
- only one keyboard need to be present when kanata starts;
- if linux-continue-if-no-devs-found is set to yes, all keyboards can
be missing at the beginning;
- all keyboards can be (un)pluged when kanata is running.

For simplicity, linux-continue-if-no-devs-found is set to yes and
systemd patch activation is removed.
parent efd1d7ed
Loading
Loading
Loading
Loading
+11 −56
Original line number Diff line number Diff line
@@ -11,16 +11,7 @@ let
        type = types.addCheck (types.listOf types.str)
          (devices: (length devices) > 0);
        example = [ "/dev/input/by-id/usb-0000_0000-event-kbd" ];
        # TODO replace note with tip, which has not been implemented yet in
        # nixos/lib/make-options-doc/mergeJSON.py
        description = mdDoc ''
          Paths to keyboard devices.

          ::: {.note}
          To avoid unnecessary triggers of the service unit, unplug devices in
          the order of the list.
          :::
        '';
        description = mdDoc "Paths to keyboard devices.";
      };
      config = mkOption {
        type = types.lines;
@@ -53,8 +44,12 @@ let
        default = "";
        example = "danger-enable-cmd yes";
        description = mdDoc ''
          Configuration of `defcfg` other than `linux-dev`. See [example
          config files](https://github.com/jtroo/kanata) for more information.
          Configuration of `defcfg` other than `linux-dev` (generated
          from the devices option) and
          `linux-continue-if-no-devs-found` (hardcoded to be yes).

          See [example config files](https://github.com/jtroo/kanata)
          for more information.
        '';
      };
      extraArgs = mkOption {
@@ -81,20 +76,14 @@ let
  mkConfig = name: keyboard: pkgs.writeText "${mkName name}-config.kdb" ''
    (defcfg
      ${keyboard.extraDefCfg}
      linux-dev ${mkDevices keyboard.devices})
      linux-dev ${mkDevices keyboard.devices}
      linux-continue-if-no-devs-found yes)

    ${keyboard.config}
  '';

  mkService = name: keyboard: nameValuePair (mkName name) {
    description = "kanata for ${mkDevices keyboard.devices}";

    # Because path units are used to activate service units, which
    # will start the old stopped services during "nixos-rebuild
    # switch", stopIfChanged here is a workaround to make sure new
    # services are running after "nixos-rebuild switch".
    stopIfChanged = false;

    wantedBy = [ "multi-user.target" ];
    serviceConfig = {
      ExecStart = ''
        ${cfg.package}/bin/kanata \
@@ -146,33 +135,6 @@ let
      UMask = "0077";
    };
  };

  mkPathName = i: name: "${mkName name}-${toString i}";

  mkPath = name: n: i: device:
    nameValuePair (mkPathName i name) {
      description =
        "${toString (i+1)}/${toString n} kanata trigger for ${name}, watching ${device}";
      wantedBy = optional (i == 0) "multi-user.target";
      pathConfig = {
        PathExists = device;
        # (ab)use systemd.path to construct a trigger chain so that the
        # service unit is only started when all paths exist
        # however, manual of systemd.path says Unit's suffix is not ".path"
        Unit =
          if (i + 1) == n
          then "${mkName name}.service"
          else "${mkPathName (i + 1) name}.path";
      };
      unitConfig.StopPropagatedFrom = optional (i > 0) "${mkName name}.service";
    };

  mkPaths = name: keyboard:
    let
      n = length keyboard.devices;
    in
    imap0 (mkPath name n) keyboard.devices
  ;
in
{
  options.services.kanata = {
@@ -201,14 +163,7 @@ in
  config = mkIf cfg.enable {
    hardware.uinput.enable = true;

    systemd = {
      paths = trivial.pipe cfg.keyboards [
        (mapAttrsToList mkPaths)
        concatLists
        listToAttrs
      ];
      services = mapAttrs' mkService cfg.keyboards;
    };
    systemd.services = mapAttrs' mkService cfg.keyboards;
  };

  meta.maintainers = with maintainers; [ linj ];