commit adbd33027f5f30bd0781f8a49478ed41b4e49c93
parent 862e676efc7cbbaf1f6fe4901be6f97cb82a0e28
Author: zeertzjq <zeertzjq@outlook.com>
Date: Sat, 3 May 2025 12:09:28 +0800
fix(tui): don't try to add unsupported modifiers (#33799)
Problem: The TUI doesn't forward a key properly when it has unsupported
modifiers like NumLock.
Solution: Don't try to add modifiers when only unsupported modifiers are
present.
Related #33791
Diffstat:
2 files changed, 28 insertions(+), 6 deletions(-)
diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c
@@ -21,6 +21,7 @@
#include "nvim/tui/input_defs.h"
#include "nvim/tui/termkey/driver-csi.h"
#include "nvim/tui/termkey/termkey.h"
+#include "nvim/tui/termkey/termkey_defs.h"
#include "nvim/tui/tui.h"
#include "nvim/ui_client.h"
@@ -249,6 +250,13 @@ static size_t handle_termkey_modifiers(TermKeyKey *key, char *buf, size_t buflen
return len;
}
+enum {
+ KEYMOD_SUPER = 1 << 3,
+ KEYMOD_META = 1 << 5,
+ KEYMOD_RECOGNIZED = (TERMKEY_KEYMOD_SHIFT | TERMKEY_KEYMOD_ALT | TERMKEY_KEYMOD_CTRL
+ | KEYMOD_SUPER | KEYMOD_META),
+};
+
/// Handle modifiers not handled by libtermkey.
/// Currently only Super ("D-") and Meta ("T-") are supported in Nvim.
///
@@ -257,10 +265,10 @@ 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
+ if (key->modifiers & KEYMOD_SUPER) {
len += (size_t)snprintf(buf + len, buflen - len, "D-");
}
- if (key->modifiers & 32) { // Meta
+ if (key->modifiers & KEYMOD_META) {
len += (size_t)snprintf(buf + len, buflen - len, "T-");
}
assert(len < buflen);
@@ -445,7 +453,7 @@ static void tk_getkeys(TermInput *input, bool force)
continue;
}
- if (key.type == TERMKEY_TYPE_UNICODE && !key.modifiers) {
+ if (key.type == TERMKEY_TYPE_UNICODE && !(key.modifiers & KEYMOD_RECOGNIZED)) {
forward_simple_utf8(input, &key);
} else if (key.type == TERMKEY_TYPE_UNICODE
|| key.type == TERMKEY_TYPE_FUNCTION
diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua
@@ -440,19 +440,32 @@ describe('TUI', function()
]])
end)
- it('interprets <Esc>[27u as <Esc>', function()
+ it('interprets <Esc> encoded with kitty keyboard protocol', function()
child_session:request(
'nvim_exec2',
[[
nnoremap <M-;> <Nop>
nnoremap <Esc> AESC<Esc>
+ nnoremap <C-Esc> ACtrlEsc<Esc>
+ nnoremap <D-Esc> ASuperEsc<Esc>
nnoremap ; Asemicolon<Esc>
]],
{}
)
+ -- Works with no modifier
feed_data('\027[27u;')
- screen:expect([[
- ESCsemicolo^n |
+ expect_child_buf_lines({ 'ESCsemicolon' })
+ -- Works with Ctrl modifier
+ feed_data('\027[27;5u')
+ expect_child_buf_lines({ 'ESCsemicolonCtrlEsc' })
+ -- Works with Super modifier
+ feed_data('\027[27;9u')
+ expect_child_buf_lines({ 'ESCsemicolonCtrlEscSuperEsc' })
+ -- Works with NumLock modifier (which should be the same as no modifier) #33799
+ feed_data('\027[27;129u')
+ expect_child_buf_lines({ 'ESCsemicolonCtrlEscSuperEscESC' })
+ screen:expect([[
+ ESCsemicolonCtrlEscSuperEscES^C |
{4:~ }|*3
{5:[No Name] [+] }|
|
@@ -461,6 +474,7 @@ describe('TUI', function()
-- <Esc>; should be recognized as <M-;> when <M-;> is mapped
feed_data('\027;')
screen:expect_unchanged()
+ expect_child_buf_lines({ 'ESCsemicolonCtrlEscSuperEscESC' })
end)
it('interprets <Esc><Nul> as <M-C-Space> #17198', function()