xstate: ignore some more BadWindow errors

Closes #24
This commit is contained in:
Shawn Wallace 2024-05-28 22:31:04 -04:00
parent 02bee5aea7
commit 601223d3ae
3 changed files with 46 additions and 43 deletions

View file

@ -42,6 +42,21 @@ impl From<xcb::ProtocolError> for MaybeBadWindow {
} }
type XResult<T> = Result<T, MaybeBadWindow>; type XResult<T> = Result<T, MaybeBadWindow>;
macro_rules! unwrap_or_skip_bad_window {
($err:expr) => {
match $err {
Ok(v) => v,
Err(e) => {
let err = MaybeBadWindow::from(e);
match err {
MaybeBadWindow::BadWindow => return,
MaybeBadWindow::Other(other) => panic!("X11 protocol error: {other:?}"),
}
}
}
};
}
/// Essentially a trait alias. /// Essentially a trait alias.
trait PropertyResolver { trait PropertyResolver {
type Output; type Output;
@ -194,7 +209,7 @@ impl XState {
} }
pub fn handle_events(&mut self, server_state: &mut super::RealServerState) { pub fn handle_events(&mut self, server_state: &mut super::RealServerState) {
macro_rules! unwrap_or_skip_bad_window { macro_rules! unwrap_or_skip_bad_window_cont {
($err:expr) => { ($err:expr) => {
match $err { match $err {
Ok(v) => v, Ok(v) => v,
@ -225,7 +240,7 @@ impl XState {
debug!("reparent event: {e:?}"); debug!("reparent event: {e:?}");
if e.parent() == self.root { if e.parent() == self.root {
let attrs = let attrs =
unwrap_or_skip_bad_window!(self.get_window_attributes(e.window())); unwrap_or_skip_bad_window_cont!(self.get_window_attributes(e.window()));
server_state.new_window( server_state.new_window(
e.window(), e.window(),
attrs.override_redirect, attrs.override_redirect,
@ -240,18 +255,19 @@ impl XState {
} }
xcb::Event::X(x::Event::MapRequest(e)) => { xcb::Event::X(x::Event::MapRequest(e)) => {
debug!("requested to map {:?}", e.window()); debug!("requested to map {:?}", e.window());
unwrap_or_skip_bad_window!(self unwrap_or_skip_bad_window_cont!(self
.connection .connection
.send_and_check_request(&x::MapWindow { window: e.window() })); .send_and_check_request(&x::MapWindow { window: e.window() }));
} }
xcb::Event::X(x::Event::MapNotify(e)) => { xcb::Event::X(x::Event::MapNotify(e)) => {
unwrap_or_skip_bad_window!(self.connection.send_and_check_request( unwrap_or_skip_bad_window_cont!(self.connection.send_and_check_request(
&x::ChangeWindowAttributes { &x::ChangeWindowAttributes {
window: e.window(), window: e.window(),
value_list: &[x::Cw::EventMask(x::EventMask::PROPERTY_CHANGE)], value_list: &[x::Cw::EventMask(x::EventMask::PROPERTY_CHANGE)],
} }
)); ));
let attrs = unwrap_or_skip_bad_window!(self.get_window_attributes(e.window())); let attrs =
unwrap_or_skip_bad_window_cont!(self.get_window_attributes(e.window()));
self.handle_window_attributes(server_state, e.window(), attrs); self.handle_window_attributes(server_state, e.window(), attrs);
server_state.map_window(e.window()); server_state.map_window(e.window());
} }
@ -261,7 +277,7 @@ impl XState {
xcb::Event::X(x::Event::UnmapNotify(e)) => { xcb::Event::X(x::Event::UnmapNotify(e)) => {
trace!("unmap event: {:?}", e.event()); trace!("unmap event: {:?}", e.event());
server_state.unmap_window(e.window()); server_state.unmap_window(e.window());
unwrap_or_skip_bad_window!(self.connection.send_and_check_request( unwrap_or_skip_bad_window_cont!(self.connection.send_and_check_request(
&x::ChangeWindowAttributes { &x::ChangeWindowAttributes {
window: e.window(), window: e.window(),
value_list: &[x::Cw::EventMask(x::EventMask::empty())], value_list: &[x::Cw::EventMask(x::EventMask::empty())],
@ -316,7 +332,7 @@ impl XState {
list.push(x::ConfigWindow::Height(e.height().into())); list.push(x::ConfigWindow::Height(e.height().into()));
} }
unwrap_or_skip_bad_window!(self.connection.send_and_check_request( unwrap_or_skip_bad_window_cont!(self.connection.send_and_check_request(
&x::ConfigureWindow { &x::ConfigureWindow {
window: e.window(), window: e.window(),
value_list: &list, value_list: &list,
@ -553,20 +569,6 @@ impl XState {
} }
let window = event.window(); let window = event.window();
macro_rules! unwrap_or_skip_bad_window {
($err:expr) => {
match $err {
Ok(v) => v,
Err(e) => {
let err = MaybeBadWindow::from(e);
match err {
MaybeBadWindow::BadWindow => return,
MaybeBadWindow::Other(other) => panic!("X11 protocol error: {other:?}"),
}
}
}
};
}
match event.atom() { match event.atom() {
x if x == x::ATOM_WM_HINTS => { x if x == x::ATOM_WM_HINTS => {
@ -751,7 +753,7 @@ impl super::XConnection for Arc<xcb::Connection> {
fn set_window_dims(&mut self, window: x::Window, dims: crate::server::PendingSurfaceState) { fn set_window_dims(&mut self, window: x::Window, dims: crate::server::PendingSurfaceState) {
trace!("reconfiguring window {window:?}"); trace!("reconfiguring window {window:?}");
self.send_and_check_request(&x::ConfigureWindow { unwrap_or_skip_bad_window!(self.send_and_check_request(&x::ConfigureWindow {
window, window,
value_list: &[ value_list: &[
x::ConfigWindow::X(dims.x), x::ConfigWindow::X(dims.x),
@ -759,8 +761,7 @@ impl super::XConnection for Arc<xcb::Connection> {
x::ConfigWindow::Width(dims.width as _), x::ConfigWindow::Width(dims.width as _),
x::ConfigWindow::Height(dims.height as _), x::ConfigWindow::Height(dims.height as _),
], ],
}) }));
.unwrap();
} }
fn set_fullscreen(&mut self, window: x::Window, fullscreen: bool, atoms: Self::ExtraData) { fn set_fullscreen(&mut self, window: x::Window, fullscreen: bool, atoms: Self::ExtraData) {
@ -780,16 +781,15 @@ impl super::XConnection for Arc<xcb::Connection> {
} }
fn focus_window(&mut self, window: x::Window, atoms: Self::ExtraData) { fn focus_window(&mut self, window: x::Window, atoms: Self::ExtraData) {
let prop = self let prop =
.wait_for_reply(self.send_request(&x::GetProperty { unwrap_or_skip_bad_window!(self.wait_for_reply(self.send_request(&x::GetProperty {
delete: false, delete: false,
window, window,
property: x::ATOM_WM_HINTS, property: x::ATOM_WM_HINTS,
r#type: x::ATOM_WM_HINTS, r#type: x::ATOM_WM_HINTS,
long_offset: 0, long_offset: 0,
long_length: 9, long_length: 9,
})) })));
.unwrap();
let set_focus = if prop.r#type() == x::ATOM_NONE { let set_focus = if prop.r#type() == x::ATOM_NONE {
true true
@ -806,19 +806,17 @@ impl super::XConnection for Arc<xcb::Connection> {
}); });
} }
self.send_and_check_request(&x::ConfigureWindow { unwrap_or_skip_bad_window!(self.send_and_check_request(&x::ConfigureWindow {
window, window,
value_list: &[x::ConfigWindow::StackMode(x::StackMode::Above)], value_list: &[x::ConfigWindow::StackMode(x::StackMode::Above)],
}) }));
.unwrap(); unwrap_or_skip_bad_window!(self.send_and_check_request(&x::ChangeProperty {
self.send_and_check_request(&x::ChangeProperty {
mode: x::PropMode::Replace, mode: x::PropMode::Replace,
window: self.root_window(), window: self.root_window(),
property: atoms.active_win, property: atoms.active_win,
r#type: x::ATOM_WINDOW, r#type: x::ATOM_WINDOW,
data: &[window], data: &[window],
}) }));
.unwrap();
} }
fn close_window(&mut self, window: x::Window, atoms: Self::ExtraData) { fn close_window(&mut self, window: x::Window, atoms: Self::ExtraData) {
@ -829,13 +827,12 @@ impl super::XConnection for Arc<xcb::Connection> {
x::ClientMessageData::Data32(data), x::ClientMessageData::Data32(data),
); );
self.send_and_check_request(&x::SendEvent { unwrap_or_skip_bad_window!(self.send_and_check_request(&x::SendEvent {
destination: x::SendEventDest::Window(window), destination: x::SendEventDest::Window(window),
propagate: false, propagate: false,
event_mask: x::EventMask::empty(), event_mask: x::EventMask::empty(),
event, event,
}) }));
.unwrap();
} }
} }

View file

@ -536,6 +536,11 @@ fn quick_delete() {
let window = connection.new_window(connection.root, 0, 0, 20, 20, false); let window = connection.new_window(connection.root, 0, 0, 20, 20, false);
connection.map_window(window); connection.map_window(window);
f.wait_and_dispatch();
let surf = f
.testwl
.last_created_surface_id()
.expect("No surface created");
connection.set_property( connection.set_property(
window, window,
x::ATOM_WM_HINTS, x::ATOM_WM_HINTS,
@ -567,12 +572,10 @@ fn quick_delete() {
value_list: &[x::ConfigWindow::X(10), x::ConfigWindow::Y(40)], value_list: &[x::ConfigWindow::X(10), x::ConfigWindow::Y(40)],
}) })
.unwrap(); .unwrap();
f.testwl
.configure_toplevel(surf, 100, 100, vec![xdg_toplevel::State::Activated]);
connection.destroy_window(window); connection.destroy_window(window);
f.wait_and_dispatch(); f.wait_and_dispatch();
let last_surf = f assert_eq!(f.testwl.get_surface_data(surf), None);
.testwl
.last_created_surface_id()
.expect("No surface created");
assert_eq!(f.testwl.get_surface_data(last_surf), None);
} }

View file

@ -170,7 +170,10 @@ impl State {
#[track_caller] #[track_caller]
fn get_toplevel(&mut self, surface_id: SurfaceId) -> &mut Toplevel { fn get_toplevel(&mut self, surface_id: SurfaceId) -> &mut Toplevel {
let surface = self.surfaces.get_mut(&surface_id).unwrap(); let surface = self
.surfaces
.get_mut(&surface_id)
.expect("Surface does not exist");
match &mut surface.role { match &mut surface.role {
Some(SurfaceRole::Toplevel(t)) => t, Some(SurfaceRole::Toplevel(t)) => t,
other => panic!("Surface does not have toplevel role: {:?}", other), other => panic!("Surface does not have toplevel role: {:?}", other),