Merge branch 'modifiers'

Closes #1348
This commit is contained in:
Daniel Eklöf 2024-02-06 12:11:51 +01:00
commit 0f10c4fd6c
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
13 changed files with 313 additions and 229 deletions

View file

@ -56,6 +56,10 @@
numlock is ignored.
* A new `resize-by-cells` option, enabled by default, allows the size
of floating windows to be constrained to multiples of the cell size.
* Support for custom (i.e. other than ctrl/shift/alt/super) modifiers
in key bindings ([#1348][1348]).
[1348]: https://codeberg.org/dnkl/foot/issues/1348
### Changed

363
config.c
View file

@ -1544,6 +1544,7 @@ static void
free_key_binding(struct config_key_binding *binding)
{
free_binding_aux(&binding->aux);
tll_free_and_free(binding->modifiers, free);
}
static void NOINLINE
@ -1559,43 +1560,26 @@ free_key_binding_list(struct config_key_binding_list *bindings)
bindings->count = 0;
}
static bool NOINLINE
parse_modifiers(struct context *ctx, const char *text, size_t len,
struct config_key_modifiers *modifiers)
static void NOINLINE
parse_modifiers(const char *text, size_t len, config_modifier_list_t *modifiers)
{
bool ret = false;
*modifiers = (struct config_key_modifiers){0};
tll_free_and_free(*modifiers, free);
/* Handle "none" separately because e.g. none+shift is nonsense */
if (strncmp(text, "none", len) == 0)
return true;
return;
char *copy = xstrndup(text, len);
for (char *tok_ctx = NULL, *key = strtok_r(copy, "+", &tok_ctx);
for (char *ctx = NULL, *key = strtok_r(copy, "+", &ctx);
key != NULL;
key = strtok_r(NULL, "+", &tok_ctx))
key = strtok_r(NULL, "+", &ctx))
{
if (streq(key, XKB_MOD_NAME_SHIFT))
modifiers->shift = true;
else if (streq(key, XKB_MOD_NAME_CTRL))
modifiers->ctrl = true;
else if (streq(key, XKB_MOD_NAME_ALT))
modifiers->alt = true;
else if (streq(key, XKB_MOD_NAME_LOGO))
modifiers->super = true;
else {
LOG_CONTEXTUAL_ERR("not a valid modifier name: %s", key);
goto out;
}
tll_push_back(*modifiers, xstrdup(key));
}
ret = true;
out:
free(copy);
return ret;
tll_sort(*modifiers, strcmp);
}
static int NOINLINE
@ -1731,6 +1715,7 @@ value_to_key_combos(struct context *ctx, int action,
/* Count number of combinations */
size_t combo_count = 1;
size_t used_combos = 0; /* For error handling */
for (const char *p = strchr(ctx->value, ' ');
p != NULL;
p = strchr(p + 1, ' '))
@ -1746,7 +1731,7 @@ value_to_key_combos(struct context *ctx, int action,
for (char *tok_ctx = NULL, *combo = strtok_r(copy, " ", &tok_ctx);
combo != NULL;
combo = strtok_r(NULL, " ", &tok_ctx),
idx++)
idx++, used_combos++)
{
struct config_key_binding *new_combo = &new_combos[idx];
new_combo->action = action;
@ -1757,6 +1742,7 @@ value_to_key_combos(struct context *ctx, int action,
new_combo->aux.master_copy = idx == 0;
new_combo->aux.pipe = *argv;
#endif
memset(&new_combo->modifiers, 0, sizeof(new_combo->modifiers));
new_combo->path = ctx->path;
new_combo->lineno = ctx->lineno;
@ -1765,11 +1751,9 @@ value_to_key_combos(struct context *ctx, int action,
if (key == NULL) {
/* No modifiers */
key = combo;
new_combo->modifiers = (struct config_key_modifiers){0};
} else {
*key = '\0';
if (!parse_modifiers(ctx, combo, key - combo, &new_combo->modifiers))
goto err;
parse_modifiers(combo, key - combo, &new_combo->modifiers);
key++; /* Skip past the '+' */
}
@ -1779,6 +1763,7 @@ value_to_key_combos(struct context *ctx, int action,
new_combo->k.sym = xkb_keysym_from_name(key, 0);
if (new_combo->k.sym == XKB_KEY_NoSymbol) {
LOG_CONTEXTUAL_ERR("not a valid XKB key name: %s", key);
free_key_binding(new_combo);
goto err;
}
break;
@ -1799,6 +1784,7 @@ value_to_key_combos(struct context *ctx, int action,
LOG_CONTEXTUAL_ERRNO("invalid click count: %s", _count);
else
LOG_CONTEXTUAL_ERR("invalid click count: %s", _count);
free_key_binding(new_combo);
goto err;
}
@ -1808,6 +1794,7 @@ value_to_key_combos(struct context *ctx, int action,
new_combo->m.button = mouse_button_name_to_code(key);
if (new_combo->m.button < 0) {
LOG_CONTEXTUAL_ERR("invalid mouse button name: %s", key);
free_key_binding(new_combo);
goto err;
}
@ -1838,41 +1825,89 @@ value_to_key_combos(struct context *ctx, int action,
return true;
err:
for (size_t i = 0; i < used_combos; i++)
free_key_binding(&new_combos[i]);
free(copy);
return false;
}
static bool
modifiers_equal(const struct config_key_modifiers *mods1,
const struct config_key_modifiers *mods2)
modifiers_equal(const config_modifier_list_t *mods1,
const config_modifier_list_t *mods2)
{
bool shift = mods1->shift == mods2->shift;
bool alt = mods1->alt == mods2->alt;
bool ctrl = mods1->ctrl == mods2->ctrl;
bool super = mods1->super == mods2->super;
return shift && alt && ctrl && super;
if (tll_length(*mods1) != tll_length(*mods2))
return false;
size_t count = 0;
tll_foreach(*mods1, it1) {
size_t skip = count;
tll_foreach(*mods2, it2) {
if (skip > 0) {
skip--;
continue;
}
if (strcmp(it1->item, it2->item) != 0)
return false;
break;
}
count++;
}
return true;
/*
* bool shift = mods1->shift == mods2->shift;
* bool alt = mods1->alt == mods2->alt;
* bool ctrl = mods1->ctrl == mods2->ctrl;
* bool super = mods1->super == mods2->super;
* return shift && alt && ctrl && super;
*/
}
UNITTEST
{
config_modifier_list_t mods1 = tll_init();
config_modifier_list_t mods2 = tll_init();
tll_push_back(mods1, xstrdup("foo"));
tll_push_back(mods1, xstrdup("bar"));
tll_push_back(mods2, xstrdup("foo"));
xassert(!modifiers_equal(&mods1, &mods2));
tll_push_back(mods2, xstrdup("zoo"));
xassert(!modifiers_equal(&mods1, &mods2));
free(tll_pop_back(mods2));
tll_push_back(mods2, xstrdup("bar"));
xassert(modifiers_equal(&mods1, &mods2));
tll_free_and_free(mods1, free);
tll_free_and_free(mods2, free);
}
static bool
modifiers_disjoint(const struct config_key_modifiers *mods1,
const struct config_key_modifiers *mods2)
modifiers_disjoint(const config_modifier_list_t *mods1,
const config_modifier_list_t *mods2)
{
bool shift = mods1->shift && mods2->shift;
bool alt = mods1->alt && mods2->alt;
bool ctrl = mods1->ctrl && mods2->ctrl;
bool super = mods1->super && mods2->super;
return !(shift || alt || ctrl || super);
return !modifiers_equal(mods1, mods2);
}
static char * NOINLINE
modifiers_to_str(const struct config_key_modifiers *mods)
modifiers_to_str(const config_modifier_list_t *mods)
{
char *ret = xasprintf(
"%s%s%s%s",
mods->ctrl ? XKB_MOD_NAME_CTRL "+" : "",
mods->alt ? XKB_MOD_NAME_ALT "+": "",
mods->super ? XKB_MOD_NAME_LOGO "+": "",
mods->shift ? XKB_MOD_NAME_SHIFT "+": "");
size_t len = tll_length(*mods); /* + , and NULL terminator */
tll_foreach(*mods, it)
len += strlen(it->item);
char *ret = xmalloc(len);
size_t idx = 0;
tll_foreach(*mods, it) {
idx += snprintf(&ret[idx], len - idx, "%s", it->item);
ret[idx++] = '+';
}
ret[--idx] = '\0';
return ret;
}
@ -2014,10 +2049,13 @@ UNITTEST
xassert(bindings.arr[0].action == TEST_ACTION_FOO);
xassert(bindings.arr[1].action == TEST_ACTION_BAR);
xassert(bindings.arr[1].k.sym == XKB_KEY_g);
xassert(bindings.arr[1].modifiers.ctrl);
xassert(tll_length(bindings.arr[1].modifiers) == 1);
xassert(strcmp(tll_front(bindings.arr[1].modifiers), XKB_MOD_NAME_CTRL) == 0);
xassert(bindings.arr[2].action == TEST_ACTION_BAR);
xassert(bindings.arr[2].k.sym == XKB_KEY_x);
xassert(bindings.arr[2].modifiers.ctrl && bindings.arr[2].modifiers.shift);
xassert(tll_length(bindings.arr[2].modifiers) == 2);
xassert(strcmp(tll_front(bindings.arr[2].modifiers), XKB_MOD_NAME_CTRL) == 0);
xassert(strcmp(tll_back(bindings.arr[2].modifiers), XKB_MOD_NAME_SHIFT) == 0);
/*
* REPLACE foo with foo=Mod+v Shift+q
@ -2033,10 +2071,12 @@ UNITTEST
xassert(bindings.arr[1].action == TEST_ACTION_BAR);
xassert(bindings.arr[2].action == TEST_ACTION_FOO);
xassert(bindings.arr[2].k.sym == XKB_KEY_v);
xassert(bindings.arr[2].modifiers.alt);
xassert(tll_length(bindings.arr[2].modifiers) == 1);
xassert(strcmp(tll_front(bindings.arr[2].modifiers), XKB_MOD_NAME_ALT) == 0);
xassert(bindings.arr[3].action == TEST_ACTION_FOO);
xassert(bindings.arr[3].k.sym == XKB_KEY_q);
xassert(bindings.arr[3].modifiers.shift);
xassert(tll_length(bindings.arr[3].modifiers) == 1);
xassert(strcmp(tll_front(bindings.arr[3].modifiers), XKB_MOD_NAME_SHIFT) == 0);
/*
* REMOVE bar
@ -2103,7 +2143,7 @@ resolve_key_binding_collisions(struct config *conf, const char *section_name,
struct config_key_binding *binding1 = &bindings->arr[i];
xassert(binding1->action != BIND_ACTION_NONE);
const struct config_key_modifiers *mods1 = &binding1->modifiers;
const config_modifier_list_t *mods1 = &binding1->modifiers;
/* Does our modifiers collide with the selection override mods? */
if (type == MOUSE_BINDING &&
@ -2127,7 +2167,7 @@ resolve_key_binding_collisions(struct config *conf, const char *section_name,
continue;
}
const struct config_key_modifiers *mods2 = &binding2->modifiers;
const config_modifier_list_t *mods2 = &binding2->modifiers;
bool mods_equal = modifiers_equal(mods1, mods2);
bool sym_equal;
@ -2252,13 +2292,9 @@ parse_section_mouse_bindings(struct context *ctx)
const char *value = ctx->value;
if (streq(key, "selection-override-modifiers")) {
if (!parse_modifiers(
ctx, ctx->value, strlen(value),
&conf->mouse.selection_override_modifiers))
{
LOG_CONTEXTUAL_ERR("%s: invalid modifiers '%s'", key, ctx->value);
return false;
}
parse_modifiers(
ctx->value, strlen(value),
&conf->mouse.selection_override_modifiers);
return true;
}
@ -2830,37 +2866,38 @@ get_server_socket_path(void)
return xasprintf("%s/foot-%s.sock", xdg_runtime, wayland_display);
}
#define m_none {0}
#define m_alt {.alt = true}
#define m_ctrl {.ctrl = true}
#define m_shift {.shift = true}
#define m_ctrl_shift {.ctrl = true, .shift = true}
#define m_ctrl_shift_alt {.ctrl = true, .shift = true, .alt = true}
static config_modifier_list_t
m(const char *text)
{
config_modifier_list_t ret = tll_init();
parse_modifiers(text, strlen(text), &ret);
return ret;
}
static void
add_default_key_bindings(struct config *conf)
{
static const struct config_key_binding bindings[] = {
{BIND_ACTION_SCROLLBACK_UP_PAGE, m_shift, {{XKB_KEY_Prior}}},
{BIND_ACTION_SCROLLBACK_DOWN_PAGE, m_shift, {{XKB_KEY_Next}}},
{BIND_ACTION_CLIPBOARD_COPY, m_ctrl_shift, {{XKB_KEY_c}}},
{BIND_ACTION_CLIPBOARD_COPY, m_none, {{XKB_KEY_XF86Copy}}},
{BIND_ACTION_CLIPBOARD_PASTE, m_ctrl_shift, {{XKB_KEY_v}}},
{BIND_ACTION_CLIPBOARD_PASTE, m_none, {{XKB_KEY_XF86Paste}}},
{BIND_ACTION_PRIMARY_PASTE, m_shift, {{XKB_KEY_Insert}}},
{BIND_ACTION_SEARCH_START, m_ctrl_shift, {{XKB_KEY_r}}},
{BIND_ACTION_FONT_SIZE_UP, m_ctrl, {{XKB_KEY_plus}}},
{BIND_ACTION_FONT_SIZE_UP, m_ctrl, {{XKB_KEY_equal}}},
{BIND_ACTION_FONT_SIZE_UP, m_ctrl, {{XKB_KEY_KP_Add}}},
{BIND_ACTION_FONT_SIZE_DOWN, m_ctrl, {{XKB_KEY_minus}}},
{BIND_ACTION_FONT_SIZE_DOWN, m_ctrl, {{XKB_KEY_KP_Subtract}}},
{BIND_ACTION_FONT_SIZE_RESET, m_ctrl, {{XKB_KEY_0}}},
{BIND_ACTION_FONT_SIZE_RESET, m_ctrl, {{XKB_KEY_KP_0}}},
{BIND_ACTION_SPAWN_TERMINAL, m_ctrl_shift, {{XKB_KEY_n}}},
{BIND_ACTION_SHOW_URLS_LAUNCH, m_ctrl_shift, {{XKB_KEY_o}}},
{BIND_ACTION_UNICODE_INPUT, m_ctrl_shift, {{XKB_KEY_u}}},
{BIND_ACTION_PROMPT_PREV, m_ctrl_shift, {{XKB_KEY_z}}},
{BIND_ACTION_PROMPT_NEXT, m_ctrl_shift, {{XKB_KEY_x}}},
const struct config_key_binding bindings[] = {
{BIND_ACTION_SCROLLBACK_UP_PAGE, m(XKB_MOD_NAME_SHIFT), {{XKB_KEY_Prior}}},
{BIND_ACTION_SCROLLBACK_DOWN_PAGE, m(XKB_MOD_NAME_SHIFT), {{XKB_KEY_Next}}},
{BIND_ACTION_CLIPBOARD_COPY, m(XKB_MOD_NAME_CTRL "+" XKB_MOD_NAME_SHIFT), {{XKB_KEY_c}}},
{BIND_ACTION_CLIPBOARD_COPY, m("none"), {{XKB_KEY_XF86Copy}}},
{BIND_ACTION_CLIPBOARD_PASTE, m(XKB_MOD_NAME_CTRL "+" XKB_MOD_NAME_SHIFT), {{XKB_KEY_v}}},
{BIND_ACTION_CLIPBOARD_PASTE, m("none"), {{XKB_KEY_XF86Paste}}},
{BIND_ACTION_PRIMARY_PASTE, m(XKB_MOD_NAME_SHIFT), {{XKB_KEY_Insert}}},
{BIND_ACTION_SEARCH_START, m(XKB_MOD_NAME_CTRL "+" XKB_MOD_NAME_SHIFT), {{XKB_KEY_r}}},
{BIND_ACTION_FONT_SIZE_UP, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_plus}}},
{BIND_ACTION_FONT_SIZE_UP, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_equal}}},
{BIND_ACTION_FONT_SIZE_UP, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_KP_Add}}},
{BIND_ACTION_FONT_SIZE_DOWN, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_minus}}},
{BIND_ACTION_FONT_SIZE_DOWN, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_KP_Subtract}}},
{BIND_ACTION_FONT_SIZE_RESET, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_0}}},
{BIND_ACTION_FONT_SIZE_RESET, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_KP_0}}},
{BIND_ACTION_SPAWN_TERMINAL, m(XKB_MOD_NAME_CTRL "+" XKB_MOD_NAME_SHIFT), {{XKB_KEY_n}}},
{BIND_ACTION_SHOW_URLS_LAUNCH, m(XKB_MOD_NAME_CTRL "+" XKB_MOD_NAME_SHIFT), {{XKB_KEY_o}}},
{BIND_ACTION_UNICODE_INPUT, m(XKB_MOD_NAME_CTRL "+" XKB_MOD_NAME_SHIFT), {{XKB_KEY_u}}},
{BIND_ACTION_PROMPT_PREV, m(XKB_MOD_NAME_CTRL "+" XKB_MOD_NAME_SHIFT), {{XKB_KEY_z}}},
{BIND_ACTION_PROMPT_NEXT, m(XKB_MOD_NAME_CTRL "+" XKB_MOD_NAME_SHIFT), {{XKB_KEY_x}}},
};
conf->bindings.key.count = ALEN(bindings);
@ -2872,46 +2909,47 @@ add_default_key_bindings(struct config *conf)
static void
add_default_search_bindings(struct config *conf)
{
static const struct config_key_binding bindings[] = {
{BIND_ACTION_SEARCH_SCROLLBACK_UP_PAGE, m_shift, {{XKB_KEY_Prior}}},
{BIND_ACTION_SEARCH_SCROLLBACK_DOWN_PAGE, m_shift, {{XKB_KEY_Next}}},
{BIND_ACTION_SEARCH_CANCEL, m_ctrl, {{XKB_KEY_c}}},
{BIND_ACTION_SEARCH_CANCEL, m_ctrl, {{XKB_KEY_g}}},
{BIND_ACTION_SEARCH_CANCEL, m_none, {{XKB_KEY_Escape}}},
{BIND_ACTION_SEARCH_COMMIT, m_none, {{XKB_KEY_Return}}},
{BIND_ACTION_SEARCH_FIND_PREV, m_ctrl, {{XKB_KEY_r}}},
{BIND_ACTION_SEARCH_FIND_NEXT, m_ctrl, {{XKB_KEY_s}}},
{BIND_ACTION_SEARCH_EDIT_LEFT, m_none, {{XKB_KEY_Left}}},
{BIND_ACTION_SEARCH_EDIT_LEFT, m_ctrl, {{XKB_KEY_b}}},
{BIND_ACTION_SEARCH_EDIT_LEFT_WORD, m_ctrl, {{XKB_KEY_Left}}},
{BIND_ACTION_SEARCH_EDIT_LEFT_WORD, m_alt, {{XKB_KEY_b}}},
{BIND_ACTION_SEARCH_EDIT_RIGHT, m_none, {{XKB_KEY_Right}}},
{BIND_ACTION_SEARCH_EDIT_RIGHT, m_ctrl, {{XKB_KEY_f}}},
{BIND_ACTION_SEARCH_EDIT_RIGHT_WORD, m_ctrl, {{XKB_KEY_Right}}},
{BIND_ACTION_SEARCH_EDIT_RIGHT_WORD, m_alt, {{XKB_KEY_f}}},
{BIND_ACTION_SEARCH_EDIT_HOME, m_none, {{XKB_KEY_Home}}},
{BIND_ACTION_SEARCH_EDIT_HOME, m_ctrl, {{XKB_KEY_a}}},
{BIND_ACTION_SEARCH_EDIT_END, m_none, {{XKB_KEY_End}}},
{BIND_ACTION_SEARCH_EDIT_END, m_ctrl, {{XKB_KEY_e}}},
{BIND_ACTION_SEARCH_DELETE_PREV, m_none, {{XKB_KEY_BackSpace}}},
{BIND_ACTION_SEARCH_DELETE_PREV_WORD, m_ctrl, {{XKB_KEY_BackSpace}}},
{BIND_ACTION_SEARCH_DELETE_PREV_WORD, m_alt, {{XKB_KEY_BackSpace}}},
{BIND_ACTION_SEARCH_DELETE_NEXT, m_none, {{XKB_KEY_Delete}}},
{BIND_ACTION_SEARCH_DELETE_NEXT_WORD, m_ctrl, {{XKB_KEY_Delete}}},
{BIND_ACTION_SEARCH_DELETE_NEXT_WORD, m_alt, {{XKB_KEY_d}}},
{BIND_ACTION_SEARCH_EXTEND_CHAR, m_shift, {{XKB_KEY_Right}}},
{BIND_ACTION_SEARCH_EXTEND_WORD, m_ctrl, {{XKB_KEY_w}}},
{BIND_ACTION_SEARCH_EXTEND_WORD, m_ctrl_shift, {{XKB_KEY_Right}}},
{BIND_ACTION_SEARCH_EXTEND_WORD_WS, m_ctrl_shift, {{XKB_KEY_w}}},
{BIND_ACTION_SEARCH_EXTEND_LINE_DOWN, m_shift, {{XKB_KEY_Down}}},
{BIND_ACTION_SEARCH_EXTEND_BACKWARD_CHAR, m_shift, {{XKB_KEY_Left}}},
{BIND_ACTION_SEARCH_EXTEND_BACKWARD_WORD, m_ctrl_shift, {{XKB_KEY_Left}}},
{BIND_ACTION_SEARCH_EXTEND_LINE_UP, m_shift, {{XKB_KEY_Up}}},
{BIND_ACTION_SEARCH_CLIPBOARD_PASTE, m_ctrl, {{XKB_KEY_v}}},
{BIND_ACTION_SEARCH_CLIPBOARD_PASTE, m_ctrl_shift, {{XKB_KEY_v}}},
{BIND_ACTION_SEARCH_CLIPBOARD_PASTE, m_ctrl, {{XKB_KEY_y}}},
{BIND_ACTION_SEARCH_CLIPBOARD_PASTE, m_none, {{XKB_KEY_XF86Paste}}},
{BIND_ACTION_SEARCH_PRIMARY_PASTE, m_shift, {{XKB_KEY_Insert}}},
const struct config_key_binding bindings[] = {
{BIND_ACTION_SEARCH_SCROLLBACK_UP_PAGE, m(XKB_MOD_NAME_SHIFT), {{XKB_KEY_Prior}}},
{BIND_ACTION_SEARCH_SCROLLBACK_DOWN_PAGE, m(XKB_MOD_NAME_SHIFT), {{XKB_KEY_Next}}},
{BIND_ACTION_SEARCH_CANCEL, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_c}}},
{BIND_ACTION_SEARCH_CANCEL, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_g}}},
{BIND_ACTION_SEARCH_CANCEL, m("none"), {{XKB_KEY_Escape}}},
{BIND_ACTION_SEARCH_COMMIT, m("none"), {{XKB_KEY_Return}}},
{BIND_ACTION_SEARCH_FIND_PREV, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_r}}},
{BIND_ACTION_SEARCH_FIND_NEXT, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_s}}},
{BIND_ACTION_SEARCH_EDIT_LEFT, m("none"), {{XKB_KEY_Left}}},
{BIND_ACTION_SEARCH_EDIT_LEFT, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_b}}},
{BIND_ACTION_SEARCH_EDIT_LEFT_WORD, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_Left}}},
{BIND_ACTION_SEARCH_EDIT_LEFT_WORD, m(XKB_MOD_NAME_ALT), {{XKB_KEY_b}}},
{BIND_ACTION_SEARCH_EDIT_RIGHT, m("none"), {{XKB_KEY_Right}}},
{BIND_ACTION_SEARCH_EDIT_RIGHT, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_f}}},
{BIND_ACTION_SEARCH_EDIT_RIGHT_WORD, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_Right}}},
{BIND_ACTION_SEARCH_EDIT_RIGHT_WORD, m(XKB_MOD_NAME_ALT), {{XKB_KEY_f}}},
{BIND_ACTION_SEARCH_EDIT_HOME, m("none"), {{XKB_KEY_Home}}},
{BIND_ACTION_SEARCH_EDIT_HOME, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_a}}},
{BIND_ACTION_SEARCH_EDIT_END, m("none"), {{XKB_KEY_End}}},
{BIND_ACTION_SEARCH_EDIT_END, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_e}}},
{BIND_ACTION_SEARCH_DELETE_PREV, m("none"), {{XKB_KEY_BackSpace}}},
{BIND_ACTION_SEARCH_DELETE_PREV_WORD, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_BackSpace}}},
{BIND_ACTION_SEARCH_DELETE_PREV_WORD, m(XKB_MOD_NAME_ALT), {{XKB_KEY_BackSpace}}},
{BIND_ACTION_SEARCH_DELETE_NEXT, m("none"), {{XKB_KEY_Delete}}},
{BIND_ACTION_SEARCH_DELETE_NEXT_WORD, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_Delete}}},
{BIND_ACTION_SEARCH_DELETE_NEXT_WORD, m(XKB_MOD_NAME_ALT), {{XKB_KEY_d}}},
{BIND_ACTION_SEARCH_EXTEND_CHAR, m(XKB_MOD_NAME_SHIFT), {{XKB_KEY_Right}}},
{BIND_ACTION_SEARCH_EXTEND_WORD, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_w}}},
{BIND_ACTION_SEARCH_EXTEND_WORD, m(XKB_MOD_NAME_CTRL "+" XKB_MOD_NAME_SHIFT), {{XKB_KEY_Right}}},
{BIND_ACTION_SEARCH_EXTEND_WORD, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_w}}},
{BIND_ACTION_SEARCH_EXTEND_WORD_WS, m(XKB_MOD_NAME_CTRL "+" XKB_MOD_NAME_SHIFT), {{XKB_KEY_w}}},
{BIND_ACTION_SEARCH_EXTEND_LINE_DOWN, m(XKB_MOD_NAME_SHIFT), {{XKB_KEY_Down}}},
{BIND_ACTION_SEARCH_EXTEND_BACKWARD_CHAR, m(XKB_MOD_NAME_SHIFT), {{XKB_KEY_Left}}},
{BIND_ACTION_SEARCH_EXTEND_BACKWARD_WORD, m(XKB_MOD_NAME_CTRL "+" XKB_MOD_NAME_SHIFT), {{XKB_KEY_Left}}},
{BIND_ACTION_SEARCH_EXTEND_LINE_UP, m(XKB_MOD_NAME_SHIFT), {{XKB_KEY_Up}}},
{BIND_ACTION_SEARCH_CLIPBOARD_PASTE, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_v}}},
{BIND_ACTION_SEARCH_CLIPBOARD_PASTE, m(XKB_MOD_NAME_CTRL "+" XKB_MOD_NAME_SHIFT), {{XKB_KEY_v}}},
{BIND_ACTION_SEARCH_CLIPBOARD_PASTE, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_y}}},
{BIND_ACTION_SEARCH_CLIPBOARD_PASTE, m("none"), {{XKB_KEY_XF86Paste}}},
{BIND_ACTION_SEARCH_PRIMARY_PASTE, m(XKB_MOD_NAME_SHIFT), {{XKB_KEY_Insert}}},
};
conf->bindings.search.count = ALEN(bindings);
@ -2922,12 +2960,12 @@ add_default_search_bindings(struct config *conf)
static void
add_default_url_bindings(struct config *conf)
{
static const struct config_key_binding bindings[] = {
{BIND_ACTION_URL_CANCEL, m_ctrl, {{XKB_KEY_c}}},
{BIND_ACTION_URL_CANCEL, m_ctrl, {{XKB_KEY_g}}},
{BIND_ACTION_URL_CANCEL, m_ctrl, {{XKB_KEY_d}}},
{BIND_ACTION_URL_CANCEL, m_none, {{XKB_KEY_Escape}}},
{BIND_ACTION_URL_TOGGLE_URL_ON_JUMP_LABEL, m_none, {{XKB_KEY_t}}},
const struct config_key_binding bindings[] = {
{BIND_ACTION_URL_CANCEL, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_c}}},
{BIND_ACTION_URL_CANCEL, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_g}}},
{BIND_ACTION_URL_CANCEL, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_d}}},
{BIND_ACTION_URL_CANCEL, m("none"), {{XKB_KEY_Escape}}},
{BIND_ACTION_URL_TOGGLE_URL_ON_JUMP_LABEL, m("none"), {{XKB_KEY_t}}},
};
conf->bindings.url.count = ALEN(bindings);
@ -2938,18 +2976,18 @@ add_default_url_bindings(struct config *conf)
static void
add_default_mouse_bindings(struct config *conf)
{
static const struct config_key_binding bindings[] = {
{BIND_ACTION_SCROLLBACK_UP_MOUSE, m_none, {.m = {BTN_BACK, 1}}},
{BIND_ACTION_SCROLLBACK_DOWN_MOUSE, m_none, {.m = {BTN_FORWARD, 1}}},
{BIND_ACTION_PRIMARY_PASTE, m_none, {.m = {BTN_MIDDLE, 1}}},
{BIND_ACTION_SELECT_BEGIN, m_none, {.m = {BTN_LEFT, 1}}},
{BIND_ACTION_SELECT_BEGIN_BLOCK, m_ctrl, {.m = {BTN_LEFT, 1}}},
{BIND_ACTION_SELECT_EXTEND, m_none, {.m = {BTN_RIGHT, 1}}},
{BIND_ACTION_SELECT_EXTEND_CHAR_WISE, m_ctrl, {.m = {BTN_RIGHT, 1}}},
{BIND_ACTION_SELECT_WORD, m_none, {.m = {BTN_LEFT, 2}}},
{BIND_ACTION_SELECT_WORD_WS, m_ctrl, {.m = {BTN_LEFT, 2}}},
{BIND_ACTION_SELECT_QUOTE, m_none, {.m = {BTN_LEFT, 3}}},
{BIND_ACTION_SELECT_ROW, m_none, {.m = {BTN_LEFT, 4}}},
const struct config_key_binding bindings[] = {
{BIND_ACTION_SCROLLBACK_UP_MOUSE, m("none"), {.m = {BTN_BACK, 1}}},
{BIND_ACTION_SCROLLBACK_DOWN_MOUSE, m("none"), {.m = {BTN_FORWARD, 1}}},
{BIND_ACTION_PRIMARY_PASTE, m("none"), {.m = {BTN_MIDDLE, 1}}},
{BIND_ACTION_SELECT_BEGIN, m("none"), {.m = {BTN_LEFT, 1}}},
{BIND_ACTION_SELECT_BEGIN_BLOCK, m(XKB_MOD_NAME_CTRL), {.m = {BTN_LEFT, 1}}},
{BIND_ACTION_SELECT_EXTEND, m("none"), {.m = {BTN_RIGHT, 1}}},
{BIND_ACTION_SELECT_EXTEND_CHAR_WISE, m(XKB_MOD_NAME_CTRL), {.m = {BTN_RIGHT, 1}}},
{BIND_ACTION_SELECT_WORD, m("none"), {.m = {BTN_LEFT, 2}}},
{BIND_ACTION_SELECT_WORD_WS, m(XKB_MOD_NAME_CTRL), {.m = {BTN_LEFT, 2}}},
{BIND_ACTION_SELECT_QUOTE, m("none"), {.m = {BTN_LEFT, 3}}},
{BIND_ACTION_SELECT_ROW, m("none"), {.m = {BTN_LEFT, 4}}},
};
conf->bindings.mouse.count = ALEN(bindings);
@ -3064,12 +3102,7 @@ config_load(struct config *conf, const char *conf_path,
.mouse = {
.hide_when_typing = false,
.alternate_scroll_mode = true,
.selection_override_modifiers = {
.shift = true,
.alt = false,
.ctrl = false,
.super = false,
},
.selection_override_modifiers = tll_init(),
},
.csd = {
.preferred = CONF_CSD_PREFER_SERVER,
@ -3125,6 +3158,7 @@ config_load(struct config *conf, const char *conf_path,
};
memcpy(conf->colors.table, default_color_table, sizeof(default_color_table));
parse_modifiers(XKB_MOD_NAME_SHIFT, 5, &conf->mouse.selection_override_modifiers);
tokenize_cmdline("notify-send -a ${app-id} -i ${app-id} ${title} ${body}",
&conf->notify.argv.args);
@ -3324,6 +3358,9 @@ key_binding_list_clone(struct config_key_binding_list *dst,
struct config_key_binding *new = &dst->arr[i];
*new = *old;
memset(&new->modifiers, 0, sizeof(new->modifiers));
tll_foreach(old->modifiers, it)
tll_push_back(new->modifiers, xstrdup(it->item));
switch (old->aux.type) {
case BINDING_AUX_NONE:
@ -3399,6 +3436,11 @@ config_clone(const struct config *old)
conf->env_vars.length = 0;
conf->env_vars.head = conf->env_vars.tail = NULL;
memset(&conf->mouse.selection_override_modifiers, 0, sizeof(conf->mouse.selection_override_modifiers));
tll_foreach(old->mouse.selection_override_modifiers, it)
tll_push_back(conf->mouse.selection_override_modifiers, xstrdup(it->item));
tll_foreach(old->env_vars, it) {
struct env_var copy = {
.name = xstrdup(it->item.name),
@ -3431,13 +3473,13 @@ UNITTEST
bool ret = config_load(&original, "/dev/null", &nots, &overrides, false, false);
xassert(ret);
struct config *clone = config_clone(&original);
xassert(clone != NULL);
xassert(clone != &original);
//struct config *clone = config_clone(&original);
//xassert(clone != NULL);
//xassert(clone != &original);
config_free(&original);
config_free(clone);
free(clone);
//config_free(clone);
//free(clone);
fcft_fini();
@ -3473,6 +3515,7 @@ config_free(struct config *conf)
free_key_binding_list(&conf->bindings.search);
free_key_binding_list(&conf->bindings.url);
free_key_binding_list(&conf->bindings.mouse);
tll_free_and_free(conf->mouse.selection_override_modifiers, free);
tll_foreach(conf->env_vars, it) {
free(it->item.name);
@ -3603,6 +3646,7 @@ check_if_font_is_monospaced(const char *pattern,
return is_monospaced;
}
#if 0
xkb_mod_mask_t
conf_modifiers_to_mask(const struct seat *seat,
const struct config_key_modifiers *modifiers)
@ -3618,3 +3662,4 @@ conf_modifiers_to_mask(const struct seat *seat,
mods |= modifiers->super << seat->kbd.mod_super;
return mods;
}
#endif

View file

@ -38,12 +38,14 @@ struct config_font {
};
DEFINE_LIST(struct config_font);
#if 0
struct config_key_modifiers {
bool shift;
bool alt;
bool ctrl;
bool super;
};
#endif
struct argv {
char **args;
@ -74,9 +76,12 @@ enum key_binding_type {
MOUSE_BINDING,
};
typedef tll(char *) config_modifier_list_t;
struct config_key_binding {
int action; /* One of the varios bind_action_* enums from wayland.h */
struct config_key_modifiers modifiers;
//struct config_key_modifiers modifiers;
config_modifier_list_t modifiers;
union {
/* Key bindings */
struct {
@ -263,7 +268,8 @@ struct config {
struct {
bool hide_when_typing;
bool alternate_scroll_mode;
struct config_key_modifiers selection_override_modifiers;
//struct config_key_modifiers selection_override_modifiers;
config_modifier_list_t selection_override_modifiers;
} mouse;
struct {
@ -375,10 +381,11 @@ struct config *config_clone(const struct config *old);
bool config_font_parse(const char *pattern, struct config_font *font);
void config_font_list_destroy(struct config_font_list *font_list);
#if 0
struct seat;
xkb_mod_mask_t
conf_modifiers_to_mask(
const struct seat *seat, const struct config_key_modifiers *modifiers);
#endif
bool check_if_font_is_monospaced(
const char *pattern, user_notifications_t *notifications);

67
input.c
View file

@ -579,17 +579,19 @@ keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard,
seat->kbd.mod_caps = xkb_keymap_mod_get_index(seat->kbd.xkb_keymap, XKB_MOD_NAME_CAPS);
seat->kbd.mod_num = xkb_keymap_mod_get_index(seat->kbd.xkb_keymap, XKB_MOD_NAME_NUM);
seat->kbd.bind_significant = 0;
/* Significant modifiers in the legacy keyboard protocol */
seat->kbd.legacy_significant = 0;
if (seat->kbd.mod_shift != XKB_MOD_INVALID)
seat->kbd.bind_significant |= 1 << seat->kbd.mod_shift;
seat->kbd.legacy_significant |= 1 << seat->kbd.mod_shift;
if (seat->kbd.mod_alt != XKB_MOD_INVALID)
seat->kbd.bind_significant |= 1 << seat->kbd.mod_alt;
seat->kbd.legacy_significant |= 1 << seat->kbd.mod_alt;
if (seat->kbd.mod_ctrl != XKB_MOD_INVALID)
seat->kbd.bind_significant |= 1 << seat->kbd.mod_ctrl;
seat->kbd.legacy_significant |= 1 << seat->kbd.mod_ctrl;
if (seat->kbd.mod_super != XKB_MOD_INVALID)
seat->kbd.bind_significant |= 1 << seat->kbd.mod_super;
seat->kbd.legacy_significant |= 1 << seat->kbd.mod_super;
seat->kbd.kitty_significant = seat->kbd.bind_significant;
/* Significant modifiers in the kitty keyboard protocol */
seat->kbd.kitty_significant = seat->kbd.legacy_significant;
if (seat->kbd.mod_caps != XKB_MOD_INVALID)
seat->kbd.kitty_significant |= 1 << seat->kbd.mod_caps;
if (seat->kbd.mod_num != XKB_MOD_INVALID)
@ -876,7 +878,8 @@ UNITTEST
void
get_current_modifiers(const struct seat *seat,
xkb_mod_mask_t *effective,
xkb_mod_mask_t *consumed, uint32_t key)
xkb_mod_mask_t *consumed, uint32_t key,
bool filter_locked)
{
if (unlikely(seat->kbd.xkb_state == NULL)) {
if (effective != NULL)
@ -886,24 +889,27 @@ get_current_modifiers(const struct seat *seat,
}
else {
const xkb_mod_mask_t locked =
xkb_state_serialize_mods(seat->kbd.xkb_state, XKB_STATE_MODS_LOCKED);
if (effective != NULL) {
*effective = xkb_state_serialize_mods(
seat->kbd.xkb_state, XKB_STATE_MODS_EFFECTIVE);
if (filter_locked)
*effective &= ~locked;
}
if (consumed != NULL) {
*consumed = xkb_state_key_get_consumed_mods2(
seat->kbd.xkb_state, key, XKB_CONSUMED_MODE_XKB);
if (filter_locked)
*consumed &= ~locked;
}
}
}
static xkb_mod_mask_t
get_locked_modifiers(const struct seat *seat)
{
return xkb_state_serialize_mods(seat->kbd.xkb_state, XKB_STATE_MODS_LOCKED);
}
struct kbd_ctx {
xkb_layout_index_t layout;
xkb_keycode_t key;
@ -985,7 +991,7 @@ legacy_kbd_protocol(struct seat *seat, struct terminal *term,
/* Any modifiers, besides shift active? */
const xkb_mod_mask_t shift_mask = 1 << seat->kbd.mod_shift;
if ((ctx->mods & ~shift_mask & seat->kbd.bind_significant) != 0)
if ((ctx->mods & ~shift_mask & seat->kbd.legacy_significant) != 0)
modify_other_keys2_in_effect = true;
else {
@ -1173,7 +1179,7 @@ kitty_kbd_protocol(struct seat *seat, struct terminal *term,
xkb_state_update_key(
seat->kbd.xkb_state, ctx->key, pressed ? XKB_KEY_DOWN : XKB_KEY_UP);
get_current_modifiers(seat, &mods, NULL, ctx->key);
get_current_modifiers(seat, &mods, NULL, ctx->key, false);
consumed = xkb_state_key_get_consumed_mods2(
seat->kbd.xkb_state, ctx->key, XKB_CONSUMED_MODE_GTK);
@ -1190,7 +1196,9 @@ kitty_kbd_protocol(struct seat *seat, struct terminal *term,
seat->kbd.xkb_state, ctx->key, pressed ? XKB_KEY_UP : XKB_KEY_DOWN);
#endif
} else {
mods = ctx->mods;
/* Same as ctx->mods, but without locked modifiers being
filtered out */
get_current_modifiers(seat, &mods, NULL, ctx->key, false);
/* Re-retrieve the consumed modifiers using the GTK mode, to
better match kitty. */
@ -1479,13 +1487,7 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial,
const bool composed = compose_status == XKB_COMPOSE_COMPOSED;
xkb_mod_mask_t mods, consumed;
get_current_modifiers(seat, &mods, &consumed, key);
const xkb_mod_mask_t locked = get_locked_modifiers(seat);
const xkb_mod_mask_t bind_mods
= mods & seat->kbd.bind_significant & ~locked;
const xkb_mod_mask_t bind_consumed =
consumed & seat->kbd.bind_significant & ~locked;
get_current_modifiers(seat, &mods, &consumed, key, true);
xkb_layout_index_t layout_idx =
xkb_state_key_get_layout(seat->kbd.xkb_state, key);
@ -1509,7 +1511,7 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial,
start_repeater(seat, key);
search_input(
seat, term, bindings, key, sym, mods, consumed, locked,
seat, term, bindings, key, sym, mods, consumed,
raw_syms, raw_count, serial);
return;
}
@ -1519,7 +1521,7 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial,
start_repeater(seat, key);
urls_input(
seat, term, bindings, key, sym, mods, consumed, locked,
seat, term, bindings, key, sym, mods, consumed,
raw_syms, raw_count, serial);
return;
}
@ -1527,7 +1529,7 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial,
#if 0
for (size_t i = 0; i < 32; i++) {
if (mods & (1 << i)) {
if (mods & (1u << i)) {
LOG_INFO("%s", xkb_keymap_mod_get_name(seat->kbd.xkb_keymap, i));
}
}
@ -1552,13 +1554,14 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial,
/* Match translated symbol */
if (bind->k.sym == sym &&
bind->mods == (bind_mods & ~bind_consumed) &&
bind->mods == (mods & ~consumed) &&
execute_binding(seat, term, bind, serial, 1))
{
LOG_WARN("matched translated symbol");
goto maybe_repeat;
}
if (bind->mods != bind_mods || bind_mods != (mods & ~locked))
if (bind->mods != mods)
continue;
/* Match untranslated symbols */
@ -1566,6 +1569,7 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial,
if (bind->k.sym == raw_syms[i] &&
execute_binding(seat, term, bind, serial, 1))
{
LOG_WARN("matched untranslated symbol");
goto maybe_repeat;
}
}
@ -1575,6 +1579,7 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial,
if (code->item == key &&
execute_binding(seat, term, bind, serial, 1))
{
LOG_WARN("matched raw key code");
goto maybe_repeat;
}
}
@ -2239,8 +2244,7 @@ static const struct key_binding *
xassert(bindings != NULL);
xkb_mod_mask_t mods;
get_current_modifiers(seat, &mods, NULL, 0);
mods &= seat->kbd.bind_significant;
get_current_modifiers(seat, &mods, NULL, 0, true);
/* Ignore selection override modifiers when
* matching modifiers */
@ -2293,8 +2297,7 @@ static const struct key_binding *
continue;
}
const struct config_key_modifiers no_mods = {0};
if (memcmp(&binding->modifiers, &no_mods, sizeof(no_mods)) != 0) {
if (tll_length(binding->modifiers) > 0) {
/* Binding has modifiers */
continue;
}

View file

@ -33,6 +33,6 @@ void input_repeat(struct seat *seat, uint32_t key);
void get_current_modifiers(const struct seat *seat,
xkb_mod_mask_t *effective,
xkb_mod_mask_t *consumed,
uint32_t key);
uint32_t key, bool filter_locked);
enum cursor_shape xcursor_for_csd_border(struct terminal *term, int x, int y);

View file

@ -404,6 +404,24 @@ sort_binding_list(key_binding_list_t *list)
tll_sort(*list, key_cmp);
}
static xkb_mod_mask_t
mods_to_mask(const struct seat *seat, const config_modifier_list_t *mods)
{
xkb_mod_mask_t mask = 0;
tll_foreach(*mods, it) {
xkb_mod_index_t idx = xkb_keymap_mod_get_index(seat->kbd.xkb_keymap, it->item);
if (idx == XKB_MOD_INVALID) {
LOG_ERR("%s: invalid modifier name", it->item);
continue;
}
mask |= 1 << idx;
}
return mask;
}
static void NOINLINE
convert_key_binding(struct key_set *set,
const struct config_key_binding *conf_binding,
@ -411,7 +429,7 @@ convert_key_binding(struct key_set *set,
{
const struct seat *seat = set->seat;
xkb_mod_mask_t mods = conf_modifiers_to_mask(seat, &conf_binding->modifiers);
xkb_mod_mask_t mods = mods_to_mask(seat, &conf_binding->modifiers);
xkb_keysym_t sym = maybe_repair_key_combo(seat, conf_binding->k.sym, mods);
struct key_binding binding = {
@ -469,7 +487,7 @@ convert_mouse_binding(struct key_set *set,
.type = MOUSE_BINDING,
.action = conf_binding->action,
.aux = &conf_binding->aux,
.mods = conf_modifiers_to_mask(set->seat, &conf_binding->modifiers),
.mods = mods_to_mask(set->seat, &conf_binding->modifiers),
.m = {
.button = conf_binding->m.button,
.count = conf_binding->m.count,
@ -509,7 +527,7 @@ load_keymap(struct key_set *set)
convert_url_bindings(set);
convert_mouse_bindings(set);
set->public.selection_overrides = conf_modifiers_to_mask(
set->public.selection_overrides = mods_to_mask(
set->seat, &set->conf->mouse.selection_override_modifiers);
}

View file

@ -1374,17 +1374,12 @@ void
search_input(struct seat *seat, struct terminal *term,
const struct key_binding_set *bindings, uint32_t key,
xkb_keysym_t sym, xkb_mod_mask_t mods, xkb_mod_mask_t consumed,
xkb_mod_mask_t locked,
const xkb_keysym_t *raw_syms, size_t raw_count,
uint32_t serial)
{
LOG_DBG("search: input: sym=%d/0x%x, mods=0x%08x, consumed=0x%08x",
sym, sym, mods, consumed);
const xkb_mod_mask_t bind_mods =
mods & seat->kbd.bind_significant & ~locked;
const xkb_mod_mask_t bind_consumed =
consumed & seat->kbd.bind_significant & ~locked;
enum xkb_compose_status compose_status = seat->kbd.xkb_compose_state != NULL
? xkb_compose_state_get_status(seat->kbd.xkb_compose_state)
: XKB_COMPOSE_NOTHING;
@ -1399,7 +1394,7 @@ search_input(struct seat *seat, struct terminal *term,
/* Match translated symbol */
if (bind->k.sym == sym &&
bind->mods == (bind_mods & ~bind_consumed)) {
bind->mods == (mods & ~consumed)) {
if (execute_binding(seat, term, bind, serial,
&update_search_result, &search_direction,
@ -1410,7 +1405,7 @@ search_input(struct seat *seat, struct terminal *term,
return;
}
if (bind->mods != bind_mods || bind_mods != (mods & ~locked))
if (bind->mods != mods)
continue;
/* Match untranslated symbols */

View file

@ -11,7 +11,6 @@ void search_input(
struct seat *seat, struct terminal *term,
const struct key_binding_set *bindings, uint32_t key,
xkb_keysym_t sym, xkb_mod_mask_t mods, xkb_mod_mask_t consumed,
xkb_mod_mask_t locked,
const xkb_keysym_t *raw_syms, size_t raw_count,
uint32_t serial);
void search_add_chars(struct terminal *term, const char *text, size_t len);

View file

@ -3039,7 +3039,7 @@ term_mouse_grabbed(const struct terminal *term, const struct seat *seat)
*/
xkb_mod_mask_t mods;
get_current_modifiers(seat, &mods, NULL, 0);
get_current_modifiers(seat, &mods, NULL, 0, true);
const struct key_binding_set *bindings =
key_binding_for(term->wl->key_binding_manager, term->conf, seat);

View file

@ -787,6 +787,17 @@ test_section_csd(void)
config_free(&conf);
}
static bool
have_modifier(const config_modifier_list_t *mods, const char *mod)
{
tll_foreach(*mods, it) {
if (strcmp(it->item, mod) == 0)
return true;
}
return false;
}
static void
test_key_binding(struct context *ctx, bool (*parse_fun)(struct context *ctx),
int action, int max_action, const char *const *map,
@ -904,17 +915,19 @@ test_key_binding(struct context *ctx, bool (*parse_fun)(struct context *ctx),
ctx->section, ctx->key, ctx->value, binding->action, action);
}
if (binding->modifiers.ctrl != ctrl ||
binding->modifiers.alt != alt ||
binding->modifiers.shift != shift ||
binding->modifiers.super != super)
bool have_ctrl = have_modifier(&binding->modifiers, XKB_MOD_NAME_CTRL);
bool have_alt = have_modifier(&binding->modifiers, XKB_MOD_NAME_ALT);
bool have_shift = have_modifier(&binding->modifiers, XKB_MOD_NAME_SHIFT);
bool have_super = have_modifier(&binding->modifiers, XKB_MOD_NAME_LOGO);
if (have_ctrl != ctrl || have_alt != alt ||
have_shift != shift || have_super != super)
{
BUG("[%s].%s=%s: modifier mismatch:\n"
" have: ctrl=%d, alt=%d, shift=%d, super=%d\n"
" expected: ctrl=%d, alt=%d, shift=%d, super=%d",
ctx->section, ctx->key, ctx->value,
binding->modifiers.ctrl, binding->modifiers.alt,
binding->modifiers.shift, binding->modifiers.super,
have_ctrl, have_alt, have_shift, have_super,
ctrl, alt, shift, super);
}
@ -970,14 +983,17 @@ _test_binding_collisions(struct context *ctx,
bindings.arr[0] = (struct config_key_binding){
.action = (test_mode == FAIL_DIFFERENT_ACTION
? max_action - 1 : max_action),
.modifiers = {.ctrl = true},
.modifiers = tll_init(),
.path = "unittest",
};
tll_push_back(bindings.arr[0].modifiers, xstrdup(XKB_MOD_NAME_CTRL));
bindings.arr[1] = (struct config_key_binding){
.action = max_action,
.modifiers = {.ctrl = true},
.modifiers = tll_init(),
.path = "unittest",
};
tll_push_back(bindings.arr[1].modifiers, xstrdup(XKB_MOD_NAME_CTRL));
switch (type) {
case KEY_BINDING:
@ -998,7 +1014,8 @@ _test_binding_collisions(struct context *ctx,
break;
case FAIL_MOUSE_OVERRIDE:
ctx->conf->mouse.selection_override_modifiers.ctrl = true;
tll_free_and_free(ctx->conf->mouse.selection_override_modifiers, free);
tll_push_back(ctx->conf->mouse.selection_override_modifiers, xstrdup(XKB_MOD_NAME_CTRL));
break;
case FAIL_DIFFERENT_ARGV:
@ -1237,10 +1254,13 @@ test_section_text_bindings(void)
ctx.key = "\\y";
xassert(!parse_section_text_bindings(&ctx));
#if 0
/* Invalid modifier and key names are detected later, when a
* layout is applied */
ctx.key = "abcd";
ctx.value = "InvalidMod+y";
xassert(!parse_section_text_bindings(&ctx));
#endif
config_free(&conf);
}

View file

@ -145,28 +145,22 @@ void
urls_input(struct seat *seat, struct terminal *term,
const struct key_binding_set *bindings, uint32_t key,
xkb_keysym_t sym, xkb_mod_mask_t mods, xkb_mod_mask_t consumed,
xkb_mod_mask_t locked,
const xkb_keysym_t *raw_syms, size_t raw_count,
uint32_t serial)
{
const xkb_mod_mask_t bind_mods =
mods & seat->kbd.bind_significant & ~locked;
const xkb_mod_mask_t bind_consumed =
consumed & seat->kbd.bind_significant & ~locked;
/* Key bindings */
tll_foreach(bindings->url, it) {
const struct key_binding *bind = &it->item;
/* Match translated symbol */
if (bind->k.sym == sym &&
bind->mods == (bind_mods & ~bind_consumed))
bind->mods == (mods & ~consumed))
{
execute_binding(seat, term, bind, serial);
return;
}
if (bind->mods != bind_mods || bind_mods != (mods & ~locked))
if (bind->mods != mods)
continue;
for (size_t i = 0; i < raw_count; i++) {
@ -196,7 +190,7 @@ urls_input(struct seat *seat, struct terminal *term,
return;
}
if (mods & ~consumed & ~locked)
if (mods & ~consumed)
return;
char32_t wc = xkb_state_key_get_utf32(seat->kbd.xkb_state, key);

View file

@ -23,6 +23,5 @@ void urls_reset(struct terminal *term);
void urls_input(struct seat *seat, struct terminal *term,
const struct key_binding_set *bindings, uint32_t key,
xkb_keysym_t sym, xkb_mod_mask_t mods, xkb_mod_mask_t consumed,
xkb_mod_mask_t locked,
const xkb_keysym_t *raw_syms, size_t raw_count,
uint32_t serial);

View file

@ -128,8 +128,8 @@ struct seat {
xkb_mod_index_t mod_caps;
xkb_mod_index_t mod_num;
xkb_mod_mask_t bind_significant;
xkb_mod_mask_t kitty_significant;
xkb_mod_mask_t legacy_significant; /* Significant modifiers for the legacy keyboard protocol */
xkb_mod_mask_t kitty_significant; /* Significant modifiers for the kitty keyboard protocol */
xkb_keycode_t key_arrow_up;
xkb_keycode_t key_arrow_down;