From 5c7e6b7eff1e396408dcd117cc591171d0274d9f Mon Sep 17 00:00:00 2001 From: apricotbucket28 <71973804+apricotbucket28@users.noreply.github.com> Date: Fri, 5 Jul 2024 17:42:11 -0300 Subject: [PATCH] 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 --- crates/gpui/src/platform.rs | 10 +++ .../gpui/src/platform/linux/wayland/client.rs | 2 +- .../gpui/src/platform/linux/wayland/window.rs | 72 +++++++++---------- .../title_bar/src/platforms/platform_linux.rs | 3 +- 4 files changed, 47 insertions(+), 40 deletions(-) diff --git a/crates/gpui/src/platform.rs b/crates/gpui/src/platform.rs index 3d81e88fb4..3d0472026a 100644 --- a/crates/gpui/src/platform.rs +++ b/crates/gpui/src/platform.rs @@ -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 diff --git a/crates/gpui/src/platform/linux/wayland/client.rs b/crates/gpui/src/platform/linux/wayland/client.rs index dd645e959b..62fb6ccc88 100644 --- a/crates/gpui/src/platform/linux/wayland/client.rs +++ b/crates/gpui/src/platform/linux/wayland/client.rs @@ -809,7 +809,7 @@ impl Dispatch for WaylandClientStatePtr { match event { wl_callback::Event::Done { .. } => { - window.frame(true); + window.frame(); } _ => {} } diff --git a/crates/gpui/src/platform/linux/wayland/window.rs b/crates/gpui/src/platform/linux/wayland/window.rs index 5ab64e9e1e..70d6ecec1b 100644 --- a/crates/gpui/src/platform/linux/wayland/window.rs +++ b/crates/gpui/src/platform/linux/wayland/window.rs @@ -100,7 +100,6 @@ pub struct WaylandWindowState { in_progress_window_controls: Option, window_controls: WindowControls, inset: Option, - requested_inset: Option, } #[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); } } diff --git a/crates/title_bar/src/platforms/platform_linux.rs b/crates/title_bar/src/platforms/platform_linux.rs index dd71e59625..8e46100479 100644 --- a/crates/title_bar/src/platforms/platform_linux.rs +++ b/crates/title_bar/src/platforms/platform_linux.rs @@ -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,