windows: enable raw keyboard input when raw mouse input is enabled
parent
35d335e61f
commit
012fc1e32b
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue