- 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.
This commit is contained in:
Raphael Junqueira 2005-03-24 15:08:27 +00:00 committed by Alexandre Julliard
parent 10a605b072
commit 97d848aa19
2 changed files with 184 additions and 167 deletions

View File

@ -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 @@
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
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 =
}; };
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) {
KBDLLHOOKSTRUCT *hook = (KBDLLHOOKSTRUCT *)lparam; if (current_lock->hEvent) SetEvent(current_lock->hEvent);
dik_code = hook->scanCode;
if (hook->flags & LLKHF_EXTENDED) dik_code |= 0x80; if (current_lock->buffer != NULL) {
down = !(hook->flags & LLKHF_UP); int n;
timestamp = hook->time;
}
DInputKeyState[dik_code] = (down ? 0x80 : 0);
TRACE(" setting %02X to %02X\n", dik_code, DInputKeyState[dik_code]);
if (current != NULL) EnterCriticalSection(&(current_lock->crit));
{
if (current->hEvent) n = (current_lock->start + current_lock->count) % current_lock->buffersize;
SetEvent(current->hEvent);
current_lock->buffer[n].dwOfs = dik_code;
if (current->buffer != NULL) current_lock->buffer[n].dwData = down ? 0x80 : 0;
{ current_lock->buffer[n].dwTimeStamp = timestamp;
int n; current_lock->buffer[n].dwSequence = current_lock->dinput->evsequence++;
EnterCriticalSection(&(current->crit)); 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);
n = (current->start + current->count) % current->buffersize;
if (current_lock->count == current_lock->buffersize) {
current->buffer[n].dwOfs = dik_code; current_lock->start = ++current_lock->start % current_lock->buffersize;
current->buffer[n].dwData = down ? 0x80 : 0; current_lock->overflow = TRUE;
current->buffer[n].dwTimeStamp = timestamp; } else
current->buffer[n].dwSequence = current->dinput->evsequence++; current_lock->count++;
TRACE("Adding event at offset %d : %ld - %ld - %ld - %ld\n", n, LeaveCriticalSection(&(current_lock->crit));
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
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)
{ {
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(
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(
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)
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) {
This->buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
if (This->buffersize > 0) This->buffersize * sizeof(*(This->buffer)));
{ This->start = 0;
This->buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, This->count = 0;
This->buffersize * sizeof(*(This->buffer))); This->overflow = FALSE;
This->start = 0; } else {
This->count = 0;
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)
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(
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(
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
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;
} }

View File

@ -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.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;
} }
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); TRACE("(this=%p)\n",This);
if (This->acquired) { if (0 == 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 {
return DI_NOEFFECT; 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; return DI_OK;
} }