mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-04-28 20:37:24 +02:00
Moved mouse/keyboard detection to a separate thread on Windows
Getting device names can hang for a long time on certain devices, so make sure this is done on a separate thread to avoid blocking initialization and the main loop. Fixes https://github.com/libsdl-org/SDL/issues/12913
This commit is contained in:
@@ -175,12 +175,39 @@ static CM_Register_NotificationFunc CM_Register_Notification;
|
||||
static CM_Unregister_NotificationFunc CM_Unregister_Notification;
|
||||
static HCMNOTIFICATION s_DeviceNotificationFuncHandle;
|
||||
static Uint64 s_LastDeviceNotification = 1;
|
||||
static HANDLE s_HotplugEvent = INVALID_HANDLE_VALUE;
|
||||
static SDL_AtomicInt s_HotplugRunning;
|
||||
static SDL_Thread *s_HotplugThread;
|
||||
|
||||
#ifdef SDL_VIDEO_DRIVER_WINDOWS
|
||||
// Defined in SDL_windowsevents.c
|
||||
extern void WIN_CheckKeyboardAndMouseHotplug(bool hid_loaded);
|
||||
#endif
|
||||
|
||||
static int SDLCALL DeviceHotplugThread(void *unused)
|
||||
{
|
||||
bool hid_loaded = WIN_LoadHIDDLL();
|
||||
|
||||
// Always run the initial device detection
|
||||
do {
|
||||
#ifdef SDL_VIDEO_DRIVER_WINDOWS
|
||||
WIN_CheckKeyboardAndMouseHotplug(hid_loaded);
|
||||
#endif
|
||||
WaitForSingleObject(s_HotplugEvent, INFINITE);
|
||||
} while (SDL_GetAtomicInt(&s_HotplugRunning));
|
||||
|
||||
if (hid_loaded) {
|
||||
WIN_UnloadHIDDLL();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DWORD CALLBACK SDL_DeviceNotificationFunc(HCMNOTIFICATION hNotify, PVOID context, CM_NOTIFY_ACTION action, PCM_NOTIFY_EVENT_DATA eventData, DWORD event_data_size)
|
||||
{
|
||||
if (action == CM_NOTIFY_ACTION_DEVICEINTERFACEARRIVAL ||
|
||||
action == CM_NOTIFY_ACTION_DEVICEINTERFACEREMOVAL) {
|
||||
s_LastDeviceNotification = SDL_GetTicksNS();
|
||||
SetEvent(s_HotplugEvent);
|
||||
}
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
@@ -192,6 +219,11 @@ void WIN_InitDeviceNotification(void)
|
||||
return;
|
||||
}
|
||||
|
||||
// Start the device hotplug thread
|
||||
SDL_SetAtomicInt(&s_HotplugRunning, true);
|
||||
s_HotplugEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
s_HotplugThread = SDL_CreateThread(DeviceHotplugThread, "DeviceHotplugThread", NULL);
|
||||
|
||||
cfgmgr32_lib_handle = LoadLibraryA("cfgmgr32.dll");
|
||||
if (cfgmgr32_lib_handle) {
|
||||
CM_Register_Notification = (CM_Register_NotificationFunc)GetProcAddress(cfgmgr32_lib_handle, "CM_Register_Notification");
|
||||
@@ -225,6 +257,12 @@ void WIN_QuitDeviceNotification(void)
|
||||
// Make sure we have balanced calls to init/quit
|
||||
SDL_assert(s_DeviceNotificationsRequested == 0);
|
||||
|
||||
// Stop the device hotplug thread
|
||||
SDL_SetAtomicInt(&s_HotplugRunning, false);
|
||||
SetEvent(s_HotplugEvent);
|
||||
SDL_WaitThread(s_HotplugThread, NULL);
|
||||
s_HotplugThread = NULL;
|
||||
|
||||
if (cfgmgr32_lib_handle) {
|
||||
if (s_DeviceNotificationFuncHandle && CM_Unregister_Notification) {
|
||||
CM_Unregister_Notification(s_DeviceNotificationFuncHandle);
|
||||
|
||||
Reference in New Issue
Block a user