Add kitty keyboard protocol support#4912
Conversation
|
Thanks. Will take a closer look some time soon. Only thing is I think this should be rolled into |
|
A few other comments:
It looks good otherwise, apart from a few style nits which can be easily fixed later. I didn't test it yet though. Thanks! |
|
I'm having a second run at it. I've been testing it - mostly good, found a couple of things. Incorporating these and will then attack your points before others can take a 2nd look. |
8adabb0 to
c92e59b
Compare
|
Ok, I've had a 2nd pass at it now. I've gone over it, fixed a few small things and added some tests and so forth. I've also incorporated the feedback - apart from somehow rolling it into extended-keys / extended-keys-format. That one I don't feel very certain around an approach for. Let me know what you think @nicm btw, the python test script is there as I didn't manage to produce a bash version. It's feel like it should be possible but I failed at it. |
|
Code looks good to me, a couple of minor things:
It's a bit of a pity they chose to occupy four modifiers to CSI u for this one feature when one would have been fine (or even extending CSI m further), but there is little to be done about that now. I tried it lightly in ghostty, at least the normal extended keys seem to still work (such as |
|
With this PR, if I run the following on Kitty 0.46 or Ghostty 1.3, most keys do not register in the resulting window (including normal letters). I'm using macOS Sequoia. I'm also using fish 4.5.0 (though I'm not sure where this matters). I think kitty-keys do not play well with extended-keys. I am also getting some separate problems with keys like ^D. When I ran pressing ^D results in Here is a log where I start tmux with According to AI:
(but I didn't trim it :) Here is AI's theory on what the bug with ^D is:
I was also sorry to discover that "release events" are discovered. My primary use-case for this was a terminal app that uses those (it's a weird one, Ki editor, it has so-called "momentary layers"). But, according to the same AI, fixing that would be a large project. |
|
Actually, I'm experiencing the bug where typing "abc" doesn't work even without turning on kitty-keys, just with this PR and It works fine without this PR, at d32088b. This does only become a problem with fish, though (I have fish 4.5.0), using dash here avoids the bug. But this is a bigger problem because this breaks existing users with |
|
Oh, and thank you for working on it! |
|
@nicm thanks for the input! I'll have a look at the smaller adjustments. In terms of folding into extended-keys it seemed "safer" to make it an opt-in for this specific case and being able to tell that mode and this mode apart. But I think you're right it could be combined. Up for attempting that. @ilyagr thanks for giving it a spin. And it draws out that I just tried this in ghostty on linux (minor testing in kitty), with kitty-keys on. I have completely glossed over any manual testing without kitty-keys being on. I think kitty-keys always is generally a bad idea - you'll get key codes sent to apps that don't support them etc. First port of call is some manual testing (outside the existing regression tests) with kitty-keys off, and with both extended-keys and kitty-keys on. I put the PR forward mostly to gage interest - I'm aware it needs a lot more testing! |
|
My quick test (zsh user, don't belive foot comes into this), on ghostty 1.2.3:
So the path that's (definitely) broken is always+always. In general testing I'm not sure it's good to ever use kitty-keys always - it'll send the wrong key codes to various applications that don't know how to handle them. I haven't taken the time to understand what extended-keys really does - but as a first step I'll fix the gridlock case. |
|
I'd be inclined to remove the It's OK to keep |
|
This removes the conflict as an intermediate step. I think I agree that it does not make sense to allow always for kitty-keys - I can't see a case where it makes sense. I'm far from an expert here though - very much open to bigger brains with more experience in this field opining! |
|
Addressed the items raised in your previous comment @nicm . Unifying kitty-keys and extended-keys is the item left out, and the one I feel a bit nervous around attempting. I'd love for people to test this more, and for more knowlegable people to comment if it makes sense to remove kitty-keys = always. I think we need to build a bit of confidence via more wide spread testing before confirming all is well. In my daily usage I haven't found any issues, but there's a lot of corner cases out there I'm sure given the rich domain of tty interactions.. |
|
You can't reproduce the issue where ^D doesn't work with |
It reproduces for me with alacritty + zsh. It's even somewhat stranger. ^D doesn't work right after tmux was started. But it starts working after Vim (which enabled the Kitty Keyboard Protocol) exited... |
|
So this is why I'm thinking that it basically never makes sense to set kitty-keys = always. With this setting you will ALWAYS have the kitty protocol active, meaning that anything running that doesn't speak it, will not get the inputs it expects. In this mode, Ctrl-D works fine if the thing you run inside of of your session support the protocol, otherwise it'll get "garbage" keys. If you run with kitty-keys = on then you will only send the extended protocol keys when the running application actually supports the protocol, and if it doesn't support it the expected codes are sent. The sane path. I strongly suggest testing with kitty-keys = on. And as I suggested before, I think it makes sense to not even support = always and I remove that from the PR. I only added it by symmetry to how the extended-keys was done, but now I think it likely doesn't make sense. |
|
Ah, okay. I set Vim requests the Kitty Keyboard Protocol by emitting Let's take ctrl-3 as example key combination. When I request disambiguate escape codes in plain Alacritty I get: This is a CSI escape code as specified by the Kitty Keyboard Protocol. Key 51 is "3", modifier is 1 + 4 for ctrl. But when I do the same in tmux I get: This is a legacy escape code. ctrl combines with "3" maps to Key 27 which is Escape. So even if disambiguate escape codes where requested, a legacy escape is send. This looks like a bug in tmux. Or am I missunderstanding something? |
|
Probably a bug! I'll look at it. |
56480e1 to
48cf779
Compare
|
@Yamagi I've attempted to deal with the outer vs inner kitty mode with this latest commit. Any feedback welcome! |
|
Hello @sundbp and thanks a lot for your efforts on this feature! I did a quick test on your latest commit with |
|
Great to hear. I'm not sure what the appropriate path to getting enough confidence to merge this looks like.. I gave it a go as it seemed that missing kitty keyboard mode is a growing "gap" in tmux, but I'm far from an expert in this space. As it touches on fairly central key code interpretation paths, even in off mode we still touch new code (that should do nothing :)) in the main input paths - hence it it does seem high impact in case I've messed something up. Review by others and real world testing is only thing I can think of. |
|
I can comfirm that Vim is now working fine with
For me this is one of the most important additions to tmux in the last years. While I can work with legacys keys and modifyOtherKeys work around the most annoying problems, the Kitty Keyboard Protocol is another level. Reliable mappings for ctrl-$number alone are a huge advantages. I'll use this branch on my work laptop over the next few days. I'll report any bugs I encounter and give feedback if there are no remaining problems for me. |
I've been doing the same and I think I found an issue with compose key and accent letters. This is what I get outside of tmux when I type And this is what I get in tmux ( |
|
Great - I don't type those kinds of characters so hadn't tried this. I pushed a fix for this case - please see if it behaves as expected @cippaciong |
|
Awesome, works now! Thanks @sundbp for the quick fix |
|
Hey! 👋 I'm super excited to try this out as I'm using dte which supports both the legacy mode ( I don't think it makes sense to ever set I'm going to report back soon! |
The kitty keyboard protocol escape sequences are universal and not something terminals implement differently, so the terminfo-style capability indirection is unnecessary. Hardcode the sequences directly and remove the kitkeys terminal feature.
When an application inside tmux requests kitty keyboard disambiguation with kitty-keys=on, mirror the visible screen's kitty flags onto the outer terminal instead of leaving the outer terminal in legacy mode. This lets ambiguous legacy combinations such as Ctrl-3 reach the pane as CSI-u rather than being collapsed to Escape. Also add an end-to-end regression that exercises the kitty-keys=on path and verifies Ctrl-3 is delivered as CSI 51;5u after the pane requests disambiguation.
When a pane enables kitty keyboard disambiguation, tmux must still pass text-producing input through as plain UTF-8 unless report-all mode is enabled. tmux was incorrectly encoding non-ASCII text through the CSI-u path in input_key_kitty(). For composed text such as è, it also used tmux's internal packed utf8_char value as the CSI-u numeric field instead of the actual Unicode codepoint, producing invalid sequences like CSI 1107339459u. Fix this by: - falling back to raw UTF-8 for text-producing keys in disambiguate-only mode, including non-ASCII text - converting tmux's internal Unicode representation back to a real codepoint before emitting CSI-u when CSI-u encoding is actually needed Add a regression for requested kitty mode with UTF-8 text input, alongside the existing requested Ctrl-3 coverage.`
Drop the public always value from kitty-keys and delete the runtime behavior that existed only for that mode. Keep kitty-keys as a two-value choice (off/on) and make on truthful: tmux now enables kitty keyboard handling only after the outer terminal has negotiated kitty support and pane state requests it. This change: - removes always from the option table - deletes unconditional kitty push/state seeding paths in tty/screen code - removes the input parser fallback that was enabled only by always - preserves active pushed kitty flags across capability query replies - rewrites the kitty regression to negotiate support explicitly under on - verifies set -g kitty-keys always now fails as an invalid value
Collapse kitty and xterm/csi-u enhanced key handling into a single configuration surface by removing the separate kitty-keys option and adding kitty as an extended-keys-format choice. Gate pane input state, key encoding, and outer tty negotiation on the selected format so tmux exposes only one enhanced key protocol at a time. When extended-keys=always, force kitty disambiguation for kitty format and xterm mode 1 for xterm/csi-u. Preserve mixed-client behavior by falling back to legacy input for clients that do not support the selected protocol, including popup jobs, while keeping pane_key_mode and the documentation truthful. Update the regressions to cover the exclusive protocol model and pin the input-keys regression to xterm format explicitly.
f380193 to
0f5d6a6
Compare
|
@nicm I've made an attempt at folding kitty keys into extended-keys here, and looked at the 4 bits. The fix to the input-keys.sh test works nicely for me - thanks! I haven't looked at the binding issue. I'm not sure I see that one clearly enough to have a solution in mind! |
|
Looks good. I would probably have added them to The point with the key bindings is that I should be able to do for example This means tmux needs to enable enough for its own use immediately - you can see this with the existing extended keys, tmux turns them on in In an ideal world, any combination of terminal and application would work as far as possible, so tmux would request either Kitty keys or extended keys (depending on the
That is, if tmux is configured for standard extended keys, but the application requests Kitty, the request would be ignored and X10 keys only would be sent. And similarly if tmux is configured for Kitty keys and the application requests standard extended keys. I think that is fine. |
|
Thanks for the feedback. I'll try to take that onboard and see what I can do. Worth noting I haven't done a ton of manual testing post the re-organization. Anyone following along is very welcome to refresh and give it a spin! |
Preserve the outer terminal's current kitty keyboard flags from CSI ? u so tmux can restore them correctly after pushing its own state. Recompute kitty mode during feature refreshes using the client's current visible screen so pane-requested kitty flags are not dropped until the next redraw. Add regressions for eager kitty enablement, tmux bindings before pane requests, wrong-format requests in both on and always modes, and correct pane_key_mode reporting. Update the manpage to match the actual fallback behavior.
|
@nicm had a first stab at the remaining parts. not done too much manual testing yet - but thought I'd share to sense check direction. |
|
Only did a quick test but works much better for me, I can bind keys only supported by Kitty like The idea looks right, tmux always turns on Kitty keys. I guess you will need to mediate between what tmux needs and what the active pane wants in terms of flags? Like we do for SGR mouse mode (and extended keys eg we always use mode 2). |
FWIW, there's some prior art for the format of these modifiers in Emacs. I opted to use the same |
|
No strong opinion from me. Happy to go with emacs conventions if that has general support. |
|
I don't really mind, I think |
|
Great work! Really miss this feature. Hope it will cover Ctrl+RET too |
|
Is this now ready to go or what is left to do? Thanks |
|
Is there a reason why release events are discarded? Is the support for the protocol intended to be partial at the moment? |
|
It's this line (also mentioned in your original PR description): I'm working a TUI that needed to detect key release events, so I'm wondering why it's getting dropped in this PR. |
|
@musjj I can't recall a reason right now.. I'm guessing I may have found issues with it and "punted" on it as not a super common use case. Any chance you could experiment with your use case to see if you can get support for it working? |
|
Ok tested your PR and key release events are not reported, unfortunately. Modifier key events are reported though, so your PR is already partially working. I tried to tweak your PR here: musjj@5ddf17d But I'm still not getting any key release events. Do you have any idea why it's not working? |
|
@musjj thanks for doing the leg work. I need to re-engage with this PR as I've forgotten a lot of it by now :/ I'll try to have a look at it and wrap this one up asap. |
tcell v3.4.0 decodes kitty/CSI-u keys, so v0.59's default <meta+enter> now works in raw Ghostty (jesseduffield/lazygit#3237). Inside tmux, <cmd+enter> still does nothing — tmux strips the kitty progressive enhancement handshake (tracking tmux/tmux#4912). Use <ctrl+s> as fallback there; deprecated upstream but functional.
Implement the kitty progressive keyboard enhancement protocol, allowing tmux to negotiate richer key encoding with supporting terminals (ghostty, kitty, foot, etc.) and forward it to applications that opt in.
New server option 'kitty-keys' (off/on/always):
Protocol support:
Disambiguate mode (flag 1) follows the kitty spec for legacy fallback:
New key definitions: F13-F35, keypad keys, media keys, modifier keys, Super/Hyper/RealMeta modifier bits, Caps Lock/Num Lock modifier bits. Key string parsing and display supports Super-, Hyper-, and RealMeta- prefixes.
Terminal feature 'kitkeys' adds Enkitk/Dskitk capabilities. Foot included in default features; other terminals auto-detected via the CSI ? u query or configurable via terminal-features.