macbook: lock before suspend via sleep.target unit; fix dpms lua syntax

This commit is contained in:
rope 2026-08-16 13:15:42 +01:00
parent cf6b7a36a1
commit dd7ba284f7

View file

@ -62,6 +62,29 @@ in
libcanberra-gtk3
];
# Lock *before* the machine actually suspends. hypridle's
# before_sleep_cmd cannot do this: it spawns the command and releases
# its sleep inhibitor in the same breath (journal: "Executing …" then
# "Releasing the sleep inhibitor!" on the same second), so the qs
# process gets frozen mid-lock and only finishes on resume — the lid
# opens showing the pre-suspend desktop for a beat before the lock
# paints. A unit ordered Before=sleep.target genuinely blocks the
# suspend until it exits. The sleep covers the gap between quickshell
# accepting the IPC and the lock surface committing a frame.
systemd.services.lock-before-sleep = lib.mkIf isMacbook {
description = "Lock the session before suspend";
before = [ "sleep.target" ];
wantedBy = [ "sleep.target" ];
serviceConfig = {
Type = "oneshot";
User = "fred";
Environment = "XDG_RUNTIME_DIR=/run/user/%U";
ExecStart = "${pkgs.quickshell}/bin/qs ipc call lock lock";
ExecStartPost = "${pkgs.coreutils}/bin/sleep 1";
TimeoutStartSec = "5s";
};
};
home-manager.users.fred = { config, lib, pkgs, inputs, ... }:
let
c = config.lib.stylix.colors;
@ -435,17 +458,10 @@ in
settings = {
general = {
lock_cmd = "qs ipc call lock lock";
# Lock directly, not via `loginctl lock-session`: hypridle waits
# for before_sleep_cmd to exit before releasing its sleep
# inhibitor, but the loginctl → logind Lock signal → lock_cmd
# detour is async and the box can suspend unlocked. Lid close
# (HandleLidSwitch=suspend) goes through here too.
# The sleep is not padding: `qs ipc call` returns once the
# handler sets locked=true, before the lock surface has
# committed a frame. Without it the box freezes mid-transition
# and the pre-lock frame flashes on resume.
before_sleep_cmd = "qs ipc call lock lock; sleep 1";
after_sleep_cmd = "hyprctl dispatch dpms on";
# No before_sleep_cmd: hypridle does not wait for it before
# dropping its sleep inhibitor, so the lock lands after resume.
# systemd.services.lock-before-sleep handles suspend instead.
after_sleep_cmd = "hyprctl dispatch 'hl.dsp.dpms({ action = \"on\" })'";
};
listener = [
{
@ -454,8 +470,11 @@ in
}
{
timeout = 420; # 7 min — display off
on-timeout = unlessPlaying "hyprctl dispatch dpms off";
on-resume = "hyprctl dispatch dpms on";
# Lua config manager: `hyprctl dispatch X` evaluates
# `hl.dispatch(X)`, and a non-table arg parses as "toggle",
# so the action has to be spelled out in a table.
on-timeout = unlessPlaying "hyprctl dispatch 'hl.dsp.dpms({ action = \"off\" })'";
on-resume = "hyprctl dispatch 'hl.dsp.dpms({ action = \"on\" })'";
}
{
timeout = 600; # 10 min — suspend