DXGrab fix

Jukka Heinonen jhei at iki.fi
Sat Aug 4 04:55:50 CDT 2001


After this patch DXGrab should work again.

The patch still has a potential for incorrect behaviour,
if an application wants to change window procedure at 
the same time we call SendMessage, but I would be surprised 
if any application did something like that. Fixing this
problem would be pretty complicated so I hope the current
behaviour (print error message) is good enough until
that kind of application turns out.

XSetInputFocus was added because Wine seems to lose
keyboard focus somewhere, which old Wine versions didn't do.

Changelog: XGrabPointer is now called from correct thread context.
           Added XSetInputFocus after XGrabPointer.

Index: wine/dlls/x11drv/x11ddraw.c
===================================================================
RCS file: /home/wine/wine/dlls/x11drv/x11ddraw.c,v
retrieving revision 1.9
diff -u -r1.9 x11ddraw.c
--- wine/dlls/x11drv/x11ddraw.c 2001/06/04 21:55:17     1.9
+++ wine/dlls/x11drv/x11ddraw.c 2001/08/04 09:33:07
@@ -31,6 +31,8 @@
 Drawable X11DRV_DD_PrimaryDrawable;
 ATOM X11DRV_DD_UserClass;
 BOOL X11DRV_DD_IsDirect;
+static UINT X11DRV_DD_GrabMessage;
+static WNDPROC X11DRV_DD_GrabOldProcedure;
 
 static void SetPrimaryDIB(HBITMAP hBmp)
 {
@@ -45,20 +47,64 @@
   }
 }
 
-static void GrabPointer(HWND hWnd)
-{
+static LRESULT WINAPI GrabWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 
+{ 
   Display *display = thread_display();
-  if (hWnd) {
-    /* find the X11 window that ddraw uses */
-    Window win = X11DRV_get_whole_window(hWnd);
-    TRACE("WND: %x win: %ld\n", hWnd, win);
-    if (!win) {
-      TRACE("host off desktop\n");
-      win = root_window;
-    }
-    TSXGrabPointer(display, win, True, 0, GrabModeAsync, GrabModeAsync, win, None, Curre
ntTime);
-  }
-  else TSXUngrabPointer(display, CurrentTime);
+
+  if(message != X11DRV_DD_GrabMessage)
+    return CallWindowProcA(X11DRV_DD_GrabOldProcedure, hWnd, message, wParam, lParam);
+ 
+  TRACE("hwnd=%d, grab=%d\n", hWnd, wParam);
+ 
+  if (wParam) 
+  {  
+    /* find the X11 window that ddraw uses */  
+    Window win = X11DRV_get_whole_window(hWnd);  
+    TRACE("X11 window: %ld\n", win);  
+    if (!win) {  
+      TRACE("host off desktop\n");  
+      win = root_window;  
+    }  
+
+    TSXGrabPointer(display, win, True, 0, GrabModeAsync, GrabModeAsync, win, None, Curre
ntTime);  
+    TSXSetInputFocus(display, win, RevertToParent, CurrentTime);
+  }  
+  else 
+  {
+    TSXUngrabPointer(display, CurrentTime);  
+  } 
+
+  return 0; 
+} 
+
+static void GrabPointer(BOOL grab)
+{
+  WND*    pWnd;
+
+  if(!X11DRV_DD_GrabMessage)
+    X11DRV_DD_GrabMessage = RegisterWindowMessageA("WINE_X11DRV_GRABPOINTER");
+
+  pWnd = WIN_FindWndPtr(X11DRV_DD_PrimaryWnd);
+  if(!pWnd)
+    return;
+
+  X11DRV_DD_GrabOldProcedure = pWnd->winproc;
+  pWnd->winproc = GrabWndProc;
+
+  WIN_ReleaseWndPtr(pWnd);
+
+  SendMessageA(X11DRV_DD_PrimaryWnd, X11DRV_DD_GrabMessage, grab ? 1 : 0, 0);
+
+  pWnd = WIN_FindWndPtr(X11DRV_DD_PrimaryWnd); 
+  if(!pWnd)
+    return;
+
+  if(pWnd->winproc != GrabWndProc)
+    ERR("Window procedure has been changed!\n");
+  else
+    pWnd->winproc = X11DRV_DD_GrabOldProcedure;
+  
+  WIN_ReleaseWndPtr(pWnd); 
 }
 
 static DWORD PASCAL X11DRV_DDHAL_DestroyDriver(LPDDHAL_DESTROYDRIVERDATA data)
@@ -75,7 +121,7 @@
     X11DRV_DD_PrimaryGbl = X11DRV_DD_Primary->lpGbl;
     SetPrimaryDIB(GET_LPDDRAWSURFACE_GBL_MORE(X11DRV_DD_PrimaryGbl)->hKernelSurface);
     X11DRV_DD_UserClass = GlobalFindAtomA("WINE_DDRAW");
-    if (dxgrab) GrabPointer(X11DRV_DD_PrimaryWnd);
+    if (dxgrab) GrabPointer(TRUE);
   }
   data->ddRVal = DD_OK;
   return DDHAL_DRIVER_NOTHANDLED;
@@ -108,12 +154,12 @@
 static DWORD PASCAL X11DRV_DDHAL_DestroySurface(LPDDHAL_DESTROYSURFACEDATA data)
 {
   if (data->lpDDSurface == X11DRV_DD_Primary) {
+    if (dxgrab) GrabPointer(FALSE);
     X11DRV_DD_Primary = NULL;
     X11DRV_DD_PrimaryWnd = 0;
     X11DRV_DD_PrimaryGbl = NULL;
     SetPrimaryDIB(0);
     X11DRV_DD_UserClass = 0;
-    if (dxgrab) GrabPointer(0);
   }
   data->ddRVal = DD_OK;
   return DDHAL_DRIVER_HANDLED;

-- 
Jukka Heinonen <http://www.iki.fi/jhei/>




More information about the wine-patches mailing list