Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect "Disambiguate escape codes" behaviour using enable_kitty_keyboard #3621

Open
AThePeanut4 opened this issue Apr 25, 2023 · 2 comments
Labels
bug Something isn't working

Comments

@AThePeanut4
Copy link

AThePeanut4 commented Apr 25, 2023

What Operating System(s) are you seeing this problem on?

Linux Wayland

Which Wayland compositor or X11 Window manager(s) are you using?

Hyprland

WezTerm version

20230425-083942-6686adba

Did you try the latest nightly build to see if the issue is better (or worse!) than your current version?

Yes, and I updated the version box above to show the version of the nightly that I tried

Describe the bug

The main issue I'm having is that Neovim is detecting the delete character as <CTRL-H>, but when investigating I found a bunch of differences between Wezterm and Kitty when the "Disambiguate escape codes" enhancement is enabled.

To Reproduce

I used another slightly modified version of the program in #3526 to test it, now having 'c' exit the loop instead of Enter:

#include <termios.h> 
#include <stdio.h> 
#include <unistd.h> 

int main()
{
    struct termios _ts = {};
    int _ts_r = tcgetattr(1, &_ts);
    if (_ts_r == 0) {
        struct termios ts_ne = _ts;
        //ts_ne.c_lflag &= ~(ECHO | ECHONL);
        cfmakeraw(&ts_ne);
        if (tcsetattr(1, TCSADRAIN, &ts_ne ) != 0) {
            perror("TTYBackend: tcsetattr");
        }
    }


    fprintf(stderr, "\x1b[?1049h");
    fprintf(stderr, "\x1b[?1000h");
    fprintf(stderr, "\x1b[?1001h");
    fprintf(stderr, "\x1b[?1002h");

    fprintf(stderr, "\x1b[=1u");

    for (;;) {
        char ch = 0;
        if (read(0, &ch, 1) <= 0) break;
        if (ch <= 0x20 || ch == 0x7f) {
            if (ch == 0x1b) fprintf(stderr, " ");
            fprintf(stderr, "\\x%02x", (unsigned int)(unsigned char)ch);
            } else {
            fprintf(stderr, "%c", ch);
        }
        if (ch == 'c') break;
    }
    fprintf(stderr, "\x1b[?1049l");
    fprintf(stderr, "\x1b[?1000l");
    fprintf(stderr, "\x1b[?1001l");
    fprintf(stderr, "\x1b[?1002l");

    fprintf(stderr, "\x1b[=0u");

    if (tcsetattr(1, TCSADRAIN, &_ts ) != 0) {
        perror("TTYBackend: tcsetattr");
    }
}

Configuration

config.enable_kitty_keyboard = true

Expected Behavior

The reason for the issue is that Wezterm is sending \x08 for <DEL>, which is the same code that <CTRL-H> would send. From the keyboard protocol docs here, when in "Disambiguate escape codes" mode, all non-text generating events should emit the new unambiguous codes and not the legacy codes.

These are the important differences I found by basically pressing every key on my keyboard:

Key ESC F1 F5 TAB BACKSPACE DEL HOME ENTER KP_ENTER PAUSE/BREAK MENU
Kitty \x1b[27u \x1b[P \x1b[15~ \x09 \x7f \x1b[3~ \x1b[H \x0d \x1b[57414u \x1b[57362u \x1b[57363u
Kitty (numlock on) \x1b[27;129u \x1b[1;129P \x1b[15;129~ \x1b[9;129u \x1b[127;129u \x1b[3;129~ \x1b[1;129H \x1b[13;129u \x1b[57414;129u \x1b[57362;129u \x1b[57363;129u
Wezterm \x1b \x1b[11;1~ \x1b[15;1~ \x09 \x7f \x08 \x1b[1;1H \x0d \x0d (nothing) (nothing)
Wezterm (numlock on) \x1b \x1b[11;129~ \x1b[15;129~ \x09 \x7f \x08 \x1b[1;129H \x0d \x0d (nothing) (nothing)

For Backspace, Tab and Enter, the Kitty docs are (ironically) a bit ambiguous on whether lock modifiers (ie Num Lock and Caps Lock) should cause those keys to stop emitting their legacy codes. In this case I actually think wezterm has the more sensible behaviour, especially given the reasoning in the docs for why those three specific keys are an exception to the new encoding system. If a program using the kitty protocol crashes, and you always have Num Lock enabled (like I do), then you wouldn't be able to use Backspace, Tab and Enter for recovery in the shell until Num Lock is disabled.

For F1, F5 and HOME (and almost all other non-text generating keys), Wezterm is sending the default modifier field of 1 along with the normal code, where Kitty just omits the modifier field since 1 is to be assumed if the field is missing. The Kitty docs don't seem to explicitly require the modifier field to be omitted if it is 1, but since the codes are different I thought I might as well include it on this list. I don't think that is an issue.

For F1, I also just included it because the codes are different - the Kitty docs allow for both forms. F2 and F4 are also different for the same reason. Again, I don't think it's an issue.

For Escape, Delete and the keypad Enter key, the behaviour is definitely incorrect - the legacy codes should not be sent. For Pause/Break and Menu, these should of course send the correct codes instead of nothing at all, but adding support for those keys is definitely less important and would be more of a nice to have.

Logs

No response

Anything else?

No response

@cstrahan
Copy link

I'm running into this as well while trying to use atuin, where I can't type symbols or uppercase letters (i.e. the shift key isn't handled as expected).

Within kitty, if I run kitten show_key -m kitty (the kitten binary is included with kitty) and hold shift, type a, and release shift, I see:

shift+LEFT_SHIFT PRESS 
CSI 57441 ; 2 u

shift+a PRESS A
CSI 97 : 65 ; 2 ; 65 u
Shifted key: A 

shift+a RELEASE 
CSI 97 : 65 ; 2 : 3 u
Shifted key: A 

LEFT_SHIFT RELEASE 
CSI 57441 ; 1 : 3 u

When I run kitten show_key -m kitty In wezterm and repeat the above, I see:

a PRESS A
CSI 97 : 65 ; 1 ; 65 u
Shifted key: A

shift+a RELEASE
CSI 97 : 65 ; 2 : 3 u
Shifted key: A

@robrecord
Copy link

robrecord commented Jan 9, 2025

I was able to work around this issue (delete key not being sent as expected) by adding the following to my keybinds:

keys = {
...    
    { key = "Delete", action = act.SendKey { key = "Delete" } },
...
}

This suggests that WezTerm knows how to send the correct codes, but perhaps has some compatibility layer or keymap turned on?

I have the following (what I assume to be potentially relevant) config:

config.disable_default_key_bindings = true
config.allow_win32_input_mode = false
config.enable_kitty_keyboard = true
config.enable_csi_u_key_encoding = false
config.term = "wezterm"

For me this was affecting correct use of the delete key in nushell, and the helix editor.

I would love for this to be fixed; sadly I am too new to rust to feel comfortable investigating this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants