From 1e9fc1d9d5bf253589cc202fe4a1c54d7419f189 Mon Sep 17 00:00:00 2001 From: Aleksandr Lebedev Date: Sun, 17 Aug 2025 22:09:05 +0200 Subject: [PATCH] Autorotate only in tablet mode Added support for actions when entering/existing tablet mode for Home Manager and fixed for NixOS --- homes/x86_64-linux/kylekrein/niri/niri.nix | 18 +++- modules/home/hardware/tablet/default.nix | 57 +++++++++++++ modules/nixos/hardware/tablet/default.nix | 96 +++++++++------------- 3 files changed, 112 insertions(+), 59 deletions(-) create mode 100644 modules/home/hardware/tablet/default.nix diff --git a/homes/x86_64-linux/kylekrein/niri/niri.nix b/homes/x86_64-linux/kylekrein/niri/niri.nix index de77281..e286d8f 100644 --- a/homes/x86_64-linux/kylekrein/niri/niri.nix +++ b/homes/x86_64-linux/kylekrein/niri/niri.nix @@ -290,7 +290,7 @@ in Description = "Makes sure that you have touchscreen gestures."; }; Install = { - WantedBy = ["default.target"]; + WantedBy = ["graphical.target"]; }; Service = { ExecStart = "${pkgs.writeShellScript "run-lisgd" '' @@ -305,7 +305,7 @@ in Description = "Adds auto rotation to Niri."; }; Install = { - WantedBy = ["default.target"]; + WantedBy = ["graphical.target"]; }; Service = { ExecStart = "${pkgs.writeShellScript "autorotate" '' @@ -342,4 +342,18 @@ in RestartSec = 5; }; }; + custom.hardware.tablet = { + onTabletModeEnable = [ + { + name = "autorotate"; + command = "systemctl --user start autorotate-niri.service"; + } + ]; + onTabletModeDisable = [ + { + name = "autorotate"; + command = "systemctl --user stop autorotate-niri.service"; + } + ]; + }; } diff --git a/modules/home/hardware/tablet/default.nix b/modules/home/hardware/tablet/default.nix new file mode 100644 index 0000000..c275f00 --- /dev/null +++ b/modules/home/hardware/tablet/default.nix @@ -0,0 +1,57 @@ +{ + lib, + pkgs, + inputs, + namespace, + system, + target, + format, + virtual, + systems, + config, + osConfig, + ... +}: +with lib; +with lib.${namespace}; let + cfg = config.${namespace}.hardware.tablet; + osCfg = osConfig.${namespace}.hardware.tablet; +in { + options.${namespace}.hardware.tablet = with types; { + enable = mkBoolOpt osCfg.enable "Enable tablet module for hardware that supports it"; + path = mkOpt path osCfg.path "Path with a file, where it's stated, whether tablet mode 'on' or 'off'"; + onTabletModeEnable = mkOpt (listOf (attrsOf str)) [] "Actions to do when entering tablet mode. Should have name and command string attributes."; + onTabletModeDisable = mkOpt (listOf (attrsOf str)) [] "Actions to do when exiting tablet mode. Should have name and command string attributes."; + }; + + config = mkIf cfg.enable { + systemd.user.services.tablet-mode-watcher = { + Service = { + Type = "oneshot"; + ExecStart = pkgs.writeShellScript "tablet-mode-watcher" '' + state=$(${pkgs.coreutils}/bin/cat "${cfg.path}" 2>/dev/null || echo 0) + + if [ "$state" -eq 1 ]; then + echo "Tablet mode ON" + ${concatStringsSep "\n" (map (cmd: '' + systemd-run --user --unit=tablet-on-${cmd.name} --collect sh -c '${cmd.command}' + '') + cfg.onTabletModeEnable)} + else + echo "Tablet mode OFF" + ${concatStringsSep "\n" (map (cmd: '' + systemd-run --user --unit=tablet-off-${cmd.name} --collect sh -c '${cmd.command}' + '') + cfg.onTabletModeDisable)} + fi + ''; + }; + }; + + systemd.user.paths.tablet-mode-watcher = { + Unit.Description = "Watch for tablet mode changes"; + Path.PathChanged = cfg.path; + Install.WantedBy = ["default.target"]; + }; + }; +} diff --git a/modules/nixos/hardware/tablet/default.nix b/modules/nixos/hardware/tablet/default.nix index ee9114e..016da8c 100644 --- a/modules/nixos/hardware/tablet/default.nix +++ b/modules/nixos/hardware/tablet/default.nix @@ -25,64 +25,46 @@ in { config = mkIf cfg.enable { # 1. System service for watching - systemd.services = - { - tablet-mode-watcher = { - description = "Watch for tablet mode changes"; - serviceConfig = { - ExecStart = "${pkgs.writeShellScript "tablet-mode-eventd" '' - in_tablet_mode=$(${pkgs.coreutils}/bin/cat "${cfg.path}" 2>/dev/null || $(echo 0 > "${cfg.path}" && echo 0)) + systemd.services = { + tablet-mode-watcher = { + description = "Watch for tablet mode changes"; + serviceConfig = { + ExecStart = "${pkgs.writeShellScript "tablet-mode-eventd" '' + if [ -f "${cfg.path}" ]; then + in_tablet_mode=$(${pkgs.coreutils}/bin/cat "${cfg.path}") + else + echo 0 > "${cfg.path}" + in_tablet_mode=0 + fi - stdbuf -oL -eL ${lib.getExe pkgs.libinput} debug-events --device "${cfg.inputDevice}" | while read -r line; do - if [[ "$line" =~ switch\ tablet-mode\ state\ ([01]) ]]; then - d="''${BASH_REMATCH[1]}" - if [ "$d" -ne "$in_tablet_mode" ]; then - in_tablet_mode=$d - if [ "$d" -eq 1 ]; then - systemctl start tablet-on.target - echo "Tablet mode ON" - echo 1 > "${cfg.path}" - else - systemctl start tablet-off.target - echo "Tablet mode OFF" - echo 0 > "${cfg.path}" - fi - fi - fi - done - ''}"; - Restart = "always"; - }; - wantedBy = ["graphical.target"]; + stdbuf -oL -eL ${lib.getExe pkgs.libinput} debug-events --device "${cfg.inputDevice}" | while read -r line; do + if [[ "$line" =~ switch\ tablet-mode\ state\ ([01]) ]]; then + d="''${BASH_REMATCH[1]}" + if [ "$d" -ne "$in_tablet_mode" ]; then + in_tablet_mode=$d + if [ "$d" -eq 1 ]; then + ${concatStringsSep "\n" (map (cmd: '' + systemd-run --unit=tablet-on-${cmd.name} --collect sh -c '${cmd.command}' + '') + cfg.onTabletModeEnable)} + echo "Tablet mode ON" + echo 1 > "${cfg.path}" + else + ${concatStringsSep "\n" (map (cmd: '' + systemd-run --unit=tablet-off-${cmd.name} --collect sh -c '${cmd.command}' + '') + cfg.onTabletModeDisable)} + echo "Tablet mode OFF" + echo 0 > "${cfg.path}" + fi + fi + fi + done + ''}"; + Restart = "always"; }; - } - // (lib.listToAttrs (map (cmd: { - name = "tablet-action-on-${cmd.name}"; - value = { - Unit.PartOf = ["tablet-on.target"]; - Service = { - Type = "oneshot"; - ExecStart = "sh -c ${cmd.command}"; - }; - Install.WantedBy = ["tablet-on.target"]; - }; - }) - cfg.onTabletModeEnable)) - // (lib.listToAttrs (map (cmd: { - name = "tablet-action-off-${cmd.name}"; - value = { - Unit.PartOf = ["tablet-off.target"]; - Service = { - Type = "oneshot"; - ExecStart = "sh -c ${cmd.command}"; - }; - Install.WantedBy = ["tablet-off.target"]; - }; - }) - cfg.onTabletModeDisable)); - - # 2. System targets - systemd.targets.tablet-on = {}; - systemd.targets.tablet-off = {}; + wantedBy = ["graphical.target"]; + }; + }; }; }