Add Low-Level hook for Windows keyboard events

windows, alt, and control keys are handled separately, before windows can get a chance to act on them. This makes win usable as an option key and prevents things like alt-esc from minimizing the window.
Some combos (alt-control-delete, windows-L, etc) cannot be blocked.
This commit is contained in:
Kelvin Sherlock 2019-02-08 00:13:09 -05:00
parent 3e6f97c3ea
commit c5c0a228ab
3 changed files with 63 additions and 20 deletions

View File

@ -112,6 +112,7 @@ int main(int argc, char **argv) {
WNDCLASS wndclass;
SIZE size;
RECT rect;
HHOOK hook;
wndclass.style = 0;
wndclass.lpfnWndProc = (WNDPROC)win_event_handler;
@ -151,9 +152,12 @@ int main(int argc, char **argv) {
SetConsoleMode(GetStdHandle(STD_INPUT_HANDLE), mode);
hook = SetWindowsHookEx(WH_KEYBOARD_LL, win_ll_keyboard, NULL, 0);
gsportinit(hwnd);
int ret = gsplusmain(argc, argv);
UnhookWindowsHookEx(hook);
UnregisterClass(wndclass.lpszClassName,GetModuleHandle(NULL));
gsportshut();

View File

@ -228,11 +228,6 @@ void win_event_key(HWND hwnd, UINT raw_vk, BOOL down, int repeat, UINT flags)
vk, down, repeat, flags);
#endif
/* remap a few keys here.. sigh */
if((vk & 0xff) == VK_APPS) {
/* remap to command */
vk = VK_MENU;
}
if((vk & 0xff) == VK_CAPITAL) {
// Windows gives us up-and-down events of the actual key
@ -262,6 +257,44 @@ void win_event_key(HWND hwnd, UINT raw_vk, BOOL down, int repeat, UINT flags)
printf("VK: %04x unknown\n", vk);
}
/* low-level hook for keyboard events, to bypass special handling of
* windows key, alt-escape, etc
*/
LRESULT CALLBACK win_ll_keyboard(int nCode, WPARAM wParam, LPARAM lParam) {
KBDLLHOOKSTRUCT *kb = (KBDLLHOOKSTRUCT *)lParam;
int down = 0;
if (nCode < 0 || GetFocus() == NULL) return CallNextHookEx(0, nCode, wParam, lParam);
if (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) down = 1;
switch (kb->vkCode) {
case VK_LWIN:
case VK_RWIN:
case VK_MENU:
case VK_LMENU:
case VK_RMENU:
case VK_CONTROL:
case VK_LCONTROL:
case VK_RCONTROL:
if (nb_win32_key < MAX_EVENT) {
win32_keys[nb_win32_key].raw_vk = kb->vkCode;
win32_keys[nb_win32_key].down = down;
win32_keys[nb_win32_key].repeat = 0;
win32_keys[nb_win32_key].flags = kb->flags; /* same? */
nb_win32_key++;
}
return 1;
break;
}
return CallNextHookEx(0, nCode, wParam, lParam);
}
void win_event_quit(HWND hwnd) {
quitEmulator();
}

View File

@ -19,7 +19,8 @@ int g_a2_key_to_wsym[][3] = {
{ kVK_F13, VK_F13, 0 },
{ kVK_F14, VK_F14, 0 },
{ kVK_F15, VK_F15, 0 },
{ kVK_Reset, VK_PAUSE, VK_CANCEL+0x100 },
{ kVK_Reset, VK_PAUSE, VK_PAUSE+0x100 },
{ kVK_Reset, VK_CANCEL, VK_CANCEL+0x100 },
{ kVK_ANSI_Grave, VK_OEM_3, 0 }, /* '`' */
{ kVK_ANSI_1, '1', 0 },
@ -57,8 +58,6 @@ int g_a2_key_to_wsym[][3] = {
{ kVK_End, VK_END+0x100, 0 },
{ kVK_PageDown, VK_NEXT+0x100, 0 },
// { kVK_CapsLock, VK_CAPITAL, 0 }, // Handled specially!
{ kVK_ANSI_A, 'A', 0 },
{ kVK_ANSI_S, 'S', 0 },
@ -73,8 +72,9 @@ int g_a2_key_to_wsym[][3] = {
{ kVK_ANSI_Quote, VK_OEM_7, 0 }, /* single quote */
{ kVK_Return, VK_RETURN, 0 },
{ kVK_Shift, VK_SHIFT, 0 },
{ kVK_Shift, VK_LSHIFT, 0 },
{ kVK_Shift, VK_RSHIFT, 0 },
{ kVK_ANSI_Z, 'Z', 0 },
{ kVK_ANSI_X, 'X', 0 },
{ kVK_ANSI_C, 'C', 0 },
@ -87,19 +87,25 @@ int g_a2_key_to_wsym[][3] = {
{ kVK_ANSI_Slash, VK_OEM_2, 0 }, /* / */
{ kVK_Control, VK_CONTROL, VK_CONTROL+0x100 },
{ kVK_Option, VK_SNAPSHOT+0x100, VK_MENU+0x100 },/* Opt=prntscrn or alt-r */
/* LMENU/RMENU = alt key = command*/
/* LWIN / RWIN = windows key = option */
/* weird menu key = APPS = option */
// OG ActiveGS map OA-CA to Win & AltKey
#ifndef ACTIVEGS
{ kVK_Command, VK_SCROLL, VK_MENU }, /* Command=scr_lock or alt-l */
#else
{ kVK_Reset, VK_CANCEL, 0 },
{ kVK_Option, VK_LWIN+0x100, VK_LWIN },
{ kVK_Command, VK_MENU, 0 }, /* Command=alt-l */
{ kVK_Command, VK_LMENU, 0 }, /* Command=alt-l */
{ kVK_Control, VK_CONTROL, VK_CONTROL+0x100 },
{ kVK_Control, VK_LCONTROL, VK_LCONTROL+0x100 },
{ kVK_Control, VK_RCONTROL, VK_RCONTROL+0x100 },
{ kVK_Option, VK_SNAPSHOT+0x100, 0 },/* Opt=prntscrn or alt-r */
{ kVK_Option, VK_LWIN, VK_LWIN+0x100 },
{ kVK_Option, VK_RWIN, VK_RWIN+0x100 },
{ kVK_Option, VK_APPS, VK_APPS+0x100 },
{ kVK_Command, VK_MENU, VK_MENU+0x100 },
{ kVK_Command, VK_LMENU, VK_LMENU+0x100 },
{ kVK_Command, VK_RMENU, VK_RMENU+0x100 },
#ifdef ACTIVEGS
{ kVK_Reset, VK_SCROLL,0 }, /* RESET */
{ kVK_Control, VK_LCONTROL, 0 }, // CTRL
#endif
{ kVK_Space, ' ', 0 },