Windows Terminal does not set CAPSLOCK_ON in KEY_EVENT_RECORD.dwControlKeyState #17152

Closed
opened 2026-01-31 05:33:39 +00:00 by claunia · 4 comments
Owner

Originally created by @matkaas on GitHub (Apr 4, 2022).

Windows Terminal version

1.11.3471.0

Windows build number

10.0.19044.1586

Other Software

No response

Steps to reproduce

Run the following code in Windows Terminal and Conhost respectively. Compile with /std:c++latest for std::format.
Strike some keys with capslock off and on.

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <format>

void write_key_event(HANDLE console_out, KEY_EVENT_RECORD& key_event) {
    auto unicode = key_event.uChar.UnicodeChar;
    auto unicode_str = unicode < 32 ? std::wstring(L" ") : std::wstring(1, unicode);
    auto key_state = (key_event.bKeyDown ? L"Down" : L"Up");
    auto msg = std::format(
        L"KeyState: {:>4}, KeyCode: {:#04x}, ScanCode: {:#04x}, Unicode: {} ({:#06x}), Modifiers: {:#06x}\n",
        key_state, key_event.wVirtualKeyCode, key_event.wVirtualScanCode,
        unicode_str, unicode, key_event.dwControlKeyState);
    WriteConsoleW(console_out, msg.data(), msg.length(), nullptr, nullptr);
}

int main() {
    HANDLE console_in = GetStdHandle(STD_INPUT_HANDLE);
    HANDLE console_out = GetStdHandle(STD_OUTPUT_HANDLE);

    // Enable raw mode.
    SetConsoleMode(console_in, 0);

    while (true) {
        INPUT_RECORD input_record;
        DWORD num_records_read = 0;
        auto result = ReadConsoleInputW(console_in, &input_record, 1, &num_records_read);
        if (input_record.EventType != KEY_EVENT) {
            continue;
        }

        KEY_EVENT_RECORD& key_event = input_record.Event.KeyEvent;
        write_key_event(console_out, key_event);

        if (key_event.uChar.UnicodeChar == 'q') {
            break;
        }
    }

    return EXIT_SUCCESS;
}

Expected Behavior

When capslock is off, the "Modifiers: ..." does not include 0x80. With capslock on, it does include 0x80.

For example, I get this output in Conhost.exe:

C:\Users\Kaas\source\Playground\x64\Debug>Playground.exe
KeyState: Down, KeyCode: 0x41, ScanCode: 0x1e, Unicode: a (0x0061), Modifiers: 0x0000
KeyState:   Up, KeyCode: 0x41, ScanCode: 0x1e, Unicode: a (0x0061), Modifiers: 0x0000
KeyState: Down, KeyCode: 0x53, ScanCode: 0x1f, Unicode: s (0x0073), Modifiers: 0x0000
KeyState:   Up, KeyCode: 0x53, ScanCode: 0x1f, Unicode: s (0x0073), Modifiers: 0x0000
KeyState: Down, KeyCode: 0x44, ScanCode: 0x20, Unicode: d (0x0064), Modifiers: 0x0000
KeyState:   Up, KeyCode: 0x44, ScanCode: 0x20, Unicode: d (0x0064), Modifiers: 0x0000
KeyState: Down, KeyCode: 0x14, ScanCode: 0x3a, Unicode:   (0x0000), Modifiers: 0x0080
KeyState:   Up, KeyCode: 0x14, ScanCode: 0x3a, Unicode:   (0x0000), Modifiers: 0x0080
KeyState: Down, KeyCode: 0x41, ScanCode: 0x1e, Unicode: A (0x0041), Modifiers: 0x0080
KeyState:   Up, KeyCode: 0x41, ScanCode: 0x1e, Unicode: A (0x0041), Modifiers: 0x0080
KeyState: Down, KeyCode: 0x53, ScanCode: 0x1f, Unicode: S (0x0053), Modifiers: 0x0080
KeyState:   Up, KeyCode: 0x53, ScanCode: 0x1f, Unicode: S (0x0053), Modifiers: 0x0080
KeyState: Down, KeyCode: 0x44, ScanCode: 0x20, Unicode: D (0x0044), Modifiers: 0x0080
KeyState:   Up, KeyCode: 0x44, ScanCode: 0x20, Unicode: D (0x0044), Modifiers: 0x0080
KeyState: Down, KeyCode: 0x14, ScanCode: 0x3a, Unicode:   (0x0000), Modifiers: 0x0000
KeyState:   Up, KeyCode: 0x14, ScanCode: 0x3a, Unicode:   (0x0000), Modifiers: 0x0000
KeyState: Down, KeyCode: 0x51, ScanCode: 0x10, Unicode: q (0x0071), Modifiers: 0x0000

Actual Behavior

Works as expected in Conhost.

In Windows Terminal, the "Modifiers: ..." doesn't include 0x80 regardless of the state of capslock.

For example, I get this output in wt.exe:

C:\Users\Kaas\source\Playground\x64\Debug>Playground.exe
KeyState:   Up, KeyCode: 0x0d, ScanCode: 0x1c, Unicode:   (0x000d), Modifiers: 0x0000
KeyState: Down, KeyCode: 0x41, ScanCode: 0x1e, Unicode: a (0x0061), Modifiers: 0x0000
KeyState:   Up, KeyCode: 0x41, ScanCode: 0x1e, Unicode: a (0x0061), Modifiers: 0x0000
KeyState: Down, KeyCode: 0x53, ScanCode: 0x1f, Unicode: s (0x0073), Modifiers: 0x0000
KeyState:   Up, KeyCode: 0x53, ScanCode: 0x1f, Unicode: s (0x0073), Modifiers: 0x0000
KeyState: Down, KeyCode: 0x44, ScanCode: 0x20, Unicode: d (0x0064), Modifiers: 0x0000
KeyState:   Up, KeyCode: 0x44, ScanCode: 0x20, Unicode: d (0x0064), Modifiers: 0x0000
KeyState: Down, KeyCode: 0x14, ScanCode: 0x3a, Unicode:   (0x0000), Modifiers: 0x0000
KeyState:   Up, KeyCode: 0x14, ScanCode: 0x3a, Unicode:   (0x0000), Modifiers: 0x0000
KeyState: Down, KeyCode: 0x41, ScanCode: 0x1e, Unicode: A (0x0041), Modifiers: 0x0000
KeyState:   Up, KeyCode: 0x41, ScanCode: 0x1e, Unicode: A (0x0041), Modifiers: 0x0000
KeyState: Down, KeyCode: 0x53, ScanCode: 0x1f, Unicode: S (0x0053), Modifiers: 0x0000
KeyState:   Up, KeyCode: 0x53, ScanCode: 0x1f, Unicode: S (0x0053), Modifiers: 0x0000
KeyState: Down, KeyCode: 0x44, ScanCode: 0x20, Unicode: D (0x0044), Modifiers: 0x0000
KeyState:   Up, KeyCode: 0x44, ScanCode: 0x20, Unicode: D (0x0044), Modifiers: 0x0000
KeyState: Down, KeyCode: 0x14, ScanCode: 0x3a, Unicode:   (0x0000), Modifiers: 0x0000
KeyState:   Up, KeyCode: 0x14, ScanCode: 0x3a, Unicode:   (0x0000), Modifiers: 0x0000
KeyState: Down, KeyCode: 0x51, ScanCode: 0x10, Unicode: q (0x0071), Modifiers: 0x0000

I haven't tested other keyboard modalities, since I don't have keys for those on my keyboard, but perhaps they're also affected?

Originally created by @matkaas on GitHub (Apr 4, 2022). ### Windows Terminal version 1.11.3471.0 ### Windows build number 10.0.19044.1586 ### Other Software _No response_ ### Steps to reproduce Run the following code in Windows Terminal and Conhost respectively. Compile with `/std:c++latest` for `std::format`. Strike some keys with capslock off and on. ``` #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <format> void write_key_event(HANDLE console_out, KEY_EVENT_RECORD& key_event) { auto unicode = key_event.uChar.UnicodeChar; auto unicode_str = unicode < 32 ? std::wstring(L" ") : std::wstring(1, unicode); auto key_state = (key_event.bKeyDown ? L"Down" : L"Up"); auto msg = std::format( L"KeyState: {:>4}, KeyCode: {:#04x}, ScanCode: {:#04x}, Unicode: {} ({:#06x}), Modifiers: {:#06x}\n", key_state, key_event.wVirtualKeyCode, key_event.wVirtualScanCode, unicode_str, unicode, key_event.dwControlKeyState); WriteConsoleW(console_out, msg.data(), msg.length(), nullptr, nullptr); } int main() { HANDLE console_in = GetStdHandle(STD_INPUT_HANDLE); HANDLE console_out = GetStdHandle(STD_OUTPUT_HANDLE); // Enable raw mode. SetConsoleMode(console_in, 0); while (true) { INPUT_RECORD input_record; DWORD num_records_read = 0; auto result = ReadConsoleInputW(console_in, &input_record, 1, &num_records_read); if (input_record.EventType != KEY_EVENT) { continue; } KEY_EVENT_RECORD& key_event = input_record.Event.KeyEvent; write_key_event(console_out, key_event); if (key_event.uChar.UnicodeChar == 'q') { break; } } return EXIT_SUCCESS; } ``` ### Expected Behavior When capslock is off, the "Modifiers: ..." does not include 0x80. With capslock on, it does include 0x80. For example, I get this output in Conhost.exe: ``` C:\Users\Kaas\source\Playground\x64\Debug>Playground.exe KeyState: Down, KeyCode: 0x41, ScanCode: 0x1e, Unicode: a (0x0061), Modifiers: 0x0000 KeyState: Up, KeyCode: 0x41, ScanCode: 0x1e, Unicode: a (0x0061), Modifiers: 0x0000 KeyState: Down, KeyCode: 0x53, ScanCode: 0x1f, Unicode: s (0x0073), Modifiers: 0x0000 KeyState: Up, KeyCode: 0x53, ScanCode: 0x1f, Unicode: s (0x0073), Modifiers: 0x0000 KeyState: Down, KeyCode: 0x44, ScanCode: 0x20, Unicode: d (0x0064), Modifiers: 0x0000 KeyState: Up, KeyCode: 0x44, ScanCode: 0x20, Unicode: d (0x0064), Modifiers: 0x0000 KeyState: Down, KeyCode: 0x14, ScanCode: 0x3a, Unicode: (0x0000), Modifiers: 0x0080 KeyState: Up, KeyCode: 0x14, ScanCode: 0x3a, Unicode: (0x0000), Modifiers: 0x0080 KeyState: Down, KeyCode: 0x41, ScanCode: 0x1e, Unicode: A (0x0041), Modifiers: 0x0080 KeyState: Up, KeyCode: 0x41, ScanCode: 0x1e, Unicode: A (0x0041), Modifiers: 0x0080 KeyState: Down, KeyCode: 0x53, ScanCode: 0x1f, Unicode: S (0x0053), Modifiers: 0x0080 KeyState: Up, KeyCode: 0x53, ScanCode: 0x1f, Unicode: S (0x0053), Modifiers: 0x0080 KeyState: Down, KeyCode: 0x44, ScanCode: 0x20, Unicode: D (0x0044), Modifiers: 0x0080 KeyState: Up, KeyCode: 0x44, ScanCode: 0x20, Unicode: D (0x0044), Modifiers: 0x0080 KeyState: Down, KeyCode: 0x14, ScanCode: 0x3a, Unicode: (0x0000), Modifiers: 0x0000 KeyState: Up, KeyCode: 0x14, ScanCode: 0x3a, Unicode: (0x0000), Modifiers: 0x0000 KeyState: Down, KeyCode: 0x51, ScanCode: 0x10, Unicode: q (0x0071), Modifiers: 0x0000 ``` ### Actual Behavior Works as expected in Conhost. In Windows Terminal, the "Modifiers: ..." doesn't include 0x80 regardless of the state of capslock. For example, I get this output in wt.exe: ``` C:\Users\Kaas\source\Playground\x64\Debug>Playground.exe KeyState: Up, KeyCode: 0x0d, ScanCode: 0x1c, Unicode: (0x000d), Modifiers: 0x0000 KeyState: Down, KeyCode: 0x41, ScanCode: 0x1e, Unicode: a (0x0061), Modifiers: 0x0000 KeyState: Up, KeyCode: 0x41, ScanCode: 0x1e, Unicode: a (0x0061), Modifiers: 0x0000 KeyState: Down, KeyCode: 0x53, ScanCode: 0x1f, Unicode: s (0x0073), Modifiers: 0x0000 KeyState: Up, KeyCode: 0x53, ScanCode: 0x1f, Unicode: s (0x0073), Modifiers: 0x0000 KeyState: Down, KeyCode: 0x44, ScanCode: 0x20, Unicode: d (0x0064), Modifiers: 0x0000 KeyState: Up, KeyCode: 0x44, ScanCode: 0x20, Unicode: d (0x0064), Modifiers: 0x0000 KeyState: Down, KeyCode: 0x14, ScanCode: 0x3a, Unicode: (0x0000), Modifiers: 0x0000 KeyState: Up, KeyCode: 0x14, ScanCode: 0x3a, Unicode: (0x0000), Modifiers: 0x0000 KeyState: Down, KeyCode: 0x41, ScanCode: 0x1e, Unicode: A (0x0041), Modifiers: 0x0000 KeyState: Up, KeyCode: 0x41, ScanCode: 0x1e, Unicode: A (0x0041), Modifiers: 0x0000 KeyState: Down, KeyCode: 0x53, ScanCode: 0x1f, Unicode: S (0x0053), Modifiers: 0x0000 KeyState: Up, KeyCode: 0x53, ScanCode: 0x1f, Unicode: S (0x0053), Modifiers: 0x0000 KeyState: Down, KeyCode: 0x44, ScanCode: 0x20, Unicode: D (0x0044), Modifiers: 0x0000 KeyState: Up, KeyCode: 0x44, ScanCode: 0x20, Unicode: D (0x0044), Modifiers: 0x0000 KeyState: Down, KeyCode: 0x14, ScanCode: 0x3a, Unicode: (0x0000), Modifiers: 0x0000 KeyState: Up, KeyCode: 0x14, ScanCode: 0x3a, Unicode: (0x0000), Modifiers: 0x0000 KeyState: Down, KeyCode: 0x51, ScanCode: 0x10, Unicode: q (0x0071), Modifiers: 0x0000 ``` I haven't tested other keyboard modalities, since I don't have keys for those on my keyboard, but perhaps they're also affected?
Author
Owner

@zadjii-msft commented on GitHub (Apr 4, 2022):

You know, I bet it doesn't.

I would reckon the problem is around e428272752/src/cascadia/TerminalControl/TermControl.cpp (L993-L997)

or lower in the stack than that. We're not checking in TermControl if capslock is pressed, so we're never pluming that flag through to ControlCore/Terminal & eventually the underlying conpty.

@zadjii-msft commented on GitHub (Apr 4, 2022): You know, I bet it doesn't. I would reckon the problem is around https://github.com/microsoft/terminal/blob/e428272752968c00ad9d4a32d3bad5ea010e991b/src/cascadia/TerminalControl/TermControl.cpp#L993-L997 or lower in the stack than that. We're not checking in TermControl if capslock is pressed, so we're never pluming that flag through to `ControlCore`/`Terminal` & eventually the underlying conpty.
Author
Owner

@matkaas commented on GitHub (Apr 4, 2022):

Hi @zadjii-msft, thank you for the prompt response. I've taken a shot at a PR with #12823, but I'm not familiar with the technologies that Terminal is built on, so perhaps it's off the mark. If the given PR is sufficient, then the fix is simple.

@matkaas commented on GitHub (Apr 4, 2022): Hi @zadjii-msft, thank you for the prompt response. I've taken a shot at a PR with #12823, but I'm not familiar with the technologies that Terminal is built on, so perhaps it's off the mark. If the given PR is sufficient, then the fix is simple.
Author
Owner

@ghost commented on GitHub (May 24, 2022):

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

Handy links:

@ghost commented on GitHub (May 24, 2022): :tada:This issue was addressed in #12823, which has now been successfully released as `Windows Terminal v1.13.1143`.:tada: Handy links: * [Release Notes](https://github.com/microsoft/terminal/releases/tag/v1.13.1143) * [Store Download](https://www.microsoft.com/store/apps/9n8g5rfz9xk3?cid=storebadge&ocid=badge)
Author
Owner

@ghost commented on GitHub (May 24, 2022):

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

Handy links:

@ghost commented on GitHub (May 24, 2022): :tada:This issue was addressed in #12823, which has now been successfully released as `Windows Terminal Preview v1.14.143`.:tada: Handy links: * [Release Notes](https://github.com/microsoft/terminal/releases/tag/v1.14.143) * [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#17152