Allow toplevels to reconfigure themselves

This commit is contained in:
Shawn Wallace 2025-05-11 11:46:29 -04:00
parent 378421d356
commit 51300780f8
4 changed files with 36 additions and 26 deletions

View file

@ -125,7 +125,7 @@ impl SurfaceData {
output_name
}
fn update_viewport(&self, dims: WindowDims, size_hints: Option<WmNormalHints>) {
pub(super) fn update_viewport(&self, dims: WindowDims, size_hints: Option<WmNormalHints>) {
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 {

View file

@ -798,8 +798,8 @@ impl<C: XConnection> ServerState<C> {
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<C: XConnection> ServerState<C> {
);
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."),
}
}

View file

@ -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<dyn FnMut(&Event) -> bool + 'a>;

View file

@ -407,21 +407,19 @@ 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 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()));
}