diff --git a/src/server/decoration.rs b/src/server/decoration.rs index 393e75b..18b56ce 100644 --- a/src/server/decoration.rs +++ b/src/server/decoration.rs @@ -41,6 +41,8 @@ pub struct DecorationsDataSatellite { x_data: DecorationsBox, title: Option, title_rect: Rect, + should_draw: bool, + remove_buffer: bool, } impl Drop for DecorationsDataSatellite { @@ -100,6 +102,8 @@ impl DecorationsDataSatellite { scale: 1.0, title: title.map(str::to_string), title_rect: Rect::from_ltrb(0.0, 0.0, 0.0, 0.0).unwrap(), + should_draw: true, + remove_buffer: false, } .into(), new_pool.map(|p| { @@ -134,9 +138,21 @@ impl DecorationsDataSatellite { self.surface.commit(); } - pub fn draw_decorations(&mut self, world: &World, width: i32, parent_scale_factor: f32) { - if width <= 0 { - return; + /// Returns true if decorations were actually drawn + #[must_use] + pub fn draw_decorations( + &mut self, + world: &World, + width: i32, + parent_scale_factor: f32, + ) -> bool { + if width <= 0 || !self.should_draw { + if self.remove_buffer { + self.surface.attach(None, 0, 0); + self.surface.commit(); + self.remove_buffer = false; + } + return false; } self.scale = parent_scale_factor; @@ -196,6 +212,7 @@ impl DecorationsDataSatellite { self.pixmap = bar; self.viewport.set_destination(width, Self::TITLEBAR_HEIGHT); self.update_buffer(world); + true } fn redraw_x_pixmap(&mut self, world: &World) { @@ -263,6 +280,13 @@ impl DecorationsDataSatellite { self.update_buffer(world); } + pub fn handle_fullscreen(&mut self, fullscreen: bool) { + if self.should_draw == fullscreen { + self.should_draw = !fullscreen; + self.remove_buffer = fullscreen; + } + } + fn handle_motion(&mut self, world: &World, x: f64, y: f64) { if self.x_data.check_hovered(x as f32, y as f32) { self.redraw_x_pixmap(world); diff --git a/src/server/event.rs b/src/server/event.rs index ad85bde..ffc3a06 100644 --- a/src/server/event.rs +++ b/src/server/event.rs @@ -313,13 +313,14 @@ impl SurfaceEvents { if let SurfaceRole::Toplevel(Some(toplevel)) = &mut *role { if let Some(d) = &mut toplevel.decoration.satellite { let surface_width = (width as f64 / scale_factor.0) as i32; - d.draw_decorations(&state.world, surface_width, scale_factor.0 as f32); - height = height - .saturating_sub( - (DecorationsDataSatellite::TITLEBAR_HEIGHT as f64 * scale_factor.0) - as u16, - ) - .max(DecorationsDataSatellite::TITLEBAR_HEIGHT as u16); + if d.draw_decorations(&state.world, surface_width, scale_factor.0 as f32) { + height = height + .saturating_sub( + (DecorationsDataSatellite::TITLEBAR_HEIGHT as f64 * scale_factor.0) + as u16, + ) + .max(DecorationsDataSatellite::TITLEBAR_HEIGHT as u16); + } } } @@ -393,6 +394,9 @@ impl SurfaceEvents { *data.get::<&x::Window>().unwrap(), toplevel.fullscreen, ); + if let Some(decorations) = toplevel.decoration.satellite.as_mut() { + decorations.handle_fullscreen(toplevel.fullscreen); + } } }; diff --git a/src/server/tests.rs b/src/server/tests.rs index 270979a..c651656 100644 --- a/src/server/tests.rs +++ b/src/server/tests.rs @@ -2608,23 +2608,61 @@ fn client_side_decorations() { let (_, id) = f.create_toplevel(&compositor, window); f.testwl .force_decoration_mode(id, zxdg_toplevel_decoration_v1::Mode::ClientSide); + f.testwl.configure_toplevel(id, 100, 100, vec![]); f.run(); + let data = f.connection().window(window); + assert_eq!( + data.dims, + WindowDims { + x: 0, + y: 0, + width: 100, + height: 75 + } + ); let subsurface_id = f.testwl.last_created_surface_id().unwrap(); assert_ne!(subsurface_id, id); let data = f.testwl.get_surface_data(subsurface_id).unwrap(); + assert!(data.buffer.is_some()); let Some(SurfaceRole::Subsurface(subsurface)) = &data.role else { panic!("surface was not a subsurface: {:?}", data.role); }; - assert_eq!(subsurface.position, testwl::Vec2 { x: 0, y: -25 }); assert_eq!(subsurface.parent, id); let subsurface = subsurface.subsurface.clone(); + f.testwl + .configure_toplevel(id, 100, 100, vec![xdg_toplevel::State::Fullscreen]); + f.run(); + let data = f.connection().window(window); + assert_eq!( + data.dims, + WindowDims { + x: 0, + y: 0, + width: 100, + height: 100 + } + ); + let data = f.testwl.get_surface_data(subsurface_id).unwrap(); + assert!(data.buffer.is_none()); + f.testwl .force_decoration_mode(id, zxdg_toplevel_decoration_v1::Mode::ServerSide); + f.testwl.configure_toplevel(id, 100, 100, vec![]); f.run(); + let data = f.connection().window(window); + assert_eq!( + data.dims, + WindowDims { + x: 0, + y: 0, + width: 100, + height: 100 + } + ); assert!(f.testwl.get_surface_data(subsurface_id).is_none()); assert!(!subsurface.is_alive()); } diff --git a/testwl/src/lib.rs b/testwl/src/lib.rs index 41c8a0b..26e4642 100644 --- a/testwl/src/lib.rs +++ b/testwl/src/lib.rs @@ -1865,6 +1865,7 @@ impl Dispatch for State { let buf = data_init.init(id, ()); state.buffers.insert(buf); } + Resize { .. } => {} Destroy => {} other => todo!("unhandled request {other:?}"), }