mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
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.
This commit is contained in:
parent
a389dc2f95
commit
b5cb69f8a4
@ -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)
|
||||
{
|
||||
|
@ -124,6 +124,7 @@ typedef enum {
|
||||
} TermKeyMouseEvent;
|
||||
|
||||
typedef enum {
|
||||
TERMKEY_EVENT_UNKNOWN,
|
||||
TERMKEY_EVENT_PRESS,
|
||||
TERMKEY_EVENT_REPEAT,
|
||||
TERMKEY_EVENT_RELEASE,
|
||||
|
Loading…
Reference in New Issue
Block a user