neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

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:
Msrc/nvim/tui/input.c | 14+++++++++++---
Mtest/functional/terminal/tui_spec.lua | 20+++++++++++++++++---
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()