summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/clients/client.rs20
-rw-r--r--src/clients/mod.rs11
-rw-r--r--src/conn_info/mod.rs17
3 files changed, 36 insertions, 12 deletions
diff --git a/src/clients/client.rs b/src/clients/client.rs
index a7b1a8d..3648f0c 100644
--- a/src/clients/client.rs
+++ b/src/clients/client.rs
@@ -3,7 +3,7 @@ use xcb::{
ChangeProperty, ChangeWindowAttributes, ConfigWindow, ConfigureNotifyEvent,
ConfigureWindow, Cw, EventMask, MapWindow, SendEvent, SendEventDest, Window,
},
- Xid,
+ VoidCookie, VoidCookieChecked, Xid,
};
use crate::{config::BORDER_WIDTH, conn_info::Connection};
@@ -125,11 +125,15 @@ impl Client {
/// Set the event mask for this window
/// This function does not check for success, so `conn.flush()` should be called after.
- pub fn set_event_mask(&self, conn: &Connection<'_>, event_mask: EventMask) {
- conn.send_request(&ChangeWindowAttributes {
+ pub fn set_event_mask(
+ &self,
+ conn: &Connection<'_>,
+ event_mask: EventMask,
+ ) -> VoidCookieChecked {
+ conn.send_request_checked(&ChangeWindowAttributes {
window: self.window(),
value_list: &[Cw::EventMask(event_mask)],
- });
+ })
}
/// Sync the non-geometry related properties with EWMH hints
@@ -150,14 +154,14 @@ impl Client {
}
/// Set the given window as withdrawn / not withdrawn.
- pub fn set_withdrawn(&self, conn: &Connection<'_>, withdrawn: bool) {
- conn.send_request(&ChangeProperty {
+ pub fn set_withdrawn(&self, conn: &Connection<'_>, withdrawn: bool) -> VoidCookieChecked {
+ conn.send_request_checked(&ChangeProperty {
mode: xcb::x::PropMode::Replace,
window: self.window,
property: conn.atoms.wm_state,
r#type: conn.atoms.wm_state,
- data: &[u8::from(!withdrawn), 0_u8],
- });
+ data: &[u32::from(!withdrawn), 0_u32],
+ })
}
pub fn set_urgent(&mut self, urgent: bool) {
diff --git a/src/clients/mod.rs b/src/clients/mod.rs
index d07de74..70e3798 100644
--- a/src/clients/mod.rs
+++ b/src/clients/mod.rs
@@ -94,7 +94,9 @@ impl WM<'_> {
pub(crate) fn handle_unmap_notify(&mut self, e: &UnmapNotifyEvent) -> Result<()> {
if let Some(c) = self.clients.find_client_mut(e.window()) {
if e.is_from_send_event() {
- c.set_withdrawn(&self.conn, true);
+ let cookie = c.set_withdrawn(&self.conn, true);
+ // The above may fail if the window has already been destroyed - just discard the error here.
+ let _ = self.conn.check_request(cookie);
} else {
self.clients.unmanage(&self.conn, e.window(), false);
}
@@ -237,9 +239,12 @@ impl ClientState {
let c = self.mons[mon].clients.remove(i);
if !already_destroyed {
- c.set_event_mask(conn, EventMask::empty());
+ c.set_event_mask(conn, EventMask::NO_EVENT);
// TODO: Ungrab button
- c.set_withdrawn(conn, true);
+ let cookie = c.set_withdrawn(conn, true);
+
+ // If any of the above requests fail, it's just a race condition and the window is already destroyed, so discard the error here.
+ let _ = conn.check_request(cookie);
}
self.rearrange(conn);
}
diff --git a/src/conn_info/mod.rs b/src/conn_info/mod.rs
index 1981938..183f691 100644
--- a/src/conn_info/mod.rs
+++ b/src/conn_info/mod.rs
@@ -4,7 +4,7 @@ use xcb::{
self, ChangeProperty, ChangeWindowAttributes, CreateWindow, DeleteProperty, DestroyWindow,
Window, WindowClass,
},
- Connection as RawConnection, Cookie,
+ Connection as RawConnection, Cookie, VoidCookieChecked,
};
mod atoms;
@@ -190,6 +190,16 @@ impl<'a> Connection<'a> {
cookie
}
+ /// Delegate for [`RawConnection::send_request_checked`]
+ pub fn send_request_checked<R>(&self, req: &R) -> VoidCookieChecked
+ where
+ R: xcb::RequestWithoutReply + Debug,
+ {
+ let cookie = self.conn.send_request_checked(req);
+ debug_req!(req, cookie);
+ cookie
+ }
+
/// Delegate for [`RawConnection::send_and_check_request`]
pub fn send_and_check_request<R>(&self, req: &R) -> Result<()>
where
@@ -199,6 +209,11 @@ impl<'a> Connection<'a> {
self.conn.send_and_check_request(req).map_err(Into::into)
}
+ /// Delegate for [`RawConnection::check_request`]
+ pub fn check_request(&self, c: VoidCookieChecked) -> Result<()> {
+ self.conn.check_request(c).map_err(Into::into)
+ }
+
/// Delegate for [`RawConnection::flush`]
pub fn flush(&self) -> Result<()> {
self.conn.flush().map_err(Into::into)