diff options
| author | srdusr <[email protected]> | 2026-05-04 21:37:00 +0200 |
|---|---|---|
| committer | srdusr <[email protected]> | 2026-05-04 21:37:00 +0200 |
| commit | 790ee906957b8b855dfc23cf1b206628585fd1ec (patch) | |
| tree | 2351094dede798ed8b3fa32fd8fa41641752c64b /crates/wayland/src/winit/capture.rs | |
| parent | 3ea84a31ee671b88d8c343b3007de0e975eff31c (diff) | |
| download | srdwm-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.rs | 16 |
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)), |