From: Rémi Bernon rbernon@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=54431 --- dlls/dinput/dinput_main.c | 52 +++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 21 deletions(-)
diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c index 149dd402aa8..6ea6338fd99 100644 --- a/dlls/dinput/dinput_main.c +++ b/dlls/dinput/dinput_main.c @@ -163,40 +163,50 @@ static void dinput_unacquire_window_devices( HWND window )
LIST_FOR_EACH_ENTRY_SAFE( impl, next, &acquired_device_list, struct dinput_device, entry ) { - if (!window || window == impl->win) - { - TRACE( "%p window is not foreground - unacquiring %p\n", impl->win, impl ); - dinput_device_internal_unacquire( &impl->IDirectInputDevice8W_iface, STATUS_UNACQUIRED ); - } + if (window != impl->win) continue; + TRACE( "%p window is not foreground - unacquiring %p\n", impl->win, impl ); + dinput_device_internal_unacquire( &impl->IDirectInputDevice8W_iface, STATUS_UNACQUIRED ); } LIST_FOR_EACH_ENTRY_SAFE( impl, next, &acquired_mouse_list, struct dinput_device, entry ) { - if (!window || window == impl->win) - { - TRACE( "%p window is not foreground - unacquiring %p\n", impl->win, impl ); - dinput_device_internal_unacquire( &impl->IDirectInputDevice8W_iface, STATUS_UNACQUIRED ); - } + if (window != impl->win) continue; + TRACE( "%p window is not foreground - unacquiring %p\n", impl->win, impl ); + dinput_device_internal_unacquire( &impl->IDirectInputDevice8W_iface, STATUS_UNACQUIRED ); } LIST_FOR_EACH_ENTRY_SAFE( impl, next, &acquired_rawmouse_list, struct dinput_device, entry ) { - if (!window || window == impl->win) - { - TRACE( "%p window is not foreground - unacquiring %p\n", impl->win, impl ); - dinput_device_internal_unacquire( &impl->IDirectInputDevice8W_iface, STATUS_UNACQUIRED ); - } + if (window != impl->win) continue; + TRACE( "%p window is not foreground - unacquiring %p\n", impl->win, impl ); + dinput_device_internal_unacquire( &impl->IDirectInputDevice8W_iface, STATUS_UNACQUIRED ); } LIST_FOR_EACH_ENTRY_SAFE( impl, next, &acquired_keyboard_list, struct dinput_device, entry ) { - if (!window || window == impl->win) - { - TRACE( "%p window is not foreground - unacquiring %p\n", impl->win, impl ); - dinput_device_internal_unacquire( &impl->IDirectInputDevice8W_iface, STATUS_UNACQUIRED ); - } + if (window != impl->win) continue; + TRACE( "%p window is not foreground - unacquiring %p\n", impl->win, impl ); + dinput_device_internal_unacquire( &impl->IDirectInputDevice8W_iface, STATUS_UNACQUIRED ); }
LeaveCriticalSection( &dinput_hook_crit ); }
+static void dinput_unacquire_devices(void) +{ + struct dinput_device *impl, *next; + + EnterCriticalSection( &dinput_hook_crit ); + + LIST_FOR_EACH_ENTRY_SAFE( impl, next, &acquired_device_list, struct dinput_device, entry ) + dinput_device_internal_unacquire( &impl->IDirectInputDevice8W_iface, STATUS_UNACQUIRED ); + LIST_FOR_EACH_ENTRY_SAFE( impl, next, &acquired_mouse_list, struct dinput_device, entry ) + dinput_device_internal_unacquire( &impl->IDirectInputDevice8W_iface, STATUS_UNACQUIRED ); + LIST_FOR_EACH_ENTRY_SAFE( impl, next, &acquired_rawmouse_list, struct dinput_device, entry ) + dinput_device_internal_unacquire( &impl->IDirectInputDevice8W_iface, STATUS_UNACQUIRED ); + LIST_FOR_EACH_ENTRY_SAFE( impl, next, &acquired_keyboard_list, struct dinput_device, entry ) + dinput_device_internal_unacquire( &impl->IDirectInputDevice8W_iface, STATUS_UNACQUIRED ); + + LeaveCriticalSection( &dinput_hook_crit ); +} + static LRESULT CALLBACK callwndproc_proc( int code, WPARAM wparam, LPARAM lparam ) { CWPSTRUCT *msg = (CWPSTRUCT *)lparam; @@ -390,7 +400,7 @@ static DWORD WINAPI dinput_thread_proc( void *params ) if (state.running) { ERR( "Unexpected termination, ret %#lx\n", ret ); - dinput_unacquire_window_devices( 0 ); + dinput_unacquire_devices(); }
while (state.devices_count--) dinput_device_internal_release( state.devices[state.devices_count] );
From: Rémi Bernon rbernon@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=54431 --- dlls/dinput/dinput_main.c | 58 ++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 35 deletions(-)
diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c index 6ea6338fd99..6b70cfbc5d9 100644 --- a/dlls/dinput/dinput_main.c +++ b/dlls/dinput/dinput_main.c @@ -56,7 +56,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]; @@ -155,7 +154,7 @@ static LRESULT CALLBACK input_thread_ll_hook_proc( int code, WPARAM wparam, LPAR return skip ? 1 : CallNextHookEx( 0, code, wparam, lparam ); }
-static void dinput_unacquire_window_devices( HWND window ) +static void dinput_unacquire_foreground_devices( HWND foreground ) { struct dinput_device *impl, *next;
@@ -163,25 +162,25 @@ static void dinput_unacquire_window_devices( HWND window )
LIST_FOR_EACH_ENTRY_SAFE( impl, next, &acquired_device_list, struct dinput_device, entry ) { - if (window != impl->win) continue; + if (!(impl->dwCoopLevel & DISCL_FOREGROUND) || impl->win == foreground) continue; TRACE( "%p window is not foreground - unacquiring %p\n", impl->win, impl ); dinput_device_internal_unacquire( &impl->IDirectInputDevice8W_iface, STATUS_UNACQUIRED ); } LIST_FOR_EACH_ENTRY_SAFE( impl, next, &acquired_mouse_list, struct dinput_device, entry ) { - if (window != impl->win) continue; + if (!(impl->dwCoopLevel & DISCL_FOREGROUND) || impl->win == foreground) continue; TRACE( "%p window is not foreground - unacquiring %p\n", impl->win, impl ); dinput_device_internal_unacquire( &impl->IDirectInputDevice8W_iface, STATUS_UNACQUIRED ); } LIST_FOR_EACH_ENTRY_SAFE( impl, next, &acquired_rawmouse_list, struct dinput_device, entry ) { - if (window != impl->win) continue; + if (!(impl->dwCoopLevel & DISCL_FOREGROUND) || impl->win == foreground) continue; TRACE( "%p window is not foreground - unacquiring %p\n", impl->win, impl ); dinput_device_internal_unacquire( &impl->IDirectInputDevice8W_iface, STATUS_UNACQUIRED ); } LIST_FOR_EACH_ENTRY_SAFE( impl, next, &acquired_keyboard_list, struct dinput_device, entry ) { - if (window != impl->win) continue; + if (!(impl->dwCoopLevel & DISCL_FOREGROUND) || impl->win == foreground) continue; TRACE( "%p window is not foreground - unacquiring %p\n", impl->win, impl ); dinput_device_internal_unacquire( &impl->IDirectInputDevice8W_iface, STATUS_UNACQUIRED ); } @@ -207,29 +206,16 @@ static void dinput_unacquire_devices(void) LeaveCriticalSection( &dinput_hook_crit ); }
-static LRESULT CALLBACK callwndproc_proc( int code, WPARAM wparam, LPARAM lparam ) -{ - CWPSTRUCT *msg = (CWPSTRUCT *)lparam; - - if (code != HC_ACTION || (msg->message != WM_KILLFOCUS && - msg->message != WM_ACTIVATEAPP && msg->message != WM_ACTIVATE)) - return CallNextHookEx( 0, code, wparam, lparam ); - - if (msg->hwnd != GetForegroundWindow()) dinput_unacquire_window_devices( msg->hwnd ); - - return CallNextHookEx( 0, code, wparam, lparam ); -} - static void input_thread_update_device_list( struct input_thread_state *state ) { RAWINPUTDEVICE rawinput_mouse = {.usUsagePage = HID_USAGE_PAGE_GENERIC, .usUsage = HID_USAGE_GENERIC_MOUSE, .dwFlags = RIDEV_REMOVE}; - UINT count = 0, keyboard_count = 0, mouse_count = 0, foreground_count = 0; + UINT count = 0, keyboard_count = 0, mouse_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++; if (!device->read_event || !device->vtbl->read) continue; state->events[count] = device->read_event; dinput_device_internal_addref( (state->devices[count] = device) ); @@ -239,7 +225,6 @@ static void input_thread_update_device_list( struct input_thread_state *state )
LIST_FOR_EACH_ENTRY( device, &acquired_rawmouse_list, struct dinput_device, entry ) { - if (device->dwCoopLevel & DISCL_FOREGROUND) foreground_count++; if (device->dwCoopLevel & DISCL_BACKGROUND) rawinput_mouse.dwFlags |= RIDEV_INPUTSINK; if (device->dwCoopLevel & DISCL_EXCLUSIVE) rawinput_mouse.dwFlags |= RIDEV_NOLEGACY | RIDEV_CAPTUREMOUSE; rawinput_mouse.dwFlags &= ~RIDEV_REMOVE; @@ -249,25 +234,15 @@ static void input_thread_update_device_list( struct input_thread_state *state ) } LIST_FOR_EACH_ENTRY( device, &acquired_mouse_list, struct dinput_device, entry ) { - if (device->dwCoopLevel & DISCL_FOREGROUND) foreground_count++; mouse_count++; } LIST_FOR_EACH_ENTRY( device, &acquired_keyboard_list, struct dinput_device, entry ) { - if (device->dwCoopLevel & DISCL_FOREGROUND) foreground_count++; keyboard_count++; } state->devices_count = count; LeaveCriticalSection( &dinput_hook_crit );
- if (foreground_count && !state->callwndproc_hook) - state->callwndproc_hook = SetWindowsHookExW( WH_CALLWNDPROC, callwndproc_proc, DINPUT_instance, GetCurrentThreadId() ); - else if (!foreground_count && state->callwndproc_hook) - { - UnhookWindowsHookEx( state->callwndproc_hook ); - state->callwndproc_hook = NULL; - } - if (keyboard_count && !state->keyboard_ll_hook) state->keyboard_ll_hook = SetWindowsHookExW( WH_KEYBOARD_LL, input_thread_ll_hook_proc, DINPUT_instance, 0 ); else if (!keyboard_count && state->keyboard_ll_hook) @@ -364,17 +339,31 @@ static void unregister_di_em_win_class(void) static DWORD WINAPI dinput_thread_proc( void *params ) { struct input_thread_state state = {.running = TRUE}; + HWND last_foreground = GetForegroundWindow(); + DWORD ret, ticks, last_ticks = 0; struct dinput_device *device; HANDLE start_event = params; - DWORD ret; MSG msg;
di_em_win = CreateWindowW( L"DIEmWin", L"DIEmWin", 0, 0, 0, 0, 0, HWND_MESSAGE, 0, DINPUT_instance, NULL ); input_thread_state = &state; SetEvent( start_event );
- while (state.running && (ret = MsgWaitForMultipleObjectsEx( state.events_count, state.events, INFINITE, QS_ALLINPUT, 0 )) <= state.events_count) + while (state.running) { + ret = MsgWaitForMultipleObjectsEx( state.events_count, state.events, 100, QS_ALLINPUT, 0 ); + + if (last_ticks + 100 < (ticks = GetTickCount())) + { + HWND foreground = GetForegroundWindow(); + if (foreground && last_foreground != foreground) + dinput_unacquire_foreground_devices( foreground ); + last_foreground = foreground; + last_ticks = ticks; + } + + if (ret == WAIT_TIMEOUT) continue; + if (ret > state.events_count) break; if (ret < state.events_count) { if ((device = state.devices[ret]) && FAILED( device->vtbl->read( &device->IDirectInputDevice8W_iface ) )) @@ -404,7 +393,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 );