gpui: Fix inset being used in SSD on Wayland (#35151)

Closes #31330

Second parts of https://github.com/zed-industries/zed/pull/31335

While the initial fix set the inset during drawing, that was after the
window was resized, resulting in needing to manually resize the window
for the change to properly take effect.

I updated the code to not make the Wayland renderer rely on
`client_inset` being updated by the API user to match with the
decoration mode (given it is supposed to only be used when using CSD).

I might later try to generalize that, and eventually make the
client_inset only defined on window creation (instead of inside
`client_side_decorations`, that would need testing on X) (and maybe also
allow configuration for shadow, but it’s not something I need).

Release Notes:

- Fixed switching from client side decoration to server side decoration
on Wayland
This commit is contained in:
marius851000 2025-07-28 10:36:00 +02:00 committed by GitHub
parent 2a0aad0aaa
commit ee9b60e60c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -111,7 +111,7 @@ pub struct WaylandWindowState {
resize_throttle: bool,
in_progress_window_controls: Option<WindowControls>,
window_controls: WindowControls,
inset: Option<Pixels>,
client_inset: Option<Pixels>,
}
#[derive(Clone)]
@ -186,7 +186,7 @@ impl WaylandWindowState {
hovered: false,
in_progress_window_controls: None,
window_controls: WindowControls::default(),
inset: None,
client_inset: None,
})
}
@ -211,6 +211,13 @@ impl WaylandWindowState {
self.display = current_output;
scale
}
pub fn inset(&self) -> Pixels {
match self.decorations {
WindowDecorations::Server => px(0.0),
WindowDecorations::Client => self.client_inset.unwrap_or(px(0.0)),
}
}
}
pub(crate) struct WaylandWindow(pub WaylandWindowStatePtr);
@ -380,7 +387,7 @@ impl WaylandWindowStatePtr {
configure.size = if got_unmaximized {
Some(state.window_bounds.size)
} else {
compute_outer_size(state.inset, configure.size, state.tiling)
compute_outer_size(state.inset(), configure.size, state.tiling)
};
if let Some(size) = configure.size {
state.window_bounds = Bounds {
@ -400,7 +407,7 @@ impl WaylandWindowStatePtr {
let window_geometry = inset_by_tiling(
state.bounds.map_origin(|_| px(0.0)),
state.inset.unwrap_or(px(0.0)),
state.inset(),
state.tiling,
)
.map(|v| v.0 as i32)
@ -818,7 +825,7 @@ impl PlatformWindow for WaylandWindow {
} else if state.maximized {
WindowBounds::Maximized(state.window_bounds)
} else {
let inset = state.inset.unwrap_or(px(0.));
let inset = state.inset();
drop(state);
WindowBounds::Windowed(self.bounds().inset(inset))
}
@ -1073,8 +1080,8 @@ impl PlatformWindow for WaylandWindow {
fn set_client_inset(&self, inset: Pixels) {
let mut state = self.borrow_mut();
if Some(inset) != state.inset {
state.inset = Some(inset);
if Some(inset) != state.client_inset {
state.client_inset = Some(inset);
update_window(state);
}
}
@ -1094,9 +1101,7 @@ fn update_window(mut state: RefMut<WaylandWindowState>) {
state.renderer.update_transparency(!opaque);
let mut opaque_area = state.window_bounds.map(|v| v.0 as i32);
if let Some(inset) = state.inset {
opaque_area.inset(inset.0 as i32);
}
opaque_area.inset(state.inset().0 as i32);
let region = state
.globals
@ -1169,12 +1174,10 @@ impl ResizeEdge {
/// updating to account for the client decorations. But that's not the area we want to render
/// to, due to our intrusize CSD. So, here we calculate the 'actual' size, by adding back in the insets
fn compute_outer_size(
inset: Option<Pixels>,
inset: Pixels,
new_size: Option<Size<Pixels>>,
tiling: Tiling,
) -> Option<Size<Pixels>> {
let Some(inset) = inset else { return new_size };
new_size.map(|mut new_size| {
if !tiling.top {
new_size.height += inset;