Skip to content

Commit

Permalink
Fixed #5205: Ctrl+Alt+2 doesn't send ^[^@ (#5272)
Browse files Browse the repository at this point in the history
## Summary of the Pull Request

Fixes #5205, by replacing another use of `MapVirtualKeyW` with `ToUnicodeEx`.
The latter just seems to be much more consistent at translating key combinations in general.
In this particular case though it fixes the issue, because there's no differentiation in `MapVirtualKeyW` for whether it failed to return a character (`'\0'`) or succeeded in turning `^@` into `'\0'`.
`ToUnicodeEx` on the other hand returns the success state separately from the translated character.

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #5205
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [x] Tests added/passed
* [ ] Requires documentation to be updated
* [x] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #5205

## Detailed Description of the Pull Request / Additional comments

This PR changes the behavior of the `Ctrl+Alt+Key` handling slightly:
⚠️ `ToUnicodeEx` returns unshifted characters. ⚠️
For instance `Ctrl+Alt+a` is now turned into `^[^a`. Due to how ASCII works this is essentially the same though because `'A' & 0b11111` and `'a' & 0b11111` are the same.

## Validation Steps Performed

* Run `showkey -a`
* Ensured `Ctrl+Alt+Space` as well as `Ctrl+Alt+Shift+2` are turned into `^[^@`
* Ensured other, random `Ctrl+Alt+Key` combination behave identical to the current master
  • Loading branch information
lhecker authored Feb 8, 2021
1 parent 2c603ef commit b009d06
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 12 deletions.
2 changes: 2 additions & 0 deletions .github/actions/spelling/dictionary/microsoft.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ systemroot
taskkill
tasklist
tdbuildteamid
VCRT
vcruntime
visualstudio
VSTHRD
Expand All @@ -47,3 +48,4 @@ wslpath
wtl
wtt
wttlog
Xamarin
32 changes: 20 additions & 12 deletions src/terminal/input/terminalInput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -565,25 +565,33 @@ bool TerminalInput::HandleKey(const IInputEvent* const pInEvent)
// for the 5 least significant ones to be zeroed out.
if (keyEvent.IsAltPressed() && keyEvent.IsCtrlPressed())
{
auto ch = keyEvent.GetCharData();
if (ch == UNICODE_NULL)
{
// For Alt+Ctrl+Key messages GetCharData() returns 0.
// The values of the ASCII characters and virtual key codes
// of <Space>, A-Z (as used below) are numerically identical.
// -> Get the char from the virtual key.
ch = keyEvent.GetVirtualKeyCode();
}
const auto ch = keyEvent.GetCharData();
const auto vkey = keyEvent.GetVirtualKeyCode();

// For Alt+Ctrl+Key messages GetCharData() usually returns 0.
// Luckily the numerical values of the ASCII characters and virtual key codes
// of <Space> and A-Z, as used below, are numerically identical.
// -> Get the char from the virtual key if it's 0.
const auto ctrlAltChar = keyEvent.GetCharData() != 0 ? keyEvent.GetCharData() : keyEvent.GetVirtualKeyCode();

// Alt+Ctrl acts as a substitute for AltGr on Windows.
// For instance using a German keyboard both AltGr+< and Alt+Ctrl+< produce a | (pipe) character.
// The below condition primitively ensures that we allow all common Alt+Ctrl combinations
// while preserving most of the functionality of Alt+Ctrl as a substitute for AltGr.
if (ch == UNICODE_SPACE || (ch > 0x40 && ch <= 0x5A))
if (ctrlAltChar == UNICODE_SPACE || (ctrlAltChar > 0x40 && ctrlAltChar <= 0x5A))
{
// Pressing the control key causes all bits but the 5 least
// significant ones to be zeroed out (when using ASCII).
ch &= 0b11111;
_SendEscapedInputSequence(ch);
_SendEscapedInputSequence(ctrlAltChar & 0b11111);
return true;
}

// Currently, when we're called with Alt+Ctrl+@, ch will be 0, since Ctrl+@ equals a null byte.
// VkKeyScanW(0) in turn returns the vkey for the null character (ASCII @).
// -> Use the vkey to determine if Ctrl+@ is being pressed and produce ^[^@.
if (ch == UNICODE_NULL && vkey == LOBYTE(VkKeyScanW(0)))
{
_SendEscapedInputSequence(L'\0');
return true;
}
}
Expand Down

0 comments on commit b009d06

Please sign in to comment.