Commit 97d848aa authored by Raphael Junqueira's avatar Raphael Junqueira Committed by Alexandre Julliard

- 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.
parent 10a605b0
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
* Copyright 1998 Marcus Meissner * Copyright 1998 Marcus Meissner
* Copyright 1998,1999 Lionel Ulmer * Copyright 1998,1999 Lionel Ulmer
* Copyright 2000-2001 TransGaming Technologies Inc. * Copyright 2000-2001 TransGaming Technologies Inc.
* Copyright 2005 Raphael Junqueira
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
...@@ -37,6 +38,8 @@ ...@@ -37,6 +38,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(dinput); WINE_DEFAULT_DEBUG_CHANNEL(dinput);
#define WINE_DINPUT_KEYBOARD_MAX_KEYS 256
static IDirectInputDevice8AVtbl SysKeyboardAvt; static IDirectInputDevice8AVtbl SysKeyboardAvt;
static IDirectInputDevice8WVtbl SysKeyboardWvt; static IDirectInputDevice8WVtbl SysKeyboardWvt;
...@@ -65,14 +68,15 @@ struct SysKeyboardImpl ...@@ -65,14 +68,15 @@ struct SysKeyboardImpl
CRITICAL_SECTION crit; CRITICAL_SECTION crit;
}; };
SysKeyboardImpl *current; /* Today's acquired device static SysKeyboardImpl* current_lock = NULL;
FIXME: currently this can be only one. /* Today's acquired device
Maybe this should be a linked list or st. * FIXME: currently this can be only one.
I don't know what the rules are for multiple acquired keyboards, * Maybe this should be a linked list or st.
but 'DI_LOSTFOCUS' and 'DI_UNACQUIRED' exist for a reason. * 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 keyboard_crit;
static CRITICAL_SECTION_DEBUG critsect_debug = static CRITICAL_SECTION_DEBUG critsect_debug =
...@@ -83,64 +87,63 @@ 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 CRITICAL_SECTION keyboard_crit = { &critsect_debug, -1, 0, 0, 0, 0 };
static DWORD keyboard_users; static DWORD keyboard_users = 0;
static HHOOK keyboard_hook; static HHOOK keyboard_hook = NULL;
LRESULT CALLBACK KeyboardCallback( int code, WPARAM wparam, LPARAM lparam ) 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); TRACE("(%d,%d,%ld)\n", code, wparam, lparam);
if (code == HC_ACTION) /** returns now if not HC_ACTION */
{ if (code != HC_ACTION) return CallNextHookEx(keyboard_hook, code, wparam, lparam);
BYTE dik_code;
BOOL down; {
DWORD timestamp; 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]);
if (current_lock != NULL) {
if (current_lock->hEvent) SetEvent(current_lock->hEvent);
if (current_lock->buffer != NULL) {
int n;
EnterCriticalSection(&(current_lock->crit));
{ n = (current_lock->start + current_lock->count) % current_lock->buffersize;
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 != NULL) current_lock->buffer[n].dwOfs = dik_code;
{ current_lock->buffer[n].dwData = down ? 0x80 : 0;
if (current->hEvent) current_lock->buffer[n].dwTimeStamp = timestamp;
SetEvent(current->hEvent); current_lock->buffer[n].dwSequence = current_lock->dinput->evsequence++;
if (current->buffer != NULL) 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);
int n;
if (current_lock->count == current_lock->buffersize) {
EnterCriticalSection(&(current->crit)); current_lock->start = ++current_lock->start % current_lock->buffersize;
current_lock->overflow = TRUE;
n = (current->start + current->count) % current->buffersize; } else
current_lock->count++;
current->buffer[n].dwOfs = dik_code;
current->buffer[n].dwData = down ? 0x80 : 0; LeaveCriticalSection(&(current_lock->crit));
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));
}
}
} }
}
return CallNextHookEx(keyboard_hook, code, wparam, lparam); return CallNextHookEx(keyboard_hook, code, wparam, lparam);
} }
...@@ -238,15 +241,20 @@ static BOOL keyboarddev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEI ...@@ -238,15 +241,20 @@ static BOOL keyboarddev_enum_deviceW(DWORD dwDevType, DWORD dwFlags, LPDIDEVICEI
static SysKeyboardImpl *alloc_device(REFGUID rguid, LPVOID kvt, IDirectInputImpl *dinput) static SysKeyboardImpl *alloc_device(REFGUID rguid, LPVOID kvt, IDirectInputImpl *dinput)
{ {
SysKeyboardImpl* newDevice; SysKeyboardImpl* newDevice;
DWORD kbd_users;
newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboardImpl)); newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboardImpl));
newDevice->lpVtbl = kvt; newDevice->lpVtbl = kvt;
newDevice->ref = 1; newDevice->ref = 1;
memcpy(&(newDevice->guid),rguid,sizeof(*rguid)); memcpy(&(newDevice->guid),rguid,sizeof(*rguid));
newDevice->dinput = dinput; newDevice->dinput = dinput;
InitializeCriticalSection(&(newDevice->crit));
EnterCriticalSection(&keyboard_crit); EnterCriticalSection(&keyboard_crit);
if (!keyboard_users++) kbd_users = InterlockedIncrement(&keyboard_users);
keyboard_hook = SetWindowsHookExW( WH_KEYBOARD_LL, KeyboardCallback, DINPUT_instance, 0 ); if (1 == kbd_users) {
keyboard_hook = SetWindowsHookExW( WH_KEYBOARD_LL, KeyboardCallback, DINPUT_instance, 0 );
}
LeaveCriticalSection(&keyboard_crit); LeaveCriticalSection(&keyboard_crit);
return newDevice; return newDevice;
...@@ -301,13 +309,15 @@ static ULONG WINAPI SysKeyboardAImpl_Release(LPDIRECTINPUTDEVICE8A iface) ...@@ -301,13 +309,15 @@ static ULONG WINAPI SysKeyboardAImpl_Release(LPDIRECTINPUTDEVICE8A iface)
{ {
SysKeyboardImpl *This = (SysKeyboardImpl *)iface; SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
ULONG ref; ULONG ref;
DWORD kbd_users;
ref = InterlockedDecrement(&(This->ref)); ref = InterlockedDecrement(&(This->ref));
if (ref) if (ref)
return ref; return ref;
EnterCriticalSection(&keyboard_crit); EnterCriticalSection(&keyboard_crit);
if (!--keyboard_users) { kbd_users = InterlockedDecrement(&keyboard_users);
if (0 == kbd_users) {
UnhookWindowsHookEx( keyboard_hook ); UnhookWindowsHookEx( keyboard_hook );
keyboard_hook = 0; keyboard_hook = 0;
} }
...@@ -388,24 +398,29 @@ static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState( ...@@ -388,24 +398,29 @@ static HRESULT WINAPI SysKeyboardAImpl_GetDeviceState(
LPDIRECTINPUTDEVICE8A iface,DWORD len,LPVOID ptr 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 */ /* Note: device does not need to be acquired */
if (len != 256) if (len != WINE_DINPUT_KEYBOARD_MAX_KEYS)
return DIERR_INVALIDPARAM; return DIERR_INVALIDPARAM;
MsgWaitForMultipleObjectsEx(0, NULL, 0, QS_ALLINPUT, 0); MsgWaitForMultipleObjectsEx(0, NULL, 0, QS_ALLINPUT, 0);
EnterCriticalSection(&(This->crit));
if (TRACE_ON(dinput)) { if (TRACE_ON(dinput)) {
int i; int i;
for (i = 0; i < 256; i++) { for (i = 0; i < WINE_DINPUT_KEYBOARD_MAX_KEYS; i++) {
if (DInputKeyState[i] != 0x00) { if (DInputKeyState[i] != 0x00) {
TRACE(" - %02X: %02x\n", i, DInputKeyState[i]); 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; return DI_OK;
} }
...@@ -490,7 +505,7 @@ static HRESULT WINAPI SysKeyboardAImpl_EnumObjects( ...@@ -490,7 +505,7 @@ static HRESULT WINAPI SysKeyboardAImpl_EnumObjects(
memset(&ddoi, 0, sizeof(ddoi)); memset(&ddoi, 0, sizeof(ddoi));
ddoi.dwSize = FIELD_OFFSET(DIDEVICEOBJECTINSTANCEA, dwFFMaxForce); 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 :-) */ /* Report 255 keys :-) */
ddoi.guidType = GUID_Key; ddoi.guidType = GUID_Key;
ddoi.dwOfs = i; ddoi.dwOfs = i;
...@@ -531,25 +546,24 @@ static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface) ...@@ -531,25 +546,24 @@ static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
This->acquired = 1; This->acquired = 1;
if (current != NULL) if (current_lock != NULL) {
{ FIXME("Not more than one keyboard can be acquired at the same time.\n");
FIXME("Not more than one keyboard can be acquired at the same time.\n"); SysKeyboardAImpl_Unacquire(iface);
SysKeyboardAImpl_Unacquire(iface); }
}
current_lock = This;
current = This;
if (This->buffersize > 0) {
if (This->buffersize > 0) This->buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
{ This->buffersize * sizeof(*(This->buffer)));
This->buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->start = 0;
This->buffersize * sizeof(*(This->buffer))); This->count = 0;
This->start = 0; This->overflow = FALSE;
This->count = 0; } else {
This->overflow = FALSE;
InitializeCriticalSection(&(This->crit));
}
else
This->buffer = NULL; This->buffer = NULL;
}
/*keyboard_hook = SetWindowsHookExW( WH_KEYBOARD_LL, KeyboardCallback, DINPUT_instance, 0 );*/
return DI_OK; return DI_OK;
} }
...@@ -562,19 +576,19 @@ static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface) ...@@ -562,19 +576,19 @@ static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
if (This->acquired == 0) if (This->acquired == 0)
return DI_NOEFFECT; return DI_NOEFFECT;
if (current == This) /* No more locks */
current = NULL; if (current_lock == This)
current_lock = NULL;
else else
ERR("this != current\n"); ERR("this != current_lock\n");
/* Unacquire device */
This->acquired = 0; This->acquired = 0;
if (This->buffersize >= 0) if (This->buffersize >= 0) {
{ HeapFree(GetProcessHeap(), 0, This->buffer);
HeapFree(GetProcessHeap(), 0, This->buffer); This->buffer = NULL;
This->buffer = NULL; }
DeleteCriticalSection(&(This->crit));
}
return DI_OK; return DI_OK;
} }
...@@ -613,7 +627,7 @@ static HRESULT WINAPI SysKeyboardAImpl_GetCapabilities( ...@@ -613,7 +627,7 @@ static HRESULT WINAPI SysKeyboardAImpl_GetCapabilities(
else else
devcaps.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8); devcaps.dwDevType = DIDEVTYPE_KEYBOARD | (DIDEVTYPEKEYBOARD_UNKNOWN << 8);
devcaps.dwAxes = 0; devcaps.dwAxes = 0;
devcaps.dwButtons = 256; devcaps.dwButtons = WINE_DINPUT_KEYBOARD_MAX_KEYS;
devcaps.dwPOVs = 0; devcaps.dwPOVs = 0;
devcaps.dwFFSamplePeriod = 0; devcaps.dwFFSamplePeriod = 0;
devcaps.dwFFMinTimeResolution = 0; devcaps.dwFFMinTimeResolution = 0;
...@@ -709,7 +723,7 @@ static HRESULT WINAPI SysKeyboardAImpl_GetDeviceInfo( ...@@ -709,7 +723,7 @@ static HRESULT WINAPI SysKeyboardAImpl_GetDeviceInfo(
TRACE("(this=%p,%p)\n", This, pdidi); TRACE("(this=%p,%p)\n", This, pdidi);
if (pdidi->dwSize != sizeof(DIDEVICEINSTANCEA)) { if (pdidi->dwSize != sizeof(DIDEVICEINSTANCEA)) {
WARN(" dinput3 not supporte yet...\n"); WARN(" dinput3 not supported yet...\n");
return DI_OK; return DI_OK;
} }
...@@ -724,7 +738,7 @@ static HRESULT WINAPI SysKeyboardWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface ...@@ -724,7 +738,7 @@ static HRESULT WINAPI SysKeyboardWImpl_GetDeviceInfo(LPDIRECTINPUTDEVICE8W iface
TRACE("(this=%p,%p)\n", This, pdidi); TRACE("(this=%p,%p)\n", This, pdidi);
if (pdidi->dwSize != sizeof(DIDEVICEINSTANCEW)) { if (pdidi->dwSize != sizeof(DIDEVICEINSTANCEW)) {
WARN(" dinput3 not supporte yet...\n"); WARN(" dinput3 not supported yet...\n");
return DI_OK; return DI_OK;
} }
......
...@@ -578,61 +578,61 @@ static void dinput_window_check(SysMouseImpl* This) { ...@@ -578,61 +578,61 @@ static void dinput_window_check(SysMouseImpl* This) {
static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface) static HRESULT WINAPI SysMouseAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
{ {
SysMouseImpl *This = (SysMouseImpl *)iface; SysMouseImpl *This = (SysMouseImpl *)iface;
RECT rect; RECT rect;
POINT point;
TRACE("(this=%p)\n",This); TRACE("(this=%p)\n",This);
if (This->acquired == 0) { if (This->acquired)
POINT point; return S_FALSE;
/* Store (in a global variable) the current lock */ This->acquired = 1;
current_lock = (IDirectInputDevice8A*)This;
/* Store (in a global variable) the current lock */
/* Init the mouse state */ current_lock = (IDirectInputDevice8A*)This;
GetCursorPos( &point );
if (This->absolute) { /* Init the mouse state */
This->m_state.lX = point.x; GetCursorPos( &point );
This->m_state.lY = point.y; if (This->absolute) {
This->prevX = point.x; This->m_state.lX = point.x;
This->prevY = point.y; This->m_state.lY = point.y;
} else { This->prevX = point.x;
This->m_state.lX = 0; This->prevY = point.y;
This->m_state.lY = 0; } else {
This->org_coords = point; This->m_state.lX = 0;
} This->m_state.lY = 0;
This->m_state.lZ = 0; This->org_coords = point;
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.lZ = 0;
This->m_state.rgbButtons[2] = ((GetKeyState(VK_MBUTTON) & 0x80) ? 0xFF : 0x00); This->m_state.rgbButtons[0] = ((GetKeyState(VK_LBUTTON) & 0x80) ? 0xFF : 0x00);
This->m_state.rgbButtons[1] = ((GetKeyState(VK_RBUTTON) & 0x80) ? 0xFF : 0x00);
/* Install our mouse hook */ This->m_state.rgbButtons[2] = ((GetKeyState(VK_MBUTTON) & 0x80) ? 0xFF : 0x00);
if (This->dwCoopLevel & DISCL_EXCLUSIVE)
ShowCursor(FALSE); /* hide cursor */ /* Install our mouse hook */
This->hook = SetWindowsHookExA( WH_MOUSE_LL, dinput_mouse_hook, DINPUT_instance, 0 ); if (This->dwCoopLevel & DISCL_EXCLUSIVE)
ShowCursor(FALSE); /* hide cursor */
/* Get the window dimension and find the center */ This->hook = SetWindowsHookExA( WH_MOUSE_LL, dinput_mouse_hook, DINPUT_instance, 0 );
GetWindowRect(This->win, &rect);
This->win_centerX = (rect.right - rect.left) / 2; /* Get the window dimension and find the center */
This->win_centerY = (rect.bottom - rect.top ) / 2; GetWindowRect(This->win, &rect);
This->win_centerX = (rect.right - rect.left) / 2;
/* Warp the mouse to the center of the window */ This->win_centerY = (rect.bottom - rect.top ) / 2;
if (This->absolute == 0) {
This->mapped_center.x = This->win_centerX; /* Warp the mouse to the center of the window */
This->mapped_center.y = This->win_centerY; if (This->absolute == 0) {
MapWindowPoints(This->win, HWND_DESKTOP, &This->mapped_center, 1); This->mapped_center.x = This->win_centerX;
TRACE("Warping mouse to %ld - %ld\n", This->mapped_center.x, This->mapped_center.y); This->mapped_center.y = This->win_centerY;
SetCursorPos( This->mapped_center.x, This->mapped_center.y ); 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 #ifdef MOUSE_HACK
This->need_warp = WARP_DONE; This->need_warp = WARP_DONE;
#else #else
This->need_warp = WARP_STARTED; This->need_warp = WARP_STARTED;
#endif #endif
}
This->acquired = 1;
return DI_OK;
} }
return S_FALSE;
return DI_OK;
} }
/****************************************************************************** /******************************************************************************
...@@ -644,29 +644,32 @@ static HRESULT WINAPI SysMouseAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface) ...@@ -644,29 +644,32 @@ static HRESULT WINAPI SysMouseAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
TRACE("(this=%p)\n",This); TRACE("(this=%p)\n",This);
if (This->acquired) { if (0 == This->acquired) {
/* Reinstall previous mouse event handler */ return DI_NOEFFECT;
if (This->hook) { }
UnhookWindowsHookEx( This->hook );
This->hook = 0;
if (This->dwCoopLevel & DISCL_EXCLUSIVE)
ShowCursor(TRUE); /* show cursor */
}
/* No more locks */ /* Reinstall previous mouse event handler */
current_lock = NULL; if (This->hook) {
UnhookWindowsHookEx( This->hook );
This->hook = 0;
if (This->dwCoopLevel & DISCL_EXCLUSIVE)
ShowCursor(TRUE); /* show cursor */
}
/* Unacquire device */ /* No more locks */
This->acquired = 0; 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 */ /* Unacquire device */
if (This->absolute == 0) { This->acquired = 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); /* And put the mouse cursor back where it was at acquire time */
} if (This->absolute == 0) {
} else { TRACE(" warping mouse back to (%ld , %ld)\n", This->org_coords.x, This->org_coords.y);
return DI_NOEFFECT; SetCursorPos(This->org_coords.x, This->org_coords.y);
} }
return DI_OK; return DI_OK;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment