From deb74efc04b52d5a8dfb747b4b683d7fd7e6f3a6 Mon Sep 17 00:00:00 2001 From: Vitaliy Margolen Date: Fri, 6 Jul 2007 23:36:30 -0600 Subject: [PATCH] dinput: Handle multiple keyboard and mouse devices. --- dlls/dinput/device_private.h | 1 + dlls/dinput/dinput_main.c | 89 ++++++++++++++++++++++++++---------- dlls/dinput/dinput_private.h | 1 + dlls/dinput/keyboard.c | 38 ++++----------- dlls/dinput/mouse.c | 25 ++-------- 5 files changed, 79 insertions(+), 75 deletions(-) diff --git a/dlls/dinput/device_private.h b/dlls/dinput/device_private.h index 6d874d4cdf..27bccc778b 100644 --- a/dlls/dinput/device_private.h +++ b/dlls/dinput/device_private.h @@ -61,6 +61,7 @@ struct IDirectInputDevice2AImpl DWORD dwCoopLevel; HWND win; int acquired; + DI_EVENT_PROC event_proc; /* function to receive mouse & keyboard events */ LPDIDEVICEOBJECTDATA data_queue; /* buffer for 'GetDeviceData'. */ int queue_len; /* size of the queue - set in 'SetProperty' */ diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c index 2399f2c781..b723de389c 100644 --- a/dlls/dinput/dinput_main.c +++ b/dlls/dinput/dinput_main.c @@ -678,50 +678,89 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) * DInput hook thread */ +static LRESULT CALLBACK LL_hook_proc( int code, WPARAM wparam, LPARAM lparam ) +{ + IDirectInputImpl *dinput; + + if (code != HC_ACTION) return CallNextHookEx( 0, code, wparam, lparam ); + + EnterCriticalSection( &dinput_hook_crit ); + LIST_FOR_EACH_ENTRY( dinput, &direct_input_list, IDirectInputImpl, entry ) + { + IDirectInputDevice2AImpl *dev; + + EnterCriticalSection( &dinput->crit ); + LIST_FOR_EACH_ENTRY( dev, &dinput->devices_list, IDirectInputDevice2AImpl, entry ) + if (dev->acquired && dev->event_proc) + { + TRACE("calling %p->%p (%lx %lx)\n", dev, dev->event_proc, wparam, lparam); + dev->event_proc( (LPDIRECTINPUTDEVICE8A)dev, wparam, lparam ); + } + LeaveCriticalSection( &dinput->crit ); + } + LeaveCriticalSection( &dinput_hook_crit ); + + return CallNextHookEx( 0, code, wparam, lparam ); +} + static LRESULT CALLBACK dinput_hook_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { static HHOOK kbd_hook, mouse_hook; - BOOL res; + UINT kbd_cnt = 0, mice_cnt = 0; TRACE("got message %x %p %p\n", message, (LPVOID)wParam, (LPVOID)lParam); switch (message) { case WM_USER+0x10: - if (wParam == WH_KEYBOARD_LL) { - if (lParam) + IDirectInputImpl *dinput; + + if (!wParam && !lParam) { - if (kbd_hook) return 0; - kbd_hook = SetWindowsHookExW(WH_KEYBOARD_LL, (LPVOID)lParam, DINPUT_instance, 0); - return (LRESULT)kbd_hook; + DestroyWindow( hWnd ); + return 0; } - else + + EnterCriticalSection( &dinput_hook_crit ); + + /* Count acquired keyboards and mice*/ + LIST_FOR_EACH_ENTRY( dinput, &direct_input_list, IDirectInputImpl, entry ) { - if (!kbd_hook) return 0; - res = UnhookWindowsHookEx(kbd_hook); - kbd_hook = NULL; - return res; + IDirectInputDevice2AImpl *dev; + + EnterCriticalSection( &dinput->crit ); + LIST_FOR_EACH_ENTRY( dev, &dinput->devices_list, IDirectInputDevice2AImpl, entry ) + { + if (!dev->acquired) continue; + + if (IsEqualGUID( &dev->guid, &GUID_SysKeyboard ) || + IsEqualGUID( &dev->guid, &DInput_Wine_Keyboard_GUID )) + kbd_cnt++; + else + if (IsEqualGUID( &dev->guid, &GUID_SysMouse ) || + IsEqualGUID( &dev->guid, &DInput_Wine_Mouse_GUID )) + mice_cnt++; + } + LeaveCriticalSection( &dinput->crit ); } - } - else if (wParam == WH_MOUSE_LL) - { - if (lParam) + LeaveCriticalSection( &dinput_hook_crit ); + + if (kbd_cnt && !kbd_hook) + kbd_hook = SetWindowsHookExW( WH_KEYBOARD_LL, LL_hook_proc, DINPUT_instance, 0 ); + else if (!kbd_cnt && kbd_hook) { - if (mouse_hook) return 0; - mouse_hook = SetWindowsHookExW(WH_MOUSE_LL, (LPVOID)lParam, DINPUT_instance, 0); - return (LRESULT)mouse_hook; + UnhookWindowsHookEx( kbd_hook ); + kbd_hook = NULL; } - else + + if (mice_cnt && !mouse_hook) + mouse_hook = SetWindowsHookExW( WH_MOUSE_LL, LL_hook_proc, DINPUT_instance, 0 ); + else if (!mice_cnt && mouse_hook) { - if (!mouse_hook) return 0; - res = UnhookWindowsHookEx(mouse_hook); + UnhookWindowsHookEx( mouse_hook ); mouse_hook = NULL; - return res; } } - else if (!wParam && !lParam) - DestroyWindow(hWnd); - return 0; case WM_DESTROY: diff --git a/dlls/dinput/dinput_private.h b/dlls/dinput/dinput_private.h index a5b74dc9e4..4bce692d88 100644 --- a/dlls/dinput/dinput_private.h +++ b/dlls/dinput/dinput_private.h @@ -58,5 +58,6 @@ extern const struct dinput_device joystick_linuxinput_device; extern HINSTANCE DINPUT_instance; extern HHOOK set_dinput_hook(int hook_id, LPVOID proc); +typedef void (*DI_EVENT_PROC)(LPDIRECTINPUTDEVICE8A, WPARAM, LPARAM); #endif /* __WINE_DLLS_DINPUT_DINPUT_PRIVATE_H */ diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c index 0c5aef0173..745ab7f4af 100644 --- a/dlls/dinput/keyboard.c +++ b/dlls/dinput/keyboard.c @@ -50,26 +50,19 @@ struct SysKeyboardImpl BYTE DInputKeyState[WINE_DINPUT_KEYBOARD_MAX_KEYS]; }; -static SysKeyboardImpl* current_lock = NULL; -/* Today's acquired device - * FIXME: currently this can be only one. - * Maybe this should be a linked list or st. - * I don't know what the rules are for multiple acquired keyboards, - * but 'DI_LOSTFOCUS' and 'DI_UNACQUIRED' exist for a reason. -*/ - -static LRESULT CALLBACK KeyboardCallback( int code, WPARAM wparam, LPARAM lparam ) +static void KeyboardCallback( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM lparam ) { - SysKeyboardImpl *This = (SysKeyboardImpl *)current_lock; + SysKeyboardImpl *This = (SysKeyboardImpl *)iface; int dik_code; KBDLLHOOKSTRUCT *hook = (KBDLLHOOKSTRUCT *)lparam; BYTE new_diks; - TRACE("(%d,%ld,%ld)\n", code, wparam, lparam); + if (wparam != WM_KEYDOWN && wparam != WM_KEYUP && + wparam != WM_SYSKEYDOWN && wparam != WM_SYSKEYUP) + return; + + TRACE("(%p) %ld,%ld\n", iface, wparam, lparam); - /* returns now if not HC_ACTION */ - if (code != HC_ACTION) return CallNextHookEx(0, code, wparam, lparam); - dik_code = hook->scanCode & 0xff; if (hook->flags & LLKHF_EXTENDED) dik_code |= 0x80; @@ -77,7 +70,7 @@ static LRESULT CALLBACK KeyboardCallback( int code, WPARAM wparam, LPARAM lparam /* returns now if key event already known */ if (new_diks == This->DInputKeyState[dik_code]) - return CallNextHookEx(0, code, wparam, lparam); + return; This->DInputKeyState[dik_code] = new_diks; TRACE(" setting %02X to %02X\n", dik_code, This->DInputKeyState[dik_code]); @@ -86,8 +79,6 @@ static LRESULT CALLBACK KeyboardCallback( int code, WPARAM wparam, LPARAM lparam EnterCriticalSection(&This->base.crit); queue_event((LPDIRECTINPUTDEVICE8A)This, dik_code, new_diks, hook->time, This->base.dinput->evsequence++); LeaveCriticalSection(&This->base.crit); - - return CallNextHookEx(0, code, wparam, lparam); } const GUID DInput_Wine_Keyboard_GUID = { /* 0ab8648a-7735-11d2-8c73-71df54a96441 */ @@ -189,6 +180,7 @@ static SysKeyboardImpl *alloc_device(REFGUID rguid, const void *kvt, IDirectInpu newDevice->base.ref = 1; memcpy(&newDevice->base.guid, rguid, sizeof(*rguid)); newDevice->base.dinput = dinput; + newDevice->base.event_proc = KeyboardCallback; InitializeCriticalSection(&newDevice->base.crit); newDevice->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SysKeyboardImpl*->base.crit"); @@ -306,12 +298,6 @@ static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface) if ((res = IDirectInputDevice2AImpl_Acquire(iface)) != DI_OK) return res; - if (current_lock != NULL) { - FIXME("Not more than one keyboard can be acquired at the same time.\n"); - SysKeyboardAImpl_Unacquire((LPDIRECTINPUTDEVICE8A)current_lock); - } - current_lock = This; - set_dinput_hook(WH_KEYBOARD_LL, KeyboardCallback); return DI_OK; @@ -328,12 +314,6 @@ static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface) set_dinput_hook(WH_KEYBOARD_LL, NULL); - /* No more locks */ - if (current_lock == This) - current_lock = NULL; - else - ERR("this != current_lock\n"); - return DI_OK; } diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c index df04ee54b7..0e9a349d19 100644 --- a/dlls/dinput/mouse.c +++ b/dlls/dinput/mouse.c @@ -68,8 +68,7 @@ struct SysMouseImpl DIMOUSESTATE2 m_state; }; -/* FIXME: This is ugly and not thread safe :/ */ -static IDirectInputDevice8A* current_lock = NULL; +static void dinput_mouse_hook( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM lparam ); const GUID DInput_Wine_Mouse_GUID = { /* 9e573ed8-7734-11d2-8d4a-23903fb6bdf7 */ 0x9e573ed8, 0x7734, 0x11d2, {0x8d, 0x4a, 0x23, 0x90, 0x3f, 0xb6, 0xbd, 0xf7} @@ -174,6 +173,7 @@ static SysMouseImpl *alloc_device(REFGUID rguid, const void *mvt, IDirectInputIm InitializeCriticalSection(&newDevice->base.crit); newDevice->base.crit.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": SysMouseImpl*->base.crit"); newDevice->base.dinput = dinput; + newDevice->base.event_proc = dinput_mouse_hook; /* Create copy of default data format */ if (!(df = HeapAlloc(GetProcessHeap(), 0, c_dfDIMouse2.dwSize))) goto failed; @@ -252,15 +252,13 @@ const struct dinput_device mouse_device = { */ /* low-level mouse hook */ -static LRESULT CALLBACK dinput_mouse_hook( int code, WPARAM wparam, LPARAM lparam ) +static void dinput_mouse_hook( LPDIRECTINPUTDEVICE8A iface, WPARAM wparam, LPARAM lparam ) { MSLLHOOKSTRUCT *hook = (MSLLHOOKSTRUCT *)lparam; - SysMouseImpl* This = (SysMouseImpl*) current_lock; + SysMouseImpl* This = (SysMouseImpl*) iface; DWORD dwCoop; int wdata = 0, inst_id = -1; - if (code != HC_ACTION) return CallNextHookEx( 0, code, wparam, lparam ); - EnterCriticalSection(&This->base.crit); dwCoop = This->base.dwCoopLevel; @@ -345,12 +343,6 @@ static LRESULT CALLBACK dinput_mouse_hook( int code, WPARAM wparam, LPARAM lpara wdata, hook->time, This->base.dinput->evsequence++); LeaveCriticalSection(&This->base.crit); - - /* Ignore message */ - if (dwCoop & DISCL_EXCLUSIVE) return 1; - - /* Pass the events down to previous handlers (e.g. win32 input) */ - return CallNextHookEx( 0, code, wparam, lparam ); } static BOOL dinput_window_check(SysMouseImpl* This) { @@ -387,9 +379,6 @@ static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface) if ((res = IDirectInputDevice2AImpl_Acquire(iface)) != DI_OK) return res; - /* Store (in a global variable) the current lock */ - current_lock = (IDirectInputDevice8A*)This; - /* Init the mouse state */ GetCursorPos( &point ); if (This->base.data_format.user_df->dwFlags & DIDF_ABSAXIS) @@ -448,12 +437,6 @@ static HRESULT WINAPI SysMouseAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface) if (This->base.dwCoopLevel & DISCL_EXCLUSIVE) ShowCursor(TRUE); /* show cursor */ - /* No more locks */ - if (current_lock == (IDirectInputDevice8A*) This) - current_lock = NULL; - else - ERR("this(%p) != current_lock(%p)\n", This, current_lock); - /* And put the mouse cursor back where it was at acquire time */ if (This->base.dwCoopLevel & DISCL_EXCLUSIVE) { -- 2.32.0.93.g670b81a890