dinput: Hook window threads instead of the entire prefix.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=54431
This commit is contained in:
Rémi Bernon 2023-02-15 13:46:49 +01:00 committed by Alexandre Julliard
parent 7a2d59fb24
commit e5c540c59b
2 changed files with 21 additions and 12 deletions

View file

@ -95,6 +95,7 @@ struct dinput_device
HWND win;
enum device_status status;
BOOL use_raw_input; /* use raw input instead of low-level messages */
HHOOK cbt_hook; /* CBT hook to track foreground changes */
LPDIDEVICEOBJECTDATA data_queue; /* buffer for 'GetDeviceData'. */
int queue_len; /* valid size of the queue */

View file

@ -61,7 +61,6 @@ struct input_thread_state
UINT devices_count;
HHOOK mouse_ll_hook;
HHOOK keyboard_ll_hook;
HHOOK callwndproc_hook;
RAWINPUTDEVICE rawinput_devices[2];
struct dinput_device *devices[INPUT_THREAD_MAX_DEVICES];
HANDLE events[INPUT_THREAD_MAX_DEVICES];
@ -112,12 +111,21 @@ void dinput_hooks_unacquire_device( IDirectInputDevice8W *iface )
SendMessageW( di_em_win, INPUT_THREAD_NOTIFY, NOTIFY_REFRESH_DEVICES, 0 );
}
static void unhook_device_window_foreground_changes( struct dinput_device *device )
{
if (!device->cbt_hook) return;
UnhookWindowsHookEx( device->cbt_hook );
device->cbt_hook = NULL;
}
static void dinput_device_internal_unacquire( IDirectInputDevice8W *iface, DWORD status )
{
struct dinput_device *impl = impl_from_IDirectInputDevice8W( iface );
TRACE( "iface %p.\n", iface );
unhook_device_window_foreground_changes( impl );
EnterCriticalSection( &impl->crit );
if (impl->status == STATUS_ACQUIRED)
{
@ -198,17 +206,26 @@ static LRESULT CALLBACK cbt_hook_proc( int code, WPARAM wparam, LPARAM lparam )
return CallNextHookEx( 0, code, wparam, lparam );
}
static void hook_device_window_foreground_changes( struct dinput_device *device )
{
DWORD tid, pid;
if (!(tid = GetWindowThreadProcessId( device->win, &pid ))) return;
device->cbt_hook = SetWindowsHookExW( WH_CBT, cbt_hook_proc, DINPUT_instance, tid );
}
static void input_thread_update_device_list( struct input_thread_state *state )
{
RAWINPUTDEVICE rawinput_keyboard = {.usUsagePage = HID_USAGE_PAGE_GENERIC, .usUsage = HID_USAGE_GENERIC_KEYBOARD, .dwFlags = RIDEV_REMOVE};
RAWINPUTDEVICE rawinput_mouse = {.usUsagePage = HID_USAGE_PAGE_GENERIC, .usUsage = HID_USAGE_GENERIC_MOUSE, .dwFlags = RIDEV_REMOVE};
UINT count = 0, keyboard_ll_count = 0, mouse_ll_count = 0, foreground_count = 0;
UINT count = 0, keyboard_ll_count = 0, mouse_ll_count = 0;
struct dinput_device *device;
EnterCriticalSection( &dinput_hook_crit );
LIST_FOR_EACH_ENTRY( device, &acquired_device_list, struct dinput_device, entry )
{
if (device->dwCoopLevel & DISCL_FOREGROUND) foreground_count++;
unhook_device_window_foreground_changes( device );
if (device->dwCoopLevel & DISCL_FOREGROUND) hook_device_window_foreground_changes( device );
if (!device->read_event || !device->vtbl->read) continue;
state->events[count] = device->read_event;
dinput_device_internal_addref( (state->devices[count] = device) );
@ -250,14 +267,6 @@ static void input_thread_update_device_list( struct input_thread_state *state )
state->devices_count = count;
LeaveCriticalSection( &dinput_hook_crit );
if (foreground_count && !state->callwndproc_hook)
state->callwndproc_hook = SetWindowsHookExW( WH_CBT, cbt_hook_proc, DINPUT_instance, 0 );
else if (!foreground_count && state->callwndproc_hook)
{
UnhookWindowsHookEx( state->callwndproc_hook );
state->callwndproc_hook = NULL;
}
if (keyboard_ll_count && !state->keyboard_ll_hook)
state->keyboard_ll_hook = SetWindowsHookExW( WH_KEYBOARD_LL, input_thread_ll_hook_proc, DINPUT_instance, 0 );
else if (!keyboard_ll_count && state->keyboard_ll_hook)
@ -413,7 +422,6 @@ static DWORD WINAPI dinput_thread_proc( void *params )
}
while (state.devices_count--) dinput_device_internal_release( state.devices[state.devices_count] );
if (state.callwndproc_hook) UnhookWindowsHookEx( state.callwndproc_hook );
if (state.keyboard_ll_hook) UnhookWindowsHookEx( state.keyboard_ll_hook );
if (state.mouse_ll_hook) UnhookWindowsHookEx( state.mouse_ll_hook );
DestroyWindow( di_em_win );