This commit is contained in:
starfrost013
2025-01-04 22:38:54 +00:00
2 changed files with 108 additions and 74 deletions

View File

@@ -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,9 @@ 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;
static int last = 0;
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 +209,53 @@ 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);
ret = CallNextHookEx(NULL, nCode, wParam, lParam);
if (lpKdhs->scanCode == 0x00000045) {
if ((lpKdhs->flags & LLKHF_EXTENDED) && (lpKdhs->vkCode == 0x00000090)) {
/* NumLock. */
lpKdhs->flags &= ~LLKHF_EXTENDED;
} else if (!(lpKdhs->flags & LLKHF_EXTENDED) && (lpKdhs->vkCode == 0x00000013)) {
/* Pause - send E1 1D. */
pclog("Send E1 1D\n");
win_keyboard_handle(0xe1, 0, 0, 0);
win_keyboard_handle(0x1d, LLKHF_UP, 0, 0);
}
} else if (!last && (lpKdhs->scanCode == 0x00000036))
/* Non-fake right shift. */
lpKdhs->flags &= ~LLKHF_EXTENDED;
if (lpKdhs->scanCode == 0x00000236)
last = 1;
else if (last && (lpKdhs->scanCode == 0x00000036))
last = 0;
win_keyboard_handle(lpKdhs->scanCode, lpKdhs->flags & LLKHF_UP, lpKdhs->flags & LLKHF_EXTENDED, 0);
return ret;
}
#endif
@@ -455,6 +529,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 +590,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 +598,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;

View File

@@ -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 <array>
#include <memory>
@@ -64,7 +66,9 @@ WindowsRawInputFilter::Register(MainWindow *window)
.hwndTarget = nullptr}
};
if (RegisterRawInputDevices(rid, 2, sizeof(rid[0])) == FALSE)
if (hook_enabled && (RegisterRawInputDevices(&(rid[1]), 1, sizeof(rid[0])) == FALSE))
return std::unique_ptr<WindowsRawInputFilter>(nullptr);
else if (!hook_enabled && (RegisterRawInputDevices(rid, 2, sizeof(rid[0])) == FALSE))
return std::unique_ptr<WindowsRawInputFilter>(nullptr);
std::unique_ptr<WindowsRawInputFilter> inputfilter(new WindowsRawInputFilter(window));
@@ -95,7 +99,10 @@ WindowsRawInputFilter::~WindowsRawInputFilter()
.hwndTarget = NULL}
};
RegisterRawInputDevices(rid, 2, sizeof(rid[0]));
if (hook_enabled)
RegisterRawInputDevices(&(rid[1]), 1, sizeof(rid[0]));
else
RegisterRawInputDevices(rid, 2, sizeof(rid[0]));
}
bool
@@ -153,10 +160,8 @@ WindowsRawInputFilter::handle_input(HRAWINPUT input)
mouse_handle(raw);
break;
case RIM_TYPEHID:
{
win_joystick_handle(raw);
break;
}
win_joystick_handle(raw);
break;
}
}
}
@@ -166,54 +171,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