[PATCH 2/3] xinput1_3: Update the controller list in the update thread.

Rémi Bernon rbernon at codeweavers.com
Tue Aug 10 06:27:23 CDT 2021


Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 dlls/xinput1_3/main.c | 49 +++++++++++++++++++------------------------
 1 file changed, 22 insertions(+), 27 deletions(-)

diff --git a/dlls/xinput1_3/main.c b/dlls/xinput1_3/main.c
index 63f125ae528..45ccb5f79db 100644
--- a/dlls/xinput1_3/main.c
+++ b/dlls/xinput1_3/main.c
@@ -118,7 +118,6 @@ static struct xinput_controller controllers[XUSER_MAX_COUNT] =
     {{ &controller_critsect_debug[3], -1, 0, 0, 0, 0 }},
 };
 
-static DWORD last_check = 0;
 static HANDLE stop_event;
 static HANDLE done_event;
 
@@ -296,12 +295,8 @@ failed:
     return FALSE;
 }
 
-static BOOL WINAPI start_update_thread_once( INIT_ONCE *once, void *param, void **context );
-
-static void HID_find_gamepads(void)
+static void update_controller_list(void)
 {
-    static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
-
     char buffer[sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA_W) + MAX_PATH * sizeof(WCHAR)];
     SP_DEVICE_INTERFACE_DETAIL_DATA_W *detail = (SP_DEVICE_INTERFACE_DETAIL_DATA_W *)buffer;
     SP_DEVICE_INTERFACE_DATA iface = {sizeof(iface)};
@@ -314,20 +309,6 @@ static void HID_find_gamepads(void)
     GUID guid;
     int i;
 
-    InitOnceExecuteOnce(&init_once, start_update_thread_once, NULL, NULL);
-
-    idx = GetTickCount();
-    if ((idx - last_check) < 2000) return;
-
-    EnterCriticalSection(&xinput_crit);
-
-    if ((idx - last_check) < 2000)
-    {
-        LeaveCriticalSection(&xinput_crit);
-        return;
-    }
-    last_check = idx;
-
     HidD_GetHidGuid(&guid);
 
     set = SetupDiGetClassDevsW(&guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
@@ -368,7 +349,6 @@ static void HID_find_gamepads(void)
     }
 
     SetupDiDestroyDeviceInfoList(set);
-    LeaveCriticalSection(&xinput_crit);
 }
 
 static void controller_destroy(struct xinput_controller *controller)
@@ -541,14 +521,18 @@ static void HID_update_state(struct xinput_controller *controller, XINPUT_STATE
 static DWORD WINAPI hid_update_thread_proc(void *param)
 {
     HANDLE events[1];
-    DWORD count, ret;
+    DWORD count, ret = WAIT_TIMEOUT;
 
     do
     {
+        EnterCriticalSection(&xinput_crit);
+        if (ret == WAIT_TIMEOUT) update_controller_list();
+
         count = 0;
         events[count++] = stop_event;
+        LeaveCriticalSection(&xinput_crit);
     }
-    while ((ret = WaitForMultipleObjectsEx( count, events, FALSE, INFINITE, TRUE )) < count - 1);
+    while ((ret = WaitForMultipleObjectsEx( count, events, FALSE, 2000, TRUE )) < count - 1 || ret == WAIT_TIMEOUT);
 
     if (ret != count - 1) ERR("update thread exited unexpectedly, ret %u\n", ret);
     SetEvent(done_event);
@@ -569,9 +553,20 @@ static BOOL WINAPI start_update_thread_once( INIT_ONCE *once, void *param, void
     if (!thread) ERR("failed to create update thread, error %u\n", GetLastError());
     CloseHandle(thread);
 
+    /* do it once now, to resolve delayed imports and populate the initial list */
+    EnterCriticalSection(&xinput_crit);
+    update_controller_list();
+    LeaveCriticalSection(&xinput_crit);
+
     return TRUE;
 }
 
+static void start_update_thread(void)
+{
+    static INIT_ONCE init_once = INIT_ONCE_STATIC_INIT;
+    InitOnceExecuteOnce(&init_once, start_update_thread_once, NULL, NULL);
+}
+
 static BOOL controller_lock(struct xinput_controller *controller)
 {
     if (!controller->device) return FALSE;
@@ -617,7 +612,7 @@ void WINAPI DECLSPEC_HOTPATCH XInputEnable(BOOL enable)
     to the controllers. Setting to true will send the last vibration
     value (sent to XInputSetState) to the controller and allow messages to
     be sent */
-    HID_find_gamepads();
+    start_update_thread();
 
     for (index = 0; index < XUSER_MAX_COUNT; index++)
     {
@@ -634,7 +629,7 @@ DWORD WINAPI DECLSPEC_HOTPATCH XInputSetState(DWORD index, XINPUT_VIBRATION *vib
 
     TRACE("(index %u, vibration %p)\n", index, vibration);
 
-    HID_find_gamepads();
+    start_update_thread();
 
     if (index >= XUSER_MAX_COUNT) return ERROR_BAD_ARGUMENTS;
     if (!controller_lock(&controllers[index])) return ERROR_DEVICE_NOT_CONNECTED;
@@ -652,7 +647,7 @@ static DWORD xinput_get_state(DWORD index, XINPUT_STATE *state)
 {
     if (!state) return ERROR_BAD_ARGUMENTS;
 
-    HID_find_gamepads();
+    start_update_thread();
 
     if (index >= XUSER_MAX_COUNT) return ERROR_BAD_ARGUMENTS;
     if (!controller_lock(&controllers[index])) return ERROR_DEVICE_NOT_CONNECTED;
@@ -908,7 +903,7 @@ DWORD WINAPI DECLSPEC_HOTPATCH XInputGetCapabilities(DWORD index, DWORD flags, X
 {
     TRACE("(index %u, flags 0x%x, capabilities %p)\n", index, flags, capabilities);
 
-    HID_find_gamepads();
+    start_update_thread();
 
     if (index >= XUSER_MAX_COUNT) return ERROR_BAD_ARGUMENTS;
 
-- 
2.32.0




More information about the wine-devel mailing list