]> Pileus Git - ~andy/gtk/blobdiff - gdk/x11/gdkwindow-x11.c
Adapt to uscore-ification of gtktextiterprivate
[~andy/gtk] / gdk / x11 / gdkwindow-x11.c
index 9030fd9d51efc46b22e0ae627b8f110ee6b439f3..73199a71c945f4aea0429d4cfda258422c00844e 100644 (file)
@@ -2,31 +2,53 @@
  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
  *
  * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
+ * modify it under the terms of the GNU Lesser General Public
  * License as published by the Free Software Foundation; either
  * version 2 of the License, or (at your option) any later version.
  *
  * This library is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
+ * Lesser 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.
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
  */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
 #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 "gdkinput.h"
-#include "gdkprivate.h"
+#include "config.h"
+
+#include "gdkwindow.h"
+#include "gdkinputprivate.h"
+#include "gdkprivate-x11.h"
+#include "gdkregion.h"
+#include "gdkinternals.h"
+#include "MwmUtil.h"
+#include "gdkwindow-x11.h"
+
 #include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
 
-int nevent_masks = 16;
-int event_mask_table[18] =
+#ifdef HAVE_SHAPE_EXT
+#include <X11/extensions/shape.h>
+#endif
+
+const int gdk_event_mask_table[21] =
 {
   ExposureMask,
   PointerMotionMask,
@@ -35,8 +57,8 @@ int event_mask_table[18] =
   Button1MotionMask,
   Button2MotionMask,
   Button3MotionMask,
-  ButtonPressMask | OwnerGrabButtonMask,
-  ButtonReleaseMask | OwnerGrabButtonMask,
+  ButtonPressMask,
+  ButtonReleaseMask,
   KeyPressMask,
   KeyReleaseMask,
   EnterWindowMask,
@@ -44,14 +66,205 @@ int event_mask_table[18] =
   FocusChangeMask,
   StructureNotifyMask,
   PropertyChangeMask,
+  VisibilityChangeMask,
   0,                           /* PROXIMITY_IN */
-  0                            /* PROXIMTY_OUT */
+  0,                           /* PROXIMTY_OUT */
+  SubstructureNotifyMask,
+  ButtonPressMask      /* SCROLL; on X mouse wheel events is treated as mouse button 4/5 */
 };
+const int gdk_nevent_masks = sizeof (gdk_event_mask_table) / sizeof (int);
+
+/* Forward declarations */
+static gboolean gdk_window_gravity_works          (void);
+static void     gdk_window_set_static_win_gravity (GdkWindow *window,
+                                                  gboolean   on);
+static gboolean gdk_window_have_shape_ext         (void);
+static gboolean gdk_window_icon_name_set          (GdkWindow *window);
+
+static GdkColormap* gdk_window_impl_x11_get_colormap (GdkDrawable *drawable);
+static void         gdk_window_impl_x11_set_colormap (GdkDrawable *drawable,
+                                                     GdkColormap *cmap);
+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;
+
+GType
+gdk_window_impl_x11_get_type (void)
+{
+  static GType object_type = 0;
+
+  if (!object_type)
+    {
+      static const GTypeInfo object_info =
+      {
+        sizeof (GdkWindowImplX11Class),
+        (GBaseInitFunc) NULL,
+        (GBaseFinalizeFunc) NULL,
+        (GClassInitFunc) gdk_window_impl_x11_class_init,
+        NULL,           /* class_finalize */
+        NULL,           /* class_data */
+        sizeof (GdkWindowImplX11),
+        0,              /* n_preallocs */
+        (GInstanceInitFunc) gdk_window_impl_x11_init,
+      };
+      
+      object_type = g_type_register_static (GDK_TYPE_DRAWABLE_IMPL_X11,
+                                            "GdkWindowImplX11",
+                                            &object_info, 0);
+    }
+  
+  return object_type;
+}
+
+GType
+_gdk_window_impl_get_type (void)
+{
+  return gdk_window_impl_x11_get_type ();
+}
+
+static void
+gdk_window_impl_x11_init (GdkWindowImplX11 *impl)
+{
+  impl->width = 1;
+  impl->height = 1;
+}
+
+static void
+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;
+  drawable_class->get_colormap = gdk_window_impl_x11_get_colormap;
+  drawable_class->get_size = gdk_window_impl_x11_get_size;
+
+  /* Visible and clip regions are the same */
+  drawable_class->get_clip_region = gdk_window_impl_x11_get_visible_region;
+  drawable_class->get_visible_region = gdk_window_impl_x11_get_visible_region;
+}
+
+static void
+gdk_window_impl_x11_finalize (GObject *object)
+{
+  GdkWindowObject *wrapper;
+  GdkDrawableImplX11 *draw_impl;
+  GdkWindowImplX11 *window_impl;
+  
+  g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (object));
+
+  draw_impl = GDK_DRAWABLE_IMPL_X11 (object);
+  window_impl = GDK_WINDOW_IMPL_X11 (object);
+  
+  wrapper = (GdkWindowObject*) draw_impl->wrapper;
+
+  if (!GDK_WINDOW_DESTROYED (wrapper))
+    {
+      gdk_xid_table_remove (draw_impl->xid);
+    }
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+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)
+    {
+      XWindowAttributes window_attributes;
+      
+      XGetWindowAttributes (drawable_impl->xdisplay,
+                            drawable_impl->xid,
+                            &window_attributes);
+      drawable_impl->colormap =
+        gdk_colormap_lookup (window_attributes.colormap);
+    }
+  
+  return drawable_impl->colormap;
+}
+
+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);
+
+  /* chain up */
+  GDK_DRAWABLE_CLASS (parent_class)->set_colormap (drawable, cmap);
+
+  if (cmap)
+    {
+      XSetWindowColormap (draw_impl->xdisplay,
+                          draw_impl->xid,
+                          GDK_COLORMAP_XCOLORMAP (cmap));
+      
+      if (((GdkWindowObject*)draw_impl->wrapper)->window_type !=
+          GDK_WINDOW_TOPLEVEL)
+        gdk_window_add_colormap_windows (GDK_WINDOW (draw_impl->wrapper));
+    }
+}
+
+
+static void
+gdk_window_impl_x11_get_size (GdkDrawable *drawable,
+                              gint        *width,
+                              gint        *height)
+{
+  g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (drawable));
 
+  if (width)
+    *width = GDK_WINDOW_IMPL_X11 (drawable)->width;
+  if (height)
+    *height = GDK_WINDOW_IMPL_X11 (drawable)->height;
+}
+
+static GdkRegion*
+gdk_window_impl_x11_get_visible_region (GdkDrawable *drawable)
+{
+  GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (drawable);
+  GdkRectangle result_rect;
+
+  result_rect.x = 0;
+  result_rect.y = 0;
+  result_rect.width = impl->width;
+  result_rect.height = impl->height;
+
+  gdk_rectangle_intersect (&result_rect, &impl->position_info.clip_rect, &result_rect);
+
+  return gdk_region_rectangle (&result_rect);
+}
 
 void
-gdk_window_init ()
+_gdk_windowing_window_init (void)
 {
+  GdkWindowObject *private;
+  GdkWindowImplX11 *impl;
+  GdkDrawableImplX11 *draw_impl;
   XWindowAttributes xattributes;
   unsigned int width;
   unsigned int height;
@@ -59,142 +272,203 @@ gdk_window_init ()
   unsigned int depth;
   int x, y;
 
+  g_assert (gdk_parent_root == NULL);
+  
   XGetGeometry (gdk_display, gdk_root_window, &gdk_root_window,
                &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.window_type = GDK_WINDOW_ROOT;
-  gdk_root_parent.window.user_data = NULL;
+  gdk_parent_root = g_object_new (GDK_TYPE_WINDOW, NULL);
+  private = (GdkWindowObject *)gdk_parent_root;
+  impl = GDK_WINDOW_IMPL_X11 (private->impl);
+  draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
+  
+  draw_impl->xdisplay = gdk_display;
+  draw_impl->xid = gdk_root_window;
+  draw_impl->wrapper = GDK_DRAWABLE (private);
+  
+  private->window_type = GDK_WINDOW_ROOT;
+  private->depth = depth;
+  impl->width = width;
+  impl->height = height;
+  
+  gdk_xid_table_insert (&gdk_root_window, gdk_parent_root);
 }
 
+static GdkAtom wm_client_leader_atom = GDK_NONE;
+
 GdkWindow*
 gdk_window_new (GdkWindow     *parent,
                GdkWindowAttr *attributes,
                gint           attributes_mask)
 {
   GdkWindow *window;
-  GdkWindowPrivate *private;
-  GdkWindowPrivate *parent_private;
+  GdkWindowObject *private;
+  GdkWindowObject *parent_private;
+  GdkWindowImplX11 *impl;
+  GdkDrawableImplX11 *draw_impl;
+  
   GdkVisual *visual;
-  GdkColormap *colormap;
-  Display *parent_display;
   Window xparent;
   Visual *xvisual;
+
   XSetWindowAttributes xattributes;
   long xattributes_mask;
   XSizeHints size_hints;
   XWMHints wm_hints;
   XClassHint *class_hint;
   int x, y, depth;
+  
   unsigned int class;
   char *title;
   int i;
-
+  
   g_return_val_if_fail (attributes != NULL, NULL);
-
+  
   if (!parent)
-    parent = (GdkWindow*) &gdk_root_parent;
-
-  parent_private = (GdkWindowPrivate*) parent;
-  xparent = parent_private->xwindow;
-  parent_display = parent_private->xdisplay;
+    parent = gdk_parent_root;
 
-  private = g_new (GdkWindowPrivate, 1);
-  window = (GdkWindow*) private;
+  g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
+  
+  parent_private = (GdkWindowObject*) parent;
+  if (GDK_WINDOW_DESTROYED (parent))
+    return NULL;
+  
+  xparent = GDK_WINDOW_XID (parent);
+  
+  window = g_object_new (GDK_TYPE_WINDOW, NULL);
+  private = (GdkWindowObject *)window;
+  impl = GDK_WINDOW_IMPL_X11 (private->impl);
+  draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
+  draw_impl->wrapper = GDK_DRAWABLE (window);
+  
+  draw_impl->xdisplay = GDK_WINDOW_XDISPLAY (parent); 
+  
+  private->parent = (GdkWindowObject *)parent;
 
-  private->parent = parent;
-  private->xdisplay = parent_display;
-  private->destroyed = FALSE;
-  private->resize_count = 0;
-  private->ref_count = 1;
   xattributes_mask = 0;
-
+  
   if (attributes_mask & GDK_WA_X)
     x = attributes->x;
   else
     x = 0;
-
+  
   if (attributes_mask & GDK_WA_Y)
     y = attributes->y;
   else
     y = 0;
-
+  
   private->x = x;
   private->y = y;
-  private->width = (attributes->width > 1) ? (attributes->width) : (1);
-  private->height = (attributes->height > 1) ? (attributes->height) : (1);
+  impl->width = (attributes->width > 1) ? (attributes->width) : (1);
+  impl->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;
-
-  window->user_data = NULL;
 
+  _gdk_window_init_position (GDK_WINDOW (private));
+  if (impl->position_info.big)
+    private->guffaw_gravity = TRUE;
+  
   if (attributes_mask & GDK_WA_VISUAL)
     visual = attributes->visual;
   else
     visual = gdk_visual_get_system ();
   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)
     xattributes_mask |= CWEventMask;
+  
+  if (attributes_mask & GDK_WA_NOREDIR)
+    {
+      xattributes.override_redirect =
+       (attributes->override_redirect == FALSE)?False:True;
+      xattributes_mask |= CWOverrideRedirect;
+    } 
+  else
+    xattributes.override_redirect = False;
 
+  if (parent_private && parent_private->guffaw_gravity)
+    {
+      xattributes.win_gravity = StaticGravity;
+      xattributes_mask |= CWWinGravity;
+    }
+  
   if (attributes->wclass == GDK_INPUT_OUTPUT)
     {
       class = InputOutput;
       depth = visual->depth;
 
+      private->input_only = FALSE;
+      private->depth = depth;
+      
       if (attributes_mask & GDK_WA_COLORMAP)
-       colormap = attributes->colormap;
+        {
+          draw_impl->colormap = attributes->colormap;
+          gdk_colormap_ref (attributes->colormap);
+        }
       else
-       colormap = gdk_colormap_get_system ();
+       {
+         if ((((GdkVisualPrivate*)gdk_visual_get_system ())->xvisual) == xvisual)
+            {
+              draw_impl->colormap =
+                gdk_colormap_get_system ();
+              gdk_colormap_ref (draw_impl->colormap);
+            }
+         else
+            {
+              draw_impl->colormap =
+                gdk_colormap_new (visual, FALSE);
+            }
+       }
+      
+      private->bg_color.pixel = BlackPixel (gdk_display, gdk_screen);
+      xattributes.background_pixel = private->bg_color.pixel;
 
-      xattributes.background_pixel = BlackPixel (gdk_display, gdk_screen);
+      private->bg_pixmap = NULL;
+      
       xattributes.border_pixel = BlackPixel (gdk_display, gdk_screen);
       xattributes_mask |= CWBorderPixel | CWBackPixel;
 
+      if (private->guffaw_gravity)
+       xattributes.bit_gravity = StaticGravity;
+      else
+       xattributes.bit_gravity = NorthWestGravity;
+      
+      xattributes_mask |= CWBitGravity;
+  
       switch (private->window_type)
        {
        case GDK_WINDOW_TOPLEVEL:
-         xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap;
+         xattributes.colormap = GDK_COLORMAP_XCOLORMAP (draw_impl->colormap);
          xattributes_mask |= CWColormap;
-
+         
          xparent = gdk_root_window;
          break;
-
+         
        case GDK_WINDOW_CHILD:
-         xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap;
+         xattributes.colormap = GDK_COLORMAP_XCOLORMAP (draw_impl->colormap);
          xattributes_mask |= CWColormap;
          break;
-
+         
        case GDK_WINDOW_DIALOG:
-         xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap;
+         xattributes.colormap = GDK_COLORMAP_XCOLORMAP (draw_impl->colormap);
          xattributes_mask |= CWColormap;
-
+         
          xparent = gdk_root_window;
          break;
-
+         
        case GDK_WINDOW_TEMP:
-         xattributes.colormap = ((GdkColormapPrivate*) colormap)->xcolormap;
+         xattributes.colormap = GDK_COLORMAP_XCOLORMAP (draw_impl->colormap);
          xattributes_mask |= CWColormap;
-
+         
          xparent = gdk_root_window;
-
+         
          xattributes.save_under = True;
          xattributes.override_redirect = True;
          xattributes.cursor = None;
@@ -203,259 +477,288 @@ gdk_window_new (GdkWindow     *parent,
        case GDK_WINDOW_ROOT:
          g_error ("cannot make windows of type GDK_WINDOW_ROOT");
          break;
-       case GDK_WINDOW_PIXMAP:
-         g_error ("cannot make windows of type GDK_WINDOW_PIXMAP (use gdk_pixmap_new)");
-         break;
        }
     }
   else
     {
-      depth = 1;
+      depth = 0;
+      private->depth = 0;
       class = InputOnly;
-      colormap = NULL;
+      private->input_only = TRUE;
+      draw_impl->colormap = gdk_colormap_get_system ();
+      gdk_colormap_ref (draw_impl->colormap);
     }
 
-  private->xwindow = XCreateWindow (private->xdisplay, xparent,
-                                   x, y, private->width, private->height,
-                                   0, depth, class, xvisual,
-                                   xattributes_mask, &xattributes);
-  gdk_xid_table_insert (&private->xwindow, window);
+  draw_impl->xid = XCreateWindow (GDK_WINDOW_XDISPLAY (parent),
+                                  xparent,
+                                  impl->position_info.x, impl->position_info.y,
+                                  impl->position_info.width, impl->position_info.height,
+                                  0, depth, class, xvisual,
+                                  xattributes_mask, &xattributes);
 
-  switch (private->window_type)
+  gdk_drawable_ref (window);
+  gdk_xid_table_insert (&GDK_WINDOW_XID (window), window);
+  
+  gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
+                                 (attributes->cursor) :
+                                 NULL));
+  
+  if (parent_private)
+    parent_private->children = g_list_prepend (parent_private->children, window);
+  
+  switch (GDK_WINDOW_TYPE (private))
     {
     case GDK_WINDOW_DIALOG:
-      XSetTransientForHint (private->xdisplay, private->xwindow, xparent);
+      XSetTransientForHint (GDK_WINDOW_XDISPLAY (window),
+                           GDK_WINDOW_XID (window),
+                           xparent);
     case GDK_WINDOW_TOPLEVEL:
     case GDK_WINDOW_TEMP:
-      XSetWMProtocols (private->xdisplay, private->xwindow, gdk_wm_window_protocols, 2);
+      XSetWMProtocols (GDK_WINDOW_XDISPLAY (window),
+                      GDK_WINDOW_XID (window),
+                      gdk_wm_window_protocols, 3);
       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))))
+         (draw_impl->colormap != gdk_colormap_get_system ()) &&
+         (draw_impl->colormap != gdk_window_get_colormap (gdk_window_get_toplevel (window))))
        {
-         g_print ("adding colormap window\n");
+         GDK_NOTE (MISC, g_message ("adding colormap window\n"));
          gdk_window_add_colormap_windows (window);
        }
-      break;
+      
+      return window;
     default:
-      break;
+      
+      return window;
     }
-
-  size_hints.flags = PSize | PBaseSize;
-  size_hints.width = private->width;
-  size_hints.height = private->height;
-  size_hints.base_width = private->width;
-  size_hints.base_height = private->height;
-
+  
+  size_hints.flags = PSize;
+  size_hints.width = impl->width;
+  size_hints.height = impl->height;
+  
   wm_hints.flags = InputHint | StateHint | WindowGroupHint;
   wm_hints.window_group = gdk_leader_window;
   wm_hints.input = True;
   wm_hints.initial_state = NormalState;
-
-  XSetWMNormalHints (private->xdisplay, private->xwindow, &size_hints);
-  XSetWMHints (private->xdisplay, private->xwindow, &wm_hints);
-
+  
+  /* FIXME: Is there any point in doing this? Do any WM's pay
+   * attention to PSize, and even if they do, is this the
+   * correct value???
+   */
+  XSetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
+                    GDK_WINDOW_XID (window),
+                    &size_hints);
+  
+  XSetWMHints (GDK_WINDOW_XDISPLAY (window),
+              GDK_WINDOW_XID (window),
+              &wm_hints);
+  
+  if (!wm_client_leader_atom)
+    wm_client_leader_atom = gdk_atom_intern ("WM_CLIENT_LEADER", FALSE);
+  
+  XChangeProperty (GDK_WINDOW_XDISPLAY (window),
+                  GDK_WINDOW_XID (window),
+                  wm_client_leader_atom,
+                  XA_WINDOW, 32, PropModeReplace,
+                  (guchar*) &gdk_leader_window, 1);
+  
   if (attributes_mask & GDK_WA_TITLE)
     title = attributes->title;
   else
-    title = gdk_progname;
-
-  XmbSetWMProperties (private->xdisplay, private->xwindow,
-                      title, title,
-                      NULL, 0,
-                      NULL, NULL, NULL);
+    title = g_get_prgname ();
 
+  gdk_window_set_title (window, title);
+  
   if (attributes_mask & GDK_WA_WMCLASS)
     {
       class_hint = XAllocClassHint ();
       class_hint->res_name = attributes->wmclass_name;
       class_hint->res_class = attributes->wmclass_class;
-      XSetClassHint (private->xdisplay, private->xwindow, class_hint);
+      XSetClassHint (GDK_WINDOW_XDISPLAY (window),
+                    GDK_WINDOW_XID (window),
+                    class_hint);
       XFree (class_hint);
     }
-
-  gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
-                                 (attributes->cursor) :
-                                 NULL));
-
+  
   return window;
 }
 
 GdkWindow *
-gdk_window_foreign_new (guint32 anid)
+gdk_window_foreign_new (GdkNativeWindow anid)
 {
   GdkWindow *window;
-  GdkWindowPrivate *private;
+  GdkWindowObject *private;
+  GdkWindowObject *parent_private;
+  GdkWindowImplX11 *impl;
+  GdkDrawableImplX11 *draw_impl;
   XWindowAttributes attrs;
+  Window root, parent;
+  Window *children = NULL;
+  guint nchildren;
+  gboolean result;
+
+  gdk_error_trap_push ();
+  result = XGetWindowAttributes (gdk_display, anid, &attrs);
+  if (gdk_error_trap_pop () || !result)
+    return NULL;
+
+  /* FIXME: This is pretty expensive. Maybe the caller should supply
+   *        the parent */
+  gdk_error_trap_push ();
+  result = XQueryTree (gdk_display, anid, &root, &parent, &children, &nchildren);
+  if (gdk_error_trap_pop () || !result)
+    return NULL;
+
+  if (children)
+    XFree (children);
+  
+  window = g_object_new (GDK_TYPE_WINDOW, NULL);
+  private = (GdkWindowObject *)window;
+  impl = GDK_WINDOW_IMPL_X11 (private->impl);
+  draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
+  draw_impl->wrapper = GDK_DRAWABLE (window);
+  
+  private->parent = gdk_xid_table_lookup (parent);
+  
+  parent_private = (GdkWindowObject *)private->parent;
+  
+  if (parent_private)
+    parent_private->children = g_list_prepend (parent_private->children, window);
 
-  private = g_new (GdkWindowPrivate, 1);
-  window = (GdkWindow*) private;
-
-  XGetWindowAttributes (gdk_display, anid, &attrs);
+  draw_impl->xid = anid;
+  draw_impl->xdisplay = gdk_display;
 
-  private->parent = NULL;
-  private->xwindow = anid;
-  private->xdisplay = gdk_display;
   private->x = attrs.x;
   private->y = attrs.y;
-  private->width = attrs.width;
-  private->height = attrs.height;
-  private->resize_count = 0;
-  private->ref_count = 1;
-  if (anid == attrs.root)
-    private->window_type = GDK_WINDOW_ROOT;
-  else
-    private->window_type = GDK_WINDOW_TOPLEVEL;
-  /* the above is probably wrong, but it may not be worth the extra
-     X call to get it right */
-    
+  impl->width = attrs.width;
+  impl->height = attrs.height;
+  private->window_type = GDK_WINDOW_FOREIGN;
   private->destroyed = FALSE;
-  private->extension_events = 0;
-
-  window->user_data = NULL;
-
-  gdk_xid_table_insert (&private->xwindow, window);
-
+  private->mapped = (attrs.map_state != IsUnmapped);
+  private->depth = attrs.depth;
+  
+  gdk_drawable_ref (window);
+  gdk_xid_table_insert (&GDK_WINDOW_XID (window), window);
+  
   return window;
 }
 
 void
-gdk_window_destroy (GdkWindow *window)
+_gdk_windowing_window_destroy (GdkWindow *window,
+                              gboolean   recursing,
+                              gboolean   foreign_destroy)
 {
-  GdkWindowPrivate *private;
-  GdkWindowPrivate *temp_private;
-  GdkWindow *temp_window;
-  GList *children;
-  GList *tmp;
+  GdkWindowObject *private = (GdkWindowObject *)window;
 
-  g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
 
-  private = (GdkWindowPrivate*) window;
-  if(private->dnd_drag_data_numtypesavail > 0) 
-    {
-      free(private->dnd_drag_data_typesavail);
-      private->dnd_drag_data_typesavail = NULL;
-    }
-  if(private->dnd_drop_data_numtypesavail > 0) 
-    {
-      free(private->dnd_drop_data_typesavail);
-      private->dnd_drop_data_typesavail = NULL;
-    }
+  _gdk_selection_window_destroyed (window);
   
-  switch (private->window_type)
-    {
-    case GDK_WINDOW_TOPLEVEL:
-    case GDK_WINDOW_CHILD:
-    case GDK_WINDOW_DIALOG:
-    case GDK_WINDOW_TEMP:
-      if (private->ref_count >= 1)
-       private->ref_count -= 1;
+  if (private->extension_events != 0)
+    gdk_input_window_destroy (window);
 
-      if (!private->destroyed || (private->destroyed == 2))
+  if (private->window_type == GDK_WINDOW_FOREIGN)
+    {
+      if (!foreign_destroy && (private->parent != NULL))
        {
-         children = gdk_window_get_children (window);
-         tmp = children;
-
-         while (tmp)
-           {
-             temp_window = tmp->data;
-             tmp = tmp->next;
-
-             temp_private = (GdkWindowPrivate*) temp_window;
-             if (temp_private && !temp_private->destroyed)
-               /* Removes some nice coredumps... /David */
-               {
-                 temp_private->destroyed = 2;
-                 temp_private->ref_count += 1;
-                 gdk_window_destroy (temp_window);
-               }
-           }
-
-         g_list_free (children);
-
-         if (!private->destroyed)
-           XDestroyWindow (private->xdisplay, private->xwindow);
-         private->destroyed = TRUE;
+         /* It's somebody else's window, but in our heirarchy,
+          * so reparent it to the root window, and then send
+          * it a delete event, as if we were a WM
+          */
+         XClientMessageEvent xevent;
+         
+         gdk_error_trap_push ();
+         gdk_window_hide (window);
+         gdk_window_reparent (window, NULL, 0, 0);
+         
+         xevent.type = ClientMessage;
+         xevent.window = GDK_WINDOW_XID (window);
+         xevent.message_type = gdk_wm_protocols;
+         xevent.format = 32;
+         xevent.data.l[0] = gdk_wm_delete_window;
+         xevent.data.l[1] = CurrentTime;
+         
+         XSendEvent (GDK_WINDOW_XDISPLAY (window),
+                     GDK_WINDOW_XID (window),
+                     False, 0, (XEvent *)&xevent);
+         gdk_flush ();
+         gdk_error_trap_pop ();
        }
-      break;
-
-    case GDK_WINDOW_ROOT:
-      g_error ("attempted to destroy root window");
-      break;
-
-    case GDK_WINDOW_PIXMAP:
-      g_warning ("called gdk_window_destroy on a pixmap (use gdk_pixmap_destroy)");
-      gdk_pixmap_destroy (window);
-      break;
     }
+  else if (!recursing && !foreign_destroy)
+    XDestroyWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
 }
 
+/* This function is called when the XWindow is really gone.
+ */
 void
-gdk_window_real_destroy (GdkWindow *window)
+gdk_window_destroy_notify (GdkWindow *window)
 {
-  GdkWindowPrivate *private;
-
   g_return_if_fail (window != NULL);
-
-  private = (GdkWindowPrivate*) window;
-
-  if (private->extension_events != 0)
-    gdk_input_window_destroy (window);
-
-  if (private->ref_count == 0)
+  
+  if (!GDK_WINDOW_DESTROYED (window))
     {
-      gdk_xid_table_remove (private->xwindow);
-      g_free (window);
-    }
-}
-
-GdkWindow*
-gdk_window_ref (GdkWindow *window)
-{
-  GdkWindowPrivate *private = (GdkWindowPrivate *)window;
-  g_return_if_fail (window != NULL);
+      if (GDK_WINDOW_TYPE(window) != GDK_WINDOW_FOREIGN)
+       g_warning ("GdkWindow %#lx unexpectedly destroyed", GDK_WINDOW_XID (window));
 
-  private->ref_count += 1;
-  return window;
+      _gdk_window_destroy (window, TRUE);
+    }
+  
+  gdk_xid_table_remove (GDK_WINDOW_XID (window));
+  gdk_drawable_unref (window);
 }
 
 void
-gdk_window_unref (GdkWindow *window)
+gdk_window_show (GdkWindow *window)
 {
-  GdkWindowPrivate *private = (GdkWindowPrivate *)window;
-  g_return_if_fail (window != NULL);
-
-  private->ref_count -= 1;
-  if (private->ref_count == 0)
-    gdk_window_real_destroy (window);
+  GdkWindowObject *private;
+  
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  
+  private = (GdkWindowObject*) window;
+  if (!private->destroyed)
+    {
+      private->mapped = TRUE;
+      XRaiseWindow (GDK_WINDOW_XDISPLAY (window),
+                   GDK_WINDOW_XID (window));
+      
+      if (GDK_WINDOW_IMPL_X11 (private->impl)->position_info.mapped)
+       XMapWindow (GDK_WINDOW_XDISPLAY (window),
+                   GDK_WINDOW_XID (window));
+    }
 }
 
 void
-gdk_window_show (GdkWindow *window)
+gdk_window_hide (GdkWindow *window)
 {
-  GdkWindowPrivate *private;
-
+  GdkWindowObject *private;
+  
   g_return_if_fail (window != NULL);
 
-  private = (GdkWindowPrivate*) window;
+  private = (GdkWindowObject*) window;
   if (!private->destroyed)
     {
-      XRaiseWindow (private->xdisplay, private->xwindow);
-      XMapWindow (private->xdisplay, private->xwindow);
+      private->mapped = FALSE;
+
+      _gdk_window_clear_update_area (window);
+      
+      XUnmapWindow (GDK_WINDOW_XDISPLAY (window),
+                   GDK_WINDOW_XID (window));
     }
 }
 
 void
-gdk_window_hide (GdkWindow *window)
+gdk_window_withdraw (GdkWindow *window)
 {
-  GdkWindowPrivate *private;
-
+  GdkWindowObject *private;
+  
   g_return_if_fail (window != NULL);
-
-  private = (GdkWindowPrivate*) window;
+  
+  private = (GdkWindowObject*) window;
   if (!private->destroyed)
-    XUnmapWindow (private->xdisplay, private->xwindow);
+    XWithdrawWindow (GDK_WINDOW_XDISPLAY (window),
+                    GDK_WINDOW_XID (window), 0);
 }
 
 void
@@ -463,17 +766,25 @@ gdk_window_move (GdkWindow *window,
                 gint       x,
                 gint       y)
 {
-  GdkWindowPrivate *private;
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowImplX11 *impl;
 
   g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
 
-  private = (GdkWindowPrivate*) window;
-  XMoveWindow (private->xdisplay, private->xwindow, x, y);
+  impl = GDK_WINDOW_IMPL_X11 (private->impl);
 
-  if (private->window_type == GDK_WINDOW_CHILD)
+  if (!GDK_WINDOW_DESTROYED (window))
     {
-      private->x = x;
-      private->y = y;
+      if (GDK_WINDOW_TYPE (private) == GDK_WINDOW_CHILD)
+       _gdk_window_move_resize_child (window, x, y,
+                                      impl->width, impl->height);
+      else
+       {
+         XMoveWindow (GDK_WINDOW_XDISPLAY (window),
+                      GDK_WINDOW_XID (window),
+                      x, y);
+       }
     }
 }
 
@@ -482,29 +793,29 @@ gdk_window_resize (GdkWindow *window,
                   gint       width,
                   gint       height)
 {
-  GdkWindowPrivate *private;
-
+  GdkWindowObject *private;
+  
   g_return_if_fail (window != NULL);
-
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  
   if (width < 1)
     width = 1;
   if (height < 1)
     height = 1;
 
-  private = (GdkWindowPrivate*) window;
-
-  if (!private->destroyed &&
-      ((private->resize_count > 0) ||
-       (private->width != (guint16) width) ||
-       (private->height != (guint16) height)))
+  private = (GdkWindowObject*) window;
+  
+  if (!GDK_WINDOW_DESTROYED (window))
     {
-      XResizeWindow (private->xdisplay, private->xwindow, width, height);
-      private->resize_count += 1;
-
-      if (private->window_type == GDK_WINDOW_CHILD)
+      if (GDK_WINDOW_TYPE (private) == GDK_WINDOW_CHILD)
+       _gdk_window_move_resize_child (window, private->x, private->y,
+                                      width, height);
+      else
        {
-         private->width = width;
-         private->height = height;
+         XResizeWindow (GDK_WINDOW_XDISPLAY (window),
+                        GDK_WINDOW_XID (window),
+                        width, height);
+         private->resize_count += 1;
        }
     }
 }
@@ -516,25 +827,29 @@ gdk_window_move_resize (GdkWindow *window,
                        gint       width,
                        gint       height)
 {
-  GdkWindowPrivate *private;
-
+  GdkWindowObject *private;
+  
   g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
 
   if (width < 1)
     width = 1;
   if (height < 1)
     height = 1;
+  
+  private = (GdkWindowObject*) window;
 
-  private = (GdkWindowPrivate*) window;
-  XMoveResizeWindow (private->xdisplay, private->xwindow, x, y, width, height);
-
-  if (!private->destroyed &&
-      (private->window_type == GDK_WINDOW_CHILD))
+  if (!GDK_WINDOW_DESTROYED (window))
     {
-      private->x = x;
-      private->y = y;
-      private->width = width;
-      private->height = height;
+      if (GDK_WINDOW_TYPE (private) == GDK_WINDOW_CHILD)
+       _gdk_window_move_resize_child (window, x, y, width, height);
+      else
+       {
+         XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
+                            GDK_WINDOW_XID (window),
+                            x, y, width, height);
+         private->resize_count += 1;
+       }
     }
 }
 
@@ -544,139 +859,89 @@ gdk_window_reparent (GdkWindow *window,
                     gint       x,
                     gint       y)
 {
-  GdkWindowPrivate *window_private;
-  GdkWindowPrivate *parent_private;
-
+  GdkWindowObject *window_private;
+  GdkWindowObject *parent_private;
+  GdkWindowObject *old_parent_private;
+  
   g_return_if_fail (window != NULL);
-
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (new_parent != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (new_parent));
+  
   if (!new_parent)
-    new_parent = (GdkWindow*) &gdk_root_parent;
-
-  window_private = (GdkWindowPrivate*) window;
-  parent_private = (GdkWindowPrivate*) new_parent;
-
-  XReparentWindow (window_private->xdisplay,
-                  window_private->xwindow,
-                  parent_private->xwindow,
-                  x, y);
-}
-
-void
-gdk_window_clear (GdkWindow *window)
-{
-  GdkWindowPrivate *private;
-
-  g_return_if_fail (window != NULL);
-
-  private = (GdkWindowPrivate*) window;
-
-  XClearWindow (private->xdisplay, private->xwindow);
+    new_parent = gdk_parent_root;
+  
+  window_private = (GdkWindowObject*) window;
+  old_parent_private = (GdkWindowObject*)window_private->parent;
+  parent_private = (GdkWindowObject*) new_parent;
+  
+  if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (new_parent))
+    XReparentWindow (GDK_WINDOW_XDISPLAY (window),
+                    GDK_WINDOW_XID (window),
+                    GDK_WINDOW_XID (new_parent),
+                    x, y);
+  
+  window_private->parent = (GdkWindowObject *)new_parent;
+  
+  if (old_parent_private)
+    old_parent_private->children = g_list_remove (old_parent_private->children, window);
+  
+  if ((old_parent_private &&
+       (!old_parent_private->guffaw_gravity != !parent_private->guffaw_gravity)) ||
+      (!old_parent_private && parent_private->guffaw_gravity))
+    gdk_window_set_static_win_gravity (window, parent_private->guffaw_gravity);
+  
+  parent_private->children = g_list_prepend (parent_private->children, window);
 }
 
 void
-gdk_window_clear_area (GdkWindow *window,
-                      gint       x,
-                      gint       y,
-                      gint       width,
-                      gint       height)
+_gdk_windowing_window_clear_area (GdkWindow *window,
+                                 gint       x,
+                                 gint       y,
+                                 gint       width,
+                                 gint       height)
 {
-  GdkWindowPrivate *private;
-
   g_return_if_fail (window != NULL);
-
-  private = (GdkWindowPrivate*) window;
-
-  if (!private->destroyed)
-    XClearArea (private->xdisplay, private->xwindow,
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  
+  if (!GDK_WINDOW_DESTROYED (window))
+    XClearArea (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
                x, y, width, height, False);
 }
 
 void
-gdk_window_clear_area_e (GdkWindow *window,
-                        gint       x,
-                        gint       y,
-                        gint       width,
-                        gint       height)
+_gdk_windowing_window_clear_area_e (GdkWindow *window,
+                                   gint       x,
+                                   gint       y,
+                                   gint       width,
+                                   gint       height)
 {
-  GdkWindowPrivate *private;
-
-  g_return_if_fail (window != NULL);
-
-  private = (GdkWindowPrivate*) window;
-
-  if (!private->destroyed)
-    XClearArea (private->xdisplay, private->xwindow,
-               x, y, width, height, True);
-}
-
-void
-gdk_window_copy_area (GdkWindow    *window,
-                     GdkGC        *gc,
-                     gint          x,
-                     gint          y,
-                     GdkWindow    *source_window,
-                     gint          source_x,
-                     gint          source_y,
-                     gint          width,
-                     gint          height)
-{
-  GdkWindowPrivate *src_private;
-  GdkWindowPrivate *dest_private;
-  GdkGCPrivate *gc_private;
-
   g_return_if_fail (window != NULL);
-  g_return_if_fail (gc != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
   
-  if (source_window == NULL)
-    source_window = window;
-
-  src_private = (GdkWindowPrivate*) source_window;
-  dest_private = (GdkWindowPrivate*) window;
-  gc_private = (GdkGCPrivate*) gc;
-  
-  if (!src_private->destroyed && !dest_private->destroyed)
-  {
-    XCopyArea (dest_private->xdisplay, src_private->xwindow, dest_private->xwindow,
-              gc_private->xgc,
-              source_x, source_y,
-              width, height,
-              x, y);
-  }
+  if (!GDK_WINDOW_DESTROYED (window))
+    XClearArea (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
+               x, y, width, height, True);
 }
 
 void
 gdk_window_raise (GdkWindow *window)
 {
-  GdkWindowPrivate *private;
-
   g_return_if_fail (window != NULL);
-
-  private = (GdkWindowPrivate*) window;
-
-  if (!private->destroyed)
-    XRaiseWindow (private->xdisplay, private->xwindow);
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  
+  if (!GDK_WINDOW_DESTROYED (window))
+    XRaiseWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
 }
 
 void
 gdk_window_lower (GdkWindow *window)
-{
-  GdkWindowPrivate *private;
-
-  g_return_if_fail (window != NULL);
-
-  private = (GdkWindowPrivate*) window;
-
-  if (!private->destroyed)
-    XLowerWindow (private->xdisplay, private->xwindow);
-}
-
-void
-gdk_window_set_user_data (GdkWindow *window,
-                         gpointer   user_data)
 {
   g_return_if_fail (window != NULL);
-
-  window->user_data = user_data;
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  
+  if (!GDK_WINDOW_DESTROYED (window))
+    XLowerWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
 }
 
 void
@@ -689,138 +954,342 @@ gdk_window_set_hints (GdkWindow *window,
                      gint       max_height,
                      gint       flags)
 {
-  GdkWindowPrivate *private;
   XSizeHints size_hints;
-
+  
   g_return_if_fail (window != NULL);
-
-  private = (GdkWindowPrivate*) window;
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+  
   size_hints.flags = 0;
-
+  
   if (flags & GDK_HINT_POS)
     {
       size_hints.flags |= PPosition;
       size_hints.x = x;
       size_hints.y = y;
     }
-
+  
   if (flags & GDK_HINT_MIN_SIZE)
     {
       size_hints.flags |= PMinSize;
       size_hints.min_width = min_width;
       size_hints.min_height = min_height;
     }
-
+  
   if (flags & GDK_HINT_MAX_SIZE)
     {
       size_hints.flags |= PMaxSize;
       size_hints.max_width = max_width;
       size_hints.max_height = max_height;
     }
+  
+  /* FIXME: Would it be better to delete this property of
+   *        flags == 0? It would save space on the server
+   */
+  XSetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
+                    GDK_WINDOW_XID (window),
+                    &size_hints);
+}
+
+void 
+gdk_window_set_geometry_hints (GdkWindow      *window,
+                              GdkGeometry    *geometry,
+                              GdkWindowHints  geom_mask)
+{
+  XSizeHints size_hints;
+  
+  g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+  
+  size_hints.flags = 0;
+  
+  if (geom_mask & GDK_HINT_POS)
+    {
+      size_hints.flags |= PPosition;
+      /* We need to initialize the following obsolete fields because KWM 
+       * apparently uses these fields if they are non-zero.
+       * #@#!#!$!.
+       */
+      size_hints.x = 0;
+      size_hints.y = 0;
+    }
+  
+  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 = MAX (geometry->max_width, 1);
+      size_hints.max_height = MAX (geometry->max_height, 1);
+    }
+  
+  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 = 65536 * geometry->min_aspect;
+         size_hints.min_aspect.y = 65536;
+       }
+      else
+       {
+         size_hints.min_aspect.x = 65536;
+         size_hints.min_aspect.y = 65536 / geometry->min_aspect;;
+       }
+      if (geometry->max_aspect <= 1)
+       {
+         size_hints.max_aspect.x = 65536 * geometry->max_aspect;
+         size_hints.max_aspect.y = 65536;
+       }
+      else
+       {
+         size_hints.max_aspect.x = 65536;
+         size_hints.max_aspect.y = 65536 / geometry->max_aspect;;
+       }
+    }
+
+  if (geom_mask & GDK_HINT_WIN_GRAVITY)
+    {
+      size_hints.flags |= PWinGravity;
+      size_hints.width_inc = geometry->win_gravity;
+    }
+  
+  /* FIXME: Would it be better to delete this property of
+   *        geom_mask == 0? It would save space on the server
+   */
+  XSetWMNormalHints (GDK_WINDOW_XDISPLAY (window),
+                    GDK_WINDOW_XID (window),
+                    &size_hints);
+}
+
+static gboolean
+utf8_is_latin1 (const gchar *str)
+{
+  const char *p = str;
+
+  while (*p)
+    {
+      gunichar ch = g_utf8_get_char (p);
+
+      if (ch >= 0xff)
+       return FALSE;
+      
+      p = g_utf8_next_char (p);
+    }
+
+  return TRUE;
+}
+
+/* Set the property to @utf8_str as STRING if the @utf8_str is fully
+ * convertable to STRING, otherwise, set it as compound text
+ */
+static void
+set_text_property (GdkWindow   *window,
+                  GdkAtom      property,
+                  const gchar *utf8_str)
+{
+  guchar *prop_text = NULL;
+  GdkAtom prop_type;
+  gint prop_length;
+  gint prop_format;
+  
+  if (utf8_is_latin1 (utf8_str))
+    {
+      prop_type = GDK_TARGET_STRING;
+      prop_text = gdk_utf8_to_string_target (utf8_str);
+      prop_length = strlen (prop_text);
+      prop_format = 8;
+    }
+  else
+    {
+      gdk_utf8_to_compound_text (utf8_str, &prop_type, &prop_format,
+                                &prop_text, &prop_length);
+    }
 
-  if (flags)
-    XSetWMNormalHints (private->xdisplay, private->xwindow, &size_hints);
+  if (prop_text)
+    {
+      XChangeProperty (GDK_WINDOW_XDISPLAY (window),
+                      GDK_WINDOW_XID (window),
+                      property,
+                      prop_type, prop_format,
+                      PropModeReplace, prop_text,
+                      prop_length);
+
+      g_free (prop_text);
+    }
 }
 
 void
 gdk_window_set_title (GdkWindow   *window,
                      const gchar *title)
 {
-  GdkWindowPrivate *private;
+  g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
 
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+  
+  XChangeProperty (GDK_WINDOW_XDISPLAY (window),
+                  GDK_WINDOW_XID (window),
+                  gdk_atom_intern ("_NET_WM_NAME", FALSE),
+                  gdk_atom_intern ("UTF8_STRING", FALSE), 8,
+                  PropModeReplace, title,
+                  strlen (title));
+
+  set_text_property (window, gdk_atom_intern ("WM_NAME", FALSE), title);
+  if (!gdk_window_icon_name_set (window))
+    set_text_property (window, gdk_atom_intern ("WM_ICON_NAME", FALSE), title);
+}
+
+void          
+gdk_window_set_role (GdkWindow   *window,
+                    const gchar *role)
+{
   g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  if (!GDK_WINDOW_DESTROYED (window))
+    {
+      if (role)
+       XChangeProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
+                        gdk_atom_intern ("WM_WINDOW_ROLE", FALSE), XA_STRING,
+                        8, PropModeReplace, role, strlen (role));
+      else
+       XDeleteProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
+                        gdk_atom_intern ("WM_WINDOW_ROLE", FALSE));
+    }
+}
 
-  private = (GdkWindowPrivate*) window;
-  XmbSetWMProperties (private->xdisplay, private->xwindow,
-                      title, title, NULL, 0, NULL, NULL, NULL);
+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),
+                         GDK_WINDOW_XID (parent));
 }
 
 void
 gdk_window_set_background (GdkWindow *window,
                           GdkColor  *color)
 {
-  GdkWindowPrivate *private;
-
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  
   g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  
+  if (!GDK_WINDOW_DESTROYED (window))
+    XSetWindowBackground (GDK_WINDOW_XDISPLAY (window),
+                         GDK_WINDOW_XID (window), color->pixel);
+
+  private->bg_color = *color;
 
-  private = (GdkWindowPrivate*) window;
-  XSetWindowBackground (private->xdisplay, private->xwindow, color->pixel);
+  if (private->bg_pixmap &&
+      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+      private->bg_pixmap != GDK_NO_BG)
+    {
+      gdk_pixmap_unref (private->bg_pixmap);
+      private->bg_pixmap = NULL;
+    }
 }
 
 void
 gdk_window_set_back_pixmap (GdkWindow *window,
                            GdkPixmap *pixmap,
-                           gint       parent_relative)
+                           gboolean   parent_relative)
 {
-  GdkWindowPrivate *window_private;
-  GdkPixmapPrivate *pixmap_private;
+  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);
 
-  window_private = (GdkWindowPrivate*) window;
-  pixmap_private = (GdkPixmapPrivate*) pixmap;
-
-  if (pixmap)
-    xpixmap = pixmap_private->xwindow;
-  else
-    xpixmap = None;
+  if (private->bg_pixmap &&
+      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+      private->bg_pixmap != GDK_NO_BG)
+    gdk_pixmap_unref (private->bg_pixmap);
 
   if (parent_relative)
-    xpixmap = ParentRelative;
-
-  XSetWindowBackgroundPixmap (window_private->xdisplay, window_private->xwindow, xpixmap);
+    {
+      xpixmap = ParentRelative;
+      private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
+    }
+  else
+    {
+      if (pixmap)
+       {
+         gdk_pixmap_ref (pixmap);
+         private->bg_pixmap = pixmap;
+         xpixmap = GDK_PIXMAP_XID (pixmap);
+       }
+      else
+       {
+         xpixmap = None;
+         private->bg_pixmap = GDK_NO_BG;
+       }
+    }
+  
+  if (!GDK_WINDOW_DESTROYED (window))
+    XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
+                               GDK_WINDOW_XID (window), xpixmap);
 }
 
 void
 gdk_window_set_cursor (GdkWindow *window,
                       GdkCursor *cursor)
 {
-  GdkWindowPrivate *window_private;
   GdkCursorPrivate *cursor_private;
   Cursor xcursor;
-
+  
   g_return_if_fail (window != NULL);
-
-  window_private = (GdkWindowPrivate*) window;
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  
   cursor_private = (GdkCursorPrivate*) cursor;
-
+  
   if (!cursor)
     xcursor = None;
   else
     xcursor = cursor_private->xcursor;
-
-  XDefineCursor (window_private->xdisplay, window_private->xwindow, xcursor);
-}
-
-void
-gdk_window_set_colormap (GdkWindow   *window,
-                        GdkColormap *colormap)
-{
-  GdkWindowPrivate *window_private;
-  GdkColormapPrivate *colormap_private;
-
-  g_return_if_fail (window != NULL);
-  g_return_if_fail (colormap != NULL);
-
-  window_private = (GdkWindowPrivate*) window;
-  colormap_private = (GdkColormapPrivate*) colormap;
-
-  XSetWindowColormap (window_private->xdisplay,
-                     window_private->xwindow,
-                     colormap_private->xcolormap);
-
-  if (window_private->window_type != GDK_WINDOW_TOPLEVEL)
-    gdk_window_add_colormap_windows (window);
-}
-
-void
-gdk_window_get_user_data (GdkWindow *window,
-                         gpointer  *data)
-{
-  g_return_if_fail (window != NULL);
-
-  *data = window->user_data;
+  
+  if (!GDK_WINDOW_DESTROYED (window))
+    XDefineCursor (GDK_WINDOW_XDISPLAY (window),
+                  GDK_WINDOW_XID (window),
+                  xcursor);
 }
 
 void
@@ -831,7 +1300,6 @@ gdk_window_get_geometry (GdkWindow *window,
                         gint      *height,
                         gint      *depth)
 {
-  GdkWindowPrivate *window_private;
   Window root;
   gint tx;
   gint ty;
@@ -839,112 +1307,29 @@ gdk_window_get_geometry (GdkWindow *window,
   guint theight;
   guint tborder_width;
   guint tdepth;
-
+  
+  g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
+  
   if (!window)
-    window = (GdkWindow*) &gdk_root_parent;
-
-  window_private = (GdkWindowPrivate*) window;
-
-  XGetGeometry (window_private->xdisplay, window_private->xwindow,
-               &root, &tx, &ty, &twidth, &theight, &tborder_width, &tdepth);
-
-  if (x)
-    *x = tx;
-  if (y)
-    *y = ty;
-  if (width)
-    *width = twidth;
-  if (height)
-    *height = theight;
-  if (depth)
-    *depth = tdepth;
-}
-
-void
-gdk_window_get_position (GdkWindow *window,
-                        gint      *x,
-                        gint      *y)
-{
-  GdkWindowPrivate *window_private;
-
-  g_return_if_fail (window != NULL);
-
-  window_private = (GdkWindowPrivate*) window;
-
-  if (x)
-    *x = window_private->x;
-  if (y)
-    *y = window_private->y;
-}
-
-void
-gdk_window_get_size (GdkWindow *window,
-                    gint       *width,
-                    gint       *height)
-{
-  GdkWindowPrivate *window_private;
-
-  g_return_if_fail (window != NULL);
-
-  window_private = (GdkWindowPrivate*) window;
-
-  if (width)
-    *width = window_private->width;
-  if (height)
-    *height = window_private->height;
-}
-
-
-GdkVisual*
-gdk_window_get_visual (GdkWindow *window)
-{
-  GdkWindowPrivate *window_private;
-  XWindowAttributes window_attributes;
-
-  g_return_val_if_fail (window != NULL, NULL);
-
-  window_private = (GdkWindowPrivate*) window;
-  while (window_private && (window_private->window_type == GDK_WINDOW_PIXMAP))
-    window_private = (GdkWindowPrivate*) window_private->parent;
-
-  if (window_private)
+    window = gdk_parent_root;
+  
+  if (!GDK_WINDOW_DESTROYED (window))
     {
-      XGetWindowAttributes (window_private->xdisplay,
-                           window_private->xwindow,
-                           &window_attributes);
-
-      return gdk_visual_lookup (window_attributes.visual);
+      XGetGeometry (GDK_WINDOW_XDISPLAY (window),
+                   GDK_WINDOW_XID (window),
+                   &root, &tx, &ty, &twidth, &theight, &tborder_width, &tdepth);
+      
+      if (x)
+       *x = tx;
+      if (y)
+       *y = ty;
+      if (width)
+       *width = twidth;
+      if (height)
+       *height = theight;
+      if (depth)
+       *depth = tdepth;
     }
-
-  return NULL;
-}
-
-GdkColormap*
-gdk_window_get_colormap (GdkWindow *window)
-{
-  GdkWindowPrivate *window_private;
-  XWindowAttributes window_attributes;
-
-  g_return_val_if_fail (window != NULL, NULL);
-
-  window_private = (GdkWindowPrivate*) window;
-
-  XGetWindowAttributes (window_private->xdisplay,
-                       window_private->xwindow,
-                       &window_attributes);
-
-  return gdk_colormap_lookup (window_attributes.colormap);
-}
-
-GdkWindowType
-gdk_window_get_type (GdkWindow *window)
-{
-  GdkWindowPrivate *window_private;
-
-  g_return_val_if_fail (window != NULL, (GdkWindowType) -1);
-
-  window_private = (GdkWindowPrivate*) window;
-  return window_private->window_type;
 }
 
 gint
@@ -952,210 +1337,355 @@ gdk_window_get_origin (GdkWindow *window,
                       gint      *x,
                       gint      *y)
 {
-  GdkWindowPrivate *private;
   gint return_val;
   Window child;
-  gint tx, ty;
-
+  gint tx = 0;
+  gint ty = 0;
+  
   g_return_val_if_fail (window != NULL, 0);
-
-  private = (GdkWindowPrivate*) window;
-
-  return_val = XTranslateCoordinates (private->xdisplay,
-                                     private->xwindow,
-                                     gdk_root_window,
-                                     0, 0, &tx, &ty,
-                                     &child);
-
+  
+  if (!GDK_WINDOW_DESTROYED (window))
+    {
+      return_val = XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window),
+                                         GDK_WINDOW_XID (window),
+                                         gdk_root_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)
+{
+  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);
+  g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
+  
+  if (!GDK_WINDOW_DESTROYED (window))
+    {
+      if (!atom)
+       atom = gdk_atom_intern ("ENLIGHTENMENT_DESKTOP", FALSE);
+      win = GDK_WINDOW_XID (window);
+      
+      while (XQueryTree (GDK_WINDOW_XDISPLAY (window), 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 (GDK_WINDOW_XDISPLAY (window), 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 (GDK_WINDOW_XDISPLAY (window),
+                                         GDK_WINDOW_XID (window),
+                                         win,
+                                         0, 0, &tx, &ty,
+                                         &root);
+      if (x)
+       *x = tx;
+      if (y)
+       *y = ty;
+    }
+  
+  
   return return_val;
 }
 
+void
+gdk_window_get_root_origin (GdkWindow *window,
+                           gint      *x,
+                           gint      *y)
+{
+  GdkWindowObject *private;
+  Window xwindow;
+  Window xparent;
+  Window root;
+  Window *children;
+  unsigned int nchildren;
+  
+  g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  
+  private = (GdkWindowObject*) window;
+  if (x)
+    *x = 0;
+  if (y)
+    *y = 0;
+
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+  
+  while (private->parent && ((GdkWindowObject*) private->parent)->parent)
+    private = (GdkWindowObject*) private->parent;
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+  
+  xparent = GDK_WINDOW_XID (window);
+  do
+    {
+      xwindow = xparent;
+      if (!XQueryTree (GDK_WINDOW_XDISPLAY (window), 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 (GDK_WINDOW_XDISPLAY (window), 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,
                        gint            *y,
                        GdkModifierType *mask)
 {
-  GdkWindowPrivate *private;
   GdkWindow *return_val;
   Window root;
   Window child;
   int rootx, rooty;
-  int winx, winy;
-  unsigned int xmask;
+  int winx = 0;
+  int winy = 0;
+  unsigned int xmask = 0;
+  gint xoffset, yoffset;
 
+  g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
+  
   if (!window)
-    window = (GdkWindow*) &gdk_root_parent;
-
-  private = (GdkWindowPrivate*) window;
+    window = gdk_parent_root;
+  
+  _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
 
   return_val = NULL;
-  if (XQueryPointer (private->xdisplay, private->xwindow, &root, &child,
-                    &rootx, &rooty, &winx, &winy, &xmask))
+  if (!GDK_WINDOW_DESTROYED (window) &&
+      XQueryPointer (GDK_WINDOW_XDISPLAY (window),
+                    GDK_WINDOW_XID (window),
+                    &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 + xoffset;
+  if (y)
+    *y = winy + yoffset;
+  if (mask)
+    *mask = xmask;
+  
   return return_val;
 }
 
 GdkWindow*
-gdk_window_get_parent (GdkWindow *window)
+gdk_window_at_pointer (gint *win_x,
+                      gint *win_y)
 {
-  g_return_val_if_fail (window != NULL, NULL);
-
-  return ((GdkWindowPrivate*) window)->parent;
-}
-
-GdkWindow*
-gdk_window_get_toplevel (GdkWindow *window)
-{
-  GdkWindowPrivate *private;
-
-  g_return_val_if_fail (window != NULL, NULL);
-
-  private = (GdkWindowPrivate*) window;
-
-  while (private->window_type == GDK_WINDOW_CHILD)
-    {
-      window = ((GdkWindowPrivate*) window)->parent;
-      private = (GdkWindowPrivate*) window;
-    }
-
-  return window;
-}
-
-GList*
-gdk_window_get_children (GdkWindow *window)
-{
-  GdkWindowPrivate *private;
-  GdkWindow *child;
-  GList *children;
+  GdkWindow *window;
   Window root;
-  Window parent;
-  Window *xchildren;
-  unsigned int nchildren;
-  unsigned int i;
-
-  g_return_val_if_fail (window != NULL, NULL);
-
-  private = (GdkWindowPrivate*) window;
-
-  XQueryTree (private->xdisplay, private->xwindow,
-             &root, &parent, &xchildren, &nchildren);
-
-  children = NULL;
-
-  if (nchildren > 0)
+  Window xwindow;
+  Window xwindow_last = 0;
+  Display *xdisplay;
+  int rootx = -1, rooty = -1;
+  int winx, winy;
+  unsigned int xmask;
+  
+  xwindow = GDK_ROOT_WINDOW ();
+  xdisplay = GDK_DISPLAY ();
+  
+  XGrabServer (xdisplay);
+  while (xwindow)
     {
-      for (i = 0; i < nchildren; i++)
-       {
-         child = gdk_window_lookup (xchildren[i]);
-          if (child)
-            children = g_list_prepend (children, child);
-       }
-
-      XFree (xchildren);
+      xwindow_last = xwindow;
+      XQueryPointer (xdisplay, xwindow,
+                    &root, &xwindow,
+                    &rootx, &rooty,
+                    &winx, &winy,
+                    &xmask);
     }
-
-  return children;
+  XUngrabServer (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;
 }
 
 GdkEventMask  
-gdk_window_get_events      (GdkWindow       *window)
+gdk_window_get_events (GdkWindow *window)
 {
   XWindowAttributes attrs;
   GdkEventMask event_mask;
   int i;
+  
+  g_return_val_if_fail (window != NULL, 0);
+  g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
 
-  XGetWindowAttributes (gdk_display, ((GdkWindowPrivate *)window)->xwindow, 
-                       &attrs);
-
-  event_mask = 0;
-  for (i = 0; i < nevent_masks; i++)
+  if (GDK_WINDOW_DESTROYED (window))
+    return 0;
+  else
     {
-      if (attrs.your_event_mask & event_mask_table[i])
-       event_mask |= 1 << (i + 1);
+      XGetWindowAttributes (GDK_WINDOW_XDISPLAY (window),
+                           GDK_WINDOW_XID (window), 
+                           &attrs);
+      
+      event_mask = 0;
+      for (i = 0; i < gdk_nevent_masks; i++)
+       {
+         if (attrs.your_event_mask & gdk_event_mask_table[i])
+           event_mask |= 1 << (i + 1);
+       }
+  
+      return event_mask;
     }
-
-  return event_mask;
 }
 
 void          
-gdk_window_set_events      (GdkWindow       *window,
-                           GdkEventMask     event_mask)
+gdk_window_set_events (GdkWindow       *window,
+                      GdkEventMask     event_mask)
 {
   long xevent_mask;
   int i;
-
-  xevent_mask = StructureNotifyMask;
-  for (i = 0; i < nevent_masks; i++)
+  
+  g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  
+  if (!GDK_WINDOW_DESTROYED (window))
     {
-      if (event_mask & (1 << (i + 1)))
-       xevent_mask |= event_mask_table[i];
+      xevent_mask = StructureNotifyMask;
+      for (i = 0; i < gdk_nevent_masks; i++)
+       {
+         if (event_mask & (1 << (i + 1)))
+           xevent_mask |= gdk_event_mask_table[i];
+       }
+      
+      XSelectInput (GDK_WINDOW_XDISPLAY (window),
+                   GDK_WINDOW_XID (window),
+                   xevent_mask);
     }
-  
-  XSelectInput (gdk_display, ((GdkWindowPrivate *)window)->xwindow, 
-               xevent_mask);
 }
 
 void
 gdk_window_add_colormap_windows (GdkWindow *window)
 {
   GdkWindow *toplevel;
-  GdkWindowPrivate *toplevel_private;
-  GdkWindowPrivate *window_private;
   Window *old_windows;
   Window *new_windows;
   int i, count;
-
+  
   g_return_if_fail (window != NULL);
-
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  
   toplevel = gdk_window_get_toplevel (window);
-  toplevel_private = (GdkWindowPrivate*) toplevel;
-  window_private = (GdkWindowPrivate*) window;
-
-  if (!XGetWMColormapWindows (toplevel_private->xdisplay,
-                             toplevel_private->xwindow,
+  if (GDK_WINDOW_DESTROYED (toplevel))
+    return;
+  
+  old_windows = NULL;
+  if (!XGetWMColormapWindows (GDK_WINDOW_XDISPLAY (toplevel),
+                             GDK_WINDOW_XID (toplevel),
                              &old_windows, &count))
     {
-      old_windows = NULL;
       count = 0;
     }
-
+  
   for (i = 0; i < count; i++)
-    if (old_windows[i] == window_private->xwindow)
-      return;
-
+    if (old_windows[i] == GDK_WINDOW_XID (window))
+      {
+       XFree (old_windows);
+       return;
+      }
+  
   new_windows = g_new (Window, count + 1);
-
+  
   for (i = 0; i < count; i++)
     new_windows[i] = old_windows[i];
-  new_windows[count] = window_private->xwindow;
-
-  XSetWMColormapWindows (toplevel_private->xdisplay,
-                        toplevel_private->xwindow,
+  new_windows[count] = GDK_WINDOW_XID (window);
+  
+  XSetWMColormapWindows (GDK_WINDOW_XDISPLAY (toplevel),
+                        GDK_WINDOW_XID (toplevel),
                         new_windows, count + 1);
-
+  
   g_free (new_windows);
   if (old_windows)
     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
@@ -1163,195 +1693,844 @@ gdk_window_shape_combine_mask (GdkWindow *window,
                               GdkBitmap *mask,
                               gint x, gint y)
 {
-  GdkWindowPrivate *window_private;
-  GdkWindowPrivate *pixmap_private;
+  Pixmap pixmap;
+  
+  g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  
+#ifdef HAVE_SHAPE_EXT
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+  
+  if (gdk_window_have_shape_ext ())
+    {
+      if (mask)
+       {
+         pixmap = GDK_PIXMAP_XID (mask);
+       }
+      else
+       {
+         x = 0;
+         y = 0;
+         pixmap = None;
+       }
+      
+      XShapeCombineMask (GDK_WINDOW_XDISPLAY (window),
+                        GDK_WINDOW_XID (window),
+                        ShapeBounding,
+                        x, y,
+                        pixmap,
+                        ShapeSet);
+    }
+#endif /* HAVE_SHAPE_EXT */
+}
 
+void
+gdk_window_set_override_redirect (GdkWindow *window,
+                                 gboolean override_redirect)
+{
+  XSetWindowAttributes attr;
+  
   g_return_if_fail (window != NULL);
-  g_return_if_fail (mask != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
 
-  window_private = (GdkWindowPrivate*) window;
-  pixmap_private = (GdkWindowPrivate*) mask;
-       
-  XShapeCombineMask  (window_private->xdisplay,
-                     window_private->xwindow,
-                     ShapeBounding,
-                     x, y, /* offset */
-                     (Pixmap)pixmap_private->xwindow,
-                     ShapeSet);
+  if (GDK_WINDOW_DESTROYED (window))
+    {
+      attr.override_redirect = (override_redirect == FALSE)?False:True;
+      XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
+                              GDK_WINDOW_XID (window),
+                              CWOverrideRedirect,
+                              &attr);
+    }
 }
 
-void
-gdk_dnd_drag_addwindow (GdkWindow *window)
+void          
+gdk_window_set_icon (GdkWindow *window, 
+                    GdkWindow *icon_window,
+                    GdkPixmap *pixmap,
+                    GdkBitmap *mask)
 {
-  GdkWindowPrivate *window_private;
+  XWMHints *wm_hints;
   
   g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
+  wm_hints = XGetWMHints (GDK_WINDOW_XDISPLAY (window),
+                         GDK_WINDOW_XID (window));
+  if (!wm_hints)
+    wm_hints = XAllocWMHints ();
+
+  if (icon_window != NULL)
+    {
+      wm_hints->flags |= IconWindowHint;
+      wm_hints->icon_window = GDK_WINDOW_XID (icon_window);
+    }
   
-  window_private = (GdkWindowPrivate *) window;
+  if (pixmap != NULL)
+    {
+      wm_hints->flags |= IconPixmapHint;
+      wm_hints->icon_pixmap = GDK_PIXMAP_XID (pixmap);
+    }
   
-  if (window_private->dnd_drag_enabled == 1 && gdk_dnd.drag_really == 0)
+  if (mask != NULL)
     {
-      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;
-    } 
+      wm_hints->flags |= IconMaskHint;
+      wm_hints->icon_mask = GDK_PIXMAP_XID (mask);
+    }
+
+  XSetWMHints (GDK_WINDOW_XDISPLAY (window),
+              GDK_WINDOW_XID (window), wm_hints);
+  XFree (wm_hints);
+}
+
+static gboolean
+gdk_window_icon_name_set (GdkWindow *window)
+{
+  return GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (window),
+                                              g_quark_from_static_string ("gdk-icon-name-set")));
+}
+
+void          
+gdk_window_set_icon_name (GdkWindow   *window, 
+                         const gchar *name)
+{
+  g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
+  g_object_set_qdata (G_OBJECT (window), g_quark_from_static_string ("gdk-icon-name-set"),
+                     GUINT_TO_POINTER (TRUE));
+
+  set_text_property (window, gdk_atom_intern ("WM_ICON_NAME", FALSE), name);
+}  
+
+void
+gdk_window_iconify (GdkWindow *window)
+{
+  Display *display;
+  
+  g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
+  display = GDK_WINDOW_XDISPLAY (window);
+  XIconifyWindow (display, GDK_WINDOW_XWINDOW (window), DefaultScreen (display));
+}
+
+void          
+gdk_window_set_group (GdkWindow *window, 
+                     GdkWindow *leader)
+{
+  XWMHints *wm_hints;
+  
+  g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (leader != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (leader));
+
+  if (GDK_WINDOW_DESTROYED (window) || GDK_WINDOW_DESTROYED (leader))
+    return;
+  
+  wm_hints = XGetWMHints (GDK_WINDOW_XDISPLAY (window),
+                         GDK_WINDOW_XID (window));
+  if (!wm_hints)
+    wm_hints = XAllocWMHints ();
+
+  wm_hints->flags |= WindowGroupHint;
+  wm_hints->window_group = GDK_WINDOW_XID (leader);
+
+  XSetWMHints (GDK_WINDOW_XDISPLAY (window),
+              GDK_WINDOW_XID (window), wm_hints);
+  XFree (wm_hints);
+}
+
+static void
+gdk_window_set_mwm_hints (GdkWindow *window,
+                         MotifWmHints *new_hints)
+{
+  static Atom hints_atom = None;
+  MotifWmHints *hints;
+  Atom type;
+  gint format;
+  gulong nitems;
+  gulong bytes_after;
+  
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+  
+  if (!hints_atom)
+    hints_atom = XInternAtom (GDK_WINDOW_XDISPLAY (window), 
+                             _XA_MOTIF_WM_HINTS, FALSE);
+  
+  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);
+  
+  if (type == None)
+    hints = new_hints;
   else
-    g_warning ("dnd_really is 1 or drag is not enabled! can't addwindow\n");
+    {
+      if (new_hints->flags & MWM_HINTS_FUNCTIONS)
+       {
+         hints->flags |= MWM_HINTS_FUNCTIONS;
+         hints->functions = new_hints->functions;
+       }
+      if (new_hints->flags & MWM_HINTS_DECORATIONS)
+       {
+         hints->flags |= MWM_HINTS_DECORATIONS;
+         hints->decorations = new_hints->decorations;
+       }
+    }
+  
+  XChangeProperty (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
+                  hints_atom, hints_atom, 32, PropModeReplace,
+                  (guchar *)hints, sizeof (MotifWmHints)/sizeof (long));
+  
+  if (hints != new_hints)
+    XFree (hints);
+}
+
+void
+gdk_window_set_decorations (GdkWindow      *window,
+                           GdkWMDecoration decorations)
+{
+  MotifWmHints hints;
+  
+  g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  
+  hints.flags = MWM_HINTS_DECORATIONS;
+  hints.decorations = decorations;
+  
+  gdk_window_set_mwm_hints (window, &hints);
 }
 
 void
-gdk_window_dnd_drag_set (GdkWindow   *window,
-                        guint8       drag_enable,
-                        gchar      **typelist,
-                        guint        numtypes)
+gdk_window_set_functions (GdkWindow    *window,
+                         GdkWMFunction functions)
 {
-  GdkWindowPrivate *window_private;
-  int i, wasset = 0;
+  MotifWmHints hints;
   
   g_return_if_fail (window != NULL);
-  window_private = (GdkWindowPrivate *) window;
+  g_return_if_fail (GDK_IS_WINDOW (window));
   
-  window_private->dnd_drag_enabled = drag_enable ? 1 : 0;
+  hints.flags = MWM_HINTS_FUNCTIONS;
+  hints.functions = functions;
   
-  if (drag_enable)
+  gdk_window_set_mwm_hints (window, &hints);
+}
+
+/* 
+ * 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,
+                gint               x,
+                gint               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)
     {
-      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++)
+      /* -- -> new span */
+      /* == -> existing span */
+      /* ## -> spans intersect */
+      /* if we are in the middle of spanning the span into the line */
+      if (spanning)
        {
-         /* 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);
+         /* 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
-           window_private->dnd_drag_data_typesavail[i] = None;
+           {
+             /* 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);
       
-      /* 
-       * 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);
+      /* 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);
     }
-  else
+  /* free up all the spans we made */
+  for (i = 0; i < baseh; i++)
     {
-      free (window_private->dnd_drag_data_typesavail);
-      window_private->dnd_drag_data_typesavail = NULL;
-      window_private->dnd_drag_data_numtypesavail = 0;
+      ptr1 = spans[i];
+      while (ptr1)
+       {
+         ptr2 = ptr1;
+         ptr1 = ptr1->next;
+         g_free (ptr2);
+       }
     }
+  g_free (spans);
 }
 
 void
-gdk_window_dnd_drop_set (GdkWindow   *window,
-                        guint8       drop_enable,
-                        gchar      **typelist,
-                        guint        numtypes,
-                        guint8       destructive_op)
+gdk_window_set_child_shapes (GdkWindow *window)
 {
-  GdkWindowPrivate *window_private;
-  int i;
+  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_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
+                         GDK_WINDOW_XID (window), FALSE);
+#endif   
+}
+
+void
+gdk_window_merge_child_shapes (GdkWindow *window)
+{
   g_return_if_fail (window != NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
   
-  window_private = (GdkWindowPrivate *) window;
+#ifdef HAVE_SHAPE_EXT
+  if (!GDK_WINDOW_DESTROYED (window) &&
+      gdk_window_have_shape_ext ())
+    gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
+                         GDK_WINDOW_XID (window), TRUE);
+#endif   
+}
+
+/* Support for windows that can be guffaw-scrolled
+ * (See http://www.gtk.org/~otaylor/whitepapers/guffaw-scrolling.txt)
+ */
+
+static gboolean
+gdk_window_gravity_works (void)
+{
+  enum { UNKNOWN, NO, YES };
+  static gint gravity_works = UNKNOWN;
   
-  window_private->dnd_drop_enabled = drop_enable ? 1 : 0;
-  if (drop_enable)
+  if (gravity_works == UNKNOWN)
     {
-      g_return_if_fail(typelist != NULL);
+      GdkWindowAttr attr;
+      GdkWindow *parent;
+      GdkWindow *child;
+      gint y;
+      
+      /* This particular server apparently has a bug so that the test
+       * works but the actual code crashes it
+       */
+      if ((!strcmp (XServerVendor (gdk_display), "Sun Microsystems, Inc.")) &&
+         (VendorRelease (gdk_display) == 3400))
+       {
+         gravity_works = NO;
+         return FALSE;
+       }
+      
+      attr.window_type = GDK_WINDOW_TEMP;
+      attr.wclass = GDK_INPUT_OUTPUT;
+      attr.x = 0;
+      attr.y = 0;
+      attr.width = 100;
+      attr.height = 100;
+      attr.event_mask = 0;
+      
+      parent = gdk_window_new (NULL, &attr, GDK_WA_X | GDK_WA_Y);
       
-      window_private->dnd_drop_data_numtypesavail = numtypes;
+      attr.window_type = GDK_WINDOW_CHILD;
+      child = gdk_window_new (parent, &attr, GDK_WA_X | GDK_WA_Y);
       
-      window_private->dnd_drop_data_typesavail =
-       g_realloc (window_private->dnd_drop_data_typesavail,
-                  (numtypes + 1) * sizeof (GdkAtom));
+      gdk_window_set_static_win_gravity (child, TRUE);
       
-      for (i = 0; i < numtypes; i++)
-       window_private->dnd_drop_data_typesavail[i] =
-         gdk_atom_intern (typelist[i], FALSE);
+      gdk_window_resize (parent, 100, 110);
+      gdk_window_move (parent, 0, -10);
+      gdk_window_move_resize (parent, 0, 0, 100, 100);
       
-      window_private->dnd_drop_destructive_op = destructive_op;
+      gdk_window_resize (parent, 100, 110);
+      gdk_window_move (parent, 0, -10);
+      gdk_window_move_resize (parent, 0, 0, 100, 100);
+      
+      gdk_window_get_geometry (child, NULL, &y, NULL, NULL, NULL);
+      
+      gdk_window_destroy (parent);
+      gdk_window_destroy (child);
+      
+      gravity_works = ((y == -20) ? YES : NO);
     }
+  
+  return (gravity_works == YES);
 }
 
-/* 
- * 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)
+static void
+gdk_window_set_static_bit_gravity (GdkWindow *window, gboolean on)
 {
-  GdkWindowPrivate *window_private;
-  XEvent sev;
-  GdkEventDropDataAvailable tmp_ev;
-  gchar *tmp;
+  XSetWindowAttributes xattributes;
+  guint xattributes_mask = 0;
   
   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);
-
-  g_free (event->dragrequest.data_type);
-  event->dragrequest.data_type = NULL;
-  
-  window_private = (GdkWindowPrivate *) window;
-  g_return_if_fail (window_private->dnd_drag_accepted != 0);    
-  
-  /* 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;
+  xattributes.bit_gravity = StaticGravity;
+  xattributes_mask |= CWBitGravity;
+  xattributes.bit_gravity = on ? StaticGravity : ForgetGravity;
+  XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
+                          GDK_WINDOW_XID (window),
+                          CWBitGravity,  &xattributes);
+}
+
+static void
+gdk_window_set_static_win_gravity (GdkWindow *window, gboolean on)
+{
+  XSetWindowAttributes xattributes;
+  
+  g_return_if_fail (window != NULL);
+  
+  xattributes.win_gravity = on ? StaticGravity : NorthWestGravity;
+  
+  XChangeWindowAttributes (GDK_WINDOW_XDISPLAY (window),
+                          GDK_WINDOW_XID (window),
+                          CWWinGravity,  &xattributes);
+}
+
+/*************************************************************
+ * gdk_window_set_static_gravities:
+ *     Set the bit gravity of the given window to static,
+ *     and flag it so all children get static subwindow
+ *     gravity.
+ *   arguments:
+ *     window: window for which to set static gravity
+ *     use_static: Whether to turn static gravity on or off.
+ *   results:
+ *     Does the XServer support static gravity?
+ *************************************************************/
+
+gboolean 
+gdk_window_set_static_gravities (GdkWindow *window,
+                                gboolean   use_static)
+{
+  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)
+    return TRUE;
+  
+  if (use_static && !gdk_window_gravity_works ())
+    return FALSE;
+  
+  private->guffaw_gravity = use_static;
+  
+  if (!GDK_WINDOW_DESTROYED (window))
+    {
+      gdk_window_set_static_bit_gravity (window, use_static);
+      
+      tmp_list = private->children;
+      while (tmp_list)
+       {
+         gdk_window_set_static_win_gravity (window, use_static);
+         
+         tmp_list = tmp_list->next;
+       }
+    }
   
-  sev.xclient.data.l[4] = 0;
+  return TRUE;
+}
+
+/* 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)
+{
+  Display *xdisplay;
+  Window *list = NULL;
+  Window child = 0, parent_win = 0, root_win = 0;
+  int i;
+  unsigned int ww, wh, wb, wd, num;
+  int wx, wy;
+  
+  xdisplay = GDK_DISPLAY ();
+  if (!XGetGeometry (xdisplay, base, &root_win, &wx, &wy, &ww, &wh, &wb, &wd))
+    return 0;
+  wx += bx;
+  wy += by;
+  
+  if (!((x >= wx) &&
+       (y >= wy) &&
+       (x < (int) (wx + ww)) &&
+       (y < (int) (wy + wh))))
+    return 0;
+  
+  if (!XQueryTree (xdisplay, base, &root_win, &parent_win, &list, &num))
+    return base;
+  
+  if (list)
+    {
+      for (i = num - 1; ; 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)
+               {
+                 XFree (list);
+                 return child;
+               }
+           }
+         if (!i)
+           break;
+       }
+      XFree (list);
+    }
+  return base;
+}
+
+/* 
+ * The following fucntion by The Rasterman <raster@redhat.com>
+ * This function returns the X Window ID in which the x y location is in 
+ * (x and y being relative to the root window), excluding any windows listed
+ * in the GList excludes (this is a list of X Window ID's - gpointer being
+ * the Window ID).
+ * 
+ * This is primarily designed for internal gdk use - for DND for example
+ * when using a shaped icon window as the drag object - you exclude the
+ * X Window ID of the "icon" (perhaps more if excludes may be needed) and
+ * You can get back an X Window ID as to what X Window ID is infact under
+ * those X,Y co-ordinates.
+ */
+Window
+gdk_window_xid_at_coords (gint     x,
+                         gint     y,
+                         GList   *excludes,
+                         gboolean excl_child)
+{
+  GdkWindow *window;
+  Display *xdisplay;
+  Window *list = NULL;
+  Window root, child = 0, parent_win = 0, root_win = 0;
+  unsigned int num;
+  int i;
+
+  window = gdk_parent_root;
+  xdisplay = GDK_WINDOW_XDISPLAY (window);
+  root = GDK_WINDOW_XID (window);
+  num = g_list_length (excludes);
   
-  XSendEvent (gdk_display, event->dragrequest.requestor, False,
-             NoEventMask, &sev);
+  XGrabServer (xdisplay);
+  if (!XQueryTree (xdisplay, root, &root_win, &parent_win, &list, &num))
+    {
+      XUngrabServer (xdisplay);
+      return root;
+    }
+  if (list)
+    {
+      i = num - 1;
+      do
+       {
+         XWindowAttributes xwa;
+         
+         XGetWindowAttributes (xdisplay, list [i], &xwa);
+         
+         if (xwa.map_state != IsViewable)
+           continue;
+         
+         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)
+           continue;
+         
+         if (excludes)
+           {
+             if (!g_list_find (excludes, (gpointer *) child))
+               {
+                 XFree (list);
+                 XUngrabServer (xdisplay);
+                 return child;
+               }
+           }
+         else
+           {
+             XFree (list);
+             XUngrabServer (xdisplay);
+             return child;
+           }
+       } while (--i > 0);
+      XFree (list);
+    }
+  XUngrabServer (xdisplay);
+  return root;
 }
+