From e5c5cd54788076973f08f6aadf0d2b2f954a0423 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 8 Feb 2022 19:35:41 +0100 Subject: [PATCH] =?UTF-8?q?config:=20=E2=80=98pipe=E2=80=99=20is=20now=20o?= =?UTF-8?q?ptional=20=E2=80=98aux=E2=80=99=20data=20in=20the=20key-binding?= =?UTF-8?q?=20struct?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows us to add helper functions that e.g. compare bindings’ aux data in a generic way. --- config.c | 126 ++++++++++++++++++++++++++------------------ config.h | 15 ++++-- input.c | 14 ++--- tests/test-config.c | 40 +++++++------- wayland.h | 4 +- 5 files changed, 116 insertions(+), 83 deletions(-) diff --git a/config.c b/config.c index 011b4875..bd28d408 100644 --- a/config.c +++ b/config.c @@ -1476,16 +1476,18 @@ parse_section_csd(struct context *ctx) } static void -free_binding_pipe(struct config_binding_pipe *pipe) +free_binding_aux(struct binding_aux *aux) { - if (pipe->master_copy) - free_argv(&pipe->argv); + switch (aux->type) { + case BINDING_AUX_NONE: break; + case BINDING_AUX_PIPE: free_argv(&aux->pipe); + } } static void free_key_binding(struct config_key_binding *binding) { - free_binding_pipe(&binding->pipe); + free_binding_aux(&binding->aux); } static void NOINLINE @@ -1568,9 +1570,25 @@ argv_compare(const struct argv *argv1, const struct argv *argv2) return 1; } +static bool NOINLINE +binding_aux_equal(const struct binding_aux *a, + const struct binding_aux *b) +{ + if (a->type != b->type) + return false; + + switch (a->type) { + case BINDING_AUX_NONE: return true; + case BINDING_AUX_PIPE: return argv_compare(&a->pipe, &b->pipe) == 0; + } + + BUG("invalid AUX type: %d", a->type); + return false; +} + static void NOINLINE remove_from_key_bindings_list(struct config_key_binding_list *bindings, - int action, const struct argv *pipe_argv) + int action, const struct binding_aux *aux) { size_t remove_first_idx = 0; size_t remove_count = 0; @@ -1581,7 +1599,7 @@ remove_from_key_bindings_list(struct config_key_binding_list *bindings, if (binding->action != action) continue; - if (argv_compare(&binding->pipe.argv, pipe_argv) == 0) { + if (binding_aux_equal(&binding->aux, aux)) { if (remove_count++ == 0) remove_first_idx = i; @@ -1638,12 +1656,13 @@ mouse_button_code_to_name(int code) } static bool NOINLINE -value_to_key_combos(struct context *ctx, int action, struct argv *argv, +value_to_key_combos(struct context *ctx, int action, + struct binding_aux *aux, struct config_key_binding_list *bindings, enum key_binding_type type) { if (strcasecmp(ctx->value, "none") == 0) { - remove_from_key_bindings_list(bindings, action, argv); + remove_from_key_bindings_list(bindings, action, aux); return true; } @@ -1668,8 +1687,13 @@ value_to_key_combos(struct context *ctx, int action, struct argv *argv, { struct config_key_binding *new_combo = &new_combos[idx]; new_combo->action = action; - new_combo->pipe.master_copy = idx == 0; - new_combo->pipe.argv = *argv; + new_combo->aux = *aux; + new_combo->aux.master_copy = idx == 0; +#if 0 + new_combo->aux.type = BINDING_AUX_PIPE; + new_combo->aux.master_copy = idx == 0; + new_combo->aux.pipe = *argv; +#endif new_combo->path = ctx->path; new_combo->lineno = ctx->lineno; @@ -1736,7 +1760,7 @@ value_to_key_combos(struct context *ctx, int action, struct argv *argv, goto err; } - remove_from_key_bindings_list(bindings, action, argv); + remove_from_key_bindings_list(bindings, action, aux); bindings->arr = xrealloc( bindings->arr, @@ -1850,12 +1874,15 @@ parse_key_binding_section(struct context *ctx, const char *const action_map[static action_count], struct config_key_binding_list *bindings) { - struct argv pipe_argv; + struct binding_aux aux; - ssize_t pipe_remove_len = pipe_argv_from_value(ctx, &pipe_argv); + ssize_t pipe_remove_len = pipe_argv_from_value(ctx, &aux.pipe); if (pipe_remove_len < 0) return false; + aux.type = pipe_remove_len == 0 ? BINDING_AUX_NONE : BINDING_AUX_PIPE; + aux.master_copy = true; + for (int action = 0; action < action_count; action++) { if (action_map[action] == NULL) continue; @@ -1863,10 +1890,8 @@ parse_key_binding_section(struct context *ctx, if (strcmp(ctx->key, action_map[action]) != 0) continue; - if (!value_to_key_combos( - ctx, action, &pipe_argv, bindings, KEY_BINDING)) - { - free_argv(&pipe_argv); + if (!value_to_key_combos(ctx, action, &aux, bindings, KEY_BINDING)) { + free_binding_aux(&aux); return false; } @@ -1874,7 +1899,7 @@ parse_key_binding_section(struct context *ctx, } LOG_CONTEXTUAL_ERR("not a valid action: %s", ctx->key); - free_argv(&pipe_argv); + free_binding_aux(&aux); return false; } @@ -2033,12 +2058,10 @@ resolve_key_binding_collisions(struct config *conf, const char *section_name, const struct config_key_binding *binding2 = &bindings->arr[j]; xassert(binding2->action != BIND_ACTION_NONE); - if (binding2->action == binding1->action) { - if (argv_compare( - &binding1->pipe.argv, &binding2->pipe.argv) == 0) - { - continue; - } + if (binding2->action == binding1->action && + binding_aux_equal(&binding1->aux, &binding2->aux)) + { + continue; } const struct config_key_modifiers *mods2 = &binding2->modifiers; @@ -2092,7 +2115,7 @@ resolve_key_binding_collisions(struct config *conf, const char *section_name, break; case COLLISION_BINDING: { - bool has_pipe = collision_binding->pipe.argv.args != NULL; + bool has_pipe = collision_binding->aux.type == BINDING_AUX_PIPE; LOG_AND_NOTIFY_ERR( "%s:%d: [%s].%s: %s%s already mapped to '%s%s%s%s'", binding1->path, binding1->lineno, section_name, @@ -2100,7 +2123,7 @@ resolve_key_binding_collisions(struct config *conf, const char *section_name, modifier_names, sym_name, action_map[collision_binding->action], has_pipe ? " [" : "", - has_pipe ? collision_binding->pipe.argv.args[0] : "", + has_pipe ? collision_binding->aux.pipe.args[0] : "", has_pipe ? "]" : ""); ret = false; break; @@ -2128,15 +2151,15 @@ resolve_key_binding_collisions(struct config *conf, const char *section_name, free(modifier_names); - if (binding1->pipe.master_copy && i + 1 < bindings->count) { + if (binding1->aux.master_copy && i + 1 < bindings->count) { struct config_key_binding *next = &bindings->arr[i + 1]; if (next->action == binding1->action && - argv_compare(&binding1->pipe.argv, &next->pipe.argv) == 0) + binding_aux_equal(&binding1->aux, &next->aux)) { /* Transfer ownership to next binding */ - next->pipe.master_copy = true; - binding1->pipe.master_copy = false; + next->aux.master_copy = true; + binding1->aux.master_copy = false; } } @@ -2150,7 +2173,6 @@ resolve_key_binding_collisions(struct config *conf, const char *section_name, i--; } - } return ret; @@ -2174,12 +2196,15 @@ parse_section_mouse_bindings(struct context *ctx) return true; } - struct argv pipe_argv; + struct binding_aux aux; - ssize_t pipe_remove_len = pipe_argv_from_value(ctx, &pipe_argv); + ssize_t pipe_remove_len = pipe_argv_from_value(ctx, &aux.pipe); if (pipe_remove_len < 0) return false; + aux.type = pipe_remove_len == 0 ? BINDING_AUX_NONE : BINDING_AUX_PIPE; + aux.master_copy = true; + for (enum bind_action_normal action = 0; action < BIND_ACTION_COUNT; action++) @@ -2191,9 +2216,9 @@ parse_section_mouse_bindings(struct context *ctx) continue; if (!value_to_key_combos( - ctx, action, &pipe_argv, &conf->bindings.mouse, MOUSE_BINDING)) + ctx, action, &aux, &conf->bindings.mouse, MOUSE_BINDING)) { - free_argv(&pipe_argv); + free_binding_aux(&aux); return false; } @@ -2201,7 +2226,7 @@ parse_section_mouse_bindings(struct context *ctx) } LOG_CONTEXTUAL_ERR("not a valid option: %s", key); - free_argv(&pipe_argv); + free_binding_aux(&aux); return false; } @@ -3055,14 +3080,6 @@ config_override_apply(struct config *conf, config_override_t *overrides, return true; } -static void -binding_pipe_clone(struct config_binding_pipe *dst, - const struct config_binding_pipe *src) -{ - xassert(src->master_copy); - clone_argv(&dst->argv, &src->argv); -} - static void NOINLINE key_binding_list_clone(struct config_key_binding_list *dst, const struct config_key_binding_list *src) @@ -3078,15 +3095,20 @@ key_binding_list_clone(struct config_key_binding_list *dst, *new = *old; - if (old->pipe.argv.args == NULL) - continue; + switch (old->aux.type) { + case BINDING_AUX_NONE: + last_master_argv = NULL; + break; - if (old->pipe.master_copy) { - binding_pipe_clone(&new->pipe, &old->pipe); - last_master_argv = &new->pipe.argv; - } else { - xassert(last_master_argv != NULL); - new->pipe.argv = *last_master_argv; + case BINDING_AUX_PIPE: + if (old->aux.master_copy) { + clone_argv(&new->aux.pipe, &old->aux.pipe); + last_master_argv = &new->aux.pipe; + } else { + xassert(last_master_argv != NULL); + new->aux.pipe = *last_master_argv; + } + break; } } } diff --git a/config.h b/config.h index 473cfdd4..927f4e5f 100644 --- a/config.h +++ b/config.h @@ -44,9 +44,18 @@ struct argv { char **args; }; -struct config_binding_pipe { - struct argv argv; +enum binding_aux_type { + BINDING_AUX_NONE, + BINDING_AUX_PIPE, +}; + +struct binding_aux { + enum binding_aux_type type; bool master_copy; + + union { + struct argv pipe; + }; }; enum key_binding_type { @@ -70,7 +79,7 @@ struct config_key_binding { } m; }; - struct config_binding_pipe pipe; + struct binding_aux aux; /* For error messages in collision handling */ const char *path; diff --git a/input.c b/input.c index 986f26bd..25778683 100644 --- a/input.c +++ b/input.c @@ -526,7 +526,7 @@ convert_key_binding(const struct seat *seat, struct key_binding binding = { .type = KEY_BINDING, .action = conf_binding->action, - .pipe_argv = conf_binding->pipe.argv.args, + .aux = &conf_binding->aux, .mods = mods, .k = { .sym = sym, @@ -570,7 +570,7 @@ convert_mouse_binding(struct seat *seat, struct key_binding binding = { .type = MOUSE_BINDING, .action = conf_binding->action, - .pipe_argv = conf_binding->pipe.argv.args, + .aux = &conf_binding->aux, .mods = conf_modifiers_to_mask(seat, &conf_binding->modifiers), .m = { .button = conf_binding->m.button, @@ -1526,7 +1526,7 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial, if (bind->k.sym == sym && bind->mods == (bind_mods & ~bind_consumed) && execute_binding( - seat, term, bind->action, bind->pipe_argv, serial)) + seat, term, bind->action, bind->aux->pipe.args, serial)) { goto maybe_repeat; } @@ -1537,7 +1537,7 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial, /* Match untranslated symbols */ for (size_t i = 0; i < raw_count; i++) { if (bind->k.sym == raw_syms[i] && execute_binding( - seat, term, bind->action, bind->pipe_argv, serial)) + seat, term, bind->action, bind->aux->pipe.args, serial)) { goto maybe_repeat; } @@ -1546,7 +1546,7 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial, /* Match raw key code */ tll_foreach(bind->k.key_codes, code) { if (code->item == key && execute_binding( - seat, term, bind->action, bind->pipe_argv, serial)) + seat, term, bind->action, bind->aux->pipe.args, serial)) { goto maybe_repeat; } @@ -2435,7 +2435,7 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, if (match != NULL) { consumed = execute_binding( - seat, term, match->action, match->pipe_argv, serial); + seat, term, match->action, match->aux->pipe.args, serial); } } @@ -2470,7 +2470,7 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, if (match != NULL) { consumed = execute_binding( - seat, term, match->action, match->pipe.argv.args, + seat, term, match->action, match->aux.pipe.args, serial); } } diff --git a/tests/test-config.c b/tests/test-config.c index 88f22a4a..be18a593 100644 --- a/tests/test-config.c +++ b/tests/test-config.c @@ -756,30 +756,30 @@ test_key_binding(struct context *ctx, bool (*parse_fun)(struct context *ctx), &bindings->arr[bindings->count - 1]; if (argv) { - if (binding->pipe.argv.args == NULL) { + if (binding->aux.pipe.args == NULL) { BUG("[%s].%s=%s: pipe argv is NULL", ctx->section, ctx->key, ctx->value); } for (size_t i = 0; i < ALEN(args); i++) { - if (binding->pipe.argv.args[i] == NULL || - strcmp(binding->pipe.argv.args[i], args[i]) != 0) + if (binding->aux.pipe.args[i] == NULL || + strcmp(binding->aux.pipe.args[i], args[i]) != 0) { BUG("[%s].%s=%s: pipe argv not the expected one: " "mismatch of arg #%zu: expected=\"%s\", got=\"%s\"", ctx->section, ctx->key, ctx->value, i, - args[i], binding->pipe.argv.args[i]); + args[i], binding->aux.pipe.args[i]); } } - if (binding->pipe.argv.args[ALEN(args)] != NULL) { + if (binding->aux.pipe.args[ALEN(args)] != NULL) { BUG("[%s].%s=%s: pipe argv not the expected one: " "expected NULL terminator at arg #%zu, got=\"%s\"", ctx->section, ctx->key, ctx->value, - ALEN(args), binding->pipe.argv.args[ALEN(args)]); + ALEN(args), binding->aux.pipe.args[ALEN(args)]); } } else { - if (binding->pipe.argv.args != NULL) { + if (binding->aux.pipe.args != NULL) { BUG("[%s].%s=%s: pipe argv not NULL", ctx->section, ctx->key, ctx->value); } @@ -889,21 +889,23 @@ _test_binding_collisions(struct context *ctx, case FAIL_DIFFERENT_ARGV: case SUCCED_SAME_ACTION_AND_ARGV: - bindings.arr[0].pipe.master_copy = true; - bindings.arr[0].pipe.argv.args = xcalloc( - 4, sizeof(bindings.arr[0].pipe.argv.args[0])); - bindings.arr[0].pipe.argv.args[0] = xstrdup("/usr/bin/foobar"); - bindings.arr[0].pipe.argv.args[1] = xstrdup("hello"); - bindings.arr[0].pipe.argv.args[2] = xstrdup("world"); + bindings.arr[0].aux.type = BINDING_AUX_PIPE; + bindings.arr[0].aux.master_copy = true; + bindings.arr[0].aux.pipe.args = xcalloc( + 4, sizeof(bindings.arr[0].aux.pipe.args[0])); + bindings.arr[0].aux.pipe.args[0] = xstrdup("/usr/bin/foobar"); + bindings.arr[0].aux.pipe.args[1] = xstrdup("hello"); + bindings.arr[0].aux.pipe.args[2] = xstrdup("world"); - bindings.arr[1].pipe.master_copy = true; - bindings.arr[1].pipe.argv.args = xcalloc( - 4, sizeof(bindings.arr[1].pipe.argv.args[0])); - bindings.arr[1].pipe.argv.args[0] = xstrdup("/usr/bin/foobar"); - bindings.arr[1].pipe.argv.args[1] = xstrdup("hello"); + bindings.arr[1].aux.type = BINDING_AUX_PIPE; + bindings.arr[1].aux.master_copy = true; + bindings.arr[1].aux.pipe.args = xcalloc( + 4, sizeof(bindings.arr[1].aux.pipe.args[0])); + bindings.arr[1].aux.pipe.args[0] = xstrdup("/usr/bin/foobar"); + bindings.arr[1].aux.pipe.args[1] = xstrdup("hello"); if (test_mode == SUCCED_SAME_ACTION_AND_ARGV) - bindings.arr[1].pipe.argv.args[2] = xstrdup("world"); + bindings.arr[1].aux.pipe.args[2] = xstrdup("world"); break; } diff --git a/wayland.h b/wayland.h index ea0b8ae6..81109673 100644 --- a/wayland.h +++ b/wayland.h @@ -104,8 +104,6 @@ struct key_binding { enum key_binding_type type; int action; /* enum bind_action_* */ - char **pipe_argv; - xkb_mod_mask_t mods; union { @@ -120,6 +118,8 @@ struct key_binding { } m; }; + const struct binding_aux *aux; + }; typedef tll(struct key_binding) key_binding_list_t;