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:
parent
1c1fd6aaa1
commit
5c7e6b7eff
4 changed files with 47 additions and 40 deletions
|
@ -281,6 +281,16 @@ pub struct Tiling {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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
|
/// Whether any edge is tiled
|
||||||
pub fn is_tiled(&self) -> bool {
|
pub fn is_tiled(&self) -> bool {
|
||||||
self.top || self.left || self.right || self.bottom
|
self.top || self.left || self.right || self.bottom
|
||||||
|
|
|
@ -809,7 +809,7 @@ impl Dispatch<WlCallback, ObjectId> for WaylandClientStatePtr {
|
||||||
|
|
||||||
match event {
|
match event {
|
||||||
wl_callback::Event::Done { .. } => {
|
wl_callback::Event::Done { .. } => {
|
||||||
window.frame(true);
|
window.frame();
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,7 +100,6 @@ pub struct WaylandWindowState {
|
||||||
in_progress_window_controls: Option<WindowControls>,
|
in_progress_window_controls: Option<WindowControls>,
|
||||||
window_controls: WindowControls,
|
window_controls: WindowControls,
|
||||||
inset: Option<Pixels>,
|
inset: Option<Pixels>,
|
||||||
requested_inset: Option<Pixels>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -189,7 +188,6 @@ impl WaylandWindowState {
|
||||||
window_menu: true,
|
window_menu: true,
|
||||||
},
|
},
|
||||||
inset: None,
|
inset: None,
|
||||||
requested_inset: None,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,12 +314,11 @@ impl WaylandWindowStatePtr {
|
||||||
Rc::ptr_eq(&self.state, &other.state)
|
Rc::ptr_eq(&self.state, &other.state)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn frame(&self, request_frame_callback: bool) {
|
pub fn frame(&self) {
|
||||||
if request_frame_callback {
|
|
||||||
let mut state = self.state.borrow_mut();
|
let mut state = self.state.borrow_mut();
|
||||||
state.surface.frame(&state.globals.qh, state.surface.id());
|
state.surface.frame(&state.globals.qh, state.surface.id());
|
||||||
drop(state);
|
drop(state);
|
||||||
}
|
|
||||||
let mut cb = self.callbacks.borrow_mut();
|
let mut cb = self.callbacks.borrow_mut();
|
||||||
if let Some(fun) = cb.request_frame.as_mut() {
|
if let Some(fun) = cb.request_frame.as_mut() {
|
||||||
fun();
|
fun();
|
||||||
|
@ -351,13 +348,12 @@ impl WaylandWindowStatePtr {
|
||||||
state.fullscreen = configure.fullscreen;
|
state.fullscreen = configure.fullscreen;
|
||||||
state.maximized = configure.maximized;
|
state.maximized = configure.maximized;
|
||||||
state.tiling = configure.tiling;
|
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 {
|
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 {
|
if let Some(size) = configure.size {
|
||||||
state.window_bounds = Bounds {
|
state.window_bounds = Bounds {
|
||||||
origin: Point::default(),
|
origin: Point::default(),
|
||||||
|
@ -373,12 +369,27 @@ impl WaylandWindowStatePtr {
|
||||||
}
|
}
|
||||||
let mut state = self.state.borrow_mut();
|
let mut state = self.state.borrow_mut();
|
||||||
state.xdg_surface.ack_configure(serial);
|
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 {
|
if request_frame_callback {
|
||||||
|
state.acknowledged_first_configure = true;
|
||||||
drop(state);
|
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();
|
let mut state = self.state.borrow_mut();
|
||||||
state.in_progress_configure = Some(InProgressConfigure {
|
state.in_progress_configure = Some(InProgressConfigure {
|
||||||
size,
|
size,
|
||||||
|
@ -893,26 +908,7 @@ impl PlatformWindow for WaylandWindow {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn completed_frame(&self) {
|
fn completed_frame(&self) {
|
||||||
let mut state = self.borrow_mut();
|
let state = self.borrow();
|
||||||
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,
|
|
||||||
);
|
|
||||||
|
|
||||||
state.surface.commit();
|
state.surface.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -973,7 +969,7 @@ impl PlatformWindow for WaylandWindow {
|
||||||
fn set_client_inset(&self, inset: Pixels) {
|
fn set_client_inset(&self, inset: Pixels) {
|
||||||
let mut state = self.borrow_mut();
|
let mut state = self.borrow_mut();
|
||||||
if Some(inset) != state.inset {
|
if Some(inset) != state.inset {
|
||||||
state.requested_inset = Some(inset);
|
state.inset = Some(inset);
|
||||||
update_window(state);
|
update_window(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use gpui::{prelude::*, Action};
|
use gpui::{prelude::*, Action, MouseButton};
|
||||||
|
|
||||||
use ui::prelude::*;
|
use ui::prelude::*;
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ impl RenderOnce for LinuxWindowControls {
|
||||||
.id("generic-window-controls")
|
.id("generic-window-controls")
|
||||||
.px_3()
|
.px_3()
|
||||||
.gap_3()
|
.gap_3()
|
||||||
|
.on_mouse_down(MouseButton::Left, |_, cx| cx.stop_propagation())
|
||||||
.child(WindowControl::new(
|
.child(WindowControl::new(
|
||||||
"minimize",
|
"minimize",
|
||||||
WindowControlType::Minimize,
|
WindowControlType::Minimize,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue