dinput: Put mouse hook callback into separate thread.

Vitaliy Margolen wine-patch at kievinfo.com
Fri Jan 27 16:03:06 CST 2006


ChangeLog:
dinput: Put mouse hook callback into separate thread.

For hooks to work properly hook callback have to be in a thread
with message loop. Some games create separate threads just to handle
mouse events that do not have message loop. This patch fixes one of such
games (Bug 4264) and hopefully should fir all the rest as well (Bug 2981).

 dlls/dinput/mouse.c |   45 ++++++++++++++++++++++++++++++++-------------
 1 files changed, 32 insertions(+), 13 deletions(-)
-------------- next part --------------
d5a0f5b12b0c63d93d1c694ce455f3332940a180
diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c
index 6570d1f..977299a 100644
--- a/dlls/dinput/mouse.c
+++ b/dlls/dinput/mouse.c
@@ -127,6 +127,8 @@ struct SysMouseImpl
     /* These are used in case of relative -> absolute transitions */
     POINT                           org_coords;
     HHOOK                           hook;
+    HANDLE                          hook_thread;
+    DWORD                           hook_tid;
     HWND			    win;
     DWORD			    dwCoopLevel;
     POINT      			    mapped_center;
@@ -332,9 +334,12 @@ static ULONG WINAPI SysMouseAImpl_Releas
     
     /* Free the data queue */
     HeapFree(GetProcessHeap(),0,This->data_queue);
-    
-    if (This->hook) {
-	UnhookWindowsHookEx( This->hook );
+    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;
+
 	if (This->dwCoopLevel & DISCL_EXCLUSIVE)
             ShowCursor(TRUE); /* show cursor */
     }
@@ -553,6 +558,19 @@ static LRESULT CALLBACK dinput_mouse_hoo
     return ret;
 }
 
+static DWORD WINAPI dinput_mouse_hook_thread_proc(void *param)
+{
+    MSG msg;
+    SysMouseImpl *This = (SysMouseImpl *)param;
+
+    This->hook = SetWindowsHookExW( WH_MOUSE_LL, dinput_mouse_hook, DINPUT_instance, 0 );
+    while (GetMessageW(&msg, 0, 0, 0))
+    {
+        TranslateMessage(&msg);
+        DispatchMessageW(&msg);
+    }
+    return 0;
+}
 
 static void dinput_window_check(SysMouseImpl* This) {
     RECT rect;
@@ -611,7 +629,8 @@ static HRESULT WINAPI SysMouseAImpl_Acqu
     /* 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 );
+    This->hook_thread = CreateThread(NULL, 0, dinput_mouse_hook_thread_proc,
+                                     This, 0, &This->hook_tid);
     
     /* Get the window dimension and find the center */
     GetWindowRect(This->win, &rect);
@@ -647,16 +666,16 @@ static HRESULT WINAPI SysMouseAImpl_Unac
     if (0 == This->acquired) {
 	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 */
+    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;
+
+	if (This->dwCoopLevel & DISCL_EXCLUSIVE)
+            ShowCursor(TRUE); /* show cursor */
     }
-	
+
     /* No more locks */
     if (current_lock == (IDirectInputDevice8A*) This)
       current_lock = NULL;


More information about the wine-patches mailing list