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

(cherry picked from commit adbd33027f)
This commit is contained in:
zeertzjq
2025-05-03 12:09:28 +08:00
committed by github-actions[bot]
parent e5e69f758d
commit cf73f21c07
2 changed files with 27 additions and 5 deletions

View File

@ -21,6 +21,7 @@
#include "nvim/tui/input_defs.h" #include "nvim/tui/input_defs.h"
#include "nvim/tui/termkey/driver-csi.h" #include "nvim/tui/termkey/driver-csi.h"
#include "nvim/tui/termkey/termkey.h" #include "nvim/tui/termkey/termkey.h"
#include "nvim/tui/termkey/termkey_defs.h"
#include "nvim/tui/tui.h" #include "nvim/tui/tui.h"
#include "nvim/ui_client.h" #include "nvim/ui_client.h"
@ -248,6 +249,13 @@ static size_t handle_termkey_modifiers(TermKeyKey *key, char *buf, size_t buflen
return len; 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. /// Handle modifiers not handled by libtermkey.
/// Currently only Super ("D-") and Meta ("T-") are supported in Nvim. /// Currently only Super ("D-") and Meta ("T-") are supported in Nvim.
/// ///
@ -256,10 +264,10 @@ static size_t handle_more_modifiers(TermKeyKey *key, char *buf, size_t buflen)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_WARN_UNUSED_RESULT
{ {
size_t len = 0; size_t len = 0;
if (key->modifiers & 8) { // Super if (key->modifiers & KEYMOD_SUPER) {
len += (size_t)snprintf(buf + len, buflen - len, "D-"); 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-"); len += (size_t)snprintf(buf + len, buflen - len, "T-");
} }
assert(len < buflen); assert(len < buflen);
@ -444,7 +452,7 @@ static void tk_getkeys(TermInput *input, bool force)
continue; continue;
} }
if (key.type == TERMKEY_TYPE_UNICODE && !key.modifiers) { if (key.type == TERMKEY_TYPE_UNICODE && !(key.modifiers & KEYMOD_RECOGNIZED)) {
forward_simple_utf8(input, &key); forward_simple_utf8(input, &key);
} else if (key.type == TERMKEY_TYPE_UNICODE } else if (key.type == TERMKEY_TYPE_UNICODE
|| key.type == TERMKEY_TYPE_FUNCTION || key.type == TERMKEY_TYPE_FUNCTION

View File

@ -440,19 +440,32 @@ describe('TUI', function()
]]) ]])
end) end)
it('interprets <Esc>[27u as <Esc>', function() it('interprets <Esc> encoded with kitty keyboard protocol', function()
child_session:request( child_session:request(
'nvim_exec2', 'nvim_exec2',
[[ [[
nnoremap <M-;> <Nop> nnoremap <M-;> <Nop>
nnoremap <Esc> AESC<Esc> nnoremap <Esc> AESC<Esc>
nnoremap <C-Esc> ACtrlEsc<Esc>
nnoremap <D-Esc> ASuperEsc<Esc>
nnoremap ; Asemicolon<Esc> nnoremap ; Asemicolon<Esc>
]], ]],
{} {}
) )
-- Works with no modifier
feed_data('\027[27u;') feed_data('\027[27u;')
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([[ screen:expect([[
ESCsemicolo^n | ESCsemicolonCtrlEscSuperEscES^C |
{4:~ }|*3 {4:~ }|*3
{5:[No Name] [+] }| {5:[No Name] [+] }|
| |
@ -461,6 +474,7 @@ describe('TUI', function()
-- <Esc>; should be recognized as <M-;> when <M-;> is mapped -- <Esc>; should be recognized as <M-;> when <M-;> is mapped
feed_data('\027;') feed_data('\027;')
screen:expect_unchanged() screen:expect_unchanged()
expect_child_buf_lines({ 'ESCsemicolonCtrlEscSuperEscESC' })
end) end)
it('interprets <Esc><Nul> as <M-C-Space> #17198', function() it('interprets <Esc><Nul> as <M-C-Space> #17198', function()