mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-03-01 01:40:13 -05:00
commit
0f10c4fd6c
13 changed files with 313 additions and 229 deletions
|
|
@ -56,6 +56,10 @@
|
||||||
numlock is ignored.
|
numlock is ignored.
|
||||||
* A new `resize-by-cells` option, enabled by default, allows the size
|
* A new `resize-by-cells` option, enabled by default, allows the size
|
||||||
of floating windows to be constrained to multiples of the cell 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
|
### Changed
|
||||||
|
|
|
||||||
363
config.c
363
config.c
|
|
@ -1544,6 +1544,7 @@ static void
|
||||||
free_key_binding(struct config_key_binding *binding)
|
free_key_binding(struct config_key_binding *binding)
|
||||||
{
|
{
|
||||||
free_binding_aux(&binding->aux);
|
free_binding_aux(&binding->aux);
|
||||||
|
tll_free_and_free(binding->modifiers, free);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void NOINLINE
|
static void NOINLINE
|
||||||
|
|
@ -1559,43 +1560,26 @@ free_key_binding_list(struct config_key_binding_list *bindings)
|
||||||
bindings->count = 0;
|
bindings->count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool NOINLINE
|
static void NOINLINE
|
||||||
parse_modifiers(struct context *ctx, const char *text, size_t len,
|
parse_modifiers(const char *text, size_t len, config_modifier_list_t *modifiers)
|
||||||
struct config_key_modifiers *modifiers)
|
|
||||||
{
|
{
|
||||||
bool ret = false;
|
tll_free_and_free(*modifiers, free);
|
||||||
|
|
||||||
*modifiers = (struct config_key_modifiers){0};
|
|
||||||
|
|
||||||
/* Handle "none" separately because e.g. none+shift is nonsense */
|
/* Handle "none" separately because e.g. none+shift is nonsense */
|
||||||
if (strncmp(text, "none", len) == 0)
|
if (strncmp(text, "none", len) == 0)
|
||||||
return true;
|
return;
|
||||||
|
|
||||||
char *copy = xstrndup(text, len);
|
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 != NULL;
|
||||||
key = strtok_r(NULL, "+", &tok_ctx))
|
key = strtok_r(NULL, "+", &ctx))
|
||||||
{
|
{
|
||||||
if (streq(key, XKB_MOD_NAME_SHIFT))
|
tll_push_back(*modifiers, xstrdup(key));
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = true;
|
|
||||||
|
|
||||||
out:
|
|
||||||
free(copy);
|
free(copy);
|
||||||
return ret;
|
tll_sort(*modifiers, strcmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int NOINLINE
|
static int NOINLINE
|
||||||
|
|
@ -1731,6 +1715,7 @@ value_to_key_combos(struct context *ctx, int action,
|
||||||
|
|
||||||
/* Count number of combinations */
|
/* Count number of combinations */
|
||||||
size_t combo_count = 1;
|
size_t combo_count = 1;
|
||||||
|
size_t used_combos = 0; /* For error handling */
|
||||||
for (const char *p = strchr(ctx->value, ' ');
|
for (const char *p = strchr(ctx->value, ' ');
|
||||||
p != NULL;
|
p != NULL;
|
||||||
p = strchr(p + 1, ' '))
|
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);
|
for (char *tok_ctx = NULL, *combo = strtok_r(copy, " ", &tok_ctx);
|
||||||
combo != NULL;
|
combo != NULL;
|
||||||
combo = strtok_r(NULL, " ", &tok_ctx),
|
combo = strtok_r(NULL, " ", &tok_ctx),
|
||||||
idx++)
|
idx++, used_combos++)
|
||||||
{
|
{
|
||||||
struct config_key_binding *new_combo = &new_combos[idx];
|
struct config_key_binding *new_combo = &new_combos[idx];
|
||||||
new_combo->action = action;
|
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.master_copy = idx == 0;
|
||||||
new_combo->aux.pipe = *argv;
|
new_combo->aux.pipe = *argv;
|
||||||
#endif
|
#endif
|
||||||
|
memset(&new_combo->modifiers, 0, sizeof(new_combo->modifiers));
|
||||||
new_combo->path = ctx->path;
|
new_combo->path = ctx->path;
|
||||||
new_combo->lineno = ctx->lineno;
|
new_combo->lineno = ctx->lineno;
|
||||||
|
|
||||||
|
|
@ -1765,11 +1751,9 @@ value_to_key_combos(struct context *ctx, int action,
|
||||||
if (key == NULL) {
|
if (key == NULL) {
|
||||||
/* No modifiers */
|
/* No modifiers */
|
||||||
key = combo;
|
key = combo;
|
||||||
new_combo->modifiers = (struct config_key_modifiers){0};
|
|
||||||
} else {
|
} else {
|
||||||
*key = '\0';
|
*key = '\0';
|
||||||
if (!parse_modifiers(ctx, combo, key - combo, &new_combo->modifiers))
|
parse_modifiers(combo, key - combo, &new_combo->modifiers);
|
||||||
goto err;
|
|
||||||
key++; /* Skip past the '+' */
|
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);
|
new_combo->k.sym = xkb_keysym_from_name(key, 0);
|
||||||
if (new_combo->k.sym == XKB_KEY_NoSymbol) {
|
if (new_combo->k.sym == XKB_KEY_NoSymbol) {
|
||||||
LOG_CONTEXTUAL_ERR("not a valid XKB key name: %s", key);
|
LOG_CONTEXTUAL_ERR("not a valid XKB key name: %s", key);
|
||||||
|
free_key_binding(new_combo);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -1799,6 +1784,7 @@ value_to_key_combos(struct context *ctx, int action,
|
||||||
LOG_CONTEXTUAL_ERRNO("invalid click count: %s", _count);
|
LOG_CONTEXTUAL_ERRNO("invalid click count: %s", _count);
|
||||||
else
|
else
|
||||||
LOG_CONTEXTUAL_ERR("invalid click count: %s", _count);
|
LOG_CONTEXTUAL_ERR("invalid click count: %s", _count);
|
||||||
|
free_key_binding(new_combo);
|
||||||
goto err;
|
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);
|
new_combo->m.button = mouse_button_name_to_code(key);
|
||||||
if (new_combo->m.button < 0) {
|
if (new_combo->m.button < 0) {
|
||||||
LOG_CONTEXTUAL_ERR("invalid mouse button name: %s", key);
|
LOG_CONTEXTUAL_ERR("invalid mouse button name: %s", key);
|
||||||
|
free_key_binding(new_combo);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1838,41 +1825,89 @@ value_to_key_combos(struct context *ctx, int action,
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
for (size_t i = 0; i < used_combos; i++)
|
||||||
|
free_key_binding(&new_combos[i]);
|
||||||
free(copy);
|
free(copy);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
modifiers_equal(const struct config_key_modifiers *mods1,
|
modifiers_equal(const config_modifier_list_t *mods1,
|
||||||
const struct config_key_modifiers *mods2)
|
const config_modifier_list_t *mods2)
|
||||||
{
|
{
|
||||||
bool shift = mods1->shift == mods2->shift;
|
if (tll_length(*mods1) != tll_length(*mods2))
|
||||||
bool alt = mods1->alt == mods2->alt;
|
return false;
|
||||||
bool ctrl = mods1->ctrl == mods2->ctrl;
|
|
||||||
bool super = mods1->super == mods2->super;
|
size_t count = 0;
|
||||||
return shift && alt && ctrl && super;
|
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
|
static bool
|
||||||
modifiers_disjoint(const struct config_key_modifiers *mods1,
|
modifiers_disjoint(const config_modifier_list_t *mods1,
|
||||||
const struct config_key_modifiers *mods2)
|
const config_modifier_list_t *mods2)
|
||||||
{
|
{
|
||||||
bool shift = mods1->shift && mods2->shift;
|
return !modifiers_equal(mods1, mods2);
|
||||||
bool alt = mods1->alt && mods2->alt;
|
|
||||||
bool ctrl = mods1->ctrl && mods2->ctrl;
|
|
||||||
bool super = mods1->super && mods2->super;
|
|
||||||
return !(shift || alt || ctrl || super);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static char * NOINLINE
|
static char * NOINLINE
|
||||||
modifiers_to_str(const struct config_key_modifiers *mods)
|
modifiers_to_str(const config_modifier_list_t *mods)
|
||||||
{
|
{
|
||||||
char *ret = xasprintf(
|
size_t len = tll_length(*mods); /* ‘+’ , and NULL terminator */
|
||||||
"%s%s%s%s",
|
tll_foreach(*mods, it)
|
||||||
mods->ctrl ? XKB_MOD_NAME_CTRL "+" : "",
|
len += strlen(it->item);
|
||||||
mods->alt ? XKB_MOD_NAME_ALT "+": "",
|
|
||||||
mods->super ? XKB_MOD_NAME_LOGO "+": "",
|
char *ret = xmalloc(len);
|
||||||
mods->shift ? XKB_MOD_NAME_SHIFT "+": "");
|
size_t idx = 0;
|
||||||
|
tll_foreach(*mods, it) {
|
||||||
|
idx += snprintf(&ret[idx], len - idx, "%s", it->item);
|
||||||
|
ret[idx++] = '+';
|
||||||
|
}
|
||||||
|
ret[--idx] = '\0';
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2014,10 +2049,13 @@ UNITTEST
|
||||||
xassert(bindings.arr[0].action == TEST_ACTION_FOO);
|
xassert(bindings.arr[0].action == TEST_ACTION_FOO);
|
||||||
xassert(bindings.arr[1].action == TEST_ACTION_BAR);
|
xassert(bindings.arr[1].action == TEST_ACTION_BAR);
|
||||||
xassert(bindings.arr[1].k.sym == XKB_KEY_g);
|
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].action == TEST_ACTION_BAR);
|
||||||
xassert(bindings.arr[2].k.sym == XKB_KEY_x);
|
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
|
* REPLACE foo with foo=Mod+v Shift+q
|
||||||
|
|
@ -2033,10 +2071,12 @@ UNITTEST
|
||||||
xassert(bindings.arr[1].action == TEST_ACTION_BAR);
|
xassert(bindings.arr[1].action == TEST_ACTION_BAR);
|
||||||
xassert(bindings.arr[2].action == TEST_ACTION_FOO);
|
xassert(bindings.arr[2].action == TEST_ACTION_FOO);
|
||||||
xassert(bindings.arr[2].k.sym == XKB_KEY_v);
|
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].action == TEST_ACTION_FOO);
|
||||||
xassert(bindings.arr[3].k.sym == XKB_KEY_q);
|
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
|
* 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];
|
struct config_key_binding *binding1 = &bindings->arr[i];
|
||||||
xassert(binding1->action != BIND_ACTION_NONE);
|
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? */
|
/* Does our modifiers collide with the selection override mods? */
|
||||||
if (type == MOUSE_BINDING &&
|
if (type == MOUSE_BINDING &&
|
||||||
|
|
@ -2127,7 +2167,7 @@ resolve_key_binding_collisions(struct config *conf, const char *section_name,
|
||||||
continue;
|
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 mods_equal = modifiers_equal(mods1, mods2);
|
||||||
bool sym_equal;
|
bool sym_equal;
|
||||||
|
|
@ -2252,13 +2292,9 @@ parse_section_mouse_bindings(struct context *ctx)
|
||||||
const char *value = ctx->value;
|
const char *value = ctx->value;
|
||||||
|
|
||||||
if (streq(key, "selection-override-modifiers")) {
|
if (streq(key, "selection-override-modifiers")) {
|
||||||
if (!parse_modifiers(
|
parse_modifiers(
|
||||||
ctx, ctx->value, strlen(value),
|
ctx->value, strlen(value),
|
||||||
&conf->mouse.selection_override_modifiers))
|
&conf->mouse.selection_override_modifiers);
|
||||||
{
|
|
||||||
LOG_CONTEXTUAL_ERR("%s: invalid modifiers '%s'", key, ctx->value);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2830,37 +2866,38 @@ get_server_socket_path(void)
|
||||||
return xasprintf("%s/foot-%s.sock", xdg_runtime, wayland_display);
|
return xasprintf("%s/foot-%s.sock", xdg_runtime, wayland_display);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define m_none {0}
|
static config_modifier_list_t
|
||||||
#define m_alt {.alt = true}
|
m(const char *text)
|
||||||
#define m_ctrl {.ctrl = true}
|
{
|
||||||
#define m_shift {.shift = true}
|
config_modifier_list_t ret = tll_init();
|
||||||
#define m_ctrl_shift {.ctrl = true, .shift = true}
|
parse_modifiers(text, strlen(text), &ret);
|
||||||
#define m_ctrl_shift_alt {.ctrl = true, .shift = true, .alt = true}
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
add_default_key_bindings(struct config *conf)
|
add_default_key_bindings(struct config *conf)
|
||||||
{
|
{
|
||||||
static const struct config_key_binding bindings[] = {
|
const struct config_key_binding bindings[] = {
|
||||||
{BIND_ACTION_SCROLLBACK_UP_PAGE, m_shift, {{XKB_KEY_Prior}}},
|
{BIND_ACTION_SCROLLBACK_UP_PAGE, m(XKB_MOD_NAME_SHIFT), {{XKB_KEY_Prior}}},
|
||||||
{BIND_ACTION_SCROLLBACK_DOWN_PAGE, m_shift, {{XKB_KEY_Next}}},
|
{BIND_ACTION_SCROLLBACK_DOWN_PAGE, m(XKB_MOD_NAME_SHIFT), {{XKB_KEY_Next}}},
|
||||||
{BIND_ACTION_CLIPBOARD_COPY, m_ctrl_shift, {{XKB_KEY_c}}},
|
{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_COPY, m("none"), {{XKB_KEY_XF86Copy}}},
|
||||||
{BIND_ACTION_CLIPBOARD_PASTE, m_ctrl_shift, {{XKB_KEY_v}}},
|
{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_CLIPBOARD_PASTE, m("none"), {{XKB_KEY_XF86Paste}}},
|
||||||
{BIND_ACTION_PRIMARY_PASTE, m_shift, {{XKB_KEY_Insert}}},
|
{BIND_ACTION_PRIMARY_PASTE, m(XKB_MOD_NAME_SHIFT), {{XKB_KEY_Insert}}},
|
||||||
{BIND_ACTION_SEARCH_START, m_ctrl_shift, {{XKB_KEY_r}}},
|
{BIND_ACTION_SEARCH_START, m(XKB_MOD_NAME_CTRL "+" XKB_MOD_NAME_SHIFT), {{XKB_KEY_r}}},
|
||||||
{BIND_ACTION_FONT_SIZE_UP, m_ctrl, {{XKB_KEY_plus}}},
|
{BIND_ACTION_FONT_SIZE_UP, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_plus}}},
|
||||||
{BIND_ACTION_FONT_SIZE_UP, m_ctrl, {{XKB_KEY_equal}}},
|
{BIND_ACTION_FONT_SIZE_UP, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_equal}}},
|
||||||
{BIND_ACTION_FONT_SIZE_UP, m_ctrl, {{XKB_KEY_KP_Add}}},
|
{BIND_ACTION_FONT_SIZE_UP, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_KP_Add}}},
|
||||||
{BIND_ACTION_FONT_SIZE_DOWN, m_ctrl, {{XKB_KEY_minus}}},
|
{BIND_ACTION_FONT_SIZE_DOWN, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_minus}}},
|
||||||
{BIND_ACTION_FONT_SIZE_DOWN, m_ctrl, {{XKB_KEY_KP_Subtract}}},
|
{BIND_ACTION_FONT_SIZE_DOWN, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_KP_Subtract}}},
|
||||||
{BIND_ACTION_FONT_SIZE_RESET, m_ctrl, {{XKB_KEY_0}}},
|
{BIND_ACTION_FONT_SIZE_RESET, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_0}}},
|
||||||
{BIND_ACTION_FONT_SIZE_RESET, m_ctrl, {{XKB_KEY_KP_0}}},
|
{BIND_ACTION_FONT_SIZE_RESET, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_KP_0}}},
|
||||||
{BIND_ACTION_SPAWN_TERMINAL, m_ctrl_shift, {{XKB_KEY_n}}},
|
{BIND_ACTION_SPAWN_TERMINAL, m(XKB_MOD_NAME_CTRL "+" XKB_MOD_NAME_SHIFT), {{XKB_KEY_n}}},
|
||||||
{BIND_ACTION_SHOW_URLS_LAUNCH, m_ctrl_shift, {{XKB_KEY_o}}},
|
{BIND_ACTION_SHOW_URLS_LAUNCH, m(XKB_MOD_NAME_CTRL "+" XKB_MOD_NAME_SHIFT), {{XKB_KEY_o}}},
|
||||||
{BIND_ACTION_UNICODE_INPUT, m_ctrl_shift, {{XKB_KEY_u}}},
|
{BIND_ACTION_UNICODE_INPUT, m(XKB_MOD_NAME_CTRL "+" XKB_MOD_NAME_SHIFT), {{XKB_KEY_u}}},
|
||||||
{BIND_ACTION_PROMPT_PREV, m_ctrl_shift, {{XKB_KEY_z}}},
|
{BIND_ACTION_PROMPT_PREV, m(XKB_MOD_NAME_CTRL "+" XKB_MOD_NAME_SHIFT), {{XKB_KEY_z}}},
|
||||||
{BIND_ACTION_PROMPT_NEXT, m_ctrl_shift, {{XKB_KEY_x}}},
|
{BIND_ACTION_PROMPT_NEXT, m(XKB_MOD_NAME_CTRL "+" XKB_MOD_NAME_SHIFT), {{XKB_KEY_x}}},
|
||||||
};
|
};
|
||||||
|
|
||||||
conf->bindings.key.count = ALEN(bindings);
|
conf->bindings.key.count = ALEN(bindings);
|
||||||
|
|
@ -2872,46 +2909,47 @@ add_default_key_bindings(struct config *conf)
|
||||||
static void
|
static void
|
||||||
add_default_search_bindings(struct config *conf)
|
add_default_search_bindings(struct config *conf)
|
||||||
{
|
{
|
||||||
static const struct config_key_binding bindings[] = {
|
const struct config_key_binding bindings[] = {
|
||||||
{BIND_ACTION_SEARCH_SCROLLBACK_UP_PAGE, m_shift, {{XKB_KEY_Prior}}},
|
{BIND_ACTION_SEARCH_SCROLLBACK_UP_PAGE, m(XKB_MOD_NAME_SHIFT), {{XKB_KEY_Prior}}},
|
||||||
{BIND_ACTION_SEARCH_SCROLLBACK_DOWN_PAGE, m_shift, {{XKB_KEY_Next}}},
|
{BIND_ACTION_SEARCH_SCROLLBACK_DOWN_PAGE, m(XKB_MOD_NAME_SHIFT), {{XKB_KEY_Next}}},
|
||||||
{BIND_ACTION_SEARCH_CANCEL, m_ctrl, {{XKB_KEY_c}}},
|
{BIND_ACTION_SEARCH_CANCEL, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_c}}},
|
||||||
{BIND_ACTION_SEARCH_CANCEL, m_ctrl, {{XKB_KEY_g}}},
|
{BIND_ACTION_SEARCH_CANCEL, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_g}}},
|
||||||
{BIND_ACTION_SEARCH_CANCEL, m_none, {{XKB_KEY_Escape}}},
|
{BIND_ACTION_SEARCH_CANCEL, m("none"), {{XKB_KEY_Escape}}},
|
||||||
{BIND_ACTION_SEARCH_COMMIT, m_none, {{XKB_KEY_Return}}},
|
{BIND_ACTION_SEARCH_COMMIT, m("none"), {{XKB_KEY_Return}}},
|
||||||
{BIND_ACTION_SEARCH_FIND_PREV, m_ctrl, {{XKB_KEY_r}}},
|
{BIND_ACTION_SEARCH_FIND_PREV, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_r}}},
|
||||||
{BIND_ACTION_SEARCH_FIND_NEXT, m_ctrl, {{XKB_KEY_s}}},
|
{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("none"), {{XKB_KEY_Left}}},
|
||||||
{BIND_ACTION_SEARCH_EDIT_LEFT, m_ctrl, {{XKB_KEY_b}}},
|
{BIND_ACTION_SEARCH_EDIT_LEFT, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_b}}},
|
||||||
{BIND_ACTION_SEARCH_EDIT_LEFT_WORD, m_ctrl, {{XKB_KEY_Left}}},
|
{BIND_ACTION_SEARCH_EDIT_LEFT_WORD, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_Left}}},
|
||||||
{BIND_ACTION_SEARCH_EDIT_LEFT_WORD, m_alt, {{XKB_KEY_b}}},
|
{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("none"), {{XKB_KEY_Right}}},
|
||||||
{BIND_ACTION_SEARCH_EDIT_RIGHT, m_ctrl, {{XKB_KEY_f}}},
|
{BIND_ACTION_SEARCH_EDIT_RIGHT, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_f}}},
|
||||||
{BIND_ACTION_SEARCH_EDIT_RIGHT_WORD, m_ctrl, {{XKB_KEY_Right}}},
|
{BIND_ACTION_SEARCH_EDIT_RIGHT_WORD, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_Right}}},
|
||||||
{BIND_ACTION_SEARCH_EDIT_RIGHT_WORD, m_alt, {{XKB_KEY_f}}},
|
{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("none"), {{XKB_KEY_Home}}},
|
||||||
{BIND_ACTION_SEARCH_EDIT_HOME, m_ctrl, {{XKB_KEY_a}}},
|
{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("none"), {{XKB_KEY_End}}},
|
||||||
{BIND_ACTION_SEARCH_EDIT_END, m_ctrl, {{XKB_KEY_e}}},
|
{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, m("none"), {{XKB_KEY_BackSpace}}},
|
||||||
{BIND_ACTION_SEARCH_DELETE_PREV_WORD, m_ctrl, {{XKB_KEY_BackSpace}}},
|
{BIND_ACTION_SEARCH_DELETE_PREV_WORD, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_BackSpace}}},
|
||||||
{BIND_ACTION_SEARCH_DELETE_PREV_WORD, m_alt, {{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, m("none"), {{XKB_KEY_Delete}}},
|
||||||
{BIND_ACTION_SEARCH_DELETE_NEXT_WORD, m_ctrl, {{XKB_KEY_Delete}}},
|
{BIND_ACTION_SEARCH_DELETE_NEXT_WORD, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_Delete}}},
|
||||||
{BIND_ACTION_SEARCH_DELETE_NEXT_WORD, m_alt, {{XKB_KEY_d}}},
|
{BIND_ACTION_SEARCH_DELETE_NEXT_WORD, m(XKB_MOD_NAME_ALT), {{XKB_KEY_d}}},
|
||||||
{BIND_ACTION_SEARCH_EXTEND_CHAR, m_shift, {{XKB_KEY_Right}}},
|
{BIND_ACTION_SEARCH_EXTEND_CHAR, m(XKB_MOD_NAME_SHIFT), {{XKB_KEY_Right}}},
|
||||||
{BIND_ACTION_SEARCH_EXTEND_WORD, m_ctrl, {{XKB_KEY_w}}},
|
{BIND_ACTION_SEARCH_EXTEND_WORD, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_w}}},
|
||||||
{BIND_ACTION_SEARCH_EXTEND_WORD, m_ctrl_shift, {{XKB_KEY_Right}}},
|
{BIND_ACTION_SEARCH_EXTEND_WORD, m(XKB_MOD_NAME_CTRL "+" XKB_MOD_NAME_SHIFT), {{XKB_KEY_Right}}},
|
||||||
{BIND_ACTION_SEARCH_EXTEND_WORD_WS, m_ctrl_shift, {{XKB_KEY_w}}},
|
{BIND_ACTION_SEARCH_EXTEND_WORD, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_w}}},
|
||||||
{BIND_ACTION_SEARCH_EXTEND_LINE_DOWN, m_shift, {{XKB_KEY_Down}}},
|
{BIND_ACTION_SEARCH_EXTEND_WORD_WS, m(XKB_MOD_NAME_CTRL "+" XKB_MOD_NAME_SHIFT), {{XKB_KEY_w}}},
|
||||||
{BIND_ACTION_SEARCH_EXTEND_BACKWARD_CHAR, m_shift, {{XKB_KEY_Left}}},
|
{BIND_ACTION_SEARCH_EXTEND_LINE_DOWN, m(XKB_MOD_NAME_SHIFT), {{XKB_KEY_Down}}},
|
||||||
{BIND_ACTION_SEARCH_EXTEND_BACKWARD_WORD, m_ctrl_shift, {{XKB_KEY_Left}}},
|
{BIND_ACTION_SEARCH_EXTEND_BACKWARD_CHAR, m(XKB_MOD_NAME_SHIFT), {{XKB_KEY_Left}}},
|
||||||
{BIND_ACTION_SEARCH_EXTEND_LINE_UP, m_shift, {{XKB_KEY_Up}}},
|
{BIND_ACTION_SEARCH_EXTEND_BACKWARD_WORD, m(XKB_MOD_NAME_CTRL "+" XKB_MOD_NAME_SHIFT), {{XKB_KEY_Left}}},
|
||||||
{BIND_ACTION_SEARCH_CLIPBOARD_PASTE, m_ctrl, {{XKB_KEY_v}}},
|
{BIND_ACTION_SEARCH_EXTEND_LINE_UP, m(XKB_MOD_NAME_SHIFT), {{XKB_KEY_Up}}},
|
||||||
{BIND_ACTION_SEARCH_CLIPBOARD_PASTE, m_ctrl_shift, {{XKB_KEY_v}}},
|
{BIND_ACTION_SEARCH_CLIPBOARD_PASTE, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_v}}},
|
||||||
{BIND_ACTION_SEARCH_CLIPBOARD_PASTE, m_ctrl, {{XKB_KEY_y}}},
|
{BIND_ACTION_SEARCH_CLIPBOARD_PASTE, m(XKB_MOD_NAME_CTRL "+" XKB_MOD_NAME_SHIFT), {{XKB_KEY_v}}},
|
||||||
{BIND_ACTION_SEARCH_CLIPBOARD_PASTE, m_none, {{XKB_KEY_XF86Paste}}},
|
{BIND_ACTION_SEARCH_CLIPBOARD_PASTE, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_y}}},
|
||||||
{BIND_ACTION_SEARCH_PRIMARY_PASTE, m_shift, {{XKB_KEY_Insert}}},
|
{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);
|
conf->bindings.search.count = ALEN(bindings);
|
||||||
|
|
@ -2922,12 +2960,12 @@ add_default_search_bindings(struct config *conf)
|
||||||
static void
|
static void
|
||||||
add_default_url_bindings(struct config *conf)
|
add_default_url_bindings(struct config *conf)
|
||||||
{
|
{
|
||||||
static const struct config_key_binding bindings[] = {
|
const struct config_key_binding bindings[] = {
|
||||||
{BIND_ACTION_URL_CANCEL, m_ctrl, {{XKB_KEY_c}}},
|
{BIND_ACTION_URL_CANCEL, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_c}}},
|
||||||
{BIND_ACTION_URL_CANCEL, m_ctrl, {{XKB_KEY_g}}},
|
{BIND_ACTION_URL_CANCEL, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_g}}},
|
||||||
{BIND_ACTION_URL_CANCEL, m_ctrl, {{XKB_KEY_d}}},
|
{BIND_ACTION_URL_CANCEL, m(XKB_MOD_NAME_CTRL), {{XKB_KEY_d}}},
|
||||||
{BIND_ACTION_URL_CANCEL, m_none, {{XKB_KEY_Escape}}},
|
{BIND_ACTION_URL_CANCEL, m("none"), {{XKB_KEY_Escape}}},
|
||||||
{BIND_ACTION_URL_TOGGLE_URL_ON_JUMP_LABEL, m_none, {{XKB_KEY_t}}},
|
{BIND_ACTION_URL_TOGGLE_URL_ON_JUMP_LABEL, m("none"), {{XKB_KEY_t}}},
|
||||||
};
|
};
|
||||||
|
|
||||||
conf->bindings.url.count = ALEN(bindings);
|
conf->bindings.url.count = ALEN(bindings);
|
||||||
|
|
@ -2938,18 +2976,18 @@ add_default_url_bindings(struct config *conf)
|
||||||
static void
|
static void
|
||||||
add_default_mouse_bindings(struct config *conf)
|
add_default_mouse_bindings(struct config *conf)
|
||||||
{
|
{
|
||||||
static const struct config_key_binding bindings[] = {
|
const struct config_key_binding bindings[] = {
|
||||||
{BIND_ACTION_SCROLLBACK_UP_MOUSE, m_none, {.m = {BTN_BACK, 1}}},
|
{BIND_ACTION_SCROLLBACK_UP_MOUSE, m("none"), {.m = {BTN_BACK, 1}}},
|
||||||
{BIND_ACTION_SCROLLBACK_DOWN_MOUSE, m_none, {.m = {BTN_FORWARD, 1}}},
|
{BIND_ACTION_SCROLLBACK_DOWN_MOUSE, m("none"), {.m = {BTN_FORWARD, 1}}},
|
||||||
{BIND_ACTION_PRIMARY_PASTE, m_none, {.m = {BTN_MIDDLE, 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, m("none"), {.m = {BTN_LEFT, 1}}},
|
||||||
{BIND_ACTION_SELECT_BEGIN_BLOCK, m_ctrl, {.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, m("none"), {.m = {BTN_RIGHT, 1}}},
|
||||||
{BIND_ACTION_SELECT_EXTEND_CHAR_WISE, m_ctrl, {.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, m("none"), {.m = {BTN_LEFT, 2}}},
|
||||||
{BIND_ACTION_SELECT_WORD_WS, m_ctrl, {.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_QUOTE, m("none"), {.m = {BTN_LEFT, 3}}},
|
||||||
{BIND_ACTION_SELECT_ROW, m_none, {.m = {BTN_LEFT, 4}}},
|
{BIND_ACTION_SELECT_ROW, m("none"), {.m = {BTN_LEFT, 4}}},
|
||||||
};
|
};
|
||||||
|
|
||||||
conf->bindings.mouse.count = ALEN(bindings);
|
conf->bindings.mouse.count = ALEN(bindings);
|
||||||
|
|
@ -3064,12 +3102,7 @@ config_load(struct config *conf, const char *conf_path,
|
||||||
.mouse = {
|
.mouse = {
|
||||||
.hide_when_typing = false,
|
.hide_when_typing = false,
|
||||||
.alternate_scroll_mode = true,
|
.alternate_scroll_mode = true,
|
||||||
.selection_override_modifiers = {
|
.selection_override_modifiers = tll_init(),
|
||||||
.shift = true,
|
|
||||||
.alt = false,
|
|
||||||
.ctrl = false,
|
|
||||||
.super = false,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
.csd = {
|
.csd = {
|
||||||
.preferred = CONF_CSD_PREFER_SERVER,
|
.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));
|
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}",
|
tokenize_cmdline("notify-send -a ${app-id} -i ${app-id} ${title} ${body}",
|
||||||
&conf->notify.argv.args);
|
&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];
|
struct config_key_binding *new = &dst->arr[i];
|
||||||
|
|
||||||
*new = *old;
|
*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) {
|
switch (old->aux.type) {
|
||||||
case BINDING_AUX_NONE:
|
case BINDING_AUX_NONE:
|
||||||
|
|
@ -3399,6 +3436,11 @@ config_clone(const struct config *old)
|
||||||
|
|
||||||
conf->env_vars.length = 0;
|
conf->env_vars.length = 0;
|
||||||
conf->env_vars.head = conf->env_vars.tail = NULL;
|
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) {
|
tll_foreach(old->env_vars, it) {
|
||||||
struct env_var copy = {
|
struct env_var copy = {
|
||||||
.name = xstrdup(it->item.name),
|
.name = xstrdup(it->item.name),
|
||||||
|
|
@ -3431,13 +3473,13 @@ UNITTEST
|
||||||
bool ret = config_load(&original, "/dev/null", ¬s, &overrides, false, false);
|
bool ret = config_load(&original, "/dev/null", ¬s, &overrides, false, false);
|
||||||
xassert(ret);
|
xassert(ret);
|
||||||
|
|
||||||
struct config *clone = config_clone(&original);
|
//struct config *clone = config_clone(&original);
|
||||||
xassert(clone != NULL);
|
//xassert(clone != NULL);
|
||||||
xassert(clone != &original);
|
//xassert(clone != &original);
|
||||||
|
|
||||||
config_free(&original);
|
config_free(&original);
|
||||||
config_free(clone);
|
//config_free(clone);
|
||||||
free(clone);
|
//free(clone);
|
||||||
|
|
||||||
fcft_fini();
|
fcft_fini();
|
||||||
|
|
||||||
|
|
@ -3473,6 +3515,7 @@ config_free(struct config *conf)
|
||||||
free_key_binding_list(&conf->bindings.search);
|
free_key_binding_list(&conf->bindings.search);
|
||||||
free_key_binding_list(&conf->bindings.url);
|
free_key_binding_list(&conf->bindings.url);
|
||||||
free_key_binding_list(&conf->bindings.mouse);
|
free_key_binding_list(&conf->bindings.mouse);
|
||||||
|
tll_free_and_free(conf->mouse.selection_override_modifiers, free);
|
||||||
|
|
||||||
tll_foreach(conf->env_vars, it) {
|
tll_foreach(conf->env_vars, it) {
|
||||||
free(it->item.name);
|
free(it->item.name);
|
||||||
|
|
@ -3603,6 +3646,7 @@ check_if_font_is_monospaced(const char *pattern,
|
||||||
return is_monospaced;
|
return is_monospaced;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
xkb_mod_mask_t
|
xkb_mod_mask_t
|
||||||
conf_modifiers_to_mask(const struct seat *seat,
|
conf_modifiers_to_mask(const struct seat *seat,
|
||||||
const struct config_key_modifiers *modifiers)
|
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;
|
mods |= modifiers->super << seat->kbd.mod_super;
|
||||||
return mods;
|
return mods;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
|
||||||
13
config.h
13
config.h
|
|
@ -38,12 +38,14 @@ struct config_font {
|
||||||
};
|
};
|
||||||
DEFINE_LIST(struct config_font);
|
DEFINE_LIST(struct config_font);
|
||||||
|
|
||||||
|
#if 0
|
||||||
struct config_key_modifiers {
|
struct config_key_modifiers {
|
||||||
bool shift;
|
bool shift;
|
||||||
bool alt;
|
bool alt;
|
||||||
bool ctrl;
|
bool ctrl;
|
||||||
bool super;
|
bool super;
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
struct argv {
|
struct argv {
|
||||||
char **args;
|
char **args;
|
||||||
|
|
@ -74,9 +76,12 @@ enum key_binding_type {
|
||||||
MOUSE_BINDING,
|
MOUSE_BINDING,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef tll(char *) config_modifier_list_t;
|
||||||
|
|
||||||
struct config_key_binding {
|
struct config_key_binding {
|
||||||
int action; /* One of the varios bind_action_* enums from wayland.h */
|
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 {
|
union {
|
||||||
/* Key bindings */
|
/* Key bindings */
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -263,7 +268,8 @@ struct config {
|
||||||
struct {
|
struct {
|
||||||
bool hide_when_typing;
|
bool hide_when_typing;
|
||||||
bool alternate_scroll_mode;
|
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;
|
} mouse;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
|
@ -375,10 +381,11 @@ struct config *config_clone(const struct config *old);
|
||||||
bool config_font_parse(const char *pattern, struct config_font *font);
|
bool config_font_parse(const char *pattern, struct config_font *font);
|
||||||
void config_font_list_destroy(struct config_font_list *font_list);
|
void config_font_list_destroy(struct config_font_list *font_list);
|
||||||
|
|
||||||
|
#if 0
|
||||||
struct seat;
|
struct seat;
|
||||||
xkb_mod_mask_t
|
xkb_mod_mask_t
|
||||||
conf_modifiers_to_mask(
|
conf_modifiers_to_mask(
|
||||||
const struct seat *seat, const struct config_key_modifiers *modifiers);
|
const struct seat *seat, const struct config_key_modifiers *modifiers);
|
||||||
|
#endif
|
||||||
bool check_if_font_is_monospaced(
|
bool check_if_font_is_monospaced(
|
||||||
const char *pattern, user_notifications_t *notifications);
|
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_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.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)
|
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)
|
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)
|
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)
|
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)
|
if (seat->kbd.mod_caps != XKB_MOD_INVALID)
|
||||||
seat->kbd.kitty_significant |= 1 << seat->kbd.mod_caps;
|
seat->kbd.kitty_significant |= 1 << seat->kbd.mod_caps;
|
||||||
if (seat->kbd.mod_num != XKB_MOD_INVALID)
|
if (seat->kbd.mod_num != XKB_MOD_INVALID)
|
||||||
|
|
@ -876,7 +878,8 @@ UNITTEST
|
||||||
void
|
void
|
||||||
get_current_modifiers(const struct seat *seat,
|
get_current_modifiers(const struct seat *seat,
|
||||||
xkb_mod_mask_t *effective,
|
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 (unlikely(seat->kbd.xkb_state == NULL)) {
|
||||||
if (effective != NULL)
|
if (effective != NULL)
|
||||||
|
|
@ -886,24 +889,27 @@ get_current_modifiers(const struct seat *seat,
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
|
const xkb_mod_mask_t locked =
|
||||||
|
xkb_state_serialize_mods(seat->kbd.xkb_state, XKB_STATE_MODS_LOCKED);
|
||||||
|
|
||||||
if (effective != NULL) {
|
if (effective != NULL) {
|
||||||
*effective = xkb_state_serialize_mods(
|
*effective = xkb_state_serialize_mods(
|
||||||
seat->kbd.xkb_state, XKB_STATE_MODS_EFFECTIVE);
|
seat->kbd.xkb_state, XKB_STATE_MODS_EFFECTIVE);
|
||||||
|
|
||||||
|
if (filter_locked)
|
||||||
|
*effective &= ~locked;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (consumed != NULL) {
|
if (consumed != NULL) {
|
||||||
*consumed = xkb_state_key_get_consumed_mods2(
|
*consumed = xkb_state_key_get_consumed_mods2(
|
||||||
seat->kbd.xkb_state, key, XKB_CONSUMED_MODE_XKB);
|
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 {
|
struct kbd_ctx {
|
||||||
xkb_layout_index_t layout;
|
xkb_layout_index_t layout;
|
||||||
xkb_keycode_t key;
|
xkb_keycode_t key;
|
||||||
|
|
@ -985,7 +991,7 @@ legacy_kbd_protocol(struct seat *seat, struct terminal *term,
|
||||||
|
|
||||||
/* Any modifiers, besides shift active? */
|
/* Any modifiers, besides shift active? */
|
||||||
const xkb_mod_mask_t shift_mask = 1 << seat->kbd.mod_shift;
|
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;
|
modify_other_keys2_in_effect = true;
|
||||||
|
|
||||||
else {
|
else {
|
||||||
|
|
@ -1173,7 +1179,7 @@ kitty_kbd_protocol(struct seat *seat, struct terminal *term,
|
||||||
xkb_state_update_key(
|
xkb_state_update_key(
|
||||||
seat->kbd.xkb_state, ctx->key, pressed ? XKB_KEY_DOWN : XKB_KEY_UP);
|
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(
|
consumed = xkb_state_key_get_consumed_mods2(
|
||||||
seat->kbd.xkb_state, ctx->key, XKB_CONSUMED_MODE_GTK);
|
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);
|
seat->kbd.xkb_state, ctx->key, pressed ? XKB_KEY_UP : XKB_KEY_DOWN);
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} 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
|
/* Re-retrieve the consumed modifiers using the GTK mode, to
|
||||||
better match kitty. */
|
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;
|
const bool composed = compose_status == XKB_COMPOSE_COMPOSED;
|
||||||
|
|
||||||
xkb_mod_mask_t mods, consumed;
|
xkb_mod_mask_t mods, consumed;
|
||||||
get_current_modifiers(seat, &mods, &consumed, key);
|
get_current_modifiers(seat, &mods, &consumed, key, true);
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
xkb_layout_index_t layout_idx =
|
xkb_layout_index_t layout_idx =
|
||||||
xkb_state_key_get_layout(seat->kbd.xkb_state, key);
|
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);
|
start_repeater(seat, key);
|
||||||
|
|
||||||
search_input(
|
search_input(
|
||||||
seat, term, bindings, key, sym, mods, consumed, locked,
|
seat, term, bindings, key, sym, mods, consumed,
|
||||||
raw_syms, raw_count, serial);
|
raw_syms, raw_count, serial);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1519,7 +1521,7 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial,
|
||||||
start_repeater(seat, key);
|
start_repeater(seat, key);
|
||||||
|
|
||||||
urls_input(
|
urls_input(
|
||||||
seat, term, bindings, key, sym, mods, consumed, locked,
|
seat, term, bindings, key, sym, mods, consumed,
|
||||||
raw_syms, raw_count, serial);
|
raw_syms, raw_count, serial);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1527,7 +1529,7 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial,
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
for (size_t i = 0; i < 32; i++) {
|
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));
|
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 */
|
/* Match translated symbol */
|
||||||
if (bind->k.sym == sym &&
|
if (bind->k.sym == sym &&
|
||||||
bind->mods == (bind_mods & ~bind_consumed) &&
|
bind->mods == (mods & ~consumed) &&
|
||||||
execute_binding(seat, term, bind, serial, 1))
|
execute_binding(seat, term, bind, serial, 1))
|
||||||
{
|
{
|
||||||
|
LOG_WARN("matched translated symbol");
|
||||||
goto maybe_repeat;
|
goto maybe_repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bind->mods != bind_mods || bind_mods != (mods & ~locked))
|
if (bind->mods != mods)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Match untranslated symbols */
|
/* 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] &&
|
if (bind->k.sym == raw_syms[i] &&
|
||||||
execute_binding(seat, term, bind, serial, 1))
|
execute_binding(seat, term, bind, serial, 1))
|
||||||
{
|
{
|
||||||
|
LOG_WARN("matched untranslated symbol");
|
||||||
goto maybe_repeat;
|
goto maybe_repeat;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1575,6 +1579,7 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial,
|
||||||
if (code->item == key &&
|
if (code->item == key &&
|
||||||
execute_binding(seat, term, bind, serial, 1))
|
execute_binding(seat, term, bind, serial, 1))
|
||||||
{
|
{
|
||||||
|
LOG_WARN("matched raw key code");
|
||||||
goto maybe_repeat;
|
goto maybe_repeat;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2239,8 +2244,7 @@ static const struct key_binding *
|
||||||
xassert(bindings != NULL);
|
xassert(bindings != NULL);
|
||||||
|
|
||||||
xkb_mod_mask_t mods;
|
xkb_mod_mask_t mods;
|
||||||
get_current_modifiers(seat, &mods, NULL, 0);
|
get_current_modifiers(seat, &mods, NULL, 0, true);
|
||||||
mods &= seat->kbd.bind_significant;
|
|
||||||
|
|
||||||
/* Ignore selection override modifiers when
|
/* Ignore selection override modifiers when
|
||||||
* matching modifiers */
|
* matching modifiers */
|
||||||
|
|
@ -2293,8 +2297,7 @@ static const struct key_binding *
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct config_key_modifiers no_mods = {0};
|
if (tll_length(binding->modifiers) > 0) {
|
||||||
if (memcmp(&binding->modifiers, &no_mods, sizeof(no_mods)) != 0) {
|
|
||||||
/* Binding has modifiers */
|
/* Binding has modifiers */
|
||||||
continue;
|
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,
|
void get_current_modifiers(const struct seat *seat,
|
||||||
xkb_mod_mask_t *effective,
|
xkb_mod_mask_t *effective,
|
||||||
xkb_mod_mask_t *consumed,
|
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);
|
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);
|
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
|
static void NOINLINE
|
||||||
convert_key_binding(struct key_set *set,
|
convert_key_binding(struct key_set *set,
|
||||||
const struct config_key_binding *conf_binding,
|
const struct config_key_binding *conf_binding,
|
||||||
|
|
@ -411,7 +429,7 @@ convert_key_binding(struct key_set *set,
|
||||||
{
|
{
|
||||||
const struct seat *seat = set->seat;
|
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);
|
xkb_keysym_t sym = maybe_repair_key_combo(seat, conf_binding->k.sym, mods);
|
||||||
|
|
||||||
struct key_binding binding = {
|
struct key_binding binding = {
|
||||||
|
|
@ -469,7 +487,7 @@ convert_mouse_binding(struct key_set *set,
|
||||||
.type = MOUSE_BINDING,
|
.type = MOUSE_BINDING,
|
||||||
.action = conf_binding->action,
|
.action = conf_binding->action,
|
||||||
.aux = &conf_binding->aux,
|
.aux = &conf_binding->aux,
|
||||||
.mods = conf_modifiers_to_mask(set->seat, &conf_binding->modifiers),
|
.mods = mods_to_mask(set->seat, &conf_binding->modifiers),
|
||||||
.m = {
|
.m = {
|
||||||
.button = conf_binding->m.button,
|
.button = conf_binding->m.button,
|
||||||
.count = conf_binding->m.count,
|
.count = conf_binding->m.count,
|
||||||
|
|
@ -509,7 +527,7 @@ load_keymap(struct key_set *set)
|
||||||
convert_url_bindings(set);
|
convert_url_bindings(set);
|
||||||
convert_mouse_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);
|
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,
|
search_input(struct seat *seat, struct terminal *term,
|
||||||
const struct key_binding_set *bindings, uint32_t key,
|
const struct key_binding_set *bindings, uint32_t key,
|
||||||
xkb_keysym_t sym, xkb_mod_mask_t mods, xkb_mod_mask_t consumed,
|
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,
|
const xkb_keysym_t *raw_syms, size_t raw_count,
|
||||||
uint32_t serial)
|
uint32_t serial)
|
||||||
{
|
{
|
||||||
LOG_DBG("search: input: sym=%d/0x%x, mods=0x%08x, consumed=0x%08x",
|
LOG_DBG("search: input: sym=%d/0x%x, mods=0x%08x, consumed=0x%08x",
|
||||||
sym, sym, mods, consumed);
|
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
|
enum xkb_compose_status compose_status = seat->kbd.xkb_compose_state != NULL
|
||||||
? xkb_compose_state_get_status(seat->kbd.xkb_compose_state)
|
? xkb_compose_state_get_status(seat->kbd.xkb_compose_state)
|
||||||
: XKB_COMPOSE_NOTHING;
|
: XKB_COMPOSE_NOTHING;
|
||||||
|
|
@ -1399,7 +1394,7 @@ search_input(struct seat *seat, struct terminal *term,
|
||||||
|
|
||||||
/* Match translated symbol */
|
/* Match translated symbol */
|
||||||
if (bind->k.sym == sym &&
|
if (bind->k.sym == sym &&
|
||||||
bind->mods == (bind_mods & ~bind_consumed)) {
|
bind->mods == (mods & ~consumed)) {
|
||||||
|
|
||||||
if (execute_binding(seat, term, bind, serial,
|
if (execute_binding(seat, term, bind, serial,
|
||||||
&update_search_result, &search_direction,
|
&update_search_result, &search_direction,
|
||||||
|
|
@ -1410,7 +1405,7 @@ search_input(struct seat *seat, struct terminal *term,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bind->mods != bind_mods || bind_mods != (mods & ~locked))
|
if (bind->mods != mods)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Match untranslated symbols */
|
/* Match untranslated symbols */
|
||||||
|
|
|
||||||
1
search.h
1
search.h
|
|
@ -11,7 +11,6 @@ void search_input(
|
||||||
struct seat *seat, struct terminal *term,
|
struct seat *seat, struct terminal *term,
|
||||||
const struct key_binding_set *bindings, uint32_t key,
|
const struct key_binding_set *bindings, uint32_t key,
|
||||||
xkb_keysym_t sym, xkb_mod_mask_t mods, xkb_mod_mask_t consumed,
|
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,
|
const xkb_keysym_t *raw_syms, size_t raw_count,
|
||||||
uint32_t serial);
|
uint32_t serial);
|
||||||
void search_add_chars(struct terminal *term, const char *text, size_t len);
|
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;
|
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 =
|
const struct key_binding_set *bindings =
|
||||||
key_binding_for(term->wl->key_binding_manager, term->conf, seat);
|
key_binding_for(term->wl->key_binding_manager, term->conf, seat);
|
||||||
|
|
|
||||||
|
|
@ -787,6 +787,17 @@ test_section_csd(void)
|
||||||
config_free(&conf);
|
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
|
static void
|
||||||
test_key_binding(struct context *ctx, bool (*parse_fun)(struct context *ctx),
|
test_key_binding(struct context *ctx, bool (*parse_fun)(struct context *ctx),
|
||||||
int action, int max_action, const char *const *map,
|
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);
|
ctx->section, ctx->key, ctx->value, binding->action, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (binding->modifiers.ctrl != ctrl ||
|
bool have_ctrl = have_modifier(&binding->modifiers, XKB_MOD_NAME_CTRL);
|
||||||
binding->modifiers.alt != alt ||
|
bool have_alt = have_modifier(&binding->modifiers, XKB_MOD_NAME_ALT);
|
||||||
binding->modifiers.shift != shift ||
|
bool have_shift = have_modifier(&binding->modifiers, XKB_MOD_NAME_SHIFT);
|
||||||
binding->modifiers.super != super)
|
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"
|
BUG("[%s].%s=%s: modifier mismatch:\n"
|
||||||
" have: ctrl=%d, alt=%d, shift=%d, super=%d\n"
|
" have: ctrl=%d, alt=%d, shift=%d, super=%d\n"
|
||||||
" expected: ctrl=%d, alt=%d, shift=%d, super=%d",
|
" expected: ctrl=%d, alt=%d, shift=%d, super=%d",
|
||||||
ctx->section, ctx->key, ctx->value,
|
ctx->section, ctx->key, ctx->value,
|
||||||
binding->modifiers.ctrl, binding->modifiers.alt,
|
have_ctrl, have_alt, have_shift, have_super,
|
||||||
binding->modifiers.shift, binding->modifiers.super,
|
|
||||||
ctrl, alt, shift, super);
|
ctrl, alt, shift, super);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -970,14 +983,17 @@ _test_binding_collisions(struct context *ctx,
|
||||||
bindings.arr[0] = (struct config_key_binding){
|
bindings.arr[0] = (struct config_key_binding){
|
||||||
.action = (test_mode == FAIL_DIFFERENT_ACTION
|
.action = (test_mode == FAIL_DIFFERENT_ACTION
|
||||||
? max_action - 1 : max_action),
|
? max_action - 1 : max_action),
|
||||||
.modifiers = {.ctrl = true},
|
.modifiers = tll_init(),
|
||||||
.path = "unittest",
|
.path = "unittest",
|
||||||
};
|
};
|
||||||
|
tll_push_back(bindings.arr[0].modifiers, xstrdup(XKB_MOD_NAME_CTRL));
|
||||||
|
|
||||||
bindings.arr[1] = (struct config_key_binding){
|
bindings.arr[1] = (struct config_key_binding){
|
||||||
.action = max_action,
|
.action = max_action,
|
||||||
.modifiers = {.ctrl = true},
|
.modifiers = tll_init(),
|
||||||
.path = "unittest",
|
.path = "unittest",
|
||||||
};
|
};
|
||||||
|
tll_push_back(bindings.arr[1].modifiers, xstrdup(XKB_MOD_NAME_CTRL));
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case KEY_BINDING:
|
case KEY_BINDING:
|
||||||
|
|
@ -998,7 +1014,8 @@ _test_binding_collisions(struct context *ctx,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FAIL_MOUSE_OVERRIDE:
|
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;
|
break;
|
||||||
|
|
||||||
case FAIL_DIFFERENT_ARGV:
|
case FAIL_DIFFERENT_ARGV:
|
||||||
|
|
@ -1237,10 +1254,13 @@ test_section_text_bindings(void)
|
||||||
ctx.key = "\\y";
|
ctx.key = "\\y";
|
||||||
xassert(!parse_section_text_bindings(&ctx));
|
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.key = "abcd";
|
||||||
ctx.value = "InvalidMod+y";
|
ctx.value = "InvalidMod+y";
|
||||||
xassert(!parse_section_text_bindings(&ctx));
|
xassert(!parse_section_text_bindings(&ctx));
|
||||||
|
#endif
|
||||||
config_free(&conf);
|
config_free(&conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
12
url-mode.c
12
url-mode.c
|
|
@ -145,28 +145,22 @@ void
|
||||||
urls_input(struct seat *seat, struct terminal *term,
|
urls_input(struct seat *seat, struct terminal *term,
|
||||||
const struct key_binding_set *bindings, uint32_t key,
|
const struct key_binding_set *bindings, uint32_t key,
|
||||||
xkb_keysym_t sym, xkb_mod_mask_t mods, xkb_mod_mask_t consumed,
|
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,
|
const xkb_keysym_t *raw_syms, size_t raw_count,
|
||||||
uint32_t serial)
|
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 */
|
/* Key bindings */
|
||||||
tll_foreach(bindings->url, it) {
|
tll_foreach(bindings->url, it) {
|
||||||
const struct key_binding *bind = &it->item;
|
const struct key_binding *bind = &it->item;
|
||||||
|
|
||||||
/* Match translated symbol */
|
/* Match translated symbol */
|
||||||
if (bind->k.sym == sym &&
|
if (bind->k.sym == sym &&
|
||||||
bind->mods == (bind_mods & ~bind_consumed))
|
bind->mods == (mods & ~consumed))
|
||||||
{
|
{
|
||||||
execute_binding(seat, term, bind, serial);
|
execute_binding(seat, term, bind, serial);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bind->mods != bind_mods || bind_mods != (mods & ~locked))
|
if (bind->mods != mods)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (size_t i = 0; i < raw_count; i++) {
|
for (size_t i = 0; i < raw_count; i++) {
|
||||||
|
|
@ -196,7 +190,7 @@ urls_input(struct seat *seat, struct terminal *term,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mods & ~consumed & ~locked)
|
if (mods & ~consumed)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
char32_t wc = xkb_state_key_get_utf32(seat->kbd.xkb_state, key);
|
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,
|
void urls_input(struct seat *seat, struct terminal *term,
|
||||||
const struct key_binding_set *bindings, uint32_t key,
|
const struct key_binding_set *bindings, uint32_t key,
|
||||||
xkb_keysym_t sym, xkb_mod_mask_t mods, xkb_mod_mask_t consumed,
|
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,
|
const xkb_keysym_t *raw_syms, size_t raw_count,
|
||||||
uint32_t serial);
|
uint32_t serial);
|
||||||
|
|
|
||||||
|
|
@ -128,8 +128,8 @@ struct seat {
|
||||||
xkb_mod_index_t mod_caps;
|
xkb_mod_index_t mod_caps;
|
||||||
xkb_mod_index_t mod_num;
|
xkb_mod_index_t mod_num;
|
||||||
|
|
||||||
xkb_mod_mask_t bind_significant;
|
xkb_mod_mask_t legacy_significant; /* Significant modifiers for the legacy keyboard protocol */
|
||||||
xkb_mod_mask_t kitty_significant;
|
xkb_mod_mask_t kitty_significant; /* Significant modifiers for the kitty keyboard protocol */
|
||||||
|
|
||||||
xkb_keycode_t key_arrow_up;
|
xkb_keycode_t key_arrow_up;
|
||||||
xkb_keycode_t key_arrow_down;
|
xkb_keycode_t key_arrow_down;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue