From 51300780f84cb61d04a3c469099c758461b2a816 Mon Sep 17 00:00:00 2001 From: Shawn Wallace Date: Sun, 11 May 2025 11:46:29 -0400 Subject: [PATCH] Allow toplevels to reconfigure themselves --- src/server/event.rs | 2 +- src/server/mod.rs | 9 +++++++-- src/server/tests.rs | 35 +++++++++++++++++++++-------------- src/xstate/mod.rs | 16 +++++++--------- 4 files changed, 36 insertions(+), 26 deletions(-) diff --git a/src/server/event.rs b/src/server/event.rs index abd74f1..550d7ef 100644 --- a/src/server/event.rs +++ b/src/server/event.rs @@ -125,7 +125,7 @@ impl SurfaceData { output_name } - fn update_viewport(&self, dims: WindowDims, size_hints: Option) { + pub(super) fn update_viewport(&self, dims: WindowDims, size_hints: Option) { let width = (dims.width as f64 / self.scale_factor) as i32; let height = (dims.height as f64 / self.scale_factor) as i32; if width > 0 && height > 0 { diff --git a/src/server/mod.rs b/src/server/mod.rs index 3c81cf5..9fb0d81 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -798,8 +798,8 @@ impl ServerState { win.surface_serial = Some(serial); } - pub fn can_reconfigure_window(&mut self, window: x::Window) -> bool { - let Some(win) = self.windows.get_mut(&window) else { + pub fn can_change_position(&self, window: x::Window) -> bool { + let Some(win) = self.windows.get(&window) else { return true; }; @@ -851,6 +851,11 @@ impl ServerState { ); popup.popup.reposition(&popup.positioner, 0); } + Some(SurfaceRole::Toplevel(Some(_))) => { + win.attrs.dims.width = dims.width; + win.attrs.dims.height = dims.height; + data.update_viewport(win.attrs.dims, win.attrs.size_hints); + } other => warn!("Non popup ({other:?}) being reconfigured, behavior may be off."), } } diff --git a/src/server/tests.rs b/src/server/tests.rs index 98c19ce..51af4c4 100644 --- a/src/server/tests.rs +++ b/src/server/tests.rs @@ -1574,17 +1574,27 @@ fn reposition_popup() { } #[test] -fn ignore_toplevel_reconfigure() { +fn toplevel_reconfigure() { let (mut f, comp) = TestFixture::new_with_compositor(); let toplevel = unsafe { Window::new(1) }; - let _ = f.create_toplevel(&comp, toplevel); + let (_, surface) = f.create_toplevel(&comp, toplevel); + + { + let data = f + .testwl + .get_surface_data(surface) + .expect("Missing surface data"); + let viewport = data.viewport.as_ref().expect("Missing viewport"); + assert_eq!(viewport.width, 100); + assert_eq!(viewport.height, 100); + } f.satellite.reconfigure_window(x::ConfigureNotifyEvent::new( toplevel, toplevel, x::WINDOW_NONE, - 40, // x - 60, // y + 0, // x + 0, // y 80, // width 100, // height 0, @@ -1592,16 +1602,13 @@ fn ignore_toplevel_reconfigure() { )); f.run(); - let win_data = &f.connection().windows[&toplevel]; - assert_eq!( - win_data.dims, - WindowDims { - x: 0, - y: 0, - width: 100, - height: 100 - } - ); + let data = f + .testwl + .get_surface_data(surface) + .expect("Missing surface data"); + let viewport = data.viewport.as_ref().expect("Missing viewport"); + assert_eq!(viewport.width, 80); + assert_eq!(viewport.height, 100); } type EventMatcher<'a, Event> = Box bool + 'a>; diff --git a/src/xstate/mod.rs b/src/xstate/mod.rs index e07974a..4cf42a9 100644 --- a/src/xstate/mod.rs +++ b/src/xstate/mod.rs @@ -407,20 +407,18 @@ impl XState { self.handle_property_change(e, server_state); } xcb::Event::X(x::Event::ConfigureRequest(e)) => { - if !server_state.can_reconfigure_window(e.window()) { - debug!("ignoring reconfigure request for {:?}", e.window()); - continue; - } debug!("{:?} request: {:?}", e.window(), e.value_mask()); let mut list = Vec::new(); let mask = e.value_mask(); - if mask.contains(x::ConfigWindowMask::X) { - list.push(x::ConfigWindow::X(e.x().into())); - } - if mask.contains(x::ConfigWindowMask::Y) { - list.push(x::ConfigWindow::Y(e.y().into())); + if server_state.can_change_position(e.window()) { + if mask.contains(x::ConfigWindowMask::X) { + list.push(x::ConfigWindow::X(e.x().into())); + } + if mask.contains(x::ConfigWindowMask::Y) { + list.push(x::ConfigWindow::Y(e.y().into())); + } } if mask.contains(x::ConfigWindowMask::WIDTH) { list.push(x::ConfigWindow::Width(e.width().into()));