mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-02-05 04:06:08 -05:00
commit
0f10c4fd6c
13 changed files with 313 additions and 229 deletions
|
|
@ -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
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);
|
||||
|
|
|
|||
67
input.c
67
input.c
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
2
input.h
2
input.h
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
9
search.c
9
search.c
|
|
@ -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 */
|
||||
|
|
|
|||
1
search.h
1
search.h
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
12
url-mode.c
12
url-mode.c
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue