Enable sending input to the Terminal with a keybinding #5342

Closed
opened 2026-01-31 00:11:03 +00:00 by claunia · 14 comments
Owner

Originally created by @compulim on GitHub (Dec 2, 2019).

Originally assigned to: @lhecker on GitHub.

Description of the new feature/enhancement

On Windows, there are difference between CTRL + C and CTRL + BREAK, as mentioned in #1118.

Some keyboard layouts do not have the BREAK key. For example, on Surface keyboard, there are no BREAK key. In some situations, CTRL + BREAK is a crucial way to break some processes.

Will be great if Windows Terminal has a command to map CTRL + BREAK to some other keys, e.g. CTRL + SHIFT + BREAK.

Proposed technical implementation details (optional)

Originally created by @compulim on GitHub (Dec 2, 2019). Originally assigned to: @lhecker on GitHub. # Description of the new feature/enhancement On Windows, there are difference between <kbd>CTRL</kbd> + <kbd>C</kbd> and <kbd>CTRL</kbd> + <kbd>BREAK</kbd>, as mentioned in #1118. Some keyboard layouts do not have the <kbd>BREAK</kbd> key. For example, on Surface keyboard, there are no <kbd>BREAK</kbd> key. In some situations, <kbd>CTRL</kbd> + <kbd>BREAK</kbd> is a crucial way to break some processes. Will be great if Windows Terminal has a command to map <kbd>CTRL</kbd> + <kbd>BREAK</kbd> to some other keys, e.g. <kbd>CTRL</kbd> + <kbd>SHIFT</kbd> + <kbd>BREAK</kbd>. # Proposed technical implementation details (optional) <!-- A clear and concise description of what you want to happen. -->
Author
Owner

@zadjii-msft commented on GitHub (Dec 2, 2019):

I could have sworn that we had an issue that was "I want to be able to send input to the Terminal with a keybinding" but it doesn't seem like we do. Congratulations! This is now that issue ☺️

Previously mentioned (in #2046):

  • We want to be able to send strings of characters
  • We want to be able to send input with or without a trailing newline (so people can run a command like #2809)
@zadjii-msft commented on GitHub (Dec 2, 2019): I could have sworn that we had an issue that was "I want to be able to send input to the Terminal with a keybinding" but it doesn't seem like we do. Congratulations! This is now that issue ☺️ Previously mentioned (in #2046): * [ ] We want to be able to send strings of characters * [ ] We want to be able to send input with or without a trailing newline (so people can run a command like #2809)
Author
Owner

@j4james commented on GitHub (Dec 2, 2019):

In case this affects the implementation, note that there are a couple of VT escape sequences for reprogramming the keyboard which we may want to support one day (e.g. DECUDK and DECPFK).

Also I think issue #2005 is quite similar to this.

@j4james commented on GitHub (Dec 2, 2019): In case this affects the implementation, note that there are a couple of VT escape sequences for reprogramming the keyboard which we may want to support one day (e.g. [`DECUDK`](https://vt100.net/docs/vt510-rm/DECUDK.html) and [`DECPFK`](https://vt100.net/docs/vt510-rm/DECPFK.html)). Also I think issue #2005 is quite similar to this.
Author
Owner

@compulim commented on GitHub (Dec 3, 2019):

@zadjii-msft I can read your mind. 😏

@compulim commented on GitHub (Dec 3, 2019): @zadjii-msft I can read your mind. 😏
Author
Owner

@SeeminglyScience commented on GitHub (Feb 19, 2020):

This would also enable a decent workaround for #530 (remap SHIFT + ENTER to some symbol that can be read instead). That would be an excellent band-aid for PowerShell folks looking to migrate.

@SeeminglyScience commented on GitHub (Feb 19, 2020): This would also enable a decent workaround for #530 (remap <kbd>SHIFT</kbd> + <kbd>ENTER</kbd> to some symbol that can be read instead). That would be an excellent band-aid for PowerShell folks looking to migrate.
Author
Owner

@damnskippy commented on GitHub (May 21, 2020):

+1 request for this feature.

@damnskippy commented on GitHub (May 21, 2020): +1 request for this feature.
Author
Owner

@damnskippy commented on GitHub (May 28, 2020):

For those who desperately seek a solution/workaround to remap key bindings, powertoys has a module to do this. Not the most perfect solution (since the mapping is global to the OS, not just the terminal) and I'm sure there are equivalents out there (AHK for instance), nor can you enter arbitrary input (only map to another shortcut), but this will at least tide one over until terminal can support this natively.

@damnskippy commented on GitHub (May 28, 2020): For those who desperately seek a solution/workaround to remap key bindings, [powertoys ](https://github.com/microsoft/PowerToys/tree/master/src/modules/keyboardmanager) has a module to do this. Not the most perfect solution (since the mapping is global to the OS, not just the terminal) and I'm sure there are equivalents out there (AHK for instance), nor can you enter arbitrary input (only map to another shortcut), but this will at least tide one over until terminal can support this natively.
Author
Owner

@damnskippy commented on GitHub (Jul 30, 2020):

Just curious if there's any love for this issue and is tracked on some milestone? Seems like a fairly popular request/demand based on the various dupes. Thanks, and much gratitude to WT - my daily driver.

@damnskippy commented on GitHub (Jul 30, 2020): Just curious if there's any love for this issue and is tracked on some milestone? Seems like a fairly popular request/demand based on the various dupes. Thanks, and much gratitude to WT - my daily driver.
Author
Owner

@DHowett commented on GitHub (Jul 31, 2020):

Alas! We haven't been working on this one, but we're pretty keen on it. I'm moving it into the 2.0 milestone and out of the backlog.

I don't know if I believe that a spec is required beyond a paragraph explaining what sendInput would do.

@DHowett commented on GitHub (Jul 31, 2020): Alas! We haven't been working on this one, but we're pretty keen on it. I'm moving it into the 2.0 milestone and out of the backlog. I don't know if I believe that a spec is required beyond a paragraph explaining what `sendInput` would do.
Author
Owner

@zadjii-msft commented on GitHub (Jul 31, 2020):

No real commitments on this one quite yet. I especially want to do this for it's potential integration with the command palette (#5400). The hardest part of this is honestly just designing exactly how the setting should work. How will arrow keys be encoded in the settings file? Trailing newlines? etc.

The implementation itself should be fairly trivial

@zadjii-msft commented on GitHub (Jul 31, 2020): No real commitments on this one quite yet. I especially want to do this for it's potential integration with the command palette (#5400). The hardest part of this is honestly just designing exactly how the setting should work. How will arrow keys be encoded in the settings file? Trailing newlines? etc. The implementation itself should be fairly trivial
Author
Owner

@damnskippy commented on GitHub (Jul 31, 2020):

Wonder if it's an option to specify a sequence/string of characters bound to a key shortcut. User can input the escape sequence for the key they want to enter. For example, left arrrow will be "\x1b[D". This would also allow for the other use case for this i.e. to be able to enter an arbitrary text (as opposed to mapping to another key). Say F12 is mapped to a character sequence "text entered over and over again\n" (including the newline). I believe Alacritty does something like this.

Just a thought, not sure how useful.

@damnskippy commented on GitHub (Jul 31, 2020): Wonder if it's an option to specify a sequence/string of characters bound to a key shortcut. User can input the escape sequence for the key they want to enter. For example, left arrrow will be `"\x1b[D"`. This would also allow for the other use case for this i.e. to be able to enter an arbitrary text (as opposed to mapping to another key). Say `F12` is mapped to a character sequence `"text entered over and over again\n"` (including the newline). I believe Alacritty does something like this. Just a thought, not sure how useful.
Author
Owner

@lhecker commented on GitHub (Aug 10, 2020):

I'd like to implement this feature, if you don't mind. 🙂

I believe this feature is crucial, but realistically will probably only be used by a small fraction of all Windows Terminal users.
As such it'd be best in my opinion to keep the feature as straightforward and low level as possible. That way it's easy to implement and simultaneously very powerful.

Config

I imagine a potential config setting to look like the following:

{
    "keybindings":
    [
        // Bind Ctrl+Shift+C to the Delete key
        { "keys": "ctrl+shift+c", "command": { "action": "sendInput", "input": "\u007f" } },

        // Send some text when pressing F12
        { "keys": "f12", "command": { "action": "sendInput", "input": "text entered over and over again\n" } },

        // Swap left/right arrow keys (lol)
        { "keys": "left", "command": { "action": "sendInput", "input": "\u001b[C" } },
        { "keys": "right", "command": { "action": "sendInput", "input": "\u001b[D" } },

        // Send a VK_PLAY (media play/pause button) key press to your shell
        { "keys": "f11", "command": { "action": "sendInput", "input": "\u001b[250;0;0;1;0;1_\u001b[250;0;0;0;0;1_" } },
    ]
}

Unfortunately I don't have a solution for CtrlBreak as that's equivalent to calling TerminateProcess and AFAICS you may just as well close the offending tab, right? 🤔

Implementation

  • Similar to other actions, extend ShortcutActionDispatch with SendInput.
  • Add a TerminalPage::_HandleSendInput method which calls TermControl::SendInput with the command.input value .
  • Add a TermControl::SendInput method which calls TermControl::_SendInputToConnection with the given input value.

Future extension

The above solution is very technical, but IMO sufficient for an initial implementation and can still be extended later on.
For instance the Win32 key sequences could also be represented with a JSON object instead.

@lhecker commented on GitHub (Aug 10, 2020): I'd like to implement this feature, if you don't mind. 🙂 I believe this feature is crucial, but realistically will probably only be used by a small fraction of all Windows Terminal users. As such it'd be best in my opinion to keep the feature as straightforward and low level as possible. That way it's easy to implement and simultaneously very powerful. ### Config I imagine a potential config setting to look like the following: ```json5 { "keybindings": [ // Bind Ctrl+Shift+C to the Delete key { "keys": "ctrl+shift+c", "command": { "action": "sendInput", "input": "\u007f" } }, // Send some text when pressing F12 { "keys": "f12", "command": { "action": "sendInput", "input": "text entered over and over again\n" } }, // Swap left/right arrow keys (lol) { "keys": "left", "command": { "action": "sendInput", "input": "\u001b[C" } }, { "keys": "right", "command": { "action": "sendInput", "input": "\u001b[D" } }, // Send a VK_PLAY (media play/pause button) key press to your shell { "keys": "f11", "command": { "action": "sendInput", "input": "\u001b[250;0;0;1;0;1_\u001b[250;0;0;0;0;1_" } }, ] } ``` Unfortunately I don't have a solution for <kbd>Ctrl</kbd><kbd>Break</kbd> as that's equivalent to calling `TerminateProcess` and AFAICS you may just as well close the offending tab, right? 🤔 ### Implementation * Similar to other actions, extend `ShortcutActionDispatch` with `SendInput`. * Add a `TerminalPage::_HandleSendInput` method which calls `TermControl::SendInput` with the `command.input` value . * Add a `TermControl::SendInput` method which calls `TermControl::_SendInputToConnection` with the given input value. ### Future extension The above solution is very technical, but IMO sufficient for an initial implementation and can still be extended later on. For instance the Win32 key sequences could also be represented with a JSON object instead.
Author
Owner

@zadjii-msft commented on GitHub (Aug 10, 2020):

Thoughts off the top of the dome:

  • I think we'll need \u001b to be the encoding for escape (for json's sake). I don't love that, but I think json will explode on \x1b
  • As far as implementation is concerned, I think it might be easier to just expose TermControl::SendInput(hstring input) as a method projected off of the TermControl class, rather than return a tuple from TryKeyChord. Then, just have TerminalPage actually send the string to the control, kinda like it handles paste or other actions with args:
    void TerminalPage::_HandleSendInput(const IInspectable& /*sender*/,
                                        const TerminalApp::ActionEventArgs& args)
    {
        if (const auto& realArgs = args.ActionArgs().try_as<TerminalApp::SendInputArgs>())
        {
            const auto termControl = _GetActiveControl();
            args.Handled(termControl.SendInput(realArgs.Input()));
        }
    }

The implementation of SendInput would be as easy as you suggest - the contents of realArgs.Input() are directly given to TermControl::_SendInputToConnection.

I'm totally on board with this, thanks for the writeup! I'll throw you on the Assigned To line 😉

@zadjii-msft commented on GitHub (Aug 10, 2020): Thoughts off the top of the dome: * I think we'll need `\u001b` to be the encoding for escape (for json's sake). I don't love that, but I think json will explode on `\x1b` * As far as implementation is concerned, I think it might be easier to just expose `TermControl::SendInput(hstring input)` as a method projected off of the `TermControl` class, rather than return a tuple from `TryKeyChord`. Then, just have `TerminalPage` actually send the string to the control, kinda like it handles paste or other actions with args: ```c++ void TerminalPage::_HandleSendInput(const IInspectable& /*sender*/, const TerminalApp::ActionEventArgs& args) { if (const auto& realArgs = args.ActionArgs().try_as<TerminalApp::SendInputArgs>()) { const auto termControl = _GetActiveControl(); args.Handled(termControl.SendInput(realArgs.Input())); } } ``` The implementation of `SendInput` would be as easy as you suggest - the contents of `realArgs.Input()` are directly given to `TermControl::_SendInputToConnection`. I'm totally on board with this, thanks for the writeup! I'll throw you on the **Assigned To** line 😉
Author
Owner

@lhecker commented on GitHub (Aug 10, 2020):

Aww... I always thought WT uses JSON5, but it seems it's using JSONC. (JSON5 supports \xNN escape codes.) *insert comment about using YAML here* 😄

Thanks @zadjii-msft! I wasn't aware about AppKeyBindings::SetDispatch and how it integrates into TerminalPage.
I've edited my proposal above to use unicode escape codes and changed the implementation section.

@lhecker commented on GitHub (Aug 10, 2020): Aww... I always thought WT uses JSON5, but it seems it's using JSONC. (JSON5 supports `\xNN` escape codes.) \*insert comment about using YAML here\* 😄 Thanks @zadjii-msft! I wasn't aware about `AppKeyBindings::SetDispatch` and how it integrates into `TerminalPage`. I've edited my proposal above to use unicode escape codes and changed the implementation section.
Author
Owner

@ghost commented on GitHub (Aug 26, 2020):

:tada:This issue was addressed in #7249, which has now been successfully released as Windows Terminal Preview v1.3.2382.0.🎉

Handy links:

@ghost commented on GitHub (Aug 26, 2020): :tada:This issue was addressed in #7249, which has now been successfully released as `Windows Terminal Preview v1.3.2382.0`.:tada: Handy links: * [Release Notes](https://github.com/microsoft/terminal/releases/tag/v1.3.2382.0) * [Store Download](https://www.microsoft.com/store/apps/9n8g5rfz9xk3?cid=storebadge&ocid=badge)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#5342