pcre_extra *extra;
};
+/**
+ * Stores a resolved keycode (from a keysym), including the modifier mask. Will
+ * be passed to xcb_grab_key().
+ *
+ */
+struct Binding_Keycode {
+ xcb_keycode_t keycode;
+ i3_event_state_mask_t modifiers;
+ TAILQ_ENTRY(Binding_Keycode) keycodes;
+};
+
/******************************************************************************
* Major types
*****************************************************************************/
* title bar (default). */
bool whole_window;
- uint32_t number_keycodes;
-
/** Keycode to bind */
uint32_t 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;
+ /** Only in use if symbol != NULL. Contains keycodes which generate the
+ * specified symbol. Useful for unbinding and checking which binding was
+ * used when a key press event comes in. */
+ TAILQ_HEAD(keycodes_head, Binding_Keycode) keycodes_head;
/** Command, like in command mode */
char *command;
struct Mode *mode = mode_from_name(modename, pango_markup);
TAILQ_INSERT_TAIL(mode->bindings, new_binding, bindings);
+ TAILQ_INIT(&(new_binding->keycodes_head));
+
return new_binding;
}
DLOG("Grabbing keycode %d with event state mask 0x%x (mods 0x%x)\n",
keycode, bind->event_state_mask, mods);
GRAB_KEY(mods);
+ /* Also bind the key with active NumLock */
GRAB_KEY(mods | xcb_numlock_mask);
+ /* Also bind the key with active CapsLock */
GRAB_KEY(mods | XCB_MOD_MASK_LOCK);
+ /* Also bind the key with active NumLock+CapsLock */
GRAB_KEY(mods | xcb_numlock_mask | XCB_MOD_MASK_LOCK);
}
continue;
}
- for (uint32_t i = 0; i < bind->number_keycodes; i++)
- grab_keycode_for_binding(conn, bind, bind->translated_to[i]);
+ struct Binding_Keycode *binding_keycode;
+ TAILQ_FOREACH(binding_keycode, &(bind->keycodes_head), keycodes) {
+ const int keycode = binding_keycode->keycode;
+ const int mods = (binding_keycode->modifiers & 0xFFFF);
+ DLOG("Grabbing keycode %d with mods %d\n", keycode, mods);
+ xcb_grab_key(conn, 0, root, mods, keycode, XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC);
+ }
}
}
* keycode */
if (input_type == B_KEYBOARD && bind->symbol != NULL) {
xcb_keycode_t input_keycode = (xcb_keycode_t)input_code;
- if (memmem(bind->translated_to,
- bind->number_keycodes * sizeof(xcb_keycode_t),
- &input_keycode, sizeof(xcb_keycode_t)) == NULL)
+ bool found_keycode = false;
+ struct Binding_Keycode *binding_keycode;
+ TAILQ_FOREACH(binding_keycode, &(bind->keycodes_head), keycodes) {
+ if (binding_keycode->keycode == input_keycode) {
+ found_keycode = true;
+ break;
+ }
+ }
+ if (!found_keycode)
continue;
} else {
/* This case is easier: The user specified a keycode */
return;
}
Binding *bind = resolving->bind;
- bind->number_keycodes++;
- bind->translated_to = srealloc(bind->translated_to,
- (sizeof(xcb_keycode_t) *
- bind->number_keycodes));
- bind->translated_to[bind->number_keycodes - 1] = key;
+
+#define ADD_TRANSLATED_KEY(mods) \
+ do { \
+ struct Binding_Keycode *binding_keycode = smalloc(sizeof(struct Binding_Keycode)); \
+ binding_keycode->modifiers = (mods); \
+ binding_keycode->keycode = key; \
+ TAILQ_INSERT_TAIL(&(bind->keycodes_head), binding_keycode, keycodes); \
+ } while (0)
+
+ ADD_TRANSLATED_KEY(bind->event_state_mask);
+
+ /* Also bind the key with active NumLock */
+ ADD_TRANSLATED_KEY(bind->event_state_mask | xcb_numlock_mask);
+
+ /* Also bind the key with active CapsLock */
+ ADD_TRANSLATED_KEY(bind->event_state_mask | XCB_MOD_MASK_LOCK);
+
+ /* Also bind the key with active NumLock+CapsLock */
+ ADD_TRANSLATED_KEY(bind->event_state_mask | xcb_numlock_mask | XCB_MOD_MASK_LOCK);
+
+#undef ADD_TRANSLATED_KEY
}
/*
.xkb_state = dummy_state,
.xkb_state_no_shift = dummy_state_no_shift,
};
- FREE(bind->translated_to);
- bind->number_keycodes = 0;
+ while (!TAILQ_EMPTY(&(bind->keycodes_head))) {
+ struct Binding_Keycode *first = TAILQ_FIRST(&(bind->keycodes_head));
+ TAILQ_REMOVE(&(bind->keycodes_head), first, keycodes);
+ FREE(first);
+ }
xkb_keymap_key_for_each(xkb_keymap, add_keycode_if_matches, &resolving);
char *keycodes = sstrdup("");
- for (uint32_t n = 0; n < bind->number_keycodes; n++) {
+ int num_keycodes = 0;
+ struct Binding_Keycode *binding_keycode;
+ TAILQ_FOREACH(binding_keycode, &(bind->keycodes_head), keycodes) {
char *tmp;
- sasprintf(&tmp, "%s %d", keycodes, bind->translated_to[n]);
+ sasprintf(&tmp, "%s %d", keycodes, binding_keycode->keycode);
free(keycodes);
keycodes = tmp;
+ num_keycodes++;
/* check for duplicate bindings */
Binding *check;
continue;
if (check->symbol != NULL)
continue;
- if (check->keycode != bind->translated_to[n] ||
- check->event_state_mask != bind->event_state_mask ||
+ if (check->keycode != binding_keycode->keycode ||
+ check->event_state_mask != binding_keycode->modifiers ||
check->release != bind->release)
continue;
has_errors = true;
}
}
DLOG("state=0x%x, cfg=\"%s\", sym=0x%x → keycodes%s (%d)\n",
- bind->event_state_mask, bind->symbol, keysym, keycodes, bind->number_keycodes);
+ bind->event_state_mask, bind->symbol, keysym, keycodes, num_keycodes);
free(keycodes);
}
ret->symbol = sstrdup(bind->symbol);
if (bind->command != NULL)
ret->command = sstrdup(bind->command);
- if (bind->translated_to != NULL) {
- ret->translated_to = smalloc(sizeof(xcb_keycode_t) * bind->number_keycodes);
- memcpy(ret->translated_to, bind->translated_to, sizeof(xcb_keycode_t) * bind->number_keycodes);
+ TAILQ_INIT(&(ret->keycodes_head));
+ struct Binding_Keycode *binding_keycode;
+ TAILQ_FOREACH(binding_keycode, &(bind->keycodes_head), keycodes) {
+ struct Binding_Keycode *ret_binding_keycode = smalloc(sizeof(struct Binding_Keycode));
+ *ret_binding_keycode = *binding_keycode;
+ TAILQ_INSERT_TAIL(&(ret->keycodes_head), ret_binding_keycode, keycodes);
}
+
return ret;
}
return;
}
+ while (!TAILQ_EMPTY(&(bind->keycodes_head))) {
+ struct Binding_Keycode *first = TAILQ_FIRST(&(bind->keycodes_head));
+ TAILQ_REMOVE(&(bind->keycodes_head), first, keycodes);
+ FREE(first);
+ }
+
FREE(bind->symbol);
- FREE(bind->translated_to);
FREE(bind->command);
FREE(bind);
}