Implement support for using key symbols in configuration file
Use "bindsym" instead of "bind". You have to use the names of keys as in xmodmap. To get a list of currently bounud symbols, use xmodmap -pke Technical quirk: Xlib generated MappingNotify events upon XkbMapNotify events (from XKB, as the name says). XCB does not yet have support for XKB, thus we need to select and handle the event by ourself. Hopefully, this will change in the future.
This commit is contained in:
parent
3bd724f08d
commit
7cdaa1b277
|
@ -79,6 +79,18 @@ struct Config {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void load_configuration(xcb_connection_t *conn, const char *override_configfile, bool reload);
|
void load_configuration(xcb_connection_t *conn, const char *override_configfile, bool reload);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ungrabs all keys, to be called before re-grabbing the keys because of a
|
||||||
|
* mapping_notify event or a configuration file reload
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void ungrab_all_keys(xcb_connection_t *conn);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Grab the bound keys (tell X to send us keypress events for those keycodes)
|
||||||
|
*
|
||||||
|
*/
|
||||||
void grab_all_keys(xcb_connection_t *conn);
|
void grab_all_keys(xcb_connection_t *conn);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -230,12 +230,29 @@ struct Workspace {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct Binding {
|
struct Binding {
|
||||||
|
/** Symbol the user specified in configfile, if any. This needs to be
|
||||||
|
* stored with the binding to be able to re-convert it into a keycode
|
||||||
|
* if the keyboard mapping changes (using Xmodmap for example) */
|
||||||
|
char *symbol;
|
||||||
|
|
||||||
|
/** Only in use if symbol != NULL. Gets set to the value to which the
|
||||||
|
* symbol got translated when binding. Useful for unbinding and
|
||||||
|
* checking which binding was used when a key press event comes in.
|
||||||
|
*
|
||||||
|
* This is an array of number_keycodes size. */
|
||||||
|
xcb_keycode_t *translated_to;
|
||||||
|
|
||||||
|
uint32_t number_keycodes;
|
||||||
|
|
||||||
/** Keycode to bind */
|
/** Keycode to bind */
|
||||||
uint32_t keycode;
|
uint32_t keycode;
|
||||||
|
|
||||||
/** Bitmask consisting of BIND_MOD_1, BIND_MODE_SWITCH, … */
|
/** Bitmask consisting of BIND_MOD_1, BIND_MODE_SWITCH, … */
|
||||||
uint32_t mods;
|
uint32_t mods;
|
||||||
|
|
||||||
/** Command, like in command mode */
|
/** Command, like in command mode */
|
||||||
char *command;
|
char *command;
|
||||||
|
|
||||||
TAILQ_ENTRY(Binding) bindings;
|
TAILQ_ENTRY(Binding) bindings;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,14 @@ int handle_enter_notify(void *ignored, xcb_connection_t *conn,
|
||||||
int handle_motion_notify(void *ignored, xcb_connection_t *conn,
|
int handle_motion_notify(void *ignored, xcb_connection_t *conn,
|
||||||
xcb_motion_notify_event_t *event);
|
xcb_motion_notify_event_t *event);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the keyboard mapping changes (for example by using Xmodmap),
|
||||||
|
* we need to update our key bindings then (re-translate symbols).
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int handle_mapping_notify(void *ignored, xcb_connection_t *conn,
|
||||||
|
xcb_mapping_notify_event_t *event);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the button press was on a stack window, handles focus setting and
|
* Checks if the button press was on a stack window, handles focus setting and
|
||||||
* returns true if so, or false otherwise.
|
* returns true if so, or false otherwise.
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
#include <xcb/xcb_property.h>
|
#include <xcb/xcb_property.h>
|
||||||
#include <xcb/xcb_event.h>
|
#include <xcb/xcb_event.h>
|
||||||
|
#include <xcb/xcb_keysyms.h>
|
||||||
|
|
||||||
#include <X11/XKBlib.h>
|
#include <X11/XKBlib.h>
|
||||||
|
|
||||||
|
@ -23,6 +24,7 @@
|
||||||
#define NUM_ATOMS 18
|
#define NUM_ATOMS 18
|
||||||
|
|
||||||
extern xcb_connection_t *global_conn;
|
extern xcb_connection_t *global_conn;
|
||||||
|
extern xcb_key_symbols_t *keysyms;
|
||||||
extern char **start_argv;
|
extern char **start_argv;
|
||||||
extern Display *xkbdpy;
|
extern Display *xkbdpy;
|
||||||
extern TAILQ_HEAD(bindings_head, Binding) bindings;
|
extern TAILQ_HEAD(bindings_head, Binding) bindings;
|
||||||
|
|
98
src/config.c
98
src/config.c
|
@ -14,6 +14,11 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <glob.h>
|
#include <glob.h>
|
||||||
|
|
||||||
|
/* We need Xlib for XStringToKeysym */
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
|
||||||
|
#include <xcb/xcb_keysyms.h>
|
||||||
|
|
||||||
#include "i3.h"
|
#include "i3.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
@ -59,15 +64,28 @@ static void replace_variable(char *buffer, const char *key, const char *value) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Ungrab the bound keys
|
* Ungrabs all keys, to be called before re-grabbing the keys because of a
|
||||||
|
* mapping_notify event or a configuration file reload
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void ungrab_all_keys(xcb_connection_t *conn) {
|
void ungrab_all_keys(xcb_connection_t *conn) {
|
||||||
Binding *bind;
|
LOG("Ungrabbing all keys\n");
|
||||||
TAILQ_FOREACH(bind, &bindings, bindings) {
|
xcb_ungrab_key(conn, XCB_GRAB_ANY, root, XCB_BUTTON_MASK_ANY);
|
||||||
LOG("Ungrabbing %d\n", bind->keycode);
|
}
|
||||||
xcb_ungrab_key(conn, bind->keycode, root, bind->keycode);
|
|
||||||
|
static void grab_keycode_for_binding(xcb_connection_t *conn, Binding *bind, uint32_t keycode) {
|
||||||
|
LOG("Grabbing %d\n", keycode);
|
||||||
|
if ((bind->mods & BIND_MODE_SWITCH) != 0)
|
||||||
|
xcb_grab_key(conn, 0, root, 0, keycode,
|
||||||
|
XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_SYNC);
|
||||||
|
else {
|
||||||
|
/* Grab the key in all combinations */
|
||||||
|
#define GRAB_KEY(modifier) xcb_grab_key(conn, 0, root, modifier, keycode, \
|
||||||
|
XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC)
|
||||||
|
GRAB_KEY(bind->mods);
|
||||||
|
GRAB_KEY(bind->mods | xcb_numlock_mask);
|
||||||
|
GRAB_KEY(bind->mods | xcb_numlock_mask | XCB_MOD_MASK_LOCK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,18 +96,41 @@ void ungrab_all_keys(xcb_connection_t *conn) {
|
||||||
void grab_all_keys(xcb_connection_t *conn) {
|
void grab_all_keys(xcb_connection_t *conn) {
|
||||||
Binding *bind;
|
Binding *bind;
|
||||||
TAILQ_FOREACH(bind, &bindings, bindings) {
|
TAILQ_FOREACH(bind, &bindings, bindings) {
|
||||||
LOG("Grabbing %d\n", bind->keycode);
|
/* The easy case: the user specified a keycode directly. */
|
||||||
if ((bind->mods & BIND_MODE_SWITCH) != 0)
|
if (bind->keycode > 0) {
|
||||||
xcb_grab_key(conn, 0, root, 0, bind->keycode,
|
grab_keycode_for_binding(conn, bind, bind->keycode);
|
||||||
XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_SYNC);
|
continue;
|
||||||
else {
|
|
||||||
/* Grab the key in all combinations */
|
|
||||||
#define GRAB_KEY(modifier) xcb_grab_key(conn, 0, root, modifier, bind->keycode, \
|
|
||||||
XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC)
|
|
||||||
GRAB_KEY(bind->mods);
|
|
||||||
GRAB_KEY(bind->mods | xcb_numlock_mask);
|
|
||||||
GRAB_KEY(bind->mods | xcb_numlock_mask | XCB_MOD_MASK_LOCK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We need to translate the symbol to a keycode */
|
||||||
|
LOG("Translating symbol to keycode (\"%s\")\n", bind->symbol);
|
||||||
|
xcb_keysym_t keysym = XStringToKeysym(bind->symbol);
|
||||||
|
if (keysym == NoSymbol) {
|
||||||
|
LOG("Could not translate string to key symbol: \"%s\"\n", bind->symbol);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
xcb_keycode_t *keycodes = xcb_key_symbols_get_keycode(keysyms, keysym);
|
||||||
|
if (keycodes == NULL) {
|
||||||
|
LOG("Could not translate symbol \"%s\"\n", bind->symbol);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t last_keycode;
|
||||||
|
bind->number_keycodes = 0;
|
||||||
|
for (xcb_keycode_t *walk = keycodes; *walk != 0; walk++) {
|
||||||
|
/* We hope duplicate keycodes will be returned in order
|
||||||
|
* and skip them */
|
||||||
|
if (last_keycode == *walk)
|
||||||
|
continue;
|
||||||
|
grab_keycode_for_binding(conn, bind, *walk);
|
||||||
|
last_keycode = *walk;
|
||||||
|
bind->number_keycodes++;
|
||||||
|
}
|
||||||
|
LOG("Got %d different keycodes\n", bind->number_keycodes);
|
||||||
|
bind->translated_to = smalloc(bind->number_keycodes * sizeof(xcb_keycode_t));
|
||||||
|
memcpy(bind->translated_to, keycodes, bind->number_keycodes * sizeof(xcb_keycode_t));
|
||||||
|
free(keycodes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,7 +275,7 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* key bindings */
|
/* key bindings */
|
||||||
if (strcasecmp(key, "bind") == 0) {
|
if (strcasecmp(key, "bind") == 0 || strcasecmp(key, "bindsym") == 0) {
|
||||||
#define CHECK_MODIFIER(name) \
|
#define CHECK_MODIFIER(name) \
|
||||||
if (strncasecmp(walk, #name, strlen(#name)) == 0) { \
|
if (strncasecmp(walk, #name, strlen(#name)) == 0) { \
|
||||||
modifiers |= BIND_##name; \
|
modifiers |= BIND_##name; \
|
||||||
|
@ -259,14 +300,25 @@ void load_configuration(xcb_connection_t *conn, const char *override_configpath,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now check for the keycode */
|
Binding *new = scalloc(sizeof(Binding));
|
||||||
|
|
||||||
|
/* Now check for the keycode or copy the symbol */
|
||||||
|
if (strcasecmp(key, "bind") == 0) {
|
||||||
int keycode = strtol(walk, &rest, 10);
|
int keycode = strtol(walk, &rest, 10);
|
||||||
if (!rest || *rest != ' ')
|
if (!rest || *rest != ' ')
|
||||||
die("Invalid binding\n");
|
die("Invalid binding (keycode)\n");
|
||||||
rest++;
|
|
||||||
LOG("keycode = %d, modifiers = %d, command = *%s*\n", keycode, modifiers, rest);
|
|
||||||
Binding *new = smalloc(sizeof(Binding));
|
|
||||||
new->keycode = keycode;
|
new->keycode = keycode;
|
||||||
|
} else {
|
||||||
|
rest = walk;
|
||||||
|
char *sym = rest;
|
||||||
|
while (*rest != '\0' && *rest != ' ')
|
||||||
|
rest++;
|
||||||
|
if (*rest != ' ')
|
||||||
|
die("Invalid binding (keysym)\n");
|
||||||
|
new->symbol = strndup(sym, (rest - sym));
|
||||||
|
}
|
||||||
|
rest++;
|
||||||
|
LOG("keycode = %d, symbol = %s, modifiers = %d, command = *%s*\n", new->keycode, new->symbol, modifiers, rest);
|
||||||
new->mods = modifiers;
|
new->mods = modifiers;
|
||||||
new->command = sstrdup(rest);
|
new->command = sstrdup(rest);
|
||||||
TAILQ_INSERT_TAIL(&bindings, new, bindings);
|
TAILQ_INSERT_TAIL(&bindings, new, bindings);
|
||||||
|
|
|
@ -119,9 +119,24 @@ int handle_key_press(void *ignored, xcb_connection_t *conn, xcb_key_press_event_
|
||||||
|
|
||||||
/* Find the binding */
|
/* Find the binding */
|
||||||
Binding *bind;
|
Binding *bind;
|
||||||
TAILQ_FOREACH(bind, &bindings, bindings)
|
TAILQ_FOREACH(bind, &bindings, bindings) {
|
||||||
if (bind->keycode == event->detail && bind->mods == state_filtered)
|
/* First compare the modifiers */
|
||||||
|
if (bind->mods != state_filtered)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* If a symbol was specified by the user, we need to look in
|
||||||
|
* the array of translated keycodes for the event’s keycode */
|
||||||
|
if (bind->symbol != NULL) {
|
||||||
|
if (memmem(bind->translated_to,
|
||||||
|
bind->number_keycodes * sizeof(xcb_keycode_t),
|
||||||
|
&(event->detail), sizeof(xcb_keycode_t)) != NULL)
|
||||||
break;
|
break;
|
||||||
|
} else {
|
||||||
|
/* This case is easier: The user specified a keycode */
|
||||||
|
if (bind->keycode == event->detail)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* No match? Then it was an actively grabbed key, that is with Mode_switch, and
|
/* No match? Then it was an actively grabbed key, that is with Mode_switch, and
|
||||||
the user did not press Mode_switch, so just pass it… */
|
the user did not press Mode_switch, so just pass it… */
|
||||||
|
@ -239,6 +254,30 @@ int handle_motion_notify(void *ignored, xcb_connection_t *conn, xcb_motion_notif
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called when the keyboard mapping changes (for example by using Xmodmap),
|
||||||
|
* we need to update our key bindings then (re-translate symbols).
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
int handle_mapping_notify(void *ignored, xcb_connection_t *conn, xcb_mapping_notify_event_t *event) {
|
||||||
|
LOG("\n\nmapping notify\n\n");
|
||||||
|
|
||||||
|
if (event->request != XCB_MAPPING_KEYBOARD &&
|
||||||
|
event->request != XCB_MAPPING_MODIFIER)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
xcb_refresh_keyboard_mapping(keysyms, event);
|
||||||
|
|
||||||
|
xcb_get_numlock_mask(conn);
|
||||||
|
|
||||||
|
ungrab_all_keys(conn);
|
||||||
|
LOG("Re-grabbing...\n");
|
||||||
|
grab_all_keys(conn);
|
||||||
|
LOG("Done\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Checks if the button press was on a stack window, handles focus setting and returns true
|
* Checks if the button press was on a stack window, handles focus setting and returns true
|
||||||
* if so, or false otherwise.
|
* if so, or false otherwise.
|
||||||
|
|
53
src/mainx.c
53
src/mainx.c
|
@ -18,6 +18,7 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
#include <X11/XKBlib.h>
|
#include <X11/XKBlib.h>
|
||||||
#include <X11/extensions/XKB.h>
|
#include <X11/extensions/XKB.h>
|
||||||
|
@ -55,6 +56,8 @@ char **start_argv;
|
||||||
/* This is our connection to X11 for use with XKB */
|
/* This is our connection to X11 for use with XKB */
|
||||||
Display *xkbdpy;
|
Display *xkbdpy;
|
||||||
|
|
||||||
|
xcb_key_symbols_t *keysyms;
|
||||||
|
|
||||||
/* The list of key bindings */
|
/* The list of key bindings */
|
||||||
struct bindings_head bindings = TAILQ_HEAD_INITIALIZER(bindings);
|
struct bindings_head bindings = TAILQ_HEAD_INITIALIZER(bindings);
|
||||||
|
|
||||||
|
@ -109,6 +112,34 @@ static void xcb_check_cb(EV_P_ ev_check *w, int revents) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When using xmodmap to change the keyboard mapping, this event
|
||||||
|
* is only sent via XKB. Therefore, we need this special handler.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void xkb_got_event(EV_P_ struct ev_io *w, int revents) {
|
||||||
|
LOG("got xkb event, yay\n");
|
||||||
|
XEvent ev;
|
||||||
|
/* When using xmodmap, every change (!) gets an own event.
|
||||||
|
* Therefore, we just read all events and only handle the
|
||||||
|
* mapping_notify once (we do not receive any other XKB
|
||||||
|
* events anyway). */
|
||||||
|
while (XPending(xkbdpy))
|
||||||
|
XNextEvent(xkbdpy, &ev);
|
||||||
|
|
||||||
|
xcb_key_symbols_free(keysyms);
|
||||||
|
keysyms = xcb_key_symbols_alloc(global_conn);
|
||||||
|
|
||||||
|
xcb_get_numlock_mask(global_conn);
|
||||||
|
|
||||||
|
ungrab_all_keys(global_conn);
|
||||||
|
LOG("Re-grabbing...\n");
|
||||||
|
grab_all_keys(global_conn);
|
||||||
|
LOG("Done\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int main(int argc, char *argv[], char *env[]) {
|
int main(int argc, char *argv[], char *env[]) {
|
||||||
int i, screens, opt;
|
int i, screens, opt;
|
||||||
char *override_configpath = NULL;
|
char *override_configpath = NULL;
|
||||||
|
@ -193,6 +224,11 @@ int main(int argc, char *argv[], char *env[]) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fcntl(ConnectionNumber(xkbdpy), F_SETFD, FD_CLOEXEC) == -1) {
|
||||||
|
fprintf(stderr, "Could not set FD_CLOEXEC on xkbdpy\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int i1;
|
int i1;
|
||||||
if (!XkbQueryExtension(xkbdpy,&i1,&evBase,&errBase,&major,&minor)) {
|
if (!XkbQueryExtension(xkbdpy,&i1,&evBase,&errBase,&major,&minor)) {
|
||||||
fprintf(stderr, "XKB not supported by X-server\n");
|
fprintf(stderr, "XKB not supported by X-server\n");
|
||||||
|
@ -200,18 +236,30 @@ int main(int argc, char *argv[], char *env[]) {
|
||||||
}
|
}
|
||||||
/* end of ugliness */
|
/* end of ugliness */
|
||||||
|
|
||||||
|
if (!XkbSelectEvents(xkbdpy, XkbUseCoreKbd, XkbMapNotifyMask, XkbMapNotifyMask)) {
|
||||||
|
fprintf(stderr, "Could not set XKB event mask\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Initialize event loop using libev */
|
/* Initialize event loop using libev */
|
||||||
struct ev_loop *loop = ev_default_loop(0);
|
struct ev_loop *loop = ev_default_loop(0);
|
||||||
if (loop == NULL)
|
if (loop == NULL)
|
||||||
die("Could not initialize libev. Bad LIBEV_FLAGS?\n");
|
die("Could not initialize libev. Bad LIBEV_FLAGS?\n");
|
||||||
|
|
||||||
struct ev_io *xcb_watcher = scalloc(sizeof(struct ev_io));
|
struct ev_io *xcb_watcher = scalloc(sizeof(struct ev_io));
|
||||||
|
struct ev_io *xkb = scalloc(sizeof(struct ev_io));
|
||||||
struct ev_check *xcb_check = scalloc(sizeof(struct ev_check));
|
struct ev_check *xcb_check = scalloc(sizeof(struct ev_check));
|
||||||
struct ev_prepare *xcb_prepare = scalloc(sizeof(struct ev_prepare));
|
struct ev_prepare *xcb_prepare = scalloc(sizeof(struct ev_prepare));
|
||||||
|
|
||||||
ev_io_init(xcb_watcher, xcb_got_event, xcb_get_file_descriptor(conn), EV_READ);
|
ev_io_init(xcb_watcher, xcb_got_event, xcb_get_file_descriptor(conn), EV_READ);
|
||||||
ev_io_start(loop, xcb_watcher);
|
ev_io_start(loop, xcb_watcher);
|
||||||
|
|
||||||
|
ev_io_init(xkb, xkb_got_event, ConnectionNumber(xkbdpy), EV_READ);
|
||||||
|
ev_io_start(loop, xkb);
|
||||||
|
|
||||||
|
/* Flush the buffer so that libev can properly get new events */
|
||||||
|
XFlush(xkbdpy);
|
||||||
|
|
||||||
ev_check_init(xcb_check, xcb_check_cb);
|
ev_check_init(xcb_check, xcb_check_cb);
|
||||||
ev_check_start(loop, xcb_check);
|
ev_check_start(loop, xcb_check);
|
||||||
|
|
||||||
|
@ -261,6 +309,9 @@ int main(int argc, char *argv[], char *env[]) {
|
||||||
* cross virtual screen boundaries doing that) */
|
* cross virtual screen boundaries doing that) */
|
||||||
xcb_event_set_motion_notify_handler(&evenths, handle_motion_notify, NULL);
|
xcb_event_set_motion_notify_handler(&evenths, handle_motion_notify, NULL);
|
||||||
|
|
||||||
|
/* Mapping notify = keyboard mapping changed (Xmodmap), re-grab bindings */
|
||||||
|
xcb_event_set_mapping_notify_handler(&evenths, handle_mapping_notify, NULL);
|
||||||
|
|
||||||
/* Client message are sent to the root window. The only interesting client message
|
/* Client message are sent to the root window. The only interesting client message
|
||||||
for us is _NET_WM_STATE, we honour _NET_WM_STATE_FULLSCREEN */
|
for us is _NET_WM_STATE, we honour _NET_WM_STATE_FULLSCREEN */
|
||||||
xcb_event_set_client_message_handler(&evenths, handle_client_message, NULL);
|
xcb_event_set_client_message_handler(&evenths, handle_client_message, NULL);
|
||||||
|
@ -341,6 +392,8 @@ int main(int argc, char *argv[], char *env[]) {
|
||||||
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, atoms[_NET_SUPPORTING_WM_CHECK], WINDOW, 32, 1, &root);
|
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, atoms[_NET_SUPPORTING_WM_CHECK], WINDOW, 32, 1, &root);
|
||||||
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, atoms[_NET_WM_NAME], atoms[UTF8_STRING], 8, strlen("i3"), "i3");
|
xcb_change_property(conn, XCB_PROP_MODE_REPLACE, root, atoms[_NET_WM_NAME], atoms[UTF8_STRING], 8, strlen("i3"), "i3");
|
||||||
|
|
||||||
|
keysyms = xcb_key_symbols_alloc(conn);
|
||||||
|
|
||||||
xcb_get_numlock_mask(conn);
|
xcb_get_numlock_mask(conn);
|
||||||
|
|
||||||
grab_all_keys(conn);
|
grab_all_keys(conn);
|
||||||
|
|
Loading…
Reference in New Issue