srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/crates/wayland/src/winit/capture.rs
diff options
context:
space:
mode:
authorsrdusr <[email protected]>2026-05-04 21:37:00 +0200
committersrdusr <[email protected]>2026-05-04 21:37:00 +0200
commit790ee906957b8b855dfc23cf1b206628585fd1ec (patch)
tree2351094dede798ed8b3fa32fd8fa41641752c64b /crates/wayland/src/winit/capture.rs
parent3ea84a31ee671b88d8c343b3007de0e975eff31c (diff)
downloadsrdwm-790ee906957b8b855dfc23cf1b206628585fd1ec.tar.gz
srdwm-790ee906957b8b855dfc23cf1b206628585fd1ec.zip
Support monitor split in the nested backend, correcting a wrong "blocked"
Earlier today I wrote that a nested compositor cannot produce a second monitor because split and fake monitors "need real head machinery that only the DRM backend has". That was inferred from both commands returning ok and changing nothing, not read from the code, and the first half is false. udev/platform.rs was simply the only backend draining those request queues. The winit poll never took them off, so the request sat there forever and the dispatch looked like it had worked. Nothing about split is DRM-bound: MonitorSplit is bookkeeping in WindowManager and split_rect is pure geometry in core. The winit poll now drains split requests the same way, and its monitors() expands a split into one Monitor per part with its own full_geometry and maximize_geometry, matching the udev expansion. Splitting the nested output into two 640x800 monitors with a seam now works, which is what a multi-monitor repro needs. Fake monitors stay udev-only; that half was not re-checked and is not claimed either way. Also corrected: the capture pass measured the shadow rect from w.geometry while both on-screen loops measure it from effective_frame, the client's real committed size. src indexes into a buffer rasterised at the frame's size, so the two disagreeing reads the wrong region whenever a client settles on a different size than it was asked for. The seam check this was meant to unblock is still not done. With the split working, the negative control failed: a floating window off the seam had no shadow either. Running both clients in one instance showed Alacritty renders a shadow in a capture and Nemo renders none, same settings, both floating, either focus. Nemo is server-side decorated and Alacritty is not, which is a lead and not a conclusion. Recorded in docs/TODO.md as open rather than guessed at. 515 tests pass, clippy clean.
Diffstat (limited to 'crates/wayland/src/winit/capture.rs')
-rw-r--r--crates/wayland/src/winit/capture.rs16
1 files changed, 14 insertions, 2 deletions
diff --git a/crates/wayland/src/winit/capture.rs b/crates/wayland/src/winit/capture.rs
index c382190..095b56b 100644
--- a/crates/wayland/src/winit/capture.rs
+++ b/crates/wayland/src/winit/capture.rs
@@ -133,8 +133,20 @@ impl WaylandPlatform {
// and re-checked by. Border strips are still absent - a real
// remaining gap, called out here rather than left silent.
if let Some(shadow) = self.state.shadow_buffers.get(&id) {
- let full = crate::decoration::shadow_rect(w.geometry);
- let rect = crate::decoration::shadow_rect_clipped(w.geometry, &monitor_bounds);
+ // `effective_frame`, not `w.geometry` - the same correction
+ // both on-screen render loops apply before sizing any
+ // decoration bitmap (see its own doc comment). The shadow
+ // buffer was rasterised at the *frame's* size, and `src`
+ // below indexes into that buffer, so measuring from
+ // `w.geometry` instead reads the wrong region whenever the
+ // two differ. They differ for exactly the windows that
+ // matter here: a CSD client whose committed surface is not
+ // the size this compositor asked for. Found by sampling
+ // pixels - Alacritty's shadow appeared in a capture and
+ // Nemo's did not, and the only difference was that gap.
+ let frame = self.state.effective_frame(id, w.geometry);
+ let full = crate::decoration::shadow_rect(frame);
+ let rect = crate::decoration::shadow_rect_clipped(frame, &monitor_bounds);
for fragment in crate::elements::visible_border_fragments(rect, &occluders) {
let src = Rectangle::new(
Point::from(((fragment.x - full.x) as f64, (fragment.y - full.y) as f64)),