From da70f81a60213f89ea3e84861ba46481a1f56fde Mon Sep 17 00:00:00 2001 From: expikr <77922942+expikr@users.noreply.github.com> Date: Fri, 29 Nov 2024 19:15:29 +0800 Subject: [PATCH] detect whether poll was idle --- src/video/windows/SDL_windowsevents.c | 33 ++++++++++--------------- src/video/windows/SDL_windowsevents.h | 2 +- src/video/windows/SDL_windowsrawinput.c | 8 ++++-- 3 files changed, 20 insertions(+), 23 deletions(-) diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index b78422e8ae43a..39cc5c460b15d 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 idle_start, Uint64 idle_end) { SDL_VideoData *data = _this->internal; UINT size, i, count, total = 0; RAWINPUT *input; - Uint64 now; + Uint64 pump_end; 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)); + pump_end = 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,29 @@ 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; + bool idleless = (idle_end - idle_start) <= SDL_US_TO_NS(125); + Uint64 delta = pump_end - (idleless ? data->last_rawinput_poll : idle_end); + 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 = pump_end - (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(pump_end, data, input->header.hDevice, rawkeyboard); } } } - data->last_rawinput_poll = now; + data->last_rawinput_poll = pump_end; } #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 a48b8aaafd60d..6f82e7f7b6bd4 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 sleep_start, Uint64 sleep_end); 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 9a003af30ea87..7cbc0592e06e8 100644 --- a/src/video/windows/SDL_windowsrawinput.c +++ b/src/video/windows/SDL_windowsrawinput.c @@ -92,15 +92,19 @@ static DWORD WINAPI WIN_RawInputThread(LPVOID param) // Tell the parent we're ready to go! SetEvent(data->ready_event); + Uint64 idle_start, idle_end; while (!data->done) { - if (MsgWaitForMultipleObjects(1, &data->done_event, FALSE, INFINITE, QS_RAWINPUT) != (WAIT_OBJECT_0 + 1)) { + idle_start = SDL_GetTicksNS(); + DWORD result = MsgWaitForMultipleObjects(1, &data->done_event, FALSE, INFINITE, QS_RAWINPUT); + 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); + WIN_PollRawInput(_this, idle_start, idle_end); } devices[0].dwFlags |= RIDEV_REMOVE;