]> Pileus Git - ~andy/gtk/blobdiff - gdk/x11/gdkwindow-x11.c
nparams for selection_get should be 3, not 2. [ From Damon Chaplin
[~andy/gtk] / gdk / x11 / gdkwindow-x11.c
index f5de78cc3f162026483fe05b5c4ac009de68a685..56e8cdfb81c01f71f3c0388c69860f12b4f1d420 100644 (file)
  * Library General Public License for more details.
  *
  * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
  */
 
 #include <X11/Xlib.h>
 #include <X11/Xutil.h>
 #include <X11/Xatom.h>
-#include <X11/extensions/shape.h>
 #include <netinet/in.h>
 #include "gdk.h"
-#include "../config.h"
+#include "config.h"
 #include "gdkinput.h"
 #include "gdkprivate.h"
 #include "MwmUtil.h"
-#include <stdlib.h>
-#include <stdio.h>
 
-int nevent_masks = 17;
-int event_mask_table[19] =
+#if HAVE_CONFIG_H
+#  include <config.h>
+#  if STDC_HEADERS
+#    include <stdlib.h>
+#    include <stdio.h>
+#    include <string.h>
+#  endif
+#else
+#  include <stdlib.h>
+#  include <stdio.h>
+#endif
+
+
+#ifdef HAVE_SHAPE_EXT
+#include <X11/extensions/shape.h>
+#endif
+
+const int gdk_event_mask_table[20] =
 {
   ExposureMask,
   PointerMotionMask,
@@ -50,48 +64,65 @@ int event_mask_table[19] =
   PropertyChangeMask,
   VisibilityChangeMask,
   0,                           /* PROXIMITY_IN */
-  0                            /* PROXIMTY_OUT */
+  0,                           /* PROXIMTY_OUT */
+  SubstructureNotifyMask
 };
+const int gdk_nevent_masks = sizeof(gdk_event_mask_table)/sizeof(int);
 
+static gboolean gdk_window_have_shape_ext (void);
 
 /* internal function created for and used by gdk_window_xid_at_coords */
 Window
-gdk_window_xid_at(Window base, gint bx, gint by, gint x, gint y, 
-                 GList *excludes, gboolean excl_child)
+gdk_window_xid_at (Window   base,
+                  gint     bx,
+                  gint     by,
+                  gint     x,
+                  gint     y, 
+                  GList   *excludes,
+                  gboolean excl_child)
 {
    GdkWindow *window;
    GdkWindowPrivate *private;
    Display *disp;
-   Window *list=NULL;
-   Window child=0,parent_win=0,root_win=0;
-   int num,i,ww,wh,wb,wd;
-   int wx,wy;
+   Window *list = NULL;
+   Window child = 0, parent_win = 0, root_win = 0;
+   int i;
+   unsigned int ww, wh, wb, wd, num;
+   int wx, wy;
    
-   window=(GdkWindow*)&gdk_root_parent;
-   private=(GdkWindowPrivate*)window;
-   disp=private->xdisplay;
-   if (!XGetGeometry(disp,base,&root_win,&wx,&wy,&ww,&wh,&wb,&wd))
+   window = (GdkWindow*) &gdk_root_parent;
+   private = (GdkWindowPrivate*) window;
+   disp = private->xdisplay;
+   if (!XGetGeometry (disp, base, &root_win, &wx, &wy, &ww, &wh, &wb, &wd))
      return 0;
-   wx+=bx;wy+=by;
-   if (!((x>=wx)&&(y>=wy)&&(x<(wx+ww))&&(y<(wy+wh))))
+   wx += bx;
+   wy += by;
+
+   if (!((x >= wx) &&
+        (y >= wy) &&
+        (x < (int) (wx + ww)) &&
+        (y < (int) (wy + wh))))
      return 0;
-   if (!XQueryTree(disp,base,&root_win,&parent_win,&list,&num))
+
+   if (!XQueryTree (disp, base, &root_win, &parent_win, &list, &num))
      return base;
+
    if (list)
      {
-       for (i=num-1;;i--)
+       for (i = num - 1; ; i--)
          {
-            if ((!excl_child)||(!g_list_find(excludes,(gpointer *)list[i])))
+            if ((!excl_child) || (!g_list_find (excludes, (gpointer *) list[i])))
               {
-                if ((child=gdk_window_xid_at(list[i],wx,wy,x,y,excludes,excl_child))!=0)
+                if ((child = gdk_window_xid_at (list[i], wx, wy, x, y, excludes, excl_child)) != 0)
                   {
-                    XFree(list);
+                    XFree (list);
                     return child;
                   }
               }
-            if (!i) break;
+            if (!i)
+              break;
          }
-       XFree(list);
+       XFree (list);
      }
    return base;
 }
@@ -110,24 +141,31 @@ gdk_window_xid_at(Window base, gint bx, gint by, gint x, gint y,
  * those X,Y co-ordinates.
  */
 Window
-gdk_window_xid_at_coords(gint x, gint y, GList *excludes, gboolean excl_child)
+gdk_window_xid_at_coords (gint     x,
+                         gint     y,
+                         GList   *excludes,
+                         gboolean excl_child)
 {
    GdkWindow *window;
    GdkWindowPrivate *private;
    Display *disp;
-   Window *list=NULL;
-   Window root,child=0,parent_win=0,root_win=0;
+   Window *list = NULL;
+   Window root, child = 0, parent_win = 0, root_win = 0;
    unsigned int num;
    int i;
    
-   window=(GdkWindow*)&gdk_root_parent;
-   private=(GdkWindowPrivate*)window;
-   disp=private->xdisplay;
-   root=private->xwindow;
-   XGrabServer(disp);
-   num=g_list_length(excludes);
-   if (!XQueryTree(disp,root,&root_win,&parent_win,&list,&num))
-       return root;
+   window = (GdkWindow*) &gdk_root_parent;
+   private = (GdkWindowPrivate*) window;
+   disp = private->xdisplay;
+   root = private->xwindow;
+   num = g_list_length (excludes);
+
+   XGrabServer (disp);
+   if (!XQueryTree (disp, root, &root_win, &parent_win, &list, &num))
+     {
+       XUngrabServer(disp);
+       return root;
+     }
    if (list)
      {
        i = num - 1;
@@ -140,7 +178,7 @@ gdk_window_xid_at_coords(gint x, gint y, GList *excludes, gboolean excl_child)
           if (xwa.map_state != IsViewable)
             continue;
 
-          if (excl_child && g_list_find(excludes,(gpointer *)list[i]))
+          if (excl_child && g_list_find (excludes, (gpointer *) list[i]))
             continue;
           
           if ((child = gdk_window_xid_at (list[i], 0, 0, x, y, excludes, excl_child)) == 0)
@@ -148,28 +186,28 @@ gdk_window_xid_at_coords(gint x, gint y, GList *excludes, gboolean excl_child)
 
           if (excludes)
             {
-              if (!g_list_find(excludes,(gpointer *)child))
+              if (!g_list_find (excludes, (gpointer *) child))
                 {
-                  XFree(list);
-                  XUngrabServer(disp);
+                  XFree (list);
+                  XUngrabServer (disp);
                   return child;
                 }
             }
           else
             {
-              XFree(list);
-              XUngrabServer(disp);
+              XFree (list);
+              XUngrabServer (disp);
               return child;
             }
         } while (--i > 0);
-       XFree(list);
+       XFree (list);
      }
-   XUngrabServer(disp);
+   XUngrabServer (disp);
    return root;
 }
 
 void
-gdk_window_init ()
+gdk_window_init (void)
 {
   XWindowAttributes xattributes;
   unsigned int width;
@@ -182,12 +220,17 @@ gdk_window_init ()
                &x, &y, &width, &height, &border_width, &depth);
   XGetWindowAttributes (gdk_display, gdk_root_window, &xattributes);
 
-  gdk_root_parent.xdisplay = gdk_display;
   gdk_root_parent.xwindow = gdk_root_window;
+  gdk_root_parent.xdisplay = gdk_display;
   gdk_root_parent.window_type = GDK_WINDOW_ROOT;
   gdk_root_parent.window.user_data = NULL;
   gdk_root_parent.width = width;
   gdk_root_parent.height = height;
+  gdk_root_parent.children = NULL;
+  gdk_root_parent.colormap = NULL;
+  gdk_root_parent.ref_count = 1;
+
+  gdk_xid_table_insert (&gdk_root_window, &gdk_root_parent);
 }
 
 GdkWindow*
@@ -199,7 +242,6 @@ gdk_window_new (GdkWindow     *parent,
   GdkWindowPrivate *private;
   GdkWindowPrivate *parent_private;
   GdkVisual *visual;
-  GdkColormap *colormap;
   Display *parent_display;
   Window xparent;
   Visual *xvisual;
@@ -229,8 +271,13 @@ gdk_window_new (GdkWindow     *parent,
   window = (GdkWindow*) private;
 
   private->parent = parent;
+
+  if (parent_private)
+    parent_private->children = g_list_prepend (parent_private->children, window);
+
   private->xdisplay = parent_display;
   private->destroyed = FALSE;
+  private->mapped = FALSE;
   private->resize_count = 0;
   private->ref_count = 1;
   xattributes_mask = 0;
@@ -251,16 +298,9 @@ gdk_window_new (GdkWindow     *parent,
   private->height = (attributes->height > 1) ? (attributes->height) : (1);
   private->window_type = attributes->window_type;
   private->extension_events = FALSE;
-  private->dnd_drag_data_type = None;
-  private->dnd_drag_data_typesavail =
-    private->dnd_drop_data_typesavail = NULL;
-  private->dnd_drop_enabled = private->dnd_drag_enabled =
-    private->dnd_drag_accepted = private->dnd_drag_datashow =
-    private->dnd_drop_data_numtypesavail =
-    private->dnd_drag_data_numtypesavail = 0;
-  private->dnd_drag_eventmask = private->dnd_drag_savedeventmask = 0;
 
   private->filters = NULL;
+  private->children = NULL;
 
   window->user_data = NULL;
 
@@ -271,10 +311,10 @@ gdk_window_new (GdkWindow     *parent,
   xvisual = ((GdkVisualPrivate*) visual)->xvisual;
 
   xattributes.event_mask = StructureNotifyMask;
-  for (i = 0; i < nevent_masks; i++)
+  for (i = 0; i < gdk_nevent_masks; i++)
     {
       if (attributes->event_mask & (1 << (i + 1)))
-       xattributes.event_mask |= event_mask_table[i];
+       xattributes.event_mask |= gdk_event_mask_table[i];
     }
 
   if (xattributes.event_mask)
@@ -293,9 +333,14 @@ gdk_window_new (GdkWindow     *parent,
       depth = visual->depth;
 
       if (attributes_mask & GDK_WA_COLORMAP)
-       colormap = attributes->colormap;
+       private->colormap = attributes->colormap;
       else
-       colormap = gdk_colormap_get_system ();
+       {
+         if ((((GdkVisualPrivate*)gdk_visual_get_system())->xvisual) == xvisual)
+           private->colormap = gdk_colormap_get_system ();
+         else
+           private->colormap = gdk_colormap_new (visual, False);
+       }
 
       xattributes.background_pixel = BlackPixel (gdk_display, gdk_screen);
       xattributes.border_pixel = BlackPixel (gdk_display, gdk_screen);
@@ -304,26 +349,26 @@ gdk_window_new (GdkWindow     *parent,
       switch (private->window_type)
        {
        case GDK_WINDOW_TOPLEVEL:
-         xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap;
+         xattributes.colormap = ((GdkColormapPrivate*) private->colormap)->xcolormap;
          xattributes_mask |= CWColormap;
 
          xparent = gdk_root_window;
          break;
 
        case GDK_WINDOW_CHILD:
-         xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap;
+         xattributes.colormap = ((GdkColormapPrivate*) private->colormap)->xcolormap;
          xattributes_mask |= CWColormap;
          break;
 
        case GDK_WINDOW_DIALOG:
-         xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap;
+         xattributes.colormap = ((GdkColormapPrivate*) private->colormap)->xcolormap;
          xattributes_mask |= CWColormap;
 
          xparent = gdk_root_window;
          break;
 
        case GDK_WINDOW_TEMP:
-         xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap;
+         xattributes.colormap = ((GdkColormapPrivate*) private->colormap)->xcolormap;
          xattributes_mask |= CWColormap;
 
          xparent = gdk_root_window;
@@ -345,7 +390,7 @@ gdk_window_new (GdkWindow     *parent,
     {
       depth = 0;
       class = InputOnly;
-      colormap = NULL;
+      private->colormap = NULL;
     }
 
   private->xwindow = XCreateWindow (private->xdisplay, xparent,
@@ -355,6 +400,9 @@ gdk_window_new (GdkWindow     *parent,
   gdk_window_ref (window);
   gdk_xid_table_insert (&private->xwindow, window);
 
+  if (private->colormap)
+    gdk_colormap_ref (private->colormap);
+
   gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
                                  (attributes->cursor) :
                                  NULL));
@@ -369,10 +417,10 @@ gdk_window_new (GdkWindow     *parent,
       break;
     case GDK_WINDOW_CHILD:
       if ((attributes->wclass == GDK_INPUT_OUTPUT) &&
-         (colormap != gdk_colormap_get_system ()) &&
-         (colormap != gdk_window_get_colormap (gdk_window_get_toplevel (window))))
+         (private->colormap != gdk_colormap_get_system ()) &&
+         (private->colormap != gdk_window_get_colormap (gdk_window_get_toplevel (window))))
        {
-         GDK_NOTE (MISC, g_print ("adding colormap window\n"));
+         GDK_NOTE (MISC, g_message ("adding colormap window\n"));
          gdk_window_add_colormap_windows (window);
        }
 
@@ -402,7 +450,7 @@ gdk_window_new (GdkWindow     *parent,
   if (attributes_mask & GDK_WA_TITLE)
     title = attributes->title;
   else
-    title = gdk_progname;
+    title = g_get_prgname ();
 
   XmbSetWMProperties (private->xdisplay, private->xwindow,
                       title, title,
@@ -427,22 +475,33 @@ gdk_window_foreign_new (guint32 anid)
 {
   GdkWindow *window;
   GdkWindowPrivate *private;
+  GdkWindowPrivate *parent_private;
   XWindowAttributes attrs;
   Window root, parent;
-  Window *children;
+  Window *children = NULL;
   guint nchildren;
 
+  if(!XGetWindowAttributes (gdk_display, anid, &attrs)) {
+    g_warning("XGetWindowAttributes failed on window ID %d\n", anid);
+    return NULL;
+  }
+
   private = g_new (GdkWindowPrivate, 1);
   window = (GdkWindow*) private;
 
-  XGetWindowAttributes (gdk_display, anid, &attrs);
-
   /* FIXME: This is pretty expensive. Maybe the caller should supply
    *        the parent */
   XQueryTree (gdk_display, anid, &root, &parent, &children, &nchildren);
-  XFree (children);
+
+  if (children)
+    XFree (children);
   private->parent = gdk_xid_table_lookup (parent);
 
+  parent_private = (GdkWindowPrivate *)private->parent;
+  
+  if (parent_private)
+    parent_private->children = g_list_prepend (parent_private->children, window);
+
   private->xwindow = anid;
   private->xdisplay = gdk_display;
   private->x = attrs.x;
@@ -453,19 +512,13 @@ gdk_window_foreign_new (guint32 anid)
   private->ref_count = 1;
   private->window_type = GDK_WINDOW_FOREIGN;
   private->destroyed = FALSE;
+  private->mapped = (attrs.map_state != IsUnmapped);
   private->extension_events = 0;
 
-
-  private->dnd_drag_data_type = None;
-  private->dnd_drag_data_typesavail =
-    private->dnd_drop_data_typesavail = NULL;
-  private->dnd_drop_enabled = private->dnd_drag_enabled =
-    private->dnd_drag_accepted = private->dnd_drag_datashow =
-    private->dnd_drop_data_numtypesavail =
-    private->dnd_drag_data_numtypesavail = 0;
-  private->dnd_drag_eventmask = private->dnd_drag_savedeventmask = 0;
+  private->colormap = NULL;
 
   private->filters = NULL;
+  private->children = NULL;
 
   window->user_data = NULL;
 
@@ -504,10 +557,17 @@ gdk_window_internal_destroy (GdkWindow *window, gboolean xdestroy,
     case GDK_WINDOW_FOREIGN:
       if (!private->destroyed)
        {
+         if (private->parent)
+           {
+             GdkWindowPrivate *parent_private = (GdkWindowPrivate *)private->parent;
+             if (parent_private->children)
+               parent_private->children = g_list_remove (parent_private->children, window);
+           }
+
          if (private->window_type != GDK_WINDOW_FOREIGN)
            {
-             children = gdk_window_get_children (window);
-             tmp = children;
+             children = tmp = private->children;
+             private->children = NULL;
 
              while (tmp)
                {
@@ -519,24 +579,13 @@ gdk_window_internal_destroy (GdkWindow *window, gboolean xdestroy,
                    gdk_window_internal_destroy (temp_window, FALSE,
                                                 our_destroy);
                }
-             
+
              g_list_free (children);
            }
 
          if (private->extension_events != 0)
            gdk_input_window_destroy (window);
 
-         if(private->dnd_drag_data_numtypesavail > 0) 
-           {
-             g_free (private->dnd_drag_data_typesavail);
-             private->dnd_drag_data_typesavail = NULL;
-           }
-         if(private->dnd_drop_data_numtypesavail > 0) 
-           {
-             g_free (private->dnd_drop_data_typesavail);
-             private->dnd_drop_data_typesavail = NULL;
-           }
-
          if (private->filters)
            {
              tmp = private->filters;
@@ -578,6 +627,9 @@ gdk_window_internal_destroy (GdkWindow *window, gboolean xdestroy,
          else if (xdestroy)
            XDestroyWindow (private->xdisplay, private->xwindow);
 
+         if (private->colormap)
+           gdk_colormap_unref (private->colormap);
+
          private->destroyed = TRUE;
        }
       break;
@@ -645,7 +697,13 @@ gdk_window_unref (GdkWindow *window)
   if (private->ref_count == 0)
     {
       if (!private->destroyed)
-       g_warning ("losing last reference to undestroyed window\n");
+       {
+         if (private->window_type == GDK_WINDOW_FOREIGN)
+           gdk_xid_table_remove (private->xwindow);
+         else
+           g_warning ("losing last reference to undestroyed window\n");
+       }
+      g_dataset_destroy (window);
       g_free (window);
     }
 }
@@ -660,6 +718,7 @@ gdk_window_show (GdkWindow *window)
   private = (GdkWindowPrivate*) window;
   if (!private->destroyed)
     {
+      private->mapped = TRUE;
       XRaiseWindow (private->xdisplay, private->xwindow);
       XMapWindow (private->xdisplay, private->xwindow);
     }
@@ -674,7 +733,10 @@ gdk_window_hide (GdkWindow *window)
 
   private = (GdkWindowPrivate*) window;
   if (!private->destroyed)
-    XUnmapWindow (private->xdisplay, private->xwindow);
+    {
+      private->mapped = FALSE;
+      XUnmapWindow (private->xdisplay, private->xwindow);
+    }
 }
 
 void
@@ -782,6 +844,7 @@ gdk_window_reparent (GdkWindow *window,
 {
   GdkWindowPrivate *window_private;
   GdkWindowPrivate *parent_private;
+  GdkWindowPrivate *old_parent_private;
 
   g_return_if_fail (window != NULL);
 
@@ -789,6 +852,7 @@ gdk_window_reparent (GdkWindow *window,
     new_parent = (GdkWindow*) &gdk_root_parent;
 
   window_private = (GdkWindowPrivate*) window;
+  old_parent_private = (GdkWindowPrivate*)window_private->parent;
   parent_private = (GdkWindowPrivate*) new_parent;
 
   if (!window_private->destroyed && !parent_private->destroyed)
@@ -796,6 +860,13 @@ gdk_window_reparent (GdkWindow *window,
                     window_private->xwindow,
                     parent_private->xwindow,
                     x, y);
+
+  window_private->parent = new_parent;
+
+  if (old_parent_private)
+    old_parent_private->children = g_list_remove (old_parent_private->children, window);
+  parent_private->children = g_list_prepend (parent_private->children, window);
+  
 }
 
 void
@@ -963,6 +1034,82 @@ gdk_window_set_hints (GdkWindow *window,
     XSetWMNormalHints (private->xdisplay, private->xwindow, &size_hints);
 }
 
+void 
+gdk_window_set_geometry_hints (GdkWindow      *window,
+                              GdkGeometry    *geometry,
+                              GdkWindowHints  geom_mask)
+{
+  GdkWindowPrivate *private;
+  XSizeHints size_hints;
+  
+  g_return_if_fail (window != NULL);
+  
+  private = (GdkWindowPrivate*) window;
+  if (private->destroyed)
+    return;
+  
+  size_hints.flags = 0;
+  
+  if (geom_mask & GDK_HINT_POS)
+    size_hints.flags |= PPosition;
+  
+  if (geom_mask & GDK_HINT_MIN_SIZE)
+    {
+      size_hints.flags |= PMinSize;
+      size_hints.min_width = geometry->min_width;
+      size_hints.min_height = geometry->min_height;
+    }
+  
+  if (geom_mask & GDK_HINT_MAX_SIZE)
+    {
+      size_hints.flags |= PMaxSize;
+      size_hints.max_width = geometry->max_width;
+      size_hints.max_height = geometry->max_height;
+    }
+  
+  if (geom_mask & GDK_HINT_BASE_SIZE)
+    {
+      size_hints.flags |= PBaseSize;
+      size_hints.base_width = geometry->base_width;
+      size_hints.base_height = geometry->base_height;
+    }
+  
+  if (geom_mask & GDK_HINT_RESIZE_INC)
+    {
+      size_hints.flags |= PResizeInc;
+      size_hints.width_inc = geometry->width_inc;
+      size_hints.height_inc = geometry->height_inc;
+    }
+  
+  if (geom_mask & GDK_HINT_ASPECT)
+    {
+      size_hints.flags |= PAspect;
+      if (geometry->min_aspect <= 1)
+       {
+         size_hints.min_aspect.x = G_MAXINT * geometry->min_aspect;
+         size_hints.min_aspect.y = G_MAXINT;
+       }
+      else
+       {
+         size_hints.min_aspect.x = G_MAXINT;
+         size_hints.min_aspect.y = G_MAXINT / geometry->min_aspect;;
+       }
+      if (geometry->max_aspect <= 1)
+       {
+         size_hints.max_aspect.x = G_MAXINT * geometry->max_aspect;
+         size_hints.max_aspect.y = G_MAXINT;
+       }
+      else
+       {
+         size_hints.max_aspect.x = G_MAXINT;
+         size_hints.max_aspect.y = G_MAXINT / geometry->max_aspect;;
+       }
+    }
+  
+  if (geom_mask)
+    XSetWMNormalHints (private->xdisplay, private->xwindow, &size_hints);
+}
+
 void
 gdk_window_set_title (GdkWindow   *window,
                      const gchar *title)
@@ -977,6 +1124,42 @@ gdk_window_set_title (GdkWindow   *window,
                        title, title, NULL, 0, NULL, NULL, NULL);
 }
 
+void          
+gdk_window_set_role (GdkWindow   *window,
+                    const gchar *role)
+{
+  GdkWindowPrivate *private;
+  
+  g_return_if_fail (window != NULL);
+  
+  private = (GdkWindowPrivate*) window;
+
+  if (role)
+    XChangeProperty (private->xdisplay, private->xwindow,
+                    gdk_atom_intern ("WM_WINDOW_ROLE", FALSE), XA_STRING,
+                    8, PropModeReplace, role, strlen(role));
+  else
+    XDeleteProperty (private->xdisplay, private->xwindow,
+                    gdk_atom_intern ("WM_WINDOW_ROLE", FALSE));
+}
+
+void          
+gdk_window_set_transient_for (GdkWindow *window, 
+                             GdkWindow *parent)
+{
+  GdkWindowPrivate *private;
+  GdkWindowPrivate *parent_private;
+  
+  g_return_if_fail (window != NULL);
+  
+  private = (GdkWindowPrivate*) window;
+  parent_private = (GdkWindowPrivate*) parent;
+
+  if (!private->destroyed && !parent_private->destroyed)
+    XSetTransientForHint (private->xdisplay, 
+                         private->xwindow, parent_private->xwindow);
+}
+
 void
 gdk_window_set_background (GdkWindow *window,
                           GdkColor  *color)
@@ -1056,6 +1239,11 @@ gdk_window_set_colormap (GdkWindow   *window,
       XSetWindowColormap (window_private->xdisplay,
                          window_private->xwindow,
                          colormap_private->xcolormap);
+
+      if (window_private->colormap)
+       gdk_colormap_unref (window_private->colormap);
+      window_private->colormap = colormap;
+      gdk_colormap_ref (window_private->colormap);
       
       if (window_private->window_type != GDK_WINDOW_TOPLEVEL)
        gdk_window_add_colormap_windows (window);
@@ -1150,20 +1338,27 @@ gdk_window_get_visual (GdkWindow *window)
 {
   GdkWindowPrivate *window_private;
   XWindowAttributes window_attributes;
-  
+   
   g_return_val_if_fail (window != NULL, NULL);
-  
+
   window_private = (GdkWindowPrivate*) window;
+  /* Huh? ->parent is never set for a pixmap. We should just return
+   * null immeditately
+   */
   while (window_private && (window_private->window_type == GDK_WINDOW_PIXMAP))
     window_private = (GdkWindowPrivate*) window_private->parent;
   
   if (window_private && !window_private->destroyed)
     {
-      XGetWindowAttributes (window_private->xdisplay,
-                           window_private->xwindow,
-                           &window_attributes);
-      
-      return gdk_visual_lookup (window_attributes.visual);
+       if (window_private->colormap == NULL)
+        {
+           XGetWindowAttributes (window_private->xdisplay,
+                                 window_private->xwindow,
+                                 &window_attributes);
+           return gdk_visual_lookup (window_attributes.visual);
+        }
+       else
+        return ((GdkColormapPrivate *)window_private->colormap)->visual;
     }
   
   return NULL;
@@ -1176,16 +1371,20 @@ gdk_window_get_colormap (GdkWindow *window)
   XWindowAttributes window_attributes;
   
   g_return_val_if_fail (window != NULL, NULL);
-  
   window_private = (GdkWindowPrivate*) window;
-  
+
+  g_return_val_if_fail (window_private->window_type != GDK_WINDOW_PIXMAP, NULL);
   if (!window_private->destroyed)
     {
-      XGetWindowAttributes (window_private->xdisplay,
-                           window_private->xwindow,
-                           &window_attributes);
-      
-      return gdk_colormap_lookup (window_attributes.colormap);
+      if (window_private->colormap == NULL)
+       {
+         XGetWindowAttributes (window_private->xdisplay,
+                               window_private->xwindow,
+                               &window_attributes);
+         return gdk_colormap_lookup (window_attributes.colormap);
+        }
+       else
+        return window_private->colormap;
     }
   
   return NULL;
@@ -1210,7 +1409,8 @@ gdk_window_get_origin (GdkWindow *window,
   GdkWindowPrivate *private;
   gint return_val;
   Window child;
-  gint tx, ty;
+  gint tx = 0;
+  gint ty = 0;
 
   g_return_val_if_fail (window != NULL, 0);
 
@@ -1224,17 +1424,140 @@ gdk_window_get_origin (GdkWindow *window,
                                          0, 0, &tx, &ty,
                                          &child);
       
+    }
+  else
+    return_val = 0;
+  
+  if (x)
+    *x = tx;
+  if (y)
+    *y = ty;
+  
+  return return_val;
+}
+
+gboolean
+gdk_window_get_deskrelative_origin (GdkWindow *window,
+                                   gint      *x,
+                                   gint      *y)
+{
+  GdkWindowPrivate *private;
+  gboolean return_val = FALSE;
+  gint num_children, format_return;
+  Window win, *child, parent, root;
+  gint tx = 0;
+  gint ty = 0;
+  Atom type_return;
+  static Atom atom = 0;
+  gulong number_return, bytes_after_return;
+  guchar *data_return;
+  
+  g_return_val_if_fail (window != NULL, 0);
+
+  private = (GdkWindowPrivate*) window;
+
+  if (!private->destroyed)
+    {
+      if (!atom)
+       atom = XInternAtom(private->xdisplay, "ENLIGHTENMENT_DESKTOP", False);
+      win = private->xwindow;
+
+      while (XQueryTree(private->xdisplay, win, &root, &parent,
+                       &child, (unsigned int *)&num_children))
+       {
+         if ((child) && (num_children > 0))
+           XFree(child);
+
+         if (!parent)
+           break;
+         else
+           win = parent;
+
+         if (win == root)
+           break;
+         
+         data_return = NULL;
+         XGetWindowProperty(private->xdisplay, win, atom, 0, 0,
+                            False, XA_CARDINAL, &type_return, &format_return,
+                            &number_return, &bytes_after_return, &data_return);
+         if (type_return == XA_CARDINAL)
+           {
+             XFree(data_return);
+              break;
+           }
+       }
+
+      return_val = XTranslateCoordinates (private->xdisplay,
+                                         private->xwindow,
+                                         win,
+                                         0, 0, &tx, &ty,
+                                         &root);
       if (x)
        *x = tx;
       if (y)
        *y = ty;
     }
-  else
-    return_val = 0;
+
   
   return return_val;
 }
 
+void
+gdk_window_get_root_origin (GdkWindow *window,
+                           gint      *x,
+                           gint      *y)
+{
+  GdkWindowPrivate *private;
+  Window xwindow;
+  Window xparent;
+  Window root;
+  Window *children;
+  unsigned int nchildren;
+
+  g_return_if_fail (window != NULL);
+
+  private = (GdkWindowPrivate*) window;
+  if (x)
+    *x = 0;
+  if (y)
+    *y = 0;
+  if (private->destroyed)
+    return;
+      
+  while (private->parent && ((GdkWindowPrivate*) private->parent)->parent)
+    private = (GdkWindowPrivate*) private->parent;
+  if (private->destroyed)
+    return;
+
+  xparent = private->xwindow;
+  do
+    {
+      xwindow = xparent;
+      if (!XQueryTree (private->xdisplay, xwindow,
+                      &root, &xparent,
+                      &children, &nchildren))
+       return;
+
+      if (children)
+       XFree (children);
+    }
+  while (xparent != root);
+
+  if (xparent == root)
+    {
+      unsigned int ww, wh, wb, wd;
+      int wx, wy;
+
+      if (XGetGeometry (private->xdisplay, xwindow, &root, &wx, &wy, &ww, &wh, &wb, &wd))
+       {
+         if (x)
+           *x = wx;
+         if (y)
+           *y = wy;
+       }
+    }
+}
+
 GdkWindow*
 gdk_window_get_pointer (GdkWindow       *window,
                        gint            *x,
@@ -1246,8 +1569,9 @@ gdk_window_get_pointer (GdkWindow       *window,
   Window root;
   Window child;
   int rootx, rooty;
-  int winx, winy;
-  unsigned int xmask;
+  int winx = 0;
+  int winy = 0;
+  unsigned int xmask = 0;
 
   if (!window)
     window = (GdkWindow*) &gdk_root_parent;
@@ -1259,17 +1583,60 @@ gdk_window_get_pointer (GdkWindow       *window,
       XQueryPointer (private->xdisplay, private->xwindow, &root, &child,
                     &rootx, &rooty, &winx, &winy, &xmask))
     {
-      if (x) *x = winx;
-      if (y) *y = winy;
-      if (mask) *mask = xmask;
-      
       if (child)
        return_val = gdk_window_lookup (child);
     }
   
+  if (x)
+    *x = winx;
+  if (y)
+    *y = winy;
+  if (mask)
+    *mask = xmask;
+  
   return return_val;
 }
 
+GdkWindow*
+gdk_window_at_pointer (gint *win_x,
+                      gint *win_y)
+{
+  GdkWindowPrivate *private;
+  GdkWindow *window;
+  Window root;
+  Window xwindow;
+  Window xwindow_last = 0;
+  int rootx = -1, rooty = -1;
+  int winx, winy;
+  unsigned int xmask;
+
+  private = &gdk_root_parent;
+
+  xwindow = private->xwindow;
+
+  XGrabServer (private->xdisplay);
+  while (xwindow)
+    {
+      xwindow_last = xwindow;
+      XQueryPointer (private->xdisplay,
+                    xwindow,
+                    &root, &xwindow,
+                    &rootx, &rooty,
+                    &winx, &winy,
+                    &xmask);
+    }
+  XUngrabServer (private->xdisplay);
+  
+  window = gdk_window_lookup (xwindow_last);
+
+  if (win_x)
+    *win_x = window ? winx : -1;
+  if (win_y)
+    *win_y = window ? winy : -1;
+
+  return window;
+}
+
 GdkWindow*
 gdk_window_get_parent (GdkWindow *window)
 {
@@ -1328,7 +1695,8 @@ gdk_window_get_children (GdkWindow *window)
             children = g_list_prepend (children, child);
        }
 
-      XFree (xchildren);
+      if (xchildren)
+       XFree (xchildren);
     }
 
   return children;
@@ -1352,9 +1720,9 @@ gdk_window_get_events      (GdkWindow       *window)
                        &attrs);
 
   event_mask = 0;
-  for (i = 0; i < nevent_masks; i++)
+  for (i = 0; i < gdk_nevent_masks; i++)
     {
-      if (attrs.your_event_mask & event_mask_table[i])
+      if (attrs.your_event_mask & gdk_event_mask_table[i])
        event_mask |= 1 << (i + 1);
     }
 
@@ -1376,10 +1744,10 @@ gdk_window_set_events      (GdkWindow       *window,
     return;
 
   xevent_mask = StructureNotifyMask;
-  for (i = 0; i < nevent_masks; i++)
+  for (i = 0; i < gdk_nevent_masks; i++)
     {
       if (event_mask & (1 << (i + 1)))
-       xevent_mask |= event_mask_table[i];
+       xevent_mask |= gdk_event_mask_table[i];
     }
   
   XSelectInput (gdk_display, private->xwindow, 
@@ -1404,17 +1772,20 @@ gdk_window_add_colormap_windows (GdkWindow *window)
   if (window_private->destroyed)
     return;
 
+  old_windows = NULL;
   if (!XGetWMColormapWindows (toplevel_private->xdisplay,
                              toplevel_private->xwindow,
                              &old_windows, &count))
     {
-      old_windows = NULL;
       count = 0;
     }
 
   for (i = 0; i < count; i++)
     if (old_windows[i] == window_private->xwindow)
-      return;
+      {
+       XFree (old_windows);
+       return;
+      }
 
   new_windows = g_new (Window, count + 1);
 
@@ -1431,10 +1802,27 @@ gdk_window_add_colormap_windows (GdkWindow *window)
     XFree (old_windows);
 }
 
+static gboolean
+gdk_window_have_shape_ext (void)
+{
+  enum { UNKNOWN, NO, YES };
+  static gint have_shape = UNKNOWN;
+
+  if (have_shape == UNKNOWN)
+    {
+      int ignore;
+      if (XQueryExtension(gdk_display, "SHAPE", &ignore, &ignore, &ignore))
+       have_shape = YES;
+      else
+       have_shape = NO;
+    }
+
+  return (have_shape == YES);
+}
+
 /*
  * This needs the X11 shape extension.
- * If not available, simply remove the call to
- * XShapeCombineMask. Shaped windows will look
+ * If not available, shaped windows will look
  * ugly, but programs still work.    Stefan Wille
  */
 void
@@ -1447,216 +1835,35 @@ gdk_window_shape_combine_mask (GdkWindow *window,
 
   g_return_if_fail (window != NULL);
 
-  /* This is needed, according to raster */
-  gdk_window_set_override_redirect(window, TRUE);
-
+#ifdef HAVE_SHAPE_EXT
   window_private = (GdkWindowPrivate*) window;
   if (window_private->destroyed)
     return;
 
-  if (mask)
+  if (gdk_window_have_shape_ext())
     {
-      GdkWindowPrivate *pixmap_private;
-
-      pixmap_private = (GdkWindowPrivate*) mask;
-      pixmap = (Pixmap) pixmap_private->xwindow;
-    }
-  else
-    {
-      x = 0;
-      y = 0;
-      pixmap = None;
-    }
-
-  XShapeCombineMask  (window_private->xdisplay,
-                     window_private->xwindow,
-                     ShapeBounding,
-                     x, y,
-                     pixmap,
-                     ShapeSet);
-}
-
-void
-gdk_dnd_drag_addwindow (GdkWindow *window)
-{
-  GdkWindowPrivate *window_private;
-  
-  g_return_if_fail (window != NULL);
-  
-  window_private = (GdkWindowPrivate *) window;
-  if (window_private->destroyed)
-    return;
-  
-  if (window_private->dnd_drag_enabled == 1 && gdk_dnd.drag_really == 0)
-    {
-      gdk_dnd.drag_numwindows++;
-      gdk_dnd.drag_startwindows = g_realloc (gdk_dnd.drag_startwindows,
-                                            gdk_dnd.drag_numwindows
-                                            * sizeof(GdkWindow *));
-      gdk_dnd.drag_startwindows[gdk_dnd.drag_numwindows - 1] = window;
-      window_private->dnd_drag_accepted = 0;
-    } 
-  else
-    g_warning ("dnd_really is 1 or drag is not enabled! can't addwindow\n");
-}
-
-void
-gdk_window_dnd_drag_set (GdkWindow   *window,
-                        guint8       drag_enable,
-                        gchar      **typelist,
-                        guint        numtypes)
-{
-  GdkWindowPrivate *window_private;
-  int i, wasset = 0;
-  
-  g_return_if_fail (window != NULL);
-  window_private = (GdkWindowPrivate *) window;
-  if (window_private->destroyed)
-    return;
-  
-  window_private->dnd_drag_enabled = drag_enable ? 1 : 0;
-  
-  if (drag_enable)
-    {
-      g_return_if_fail(typelist != NULL);
-      
-      if (window_private->dnd_drag_data_numtypesavail > 3)
-       wasset = 1;
-      window_private->dnd_drag_data_numtypesavail = numtypes;
-      
-      window_private->dnd_drag_data_typesavail =
-       g_realloc (window_private->dnd_drag_data_typesavail,
-                  (numtypes + 1) * sizeof (GdkAtom));
-      
-      for (i = 0; i < numtypes; i++)
+      if (mask)
        {
-         /* Allow blanket use of ALL to get anything... */
-         if (strcmp (typelist[i], "ALL"))
-           window_private->dnd_drag_data_typesavail[i] =
-             gdk_atom_intern (typelist[i], FALSE);
-         else
-           window_private->dnd_drag_data_typesavail[i] = None;
+         GdkWindowPrivate *pixmap_private;
+         
+         pixmap_private = (GdkWindowPrivate*) mask;
+         pixmap = (Pixmap) pixmap_private->xwindow;
+       }
+      else
+       {
+         x = 0;
+         y = 0;
+         pixmap = None;
        }
       
-      /* 
-       * set our extended type list if we need to 
-       */
-      if (numtypes > 3)
-       gdk_property_change(window, gdk_dnd.gdk_XdeTypelist,
-                           XA_PRIMARY, 32, GDK_PROP_MODE_REPLACE,
-                           (guchar *)(window_private->dnd_drag_data_typesavail
-                            + (sizeof(GdkAtom) * 3)),
-                           (numtypes - 3) * sizeof(GdkAtom));
-      else if (wasset)
-       gdk_property_delete (window, gdk_dnd.gdk_XdeTypelist);
-    }
-  else
-    {
-      g_free (window_private->dnd_drag_data_typesavail);
-      window_private->dnd_drag_data_typesavail = NULL;
-      window_private->dnd_drag_data_numtypesavail = 0;
-    }
-}
-
-void
-gdk_window_dnd_drop_set (GdkWindow   *window,
-                        guint8       drop_enable,
-                        gchar      **typelist,
-                        guint        numtypes,
-                        guint8       destructive_op)
-{
-  GdkWindowPrivate *window_private;
-  int i;
-  
-  g_return_if_fail (window != NULL);
-  window_private = (GdkWindowPrivate *) window;
-  if (window_private->destroyed)
-    return;
-  
-  window_private->dnd_drop_enabled = drop_enable ? 1 : 0;
-  if (drop_enable)
-    {
-      g_return_if_fail(typelist != NULL);
-      
-      window_private->dnd_drop_data_numtypesavail = numtypes;
-      
-      window_private->dnd_drop_data_typesavail =
-       g_realloc (window_private->dnd_drop_data_typesavail,
-                  (numtypes + 1) * sizeof (GdkAtom));
-      
-      for (i = 0; i < numtypes; i++)
-       window_private->dnd_drop_data_typesavail[i] =
-         gdk_atom_intern (typelist[i], FALSE);
-      
-      window_private->dnd_drop_destructive_op = destructive_op;
+      XShapeCombineMask  (window_private->xdisplay,
+                         window_private->xwindow,
+                         ShapeBounding,
+                         x, y,
+                         pixmap,
+                         ShapeSet);
     }
-}
-
-/* 
- * This is used to reply to a GDK_DRAG_REQUEST event
- * (which may be generated by XdeRequest or a confirmed drop... 
- */
-void
-gdk_window_dnd_data_set (GdkWindow       *window,
-                        GdkEvent        *event,
-                        gpointer         data,
-                        gulong           data_numbytes)
-{
-  GdkWindowPrivate *window_private;
-  XEvent sev;
-  GdkEventDropDataAvailable tmp_ev;
-  gchar *tmp;
-  
-  g_return_if_fail (window != NULL);
-  g_return_if_fail (event != NULL);
-  g_return_if_fail (data != NULL);
-  g_return_if_fail (data_numbytes > 0);
-  g_return_if_fail (event->type == GDK_DRAG_REQUEST);
-
-  window_private = (GdkWindowPrivate *) window;
-  g_return_if_fail (window_private->dnd_drag_accepted != 0);    
-  if (window_private->destroyed)
-    return;
-  
-  /* We set the property on our window... */
-  gdk_property_change (window, window_private->dnd_drag_data_type,
-                      XA_PRIMARY, 8, GDK_PROP_MODE_REPLACE, data,
-                      data_numbytes);
-  tmp = gdk_atom_name(window_private->dnd_drag_data_type);
-#ifdef DEBUG_DND
-  g_print("DnD type %s on window %ld\n", tmp, window_private->xwindow);
-#endif
-  g_free(tmp);
-  
-  /* 
-   * Then we send the event to tell the receiving window that the
-   * drop has happened 
-   */
-  tmp_ev.u.allflags = 0;
-  tmp_ev.u.flags.protocol_version = DND_PROTOCOL_VERSION;
-  tmp_ev.u.flags.isdrop = event->dragrequest.isdrop;
-  
-  sev.xclient.type = ClientMessage;
-  sev.xclient.format = 32;
-  sev.xclient.window = event->dragrequest.requestor;
-  sev.xclient.message_type = gdk_dnd.gdk_XdeDataAvailable;
-  sev.xclient.data.l[0] = window_private->xwindow;
-  sev.xclient.data.l[1] = tmp_ev.u.allflags;
-  sev.xclient.data.l[2] = window_private->dnd_drag_data_type;
-
-  if (event->dragrequest.isdrop)
-    sev.xclient.data.l[3] = event->dragrequest.drop_coords.x +
-      (event->dragrequest.drop_coords.y << 16);
-  else
-    sev.xclient.data.l[3] = 0;
-
-  sev.xclient.data.l[4] = event->dragrequest.timestamp;
-
-  if (!gdk_send_xevent (event->dragrequest.requestor, False,
-                      StructureNotifyMask, &sev))
-    GDK_NOTE (DND, g_print("Sending XdeDataAvailable to %#x failed\n",
-                          event->dragrequest.requestor));
-
+#endif /* HAVE_SHAPE_EXT */
 }
 
 void          
@@ -1701,7 +1908,7 @@ gdk_window_remove_filter  (GdkWindow     *window,
                           gpointer       data)
 {
   GdkWindowPrivate *private;
-  GList *tmp_list;
+  GList *tmp_list, *node;
   GdkEventFilter *filter;
 
   private = (GdkWindowPrivate*) window;
@@ -1714,15 +1921,16 @@ gdk_window_remove_filter  (GdkWindow     *window,
   while (tmp_list)
     {
       filter = (GdkEventFilter *)tmp_list->data;
+      node = tmp_list;
       tmp_list = tmp_list->next;
 
       if ((filter->function == function) && (filter->data == data))
        {
          if(private)
-           private->filters = g_list_remove_link (private->filters, tmp_list);
+           private->filters = g_list_remove_link (private->filters, node);
          else
            gdk_default_filters = g_list_remove_link (gdk_default_filters, tmp_list);
-         g_list_free_1 (tmp_list);
+         g_list_free_1 (node);
          g_free (filter);
          
          return;
@@ -1814,7 +2022,8 @@ gdk_window_set_icon_name   (GdkWindow *window,
   XSetWMIconName (window_private->xdisplay, window_private->xwindow,
                  &property);
 
-  XFree(property.value);
+  if (property.value)
+    XFree (property.value);
 }
 
 void          
@@ -1912,3 +2121,417 @@ gdk_window_set_functions (GdkWindow    *window,
 
   gdk_window_set_mwm_hints (window, &hints);
 }
+
+GList *
+gdk_window_get_toplevels (void)
+{
+  GList *new_list = NULL;
+  GList *tmp_list;
+
+  tmp_list = gdk_root_parent.children;
+  while (tmp_list)
+    {
+      new_list = g_list_prepend (new_list, tmp_list->data);
+      tmp_list = tmp_list->next;
+    }
+
+  return new_list;
+}
+
+/* 
+ * propagate the shapes from all child windows of a GDK window to the parent 
+ * window. Shamelessly ripped from Enlightenment's code
+ * 
+ * - Raster
+ */
+
+struct _gdk_span
+{
+   gint                start;
+   gint                end;
+   struct _gdk_span    *next;
+};
+
+static void
+gdk_add_to_span(struct _gdk_span **s, int x, int xx)
+{
+   struct _gdk_span   *ptr1, *ptr2, *noo, *ss;
+   gchar               spanning;
+   
+   ptr2 = NULL;
+   ptr1 = *s;
+   spanning = 0;
+   ss = NULL;
+   /* scan the spans for this line */
+   while (ptr1)
+     {
+       /* -- -> new span */
+       /* == -> existing span */
+       /* ## -> spans intersect */
+       /* if we are in the middle of spanning the span into the line */
+       if (spanning)
+         {
+            /* case: ---- ==== */
+            if (xx < ptr1->start - 1)
+              {
+                 /* ends before next span - extend to here */
+                 ss->end = xx;
+                 return;
+              }
+            /* case: ----##=== */
+            else if (xx <= ptr1->end)
+              {
+                 /* crosses into next span - delete next span and append */
+                 ss->end = ptr1->end;
+                 ss->next = ptr1->next;
+                 g_free(ptr1);
+                 return;
+              }
+            /* case: ---###--- */
+            else
+              {
+                 /* overlaps next span - delete and keep checking */
+                 ss->next = ptr1->next;
+                 g_free(ptr1);
+                 ptr1 = ss;
+              }
+         }
+       /* otherwise havent started spanning it in yet */
+       else
+         {
+            /* case: ---- ==== */
+            if (xx < ptr1->start - 1)
+              {
+                 /* insert span here in list */
+                 noo = g_malloc(sizeof(struct _gdk_span));
+                 
+                 if (noo)
+                   {
+                      noo->start = x;
+                      noo->end = xx;
+                      noo->next = ptr1;
+                      if (ptr2)
+                        ptr2->next = noo;
+                      else
+                        *s = noo;
+                   }
+                 return;
+              }
+            /* case: ----##=== */
+            else if ((x < ptr1->start) && (xx <= ptr1->end))
+              {
+                 /* expand this span to the left point of the new one */
+                 ptr1->start = x;
+                 return;
+              }
+            /* case: ===###=== */
+            else if ((x >= ptr1->start) && (xx <= ptr1->end))
+              {
+                 /* throw the span away */
+                 return;
+              }
+            /* case: ---###--- */
+            else if ((x < ptr1->start) && (xx > ptr1->end))
+              {
+                 ss = ptr1;
+                 spanning = 1;
+                 ptr1->start = x;
+                 ptr1->end = xx;
+              }
+            /* case: ===##---- */
+            else if ((x >= ptr1->start) && (x <= ptr1->end + 1) && (xx > ptr1->end))
+              {
+                 ss = ptr1;
+                 spanning = 1;
+                 ptr1->end = xx;
+              }
+            /* case: ==== ---- */
+            /* case handled by next loop iteration - first case */
+         }
+       ptr2 = ptr1;
+       ptr1 = ptr1->next;
+     }
+   /* it started in the middle but spans beyond your current list */
+   if (spanning)
+     {
+       ptr2->end = xx;
+       return;
+     }
+   /* it does not start inside a span or in the middle, so add it to the end */
+   noo = g_malloc(sizeof(struct _gdk_span));
+   
+   if (noo)
+     {
+       noo->start = x;
+       noo->end = xx;
+       if (ptr2)
+         {
+            noo->next = ptr2->next;
+            ptr2->next = noo;
+         }
+       else
+         {
+            noo->next = NULL;
+            *s = noo;
+         }
+     }
+   return;
+}
+
+static void
+gdk_add_rectangles (Display *disp, Window win, struct _gdk_span **spans,
+                   gint basew, gint baseh, gint x, gint y)
+{
+  gint a, k;
+  gint x1, y1, x2, y2;
+  gint rn, ord;
+  XRectangle *rl;
+
+  rl = XShapeGetRectangles(disp, win, ShapeBounding, &rn, &ord);
+  if (rl)
+    {
+      /* go through all clip rects in this window's shape */
+      for (k = 0; k < rn; k++)
+       {
+         /* for each clip rect, add it to each line's spans */
+         x1 = x + rl[k].x;
+         x2 = x + rl[k].x + (rl[k].width - 1);
+         y1 = y + rl[k].y;
+         y2 = y + rl[k].y + (rl[k].height - 1);
+         if (x1 < 0)
+           x1 = 0;
+         if (y1 < 0)
+           y1 = 0;
+         if (x2 >= basew)
+           x2 = basew - 1;
+         if (y2 >= baseh)
+           y2 = baseh - 1;
+         for (a = y1; a <= y2; a++)
+           {
+             if ((x2 - x1) >= 0)
+               gdk_add_to_span(&spans[a], x1, x2);
+           }
+       }
+      XFree(rl);
+    }
+}
+
+static void
+gdk_propagate_shapes(Display *disp, Window win, gboolean merge)
+{
+   Window              rt, par, *list = NULL;
+   gint                i, j, num = 0, num_rects = 0;
+   gint                x, y, contig;
+   guint               w, h, d;
+   gint                baseh, basew;
+   XRectangle         *rects = NULL;
+   struct _gdk_span  **spans = NULL, *ptr1, *ptr2, *ptr3;
+   XWindowAttributes   xatt;
+   
+   XGetGeometry(disp, win, &rt, &x, &y, &w, &h, &d, &d);
+   if (h <= 0)
+     return;
+   basew = w;
+   baseh = h;
+   spans = g_malloc(sizeof(struct _gdk_span *) * h);
+   
+   for (i = 0; i < h; i++)
+     spans[i] = NULL;
+   XQueryTree(disp, win, &rt, &par, &list, (unsigned int *)&num);
+   if (list)
+     {
+       /* go through all child windows and create/insert spans */
+       for (i = 0; i < num; i++)
+         {
+            if (XGetWindowAttributes(disp, list[i], &xatt) && (xatt.map_state != IsUnmapped))
+              if (XGetGeometry(disp, list[i], &rt, &x, &y, &w, &h, &d, &d))
+                gdk_add_rectangles (disp, list[i], spans, basew, baseh, x, y);
+         }
+       if (merge)
+         gdk_add_rectangles (disp, win, spans, basew, baseh, x, y);
+
+       /* go through the spans list and build a list of rects */
+       rects = g_malloc(sizeof(XRectangle) * 256);
+       num_rects = 0;
+       for (i = 0; i < baseh; i++)
+         {
+            ptr1 = spans[i];
+            /* go through the line for all spans */
+            while (ptr1)
+              {
+                 rects[num_rects].x = ptr1->start;
+                 rects[num_rects].y = i;
+                 rects[num_rects].width = ptr1->end - ptr1->start + 1;
+                 rects[num_rects].height = 1;
+                 j = i + 1;
+                 /* if there are more lines */
+                 contig = 1;
+                 /* while contigous rects (same start/end coords) exist */
+                 while ((contig) && (j < baseh))
+                   {
+                      /* search next line for spans matching this one */
+                      contig = 0;
+                      ptr2 = spans[j];
+                      ptr3 = NULL;
+                      while (ptr2)
+                        {
+                           /* if we have an exact span match set contig */
+                           if ((ptr2->start == ptr1->start) &&
+                               (ptr2->end == ptr1->end))
+                             {
+                                contig = 1;
+                                /* remove the span - not needed */
+                                if (ptr3)
+                                  {
+                                     ptr3->next = ptr2->next;
+                                     g_free(ptr2);
+                                     ptr2 = NULL;
+                                  }
+                                else
+                                  {
+                                     spans[j] = ptr2->next;
+                                     g_free(ptr2);
+                                     ptr2 = NULL;
+                                  }
+                                break;
+                             }
+                           /* gone past the span point no point looking */
+                           else if (ptr2->start < ptr1->start)
+                             break;
+                           if (ptr2)
+                             {
+                                ptr3 = ptr2;
+                                ptr2 = ptr2->next;
+                             }
+                        }
+                      /* if a contiguous span was found increase the rect h */
+                      if (contig)
+                        {
+                           rects[num_rects].height++;
+                           j++;
+                        }
+                   }
+                 /* up the rect count */
+                 num_rects++;
+                 /* every 256 new rects increase the rect array */
+                 if ((num_rects % 256) == 0)
+                   rects = g_realloc(rects, sizeof(XRectangle) * (num_rects + 256));
+                 ptr1 = ptr1->next;
+              }
+         }
+       /* set the rects as the shape mask */
+       if (rects)
+         {
+            XShapeCombineRectangles(disp, win, ShapeBounding, 0, 0, rects, num_rects,
+                                    ShapeSet, YXSorted);
+            g_free(rects);
+         }
+       XFree(list);
+     }
+   /* free up all the spans we made */
+   for (i = 0; i < baseh; i++)
+     {
+       ptr1 = spans[i];
+       while (ptr1)
+         {
+            ptr2 = ptr1;
+            ptr1 = ptr1->next;
+            g_free(ptr2);
+         }
+     }
+   g_free(spans);
+}
+
+void
+gdk_window_set_child_shapes (GdkWindow *window)
+{
+  GdkWindowPrivate *private;
+   
+  g_return_if_fail (window != NULL);
+   
+#ifdef HAVE_SHAPE_EXT
+  private = (GdkWindowPrivate*) window;
+  if (private->destroyed)
+    return;
+
+  if (gdk_window_have_shape_ext())
+    gdk_propagate_shapes (private->xdisplay, private->xwindow, FALSE);
+#endif   
+}
+
+void
+gdk_window_merge_child_shapes (GdkWindow *window)
+{
+  GdkWindowPrivate *private;
+  
+  g_return_if_fail (window != NULL);
+  
+#ifdef HAVE_SHAPE_EXT
+  private = (GdkWindowPrivate*) window;
+  if (private->destroyed)
+    return;
+
+  if (gdk_window_have_shape_ext())
+    gdk_propagate_shapes (private->xdisplay, private->xwindow, TRUE);
+#endif   
+}
+
+/*************************************************************
+ * gdk_window_is_visible:
+ *     Check if the given window is mapped.
+ *   arguments:
+ *     window: 
+ *   results:
+ *     is the window mapped
+ *************************************************************/
+
+gboolean 
+gdk_window_is_visible (GdkWindow *window)
+{
+  GdkWindowPrivate *private = (GdkWindowPrivate *)window;
+
+  g_return_val_if_fail (window != NULL, FALSE);
+
+  return private->mapped;
+}
+
+/*************************************************************
+ * gdk_window_is_viewable:
+ *     Check if the window and all ancestors of the window
+ *     are mapped. (This is not necessarily "viewable" in
+ *     the X sense, since we only check as far as we have
+ *     GDK window parents, not to the root window)
+ *   arguments:
+ *     window:
+ *   results:
+ *     is the window viewable
+ *************************************************************/
+
+gboolean 
+gdk_window_is_viewable (GdkWindow *window)
+{
+  GdkWindowPrivate *private = (GdkWindowPrivate *)window;
+
+  g_return_val_if_fail (window != NULL, FALSE);
+
+  while (private && (private != &gdk_root_parent))
+    {
+      if (!private->mapped)
+       return FALSE;
+
+      private = (GdkWindowPrivate *)private->parent;
+    }
+
+  return TRUE;
+}
+
+void          
+gdk_drawable_set_data (GdkDrawable   *drawable,
+                      const gchar   *key,
+                      gpointer       data,
+                      GDestroyNotify destroy_func)
+{
+  g_dataset_set_data_full (drawable, key, data, destroy_func);
+}
+
+