wezterm icon indicating copy to clipboard operation
wezterm copied to clipboard

Incorrect "Disambiguate escape codes" behaviour using enable_kitty_keyboard

Open AThePeanut4 opened this issue 1 year ago • 1 comments

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

AThePeanut4 avatar Apr 25 '23 23:04 AThePeanut4

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

cstrahan avatar Feb 16 '24 04:02 cstrahan