Conversation
This comment has been minimized.
This comment has been minimized.
| } | ||
|
|
||
| // Keep track of key repeats. | ||
| key.keyRepeat = _lastVirtualKeyCode == key.virtualKey; |
There was a problem hiding this comment.
Placing the detection outside a if (key.keyDown) block meant that a single key up/down would already be detected as a key repeat.
| if (const auto flags = _controlKeyStateFromVirtualKey(key.virtualKey, key.controlKeyState)) | ||
| { | ||
| key.keyRepeat = (_previousControlKeyState & flags) != 0; | ||
| } |
There was a problem hiding this comment.
These 3 lines fix the AltGr key repeat.
| // Suppress modifier key events at all times - they aren't reported in any protocol. | ||
| (key.virtualKey >= VK_SHIFT && key.virtualKey <= VK_MENU) || | ||
| (key.virtualKey >= VK_LSHIFT && key.virtualKey <= VK_RMENU) || |
There was a problem hiding this comment.
KKP doesn't report key repeats for modifier keys.
| (key.virtualKey >= VK_LSHIFT && key.virtualKey <= VK_RMENU) || | ||
| (_kittyFlags != 0 ? | ||
| // If KKP is enabled, we only report repeats if ReportEventTypes is enabled. | ||
| WI_IsFlagClear(_kittyFlags, KittyKeyboardProtocolFlags::ReportEventTypes) : |
There was a problem hiding this comment.
We also shouldn't report key repeats at all if the flag is off.
src/terminal/input/terminalInput.cpp
Outdated
| key.altGrPressed = anyAltPressed && anyCtrlPressed; | ||
| key.ctrlPressed = key.altGrPressed ? (bothCtrlPressed || (rightAltPressed && leftCtrlIsReallyPressed)) : anyCtrlPressed; | ||
| key.altPressed = key.altGrPressed ? bothAltPressed : anyAltPressed; | ||
| key.shiftPressed = WI_IsFlagSet(key.controlKeyState, SHIFT_PRESSED); |
There was a problem hiding this comment.
To make reliable AltGr detection possible throughout the code, I've made a bit of a more controversial change and removed the entire key.controlKeyState reliance throughout the code.
This crucially means that even the legacy key encoding will now treat AltGr distinct from other modifiers.
| // NOTE: MSDN states that `lpSrcStr == lpDestStr` is valid for LCMAP_LOWERCASE. | ||
| len = LCMapStringW(LOCALE_INVARIANT, LCMAP_LOWERCASE, &buf[0], len, &buf[0], ARRAYSIZE(buf)); | ||
| // NOTE: LCMapStringW returns the length including the null terminator. | ||
| len -= 1; |
There was a problem hiding this comment.
len -= 1 was wrong and only applies to encoding null-terminated strings. I have switched to a length-based buffer a long time ago and missed fixing this. 🙈
| // In the context of KKP, AltGr acts more like a keyboard "layer" toggle. | ||
| // It's not a modifier that's ever transmitted as-is and instead modifies the actual base key code. | ||
| if (key.altGrPressed) | ||
| { | ||
| controlKeyState |= LEFT_CTRL_PRESSED | RIGHT_ALT_PRESSED; | ||
| } |
There was a problem hiding this comment.
This new if condition ensures we treat AltGr like a layer shift that changes the base encoding of the key.
| { L"D Shift+Alt+a", L"\x1b[97;4u", D, true, 'A', 0x1E, L'A', Shift | Alt }, | ||
| { L"D Shift+a", L"A", D, true, 'A', 0x1E, L'A', Shift }, | ||
| { L"D Ctrl+a", L"\x1b[97;5u", D, true, 'A', 0x10, 0, Ctrl }, | ||
| { L"D Ctrl+Alt+a", L"æ", D, true, 'A', 0x10, L'æ', Ctrl | Alt }, |
There was a problem hiding this comment.
This has been rewritten to use French AZERTY events.
There was a problem hiding this comment.
all of them ??? is that safe? ... are we guaranteed that it exists on OneCore?
should we have tests in US-104 for the most part and allow a TestCase to specify a keyboard layout to set?
This comment has been minimized.
This comment has been minimized.
| Log::Comment(L"Sending every possible VKEY at the input stream for interception during key DOWN."); | ||
|
|
||
| BYTE vkey = LOBYTE(OneCoreSafeVkKeyScanW(0)); | ||
| BYTE vkey = LOBYTE(VkKeyScanExW(0, layout)); |
There was a problem hiding this comment.
We still need to use OneCoreSaveVkKeyScanW; this test will fail to run (or, maybe the entire fixture will fail to load?) if we link VkKeyScanW.
There was a problem hiding this comment.
But it depends on LoadKeyboardLayout and ToUnicodeEx now. Won't all of these fail to work anyway? Do they have to work in the first? The TerminalInput logic is platform-independent with the exception of a single ToUnicodeEx call.
There was a problem hiding this comment.
Okay, so here's what I have come to understand.
We refer to these APIs using an extension APIset.
ext-ms-win-ntuser-keyboard-l1-1-0
GetKeyState
GetKeyboardLayout
MapVirtualKeyW
ToUnicodeEx
VkKeyScanW
OneCoreSafeEtc runs those through coniosrv or equivalent rather than ntuser.
In theory, we could have done some effort to compose onecore with a new extension apiset that fills the same contract. Instead we used runtime dynamic dispatch. Eh.
As long as the implementation calls OneCoreSafeEtc, we're fine.
We will need to prevent the kitty tests from running on OneCore, so that we do not experience test gate failures. :)
|
It is rather annoying that the |
Unfortunately, the deal with TestHook is that the no-op implementation must be in a separate This type of test hook relies on the classic model of linking where objects are only pulled in even from libs if they are referred to for an unresolved symbol. |
|
(Whereas you have TestHook.obj in the UT project; you rather need TestHook.obj in TerminalInput which contains the no-op implementation; then you can implement the hook in the UT in whatever object file you want, including the test file that relies on the overridden hook) |
NOTE:
This commit changes our input model to treat all
Ctrl-Alt combinations as an AltGr modifier by default.
Ctrl+Alt+/ will not produce
"\x1b\x1f"anymore.This fixes the following issues:
Ctrl/Alt up/down events repeatedly forever
but should've been just plain Key-But-Modified
Closes #19977
Validation Steps Performed
This cannot be easily tested in unit tests, due to
the dependence on international keyboard layouts.
It appears to work correctly from what I can tell.