11 #include <xkbcommon/xkbcommon.h>
31 if (strcmp(mode->
name, name) == 0)
52 const char *release,
const char *whole_window,
const char *command,
const char *modename) {
54 DLOG(
"bindtype %s, modifiers %s, input code %s, release %s\n", bindtype, modifiers, input_code, release);
55 new_binding->
release = (release != NULL ? B_UPON_KEYRELEASE : B_UPON_KEYPRESS);
57 if (strcmp(bindtype,
"bindsym") == 0) {
58 new_binding->
input_type = (strncasecmp(input_code,
"button", (
sizeof(
"button") - 1)) == 0
65 new_binding->
keycode = atoi(input_code);
67 if (new_binding->
keycode == 0) {
68 ELOG(
"Could not parse \"%s\" as an input code, ignoring this binding.\n", input_code);
86 DLOG(
"Grabbing %d with modifiers %d (with mod_mask_lock %d)\n", keycode, bind->
mods, bind->
mods | XCB_MOD_MASK_LOCK);
88 #define GRAB_KEY(modifier) \
90 xcb_grab_key(conn, 0, root, modifier, keycode, XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC); \
92 int mods = bind->
mods;
96 mods = XCB_MOD_MASK_ANY;
142 if (bind->
release == B_UPON_KEYRELEASE_IGNORE_MODS)
143 bind->
release = B_UPON_KEYRELEASE;
153 if (bind->
mods != modifiers &&
154 (bind->
release != B_UPON_KEYRELEASE_IGNORE_MODS ||
162 xcb_keycode_t input_keycode = (xcb_keycode_t)input_code;
165 &input_keycode,
sizeof(xcb_keycode_t)) == NULL)
169 if (bind->
keycode != input_code)
177 if (bind->
release == B_UPON_KEYRELEASE && !is_release)
178 bind->
release = B_UPON_KEYRELEASE_IGNORE_MODS;
181 if ((bind->
release == B_UPON_KEYPRESS && is_release) ||
182 (bind->
release >= B_UPON_KEYRELEASE && !is_release))
197 bool is_release = (
event->response_type == XCB_KEY_RELEASE ||
event->response_type == XCB_BUTTON_RELEASE);
199 input_type_t input_type = ((
event->response_type == XCB_BUTTON_RELEASE ||
event->response_type == XCB_BUTTON_PRESS)
203 uint16_t event_state = ((xcb_key_press_event_t *)event)->state;
204 uint16_t event_detail = ((xcb_key_press_event_t *)event)->detail;
207 uint16_t state_filtered = event_state & ~(
xcb_numlock_mask | XCB_MOD_MASK_LOCK);
208 DLOG(
"(removed numlock, state = %d)\n", state_filtered);
211 state_filtered &= 0xFF;
212 DLOG(
"(removed upper 8 bits, state = %d)\n", state_filtered);
217 DLOG(
"(checked mode_switch, state %d)\n", state_filtered);
228 DLOG(
"no match, new state_filtered = %d\n", state_filtered);
229 if ((bind =
get_binding(state_filtered, is_release, event_detail, input_type)) == NULL) {
234 DLOG(
"Could not lookup key binding (modifiers %d, keycode %d)\n",
235 state_filtered, event_detail);
250 xcb_keycode_t i, min_keycode, max_keycode;
252 min_keycode = xcb_get_setup(
conn)->min_keycode;
253 max_keycode = xcb_get_setup(
conn)->max_keycode;
257 int button = atoi(bind->
symbol + (
sizeof(
"button") - 1));
261 ELOG(
"Could not translate string to button: \"%s\"\n", bind->
symbol);
270 keysym = xkb_keysym_from_name(bind->
symbol, XKB_KEYSYM_NO_FLAGS);
271 if (keysym == XKB_KEY_NoSymbol) {
272 ELOG(
"Could not translate string to key symbol: \"%s\"\n",
286 for (i = min_keycode; i && i <= max_keycode; i++) {
287 if ((xcb_key_symbols_get_keysym(
keysyms, i, col) != keysym) &&
288 (xcb_key_symbols_get_keysym(
keysyms, i, col + 1) != keysym))
292 (
sizeof(xcb_keycode_t) *
297 DLOG(
"Translated symbol \"%s\" to %d keycode (mods %d)\n", bind->
symbol,
309 DLOG(
"Switching to mode %s\n", new_mode);
312 if (strcasecmp(mode->
name, new_mode) != 0)
329 ELOG(
"ERROR: Mode not found\n");
356 if ((bind->
symbol == NULL && current->
symbol != NULL) ||
362 if (bind->
symbol != NULL &&
375 ELOG(
"Duplicate keybinding in config file:\n modmask %d with keycode %d, command \"%s\"\n",
378 ELOG(
"Duplicate keybinding in config file:\n modmask %d with keysym %s, command \"%s\"\n",
451 "The configured command for this shortcut could not be run successfully.",
char * sstrdup(const char *str)
Safe-wrapper around strdup which exits if malloc returns NULL (meaning that there is no more memory a...
#define SLIST_FOREACH(var, head, field)
char * symbol
Symbol the user specified in configfile, if any.
void tree_render(void)
Renders the tree, that is rendering all outputs using render_con() and pushing the changes to X11 usi...
void check_for_duplicate_bindings(struct context *context)
Checks for duplicate key bindings (the same keycode or keysym is configured more than once)...
const char * DEFAULT_BINDING_MODE
Binding * configure_binding(const char *bindtype, const char *modifiers, const char *input_code, const char *release, const char *whole_window, const char *command, const char *modename)
Adds a binding from config parameters given as strings and returns a pointer to the binding structure...
void translate_keysyms(void)
Translates keysymbols to keycodes for all bindings which use keysyms.
static Binding * binding_copy(Binding *bind)
CommandResult * parse_command(const char *input, yajl_gen gen)
Parses and executes the given command.
#define SLIST_INSERT_HEAD(head, elm, field)
static Binding * get_binding(uint16_t modifiers, bool is_release, uint16_t input_code, input_type_t input_type)
static void grab_keycode_for_binding(xcb_connection_t *conn, Binding *bind, uint32_t keycode)
uint32_t modifiers_from_str(const char *str)
A utility function to convert a string of modifiers to the corresponding bit mask.
static struct Mode * mode_from_name(const char *name)
void grab_all_keys(xcb_connection_t *conn, bool bind_mode_switch)
Grab the bound keys (tell X to send us keypress events for those keycodes)
Holds a keybinding, consisting of a keycode combined with modifiers and the command which is executed...
void ipc_send_event(const char *event, uint32_t message_type, const char *payload)
Sends the specified event to all IPC clients which are currently connected and subscribed to this kin...
CommandResult * run_binding(Binding *bind, Con *con)
Runs the given binding and handles parse errors.
pid_t command_error_nagbar_pid
void switch_mode(const char *new_mode)
Switches the key bindings to the given mode, if the mode exists.
struct bindings_head * bindings
A struct that contains useful information about the result of a command as a whole (e...
char * command
Command, like in command mode.
int sasprintf(char **strp, const char *fmt,...)
Safe-wrapper around asprintf which exits if it returns -1 (meaning that there is no more memory avail...
The configuration file can contain multiple sets of bindings.
enum Binding::@10 release
If true, the binding should be executed upon a KeyRelease event, not a KeyPress (the default)...
void start_nagbar(pid_t *nagbar_pid, char *argv[])
Starts an i3-nagbar instance with the given parameters.
Used during the config file lexing/parsing to keep the state of the lexer in order to provide useful ...
input_type_t
Binding input types.
char * pattern
The pattern/name used to load the font.
bool whole_window
If this is true for a mouse binding, the binding should be executed when the button is pressed over a...
void ungrab_all_keys(xcb_connection_t *conn)
Ungrabs all keys, to be called before re-grabbing the keys because of a mapping_notify event or a con...
#define GRAB_KEY(modifier)
unsigned int xcb_numlock_mask
A 'Con' represents everything from the X11 root window down to a single X11 window.
void * scalloc(size_t size)
Safe-wrapper around calloc which exits if malloc returns NULL (meaning that there is no more memory a...
struct bindings_head * bindings
void binding_free(Binding *bind)
Frees the binding.
uint32_t keycode
Keycode to bind.
Binding * get_binding_from_xcb_event(xcb_generic_event_t *event)
Returns a pointer to the Binding that matches the given xcb event or NULL if no such binding exists...
#define TAILQ_INSERT_TAIL(head, elm, field)
uint32_t mods
Bitmask consisting of BIND_MOD_1, BIND_MODE_SWITCH, …
void * smalloc(size_t size)
Safe-wrapper around malloc which exits if malloc returns NULL (meaning that there is no more memory a...
xcb_key_symbols_t * keysyms
#define TAILQ_FOREACH(var, head, field)
xcb_keycode_t * translated_to
Only in use if symbol != NULL.
void * srealloc(void *ptr, size_t size)
Safe-wrapper around realloc which exits if realloc returns NULL (meaning that there is no more memory...
void ipc_send_binding_event(const char *event_type, Binding *bind)
For the binding events, we send the serialized binding struct.