From 9ce79e2ef0b0b19b06990302807d6c3b3a755e1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Fri, 6 Nov 2020 19:29:23 +0100 Subject: [PATCH] config: add support for pipe-* actions in mouse bindings Closes #183 --- CHANGELOG.md | 4 ++++ config.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++---- config.h | 5 +++++ input.c | 5 +++-- wayland.h | 1 + 5 files changed, 65 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c94ea81..e6ad80b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -77,6 +77,10 @@ window (https://codeberg.org/dnkl/foot/issues/179). * Character dropped from selection when "right-click-hold"-extending a selection (https://codeberg.org/dnkl/foot/issues/180). +* Support for **pipe-\*** actions in mouse bindings. It was previously + not possible to add a command to these actions when used in mouse + bindings, making them useless + (https://codeberg.org/dnkl/foot/issues/183). ### Security diff --git a/config.c b/config.c index c460c987..bb8324db 100644 --- a/config.c +++ b/config.c @@ -1470,8 +1470,13 @@ has_mouse_binding_collisions(struct config *conf, const key_combo_list_t *key_co bool count = it->item.count == it2->item.m.count; if (shift && alt && ctrl && meta && button && count) { + 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]); + binding_action_map[it->item.action], + has_pipe ? " [" : "", + has_pipe ? it->item.pipe.cmd : "", + has_pipe ? "]" : ""); return true; } } @@ -1486,6 +1491,17 @@ parse_section_mouse_bindings( const char *key, const char *value, struct config *conf, const char *path, unsigned lineno) { + char *pipe_cmd; + char **pipe_argv; + + ssize_t pipe_remove_len = pipe_argv_from_string( + value, &pipe_cmd, &pipe_argv, conf, path, lineno); + + if (pipe_remove_len < 0) + return false; + + value += pipe_remove_len; + for (enum bind_action_normal action = 0; action < BIND_ACTION_COUNT; action++) @@ -1502,9 +1518,16 @@ parse_section_mouse_bindings( /* Unset binding */ if (strcasecmp(value, "none") == 0) { tll_foreach(conf->bindings.mouse, it) { - if (it->item.action == action) + 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.mouse, it); + } } + free(pipe_argv); + free(pipe_cmd); return true; } @@ -1512,26 +1535,43 @@ parse_section_mouse_bindings( if (!parse_mouse_combos(conf, value, &key_combos, path, lineno) || has_mouse_binding_collisions(conf, &key_combos, path, lineno)) { + free(pipe_argv); + free(pipe_cmd); free_key_combo_list(&key_combos); return false; } /* Remove existing bindings for this action */ tll_foreach(conf->bindings.mouse, it) { - if (it->item.action == action) { + if (it->item.action == action && + ((it->item.pipe.argv == NULL && pipe_argv == NULL) || + (it->item.pipe.argv != NULL && pipe_argv != NULL && + argv_compare(it->item.pipe.argv, pipe_argv) == 0))) + { + if (it->item.pipe.master_copy) { + free(it->item.pipe.cmd); + free(it->item.pipe.argv); + } tll_remove(conf->bindings.mouse, it); } } /* Emit mouse bindings */ + bool first = true; tll_foreach(key_combos, it) { struct config_mouse_binding binding = { .action = action, .modifiers = it->item.modifiers, .button = it->item.m.button, .count = it->item.m.count, + .pipe = { + .cmd = pipe_cmd, + .argv = pipe_argv, + .master_copy = first, + }, }; tll_push_back(conf->bindings.mouse, binding); + first = false; } free_key_combo_list(&key_combos); @@ -1539,6 +1579,8 @@ parse_section_mouse_bindings( } LOG_AND_NOTIFY_ERR("%s:%u: [mouse-bindings]: %s: invalid key", path, lineno, key); + free(pipe_argv); + free(pipe_cmd); return false; } @@ -1937,7 +1979,7 @@ add_default_mouse_bindings(struct config *conf) do { \ tll_push_back( \ conf->bindings.mouse, \ - ((struct config_mouse_binding){action, mods, btn, count})); \ + ((struct config_mouse_binding){action, mods, btn, count, {0}})); \ } while (0) const struct config_key_modifiers none = {0}; @@ -2133,6 +2175,12 @@ config_free(struct config conf) 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); + } + } tll_free(conf.bindings.key); tll_free(conf.bindings.mouse); diff --git a/config.h b/config.h index 7313f42f..48961790 100644 --- a/config.h +++ b/config.h @@ -47,6 +47,11 @@ struct config_mouse_binding { struct config_key_modifiers modifiers; int button; int count; + struct { + char *cmd; + char **argv; + bool master_copy; + } pipe; }; struct config { diff --git a/input.c b/input.c index 8140e250..60780dc9 100644 --- a/input.c +++ b/input.c @@ -424,6 +424,7 @@ convert_mouse_binding(struct seat *seat, .mods = conf_modifiers_to_mask(seat, &conf_binding->modifiers), .button = conf_binding->button, .count = conf_binding->count, + .pipe_argv = conf_binding->pipe.argv, }; tll_push_back(seat->mouse.bindings, binding); } @@ -1628,7 +1629,7 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, if (match != NULL) { seat->mouse.consumed = execute_binding( - seat, term, match->action, NULL, serial); + seat, term, match->action, match->pipe_argv, serial); } } @@ -1661,7 +1662,7 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, if (match != NULL) { seat->mouse.consumed = execute_binding( - seat, term, match->action, NULL, serial); + seat, term, match->action, match->pipe.argv, serial); } } diff --git a/wayland.h b/wayland.h index e64663e2..ac6dd9a7 100644 --- a/wayland.h +++ b/wayland.h @@ -72,6 +72,7 @@ struct mouse_binding { xkb_mod_mask_t mods; uint32_t button; int count; + char **pipe_argv; }; typedef tll(struct mouse_binding) mouse_binding_list_t;