[PATCH 4/6] dinput8: Add support for rawinput based devices.
Rémi Bernon
rbernon at codeweavers.com
Mon Jun 29 13:33:58 CDT 2020
This adds a message window that will be used as the rawinput target
window for WM_INPUT messages.
Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
dlls/dinput/device_private.h | 3 ++
dlls/dinput/dinput_main.c | 76 ++++++++++++++++++++++++++++++++++++
2 files changed, 79 insertions(+)
diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h
index fe5644f21c7..2fac4f0e61e 100644
--- a/dlls/dinput/device_private.h
+++ b/dlls/dinput/device_private.h
@@ -69,6 +69,9 @@ struct IDirectInputDeviceImpl
HWND win;
int acquired;
+ 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; /* valid size of the queue */
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 2e561502406..d47e9a420f2 100644
--- a/dlls/dinput/dinput_main.c
+++ b/dlls/dinput/dinput_main.c
@@ -97,6 +97,9 @@ static const struct dinput_device *dinput_devices[] =
HINSTANCE DINPUT_instance;
+static const WCHAR di_em_win_w[] = {'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 );
@@ -637,6 +640,44 @@ 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)
+{
+ IDirectInputDeviceImpl *dev;
+ RAWINPUT ri;
+ UINT size = sizeof(ri);
+ int rim = GET_RAWINPUT_CODE_WPARAM( wparam );
+
+ TRACE( "%p %d %lx %lx\n", hwnd, msg, wparam, lparam );
+
+ if (msg == WM_INPUT && (rim == RIM_INPUT || rim == RIM_INPUTSINK))
+ {
+ if (GetRawInputData( (HRAWINPUT)lparam, RID_INPUT, &ri, &size, sizeof(RAWINPUTHEADER) ) > sizeof(ri))
+ WARN( "Unable to read raw input data\n" );
+ }
+
+ return DefWindowProcW( hwnd, msg, wparam, lparam );
+}
+
+static void register_di_em_win_class(void)
+{
+ WNDCLASSEXW class;
+
+ memset(&class, 0, sizeof(class));
+ class.cbSize = sizeof(class);
+ class.lpfnWndProc = di_em_win_wndproc;
+ class.hInstance = DINPUT_instance;
+ class.lpszClassName = di_em_win_w;
+
+ if (!RegisterClassExW( &class ) && GetLastError() != ERROR_CLASS_ALREADY_EXISTS)
+ WARN( "Unable to register message window class\n" );
+}
+
+static void unregister_di_em_win_class(void)
+{
+ if (!UnregisterClassW( di_em_win_w, NULL ) && GetLastError() != ERROR_CLASS_DOES_NOT_EXIST)
+ WARN( "Unable to unregister message window class\n" );
+}
+
static HRESULT initialize_directinput_instance(IDirectInputImpl *This, DWORD dwVersion)
{
if (!This->initialized)
@@ -1668,11 +1709,13 @@ static LRESULT CALLBACK LL_hook_proc( int code, WPARAM wparam, LPARAM lparam )
EnterCriticalSection( &dinput_hook_crit );
LIST_FOR_EACH_ENTRY( dev, &acquired_mouse_list, IDirectInputDeviceImpl, entry )
{
+ if (dev->use_raw_input) continue;
TRACE("calling dinput_mouse_hook (%p %lx %lx)\n", dev, wparam, lparam);
skip |= dinput_mouse_hook( &dev->IDirectInputDevice8A_iface, wparam, lparam );
}
LIST_FOR_EACH_ENTRY( dev, &acquired_keyboard_list, IDirectInputDeviceImpl, entry )
{
+ if (dev->use_raw_input) continue;
TRACE("calling dinput_keyboard_hook (%p %lx %lx)\n", dev, wparam, lparam);
skip |= dinput_keyboard_hook( &dev->IDirectInputDevice8A_iface, wparam, lparam );
}
@@ -1728,6 +1771,9 @@ static DWORD WINAPI hook_thread_proc(void *param)
static HHOOK kbd_hook, mouse_hook;
MSG msg;
+ di_em_win = CreateWindowW( di_em_win_w, di_em_win_w, 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);
@@ -1778,6 +1824,9 @@ static DWORD WINAPI hook_thread_proc(void *param)
DispatchMessageW(&msg);
}
+ DestroyWindow( di_em_win );
+ di_em_win = NULL;
+
FreeLibraryAndExitThread(DINPUT_instance, 0);
}
@@ -1860,6 +1909,31 @@ void check_dinput_hooks(LPDIRECTINPUTDEVICE8W iface, BOOL acquired)
hook_thread_event = NULL;
}
+ if (dev->use_raw_input)
+ {
+ if (acquired)
+ {
+ dev->raw_device.dwFlags = 0;
+ if (dev->dwCoopLevel & DISCL_BACKGROUND)
+ dev->raw_device.dwFlags |= RIDEV_INPUTSINK;
+ if (dev->dwCoopLevel & DISCL_EXCLUSIVE)
+ dev->raw_device.dwFlags |= RIDEV_NOLEGACY;
+ if ((dev->dwCoopLevel & DISCL_EXCLUSIVE) && dev->raw_device.usUsage == 2)
+ dev->raw_device.dwFlags |= RIDEV_CAPTUREMOUSE;
+ if ((dev->dwCoopLevel & DISCL_EXCLUSIVE) && dev->raw_device.usUsage == 6)
+ dev->raw_device.dwFlags |= RIDEV_NOHOTKEYS;
+ dev->raw_device.hwndTarget = di_em_win;
+ }
+ else
+ {
+ dev->raw_device.dwFlags = RIDEV_REMOVE;
+ dev->raw_device.hwndTarget = NULL;
+ }
+
+ 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 );
+ }
+
if (acquired)
hook_change_finished_event = CreateEventW( NULL, FALSE, FALSE, NULL );
PostThreadMessageW( hook_thread_id, WM_USER+0x10, 1, (LPARAM)hook_change_finished_event );
@@ -1894,9 +1968,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.27.0
More information about the wine-devel
mailing list