diff --git a/src/cfgparse.y b/src/cfgparse.y index 59b22c6c..8426de0b 100644 --- a/src/cfgparse.y +++ b/src/cfgparse.y @@ -310,6 +310,53 @@ void kill_configerror_nagbar(bool wait_for_it) { waitpid(configerror_pid, NULL, 0); } +/* + * Checks for duplicate key bindings (the same keycode or keysym is configured + * more than once). If a duplicate binding is found, a message is printed to + * stderr and the has_errors variable is set to true, which will start + * i3-nagbar. + * + */ +static void check_for_duplicate_bindings(struct context *context) { + Binding *bind, *current; + TAILQ_FOREACH(current, bindings, bindings) { + TAILQ_FOREACH(bind, bindings, bindings) { + /* Abort when we reach the current keybinding, only check the + * bindings before */ + if (bind == current) + break; + + /* Check if one is using keysym while the other is using bindsym. + * If so, skip. */ + /* XXX: It should be checked at a later place (when translating the + * keysym to keycodes) if there are any duplicates */ + if ((bind->symbol == NULL && current->symbol != NULL) || + (bind->symbol != NULL && current->symbol == NULL)) + continue; + + /* If bind is NULL, current has to be NULL, too (see above). + * If the keycodes differ, it can't be a duplicate. */ + if (bind->symbol != NULL && + strcasecmp(bind->symbol, current->symbol) != 0) + continue; + + /* Check if the keycodes or modifiers are different. If so, they + * can't be duplicate */ + if (bind->keycode != current->keycode || + bind->mods != current->mods) + continue; + context->has_errors = true; + if (current->keycode != 0) { + ELOG("Duplicate keybinding in config file:\n modmask %d with keycode %d, command \"%s\"\n", + current->mods, current->keycode, current->command); + } else { + ELOG("Duplicate keybinding in config file:\n modmask %d with keysym %s, command \"%s\"\n", + current->mods, current->symbol, current->command); + } + } + } +} + void parse_file(const char *f) { SLIST_HEAD(variables_head, Variable) variables = SLIST_HEAD_INITIALIZER(&variables); int fd, ret, read_bytes = 0; @@ -463,6 +510,8 @@ void parse_file(const char *f) { exit(1); } + check_for_duplicate_bindings(context); + if (context->has_errors) { start_configerror_nagbar(f); }