Files
hyprland-hdmi-revive/docs/architecture.md
T

82 lines
2.3 KiB
Markdown

# Architecture
## Problem
A monitor shared between multiple physical HDMI inputs can keep its EDID/output state visible to Linux even while the monitor is displaying another source. When switching back, Hyprland may report the output as completely healthy while the physical monitor remains black or reports no source.
Typical Hyprland state in the broken condition:
```text
focused: yes
dpmsStatus: 1
disabled: false
active workspace: 1
```
Commands such as `hyprctl reload`, `hyprctl dispatch dpms on`, and `hyprctl dispatch focusmonitor` may all return `ok` without restoring the image.
## Discovery
Listening to Hyprland's event socket did not provide a reliable monitor add/remove event for the physical input switch.
The kernel DRM subsystem did, however, emit:
```text
SUBSYSTEM=drm
HOTPLUG=1
```
via:
```bash
udevadm monitor --kernel --property --subsystem-match=drm
```
A manual VT switch restored the image, indicating that the required reset happens below the compositor level.
## Final design
The long-running watcher consumes kernel DRM events. For every `HOTPLUG=1` event it:
1. checks `systemd-logind` for an active Wayland session belonging to the current user;
2. ignores the event if no such session exists;
3. dynamically determines that session's VT;
4. applies debounce protection;
5. calls the recovery script with the detected VT.
The recovery script:
1. uses `flock` to prevent overlap;
2. waits for the HDMI handshake to settle;
3. asks Hyprland to enable/focus the output;
4. uses `chvt` to move to another VT;
5. returns to the dynamically detected graphical VT;
6. refreshes Hyprland DPMS/focus once more.
## Why the Wayland-session guard is critical
GPU initialization during boot can generate DRM hotplug events. If the recovery script blindly executes a hard-coded `chvt 2` followed by `chvt 1`, the machine can end up showing tty1 even though the display manager is running on tty2.
The current implementation prevents this by requiring:
```text
Name=<current user>
Type=wayland
Active=yes
VTNr>0
```
before performing any recovery.
## Privilege boundary
The watcher and recovery script run as the normal user. Only `chvt` needs elevated privileges.
The recommended sudoers rule limits passwordless sudo to:
```text
/usr/bin/chvt
```
The script always calls it through `sudo -n`, which fails instead of prompting for a password.