From 97d848aa1980e51e55d78f8b4b89f61f7d3fb60c Mon Sep 17 00:00:00 2001 From: Raphael Junqueira Date: Thu, 24 Mar 2005 15:08:27 +0000 Subject: [PATCH] - use WINE_DINPUT_KEYBOARD_MAX_KEYS instead hard-coded 256 value - better use of critical section - some cleanup to better understand code paths - logic correction on SetWindowsHookExA/UnhookWindowsHookEx on keyboard. --- dlls/dinput/keyboard.c | 202 ++++++++++++++++++++++------------------- dlls/dinput/mouse.c | 149 +++++++++++++++--------------- 2 files changed, 184 insertions(+), 167 deletions(-) diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c index ceee1f591d4..1114d5f8727 100644 --- a/dlls/dinput/keyboard.c +++ b/dlls/dinput/keyboard.c @@ -3,6 +3,7 @@ * Copyright 1998 Marcus Meissner * Copyright 1998,1999 Lionel Ulmer * Copyright 2000-2001 TransGaming Technologies Inc. + * Copyright 2005 Raphael Junqueira * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -37,6 +38,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(dinput); +#define WINE_DINPUT_KEYBOARD_MAX_KEYS 256 + static IDirectInputDevice8AVtbl SysKeyboardAvt; static IDirectInputDevice8WVtbl SysKeyboardWvt; @@ -65,14 +68,15 @@ struct SysKeyboardImpl CRITICAL_SECTION crit; }; -SysKeyboardImpl *current; /* 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 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 BYTE DInputKeyState[256]; /* array for 'GetDeviceState' */ +static BYTE DInputKeyState[WINE_DINPUT_KEYBOARD_MAX_KEYS]; /* array for 'GetDeviceState' */ static CRITICAL_SECTION keyboard_crit; static CRITICAL_SECTION_DEBUG critsect_debug = @@ -83,64 +87,63 @@ static CRITICAL_SECTION_DEBUG critsect_debug = }; static CRITICAL_SECTION keyboard_crit = { &critsect_debug, -1, 0, 0, 0, 0 }; -static DWORD keyboard_users; -static HHOOK keyboard_hook; +static DWORD keyboard_users = 0; +static HHOOK keyboard_hook = NULL; LRESULT CALLBACK KeyboardCallback( int code, WPARAM wparam, LPARAM lparam ) { + BYTE dik_code; + BOOL down; + DWORD timestamp; + KBDLLHOOKSTRUCT *hook = (KBDLLHOOKSTRUCT *)lparam; + BYTE new_diks; + TRACE("(%d,%d,%ld)\n", code, wparam, lparam); - if (code == HC_ACTION) - { - BYTE dik_code; - BOOL down; - DWORD timestamp; + /** returns now if not HC_ACTION */ + if (code != HC_ACTION) return CallNextHookEx(keyboard_hook, code, wparam, lparam); + + { + dik_code = hook->scanCode; + if (hook->flags & LLKHF_EXTENDED) dik_code |= 0x80; + down = !(hook->flags & LLKHF_UP); + timestamp = hook->time; + } + + /** returns now if key event already known */ + new_diks = (down ? 0x80 : 0); + /*if (new_diks != DInputKeyState[dik_code]) return CallNextHookEx(keyboard_hook, code, wparam, lparam); TO BE FIXED */ + + DInputKeyState[dik_code] = new_diks; + TRACE(" setting %02X to %02X\n", dik_code, DInputKeyState[dik_code]); - { - KBDLLHOOKSTRUCT *hook = (KBDLLHOOKSTRUCT *)lparam; - dik_code = hook->scanCode; - if (hook->flags & LLKHF_EXTENDED) dik_code |= 0x80; - down = !(hook->flags & LLKHF_UP); - timestamp = hook->time; - } - - DInputKeyState[dik_code] = (down ? 0x80 : 0); - TRACE(" setting %02X to %02X\n", dik_code, DInputKeyState[dik_code]); + if (current_lock != NULL) { + if (current_lock->hEvent) SetEvent(current_lock->hEvent); + + if (current_lock->buffer != NULL) { + int n; - if (current != NULL) - { - if (current->hEvent) - SetEvent(current->hEvent); - - if (current->buffer != NULL) - { - int n; - - EnterCriticalSection(&(current->crit)); - - n = (current->start + current->count) % current->buffersize; - - current->buffer[n].dwOfs = dik_code; - current->buffer[n].dwData = down ? 0x80 : 0; - current->buffer[n].dwTimeStamp = timestamp; - current->buffer[n].dwSequence = current->dinput->evsequence++; - - TRACE("Adding event at offset %d : %ld - %ld - %ld - %ld\n", n, - current->buffer[n].dwOfs, current->buffer[n].dwData, current->buffer[n].dwTimeStamp, current->buffer[n].dwSequence); - - if (current->count == current->buffersize) - { - current->start = ++current->start % current->buffersize; - current->overflow = TRUE; - } - else - current->count++; - - LeaveCriticalSection(&(current->crit)); - } - } + EnterCriticalSection(&(current_lock->crit)); + + n = (current_lock->start + current_lock->count) % current_lock->buffersize; + + current_lock->buffer[n].dwOfs = dik_code; + current_lock->buffer[n].dwData = down ? 0x80 : 0; + current_lock->buffer[n].dwTimeStamp = timestamp; + current_lock->buffer[n].dwSequence = current_lock->dinput->evsequence++; + + TRACE("Adding event at offset %d : %ld - %ld - %ld - %ld\n", n, + current_lock->buffer[n].dwOfs, current_lock->buffer[n].dwData, current_lock->buffer[n].dwTimeStamp, current_lock->buffer[n].dwSequence); + + if (current_lock->count == current_lock->buffersize) { + current_lock->start = ++current_lock->start % current_lock->buffersize; + current_lock->overflow = TRUE; + } else + current_lock->count++; + + LeaveCriticalSection(&(current_lock->crit)); } - + } return CallNextHookEx(keyboard_hook, code, wparam, lparam); } @@ -238,15 +241,20 @@ static BOOL keyboarddev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEI static SysKeyboardImpl *alloc_device(REFGUID rguid, LPVOID kvt, IDirectInputImpl *dinput) { SysKeyboardImpl* newDevice; + DWORD kbd_users; + newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboardImpl)); newDevice->lpVtbl = kvt; newDevice->ref = 1; memcpy(&(newDevice->guid),rguid,sizeof(*rguid)); newDevice->dinput = dinput; + InitializeCriticalSection(&(newDevice->crit)); EnterCriticalSection(&keyboard_crit); - if (!keyboard_users++) - keyboard_hook = SetWindowsHookExW( WH_KEYBOARD_LL, KeyboardCallback, DINPUT_instance, 0 ); + kbd_users = InterlockedIncrement(&keyboard_users); + if (1 == kbd_users) { + keyboard_hook = SetWindowsHookExW( WH_KEYBOARD_LL, KeyboardCallback, DINPUT_instance, 0 ); + } LeaveCriticalSection(&keyboard_crit); return newDevice; @@ -301,13 +309,15 @@ static ULONG WINAPI SysKeyboardAImpl_Release(LPDIRECTINPUTDEVICE8A iface) { SysKeyboardImpl *This = (SysKeyboardImpl *)iface; ULONG ref; + DWORD kbd_users; ref = InterlockedDecrement(&(This->ref)); if (ref) return ref; - EnterCriticalSection(&keyboard_crit); - if (!--keyboard_users) { + EnterCriticalSection(&keyboard_crit); + kbd_users = InterlockedDecrement(&keyboard_users); + if (0 == kbd_users) { UnhookWindowsHookEx( keyboard_hook ); keyboard_hook = 0; } @@ -388,24 +398,29 @@ static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState( LPDIRECTINPUTDEVICE8A iface,DWORD len,LPVOID ptr ) { - TRACE("(%p)->(%ld,%p)\n", iface, len, ptr); + SysKeyboardImpl *This = (SysKeyboardImpl *)iface; + TRACE("(%p)->(%ld,%p)\n", This, len, ptr); /* Note: device does not need to be acquired */ - if (len != 256) + if (len != WINE_DINPUT_KEYBOARD_MAX_KEYS) return DIERR_INVALIDPARAM; MsgWaitForMultipleObjectsEx(0, NULL, 0, QS_ALLINPUT, 0); + EnterCriticalSection(&(This->crit)); + if (TRACE_ON(dinput)) { int i; - for (i = 0; i < 256; i++) { + for (i = 0; i < WINE_DINPUT_KEYBOARD_MAX_KEYS; i++) { if (DInputKeyState[i] != 0x00) { TRACE(" - %02X: %02x\n", i, DInputKeyState[i]); } } } - memcpy(ptr, DInputKeyState, 256); + memcpy(ptr, DInputKeyState, WINE_DINPUT_KEYBOARD_MAX_KEYS); + LeaveCriticalSection(&(This->crit)); + return DI_OK; } @@ -490,7 +505,7 @@ static HRESULT WINAPI SysKeyboardAImpl_EnumObjects( memset(&ddoi, 0, sizeof(ddoi)); ddoi.dwSize = FIELD_OFFSET(DIDEVICEOBJECTINSTANCEA, dwFFMaxForce); - for (i = 0; i < 256; i++) { + for (i = 0; i < WINE_DINPUT_KEYBOARD_MAX_KEYS; i++) { /* Report 255 keys :-) */ ddoi.guidType = GUID_Key; ddoi.dwOfs = i; @@ -531,25 +546,24 @@ static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface) This->acquired = 1; - if (current != NULL) - { - FIXME("Not more than one keyboard can be acquired at the same time.\n"); - SysKeyboardAImpl_Unacquire(iface); - } + if (current_lock != NULL) { + FIXME("Not more than one keyboard can be acquired at the same time.\n"); + SysKeyboardAImpl_Unacquire(iface); + } + + current_lock = This; - current = This; - - if (This->buffersize > 0) - { - This->buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - This->buffersize * sizeof(*(This->buffer))); - This->start = 0; - This->count = 0; - This->overflow = FALSE; - InitializeCriticalSection(&(This->crit)); - } - else + if (This->buffersize > 0) { + This->buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + This->buffersize * sizeof(*(This->buffer))); + This->start = 0; + This->count = 0; + This->overflow = FALSE; + } else { This->buffer = NULL; + } + + /*keyboard_hook = SetWindowsHookExW( WH_KEYBOARD_LL, KeyboardCallback, DINPUT_instance, 0 );*/ return DI_OK; } @@ -562,19 +576,19 @@ static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface) if (This->acquired == 0) return DI_NOEFFECT; - if (current == This) - current = NULL; + /* No more locks */ + if (current_lock == This) + current_lock = NULL; else - ERR("this != current\n"); + ERR("this != current_lock\n"); + /* Unacquire device */ This->acquired = 0; - if (This->buffersize >= 0) - { - HeapFree(GetProcessHeap(), 0, This->buffer); - This->buffer = NULL; - DeleteCriticalSection(&(This->crit)); - } + if (This->buffersize >= 0) { + HeapFree(GetProcessHeap(), 0, This->buffer); + This->buffer = NULL; + } return DI_OK; } @@ -613,7 +627,7 @@ static HRESULT WINAPI SysKeyboardAImpl_GetCapabilities( else devcaps.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8); devcaps.dwAxes = 0; - devcaps.dwButtons = 256; + devcaps.dwButtons = WINE_DINPUT_KEYBOARD_MAX_KEYS; devcaps.dwPOVs = 0; devcaps.dwFFSamplePeriod = 0; devcaps.dwFFMinTimeResolution = 0; @@ -709,7 +723,7 @@ static HRESULT WINAPI SysKeyboardAImpl_GetDeviceInfo( TRACE("(this=%p,%p)\n", This, pdidi); if (pdidi->dwSize != sizeof(DIDEVICEINSTANCEA)) { - WARN(" dinput3 not supporte yet...\n"); + WARN(" dinput3 not supported yet...\n"); return DI_OK; } @@ -724,7 +738,7 @@ static HRESULT WINAPI SysKeyboardWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface TRACE("(this=%p,%p)\n", This, pdidi); if (pdidi->dwSize != sizeof(DIDEVICEINSTANCEW)) { - WARN(" dinput3 not supporte yet...\n"); + WARN(" dinput3 not supported yet...\n"); return DI_OK; } diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c index 3394142b3b5..162bcbdad67 100644 --- a/dlls/dinput/mouse.c +++ b/dlls/dinput/mouse.c @@ -578,61 +578,61 @@ static void dinput_window_check(SysMouseImpl* This) { static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface) { SysMouseImpl *This = (SysMouseImpl *)iface; - RECT rect; + RECT rect; + POINT point; TRACE("(this=%p)\n",This); - if (This->acquired == 0) { - POINT point; - - /* Store (in a global variable) the current lock */ - current_lock = (IDirectInputDevice8A*)This; - - /* Init the mouse state */ - GetCursorPos( &point ); - if (This->absolute) { - This->m_state.lX = point.x; - This->m_state.lY = point.y; - This->prevX = point.x; - This->prevY = point.y; - } else { - This->m_state.lX = 0; - This->m_state.lY = 0; - This->org_coords = point; - } - This->m_state.lZ = 0; - This->m_state.rgbButtons[0] = ((GetKeyState(VK_LBUTTON) & 0x80) ? 0xFF : 0x00); - This->m_state.rgbButtons[1] = ((GetKeyState(VK_RBUTTON) & 0x80) ? 0xFF : 0x00); - This->m_state.rgbButtons[2] = ((GetKeyState(VK_MBUTTON) & 0x80) ? 0xFF : 0x00); - - /* Install our mouse hook */ - if (This->dwCoopLevel & DISCL_EXCLUSIVE) - ShowCursor(FALSE); /* hide cursor */ - This->hook = SetWindowsHookExA( WH_MOUSE_LL, dinput_mouse_hook, DINPUT_instance, 0 ); - - /* Get the window dimension and find the center */ - GetWindowRect(This->win, &rect); - This->win_centerX = (rect.right - rect.left) / 2; - This->win_centerY = (rect.bottom - rect.top ) / 2; - - /* Warp the mouse to the center of the window */ - if (This->absolute == 0) { - This->mapped_center.x = This->win_centerX; - This->mapped_center.y = This->win_centerY; - MapWindowPoints(This->win, HWND_DESKTOP, &This->mapped_center, 1); - TRACE("Warping mouse to %ld - %ld\n", This->mapped_center.x, This->mapped_center.y); - SetCursorPos( This->mapped_center.x, This->mapped_center.y ); -#ifdef MOUSE_HACK - This->need_warp = WARP_DONE; -#else - This->need_warp = WARP_STARTED; -#endif - } - - This->acquired = 1; - return DI_OK; + if (This->acquired) + return S_FALSE; + + This->acquired = 1; + + /* Store (in a global variable) the current lock */ + current_lock = (IDirectInputDevice8A*)This; + + /* Init the mouse state */ + GetCursorPos( &point ); + if (This->absolute) { + This->m_state.lX = point.x; + This->m_state.lY = point.y; + This->prevX = point.x; + This->prevY = point.y; + } else { + This->m_state.lX = 0; + This->m_state.lY = 0; + This->org_coords = point; } - return S_FALSE; + This->m_state.lZ = 0; + This->m_state.rgbButtons[0] = ((GetKeyState(VK_LBUTTON) & 0x80) ? 0xFF : 0x00); + This->m_state.rgbButtons[1] = ((GetKeyState(VK_RBUTTON) & 0x80) ? 0xFF : 0x00); + This->m_state.rgbButtons[2] = ((GetKeyState(VK_MBUTTON) & 0x80) ? 0xFF : 0x00); + + /* Install our mouse hook */ + if (This->dwCoopLevel & DISCL_EXCLUSIVE) + ShowCursor(FALSE); /* hide cursor */ + This->hook = SetWindowsHookExA( WH_MOUSE_LL, dinput_mouse_hook, DINPUT_instance, 0 ); + + /* Get the window dimension and find the center */ + GetWindowRect(This->win, &rect); + This->win_centerX = (rect.right - rect.left) / 2; + This->win_centerY = (rect.bottom - rect.top ) / 2; + + /* Warp the mouse to the center of the window */ + if (This->absolute == 0) { + This->mapped_center.x = This->win_centerX; + This->mapped_center.y = This->win_centerY; + MapWindowPoints(This->win, HWND_DESKTOP, &This->mapped_center, 1); + TRACE("Warping mouse to %ld - %ld\n", This->mapped_center.x, This->mapped_center.y); + SetCursorPos( This->mapped_center.x, This->mapped_center.y ); +#ifdef MOUSE_HACK + This->need_warp = WARP_DONE; +#else + This->need_warp = WARP_STARTED; +#endif + } + + return DI_OK; } /****************************************************************************** @@ -644,31 +644,34 @@ static HRESULT WINAPI SysMouseAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface) TRACE("(this=%p)\n",This); - if (This->acquired) { - /* Reinstall previous mouse event handler */ - if (This->hook) { - UnhookWindowsHookEx( This->hook ); - This->hook = 0; - - if (This->dwCoopLevel & DISCL_EXCLUSIVE) - ShowCursor(TRUE); /* show cursor */ - } - - /* No more locks */ - current_lock = NULL; - - /* Unacquire device */ - This->acquired = 0; - - /* And put the mouse cursor back where it was at acquire time */ - if (This->absolute == 0) { - TRACE(" warping mouse back to (%ld , %ld)\n", This->org_coords.x, This->org_coords.y); - SetCursorPos(This->org_coords.x, This->org_coords.y); - } - } else { + if (0 == This->acquired) { return DI_NOEFFECT; } + /* Reinstall previous mouse event handler */ + if (This->hook) { + UnhookWindowsHookEx( This->hook ); + This->hook = 0; + + if (This->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); + + /* Unacquire device */ + This->acquired = 0; + + /* And put the mouse cursor back where it was at acquire time */ + if (This->absolute == 0) { + TRACE(" warping mouse back to (%ld , %ld)\n", This->org_coords.x, This->org_coords.y); + SetCursorPos(This->org_coords.x, This->org_coords.y); + } + return DI_OK; }