diff --git a/config.c b/config.c index f7452994..b12c7858 100644 --- a/config.c +++ b/config.c @@ -1175,11 +1175,13 @@ err: } static bool -has_key_binding_collisions(struct config *conf, enum bind_action_normal action, +has_key_binding_collisions(struct config *conf, + int action, const char *const action_map[], + config_key_binding_list_t *bindings, const key_combo_list_t *key_combos, const char *path, unsigned lineno) { - tll_foreach(conf->bindings.key, it) { + tll_foreach(*bindings, it) { if (it->item.action == action) continue; @@ -1197,7 +1199,7 @@ has_key_binding_collisions(struct config *conf, enum bind_action_normal action, bool has_pipe = it->item.pipe.cmd != NULL; LOG_AND_NOTIFY_ERR("%s:%d: %s already mapped to '%s%s%s%s'", path, lineno, it2->item.text, - binding_action_map[it->item.action], + action_map[it->item.action], has_pipe ? " [" : "", has_pipe ? it->item.pipe.cmd : "", has_pipe ? "]" : ""); @@ -1209,68 +1211,6 @@ has_key_binding_collisions(struct config *conf, enum bind_action_normal action, return false; } -static bool -has_search_binding_collisions(struct config *conf, enum bind_action_search action, - const key_combo_list_t *key_combos, - const char *path, unsigned lineno) -{ - tll_foreach(conf->bindings.search, it) { - if (it->item.action == action) - continue; - - tll_foreach(*key_combos, it2) { - const struct config_key_modifiers *mods1 = &it->item.modifiers; - const struct config_key_modifiers *mods2 = &it2->item.modifiers; - - bool shift = mods1->shift == mods2->shift; - bool alt = mods1->alt == mods2->alt; - bool ctrl = mods1->ctrl == mods2->ctrl; - bool meta = mods1->meta == mods2->meta; - bool sym = it->item.sym == it2->item.sym; - - if (shift && alt && ctrl && meta && sym) { - LOG_AND_NOTIFY_ERR("%s:%d: %s already mapped to '%s'", - path, lineno, it2->item.text, - search_binding_action_map[it->item.action]); - return true; - } - } - } - - return false; -} - -static bool -has_url_binding_collisions(struct config *conf, enum bind_action_url action, - const key_combo_list_t *key_combos, - const char *path, unsigned lineno) -{ - tll_foreach(conf->bindings.url, it) { - if (it->item.action == action) - continue; - - tll_foreach(*key_combos, it2) { - const struct config_key_modifiers *mods1 = &it->item.modifiers; - const struct config_key_modifiers *mods2 = &it2->item.modifiers; - - bool shift = mods1->shift == mods2->shift; - bool alt = mods1->alt == mods2->alt; - bool ctrl = mods1->ctrl == mods2->ctrl; - bool meta = mods1->meta == mods2->meta; - bool sym = it->item.sym == it2->item.sym; - - if (shift && alt && ctrl && meta && sym) { - LOG_AND_NOTIFY_ERR("%s:%d: %s already mapped to '%s'", - path, lineno, it2->item.text, - url_binding_action_map[it->item.action]); - return true; - } - } - } - - return false; -} - static int argv_compare(char *const *argv1, char *const *argv2) { @@ -1351,10 +1291,12 @@ pipe_argv_from_string(const char *value, char **cmd, char ***argv, return remove_len; } -static bool -parse_section_key_bindings( - const char *key, const char *value, struct config *conf, - const char *path, unsigned lineno) +static bool NOINLINE +parse_key_binding_section( + const char *section, const char *key, const char *value, + int action_count, const char *const action_map[static action_count], + config_key_binding_list_t *bindings, + struct config *conf, const char *path, unsigned lineno) { char *pipe_cmd; char **pipe_argv; @@ -1367,25 +1309,22 @@ parse_section_key_bindings( value += pipe_remove_len; - for (enum bind_action_normal action = 0; - action < BIND_ACTION_KEY_COUNT; - action++) - { - if (binding_action_map[action] == NULL) + for (int action = 0; action < action_count; action++) { + if (action_map[action] == NULL) continue; - if (strcmp(key, binding_action_map[action]) != 0) + if (strcmp(key, action_map[action]) != 0) continue; /* Unset binding */ if (strcasecmp(value, "none") == 0) { - tll_foreach(conf->bindings.key, it) { + tll_foreach(*bindings, it) { if (it->item.action == action) { if (it->item.pipe.master_copy) { free(it->item.pipe.cmd); free(it->item.pipe.argv); } - tll_remove(conf->bindings.key, it); + tll_remove(*bindings, it); } } free(pipe_argv); @@ -1395,7 +1334,9 @@ parse_section_key_bindings( key_combo_list_t key_combos = tll_init(); if (!parse_key_combos(conf, value, &key_combos, path, lineno) || - has_key_binding_collisions(conf, action, &key_combos, path, lineno)) + has_key_binding_collisions( + conf, action, binding_action_map, bindings, &key_combos, + path, lineno)) { free(pipe_argv); free(pipe_cmd); @@ -1404,7 +1345,7 @@ parse_section_key_bindings( } /* Remove existing bindings for this action+pipe */ - tll_foreach(conf->bindings.key, it) { + tll_foreach(*bindings, it) { if (it->item.action == action && ((it->item.pipe.argv == NULL && pipe_argv == NULL) || (it->item.pipe.argv != NULL && pipe_argv != NULL && @@ -1415,14 +1356,14 @@ parse_section_key_bindings( free(it->item.pipe.cmd); free(it->item.pipe.argv); } - tll_remove(conf->bindings.key, it); + tll_remove(*bindings, it); } } /* Emit key bindings */ bool first = true; tll_foreach(key_combos, it) { - struct config_key_binding_normal binding = { + struct config_key_binding binding = { .action = action, .modifiers = it->item.modifiers, .sym = it->item.sym, @@ -1433,7 +1374,7 @@ parse_section_key_bindings( }, }; - tll_push_back(conf->bindings.key, binding); + tll_push_back(*bindings, binding); first = false; } @@ -1441,12 +1382,21 @@ parse_section_key_bindings( return true; } - LOG_AND_NOTIFY_ERR("%s:%u: [key-bindings]: %s: invalid action", - path, lineno, key); + LOG_AND_NOTIFY_ERR("%s:%u: [%s]: %s: invalid action", + path, lineno, section, key); free(pipe_cmd); free(pipe_argv); return false; +} +static bool +parse_section_key_bindings( + const char *key, const char *value, struct config *conf, + const char *path, unsigned lineno) +{ + return parse_key_binding_section( + "key-bindings", key, value, BIND_ACTION_KEY_COUNT, binding_action_map, + &conf->bindings.key, conf, path, lineno); } static bool @@ -1454,56 +1404,9 @@ parse_section_search_bindings( const char *key, const char *value, struct config *conf, const char *path, unsigned lineno) { - for (enum bind_action_search action = 0; - action < BIND_ACTION_SEARCH_COUNT; - action++) - { - if (search_binding_action_map[action] == NULL) - continue; - - if (strcmp(key, search_binding_action_map[action]) != 0) - continue; - - /* Unset binding */ - if (strcasecmp(value, "none") == 0) { - tll_foreach(conf->bindings.search, it) { - if (it->item.action == action) - tll_remove(conf->bindings.search, it); - } - return true; - } - - key_combo_list_t key_combos = tll_init(); - if (!parse_key_combos(conf, value, &key_combos, path, lineno) || - has_search_binding_collisions(conf, action, &key_combos, path, lineno)) - { - free_key_combo_list(&key_combos); - return false; - } - - /* Remove existing bindings for this action */ - tll_foreach(conf->bindings.search, it) { - if (it->item.action == action) - tll_remove(conf->bindings.search, it); - } - - /* Emit key bindings */ - tll_foreach(key_combos, it) { - struct config_key_binding_search binding = { - .action = action, - .modifiers = it->item.modifiers, - .sym = it->item.sym, - }; - tll_push_back(conf->bindings.search, binding); - } - - free_key_combo_list(&key_combos); - return true; - } - - LOG_AND_NOTIFY_ERR("%s:%u: [search-bindings]: %s: invalid key", path, lineno, key); - return false; - + return parse_key_binding_section( + "search-bindings", key, value, BIND_ACTION_SEARCH_COUNT, + search_binding_action_map, &conf->bindings.search, conf, path, lineno); } static bool @@ -1511,56 +1414,9 @@ parse_section_url_bindings( const char *key, const char *value, struct config *conf, const char *path, unsigned lineno) { - for (enum bind_action_url action = 0; - action < BIND_ACTION_URL_COUNT; - action++) - { - if (url_binding_action_map[action] == NULL) - continue; - - if (strcmp(key, url_binding_action_map[action]) != 0) - continue; - - /* Unset binding */ - if (strcasecmp(value, "none") == 0) { - tll_foreach(conf->bindings.url, it) { - if (it->item.action == action) - tll_remove(conf->bindings.url, it); - } - return true; - } - - key_combo_list_t key_combos = tll_init(); - if (!parse_key_combos(conf, value, &key_combos, path, lineno) || - has_url_binding_collisions(conf, action, &key_combos, path, lineno)) - { - free_key_combo_list(&key_combos); - return false; - } - - /* Remove existing bindings for this action */ - tll_foreach(conf->bindings.url, it) { - if (it->item.action == action) - tll_remove(conf->bindings.url, it); - } - - /* Emit key bindings */ - tll_foreach(key_combos, it) { - struct config_key_binding_url binding = { - .action = action, - .modifiers = it->item.modifiers, - .sym = it->item.sym, - }; - tll_push_back(conf->bindings.url, binding); - } - - free_key_combo_list(&key_combos); - return true; - } - - LOG_AND_NOTIFY_ERR("%s:%u: [url-bindings]: %s: invalid key", path, lineno, key); - return false; - + return parse_key_binding_section( + "url-bindings", key, value, BIND_ACTION_URL_COUNT, + url_binding_action_map, &conf->bindings.url, conf, path, lineno); } static bool @@ -1659,9 +1515,10 @@ parse_mouse_combos(struct config *conf, const char *combos, key_combo_list_t *ke return true; err: - tll_foreach(*key_combos, it) + tll_foreach(*key_combos, it) { free(it->item.text); - tll_free(*key_combos); + tll_remove(*key_combos, it); + } free(copy); return false; } @@ -2134,7 +1991,7 @@ add_default_key_bindings(struct config *conf) do { \ tll_push_back( \ conf->bindings.key, \ - ((struct config_key_binding_normal){action, mods, sym})); \ + ((struct config_key_binding){action, mods, sym})); \ } while (0) const struct config_key_modifiers shift = {.shift = true}; @@ -2167,7 +2024,7 @@ add_default_search_bindings(struct config *conf) do { \ tll_push_back( \ conf->bindings.search, \ - ((struct config_key_binding_search){action, mods, sym})); \ + ((struct config_key_binding){action, mods, sym})); \ } while (0) const struct config_key_modifiers none = {0}; @@ -2215,7 +2072,7 @@ add_default_url_bindings(struct config *conf) do { \ tll_push_back( \ conf->bindings.url, \ - ((struct config_key_binding_url){action, mods, sym})); \ + ((struct config_key_binding){action, mods, sym})); \ } while (0) const struct config_key_modifiers none = {0}; @@ -2450,6 +2307,30 @@ free_spawn_template(struct config_spawn_template *template) free(template->argv); } +static void +binding_pipe_free(struct config_binding_pipe *pipe) +{ + if (pipe->master_copy) { + free(pipe->cmd); + free(pipe->argv); + } +} + +static void +key_binding_free(struct config_key_binding *binding) +{ + binding_pipe_free(&binding->pipe); +} + +static void +key_binding_list_free(config_key_binding_list_t *bindings) +{ + tll_foreach(*bindings, it) { + key_binding_free(&it->item); + tll_remove(*bindings, it); + } +} + void config_free(struct config conf) { @@ -2468,23 +2349,14 @@ config_free(struct config conf) } free(conf.server_socket_path); - tll_foreach(conf.bindings.key, it) { - if (it->item.pipe.master_copy) { - free(it->item.pipe.cmd); - free(it->item.pipe.argv); - } - } - tll_foreach(conf.bindings.mouse, it) { - if (it->item.pipe.master_copy) { - free(it->item.pipe.cmd); - free(it->item.pipe.argv); - } - } + key_binding_list_free(&conf.bindings.key); + key_binding_list_free(&conf.bindings.search); + key_binding_list_free(&conf.bindings.url); - tll_free(conf.bindings.key); - tll_free(conf.bindings.mouse); - tll_free(conf.bindings.search); - tll_free(conf.bindings.url); + tll_foreach(conf.bindings.mouse, it) { + binding_pipe_free(&it->item.pipe); + tll_remove(conf.bindings.mouse, it); + } user_notifications_free(&conf.notifications); } diff --git a/config.h b/config.h index 5ae70ae3..68a13434 100644 --- a/config.h +++ b/config.h @@ -25,39 +25,26 @@ struct config_key_modifiers { bool meta; }; -struct config_key_binding_normal { - enum bind_action_normal action; - struct config_key_modifiers modifiers; - xkb_keysym_t sym; - struct { - char *cmd; - char **argv; - bool master_copy; - } pipe; +struct config_binding_pipe { + char *cmd; + char **argv; + bool master_copy; }; -struct config_key_binding_search { - enum bind_action_search action; - struct config_key_modifiers modifiers; - xkb_keysym_t sym; -}; - -struct config_key_binding_url { - enum bind_action_url action; +struct config_key_binding { + int action; /* One of the varios bind_action_* enums from wayland.h */ struct config_key_modifiers modifiers; xkb_keysym_t sym; + struct config_binding_pipe pipe; }; +typedef tll(struct config_key_binding) config_key_binding_list_t; struct config_mouse_binding { enum bind_action_normal action; struct config_key_modifiers modifiers; int button; int count; - struct { - char *cmd; - char **argv; - bool master_copy; - } pipe; + struct config_binding_pipe pipe; }; /* If px != 0 then px is valid, otherwise pt is valid */ @@ -169,7 +156,7 @@ struct config { struct { /* Bindings for "normal" mode */ - tll(struct config_key_binding_normal) key; + config_key_binding_list_t key; tll(struct config_mouse_binding) mouse; /* @@ -178,10 +165,10 @@ struct config { /* While searching (not - action to *start* a search is in the * 'key' bindings above */ - tll(struct config_key_binding_search) search; + config_key_binding_list_t search; /* While showing URL jump labels */ - tll(struct config_key_binding_url) url; + config_key_binding_list_t url; } bindings; struct { diff --git a/input.c b/input.c index 69fce248..79368270 100644 --- a/input.c +++ b/input.c @@ -373,72 +373,39 @@ key_codes_for_xkb_sym(struct xkb_keymap *keymap, xkb_keysym_t sym) static void convert_key_binding(struct seat *seat, - const struct config_key_binding_normal *conf_binding) + const struct config_key_binding *conf_binding, + key_binding_list_t *bindings) { - struct key_binding_normal binding = { + struct key_binding binding = { + .mods = conf_modifiers_to_mask(seat, &conf_binding->modifiers), + .sym = conf_binding->sym, + .key_codes = key_codes_for_xkb_sym( + seat->kbd.xkb_keymap, conf_binding->sym), .action = conf_binding->action, - .bind = { - .mods = conf_modifiers_to_mask(seat, &conf_binding->modifiers), - .sym = conf_binding->sym, - .key_codes = key_codes_for_xkb_sym( - seat->kbd.xkb_keymap, conf_binding->sym), - }, .pipe_argv = conf_binding->pipe.argv, }; - tll_push_back(seat->kbd.bindings.key, binding); + tll_push_back(*bindings, binding); } static void convert_key_bindings(const struct config *conf, struct seat *seat) { tll_foreach(conf->bindings.key, it) - convert_key_binding(seat, &it->item); -} - -static void -convert_search_binding(struct seat *seat, - const struct config_key_binding_search *conf_binding) -{ - struct key_binding_search binding = { - .action = conf_binding->action, - .bind = { - .mods = conf_modifiers_to_mask(seat, &conf_binding->modifiers), - .sym = conf_binding->sym, - .key_codes = key_codes_for_xkb_sym( - seat->kbd.xkb_keymap, conf_binding->sym), - }, - }; - tll_push_back(seat->kbd.bindings.search, binding); + convert_key_binding(seat, &it->item, &seat->kbd.bindings.key); } static void convert_search_bindings(const struct config *conf, struct seat *seat) { tll_foreach(conf->bindings.search, it) - convert_search_binding(seat, &it->item); -} - -static void -convert_url_binding(struct seat *seat, - const struct config_key_binding_url *conf_binding) -{ - struct key_binding_url binding = { - .action = conf_binding->action, - .bind = { - .mods = conf_modifiers_to_mask(seat, &conf_binding->modifiers), - .sym = conf_binding->sym, - .key_codes = key_codes_for_xkb_sym( - seat->kbd.xkb_keymap, conf_binding->sym), - }, - }; - tll_push_back(seat->kbd.bindings.url, binding); + convert_key_binding(seat, &it->item, &seat->kbd.bindings.search); } static void convert_url_bindings(const struct config *conf, struct seat *seat) { tll_foreach(conf->bindings.url, it) - convert_url_binding(seat, &it->item); + convert_key_binding(seat, &it->item, &seat->kbd.bindings.url); } static void @@ -498,11 +465,11 @@ keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard, } tll_foreach(seat->kbd.bindings.key, it) - tll_free(it->item.bind.key_codes); + tll_free(it->item.key_codes); tll_free(seat->kbd.bindings.key); tll_foreach(seat->kbd.bindings.search, it) - tll_free(it->item.bind.key_codes); + tll_free(it->item.key_codes); tll_free(seat->kbd.bindings.search); tll_free(seat->mouse.bindings); @@ -895,17 +862,17 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial, * User configurable bindings */ tll_foreach(seat->kbd.bindings.key, it) { - if (it->item.bind.mods != effective_mods) + if (it->item.mods != effective_mods) continue; /* Match symbol */ - if (it->item.bind.sym == sym) { + if (it->item.sym == sym) { if (execute_binding(seat, term, it->item.action, it->item.pipe_argv, serial)) goto maybe_repeat; } /* Match raw key code */ - tll_foreach(it->item.bind.key_codes, code) { + tll_foreach(it->item.key_codes, code) { if (code->item == key) { if (execute_binding(seat, term, it->item.action, it->item.pipe_argv, serial)) goto maybe_repeat; diff --git a/search.c b/search.c index 0391c281..4fde8a92 100644 --- a/search.c +++ b/search.c @@ -807,11 +807,11 @@ search_input(struct seat *seat, struct terminal *term, uint32_t key, /* Key bindings */ tll_foreach(seat->kbd.bindings.search, it) { - if (it->item.bind.mods != mods) + if (it->item.mods != mods) continue; /* Match symbol */ - if (it->item.bind.sym == sym) { + if (it->item.sym == sym) { if (execute_binding(seat, term, it->item.action, serial, &update_search_result, &redraw)) { @@ -821,7 +821,7 @@ search_input(struct seat *seat, struct terminal *term, uint32_t key, } /* Match raw key code */ - tll_foreach(it->item.bind.key_codes, code) { + tll_foreach(it->item.key_codes, code) { if (code->item == key) { if (execute_binding(seat, term, it->item.action, serial, &update_search_result, &redraw)) diff --git a/url-mode.c b/url-mode.c index 40f3372f..304590ff 100644 --- a/url-mode.c +++ b/url-mode.c @@ -80,17 +80,17 @@ urls_input(struct seat *seat, struct terminal *term, uint32_t key, { /* Key bindings */ tll_foreach(seat->kbd.bindings.url, it) { - if (it->item.bind.mods != mods) + if (it->item.mods != mods) continue; /* Match symbol */ - if (it->item.bind.sym == sym) { + if (it->item.sym == sym) { execute_binding(seat, term, it->item.action, serial); return; } /* Match raw key code */ - tll_foreach(it->item.bind.key_codes, code) { + tll_foreach(it->item.key_codes, code) { if (code->item == key) { execute_binding(seat, term, it->item.action, serial); return; diff --git a/wayland.c b/wayland.c index 2a79bb10..fa3f873e 100644 --- a/wayland.c +++ b/wayland.c @@ -132,6 +132,15 @@ seat_add_text_input(struct seat *seat) #endif } +static void +key_bindings_destroy(key_binding_list_t *bindings) +{ + tll_foreach(*bindings, it) { + tll_free(it->item.key_codes); + tll_remove(*bindings, it); + } +} + static void seat_destroy(struct seat *seat) { @@ -140,17 +149,9 @@ seat_destroy(struct seat *seat) tll_free(seat->mouse.buttons); - tll_foreach(seat->kbd.bindings.key, it) - tll_free(it->item.bind.key_codes); - tll_free(seat->kbd.bindings.key); - - tll_foreach(seat->kbd.bindings.search, it) - tll_free(it->item.bind.key_codes); - tll_free(seat->kbd.bindings.search); - - tll_foreach(seat->kbd.bindings.url, it) - tll_free(it->item.bind.key_codes); - tll_free(seat->kbd.bindings.url); + key_bindings_destroy(&seat->kbd.bindings.key); + key_bindings_destroy(&seat->kbd.bindings.search); + key_bindings_destroy(&seat->kbd.bindings.url); tll_free(seat->mouse.bindings); diff --git a/wayland.h b/wayland.h index 3c160b7c..bd1102c4 100644 --- a/wayland.h +++ b/wayland.h @@ -18,15 +18,6 @@ /* Forward declarations */ struct terminal; -typedef tll(xkb_keycode_t) xkb_keycode_list_t; - -struct key_binding { - xkb_mod_mask_t mods; - xkb_keysym_t sym; - xkb_keycode_list_t key_codes; -}; -typedef tll(struct key_binding) key_binding_list_t; - enum bind_action_normal { BIND_ACTION_NONE, BIND_ACTION_SCROLLBACK_UP_PAGE, @@ -65,21 +56,6 @@ enum bind_action_normal { BIND_ACTION_COUNT = BIND_ACTION_SELECT_ROW + 1, }; -struct key_binding_normal { - struct key_binding bind; - enum bind_action_normal action; - char **pipe_argv; -}; - -struct mouse_binding { - enum bind_action_normal action; - xkb_mod_mask_t mods; - uint32_t button; - int count; - char **pipe_argv; -}; -typedef tll(struct mouse_binding) mouse_binding_list_t; - enum bind_action_search { BIND_ACTION_SEARCH_NONE, BIND_ACTION_SEARCH_CANCEL, @@ -103,21 +79,32 @@ enum bind_action_search { BIND_ACTION_SEARCH_COUNT, }; -struct key_binding_search { - struct key_binding bind; - enum bind_action_search action; -}; - enum bind_action_url { BIND_ACTION_URL_NONE, BIND_ACTION_URL_CANCEL, BIND_ACTION_URL_COUNT, }; -struct key_binding_url { - struct key_binding bind; - enum bind_action_url action; +typedef tll(xkb_keycode_t) xkb_keycode_list_t; + +struct key_binding { + xkb_mod_mask_t mods; + xkb_keysym_t sym; + xkb_keycode_list_t key_codes; + + int action; /* enum bind_action_* */ + char **pipe_argv; }; +typedef tll(struct key_binding) key_binding_list_t; + +struct mouse_binding { + enum bind_action_normal action; + xkb_mod_mask_t mods; + uint32_t button; + int count; + char **pipe_argv; +}; +typedef tll(struct mouse_binding) mouse_binding_list_t; /* Mime-types we support when dealing with data offers (e.g. copy-paste, or DnD) */ enum data_offer_mime_type { @@ -203,9 +190,9 @@ struct seat { bool meta; struct { - tll(struct key_binding_normal) key; - tll(struct key_binding_search) search; - tll(struct key_binding_url) url; + key_binding_list_t key; + key_binding_list_t search; + key_binding_list_t url; } bindings; } kbd;