Commit 6bd7451e authored by Vitaliy Margolen's avatar Vitaliy Margolen Committed by Alexandre Julliard

dinput: Keyboard: Use the same event queue mechanism as mouse.

parent 65e5ed60
...@@ -55,16 +55,13 @@ struct SysKeyboardImpl ...@@ -55,16 +55,13 @@ struct SysKeyboardImpl
HANDLE hEvent; HANDLE hEvent;
/* SysKeyboardAImpl */ /* SysKeyboardAImpl */
int acquired; int acquired;
int buffersize; /* set in 'SetProperty' */
LPDIDEVICEOBJECTDATA buffer; /* buffer for 'GetDeviceData'. LPDIDEVICEOBJECTDATA data_queue; /* buffer for 'GetDeviceData'. Alloc at
Alloc at 'Acquire', Free at 'Acquire', Free at 'Unacquire' */
'Unacquire' */ int queue_len; /* size of the queue - set in 'SetProperty' */
int count; /* number of objects in use in int queue_head; /* position to write new event into queue */
'buffer' */ int queue_tail; /* next event to read from queue */
int start; /* 'buffer' rotates. This is the BOOL overflow; /* return DI_BUFFEROVERFLOW in 'GetDeviceData' */
first in use (if count > 0) */
BOOL overflow; /* return DI_BUFFEROVERFLOW in
'GetDeviceData' */
CRITICAL_SECTION crit; CRITICAL_SECTION crit;
}; };
...@@ -81,8 +78,7 @@ static BYTE DInputKeyState[WINE_DINPUT_KEYBOARD_MAX_KEYS]; /* array for 'GetDevi ...@@ -81,8 +78,7 @@ static BYTE DInputKeyState[WINE_DINPUT_KEYBOARD_MAX_KEYS]; /* array for 'GetDevi
LRESULT CALLBACK KeyboardCallback( int code, WPARAM wparam, LPARAM lparam ) LRESULT CALLBACK KeyboardCallback( int code, WPARAM wparam, LPARAM lparam )
{ {
SysKeyboardImpl *This = (SysKeyboardImpl *)current_lock; SysKeyboardImpl *This = (SysKeyboardImpl *)current_lock;
BYTE dik_code; int dik_code;
BOOL down;
KBDLLHOOKSTRUCT *hook = (KBDLLHOOKSTRUCT *)lparam; KBDLLHOOKSTRUCT *hook = (KBDLLHOOKSTRUCT *)lparam;
BYTE new_diks; BYTE new_diks;
...@@ -91,44 +87,24 @@ LRESULT CALLBACK KeyboardCallback( int code, WPARAM wparam, LPARAM lparam ) ...@@ -91,44 +87,24 @@ LRESULT CALLBACK KeyboardCallback( int code, WPARAM wparam, LPARAM lparam )
/* returns now if not HC_ACTION */ /* returns now if not HC_ACTION */
if (code != HC_ACTION) return CallNextHookEx(0, code, wparam, lparam); if (code != HC_ACTION) return CallNextHookEx(0, code, wparam, lparam);
dik_code = hook->scanCode; dik_code = hook->scanCode & 0xff;
if (hook->flags & LLKHF_EXTENDED) dik_code |= 0x80; if (hook->flags & LLKHF_EXTENDED) dik_code |= 0x80;
down = !(hook->flags & LLKHF_UP);
/** returns now if key event already known */ new_diks = hook->flags & LLKHF_UP ? 0 : 0x80;
new_diks = (down ? 0x80 : 0);
/* returns now if key event already known */
if (new_diks == DInputKeyState[dik_code]) if (new_diks == DInputKeyState[dik_code])
return CallNextHookEx(0, code, wparam, lparam); return CallNextHookEx(0, code, wparam, lparam);
DInputKeyState[dik_code] = new_diks; DInputKeyState[dik_code] = new_diks;
TRACE(" setting %02X to %02X\n", dik_code, DInputKeyState[dik_code]); TRACE(" setting %02X to %02X\n", dik_code, DInputKeyState[dik_code]);
if (This->hEvent) SetEvent(This->hEvent); EnterCriticalSection(&This->crit);
GEN_EVENT(dik_code, new_diks, hook->time, This->dinput->evsequence++);
if (This->buffer != NULL) LeaveCriticalSection(&This->crit);
{
int n;
EnterCriticalSection(&(This->crit));
n = (This->start + This->count) % This->buffersize;
This->buffer[n].dwOfs = dik_code;
This->buffer[n].dwData = down ? 0x80 : 0;
This->buffer[n].dwTimeStamp = hook->time;
This->buffer[n].dwSequence = This->dinput->evsequence++;
TRACE("Adding event at offset %d : %ld - %ld - %ld - %ld\n", n, if (This->hEvent) SetEvent(This->hEvent);
This->buffer[n].dwOfs, This->buffer[n].dwData, This->buffer[n].dwTimeStamp, This->buffer[n].dwSequence);
if (This->count == This->buffersize) {
This->start = ++This->start % This->buffersize;
This->overflow = TRUE;
}
else This->count++;
LeaveCriticalSection(&(This->crit));
}
return CallNextHookEx(0, code, wparam, lparam); return CallNextHookEx(0, code, wparam, lparam);
} }
...@@ -293,7 +269,7 @@ static ULONG WINAPI SysKeyboardAImpl_Release(LPDIRECTINPUTDEVICE8A iface) ...@@ -293,7 +269,7 @@ static ULONG WINAPI SysKeyboardAImpl_Release(LPDIRECTINPUTDEVICE8A iface)
set_dinput_hook(WH_KEYBOARD_LL, NULL); set_dinput_hook(WH_KEYBOARD_LL, NULL);
/* Free the data queue */ /* Free the data queue */
HeapFree(GetProcessHeap(),0,This->buffer); HeapFree(GetProcessHeap(), 0, This->data_queue);
DeleteCriticalSection(&(This->crit)); DeleteCriticalSection(&(This->crit));
...@@ -320,7 +296,7 @@ static HRESULT WINAPI SysKeyboardAImpl_SetProperty( ...@@ -320,7 +296,7 @@ static HRESULT WINAPI SysKeyboardAImpl_SetProperty(
if (This->acquired) if (This->acquired)
return DIERR_INVALIDPARAM; return DIERR_INVALIDPARAM;
This->buffersize = pd->dwData; This->queue_len = pd->dwData;
break; break;
} }
...@@ -351,7 +327,7 @@ static HRESULT WINAPI SysKeyboardAImpl_GetProperty( ...@@ -351,7 +327,7 @@ static HRESULT WINAPI SysKeyboardAImpl_GetProperty(
if (This->acquired) if (This->acquired)
return DIERR_INVALIDPARAM; return DIERR_INVALIDPARAM;
pd->dwData = This->buffersize; pd->dwData = This->queue_len;
break; break;
} }
...@@ -400,41 +376,38 @@ static HRESULT WINAPI SysKeyboardAImpl_GetDeviceData( ...@@ -400,41 +376,38 @@ static HRESULT WINAPI SysKeyboardAImpl_GetDeviceData(
) )
{ {
SysKeyboardImpl *This = (SysKeyboardImpl *)iface; SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
int ret = DI_OK, i = 0; HRESULT ret = DI_OK;
int len;
TRACE("(this=%p,%ld,%p,%p(%ld)),0x%08lx)\n", TRACE("(%p) %p -> %p(%ld) x%ld, 0x%08lx\n",
This,dodsize,dod,entries,entries?*entries:0,flags); This, dod, entries, entries ? *entries : 0, dodsize, flags);
if (This->acquired == 0) if (!This->acquired)
return DIERR_NOTACQUIRED; return DIERR_NOTACQUIRED;
if (This->buffer == NULL) if (!This->data_queue)
return DIERR_NOTBUFFERED; return DIERR_NOTBUFFERED;
if (dodsize < sizeof(DIDEVICEOBJECTDATA_DX3)) if (dodsize < sizeof(DIDEVICEOBJECTDATA_DX3))
return DIERR_INVALIDPARAM; return DIERR_INVALIDPARAM;
MsgWaitForMultipleObjectsEx(0, NULL, 0, QS_ALLINPUT, 0); MsgWaitForMultipleObjectsEx(0, NULL, 0, QS_ALLINPUT, 0);
EnterCriticalSection(&This->crit);
EnterCriticalSection(&(This->crit)); len = ((This->queue_head < This->queue_tail) ? This->queue_len : 0) +
This->queue_head - This->queue_tail;
if ((*entries != INFINITE) && (len > *entries)) len = *entries;
/* Copy item at a time for the case dodsize > sizeof(buffer[n]) */ if (dod)
while ((i < *entries || *entries == INFINITE) && i < This->count)
{ {
if (dod != NULL) int i;
for(i = 0; i < len; i++)
{ {
int n = (This->start + i) % This->buffersize; int n = (This->queue_tail + i) % This->queue_len;
LPDIDEVICEOBJECTDATA pd memcpy((char *)dod + dodsize * i, This->data_queue + n, dodsize);
= (LPDIDEVICEOBJECTDATA)((BYTE *)dod + dodsize * i);
pd->dwOfs = This->buffer[n].dwOfs;
pd->dwData = This->buffer[n].dwData;
pd->dwTimeStamp = This->buffer[n].dwTimeStamp;
pd->dwSequence = This->buffer[n].dwSequence;
} }
i++;
} }
*entries = len;
*entries = i;
if (This->overflow) if (This->overflow)
ret = DI_BUFFEROVERFLOW; ret = DI_BUFFEROVERFLOW;
...@@ -442,15 +415,13 @@ static HRESULT WINAPI SysKeyboardAImpl_GetDeviceData( ...@@ -442,15 +415,13 @@ static HRESULT WINAPI SysKeyboardAImpl_GetDeviceData(
if (!(flags & DIGDD_PEEK)) if (!(flags & DIGDD_PEEK))
{ {
/* Empty buffer */ /* Empty buffer */
This->count -= i; This->queue_tail = (This->queue_tail + len) % This->queue_len;
This->start = (This->start + i) % This->buffersize;
This->overflow = FALSE; This->overflow = FALSE;
} }
LeaveCriticalSection(&(This->crit)); LeaveCriticalSection(&This->crit);
TRACE("Returning %ld events queued\n", *entries); TRACE("Returning %ld events queued\n", *entries);
return ret; return ret;
} }
...@@ -509,29 +480,26 @@ static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface) ...@@ -509,29 +480,26 @@ static HRESULT WINAPI SysKeyboardAImpl_Acquire(LPDIRECTINPUTDEVICE8A iface)
{ {
SysKeyboardImpl *This = (SysKeyboardImpl *)iface; SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
TRACE("(this=%p)\n",This); TRACE("(%p)\n",This);
if (This->acquired)
return S_FALSE;
if (This->acquired) return DI_NOEFFECT;
This->acquired = 1; This->acquired = 1;
if (current_lock != 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((LPDIRECTINPUTDEVICE8A)current_lock); SysKeyboardAImpl_Unacquire((LPDIRECTINPUTDEVICE8A)current_lock);
} }
current_lock = This; current_lock = This;
if (This->buffersize > 0) { if (This->queue_len > 0)
This->buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, {
This->buffersize * sizeof(*(This->buffer))); This->data_queue = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
This->start = 0; This->queue_len * sizeof(*(This->data_queue)));
This->count = 0; This->queue_head = 0;
This->queue_tail = 0;
This->overflow = FALSE; This->overflow = FALSE;
} else { } else
This->buffer = NULL; This->data_queue = NULL;
}
set_dinput_hook(WH_KEYBOARD_LL, KeyboardCallback); set_dinput_hook(WH_KEYBOARD_LL, KeyboardCallback);
...@@ -557,9 +525,9 @@ static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface) ...@@ -557,9 +525,9 @@ static HRESULT WINAPI SysKeyboardAImpl_Unacquire(LPDIRECTINPUTDEVICE8A iface)
/* Unacquire device */ /* Unacquire device */
This->acquired = 0; This->acquired = 0;
if (This->buffersize >= 0) { if (This->queue_len >= 0) {
HeapFree(GetProcessHeap(), 0, This->buffer); HeapFree(GetProcessHeap(), 0, This->data_queue);
This->buffer = NULL; This->data_queue = NULL;
} }
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