dinput-keyboard: Move few global variables into object.
Vitaliy Margolen
wine-patch at kievinfo.com
Sat Jan 28 00:11:31 CST 2006
ChangeLog:
dinput-keyboard: Move few global variables into object.
Move low level hook callback into it's own thread.
Hook and unhook in Acquire/Unacquire - same as mouse.
Along the same lines as mouse patch.
This one actually does fix the bug 2981.
dlls/dinput/keyboard.c | 149 +++++++++++++++++++++++++-----------------------
1 files changed, 78 insertions(+), 71 deletions(-)
-------------- next part --------------
3617f22940759ae598f510bbd5582ee8cab1de16
diff --git a/dlls/dinput/keyboard.c b/dlls/dinput/keyboard.c
index aa6cbcb..122a350 100644
--- a/dlls/dinput/keyboard.c
+++ b/dlls/dinput/keyboard.c
@@ -52,7 +52,10 @@ struct SysKeyboardImpl
IDirectInputImpl* dinput;
- HANDLE hEvent;
+ HANDLE hEvent;
+ HHOOK hook; /* installed WH_KEYBOARD_LL hook */
+ HANDLE hook_thread; /* hook callback tread */
+ DWORD hook_tid;
/* SysKeyboardAImpl */
int acquired;
int buffersize; /* set in 'SetProperty' */
@@ -87,64 +90,71 @@ static CRITICAL_SECTION_DEBUG critsect_d
};
static CRITICAL_SECTION keyboard_crit = { &critsect_debug, -1, 0, 0, 0, 0 };
-static LONG 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;
+ SysKeyboardImpl *This = (SysKeyboardImpl *)current_lock;
+ BYTE dik_code;
+ BOOL down;
+ KBDLLHOOKSTRUCT *hook = (KBDLLHOOKSTRUCT *)lparam;
+ BYTE new_diks;
- TRACE("(%d,%d,%ld)\n", code, wparam, lparam);
+ TRACE("(%d,%d,%ld)\n", code, wparam, lparam);
- /** returns now if not HC_ACTION */
- if (code != HC_ACTION) return CallNextHookEx(keyboard_hook, code, wparam, lparam);
+ /* returns now if not HC_ACTION */
+ if (code != HC_ACTION) return CallNextHookEx(This->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 */
+ /** 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]);
+ 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 (This->hEvent) SetEvent(This->hEvent);
- if (current_lock->buffer != NULL) {
- int n;
-
- 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++;
+ if (This->buffer != NULL)
+ {
+ 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,
- current_lock->buffer[n].dwOfs, current_lock->buffer[n].dwData, current_lock->buffer[n].dwTimeStamp, current_lock->buffer[n].dwSequence);
+ TRACE("Adding event at offset %d : %ld - %ld - %ld - %ld\n", n,
+ This->buffer[n].dwOfs, This->buffer[n].dwData, This->buffer[n].dwTimeStamp, This->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++;
+ if (This->count == This->buffersize) {
+ This->start = ++This->start % This->buffersize;
+ This->overflow = TRUE;
+ }
+ else This->count++;
- LeaveCriticalSection(&(current_lock->crit));
+ LeaveCriticalSection(&(This->crit));
}
- }
- return CallNextHookEx(keyboard_hook, code, wparam, lparam);
+ return CallNextHookEx(This->hook, code, wparam, lparam);
+}
+
+static DWORD WINAPI dinput_keyboard_hook_thread_proc(void *param)
+{
+ MSG msg;
+ SysKeyboardImpl *This = (SysKeyboardImpl *)param;
+
+ This->hook = SetWindowsHookExW( WH_KEYBOARD_LL, KeyboardCallback, DINPUT_instance, 0 );
+ while (GetMessageW(&msg, 0, 0, 0))
+ {
+ TranslateMessage(&msg);
+ DispatchMessageW(&msg);
+ }
+ return 0;
}
static GUID DInput_Wine_Keyboard_GUID = { /* 0ab8648a-7735-11d2-8c73-71df54a96441 */
@@ -241,7 +251,6 @@ static BOOL keyboarddev_enum_deviceW(DWO
static SysKeyboardImpl *alloc_device(REFGUID rguid, const void *kvt, IDirectInputImpl *dinput)
{
SysKeyboardImpl* newDevice;
- DWORD kbd_users;
newDevice = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(SysKeyboardImpl));
newDevice->lpVtbl = kvt;
@@ -250,13 +259,6 @@ static SysKeyboardImpl *alloc_device(REF
newDevice->dinput = dinput;
InitializeCriticalSection(&(newDevice->crit));
- EnterCriticalSection(&keyboard_crit);
- kbd_users = InterlockedIncrement(&keyboard_users);
- if (1 == kbd_users) {
- keyboard_hook = SetWindowsHookExW( WH_KEYBOARD_LL, KeyboardCallback, DINPUT_instance, 0 );
- }
- LeaveCriticalSection(&keyboard_crit);
-
return newDevice;
}
@@ -307,29 +309,26 @@ const struct dinput_device keyboard_devi
static ULONG WINAPI SysKeyboardAImpl_Release(LPDIRECTINPUTDEVICE8A iface)
{
- SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
- ULONG ref;
- DWORD kbd_users;
+ SysKeyboardImpl *This = (SysKeyboardImpl *)iface;
+ ULONG ref;
- ref = InterlockedDecrement(&(This->ref));
- if (ref)
- return ref;
-
- EnterCriticalSection(&keyboard_crit);
- kbd_users = InterlockedDecrement(&keyboard_users);
- if (0 == kbd_users) {
- UnhookWindowsHookEx( keyboard_hook );
- keyboard_hook = 0;
- }
- LeaveCriticalSection(&keyboard_crit);
+ ref = InterlockedDecrement(&(This->ref));
+ if (ref) return ref;
- /* Free the data queue */
- HeapFree(GetProcessHeap(),0,This->buffer);
+ if (This->hook_tid) {
+ while (!PostThreadMessageW(This->hook_tid, WM_QUIT, 0, 0)) Sleep(100);
+ WaitForSingleObject(This->hook_thread, INFINITE);
+ CloseHandle(This->hook_thread);
+ This->hook_tid = 0;
+ }
- DeleteCriticalSection(&(This->crit));
+ /* Free the data queue */
+ HeapFree(GetProcessHeap(),0,This->buffer);
- HeapFree(GetProcessHeap(),0,This);
- return DI_OK;
+ DeleteCriticalSection(&(This->crit));
+
+ HeapFree(GetProcessHeap(),0,This);
+ return DI_OK;
}
static HRESULT WINAPI SysKeyboardAImpl_SetProperty(
@@ -563,7 +562,8 @@ static HRESULT WINAPI SysKeyboardAImpl_A
This->buffer = NULL;
}
- /*keyboard_hook = SetWindowsHookExW( WH_KEYBOARD_LL, KeyboardCallback, DINPUT_instance, 0 );*/
+ This->hook_thread = CreateThread(NULL, 0, dinput_keyboard_hook_thread_proc,
+ This, 0, &This->hook_tid);
return DI_OK;
}
@@ -576,6 +576,13 @@ static HRESULT WINAPI SysKeyboardAImpl_U
if (This->acquired == 0)
return DI_NOEFFECT;
+ if (This->hook_tid) {
+ while (!PostThreadMessageW(This->hook_tid, WM_QUIT, 0, 0)) Sleep(100);
+ WaitForSingleObject(This->hook_thread, INFINITE);
+ CloseHandle(This->hook_thread);
+ This->hook_tid = 0;
+ }
+
/* No more locks */
if (current_lock == This)
current_lock = NULL;
More information about the wine-patches
mailing list