diff --git a/config.c b/config.c index 0c9c8f43..37768a8e 100644 --- a/config.c +++ b/config.c @@ -1451,7 +1451,7 @@ parse_section_csd(struct context *ctx) } else if (strcmp(key, "button-close-color") == 0) { - if (!value_to_color(ctx, &conf->csd.color.close, true)) + if (!value_to_color(ctx, &conf->csd.color.quit, true)) return false; conf->csd.color.close_set = true; @@ -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 config_key_binding_type type) + 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; } @@ -2002,7 +2027,7 @@ static bool NOINLINE resolve_key_binding_collisions(struct config *conf, const char *section_name, const char *const action_map[], struct config_key_binding_list *bindings, - enum config_key_binding_type type) + enum key_binding_type type) { bool ret = true; @@ -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 2f318d1d..cd5bbd14 100644 --- a/config.h +++ b/config.h @@ -4,11 +4,11 @@ #include #include +#include #include +#include -#include "terminal.h" #include "user-notification.h" -#include "wayland.h" #define DEFINE_LIST(type) \ type##_list { \ @@ -16,6 +16,14 @@ type *arr; \ } +/* If px != 0 then px is valid, otherwise pt is valid */ +struct pt_or_px { + int16_t px; + float pt; +}; + +enum cursor_style { CURSOR_BLOCK, CURSOR_UNDERLINE, CURSOR_BEAM }; + enum conf_size_type {CONF_SIZE_PX, CONF_SIZE_CELLS}; struct config_font { @@ -36,12 +44,21 @@ struct argv { char **args; }; -struct config_binding_pipe { - struct argv argv; - bool master_copy; +enum binding_aux_type { + BINDING_AUX_NONE, + BINDING_AUX_PIPE, }; -enum config_key_binding_type { +struct binding_aux { + enum binding_aux_type type; + bool master_copy; + + union { + struct argv pipe; + }; +}; + +enum key_binding_type { KEY_BINDING, MOUSE_BINDING, }; @@ -62,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; @@ -245,7 +262,7 @@ struct config { uint32_t buttons; uint32_t minimize; uint32_t maximize; - uint32_t close; + uint32_t quit; /* ‘close’ collides with #define in epoll-shim */ uint32_t border; } color; diff --git a/input.c b/input.c index 68db9929..5a2489de 100644 --- a/input.c +++ b/input.c @@ -81,9 +81,10 @@ pipe_closed: static bool execute_binding(struct seat *seat, struct terminal *term, - enum bind_action_normal action, char *const *pipe_argv, - uint32_t serial) + const struct key_binding *binding, uint32_t serial) { + const enum bind_action_normal action = binding->action; + switch (action) { case BIND_ACTION_NONE: return true; @@ -193,7 +194,7 @@ execute_binding(struct seat *seat, struct terminal *term, /* FALLTHROUGH */ case BIND_ACTION_PIPE_VIEW: case BIND_ACTION_PIPE_SELECTED: { - if (pipe_argv == NULL) + if (binding->aux->type != BINDING_AUX_PIPE) return true; struct pipe_context *ctx = NULL; @@ -266,7 +267,7 @@ execute_binding(struct seat *seat, struct terminal *term, } } - if (!spawn(term->reaper, NULL, pipe_argv, pipe_fd[0], stdout_fd, stderr_fd)) + if (!spawn(term->reaper, NULL, binding->aux->pipe.args, pipe_fd[0], stdout_fd, stderr_fd)) goto pipe_err; /* Close read end */ @@ -524,11 +525,14 @@ convert_key_binding(const struct seat *seat, xkb_keysym_t sym = maybe_repair_key_combo(seat, conf_binding->k.sym, mods); struct key_binding binding = { - .mods = mods, - .sym = sym, - .key_codes = key_codes_for_xkb_sym(seat->kbd.xkb_keymap, sym), + .type = KEY_BINDING, .action = conf_binding->action, - .pipe_argv = conf_binding->pipe.argv.args, + .aux = &conf_binding->aux, + .mods = mods, + .k = { + .sym = sym, + .key_codes = key_codes_for_xkb_sym(seat->kbd.xkb_keymap, sym), + }, }; tll_push_back(*bindings, binding); } @@ -564,12 +568,15 @@ static void convert_mouse_binding(struct seat *seat, const struct config_key_binding *conf_binding) { - struct mouse_binding binding = { + struct key_binding binding = { + .type = MOUSE_BINDING, .action = conf_binding->action, + .aux = &conf_binding->aux, .mods = conf_modifiers_to_mask(seat, &conf_binding->modifiers), - .button = conf_binding->m.button, - .count = conf_binding->m.count, - .pipe_argv = conf_binding->pipe.argv.args, + .m = { + .button = conf_binding->m.button, + .count = conf_binding->m.count, + }, }; tll_push_back(seat->mouse.bindings, binding); } @@ -618,15 +625,7 @@ keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard, seat->kbd.xkb = NULL; } - tll_foreach(seat->kbd.bindings.key, it) - tll_free(it->item.key_codes); - tll_free(seat->kbd.bindings.key); - - tll_foreach(seat->kbd.bindings.search, it) - tll_free(it->item.key_codes); - tll_free(seat->kbd.bindings.search); - - tll_free(seat->mouse.bindings); + wayl_bindings_reset(seat); /* Verify keymap is in a format we understand */ switch ((enum wl_keyboard_keymap_format)format) { @@ -1525,10 +1524,9 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial, const struct key_binding *bind = &it->item; /* Match translated symbol */ - if (bind->sym == sym && + if (bind->k.sym == sym && bind->mods == (bind_mods & ~bind_consumed) && - execute_binding( - seat, term, bind->action, bind->pipe_argv, serial)) + execute_binding(seat, term, bind, serial)) { goto maybe_repeat; } @@ -1538,17 +1536,17 @@ 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->sym == raw_syms[i] && execute_binding( - seat, term, bind->action, bind->pipe_argv, serial)) + if (bind->k.sym == raw_syms[i] && + execute_binding(seat, term, bind, serial)) { goto maybe_repeat; } } /* Match raw key code */ - tll_foreach(bind->key_codes, code) { - if (code->item == key && execute_binding( - seat, term, bind->action, bind->pipe_argv, serial)) + tll_foreach(bind->k.key_codes, code) { + if (code->item == key && + execute_binding(seat, term, bind, serial)) { goto maybe_repeat; } @@ -2411,12 +2409,12 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, /* Ignore selection override modifiers when matching modifiers */ mods &= ~seat->kbd.selection_override_modmask; - const struct mouse_binding *match = NULL; + const struct key_binding *match = NULL; tll_foreach(seat->mouse.bindings, it) { - const struct mouse_binding *binding = &it->item; + const struct key_binding *binding = &it->item; - if (binding->button != button) { + if (binding->m.button != button) { /* Wrong button */ continue; } @@ -2426,19 +2424,17 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, continue; } - if (binding->count > seat->mouse.count) { + if (binding->m.count > seat->mouse.count) { /* Not correct click count */ continue; } - if (match == NULL || binding->count > match->count) + if (match == NULL || binding->m.count > match->m.count) match = binding; } - if (match != NULL) { - consumed = execute_binding( - seat, term, match->action, match->pipe_argv, serial); - } + if (match != NULL) + consumed = execute_binding(seat, term, match, serial); } else { @@ -2471,9 +2467,11 @@ wl_pointer_button(void *data, struct wl_pointer *wl_pointer, } if (match != NULL) { - consumed = execute_binding( - seat, term, match->action, match->pipe.argv.args, - serial); + struct key_binding bind = { + .action = match->action, + .aux = &match->aux, + }; + consumed = execute_binding(seat, term, &bind, serial); } } } diff --git a/render.c b/render.c index d873aa79..d6fd6d6b 100644 --- a/render.c +++ b/render.c @@ -2052,7 +2052,7 @@ render_csd_button(struct terminal *term, enum csd_surface surf_idx, case CSD_SURF_CLOSE: _color = term->conf->colors.table[1]; /* red */ is_set = term->conf->csd.color.close_set; - conf_color = &term->conf->csd.color.close; + conf_color = &term->conf->csd.color.quit; is_active = term->active_surface == TERM_SURF_BUTTON_CLOSE; break; diff --git a/search.c b/search.c index 8015f265..6251c697 100644 --- a/search.c +++ b/search.c @@ -604,10 +604,11 @@ from_clipboard_done(void *user) static bool execute_binding(struct seat *seat, struct terminal *term, - enum bind_action_search action, uint32_t serial, + const struct key_binding *binding, uint32_t serial, bool *update_search_result, bool *redraw) { *update_search_result = *redraw = false; + const enum bind_action_search action = binding->action; switch (action) { case BIND_ACTION_SEARCH_NONE: @@ -838,10 +839,10 @@ search_input(struct seat *seat, struct terminal *term, uint32_t key, const struct key_binding *bind = &it->item; /* Match translated symbol */ - if (bind->sym == sym && + if (bind->k.sym == sym && bind->mods == (mods & ~consumed)) { - if (execute_binding(seat, term, bind->action, serial, + if (execute_binding(seat, term, bind, serial, &update_search_result, &redraw)) { goto update_search; @@ -854,8 +855,8 @@ search_input(struct seat *seat, struct terminal *term, uint32_t key, /* Match untranslated symbols */ for (size_t i = 0; i < raw_count; i++) { - if (bind->sym == raw_syms[i]) { - if (execute_binding(seat, term, bind->action, serial, + if (bind->k.sym == raw_syms[i]) { + if (execute_binding(seat, term, bind, serial, &update_search_result, &redraw)) { goto update_search; @@ -865,9 +866,9 @@ search_input(struct seat *seat, struct terminal *term, uint32_t key, } /* Match raw key code */ - tll_foreach(bind->key_codes, code) { + tll_foreach(bind->k.key_codes, code) { if (code->item == key) { - if (execute_binding(seat, term, bind->action, serial, + if (execute_binding(seat, term, bind, serial, &update_search_result, &redraw)) { goto update_search; diff --git a/server.h b/server.h index 55a031b4..50797540 100644 --- a/server.h +++ b/server.h @@ -2,6 +2,7 @@ #include "fdm.h" #include "config.h" +#include "reaper.h" #include "wayland.h" struct server; diff --git a/terminal.h b/terminal.h index d3602383..f1523939 100644 --- a/terminal.h +++ b/terminal.h @@ -14,7 +14,7 @@ #include #include -//#include "config.h" +#include "config.h" #include "composed.h" #include "debug.h" #include "fdm.h" @@ -248,8 +248,6 @@ enum mouse_reporting { MOUSE_SGR_PIXELS, /* ?1016h */ }; -enum cursor_style { CURSOR_BLOCK, CURSOR_UNDERLINE, CURSOR_BEAM }; - enum selection_kind { SELECTION_NONE, SELECTION_CHAR_WISE, @@ -299,12 +297,6 @@ struct url { }; typedef tll(struct url) url_list_t; -/* If px != 0 then px is valid, otherwise pt is valid */ -struct pt_or_px { - int16_t px; - float pt; -}; - struct terminal { struct fdm *fdm; struct reaper *reaper; diff --git a/tests/test-config.c b/tests/test-config.c index bced6b5c..04149a59 100644 --- a/tests/test-config.c +++ b/tests/test-config.c @@ -665,7 +665,7 @@ test_section_csd(void) test_color(&ctx, &parse_section_csd, "button-maximize-color", true, &conf.csd.color.maximize); test_color(&ctx, &parse_section_csd, "button-close-color", true, - &conf.csd.color.close); + &conf.csd.color.quit); /* TODO: verify the ‘set’ bit is actually set for colors */ /* TODO: font */ @@ -677,7 +677,7 @@ static void test_key_binding(struct context *ctx, bool (*parse_fun)(struct context *ctx), int action, int max_action, const char *const *map, struct config_key_binding_list *bindings, - enum config_key_binding_type type) + enum key_binding_type type) { xassert(map[action] != NULL); xassert(bindings->count == 0); @@ -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); } @@ -840,7 +840,7 @@ enum collision_test_mode { static void _test_binding_collisions(struct context *ctx, int max_action, const char *const *map, - enum config_key_binding_type type, + enum key_binding_type type, enum collision_test_mode test_mode) { struct config_key_binding *bindings_array = @@ -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; } @@ -937,7 +939,7 @@ _test_binding_collisions(struct context *ctx, static void test_binding_collisions(struct context *ctx, int max_action, const char *const *map, - enum config_key_binding_type type) + enum key_binding_type type) { _test_binding_collisions(ctx, max_action, map, type, FAIL_DIFFERENT_ACTION); _test_binding_collisions(ctx, max_action, map, type, FAIL_DIFFERENT_ARGV); diff --git a/url-mode.c b/url-mode.c index 82002fa0..350bdf25 100644 --- a/url-mode.c +++ b/url-mode.c @@ -25,8 +25,10 @@ static void url_destroy(struct url *url); static bool execute_binding(struct seat *seat, struct terminal *term, - enum bind_action_url action, uint32_t serial) + const struct key_binding *binding, uint32_t serial) { + const enum bind_action_url action = binding->action; + switch (action) { case BIND_ACTION_URL_NONE: return false; @@ -125,10 +127,10 @@ urls_input(struct seat *seat, struct terminal *term, uint32_t key, const struct key_binding *bind = &it->item; /* Match translated symbol */ - if (bind->sym == sym && + if (bind->k.sym == sym && bind->mods == (mods & ~consumed)) { - execute_binding(seat, term, bind->action, serial); + execute_binding(seat, term, bind, serial); return; } @@ -136,16 +138,16 @@ urls_input(struct seat *seat, struct terminal *term, uint32_t key, continue; for (size_t i = 0; i < raw_count; i++) { - if (bind->sym == raw_syms[i]) { - execute_binding(seat, term, bind->action, serial); + if (bind->k.sym == raw_syms[i]) { + execute_binding(seat, term, bind, serial); return; } } /* Match raw key code */ - tll_foreach(bind->key_codes, code) { + tll_foreach(bind->k.key_codes, code) { if (code->item == key) { - execute_binding(seat, term, bind->action, serial); + execute_binding(seat, term, bind, serial); return; } } diff --git a/wayland.c b/wayland.c index bac94f48..7206d982 100644 --- a/wayland.c +++ b/wayland.c @@ -158,11 +158,26 @@ static void key_bindings_destroy(key_binding_list_t *bindings) { tll_foreach(*bindings, it) { - tll_free(it->item.key_codes); + struct key_binding *bind = &it->item; + switch (bind->type) { + case KEY_BINDING: tll_free(it->item.k.key_codes); break; + case MOUSE_BINDING: break; + } + tll_remove(*bindings, it); } } +void +wayl_bindings_reset(struct seat *seat) +{ + + key_bindings_destroy(&seat->kbd.bindings.key); + key_bindings_destroy(&seat->kbd.bindings.search); + key_bindings_destroy(&seat->kbd.bindings.url); + key_bindings_destroy(&seat->mouse.bindings); +} + static void seat_destroy(struct seat *seat) { @@ -170,12 +185,7 @@ seat_destroy(struct seat *seat) return; tll_free(seat->mouse.buttons); - - 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); + wayl_bindings_reset(seat); if (seat->kbd.xkb_compose_state != NULL) xkb_compose_state_unref(seat->kbd.xkb_compose_state); diff --git a/wayland.h b/wayland.h index c3e6bb6d..81109673 100644 --- a/wayland.h +++ b/wayland.h @@ -23,6 +23,7 @@ #include #include +#include "config.h" #include "fdm.h" /* Forward declarations */ @@ -100,24 +101,28 @@ enum bind_action_url { 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; + enum key_binding_type type; int action; /* enum bind_action_* */ - char **pipe_argv; + xkb_mod_mask_t mods; + + union { + struct { + xkb_keysym_t sym; + xkb_keycode_list_t key_codes; + } k; + + struct { + uint32_t button; + int count; + } m; + }; + + const struct binding_aux *aux; + }; 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 { DATA_OFFER_MIME_UNSET, @@ -253,7 +258,7 @@ struct seat { double aggregated[2]; bool have_discrete; - mouse_binding_list_t bindings; + key_binding_list_t bindings; } mouse; /* Clipboard */ @@ -510,3 +515,5 @@ bool wayl_win_subsurface_new_with_custom_parent( struct wl_window *win, struct wl_surface *parent, struct wl_surf_subsurf *surf); void wayl_win_subsurface_destroy(struct wl_surf_subsurf *surf); + +void wayl_bindings_reset(struct seat *seat);