Mouse events are double-encoded with win32-input-mode #22201

Open
opened 2026-01-31 08:06:20 +00:00 by claunia · 0 comments
Owner

Originally created by @lhecker on GitHub (Sep 3, 2024).

Windows Terminal version

1.23.2421.0

Windows build number

No response

Other Software

No response

Steps to reproduce

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>

int main() {
    const auto inputHandle = GetStdHandle(STD_INPUT_HANDLE);
    const auto outputHandle = GetStdHandle(STD_OUTPUT_HANDLE);

    const auto previousInputCP = GetConsoleCP();
    const auto previousOutputCP = GetConsoleOutputCP();
    DWORD previousInputMode = 0;
    DWORD previousOutputMode = 0;
    GetConsoleMode(inputHandle, &previousInputMode);
    GetConsoleMode(outputHandle, &previousOutputMode);

    SetConsoleCP(CP_UTF8);
    SetConsoleOutputCP(CP_UTF8);
    SetConsoleMode(inputHandle, ENABLE_PROCESSED_INPUT | ENABLE_WINDOW_INPUT | ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS | ENABLE_VIRTUAL_TERMINAL_INPUT);
    SetConsoleMode(outputHandle, ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN);

    static bool exit;
    SetConsoleCtrlHandler([](DWORD) -> BOOL {
        exit = true;
        return TRUE;
    }, TRUE);

    WriteFile(outputHandle, "\033[?9001h\x1b[?1003;1006h", 21, nullptr, nullptr);

    char buffer[4096];
    while (!exit) {
        DWORD read;
        ReadFile(inputHandle, &buffer[0], sizeof(buffer), &read, nullptr);
        if (read == 0 || (read == 1 && (buffer[0] == 'q' || buffer[0] == 'Q'))) {
            break;
        }

        // Expand buffer and replace Esc with "\\x1b"
        char expanded[4 * ARRAYSIZE(buffer)];
        size_t expendedLength = 0;
        for (size_t i = 0; i < read; i++) {
            if (buffer[i] == 27) {
                expanded[expendedLength++] = '\\';
                expanded[expendedLength++] = 'x';
                expanded[expendedLength++] = '1';
                expanded[expendedLength++] = 'b';
            } else {
                expanded[expendedLength++] = buffer[i];
            }
        }

        expanded[expendedLength++] = '\r';
        expanded[expendedLength++] = '\n';
        WriteFile(outputHandle, expanded, expendedLength, nullptr, nullptr);
    }

    WriteFile(outputHandle, "\033[?9001l\x1b[?1003;1006l", 21, nullptr, nullptr);
    
    SetConsoleMode(inputHandle, previousInputMode);
    SetConsoleMode(outputHandle, previousOutputMode);
    SetConsoleCP(previousInputCP);
    SetConsoleOutputCP(previousOutputCP);
    return 0;
}

Expected Behavior

No response

Actual Behavior

Double-encoding!

Originally created by @lhecker on GitHub (Sep 3, 2024). ### Windows Terminal version 1.23.2421.0 ### Windows build number _No response_ ### Other Software _No response_ ### Steps to reproduce ```cpp #define WIN32_LEAN_AND_MEAN #include <Windows.h> int main() { const auto inputHandle = GetStdHandle(STD_INPUT_HANDLE); const auto outputHandle = GetStdHandle(STD_OUTPUT_HANDLE); const auto previousInputCP = GetConsoleCP(); const auto previousOutputCP = GetConsoleOutputCP(); DWORD previousInputMode = 0; DWORD previousOutputMode = 0; GetConsoleMode(inputHandle, &previousInputMode); GetConsoleMode(outputHandle, &previousOutputMode); SetConsoleCP(CP_UTF8); SetConsoleOutputCP(CP_UTF8); SetConsoleMode(inputHandle, ENABLE_PROCESSED_INPUT | ENABLE_WINDOW_INPUT | ENABLE_QUICK_EDIT_MODE | ENABLE_EXTENDED_FLAGS | ENABLE_VIRTUAL_TERMINAL_INPUT); SetConsoleMode(outputHandle, ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT | ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN); static bool exit; SetConsoleCtrlHandler([](DWORD) -> BOOL { exit = true; return TRUE; }, TRUE); WriteFile(outputHandle, "\033[?9001h\x1b[?1003;1006h", 21, nullptr, nullptr); char buffer[4096]; while (!exit) { DWORD read; ReadFile(inputHandle, &buffer[0], sizeof(buffer), &read, nullptr); if (read == 0 || (read == 1 && (buffer[0] == 'q' || buffer[0] == 'Q'))) { break; } // Expand buffer and replace Esc with "\\x1b" char expanded[4 * ARRAYSIZE(buffer)]; size_t expendedLength = 0; for (size_t i = 0; i < read; i++) { if (buffer[i] == 27) { expanded[expendedLength++] = '\\'; expanded[expendedLength++] = 'x'; expanded[expendedLength++] = '1'; expanded[expendedLength++] = 'b'; } else { expanded[expendedLength++] = buffer[i]; } } expanded[expendedLength++] = '\r'; expanded[expendedLength++] = '\n'; WriteFile(outputHandle, expanded, expendedLength, nullptr, nullptr); } WriteFile(outputHandle, "\033[?9001l\x1b[?1003;1006l", 21, nullptr, nullptr); SetConsoleMode(inputHandle, previousInputMode); SetConsoleMode(outputHandle, previousOutputMode); SetConsoleCP(previousInputCP); SetConsoleOutputCP(previousOutputCP); return 0; } ``` ### Expected Behavior _No response_ ### Actual Behavior Double-encoding!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#22201