]> Pileus Git - ~andy/gtk/blobdiff - gdk/x11/gdkwindow-x11.c
Zero out some stack-allocated X structures, to avoid valgrind warnings
[~andy/gtk] / gdk / x11 / gdkwindow-x11.c
index f96e693e876591f6af06b1f4a1abc4fb6cc4ca66..2a71b22ada3f302c5e439679ed40f6c00268d2f8 100644 (file)
@@ -83,12 +83,12 @@ const int _gdk_nenvent_masks = sizeof (_gdk_event_mask_table) / sizeof (int);
 /* Forward declarations */
 static void     gdk_window_set_static_win_gravity (GdkWindow  *window,
                                                   gboolean    on);
-static gboolean gdk_window_have_shape_ext         (GdkDisplay *display);
 static gboolean gdk_window_icon_name_set          (GdkWindow  *window);
 static void     gdk_window_add_colormap_windows   (GdkWindow  *window);
 static void     set_wm_name                       (GdkDisplay  *display,
                                                   Window       xwindow,
                                                   const gchar *name);
+static void     move_to_current_desktop           (GdkWindow *window);
 
 static GdkColormap* gdk_window_impl_x11_get_colormap (GdkDrawable *drawable);
 static void         gdk_window_impl_x11_set_colormap (GdkDrawable *drawable,
@@ -97,12 +97,8 @@ static void         gdk_window_impl_x11_get_size    (GdkDrawable *drawable,
                                                     gint *width,
                                                     gint *height);
 static GdkRegion*  gdk_window_impl_x11_get_visible_region (GdkDrawable *drawable);
-static void gdk_window_impl_x11_init       (GdkWindowImplX11      *window);
-static void gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass);
 static void gdk_window_impl_x11_finalize   (GObject            *object);
 
-static gpointer parent_class = NULL;
-
 #define WINDOW_IS_TOPLEVEL(window)                \
   (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
    GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
@@ -115,33 +111,7 @@ static gpointer parent_class = NULL;
     (( time1 < time2 ) && ( time2 - time1 > ((guint32)-1)/2 ))     \
   )
 
-GType
-gdk_window_impl_x11_get_type (void)
-{
-  static GType object_type = 0;
-
-  if (!object_type)
-    {
-      static const GTypeInfo object_info =
-      {
-        sizeof (GdkWindowImplX11Class),
-        (GBaseInitFunc) NULL,
-        (GBaseFinalizeFunc) NULL,
-        (GClassInitFunc) gdk_window_impl_x11_class_init,
-        NULL,           /* class_finalize */
-        NULL,           /* class_data */
-        sizeof (GdkWindowImplX11),
-        0,              /* n_preallocs */
-        (GInstanceInitFunc) gdk_window_impl_x11_init,
-      };
-      
-      object_type = g_type_register_static (GDK_TYPE_DRAWABLE_IMPL_X11,
-                                            g_intern_static_string ("GdkWindowImplX11"),
-                                            &object_info, 0);
-    }
-  
-  return object_type;
-}
+G_DEFINE_TYPE (GdkWindowImplX11, gdk_window_impl_x11, GDK_TYPE_DRAWABLE_IMPL_X11)
 
 GType
 _gdk_window_impl_get_type (void)
@@ -183,8 +153,6 @@ gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
   
-  parent_class = g_type_class_peek_parent (klass);
-
   object_class->finalize = gdk_window_impl_x11_finalize;
 
   drawable_class->set_colormap = gdk_window_impl_x11_set_colormap;
@@ -227,7 +195,7 @@ gdk_window_impl_x11_finalize (GObject *object)
   if (window_impl->cursor)
     gdk_cursor_unref (window_impl->cursor);
 
-  G_OBJECT_CLASS (parent_class)->finalize (object);
+  G_OBJECT_CLASS (gdk_window_impl_x11_parent_class)->finalize (object);
 }
 
 static void
@@ -290,6 +258,13 @@ tmp_reset_bg (GdkWindow *window)
     }
 }
 
+/* Unsetting and resetting window backgrounds.
+ *
+ * In many cases it is possible to avoid flicker by unsetting the
+ * background of windows. For example if the background of the
+ * parent window is unset when a window is unmapped, a brief flicker
+ * of background painting is avoided.
+ */
 void
 _gdk_x11_window_tmp_unset_bg (GdkWindow *window,
                              gboolean   recurse)
@@ -358,12 +333,10 @@ static GdkColormap*
 gdk_window_impl_x11_get_colormap (GdkDrawable *drawable)
 {
   GdkDrawableImplX11 *drawable_impl;
-  GdkWindowImplX11 *window_impl;
   
   g_return_val_if_fail (GDK_IS_WINDOW_IMPL_X11 (drawable), NULL);
 
   drawable_impl = GDK_DRAWABLE_IMPL_X11 (drawable);
-  window_impl = GDK_WINDOW_IMPL_X11 (drawable);
 
   if (!((GdkWindowObject *) drawable_impl->wrapper)->input_only && 
       drawable_impl->colormap == NULL)
@@ -388,19 +361,17 @@ static void
 gdk_window_impl_x11_set_colormap (GdkDrawable *drawable,
                                   GdkColormap *cmap)
 {
-  GdkWindowImplX11 *impl;
   GdkDrawableImplX11 *draw_impl;
   
   g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (drawable));
 
-  impl = GDK_WINDOW_IMPL_X11 (drawable);
   draw_impl = GDK_DRAWABLE_IMPL_X11 (drawable);
 
   if (cmap && GDK_WINDOW_DESTROYED (draw_impl->wrapper))
     return;
 
   /* chain up */
-  GDK_DRAWABLE_CLASS (parent_class)->set_colormap (drawable, cmap);
+  GDK_DRAWABLE_CLASS (gdk_window_impl_x11_parent_class)->set_colormap (drawable, cmap);
 
   if (cmap)
     {
@@ -761,6 +732,17 @@ gdk_window_new (GdkWindow     *parent,
   else
     private->window_type = attributes->window_type;
 
+  /* Work around a bug where Xorg refuses to map toplevel InputOnly windows 
+   * from an untrusted client: http://bugs.freedesktop.org/show_bug.cgi?id=6988
+   */
+  if (attributes->wclass == GDK_INPUT_ONLY &&
+      GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT &&
+      !G_LIKELY (GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (parent))->trusted_client))
+    {
+      g_warning ("Coercing GDK_INPUT_ONLY toplevel window to GDK_INPUT_OUTPUT to work around bug in Xorg server");
+      attributes->wclass = GDK_INPUT_OUTPUT;
+    }
+
   _gdk_window_init_position (GDK_WINDOW (private));
   if (impl->position_info.big)
     private->guffaw_gravity = TRUE;
@@ -1287,7 +1269,7 @@ set_initial_hints (GdkWindow *window)
   Window xwindow = GDK_WINDOW_XID (window);  
   GdkWindowObject *private;
   GdkToplevelX11 *toplevel;
-  Atom atoms[7];
+  Atom atoms[9];
   gint i;
 
   private = (GdkWindowObject*) window;
@@ -1846,7 +1828,6 @@ gdk_window_reparent (GdkWindow *window,
                     gint       x,
                     gint       y)
 {
-  GdkDisplay *display;
   GdkWindowObject *window_private;
   GdkWindowObject *parent_private;
   GdkWindowObject *old_parent_private;
@@ -1866,8 +1847,6 @@ gdk_window_reparent (GdkWindow *window,
   if (!new_parent)
     new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
 
-  display = GDK_WINDOW_DISPLAY (window);
-  
   window_private = (GdkWindowObject*) window;
   old_parent_private = (GdkWindowObject*)window_private->parent;
   parent_private = (GdkWindowObject*) new_parent;
@@ -2040,7 +2019,13 @@ gdk_x11_window_move_to_current_desktop (GdkWindow *window)
 
   if (toplevel->on_all_desktops)
     return;
+  
+  move_to_current_desktop (window);
+}
 
+static void
+move_to_current_desktop (GdkWindow *window)
+{
   if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
                                           gdk_atom_intern_static_string ("_NET_WM_DESKTOP")))
     {
@@ -2266,6 +2251,24 @@ gdk_window_set_type_hint (GdkWindow        *window,
     case GDK_WINDOW_TYPE_HINT_DESKTOP:
       atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP");
       break;
+    case GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU:
+      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU");
+      break;
+    case GDK_WINDOW_TYPE_HINT_POPUP_MENU:
+      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_POPUP_MENU");
+      break;
+    case GDK_WINDOW_TYPE_HINT_TOOLTIP:
+      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLTIP");
+      break;
+    case GDK_WINDOW_TYPE_HINT_NOTIFICATION:
+      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NOTIFICATION");
+      break;
+    case GDK_WINDOW_TYPE_HINT_COMBO:
+      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_COMBO");
+      break;
+    case GDK_WINDOW_TYPE_HINT_DND:
+      atom = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DND");
+      break;
     default:
       g_warning ("Unknown hint %d passed to gdk_window_set_type_hint", hint);
       /* Fall thru */
@@ -2280,6 +2283,81 @@ gdk_window_set_type_hint (GdkWindow        *window,
                   (guchar *)&atom, 1);
 }
 
+/**
+ * gdk_window_get_type_hint:
+ * @window: A toplevel #GdkWindow
+ *
+ * This function returns the type hint set for a window.
+ *
+ * Return value: The type hint set for @window
+ *
+ * Since: 2.10
+ **/
+GdkWindowTypeHint
+gdk_window_get_type_hint (GdkWindow *window)
+{
+  GdkDisplay *display;
+  GdkWindowTypeHint type;
+  Atom type_return;
+  gint format_return;
+  gulong nitems_return;
+  gulong bytes_after_return;
+  guchar *data = NULL;
+
+  g_return_val_if_fail (GDK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
+
+  if (GDK_WINDOW_DESTROYED (window))
+    return GDK_WINDOW_TYPE_HINT_NORMAL;
+
+  type = GDK_WINDOW_TYPE_HINT_NORMAL;
+
+  display = gdk_drawable_get_display (window);
+
+  if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
+                          gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE"),
+                          0, G_MAXLONG, False, XA_ATOM, &type_return,
+                          &format_return, &nitems_return, &bytes_after_return,
+                          &data) == Success)
+    {
+      if ((type_return == XA_ATOM) && (format_return == 32) &&
+          (data) && (nitems_return == 1))
+        {
+          Atom atom = *(Atom*)data;
+
+          if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DIALOG"))
+            type = GDK_WINDOW_TYPE_HINT_DIALOG;
+          else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_MENU"))
+            type = GDK_WINDOW_TYPE_HINT_MENU;
+          else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLBAR"))
+            type = GDK_WINDOW_TYPE_HINT_TOOLBAR;
+          else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_UTILITY"))
+            type = GDK_WINDOW_TYPE_HINT_UTILITY;
+          else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_SPLASH"))
+            type = GDK_WINDOW_TYPE_HINT_SPLASHSCREEN;
+          else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DOCK"))
+            type = GDK_WINDOW_TYPE_HINT_DOCK;
+          else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DESKTOP"))
+            type = GDK_WINDOW_TYPE_HINT_DESKTOP;
+         else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU"))
+           type = GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU;
+         else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_POPUP_MENU"))
+           type = GDK_WINDOW_TYPE_HINT_POPUP_MENU;
+         else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_TOOLTIP"))
+           type = GDK_WINDOW_TYPE_HINT_TOOLTIP;
+         else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_NOTIFICATION"))
+           type = GDK_WINDOW_TYPE_HINT_NOTIFICATION;
+         else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_COMBO"))
+           type = GDK_WINDOW_TYPE_HINT_COMBO;
+         else if (atom == gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_WINDOW_TYPE_DND"))
+           type = GDK_WINDOW_TYPE_HINT_DND;
+        }
+
+      if (type_return != None && data != NULL)
+        XFree (data);
+    }
+
+  return type;
+}
 
 static void
 gdk_wmspec_change_state (gboolean   add,
@@ -2662,7 +2740,7 @@ set_text_property (GdkDisplay  *display,
                   Atom         property,
                   const gchar *utf8_str)
 {
-  guchar *prop_text = NULL;
+  gchar *prop_text = NULL;
   Atom prop_type;
   gint prop_length;
   gint prop_format;
@@ -2682,7 +2760,7 @@ set_text_property (GdkDisplay  *display,
       
       gdk_utf8_to_compound_text_for_display (display,
                                             utf8_str, &gdk_type, &prop_format,
-                                            &prop_text, &prop_length);
+                                            (guchar **)&prop_text, &prop_length);
       prop_type = gdk_x11_atom_to_xatom_for_display (display, gdk_type);
       is_compound_text = TRUE;
     }
@@ -2693,11 +2771,11 @@ set_text_property (GdkDisplay  *display,
                       xwindow,
                       property,
                       prop_type, prop_format,
-                      PropModeReplace, prop_text,
+                      PropModeReplace, (guchar *)prop_text,
                       prop_length);
 
       if (is_compound_text)
-       gdk_free_compound_text (prop_text);
+       gdk_free_compound_text ((guchar *)prop_text);
       else
        g_free (prop_text);
     }
@@ -2713,7 +2791,7 @@ set_wm_name (GdkDisplay  *display,
   XChangeProperty (GDK_DISPLAY_XDISPLAY (display), xwindow,
                   gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_NAME"),
                   gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
-                  PropModeReplace, name, strlen (name));
+                  PropModeReplace, (guchar *)name, strlen (name));
   
   set_text_property (display, xwindow,
                     gdk_x11_get_xatom_by_name_for_display (display, "WM_NAME"),
@@ -2756,7 +2834,7 @@ gdk_window_set_title (GdkWindow   *window,
       XChangeProperty (xdisplay, xwindow,
                       gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
                       gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
-                      PropModeReplace, title, strlen (title));
+                      PropModeReplace, (guchar *)title, strlen (title));
       
       set_text_property (display, xwindow,
                         gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
@@ -2798,7 +2876,7 @@ gdk_window_set_role (GdkWindow   *window,
       if (role)
        XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
                         gdk_x11_get_xatom_by_name_for_display (display, "WM_WINDOW_ROLE"),
-                        XA_STRING, 8, PropModeReplace, role, strlen (role));
+                        XA_STRING, 8, PropModeReplace, (guchar *)role, strlen (role));
       else
        XDeleteProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
                         gdk_x11_get_xatom_by_name_for_display (display, "WM_WINDOW_ROLE"));
@@ -2823,14 +2901,8 @@ void
 gdk_window_set_transient_for (GdkWindow *window, 
                              GdkWindow *parent)
 {
-  GdkWindowObject *private;
-  GdkWindowObject *parent_private;
-  
   g_return_if_fail (GDK_IS_WINDOW (window));
   
-  private = (GdkWindowObject*) window;
-  parent_private = (GdkWindowObject*) parent;
-  
   if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (parent))
     XSetTransientForHint (GDK_WINDOW_XDISPLAY (window), 
                          GDK_WINDOW_XID (window),
@@ -3374,6 +3446,8 @@ _gdk_windowing_get_pointer (GdkDisplay       *display,
                            GdkModifierType  *mask)
 {
   GdkScreen *default_screen;
+  Display *xdisplay;
+  Window xwindow;
   Window root = None;
   Window child;
   int rootx, rooty;
@@ -3385,10 +3459,27 @@ _gdk_windowing_get_pointer (GdkDisplay       *display,
     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,13 +3513,28 @@ _gdk_windowing_window_get_pointer (GdkDisplay      *display,
   _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 (!GDK_WINDOW_DESTROYED (window)) 
     {
-      if (child)
-       return_val = gdk_window_lookup_for_display (GDK_WINDOW_DISPLAY (window), child);
+      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;
@@ -3501,24 +3607,89 @@ _gdk_windowing_window_at_pointer (GdkDisplay *display,
    * and the result.
    */
   gdk_x11_display_grab (display);
-  XQueryPointer (xdisplay, xwindow,
-                &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
-
-  if (root == xwindow)
-    xwindow = child;
-  else
-    xwindow = root;
-  
-  while (xwindow)
+  if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client)) 
     {
-      xwindow_last = xwindow;
       XQueryPointer (xdisplay, xwindow,
-                    &root, &xwindow, &rootx, &rooty, &winx, &winy, &xmask);
+                    &root, &child, &rootx, &rooty, &winx, &winy, &xmask);
+      if (root == xwindow)
+       xwindow = child;
+      else
+       xwindow = root;
+      
+      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;
 
@@ -3636,19 +3807,6 @@ gdk_window_add_colormap_windows (GdkWindow *window)
     XFree (old_windows);
 }
 
-static gboolean
-gdk_window_have_shape_ext (GdkDisplay *display)
-{
-#ifdef HAVE_SHAPE_EXT
-  int ignore;
-
-  return XShapeQueryExtension (GDK_DISPLAY_XDISPLAY (display),
-                              &ignore, &ignore);
-#else
-  return 0;
-#endif  
-}
-
 #define WARN_SHAPE_TOO_BIG() g_warning ("GdkWindow is too large to allow the use of shape masks or shape regions.")
 
 /*
@@ -3656,35 +3814,14 @@ gdk_window_have_shape_ext (GdkDisplay *display)
  * If not available, shaped windows will look
  * ugly, but programs still work.    Stefan Wille
  */
-/**
- * gdk_window_shape_combine_mask:
- * @window: a #GdkWindow
- * @mask: shape mask
- * @x: X position of shape mask with respect to @window
- * @y: Y position of shape mask with respect to @window
- *
- * Applies a shape mask to @window. Pixels in @window corresponding to
- * set bits in the @mask will be visible; pixels in @window
- * corresponding to unset bits in the @mask will be transparent. This
- * gives a non-rectangular window.
- *
- * If @mask is %NULL, the shape mask will be unset, and the @x/@y
- * parameters are not used.
- *
- * On the X11 platform, this uses an X server extension which is
- * widely available on most common platforms, but not available on
- * very old X servers, and occasionally the implementation will be
- * buggy. On servers without the shape extension, this function
- * will do nothing.
- *
- * This function works on both toplevel and child windows.
- * 
- **/
-void
-gdk_window_shape_combine_mask (GdkWindow *window,
-                              GdkBitmap *mask,
-                              gint x, gint y)
+static void
+do_shape_combine_mask (GdkWindow *window,
+                      GdkBitmap *mask,
+                      gint       x, 
+                      gint       y,
+                      gint       shape)
 {
+  GdkWindowObject *private = (GdkWindowObject *)window;
   Pixmap pixmap;
   gint xoffset, yoffset;
   
@@ -3702,22 +3839,28 @@ gdk_window_shape_combine_mask (GdkWindow *window,
       return;
     }
   
-  if (gdk_window_have_shape_ext (GDK_WINDOW_DISPLAY (window)))
+  if (shape == ShapeBounding
+      ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
+      : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
     {
       if (mask)
        {
          pixmap = GDK_PIXMAP_XID (mask);
+         
+         private->shaped = (shape == ShapeBounding);
        }
       else
        {
          x = 0;
          y = 0;
          pixmap = None;
+
+         private->shaped = FALSE;
        }
       
       XShapeCombineMask (GDK_WINDOW_XDISPLAY (window),
                         GDK_WINDOW_XID (window),
-                        ShapeBounding,
+                        shape,
                         x, y,
                         pixmap,
                         ShapeSet);
@@ -3726,20 +3869,20 @@ gdk_window_shape_combine_mask (GdkWindow *window,
 }
 
 /**
- * gdk_window_shape_combine_region:
+ * gdk_window_shape_combine_mask:
  * @window: a #GdkWindow
- * @shape_region: region of window to be non-transparent
- * @offset_x: X position of @shape_region in @window coordinates
- * @offset_y: Y position of @shape_region in @window coordinates
+ * @mask: shape mask
+ * @x: X position of shape mask with respect to @window
+ * @y: Y position of shape mask with respect to @window
  *
- * Makes pixels in @window outside @shape_region be transparent,
- * so that the window may be nonrectangular. See also
- * gdk_window_shape_combine_mask() to use a bitmap as the mask.
+ * Applies a shape mask to @window. Pixels in @window corresponding to
+ * set bits in the @mask will be visible; pixels in @window
+ * corresponding to unset bits in the @mask will be transparent. This
+ * gives a non-rectangular window.
+ *
+ * If @mask is %NULL, the shape mask will be unset, and the @x/@y
+ * parameters are not used.
  *
- * If @shape_region is %NULL, the shape will be unset, so the whole
- * window will be opaque again. @offset_x and @offset_y are ignored
- * if @shape_region is %NULL.
- * 
  * On the X11 platform, this uses an X server extension which is
  * widely available on most common platforms, but not available on
  * very old X servers, and occasionally the implementation will be
@@ -3750,11 +3893,57 @@ gdk_window_shape_combine_mask (GdkWindow *window,
  * 
  **/
 void
-gdk_window_shape_combine_region (GdkWindow *window,
-                                 GdkRegion *shape_region,
-                                 gint       offset_x,
-                                 gint       offset_y)
+gdk_window_shape_combine_mask (GdkWindow *window,
+                              GdkBitmap *mask,
+                              gint       x, 
+                              gint       y)
+{
+  do_shape_combine_mask (window, mask, x, y, ShapeBounding);
+}
+
+/**
+ * gdk_window_input_shape_combine_mask:
+ * @window: a #GdkWindow
+ * @mask: shape mask
+ * @x: X position of shape mask with respect to @window
+ * @y: Y position of shape mask with respect to @window
+ * 
+ * Like gdk_window_shape_combine_mask(), but the shape applies
+ * only to event handling. Mouse events which happen while
+ * the pointer position corresponds to an unset bit in the 
+ * mask will be passed on the window below @window.
+ *
+ * An input shape is typically used with RGBA windows.
+ * The alpha channel of the window defines which pixels are 
+ * invisible and allows for nicely antialiased borders,
+ * and the input shape controls where the window is
+ * "clickable".
+ *
+ * On the X11 platform, this requires version 1.1 of the
+ * shape extension.
+ *
+ * Since: 2.10
+ */
+void 
+gdk_window_input_shape_combine_mask (GdkWindow *window,
+                                    GdkBitmap *mask,
+                                    gint       x,
+                                    gint       y)
 {
+#ifdef ShapeInput
+  do_shape_combine_mask (window, mask, x, y, ShapeInput);
+#endif
+}
+
+
+static void
+do_shape_combine_region (GdkWindow *window,
+                        GdkRegion *shape_region,
+                        gint       offset_x,
+                        gint       offset_y,
+                        gint       shape)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
   gint xoffset, yoffset;
   
   g_return_if_fail (GDK_IS_WINDOW (window));
@@ -3778,18 +3967,22 @@ gdk_window_shape_combine_region (GdkWindow *window,
       return;
     }
   
-  if (gdk_window_have_shape_ext (GDK_WINDOW_DISPLAY (window)))
+  if (shape == ShapeBounding
+      ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
+      : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
     {
       gint n_rects = 0;
       XRectangle *xrects = NULL;
 
+      private->shaped = shape == ShapeBounding;
+
       _gdk_region_get_xrectangles (shape_region,
                                    0, 0,
                                    &xrects, &n_rects);
       
       XShapeCombineRectangles (GDK_WINDOW_XDISPLAY (window),
                                GDK_WINDOW_XID (window),
-                               ShapeBounding,
+                               shape,
                                offset_x, offset_y,
                                xrects, n_rects,
                                ShapeSet,
@@ -3800,6 +3993,73 @@ gdk_window_shape_combine_region (GdkWindow *window,
 #endif /* HAVE_SHAPE_EXT */
 }
 
+/**
+ * gdk_window_shape_combine_region:
+ * @window: a #GdkWindow
+ * @shape_region: region of window to be non-transparent
+ * @offset_x: X position of @shape_region in @window coordinates
+ * @offset_y: Y position of @shape_region in @window coordinates
+ *
+ * Makes pixels in @window outside @shape_region be transparent,
+ * so that the window may be nonrectangular. See also
+ * gdk_window_shape_combine_mask() to use a bitmap as the mask.
+ *
+ * If @shape_region is %NULL, the shape will be unset, so the whole
+ * window will be opaque again. @offset_x and @offset_y are ignored
+ * if @shape_region is %NULL.
+ * 
+ * On the X11 platform, this uses an X server extension which is
+ * widely available on most common platforms, but not available on
+ * very old X servers, and occasionally the implementation will be
+ * buggy. On servers without the shape extension, this function
+ * will do nothing.
+ *
+ * This function works on both toplevel and child windows.
+ * 
+ **/
+void
+gdk_window_shape_combine_region (GdkWindow *window,
+                                 GdkRegion *shape_region,
+                                 gint       offset_x,
+                                 gint       offset_y)
+{ 
+  do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeBounding);
+}
+
+/**
+ * gdk_window_input_shape_combine_region:
+ * @window: a #GdkWindow
+ * @shape_region: region of window to be non-transparent
+ * @offset_x: X position of @shape_region in @window coordinates
+ * @offset_y: Y position of @shape_region in @window coordinates
+ * 
+ * Like gdk_window_shape_combine_region(), but the shape applies
+ * only to event handling. Mouse events which happen while
+ * the pointer position corresponds to an unset bit in the 
+ * mask will be passed on the window below @window.
+ *
+ * An input shape is typically used with RGBA windows.
+ * The alpha channel of the window defines which pixels are 
+ * invisible and allows for nicely antialiased borders,
+ * and the input shape controls where the window is
+ * "clickable".
+ *
+ * On the X11 platform, this requires version 1.1 of the
+ * shape extension.
+ *
+ * Since: 2.10
+ */
+void 
+gdk_window_input_shape_combine_region (GdkWindow *window,
+                                      GdkRegion *shape_region,
+                                      gint       offset_x,
+                                      gint       offset_y)
+{
+#ifdef ShapeInput
+  do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeInput);
+#endif
+}
+
 
 /**
  * gdk_window_set_override_redirect:
@@ -3959,6 +4219,12 @@ gdk_x11_window_set_user_time (GdkWindow *window,
   toplevel->user_time = timestamp_long;
 }
 
+#define GDK_SELECTION_MAX_SIZE(display)                                 \
+  MIN(262144,                                                           \
+      XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) == 0     \
+       ? XMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100         \
+       : XExtendedMaxRequestSize (GDK_DISPLAY_XDISPLAY (display)) - 100)
+
 /**
  * gdk_window_set_icon_list:
  * @window: The #GdkWindow toplevel window to set the icon of.
@@ -3987,6 +4253,7 @@ gdk_window_set_icon_list (GdkWindow *window,
   gint x, y;
   gint n_channels;
   GdkDisplay *display;
+  gint n;
   
   g_return_if_fail (GDK_IS_WINDOW (window));
 
@@ -3997,7 +4264,7 @@ gdk_window_set_icon_list (GdkWindow *window,
   
   l = pixbufs;
   size = 0;
-  
+  n = 0;
   while (l)
     {
       pixbuf = l->data;
@@ -4006,8 +4273,16 @@ gdk_window_set_icon_list (GdkWindow *window,
       width = gdk_pixbuf_get_width (pixbuf);
       height = gdk_pixbuf_get_height (pixbuf);
       
+      /* silently ignore overlarge icons */
+      if (size + 2 + width * height > GDK_SELECTION_MAX_SIZE(display))
+       {
+         g_warning ("gdk_window_set_icon_list: icons too large");
+         break;
+       }
+     
+      n++;
       size += 2 + width * height;
-
+      
       l = g_list_next (l);
     }
 
@@ -4015,7 +4290,7 @@ gdk_window_set_icon_list (GdkWindow *window,
 
   l = pixbufs;
   p = data;
-  while (l)
+  while (l && n > 0)
     {
       pixbuf = l->data;
       
@@ -4048,6 +4323,7 @@ gdk_window_set_icon_list (GdkWindow *window,
        }
 
       l = g_list_next (l);
+      n--;
     }
 
   if (size > 0)
@@ -4165,7 +4441,7 @@ gdk_window_set_icon_name (GdkWindow   *window,
                   GDK_WINDOW_XID (window),
                   gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_ICON_NAME"),
                   gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
-                  PropModeReplace, name, strlen (name));
+                  PropModeReplace, (guchar *)name, strlen (name));
   
   set_text_property (display, GDK_WINDOW_XID (window),
                     gdk_x11_get_xatom_by_name_for_display (display, "WM_ICON_NAME"),
@@ -4186,15 +4462,11 @@ gdk_window_set_icon_name (GdkWindow   *window,
 void
 gdk_window_iconify (GdkWindow *window)
 {
-  GdkWindowObject *private;
-  
   g_return_if_fail (GDK_IS_WINDOW (window));
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
-  private = (GdkWindowObject*) window;
-
   if (GDK_WINDOW_IS_MAPPED (window))
     {  
       XIconifyWindow (GDK_WINDOW_XDISPLAY (window),
@@ -4224,15 +4496,11 @@ gdk_window_iconify (GdkWindow *window)
 void
 gdk_window_deiconify (GdkWindow *window)
 {
-  GdkWindowObject *private;
-  
   g_return_if_fail (GDK_IS_WINDOW (window));
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
-  private = (GdkWindowObject*) window;
-
   if (GDK_WINDOW_IS_MAPPED (window))
     {  
       gdk_window_show (window);
@@ -4329,52 +4597,12 @@ gdk_window_unstick (GdkWindow *window)
 
   if (GDK_WINDOW_IS_MAPPED (window))
     {
-      XEvent xev;
-      Atom type;
-      gint format;
-      gulong nitems;
-      gulong bytes_after;
-      guchar *data;
-      gulong *current_desktop;
-      GdkDisplay *display = gdk_drawable_get_display (window);
-      
       /* Request unstick from viewport */
       gdk_wmspec_change_state (FALSE, window,
                               gdk_atom_intern_static_string ("_NET_WM_STATE_STICKY"),
                               NULL);
 
-      /* Get current desktop, then set it; this is a race, but not
-       * one that matters much in practice.
-       */
-      XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window),
-                         gdk_x11_get_xatom_by_name_for_display (display, "_NET_CURRENT_DESKTOP"),
-                          0, G_MAXLONG,
-                          False, XA_CARDINAL, &type, &format, &nitems,
-                          &bytes_after, &data);
-
-      if (type == XA_CARDINAL)
-        {
-         current_desktop = (gulong *)data;
-         
-          xev.xclient.type = ClientMessage;
-          xev.xclient.serial = 0;
-          xev.xclient.send_event = True;
-          xev.xclient.window = GDK_WINDOW_XWINDOW (window);
-         xev.xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_DESKTOP");
-          xev.xclient.format = 32;
-
-          xev.xclient.data.l[0] = *current_desktop;
-          xev.xclient.data.l[1] = 0;
-          xev.xclient.data.l[2] = 0;
-          xev.xclient.data.l[3] = 0;
-          xev.xclient.data.l[4] = 0;
-      
-          XSendEvent (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XROOTWIN (window), False,
-                      SubstructureRedirectMask | SubstructureNotifyMask,
-                      &xev);
-
-          XFree (current_desktop);
-        }
+      move_to_current_desktop (window);
     }
   else
     {
@@ -4793,6 +5021,8 @@ gdk_window_set_decorations (GdkWindow      *window,
   
   g_return_if_fail (GDK_IS_WINDOW (window));
   
+  /* initialize to zero to avoid writing uninitialized data to socket */
+  memset(&hints, 0, sizeof(hints));
   hints.flags = MWM_HINTS_DECORATIONS;
   hints.decorations = decorations;
   
@@ -4838,9 +5068,11 @@ gdk_window_get_decorations(GdkWindow       *window,
  * @window: a toplevel #GdkWindow
  * @functions: bitmask of operations to allow on @window
  *
- * This function isn't really good for much. It sets the traditional
- * Motif window manager hint for which operations the window manager
- * should allow on a toplevel window. However, few window managers do
+ * Sets hints about the window management functions to make available
+ * via buttons on the window frame.
+ * 
+ * On the X backend, this function sets the traditional Motif window 
+ * manager hint for this purpose. However, few window managers do
  * anything reliable or interesting with this hint. Many ignore it
  * entirely.
  *
@@ -4859,6 +5091,8 @@ gdk_window_set_functions (GdkWindow    *window,
   
   g_return_if_fail (GDK_IS_WINDOW (window));
   
+  /* initialize to zero to avoid writing uninitialized data to socket */
+  memset(&hints, 0, sizeof(hints));
   hints.flags = MWM_HINTS_FUNCTIONS;
   hints.functions = functions;
   
@@ -5054,7 +5288,8 @@ gdk_add_rectangles (Display           *disp,
 static void
 gdk_propagate_shapes (Display *disp,
                      Window   win,
-                     gboolean merge)
+                     gboolean merge,
+                     int      shape)
 {
   Window              rt, par, *list = NULL;
   gint                i, j, num = 0, num_rects = 0;
@@ -5159,7 +5394,7 @@ gdk_propagate_shapes (Display *disp,
       /* set the rects as the shape mask */
       if (rects)
        {
-         XShapeCombineRectangles (disp, win, ShapeBounding, 0, 0, rects, num_rects,
+         XShapeCombineRectangles (disp, win, shape, 0, 0, rects, num_rects,
                                   ShapeSet, YXSorted);
          g_free (rects);
        }
@@ -5195,11 +5430,12 @@ gdk_window_set_child_shapes (GdkWindow *window)
 {
   g_return_if_fail (GDK_IS_WINDOW (window));
   
+  
 #ifdef HAVE_SHAPE_EXT
   if (!GDK_WINDOW_DESTROYED (window) &&
-      gdk_window_have_shape_ext (GDK_WINDOW_DISPLAY (window)))
+      gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
     gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
-                         GDK_WINDOW_XID (window), FALSE);
+                         GDK_WINDOW_XID (window), FALSE, ShapeBounding);
 #endif   
 }
 
@@ -5215,7 +5451,6 @@ gdk_window_set_child_shapes (GdkWindow *window)
  * This function is distinct from gdk_window_set_child_shapes()
  * because it includes @window's shape mask in the set of shapes to
  * be merged.
- * 
  **/
 void
 gdk_window_merge_child_shapes (GdkWindow *window)
@@ -5224,12 +5459,69 @@ gdk_window_merge_child_shapes (GdkWindow *window)
   
 #ifdef HAVE_SHAPE_EXT
   if (!GDK_WINDOW_DESTROYED (window) &&
-      gdk_window_have_shape_ext (GDK_WINDOW_DISPLAY (window)))
+      gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
     gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
-                         GDK_WINDOW_XID (window), TRUE);
+                         GDK_WINDOW_XID (window), TRUE, ShapeBounding);
 #endif   
 }
 
+/**
+ * gdk_window_set_child_input_shapes:
+ * @window: a #GdkWindow
+ * 
+ * Sets the input shape mask of @window to the union of input shape masks
+ * for all children of @window, ignoring the input shape mask of @window
+ * itself. Contrast with gdk_window_merge_child_input_shapes() which includes
+ * the input shape mask of @window in the masks to be merged.
+ *
+ * Since: 2.10
+ **/
+void 
+gdk_window_set_child_input_shapes (GdkWindow *window)
+{
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  
+#ifdef HAVE_SHAPE_EXT
+#ifdef ShapeInput
+  if (!GDK_WINDOW_DESTROYED (window) &&
+      gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
+    gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
+                         GDK_WINDOW_XID (window), FALSE, ShapeInput);
+#endif
+#endif   
+}
+
+/**
+ * gdk_window_merge_child_input_shapes:
+ * @window: a #GdkWindow
+ * 
+ * Merges the input shape masks for any child windows into the
+ * input shape mask for @window. i.e. the union of all input masks
+ * for @window and its children will become the new input mask
+ * for @window. See gdk_window_input_shape_combine_mask().
+ *
+ * This function is distinct from gdk_window_set_child_input_shapes()
+ * because it includes @window's input shape mask in the set of 
+ * shapes to be merged.
+ *
+ * Since: 2.10
+ **/
+void 
+gdk_window_merge_child_input_shapes (GdkWindow *window)
+{
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  
+#ifdef HAVE_SHAPE_EXT
+#ifdef ShapeInput
+  if (!GDK_WINDOW_DESTROYED (window) &&
+      gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
+    gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
+                         GDK_WINDOW_XID (window), TRUE, ShapeInput);
+#endif
+#endif   
+}
+
+
 static void
 gdk_window_set_static_bit_gravity (GdkWindow *window, gboolean on)
 {
@@ -5541,6 +5833,7 @@ finish_drag (MoveResizeData *mv_resize)
 {
   gdk_window_destroy (mv_resize->moveresize_emulation_window);
   mv_resize->moveresize_emulation_window = NULL;
+  g_object_unref (mv_resize->moveresize_window);
   mv_resize->moveresize_window = NULL;
 
   if (mv_resize->moveresize_pending_event)
@@ -5720,8 +6013,7 @@ create_moveresize_window (MoveResizeData *mv_resize,
       /* If this fails, some other client has grabbed the window
        * already.
        */
-      gdk_window_destroy (mv_resize->moveresize_emulation_window);
-      mv_resize->moveresize_emulation_window = NULL;
+      finish_drag (mv_resize);
     }
 
   mv_resize->moveresize_process_time = 0;