feat(power): clamshell — ignore lid suspend when docked (#86)
Some checks failed
Check / eval (push) Has been cancelled

Explicit HandleLidSwitchDocked=ignore under services.logind so closing
the lid with an external display connected does not suspend. Undocked
lid path left to upstream defaults. checks.clamshell-logind asserts the
baked logind.conf and active logind; real multi-monitor lid V3 queued.

Verified: V2 — flake check --no-build; checks.clamshell-logind green.
V3 pending: HARDWARE-QUEUE #86 lid+external on a laptop.
This commit is contained in:
Bernardo Magri
2026-07-11 10:32:18 +01:00
parent ce05eed754
commit 27f18e4ccc
9 changed files with 73 additions and 13 deletions

View File

@@ -510,6 +510,33 @@
'';
};
# Clamshell / dock lid policy (#86): logind must ignore lid close
# when docked (external display present). Real multi-monitor lid
# events stay V3; this asserts the baked logind.conf + that
# logind is alive to consume it. Imports options + power only.
clamshell-logind = pkgs.testers.runNixOSTest {
name = "nomarchy-clamshell-logind";
nodes.machine = { ... }: {
imports = [ ./modules/nixos/options.nix ./modules/nixos/power.nix ];
nomarchy.system.power = {
enable = true;
laptop = true;
};
};
testScript = ''
machine.wait_for_unit("multi-user.target")
machine.wait_for_unit("systemd-logind.service")
conf = machine.succeed("cat /etc/systemd/logind.conf")
assert "HandleLidSwitchDocked=ignore" in conf.replace(" ", ""), (
f"clamshell: logind.conf missing HandleLidSwitchDocked=ignore:\n{conf}"
)
# logind must be running (policy is dead if the unit is down).
machine.succeed("systemctl is-active systemd-logind.service")
# busctl property: Docked lid policy is not always exported;
# re-read conf after logind start is enough for the contract.
'';
};
# Runtime VM check for the battery-charge-limit re-apply: the udev
# rule must restart the oneshot on an AC state change (firmware can
# clear the threshold on unplug). The `test_power` module fakes a