560 lines
24 KiB
Markdown
560 lines
24 KiB
Markdown
---
|
|
author: Mike Griese @zadjii-msft
|
|
created on: 2020-05-07
|
|
last updated: 2020-06-03
|
|
issue id: 4999
|
|
---
|
|
|
|
# Improved keyboard handling in Conpty
|
|
|
|
## Abstract
|
|
|
|
The Windows Console internally uses [`INPUT_RECORD`]s to represent the various
|
|
types of input that a user might send to a client application. This includes
|
|
things like keypresses, mouse events, window resizes, etc.
|
|
|
|
However, conpty's keyboard input is fundamentally backed by VT sequences, which
|
|
limits the range of keys that a terminal application can actually send relative
|
|
to what the console was capable of. This results in a number of keys that were
|
|
previously representable in the console as `INPUT_RECORD`s, but are impossible
|
|
to send to a client application that's running in conpty mode.
|
|
|
|
Some of these issues include, but are not limited to:
|
|
|
|
* Some keybindings used by PSReadLine aren't getting through [#879]
|
|
* Bug Report: Control+Space not sent to terminal emulator. [#2865]
|
|
* Shift+Enter always submits, breaking PSReadline features [#530]
|
|
* Powershell: Ctrl-Alt-? does not work in Windows Terminal [#3079]
|
|
* Bug: ctrl+break is not ctrl+c [#1119]
|
|
* Something wrong with keyboard modifiers processing? [#1694]
|
|
* Numeric input not accepted by choice.exe [#3608]
|
|
* Ctrl+Keys that can't be encoded as VT should still fall through as the unmodified character [#3483]
|
|
* Modifier keys are not properly propagated to application hosted in Windows Terminal [#4334] / [#4446]
|
|
|
|
This spec covers a mechanism by which we can add support to ConPTY so that a
|
|
terminal application could send `INPUT_RECORD`-like key events to conpty,
|
|
enabling client applications to receive the full range of keys once again.
|
|
Included at the bottom of this document is a collection of [options that were
|
|
investigated](#options-considered) as a part of preparing this document.
|
|
|
|
## Considerations
|
|
|
|
When evaluating existing encoding schemes for viability, the following things
|
|
were used to evaluate whether or not a particular encoding would work for our
|
|
needs:
|
|
|
|
* Would a particular encoding be mixable with other normal VT processing easily?
|
|
- How would the Terminal know when it should send a \<chosen_encoding> key vs
|
|
a normally encoded one?
|
|
- For ex, <kbd>Ctrl+space</kbd> - should we send `NUL` or
|
|
\<chosen_encoding's version of ctrl+space>
|
|
* If there's a scenario where Windows Terminal might _not_ be connected to a
|
|
conpty, then how does conpty enable \<chosen_encoding>?
|
|
* Is the goal "Full `INPUT_RECORD` fidelity" or "Make the above scenarios work"?
|
|
- One could imagine having the Terminal special-case the above keys, and send
|
|
the xterm modifyOtherKeys sequences just for those scenarios.
|
|
- This would _not_ work for <kbd>shift</kbd> all by itself.
|
|
- In my _opinion_, "just making the above work" is a subset of "full
|
|
INPUT_RECORD", and inevitably we're going to want "full INPUT_RECORD"
|
|
|
|
The goal we're trying to achieve is communicating `INPUT_RECORD`s from the
|
|
terminal to the client app via conpty. This isn't supposed to be a \*nix
|
|
terminal compatible communication, it's supposed to be fundamentally Win32-like.
|
|
|
|
Keys that we definitely need to support, that don't have unique VT sequences:
|
|
* <kbd>Ctrl+Space</kbd> ([#879], [#2865])
|
|
* <kbd>Shift+Enter</kbd> ([#530])
|
|
* <kbd>Ctrl+Break</kbd> ([#1119])
|
|
* <kbd>Ctrl+Alt+?</kbd> ([#3079])
|
|
* <kbd>Ctrl</kbd>, <kbd>Alt</kbd>, <kbd>Shift</kbd>, (without another keydown/up) ([#3608], [#4334], [#4446])
|
|
|
|
> 👉 NOTE: There are actually 5 types of events that can all be encoded as an
|
|
> `INPUT_RECORD`. This spec primarily focuses on the encoding of
|
|
> `KEY_EVENT_RECORD`s. It is left as a Future Consideration to add support for
|
|
> the other types of `INPUT_RECORD` as other sequences, which could be done
|
|
> trivially similarly to the following proposal.
|
|
|
|
## Solution Design
|
|
|
|
### Inspiration
|
|
|
|
The design we've settled upon is one that's highly inspired by a few precedents:
|
|
* `Application Cursor Keys (DECCKM)` is a long-supported VT sequence which a
|
|
client application can use to request a different input format from the
|
|
Terminal. This is the DECSET sequence `^[[?1h`/`^[[?1l` (for enable/disable,
|
|
respectively). This changes the sequences sent by keys like the Arrow keys
|
|
from a sequence like `^[[A` to `^[OA` instead.
|
|
* The `kitty` terminal emulator uses a similar DECSET sequence for enabling
|
|
their own input format, which they call ["full mode"]. Similar to DECCKM, this
|
|
changes the format of the sequences that the terminal should send for keyboard
|
|
input. Their "full mode" contains much more information when keys are pressed
|
|
or released (though, less than a full `INPUT_RECORD` worth of data). Instead
|
|
of input being sent to the client as a CSI or SS3 sequence, this `kitty` mode
|
|
uses "Application Program-Command" (or "APC") sequences , prefixed with `^[_`.
|
|
* [iTerm2](https://www.iterm2.com/documentation-escape-codes.html) has a region
|
|
of OSC's that they've carved for themselves all starting with the same initial
|
|
parameter, `1337`. They then have a number of commands that all use the second
|
|
parameter to indicate what command specific to iTerm2 they're actually
|
|
implementing.
|
|
|
|
### Requesting `win32-input-mode`
|
|
|
|
An application can request `win32-input-mode` with the following private mode sequence:
|
|
|
|
```
|
|
^[ [ ? 9001 h/l
|
|
l: Disable win32-input-mode
|
|
h: Enable win32-input-mode
|
|
```
|
|
|
|
Private mode `9001` seems unused according to the [xterm
|
|
documentation](https://invisible-island.net/xterm/ctlseqs/ctlseqs.html). This is
|
|
stylistically similar to how `DECKPM`, `DECCKM`, and `kitty`'s ["full mode"] are
|
|
enabled.
|
|
|
|
> 👉 NOTE: an earlier draft of this spec used an OSC sequence for enabling these
|
|
> sequences. This was abandoned in favor of the more stylistically consistent
|
|
> private mode params proposed above. Additionally, if implemented as a private
|
|
> mode, then a client app could query if this setting was set with `DECRQM`
|
|
|
|
When a terminal receives a `^[[?9001h` sequence, they should switch into
|
|
`win32-input-mode`. In `win32-input-mode`, the terminal will send keyboard input
|
|
to the connected client application in the following format:
|
|
|
|
### `win32-input-mode` sequences
|
|
|
|
The `KEY_EVENT_RECORD` portion of an input record (the part that's important for
|
|
us to encode in this feature) is defined as the following:
|
|
|
|
```c++
|
|
typedef struct _KEY_EVENT_RECORD {
|
|
BOOL bKeyDown;
|
|
WORD wRepeatCount;
|
|
WORD wVirtualKeyCode;
|
|
WORD wVirtualScanCode;
|
|
union {
|
|
WCHAR UnicodeChar;
|
|
CHAR AsciiChar;
|
|
} uChar;
|
|
DWORD dwControlKeyState;
|
|
} KEY_EVENT_RECORD;
|
|
```
|
|
|
|
To encode all of this information, I propose the following sequence. This is a
|
|
CSI sequence with a final terminator character of `_`. This character appears to
|
|
only be used as a terminator for the [SCO input
|
|
sequence](https://vt100.net/docs/vt510-rm/chapter6.html) for
|
|
<kbd>Ctrl+Shift+F10</kbd>. This conflict isn't a real concern for us
|
|
compatibility wise. For more details, see [SCO
|
|
Compatibility](#SCO-compatibility) below.
|
|
|
|
```
|
|
^[ [ Vk ; Sc ; Uc ; Kd ; Cs ; Rc _
|
|
|
|
Vk: the value of wVirtualKeyCode - any number. If omitted, defaults to '0'.
|
|
|
|
Sc: the value of wVirtualScanCode - any number. If omitted, defaults to '0'.
|
|
|
|
Uc: the decimal value of UnicodeChar - for example, NUL is "0", LF is
|
|
"10", the character 'A' is "65". If omitted, defaults to '0'.
|
|
|
|
Kd: the value of bKeyDown - either a '0' or '1'. If omitted, defaults to '0'.
|
|
|
|
Cs: the value of dwControlKeyState - any number. If omitted, defaults to '0'.
|
|
|
|
Rc: the value of wRepeatCount - any number. If omitted, defaults to '1'.
|
|
|
|
```
|
|
|
|
> 👉 NOTE: an earlier draft of this spec used an APC sequence for encoding the
|
|
> input sequences. This was changed to a CSI for stylistic reasons. There's not
|
|
> a great body of reference anywhere that lists APC sequences in use, so there's
|
|
> no way to know if the sequence would collide with another terminal emulator's
|
|
> usage. Furthermore, using an APC seems to give a distinct impression that
|
|
> this is some "Windows Terminal" specific sequence, which is not intended. This
|
|
> is a Windows-specific sequence, but one that any Terminal/application could
|
|
> use.
|
|
|
|
In this way, a terminal can communicate input to a connected client application
|
|
as `INPUT_RECORD`s, without any loss of fidelity.
|
|
|
|
#### Example
|
|
|
|
When the user presses <kbd>Ctrl+F1</kbd> in the console, the console actually
|
|
send 4 input records to the client application:
|
|
* A <kbd>Ctrl</kbd> down event
|
|
* A <kbd>F1</kbd> down event
|
|
* A <kbd>F1</kbd> up event
|
|
* A <kbd>Ctrl</kbd> up event
|
|
|
|
Encoded in `win32-input-mode`, this would look like the following:
|
|
```
|
|
^[[17;29;0;1;8;1_
|
|
^[[112;59;0;1;8;1_
|
|
^[[112;59;0;0;8;1_
|
|
^[[17;29;0;0;0;1_
|
|
|
|
Down: 1 Repeat: 1 KeyCode: 0x11 ScanCode: 0x1d Char: \0 (0x0) KeyState: 0x28
|
|
Down: 1 Repeat: 1 KeyCode: 0x70 ScanCode: 0x3b Char: \0 (0x0) KeyState: 0x28
|
|
Down: 0 Repeat: 1 KeyCode: 0x70 ScanCode: 0x3b Char: \0 (0x0) KeyState: 0x28
|
|
Down: 0 Repeat: 1 KeyCode: 0x11 ScanCode: 0x1d Char: \0 (0x0) KeyState: 0x20
|
|
```
|
|
|
|
Similarly, for a keypress like <kbd>Ctrl+Alt+A</kbd>, which is 6 key events:
|
|
```
|
|
^[[17;29;0;1;8;1_
|
|
^[[18;56;0;1;10;1_
|
|
^[[65;30;0;1;10;1_
|
|
^[[65;30;0;0;10;1_
|
|
^[[18;56;0;0;8;1_
|
|
^[[17;29;0;0;0;1_
|
|
|
|
Down: 1 Repeat: 1 KeyCode: 0x11 ScanCode: 0x1d Char: \0 (0x0) KeyState: 0x28
|
|
Down: 1 Repeat: 1 KeyCode: 0x12 ScanCode: 0x38 Char: \0 (0x0) KeyState: 0x2a
|
|
Down: 1 Repeat: 1 KeyCode: 0x41 ScanCode: 0x1e Char: \0 (0x0) KeyState: 0x2a
|
|
Down: 0 Repeat: 1 KeyCode: 0x41 ScanCode: 0x1e Char: \0 (0x0) KeyState: 0x2a
|
|
Down: 0 Repeat: 1 KeyCode: 0x12 ScanCode: 0x38 Char: \0 (0x0) KeyState: 0x28
|
|
Down: 0 Repeat: 1 KeyCode: 0x11 ScanCode: 0x1d Char: \0 (0x0) KeyState: 0x20
|
|
```
|
|
|
|
Or, for something simple like <kbd>A</kbd> (which is 4 key events):
|
|
```
|
|
^[[16;42;0;1;16;1_
|
|
^[[65;30;65;1;16;1_
|
|
^[[16;42;0;0;0;1_
|
|
^[[65;30;97;0;0;1_
|
|
|
|
Down: 1 Repeat: 1 KeyCode: 0x10 ScanCode: 0x2a Char: \0 (0x0) KeyState: 0x30
|
|
Down: 1 Repeat: 1 KeyCode: 0x41 ScanCode: 0x1e Char: A (0x41) KeyState: 0x30
|
|
Down: 0 Repeat: 1 KeyCode: 0x10 ScanCode: 0x2a Char: \0 (0x0) KeyState: 0x20
|
|
Down: 0 Repeat: 1 KeyCode: 0x41 ScanCode: 0x1e Char: a (0x61) KeyState: 0x20
|
|
```
|
|
|
|
> 👉 NOTE: In all the above examples, I had my NumLock key off. If I had the
|
|
> NumLock key instead pressed, all the KeyState parameters would have bits 0x20
|
|
> set. To get these keys with a NumLock, add 32 to the value.
|
|
|
|
These parameters are ordered based on how likely they are to be used. Most of
|
|
the time, the repeat count is not needed (it's almost always `1`), so it can be
|
|
left off when not required. Similarly, the control key state is probably going
|
|
to be 0 a lot of the time too, so that is second last. Even keydown will be 0 at
|
|
least half the time, so that can be omitted some of the time.
|
|
|
|
Furthermore, considering omitted values in CSI parameters default to the values
|
|
specified above, the above sequences could each be shortened to the following.
|
|
|
|
* <kbd>Ctrl+F1</kbd>
|
|
```
|
|
^[[17;29;;1;8_
|
|
^[[112;59;;1;8_
|
|
^[[112;59;;;8_
|
|
^[[17;29_
|
|
```
|
|
|
|
* <kbd>Ctrl+Alt+A</kbd>
|
|
```
|
|
^[[17;29;;1;8_
|
|
^[[18;56;;1;10_
|
|
^[[65;30;;1;10_
|
|
^[[65;30;;;10_
|
|
^[[18;56;;;8_
|
|
^[[17;29;;_
|
|
```
|
|
|
|
* <kbd>A</kbd> (which is <kbd>shift+a</kbd>)
|
|
```
|
|
^[[16;42;;1;16_
|
|
^[[65;30;65;1;16_
|
|
^[[16;42_
|
|
^[[65;30;97_
|
|
```
|
|
|
|
* Or even easier, just <kbd>a</kbd>
|
|
```
|
|
^[[65;30;97;1_
|
|
^[[65;30;97_
|
|
```
|
|
|
|
### Scenarios
|
|
|
|
#### User is typing into WSL from the Windows Terminal
|
|
|
|
`WT -> conpty[1] -> wsl`
|
|
|
|
* Conpty[1] will ask for `win32-input-mode` from the Windows Terminal when
|
|
conpty[1] first boots up. Conpty will _always_ ask for win32-input-mode -
|
|
Terminals that _don't_ support this mode will ignore this sequence on startup.
|
|
* When the user types keys in Windows Terminal, WT will translate them into
|
|
win32 sequences and send them to conpty[1]
|
|
* Conpty[1] will translate those win32 sequences into `INPUT_RECORD`s.
|
|
- When those `INPUT_RECORD`s are written to the input buffer, they'll be
|
|
converted into VT sequences corresponding to whatever input mode the linux
|
|
app is in.
|
|
* When WSL reads the input, it'll read (using `ReadConsoleInput`) a stream of
|
|
`INPUT_RECORD`s that contain only character information, which it will then
|
|
pass to the linux application.
|
|
- This is how `wsl.exe` behaves today, before this change.
|
|
|
|
#### User is typing into `cmd.exe` running in WSL interop
|
|
|
|
`WT -> conpty[1] -> wsl -> conpty[2] -> cmd.exe`
|
|
|
|
(presuming you start from the previous scenario, and launch `cmd.exe` inside wsl)
|
|
|
|
* Conpty[2] will ask for `win32-input-mode` from conpty[1] when conpty[2] first
|
|
boots up.
|
|
- As conpty[1] is just a conhost that knows how to handle
|
|
`win32-input-mode`, it will switch its own VT input handling into
|
|
`win32-input-mode`
|
|
* When the user types keys in Windows Terminal, WT will translate them into
|
|
win32 sequences and send them to conpty[1]
|
|
* Conpty[1] will translate those win32 sequences into `INPUT_RECORD`s. When
|
|
conpty[1] writes these to its buffer, it will translate the `INPUT_RECORD`s
|
|
into VT sequences for the `win32-input-mode`. This is because it believes the
|
|
client (in this case, the conpty[2] running attached to `wsl`) wants
|
|
`win32-input-mode`.
|
|
* When WSL reads the input, it'll read (using `ReadConsoleInput`) a stream of
|
|
`INPUT_RECORD`s that contain only character information, which it will then
|
|
use to pass a stream of characters to conpty[2].
|
|
* Conpty[2] will get those sequences, and will translate those win32 sequences
|
|
into `INPUT_RECORD`s
|
|
* When `cmd.exe` reads the input, they'll receive the full `INPUT_RECORD`s
|
|
they're expecting
|
|
|
|
|
|
## UI/UX Design
|
|
|
|
This is not a user-facing feature.
|
|
|
|
## Capabilities
|
|
|
|
### Accessibility
|
|
|
|
_(no change expected)_
|
|
|
|
### Security
|
|
|
|
_(no change expected)_
|
|
|
|
### Reliability
|
|
|
|
_(no change expected)_
|
|
|
|
### Compatibility
|
|
|
|
This isn't expected to break any existing scenarios. The information that we're
|
|
passing to conpty from the Terminal should strictly have _more_ information in
|
|
them than they used to. Conhost was already capable of translating
|
|
`INPUT_RECORD`s back into VT sequences, so this should work the same as before.
|
|
|
|
There's some hypothetical future where the Terminal isn't connected to conpty.
|
|
In that future, the Terminal will still be able to work correctly, even with
|
|
this ConPTY change. The Terminal will only switch into sending
|
|
`win32-input-mode` sequences when _conpty asks for them_. Otherwise, the
|
|
Terminal will still behave like a normal terminal emulator.
|
|
|
|
#### Terminals that don't support `?9001h`
|
|
|
|
Traditionally, whenever a terminal emulator doesn't understand a particular VT
|
|
sequence, they simply ignore the unknown sequence. This assumption is being
|
|
relied upon heavily, as ConPTY will _always_ emit a `^[[?9001h` on
|
|
initialization, to request `win32-input-mode`.
|
|
|
|
#### SCO Compatibility
|
|
|
|
As mentioned above, the `_` character is used as a terminator for the [SCO input
|
|
sequence](https://vt100.net/docs/vt510-rm/chapter6.html) for
|
|
<kbd>Ctrl+Shift+F10</kbd>. This conflict would be a problem if a hypothetical
|
|
terminal was connected to conpty that sent input to conpty in SCO format.
|
|
However, if that terminal was only sending input to conpty in SCO mode, it would
|
|
have much worse problems than just <kbd>Ctrl+Shift+F10</kbd> not working. If we
|
|
did want to support SCO mode in the future, I'd even go so far as to say we
|
|
could maybe treat a `win32-input-mode` sequence with no params as
|
|
<kbd>Ctrl+Shift+F10</kbd>, considering that `KEY_EVENT_RECORD{0}` isn't really
|
|
valid anyways.
|
|
|
|
#### Remoting `INPUT_RECORD`s
|
|
|
|
A potential area of concern is the fact that VT sequences are often used to
|
|
remote input from one machine to another. For example, a terminal might be
|
|
running on machine A, and the conpty at the end of the pipe (which is running
|
|
the client application) might be running on another machine B.
|
|
|
|
If these two machines have different keyboard layouts, then it's possible that
|
|
the `INPUT_RECORD`s synthesized by the terminal on machine A won't really be
|
|
valid on machine B. It's possible that machine B has a different mapping of scan
|
|
codes \<-> characters. A client that's running on machine B that uses win32 APIs
|
|
to try and infer the vkey, scancode, or character from the other information in
|
|
the `INPUT_RECORD` might end up synthesizing the wrong values.
|
|
|
|
At the time of writing, we're not really sure what a good solution to this
|
|
problem would be. Client applications that use `win32-input-mode` should be
|
|
aware of this, and be written with the understanding that these values are
|
|
coming from the terminal's machine, which might not necessarily be the local
|
|
machine.
|
|
|
|
### Performance, Power, and Efficiency
|
|
|
|
_(no change expected)_
|
|
|
|
## Potential Issues
|
|
|
|
_(no change expected)_
|
|
|
|
## Future considerations
|
|
|
|
* We could also hypothetically use this same mechanism to send Win32-like mouse
|
|
events to conpty, since similar to VT keyboard events, VT mouse events don't
|
|
have the same fidelity that Win32 mouse events do.
|
|
- We could enable this with a different terminating character, to identify
|
|
which type of `INPUT_RECORD` event we're encoding.
|
|
* Client applications that want to be able to read full Win32 keyboard input
|
|
from `conhost` _using VT_ will also be able to use `^[[?9001h` to do this. If
|
|
they emit `^[[?9001h`, then conhost will switch itself into
|
|
`win32-input-mode`, and the client will read `win32-input-mode` encoded
|
|
sequences as input. This could enable other cross-platform applications to
|
|
also use win32-like input in the future.
|
|
|
|
## Options Considered
|
|
|
|
_disclaimer: these notes are verbatim from my research notes in [#4999]_.
|
|
|
|
### Create our own format for `INPUT_RECORD`s
|
|
|
|
* If we wanted to do this, then we'd probably want to have the Terminal only
|
|
send input as this format, and not use the existing translator to synthesize
|
|
VT sequences
|
|
- Consider sending a ctrl down, '^A', ctrl up. We wouldn't want to send this
|
|
as three sequences, because conpty will take the '^A' and synthesize
|
|
_another_ ctrl down, ctrl up pair.
|
|
* With conpty passthrough mode, we'd still need the `InputStateMachineEngine`
|
|
to convert these sequences into INPUT_RECORDs to translate back to VT
|
|
* Wouldn't really expect client apps to ever _need_ this format, but it could
|
|
always be possible for them to need it in the future.
|
|
|
|
#### Pros:
|
|
* Definitely gets us all the information that we need.
|
|
* Can handle solo modifiers
|
|
* Can handle keydown and keyup separately
|
|
* We can make the sequence however we want to parse it.
|
|
|
|
#### Cons:
|
|
* No reference implementation, so we'd be flying blind
|
|
* We'd be defining our own VT sequences for these, which we've never done
|
|
before. This was _inevitable_, however, this is still the first time we'd be
|
|
doing this.
|
|
* By having the Terminal send all input as _this protocol_, VT Input passthrough
|
|
to apps that want VT input won't work anymore for the Terminal. That's _okay_
|
|
|
|
### kitty extension
|
|
[Reference](https://sw.kovidgoyal.net/kitty/protocol-extensions.html#keyboard-handling)
|
|
|
|
#### Pros:
|
|
* Not terribly difficult to decode
|
|
* Unique from anything else we'd be processing, as it's an APC sequence
|
|
(`\x1b_`)
|
|
* From their docs:
|
|
> All printable key presses without modifier keys are sent
|
|
just as in the normal mode. ... For non printable keys and key combinations
|
|
including one or more modifiers, an escape sequence encoding the key event is
|
|
sent
|
|
- I think I like this. ASCII and other keyboard layout chars (things that would
|
|
hit `SendChar`) would still just come through as the normal char.
|
|
|
|
#### Cons:
|
|
* Their encoding table is _odd_. [Look at
|
|
this](https://sw.kovidgoyal.net/kitty/key-encoding.html). What order is that
|
|
in? Obviously the first column is sorted alphabetically, but the mapping of
|
|
key->char is in a certainly hard to decipher order.
|
|
* I can't get it working locally, so hard to test 😐
|
|
* They do declare the `fullkbd` terminfo capability to identify that they
|
|
support this mode, but I'm not sure anyone else uses it.
|
|
- I'm also not sure that any _client_ apps are reading this currently.
|
|
* This isn't designed to be full `KEY_EVENT`s - where would we put the scancode
|
|
(for apps that think that's important)?
|
|
- We'd have to extend this protocol _anyways_
|
|
|
|
### `xterm` "Set key modifier options"
|
|
Notably looking at
|
|
[`modifyOtherKeys`](https://invisible-island.net/xterm/manpage/xterm.html#VT100-Widget-Resources:modifyOtherKeys).
|
|
|
|
#### Pros:
|
|
* `xterm` implements this so there's a reference implementation
|
|
* relatively easy to parse these sequences. `CSI 27 ; <modifiers> ; <key> ~`
|
|
|
|
#### Cons:
|
|
* Only sends the sequence on key-up
|
|
* Doesn't send modifiers all on their own
|
|
|
|
### `DECPCTERM`
|
|
[VT100.net doc](https://vt100.net/docs/vt510-rm/DECPCTERM.html)
|
|
|
|
#### Pros:
|
|
* Enables us to send key-down and key-up keys independently
|
|
* Enables us to send modifiers on their own
|
|
* Part of the VT 510 standard
|
|
|
|
#### Cons:
|
|
* neither `xterm` nor `gnome-terminal` (VTE) seem to implement this. I'm not
|
|
sure if anyone's got a reference implementation for us to work with.
|
|
* Unsure how this would work with other keyboard layouts
|
|
- [this doc](https://vt100.net/docs/vt510-rm/chapter8.html#S8.13) seems to
|
|
list the key-down/up codes for all the en-us keyboard keys, but the
|
|
scancodes for these are different for up and down. That would seem to
|
|
imply we couldn't just shove the Win32 scancode in those bits
|
|
|
|
### `DECKPM`, `DECSMKR`
|
|
[DECKPM](https://vt100.net/docs/vt510-rm/DECKPM.html)
|
|
[DECSMKR](https://vt100.net/docs/vt510-rm/DECSMKR.html)
|
|
[DECEKBD](https://vt100.net/docs/vt510-rm/DECEKBD.html)
|
|
|
|
#### Pros:
|
|
* Enables us to send key-down and key-up keys independently
|
|
* Enables us to send modifiers on their own
|
|
* Part of the VT 510 standard
|
|
|
|
#### Cons:
|
|
* neither `xterm` nor `gnome-terminal` (VTE) seem to implement this. I'm not
|
|
sure if anyone's got a reference implementation for us to work with.
|
|
* not sure that "a three-character ISO key position name, for example C01" is
|
|
super compatible with our Win32 VKEYs.
|
|
|
|
|
|
### `libtickit` encoding
|
|
[Source](http://www.leonerd.org.uk/hacks/fixterms)
|
|
|
|
#### Pros:
|
|
* Simple encoding scheme
|
|
|
|
#### Cons:
|
|
* Doesn't differentiate between keydowns and keyups
|
|
* Unsure who implements this - not extensively investigated
|
|
|
|
|
|
## Resources
|
|
|
|
* The initial discussion for this topic was done in [#879], and much of the
|
|
research of available options is also available as a discussion in [#4999].
|
|
* [Why Is It so Hard to Detect Keyup Event on Linux?](https://blog.robertelder.org/detect-keyup-event-linux-terminal/)
|
|
- and the [HackerNews discussion](https://news.ycombinator.com/item?id=19012132)
|
|
* [ConEmu specific OSCs](https://conemu.github.io/en/AnsiEscapeCodes.html#ConEmu_specific_OSC)
|
|
* [iterm2 specific sequences](https://www.iterm2.com/documentation-escape-codes.html)
|
|
* [terminal-wg draft list of OSCs](https://gitlab.freedesktop.org/terminal-wg/specifications/-/issues/10)
|
|
|
|
<!-- Footnotes -->
|
|
[#530]: https://github.com/microsoft/terminal/issues/530
|
|
[#879]: https://github.com/microsoft/terminal/issues/879
|
|
[#1119]: https://github.com/microsoft/terminal/issues/1119
|
|
[#1694]: https://github.com/microsoft/terminal/issues/1694
|
|
[#2865]: https://github.com/microsoft/terminal/issues/2865
|
|
[#3079]: https://github.com/microsoft/terminal/issues/3079
|
|
[#3483]: https://github.com/microsoft/terminal/issues/3483
|
|
[#3608]: https://github.com/microsoft/terminal/issues/3608
|
|
[#4334]: https://github.com/microsoft/terminal/issues/4334
|
|
[#4446]: https://github.com/microsoft/terminal/issues/4446
|
|
[#4999]: https://github.com/microsoft/terminal/issues/4999
|
|
|
|
[`INPUT_RECORD`]: https://docs.microsoft.com/en-us/windows/console/input-record-str
|
|
|
|
["full mode"]: https://sw.kovidgoyal.net/kitty/protocol-extensions.html#keyboard-handling
|