diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index b78422e8ae..c51ec92021 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/src/video/windows/SDL_windowsevents.c @@ -740,12 +740,12 @@ static void WIN_HandleRawKeyboardInput(Uint64 timestamp, SDL_VideoData *data, HA SDL_SendKeyboardKey(timestamp, keyboardID, rawcode, code, down); } -void WIN_PollRawInput(SDL_VideoDevice *_this) +void WIN_PollRawInput(SDL_VideoDevice *_this, Uint64 poll_start) { SDL_VideoData *data = _this->internal; UINT size, i, count, total = 0; RAWINPUT *input; - Uint64 now; + Uint64 poll_finish; if (data->rawinput_offset == 0) { BOOL isWow64; @@ -762,6 +762,7 @@ void WIN_PollRawInput(SDL_VideoDevice *_this) for (;;) { size = data->rawinput_size - (UINT)((BYTE *)input - data->rawinput); count = GetRawInputBuffer(input, &size, sizeof(RAWINPUTHEADER)); + poll_finish = SDL_GetTicksNS(); if (count == 0 || count == (UINT)-1) { if (!data->rawinput || (count == (UINT)-1 && GetLastError() == ERROR_INSUFFICIENT_BUFFER)) { const UINT RAWINPUT_BUFFER_SIZE_INCREMENT = 96; // 2 64-bit raw mouse packets @@ -785,37 +786,28 @@ void WIN_PollRawInput(SDL_VideoDevice *_this) } } - now = SDL_GetTicksNS(); if (total > 0) { - Uint64 mouse_timestamp, mouse_increment; - Uint64 delta = (now - data->last_rawinput_poll); - UINT total_mouse = 0; + Uint64 delta = poll_finish - poll_start; + UINT mouse_total = 0; for (i = 0, input = (RAWINPUT *)data->rawinput; i < total; ++i, input = NEXTRAWINPUTBLOCK(input)) { if (input->header.dwType == RIM_TYPEMOUSE) { - ++total_mouse; + mouse_total += 1; } } - if (total_mouse > 1 && delta <= SDL_MS_TO_NS(100)) { - // We'll spread these events over the time since the last poll - mouse_timestamp = data->last_rawinput_poll; - mouse_increment = delta / total_mouse; - } else { - // Do we want to track the update rate per device? - mouse_timestamp = now; - mouse_increment = 0; - } + int mouse_index = 0; for (i = 0, input = (RAWINPUT *)data->rawinput; i < total; ++i, input = NEXTRAWINPUTBLOCK(input)) { if (input->header.dwType == RIM_TYPEMOUSE) { + mouse_index += 1; // increment first so that it starts at one RAWMOUSE *rawmouse = (RAWMOUSE *)((BYTE *)input + data->rawinput_offset); - mouse_timestamp += mouse_increment; - WIN_HandleRawMouseInput(mouse_timestamp, data, input->header.hDevice, rawmouse); + Uint64 time = poll_finish - (delta * (mouse_total - mouse_index)) / mouse_total; + WIN_HandleRawMouseInput(time, data, input->header.hDevice, rawmouse); } else if (input->header.dwType == RIM_TYPEKEYBOARD) { RAWKEYBOARD *rawkeyboard = (RAWKEYBOARD *)((BYTE *)input + data->rawinput_offset); - WIN_HandleRawKeyboardInput(now, data, input->header.hDevice, rawkeyboard); + WIN_HandleRawKeyboardInput(poll_finish, data, input->header.hDevice, rawkeyboard); } } } - data->last_rawinput_poll = now; + data->last_rawinput_poll = poll_finish; } #endif // !defined(SDL_PLATFORM_XBOXONE) && !defined(SDL_PLATFORM_XBOXSERIES) diff --git a/src/video/windows/SDL_windowsevents.h b/src/video/windows/SDL_windowsevents.h index a48b8aaafd..8d4e762a0e 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_PollRawInput(SDL_VideoDevice *_this); +extern void WIN_PollRawInput(SDL_VideoDevice *_this, Uint64 poll_start); extern void WIN_CheckKeyboardAndMouseHotplug(SDL_VideoDevice *_this, 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_windowsrawinput.c b/src/video/windows/SDL_windowsrawinput.c index 9a003af30e..1d3a9e98c1 100644 --- a/src/video/windows/SDL_windowsrawinput.c +++ b/src/video/windows/SDL_windowsrawinput.c @@ -93,14 +93,21 @@ static DWORD WINAPI WIN_RawInputThread(LPVOID param) SetEvent(data->ready_event); while (!data->done) { - if (MsgWaitForMultipleObjects(1, &data->done_event, FALSE, INFINITE, QS_RAWINPUT) != (WAIT_OBJECT_0 + 1)) { + Uint64 idle_begin = SDL_GetTicksNS(); + DWORD result = MsgWaitForMultipleObjects(1, &data->done_event, FALSE, INFINITE, QS_RAWINPUT); + Uint64 idle_end = SDL_GetTicksNS(); + if (result != (WAIT_OBJECT_0 + 1)) { break; } // Clear the queue status so MsgWaitForMultipleObjects() will wait again (void)GetQueueStatus(QS_RAWINPUT); - WIN_PollRawInput(_this); + Uint64 idle_time = idle_end - idle_begin; + Uint64 usb_8khz_interval = SDL_US_TO_NS(125); + Uint64 poll_start = idle_time < usb_8khz_interval ? _this->internal->last_rawinput_poll : idle_end; + + WIN_PollRawInput(_this, poll_start); } devices[0].dwFlags |= RIDEV_REMOVE;