Avoid processing events from a reparented window

Should fix #71
This commit is contained in:
Shawn Wallace 2024-11-08 22:36:27 -05:00
parent b0ee6db9fa
commit 3e6f892d20
3 changed files with 77 additions and 7 deletions

View file

@ -575,7 +575,10 @@ impl<C: XConnection> ServerState<C> {
} }
pub fn set_win_title(&mut self, window: x::Window, name: WmName) { pub fn set_win_title(&mut self, window: x::Window, name: WmName) {
let win = self.windows.get_mut(&window).unwrap(); let Some(win) = self.windows.get_mut(&window) else {
debug!("not setting title for unknown window {window:?}");
return;
};
let new_title = match &mut win.attrs.title { let new_title = match &mut win.attrs.title {
Some(w) => { Some(w) => {
@ -607,7 +610,10 @@ impl<C: XConnection> ServerState<C> {
} }
pub fn set_win_class(&mut self, window: x::Window, class: String) { pub fn set_win_class(&mut self, window: x::Window, class: String) {
let win = self.windows.get_mut(&window).unwrap(); let Some(win) = self.windows.get_mut(&window) else {
debug!("not setting class for unknown window {window:?}");
return;
};
let class = win.attrs.class.insert(class); let class = win.attrs.class.insert(class);
if let Some(key) = win.surface_key { if let Some(key) = win.surface_key {
@ -623,12 +629,18 @@ impl<C: XConnection> ServerState<C> {
} }
pub fn set_win_hints(&mut self, window: x::Window, hints: WmHints) { pub fn set_win_hints(&mut self, window: x::Window, hints: WmHints) {
let win = self.windows.get_mut(&window).unwrap(); let Some(win) = self.windows.get_mut(&window) else {
debug!("not setting hints for unknown window {window:?}");
return;
};
win.attrs.group = hints.window_group; win.attrs.group = hints.window_group;
} }
pub fn set_size_hints(&mut self, window: x::Window, hints: WmNormalHints) { pub fn set_size_hints(&mut self, window: x::Window, hints: WmNormalHints) {
let win = self.windows.get_mut(&window).unwrap(); let Some(win) = self.windows.get_mut(&window) else {
debug!("not setting size hints for unknown window {window:?}");
return;
};
if win.attrs.size_hints.is_none() || *win.attrs.size_hints.as_ref().unwrap() != hints { if win.attrs.size_hints.is_none() || *win.attrs.size_hints.as_ref().unwrap() != hints {
debug!("setting {window:?} hints {hints:?}"); debug!("setting {window:?} hints {hints:?}");
@ -669,7 +681,10 @@ impl<C: XConnection> ServerState<C> {
} }
pub fn reconfigure_window(&mut self, event: x::ConfigureNotifyEvent) { pub fn reconfigure_window(&mut self, event: x::ConfigureNotifyEvent) {
let win = self.windows.get_mut(&event.window()).unwrap(); let Some(win) = self.windows.get_mut(&event.window()) else {
debug!("not reconfiguring unknown window {:?}", event.window());
return;
};
let dims = WindowDims { let dims = WindowDims {
x: event.x(), x: event.x(),
y: event.y(), y: event.y(),
@ -716,7 +731,10 @@ impl<C: XConnection> ServerState<C> {
pub fn map_window(&mut self, window: x::Window) { pub fn map_window(&mut self, window: x::Window) {
debug!("mapping {window:?}"); debug!("mapping {window:?}");
let window = self.windows.get_mut(&window).unwrap(); let Some(window) = self.windows.get_mut(&window) else {
debug!("not mapping unknown window {window:?}");
return;
};
window.mapped = true; window.mapped = true;
} }

View file

@ -235,6 +235,8 @@ impl XState {
} }
}; };
} }
let mut ignored_windows = Vec::new();
while let Some(event) = self.connection.poll_for_event().unwrap() { while let Some(event) = self.connection.poll_for_event().unwrap() {
trace!("x11 event: {event:?}"); trace!("x11 event: {event:?}");
@ -268,6 +270,7 @@ impl XState {
} else { } else {
debug!("destroying window since its parent is no longer root!"); debug!("destroying window since its parent is no longer root!");
server_state.destroy_window(e.window()); server_state.destroy_window(e.window());
ignored_windows.push(e.window());
} }
} }
xcb::Event::X(x::Event::MapRequest(e)) => { xcb::Event::X(x::Event::MapRequest(e)) => {
@ -325,6 +328,9 @@ impl XState {
server_state.destroy_window(e.window()); server_state.destroy_window(e.window());
} }
xcb::Event::X(x::Event::PropertyNotify(e)) => { xcb::Event::X(x::Event::PropertyNotify(e)) => {
if ignored_windows.contains(&e.window()) {
continue;
}
self.handle_property_change(e, server_state); self.handle_property_change(e, server_state);
} }
xcb::Event::X(x::Event::ConfigureRequest(e)) => { xcb::Event::X(x::Event::ConfigureRequest(e)) => {

View file

@ -428,7 +428,7 @@ fn toplevel_flow() {
window, window,
x::ATOM_STRING, x::ATOM_STRING,
x::ATOM_WM_CLASS, x::ATOM_WM_CLASS,
&[c"boink".to_bytes()].concat(), c"boink".to_bytes(),
); );
connection.set_property( connection.set_property(
window, window,
@ -485,6 +485,52 @@ fn reparent() {
f.configure_and_verify_new_toplevel(&mut connection, child, surface); f.configure_and_verify_new_toplevel(&mut connection, child, surface);
} }
#[test]
fn window_properties_after_reparent() {
let mut f = Fixture::new();
let mut connection = Connection::new(&f.display);
let child = connection.new_window(connection.root, 0, 0, 1, 1, true);
connection.map_window(child);
f.wait_and_dispatch();
let child_surface = f
.testwl
.last_created_surface_id()
.expect("No surface created!");
f.configure_and_verify_new_toplevel(&mut connection, child, child_surface);
let other = connection.new_window(connection.root, 0, 0, 100, 100, false);
connection.map_window(other);
f.wait_and_dispatch();
let other_surface = f
.testwl
.last_created_surface_id()
.expect("No surface created!");
f.configure_and_verify_new_toplevel(&mut connection, other, other_surface);
connection.send_request(&x::UnmapWindow { window: child });
let parent = connection.new_window(connection.root, 0, 0, 20, 20, false);
connection.send_request(&x::ReparentWindow {
window: child,
parent,
x: 0,
y: 0,
});
// The server should get the notifications for these properties and shouldn't crash
connection.set_property(
child,
x::ATOM_WM_SIZE_HINTS,
x::ATOM_WM_NORMAL_HINTS,
&[16u32, 0, 0, 0, 0, 200, 400],
);
connection.set_property(child, x::ATOM_STRING, x::ATOM_WM_NAME, b"title\0");
connection.set_property(child, x::ATOM_STRING, x::ATOM_WM_CLASS, c"class".to_bytes());
f.wait_and_dispatch();
}
#[test] #[test]
fn input_focus() { fn input_focus() {
let mut f = Fixture::new(); let mut f = Fixture::new();