GPUI: Wayland: Add fullscreen, minimize and avoid unnecessary resizes (#9060)

Release Notes:
- N/A
This commit is contained in:
bbb651 2024-03-09 05:52:36 +02:00 committed by GitHub
parent 146971fb02
commit efe5203a09
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 65 additions and 26 deletions

View file

@ -520,15 +520,16 @@ impl Dispatch<xdg_toplevel::XdgToplevel, ()> for WaylandClientState {
if let xdg_toplevel::Event::Configure { if let xdg_toplevel::Event::Configure {
width, width,
height, height,
states: _states, states,
} = event } = event
{ {
if width == 0 || height == 0 { let width = NonZeroU32::new(width as u32);
return; let height = NonZeroU32::new(height as u32);
} let fullscreen = states.contains(&(xdg_toplevel::State::Fullscreen as u8));
for window in &state.windows { for window in &state.windows {
if window.1.toplevel.id() == xdg_toplevel.id() { if window.1.toplevel.id() == xdg_toplevel.id() {
window.1.resize(width, height); window.1.resize(width, height);
window.1.set_fullscreen(fullscreen);
window.1.surface.commit(); window.1.surface.commit();
return; return;
} }

View file

@ -1,6 +1,7 @@
use std::any::Any; use std::any::Any;
use std::cell::RefCell; use std::cell::RefCell;
use std::ffi::c_void; use std::ffi::c_void;
use std::num::NonZeroU32;
use std::rc::Rc; use std::rc::Rc;
use std::sync::Arc; use std::sync::Arc;
@ -40,8 +41,9 @@ pub(crate) struct Callbacks {
struct WaylandWindowInner { struct WaylandWindowInner {
renderer: BladeRenderer, renderer: BladeRenderer,
bounds: Bounds<i32>, bounds: Bounds<u32>,
scale: f32, scale: f32,
fullscreen: bool,
input_handler: Option<PlatformInputHandler>, input_handler: Option<PlatformInputHandler>,
decoration_state: WaylandDecorationState, decoration_state: WaylandDecorationState,
} }
@ -68,7 +70,7 @@ unsafe impl HasRawDisplayHandle for RawWindow {
} }
impl WaylandWindowInner { impl WaylandWindowInner {
fn new(wl_surf: &Arc<wl_surface::WlSurface>, bounds: Bounds<i32>) -> Self { fn new(wl_surf: &Arc<wl_surface::WlSurface>, bounds: Bounds<u32>) -> Self {
let raw = RawWindow { let raw = RawWindow {
window: wl_surf.id().as_ptr().cast::<c_void>(), window: wl_surf.id().as_ptr().cast::<c_void>(),
display: wl_surf display: wl_surf
@ -92,14 +94,15 @@ impl WaylandWindowInner {
.unwrap(), .unwrap(),
); );
let extent = gpu::Extent { let extent = gpu::Extent {
width: bounds.size.width as u32, width: bounds.size.width,
height: bounds.size.height as u32, height: bounds.size.height,
depth: 1, depth: 1,
}; };
Self { Self {
renderer: BladeRenderer::new(gpu, extent), renderer: BladeRenderer::new(gpu, extent),
bounds, bounds,
scale: 1.0, scale: 1.0,
fullscreen: false,
input_handler: None, input_handler: None,
// On wayland, decorations are by default provided by the client // On wayland, decorations are by default provided by the client
@ -130,7 +133,7 @@ impl WaylandWindowState {
toplevel.set_fullscreen(None); toplevel.set_fullscreen(None);
} }
let bounds: Bounds<i32> = match options.bounds { let bounds: Bounds<u32> = match options.bounds {
WindowBounds::Fullscreen | WindowBounds::Maximized => Bounds { WindowBounds::Fullscreen | WindowBounds::Maximized => Bounds {
origin: Point::default(), origin: Point::default(),
size: Size { size: Size {
@ -138,7 +141,7 @@ impl WaylandWindowState {
height: 500, height: 500,
}, // todo(implement) }, // todo(implement)
}, },
WindowBounds::Fixed(bounds) => bounds.map(|p| p.0 as i32), WindowBounds::Fixed(bounds) => bounds.map(|p| p.0 as u32),
}; };
Self { Self {
@ -160,14 +163,38 @@ impl WaylandWindowState {
} }
} }
pub fn set_size_and_scale(&self, width: i32, height: i32, scale: f32) { pub fn set_size_and_scale(
self.inner.borrow_mut().scale = scale; &self,
self.inner.borrow_mut().bounds.size.width = width; width: Option<NonZeroU32>,
self.inner.borrow_mut().bounds.size.height = height; height: Option<NonZeroU32>,
self.inner.borrow_mut().renderer.update_drawable_size(size( scale: Option<f32>,
width as f64 * scale as f64, ) {
height as f64 * scale as f64, let (width, height, scale) = {
)); let mut inner = self.inner.borrow_mut();
if width.map_or(true, |width| width.get() == inner.bounds.size.width)
&& height.map_or(true, |height| height.get() == inner.bounds.size.height)
&& scale.map_or(true, |scale| scale == inner.scale)
{
return;
}
if let Some(width) = width {
inner.bounds.size.width = width.get();
}
if let Some(height) = height {
inner.bounds.size.height = height.get();
}
if let Some(scale) = scale {
inner.scale = scale;
}
let width = inner.bounds.size.width;
let height = inner.bounds.size.height;
let scale = inner.scale;
inner.renderer.update_drawable_size(size(
width as f64 * scale as f64,
height as f64 * scale as f64,
));
(width, height, scale)
};
if let Some(ref mut fun) = self.callbacks.borrow_mut().resize { if let Some(ref mut fun) = self.callbacks.borrow_mut().resize {
fun( fun(
@ -180,18 +207,25 @@ impl WaylandWindowState {
} }
if let Some(viewport) = &self.viewport { if let Some(viewport) = &self.viewport {
viewport.set_destination(width, height); viewport.set_destination(width as i32, height as i32);
} }
} }
pub fn resize(&self, width: i32, height: i32) { pub fn resize(&self, width: Option<NonZeroU32>, height: Option<NonZeroU32>) {
let scale = self.inner.borrow_mut().scale; let scale = self.inner.borrow_mut().scale;
self.set_size_and_scale(width, height, scale); self.set_size_and_scale(width, height, None);
} }
pub fn rescale(&self, scale: f32) { pub fn rescale(&self, scale: f32) {
let bounds = self.inner.borrow_mut().bounds; self.set_size_and_scale(None, None, Some(scale));
self.set_size_and_scale(bounds.size.width, bounds.size.height, scale) }
pub fn set_fullscreen(&self, fullscreen: bool) {
let mut callbacks = self.callbacks.borrow_mut();
if let Some(ref mut fun) = callbacks.fullscreen {
fun(fullscreen)
}
self.inner.borrow_mut().fullscreen = fullscreen;
} }
/// Notifies the window of the state of the decorations. /// Notifies the window of the state of the decorations.
@ -337,7 +371,7 @@ impl PlatformWindow for WaylandWindow {
} }
fn minimize(&self) { fn minimize(&self) {
// todo(linux) self.0.toplevel.set_minimized();
} }
fn zoom(&self) { fn zoom(&self) {
@ -345,7 +379,11 @@ impl PlatformWindow for WaylandWindow {
} }
fn toggle_full_screen(&self) { fn toggle_full_screen(&self) {
// todo(linux) if !self.0.inner.borrow_mut().fullscreen {
self.0.toplevel.set_fullscreen(None);
} else {
self.0.toplevel.unset_fullscreen();
}
} }
fn on_request_frame(&self, callback: Box<dyn FnMut()>) { fn on_request_frame(&self, callback: Box<dyn FnMut()>) {
@ -365,7 +403,7 @@ impl PlatformWindow for WaylandWindow {
} }
fn on_fullscreen(&self, callback: Box<dyn FnMut(bool)>) { fn on_fullscreen(&self, callback: Box<dyn FnMut(bool)>) {
// todo(linux) self.0.callbacks.borrow_mut().fullscreen = Some(callback);
} }
fn on_moved(&self, callback: Box<dyn FnMut()>) { fn on_moved(&self, callback: Box<dyn FnMut()>) {