Skip to content

Kitty keyboard: Shift is unwound only for Digit* and Key* codes, so shifted punctuation reports the shifted character as the key code #165

Closed

Description

@alexeyzimarev

What happens

KittyKeyboard.GetKeyCode recovers the unshifted key from KeyEvent.Code only when the code starts with Digit or Key. For the main-keyboard punctuation positions (Backquote, Minus, Equal, BracketLeft, BracketRight, Backslash, Semicolon, Quote, Comma, Period, Slash) it falls through to ev.Key[0], which is the shifted character, so the key code reported is the shifted symbol rather than the key.

Observed through Terminal.GenerateKittyKeyInput on 2.0.3 (KittyKeyboard.cs on main is identical):

Flags Event Sent Per spec
>9u Shift, key !, code Digit1 CSI 49;2u CSI 49;2u
>9u Shift, key +, code Equal CSI 43;2u CSI 61;2u
>9u Shift, key :, code Semicolon CSI 58;2u CSI 59;2u
>9u Shift, key _, code Minus CSI 95;2u CSI 45;2u
>9u Shift, key ?, code Slash CSI 63;2u CSI 47;2u
>5u Ctrl+Shift, key +, code Equal CSI 43:43;6u CSI 61:43;6u
>1u Ctrl+Shift, key +, code Equal CSI 43;6u CSI 61;6u

The spec defines the key code as the key without modifiers, with the shifted key in the first sub-parameter, which is what the digit row already does: Shifted_key_appears_as_a_sub_parameter pins % on Digit5 as 53:37. An application matching the spec form for Ctrl+Shift+= never sees the chord, and with alternate keys on the sub-parameter duplicates the key code instead of carrying the shifted symbol.

Where it comes from

xterm.js has the same two prefixes in KittyKeyboard.ts (ev.code.startsWith('Digit') and startsWith('Key')), so this is inherited from the port, like the astral-plane gate noted in the GetKeyCode remarks.

Possible fix

Extend the unwinding with the US-positional base character for those codes, under the same ShiftKey || (macOptionAsAlt && AltKey) condition:

Backquote `   Minus -   Equal =   BracketLeft [   BracketRight ]   Backslash \
Semicolon ;   Quote '   Comma ,   Period .   Slash /

It carries the layout assumption the Digit* unwinding already makes (Digit5 is 5 unshifted on a US layout but ( on AZERTY), so non-US layouts are no worse off than the digit row is today. A host that knows the base-layout key could later supply it as the third sub-parameter, but KeyEvent has no field for it yet. Happy to send a PR with a regression test beside Shifted_key_appears_as_a_sub_parameter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions