--- gdk/x11/gdkwindow-x11.c	2006/03/30 03:49:42	1.1
+++ gdk/x11/gdkwindow-x11.c	2006/03/31 03:08:27
@@ -3374,6 +3374,8 @@ _gdk_windowing_get_pointer (GdkDisplay  
 			    GdkModifierType  *mask)
 {
   GdkScreen *default_screen;
+  Display *xdisplay;
+  Window xwindow;
   Window root = None;
   Window child;
   int rootx, rooty;
@@ -3385,10 +3387,26 @@ _gdk_windowing_get_pointer (GdkDisplay  
     return;
 
   default_screen = gdk_display_get_default_screen (display);
+
+  xdisplay = GDK_SCREEN_XDISPLAY (default_screen);
+  xwindow = GDK_SCREEN_XROOTWIN (default_screen);
   
-  XQueryPointer (GDK_SCREEN_XDISPLAY (default_screen),
-		 GDK_SCREEN_XROOTWIN (default_screen),
+  gdk_error_trap_push ();
+  XQueryPointer (xdisplay, xwindow,
 		 &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
+  gdk_flush ();
+  if (gdk_error_trap_pop ()) {
+    /* BadWindow on root: are we running untrusted? */
+    XSetWindowAttributes attributes;
+    Window w;
+
+    w = XCreateWindow (xdisplay, xwindow, 0, 0, 1, 1, 0, 
+		       CopyFromParent, InputOnly, CopyFromParent, 
+		       0, &attributes);
+    XQueryPointer (xdisplay, w, 
+		   &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
+    XDestroyWindow (xdisplay, w);
+  }
   
   if (root != None)
     {
@@ -3422,6 +3440,7 @@ _gdk_windowing_window_get_pointer (GdkDi
   _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
 
   return_val = NULL;
+  gdk_error_trap_push ();
   if (!GDK_WINDOW_DESTROYED (window) &&
       XQueryPointer (GDK_WINDOW_XDISPLAY (window),
 		     GDK_WINDOW_XID (window),
@@ -3430,6 +3449,17 @@ _gdk_windowing_window_get_pointer (GdkDi
       if (child)
 	return_val = gdk_window_lookup_for_display (GDK_WINDOW_DISPLAY (window), child);
     }
+  gdk_flush ();
+  if (gdk_error_trap_pop ()) {
+    /* BadWindow: are we running untrusted? */
+    GdkScreen *screen;
+    int originx, originy;
+    _gdk_windowing_get_pointer (gdk_drawable_get_display (window), &screen, 
+				&rootx, &rooty, &xmask);
+    gdk_window_get_origin (window, &originx, &originy);
+    winx = rootx - originx;
+    winy = rooty - originy;
+  }
   
   *x = winx + xoffset;
   *y = winy + yoffset;
@@ -3501,24 +3531,78 @@ _gdk_windowing_window_at_pointer (GdkDis
    * and the result.
    */
   gdk_x11_display_grab (display);
+  gdk_error_trap_push ();
   XQueryPointer (xdisplay, xwindow,
 		 &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
-
-  if (root == xwindow)
-    xwindow = child;
-  else
-    xwindow = root;
+  gdk_flush ();
+  if (gdk_error_trap_pop ()) {
+    /* BadWindow on root: are we running untrusted? */
+    gint i, screens, width, height;
+    GList *toplevels, *list;
+    Window pointer_window;
+
+    pointer_window = None;
+    screens = gdk_display_get_n_screens (display);
+    for (i = 0; i < screens; ++i) {
+      screen = gdk_display_get_screen (display, i);
+      toplevels = gdk_screen_get_toplevel_windows (screen);
+      for (list = toplevels; list != NULL; list = g_list_next (list)) {
+	window = GDK_WINDOW (list->data);
+	xwindow = GDK_WINDOW_XWINDOW (window);
+	gdk_error_trap_push ();
+	XQueryPointer (xdisplay, xwindow,
+		       &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
+	gdk_flush ();
+	if (gdk_error_trap_pop ())
+	  continue;
+	if (child != None) {
+	  pointer_window = child;
+	  break;
+	}
+	gdk_window_get_geometry (window, NULL, NULL, &width, &height, NULL);
+	if (winx >= 0 && winy >= 0 && winx < width && winy < height) {
+	  /* A childless toplevel, or below another window? */
+	  XSetWindowAttributes attributes;
+	  Window w;
+
+	  w = XCreateWindow (xdisplay, xwindow, winx, winy, 1, 1, 0, 
+			     CopyFromParent, InputOnly, CopyFromParent, 
+			     0, &attributes);
+	  XMapWindow (xdisplay, w);
+	  XQueryPointer (xdisplay, xwindow, 
+			 &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
+	  XDestroyWindow (xdisplay, w);
+	  if (child == w) {
+	    pointer_window = xwindow;
+	    break;
+	  }
+	}
+      }
+      g_list_free (toplevels);
+      if (pointer_window != None)
+	break;
+    }
+    xwindow = pointer_window;
+  } else {
+    if (root == xwindow)
+      xwindow = child;
+    else
+      xwindow = root;
+  }
   
   while (xwindow)
     {
       xwindow_last = xwindow;
+      gdk_error_trap_push ();
       XQueryPointer (xdisplay, xwindow,
 		     &root, &xwindow, &rootx, &rooty, &winx, &winy, &xmask);
+      gdk_flush ();
+      if (gdk_error_trap_pop ())
+	break;
     }
   gdk_x11_display_ungrab (display);
 
-  window = gdk_window_lookup_for_display (GDK_SCREEN_DISPLAY(screen),
-					  xwindow_last);
+  window = gdk_window_lookup_for_display (display, xwindow_last);
   *win_x = window ? winx : -1;
   *win_y = window ? winy : -1;
 
