Import initial Hyprland HDMI recovery implementation
This commit is contained in:
commit
73e727ef4c
19 files changed
+1041
No files matched your search
@@ -0,0 +1,81 @@
|
||||
# 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.
|
||||
@@ -0,0 +1,139 @@
|
||||
# Troubleshooting
|
||||
|
||||
## Check the Hyprland output name
|
||||
|
||||
```bash
|
||||
hyprctl monitors
|
||||
```
|
||||
|
||||
Update:
|
||||
|
||||
```text
|
||||
~/.config/revive-monitor/config.env
|
||||
```
|
||||
|
||||
if the output is not `HDMI-A-2`.
|
||||
|
||||
## Check the user service
|
||||
|
||||
```bash
|
||||
systemctl --user status revive-monitor-drm-watch.service
|
||||
```
|
||||
|
||||
## Follow logs
|
||||
|
||||
```bash
|
||||
journalctl --user -u revive-monitor-drm-watch.service -f
|
||||
```
|
||||
|
||||
For the recovery script tag:
|
||||
|
||||
```bash
|
||||
journalctl --user -t revive-monitor-fix -f
|
||||
```
|
||||
|
||||
## Verify DRM hotplug events manually
|
||||
|
||||
```bash
|
||||
udevadm monitor --kernel --property --subsystem-match=drm
|
||||
```
|
||||
|
||||
Switch the physical monitor input away and back. Look for:
|
||||
|
||||
```text
|
||||
HOTPLUG=1
|
||||
```
|
||||
|
||||
If no DRM hotplug event is emitted, this project has no reliable event to trigger from.
|
||||
|
||||
## Verify the active Wayland session
|
||||
|
||||
```bash
|
||||
loginctl list-sessions
|
||||
```
|
||||
|
||||
Then:
|
||||
|
||||
```bash
|
||||
for s in $(loginctl list-sessions --no-legend | awk '{print $1}'); do
|
||||
echo "=== Session $s ==="
|
||||
loginctl show-session "$s" -p Name -p Type -p Active -p VTNr
|
||||
done
|
||||
```
|
||||
|
||||
A normal Hyprland session should look similar to:
|
||||
|
||||
```text
|
||||
Name=your-user
|
||||
VTNr=1
|
||||
Type=wayland
|
||||
Active=yes
|
||||
```
|
||||
|
||||
## Display manager appears only after manually switching TTY
|
||||
|
||||
Check the boot journal:
|
||||
|
||||
```bash
|
||||
journalctl -b --no-pager | grep -E 'revive-monitor|COMMAND=/usr/bin/chvt|chvt'
|
||||
```
|
||||
|
||||
If `chvt` runs before login, verify that you installed the current watcher script. It must ignore hotplug events when there is no active Wayland session.
|
||||
|
||||
Expected pre-login behavior:
|
||||
|
||||
```text
|
||||
No active Wayland session - DRM hotplug ignored
|
||||
```
|
||||
|
||||
## sudo / chvt fails
|
||||
|
||||
Test non-interactively:
|
||||
|
||||
```bash
|
||||
sudo -n /usr/bin/chvt 2
|
||||
```
|
||||
|
||||
If sudo asks for a password or exits with an error, verify:
|
||||
|
||||
```text
|
||||
/etc/sudoers.d/revive-monitor-chvt
|
||||
```
|
||||
|
||||
Always edit sudoers files with `visudo`.
|
||||
|
||||
## Recovery runs multiple times
|
||||
|
||||
Increase:
|
||||
|
||||
```bash
|
||||
DEBOUNCE_SECONDS=30
|
||||
```
|
||||
|
||||
in:
|
||||
|
||||
```text
|
||||
~/.config/revive-monitor/config.env
|
||||
```
|
||||
|
||||
For noisy hardware, `60` may be more appropriate.
|
||||
|
||||
## Recovery runs but the monitor still stays black
|
||||
|
||||
Increase:
|
||||
|
||||
```bash
|
||||
HDMI_SETTLE_SECONDS=5
|
||||
```
|
||||
|
||||
to `7` or `10` and test again.
|
||||
|
||||
Also manually verify that a VT switch actually restores the image:
|
||||
|
||||
```bash
|
||||
sudo chvt 2
|
||||
sleep 1
|
||||
sudo chvt 1
|
||||
```
|
||||
|
||||
Adjust the numbers to match the machine's graphical VT.
|
||||
Reference in new issue
Block a user