summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortcmal <me@aria.rip>2024-08-30 15:48:34 +0100
committertcmal <me@aria.rip>2024-08-30 16:20:29 +0100
commitb5601a6eb3a8d0603bb837a847701d3d49f984c3 (patch)
tree3004b27ed9b710b7cd8d4569e852f072db7814e8
parent12c930d9118941997336deb9ef6c676aa35b1cd9 (diff)
Add bind for killing clients
-rw-r--r--src/clients/mod.rs28
-rw-r--r--src/config.rs5
-rw-r--r--src/conn_info/mod.rs8
-rw-r--r--src/helpers.rs7
4 files changed, 39 insertions, 9 deletions
diff --git a/src/clients/mod.rs b/src/clients/mod.rs
index da341ba..4ebd634 100644
--- a/src/clients/mod.rs
+++ b/src/clients/mod.rs
@@ -11,12 +11,12 @@ use crate::{
};
use xcb::{
x::{
- self, ChangeProperty, ConfigWindow, ConfigWindowMask, ConfigureNotifyEvent,
+ self, ChangeProperty, CloseDown, ConfigWindow, ConfigWindowMask, ConfigureNotifyEvent,
ConfigureRequestEvent, ConfigureWindow, DeleteProperty, DestroyNotifyEvent, EventMask,
- GetWindowAttributes, InputFocus, MapRequestEvent, PropMode, SetInputFocus,
- UnmapNotifyEvent, Window,
+ GetWindowAttributes, InputFocus, KillClient, MapRequestEvent, PropMode, SetCloseDownMode,
+ SetInputFocus, UnmapNotifyEvent, Window,
},
- xinerama, BaseEvent, Extension,
+ xinerama, BaseEvent, Extension, Xid,
};
pub use client::*;
@@ -548,6 +548,26 @@ impl ClientState {
pub fn client_mon(&self, pos: ClientIdx) -> &MonitorInfo {
&self.mons[self.client_mon_idx(pos)]
}
+
+ pub fn kill_client(&self, conn: &Connection, pos: usize) {
+ let c = self.client(pos);
+ // Modern clients respond to the WM_DELETE event
+ if !conn.send_event(c.window(), conn.atoms.wm_delete) {
+ // Fallback to the old fashioned way
+
+ // Using checked requests so we can ignore errors here without waiting for them to go to
+ // the event loop
+ let cookie1 = conn.send_request_checked(&SetCloseDownMode {
+ mode: CloseDown::DestroyAll,
+ });
+ let cookie2 = conn.send_request_checked(&KillClient {
+ resource: c.window().resource_id(),
+ });
+
+ let _ = conn.check_request(cookie1);
+ let _ = conn.check_request(cookie2);
+ }
+ }
}
impl Default for ClientState {
diff --git a/src/config.rs b/src/config.rs
index f052c22..f806df4 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -9,8 +9,8 @@ use crate::{
clients::TagFocus,
conn_info::Colour,
helpers::{
- focus_next, focus_prev, mouse_move, mouse_resize, set_tag, set_tag_focus, spawn,
- toggle_floating, toggle_fullscreen,
+ focus_next, focus_prev, kill_client, mouse_move, mouse_resize, set_tag, set_tag_focus,
+ spawn, toggle_floating, toggle_fullscreen,
},
keys::Keybinds,
};
@@ -49,6 +49,7 @@ pub const KEYBINDS: Keybinds = Keybinds(&[
bind!(MAIN_MODIFIER , k -> &focus_prev),
bind!(MAIN_MODIFIER.union(ModMask::SHIFT) , space -> &toggle_floating),
bind!(MAIN_MODIFIER.union(ModMask::SHIFT) , f -> &toggle_fullscreen),
+ bind!(MAIN_MODIFIER.union(ModMask::SHIFT) , q -> &kill_client),
bind!(MAIN_MODIFIER , _1 -> &|wm| set_tag_focus(wm, TagFocus::Tag(1))),
bind!(MAIN_MODIFIER , _2 -> &|wm| set_tag_focus(wm, TagFocus::Tag(2))),
bind!(MAIN_MODIFIER , _3 -> &|wm| set_tag_focus(wm, TagFocus::Tag(3))),
diff --git a/src/conn_info/mod.rs b/src/conn_info/mod.rs
index f85cdc0..42f3955 100644
--- a/src/conn_info/mod.rs
+++ b/src/conn_info/mod.rs
@@ -180,7 +180,7 @@ impl<'a> Connection<'a> {
}
/// Send event to window `w`, if the event is supported.
- pub fn send_event(&self, window: Window, event: Atom) {
+ pub fn send_event(&self, window: Window, event: Atom) -> bool {
let Ok(protocols) = self.wait_for_reply(self.send_request(&GetProperty {
delete: false,
window,
@@ -189,11 +189,11 @@ impl<'a> Connection<'a> {
long_offset: 0,
long_length: 100_000,
})) else {
- return;
+ return false;
};
if protocols.r#type() != x::ATOM_ATOM || protocols.format() != 32 {
- return;
+ return false;
}
let supported = protocols
@@ -213,6 +213,8 @@ impl<'a> Connection<'a> {
),
});
}
+
+ supported
}
/// Delegate for [`RawConnection::send_request`]
diff --git a/src/helpers.rs b/src/helpers.rs
index 5a2844d..819719b 100644
--- a/src/helpers.rs
+++ b/src/helpers.rs
@@ -70,6 +70,13 @@ pub fn toggle_fullscreen(wm: &mut WM<'_>) {
}
}
+/// Send the kill signal to the currently focused client
+pub fn kill_client(wm: &mut WM<'_>) {
+ if let Some(pos) = wm.clients.focused_pos() {
+ wm.clients.kill_client(&wm.conn, pos);
+ }
+}
+
/// Set the focused tag for the currently selected monitor
pub fn set_tag_focus(wm: &mut WM<'_>, tag_focus: TagFocus) {
wm.clients