Implement kill-command to kill the current window, document it
This commit is contained in:
parent
cc0b060628
commit
cb9c7078be
2
CMDMODE
2
CMDMODE
|
@ -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
|
||||
|
||||
|
|
|
@ -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 don’t have an own launcher
|
||||
bind Mod1+55 exec /usr/bin/dmenu_run
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue