kovidgoyal / kitty

Cross-platform, fast, feature-rich, GPU based terminal
https://sw.kovidgoyal.net/kitty/
GNU General Public License v3.0
23.72k stars 958 forks source link

[RFC] New keyboard reporting protocol #3248

Closed kovidgoyal closed 3 years ago

kovidgoyal commented 3 years ago

Since the previous kitty keyboard reporting protocol was not well received, I have implemented a new one. The new proposal is backward compatible by default producing the exact same bytes as traditional terminals. Applications that want to enable more robust key handling can use progressive enhancement to request more sophisticated behavior. Notable features:

1) Distinguish between press, repeat and release events. And the four modifiers ctrl, shift, alt, and super. 2) Have a "game mode" where all key events generate escape codes rather than some generating text and some escape codes 3) Disambiguate all key presses. Currently, many key presses are overlapping, generate the same bytes, the most egregious example being pressing Esc. 4) Allow reporting the pressed key, the shifted key and an "alternate" key in the default keyboard layout for advanced shortcut matching 5) Allow sending text encoded as unicode code points within the escape code rather than as separate UTF-8 bytes. This is useful for applications that want to customise text+key event handling. 6) Add a way to query for support and current progressive enhancement level. Also allow saving and restoring current enhancement level on a stack. 7) Make a canonical mapping of functional key names to PUA unicode characters. 8) Support any key from any language that is present in Unicode.

The new protocol has been implemented in master and will be in the next kitty release. The spec for the protocol is: https://sw.kovidgoyal.net/kitty/keyboard-protocol.html

The new escape code is based on the proposal in http://www.leonerd.org.uk/hacks/fixterms/ however, it is more general and fixes various bugs in that proposal.

If there are bugs or things I have overlooked, now is the time to point them out. You can test the implementation in kitty (which is mostly complete, barring bugs) by building kitty from master and running

kitty +kitten key_demo

inside kitty, to see how key events are reported with full progressive enhancement.

@msokalski Please check if this meets your game use case

@gnachman I believe iTerm implements some version of fixterms, so you might be interested in the bugs I discovered in that proposal

@leonerd Please look over the list of bugs in fixterms and correct me if I am wrong about anything https://sw.kovidgoyal.net/kitty/keyboard-protocol.html#bugs-in-fixterms

In particular, there is some controversy about how to encode shift+key, for instance should ctrl+shift+a be encoded as CSI 97; 6 or CSI 65; 5 IMO the former is correct. One reports the actual key pressed, not the shifted form of the key. In my spec the shifted form is available as a sub-parameter.

A general note, I will not entertain bike-shedding about the escape code format. Unless there is a serious bug or concern that causes backward incompatibility/inoperability.

msokalski commented 3 years ago

I think there's a tiny typo in the spec. Event types, examples section, release event uses two colons, shouldn't it be semicolon after the key-code?

CSI key-code:modifier:3 # this is a release event
kovidgoyal commented 3 years ago

On Sun, Jan 17, 2021 at 03:11:05AM -0800, msokalski wrote:

I think there's a tiny typo in the spec. Event types, examples section, release event uses two colons, shouldn't it be semicolon after the key-code?

CSI key-code:modifier:3 # this is a release event

No, that is a sub-parameter. Parameters are separated by semi-colons and sub-parameters by colons. This is for example how, how the CSI for underline styles, work.

msokalski commented 3 years ago

I'm now confused with semicolons for other events, isn't modifier a sub-parameter in that case?


CSI key-code;modifier:1  # this is a press event
CSI key-code;modifier:2  # this is a repeat event```
kovidgoyal commented 3 years ago

Oh yeah sorry my mistake, that was indeed a typo, there is semi-colon between key-code and modifier. I misread your previous post. Now fixed.

browser-bug commented 3 years ago

My keyboard specs:

rules:      evdev
model:      pc105
layout:     it
Trying to build keymap using the following components:
keycodes:   evdev+aliases(qwerty)
types:      complete
compat:     complete
symbols:    pc+it+inet(evdev)
geometry:   pc(pc105)
xkb_keymap {
    xkb_keycodes  { include "evdev+aliases(qwerty)" };
    xkb_types     { include "complete"  };
    xkb_compat    { include "complete"  };
    xkb_symbols   { include "pc+it+inet(evdev)" };
    xkb_geometry  { include "pc(pc105)" };
};

When I'm typing these combinations in terminal I get the following prints:

Keys                                Output          Expected
Shift+3 PRESS                       <ffffffff>      £
CSI 51 : 163 ; 2 u
Shifted key: £ 

Shift+è PRESS                       2;2u            é
CSI 232 : 233 : 91 ; 2 u
Shifted key: é Alternate key: [

Shift+ò PRESS                       2;2u            ç
CSI 242 : 231 : 59 ; 2 u
Shifted key: ç Alternate key: ;

Shift+à PRESS                       4;2u            °
CSI 224 : 176 : 39 ; 2 u
Shifted key: ° Alternate key: '

Shift+ù PRESS                       9;2u            §
CSI 249 : 167 : 92 ; 2 u
Shifted key: § Alternate key: \

Shift+ PRESS                        ;2u             Nothing
CSI 0 :  : 57433 ; 2 u
Alternate key: RIGHT_ALT

Tested with an empty config file. Is this normal or I'm missing something? The last one I showed is particularly annoying because inside nvim it gets interpreted as <space>.

kovidgoyal commented 3 years ago

@browser-bug Can you run kitty as kitty --debug-keyboard and post the output when pressing the problem keys. From your description it looks like those keys are not generating text on your system.

browser-bug commented 3 years ago

@kovidgoyal Sure thing. Following the order in which I posted.

Loading new XKB keymaps
Press xkb_keycode: 0x32 clean_sym: Shift_L composed_sym: Shift_L mods: none glfw_key: 57427 (LEFT_SHIFT) xkb_key: 65505 (Shift_L)
on_key_input: glfw key: 57427 native_code: 0xffe1 action: PRESS mods: 0x0 text: '' state: 0 ignoring as keyboard mode does not allow repeat events
Press xkb_keycode: 0xc clean_sym: 3 composed_sym: sterling text: £ mods: shift glfw_key: 51 (3) xkb_key: 51 (3) shifted_key: 163 (£)
on_key_input: glfw key: 51 native_code: 0x33 action: PRESS mods: 0x1 text: '£' state: 0 sent key to child
Release xkb_keycode: 0xc clean_sym: 3 mods: shift glfw_key: 51 (3) xkb_key: 51 (3) shifted_key: 163 (£)
on_key_input: glfw key: 51 native_code: 0x33 action: RELEASE mods: 0x1 text: '' state: 0 ignoring as keyboard mode does not allow release events
Release xkb_keycode: 0x32 clean_sym: Shift_L mods: shift glfw_key: 57427 (LEFT_SHIFT) xkb_key: 65505 (Shift_L)
on_key_input: glfw key: 57427 native_code: 0xffe1 action: RELEASE mods: 0x1 text: '' state: 0 ignoring as keyboard mode does not allow release events

Loading new XKB keymaps
Press xkb_keycode: 0x32 clean_sym: Shift_L composed_sym: Shift_L mods: none glfw_key: 57427 (LEFT_SHIFT) xkb_key: 65505 (Shift_L)
on_key_input: glfw key: 57427 native_code: 0xffe1 action: PRESS mods: 0x0 text: '' state: 0 ignoring as keyboard mode does not allow repeat events
Press xkb_keycode: 0xc clean_sym: 3 composed_sym: sterling text: £ mods: shift glfw_key: 51 (3) xkb_key: 51 (3) shifted_key: 163 (£)
on_key_input: glfw key: 51 native_code: 0x33 action: PRESS mods: 0x1 text: '£' state: 0 sent key to child
Release xkb_keycode: 0xc clean_sym: 3 mods: shift glfw_key: 51 (3) xkb_key: 51 (3) shifted_key: 163 (£)
on_key_input: glfw key: 51 native_code: 0x33 action: RELEASE mods: 0x1 text: '' state: 0 ignoring as keyboard mode does not allow release events
Release xkb_keycode: 0x32 clean_sym: Shift_L mods: shift glfw_key: 57427 (LEFT_SHIFT) xkb_key: 65505 (Shift_L)
on_key_input: glfw key: 57427 native_code: 0xffe1 action: RELEASE mods: 0x1 text: '' state: 0 ignoring as keyboard mode does not allow release events

Loading new XKB keymaps
Press xkb_keycode: 0x32 clean_sym: Shift_L composed_sym: Shift_L mods: none glfw_key: 57427 (LEFT_SHIFT) xkb_key: 65505 (Shift_L)
on_key_input: glfw key: 57427 native_code: 0xffe1 action: PRESS mods: 0x0 text: '' state: 0 ignoring as keyboard mode does not allow repeat events
Press xkb_keycode: 0xc clean_sym: 3 composed_sym: sterling text: £ mods: shift glfw_key: 51 (3) xkb_key: 51 (3) shifted_key: 163 (£)
on_key_input: glfw key: 51 native_code: 0x33 action: PRESS mods: 0x1 text: '£' state: 0 sent key to child
Release xkb_keycode: 0xc clean_sym: 3 mods: shift glfw_key: 51 (3) xkb_key: 51 (3) shifted_key: 163 (£)
on_key_input: glfw key: 51 native_code: 0x33 action: RELEASE mods: 0x1 text: '' state: 0 ignoring as keyboard mode does not allow release events
Release xkb_keycode: 0x32 clean_sym: Shift_L mods: shift glfw_key: 57427 (LEFT_SHIFT) xkb_key: 65505 (Shift_L)
on_key_input: glfw key: 57427 native_code: 0xffe1 action: RELEASE mods: 0x1 text: '' state: 0 ignoring as keyboard mode does not allow release events

Press xkb_keycode: 0x32 clean_sym: Shift_L composed_sym: Shift_L mods: none glfw_key: 57427 (LEFT_SHIFT) xkb_key: 65505 (Shift_L)
on_key_input: glfw key: 57427 native_code: 0xffe1 action: PRESS mods: 0x0 text: '' state: 0 ignoring as keyboard mode does not allow repeat events
Press xkb_keycode: 0x30 clean_sym: agrave composed_sym: degree text: ° mods: shift glfw_key: 224 (à) xkb_key: 224 (agrave) shifted_key: 176 (°) alternate_key: 39 (')
on_key_input: glfw key: 224 native_code: 0xe0 action: PRESS mods: 0x1 text: '°' state: 0 sent key to child
Release xkb_keycode: 0x30 clean_sym: agrave mods: shift glfw_key: 224 (à) xkb_key: 224 (agrave) shifted_key: 176 (°) alternate_key: 39 (')
on_key_input: glfw key: 224 native_code: 0xe0 action: RELEASE mods: 0x1 text: '' state: 0 ignoring as keyboard mode does not allow release events
Release xkb_keycode: 0x32 clean_sym: Shift_L mods: shift glfw_key: 57427 (LEFT_SHIFT) xkb_key: 65505 (Shift_L)
on_key_input: glfw key: 57427 native_code: 0xffe1 action: RELEASE mods: 0x1 text: '' state: 0 ignoring as keyboard mode does not allow release events

Press xkb_keycode: 0x32 clean_sym: Shift_L composed_sym: Shift_L mods: none glfw_key: 57427 (LEFT_SHIFT) xkb_key: 65505 (Shift_L)
on_key_input: glfw key: 57427 native_code: 0xffe1 action: PRESS mods: 0x0 text: '' state: 0 ignoring as keyboard mode does not allow repeat events
Press xkb_keycode: 0x33 clean_sym: ugrave composed_sym: section text: § mods: shift glfw_key: 249 (ù) xkb_key: 249 (ugrave) shifted_key: 167 (§) alternate_key: 92 (\)
on_key_input: glfw key: 249 native_code: 0xf9 action: PRESS mods: 0x1 text: '§' state: 0 sent key to child
Release xkb_keycode: 0x33 clean_sym: ugrave mods: shift glfw_key: 249 (ù) xkb_key: 249 (ugrave) shifted_key: 167 (§) alternate_key: 92 (\)
on_key_input: glfw key: 249 native_code: 0xf9 action: RELEASE mods: 0x1 text: '' state: 0 ignoring as keyboard mode does not allow release events
Release xkb_keycode: 0x32 clean_sym: Shift_L mods: shift glfw_key: 57427 (LEFT_SHIFT) xkb_key: 65505 (Shift_L)
on_key_input: glfw key: 57427 native_code: 0xffe1 action: RELEASE mods: 0x1 text: '' state: 0 ignoring as keyboard mode does not allow release events

Press xkb_keycode: 0x32 clean_sym: Shift_L composed_sym: Shift_L mods: none glfw_key: 57427 (LEFT_SHIFT) xkb_key: 65505 (Shift_L)
on_key_input: glfw key: 57427 native_code: 0xffe1 action: PRESS mods: 0x0 text: '' state: 0 ignoring as keyboard mode does not allow repeat events
Press xkb_keycode: 0x6c clean_sym: ISO_Level3_Shift composed_sym: ISO_Level3_Shift mods: shift glfw_key: 0 (UNKNOWN) xkb_key: 65027 (ISO_Level3_Shift) alternate_key: 57433 (RIGHT_ALT)
on_key_input: glfw key: 0 native_code: 0xfe03 action: PRESS mods: 0x1 text: '' state: 0 sent key to child
Release xkb_keycode: 0x6c clean_sym: ISO_Level3_Shift mods: shift glfw_key: 0 (UNKNOWN) xkb_key: 65027 (ISO_Level3_Shift) alternate_key: 57433 (RIGHT_ALT)
on_key_input: glfw key: 0 native_code: 0xfe03 action: RELEASE mods: 0x1 text: '' state: 0 ignoring release event for previous press that was handled as shortcutRelease xkb_keycode: 0x32 clean_sym: Shift_L mods: shift glfw_key: 57427 (LEFT_SHIFT) xkb_key: 65505 (Shift_L)
on_key_input: glfw key: 57427 native_code: 0xffe1 action: RELEASE mods: 0x1 text: '' state: 0 ignoring as keyboard mode does not allow release events
kovidgoyal commented 3 years ago

Should be fixed by my latest commit

browser-bug commented 3 years ago

@kovidgoyal now <backspace> <enter>, <tab> and LEFT_CTRL/RIGHT_CTRL don't work on my end.

kovidgoyal commented 3 years ago

enter and backspace were a typo, now fixed. What does left_ctrl and right_ctrl not work mean?

browser-bug commented 3 years ago

@kovidgoyal it was connected to the typo since any combination of L_CTRL/R_CTRL + wasn't sending any command. Now everything works.

browser-bug commented 3 years ago

I'm signaling others unexpected key combs:

Keys                                Output          Expected
Shift+MENU PRESS                    363;2u          $
CSI 57363 ; 2 u

Shift+ENTER PRESS                      ;2u          <enter>
CSI 13 ; 2 u

Shift+BACKSPACE PRESS                 7;2u          <del>  
CSI 127 ; 2 u

Shift+PAGE_UP PRESS                     2~          Nothing
CSI 5 ; 2 ~

Shift+PAGE_DOWN PRESS                   2~          Nothing
CSI 6 ; 2 ~

Ctrl+MENU PRESS                     363;5u          ^
CSI 57363 ; 5 u

Ctrl+PAGE_UP PRESS                      5~          Nothing
CSI 5 ; 5 ~

Ctrl+PAGE_DOWN PRESS                    5~          Nothing
CSI 6 ; 5 ~
Loading new XKB keymaps
Press xkb_keycode: 0x1d clean_sym: y composed_sym: y text: y mods: none glfw_key: 121 (y) xkb_key: 121 (y)
on_key_input: glfw key: 121 native_code: 0x79 action: PRESS mods: 0x0 text: 'y' state: 0 sent text to child
Release xkb_keycode: 0x1d clean_sym: y mods: none glfw_key: 121 (y) xkb_key: 121 (y)
on_key_input: glfw key: 121 native_code: 0x79 action: RELEASE mods: 0x0 text: '' state: 0 ignoring as keyboard mode does not allow release events
Press xkb_keycode: 0x85 clean_sym: Super_L composed_sym: Super_L mods: none glfw_key: 57443 (LEFT_SUPER) xkb_key: 65515 (Super_L)
on_key_input: glfw key: 57443 native_code: 0xffeb action: PRESS mods: 0x0 text: '' state: 0 ignoring as keyboard mode does not allow repeat events
bernardo@MS-7821 ➜  ~ kitty --debug-keyboard
Loading new XKB keymaps
Press xkb_keycode: 0x32 clean_sym: Shift_L composed_sym: Shift_L mods: none glfw_key: 57440 (LEFT_SHIFT) xkb_key: 65505 (Shift_L)
on_key_input: glfw key: 57440 native_code: 0xffe1 action: PRESS mods: 0x0 text: '' state: 0 ignoring as keyboard mode does not allow repeat events
Press xkb_keycode: 0x87 clean_sym: Menu composed_sym: Menu mods: shift glfw_key: 57363 (MENU) xkb_key: 65383 (Menu)
on_key_input: glfw key: 57363 native_code: 0xff67 action: PRESS mods: 0x1 text: '' state: 0 sent key to child
Release xkb_keycode: 0x87 clean_sym: Menu mods: shift glfw_key: 57363 (MENU) xkb_key: 65383 (Menu)
on_key_input: glfw key: 57363 native_code: 0xff67 action: RELEASE mods: 0x1 text: '' state: 0 ignoring as keyboard mode does not allow release events
Release xkb_keycode: 0x32 clean_sym: Shift_L mods: shift glfw_key: 57440 (LEFT_SHIFT) xkb_key: 65505 (Shift_L)
on_key_input: glfw key: 57440 native_code: 0xffe1 action: RELEASE mods: 0x1 text: '' state: 0 ignoring as keyboard mode does not allow release events
Press xkb_keycode: 0x32 clean_sym: Shift_L composed_sym: Shift_L mods: none glfw_key: 57440 (LEFT_SHIFT) xkb_key: 65505 (Shift_L)
on_key_input: glfw key: 57440 native_code: 0xffe1 action: PRESS mods: 0x0 text: '' state: 0 ignoring as keyboard mode does not allow repeat events
Press xkb_keycode: 0x24 clean_sym: Return composed_sym: Return mods: shift glfw_key: 57345 (ENTER) xkb_key: 65293 (Return)
on_key_input: glfw key: 57345 native_code: 0xff0d action: PRESS mods: 0x1 text: '' state: 0 sent key to child
Release xkb_keycode: 0x24 clean_sym: Return mods: shift glfw_key: 57345 (ENTER) xkb_key: 65293 (Return)
on_key_input: glfw key: 57345 native_code: 0xff0d action: RELEASE mods: 0x1 text: '' state: 0 ignoring as keyboard mode does not allow release events
Release xkb_keycode: 0x32 clean_sym: Shift_L mods: shift glfw_key: 57440 (LEFT_SHIFT) xkb_key: 65505 (Shift_L)
on_key_input: glfw key: 57440 native_code: 0xffe1 action: RELEASE mods: 0x1 text: '' state: 0 ignoring as keyboard mode does not allow release events
Press xkb_keycode: 0x32 clean_sym: Shift_L composed_sym: Shift_L mods: none glfw_key: 57440 (LEFT_SHIFT) xkb_key: 65505 (Shift_L)
on_key_input: glfw key: 57440 native_code: 0xffe1 action: PRESS mods: 0x0 text: '' state: 0 ignoring as keyboard mode does not allow repeat events
Press xkb_keycode: 0x16 clean_sym: BackSpace composed_sym: BackSpace mods: shift glfw_key: 57347 (BACKSPACE) xkb_key: 65288 (BackSpace)
on_key_input: glfw key: 57347 native_code: 0xff08 action: PRESS mods: 0x1 text: '' state: 0 sent key to child
Release xkb_keycode: 0x16 clean_sym: BackSpace mods: shift glfw_key: 57347 (BACKSPACE) xkb_key: 65288 (BackSpace)
on_key_input: glfw key: 57347 native_code: 0xff08 action: RELEASE mods: 0x1 text: '' state: 0 ignoring as keyboard mode does not allow release events
Release xkb_keycode: 0x32 clean_sym: Shift_L mods: shift glfw_key: 57440 (LEFT_SHIFT) xkb_key: 65505 (Shift_L)
on_key_input: glfw key: 57440 native_code: 0xffe1 action: RELEASE mods: 0x1 text: '' state: 0 ignoring as keyboard mode does not allow release events
Press xkb_keycode: 0x32 clean_sym: Shift_L composed_sym: Shift_L mods: none glfw_key: 57440 (LEFT_SHIFT) xkb_key: 65505 (Shift_L)
on_key_input: glfw key: 57440 native_code: 0xffe1 action: PRESS mods: 0x0 text: '' state: 0 ignoring as keyboard mode does not allow repeat events
Press xkb_keycode: 0x70 clean_sym: Prior composed_sym: Prior mods: shift glfw_key: 57354 (PAGE_UP) xkb_key: 65365 (Prior)
on_key_input: glfw key: 57354 native_code: 0xff55 action: PRESS mods: 0x1 text: '' state: 0 sent key to child
Release xkb_keycode: 0x70 clean_sym: Prior mods: shift glfw_key: 57354 (PAGE_UP) xkb_key: 65365 (Prior)
on_key_input: glfw key: 57354 native_code: 0xff55 action: RELEASE mods: 0x1 text: '' state: 0 ignoring as keyboard mode does not allow release events
Release xkb_keycode: 0x32 clean_sym: Shift_L mods: shift glfw_key: 57440 (LEFT_SHIFT) xkb_key: 65505 (Shift_L)
on_key_input: glfw key: 57440 native_code: 0xffe1 action: RELEASE mods: 0x1 text: '' state: 0 ignoring as keyboard mode does not allow release events
Press xkb_keycode: 0x32 clean_sym: Shift_L composed_sym: Shift_L mods: none glfw_key: 57440 (LEFT_SHIFT) xkb_key: 65505 (Shift_L)
on_key_input: glfw key: 57440 native_code: 0xffe1 action: PRESS mods: 0x0 text: '' state: 0 ignoring as keyboard mode does not allow repeat events
Press xkb_keycode: 0x75 clean_sym: Next composed_sym: Next mods: shift glfw_key: 57355 (PAGE_DOWN) xkb_key: 65366 (Next)
on_key_input: glfw key: 57355 native_code: 0xff56 action: PRESS mods: 0x1 text: '' state: 0 sent key to child
Release xkb_keycode: 0x75 clean_sym: Next mods: shift glfw_key: 57355 (PAGE_DOWN) xkb_key: 65366 (Next)
on_key_input: glfw key: 57355 native_code: 0xff56 action: RELEASE mods: 0x1 text: '' state: 0 ignoring as keyboard mode does not allow release events
Release xkb_keycode: 0x32 clean_sym: Shift_L mods: shift glfw_key: 57440 (LEFT_SHIFT) xkb_key: 65505 (Shift_L)
on_key_input: glfw key: 57440 native_code: 0xffe1 action: RELEASE mods: 0x1 text: '' state: 0 ignoring as keyboard mode does not allow release events
Press xkb_keycode: 0x25 clean_sym: Control_L composed_sym: Control_L mods: none glfw_key: 57441 (LEFT_CONTROL) xkb_key: 65507 (Control_L)
on_key_input: glfw key: 57441 native_code: 0xffe3 action: PRESS mods: 0x0 text: '' state: 0 ignoring as keyboard mode does not allow repeat events
Press xkb_keycode: 0x87 clean_sym: Menu composed_sym: Menu mods: ctrl glfw_key: 57363 (MENU) xkb_key: 65383 (Menu)
on_key_input: glfw key: 57363 native_code: 0xff67 action: PRESS mods: 0x4 text: '' state: 0 sent key to child
Release xkb_keycode: 0x87 clean_sym: Menu mods: ctrl glfw_key: 57363 (MENU) xkb_key: 65383 (Menu)
on_key_input: glfw key: 57363 native_code: 0xff67 action: RELEASE mods: 0x4 text: '' state: 0 ignoring as keyboard mode does not allow release events
Release xkb_keycode: 0x25 clean_sym: Control_L mods: ctrl glfw_key: 57441 (LEFT_CONTROL) xkb_key: 65507 (Control_L)
on_key_input: glfw key: 57441 native_code: 0xffe3 action: RELEASE mods: 0x4 text: '' state: 0 ignoring as keyboard mode does not allow release events
Press xkb_keycode: 0x25 clean_sym: Control_L composed_sym: Control_L mods: none glfw_key: 57441 (LEFT_CONTROL) xkb_key: 65507 (Control_L)
on_key_input: glfw key: 57441 native_code: 0xffe3 action: PRESS mods: 0x0 text: '' state: 0 ignoring as keyboard mode does not allow repeat events
Press xkb_keycode: 0x70 clean_sym: Prior composed_sym: Prior mods: ctrl glfw_key: 57354 (PAGE_UP) xkb_key: 65365 (Prior)
on_key_input: glfw key: 57354 native_code: 0xff55 action: PRESS mods: 0x4 text: '' state: 0 sent key to child
Release xkb_keycode: 0x70 clean_sym: Prior mods: ctrl glfw_key: 57354 (PAGE_UP) xkb_key: 65365 (Prior)
on_key_input: glfw key: 57354 native_code: 0xff55 action: RELEASE mods: 0x4 text: '' state: 0 ignoring as keyboard mode does not allow release events
Release xkb_keycode: 0x25 clean_sym: Control_L mods: ctrl glfw_key: 57441 (LEFT_CONTROL) xkb_key: 65507 (Control_L)
on_key_input: glfw key: 57441 native_code: 0xffe3 action: RELEASE mods: 0x4 text: '' state: 0 ignoring as keyboard mode does not allow release events
Press xkb_keycode: 0x25 clean_sym: Control_L composed_sym: Control_L mods: none glfw_key: 57441 (LEFT_CONTROL) xkb_key: 65507 (Control_L)
on_key_input: glfw key: 57441 native_code: 0xffe3 action: PRESS mods: 0x0 text: '' state: 0 ignoring as keyboard mode does not allow repeat events
Press xkb_keycode: 0x75 clean_sym: Next composed_sym: Next mods: ctrl glfw_key: 57355 (PAGE_DOWN) xkb_key: 65366 (Next)
on_key_input: glfw key: 57355 native_code: 0xff56 action: PRESS mods: 0x4 text: '' state: 0 sent key to child
Release xkb_keycode: 0x75 clean_sym: Next mods: ctrl glfw_key: 57355 (PAGE_DOWN) xkb_key: 65366 (Next)
on_key_input: glfw key: 57355 native_code: 0xff56 action: RELEASE mods: 0x4 text: '' state: 0 ignoring as keyboard mode does not allow release events
Release xkb_keycode: 0x25 clean_sym: Control_L mods: ctrl glfw_key: 57441 (LEFT_CONTROL) xkb_key: 65507 (Control_L)
on_key_input: glfw key: 57441 native_code: 0xffe3 action: RELEASE mods: 0x4 text: '' state: 0 ignoring as keyboard mode does not allow release events
kovidgoyal commented 3 years ago

Those are expected, keys that produce no output normally now are encoded so they can be used in terminal programs that dont want to adopt the full protocol.

craigbarnes commented 3 years ago

@kovidgoyal I've read through the docs and I'm really liking this proposal so far. It's a huge improvement over the previous protocol, in my opinion, and seems to solve pretty much every problem I've encountered w.r.t. terminal key codes. I'm planning to start working on a patch to add this protocol to the foot terminal in the near future.

However, if you'll forgive me for bikeshedding just a little, my only minor criticism would be the event type sub-param:

No, that is a sub-parameter. Parameters are separated by semi-colons and sub-parameters by colons. This is for example how, how the CSI for underline styles, work.

I agree that sub-params make perfect sense for underline styles (and RGB colors) in SGR sequences, but I can't really see how they're appropriate for key event types. It seems to me that all 3 params in this case are logically just parameters of the CSI u control function and the event type and modifiers are no more closely related than the modifiers and the key are.

I hope this isn't too much of a nitpick, but it was the only thing that struck me as somewhat odd when reading through the docs. Thank you for putting this protocol together and documenting it so well!

kovidgoyal commented 3 years ago

On Mon, Jan 25, 2021 at 04:22:56PM -0800, Craig Barnes wrote:

@kovidgoyal I've read through the docs and I'm really liking this proposal so far. It's a huge improvement over the previous protocol, in my opinion, and seems to solve pretty much every problem I've encountered w.r.t. terminal key codes. I'm planning to start working on a patch to add this protocol to the foot terminal in the near future.

Glad to hear it :)

However, if you'll forgive me for bikeshedding just a little, my only small criticism would be the event type sub-params:

Well, I knew sooner or later someone would :)

No, that is a sub-parameter. Parameters are separated by semi-colons and sub-parameters by colons. This is for example how, how the CSI for underline styles, work.

I agree that sub-params make perfect sense for underline styles (and RGB colors) in SGR sequences, but I can't really see how they're appropriate for key event types. It seems to me that all 3 params in this case are logically just parameters of the CSI u control function. The event type and the modifier don't seem any more closely related than the key and the modifier are.

The reason sub-parameters are used are:

1) The data belongs together. For instance, the main key code, shifted key code and alternate key code are all key codes, and therefore are one parameter with sub-parameters. Text is a sequence of related code points and so belongs together. Similarly the modifiers and event types are both things that modify the meaning of a key event, and therefore belong together. In the last case, I agree it's possible to argue it either way, but given that the use of sub-parameters is clear cut in the other two cases, it seemed odder to leave it out in the last case.

2) I find thinking and parsing and generating grouped sets of parameters easier. Without it it means lots of empty ;;;; sections. It makes the simplest form of the escape code backwards compatible with the fixterms proposal and the legacy CSI~ encoding. Without using subparameters, you would either have to make the first two parameters key code and modifier or break backwards compatibility. The former means related things are no longer together, the latter is not desirable for obvious reasons.

craigbarnes commented 3 years ago

2) I find thinking and parsing and generating grouped sets of parameters easier. Without it it means lots of empty ;;;; sections.

In practice, I guess most terminals wouldn't emit more than 1 key event as a single sequence, but I see your point.

It makes the simplest form of the escape code backwards compatible with the fixterms proposal and the legacy CSI~ encoding. Without using subparameters, you would either have to make the first two parameters key code and modifier or break backwards compatibility. The former means related things are no longer together, the latter is not desirable for obvious reasons.

Yeah, that makes sense from a backwards compatibility perspective. It just seems a little strange to see the event type as a sub-param, but not the modifiers. I don't have a particularly strong opinion either way though. Agreeing on a common protocol with a few minor back compat. artifacts seems a lot better than mindless nitpicking. The rest of the protocol also seems very well thought out, so I'll just trust your judgement and implement it as-is.

kovidgoyal commented 3 years ago

Just to be clear you can have only one key event per CSIu escape code. The empty ;;;; sections when not using subgroups are caused by the fact that one there could be data that needs to be encoded in a later field of a single event while earlier fields are empty (default valued). For example, CSI keycode;;shifted-keycode;;u where the empty fields are default valued such as CSI keycode;modifier;shifted-keycode;alternate-keycode;event-type;...u

mawww commented 3 years ago

Gave it a go in Kakoune, almost works out of the box after manually enabling it with nop %sh{ printf '\033[>1u' > /dev/tty }, it did trigger a bug Kakoune side (escape coming in as CSI 27 u was not recognized), but it work nicely after fixing that.

I think having an opt-in escape sequence to enable/disable this is the way to go, as shells tend to get confused with CSI u encoding (as I could see when enabling it in the settings on iterm2). I'd be happy to make Kakoune emit CSI > 1 u on terminal setup provided this does not confuse other terminals (I'd expect them to ignore it gracefully as its a private sequence).

Out of curiosity, what is the reason you did not go with the more classic CSI ? <number> h and CSI ? <number> l for enabling disabling ?

kovidgoyal commented 3 years ago

On Mon, Feb 01, 2021 at 10:22:26PM -0800, Maxime Coste wrote:

Gave it a go in Kakoune, almost works out of the box after manually enabling it with nop %sh{ printf '\033[>1u' > /dev/tty }, it did trigger a bug Kakoune side (escape coming in as CSI 27 u was not recognized), but it work nicely after fixing that.

Good to hear.

I think having an opt-in escape sequence to enable/disable this is the way to go, as shells tend to get confused with CSI u encoding (as I could see when enabling it in the settings on iterm2). I'd be happy to make Kakoune emit CSI > 1 u on terminal setup provided this does not confuse other terminals (I'd expect them to ignore it gracefully as its a private sequence).

Non-buggy terminals will ignore it, and given that CSI is the most common escape sequence it is unlikely many terminal wont at least parse it correctly. Still you could make it conditional on detecting "kitty" in TERM, at least to start with, until it is more widepsread.

Out of curiosity, what is the reason you did not go with the more classic CSI ? <number> h and CSI ? <number> l for enabling disabling ?

It's not a binary on/off. There are various different features you can enable, see the full spec, beyond the quickstart. Also I want there to be a stack so an application can easily change modes and restore the previous mode on exit without needing to query the terminal. So for example if a shell wnts to implement it, it can push the mode it wants onto the stack, and pop it off before running a command, easily.

craigbarnes commented 3 years ago

Just to be clear you can have only one key event per CSIu escape code. The empty ;;;; sections when not using subgroups are caused by the fact that one there could be data that needs to be encoded in a later field of a single event while earlier fields are empty (default valued). For example, CSI keycode;;shifted-keycode;;u where the empty fields are default valued such as CSI keycode;modifier;shifted-keycode;alternate-keycode;event-type;...u

Ah, I see what you mean now. My main concern with the sub-params is that it seems somewhat opaque as to why they're being used, even after reading the documentation. It's also the first time I've seen them used in sequences sent from terminal to client.

What do you think about using different final bytes to indicate the different event types (e.g. v=repeat, w=release) or, alternatively, using an intermediate byte?

kovidgoyal commented 3 years ago

On Mon, Feb 01, 2021 at 10:49:18PM -0800, Craig Barnes wrote:

Just to be clear you can have only one key event per CSIu escape code. The empty ;;;; sections when not using subgroups are caused by the fact that one there could be data that needs to be encoded in a later field of a single event while earlier fields are empty (default valued). For example, CSI keycode;;shifted-keycode;;u where the empty fields are default valued such as CSI keycode;modifier;shifted-keycode;alternate-keycode;event-type;...u

Ah, I see what you mean now. My main concern with the sub-params is that it seems quite opaque as to why they're being used, even after reading the documentation. It's also the first time I've seen them used in sequences sent from terminal to client.

Seemed fairly self evident to me why they are used, but I can add a line clarifying it if it helps. And since clients can generate sub-parameters, I dont see how expecting them to parse them is an undue burden. And note that in the lowest level of progressive enhancement, which has the maximum backward compatibility and least amount of changes required from a client, there are no sub parameters, since the only information reported is key code and modifiers.

What do you think about using different final bytes to indicate the different event types (e.g. v=repeat, w=release) or, alternatively, using an intermediate byte?

Why? It would no longer be a CSI u code but a random collection of things and it would use up a lot more of the potential escape code space. As for an intermediate byte, what's the advantage over a number?? Not to mention that I tend to regard intermediate bytes as changing the meaning of the escape code, not adding information to it. That is how intermediate bytes have been used historically.

rien333 commented 3 years ago

Thanks for all your work, should be useful. Continuing from my earlier issue (#3285), I do hope that terminal programs (shells, text editors, etc.) will adopt an intelligent way to respond to the novelties introduced in this protocol. As it stands, I appear to accidentally and frequently trigger key combos (e.g. Ctrl+enter) that result in some garbage being printed, which can be quite disruptive.

What would be the best way forward here? Should I, as a user, configure programs (e.g. fish shell) to somehow deal with the novel key combos introduced in this protocol? Or should people "pressure" maintainers of other programs to implement this new protocol, by e.g. opening issues? I would be happy to do the latter. Emacs, for example, could benefit from being capable of handling more key combos, but currently doesn't understand the new protocol at all.

kovidgoyal commented 3 years ago

On Thu, Feb 11, 2021 at 08:09:41AM -0800, Rijnder Wever wrote:

Thanks for all your work, should be useful. Continuing from my earlier issue (#3285), I do hope that terminal programs (shells, text editors, etc.) will adopt an intelligent way to respond to the novelties introduced in this protocol. As it stands, I appear to accidentally and frequently trigger key combos (e.g. Ctrl+enter) that result in some garbage being printed, which can be quite disruptive.

Yes, that's the hope. It's debatable whether I should not generate any bytes different from traditional terminals in the default mode, that avoids the occasional accidental keypress generating garbage instead of being ignored, in non-supporting programs problem. However it means that any program that wants to use it then has to opt-in, even for things like ctrl+enter, shift+enter, etc.

It would be nice to get some more opinions on this. Personally, I find pressing shift+enter the most common accident. Maybe just filter out shift and ctrl + enter.

What would be the best way forward here? Should I, as a user, configure programs (e.g. fish shell) to somehow deal with the novel key combos introduced in this protocol? Or should people "pressure" maintainers of other programs to implement this new protocol, by e.g. opening issues? I would be happy to do the latter. Emacs, for example, could benefit from being capable of handling more key combos, but currently doesn't understand the new protocol at all.

I think you opening issues informing the maintainers of the existence of this protocol would be useful. Whether they choose to adopt or ignore it remains to be seen.

Sleepful commented 3 years ago

ctrl+shift+letter isn't working in my OSX machine, I was trying to look at different layouts.

here I tried with ctrl+shift+l

Press any keys - Ctrl+C or Ctrl+D will terminate
Ctrl+LEFT_CONTROL PRESS 
CSI 57441 ; 5 u

Shift+Ctrl+LEFT_SHIFT PRESS 
CSI 57440 ; 6 u

Ctrl+LEFT_SHIFT RELEASE 
CSI 57440 ; 5 : 3 u

LEFT_CONTROL RELEASE 
CSI 57441 ; 1 : 3 u
2021-02-17 00:30:30.728 kitty[68055:2243535] updateIMEState: 0.500000, 0.000000, 0.000000, 0.000000
2021-02-17 00:30:34.385 kitty[68055:2243535] updateIMEState: 0.000000, 15.500000, 7.000000, 12.500000
on_key_input: glfw key: 57441 native_code: 0x3b action: PRESS mods: 0x4 text: '' state: 0 sent key to child
2021-02-17 00:30:34.541 kitty[68055:2243535] updateIMEState: 0.000000, 53.000000, 7.000000, 12.500000
on_key_input: glfw key: 57440 native_code: 0x38 action: PRESS mods: 0x5 text: '' state: 0 sent key to child
2021-02-17 00:30:34.880 kitty[68055:2243535] keycode: 0x7c (<cc>) mods: ctrl+shift char_count: 1 deadKeyState: 0 repeat: 0
2021-02-17 00:30:34.880 kitty[68055:2243535] text: <none> glfw_key: RIGHT marked_text: 
2021-02-17 00:30:34.880 kitty[68055:2243535] updateIMEState: 0.000000, 90.500000, 7.000000, 12.500000
Keypress matched action: next_tab
on_key_input: glfw key: 57351 native_code: 0x7c action: PRESS mods: 0x5 text: '' state: 0 handled as shortcut
2021-02-17 00:30:34.953 kitty[68055:2243535] updateIMEState: 0.000000, 90.500000, 7.000000, 12.500000
2021-02-17 00:30:35.511 kitty[68055:2243535] updateIMEState: 0.000000, 90.500000, 7.000000, 12.500000
on_key_input: glfw key: 57351 native_code: 0x7c action: RELEASE mods: 0x5 text: '' state: 0 ignoring release event for previous press that was handled as shortcuton_key_input: glfw key: 57440 native_code: 0x38 action: RELEASE mods: 0x4 text: '' state: 0 sent key to child
2021-02-17 00:30:35.514 kitty[68055:2243535] updateIMEState: 0.000000, 90.500000, 7.000000, 12.500000
on_key_input: glfw key: 57441 native_code: 0x3b action: RELEASE mods: 0x0 text: '' state: 0 sent key to child

it actually works with some letters, such as i, but it does not work with a lot of letters, such as o, p , h, j , k , l,, don't know which others.

Apparently it matches a next_tab action, but my kitty.conf doesn't have such configuration...

Here is for ctrl+shift+k

2021-02-17 00:39:13.033 kitty[68055:2243535] updateIMEState: 0.000000, 603.000000, 7.000000, 12.500000
2021-02-17 00:39:13.920 kitty[68055:2243535] keycode: 0x7e (<cc>) mods: ctrl+shift char_count: 1 deadKeyState: 0 repeat: 0
2021-02-17 00:39:13.920 kitty[68055:2243535] text: <none> glfw_key: UP marked_text: 
2021-02-17 00:39:13.920 kitty[68055:2243535] updateIMEState: 0.000000, 603.000000, 7.000000, 12.500000
Keypress matched action: scroll_line_up
on_key_input: glfw key: 57352 native_code: 0x7e action: RELEASE mods: 0x5 text: '' state: 0 ignoring release event for previous press that was handled as shortcuton_key_input: glfw key: 57352 native_code: 0x7e action: PRESS mods: 0x5 text: '' state: 0 handled as shortcut

scroll_line_up

I have no idea where this is coming from... I think GLFW? It's misleading because the docs say ctrl+shift+l is bound to cycling the layout, but the next_tab takes over. However, if I use map alt+shift+l next_layout then I can cycle layout just fine. I did not find anything in the docs that would point me towards turning off this matched action effect.

kovidgoyal commented 3 years ago

ctrl+shift is kitty_mod and is used for kitty shortcuts

Sleepful commented 3 years ago

so why am I getting next_tab with ctrl+shift+l, instead of next_layout?

kovidgoyal commented 3 years ago

Works fine for me with

kitty --config NONE

altough I tested on linux not macos as currently dont have access to my macos machine.

ctrl+shift+l cycles layouts as expected. The default bindings for next_tab on macos are kitty_mod+right, ctrl+tab and shift+cmd+]

kovidgoyal commented 3 years ago

Also tested on my macOS machine, ctrl+shift+l changes layouts as expected.

Sleepful commented 3 years ago

thanks @kovidgoyal , turns out it was my Karabiner configuration...

Sleepful commented 3 years ago

About this reporting protocol, if I am running an app inside Tmux, would the app be able to use the reporting protocol?

kovidgoyal commented 3 years ago

On Wed, Feb 17, 2021 at 09:39:53AM -0800, Jose Vargas wrote:

About this reporting protocol, if I am running an app inside Tmux, would the app be able to use the reporting protocol?

tmux would need to add support for it, or pass it through at a minimum, that is true for any imaginable reporting protocol, and is one of the reasons terminal multiplexers are poison.

kovidgoyal commented 3 years ago

I changed the legacy encoding for modifiers + (enter|backspace|tab|space) to not emit CSI u escape sequences, as it is easy to generate these accidentally, and various terminal programs dont parse CSI escape sequences at all. This should fix the issues reported in #3285 and #3329

https://github.com/kovidgoyal/kitty/commit/56fcbb95abb8409ca7ad2bcc185fa374d8f4bbc0

Kyran-C commented 3 years ago

This looks great! I applaud your efforts as well as @leonerd for his work and evangelism. Kitty has strong enough adoption that application developers will be encouraged to support this protocol, and hopefully overcome the chicken/egg problem. It seems that a lot of consideration has been given to backwards compatibility which is crucial for a protocol like this.

I'm not a terminal maintainer so I can't comment on any obscure pitfalls or corner cases, but it seems well-designed in general. All the extended features are opt-in so that should eliminate any potential conflicts.



Aside from disambiguating key presses, the extended key event types are also very useful, and not just for games. One thing I haven't seen brought up yet is so called 'smart keys'. The earliest incarnation I'm aware of dates back to the Space Cadet keyboards which had shift keys that output open or close parenthesis when tapped, and worked as normal shift when held.

It's a pretty popular feature in the custom keyboard community. My left spacebar (it's split into multiple keys) will emit backspace when tapped, and shift when held. The right spacebar emits space when tapped, and on hold it switches to another layer that changes my home row to navigational keys for when I'm outside of vim. This is all implemented in firmware, but exposing button press and release events to a cooperating program would allow that sort of thing in software. It's a lot more accessible for someone to write a script for their editor than to build a custom keyboard and compile and flash their own firmware.

It's a really powerful feature, especially when you consider how crowded the default mappings of vim are. Rather than having to reach for backslash as a leader key, you could overload a more comfy key to act as a modifier when held.

For instance, semicolon could act as a layer switch while still retaining its default functionality when tapped. You could have keys send a lowercase letter on short press, and uppercase on long press. Or create mappings assigned to chords based on multiple simultaneous keys pressed (similar to stenography) rather than just sequences of keys pressed really quickly in succession.

You effectively increase your potential modifier keys from 4 to however many keys are within reach (meaning 2^4 -> 2^N unique modifier combinations). And conversely, the modifier keys can gain additional functionality by firing off one-shot mappings when tapped.


A couple questions/suggestions regarding some details of the protocol:


Disambiguate escape codes Turning on this flag will cause the terminal to report (...) keys using CSI u sequences instead of legacy ones. The only exceptions are the Enter, Tab and Backspace keys which still generate the same bytes as in legacy mode this is to allow the user to type and execute commands in the shell such as reset after a program that sets this mode crashes without clearing it.

To clarify, this will still allow modifier combinations of those keys, but the base keys will just use legacy codepoints, correct?


I do like the idea of using a stack of capability flags.

If a push request is received and the stack is full, the oldest entry from the stack must be evicted.

Instead of this, perhaps the terminal should just refuse any escalation of capabilities until flags are popped from the stack? Either the terminal could immediately reply back to reset to the previous flags, or that could be part of the query step somehow (assuming the program will query the terminal for its capabilities before attempting to push a flag).

My reasoning is: from a program's perspective, pushing some flags should mean I'm only ever passed codes that I'm expecting, and N pushes followed by N pops should result in the original capability flags I asked for, regardless of the terminal's stack size. The existing spec sort of guards this by specifying that the flags are reset when the stack is empty, so at least we can be sure programs are never called with flags that exceed their capabilities. But that may still cause issues if the program is expecting a higher tier protocol (for instance, waiting for key release that never occurs, etc).

As an alternative to capping the stack, the terminal could still use the ring buffer approach when capacity is exceeded and then once the stack is finally emptied, it can issue a message notifying the program of the capability downgrade so it can can fall back to its legacy handling.

In either case there's the minor risk that an application absolutely needs the capabilities that it requests, but I think it's better for it to be denied right away so it can fail gracefully (in the case of a fixed stack) vs failing later on after a protocol downgrade message, which may be difficult to recover from (in the case of a forgetful stack/ring buffer).

kovidgoyal commented 3 years ago

1) Regarding special keys, if they are implemented in firmware, then they will not be visible to the OS and hence to programs such as terminal emulators, which in turn means, there's not much point adding support for them to the protocol since it wont be implementable. That said, the protocol is extensible and support for these could be added in the future.

2) Any single program is unlikely to call push more than once. There's no point in supporting multiple levels of enhancement in a single program. And note that this stack is a stack of bitfields (so 1-4 bytes per entry depending on implementation), so it can easily be a thousand entries long, without any significant memory usage. So I dont think this is a problem in practice. And to me, having client programs needing to understand another escape code is a more significant burden than the largely theoretical chance of the stack being exhausted.

Kyran-C commented 3 years ago

I meant that the smart key functionality can be implemented in software (ie inside a vim script) since we'd be able to detect key press/hold/release inside a terminal program. So rather than having to program your own keyboard firmware, you could download a plugin or script that implements that already (assuming you're using a compatible terminal that supports this protocol).

Fair point on the stack, it does seem like a pretty remote corner case.

kovidgoyal commented 3 years ago

Ah ok, sorry, I misunderstood. In that case I think the protocol already supports this use case as is. Correct me if I am wrong.

Kyran-C commented 3 years ago

Yeah definitely! I was just pointing that out as another motivator for the extended key events besides games.

klooj commented 3 years ago

I just switched to kitty from iterm about 48 hours ago. simply put, the difference is compelling and I'm a kitty user now.

I am a little lost in the sauce here with key reporting though. in iterm, I used CSI u reporting and in Neovim I mapped ctrl+<CR>, shift+<CR>,ctrl+<BS>, shift+<BS> to functions I wrote for padding or removing blank lines above and below the current line. kitty is not reporting them the same way to nvim and I don't know how to configure properly. for instance, shift+<CR> is reporting as ^M. I don't think this is a bug or an error of kitty. I think it's something I have to learn. Can somebody point me in the right direction please? Thank you in advance.

edit: using macOS Big Sur (linux via ssh only).

kovidgoyal commented 3 years ago

On Thu, Mar 04, 2021 at 10:19:09PM -0800, klooj wrote:

I am a little lost in the sauce here with key reporting though. in iterm, I used CSI u reporting and in Neovim I mapped ctrl+enter, shift+enter, ctrl+backspace, shift+backspace to functions I wrote for padding or removing blank lines above and below the current line. These are not working in kitty and I don't know how to configure properly. I don't think this is a bug or an error of kitty. I think it's something I have to learn. Can somebody point me in the right direction please? Thank you in advance.

You have two options: 1) You need to run kitty from master

kitty, unlike iterm does not output CSIu codes by default, the application has to actually enable them. See https://github.com/kovidgoyal/kitty/issues/3248#issuecomment-782804649

If you want to use those key bindings in nvim, you can Write a wrapper script to launch nvim that writes CSI > 1 u (the bytes 0x1b [ > 1 u) to put kitty into disambiguate mode and then runs nvim.

2) No need to run kitty from master, instead simply add the definitions for those keys in kitty.conf using send_text

Run cat in iTerm and see the bytes produced when pressing the keys of interest, then in kitty.conf add

map ctrl+enter send_text normal bytes_from_above map ctrl+enter send_text application bytes_from_above ...

mawww commented 3 years ago

unlike iterm does not output CSIu codes by default, the application has to actually enable them.

iterm2 current master now supports the control escape sequence: See this issue.

Thanks for pushing this improvement through, Kakoune now has support for it in its soon-to-be-merged builtin-terminal-ui branch. Hopefully more terminal application follow.

kovidgoyal commented 3 years ago

On Sun, Mar 07, 2021 at 01:46:16PM -0800, Maxime Coste wrote:

unlike iterm does not output CSIu codes by default, the application has to actually enable them.

iterm2 current master now supports the control escape sequence: See this issue.

Thanks for pushing this improvement through, Kakoune now has support for it in its soon-to-be-merged builtin-terminal-ui branch. Hopefully more terminal application follow.

Glad to hear it hopefully we are on the road to putting keyboard issues in terminals finally behind us.

kovidgoyal commented 3 years ago

I have added a paragraph to the spec to treat the escape codes that XTerm uses to turn off/on its modifyOtherKeys resource as activating the lowest level of progressive enhancement of this protocol. This should make it easier for client applications to interoperate with both xterm and kitty. See https://github.com/kovidgoyal/kitty/commit/d360d077d1f7723b1023b77969c38436353b9519

If anyone sees any issues with this, let me know.

klooj commented 3 years ago

I really hate to pollute this thread but ...

Write a wrapper script to launch nvim that writes CSI > 1 u (the bytes 0x1b [ > 1 u) to put kitty into disambiguate mode

I do not know how to do this. I spent a week trying to figure it out but I cannot even find relevant sources of info. I would be super grateful for an example. If you don't want to hold my hand(understandable), even a link for emitting escape sequences generally (outside of printf) would be appreciated.

I tried falling back to your other suggestion (map ctrl+enter send_text normal ^[[13;5u) but that yielded unexpected results.

kovidgoyal commented 3 years ago

On Thu, Mar 18, 2021 at 10:45:13PM -0700, klooj wrote:

I really hate to pollute this thread but ...

Write a wrapper script to launch nvim that writes CSI > 1 u (the bytes 0x1b [ > 1 u) to put kitty into disambiguate mode

I do not know how to do this. I spent a week trying to figure it out but I cannot even find relevant sources of info. I would be super grateful for an example. If you don't want to hold my hand(understandable), even a link for emitting escape sequences generally (outside of printf) would be appreciated.

I tried falling back to your other suggestion (map ctrl+enter send_text normal ^[[13;5u) but that yielded unexpected results.

map ctrl+enter send_text normal,application \x1b[13;5u
orki commented 3 years ago

Pull request #3430 adds support for hyper and meta along with the existing modifiers. Emacs (with a little help from some elisp) can parse it completely, including support for all combinations of all 6 modifiers (shift,control,alt,meta,hyper,super) for every key. As mentioned in the pull request, I have been using emacs with it as my daily driver for a few days, with no issues beyond those that are emacs-specific. (The emacs-specific issues are limited to quoted-insert and view-lossage, but those have nothing to do with kitty.)

orki commented 3 years ago

In case the request was not clear, @kovidgoyal are you willing to consider adding hyper and meta to the protocol spec before 0.20.0, now that there exists an actual implemetantion in pull request #3430 ? I'm happy to provide patches to the keyboard protocol documentation. This has been long sought by terminal emacs users for decades.

kovidgoyal commented 3 years ago

Yes, I have no objections to adding more modifiers. One can never have too many modifiers :)

kovidgoyal commented 3 years ago

Note the protocol has been updated to add support for four more modifiers, hyper, meta, num lock and caps lock. Also, I neglected to assign the keypad begin key a code, this has now been fixed.

dankamongmen commented 2 years ago

@kovidgoyal I've read through the docs and I'm really liking this proposal so far. It's a huge improvement over the previous protocol, in my opinion, and seems to solve pretty much every problem I've encountered w.r.t. terminal key codes. I'm planning to start working on a patch to add this protocol to the foot terminal in the near future.

@craigbarnes did foot ever gain support for the protocol? I've recently added support and discovery to Notcurses, but even with foot 1.8.2-144 i don't get any response to my CSI > u query, and thus i don't discover support for it there.

fwiw, i agree that this is a tremendous and necessary improvement over what existed before.

kovidgoyal commented 2 years ago

@dankmongmen You might want to test with iTerm2 as well, it seems to have some kind of partial support for this protocol: https://github.com/gnachman/iTerm2/commit/bd3865bd94ef7f34e45d412350333d56f881a4ee and https://gitlab.com/gnachman/iterm2/-/issues/9506