feat(tui): support Super and Meta modifiers (#24357)

This commit is contained in:
zeertzjq
2023-07-15 15:03:01 +08:00
committed by GitHub
parent 33e1a8cd70
commit 622ae2f53e
2 changed files with 79 additions and 21 deletions

View File

@@ -229,6 +229,44 @@ static void tinput_enqueue(TermInput *input, char *buf, size_t size)
rbuffer_write(input->key_buffer, buf, size);
}
/// Handle TERMKEY_KEYMOD_* modifiers, i.e. Shift, Alt and Ctrl.
///
/// @return The number of bytes written into "buf", excluding the final NUL.
static size_t handle_termkey_modifiers(TermKeyKey *key, char *buf, size_t buflen)
FUNC_ATTR_WARN_UNUSED_RESULT
{
size_t len = 0;
if (key->modifiers & TERMKEY_KEYMOD_SHIFT) { // Shift
len += (size_t)snprintf(buf + len, sizeof(buf) - len, "S-");
}
if (key->modifiers & TERMKEY_KEYMOD_ALT) { // Alt
len += (size_t)snprintf(buf + len, sizeof(buf) - len, "A-");
}
if (key->modifiers & TERMKEY_KEYMOD_CTRL) { // Ctrl
len += (size_t)snprintf(buf + len, sizeof(buf) - len, "C-");
}
assert(len < buflen);
return len;
}
/// Handle modifiers not handled by libtermkey.
/// Currently only Super ("D-") and Meta ("T-") are supported in Nvim.
///
/// @return The number of bytes written into "buf", excluding the final NUL.
static size_t handle_more_modifiers(TermKeyKey *key, char *buf, size_t buflen)
FUNC_ATTR_WARN_UNUSED_RESULT
{
size_t len = 0;
if (key->modifiers & 8) { // Super
len += (size_t)snprintf(buf + len, buflen - len, "D-");
}
if (key->modifiers & 32) { // Meta
len += (size_t)snprintf(buf + len, buflen - len, "T-");
}
assert(len < buflen);
return len;
}
static void handle_kitty_key_protocol(TermInput *input, TermKeyKey *key)
{
const char *name = map_get(int, cstr_t)(&kitty_key_map, (int)key->code.codepoint);
@@ -236,16 +274,10 @@ static void handle_kitty_key_protocol(TermInput *input, TermKeyKey *key)
char buf[64];
size_t len = 0;
buf[len++] = '<';
if (key->modifiers & TERMKEY_KEYMOD_SHIFT) {
len += (size_t)snprintf(buf + len, sizeof(buf) - len, "S-");
}
if (key->modifiers & TERMKEY_KEYMOD_ALT) {
len += (size_t)snprintf(buf + len, sizeof(buf) - len, "A-");
}
if (key->modifiers & TERMKEY_KEYMOD_CTRL) {
len += (size_t)snprintf(buf + len, sizeof(buf) - len, "C-");
}
len += handle_termkey_modifiers(key, buf + len, sizeof(buf) - len);
len += handle_more_modifiers(key, buf + len, sizeof(buf) - len);
len += (size_t)snprintf(buf + len, sizeof(buf) - len, "%s>", name);
assert(len < sizeof(buf));
tinput_enqueue(input, buf, len);
}
}
@@ -270,6 +302,7 @@ static void forward_simple_utf8(TermInput *input, TermKeyKey *key)
ptr++;
}
assert(len < sizeof(buf));
tinput_enqueue(input, buf, len);
}
@@ -297,7 +330,7 @@ static void forward_modified_utf8(TermInput *input, TermKeyKey *key)
if ((key->modifiers & TERMKEY_KEYMOD_CTRL)
&& !(key->modifiers & TERMKEY_KEYMOD_SHIFT)
&& ASCII_ISUPPER(key->code.codepoint)) {
assert(len <= 62);
assert(len + 2 < sizeof(buf));
// Make room for the S-
memmove(buf + 3, buf + 1, len - 1);
buf[1] = 'S';
@@ -306,6 +339,16 @@ static void forward_modified_utf8(TermInput *input, TermKeyKey *key)
}
}
char more_buf[25];
size_t more_len = handle_more_modifiers(key, more_buf, sizeof(more_buf));
if (more_len > 0) {
assert(len + more_len < sizeof(buf));
memmove(buf + 1 + more_len, buf + 1, len - 1);
memcpy(buf + 1, more_buf, more_len);
len += more_len;
}
assert(len < sizeof(buf));
tinput_enqueue(input, buf, len);
}
@@ -343,17 +386,9 @@ static void forward_mouse_event(TermInput *input, TermKeyKey *key)
row--; col--; // Termkey uses 1-based coordinates
buf[len++] = '<';
if (key->modifiers & TERMKEY_KEYMOD_SHIFT) {
len += (size_t)snprintf(buf + len, sizeof(buf) - len, "S-");
}
if (key->modifiers & TERMKEY_KEYMOD_CTRL) {
len += (size_t)snprintf(buf + len, sizeof(buf) - len, "C-");
}
if (key->modifiers & TERMKEY_KEYMOD_ALT) {
len += (size_t)snprintf(buf + len, sizeof(buf) - len, "A-");
}
len += handle_termkey_modifiers(key, buf + len, sizeof(buf) - len);
// Doesn't actually work because there are only 3 bits (0x1c) for modifiers.
// len += handle_more_modifiers(key, buf + len, sizeof(buf) - len);
if (button == 1) {
len += (size_t)snprintf(buf + len, sizeof(buf) - len, "Left");
@@ -390,6 +425,7 @@ static void forward_mouse_event(TermInput *input, TermKeyKey *key)
}
len += (size_t)snprintf(buf + len, sizeof(buf) - len, "><%d,%d>", col, row);
assert(len < sizeof(buf));
tinput_enqueue(input, buf, len);
}