diff options
| author | srdusr <[email protected]> | 2025-11-10 09:31:00 +0200 |
|---|---|---|
| committer | srdusr <[email protected]> | 2025-11-10 09:31:00 +0200 |
| commit | f988203a7c22d945383efa9609f5c8a09a9506d2 (patch) | |
| tree | a88281daee61cf148362e7b83132a86a5ae43444 /crates/x11/src/platform/trait_impl.rs | |
| parent | ea78f94027ecd2c690904a6d7729e9e3cc190a20 (diff) | |
| download | srdwm-f988203a7c22d945383efa9609f5c8a09a9506d2.tar.gz srdwm-f988203a7c22d945383efa9609f5c8a09a9506d2.zip | |
Fix a maximized X11 window overhanging the screen by its own border
Reported by the aegis-fc peer session testing srdwm's own layer-shell
strut handling: a maximized X11 client sat 4-8px past the right and
bottom screen edges whenever its border was nonzero.
set_border_width sets the frame's native X11 border-width attribute,
which the X server draws outside a window's own declared width/height on
all four sides - unlike every other backend's own border in this
compositor (rendered as ordinary pixels inside the allocated geometry
rect). apply_geometry configured the frame at geometry's own x/y/width/
height verbatim, so a nonzero native border pushed the frame's true
visible footprint 2*border_width past every edge of what geometry
actually promised.
Fixed by shifting the configured origin inward and the configured size
down by border_width on both axes (frame_geometry_for, pulled out as a
pure function so it's unit-tested without a real X11 connection) - the
visible footprint, native border included, now lands exactly on
geometry. border_width == 0 reduces to the prior behavior exactly.
Diffstat (limited to 'crates/x11/src/platform/trait_impl.rs')
| -rw-r--r-- | crates/x11/src/platform/trait_impl.rs | 22 |
1 files changed, 16 insertions, 6 deletions
diff --git a/crates/x11/src/platform/trait_impl.rs b/crates/x11/src/platform/trait_impl.rs index b45a4aa..6c68e9f 100644 --- a/crates/x11/src/platform/trait_impl.rs +++ b/crates/x11/src/platform/trait_impl.rs @@ -103,18 +103,28 @@ impl Platform for X11Platform { // shrunk by, a titlebar that `redraw_decoration` (below) is // correctly not drawing at all, leaving a blank strip and the // frame visibly not matching what's inside it. - let decorated = self.wm.borrow().window(window).map(|w| w.decorated).unwrap_or(true); + let (decorated, border_width) = { + let wm = self.wm.borrow(); + let w = wm.window(window); + (w.map(|w| w.decorated).unwrap_or(true), w.map(|w| w.border_width).unwrap_or(0)) + }; let band = if decorated { TITLEBAR_HEIGHT } else { 0 }; + // See `frame_geometry_for`'s own doc comment: X11's native border + // is drawn outside a window's declared size, so configuring the + // frame at `geometry` verbatim with a nonzero border pushed the + // frame's true on-screen footprint past every edge of what + // `geometry` actually promised - reported live (found by the + // aegis peer session testing srdwm's own strut handling) as a + // maximized window sitting 4-8px past the right and bottom screen + // edges. + let (frame_x, frame_y, frame_w, frame_h) = frame_geometry_for(geometry, border_width); self.conn - .configure_window( - frame_id, - &ConfigureWindowAux::new().x(geometry.x).y(geometry.y).width(geometry.width).height(geometry.height), - ) + .configure_window(frame_id, &ConfigureWindowAux::new().x(frame_x).y(frame_y).width(frame_w).height(frame_h)) .map_err(err)?; self.conn .configure_window( client_id, - &ConfigureWindowAux::new().x(0).y(band as i32).width(geometry.width).height(geometry.height.saturating_sub(band)), + &ConfigureWindowAux::new().x(0).y(band as i32).width(frame_w).height(frame_h.saturating_sub(band)), ) .map_err(err)?; self.conn.flush().map_err(err)?; |