dinput8: Add support for rawinput based devices.
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@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
03ad3ca17a
commit
225be12999
|
@ -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 */
|
||||
|
|
|
@ -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,45 @@ 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))
|
||||
{
|
||||
size = GetRawInputData( (HRAWINPUT)lparam, RID_INPUT, &ri, &size, sizeof(RAWINPUTHEADER) );
|
||||
if (size == (UINT)-1 || size < sizeof(RAWINPUTHEADER))
|
||||
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 +1710,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 +1772,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 +1825,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 +1910,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 +1969,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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue