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

diff --git a/dlls/x11drv/x11ddraw.c b/dlls/x11drv/x11ddraw.c
index 6e6367b..75447c3 100644
--- a/dlls/x11drv/x11ddraw.c
+++ b/dlls/x11drv/x11ddraw.c
@@ -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, 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, CurrentTime);
-  }
-  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, 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)->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 +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;