Implement kill-command to kill the current window, document it
This commit is contained in:
@ -560,8 +560,10 @@ void parse_command(xcb_connection_t *conn, const char *command) {
|
||||
}
|
||||
|
||||
/* Is it an <exit>? */
|
||||
if (STARTS_WITH(command, "exit"))
|
||||
exit(0);
|
||||
if (STARTS_WITH(command, "exit")) {
|
||||
LOG("User issued exit-command, exiting without error.\n");
|
||||
exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/* Is it <restart>? Then restart in place. */
|
||||
if (STARTS_WITH(command, "restart")) {
|
||||
@ -570,6 +572,17 @@ void parse_command(xcb_connection_t *conn, const char *command) {
|
||||
/* not reached */
|
||||
}
|
||||
|
||||
if (STARTS_WITH(command, "kill")) {
|
||||
if (CUR_CELL->currently_focused == NULL) {
|
||||
LOG("There is no window to kill\n");
|
||||
return;
|
||||
}
|
||||
|
||||
LOG("Killing current window\n");
|
||||
kill_window(conn, CUR_CELL->currently_focused);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Is it 'f' for fullscreen? */
|
||||
if (command[0] == 'f') {
|
||||
if (CUR_CELL->currently_focused == NULL)
|
||||
|
@ -375,6 +375,8 @@ int main(int argc, char *argv[], char *env[]) {
|
||||
REQUEST_ATOM(_NET_WM_DESKTOP);
|
||||
REQUEST_ATOM(_NET_WM_WINDOW_TYPE_DOCK);
|
||||
REQUEST_ATOM(_NET_WM_STRUT_PARTIAL);
|
||||
REQUEST_ATOM(WM_PROTOCOLS);
|
||||
REQUEST_ATOM(WM_DELETE_WINDOW);
|
||||
REQUEST_ATOM(UTF8_STRING);
|
||||
|
||||
/* TODO: this has to be more beautiful somewhen */
|
||||
@ -475,6 +477,8 @@ int main(int argc, char *argv[], char *env[]) {
|
||||
GET_ATOM(_NET_WM_DESKTOP);
|
||||
GET_ATOM(_NET_WM_WINDOW_TYPE_DOCK);
|
||||
GET_ATOM(_NET_WM_STRUT_PARTIAL);
|
||||
GET_ATOM(WM_PROTOCOLS);
|
||||
GET_ATOM(WM_DELETE_WINDOW);
|
||||
GET_ATOM(UTF8_STRING);
|
||||
|
||||
xcb_property_set_handler(&prophs, atoms[_NET_WM_WINDOW_TYPE], UINT_MAX, handle_window_type, NULL);
|
||||
|
53
src/util.c
53
src/util.c
@ -19,6 +19,8 @@
|
||||
#include <assert.h>
|
||||
#include <iconv.h>
|
||||
|
||||
#include <xcb/xcb_icccm.h>
|
||||
|
||||
#include "i3.h"
|
||||
#include "data.h"
|
||||
#include "table.h"
|
||||
@ -391,3 +393,54 @@ void toggle_fullscreen(xcb_connection_t *conn, Client *client) {
|
||||
|
||||
xcb_flush(conn);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns true if the client supports the given protocol atom (like WM_DELETE_WINDOW)
|
||||
*
|
||||
*/
|
||||
static bool client_supports_protocol(xcb_connection_t *conn, Client *client, xcb_atom_t atom) {
|
||||
xcb_get_property_cookie_t cookie;
|
||||
xcb_get_wm_protocols_reply_t protocols;
|
||||
bool result = false;
|
||||
|
||||
cookie = xcb_get_wm_protocols_unchecked(conn, client->child, atoms[WM_PROTOCOLS]);
|
||||
if (xcb_get_wm_protocols_reply(conn, cookie, &protocols, NULL) != 1)
|
||||
return false;
|
||||
|
||||
/* Check if the client’s protocols have the requested atom set */
|
||||
for (uint32_t i = 0; i < protocols.atoms_len; i++)
|
||||
if (protocols.atoms[i] == atom)
|
||||
result = true;
|
||||
|
||||
xcb_get_wm_protocols_reply_wipe(&protocols);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Kills the given window using WM_DELETE_WINDOW or xcb_kill_window
|
||||
*
|
||||
*/
|
||||
void kill_window(xcb_connection_t *conn, Client *window) {
|
||||
/* If the client does not support WM_DELETE_WINDOW, we kill it the hard way */
|
||||
if (!client_supports_protocol(conn, window, atoms[WM_DELETE_WINDOW])) {
|
||||
LOG("Killing window the hard way\n");
|
||||
xcb_kill_client(conn, window->child);
|
||||
return;
|
||||
}
|
||||
|
||||
xcb_client_message_event_t ev;
|
||||
|
||||
memset(&ev, 0, sizeof(xcb_client_message_event_t));
|
||||
|
||||
ev.response_type = XCB_CLIENT_MESSAGE;
|
||||
ev.window = window->child;
|
||||
ev.type = atoms[WM_PROTOCOLS];
|
||||
ev.format = 32;
|
||||
ev.data.data32[0] = atoms[WM_DELETE_WINDOW];
|
||||
ev.data.data32[1] = XCB_CURRENT_TIME;
|
||||
|
||||
LOG("Sending WM_DELETE to the client\n");
|
||||
xcb_send_event(conn, false, window->child, XCB_EVENT_MASK_NO_EVENT, (char*)&ev);
|
||||
xcb_flush(conn);
|
||||
}
|
||||
|
Reference in New Issue
Block a user