diff options
| author | srdusr <[email protected]> | 2025-10-29 22:24:00 +0200 |
|---|---|---|
| committer | srdusr <[email protected]> | 2025-10-29 22:24:00 +0200 |
| commit | a4710d792a1b16698fc30b9e97e6c08c82129d6d (patch) | |
| tree | 9d56a3c2106db783e1fad0cf817ecc1d7510bd8f /crates/core/src/manager | |
| parent | 9592fd7acb5b68f3fae139dfac22b728c35b6198 (diff) | |
| download | srdwm-a4710d792a1b16698fc30b9e97e6c08c82129d6d.tar.gz srdwm-a4710d792a1b16698fc30b9e97e6c08c82129d6d.zip | |
Fix set_monitor_split never actually reaching srd monitors
Live-tested right after shipping it and caught immediately: srd dispatch
set output split returned ok, but srd monitors kept reporting the whole,
unsplit output. WindowManager::monitors is a passive cache, only
refreshed when a backend re-queries and calls set_monitors again - the
IPC handler mutated the split map directly but never triggered that
requery, unlike set_output_position's own drain site, which already
pushes a "just go recompute" event after applying.
Makes it a proper queued cross-boundary request instead, the same shape
as every other backend-owned effect on this socket: WindowManager::
request_monitor_split/drain_monitor_split_requests, dispatch queues
instead of mutating, the udev backend's poll drains it, applies via
set_monitor_split, and pushes the same recompute event. srd.monitor.
split's Lua config-time path is untouched - it runs before the very
first startup query, so it never had this problem.
Diffstat (limited to 'crates/core/src/manager')
| -rw-r--r-- | crates/core/src/manager/mod.rs | 17 | ||||
| -rw-r--r-- | crates/core/src/manager/monitors.rs | 18 |
2 files changed, 35 insertions, 0 deletions
diff --git a/crates/core/src/manager/mod.rs b/crates/core/src/manager/mod.rs index bb22533..c9c77b2 100644 --- a/crates/core/src/manager/mod.rs +++ b/crates/core/src/manager/mod.rs @@ -103,6 +103,22 @@ pub struct WindowManager { /// [`MonitorSplit`]'s own doc comment for what this deliberately does /// and does not give a client (no new `wl_output`). monitor_splits: HashMap<String, MonitorSplit>, + /// Same cross-boundary-request pattern as `output_position_requests` + /// above - an IPC `set_monitor_split` dispatch (the live CLI/IPC path + /// for `srd.monitor.split`) mutating `monitor_splits` directly is not + /// enough on its own: `monitors` above is a passive cache, only + /// refreshed when a backend re-queries and calls `set_monitors` again + /// (a real hotplug, or another queued request's own drain site pushing + /// the same "just go recompute" `MonitorAdded` event - see `output_ + /// position_requests`' own drain site for the exact precedent). A + /// direct mutation with nothing to trigger that requery left `srd + /// monitors` reporting the pre-split layout indefinitely, live- + /// reproduced the first time this was tried: `{"ok":true}` came back, + /// but the very next `srd monitors` still showed one whole, unsplit + /// output. Queued here instead so the backend's own drain site can + /// apply the split *and* push that same recompute signal, exactly like + /// `output_position_requests` already does. + monitor_split_requests: Vec<(String, u32, bool)>, /// `srd.monitor.scale(name, factor)` requests, by connector name -- /// read once by a backend when it brings a head up (startup, hotplug, /// or re-enable), so a physically large, low-DPI monitor can run @@ -454,6 +470,7 @@ impl WindowManager { output_enable_requests: Vec::new(), disabled_monitors: HashMap::new(), monitor_splits: HashMap::new(), + monitor_split_requests: Vec::new(), monitor_scales: HashMap::new(), lock_requested: false, capture_requests: Vec::new(), diff --git a/crates/core/src/manager/monitors.rs b/crates/core/src/manager/monitors.rs index bff3bc9..c79f76f 100644 --- a/crates/core/src/manager/monitors.rs +++ b/crates/core/src/manager/monitors.rs @@ -233,6 +233,24 @@ impl WindowManager { self.monitor_splits.get(name).copied() } + /// Queues a live `srd dispatch set output split` request - see + /// `monitor_split_requests`' own doc comment for why this can't just + /// call `set_monitor_split` directly from the IPC dispatch handler. + /// Same "replace, don't accumulate" per-name semantics as `request_ + /// output_position`. + pub fn request_monitor_split(&mut self, name: String, parts: u32, rows: bool) { + self.monitor_split_requests.retain(|(existing, _, _)| *existing != name); + self.monitor_split_requests.push((name, parts, rows)); + } + + /// [`Self::drain_output_position_requests`]'s counterpart for split + /// requests - the backend applies each via `set_monitor_split` and + /// pushes its own "just go recompute" event afterward, same as that + /// function's own drain site. + pub fn drain_monitor_split_requests(&mut self) -> Vec<(String, u32, bool)> { + std::mem::take(&mut self.monitor_split_requests) + } + /// `srd.monitor.scale(name, factor)` - a backend applies this the /// next time it brings connector `name`'s head up (startup, hotplug, /// or re-enable). `factor <= 0.0` clears any existing override rather |