]> 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 79f5fb52c4ad9608aeaaa27ebd6aad597d55483e..2a71b22ada3f302c5e439679ed40f6c00268d2f8 100644 (file)
@@ -31,6 +31,7 @@
 #include <X11/Xatom.h>
 #include <netinet/in.h>
 #include <unistd.h>
+
 #include "gdk.h"
 
 #include "gdkwindow.h"
@@ -42,6 +43,7 @@
 #include "gdkinternals.h"
 #include "MwmUtil.h"
 #include "gdkwindow-x11.h"
+#include "gdkalias.h"
 
 #include <stdlib.h>
 #include <stdio.h>
@@ -81,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,
@@ -95,43 +97,21 @@ 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)
 
-GType
-gdk_window_impl_x11_get_type (void)
-{
-  static GType object_type = 0;
+/* Return whether time1 is considered later than time2 as far as xserver
+ * time is concerned.  Accounts for wraparound.
+ */
+#define XSERVER_TIME_IS_LATER(time1, time2)                        \
+  ( (( time1 > time2 ) && ( time1 - time2 < ((guint32)-1)/2 )) ||  \
+    (( time1 < time2 ) && ( time2 - time1 > ((guint32)-1)/2 ))     \
+  )
 
-  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,
-                                            "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)
@@ -173,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;
@@ -214,19 +192,151 @@ gdk_window_impl_x11_finalize (GObject *object)
   if (window_impl->toplevel)
     g_free (window_impl->toplevel);
 
-  G_OBJECT_CLASS (parent_class)->finalize (object);
+  if (window_impl->cursor)
+    gdk_cursor_unref (window_impl->cursor);
+
+  G_OBJECT_CLASS (gdk_window_impl_x11_parent_class)->finalize (object);
+}
+
+static void
+tmp_unset_bg (GdkWindow *window)
+{
+  GdkWindowImplX11 *impl;
+  GdkWindowObject *obj;
+
+  obj = (GdkWindowObject *) window;
+  impl = GDK_WINDOW_IMPL_X11 (obj->impl);
+
+  /* For windows without EXPOSURE_MASK, we can't do this
+   * unsetting because such windows depend on the drawing
+   * that the X server is going to do
+   */
+  if (!(obj->event_mask & GDK_EXPOSURE_MASK))
+    return;
+    
+  impl->position_info.no_bg = TRUE;
+
+  if (obj->bg_pixmap != GDK_NO_BG)
+    XSetWindowBackgroundPixmap (GDK_DRAWABLE_XDISPLAY (window),
+                               GDK_DRAWABLE_XID (window), None);
+}
+
+static void
+tmp_reset_bg (GdkWindow *window)
+{
+  GdkWindowImplX11 *impl;
+  GdkWindowObject *obj;
+
+  obj = (GdkWindowObject *) window;
+  impl = GDK_WINDOW_IMPL_X11 (obj->impl);
+
+  if (!(obj->event_mask & GDK_EXPOSURE_MASK))
+    return;
+    
+  impl->position_info.no_bg = FALSE;
+
+  if (obj->bg_pixmap == GDK_NO_BG)
+    return;
+  
+  if (obj->bg_pixmap)
+    {
+      Pixmap xpixmap;
+
+      if (obj->bg_pixmap == GDK_PARENT_RELATIVE_BG)
+       xpixmap = ParentRelative;
+      else 
+       xpixmap = GDK_DRAWABLE_XID (obj->bg_pixmap);
+
+      XSetWindowBackgroundPixmap (GDK_DRAWABLE_XDISPLAY (window),
+                                 GDK_DRAWABLE_XID (window), xpixmap);
+    }
+  else
+    {
+      XSetWindowBackground (GDK_DRAWABLE_XDISPLAY (window),
+                           GDK_DRAWABLE_XID (window),
+                           obj->bg_color.pixel);
+    }
+}
+
+/* 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)
+{
+  GdkWindowObject *private;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  
+  private = (GdkWindowObject *)window;
+
+  if (private->input_only || private->destroyed ||
+      (private->window_type != GDK_WINDOW_ROOT &&
+       !GDK_WINDOW_IS_MAPPED (window)))
+    {
+      return;
+    }
+
+  if (private->window_type != GDK_WINDOW_ROOT &&
+      private->window_type != GDK_WINDOW_FOREIGN)
+    {
+      tmp_unset_bg (window);
+    }
+
+  if (recurse)
+    {
+      GList *l;
+
+      for (l = private->children; l != NULL; l = l->next)
+       _gdk_x11_window_tmp_unset_bg (l->data, TRUE);
+    }
+}
+
+void
+_gdk_x11_window_tmp_reset_bg (GdkWindow *window,
+                             gboolean   recurse)
+{
+  GdkWindowObject *private;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *)window;
+
+  if (private->input_only || private->destroyed ||
+      (private->window_type != GDK_WINDOW_ROOT &&
+       !GDK_WINDOW_IS_MAPPED (window)))
+    {
+      return;
+    }
+
+  if (private->window_type != GDK_WINDOW_ROOT &&
+      private->window_type != GDK_WINDOW_FOREIGN)
+    {
+      tmp_reset_bg (window);
+    }
+
+  if (recurse)
+    {
+      GList *l;
+
+      for (l = private->children; l != NULL; l = l->next)
+       _gdk_x11_window_tmp_reset_bg (l->data, TRUE);
+    }
 }
 
 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)
@@ -251,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)
     {
@@ -350,13 +458,19 @@ static void
 set_wm_protocols (GdkWindow *window)
 {
   GdkDisplay *display = gdk_drawable_get_display (window);
-  Atom protocols[3];
+  Atom protocols[4];
+  int n = 0;
   
-  protocols[0] = gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW");
-  protocols[1] = gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS");
-  protocols[2] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING");
+  protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_DELETE_WINDOW");
+  protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "WM_TAKE_FOCUS");
+  protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_PING");
 
-  XSetWMProtocols (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window), protocols, 3);
+#ifdef HAVE_XSYNC
+  if (GDK_DISPLAY_X11 (display)->use_sync)
+    protocols[n++] = gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_SYNC_REQUEST");
+#endif
+  
+  XSetWMProtocols (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window), protocols, n);
 }
 
 static const gchar *
@@ -405,7 +519,45 @@ create_focus_window (Display *xdisplay,
 }
 
 static void
-setup_toplevel_window (GdkWindow *window, GdkWindow *parent)
+ensure_sync_counter (GdkWindow *window)
+{
+#ifdef HAVE_XSYNC
+  if (!GDK_WINDOW_DESTROYED (window))
+    {
+      GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
+      GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
+      GdkWindowObject *private = (GdkWindowObject *)window;
+      GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
+
+      if (toplevel && impl->use_synchronized_configure &&
+         toplevel->update_counter == None &&
+         GDK_DISPLAY_X11 (display)->use_sync)
+       {
+         Display *xdisplay = GDK_DISPLAY_XDISPLAY (display);
+         XSyncValue value;
+         Atom atom;
+
+         XSyncIntToValue (&value, 0);
+         
+         toplevel->update_counter = XSyncCreateCounter (xdisplay, value);
+         
+         atom = gdk_x11_get_xatom_by_name_for_display (display,
+                                                       "_NET_WM_SYNC_REQUEST_COUNTER");
+         
+         XChangeProperty (xdisplay, GDK_WINDOW_XID (window),
+                          atom, XA_CARDINAL,
+                          32, PropModeReplace,
+                          (guchar *)&toplevel->update_counter, 1);
+         
+         XSyncIntToValue (&toplevel->current_counter_value, 0);
+       }
+    }
+#endif
+}
+
+static void
+setup_toplevel_window (GdkWindow *window, 
+                      GdkWindow *parent)
 {
   GdkWindowObject *obj = (GdkWindowObject *)window;
   GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
@@ -462,6 +614,8 @@ setup_toplevel_window (GdkWindow *window, GdkWindow *parent)
     gdk_x11_window_set_user_time (window, 0);
   else if (GDK_DISPLAY_X11 (screen_x11->display)->user_time != 0)
     gdk_x11_window_set_user_time (window, GDK_DISPLAY_X11 (screen_x11->display)->user_time);
+
+  ensure_sync_counter (window);
 }
 
 /**
@@ -578,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;
@@ -608,6 +773,8 @@ gdk_window_new (GdkWindow     *parent,
   else
     xattributes.override_redirect = False;
 
+  impl->override_redirect = xattributes.override_redirect;
+  
   if (private->parent && private->parent->guffaw_gravity)
     {
       xattributes.win_gravity = StaticGravity;
@@ -660,6 +827,7 @@ gdk_window_new (GdkWindow     *parent,
        }
       
       private->bg_color.pixel = BlackPixel (xdisplay, screen_x11->screen_num);
+      private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
       xattributes.background_pixel = private->bg_color.pixel;
 
       private->bg_pixmap = NULL;
@@ -683,6 +851,8 @@ gdk_window_new (GdkWindow     *parent,
          xattributes.override_redirect = True;
          xattributes.cursor = None;
          xattributes_mask |= CWSaveUnder | CWOverrideRedirect;
+
+         impl->override_redirect = TRUE;
        }
     }
   else
@@ -773,13 +943,16 @@ x_event_mask_to_gdk_event_mask (long mask)
  * @anid: a native window handle.
  * 
  * Wraps a native window in a #GdkWindow.
- * This may fail if the window has been destroyed.
+ * This may fail if the window has been destroyed. If the window
+ * was already known to GDK, a new reference to the existing 
+ * #GdkWindow is returned.
  *
  * For example in the X backend, a native window handle is an Xlib
  * <type>XID</type>.
  * 
- * Return value: the newly-created #GdkWindow wrapper for the 
- *    native window or %NULL if the window has been destroyed.
+ * Return value: a #GdkWindow wrapper for the native window or 
+ *   %NULL if the window has been destroyed. The wrapper will be
+ *   newly created, if one doesn't exist already.
  *
  * Since: 2.2
  **/
@@ -801,7 +974,10 @@ gdk_window_foreign_new_for_display (GdkDisplay     *display,
   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
 
   display_x11 = GDK_DISPLAY_X11 (display);
-  
+
+  if ((window = gdk_xid_table_lookup_for_display (display, anid)) != NULL)
+    return g_object_ref (window);
+
   gdk_error_trap_push ();
   result = XGetWindowAttributes (display_x11->xdisplay, anid, &attrs);
   if (gdk_error_trap_pop () || !result)
@@ -896,7 +1072,8 @@ gdk_window_lookup (GdkNativeWindow anid)
 }
 
 static void
-gdk_toplevel_x11_free_contents (GdkToplevelX11 *toplevel)
+gdk_toplevel_x11_free_contents (GdkDisplay *display,
+                               GdkToplevelX11 *toplevel)
 {
   if (toplevel->icon_window)
     {
@@ -918,6 +1095,16 @@ gdk_toplevel_x11_free_contents (GdkToplevelX11 *toplevel)
       g_object_unref (toplevel->group_leader);
       toplevel->group_leader = NULL;
     }
+#ifdef HAVE_XSYNC
+  if (toplevel->update_counter != None)
+    {
+      XSyncDestroyCounter (GDK_DISPLAY_XDISPLAY (display), 
+                          toplevel->update_counter);
+      toplevel->update_counter = None;
+
+      XSyncIntToValue (&toplevel->current_counter_value, 0);
+    }
+#endif
 }
 
 void
@@ -927,7 +1114,6 @@ _gdk_windowing_window_destroy (GdkWindow *window,
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
   GdkToplevelX11 *toplevel;
-  GdkDrawableImplX11 *draw_impl;
   
   g_return_if_fail (GDK_IS_WINDOW (window));
 
@@ -938,12 +1124,9 @@ _gdk_windowing_window_destroy (GdkWindow *window,
 
   toplevel = _gdk_x11_window_get_toplevel (window);
   if (toplevel)
-    gdk_toplevel_x11_free_contents (toplevel);
+    gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), toplevel);
 
-  draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
-    
-  if (draw_impl->xft_draw)
-    XftDrawDestroy (draw_impl->xft_draw);
+  _gdk_x11_drawable_finish (private->impl);
 
   if (!recursing && !foreign_destroy)
     {
@@ -983,6 +1166,14 @@ _gdk_windowing_window_destroy_foreign (GdkWindow *window)
   gdk_error_trap_pop ();
 }
 
+static GdkWindow *
+get_root (GdkWindow *window)
+{
+  GdkScreen *screen = gdk_drawable_get_screen (window);
+
+  return gdk_screen_get_root_window (screen);
+}
+
 /* This function is called when the XWindow is really gone.
  */
 void
@@ -990,7 +1181,7 @@ gdk_window_destroy_notify (GdkWindow *window)
 {
   GdkWindowImplX11 *window_impl;
 
-  g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
   
   window_impl = GDK_WINDOW_IMPL_X11 (((GdkWindowObject *)window)->impl);
 
@@ -1021,6 +1212,7 @@ update_wm_hints (GdkWindow *window,
   XWMHints wm_hints;
 
   if (!force &&
+      !toplevel->is_leader &&
       private->state & GDK_WINDOW_STATE_WITHDRAWN)
     return;
 
@@ -1060,6 +1252,9 @@ update_wm_hints (GdkWindow *window,
     }
   else
     wm_hints.window_group = GDK_DISPLAY_X11 (display)->leader_window;
+
+  if (toplevel->urgency_hint)
+    wm_hints.flags |= XUrgencyHint;
   
   XSetWMHints (GDK_WINDOW_XDISPLAY (window),
               GDK_WINDOW_XID (window),
@@ -1074,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;
@@ -1190,6 +1385,9 @@ show_window_internal (GdkWindow *window,
                       gboolean   raise)
 {
   GdkWindowObject *private;
+  GdkDisplay *display;
+  GdkDisplayX11 *display_x11;
+  GdkToplevelX11 *toplevel;
   
   g_return_if_fail (GDK_IS_WINDOW (window));
   
@@ -1214,8 +1412,36 @@ show_window_internal (GdkWindow *window,
       
       g_assert (GDK_WINDOW_IS_MAPPED (window));
 
+      if (WINDOW_IS_TOPLEVEL (window))
+       {
+         display = gdk_drawable_get_display (window);
+         display_x11 = GDK_DISPLAY_X11 (display);
+         toplevel = _gdk_x11_window_get_toplevel (window);
+
+          if (toplevel->user_time != 0 &&
+             display_x11->user_time != 0 &&
+             XSERVER_TIME_IS_LATER (display_x11->user_time, toplevel->user_time))
+           gdk_x11_window_set_user_time (window, display_x11->user_time);
+       }
+
       if (impl->position_info.mapped)
-        XMapWindow (xdisplay, xwindow);
+       {
+         gboolean unset_bg = !private->input_only &&
+           (private->window_type == GDK_WINDOW_CHILD ||
+            impl->override_redirect) &&
+           gdk_window_is_viewable (window);
+
+         if (unset_bg)
+           _gdk_x11_window_tmp_unset_bg (window, TRUE);
+         
+         XMapWindow (xdisplay, xwindow);
+
+         if (unset_bg)
+           {
+             _gdk_x11_window_tmp_reset_bg (window, TRUE);
+             gdk_window_invalidate_rect (window, NULL, TRUE);
+           }
+       }
     }
 }
 
@@ -1263,6 +1489,55 @@ gdk_window_show (GdkWindow *window)
   show_window_internal (window, TRUE);
 }
 
+static void
+pre_unmap (GdkWindow *window)
+{
+  GdkWindow *start_window = NULL;
+  GdkWindowObject *private = (GdkWindowObject *)window;
+
+  if (private->input_only)
+    return;
+
+  if (private->window_type == GDK_WINDOW_CHILD)
+    start_window = (GdkWindow *)private->parent;
+  else if (private->window_type == GDK_WINDOW_TEMP)
+    start_window = get_root (window);
+
+  if (start_window)
+    _gdk_x11_window_tmp_unset_bg (start_window, TRUE);
+}
+
+static void
+post_unmap (GdkWindow *window)
+{
+  GdkWindow *start_window = NULL;
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  
+  if (private->input_only)
+    return;
+
+  if (private->window_type == GDK_WINDOW_CHILD)
+    start_window = (GdkWindow *)private->parent;
+  else if (private->window_type == GDK_WINDOW_TEMP)
+    start_window = get_root (window);
+
+  if (start_window)
+    {
+      _gdk_x11_window_tmp_reset_bg (start_window, TRUE);
+
+      if (private->window_type == GDK_WINDOW_CHILD && private->parent)
+       {
+         GdkRectangle invalid_rect;
+      
+         gdk_window_get_position (window, &invalid_rect.x, &invalid_rect.y);
+         gdk_drawable_get_size (GDK_DRAWABLE (window),
+                                &invalid_rect.width, &invalid_rect.height);
+         gdk_window_invalidate_rect ((GdkWindow *)private->parent,
+                                     &invalid_rect, TRUE);
+       }
+    }
+}
+
 /**
  * gdk_window_hide:
  * @window: a #GdkWindow
@@ -1278,7 +1553,7 @@ gdk_window_hide (GdkWindow *window)
 {
   GdkWindowObject *private;
   
-  g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
 
   private = (GdkWindowObject*) window;
 
@@ -1315,9 +1590,13 @@ gdk_window_hide (GdkWindow *window)
       g_assert (!GDK_WINDOW_IS_MAPPED (window));
       
       _gdk_window_clear_update_area (window);
+
+      pre_unmap (window);
       
       XUnmapWindow (GDK_WINDOW_XDISPLAY (window),
                     GDK_WINDOW_XID (window));
+
+      post_unmap (window);
     }
 }
 
@@ -1335,7 +1614,7 @@ gdk_window_withdraw (GdkWindow *window)
 {
   GdkWindowObject *private;
   
-  g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
   
   private = (GdkWindowObject*) window;
   if (!private->destroyed)
@@ -1346,9 +1625,13 @@ gdk_window_withdraw (GdkWindow *window)
                                      GDK_WINDOW_STATE_WITHDRAWN);
 
       g_assert (!GDK_WINDOW_IS_MAPPED (window));
+
+      pre_unmap (window);
       
       XWithdrawWindow (GDK_WINDOW_XDISPLAY (window),
                        GDK_WINDOW_XID (window), 0);
+
+      post_unmap (window);
     }
 }
 
@@ -1375,21 +1658,28 @@ gdk_window_move (GdkWindow *window,
   GdkWindowObject *private = (GdkWindowObject *)window;
   GdkWindowImplX11 *impl;
 
-  g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
 
   impl = GDK_WINDOW_IMPL_X11 (private->impl);
-
+         
   if (!GDK_WINDOW_DESTROYED (window))
     {
       if (GDK_WINDOW_TYPE (private) == GDK_WINDOW_CHILD)
-       _gdk_window_move_resize_child (window, x, y,
-                                      impl->width, impl->height);
+       {
+         _gdk_window_move_resize_child (window, x, y,
+                                        impl->width, impl->height);
+       }
       else
        {
          XMoveWindow (GDK_WINDOW_XDISPLAY (window),
                       GDK_WINDOW_XID (window),
                       x, y);
+
+         if (impl->override_redirect)
+           {
+             private->x = x;
+             private->y = y;
+           }
        }
     }
 }
@@ -1416,7 +1706,6 @@ gdk_window_resize (GdkWindow *window,
 {
   GdkWindowObject *private;
   
-  g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
   
   if (width < 1)
@@ -1429,19 +1718,33 @@ gdk_window_resize (GdkWindow *window,
   if (!GDK_WINDOW_DESTROYED (window))
     {
       if (GDK_WINDOW_TYPE (private) == GDK_WINDOW_CHILD)
-       _gdk_window_move_resize_child (window, private->x, private->y,
-                                      width, height);
+       {
+         _gdk_window_move_resize_child (window, private->x, private->y,
+                                        width, height);
+         _gdk_x11_drawable_update_size (private->impl);
+       }
       else
        {
          GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
-         
-         if (width != impl->width || height != impl->height)
-           private->resize_count += 1;
 
          XResizeWindow (GDK_WINDOW_XDISPLAY (window),
                         GDK_WINDOW_XID (window),
                         width, height);
+
+         if (impl->override_redirect)
+           {
+             impl->width = width;
+             impl->height = height;
+             _gdk_x11_drawable_update_size (private->impl);
+           }
+         else
+           {
+             if (width != impl->width || height != impl->height)
+               private->resize_count += 1;
+           }
        }
+
+      _gdk_x11_drawable_update_size (private->impl);
     }
 }
 
@@ -1467,7 +1770,6 @@ gdk_window_move_resize (GdkWindow *window,
 {
   GdkWindowObject *private;
   
-  g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
 
   if (width < 1)
@@ -1480,17 +1782,31 @@ gdk_window_move_resize (GdkWindow *window,
   if (!GDK_WINDOW_DESTROYED (window))
     {
       if (GDK_WINDOW_TYPE (private) == GDK_WINDOW_CHILD)
-       _gdk_window_move_resize_child (window, x, y, width, height);
+       {
+         _gdk_window_move_resize_child (window, x, y, width, height);
+         _gdk_x11_drawable_update_size (private->impl);
+       }
       else
        {
          GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
-         
-         if (width != impl->width || height != impl->height)
-           private->resize_count += 1;
-         
+
          XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
                             GDK_WINDOW_XID (window),
                             x, y, width, height);
+         if (impl->override_redirect)
+           {
+             private->x = x;
+             private->y = y;
+             impl->width = width;
+             impl->height = height;
+
+             _gdk_x11_drawable_update_size (private->impl);
+           }
+         else
+           {
+             if (width != impl->width || height != impl->height)
+               private->resize_count += 1;
+           }
        }
     }
 }
@@ -1512,14 +1828,12 @@ gdk_window_reparent (GdkWindow *window,
                     gint       x,
                     gint       y)
 {
-  GdkDisplay *display;
   GdkWindowObject *window_private;
   GdkWindowObject *parent_private;
   GdkWindowObject *old_parent_private;
   GdkWindowImplX11 *impl;
   gboolean was_toplevel;
   
-  g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
@@ -1533,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;
@@ -1591,7 +1903,8 @@ gdk_window_reparent (GdkWindow *window,
                  _gdk_xid_table_remove (GDK_WINDOW_DISPLAY (window), impl->toplevel->focus_window);
                }
                
-             gdk_toplevel_x11_free_contents (impl->toplevel);
+             gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), 
+                                             impl->toplevel);
              g_free (impl->toplevel);
              impl->toplevel = NULL;
            }
@@ -1617,7 +1930,6 @@ _gdk_windowing_window_clear_area (GdkWindow *window,
                                  gint       width,
                                  gint       height)
 {
-  g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
   
   if (!GDK_WINDOW_DESTROYED (window))
@@ -1632,7 +1944,6 @@ _gdk_windowing_window_clear_area_e (GdkWindow *window,
                                    gint       width,
                                    gint       height)
 {
-  g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
   
   if (!GDK_WINDOW_DESTROYED (window))
@@ -1657,7 +1968,6 @@ _gdk_windowing_window_clear_area_e (GdkWindow *window,
 void
 gdk_window_raise (GdkWindow *window)
 {
-  g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
   
   if (!GDK_WINDOW_DESTROYED (window))
@@ -1683,21 +1993,98 @@ gdk_window_raise (GdkWindow *window)
 void
 gdk_window_lower (GdkWindow *window)
 {
-  g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
   
   if (!GDK_WINDOW_DESTROYED (window))
     XLowerWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
 }
 
+/**
+ * gdk_x11_window_move_to_current_desktop:
+ * @window: a #GdkWindow
+ * 
+ * Moves the window to the correct workspace when running under a 
+ * window manager that supports multiple workspaces, as described
+ * in the <ulink url="http://www.freedesktop.org/Standards/wm-spec">Extended 
+ * Window Manager Hints</ulink>.  Will not do anything if the
+ * window is already on all workspaces.
+ * 
+ * Since: 2.8
+ */
+void
+gdk_x11_window_move_to_current_desktop (GdkWindow *window)
+{
+  GdkToplevelX11 *toplevel;
+  toplevel = _gdk_x11_window_get_toplevel (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")))
+    {
+      XEvent xev;
+      Atom type;
+      gint format;
+      gulong nitems;
+      gulong bytes_after;
+      guchar *data;
+      gulong *current_desktop;
+      GdkDisplay *display;
+      
+      display = gdk_drawable_get_display (window);
+
+      /* 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);
+        }
+    }
+}
+
 /**
  * gdk_window_focus:
  * @window: a #GdkWindow
  * @timestamp: timestamp of the event triggering the window focus
  *
- * Sets keyboard focus to @window. If @window is not onscreen this
- * will not work. In most cases, gtk_window_present() should be used on
- * a #GtkWindow, rather than calling this function.
+ * Sets keyboard focus to @window. In most cases, gtk_window_present() 
+ * should be used on a #GtkWindow, rather than calling this function.
  * 
  **/
 void
@@ -1714,7 +2101,7 @@ gdk_window_focus (GdkWindow *window,
   display = GDK_WINDOW_DISPLAY (window);
 
   if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
-                                          gdk_atom_intern ("_NET_ACTIVE_WINDOW", FALSE)))
+                                          gdk_atom_intern_static_string ("_NET_ACTIVE_WINDOW")))
     {
       XEvent xev;
 
@@ -1725,9 +2112,9 @@ gdk_window_focus (GdkWindow *window,
       xev.xclient.message_type = gdk_x11_get_xatom_by_name_for_display (display,
                                                                        "_NET_ACTIVE_WINDOW");
       xev.xclient.format = 32;
-      xev.xclient.data.l[0] = 0;
-      xev.xclient.data.l[1] = 0;
-      xev.xclient.data.l[2] = 0;
+      xev.xclient.data.l[0] = 1; /* requestor type; we're an app */
+      xev.xclient.data.l[1] = timestamp;
+      xev.xclient.data.l[2] = None; /* currently active window */
       xev.xclient.data.l[3] = 0;
       xev.xclient.data.l[4] = 0;
       
@@ -1779,7 +2166,6 @@ gdk_window_set_hints (GdkWindow *window,
 {
   XSizeHints size_hints;
   
-  g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
   
   if (GDK_WINDOW_DESTROYED (window))
@@ -1835,7 +2221,6 @@ gdk_window_set_type_hint (GdkWindow        *window,
   GdkDisplay *display;
   Atom atom;
   
-  g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
   
   if (GDK_WINDOW_DESTROYED (window))
@@ -1866,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 */
@@ -1880,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,
@@ -1914,7 +2392,7 @@ gdk_wmspec_change_state (gboolean   add,
 /**
  * gdk_window_set_modal_hint:
  * @window: A toplevel #GdkWindow
- * @modal: TRUE if the window is modal, FALSE otherwise.
+ * @modal: %TRUE if the window is modal, %FALSE otherwise.
  *
  * The application can use this hint to tell the window manager
  * that a certain window has modal behaviour. The window manager
@@ -1922,7 +2400,7 @@ gdk_wmspec_change_state (gboolean   add,
  * way.
  *
  * You should only use this on windows for which you have
- * previously called #gdk_window_set_transient_for()
+ * previously called gdk_window_set_transient_for()
  **/
 void
 gdk_window_set_modal_hint (GdkWindow *window,
@@ -1930,7 +2408,6 @@ gdk_window_set_modal_hint (GdkWindow *window,
 {
   GdkWindowObject *private;
 
-  g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
   
   if (GDK_WINDOW_DESTROYED (window))
@@ -1942,8 +2419,8 @@ gdk_window_set_modal_hint (GdkWindow *window,
 
   if (GDK_WINDOW_IS_MAPPED (window))
     gdk_wmspec_change_state (modal, window,
-                            gdk_atom_intern ("_NET_WM_STATE_MODAL", FALSE), 
-                            0);
+                            gdk_atom_intern_static_string ("_NET_WM_STATE_MODAL"), 
+                            NULL);
 }
 
 /**
@@ -1954,9 +2431,9 @@ gdk_window_set_modal_hint (GdkWindow *window,
  * Toggles whether a window should appear in a task list or window
  * list. If a window's semantic type as specified with
  * gdk_window_set_type_hint() already fully describes the window, this
- * function should NOT be called in addition, instead you should allow
- * the window to be treated according to standard policy for its
- * semantic type.
+ * function should <emphasis>not</emphasis> be called in addition, 
+ * instead you should allow the window to be treated according to 
+ * standard policy for its semantic type.
  *
  * Since: 2.2
  **/
@@ -1966,7 +2443,6 @@ gdk_window_set_skip_taskbar_hint (GdkWindow *window,
 {
   GdkToplevelX11 *toplevel;
   
-  g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
   
@@ -1978,8 +2454,8 @@ gdk_window_set_skip_taskbar_hint (GdkWindow *window,
 
   if (GDK_WINDOW_IS_MAPPED (window))
     gdk_wmspec_change_state (skips_taskbar, window,
-                            gdk_atom_intern ("_NET_WM_STATE_SKIP_TASKBAR", FALSE), 
-                            0);
+                            gdk_atom_intern_static_string ("_NET_WM_STATE_SKIP_TASKBAR"), 
+                            NULL);
 }
 
 /**
@@ -1991,9 +2467,10 @@ gdk_window_set_skip_taskbar_hint (GdkWindow *window,
  * switcher, or other desktop utility program that displays a small
  * thumbnail representation of the windows on the desktop). If a
  * window's semantic type as specified with gdk_window_set_type_hint()
- * already fully describes the window, this function should NOT be
- * called in addition, instead you should allow the window to be
- * treated according to standard policy for its semantic type.
+ * already fully describes the window, this function should 
+ * <emphasis>not</emphasis> be called in addition, instead you should 
+ * allow the window to be treated according to standard policy for 
+ * its semantic type.
  *
  * Since: 2.2
  **/
@@ -2003,7 +2480,6 @@ gdk_window_set_skip_pager_hint (GdkWindow *window,
 {
   GdkToplevelX11 *toplevel;
     
-  g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
   
@@ -2015,8 +2491,36 @@ gdk_window_set_skip_pager_hint (GdkWindow *window,
   
   if (GDK_WINDOW_IS_MAPPED (window))
     gdk_wmspec_change_state (skips_pager, window,
-                            gdk_atom_intern ("_NET_WM_STATE_SKIP_PAGER", FALSE), 
-                            0);
+                            gdk_atom_intern_static_string ("_NET_WM_STATE_SKIP_PAGER"), 
+                            NULL);
+}
+
+/**
+ * gdk_window_set_urgency_hint:
+ * @window: a toplevel #GdkWindow
+ * @urgent: %TRUE if the window is urgent
+ * 
+ * Toggles whether a window needs the user's
+ * urgent attention.
+ *
+ * Since: 2.8
+ **/
+void
+gdk_window_set_urgency_hint (GdkWindow *window,
+                            gboolean   urgent)
+{
+  GdkToplevelX11 *toplevel;
+    
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
+  
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
+  toplevel = _gdk_x11_window_get_toplevel (window);
+  toplevel->urgency_hint = urgent;
+  
+  update_wm_hints (window, FALSE);
 }
 
 /**
@@ -2038,7 +2542,7 @@ gdk_window_set_skip_pager_hint (GdkWindow *window,
  * gdk_window_move_resize().
  * 
  * Note that on X11, this effect has no effect on windows
- * of type GDK_WINDOW_TEMP or windows where override_redirect
+ * of type %GDK_WINDOW_TEMP or windows where override redirect
  * has been turned on via gdk_window_set_override_redirect()
  * since these windows are not resizable by the user.
  * 
@@ -2055,7 +2559,6 @@ gdk_window_set_geometry_hints (GdkWindow      *window,
 {
   XSizeHints size_hints;
   
-  g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
   
   if (GDK_WINDOW_DESTROYED (window))
@@ -2237,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;
@@ -2257,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;
     }
@@ -2268,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);
     }
@@ -2288,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"),
@@ -2314,7 +2817,6 @@ gdk_window_set_title (GdkWindow   *window,
   Display *xdisplay;
   Window xwindow;
   
-  g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (title != NULL);
 
@@ -2332,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"),
@@ -2365,7 +2867,6 @@ gdk_window_set_role (GdkWindow   *window,
 {
   GdkDisplay *display;
   
-  g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
 
   display = gdk_drawable_get_display (window);
@@ -2375,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"));
@@ -2400,15 +2901,8 @@ void
 gdk_window_set_transient_for (GdkWindow *window, 
                              GdkWindow *parent)
 {
-  GdkWindowObject *private;
-  GdkWindowObject *parent_private;
-  
-  g_return_if_fail (window != NULL);
   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),
@@ -2436,8 +2930,8 @@ gdk_window_set_background (GdkWindow      *window,
                           const GdkColor *color)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkColormap *colormap = gdk_drawable_get_colormap (window);
   
-  g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
   
   if (!GDK_WINDOW_DESTROYED (window))
@@ -2445,6 +2939,7 @@ gdk_window_set_background (GdkWindow      *window,
                          GDK_WINDOW_XID (window), color->pixel);
 
   private->bg_color = *color;
+  gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
 
   if (private->bg_pixmap &&
       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
@@ -2486,10 +2981,15 @@ gdk_window_set_back_pixmap (GdkWindow *window,
   GdkWindowObject *private = (GdkWindowObject *)window;
   Pixmap xpixmap;
   
-  g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (pixmap == NULL || !parent_relative);
   g_return_if_fail (pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap));
+
+  if (pixmap && !gdk_drawable_get_colormap (pixmap))
+    {
+      g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
+      return;
+    }
   
   if (private->bg_pixmap &&
       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
@@ -2538,23 +3038,54 @@ void
 gdk_window_set_cursor (GdkWindow *window,
                       GdkCursor *cursor)
 {
+  GdkWindowObject *private;
+  GdkWindowImplX11 *impl;
   GdkCursorPrivate *cursor_private;
   Cursor xcursor;
   
-  g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
-  
+    
+  private = (GdkWindowObject *)window;
+  impl = GDK_WINDOW_IMPL_X11 (private->impl);
   cursor_private = (GdkCursorPrivate*) cursor;
-  
+
+  if (impl->cursor)
+    {
+      gdk_cursor_unref (impl->cursor);
+      impl->cursor = NULL;
+    }
+
   if (!cursor)
     xcursor = None;
   else
-    xcursor = cursor_private->xcursor;
+    {
+      _gdk_x11_cursor_update_theme (cursor);
+      xcursor = cursor_private->xcursor;
+    }
   
   if (!GDK_WINDOW_DESTROYED (window))
-    XDefineCursor (GDK_WINDOW_XDISPLAY (window),
-                  GDK_WINDOW_XID (window),
-                  xcursor);
+    {
+      XDefineCursor (GDK_WINDOW_XDISPLAY (window),
+                    GDK_WINDOW_XID (window),
+                    xcursor);
+      
+      if (cursor)
+       impl->cursor = gdk_cursor_ref (cursor);
+    }
+}
+
+GdkCursor *
+_gdk_x11_window_get_cursor (GdkWindow *window)
+{
+  GdkWindowObject *private;
+  GdkWindowImplX11 *impl;
+  
+  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
+    
+  private = (GdkWindowObject *)window;
+  impl = GDK_WINDOW_IMPL_X11 (private->impl);
+
+  return impl->cursor;
 }
 
 /**
@@ -2580,6 +3111,14 @@ gdk_window_set_cursor (GdkWindow *window,
  * #GdkEventConfigure. gdk_window_get_position() in contrast gets the
  * position from the most recent configure event.
  * 
+ * <note>
+ * If @window is not a toplevel, it is <emphasis>much</emphasis> better 
+ * to call gdk_window_get_position() and gdk_drawable_get_size() instead, 
+ * because it avoids the roundtrip to the X server and because 
+ * gdk_drawable_get_size() supports the full 32-bit coordinate space,
+ * whereas gdk_window_get_geometry() is restricted to the 16-bit
+ * coordinates of X11.
+ *</note>
  **/
 void
 gdk_window_get_geometry (GdkWindow *window,
@@ -2648,7 +3187,7 @@ gdk_window_get_origin (GdkWindow *window,
   gint tx = 0;
   gint ty = 0;
   
-  g_return_val_if_fail (window != NULL, 0);
+  g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
   
   if (!GDK_WINDOW_DESTROYED (window))
     {
@@ -2699,7 +3238,6 @@ gdk_window_get_deskrelative_origin (GdkWindow *window,
   gulong number_return, bytes_after_return;
   guchar *data_return;
   
-  g_return_val_if_fail (window != NULL, FALSE);
   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
   
   if (!GDK_WINDOW_DESTROYED (window))
@@ -2792,12 +3330,23 @@ void
 gdk_window_get_frame_extents (GdkWindow    *window,
                               GdkRectangle *rect)
 {
+  GdkDisplay *display;
   GdkWindowObject *private;
   Window xwindow;
   Window xparent;
   Window root;
   Window *children;
-  unsigned int nchildren;
+  guchar *data;
+  Window *vroots;
+  Atom type_return;
+  guint nchildren;
+  guint nvroots;
+  gulong nitems_return;
+  gulong bytes_after_return;
+  gint format_return;
+  gint i;
+  guint ww, wh, wb, wd;
+  gint wx, wy;
   
   g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (rect != NULL);
@@ -2825,35 +3374,67 @@ gdk_window_get_frame_extents (GdkWindow    *window,
 
   gdk_error_trap_push();
   
+  /* use NETWM_VIRTUAL_ROOTS if available */
+  display = gdk_drawable_get_display (window);
+  root = GDK_WINDOW_XROOTWIN (window);
+
+  nvroots = 0;
+  vroots = NULL;
+
+  if (XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), root,
+                         gdk_x11_get_xatom_by_name_for_display (display, 
+                                                                "_NET_VIRTUAL_ROOTS"),
+                         0, G_MAXLONG, False, XA_WINDOW, &type_return,
+                         &format_return, &nitems_return, &bytes_after_return,
+                         &data)
+      == Success)
+    {
+      if ((type_return == XA_WINDOW) && (format_return == 32) && (data))
+       {
+         nvroots = nitems_return;
+         vroots = (Window *)data;
+       }
+    }
+
   xparent = GDK_WINDOW_XID (window);
+
   do
     {
       xwindow = xparent;
-      if (!XQueryTree (GDK_WINDOW_XDISPLAY (window), xwindow,
+
+      if (!XQueryTree (GDK_DISPLAY_XDISPLAY (display), xwindow,
                       &root, &xparent,
                       &children, &nchildren))
        goto fail;
       
       if (children)
        XFree (children);
+
+      /* check virtual roots */
+      for (i = 0; i < nvroots; i++)
+       {
+         if (xparent == vroots[i])
+           {
+             root = xparent;
+             break;
+           }
+       }
     }
   while (xparent != root);
   
-  if (xparent == root)
+  if (XGetGeometry (GDK_DISPLAY_XDISPLAY (display), xwindow, 
+                   &root, &wx, &wy, &ww, &wh, &wb, &wd))
     {
-      unsigned int ww, wh, wb, wd;
-      int wx, wy;
-      
-      if (XGetGeometry (GDK_WINDOW_XDISPLAY (window), xwindow, &root, &wx, &wy, &ww, &wh, &wb, &wd))
-       {
-          rect->x = wx;
-          rect->y = wy;
-          rect->width = ww;
-          rect->height = wh;
-       }
+      rect->x = wx;
+      rect->y = wy;
+      rect->width = ww;
+      rect->height = wh;
     }
 
  fail:
+  if (vroots)
+    XFree (vroots);
+
   gdk_error_trap_pop ();
 }
 
@@ -2865,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;
@@ -2876,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)
     {
@@ -2913,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;
@@ -2929,6 +3544,42 @@ _gdk_windowing_window_get_pointer (GdkDisplay      *display,
   return return_val;
 }
 
+/**
+ * gdk_display_warp_pointer:
+ * @display: a #GdkDisplay
+ * @screen: the screen of @display to warp the pointer to
+ * @x: the x coordinate of the destination
+ * @y: the y coordinate of the destination
+ * 
+ * Warps the pointer of @display to the point @x,@y on 
+ * the screen @screen, unless the pointer is confined
+ * to a window by a grab, in which case it will be moved
+ * as far as allowed by the grab. Warping the pointer 
+ * creates events as if the user had moved the mouse 
+ * instantaneously to the destination.
+ * 
+ * Note that the pointer should normally be under the
+ * control of the user. This function was added to cover
+ * some rare use cases like keyboard navigation support
+ * for the color picker in the #GtkColorSelectionDialog.
+ *
+ * Since: 2.8
+ */ 
+void
+gdk_display_warp_pointer (GdkDisplay *display,
+                         GdkScreen  *screen,
+                         gint        x,
+                         gint        y)
+{
+  Display *xdisplay;
+  Window dest;
+
+  xdisplay = GDK_DISPLAY_XDISPLAY (display);
+  dest = GDK_WINDOW_XWINDOW (gdk_screen_get_root_window (screen));
+
+  XWarpPointer (xdisplay, None, dest, 0, 0, 0, 0, x, y);  
+}
+
 GdkWindow*
 _gdk_windowing_window_at_pointer (GdkDisplay *display,
                                   gint       *win_x,
@@ -2956,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;
 
@@ -2994,7 +3710,6 @@ gdk_window_get_events (GdkWindow *window)
   XWindowAttributes attrs;
   GdkEventMask event_mask;
   
-  g_return_val_if_fail (window != NULL, 0);
   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
 
   if (GDK_WINDOW_DESTROYED (window))
@@ -3030,7 +3745,6 @@ gdk_window_set_events (GdkWindow       *window,
   long xevent_mask;
   int i;
   
-  g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
   
   if (!GDK_WINDOW_DESTROYED (window))
@@ -3057,7 +3771,6 @@ gdk_window_add_colormap_windows (GdkWindow *window)
   Window *new_windows;
   int i, count;
   
-  g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
 
   if (GDK_WINDOW_DESTROYED (window))
@@ -3094,59 +3807,24 @@ 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.")
-
-/*
- * This needs the X11 shape extension.
- * 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)
+#define WARN_SHAPE_TOO_BIG() g_warning ("GdkWindow is too large to allow the use of shape masks or shape regions.")
+
+/*
+ * This needs the X11 shape extension.
+ * If not available, shaped windows will look
+ * ugly, but programs still work.    Stefan Wille
+ */
+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;
   
-  g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
   
 #ifdef HAVE_SHAPE_EXT
@@ -3161,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);
@@ -3185,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
@@ -3209,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));
@@ -3237,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,
@@ -3259,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:
@@ -3281,16 +4082,20 @@ gdk_window_set_override_redirect (GdkWindow *window,
 {
   XSetWindowAttributes attr;
   
-  g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
 
   if (!GDK_WINDOW_DESTROYED (window))
     {
-      attr.override_redirect = (override_redirect == FALSE)?False:True;
+      GdkWindowObject *private = (GdkWindowObject *)window;
+      GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
+
+      attr.override_redirect = (override_redirect? True : False);
       XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
                               GDK_WINDOW_XID (window),
                               CWOverrideRedirect,
                               &attr);
+
+      impl->override_redirect = attr.override_redirect;
     }
 }
 
@@ -3312,7 +4117,7 @@ gdk_window_set_accept_focus (GdkWindow *window,
                             gboolean accept_focus)
 {
   GdkWindowObject *private;
-  g_return_if_fail (window != NULL);
+
   g_return_if_fail (GDK_IS_WINDOW (window));
 
   private = (GdkWindowObject *)window;  
@@ -3349,7 +4154,7 @@ gdk_window_set_focus_on_map (GdkWindow *window,
                             gboolean focus_on_map)
 {
   GdkWindowObject *private;
-  g_return_if_fail (window != NULL);
+
   g_return_if_fail (GDK_IS_WINDOW (window));
 
   private = (GdkWindowObject *)window;  
@@ -3391,9 +4196,9 @@ gdk_x11_window_set_user_time (GdkWindow *window,
 {
   GdkDisplay *display;
   GdkDisplayX11 *display_x11;
+  GdkToplevelX11 *toplevel;
   glong timestamp_long = (glong)timestamp;
 
-  g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
 
   if (GDK_WINDOW_DESTROYED (window))
@@ -3401,6 +4206,7 @@ gdk_x11_window_set_user_time (GdkWindow *window,
 
   display = gdk_drawable_get_display (window);
   display_x11 = GDK_DISPLAY_X11 (display);
+  toplevel = _gdk_x11_window_get_toplevel (window);
 
   XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
                    gdk_x11_get_xatom_by_name_for_display (display, "_NET_WM_USER_TIME"),
@@ -3409,8 +4215,16 @@ gdk_x11_window_set_user_time (GdkWindow *window,
 
   if (timestamp_long != GDK_CURRENT_TIME)
     display_x11->user_time = timestamp_long;
+
+  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.
@@ -3439,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));
 
@@ -3449,7 +4264,7 @@ gdk_window_set_icon_list (GdkWindow *window,
   
   l = pixbufs;
   size = 0;
-  
+  n = 0;
   while (l)
     {
       pixbuf = l->data;
@@ -3458,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);
     }
 
@@ -3467,7 +4290,7 @@ gdk_window_set_icon_list (GdkWindow *window,
 
   l = pixbufs;
   p = data;
-  while (l)
+  while (l && n > 0)
     {
       pixbuf = l->data;
       
@@ -3500,6 +4323,7 @@ gdk_window_set_icon_list (GdkWindow *window,
        }
 
       l = g_list_next (l);
+      n--;
     }
 
   if (size > 0)
@@ -3543,7 +4367,6 @@ gdk_window_set_icon (GdkWindow *window,
 {
   GdkToplevelX11 *toplevel;
 
-  g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
   
@@ -3604,7 +4427,6 @@ gdk_window_set_icon_name (GdkWindow   *window,
 {
   GdkDisplay *display;
   
-  g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
 
   if (GDK_WINDOW_DESTROYED (window))
@@ -3619,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"),
@@ -3640,16 +4462,11 @@ gdk_window_set_icon_name (GdkWindow   *window,
 void
 gdk_window_iconify (GdkWindow *window)
 {
-  GdkWindowObject *private;
-  
-  g_return_if_fail (window != NULL);
   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),
@@ -3679,16 +4496,11 @@ gdk_window_iconify (GdkWindow *window)
 void
 gdk_window_deiconify (GdkWindow *window)
 {
-  GdkWindowObject *private;
-  
-  g_return_if_fail (window != NULL);
   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);
@@ -3735,8 +4547,8 @@ gdk_window_stick (GdkWindow *window)
 
       /* Request stick during viewport scroll */
       gdk_wmspec_change_state (TRUE, window,
-                              gdk_atom_intern ("_NET_WM_STATE_STICKY", FALSE),
-                              0);
+                              gdk_atom_intern_static_string ("_NET_WM_STATE_STICKY"),
+                              NULL);
 
       /* Request desktop 0xFFFFFFFF */
       xev.xclient.type = ClientMessage;
@@ -3785,49 +4597,12 @@ gdk_window_unstick (GdkWindow *window)
 
   if (GDK_WINDOW_IS_MAPPED (window))
     {
-      XEvent xev;
-      Atom type;
-      gint format;
-      gulong nitems;
-      gulong bytes_after;
-      gulong *current_desktop;
-      GdkDisplay *display = gdk_drawable_get_display (window);
-      
       /* Request unstick from viewport */
       gdk_wmspec_change_state (FALSE, window,
-                              gdk_atom_intern ("_NET_WM_STATE_STICKY", FALSE),
-                              0);
-
-      /* 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, (guchar **)&current_desktop);
-
-      if (type == XA_CARDINAL)
-        {
-          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);
+                              gdk_atom_intern_static_string ("_NET_WM_STATE_STICKY"),
+                              NULL);
 
-          XFree (current_desktop);
-        }
+      move_to_current_desktop (window);
     }
   else
     {
@@ -3866,8 +4641,8 @@ gdk_window_maximize (GdkWindow *window)
 
   if (GDK_WINDOW_IS_MAPPED (window))
     gdk_wmspec_change_state (TRUE, window,
-                            gdk_atom_intern ("_NET_WM_STATE_MAXIMIZED_VERT", FALSE),
-                            gdk_atom_intern ("_NET_WM_STATE_MAXIMIZED_HORZ", FALSE));
+                            gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_VERT"),
+                            gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_HORZ"));
   else
     gdk_synthesize_window_state (window,
                                 0,
@@ -3901,8 +4676,8 @@ gdk_window_unmaximize (GdkWindow *window)
 
   if (GDK_WINDOW_IS_MAPPED (window))
     gdk_wmspec_change_state (FALSE, window,
-                            gdk_atom_intern ("_NET_WM_STATE_MAXIMIZED_VERT", FALSE),
-                            gdk_atom_intern ("_NET_WM_STATE_MAXIMIZED_HORZ", FALSE));
+                            gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_VERT"),
+                            gdk_atom_intern_static_string ("_NET_WM_STATE_MAXIMIZED_HORZ"));
   else
     gdk_synthesize_window_state (window,
                                 GDK_WINDOW_STATE_MAXIMIZED,
@@ -3939,7 +4714,7 @@ gdk_window_fullscreen (GdkWindow *window)
 
   if (GDK_WINDOW_IS_MAPPED (window))
     gdk_wmspec_change_state (TRUE, window,
-                            gdk_atom_intern ("_NET_WM_STATE_FULLSCREEN", FALSE),
+                            gdk_atom_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
                              GDK_NONE);
 
   else
@@ -3975,7 +4750,7 @@ gdk_window_unfullscreen (GdkWindow *window)
 
   if (GDK_WINDOW_IS_MAPPED (window))
     gdk_wmspec_change_state (FALSE, window,
-                            gdk_atom_intern ("_NET_WM_STATE_FULLSCREEN", FALSE),
+                            gdk_atom_intern_static_string ("_NET_WM_STATE_FULLSCREEN"),
                              GDK_NONE);
 
   else
@@ -4010,10 +4785,15 @@ gdk_window_set_keep_above (GdkWindow *window, gboolean setting)
     return;
 
   if (GDK_WINDOW_IS_MAPPED (window))
-    gdk_wmspec_change_state (setting, window,
-                            gdk_atom_intern ("_NET_WM_STATE_ABOVE", setting),
-                            setting ? gdk_atom_intern ("_NET_WM_STATE_BELOW", FALSE)
-                               : GDK_NONE);
+    {
+      if (setting)
+       gdk_wmspec_change_state (FALSE, window,
+                                gdk_atom_intern_static_string ("_NET_WM_STATE_BELOW"),
+                                GDK_NONE);
+      gdk_wmspec_change_state (setting, window,
+                              gdk_atom_intern_static_string ("_NET_WM_STATE_ABOVE"),
+                              GDK_NONE);
+    }
   else
     gdk_synthesize_window_state (window,
                                 setting ? GDK_WINDOW_STATE_BELOW : GDK_WINDOW_STATE_ABOVE,
@@ -4046,10 +4826,15 @@ gdk_window_set_keep_below (GdkWindow *window, gboolean setting)
     return;
 
   if (GDK_WINDOW_IS_MAPPED (window))
-    gdk_wmspec_change_state (setting, window,
-                            gdk_atom_intern ("_NET_WM_STATE_BELOW", setting),
-                            setting ? gdk_atom_intern ("_NET_WM_STATE_ABOVE", FALSE)
-                                : GDK_NONE);
+    {
+      if (setting)
+       gdk_wmspec_change_state (FALSE, window,
+                                gdk_atom_intern_static_string ("_NET_WM_STATE_ABOVE"),
+                                GDK_NONE);
+      gdk_wmspec_change_state (setting, window,
+                              gdk_atom_intern_static_string ("_NET_WM_STATE_BELOW"),
+                              GDK_NONE);
+    }
   else
     gdk_synthesize_window_state (window,
                                 setting ? GDK_WINDOW_STATE_ABOVE : GDK_WINDOW_STATE_BELOW,
@@ -4071,7 +4856,6 @@ gdk_window_get_group (GdkWindow *window)
 {
   GdkToplevelX11 *toplevel;
   
-  g_return_val_if_fail (window != NULL, NULL);
   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
   g_return_val_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD, NULL);
 
@@ -4105,7 +4889,6 @@ gdk_window_set_group (GdkWindow *window,
 {
   GdkToplevelX11 *toplevel;
   
-  g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
   g_return_if_fail (leader == NULL || GDK_IS_WINDOW (leader));
@@ -4123,6 +4906,7 @@ gdk_window_set_group (GdkWindow *window,
       if (toplevel->group_leader)
        g_object_unref (toplevel->group_leader);
       toplevel->group_leader = g_object_ref (leader);
+      (_gdk_x11_window_get_toplevel (leader))->is_leader = TRUE;      
     }
 
   update_wm_hints (window, FALSE);
@@ -4133,7 +4917,7 @@ gdk_window_get_mwm_hints (GdkWindow *window)
 {
   GdkDisplay *display;
   Atom hints_atom = None;
-  MotifWmHints *hints;
+  guchar *data;
   Atom type;
   gint format;
   gulong nitems;
@@ -4149,12 +4933,12 @@ gdk_window_get_mwm_hints (GdkWindow *window)
   XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
                      hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
                      False, AnyPropertyType, &type, &format, &nitems,
-                     &bytes_after, (guchar **)&hints);
+                     &bytes_after, &data);
 
   if (type == None)
     return NULL;
   
-  return hints;
+  return (MotifWmHints *)data;
 }
 
 static void
@@ -4163,6 +4947,7 @@ gdk_window_set_mwm_hints (GdkWindow *window,
 {
   GdkDisplay *display;
   Atom hints_atom = None;
+  guchar *data;
   MotifWmHints *hints;
   Atom type;
   gint format;
@@ -4179,12 +4964,14 @@ gdk_window_set_mwm_hints (GdkWindow *window,
   XGetWindowProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
                      hints_atom, 0, sizeof (MotifWmHints)/sizeof (long),
                      False, AnyPropertyType, &type, &format, &nitems,
-                     &bytes_after, (guchar **)&hints);
+                     &bytes_after, &data);
   
   if (type == None)
     hints = new_hints;
   else
     {
+      hints = (MotifWmHints *)data;
+       
       if (new_hints->flags & MWM_HINTS_FUNCTIONS)
        {
          hints->flags |= MWM_HINTS_FUNCTIONS;
@@ -4232,9 +5019,10 @@ gdk_window_set_decorations (GdkWindow      *window,
 {
   MotifWmHints hints;
   
-  g_return_if_fail (window != NULL);
   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;
   
@@ -4280,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.
  *
@@ -4299,9 +5089,10 @@ gdk_window_set_functions (GdkWindow    *window,
 {
   MotifWmHints hints;
   
-  g_return_if_fail (window != NULL);
   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;
   
@@ -4497,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;
@@ -4602,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);
        }
@@ -4636,14 +5428,14 @@ gdk_propagate_shapes (Display *disp,
 void
 gdk_window_set_child_shapes (GdkWindow *window)
 {
-  g_return_if_fail (window != NULL);
   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   
 }
 
@@ -4659,22 +5451,77 @@ 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)
 {
-  g_return_if_fail (window != NULL);
   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), 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);
+                         GDK_WINDOW_XID (window), TRUE, ShapeInput);
+#endif
 #endif   
 }
 
+
 static void
 gdk_window_set_static_bit_gravity (GdkWindow *window, gboolean on)
 {
@@ -4682,7 +5529,7 @@ gdk_window_set_static_bit_gravity (GdkWindow *window, gboolean on)
   GdkWindowObject *private;
   guint xattributes_mask = 0;
   
-  g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
 
   private = GDK_WINDOW_OBJECT (window);
   if (private->input_only)
@@ -4701,7 +5548,7 @@ gdk_window_set_static_win_gravity (GdkWindow *window, gboolean on)
 {
   XSetWindowAttributes xattributes;
   
-  g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
   
   xattributes.win_gravity = on ? StaticGravity : NorthWestGravity;
   
@@ -4729,7 +5576,6 @@ gdk_window_set_static_gravities (GdkWindow *window,
   GdkWindowObject *private = (GdkWindowObject *)window;
   GList *tmp_list;
   
-  g_return_val_if_fail (window != NULL, FALSE);
   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
   if (!use_static == !private->guffaw_gravity)
@@ -4987,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)
@@ -5166,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;
@@ -5309,9 +6155,8 @@ emulate_move_drag (GdkWindow     *window,
  * Begins a window resize operation (for a toplevel window).
  * You might use this function to implement a "window resize grip," for
  * example; in fact #GtkStatusbar uses it. The function works best
- * with window managers that support the Extended Window Manager Hints spec
- * (see http://www.freedesktop.org), but has a fallback implementation
- * for other window managers.
+ * with window managers that support the <ulink url="http://www.freedesktop.org/Standards/wm-spec">Extended Window Manager Hints</ulink>, but has a 
+ * fallback implementation for other window managers.
  * 
  **/
 void
@@ -5328,7 +6173,7 @@ gdk_window_begin_resize_drag (GdkWindow     *window,
     return;
 
   if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
-                                          gdk_atom_intern ("_NET_WM_MOVERESIZE", FALSE)))
+                                          gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
     wmspec_resize_drag (window, edge, button, root_x, root_y, timestamp);
   else
     emulate_resize_drag (window, edge, button, root_x, root_y, timestamp);
@@ -5345,8 +6190,8 @@ gdk_window_begin_resize_drag (GdkWindow     *window,
  * Begins a window move operation (for a toplevel window).  You might
  * use this function to implement a "window move grip," for
  * example. The function works best with window managers that support
- * the Extended Window Manager Hints spec (see
- * http://www.freedesktop.org), but has a fallback implementation for
+ * the <ulink url="http://www.freedesktop.org/Standards/wm-spec">Extended 
+ * Window Manager Hints</ulink>, but has a fallback implementation for
  * other window managers.
  * 
  **/
@@ -5363,9 +6208,92 @@ gdk_window_begin_move_drag (GdkWindow *window,
     return;
 
   if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
-                                          gdk_atom_intern ("_NET_WM_MOVERESIZE", FALSE)))
+                                          gdk_atom_intern_static_string ("_NET_WM_MOVERESIZE")))
     wmspec_moveresize (window, _NET_WM_MOVERESIZE_MOVE, root_x, root_y,
                       timestamp);
   else
     emulate_move_drag (window, button, root_x, root_y, timestamp);
 }
+
+/**
+ * gdk_window_enable_synchronized_configure:
+ * @window: a toplevel #GdkWindow
+ * 
+ * Indicates that the application will cooperate with the window
+ * system in synchronizing the window repaint with the window
+ * manager during resizing operations. After an application calls
+ * this function, it must call gdk_window_configure_finished() every
+ * time it has finished all processing associated with a set of
+ * Configure events. Toplevel GTK+ windows automatically use this
+ * protocol.
+ * 
+ * On X, calling this function makes @window participate in the
+ * _NET_WM_SYNC_REQUEST window manager protocol.
+ * 
+ * Since: 2.6
+ **/
+void
+gdk_window_enable_synchronized_configure (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowImplX11 *impl;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  impl = GDK_WINDOW_IMPL_X11 (private->impl);
+         
+  if (!impl->use_synchronized_configure)
+    {
+      impl->use_synchronized_configure = TRUE;
+      ensure_sync_counter (window);
+    }
+}
+
+/**
+ * gdk_window_configure_finished:
+ * @window: a toplevel #GdkWindow
+ * 
+ * Signal to the window system that the application has finished
+ * handling Configure events it has received. Window Managers can
+ * use this to better synchronize the frame repaint with the
+ * application. GTK+ applications will automatically call this
+ * function when appropriate.
+ *
+ * This function can only be called if gdk_window_enable_synchronized_configure()
+ * was called previously.
+ *
+ * Since: 2.6
+ **/
+void
+gdk_window_configure_finished (GdkWindow *window)
+{
+  GdkWindowImplX11 *impl;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  
+  impl = GDK_WINDOW_IMPL_X11 (((GdkWindowObject *)window)->impl);
+  if (!impl->use_synchronized_configure)
+    return;
+  
+#ifdef HAVE_XSYNC
+  if (!GDK_WINDOW_DESTROYED (window))
+    {
+      GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
+      GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
+
+      if (toplevel && toplevel->update_counter != None &&
+         GDK_DISPLAY_X11 (display)->use_sync &&
+         !XSyncValueIsZero (toplevel->current_counter_value))
+       {
+         XSyncSetCounter (GDK_WINDOW_XDISPLAY (window), 
+                          toplevel->update_counter,
+                          toplevel->current_counter_value);
+         
+         XSyncIntToValue (&toplevel->current_counter_value, 0);
+       }
+    }
+#endif
+}
+
+#define __GDK_WINDOW_X11_C__
+#include "gdkaliasdef.c"