Fixed #5205: Ctrl+Alt+2 doesn't send ^[^@ (#5272)

## 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
This commit is contained in:
Leonard Hecker 2021-02-08 16:33:38 +01:00 committed by GitHub
parent 2c603ef953
commit b009d06bc3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 22 additions and 12 deletions

View file

@ -39,6 +39,7 @@ systemroot
taskkill
tasklist
tdbuildteamid
VCRT
vcruntime
visualstudio
VSTHRD
@ -47,3 +48,4 @@ wslpath
wtl
wtt
wttlog
Xamarin

View file

@ -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;
}
}