mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-03-17 05:33:52 -04:00
input: don’t allow non-significant modifiers when matching untranslated symbols
When matching “untranslated” bindings (by matching the base symbol of the key, e.g. ctrl+shift+2 in US layout), require that no non-significant modifiers are active. This fixes an issue where AltGr was “ignored”, and would cause certain combinations to match a key binding. Example: ctrl+altgr+0, on many European layouts matched against the default ctrl+0 (reset the font size), instead of emitting ^] To make this work, we now need to filter out “locked” modifiers (e.g. NumLock and CapsLock). Otherwise having e.g. NumLock active would prevent *all* untranslated matching to fail. Closes #983
This commit is contained in:
parent
dcdbb3613c
commit
1e63dddb89
6 changed files with 33 additions and 9 deletions
|
|
@ -89,6 +89,8 @@
|
||||||
overrides on the command line.
|
overrides on the command line.
|
||||||
* Crash when seat has no keyboard
|
* Crash when seat has no keyboard
|
||||||
(https://codeberg.org/dnkl/foot/issues/963).
|
(https://codeberg.org/dnkl/foot/issues/963).
|
||||||
|
* Key presses with e.g. `AltGr` triggering key combinations with the
|
||||||
|
base symbol (https://codeberg.org/dnkl/foot/issues/983).
|
||||||
|
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
|
||||||
19
input.c
19
input.c
|
|
@ -1030,6 +1030,12 @@ get_current_modifiers(const struct seat *seat,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
@ -1488,8 +1494,11 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial,
|
||||||
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);
|
||||||
|
|
||||||
xkb_mod_mask_t bind_mods = mods & seat->kbd.bind_significant;
|
const xkb_mod_mask_t locked = get_locked_modifiers(seat);
|
||||||
xkb_mod_mask_t bind_consumed = consumed & seat->kbd.bind_significant;
|
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);
|
||||||
|
|
@ -1504,7 +1513,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, key, sym, bind_mods, bind_consumed,
|
seat, term, key, sym, mods, consumed, locked,
|
||||||
raw_syms, raw_count, serial);
|
raw_syms, raw_count, serial);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1514,7 +1523,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, key, sym, bind_mods, bind_consumed,
|
seat, term, key, sym, mods, consumed, locked,
|
||||||
raw_syms, raw_count, serial);
|
raw_syms, raw_count, serial);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1553,7 +1562,7 @@ key_press_release(struct seat *seat, struct terminal *term, uint32_t serial,
|
||||||
goto maybe_repeat;
|
goto maybe_repeat;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bind->mods != bind_mods)
|
if (bind->mods != bind_mods || bind_mods != (mods & ~locked))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Match untranslated symbols */
|
/* Match untranslated symbols */
|
||||||
|
|
|
||||||
9
search.c
9
search.c
|
|
@ -822,11 +822,16 @@ execute_binding(struct seat *seat, struct terminal *term,
|
||||||
void
|
void
|
||||||
search_input(struct seat *seat, struct terminal *term, uint32_t key,
|
search_input(struct seat *seat, struct terminal *term, 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", sym, sym, mods);
|
LOG_DBG("search: input: sym=%d/0x%x, mods=0x%08x", sym, sym, mods);
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
@ -840,7 +845,7 @@ search_input(struct seat *seat, struct terminal *term, uint32_t key,
|
||||||
|
|
||||||
/* Match translated symbol */
|
/* Match translated symbol */
|
||||||
if (bind->k.sym == sym &&
|
if (bind->k.sym == sym &&
|
||||||
bind->mods == (mods & ~consumed)) {
|
bind->mods == (bind_mods & ~bind_consumed)) {
|
||||||
|
|
||||||
if (execute_binding(seat, term, bind, serial,
|
if (execute_binding(seat, term, bind, serial,
|
||||||
&update_search_result, &redraw))
|
&update_search_result, &redraw))
|
||||||
|
|
@ -850,7 +855,7 @@ search_input(struct seat *seat, struct terminal *term, uint32_t key,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bind->mods != mods)
|
if (bind->mods != bind_mods || bind_mods != (mods & ~locked))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Match untranslated symbols */
|
/* Match untranslated symbols */
|
||||||
|
|
|
||||||
1
search.h
1
search.h
|
|
@ -8,6 +8,7 @@ void search_cancel(struct terminal *term);
|
||||||
void search_input(
|
void search_input(
|
||||||
struct seat *seat, struct terminal *term, uint32_t key,
|
struct seat *seat, struct terminal *term, 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);
|
||||||
|
|
|
||||||
10
url-mode.c
10
url-mode.c
|
|
@ -119,22 +119,28 @@ activate_url(struct seat *seat, struct terminal *term, const struct url *url)
|
||||||
void
|
void
|
||||||
urls_input(struct seat *seat, struct terminal *term, uint32_t key,
|
urls_input(struct seat *seat, struct terminal *term, 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(seat->kbd.bindings.url, it) {
|
tll_foreach(seat->kbd.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 == (mods & ~consumed))
|
bind->mods == (bind_mods & ~bind_consumed))
|
||||||
{
|
{
|
||||||
execute_binding(seat, term, bind, serial);
|
execute_binding(seat, term, bind, serial);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bind->mods != mods)
|
if (bind->mods != bind_mods || bind_mods != (mods & ~locked))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (size_t i = 0; i < raw_count; i++) {
|
for (size_t i = 0; i < raw_count; i++) {
|
||||||
|
|
|
||||||
|
|
@ -21,5 +21,6 @@ void urls_reset(struct terminal *term);
|
||||||
|
|
||||||
void urls_input(struct seat *seat, struct terminal *term, uint32_t key,
|
void urls_input(struct seat *seat, struct terminal *term, 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);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue