terminal icon indicating copy to clipboard operation
terminal copied to clipboard

Cmd.exe traps short cut keys with dwMode=ENABLE_VIRTUAL_TERMINAL_INPUT for input

Open JacqKrol opened this issue 3 years ago • 6 comments

Windows Terminal version

1.15.2875.0

Windows build number

10.0.22000.1219

Other Software

No response

Steps to reproduce

Set ConsoleMode on input handle to ENABLE_VIRTUAL_TERMINAL_INPUT and try to ReadConsoleInput on CTRL-C or CTRL-V. The console doesn't react as a VT100 terminal.

Expected Behavior

I set the terminal input mode to dwMode=ENABLE_VIRTUAL_TERMINAL_INPUT.

I expect that with ReadConsoleInput transforms all keyboard input to VT100 terminal output. For example CTRL-C should return ETC and CTRL-V should return SYN. However the console (cmd.exe) overrides these actions. The same for a lot of other keyboard shortcuts. This is not standard VT100 behavior and should not occur.

How can this non VT100 behavior be disabled ?

Actual Behavior

Termina in VT100 input mode behaves like Windows short cut keys, for example CTRL-C and CTRL-V are copy/paste.

JacqKrol avatar Nov 28 '22 07:11 JacqKrol

Do you have a minimal program that repros what you're seeing/? Are you using the Windows Terminal, or the vintage Console Host? If you're using the Terminal, could you share your settings.json file?

zadjii-msft avatar Nov 28 '22 12:11 zadjii-msft

#include <stdlib.h> #include <stdio.h> #include <windows.h>

unsigned int keyboard(HANDLE hIn) { INPUT_RECORD input[25]; int n = 25, out;

while (1) {
    // Wait for the events, read at least 
    ReadConsoleInput(hIn, input, n, &out);

    unsigned char c;
    // Dispatch the events to the appropriate handler.
    for (int i = 0; i < out; i++)
    {
        switch (input[i].EventType)
        {
        case KEY_EVENT: // keyboard input
            c = input[i].Event.KeyEvent.uChar.AsciiChar;
            if (c && input[i].Event.KeyEvent.bKeyDown == 1)
                return c;
            break;
        case MOUSE_EVENT: // mouse input
            break;
        case WINDOW_BUFFER_SIZE_EVENT: // scrn buf. resizing
            //ResizeEventProc(input[i].Event.WindowBufferSizeEvent);
            break;
        case FOCUS_EVENT:  // disregard focus events
        case MENU_EVENT:   // disregard menu events
            break;
        default:
            break;
        }
    }
}

}

int main() { HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE); HANDLE hOut= GetStdHandle(STD_OUTPUT_HANDLE);

DWORD dwMode;
GetConsoleMode(hOut, &dwMode);
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
SetConsoleMode(hOut, dwMode);

dwMode = ENABLE_VIRTUAL_TERMINAL_INPUT;
SetConsoleMode(hIn, dwMode);

unsigned char c;
while (c = keyboard(hIn)) {
    printf("%x,", c);
    if (c == 'q') break;
}

}

JacqKrol avatar Nov 28 '22 14:11 JacqKrol

Hi,

I use the windows terminal, launched by VS2022 and have attached the json file.

settings.json.txt

JacqKrol avatar Nov 28 '22 17:11 JacqKrol

#include <stdlib.h>
#include <stdio.h>
#include <windows.h>


unsigned int keyboard(HANDLE  hIn) {
    INPUT_RECORD input[25];
    int n = 25, out;

    while (1) {
        // Wait for the events, read at least 
        ReadConsoleInput(hIn, input, n, &out);

        unsigned char c;
        // Dispatch the events to the appropriate handler.
        for (int i = 0; i < out; i++)
        {
            switch (input[i].EventType)
            {
            case KEY_EVENT: // keyboard input
                c = input[i].Event.KeyEvent.uChar.AsciiChar;
                if (c && input[i].Event.KeyEvent.bKeyDown == 1)
                    return c;
                break;
            case MOUSE_EVENT: // mouse input
                break;
            case WINDOW_BUFFER_SIZE_EVENT: // scrn buf. resizing
                //ResizeEventProc(input[i].Event.WindowBufferSizeEvent);
                break;
            case FOCUS_EVENT:  // disregard focus events
            case MENU_EVENT:   // disregard menu events
                break;
            default:
                break;
            }
        }
    }
}




int main() {
    HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
    HANDLE hOut= GetStdHandle(STD_OUTPUT_HANDLE);

    DWORD dwMode;
    GetConsoleMode(hOut, &dwMode);
    dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
    SetConsoleMode(hOut, dwMode);

    dwMode = ENABLE_VIRTUAL_TERMINAL_INPUT;
    SetConsoleMode(hIn, dwMode);

    unsigned char c;
    while (c = keyboard(hIn)) {
        printf("%x,", c);
        if (c == 'q') break;
    }
}

(codeformatted from email)

Without more digging in, I'm betting there's something to do with SetConsoleCtrlHandler that's missing.

zadjii-msft avatar Nov 30 '22 22:11 zadjii-msft

Thanks for providing the info! Someone from our team will try and repro this to figure out what's going on

PankajBhojwani avatar Nov 30 '22 23:11 PankajBhojwani

Thanks. I think if you enable VT100 you just should disable keyboard shortcuts and just sent the VT100 output to the input buffer. this is what happens for CTLR-c combinations not mapped to shortcuts.

JacqKrol avatar Dec 01 '22 06:12 JacqKrol