diff options
author | Gregory Anders <greg@gpanders.com> | 2024-12-31 12:16:25 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-12-31 12:16:25 -0600 |
commit | b5cb69f8a4a310fb3f18e79bcf5c7ed41d635a48 (patch) | |
tree | d8ee38a615937377f1fd9f4a4fb067f234672480 | |
parent | a389dc2f950ef89492dfc2d8334e421d2252cddf (diff) | |
download | rneovim-b5cb69f8a4a310fb3f18e79bcf5c7ed41d635a48.tar.gz rneovim-b5cb69f8a4a310fb3f18e79bcf5c7ed41d635a48.tar.bz2 rneovim-b5cb69f8a4a310fb3f18e79bcf5c7ed41d635a48.zip |
fix(tui): handle key events for arrow and function keys (#31804)
Arrow and function keys do not use CSI u with the kitty keyboard
protocol. For example, the Up arrow key uses CSI A, and the function
keys use a variety of different CSI sequences.
Until now, termkey only parsed subparams used by key events for CSI u
sequences. The result being that any key which did not use CSI u (e.g.
arrow and function keys) was being emitted twice by termkey since it was
not recognizing the separate press and release events.
This commit makes termkey also parse subparams for other key sequences
so that the release key events do not send duplicate keys.
-rw-r--r-- | src/nvim/tui/termkey/driver-csi.c | 50 | ||||
-rw-r--r-- | src/nvim/tui/termkey/termkey_defs.h | 1 |
2 files changed, 37 insertions, 14 deletions
diff --git a/src/nvim/tui/termkey/driver-csi.c b/src/nvim/tui/termkey/driver-csi.c index 3f54c874d1..9741ec72b9 100644 --- a/src/nvim/tui/termkey/driver-csi.c +++ b/src/nvim/tui/termkey/driver-csi.c @@ -31,11 +31,20 @@ static TermKeyResult handle_csi_ss3_full(TermKey *tk, TermKeyKey *key, int cmd, if (nparams > 1 && params[1].param != NULL) { int arg = 0; - result = termkey_interpret_csi_param(params[1], &arg, NULL, NULL); + int subparam = 0; + size_t nsubparams = 1; + result = termkey_interpret_csi_param(params[1], &arg, &subparam, &nsubparams); if (result != TERMKEY_RES_KEY) { return result; } + if (nsubparams > 0) { + key->event = parse_key_event(subparam); + if (key->event == TERMKEY_EVENT_UNKNOWN) { + return TERMKEY_RES_NONE; + } + } + key->modifiers = arg - 1; } else { key->modifiers = 0; @@ -103,11 +112,20 @@ static TermKeyResult handle_csifunc(TermKey *tk, TermKeyKey *key, int cmd, TermK int args[3]; if (nparams > 1 && params[1].param != NULL) { - result = termkey_interpret_csi_param(params[1], &args[1], NULL, NULL); + int subparam = 0; + size_t nsubparams = 1; + result = termkey_interpret_csi_param(params[1], &args[1], &subparam, &nsubparams); if (result != TERMKEY_RES_KEY) { return result; } + if (nsubparams > 0) { + key->event = parse_key_event(subparam); + if (key->event == TERMKEY_EVENT_UNKNOWN) { + return TERMKEY_RES_NONE; + } + } + key->modifiers = args[1] - 1; } else { key->modifiers = 0; @@ -178,18 +196,8 @@ static TermKeyResult handle_csi_u(TermKey *tk, TermKeyKey *key, int cmd, TermKey } if (nsubparams > 0) { - switch (subparam) { - case 1: - key->event = TERMKEY_EVENT_PRESS; - break; - case 2: - key->event = TERMKEY_EVENT_REPEAT; - break; - case 3: - key->event = TERMKEY_EVENT_RELEASE; - break; - default: - // Invalid event + key->event = parse_key_event(subparam); + if (key->event == TERMKEY_EVENT_UNKNOWN) { return TERMKEY_RES_NONE; } } @@ -430,6 +438,20 @@ TermKeyResult termkey_interpret_modereport(TermKey *tk, const TermKeyKey *key, i #define CHARAT(i) (tk->buffer[tk->buffstart + (i)]) +static TermKeyEvent parse_key_event(int n) +{ + switch (n) { + case 1: + return TERMKEY_EVENT_PRESS; + case 2: + return TERMKEY_EVENT_REPEAT; + case 3: + return TERMKEY_EVENT_RELEASE; + default: + return TERMKEY_EVENT_UNKNOWN; + } +} + static TermKeyResult parse_csi(TermKey *tk, size_t introlen, size_t *csi_len, TermKeyCsiParam params[], size_t *nargs, unsigned *commandp) { diff --git a/src/nvim/tui/termkey/termkey_defs.h b/src/nvim/tui/termkey/termkey_defs.h index 09d3a5615a..87d3f63447 100644 --- a/src/nvim/tui/termkey/termkey_defs.h +++ b/src/nvim/tui/termkey/termkey_defs.h @@ -124,6 +124,7 @@ typedef enum { } TermKeyMouseEvent; typedef enum { + TERMKEY_EVENT_UNKNOWN, TERMKEY_EVENT_PRESS, TERMKEY_EVENT_REPEAT, TERMKEY_EVENT_RELEASE, |