kbgwm

sucklessy floating window manager
git clone https://git.neuralcrash.com/kbgwm.git
Log | Files | Refs | README | LICENSE

commit 54dc2aae7587e02e5824a0db3621582ae978a966
parent 9202c0151600cf238b17df993f099e071bebf771
Author: Kebigon <git@kebigon.xyz>
Date:   Tue, 21 Jul 2020 18:38:05 +0900

Add possibility to kill a client

Diffstat:
Mconfig.h | 1+
Mkbgwm.c | 19+++++++++++++++++++
Mxcbutils.c | 63++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
Mxcbutils.h | 13+++++++++++++
4 files changed, 95 insertions(+), 1 deletion(-)

diff --git a/config.h b/config.h @@ -27,6 +27,7 @@ static Key keys[] = { MODKEY, XK_Page_Down, workspace_next, { 0 } }, { MODKEY | SHIFT, XK_Tab, focus_next, { .b = true } }, { MODKEY, XK_Tab, focus_next, { .b = false } }, + { MODKEY, XK_q, client_kill, { 0 } }, { MODKEY | SHIFT, XK_q, quit, { 0 } }, WORKSPACEKEYS(XK_Home, 0) WORKSPACEKEYS(XK_1, 0) diff --git a/kbgwm.c b/kbgwm.c @@ -22,6 +22,7 @@ static client* client_find(xcb_window_t); static client* client_find_workspace(xcb_window_t, uint_fast8_t); static client* client_remove(); static client* client_remove_workspace(uint_fast8_t); +static void client_kill(const Arg*); static void client_create(xcb_window_t); static void client_sanitize_position(client*); static void client_sanitize_dimensions(client*); @@ -361,6 +362,21 @@ void client_sanitize_dimensions(client* client) client->height = height; } +void client_kill(__attribute__((unused))const Arg* arg) +{ + // No client are focused + if (workspaces[current_workspace] == NULL) + return; // Nothing to be done + + if (!xcb_send_atom(workspaces[current_workspace], wm_delete_window)) + { + // The client does not support WM_DELETE, let's kill it + xcb_kill_client(c, workspaces[current_workspace]->id); + } + + xcb_flush(c); +} + /* * Focus */ @@ -752,6 +768,9 @@ int main(void) for (uint_fast8_t i = 0; i != NB_WORKSPACES; i++) workspaces[i] = NULL; + wm_protocols = xcb_get_atom(WM_PROTOCOLS); + wm_delete_window = xcb_get_atom(WM_DELETE_WINDOW); + setup_keyboard(); setup_screen(); setup_events(); diff --git a/xcbutils.c b/xcbutils.c @@ -1,7 +1,11 @@ #include "xcbutils.h" -#include <stdio.h> +#include <assert.h> #include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <xcb/xcb_icccm.h> +#include <xcb/xproto.h> extern xcb_connection_t* c; extern xcb_window_t root; @@ -93,3 +97,60 @@ xcb_keysym_t xcb_get_keysym(xcb_keycode_t keycode) xcb_key_symbols_free(keysyms); return (keysym); } + +#define ONLY_IF_EXISTS 0 + +/* Get a defined atom from the X server. */ +xcb_atom_t xcb_get_atom(const char* atom_name) +{ + xcb_intern_atom_cookie_t cookie = xcb_intern_atom(c, ONLY_IF_EXISTS, strlen(atom_name), atom_name); + + xcb_intern_atom_reply_t* reply = xcb_intern_atom_reply(c, cookie, NULL); + + /* XXX Note that we return 0 as an atom if anything goes wrong. + * Might become interesting.*/ + + if (reply == NULL) + return 0; + + xcb_atom_t atom = reply->atom; + free(reply); + return atom; +} + +bool xcb_send_atom(client* client, xcb_atom_t atom) +{ + assert(client != NULL); + + bool supported = false; + xcb_get_property_cookie_t cookie = xcb_icccm_get_wm_protocols_unchecked(c, client->id, wm_protocols); + + // Get the supported atoms for this client + xcb_icccm_get_wm_protocols_reply_t protocols; + if (xcb_icccm_get_wm_protocols_reply(c, cookie, &protocols, NULL) == 1) + { + for (uint_fast32_t i = 0; i < protocols.atoms_len; i++) + { + if (protocols.atoms[i] == atom) + { + supported = true; + break; + } + } + } + + // The client does not support WM_DELETE, let's kill it + if (!supported) + return false; + + xcb_client_message_event_t ev; + ev.response_type = XCB_CLIENT_MESSAGE; + ev.format = 32; + ev.sequence = 0; + ev.window = client->id; + ev.type = wm_protocols; + ev.data.data32[0] = atom; + ev.data.data32[1] = XCB_CURRENT_TIME; + xcb_send_event(c, false, client->id, XCB_EVENT_MASK_NO_EVENT, (char*) &ev); + return true; +} diff --git a/xcbutils.h b/xcbutils.h @@ -21,4 +21,17 @@ void xcb_register_button_events(Button button); xcb_keycode_t* xcb_get_keycodes(xcb_keysym_t); xcb_keysym_t xcb_get_keysym(xcb_keycode_t); +/* + * Atoms + */ + +#define WM_DELETE_WINDOW "WM_DELETE_WINDOW" +#define WM_PROTOCOLS "WM_PROTOCOLS" + +xcb_atom_t wm_protocols; +xcb_atom_t wm_delete_window; + +xcb_atom_t xcb_get_atom(const char*); +bool xcb_send_atom(client*, xcb_atom_t); + #endif /* XCBUTILS_H_ */