srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/legacy-cpp/src/input
diff options
context:
space:
mode:
authorsrdusr <[email protected]>2024-04-12 22:35:00 +0200
committersrdusr <[email protected]>2024-04-12 22:35:00 +0200
commita9dd8a6d4947cb537f7919c5a66ba4624af61800 (patch)
treed4731cded04ce159ebf3547d4dfe95ca24f4bb02 /legacy-cpp/src/input
parent709333908d5b7d3157165d1811c8bc1795ab0028 (diff)
downloadsrdwm-a9dd8a6d4947cb537f7919c5a66ba4624af61800.tar.gz
srdwm-a9dd8a6d4947cb537f7919c5a66ba4624af61800.zip
udev: connector hotplug, and rescue windows on an unplugged monitor
Monitors were probed once at startup, so plugging or unplugging one while srdwm was running went unnoticed. A UdevBackend event source now watches for the kernel's `change` uevent and reconciles the head list against a fresh connector probe - forcing a re-probe rather than trusting cached status, since on a hotplug the cache is exactly what has gone stale. Removing a head tears down everything it owned: the wl_output global, its place in the Space, its DRM framebuffers and dumb buffers (dropping the Rust structs alone leaks the kernel-side objects, which matters when a cable is plugged repeatedly), and any lock surface for it - otherwise confirm_lock_if_presented would wait forever on a monitor that no longer exists. New connectors go through the same bring_up_head path as startup, so a monitor plugged in later is set up identically to one present at boot. Heads are then repositioned left-to-right, since removing one shifts the rest, and layer maps re-arranged so bars follow their moved output. set_monitors rehomes windows stranded by the change, and main.rs re-queries the whole monitor list on MonitorAdded/MonitorRemoved rather than applying the single monitor in the event, because the others' positions move too. The rehoming had a bug that unit tests missed and live testing caught. It originally keyed off Window::monitor, but that field records the monitor a window was *assigned* at creation, not where it is: add_window always sets it from the primary monitor, so a window placed on the second monitor by a rule - or dragged there - still reads monitor == 0. The field-only check saw a valid id, skipped the window, and left it at coordinates that no longer existed: invisible and unreachable. Found by unplugging a monitor out from under a real xterm and watching it vanish from both heads. It now keys off geometry, with a regression test that fails against the old logic. Verified in the QEMU VM, booting with one connector and toggling the second at runtime: plug in -> head added and rendering at its own resolution; unplug -> head removed cleanly; and an xterm at global x=1500 survived its monitor being unplugged, reappearing at x=680 (= min(1500, 1280-600)) with its size intact. Writing to /sys/class/drm/<connector>/status changes the connector but emits no uevent on this kernel, so the signal the kernel would send is synthesized with `udevadm trigger`; the whole reaction path is genuinely exercised.
Diffstat (limited to 'legacy-cpp/src/input')
0 files changed, 0 insertions, 0 deletions