mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-04 04:06:06 -05:00
input/config: support *all* modifier names
That is, allow custom modifiers (i.e. other than ctrl/shift/alt etc) in key bindings. This is done by no longer validating/translating modifier names to booleans for a pre-configured set of modifiers (ctrl, shift, alt, super). Instead, we keep the modifier *names* in a list, in the key binding struct. When a keymap is loaded, and we "convert" the key binding, _then_ we do modifier translation. For invalid modifier names, we print an error, and then ignore it. I.e. we no longer fail to load a config due to invalid modifier names. We also need to update how we determine the set of significant modifiers. Any modifier not in this list will be ignored when matching key bindings. Before this patch, we hardcoded this to shift/alt/ctrl/super. Now, to handle custom modifiers as well, we simply treat *all* modifiers defined by the current layout as significant. Typically, the only unwanted modifiers are "locked" modifiers. We are already filtering these out.
This commit is contained in:
parent
21a8d832ce
commit
4730ff8d08
6 changed files with 291 additions and 187 deletions
363
config.c
363
config.c
|
|
@ -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", ¬s, &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
|
||||
|
|
|
|||
13
config.h
13
config.h
|
|
@ -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);
|
||||
|
|
|
|||
33
input.c
33
input.c
|
|
@ -579,22 +579,33 @@ 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)
|
||||
seat->kbd.kitty_significant |= 1 << seat->kbd.mod_num;
|
||||
|
||||
/* Significant modifiers when handling shortcuts - use all available */
|
||||
seat->kbd.bind_significant = 0;
|
||||
const xkb_mod_index_t mod_count = xkb_keymap_num_mods(seat->kbd.xkb_keymap);
|
||||
for (xkb_mod_index_t i = 0; i < mod_count; i++) {
|
||||
LOG_DBG("significant modifier: %s",
|
||||
xkb_keymap_mod_get_name(seat->kbd.xkb_keymap, i));
|
||||
seat->kbd.bind_significant |= 1 << i;
|
||||
}
|
||||
|
||||
seat->kbd.key_arrow_up = xkb_keymap_key_by_name(seat->kbd.xkb_keymap, "UP");
|
||||
seat->kbd.key_arrow_down = xkb_keymap_key_by_name(seat->kbd.xkb_keymap, "DOWN");
|
||||
}
|
||||
|
|
@ -985,7 +996,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 {
|
||||
|
|
@ -1527,7 +1538,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));
|
||||
}
|
||||
}
|
||||
|
|
@ -1555,6 +1566,7 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial,
|
|||
bind->mods == (bind_mods & ~bind_consumed) &&
|
||||
execute_binding(seat, term, bind, serial, 1))
|
||||
{
|
||||
LOG_WARN("matched translated symbol");
|
||||
goto maybe_repeat;
|
||||
}
|
||||
|
||||
|
|
@ -1566,6 +1578,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 +1588,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;
|
||||
}
|
||||
}
|
||||
|
|
@ -2293,8 +2307,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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -128,8 +128,9 @@ 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 bind_significant; /* Significant modifiers for shortcut handling */
|
||||
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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue