DXGrab fix, second try

Jukka Heinonen jhei at iki.fi
Sat Aug 4 08:45:32 CDT 2001


After I tested my patch in another application, I found
out that I was setting keyboard focus to a wrong window.
This would for some reason mess up the window stacking order.
Possibly window manager had something to do with that.

The following patch should correctly make sure that
when we use DirextX with DXGrab turned on, 
we always have keyboard focus.

Changelog: XGrabPointer is now called from the correct thread context and
           it is made sure that we have keyboard focus when using DirectX.           

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 13:26:19
@@ -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,69 @@
   }
 }
 
-static void GrabPointer(HWND hWnd)
-{
+static LRESULT WINAPI GrabWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARA
M 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, No
ne, CurrentTime);
-  }
-  else TSXUngrabPointer(display, CurrentTime);
+
+  if(message != X11DRV_DD_GrabMessage)
+    return CallWindowProcA(X11DRV_DD_GrabOldProcedure, hWnd, message, wParam, l
Param);
+ 
+  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, No
ne, CurrentTime);  
+  }  
+  else 
+  {
+    TSXUngrabPointer(display, CurrentTime);  
+  } 
+
+  return 0; 
+} 
+
+static void GrabPointer(BOOL grab)
+{
+  WND*    pWnd;
+
+  if(grab) { 
+    Window window = X11DRV_get_whole_window(GetFocus()); 
+    if(window)
+      XSetInputFocus(thread_display(), window, RevertToParent, CurrentTime); 
+  } 
+
+  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 +126,7 @@
     X11DRV_DD_PrimaryGbl = X11DRV_DD_Primary->lpGbl;
     SetPrimaryDIB(GET_LPDDRAWSURFACE_GBL_MORE(X11DRV_DD_PrimaryGbl)->hKernelSur
face);
     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 +159,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