Add support for DECBKM (Backarrow Key Mode)#13894
Conversation
| // It's like a "filter" left to right. Due to the early return via | ||
| // !IsConsolePty, once you're at the !enable part, IsConsolePty can only be | ||
| // true anymore. | ||
| return !_api.IsConsolePty() || !_api.IsVtInputEnabled(); |
There was a problem hiding this comment.
Note to reviewers, if you didn't read the PR description, the additional check here that was specific to the FocusEvent mode has now been moved down into the EnableFocusEventMode method. I think this reduces some of the confusion that was introduced here, and also avoids unnecessary overhead in the other input mode operations.
This is isn't strictly related to DECBKM mode, though (other than as a minor optimisation), so if you'd prefer not to include this change in the PR, it wouldn't be a problem to revert it.
There was a problem hiding this comment.
This makes way more sense. Thanks!
DHowett
left a comment
There was a problem hiding this comment.
Not a single complaint. Thank you!
| // It's like a "filter" left to right. Due to the early return via | ||
| // !IsConsolePty, once you're at the !enable part, IsConsolePty can only be | ||
| // true anymore. | ||
| return !_api.IsConsolePty() || !_api.IsVtInputEnabled(); |
There was a problem hiding this comment.
This makes way more sense. Thanks!
|
Hello @DHowett! Because this pull request has the p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (
|
|
🎉 Handy links: |
The reverse VT input path in _DoControlCharacter mapped the byte 0x08 to a Ctrl+Backspace key event (VK_BACK with LEFT_CTRL_PRESSED and character 0x7F). This was introduced in PR microsoft#3935 (Jan 2020) to make Ctrl+Backspace delete whole words, which fixed issue microsoft#755. At that time, the forward path (TerminalInput) also sent 0x08 for Ctrl+Backspace, so the mapping was internally consistent, if a bit unusual. In September 2022, PR microsoft#13894 rewrote the forward path to properly implement DECBKM (Backarrow Key Mode). Under the default DECBKM setting, TerminalInput now sends 0x08 for plain Backspace and 0x7F for Ctrl+Backspace. The reverse path was never updated to match, breaking the roundtrip: a Backspace keypress encodes to 0x08, which decodes back as Ctrl+Backspace. The Cygwin project is working on using OpenConsole.exe for its ConPTY support, and a proposed patch series contains an ugly workaround for this bug that bypasses the normal input pipe and injects raw WriteConsoleInput events whenever 0x08 appears in the stream (https://inbox.sourceware.org/cygwin-patches/20260312113923.1528-4-takashi.yano@nifty.ne.jp/). Fixing the bug here avoids the need to accept that workaround. The fix assigns VK_BACK directly and clears writeCtrl, following the same pattern as the existing L'\x1b' case. This avoids the VkKeyScanW roundtrip through _GenerateKeyFromChar, which was the root cause: it reverse-mapped 0x7F to Ctrl+Backspace (since that is the keyboard combination that produces 0x7F), and then writeCtrl added LEFT_CTRL_PRESSED back after modifierState was zeroed. Note that the 0x7F handler (line 221) has the inverse problem: it maps 0x7F to plain Backspace, but the forward path now uses 0x7F for Ctrl+Backspace. That is a separate issue left for a follow-up. Assisted-by: Claude Opus 4.6 Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This is the companion to the previous commit which fixed 0x08. The forward path in TerminalInput (since PR microsoft#13894, DECBKM support) sends 0x7F for Ctrl+Backspace, but the reverse path in _DoControlCharacter was mapping 0x7F to a plain Backspace event (VK_BACK with character 0x08, no modifiers). The deleted comment acknowledged the mapping was a known compromise: it noted that "The windows telnet expects to send x7f as DELETE, not backspace" but chose to treat it as Backspace anyway because the old Windows telnetd could not move the cursor, making the distinction between delete-forward and backspace moot. That rationale no longer applies now that the forward path explicitly uses 0x7F for Ctrl+Backspace. The fix maps 0x7F to VK_BACK with LEFT_CTRL_PRESSED, restoring roundtrip symmetry with the forward path: Ctrl+Backspace encodes to 0x7F and now decodes back to Ctrl+Backspace. Assisted-by: Claude Opus 4.6 Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
In Windows 11, pseudo console has a weird behaviour that the Ctrl-H is translated into Ctrl-Backspace (not Backspace). The analysis in https://inbox.sourceware.org/cygwin-patches/2f8628d2-b79a-95a6-480d-7508375958d5@gmx.de/ shows that the reverse VT input path in conhost's `_DoControlCharacter()` maps the byte 0x08 to a Ctrl+Backspace key event (VK_BACK with LEFT_CTRL_PRESSED and character 0x7F). This was introduced in PR microsoft/terminal#3935 (Jan 2020) to make Ctrl+Backspace delete whole words. In September 2022, PR microsoft/terminal#13894 rewrote the forward path to properly implement DECBKM (Backarrow Key Mode), but the reverse path was never updated to match, breaking the roundtrip. Similary, Backspace (0x7f) is translated into Ctrl-H. Due to this behaviour, `inrec_eq()` in `cons_master_thread()` fails to compare backspace/Ctrl-H events in the input record sequence. This patch is a workaround for the issue that replaces Ctrl-H with backspace (0x7f), which will be translated into Ctrl-H in pseudo console. Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp> Reviewed-by: Johannes Schindelin <Johannes.Schindelin@gmx.de> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
This PR adds support for the
DECBKMsequence, which provides a way forapplications to specify whether the
Backspacekey should generate aBScharacter or aDELcharacter.On the original VT100 terminals, the
Backarrowkey generated aBS,and there was a separate
Deletekey that generatedDEL. However, onthe VT220 and later, there was only the
Backarrowkey. By default itgenerated
DEL, but from the VT320 onwards there was an option to makeit generate
BS, and theDECBKMsequence provided a way to controlthat behavior programmatically.
On modern terminals, the
Backspacekey serves as the equivalent of theVT
Backarrow, and typically generatesDEL, whileCtrl+Backspacegenerates
BS. WhenDECBKMis enabled (for those that support it),that behavior is reversed, i.e.
BackspacegeneratesBSandCtrl+BackspacegeneratesDEL.This PR also gets the other
Backspacemodifiers more closely alignedwith the expected behavior for modern terminals. The
Shiftmodifiertypically has no effect, and the
Altmodifier typically prefixes thegenerated sequence with an
ESCcharacter.While not strictly related to
DECBKM, I noticed while testing that the_SetInputModemethod was doing unnecessary work that was specific tothe
FocusEventmode. I've now moved that additional processing intothe
EnableFocusEventModemethod, which I think makes things somewhatsimpler.
Validation Steps Performed
I've tested the basic
DECBKMfunctionality in Vttest, and I'vemanually tested all the modifier key combinations to make sure they
match what most modern terminals generate.
I've also added a unit test that confirms that the expected sequences
are generated correctly when the
DECBKMmode is toggled.Closes #13884