fix(tui): use 0x7f as Backspace on Windows with VT input (#37679)

Problem:  0x08 is treated as Backspace instead of Ctrl-H on Windows.
Solution: Treat 0x7f as Backspace if VT input is enabled, so that 0x08
          is treated as Ctrl-H.

Ref: https://github.com/microsoft/terminal/issues/4949
This commit is contained in:
zeertzjq
2026-02-03 21:40:40 +08:00
committed by GitHub
parent 41cac54325
commit 16680e57ba
3 changed files with 16 additions and 7 deletions

View File

@@ -132,6 +132,9 @@ void tinput_init(TermInput *input, Loop *loop, TerminfoEntry *ti)
input->ttimeout = (bool)p_ttimeout;
input->ttimeoutlen = p_ttm;
// setup input handle
rstream_init_fd(loop, &input->read_stream, input->in_fd);
for (size_t i = 0; i < ARRAY_SIZE(kitty_key_map_entry); i++) {
pmap_put(int)(&kitty_key_map, kitty_key_map_entry[i].key, (ptr_t)kitty_key_map_entry[i].name);
}
@@ -145,9 +148,6 @@ void tinput_init(TermInput *input, Loop *loop, TerminfoEntry *ti)
int curflags = termkey_get_canonflags(input->tk);
termkey_set_canonflags(input->tk, curflags | TERMKEY_CANON_DELBS);
// setup input handle
rstream_init_fd(loop, &input->read_stream, input->in_fd);
// initialize a timer handle for handling ESC with libtermkey
uv_timer_init(&loop->uv, &input->timer_handle);
input->timer_handle.data = input;

View File

@@ -2515,19 +2515,29 @@ static void flush_buf(TUIData *tui)
/// Try to get "kbs" code from stty because "the terminfo kbs entry is extremely
/// unreliable." (Vim, Bash, and tmux also do this.)
/// On Windows, use 0x7f as Backspace if VT input has been enabled by stream_init().
///
/// @see tmux/tty-keys.c fe4e9470bb504357d073320f5d305b22663ee3fd
/// @see https://bugzilla.redhat.com/show_bug.cgi?id=142659
static const char *tui_get_stty_erase(int fd)
/// @see https://github.com/microsoft/terminal/issues/4949
static const char *tui_get_stty_erase(TermInput *input)
{
static char stty_erase[2] = { 0 };
#if defined(HAVE_TERMIOS_H)
struct termios t;
if (tcgetattr(fd, &t) != -1) {
if (tcgetattr(input->in_fd, &t) != -1) {
stty_erase[0] = (char)t.c_cc[VERASE];
stty_erase[1] = NUL;
DLOG("stty/termios:erase=%s", stty_erase);
}
#elif defined(MSWIN)
DWORD dwMode;
if (((uv_handle_t *)&input->read_stream.s.uv)->type == UV_TTY
&& GetConsoleMode(input->read_stream.s.uv.tty.handle, &dwMode)
&& (dwMode & ENABLE_VIRTUAL_TERMINAL_INPUT)) {
stty_erase[0] = '\x7f';
stty_erase[1] = NUL;
}
#endif
return stty_erase;
}
@@ -2539,7 +2549,7 @@ static const char *tui_tk_ti_getstr(const char *name, const char *value, void *d
TermInput *input = data;
static const char *stty_erase = NULL;
if (stty_erase == NULL) {
stty_erase = tui_get_stty_erase(input->in_fd);
stty_erase = tui_get_stty_erase(input);
}
if (strequal(name, "key_backspace")) {

View File

@@ -2830,7 +2830,6 @@ describe('TUI', function()
end)
it('<C-h> #10134', function()
t.skip(is_os('win'), 'FIXME: does not work on Windows #36660')
local screen = tt.setup_child_nvim({
'--clean',
'--cmd',