diff --git a/src/qt/qt_main.cpp b/src/qt/qt_main.cpp index c24f9f8ba..bf8de4070 100644 --- a/src/qt/qt_main.cpp +++ b/src/qt/qt_main.cpp @@ -144,6 +144,54 @@ keyboard_getkeymap() } } +void +win_keyboard_handle(uint32_t scancode, int up, int e0, int e1) +{ + /* If it's not a scan code that starts with 0xE1 */ + if (e1) { + if (scancode == 0x1D) { + scancode = scancode_map[0x100]; /* Translate E1 1D to 0x100 (which would + otherwise be E0 00 but that is invalid + anyway). + Also, take a potential mapping into + account. */ + } else + scancode = 0xFFFF; + if (scancode != 0xFFFF) + keyboard_input(!up, scancode); + } else { + if (e0) + scancode |= 0x100; + + /* Translate the scan code to 9-bit */ + scancode = convert_scan_code(scancode); + + /* Remap it according to the list from the Registry */ + if ((scancode < (sizeof(scancode_map) / sizeof(scancode_map[0]))) && (scancode != scancode_map[scancode])) { + // pclog("Scan code remap: %03X -> %03X\n", scancode, scancode_map[scancode]); + scancode = scancode_map[scancode]; + } + + /* If it's not 0xFFFF, send it to the emulated + keyboard. + We use scan code 0xFFFF to mean a mapping that + has a prefix other than E0 and that is not E1 1D, + which is, for our purposes, invalid. */ + + /* Translate right CTRL to left ALT if the user has so + chosen. */ + if ((scancode == 0x11d) && rctrl_is_lalt) + scancode = 0x038; + + /* Normal scan code pass through, pass it through as is if + it's not an invalid scan code. */ + if (scancode != 0xFFFF) + keyboard_input(!up, scancode); + + main_window->checkFullscreenHotkey(); + } +} + static LRESULT CALLBACK emu_LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) { @@ -151,6 +199,23 @@ emu_LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) /* Checks if CTRL was pressed. */ BOOL bCtrlDown = GetAsyncKeyState (VK_CONTROL) >> ((sizeof(SHORT) * 8) - 1); BOOL is_over_window = (GetForegroundWindow() == ((HWND) main_window->winId())); + BOOL ret = TRUE; +/* Leave this in, in case we have to still bring hook input back. */ +#ifdef HOOK_INPUT_TESTS + static int last = 0; + + pclog("Old: %08X, %08X, %08X, %i\n", lpKdhs->scanCode, lpKdhs->flags, lpKdhs->vkCode, last); + + if (!last && (lpKdhs->scanCode == 0x00000036)) + lpKdhs->flags &= ~LLKHF_EXTENDED; + + if (lpKdhs->scanCode == 0x00000236) + last = 1; + else if (last && (lpKdhs->scanCode == 0x00000036)) + last = 0; + + pclog("New: %08X, %08X, %08X, %i\n", lpKdhs->scanCode, lpKdhs->flags, lpKdhs->vkCode, last); +#endif if (show_second_monitors) for (int monitor_index = 1; monitor_index < MONITORS_NUM; monitor_index++) { const auto &secondaryRenderer = main_window->renderers[monitor_index]; @@ -158,30 +223,34 @@ emu_LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) (GetForegroundWindow() == ((HWND) secondaryRenderer->winId()))); } - if ((nCode < 0) || (nCode != HC_ACTION)/* || (!mouse_capture && !video_fullscreen)*/ || !is_over_window) + if ((nCode < 0) || (nCode != HC_ACTION) || !is_over_window) return CallNextHookEx(NULL, nCode, wParam, lParam); else if ((lpKdhs->scanCode == 0x01) && (lpKdhs->flags & LLKHF_ALTDOWN) && !(lpKdhs->flags & (LLKHF_UP | LLKHF_EXTENDED))) - return TRUE; + ret = TRUE; else if ((lpKdhs->scanCode == 0x01) && bCtrlDown && !(lpKdhs->flags & (LLKHF_UP | LLKHF_EXTENDED))) - return TRUE; + ret = TRUE; else if ((lpKdhs->scanCode == 0x0f) && (lpKdhs->flags & LLKHF_ALTDOWN) && !(lpKdhs->flags & (LLKHF_UP | LLKHF_EXTENDED))) - return TRUE; + ret = TRUE; else if ((lpKdhs->scanCode == 0x0f) && bCtrlDown && !(lpKdhs->flags & (LLKHF_UP | LLKHF_EXTENDED))) - return TRUE; + ret = TRUE; else if ((lpKdhs->scanCode == 0x39) && (lpKdhs->flags & LLKHF_ALTDOWN) && !(lpKdhs->flags & (LLKHF_UP | LLKHF_EXTENDED))) - return TRUE; + ret = TRUE; else if ((lpKdhs->scanCode == 0x3e) && (lpKdhs->flags & LLKHF_ALTDOWN) && !(lpKdhs->flags & (LLKHF_UP | LLKHF_EXTENDED))) - return TRUE; + ret = TRUE; else if ((lpKdhs->scanCode == 0x49) && bCtrlDown && !(lpKdhs->flags & LLKHF_UP)) - return TRUE; + ret = TRUE; else if ((lpKdhs->scanCode >= 0x5b) && (lpKdhs->scanCode <= 0x5d) && (lpKdhs->flags & LLKHF_EXTENDED)) - return TRUE; + ret = TRUE; else return CallNextHookEx(NULL, nCode, wParam, lParam); + + win_keyboard_handle(lpKdhs->scanCode, lpKdhs->flags & LLKHF_UP, lpKdhs->flags & LLKHF_EXTENDED, 0); + + return ret; } #endif @@ -455,6 +524,15 @@ main(int argc, char *argv[]) hook_enabled = 0; } + if (hook_enabled) { + /* Yes, low-level hooks *DO* work with raw input, at least global ones. */ + llhook = SetWindowsHookEx(WH_KEYBOARD_LL, emu_LowLevelKeyboardProc, NULL, 0); + atexit([] () -> void { + if (llhook) + UnhookWindowsHookEx(llhook); + }); + } + /* Setup raw input */ auto rawInputFilter = WindowsRawInputFilter::Register(main_window); if (rawInputFilter) { @@ -507,7 +585,6 @@ main(int argc, char *argv[]) /* Initialize the rendering window, or fullscreen. */ QTimer::singleShot(0, &app, [] { pc_reset_hard_init(); - main_thread = new std::thread(main_thread_fn); /* Set the PAUSE mode depending on the renderer. */ #ifdef USE_VNC @@ -516,18 +593,9 @@ main(int argc, char *argv[]) else #endif plat_pause(0); - }); -#ifdef Q_OS_WINDOWS - if (hook_enabled) { - /* Yes, low-level hooks *DO* work with raw input, at least global ones. */ - llhook = SetWindowsHookEx(WH_KEYBOARD_LL, emu_LowLevelKeyboardProc, NULL, 0); - atexit([] () -> void { - if (llhook) - UnhookWindowsHookEx(llhook); - }); - } -#endif + main_thread = new std::thread(main_thread_fn); + }); const auto ret = app.exec(); cpu_thread_run = 0; diff --git a/src/qt/qt_winrawinputfilter.cpp b/src/qt/qt_winrawinputfilter.cpp index 2c11a068a..3a2109c8e 100644 --- a/src/qt/qt_winrawinputfilter.cpp +++ b/src/qt/qt_winrawinputfilter.cpp @@ -44,6 +44,8 @@ #include <86box/plat.h> #include <86box/86box.h> +extern void win_keyboard_handle(uint32_t scancode, int up, int e0, int e1); + #include #include @@ -166,54 +168,10 @@ WindowsRawInputFilter::handle_input(HRAWINPUT input) void WindowsRawInputFilter::keyboard_handle(PRAWINPUT raw) { - USHORT scancode; - RAWKEYBOARD rawKB = raw->data.keyboard; - scancode = rawKB.MakeCode; - /* If it's not a scan code that starts with 0xE1 */ - if ((rawKB.Flags & RI_KEY_E1)) { - if (rawKB.MakeCode == 0x1D) { - scancode = scancode_map[0x100]; /* Translate E1 1D to 0x100 (which would - otherwise be E0 00 but that is invalid - anyway). - Also, take a potential mapping into - account. */ - } else - scancode = 0xFFFF; - if (scancode != 0xFFFF) - keyboard_input(!(rawKB.Flags & RI_KEY_BREAK), scancode); - } else { - if (rawKB.Flags & RI_KEY_E0) - scancode |= 0x100; - - /* Translate the scan code to 9-bit */ - scancode = convert_scan_code(scancode); - - /* Remap it according to the list from the Registry */ - if ((scancode < (sizeof(scancode_map) / sizeof(scancode_map[0]))) && (scancode != scancode_map[scancode])) { - // pclog("Scan code remap: %03X -> %03X\n", scancode, scancode_map[scancode]); - scancode = scancode_map[scancode]; - } - - /* If it's not 0xFFFF, send it to the emulated - keyboard. - We use scan code 0xFFFF to mean a mapping that - has a prefix other than E0 and that is not E1 1D, - which is, for our purposes, invalid. */ - - /* Translate right CTRL to left ALT if the user has so - chosen. */ - if ((scancode == 0x11d) && rctrl_is_lalt) - scancode = 0x038; - - /* Normal scan code pass through, pass it through as is if - it's not an invalid scan code. */ - if (scancode != 0xFFFF) - keyboard_input(!(rawKB.Flags & RI_KEY_BREAK), scancode); - - window->checkFullscreenHotkey(); - } + win_keyboard_handle(rawKB.MakeCode, (rawKB.Flags & RI_KEY_BREAK), + (rawKB.Flags & RI_KEY_E0), (rawKB.Flags & RI_KEY_E1)); } void