Import initial Hyprland HDMI recovery implementation

This commit is contained in:
admin committed 2026-09-23 09:10:57 +02:00
commit 73e727ef4c
19 files changed
+1041

No files matched your search

+35
View File
@@ -0,0 +1,35 @@
#!/usr/bin/env bash
set -euo pipefail
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
BIN_DIR="$HOME/.local/bin"
SYSTEMD_DIR="$HOME/.config/systemd/user"
CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/revive-monitor"
mkdir -p "$BIN_DIR" "$SYSTEMD_DIR" "$CONFIG_DIR"
install -m 0755 "$REPO_ROOT/scripts/revive-monitor-fix.sh" "$BIN_DIR/revive-monitor-fix"
install -m 0755 "$REPO_ROOT/scripts/revive-monitor-drm-watch.sh" "$BIN_DIR/revive-monitor-drm-watch"
install -m 0644 "$REPO_ROOT/systemd/user/revive-monitor-drm-watch.service" "$SYSTEMD_DIR/revive-monitor-drm-watch.service"
if [[ ! -e "$CONFIG_DIR/config.env" ]]; then
install -m 0644 "$REPO_ROOT/config/revive-monitor.env.example" "$CONFIG_DIR/config.env"
printf 'Created %s\n' "$CONFIG_DIR/config.env"
printf 'Edit MONITOR before using the service if your output is not HDMI-A-2.\n'
else
printf 'Keeping existing config: %s\n' "$CONFIG_DIR/config.env"
fi
systemctl --user daemon-reload
systemctl --user enable --now revive-monitor-drm-watch.service
cat <<'MSG'
Installed successfully.
Next steps:
1. Verify ~/.config/revive-monitor/config.env
2. Configure /etc/sudoers.d/revive-monitor-chvt using one of the templates in sudoers/
3. Test with: systemctl --user status revive-monitor-drm-watch.service
4. Watch logs: journalctl --user -u revive-monitor-drm-watch.service -f
MSG
+115
View File
@@ -0,0 +1,115 @@
#!/usr/bin/env bash
set -u
LOGTAG="revive-monitor-drm-watch"
CONFIG_FILE="${XDG_CONFIG_HOME:-$HOME/.config}/revive-monitor/config.env"
FIX_SCRIPT="${REVIVE_MONITOR_FIX_SCRIPT:-$HOME/.local/bin/revive-monitor-fix}"
# Defaults. Override in ~/.config/revive-monitor/config.env
DEBOUNCE_SECONDS="30"
if [[ -r "$CONFIG_FILE" ]]; then
# shellcheck disable=SC1090
source "$CONFIG_FILE"
fi
STATE_DIR="${XDG_RUNTIME_DIR:-/tmp}/revive-monitor"
LAST_RUN_FILE="$STATE_DIR/last-drm-hotplug-run"
mkdir -p "$STATE_DIR"
log() {
logger -t "$LOGTAG" -- "$*"
}
get_active_wayland_session() {
local sid
local name
local type
local active
local vt
while read -r sid; do
[[ -n "$sid" ]] || continue
name="$(loginctl show-session "$sid" -p Name --value 2>/dev/null)"
[[ "$name" == "$USER" ]] || continue
type="$(loginctl show-session "$sid" -p Type --value 2>/dev/null)"
[[ "$type" == "wayland" ]] || continue
active="$(loginctl show-session "$sid" -p Active --value 2>/dev/null)"
[[ "$active" == "yes" ]] || continue
vt="$(loginctl show-session "$sid" -p VTNr --value 2>/dev/null)"
if [[ "$vt" =~ ^[1-9][0-9]*$ ]]; then
printf '%s:%s\n' "$sid" "$vt"
return 0
fi
done < <(
loginctl list-sessions --no-legend --no-pager 2>/dev/null | awk '{print $1}'
)
return 1
}
run_recovery() {
local session_info
local session_id
local graphical_vt
local now
local last="0"
local diff
if ! session_info="$(get_active_wayland_session)"; then
log "No active Wayland session - DRM hotplug ignored"
return 0
fi
session_id="${session_info%%:*}"
graphical_vt="${session_info##*:}"
now="$(date +%s)"
if [[ -r "$LAST_RUN_FILE" ]]; then
last="$(cat "$LAST_RUN_FILE" 2>/dev/null || printf '0')"
fi
[[ "$last" =~ ^[0-9]+$ ]] || last="0"
diff=$((now - last))
if (( diff < DEBOUNCE_SECONDS )); then
log "DRM hotplug ignored because of debounce (${diff}s)"
return 0
fi
printf '%s\n' "$now" > "$LAST_RUN_FILE"
log "DRM hotplug detected - Wayland session $session_id on VT $graphical_vt"
"$FIX_SCRIPT" "$graphical_vt"
log "Recovery after DRM hotplug finished"
}
if ! command -v udevadm >/dev/null 2>&1; then
log "udevadm not found"
exit 1
fi
if [[ ! -x "$FIX_SCRIPT" ]]; then
log "Recovery script is not executable: $FIX_SCRIPT"
exit 1
fi
log "Listening for DRM hotplug events"
stdbuf -oL udevadm monitor --kernel --property --subsystem-match=drm |
while IFS= read -r line; do
case "$line" in
HOTPLUG=1)
run_recovery
;;
esac
done
+77
View File
@@ -0,0 +1,77 @@
#!/usr/bin/env bash
set -u
LOGTAG="revive-monitor-fix"
CONFIG_FILE="${XDG_CONFIG_HOME:-$HOME/.config}/revive-monitor/config.env"
# Defaults. Override in ~/.config/revive-monitor/config.env
MONITOR="HDMI-A-2"
HDMI_SETTLE_SECONDS="5"
VT_SWITCH_DELAY_SECONDS="1"
VT_RETURN_SETTLE_SECONDS="2"
if [[ -r "$CONFIG_FILE" ]]; then
# shellcheck disable=SC1090
source "$CONFIG_FILE"
fi
GRAPHICAL_VT="${1:-}"
STATE_DIR="${XDG_RUNTIME_DIR:-/tmp}/revive-monitor"
LOCK_FILE="$STATE_DIR/fix.lock"
mkdir -p "$STATE_DIR"
log() {
logger -t "$LOGTAG" -- "$*"
}
run_quiet() {
"$@" >/dev/null 2>&1
}
if ! [[ "$GRAPHICAL_VT" =~ ^[1-9][0-9]*$ ]]; then
log "No valid graphical VT supplied - recovery aborted"
exit 0
fi
if [[ "$GRAPHICAL_VT" -eq 1 ]]; then
TEMP_VT=2
else
TEMP_VT=1
fi
exec 9>"$LOCK_FILE"
if ! flock -n 9; then
log "Recovery already running - skipping"
exit 0
fi
log "Recovery started for $MONITOR on VT $GRAPHICAL_VT"
sleep "$HDMI_SETTLE_SECONDS"
run_quiet hyprctl dispatch dpms on "$MONITOR"
run_quiet hyprctl dispatch focusmonitor "$MONITOR"
sleep 1
log "VT refresh: $TEMP_VT -> $GRAPHICAL_VT"
if ! sudo -n /usr/bin/chvt "$TEMP_VT"; then
log "Failed to switch to temporary VT $TEMP_VT"
exit 1
fi
sleep "$VT_SWITCH_DELAY_SECONDS"
if ! sudo -n /usr/bin/chvt "$GRAPHICAL_VT"; then
log "Failed to return to graphical VT $GRAPHICAL_VT"
exit 1
fi
sleep "$VT_RETURN_SETTLE_SECONDS"
run_quiet hyprctl dispatch dpms on "$MONITOR"
run_quiet hyprctl dispatch focusmonitor "$MONITOR"
log "Recovery completed for $MONITOR"
+24
View File
@@ -0,0 +1,24 @@
#!/usr/bin/env bash
set -euo pipefail
BIN_DIR="$HOME/.local/bin"
SYSTEMD_DIR="$HOME/.config/systemd/user"
systemctl --user disable --now revive-monitor-drm-watch.service 2>/dev/null || true
rm -f "$SYSTEMD_DIR/revive-monitor-drm-watch.service"
rm -f "$BIN_DIR/revive-monitor-fix"
rm -f "$BIN_DIR/revive-monitor-drm-watch"
systemctl --user daemon-reload
systemctl --user reset-failed
cat <<'MSG'
Removed the user service and installed scripts.
Not removed automatically:
~/.config/revive-monitor/config.env
/etc/sudoers.d/revive-monitor-chvt
Remove those manually if you no longer need them.
MSG