Autorotate only in tablet mode

Added support for actions when entering/existing tablet mode for Home
Manager and fixed for NixOS
This commit is contained in:
Aleksandr Lebedev 2025-08-17 22:09:05 +02:00
parent 466cdb10b3
commit 1e9fc1d9d5
3 changed files with 112 additions and 59 deletions

View file

@ -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";
}
];
};
}

View file

@ -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"];
};
};
}

View file

@ -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"];
};
};
};
}