From 5cbd0527d703b2013b175d371de6c81aa7792863 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 12 Mar 2020 17:16:35 +0100 Subject: [PATCH] config: key-bindings: verify key combo isn't already mapped to another action --- config.c | 58 ++++++++++++++++++++++++++++++++++++++++---------- doc/foot.5.scd | 6 ++++++ 2 files changed, 53 insertions(+), 11 deletions(-) diff --git a/config.c b/config.c index ba216348..bd237604 100644 --- a/config.c +++ b/config.c @@ -449,6 +449,47 @@ parse_section_csd(const char *key, const char *value, struct config *conf, return true; } +static bool +verify_key_combo(const struct config *conf, const char *combo, const char *path, unsigned lineno) +{ + for (enum binding_action action = 0; action < BIND_ACTION_COUNT; action++) { + if (conf->bindings.key[action] == NULL) + continue; + + char *copy = strdup(conf->bindings.key[action]); + + for (char *save = NULL, *collision = strtok_r(copy, " ", &save); + collision != NULL; + collision = strtok_r(NULL, " ", &save)) + { + if (strcmp(combo, collision) == 0) { + LOG_ERR("%s:%d: %s already mapped to %s", path, lineno, combo, binding_action_map[action]); + free(copy); + return false; + } + } + + free(copy); + } + + struct xkb_context *ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); + struct xkb_keymap *keymap = xkb_keymap_new_from_names( + ctx, &(struct xkb_rule_names){0}, XKB_KEYMAP_COMPILE_NO_FLAGS); + + bool valid_combo = input_parse_key_binding_for_action( + keymap, BIND_ACTION_NONE, combo, NULL); + + xkb_keymap_unref(keymap); + xkb_context_unref(ctx); + + if (!valid_combo) { + LOG_ERR("%s:%d: invalid key combination: %s", path, lineno, combo); + return false; + } + + return true; +} + static bool parse_section_key_bindings( const char *key, const char *value, struct config *conf, @@ -461,18 +502,13 @@ parse_section_key_bindings( if (strcmp(key, binding_action_map[action]) != 0) continue; - struct xkb_context *ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); - struct xkb_keymap *keymap = xkb_keymap_new_from_names( - ctx, &(struct xkb_rule_names){0}, XKB_KEYMAP_COMPILE_NO_FLAGS); + if (strcmp(value, "NONE") == 0) { + free(conf->bindings.key[action]); + conf->bindings.key[action] = NULL; + return true; + } - bool valid_combo = input_parse_key_binding_for_action( - keymap, action, value, NULL); - - xkb_keymap_unref(keymap); - xkb_context_unref(ctx); - - if (!valid_combo) { - LOG_ERR("%s:%d: invalid key combination: %s", path, lineno, value); + if (!verify_key_combo(conf, value, path, lineno)) { return false; } diff --git a/doc/foot.5.scd b/doc/foot.5.scd index 457d053b..d01a3d6e 100644 --- a/doc/foot.5.scd +++ b/doc/foot.5.scd @@ -161,6 +161,12 @@ upper case. Note that *Alt* is usually called *Mod1*. +A key combination can only be mapped to *one* action. Lets say you +want to bind *Control*+*Shift*+*R* to *fullscreen*. Since this is the +default shortcut for *search-start*, you first need to unmap the +default binding. This can be done by setting _action_=*NONE*; +e.g. *search-start*=*NONE*. + *scrollback-up* Scrolls up/back in history. Default: _Shift+Page_Up_.