diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index 9409c3fbf..96dfcb07c 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -512,9 +512,13 @@ WIN_KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam) } if (wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN) { - SDL_SendKeyboardKey(0, SDL_GLOBAL_KEYBOARD_ID, SDL_PRESSED, scanCode); + if (data->raw_input_enable_count == 0) { + SDL_SendKeyboardKey(0, SDL_GLOBAL_KEYBOARD_ID, SDL_PRESSED, scanCode); + } } else { - SDL_SendKeyboardKey(0, SDL_GLOBAL_KEYBOARD_ID, SDL_RELEASED, scanCode); + if (data->raw_input_enable_count == 0) { + SDL_SendKeyboardKey(0, SDL_GLOBAL_KEYBOARD_ID, SDL_RELEASED, scanCode); + } /* If the key was down prior to our hook being installed, allow the key up message to pass normally the first time. This ensures other @@ -532,8 +536,14 @@ WIN_KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam) static void WIN_HandleRawMouseInput(Uint64 timestamp, SDL_WindowData *data, HANDLE hDevice, RAWMOUSE *rawmouse) { + SDL_Mouse *mouse = SDL_GetMouse(); SDL_MouseID mouseID; + /* We only use raw mouse input in relative mode */ + if (!mouse->relative_mode || mouse->relative_mode_warp) { + return; + } + if (GetMouseMessageSource(rawmouse->ulExtraInformation) == SDL_MOUSE_EVENT_SOURCE_TOUCH) { return; } @@ -619,17 +629,34 @@ static void WIN_HandleRawMouseInput(Uint64 timestamp, SDL_WindowData *data, HAND WIN_CheckRawMouseButtons(timestamp, hDevice, rawmouse->usButtonFlags, data, mouseID); } -void WIN_PollRawMouseInput(void) +static void WIN_HandleRawKeyboardInput(Uint64 timestamp, SDL_WindowData *data, HANDLE hDevice, RAWKEYBOARD *rawkeyboard) +{ + SDL_KeyboardID keyboardID = (SDL_KeyboardID)(uintptr_t)hDevice; + + Uint8 state = (rawkeyboard->Flags & RI_KEY_BREAK) ? SDL_RELEASED : SDL_PRESSED; + Uint16 scanCode = rawkeyboard->MakeCode; + if (rawkeyboard->Flags & RI_KEY_E0) { + scanCode |= (0xE0 << 8); + } else if (rawkeyboard->Flags & RI_KEY_E1) { + scanCode |= (0xE1 << 8); + } + + // Pack scan code into one byte to make the index + Uint8 index = LOBYTE(scanCode) | (HIBYTE(scanCode) ? 0x80 : 0x00); + SDL_Scancode code = windows_scancode_table[index]; + + SDL_SendKeyboardKey(timestamp, keyboardID, state, code); +} + +void WIN_PollRawInput(SDL_VideoDevice *_this) { - SDL_Mouse *mouse = SDL_GetMouse(); SDL_Window *window; SDL_WindowData *data; UINT size, count, i, total = 0; RAWINPUT *input; Uint64 now; - /* We only use raw mouse input in relative mode */ - if (!mouse->relative_mode || mouse->relative_mode_warp) { + if (_this->driverdata->raw_input_enable_count == 0) { return; } @@ -695,6 +722,9 @@ void WIN_PollRawMouseInput(void) if (input->header.dwType == RIM_TYPEMOUSE) { RAWMOUSE *rawmouse = (RAWMOUSE *)((BYTE *)input + data->rawinput_offset); WIN_HandleRawMouseInput(timestamp, window->driverdata, input->header.hDevice, rawmouse); + } else if (input->header.dwType == RIM_TYPEKEYBOARD) { + RAWKEYBOARD *rawkeyboard = (RAWKEYBOARD *)((BYTE *)input + data->rawinput_offset); + WIN_HandleRawKeyboardInput(timestamp, window->driverdata, input->header.hDevice, rawkeyboard); } } } @@ -1024,13 +1054,11 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara #if 0 /* We handle raw input all at once instead of using a syscall for each mouse event */ case WM_INPUT: { - SDL_Mouse *mouse = SDL_GetMouse(); HRAWINPUT hRawInput = (HRAWINPUT)lParam; RAWINPUT inp; UINT size = sizeof(inp); - /* We only use raw mouse input in relative mode */ - if (!mouse->relative_mode || mouse->relative_mode_warp) { + if (data->raw_input_enable_count == 0) { break; } @@ -1040,10 +1068,10 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara } GetRawInputData(hRawInput, RID_INPUT, &inp, &size, sizeof(RAWINPUTHEADER)); - - /* Mouse data (ignoring synthetic mouse events generated for touchscreens) */ if (inp.header.dwType == RIM_TYPEMOUSE) { WIN_HandleRawMouseInput(WIN_GetEventTimestamp(), data, inp.header.hDevice, &inp.data.mouse); + } else if (inp.header.dwType == RIM_TYPEKEYBOARD) { + WIN_HandleRawKeyboardInput(WIN_GetEventTimestamp(), data, inp.header.hDevice, &inp.data.keyboard); } } break; #endif @@ -1107,7 +1135,7 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara } } - if (code != SDL_SCANCODE_UNKNOWN) { + if (data->videodata->raw_input_enable_count == 0 && code != SDL_SCANCODE_UNKNOWN) { SDL_SendKeyboardKey(WIN_GetEventTimestamp(), SDL_GLOBAL_KEYBOARD_ID, SDL_PRESSED, code); } } @@ -1121,7 +1149,7 @@ LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lPara SDL_Scancode code = WindowsScanCodeToSDLScanCode(lParam, wParam); const Uint8 *keyboardState = SDL_GetKeyboardState(NULL); - if (code != SDL_SCANCODE_UNKNOWN) { + if (data->videodata->raw_input_enable_count == 0 && code != SDL_SCANCODE_UNKNOWN) { if (code == SDL_SCANCODE_PRINTSCREEN && keyboardState[code] == SDL_RELEASED) { SDL_SendKeyboardKey(WIN_GetEventTimestamp(), SDL_GLOBAL_KEYBOARD_ID, SDL_PRESSED, code); diff --git a/src/video/windows/SDL_windowsevents.h b/src/video/windows/SDL_windowsevents.h index 1b01ba4bd..5acd69b12 100644 --- a/src/video/windows/SDL_windowsevents.h +++ b/src/video/windows/SDL_windowsevents.h @@ -30,7 +30,7 @@ extern HINSTANCE SDL_Instance; extern LRESULT CALLBACK WIN_KeyboardHookProc(int nCode, WPARAM wParam, LPARAM lParam); extern LRESULT CALLBACK WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); -extern void WIN_PollRawMouseInput(void); +extern void WIN_PollRawInput(SDL_VideoDevice *_this); extern void WIN_CheckKeyboardAndMouseHotplug(SDL_VideoDevice *_this, SDL_bool initial_check); extern void WIN_PumpEvents(SDL_VideoDevice *_this); extern void WIN_SendWakeupEvent(SDL_VideoDevice *_this, SDL_Window *window); diff --git a/src/video/windows/SDL_windowsmouse.c b/src/video/windows/SDL_windowsmouse.c index 5485f0213..74ddae624 100644 --- a/src/video/windows/SDL_windowsmouse.c +++ b/src/video/windows/SDL_windowsmouse.c @@ -33,24 +33,24 @@ DWORD SDL_last_warp_time = 0; HCURSOR SDL_cursor = NULL; static SDL_Cursor *SDL_blank_cursor = NULL; -static int rawInputEnableCount = 0; - typedef struct { HANDLE ready_event; HANDLE done_event; HANDLE thread; -} RawMouseThreadData; +} RawInputThreadData; -static RawMouseThreadData thread_data = { +static RawInputThreadData thread_data = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE }; -static DWORD WINAPI WIN_RawMouseThread(LPVOID param) +static DWORD WINAPI WIN_RawInputThread(LPVOID param) { - RAWINPUTDEVICE rawMouse; + SDL_VideoDevice *_this = SDL_GetVideoDevice(); + RawInputThreadData *data = (RawInputThreadData *)param; + RAWINPUTDEVICE devices[2]; HWND window; window = CreateWindowEx(0, TEXT("Message"), NULL, 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL); @@ -58,76 +58,83 @@ static DWORD WINAPI WIN_RawMouseThread(LPVOID param) return 0; } - rawMouse.usUsagePage = USB_USAGEPAGE_GENERIC_DESKTOP; - rawMouse.usUsage = USB_USAGE_GENERIC_MOUSE; - rawMouse.dwFlags = 0; - rawMouse.hwndTarget = window; + devices[0].usUsagePage = USB_USAGEPAGE_GENERIC_DESKTOP; + devices[0].usUsage = USB_USAGE_GENERIC_MOUSE; + devices[0].dwFlags = 0; + devices[0].hwndTarget = window; - if (!RegisterRawInputDevices(&rawMouse, 1, sizeof(rawMouse))) { + devices[1].usUsagePage = USB_USAGEPAGE_GENERIC_DESKTOP; + devices[1].usUsage = USB_USAGE_GENERIC_KEYBOARD; + devices[1].dwFlags = 0; + devices[1].hwndTarget = window; + + if (!RegisterRawInputDevices(devices, SDL_arraysize(devices), sizeof(devices[0]))) { DestroyWindow(window); return 0; } - /* Make sure we get mouse events as soon as possible */ + /* Make sure we get events as soon as possible */ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); /* Tell the parent we're ready to go! */ - SetEvent(thread_data.ready_event); + SetEvent(data->ready_event); for ( ; ; ) { - if (MsgWaitForMultipleObjects(1, &thread_data.done_event, 0, INFINITE, QS_RAWINPUT) != WAIT_OBJECT_0 + 1) { + if (MsgWaitForMultipleObjects(1, &data->done_event, 0, INFINITE, QS_RAWINPUT) != WAIT_OBJECT_0 + 1) { break; } /* Clear the queue status so MsgWaitForMultipleObjects() will wait again */ (void)GetQueueStatus(QS_RAWINPUT); - WIN_PollRawMouseInput(); + WIN_PollRawInput(_this); } - rawMouse.dwFlags |= RIDEV_REMOVE; - RegisterRawInputDevices(&rawMouse, 1, sizeof(rawMouse)); + devices[0].dwFlags |= RIDEV_REMOVE; + devices[1].dwFlags |= RIDEV_REMOVE; + RegisterRawInputDevices(devices, SDL_arraysize(devices), sizeof(devices[0])); DestroyWindow(window); return 0; } -static void CleanupRawMouseThreadData(void) +static void CleanupRawInputThreadData(RawInputThreadData *data) { - if (thread_data.thread != INVALID_HANDLE_VALUE) { - SetEvent(thread_data.done_event); - WaitForSingleObject(thread_data.thread, 500); - CloseHandle(thread_data.thread); - thread_data.thread = INVALID_HANDLE_VALUE; + if (data->thread != INVALID_HANDLE_VALUE) { + SetEvent(data->done_event); + WaitForSingleObject(data->thread, 500); + CloseHandle(data->thread); + data->thread = INVALID_HANDLE_VALUE; } - if (thread_data.ready_event != INVALID_HANDLE_VALUE) { - CloseHandle(thread_data.ready_event); - thread_data.ready_event = INVALID_HANDLE_VALUE; + if (data->ready_event != INVALID_HANDLE_VALUE) { + CloseHandle(data->ready_event); + data->ready_event = INVALID_HANDLE_VALUE; } - if (thread_data.done_event != INVALID_HANDLE_VALUE) { - CloseHandle(thread_data.done_event); - thread_data.done_event = INVALID_HANDLE_VALUE; + if (data->done_event != INVALID_HANDLE_VALUE) { + CloseHandle(data->done_event); + data->done_event = INVALID_HANDLE_VALUE; } } -static int ToggleRawInput(SDL_bool enabled) +static int ToggleRawInput(SDL_VideoDevice *_this, SDL_bool enabled) { + SDL_VideoData *data = _this->driverdata; int result = -1; if (enabled) { - rawInputEnableCount++; - if (rawInputEnableCount > 1) { + ++data->raw_input_enable_count; + if (data->raw_input_enable_count > 1) { return 0; /* already done. */ } } else { - if (rawInputEnableCount == 0) { + if (data->raw_input_enable_count == 0) { return 0; /* already done. */ } - rawInputEnableCount--; - if (rawInputEnableCount > 0) { + --data->raw_input_enable_count; + if (data->raw_input_enable_count > 0) { return 0; /* not time to disable yet */ } } @@ -147,7 +154,7 @@ static int ToggleRawInput(SDL_bool enabled) goto done; } - thread_data.thread = CreateThread(NULL, 0, WIN_RawMouseThread, &thread_data, 0, NULL); + thread_data.thread = CreateThread(NULL, 0, WIN_RawInputThread, &thread_data, 0, NULL); if (thread_data.thread == INVALID_HANDLE_VALUE) { WIN_SetError("CreateThread"); goto done; @@ -162,16 +169,16 @@ static int ToggleRawInput(SDL_bool enabled) } result = 0; } else { - CleanupRawMouseThreadData(); + CleanupRawInputThreadData(&thread_data); result = 0; } done: if (enabled && result < 0) { - CleanupRawMouseThreadData(); + CleanupRawInputThreadData(&thread_data); - /* Reset rawInputEnableCount so we can try again */ - rawInputEnableCount = 0; + /* Reset so we can try again */ + data->raw_input_enable_count = 0; } return result; } @@ -509,7 +516,7 @@ static int WIN_WarpMouseGlobal(float x, float y) static int WIN_SetRelativeMouseMode(SDL_bool enabled) { - return ToggleRawInput(enabled); + return ToggleRawInput(SDL_GetVideoDevice(), enabled); } static int WIN_CaptureMouse(SDL_Window *window) @@ -574,9 +581,10 @@ void WIN_InitMouse(SDL_VideoDevice *_this) void WIN_QuitMouse(SDL_VideoDevice *_this) { - if (rawInputEnableCount) { /* force RAWINPUT off here. */ - rawInputEnableCount = 1; - ToggleRawInput(SDL_FALSE); + SDL_VideoData *data = _this->driverdata; + if (data->raw_input_enable_count) { /* force RAWINPUT off here. */ + data->raw_input_enable_count = 1; + ToggleRawInput(_this, SDL_FALSE); } if (SDL_blank_cursor) { diff --git a/src/video/windows/SDL_windowsvideo.h b/src/video/windows/SDL_windowsvideo.h index 4b3d3c27a..9dbcc0100 100644 --- a/src/video/windows/SDL_windowsvideo.h +++ b/src/video/windows/SDL_windowsvideo.h @@ -406,6 +406,8 @@ struct SDL_VideoData SDL_bool cleared; + int raw_input_enable_count; + #ifndef SDL_DISABLE_WINDOWS_IME SDL_bool ime_com_initialized; struct ITfThreadMgr *ime_threadmgr;