diff options
| author | srdusr <[email protected]> | 2025-10-28 20:09:00 +0200 |
|---|---|---|
| committer | srdusr <[email protected]> | 2025-10-28 20:09:00 +0200 |
| commit | 9592fd7acb5b68f3fae139dfac22b728c35b6198 (patch) | |
| tree | ebdaab6064388b67ffe06a611d934d7a29120959 /crates/core | |
| parent | 304f3a374408bb6a5a04ebb7d4652c631395f5c6 (diff) | |
| download | srdwm-9592fd7acb5b68f3fae139dfac22b728c35b6198.tar.gz srdwm-9592fd7acb5b68f3fae139dfac22b728c35b6198.zip | |
Fix a fake monitor's layer-shell surfaces misrouting onto the real primary
Live incident, root-caused jointly with the AGS peer session: creating a
fake monitor visibly shrank the real primary output's usable area
(full_y stayed 0 throughout - its true position never moved) each time,
tracking almost exactly one bar height per fake monitor created.
create_virtual_head registered its new Output in udev.virtual_heads but
never in CompState::outputs, the list output_for_wl searches to resolve
a client-named wl_output back to anything. new_layer_surface's own
fallback for an output it can't resolve is landing on the primary output
- so AGS's own per-monitor bar, aimed at the fake monitor it reasonably
believed was a new real one, silently landed on the real primary output
instead, stacking its own exclusive-zone reservation on top of the real
bar already there. Two fake monitors, two misrouted bars, two zone
increments, matching the observed climb exactly.
Fixed by registering (and, on removal, deregistering) a virtual head's
Output in CompState::outputs the same way bring_up_head already does for
a real one. Also adds Monitor::is_virtual / MonitorInfo's "virtual" JSON
field, requested directly by the AGS peer session as the real
discriminator their own temporary FAKE- name-pattern match was standing
in for.
The X-position half of this same incident was AGS's own remembered-
layout restore treating a fake monitor's wl_output as a real hotplug --
already fixed on their side (readArrangeable() now filters split/virtual
outputs).
Diffstat (limited to 'crates/core')
| -rw-r--r-- | crates/core/src/monitor.rs | 32 |
1 files changed, 31 insertions, 1 deletions
diff --git a/crates/core/src/monitor.rs b/crates/core/src/monitor.rs index 6ea053f..f18edea 100644 --- a/crates/core/src/monitor.rs +++ b/crates/core/src/monitor.rs @@ -65,11 +65,41 @@ pub struct Monitor { /// other than `1.0`) traced back to exactly this missing piece of /// information. pub scale: f64, + /// `true` for a fully virtual/headless output created by `srd dispatch + /// create fake-monitor` (`crates/wayland/src/udev/virtual_heads.rs`) -- + /// a real, independent `wl_output` global with no DRM connector behind + /// it. `false` for every ordinary connected output, split part + /// included (`split` and `is_virtual` are independent: a split part is + /// still a real output's own rectangle, not a second `wl_output`). + /// + /// Requested directly by the AGS peer session after a fake monitor's + /// `wl_output` caused a real live incident: a fake output looks like an + /// ordinary new monitor to any client watching the core Wayland + /// registry (not just `wlr-output-management-v1`, which already + /// deliberately excludes it - see `virtual_heads.rs`'s own module doc + /// comment), so AGS's own remembered-layout restore treated it as a + /// real hotplug and repositioned the *real* monitor to make room for + /// it, twice, once per fake monitor created. AGS's own fix was a + /// name-pattern match (`/^FAKE-/i`) since nothing else in `srd + /// monitors`' output let it tell a fake output apart from a real one -- + /// this field is the real discriminator that match was standing in for. + pub is_virtual: bool, } impl Monitor { pub fn new(id: MonitorId, name: impl Into<String>, geometry: Rect) -> Self { - Self { id, name: name.into(), geometry, full_geometry: geometry, maximize_geometry: geometry, refresh_rate_mhz: 60_000, primary: false, split: false, scale: 1.0 } + Self { + id, + name: name.into(), + geometry, + full_geometry: geometry, + maximize_geometry: geometry, + refresh_rate_mhz: 60_000, + primary: false, + split: false, + scale: 1.0, + is_virtual: false, + } } } |