wayland: Fix window state issues (#13885)

Fixes some issues with the CSD added in
https://github.com/zed-industries/zed/pull/13611

Here's a video comparing the master branch (yellow icon) with this PR
(blue icon):


https://github.com/zed-industries/zed/assets/71973804/35be443a-8f24-4aed-910b-625bad9821e2

_Note: the flicker at the bottom of the window when maximizing is an
issue with the KDE floating task bar, it happens with all programs._

Release Notes:

- N/A
This commit is contained in:
apricotbucket28 2024-07-05 17:42:11 -03:00 committed by GitHub
parent 1c1fd6aaa1
commit 5c7e6b7eff
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 47 additions and 40 deletions

View File

@ -281,6 +281,16 @@ pub struct Tiling {
}
impl Tiling {
/// Initializes a [`Tiling`] type with all sides tiled
pub fn tiled() -> Self {
Self {
top: true,
left: true,
right: true,
bottom: true,
}
}
/// Whether any edge is tiled
pub fn is_tiled(&self) -> bool {
self.top || self.left || self.right || self.bottom

View File

@ -809,7 +809,7 @@ impl Dispatch<WlCallback, ObjectId> for WaylandClientStatePtr {
match event {
wl_callback::Event::Done { .. } => {
window.frame(true);
window.frame();
}
_ => {}
}

View File

@ -100,7 +100,6 @@ pub struct WaylandWindowState {
in_progress_window_controls: Option<WindowControls>,
window_controls: WindowControls,
inset: Option<Pixels>,
requested_inset: Option<Pixels>,
}
#[derive(Clone)]
@ -189,7 +188,6 @@ impl WaylandWindowState {
window_menu: true,
},
inset: None,
requested_inset: None,
})
}
@ -316,12 +314,11 @@ impl WaylandWindowStatePtr {
Rc::ptr_eq(&self.state, &other.state)
}
pub fn frame(&self, request_frame_callback: bool) {
if request_frame_callback {
let mut state = self.state.borrow_mut();
state.surface.frame(&state.globals.qh, state.surface.id());
drop(state);
}
pub fn frame(&self) {
let mut state = self.state.borrow_mut();
state.surface.frame(&state.globals.qh, state.surface.id());
drop(state);
let mut cb = self.callbacks.borrow_mut();
if let Some(fun) = cb.request_frame.as_mut() {
fun();
@ -351,13 +348,12 @@ impl WaylandWindowStatePtr {
state.fullscreen = configure.fullscreen;
state.maximized = configure.maximized;
state.tiling = configure.tiling;
if got_unmaximized {
configure.size = Some(state.window_bounds.size);
} else if !configure.maximized {
configure.size =
compute_outer_size(state.inset, configure.size, state.tiling);
}
if !configure.fullscreen && !configure.maximized {
configure.size = if got_unmaximized {
Some(state.window_bounds.size)
} else {
compute_outer_size(state.inset, configure.size, state.tiling)
};
if let Some(size) = configure.size {
state.window_bounds = Bounds {
origin: Point::default(),
@ -373,12 +369,27 @@ impl WaylandWindowStatePtr {
}
let mut state = self.state.borrow_mut();
state.xdg_surface.ack_configure(serial);
let request_frame_callback = !state.acknowledged_first_configure;
state.acknowledged_first_configure = true;
let window_geometry = inset_by_tiling(
state.bounds.map_origin(|_| px(0.0)),
state.inset.unwrap_or(px(0.0)),
state.tiling,
)
.map(|v| v.0 as i32)
.map_size(|v| if v <= 0 { 1 } else { v });
state.xdg_surface.set_window_geometry(
window_geometry.origin.x,
window_geometry.origin.y,
window_geometry.size.width,
window_geometry.size.height,
);
let request_frame_callback = !state.acknowledged_first_configure;
if request_frame_callback {
state.acknowledged_first_configure = true;
drop(state);
self.frame(true);
self.frame();
}
}
_ => {}
@ -470,6 +481,10 @@ impl WaylandWindowStatePtr {
}
}
if fullscreen || maximized {
tiling = Tiling::tiled();
}
let mut state = self.state.borrow_mut();
state.in_progress_configure = Some(InProgressConfigure {
size,
@ -893,26 +908,7 @@ impl PlatformWindow for WaylandWindow {
}
fn completed_frame(&self) {
let mut state = self.borrow_mut();
if let Some(area) = state.requested_inset {
state.inset = Some(area);
}
let window_geometry = inset_by_tiling(
state.bounds.map_origin(|_| px(0.0)),
state.inset.unwrap_or(px(0.0)),
state.tiling,
)
.map(|v| v.0 as i32)
.map_size(|v| if v <= 0 { 1 } else { v });
state.xdg_surface.set_window_geometry(
window_geometry.origin.x,
window_geometry.origin.y,
window_geometry.size.width,
window_geometry.size.height,
);
let state = self.borrow();
state.surface.commit();
}
@ -973,7 +969,7 @@ impl PlatformWindow for WaylandWindow {
fn set_client_inset(&self, inset: Pixels) {
let mut state = self.borrow_mut();
if Some(inset) != state.inset {
state.requested_inset = Some(inset);
state.inset = Some(inset);
update_window(state);
}
}

View File

@ -1,4 +1,4 @@
use gpui::{prelude::*, Action};
use gpui::{prelude::*, Action, MouseButton};
use ui::prelude::*;
@ -23,6 +23,7 @@ impl RenderOnce for LinuxWindowControls {
.id("generic-window-controls")
.px_3()
.gap_3()
.on_mouse_down(MouseButton::Left, |_, cx| cx.stop_propagation())
.child(WindowControl::new(
"minimize",
WindowControlType::Minimize,