/* Try to find the mode in the list of modes and return it */
SLIST_FOREACH(mode, &modes, modes) {
- if (strcmp(mode->name, name) == 0)
+ if (strcmp(mode->name, name) == 0) {
return mode;
+ }
}
/* If the mode was not found, create a new one */
*/
Binding *configure_binding(const char *bindtype, const char *modifiers, const char *input_code,
const char *release, const char *border, const char *whole_window,
- const char *command, const char *modename, bool pango_markup) {
+ const char *exclude_titlebar, const char *command, const char *modename,
+ bool pango_markup) {
Binding *new_binding = scalloc(1, sizeof(Binding));
DLOG("Binding %p bindtype %s, modifiers %s, input code %s, release %s\n", new_binding, bindtype, modifiers, input_code, release);
new_binding->release = (release != NULL ? B_UPON_KEYRELEASE : B_UPON_KEYPRESS);
new_binding->border = (border != NULL);
new_binding->whole_window = (whole_window != NULL);
+ new_binding->exclude_titlebar = (exclude_titlebar != NULL);
if (strcmp(bindtype, "bindsym") == 0) {
new_binding->input_type = (strncasecmp(input_code, "button", (sizeof("button") - 1)) == 0
? B_MOUSE
new_binding->symbol = sstrdup(input_code);
} else {
- char *endptr;
- long keycode = strtol(input_code, &endptr, 10);
- new_binding->keycode = keycode;
- new_binding->input_type = B_KEYBOARD;
- if (keycode == LONG_MAX || keycode == LONG_MIN || keycode < 0 || *endptr != '\0' || endptr == input_code) {
+ long keycode;
+ if (!parse_long(input_code, &keycode, 10)) {
ELOG("Could not parse \"%s\" as an input code, ignoring this binding.\n", input_code);
FREE(new_binding);
return NULL;
}
+
+ new_binding->keycode = keycode;
+ new_binding->input_type = B_KEYBOARD;
}
new_binding->command = sstrdup(command);
new_binding->event_state_mask = event_state_from_str(modifiers);
/* Like |xkb_state|, but with NumLock. */
struct xkb_state *xkb_state_numlock;
+
+ /* Like |xkb_state|, but with NumLock, just without the shift modifier, if shift was specified. */
+ struct xkb_state *xkb_state_numlock_no_shift;
};
/*
*/
static void add_keycode_if_matches(struct xkb_keymap *keymap, xkb_keycode_t key, void *data) {
const struct resolve *resolving = data;
+ struct xkb_state *numlock_state = resolving->xkb_state_numlock;
xkb_keysym_t sym = xkb_state_key_get_one_sym(resolving->xkb_state, key);
if (sym != resolving->keysym) {
/* Check if Shift was specified, and try resolving the symbol without
return;
if (xkb_state_key_get_level(resolving->xkb_state, key, layout) > 1)
return;
+ /* Skip the Shift fallback for keypad keys, otherwise one cannot bind
+ * KP_1 independent of KP_End. */
+ if (sym >= XKB_KEY_KP_Space && sym <= XKB_KEY_KP_Equal)
+ return;
+ numlock_state = resolving->xkb_state_numlock_no_shift;
sym = xkb_state_key_get_one_sym(resolving->xkb_state_no_shift, key);
if (sym != resolving->keysym)
return;
* active. If so, grab the key with NumLock as well, so that users don’t
* need to duplicate every key binding with an additional Mod2 specified.
*/
- xkb_keysym_t sym_numlock = xkb_state_key_get_one_sym(resolving->xkb_state_numlock, key);
+ xkb_keysym_t sym_numlock = xkb_state_key_get_one_sym(numlock_state, key);
if (sym_numlock == resolving->keysym) {
/* Also bind the key with active NumLock */
ADD_TRANSLATED_KEY(bind->event_state_mask | xcb_numlock_mask);
return;
}
+ struct xkb_state *dummy_state_numlock_no_shift = xkb_state_new(xkb_keymap);
+ if (dummy_state_numlock_no_shift == NULL) {
+ ELOG("Could not create XKB state, cannot translate keysyms.\n");
+ return;
+ }
+
bool has_errors = false;
Binding *bind;
TAILQ_FOREACH(bind, bindings, bindings) {
if (bind->input_type == B_MOUSE) {
- char *endptr;
- long button = strtol(bind->symbol + (sizeof("button") - 1), &endptr, 10);
- bind->keycode = button;
-
- if (button == LONG_MAX || button == LONG_MIN || button < 0 || *endptr != '\0' || endptr == bind->symbol)
+ long button;
+ if (!parse_long(bind->symbol + (sizeof("button") - 1), &button, 10)) {
ELOG("Could not translate string to button: \"%s\"\n", bind->symbol);
+ }
+ bind->keycode = button;
continue;
}
0 /* xkb_layout_index_t latched_group, */,
group /* xkb_layout_index_t locked_group, */);
+ (void)xkb_state_update_mask(
+ dummy_state_numlock_no_shift,
+ ((bind->event_state_mask & 0x1FFF) | xcb_numlock_mask) ^ XCB_KEY_BUT_MASK_SHIFT /* xkb_mod_mask_t base_mods, */,
+ 0 /* xkb_mod_mask_t latched_mods, */,
+ 0 /* xkb_mod_mask_t locked_mods, */,
+ 0 /* xkb_layout_index_t base_group, */,
+ 0 /* xkb_layout_index_t latched_group, */,
+ group /* xkb_layout_index_t locked_group, */);
+
struct resolve resolving = {
.bind = bind,
.keysym = keysym,
.xkb_state = dummy_state,
.xkb_state_no_shift = dummy_state_no_shift,
.xkb_state_numlock = dummy_state_numlock,
+ .xkb_state_numlock_no_shift = dummy_state_numlock_no_shift,
};
while (!TAILQ_EMPTY(&(bind->keycodes_head))) {
struct Binding_Keycode *first = TAILQ_FIRST(&(bind->keycodes_head));
xkb_state_unref(dummy_state);
xkb_state_unref(dummy_state_no_shift);
xkb_state_unref(dummy_state_numlock);
+ xkb_state_unref(dummy_state_numlock_no_shift);
if (has_errors) {
start_config_error_nagbar(current_configpath, true);
if (bind->input_type != B_MOUSE || !bind->whole_window)
continue;
- char *endptr;
- long button = strtol(bind->symbol + (sizeof("button") - 1), &endptr, 10);
- if (button == LONG_MAX || button == LONG_MIN || button < 0 || *endptr != '\0' || endptr == bind->symbol) {
+ long button;
+ if (!parse_long(bind->symbol + (sizeof("button") - 1), &button, 10)) {
ELOG("Could not parse button number, skipping this binding. Please report this bug in i3.\n");
continue;
}
/* Avoid duplicates. */
- for (int i = 0; i < num_max; i++) {
+ for (int i = 0; i < num; i++) {
if (buffer[i] == button)
continue;
}