[PATCH v2 2/4] dinput8: Add support for dinput devices that use raw input interface
Rémi Bernon
rbernon at codeweavers.com
Thu Aug 29 03:30:57 CDT 2019
This adds a global message window that will receive WM_INPUT messages,
dispatched to every raw input device event_proc.
Devices that use raw input interface will not register low-level hooks
anymore. They will also conflict with any raw input device registered
outside of dinput, as exposed by the unit tests.
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
dlls/dinput/device_private.h | 3 ++
dlls/dinput/dinput_main.c | 79 +++++++++++++++++++++++++++++++++++-
2 files changed, 81 insertions(+), 1 deletion(-)
diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h
index 27e9c262869..8d4d6a0b5bf 100644
--- a/dlls/dinput/device_private.h
+++ b/dlls/dinput/device_private.h
@@ -70,6 +70,9 @@ struct IDirectInputDeviceImpl
int acquired;
DI_EVENT_PROC event_proc; /* function to receive mouse & keyboard events */
+ BOOL use_raw_input; /* use raw input instead of low-level messages */
+ RAWINPUTDEVICE raw_device; /* raw device to (un)register */
+
LPDIDEVICEOBJECTDATA data_queue; /* buffer for 'GetDeviceData'. */
int queue_len; /* size of the queue - set in 'SetProperty' */
int queue_head; /* position to write new event into queue */
diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
index 0855cb41cd5..4fd0b9cc5a9 100644
--- a/dlls/dinput/dinput_main.c
+++ b/dlls/dinput/dinput_main.c
@@ -97,6 +97,10 @@ static const struct dinput_device *dinput_devices[] =
HINSTANCE DINPUT_instance;
+static ATOM di_em_win_class;
+static const WCHAR di_em_winW[] = {'D','I','E','m','W','i','n',0};
+static HWND di_em_win;
+
static BOOL check_hook_thread(void);
static CRITICAL_SECTION dinput_hook_crit;
static struct list direct_input_list = LIST_INIT( direct_input_list );
@@ -611,6 +615,59 @@ static HRESULT WINAPI IDirectInputWImpl_QueryInterface(LPDIRECTINPUT7W iface, RE
return IDirectInputAImpl_QueryInterface( &This->IDirectInput7A_iface, riid, ppobj );
}
+static LRESULT WINAPI di_em_win_wndproc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
+{
+ IDirectInputImpl *dinput;
+
+ TRACE( "%p %d %lx %lx\n", hwnd, msg, wparam, lparam );
+
+ if (msg == WM_INPUT)
+ {
+ EnterCriticalSection( &dinput_hook_crit );
+ LIST_FOR_EACH_ENTRY( dinput, &direct_input_list, IDirectInputImpl, entry )
+ {
+ IDirectInputDeviceImpl *dev;
+
+ EnterCriticalSection( &dinput->crit );
+ LIST_FOR_EACH_ENTRY( dev, &dinput->devices_list, IDirectInputDeviceImpl, entry )
+ {
+ if (dev->acquired && dev->event_proc && dev->use_raw_input)
+ {
+ TRACE("calling %p->%p (%lx %lx)\n", dev, dev->event_proc, wparam, lparam);
+ dev->event_proc( &dev->IDirectInputDevice8A_iface, GET_RAWINPUT_CODE_WPARAM(wparam), lparam );
+ }
+ }
+ LeaveCriticalSection( &dinput->crit );
+ }
+ LeaveCriticalSection( &dinput_hook_crit );
+ }
+
+ return DefWindowProcW(hwnd, msg, wparam, lparam);
+}
+
+static void register_di_em_win_class(void)
+{
+ static WNDCLASSEXW class;
+
+ ZeroMemory(&class, sizeof(class));
+ class.cbSize = sizeof(class);
+ class.lpfnWndProc = di_em_win_wndproc;
+ class.hInstance = DINPUT_instance;
+ class.lpszClassName = di_em_winW;
+
+ if (!(di_em_win_class = RegisterClassExW( &class )))
+ WARN( "Unable to register message window class\n" );
+}
+
+static void unregister_di_em_win_class(void)
+{
+ if (!di_em_win_class)
+ return;
+
+ if (!UnregisterClassW( MAKEINTRESOURCEW( di_em_win_class ), DINPUT_instance ))
+ WARN( "Unable to unregister message window class\n" );
+}
+
static HRESULT initialize_directinput_instance(IDirectInputImpl *This, DWORD dwVersion)
{
if (!This->initialized)
@@ -1706,6 +1763,9 @@ static DWORD WINAPI hook_thread_proc(void *param)
static HHOOK kbd_hook, mouse_hook;
MSG msg;
+ di_em_win = CreateWindowW( MAKEINTRESOURCEW(di_em_win_class), di_em_winW,
+ 0, 0, 0, 0, 0, HWND_MESSAGE, 0, DINPUT_instance, NULL );
+
/* Force creation of the message queue */
PeekMessageW( &msg, 0, 0, 0, PM_NOREMOVE );
SetEvent(param);
@@ -1738,7 +1798,7 @@ static DWORD WINAPI hook_thread_proc(void *param)
EnterCriticalSection( &dinput->crit );
LIST_FOR_EACH_ENTRY( dev, &dinput->devices_list, IDirectInputDeviceImpl, entry )
{
- if (!dev->acquired || !dev->event_proc) continue;
+ if (!dev->acquired || !dev->event_proc || dev->use_raw_input) continue;
if (IsEqualGUID( &dev->guid, &GUID_SysKeyboard ))
kbd_cnt++;
@@ -1770,6 +1830,9 @@ static DWORD WINAPI hook_thread_proc(void *param)
DispatchMessageW(&msg);
}
+ DestroyWindow( di_em_win );
+ di_em_win = NULL;
+
FreeLibraryAndExitThread(DINPUT_instance, 0);
}
@@ -1851,6 +1914,18 @@ void check_dinput_hooks(LPDIRECTINPUTDEVICE8W iface, BOOL acquired)
hook_thread_event = NULL;
}
+ if (dev->use_raw_input)
+ {
+ if (acquired)
+ dev->raw_device.dwFlags = RIDEV_INPUTSINK;
+ else
+ dev->raw_device.dwFlags = RIDEV_REMOVE;
+ dev->raw_device.hwndTarget = di_em_win;
+
+ if (!RegisterRawInputDevices( &dev->raw_device, 1, sizeof(RAWINPUTDEVICE) ))
+ WARN( "Unable to (un)register raw device %x:%x\n", dev->raw_device.usUsagePage, dev->raw_device.usUsage );
+ }
+
PostThreadMessageW( hook_thread_id, WM_USER+0x10, 1, 0 );
LeaveCriticalSection(&dinput_hook_crit);
@@ -1877,9 +1952,11 @@ BOOL WINAPI DllMain( HINSTANCE inst, DWORD reason, LPVOID reserved)
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(inst);
DINPUT_instance = inst;
+ register_di_em_win_class();
break;
case DLL_PROCESS_DETACH:
if (reserved) break;
+ unregister_di_em_win_class();
DeleteCriticalSection(&dinput_hook_crit);
break;
}
--
2.23.0.rc1
More information about the wine-devel
mailing list