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