--- gdk/x11/gdkdisplay-x11.h	2006/05/05 16:16:18	1.1
+++ gdk/x11/gdkdisplay-x11.h	2006/05/05 21:46:06
@@ -81,6 +81,11 @@ struct _GdkDisplayX11
   gboolean have_xfixes;
   gint xfixes_event_base;
 
+  /* If the SECURITY extension is in place, whether this client holds 
+   * a trusted authorization and so is allowed to make various requests 
+   * (grabs, properties etc.) Otherwise always TRUE. */
+  gboolean trusted_client;
+
   /* Information about current pointer and keyboard grabs held by this
    * client. If gdk_pointer_xgrab_window or gdk_keyboard_xgrab_window
    * window is NULL, then the other associated fields are ignored
--- gdk/x11/gdkdisplay-x11.c	2006/05/05 16:14:19	1.1
+++ gdk/x11/gdkdisplay-x11.c	2006/05/07 00:48:04
@@ -224,6 +224,21 @@ gdk_display_open (const gchar *display_n
 #endif
   display_x11->have_xfixes = FALSE;
 
+  display_x11->trusted_client = TRUE;
+  {
+    Window root, child;
+    int rootx, rooty, winx, winy;
+    unsigned int xmask;
+
+    gdk_error_trap_push ();
+    XQueryPointer (display_x11->xdisplay, 
+		   GDK_SCREEN_X11 (display_x11->default_screen)->xroot_window,
+		   &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
+    gdk_flush ();
+    if (G_UNLIKELY (gdk_error_trap_pop () == BadWindow))
+      display_x11->trusted_client = FALSE;
+  }
+
   if (_gdk_synchronize)
     XSynchronize (display_x11->xdisplay, True);
   
--- gdk/x11/gdkwindow-x11.c	2006/05/05 02:19:48	1.1
+++ gdk/x11/gdkwindow-x11.c	2006/05/07 00:47:49
@@ -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,24 @@ _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),
-		 &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
+  if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client)) {
+    XQueryPointer (xdisplay, xwindow,
+		   &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
+  } else {
+    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,14 +3438,25 @@ _gdk_windowing_window_get_pointer (GdkDi
   _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
 
   return_val = NULL;
-  if (!GDK_WINDOW_DESTROYED (window) &&
-      XQueryPointer (GDK_WINDOW_XDISPLAY (window),
-		     GDK_WINDOW_XID (window),
-		     &root, &child, &rootx, &rooty, &winx, &winy, &xmask))
-    {
-      if (child)
-	return_val = gdk_window_lookup_for_display (GDK_WINDOW_DISPLAY (window), child);
+  if (!GDK_WINDOW_DESTROYED (window)) {
+    if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client)) {
+      if (XQueryPointer (GDK_WINDOW_XDISPLAY (window),
+			 GDK_WINDOW_XID (window),
+			 &root, &child, &rootx, &rooty, &winx, &winy, &xmask))
+	{
+	  if (child)
+	    return_val = gdk_window_lookup_for_display (GDK_WINDOW_DISPLAY (window), child);
+	}
+    } else {
+      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 +3528,83 @@ _gdk_windowing_window_at_pointer (GdkDis
    * and the result.
    */
   gdk_x11_display_grab (display);
-  XQueryPointer (xdisplay, xwindow,
-		 &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
+  if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client)) {
+    XQueryPointer (xdisplay, xwindow,
+		   &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
+    if (root == xwindow)
+      xwindow = child;
+    else
+      xwindow = root;
 
-  if (root == xwindow)
-    xwindow = child;
-  else
-    xwindow = root;
-  
-  while (xwindow)
+    while (xwindow)
+      {
+	xwindow_last = xwindow;
+	XQueryPointer (xdisplay, xwindow,
+		       &root, &xwindow, &rootx, &rooty, &winx, &winy, &xmask);
+      }
+  } else {
+    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;
+
+    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;
 
--- gdk/x11/gdkmain-x11.c	2006/05/05 21:06:32	1.1
+++ gdk/x11/gdkmain-x11.c	2006/05/07 00:49:30
@@ -191,6 +191,7 @@ gdk_pointer_grab (GdkWindow *	  window,
 {
   gint return_val;
   GdkCursorPrivate *cursor_private;
+  GdkDisplayX11 *display_x11;
   guint xevent_mask;
   Window xwindow;
   Window xconfine_to;
@@ -202,6 +203,8 @@ gdk_pointer_grab (GdkWindow *	  window,
   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
   g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
   
+  display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
+
   cursor_private = (GdkCursorPrivate*) cursor;
   
   xwindow = GDK_WINDOW_XID (window);
@@ -233,7 +236,8 @@ gdk_pointer_grab (GdkWindow *	  window,
 					confine_to,
 					time);
 
-  if (return_val == GrabSuccess)
+  if (return_val == GrabSuccess || 
+      G_UNLIKELY (!display_x11->trusted_client && return_val == AlreadyGrabbed))
     {
       if (!GDK_WINDOW_DESTROYED (window))
 	{
@@ -257,7 +261,6 @@ gdk_pointer_grab (GdkWindow *	  window,
   
   if (return_val == GrabSuccess)
     {
-      GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
       if (display_x11->pointer_xgrab_window != NULL &&
 	  display_x11->pointer_xgrab_window != (GdkWindowObject *)window)
 	generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_xgrab_window),
@@ -338,10 +341,13 @@ gdk_keyboard_grab (GdkWindow *	   window
 {
   gint return_val;
   unsigned long serial;
+  GdkDisplayX11 *display_x11;
   
   g_return_val_if_fail (window != NULL, 0);
   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
   
+  display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
+
   serial = NextRequest (GDK_WINDOW_XDISPLAY (window));
 
   if (!GDK_WINDOW_DESTROYED (window))
@@ -356,13 +362,16 @@ gdk_keyboard_grab (GdkWindow *	   window
 				    owner_events,
 				    GrabModeAsync, GrabModeAsync,
 				    time);
+	if (G_UNLIKELY (!display_x11->trusted_client && 
+			return_val == AlreadyGrabbed))
+	  /* we can't grab the keyboard, but we can do a GTK-local grab */
+	  return_val = GrabSuccess;
     }
   else
     return_val = AlreadyGrabbed;
 
   if (return_val == GrabSuccess)
     {
-      GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (gdk_drawable_get_display (window));
       if (display_x11->keyboard_xgrab_window != NULL &&
 	  display_x11->keyboard_xgrab_window != (GdkWindowObject *)window)
 	generate_grab_broken_event (GDK_WINDOW (display_x11->keyboard_xgrab_window),
--- gtk/gtkmenu.c	2006/05/05 21:49:49	1.1
+++ gtk/gtkmenu.c	2006/05/07 00:50:45
@@ -229,7 +229,8 @@ static void gtk_menu_remove         (Gtk
 static void gtk_menu_update_title   (GtkMenu           *menu);
 
 static void       menu_grab_transfer_window_destroy (GtkMenu *menu);
-static GdkWindow *menu_grab_transfer_window_get     (GtkMenu *menu);
+static GdkWindow *menu_grab_transfer_window_get     (GtkMenu *menu,
+						     gboolean input_output);
 
 static gboolean gtk_menu_real_can_activate_accel (GtkWidget *widget,
                                                   guint      signal_id);
@@ -1223,19 +1224,21 @@ gtk_menu_tearoff_bg_copy (GtkMenu *menu)
 }
 
 static gboolean
-popup_grab_on_window (GdkWindow *window,
-		      guint32    activate_time,
-		      gboolean   grab_keyboard)
-{
-  if ((gdk_pointer_grab (window, TRUE,
-			 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
-			 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
-			 GDK_POINTER_MOTION_MASK,
-			 NULL, NULL, activate_time) == 0))
+popup_grab_on_window (GdkWindow     *window,
+		      guint32        activate_time,
+		      gboolean       grab_keyboard,
+		      GdkGrabStatus *grab_status)
+{
+  if (((*grab_status = gdk_pointer_grab (window, TRUE,
+	    				 GDK_BUTTON_PRESS_MASK | 
+					 GDK_BUTTON_RELEASE_MASK |
+					 GDK_ENTER_NOTIFY_MASK | 
+					 GDK_LEAVE_NOTIFY_MASK |
+					 GDK_POINTER_MOTION_MASK,
+					 NULL, NULL, activate_time)) == 0))
     {
       if (!grab_keyboard ||
-	  gdk_keyboard_grab (window, TRUE,
-			     activate_time) == 0)
+	  (*grab_status = gdk_keyboard_grab (window, TRUE, activate_time)) == 0)
 	return TRUE;
       else
 	{
@@ -1290,6 +1293,7 @@ gtk_menu_popup (GtkMenu		    *menu,
   GtkMenuShell *menu_shell;
   gboolean grab_keyboard;
   GtkMenuPrivate *priv;
+  GdkGrabStatus grab_status;
 
   g_return_if_fail (GTK_IS_MENU (menu));
 
@@ -1346,7 +1350,8 @@ gtk_menu_popup (GtkMenu		    *menu,
 
   if (xgrab_shell && xgrab_shell != widget)
     {
-      if (popup_grab_on_window (xgrab_shell->window, activate_time, grab_keyboard))
+      if (popup_grab_on_window (xgrab_shell->window, activate_time, 
+	    			grab_keyboard, &grab_status))
 	GTK_MENU_SHELL (xgrab_shell)->have_xgrab = TRUE;
     }
   else
@@ -1354,9 +1359,17 @@ gtk_menu_popup (GtkMenu		    *menu,
       GdkWindow *transfer_window;
 
       xgrab_shell = widget;
-      transfer_window = menu_grab_transfer_window_get (menu);
-      if (popup_grab_on_window (transfer_window, activate_time, grab_keyboard))
+      transfer_window = menu_grab_transfer_window_get (menu, FALSE);
+      if (popup_grab_on_window (transfer_window, activate_time, 
+	    			grab_keyboard, &grab_status))
 	GTK_MENU_SHELL (xgrab_shell)->have_xgrab = TRUE;
+      else if (G_UNLIKELY (grab_status == GDK_GRAB_NOT_VIEWABLE)) {
+      	menu_grab_transfer_window_destroy (menu);
+      	transfer_window = menu_grab_transfer_window_get (menu, TRUE);
+	if (popup_grab_on_window (transfer_window, activate_time, 
+				  grab_keyboard, &grab_status))
+	  GTK_MENU_SHELL (xgrab_shell)->have_xgrab = TRUE;
+      }
     }
 
   if (!GTK_MENU_SHELL (xgrab_shell)->have_xgrab)
@@ -1447,7 +1460,8 @@ gtk_menu_popup (GtkMenu		    *menu,
   gtk_widget_show (menu->toplevel);
 
   if (xgrab_shell == widget)
-    popup_grab_on_window (widget->window, activate_time, grab_keyboard); /* Should always succeed */
+    popup_grab_on_window (widget->window, activate_time, grab_keyboard, 
+			  &grab_status); /* Should always succeed */
   gtk_grab_add (GTK_WIDGET (menu));
 }
 
@@ -2096,7 +2110,8 @@ gtk_menu_focus (GtkWidget       *widget,
 /* See notes in gtk_menu_popup() for information about the "grab transfer window"
  */
 static GdkWindow *
-menu_grab_transfer_window_get (GtkMenu *menu)
+menu_grab_transfer_window_get (GtkMenu *menu,
+			       gboolean input_output)
 {
   GdkWindow *window = g_object_get_data (G_OBJECT (menu), "gtk-menu-transfer-window");
   if (!window)
@@ -2109,7 +2124,7 @@ menu_grab_transfer_window_get (GtkMenu *
       attributes.width = 10;
       attributes.height = 10;
       attributes.window_type = GDK_WINDOW_TEMP;
-      attributes.wclass = GDK_INPUT_ONLY;
+      attributes.wclass = input_output ? GDK_INPUT_OUTPUT : GDK_INPUT_ONLY;
       attributes.override_redirect = TRUE;
       attributes.event_mask = 0;
 
--- gtk/gtkdnd.c	2006/05/06 03:52:20	1.1
+++ gtk/gtkdnd.c	2006/05/06 14:56:46
@@ -334,6 +334,39 @@ get_can_change_screen (GtkWidget *widget
 
 }
 
+static void
+gtk_drag_ipc_widget_make_viewable (GtkWidget *widget)
+{
+  GdkWindowAttr attributes;
+  gint attributes_mask;
+
+  if (!GTK_WIDGET_REALIZED (widget))
+    gtk_widget_realize (widget);
+
+  g_object_unref (widget->window);
+  gtk_style_detach (widget->style);
+
+  attributes.x = -100;
+  attributes.y = -100;
+  attributes.width = 10;
+  attributes.height = 10;
+  attributes.window_type = GDK_WINDOW_TEMP;
+  attributes.wclass = GDK_INPUT_OUTPUT;
+  attributes.override_redirect = TRUE;
+  attributes.event_mask = gtk_widget_get_events (widget);
+
+  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_NOREDIR;
+
+  widget->window = gdk_window_new (gtk_widget_get_root_window (widget),
+				   &attributes, attributes_mask);
+					      
+  gdk_window_set_user_data (widget->window, widget);
+  
+  widget->style = gtk_style_attach (widget->style, widget->window);
+
+  gdk_window_show_unraised (widget->window);
+}
+
 /*************************************************************
  * gtk_drag_get_ipc_widget:
  *     Return a invisible, off-screen, override-redirect
@@ -2112,13 +2145,25 @@ gtk_drag_begin_internal (GtkWidget      
   if (event)
     time = gdk_event_get_time (event);
 
-  if (gdk_pointer_grab (ipc_widget->window, FALSE,
-			GDK_POINTER_MOTION_MASK |
-			GDK_BUTTON_RELEASE_MASK, NULL,
-			cursor, time) != GDK_GRAB_SUCCESS)
+  switch (gdk_pointer_grab (ipc_widget->window, FALSE,
+			    GDK_POINTER_MOTION_MASK |
+			    GDK_BUTTON_RELEASE_MASK, NULL,
+			    cursor, time))
     {
-      gtk_drag_release_ipc_widget (ipc_widget);
-      return NULL;
+      case GDK_GRAB_SUCCESS:
+	break;
+
+      case GDK_GRAB_NOT_VIEWABLE:
+	gtk_drag_ipc_widget_make_viewable (ipc_widget);
+	if (gdk_pointer_grab (ipc_widget->window, FALSE,
+			      GDK_POINTER_MOTION_MASK |
+			      GDK_BUTTON_RELEASE_MASK, NULL,
+			      cursor, time) == GDK_GRAB_SUCCESS)
+	  break;
+
+      default:
+	gtk_drag_release_ipc_widget (ipc_widget);
+	return NULL;
     }
 
   gdk_keyboard_grab (ipc_widget->window, FALSE, time);
--- gdk/x11/gdkdnd-x11.c	2006/05/06 15:10:02	1.1
+++ gdk/x11/gdkdnd-x11.c	2006/05/07 00:51:57
@@ -489,6 +489,24 @@ gdk_window_cache_new (GdkScreen *screen)
 
   XGetWindowAttributes (xdisplay, GDK_WINDOW_XWINDOW (root_window), &xwa);
   result->old_event_mask = xwa.your_event_mask;
+
+  if (G_UNLIKELY (!GDK_DISPLAY_X11 (GDK_SCREEN_X11 (screen)->display)->trusted_client)) {
+    GList *toplevel_windows, *list;
+    GdkWindow *window;
+    gint x, y, width, height;
+    
+    toplevel_windows = gdk_screen_get_toplevel_windows (screen);
+    for (list = toplevel_windows; list; list = list->next) {
+      window = GDK_WINDOW (list->data);
+      gdk_window_get_geometry (window, &x, &y, &width, &height, NULL);
+      gdk_window_cache_add (result, GDK_WINDOW_XID (window), 
+			    x, y, width, height, 
+			    gdk_window_is_visible (window));
+    }
+    g_list_free (toplevel_windows);
+    return result;
+  }
+
   XSelectInput (xdisplay, GDK_WINDOW_XWINDOW (root_window),
 		result->old_event_mask | SubstructureNotifyMask);
   gdk_window_add_filter (root_window, gdk_window_cache_filter, result);
