Rémi Bernon : xinput1_3: Register for device notifications to update controller list.

Alexandre Julliard julliard at winehq.org
Fri Oct 8 14:12:27 CDT 2021


Module: wine
Branch: master
Commit: ebc70f78fba85309108a4396a7e6801d7d878839
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=ebc70f78fba85309108a4396a7e6801d7d878839

Author: Rémi Bernon <rbernon at codeweavers.com>
Date:   Fri Oct  8 13:02:26 2021 +0200

xinput1_3: Register for device notifications to update controller list.

Based on a patch from Andrew Eikum <aeikum at codeweavers.com>.

Dark Souls Remasters checks for xinput devices when it receives a
WM_DEVICECHANGE message. We would only poll for new devices if it had
been at least 2 seconds since the last check. So often, DS would receive
the message, but we would refuse to poll for devices, so the game would
think no controller was present.

This commit fixes that by also subscribing to event notifications and
triggering a poll.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/xinput1_1/Makefile.in   |  2 +-
 dlls/xinput1_2/Makefile.in   |  2 +-
 dlls/xinput1_3/Makefile.in   |  2 +-
 dlls/xinput1_3/main.c        | 38 +++++++++++++++++++++++++++++++++++++-
 dlls/xinput1_4/Makefile.in   |  2 +-
 dlls/xinput9_1_0/Makefile.in |  2 +-
 6 files changed, 42 insertions(+), 6 deletions(-)

diff --git a/dlls/xinput1_1/Makefile.in b/dlls/xinput1_1/Makefile.in
index 864b976f7e0..cc2825d0d19 100644
--- a/dlls/xinput1_1/Makefile.in
+++ b/dlls/xinput1_1/Makefile.in
@@ -1,5 +1,5 @@
 MODULE    = xinput1_1.dll
-IMPORTS   = hid setupapi advapi32
+IMPORTS   = hid setupapi advapi32 user32
 PARENTSRC = ../xinput1_3
 
 C_SRCS = \
diff --git a/dlls/xinput1_2/Makefile.in b/dlls/xinput1_2/Makefile.in
index 4dfcab040ee..1c4b48cdbda 100644
--- a/dlls/xinput1_2/Makefile.in
+++ b/dlls/xinput1_2/Makefile.in
@@ -1,5 +1,5 @@
 MODULE    = xinput1_2.dll
-IMPORTS   = hid setupapi advapi32
+IMPORTS   = hid setupapi advapi32 user32
 PARENTSRC = ../xinput1_3
 
 C_SRCS = \
diff --git a/dlls/xinput1_3/Makefile.in b/dlls/xinput1_3/Makefile.in
index 105d29f3300..a1c58a7452a 100644
--- a/dlls/xinput1_3/Makefile.in
+++ b/dlls/xinput1_3/Makefile.in
@@ -1,6 +1,6 @@
 MODULE    = xinput1_3.dll
 IMPORTLIB = xinput
-IMPORTS   = hid setupapi advapi32
+IMPORTS   = hid setupapi advapi32 user32
 
 C_SRCS = \
 	main.c
diff --git a/dlls/xinput1_3/main.c b/dlls/xinput1_3/main.c
index f49e74dc4b1..506802d142a 100644
--- a/dlls/xinput1_3/main.c
+++ b/dlls/xinput1_3/main.c
@@ -33,6 +33,7 @@
 #include "winnls.h"
 #include "winternl.h"
 
+#include "dbt.h"
 #include "setupapi.h"
 #include "devpkey.h"
 #include "hidusage.h"
@@ -118,6 +119,7 @@ static struct xinput_controller controllers[XUSER_MAX_COUNT] =
     {{ &controller_critsect_debug[3], -1, 0, 0, 0, 0 }},
 };
 
+static HMODULE xinput_instance;
 static HANDLE start_event;
 static HANDLE stop_event;
 static HANDLE done_event;
@@ -641,17 +643,45 @@ static void read_controller_state(struct xinput_controller *controller)
     LeaveCriticalSection(&controller->crit);
 }
 
+static LRESULT CALLBACK xinput_devnotify_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+    if (msg == WM_DEVICECHANGE && wparam == DBT_DEVICEARRIVAL) update_controller_list();
+    return DefWindowProcW(hwnd, msg, wparam, lparam);
+}
+
 static DWORD WINAPI hid_update_thread_proc(void *param)
 {
     struct xinput_controller *devices[XUSER_MAX_COUNT + 2];
     HANDLE events[XUSER_MAX_COUNT + 2];
     DWORD i, count = 2, ret = WAIT_TIMEOUT;
+    DEV_BROADCAST_DEVICEINTERFACE_W filter =
+    {
+        .dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE_W),
+        .dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE,
+        .dbcc_classguid = GUID_DEVINTERFACE_WINEXINPUT,
+    };
+    WNDCLASSEXW cls =
+    {
+        .cbSize = sizeof(WNDCLASSEXW),
+        .hInstance = xinput_instance,
+        .lpszClassName = L"__wine_xinput_devnotify",
+        .lpfnWndProc = xinput_devnotify_wndproc,
+    };
+    HDEVNOTIFY notif;
+    HWND hwnd;
+    MSG msg;
+
+    RegisterClassExW(&cls);
+    hwnd = CreateWindowExW(0, cls.lpszClassName, NULL, 0, 0, 0, 0, 0,
+                           HWND_MESSAGE, NULL, NULL, NULL);
+    notif = RegisterDeviceNotificationW(hwnd, &filter, DEVICE_NOTIFY_WINDOW_HANDLE);
 
     update_controller_list();
     SetEvent(start_event);
 
     do
     {
+        if (ret == count) while (PeekMessageW(&msg, hwnd, 0, 0, PM_REMOVE)) DispatchMessageW(&msg);
         if (ret == WAIT_TIMEOUT) update_controller_list();
         if (ret < count - 2) read_controller_state(devices[ret]);
 
@@ -671,7 +701,12 @@ static DWORD WINAPI hid_update_thread_proc(void *param)
         events[count++] = update_event;
         events[count++] = stop_event;
     }
-    while ((ret = WaitForMultipleObjectsEx( count, events, FALSE, 2000, TRUE )) < count - 1 || ret == WAIT_TIMEOUT);
+    while ((ret = MsgWaitForMultipleObjectsEx(count, events, 2000, QS_ALLINPUT, MWMO_ALERTABLE)) < count - 1 ||
+            ret == count || ret == WAIT_TIMEOUT);
+
+    UnregisterDeviceNotification(notif);
+    DestroyWindow(hwnd);
+    UnregisterClassW(cls.lpszClassName, xinput_instance);
 
     if (ret != count - 1) ERR("update thread exited unexpectedly, ret %u\n", ret);
     SetEvent(done_event);
@@ -733,6 +768,7 @@ BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved)
     switch (reason)
     {
     case DLL_PROCESS_ATTACH:
+        xinput_instance = inst;
         DisableThreadLibraryCalls(inst);
         break;
     case DLL_PROCESS_DETACH:
diff --git a/dlls/xinput1_4/Makefile.in b/dlls/xinput1_4/Makefile.in
index 2e243d8b268..393a416af9e 100644
--- a/dlls/xinput1_4/Makefile.in
+++ b/dlls/xinput1_4/Makefile.in
@@ -1,5 +1,5 @@
 MODULE    = xinput1_4.dll
-IMPORTS   = hid setupapi advapi32
+IMPORTS   = hid setupapi advapi32 user32
 PARENTSRC = ../xinput1_3
 
 C_SRCS = \
diff --git a/dlls/xinput9_1_0/Makefile.in b/dlls/xinput9_1_0/Makefile.in
index dc97909914d..55ea44ba666 100644
--- a/dlls/xinput9_1_0/Makefile.in
+++ b/dlls/xinput9_1_0/Makefile.in
@@ -1,5 +1,5 @@
 MODULE    = xinput9_1_0.dll
-IMPORTS   = hid setupapi advapi32
+IMPORTS   = hid setupapi advapi32 user32
 PARENTSRC = ../xinput1_3
 
 C_SRCS = \




More information about the wine-cvs mailing list