Files
omarchy-setup/bin/fix-stuck-displays
noconnorandClaude Opus 5 9ac198da26 Capture this laptop's Omarchy customizations
Everything on top of a stock Omarchy 4.0.4-1 install, gathered so a second
machine can be brought to the same state: the ~/.config files that actually
differ from the shipped defaults, the three hand-built themes, the ten shell
plugins pinned to commits, the two custom scripts, two user units, and the
/etc drop-ins.

install.sh applies it all idempotently, backing up anything it overwrites.
capture.sh runs the other way so the repo stays the source of truth rather
than a snapshot that rots.

indie.herdr-hud's ten local-only commits ship as a git bundle plus a
working-tree patch, since they stay off the upstream PR deliberately.

Secrets, the dotfiles repo's territory (shell/git/mise), the remote-access
stack and aether-managed themes are all scoped out; README says why for each.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-10-10 12:07:15 -04:00

54 lines
1.9 KiB
Bash
Executable File

#!/bin/bash
# Release display pipes the kernel left enabled on unplugged connectors.
#
# After suspend/resume (or unplugging a USB-C display) i915 can leave a
# connector "disconnected" but still "enabled" on a pipe that Hyprland has
# forgotten. That pipe then blocks every other external output from
# modesetting (black screens, or a ~5 s re-modeset loop).
#
# Fix: force the connector on so Hyprland sees it, disable it from Hyprland
# (which releases the pipe), force it off, then return it to auto-detect.
# Never `hyprctl reload` here: a reload re-enables the connector while it is
# forced on and re-sticks the pipe.
log() { echo "fix-stuck-displays: $*"; logger -t fix-stuck-displays -- "$*"; }
wait_for() { # wait_for <seconds> <command...>
local n=$(( $1 * 4 )); shift
for _ in $(seq "$n"); do "$@" && return 0; sleep 0.25; done
return 1
}
stuck=()
for d in /sys/class/drm/card*-*; do
[[ -f $d/status && -f $d/enabled ]] || continue
[[ $d == *eDP* ]] && continue
[[ $(<"$d/status") == disconnected && $(<"$d/enabled") == enabled ]] && stuck+=("$d")
done
if (( ${#stuck[@]} == 0 )); then
log "no stuck connectors"
exit 0
fi
systemctl --user stop hyprmoncfgd
for d in "${stuck[@]}"; do
out=${d##*/card*-}
log "releasing $out"
echo on | sudo -n tee "$d/status" >/dev/null
wait_for 5 sh -c "hyprctl monitors all | grep -q '^Monitor $out '" || log "$out never appeared in Hyprland"
hyprctl eval "hl.monitor({ output = \"$out\", disabled = true })" >/dev/null
wait_for 5 grep -qx disabled "$d/enabled" || log "$out still enabled after disable"
echo off | sudo -n tee "$d/status" >/dev/null
sleep 1
echo detect | sudo -n tee "$d/status" >/dev/null
log "$out now $(<"$d/status") $(<"$d/enabled")"
done
# Drop any low-refresh fallback hyprmoncfgd wrote while outputs were failing.
rm -f ~/.config/hyprmoncfg/display-fallbacks.json
# hyprmoncfgd re-applies the matching profile (modes, positions) on startup.
systemctl --user start hyprmoncfgd