Vitaliy Margolen : dinput: Use CALLWINDPROC hook to monitor focus loses away from acquired windows.

Alexandre Julliard julliard at wine.codeweavers.com
Mon Jul 16 16:27:18 CDT 2007


Module: wine
Branch: master
Commit: 41ce4a01583d552a976cb921d2991a043e0363e4
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=41ce4a01583d552a976cb921d2991a043e0363e4

Author: Vitaliy Margolen <wine-patches at kievinfo.com>
Date:   Sun Jul 15 10:40:00 2007 -0600

dinput: Use CALLWINDPROC hook to monitor focus loses away from acquired windows.

---

 dlls/dinput/dinput_main.c |   58 +++++++++++++++++++++++++++++++++++++++++++++
 dlls/dinput/tests/mouse.c |    1 -
 2 files changed, 58 insertions(+), 1 deletions(-)

diff --git a/dlls/dinput/dinput_main.c b/dlls/dinput/dinput_main.c
index 5052829..4f15c58 100644
--- a/dlls/dinput/dinput_main.c
+++ b/dlls/dinput/dinput_main.c
@@ -848,6 +848,41 @@ static LRESULT CALLBACK LL_hook_proc( int code, WPARAM wparam, LPARAM lparam )
     return CallNextHookEx( 0, code, wparam, lparam );
 }
 
+static LRESULT CALLBACK callwndproc_proc( int code, WPARAM wparam, LPARAM lparam )
+{
+    CWPSTRUCT *msg = (CWPSTRUCT *)lparam;
+    IDirectInputImpl *dinput;
+    HWND foreground;
+
+    if (code != HC_ACTION || msg->message != WM_KILLFOCUS)
+        return CallNextHookEx( 0, code, wparam, lparam );
+
+    foreground = GetForegroundWindow();
+
+    EnterCriticalSection( &dinput_hook_crit );
+
+    LIST_FOR_EACH_ENTRY( dinput, &direct_input_list, IDirectInputImpl, entry )
+    {
+        IDirectInputDevice2AImpl *dev;
+
+        EnterCriticalSection( &dinput->crit );
+        LIST_FOR_EACH_ENTRY( dev, &dinput->devices_list, IDirectInputDevice2AImpl, entry )
+        {
+            if (!dev->acquired) continue;
+
+            if (msg->hwnd == dev->win && msg->hwnd != foreground)
+            {
+                TRACE( "%p window is not foreground - unacquiring %p\n", dev->win, dev );
+                IDirectInputDevice_Unacquire( (LPDIRECTINPUTDEVICE8A)dev );
+            }
+        }
+        LeaveCriticalSection( &dinput->crit );
+    }
+    LeaveCriticalSection( &dinput_hook_crit );
+
+    return CallNextHookEx( 0, code, wparam, lparam );
+}
+
 static DWORD WINAPI hook_thread_proc(void *param)
 {
     static HHOOK kbd_hook, mouse_hook;
@@ -976,7 +1011,30 @@ static BOOL check_hook_thread(void)
 
 void check_dinput_hooks(LPDIRECTINPUTDEVICE8A iface)
 {
+    static HHOOK callwndproc_hook;
+    static ULONG foreground_cnt;
+    IDirectInputDevice2AImpl *dev = (IDirectInputDevice2AImpl *)iface;
+
     EnterCriticalSection(&dinput_hook_crit);
+
+    if (dev->dwCoopLevel & DISCL_FOREGROUND)
+    {
+        if (dev->acquired)
+            foreground_cnt++;
+        else
+            foreground_cnt--;
+    }
+
+    if (foreground_cnt && !callwndproc_hook)
+        callwndproc_hook = SetWindowsHookExW( WH_CALLWNDPROC, callwndproc_proc,
+                                              DINPUT_instance, GetCurrentThreadId() );
+    else if (!foreground_cnt && callwndproc_hook)
+    {
+        UnhookWindowsHookEx( callwndproc_hook );
+        callwndproc_hook = NULL;
+    }
+
     PostThreadMessageW( hook_thread_id, WM_USER+0x10, 1, 0 );
+
     LeaveCriticalSection(&dinput_hook_crit);
 }
diff --git a/dlls/dinput/tests/mouse.c b/dlls/dinput/tests/mouse.c
index 0f9c88b..3ea2147 100644
--- a/dlls/dinput/tests/mouse.c
+++ b/dlls/dinput/tests/mouse.c
@@ -95,7 +95,6 @@ static void test_acquire(LPDIRECTINPUT pDI, HWND hwnd)
     SetActiveWindow( 0 );
 
     hr = IDirectInputDevice_GetDeviceState(pMouse, sizeof(m_state), &m_state);
-    todo_wine
     ok(hr == DIERR_NOTACQUIRED, "GetDeviceState() should have failed: %s\n", DXGetErrorString8(hr));
     /* Workaround so we can test other things. Remove when Wine is fixed */
     IDirectInputDevice_Unacquire(pMouse);




More information about the wine-cvs mailing list