diff --git a/drivers/multiple/Win32/gdisp_lld_Win32.c b/drivers/multiple/Win32/gdisp_lld_Win32.c index 8de2f9c8..876c50b4 100644 --- a/drivers/multiple/Win32/gdisp_lld_Win32.c +++ b/drivers/multiple/Win32/gdisp_lld_Win32.c @@ -105,6 +105,268 @@ }}; #endif +#if GINPUT_NEED_KEYBOARD + // Include mouse support code + #define GKEYBOARD_DRIVER_VMT GKEYBOARDVMT_Win32 + #include "src/ginput/driver_keyboard.h" + #include "src/ginput/keyboard_microcode.h" + + // Forward definitions + static bool_t Win32KeyboardInit(GKeyboard *k, unsigned driverinstance); + static int Win32KeyboardGetData(GKeyboard *k, uint8_t *pch, int sz); + + // This is the layout code for the English US keyboard. + // We make it public so that a user can switch to a different layout if required. + uint8_t KeyboardLayout_Win32_US[] = { + KMC_HEADERSTART, KMC_HEADER_ID1, KMC_HEADER_ID2, KMC_HEADER_VER_1, + + // Transient Shifters: SHIFT, CTRL, ALT, WINKEY + /* 1 */KMC_RECORDSTART, 9, // SHIFT (left & Right) + KMC_TEST_CODETABLE, 2, VK_SHIFT, VK_LSHIFT, + KMC_TEST_LASTCODE, 0x00, + KMC_ACT_STATEBIT, GKEYSTATE_SHIFT_L_BIT|KMC_BIT_CLEAR, + KMC_ACT_DONE, + /* 2 */KMC_RECORDSTART, 9, + KMC_TEST_CODETABLE, 2, VK_SHIFT, VK_LSHIFT, + KMC_TEST_STATEBIT, GKEYSTATE_SHIFT_L_BIT|KMC_BIT_CLEAR, + KMC_ACT_STATEBIT, GKEYSTATE_SHIFT_L_BIT, + KMC_ACT_DONE, + /* 3 */KMC_RECORDSTART, 7, + KMC_TEST_CODE, VK_RSHIFT, + KMC_TEST_LASTCODE, 0x00, + KMC_ACT_STATEBIT, GKEYSTATE_SHIFT_R_BIT|KMC_BIT_CLEAR, + KMC_ACT_DONE, + /* 4 */KMC_RECORDSTART, 7, + KMC_TEST_CODE, VK_RSHIFT, + KMC_TEST_STATEBIT, GKEYSTATE_SHIFT_R_BIT|KMC_BIT_CLEAR, + KMC_ACT_STATEBIT, GKEYSTATE_SHIFT_R_BIT, + KMC_ACT_DONE, + /* 5 */KMC_RECORDSTART, 9, // CONTROL (left & Right) + KMC_TEST_CODETABLE, 2, VK_CONTROL, VK_LCONTROL, + KMC_TEST_LASTCODE, 0x00, + KMC_ACT_STATEBIT, GKEYSTATE_CTRL_L_BIT|KMC_BIT_CLEAR, + KMC_ACT_DONE, + /* 6 */KMC_RECORDSTART, 9, + KMC_TEST_CODETABLE, 2, VK_CONTROL, VK_LCONTROL, + KMC_TEST_STATEBIT, GKEYSTATE_CTRL_L_BIT|KMC_BIT_CLEAR, + KMC_ACT_STATEBIT, GKEYSTATE_CTRL_L_BIT, + KMC_ACT_DONE, + /* 7 */KMC_RECORDSTART, 7, + KMC_TEST_CODE, VK_RCONTROL, + KMC_TEST_LASTCODE, 0x00, + KMC_ACT_STATEBIT, GKEYSTATE_CTRL_R_BIT|KMC_BIT_CLEAR, + KMC_ACT_DONE, + /* 8 */KMC_RECORDSTART, 7, + KMC_TEST_CODE, VK_RCONTROL, + KMC_TEST_STATEBIT, GKEYSTATE_CTRL_R_BIT|KMC_BIT_CLEAR, + KMC_ACT_STATEBIT, GKEYSTATE_CTRL_R_BIT, + KMC_ACT_DONE, + /* 9 */KMC_RECORDSTART, 9, // ALT (left & Right) + KMC_TEST_CODETABLE, 2, VK_MENU, VK_LMENU, + KMC_TEST_LASTCODE, 0x00, + KMC_ACT_STATEBIT, GKEYSTATE_ALT_L_BIT|KMC_BIT_CLEAR, + KMC_ACT_DONE, + /* 10 */KMC_RECORDSTART, 9, + KMC_TEST_CODETABLE, 2, VK_MENU, VK_LMENU, + KMC_TEST_STATEBIT, GKEYSTATE_ALT_L_BIT|KMC_BIT_CLEAR, + KMC_ACT_STATEBIT, GKEYSTATE_ALT_L_BIT, + KMC_ACT_DONE, + /* 11 */KMC_RECORDSTART, 7, + KMC_TEST_CODE, VK_RMENU, + KMC_TEST_LASTCODE, 0x00, + KMC_ACT_STATEBIT, GKEYSTATE_ALT_R_BIT|KMC_BIT_CLEAR, + KMC_ACT_DONE, + /* 12 */KMC_RECORDSTART, 7, + KMC_TEST_CODE, VK_RMENU, + KMC_TEST_STATEBIT, GKEYSTATE_ALT_R_BIT|KMC_BIT_CLEAR, + KMC_ACT_STATEBIT, GKEYSTATE_ALT_R_BIT, + KMC_ACT_DONE, + /* 13 */KMC_RECORDSTART, 9, // WinKey (left or right) + KMC_TEST_CODETABLE, 2, VK_LWIN, VK_RWIN, + KMC_TEST_LASTCODE, 0x00, + KMC_ACT_STATEBIT, GKEYSTATE_WINKEY_BIT|KMC_BIT_CLEAR, + KMC_ACT_DONE, + /* 14 */KMC_RECORDSTART, 9, + KMC_TEST_CODETABLE, 2, VK_LWIN, VK_RWIN, + KMC_TEST_STATEBIT, GKEYSTATE_WINKEY_BIT|KMC_BIT_CLEAR, + KMC_ACT_STATEBIT, GKEYSTATE_WINKEY_BIT, + KMC_ACT_DONE, + + // Locking Shifters: CAPSLOCK, NUMLOCK and SCROLLLOCK + /* 15 */KMC_RECORDSTART, 7, // CAPSLOCK (keyup only) + KMC_TEST_CODE, VK_CAPITAL, + KMC_TEST_LASTCODE, 0x00, + KMC_ACT_STATEBIT, GKEYSTATE_CAPSLOCK_BIT|KMC_BIT_INVERT, + KMC_ACT_DONE, + /* 16 */KMC_RECORDSTART, 7, // NUMLOCK (keyup only) + KMC_TEST_CODE, VK_NUMLOCK, + KMC_TEST_LASTCODE, 0x00, + KMC_ACT_STATEBIT, GKEYSTATE_NUMLOCK_BIT|KMC_BIT_INVERT, + KMC_ACT_DONE, + /* 17 */KMC_RECORDSTART, 7, // SCROLLLOCK (keyup only) + KMC_TEST_CODE, VK_SCROLL, + KMC_TEST_LASTCODE, 0x00, + KMC_ACT_STATEBIT, GKEYSTATE_SCROLLLOCK_BIT|KMC_BIT_INVERT, + KMC_ACT_DONE, + + // Keyup, Repeat + /* 18 */KMC_RECORDSTART, 18, // Clear any shifter keys that got through + KMC_TEST_CODETABLE, 14, VK_SHIFT, VK_LSHIFT, VK_RSHIFT, + VK_CONTROL, VK_LCONTROL, VK_RCONTROL, + VK_MENU, VK_LMENU, VK_RMENU, + VK_LWIN, VK_RWIN, + VK_CAPITAL, VK_NUMLOCK, VK_SCROLL, + KMC_ACT_RESET, + KMC_ACT_STOP, + /* 19 */KMC_RECORDSTART, 4, // Skip special codes 0x00 (Keyup) & 0x01 (Repeat) + KMC_TEST_CODERANGE, 0x00, 0x01, + KMC_ACT_STOP, + /* 20 */KMC_RECORDSTART, 6, // Keyup + KMC_ACT_STATEBIT, GKEYSTATE_KEYUP_BIT|KMC_BIT_CLEAR, + KMC_TEST_LASTCODE, 0x00, + KMC_ACT_STATEBIT, GKEYSTATE_KEYUP_BIT, + /* 21 */KMC_RECORDSTART, 6, // Repeat + KMC_ACT_STATEBIT, GKEYSTATE_REPEAT_BIT|KMC_BIT_CLEAR, + KMC_TEST_LASTCODE, 0x01, + KMC_ACT_STATEBIT, GKEYSTATE_REPEAT_BIT, + + // 0 - 9 + /* 22 */KMC_RECORDSTART, 7, // Alt 0-9 + KMC_TEST_ALT, + KMC_TEST_CODERANGE, '0', '9', + KMC_ACT_CHARADD, 10, + KMC_ACT_STOP, + /* 23 */KMC_RECORDSTART, 17, // Shifted 0-9 + KMC_TEST_SHIFT, + KMC_TEST_CODERANGE, '0', '9', + KMC_ACT_CHARTABLE, 10, ')', '!', '@', '#', '$', '%', '^', '&', '*', '(', + KMC_ACT_DONE, + /* 24 */KMC_RECORDSTART, 5, // 0 - 9 + KMC_TEST_CODERANGE, '0', '9', + KMC_ACT_CHARCODE, + KMC_ACT_DONE, + + // A - Z + /* 25 */KMC_RECORDSTART, 7, // Control A-Z + KMC_TEST_CTRL, + KMC_TEST_CODERANGE, 'A', 'Z', + KMC_ACT_CHARRANGE, 1, + KMC_ACT_DONE, + /* 26 */KMC_RECORDSTART, 7, // No Caps A-Z + KMC_TEST_NOCAPS, + KMC_TEST_CODERANGE, 'A', 'Z', + KMC_ACT_CHARRANGE, 'a', + KMC_ACT_DONE, + /* 27 */KMC_RECORDSTART, 5, // Caps A-Z + KMC_TEST_CODERANGE, 'A', 'Z', + KMC_ACT_CHARCODE, + KMC_ACT_DONE, + + // Number pad + /* 28 */KMC_RECORDSTART, 7, // Alt Number pad + KMC_TEST_ALT, + KMC_TEST_CODERANGE, VK_NUMPAD0, VK_NUMPAD9, + KMC_ACT_CHARADD, 10, + KMC_ACT_STOP, + /* 29 */KMC_RECORDSTART, 5, + KMC_TEST_ALT, + KMC_TEST_CODERANGE, VK_MULTIPLY, VK_DIVIDE, + KMC_ACT_STOP, + /* 30 */KMC_RECORDSTART, 7, // Number pad with Numlock + KMC_TEST_NUMLOCK, + KMC_TEST_CODERANGE, VK_NUMPAD0, VK_NUMPAD9, + KMC_ACT_CHARRANGE, '0', + KMC_ACT_DONE, + /* 31 */KMC_RECORDSTART, 13, + KMC_TEST_NUMLOCK, + KMC_TEST_CODERANGE, VK_MULTIPLY, VK_DIVIDE, + KMC_ACT_CHARTABLE, 6, '*', '+', GKEY_ENTER, '-', '.', '/', + KMC_ACT_DONE, + /* 32 */KMC_RECORDSTART, 4, // Number pad with no Numlock + KMC_TEST_CODE, VK_NUMPAD5, + KMC_ACT_RESET, + KMC_ACT_STOP, + /* 33 */KMC_RECORDSTART, 12, + KMC_TEST_CODERANGE, VK_MULTIPLY, VK_DIVIDE, + KMC_ACT_CHARTABLE, 6, '*', '+', GKEY_ENTER, '-', GKEY_DEL, '/', + KMC_ACT_DONE, + /* 34 */KMC_RECORDSTART, 18, + KMC_TEST_CODERANGE, VK_NUMPAD0, VK_NUMPAD9, + KMC_ACT_STATEBIT, GKEYSTATE_SPECIAL_BIT, + KMC_ACT_CHARTABLE, 10, GKEY_INSERT, GKEY_END, GKEY_DOWN, GKEY_PAGEDOWN, GKEY_LEFT, '5', GKEY_RIGHT, GKEY_HOME, GKEY_UP, GKEY_PAGEUP, + KMC_ACT_DONE, + + // Symbols + /* 35 */KMC_RECORDSTART, 14, // Shifted Symbols + KMC_TEST_SHIFT, + KMC_TEST_CODERANGE, VK_OEM_1, VK_OEM_3, + KMC_ACT_CHARTABLE, 7, ':', '+', '<', '_', '>', '?', '~', + KMC_ACT_DONE, + /* 36 */KMC_RECORDSTART, 11, + KMC_TEST_SHIFT, + KMC_TEST_CODERANGE, VK_OEM_4, VK_OEM_7, + KMC_ACT_CHARTABLE, 4, '{', '|', '}', '"', + KMC_ACT_DONE, + /* 37 */KMC_RECORDSTART, 13, // Non-shifted Symbols + KMC_TEST_CODERANGE, VK_OEM_1, VK_OEM_3, + KMC_ACT_CHARTABLE, 7, ';', '=', ',', '-', '.', '/', '`', + KMC_ACT_DONE, + /* 38 */KMC_RECORDSTART, 10, + KMC_TEST_CODERANGE, VK_OEM_4, VK_OEM_7, + KMC_ACT_CHARTABLE, 4, '[', '\\', ']', '\'', + KMC_ACT_DONE, + + // Special Keys + // Extra special keys like Media and Browser keys are still to be implemented. + /* 39 */KMC_RECORDSTART, 17, // Normal Control Type Keys + KMC_TEST_CODETABLE, 6, VK_BACK, VK_TAB, VK_RETURN, VK_ESCAPE, VK_SPACE, VK_DELETE, + KMC_ACT_CHARTABLE, 6, GKEY_BACKSPACE, GKEY_TAB, GKEY_ENTER, GKEY_ESC, GKEY_SPACE, GKEY_DEL, + KMC_ACT_DONE, + /* 40 */KMC_RECORDSTART, 35, // Special Keys + KMC_TEST_CODETABLE, 14, VK_PRIOR, VK_NEXT, + VK_HOME, VK_END, + VK_LEFT, VK_RIGHT, VK_UP, VK_DOWN, + VK_INSERT, + VK_SNAPSHOT, VK_SLEEP, VK_PAUSE, VK_CANCEL, + VK_APPS, + KMC_ACT_STATEBIT, GKEYSTATE_SPECIAL_BIT, + KMC_ACT_CHARTABLE, 14, GKEY_PAGEUP, GKEY_PAGEDOWN, + GKEY_HOME, GKEY_END, + GKEY_LEFT, GKEY_RIGHT, GKEY_UP, GKEY_DOWN, + GKEY_INSERT, + GKEY_PRINTSCREEN, GKEY_SLEEP, GKEY_CTRLPAUSE, GKEY_CTRLBREAK, + GKEY_RIGHTCLICKKEY, + KMC_ACT_DONE, + /* 41 */KMC_RECORDSTART, 8, // F1 .. F15 + KMC_TEST_CODERANGE, VK_F1, VK_F15, + KMC_ACT_STATEBIT, GKEYSTATE_SPECIAL_BIT, + KMC_ACT_CHARRANGE, GKEY_FN1, + KMC_ACT_DONE, + + // Anything else + /* 40 */KMC_RECORDSTART, 1, // Just send the scan code to the user + KMC_ACT_DONE, + }; + + const GKeyboardVMT const GKEYBOARD_DRIVER_VMT[1] = {{ + { + GDRIVER_TYPE_KEYBOARD, + GKEYBOARD_VFLG_NOPOLL, // GKEYBOARD_VFLG_DYNAMICONLY + sizeof(GKeyboard), + _gkeyboardInitDriver, _gkeyboardPostInitDriver, _gkeyboardDeInitDriver + }, + KeyboardLayout_Win32_US, // The Win32 keyboard layout + Win32KeyboardInit, // init + 0, // deinit + Win32KeyboardGetData, // getdata + 0 // putdata void (*putdata)(GKeyboard *k, char ch); Optional + }}; + + static int keypos; + static uint8_t keybuffer[8]; + static GKeyboard *keyboard; +#endif + static DWORD winThreadId; static volatile bool_t QReady; static HANDLE drawMutex; @@ -287,16 +549,29 @@ static LRESULT myWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) break; #endif - case WM_SYSKEYDOWN: - case WM_KEYDOWN: - case WM_SYSKEYUP: - case WM_KEYUP: - break; - case WM_CHAR: - case WM_DEADCHAR: - case WM_SYSCHAR: - case WM_SYSDEADCHAR: - break; + #if GINPUT_NEED_KEYBOARD + case WM_SYSKEYDOWN: + case WM_SYSKEYUP: + case WM_KEYDOWN: + case WM_KEYUP: + if (keyboard && keypos < (int)sizeof(keybuffer)-1 && (wParam & 0xFF) > 0x01) { + if (Msg == WM_KEYUP || Msg == WM_SYSKEYUP) + keybuffer[keypos++] = 0x00; // Keyup + else if (HIWORD(lParam) & KF_REPEAT) + keybuffer[keypos++] = 0x01; // Repeat + keybuffer[keypos++] = wParam; + if ((gkvmt(keyboard)->d.flags & GKEYBOARD_VFLG_NOPOLL)) // For normal setup this is always TRUE + _gkeyboardWakeup(keyboard); + } + return 0; + /* + case WM_CHAR: + case WM_DEADCHAR: + case WM_SYSCHAR: + case WM_SYSDEADCHAR: + break; + */ + #endif case WM_ERASEBKGND: // Pretend we have erased the background. @@ -1213,6 +1488,34 @@ LLDSPEC bool_t gdisp_lld_init(GDisplay *g) { } #endif /* GINPUT_NEED_MOUSE */ +#if GINPUT_NEED_KEYBOARD + static bool_t Win32KeyboardInit(GKeyboard *k, unsigned driverinstance) { + (void) driverinstance; + + // Only one please + if (keyboard) + return FALSE; + + keyboard = k; + return TRUE; + } + + static int Win32KeyboardGetData(GKeyboard *k, uint8_t *pch, int sz) { + int i, j; + (void) k; + + if (!keypos) + return 0; + + for(i = 0; i < keypos && i < sz; i++) + pch[i] = keybuffer[i]; + keypos -= i; + for(j=0; j < keypos; j++) + keybuffer[j] = keybuffer[i+j]; + return i; + } +#endif + #if GINPUT_NEED_TOGGLE #if GINPUT_TOGGLE_CONFIG_ENTRIES > GDISP_DRIVER_COUNT_WIN32 #error "GDISP Win32: GINPUT_TOGGLE_CONFIG_ENTRIES must not be greater than GDISP_DRIVER_COUNT_WIN32"