All checks were successful
Check / eval (push) Successful in 3m44s
Recover from DPMS/lock blackout without a second machine: undock/enable always issue dpms on; hypridle on-resume and after_sleep run nomarchy-display-wake (zero-output undock rescue + auto-dump). nomarchy-display-dump writes ~/nomarchy-display-dump-*.txt (SUPER+SHIFT+D or Ctrl+Alt+F3 TTY). HARDWARE-QUEUE #127 no longer requires SSH. V1: nix flake check --no-build. V3: docked idle on AMD box still open.
104 lines
4.4 KiB
Nix
104 lines
4.4 KiB
Nix
# Shared display recovery helpers (#127). Used by hyprland.nix (PATH +
|
|
# undock dump) and idle.nix (hypridle on-resume / after_sleep absolute paths).
|
|
#
|
|
# dump — evidence to ~/nomarchy-display-dump-*.txt without SSH
|
|
# wake — dpms on + zero-output undock rescue + dump if still dark
|
|
# Pass displayTransition so wake pins the same binary hyprland ships.
|
|
# Call once with only pkgs to get dump (transition not ready yet), then
|
|
# again with displayTransition for wake.
|
|
{ pkgs, displayTransition ? null }:
|
|
|
|
let
|
|
dump = pkgs.writeShellScriptBin "nomarchy-display-dump" ''
|
|
set -u
|
|
reason="''${1:-manual}"
|
|
stamp=$(date +%Y%m%d-%H%M%S)
|
|
out="''${HOME:-/tmp}/nomarchy-display-dump-''${stamp}.txt"
|
|
{
|
|
echo "=== nomarchy-display-dump reason=$reason ==="
|
|
echo "date: $(date -Is 2>/dev/null || date)"
|
|
echo "user: $(id -un 2>/dev/null || echo ?)"
|
|
echo "HYPRLAND_INSTANCE_SIGNATURE=''${HYPRLAND_INSTANCE_SIGNATURE:-}"
|
|
echo
|
|
echo "=== hyprctl monitors (enabled) ==="
|
|
hyprctl monitors -j 2>&1 || true
|
|
echo
|
|
echo "=== hyprctl monitors all ==="
|
|
hyprctl monitors all -j 2>&1 || true
|
|
echo
|
|
echo "=== hyprctl workspaces ==="
|
|
hyprctl workspaces -j 2>&1 || true
|
|
echo
|
|
echo "=== hyprctl devices (keyboards) ==="
|
|
hyprctl devices -j 2>/dev/null | ${pkgs.jq}/bin/jq '.keyboards // .' 2>&1 || true
|
|
echo
|
|
echo "=== systemd-inhibit --list ==="
|
|
${pkgs.systemd}/bin/systemd-inhibit --list 2>&1 || true
|
|
echo
|
|
echo "=== DRM connector status ==="
|
|
for s in /sys/class/drm/*/status; do
|
|
[ -r "$s" ] || continue
|
|
echo "$s: $(cat "$s" 2>/dev/null)"
|
|
done
|
|
echo
|
|
echo "=== journal user display/idle (last 100) ==="
|
|
journalctl --user -t nomarchy-display-watch -t nomarchy-display-transition \
|
|
-t nomarchy-display-wake -t hypridle -t hyprlock -n 100 --no-pager 2>&1 || true
|
|
echo
|
|
echo "=== journal -b suspend/sleep/dpms (last 80 matching) ==="
|
|
journalctl -b --no-pager 2>/dev/null \
|
|
| ${pkgs.gnugrep}/bin/grep -iE 'Suspending|PM: suspend|PM: hibernate|dpms|sleep\.target|systemd-sleep' \
|
|
| ${pkgs.coreutils}/bin/tail -n 80 || true
|
|
} >"$out" 2>&1
|
|
${pkgs.util-linux}/bin/logger -t nomarchy-display-dump -- "reason=$reason wrote $out"
|
|
command -v notify-send >/dev/null 2>&1 \
|
|
&& notify-send "Display dump" "$out" 2>/dev/null || true
|
|
printf '%s\n' "$out"
|
|
'';
|
|
|
|
wake =
|
|
if displayTransition == null then null
|
|
else pkgs.writeShellScriptBin "nomarchy-display-wake" ''
|
|
set -u
|
|
LOGGER=${pkgs.util-linux}/bin/logger
|
|
log() { "$LOGGER" -t nomarchy-display-wake -- "$*"; }
|
|
TRANSITION=${displayTransition}/bin/nomarchy-display-transition
|
|
DUMP=${dump}/bin/nomarchy-display-dump
|
|
hyprctl dispatch dpms on >/dev/null 2>&1 || true
|
|
enabled=$(hyprctl monitors -j 2>/dev/null | ${pkgs.jq}/bin/jq 'length' 2>/dev/null || echo 0)
|
|
case "$enabled" in *[!0-9]*|"") enabled=0 ;; esac
|
|
if [ "$enabled" -eq 0 ]; then
|
|
log "zero-enabled-outputs: attempting internal enable"
|
|
internal=$(hyprctl monitors all -j 2>/dev/null \
|
|
| ${pkgs.jq}/bin/jq -r '.[] | select(.name | test("^(eDP|LVDS|DSI)")) | .name' 2>/dev/null \
|
|
| ${pkgs.coreutils}/bin/head -n1)
|
|
if [ -n "$internal" ]; then
|
|
if "$TRANSITION" undock "$internal" 2>/dev/null; then
|
|
log "rescued via undock internal=$internal"
|
|
elif "$TRANSITION" enable "$internal" 2>/dev/null; then
|
|
log "rescued via enable internal=$internal"
|
|
else
|
|
log "rescue failed internal=$internal"
|
|
fi
|
|
else
|
|
log "no internal output in monitors all"
|
|
fi
|
|
hyprctl dispatch dpms on >/dev/null 2>&1 || true
|
|
enabled=$(hyprctl monitors -j 2>/dev/null | ${pkgs.jq}/bin/jq 'length' 2>/dev/null || echo 0)
|
|
case "$enabled" in *[!0-9]*|"") enabled=0 ;; esac
|
|
if [ "$enabled" -eq 0 ]; then
|
|
log "still zero-enabled: dumping"
|
|
"$DUMP" auto-zero-after-wake >/dev/null 2>&1 || true
|
|
fi
|
|
fi
|
|
first=$(hyprctl monitors -j 2>/dev/null \
|
|
| ${pkgs.jq}/bin/jq -r '.[0].name // empty' 2>/dev/null || true)
|
|
[ -n "$first" ] && hyprctl dispatch focusmonitor "$first" >/dev/null 2>&1 || true
|
|
log "done enabled=$enabled first=''${first:-none}"
|
|
'';
|
|
in
|
|
{
|
|
displayDumpTool = dump;
|
|
displayWakeTool = wake;
|
|
}
|