diff options
| author | srdusr <[email protected]> | 2026-05-15 19:05:00 +0200 |
|---|---|---|
| committer | srdusr <[email protected]> | 2026-05-15 19:05:00 +0200 |
| commit | 27daed83230eaefd0f41461cad20bbed7d1ad575 (patch) | |
| tree | c725244151b2128748e6c6ab07ff0578c6da200c /crates/wayland/src | |
| parent | 8174ced0d9d42343b18072c64491ccb06632a75f (diff) | |
| download | srdwm-27daed83230eaefd0f41461cad20bbed7d1ad575.tar.gz srdwm-27daed83230eaefd0f41461cad20bbed7d1ad575.zip | |
Fix the maximize border on the path that actually runs, and three spawn faults
The maximize border was still drawn because the earlier fix landed on the
wrong branch. udev/render.rs has three border blocks: the SRDWM_GPU=1 path
at the top and two Pixman ones below. The patch replaced the first match in
the file, which is the GPU branch a real DRM session never runs. All four
sites across both backends are now gated on !maximized.
The verification had failed twice for a separate reason: winit/capture.rs
did not draw border strips at all, so a screenshot could never answer "is
there a border here" and the control passed for the wrong reason. Border
strips are now drawn into that pass as solid fills - corner rounding is not
reproduced, so a capture is not pixel-exact at the corners, but presence,
position, thickness and colour are. With that closed the test has a real
control: unmaximized gives 6 accent pixels at x=800..805, exactly the
configured border_width, and maximized gives none at the right edge or along
the top row. That proves the winit path; the Pixman path is the same change
at two more sites and is not separately confirmed on screen.
Windows spawning as squares, partly off-screen, and always on the left were
all SmartPlacement::grid. It returned size.min(cell), shrinking every window
to its grid cell whatever size it asked for; it scanned cells in reading
order and took the first free one, which is the leftmost; and nothing clamped
the result, so a window larger than its cell could hang off the edge with its
border out of view. The cell now decides only where a window goes, the scan
starts from a rotating cell, and both grid and cascade clamp into the usable
area. Four tests, one per reported symptom.
525 tests pass, clippy clean.
Diffstat (limited to 'crates/wayland/src')
| -rw-r--r-- | crates/wayland/src/state/mod.rs | 6 | ||||
| -rw-r--r-- | crates/wayland/src/udev/platform.rs | 1 | ||||
| -rw-r--r-- | crates/wayland/src/udev/render.rs | 11 | ||||
| -rw-r--r-- | crates/wayland/src/winit/capture.rs | 27 | ||||
| -rw-r--r-- | crates/wayland/src/winit/connect.rs | 1 |
5 files changed, 44 insertions, 2 deletions
diff --git a/crates/wayland/src/state/mod.rs b/crates/wayland/src/state/mod.rs index fee7af3..5c1b02e 100644 --- a/crates/wayland/src/state/mod.rs +++ b/crates/wayland/src/state/mod.rs @@ -589,6 +589,12 @@ pub(crate) struct CompState { /// one drag is in progress at a time. See /// `elements::snap_preview_elements`. pub(crate) snap_preview_buffers: Vec<SolidColorBuffer>, + /// Persistent solid-colour buffers for the border strips drawn into the + /// winit backend's screencopy pass - same stable-`Id` reasoning as + /// `border_side_buffers`. One shared pool rather than one per window: + /// a capture pass runs to completion in a single frame, so nothing + /// needs to persist per window between windows. + pub(crate) capture_border_buffers: Vec<SolidColorBuffer>, /// Persistent solid-colour buffer backing the whole-output night-light/ /// reading-mode overlay, one per output name - same "reuse the buffer /// so its `Id` stays stable across frames" reasoning as `border_side_ diff --git a/crates/wayland/src/udev/platform.rs b/crates/wayland/src/udev/platform.rs index ea2260e..8dad7c3 100644 --- a/crates/wayland/src/udev/platform.rs +++ b/crates/wayland/src/udev/platform.rs @@ -268,6 +268,7 @@ impl UdevPlatform { rounded_content_buffers: HashMap::new(), border_side_buffers: HashMap::new(), snap_preview_buffers: Vec::new(), + capture_border_buffers: Vec::new(), color_filter_buffers: HashMap::new(), last_synced_size: HashMap::new(), provisional_size: HashSet::new(), diff --git a/crates/wayland/src/udev/render.rs b/crates/wayland/src/udev/render.rs index 3bd9a52..9992b2c 100644 --- a/crates/wayland/src/udev/render.rs +++ b/crates/wayland/src/udev/render.rs @@ -668,7 +668,14 @@ impl CompState { // instead, since `custom_elements` composites earlier- // pushed entries over later ones - exactly backwards // from what this overlap needs. - if w.border_width > 0 { + // No border on a maximized window - see the matching + // gate on the GPU path above. This is the Pixman path, + // the one a real DRM session actually runs: the earlier + // fix landed only on the GPU branch, so the border kept + // being drawn on real hardware and was reported again as + // "i still see the border or at least the top border + // when maximized". + if w.border_width > 0 && !w.maximized { let strips = decoration::border_strips(frame, w.border_width); // Strip 0 (top) rounded on its own two corners - see // `render_border_top`'s own doc comment - so it's a @@ -773,7 +780,7 @@ impl CompState { // (unlike the bottom strip) *do* need cropping against // this same top/bottom-strip overlap, a real bug this // comment used to claim didn't exist here at all. - if w.border_width > 0 { + if w.border_width > 0 && !w.maximized { let color = crate::state::effective_border_color(w.border_color, focused == Some(id), self.wm.borrow().theme.border_inactive_dim); let strips = decoration::border_strips(frame, w.border_width); // Strip 1 (bottom), the top strip's own mirror -- diff --git a/crates/wayland/src/winit/capture.rs b/crates/wayland/src/winit/capture.rs index 095b56b..3813559 100644 --- a/crates/wayland/src/winit/capture.rs +++ b/crates/wayland/src/winit/capture.rs @@ -96,6 +96,7 @@ impl WaylandPlatform { // as both on-screen render loops do it. let monitor_bounds: Vec<srdwm_core::Rect> = self.wm.borrow().monitors().iter().map(|m| m.full_geometry).collect(); let mut occluders: Vec<srdwm_core::Rect> = Vec::new(); + let focused = self.wm.borrow().focused_id(); for id in self.wm.borrow().visible_windows_front_to_back().map(|w| w.id).collect::<Vec<_>>() { let Some(w) = self.wm.borrow().window(id).cloned() else { continue }; if let Some(deco) = self.state.decorations.get(&id) { @@ -158,6 +159,32 @@ impl WaylandPlatform { } } } + // Border strips, as plain solid fills. + // + // The on-screen loop draws the top and bottom strips from + // cached bitmaps so their corners round into the titlebar's + // curve, and only the sides as fills. This pass approximates + // all four with fills: corner rounding is not reproduced, so a + // capture is not pixel-exact at the four corners. Everything + // that matters for checking a border - whether one is drawn at + // all, where, how thick, and in what colour - is faithful. + // + // Without this a screenshot could not answer "is there a border + // here", which is exactly the question a border bug asks. That + // gap was documented and then walked into twice: a maximize + // border fix was checked against a capture that never draws + // borders, and the control silently passed for the wrong + // reason both times. + if w.border_width > 0 && !w.maximized { + let color = crate::state::effective_border_color(w.border_color, focused == Some(id), self.wm.borrow().theme.border_inactive_dim); + let frame = self.state.effective_frame(id, w.geometry); + for (index, strip) in crate::decoration::border_strips(frame, w.border_width).into_iter().enumerate() { + for fragment in crate::elements::visible_border_fragments(strip, &occluders) { + let buf = crate::elements::border_fragment_buffer(&mut self.state.capture_border_buffers, index); + custom_elements.push(crate::elements::OverlayElement::Solid(crate::elements::border_side_render_element(buf, fragment, color, (0, 0)))); + } + } + } occluders.push(w.geometry); } custom_elements.extend(crate::elements::output_layer_elements(renderer, &self.output, |layer| matches!(layer, Layer::Background | Layer::Bottom))); diff --git a/crates/wayland/src/winit/connect.rs b/crates/wayland/src/winit/connect.rs index 1648826..aa59d9d 100644 --- a/crates/wayland/src/winit/connect.rs +++ b/crates/wayland/src/winit/connect.rs @@ -180,6 +180,7 @@ impl WaylandPlatform { rounded_content_buffers: HashMap::new(), border_side_buffers: HashMap::new(), snap_preview_buffers: Vec::new(), + capture_border_buffers: Vec::new(), color_filter_buffers: HashMap::new(), last_synced_size: HashMap::new(), provisional_size: HashSet::new(), |