Implement kill-command to kill the current window, document it

next
Michael Stapelberg 2009-03-14 22:09:36 +01:00
parent cc0b060628
commit cb9c7078be
9 changed files with 86 additions and 4 deletions

View File

@ -17,7 +17,7 @@ with := <w> { [ <times> ] <where> }+ <space> <cmd>
oder
special := [ exec <path> | exit | restart ]
special := [ exec <path> | kill | exit | restart ]
an jeder Stelle kann mit escape abgebrochen werden

View File

@ -72,6 +72,9 @@ bind Mod1+Shift+19 m10
# Mod1+Enter starts a new terminal
bind Mod1+36 exec /usr/bin/urxvt
# Mod1+Shift+q kills the current client
bind Mod1+Shift+24 kill
# Mod1+v starts dmenu and launches the selected application
# for now, we dont have an own launcher
bind Mod1+55 exec /usr/bin/dmenu_run

View File

@ -18,7 +18,7 @@
#ifndef _I3_H
#define _I3_H
#define NUM_ATOMS 10
#define NUM_ATOMS 12
extern char *application_path;
extern Display *xkbdpy;

View File

@ -46,5 +46,6 @@ void leave_stack_mode(xcb_connection_t *conn, Container *container);
void switch_layout_mode(xcb_connection_t *conn, Container *container, int mode);
void warp_pointer_into(xcb_connection_t *conn, Client *client);
void toggle_fullscreen(xcb_connection_t *conn, Client *client);
void kill_window(xcb_connection_t *conn, Client *window);
#endif

View File

@ -46,6 +46,8 @@ enum { _NET_SUPPORTED = 0,
_NET_WM_WINDOW_TYPE_DOCK,
_NET_WM_DESKTOP,
_NET_WM_STRUT_PARTIAL,
WM_PROTOCOLS,
WM_DELETE_WINDOW,
UTF8_STRING
};

View File

@ -108,6 +108,9 @@ Enable stacking layout for the current container.
Mod1+d::
Enable default layout for the current container.
Mod1+Shift+q::
Kills the current client.
Mod1+Shift+r::
Restarts i3 in place (without losing any windows, but the layout).
@ -136,6 +139,9 @@ bind Mod1+36 exec /usr/bin/urxvt
# Start dmenu (Mod1+v)
bind Mod1+55 exec /usr/bin/dmenu_run
# Kill current client (Mod1+Shift+q)
bind Mod1+Shift+24 kill
# Beamer on/off
bind Mod1+73 exec /home/michael/toggle_beamer.sh

View File

@ -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)

View File

@ -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);

View File

@ -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 clients 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);
}