Signed-off-by: Rémi Bernon rbernon@codeweavers.com ---
v2: Split the state reading patch, introduce the read event and callback first, and loop on PeekMessageW instead of only calling once, missing messages and causing test timeouts.
dlls/dinput/device_private.h | 6 ++++ dlls/dinput/dinput_main.c | 53 ++++++++++++++++++++++++++++++++---- 2 files changed, 53 insertions(+), 6 deletions(-)
diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h index 1811e0cc5a6..0e72ee77bf1 100644 --- a/dlls/dinput/device_private.h +++ b/dlls/dinput/device_private.h @@ -53,6 +53,8 @@ typedef struct UINT_PTR uAppData; } ActionMap;
+typedef HRESULT dinput_device_read_state( IDirectInputDevice8W *iface ); + /* Device implementation */ typedef struct IDirectInputDeviceImpl IDirectInputDeviceImpl; struct IDirectInputDeviceImpl @@ -84,6 +86,10 @@ struct IDirectInputDeviceImpl /* Action mapping */ int num_actions; /* number of actions mapped */ ActionMap *action_map; /* array of mappings */ + + /* internal device file reading */ + HANDLE read_event; + dinput_device_read_state *read_callback; };
extern HRESULT direct_input_device_alloc( SIZE_T size, const IDirectInputDevice8WVtbl *vtbl, const GUID *guid, diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c index 88ee1855675..1cd6d390430 100644 --- a/dlls/dinput/dinput_main.c +++ b/dlls/dinput/dinput_main.c @@ -1289,6 +1289,12 @@ static LRESULT CALLBACK callwndproc_proc( int code, WPARAM wparam, LPARAM lparam static DWORD WINAPI hook_thread_proc(void *param) { static HHOOK kbd_hook, mouse_hook; + IDirectInputDeviceImpl *impl; + IDirectInputDevice8W *iface; + SIZE_T events_count = 0; + HANDLE finished_event; + HANDLE events[128]; + DWORD ret; MSG msg;
di_em_win = CreateWindowW( di_em_win_w, di_em_win_w, 0, 0, 0, 0, 0, @@ -1298,13 +1304,42 @@ static DWORD WINAPI hook_thread_proc(void *param) PeekMessageW( &msg, 0, 0, 0, PM_NOREMOVE ); SetEvent(param);
- while (GetMessageW( &msg, 0, 0, 0 )) + while ((ret = MsgWaitForMultipleObjectsEx( events_count, events, INFINITE, QS_ALLINPUT, 0 )) <= events_count) { UINT kbd_cnt = 0, mice_cnt = 0;
- if (msg.message == WM_USER+0x10) + if (ret < events_count) { - HANDLE finished_event = (HANDLE)msg.lParam; + iface = NULL; + EnterCriticalSection( &dinput_hook_crit ); + LIST_FOR_EACH_ENTRY( impl, &acquired_device_list, IDirectInputDeviceImpl, entry ) + { + if (impl->read_event == events[ret]) + { + iface = &impl->IDirectInputDevice8W_iface; + IDirectInputDevice8_AddRef( iface ); + break; + } + } + LeaveCriticalSection( &dinput_hook_crit ); + + if (iface) + { + impl->read_callback( iface ); + IDirectInputDevice8_Release( iface ); + } + } + + while (PeekMessageW( &msg, 0, 0, 0, PM_REMOVE )) + { + if (msg.message != WM_USER+0x10) + { + TranslateMessage(&msg); + DispatchMessageW(&msg); + continue; + } + + finished_event = (HANDLE)msg.lParam;
TRACE( "Processing hook change notification wp:%ld lp:%#lx\n", msg.wParam, msg.lParam );
@@ -1313,12 +1348,19 @@ static DWORD WINAPI hook_thread_proc(void *param) if (kbd_hook) UnhookWindowsHookEx( kbd_hook ); if (mouse_hook) UnhookWindowsHookEx( mouse_hook ); kbd_hook = mouse_hook = NULL; - break; + goto done; }
+ events_count = 0; EnterCriticalSection( &dinput_hook_crit ); kbd_cnt = list_count( &acquired_keyboard_list ); mice_cnt = list_count( &acquired_mouse_list ); + LIST_FOR_EACH_ENTRY( impl, &acquired_device_list, IDirectInputDeviceImpl, entry ) + { + if (!impl->read_event || !impl->read_callback) continue; + if (events_count >= ARRAY_SIZE(events)) break; + events[events_count++] = impl->read_event; + } LeaveCriticalSection( &dinput_hook_crit );
if (kbd_cnt && !kbd_hook) @@ -1340,10 +1382,9 @@ static DWORD WINAPI hook_thread_proc(void *param) if (finished_event) SetEvent(finished_event); } - TranslateMessage(&msg); - DispatchMessageW(&msg); }
+done: DestroyWindow( di_em_win ); di_em_win = NULL;