Files
sam_oneal 2b7b18c66d manage monitors with monique; reduce hypr-lid to lock/suspend timers
Add the monique GUI/daemon for monitor arrangement, hotplug profiles and
clamshell handling (writes monitors.lua, keybind SUPER+SHIFT+M, stowed
settings). hypr-lid is trimmed to hypr-lid-power: display management moved
to moniqued, it now only runs the delayed lock/suspend timers when the lid
is closed undocked. Update logind drop-in comments accordingly.
2026-08-14 21:25:38 -06:00

92 lines
2.6 KiB
Bash
Executable File

#!/usr/bin/env bash
# hypr-lid-power: delayed lock/suspend for the laptop lid.
#
# Display/clamshell/hotplug handling is owned by moniqued (see
# ~/.config/hypr/monitors.lua and moniqued's clamshell mode). This service only
# runs the power timers while the lid is closed with no external display
# attached:
# - lock after LOCK_SECONDS
# - suspend after SUSPEND_SECONDS
#
# Runs as a systemd user service (hypr-lid-power.service) and polls the lid +
# monitor state, so connecting/disconnecting a dock while the lid is closed is
# handled too. Lock/suspend use transient systemd timers, which pause during
# suspend and are recreated afterwards, so if the machine wakes while the lid
# stays closed it will sleep again after the full timeout.
set -uo pipefail
RUNTIME="/run/user/$(id -u)"
LOCK_SECONDS=60
SUSPEND_SECONDS=600
POLL_SECONDS=2
log() { printf '[hypr-lid-power] %s %s\n' "$(date '+%H:%M:%S')" "$*"; }
# Run hyprctl against the active Hyprland instance, if any.
hypr() {
local sig=""
for d in "$RUNTIME"/hypr/*/; do
if [ -S "$d/.socket.sock" ]; then
sig="$(basename "$d")"
break
fi
done
[ -n "$sig" ] || return 1
HYPRLAND_INSTANCE_SIGNATURE="$sig" command hyprctl "$@"
}
lid_closed() {
local state
state="$(cat /proc/acpi/button/lid/*/state 2>/dev/null)" || return 1
[[ "$state" == *closed* ]]
}
# True when Hyprland has any output up that is not the built-in panel/headless.
has_external() {
hypr monitors -j 2>/dev/null | grep '"name": "' | grep -qvE '"(eDP|HEADLESS)-'
}
stop_timers() {
systemctl --user stop hypr-lid-lock.timer hypr-lid-suspend.timer 2>/dev/null || true
}
# Re-create the named timer unless it is already waiting. Transient timers are
# collected after they fire, so this also restarts them after a suspend.
ensure_timer() {
local name="$1" seconds="$2"
shift 2
if ! systemctl --user --quiet is-active "hypr-lid-$name.timer"; then
systemd-run --user --quiet --unit="hypr-lid-$name" --on-active="${seconds}s" --collect "$@"
fi
}
powering=no
while true; do
if ! hypr monitors >/dev/null 2>&1; then
# No Hyprland running (e.g. another compositor, or before first launch).
powering=no
sleep 3
continue
fi
want_power="no"
if lid_closed && ! has_external; then
want_power="yes"
fi
if [ "$want_power" != "$powering" ]; then
log "power mode: $powering -> $want_power"
if [ "$want_power" = "yes" ]; then
ensure_timer lock "$LOCK_SECONDS" loginctl lock-sessions
ensure_timer suspend "$SUSPEND_SECONDS" systemctl suspend
else
stop_timers
fi
powering="$want_power"
fi
sleep "$POLL_SECONDS"
done