[gtk+/client-side-windows: 2/284] Initial client-side-windows work



commit eabac453e652d5aa2e535d957057f9c84803eea9
Author: Alexander Larsson <alexl redhat com>
Date:   Fri Jul 18 15:03:42 2008 +0200

    Initial client-side-windows work
    
    The history before this was kind of twisted as several different
    approaches were tested, so that was all squashed into this initial
    commit to hide the uninteresting changes and files that were later
    removed.
---
 gdk/Makefile.am               |    1 +
 gdk/gdk.symbols               |   22 +-
 gdk/gdkcairo.c                |    4 +
 gdk/gdkdisplay.c              |  290 ++++-
 gdk/gdkdisplay.h              |   29 +
 gdk/gdkdraw.c                 |   28 +-
 gdk/gdkdrawable.h             |    6 +-
 gdk/gdkevents.c               |   64 +-
 gdk/gdkevents.h               |    3 +-
 gdk/gdkgc.c                   |   69 +-
 gdk/gdkinternals.h            |  165 ++-
 gdk/gdkoffscreenwindow.c      | 1217 ++++++++++++++
 gdk/gdkpango.c                |    3 +-
 gdk/gdkpixmap.c               |   42 +
 gdk/gdkwindow.c               | 3595 ++++++++++++++++++++++++++++++++++++-----
 gdk/gdkwindow.h               |   61 +-
 gdk/gdkwindowimpl.h           |   41 +-
 gdk/quartz/gdkpixmap-quartz.c |   30 +-
 gdk/x11/gdkdisplay-x11.c      |   42 +-
 gdk/x11/gdkdisplay-x11.h      |   15 +-
 gdk/x11/gdkdnd-x11.c          |    4 +-
 gdk/x11/gdkdrawable-x11.c     |   81 +-
 gdk/x11/gdkevents-x11.c       |   74 +-
 gdk/x11/gdkgc-x11.c           |   10 +-
 gdk/x11/gdkgeometry-x11.c     |  786 +---------
 gdk/x11/gdkinput.c            |    4 +-
 gdk/x11/gdkmain-x11.c         |  172 +--
 gdk/x11/gdkpixmap-x11.c       |   30 +-
 gdk/x11/gdkprivate-x11.h      |   12 +-
 gdk/x11/gdkproperty-x11.c     |   13 +-
 gdk/x11/gdkselection-x11.c    |    7 +-
 gdk/x11/gdkwindow-x11.c       |  657 +++-----
 gdk/x11/gdkwindow-x11.h       |   22 +-
 33 files changed, 5620 insertions(+), 1979 deletions(-)

diff --git a/gdk/Makefile.am b/gdk/Makefile.am
index cc0ae0d..580db1b 100644
--- a/gdk/Makefile.am
+++ b/gdk/Makefile.am
@@ -120,6 +120,7 @@ gdk_c_sources =                 \
 	gdkintl.h		\
 	gdkkeys.c		\
 	gdkkeyuni.c		\
+	gdkoffscreenwindow.c	\
 	gdkpango.c		\
 	gdkpixbuf-drawable.c	\
 	gdkpixbuf-render.c	\
diff --git a/gdk/gdk.symbols b/gdk/gdk.symbols
index cfb54c2..30c5376 100644
--- a/gdk/gdk.symbols
+++ b/gdk/gdk.symbols
@@ -71,7 +71,6 @@ gdk_set_use_xshm
 gdk_keyboard_grab
 gdk_keyboard_grab_info_libgtk_only
 gdk_pointer_grab
-gdk_pointer_grab_info_libgtk_only
 #endif
 #endif
 
@@ -85,6 +84,8 @@ gdk_pointer_is_grabbed
 gdk_pointer_ungrab
 gdk_event_send_client_message
 gdk_event_send_clientmessage_toall
+gdk_pointer_grab_info_libgtk_only
+gdk_display_pointer_is_grabbed
 #endif
 #endif
 
@@ -254,12 +255,6 @@ gdk_visual_type_get_type G_GNUC_CONST
 #endif
 #endif
 
-#if IN_HEADER(__GDK_PIXMAP_H__)
-#if IN_FILE(__GDK_PIXMAP_X11_C__)
-gdk_bitmap_create_from_data
-#endif
-#endif
-
 #if IN_HEADER(__GDK_FONT_H__)
 #if IN_FILE(__GDK_FONT_C__)
 #ifndef GDK_DISABLE_DEPRECATED
@@ -466,7 +461,6 @@ gdk_display_get_default_screen
 gdk_display_get_name
 gdk_display_get_n_screens
 gdk_display_get_screen
-gdk_display_pointer_is_grabbed
 gdk_display_pointer_ungrab
 gdk_display_keyboard_ungrab
 gdk_display_open
@@ -720,6 +714,13 @@ gdk_window_set_composited
 #endif
 
 #if IN_HEADER(__GDK_WINDOW_H__)
+#if IN_FILE(__GDK_OFFSCREEN_WINDOW_C__)
+gdk_window_set_offscreen_hooks
+gdk_window_get_offscreen_pixmap
+#endif
+#endif
+
+#if IN_HEADER(__GDK_WINDOW_H__)
 #if IN_FILE(__GDK_DND_X11_C__)
 gdk_window_register_dnd
 #endif
@@ -925,23 +926,24 @@ gdk_pixbuf_render_to_drawable_alpha
 
 #if IN_HEADER(__GDK_PIXMAP_H__)
 #if IN_FILE(__GDK_PIXMAP_C__)
+gdk_bitmap_create_from_data
 gdk_pixmap_colormap_create_from_xpm
+gdk_pixmap_create_from_data
 gdk_pixmap_create_from_xpm
 gdk_pixmap_colormap_create_from_xpm_d
 gdk_pixmap_create_from_xpm_d
 gdk_pixmap_get_type G_GNUC_CONST
+gdk_pixmap_new
 #endif
 #endif
 
 #if IN_HEADER(__GDK_PIXMAP_H__)
 #if IN_FILE(__GDK_PIXMAP_X11_C__)
-gdk_pixmap_create_from_data
 gdk_pixmap_foreign_new
 gdk_pixmap_foreign_new_for_display
 gdk_pixmap_foreign_new_for_screen
 gdk_pixmap_lookup
 gdk_pixmap_lookup_for_display
-gdk_pixmap_new
 #endif
 #endif
 
diff --git a/gdk/gdkcairo.c b/gdk/gdkcairo.c
index 6e83f53..9d3ce2d 100644
--- a/gdk/gdkcairo.c
+++ b/gdk/gdkcairo.c
@@ -50,6 +50,10 @@ gdk_cairo_create (GdkDrawable *drawable)
 
   surface = _gdk_drawable_ref_cairo_surface (drawable);
   cr = cairo_create (surface);
+
+  if (GDK_DRAWABLE_GET_CLASS (drawable)->set_cairo_clip)
+    GDK_DRAWABLE_GET_CLASS (drawable)->set_cairo_clip (drawable, cr);
+    
   cairo_surface_destroy (surface);
 
   return cr;
diff --git a/gdk/gdkdisplay.c b/gdk/gdkdisplay.c
index 9417c4e..1e0c45a 100644
--- a/gdk/gdkdisplay.c
+++ b/gdk/gdkdisplay.c
@@ -22,9 +22,11 @@
  */
 
 #include "config.h"
+#include <math.h>
 #include <glib.h>
 #include "gdk.h"		/* gdk_event_send_client_message() */
 #include "gdkdisplay.h"
+#include "gdkwindowimpl.h"
 #include "gdkinternals.h"
 #include "gdkmarshalers.h"
 #include "gdkscreen.h"
@@ -60,6 +62,14 @@ static GdkWindow* singlehead_default_window_get_pointer (GdkWindow       *window
 static GdkWindow* singlehead_default_window_at_pointer  (GdkScreen       *screen,
 							 gint            *win_x,
 							 gint            *win_y);
+static GdkWindow *gdk_window_real_window_get_pointer     (GdkDisplay       *display,
+                                                          GdkWindow        *window,
+                                                          gint             *x,
+                                                          gint             *y,
+                                                          GdkModifierType  *mask);
+static GdkWindow *gdk_display_real_get_window_at_pointer (GdkDisplay       *display,
+                                                          gint             *win_x,
+                                                          gint             *win_y);
 
 static guint signals[LAST_SIGNAL] = { 0 };
 
@@ -67,8 +77,8 @@ static char *gdk_sm_client_id;
 
 static const GdkDisplayPointerHooks default_pointer_hooks = {
   _gdk_windowing_get_pointer,
-  _gdk_windowing_window_get_pointer,
-  _gdk_windowing_window_at_pointer
+  gdk_window_real_window_get_pointer,
+  gdk_display_real_get_window_at_pointer
 };
 
 static const GdkDisplayPointerHooks singlehead_pointer_hooks = {
@@ -473,6 +483,79 @@ gdk_display_get_pointer (GdkDisplay      *display,
     *mask = tmp_mask;
 }
 
+static GdkWindow *
+gdk_display_real_get_window_at_pointer (GdkDisplay *display,
+                                        gint       *win_x,
+                                        gint       *win_y)
+{
+  GdkWindow *window;
+  gint x, y;
+
+  window = _gdk_windowing_window_at_pointer (display, &x, &y);
+
+  /* This might need corrections, as the native window returned
+     may contain client side children */
+  if (window)
+    {
+      double xx, yy;
+      
+      window = _gdk_window_find_descendant_at (window,
+					       x, y, 
+					       &xx, &yy);
+      x = floor (xx + 0.5);
+      y = floor (yy + 0.5);
+    }
+  
+  *win_x = x;
+  *win_y = y;
+  
+  return window;
+}
+
+static GdkWindow *
+gdk_window_real_window_get_pointer (GdkDisplay       *display,
+                                    GdkWindow        *window,
+                                    gint             *x,
+                                    gint             *y,
+                                    GdkModifierType  *mask)
+{
+  GdkWindowObject *private;
+  GdkWindow *pointer_window;
+  gint tmpx, tmpy;
+
+  private = (GdkWindowObject *) window;
+
+  pointer_window = _gdk_windowing_window_get_pointer (display,
+                                                      window,
+                                                      &tmpx, &tmpy,
+                                                      mask);
+  /* We got the coords on the impl, conver to the window */
+  tmpx += private->abs_x;
+  tmpy += private->abs_y;
+  
+  if (x)
+    *x = tmpx;
+  if (y)
+    *y = tmpy;
+
+  /* We need to recalculate the true child window with the pointer in it
+     due to possible client side child windows */
+  if (pointer_window != NULL)
+    {
+      /* First get the pointer coords relative to pointer_window */
+      _gdk_windowing_window_get_pointer (display,
+					 pointer_window,
+					 &tmpx, &tmpy,
+					 NULL);
+      /* Then convert that to a client side window */
+      pointer_window = _gdk_window_find_descendant_at (pointer_window,
+						       tmpx, tmpy, 
+						       NULL, NULL);
+    }
+
+  return pointer_window;
+}
+
 /**
  * gdk_display_get_window_at_pointer:
  * @display: a #GdkDisplay
@@ -586,8 +669,8 @@ singlehead_default_window_get_pointer (GdkWindow       *window,
 				       gint            *y,
 				       GdkModifierType *mask)
 {
-  return _gdk_windowing_window_get_pointer (gdk_drawable_get_display (window),
-					    window, x, y, mask);
+  return gdk_window_real_window_get_pointer (gdk_drawable_get_display (window),
+                                             window, x, y, mask);
 }
 
 static GdkWindow*
@@ -595,8 +678,8 @@ singlehead_default_window_at_pointer  (GdkScreen       *screen,
 				       gint            *win_x,
 				       gint            *win_y)
 {
-  return _gdk_windowing_window_at_pointer (gdk_screen_get_display (screen),
-					   win_x, win_y);
+  return gdk_display_real_get_window_at_pointer (gdk_screen_get_display (screen),
+                                                 win_x, win_y);
 }
 
 /**
@@ -632,5 +715,200 @@ gdk_set_pointer_hooks (const GdkPointerHooks *new_hooks)
   return (GdkPointerHooks *)result;
 }
 
+static void
+generate_grab_broken_event (GdkWindow *window,
+			    gboolean   keyboard,
+			    gboolean   implicit,
+			    GdkWindow *grab_window)
+{
+  g_return_if_fail (window != NULL);
+
+  if (!GDK_WINDOW_DESTROYED (window))
+    {
+      GdkEvent event;
+      event.type = GDK_GRAB_BROKEN;
+      event.grab_broken.window = window;
+      event.grab_broken.send_event = 0;
+      event.grab_broken.keyboard = keyboard;
+      event.grab_broken.implicit = implicit;
+      event.grab_broken.grab_window = grab_window;
+      gdk_event_put (&event);
+    }
+}
+
+void
+_gdk_display_set_has_pointer_grab (GdkDisplay *display,
+				   GdkWindow *window,
+				   GdkWindow *native_window,
+				   gboolean owner_events,
+				   GdkEventMask event_mask,
+				   unsigned long serial,
+				   guint32 time,
+				   gboolean implicit)
+{
+  int wx, wy;
+  
+  /* Normal GRAB events are sent by listening for enter and leave
+   * events on the native event window, which is then proxied
+   * into the virtual windows when the events are seen.
+   * However, there are two cases where X will not send these events:
+   * * When there is already a grab on the native parent of the
+   *   virtual grab window
+   * * When there is no grab, but the pointer is already in the
+   *   native parent of the virtual grab window
+   * In the first case we send the right GRAB events from the grab, but
+   * in the second case we need to generate our own UNGRAB crossing events.
+   */
+  if (display->pointer_grab.window != NULL &&
+      display->pointer_grab.window != window)
+    {
+      generate_grab_broken_event (GDK_WINDOW (display->pointer_grab.window),
+				  FALSE, display->pointer_grab.implicit,
+				  window);
+
+      /* Re-grabbing. Pretend we have no grab for now so that
+	 the GRAB events get delivered */
+      display->pointer_grab.window = NULL;
+      _gdk_syntesize_crossing_events (display, 
+				      display->pointer_grab.window,
+				      window,
+				      GDK_CROSSING_GRAB,
+				      /* These may be stale... */
+				      display->pointer_info.toplevel_x,
+				      display->pointer_info.toplevel_y,
+				      display->pointer_info.state,
+				      time, TRUE, TRUE);
+    }
+  else if (_gdk_windowing_window_at_pointer (display, &wx, &wy) == native_window)
+    {
+      _gdk_syntesize_crossing_events (display, 
+				      display->pointer_info.window_under_pointer,
+				      window,
+				      GDK_CROSSING_GRAB,
+				      /* These may be stale... */
+				      display->pointer_info.toplevel_x,
+				      display->pointer_info.toplevel_y,
+				      display->pointer_info.state,
+				      time, TRUE, TRUE);
+      
+    }
+
+  display->pointer_grab.window = window;
+  display->pointer_grab.native_window = native_window;
+  display->pointer_grab.serial = serial;
+  display->pointer_grab.owner_events = owner_events;
+  display->pointer_grab.event_mask = event_mask;
+  display->pointer_grab.time = time;
+  display->pointer_grab.implicit = implicit;
+  display->pointer_grab.converted_implicit = FALSE;
+}
+
+void
+_gdk_display_unset_has_pointer_grab (GdkDisplay *display,
+				     gboolean implicit,
+				     gboolean do_grab_one_pointer_release_event,
+				     guint32 time)
+{
+  int wx, wy;
+  GdkWindow *old_grab_window;
+  GdkWindow *old_native_grab_window;
+
+
+  old_grab_window = display->pointer_grab.window;
+  old_native_grab_window = display->pointer_grab.native_window;
+
+  if (do_grab_one_pointer_release_event)
+    display->pointer_grab.grab_one_pointer_release_event = display->pointer_grab.window;
+
+  /* We need to set this to null befor syntesizing events to make sure they get
+     delivered to anything but the grab window */
+  display->pointer_grab.window = NULL;
+  
+  /* Normal UNGRAB events are sent by listening for enter and leave
+   * events on the native event window, which is then proxied
+   * into the virtual windows when the events are seen.
+   * However, there are two cases where X will not send these events:
+   * * When this ungrab is due to a new grab on the native window that
+   *   is a parent of the currently grabbed virtual window
+   * * When there is no new grab, and the pointer is already in the
+   *   grabbed virtual windows parent native window
+   * In the first case we send the right GRAB events from the grab, but
+   * in the second case we need to generate our own UNGRAB crossing events.
+   */
+
+  if (_gdk_windowing_window_at_pointer (display, &wx, &wy) == old_native_grab_window)
+    {
+      _gdk_syntesize_crossing_events (display, 
+				      old_grab_window,
+				      display->pointer_info.window_under_pointer,
+				      GDK_CROSSING_UNGRAB,
+				      /* These may be stale... */
+				      display->pointer_info.toplevel_x,
+				      display->pointer_info.toplevel_y,
+				      display->pointer_info.state,
+				      time, TRUE, TRUE);
+    }
+  
+  if (implicit)
+    generate_grab_broken_event (old_grab_window,
+				FALSE, implicit, 
+				NULL);
+  
+}
+
+
+/**
+ * gdk_pointer_grab_info_libgtk_only:
+ * @display: the #GdkDisplay for which to get the grab information
+ * @grab_window: location to store current grab window
+ * @owner_events: location to store boolean indicating whether
+ *   the @owner_events flag to gdk_pointer_grab() was %TRUE.
+ * 
+ * Determines information about the current pointer grab.
+ * This is not public API and must not be used by applications.
+ * 
+ * Return value: %TRUE if this application currently has the
+ *  pointer grabbed.
+ **/
+gboolean
+gdk_pointer_grab_info_libgtk_only (GdkDisplay *display,
+				   GdkWindow **grab_window,
+				   gboolean   *owner_events)
+{
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
+
+  if (display->pointer_grab.window)
+    {
+      if (grab_window)
+        *grab_window = (GdkWindow *)display->pointer_grab.window;
+      if (owner_events)
+        *owner_events = display->pointer_grab.owner_events;
+
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+
+/**
+ * gdk_display_pointer_is_grabbed:
+ * @display: a #GdkDisplay
+ *
+ * Test if the pointer is grabbed.
+ *
+ * Returns: %TRUE if an active X pointer grab is in effect
+ *
+ * Since: 2.2
+ */
+gboolean
+gdk_display_pointer_is_grabbed (GdkDisplay *display)
+{
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
+  
+  return (display->pointer_grab.window != NULL &&
+	  !display->pointer_grab.implicit);
+}
+
 #define __GDK_DISPLAY_C__
 #include "gdkaliasdef.c"
diff --git a/gdk/gdkdisplay.h b/gdk/gdkdisplay.h
index 04bf183..790bc0b 100644
--- a/gdk/gdkdisplay.h
+++ b/gdk/gdkdisplay.h
@@ -43,6 +43,32 @@ typedef struct _GdkDisplayPointerHooks GdkDisplayPointerHooks;
 #define GDK_IS_DISPLAY_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_DISPLAY))
 #define GDK_DISPLAY_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_DISPLAY, GdkDisplayClass))
 
+/* Tracks information about the pointer grab on this display */
+typedef struct
+{
+  GdkWindow *window;
+  GdkWindow *native_window;
+  gulong serial;
+  gboolean owner_events;
+  guint event_mask;
+  gboolean implicit;
+  gboolean converted_implicit;
+  guint32 time;
+
+  GdkWindow *grab_one_pointer_release_event;
+} GdkPointerGrabInfo;
+
+/* Tracks information about which window the pointer is in and
+ * at what position the mouse is. This is useful when we need
+ * to synthesize events later.
+ */
+typedef struct
+{
+  GdkWindow *window_under_pointer;
+  gdouble toplevel_x, toplevel_y;
+  guint32 state;
+} GdkPointerWindowInfo;
+
 struct _GdkDisplay
 {
   GObject parent_instance;
@@ -68,6 +94,9 @@ struct _GdkDisplay
   guint double_click_distance;	/* Maximum distance between clicks in pixels */
   gint button_x[2];             /* The last 2 button click positions. */
   gint button_y[2];
+
+  GdkPointerGrabInfo pointer_grab;
+  GdkPointerWindowInfo pointer_info;
 };
 
 struct _GdkDisplayClass
diff --git a/gdk/gdkdraw.c b/gdk/gdkdraw.c
index 81e6e08..7b3fb5a 100644
--- a/gdk/gdkdraw.c
+++ b/gdk/gdkdraw.c
@@ -652,6 +652,8 @@ gdk_draw_drawable (GdkDrawable *drawable,
                                                           &composite_x_offset,
                                                           &composite_y_offset);
 
+  /* TODO: For non-native windows this may copy stuff from other overlapping
+     windows. We should clip that and clear that area in the destination instead. */
   
   GDK_DRAWABLE_GET_CLASS (drawable)->draw_drawable (drawable, gc, composite,
                                                     xsrc - composite_x_offset,
@@ -871,7 +873,7 @@ real_draw_glyphs (GdkDrawable       *drawable,
   cairo_t *cr;
 
   cr = gdk_cairo_create (drawable);
-  _gdk_gc_update_context (gc, cr, NULL, NULL, TRUE);
+  _gdk_gc_update_context (gc, cr, NULL, NULL, TRUE, drawable);
 
   if (matrix)
     {
@@ -995,7 +997,7 @@ gdk_draw_trapezoids (GdkDrawable        *drawable,
   g_return_if_fail (n_trapezoids == 0 || trapezoids != NULL);
 
   cr = gdk_cairo_create (drawable);
-  _gdk_gc_update_context (gc, cr, NULL, NULL, TRUE);
+  _gdk_gc_update_context (gc, cr, NULL, NULL, TRUE, drawable);
   
   for (i = 0; i < n_trapezoids; i++)
     {
@@ -1185,7 +1187,7 @@ gdk_drawable_real_get_image (GdkDrawable     *drawable,
   return gdk_drawable_copy_to_image (drawable, NULL, x, y, 0, 0, width, height);
 }
 
-static GdkDrawable*
+static GdkDrawable *
 gdk_drawable_real_get_composite_drawable (GdkDrawable *drawable,
                                           gint         x,
                                           gint         y,
@@ -1771,5 +1773,25 @@ _gdk_drawable_get_scratch_gc (GdkDrawable *drawable,
     }
 }
 
+/**
+ * _gdk_drawable_get_source_drawable:
+ * @drawable: a #GdkDrawable
+ *
+ * Returns a drawable for the passed @drawable that is guaranteed to be
+ * usable to create a pixmap (e.g.: not an offscreen window).
+ *
+ * Since: 2.16
+ */
+GdkDrawable *
+_gdk_drawable_get_source_drawable (GdkDrawable *drawable)
+{
+  g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
+
+  if (GDK_DRAWABLE_GET_CLASS (drawable)->get_source_drawable)
+    return GDK_DRAWABLE_GET_CLASS (drawable)->get_source_drawable (drawable);
+
+  return drawable;
+}
+
 #define __GDK_DRAW_C__
 #include "gdkaliasdef.c"
diff --git a/gdk/gdkdrawable.h b/gdk/gdkdrawable.h
index 508bf86..10910c0 100644
--- a/gdk/gdkdrawable.h
+++ b/gdk/gdkdrawable.h
@@ -200,9 +200,11 @@ struct _GdkDrawableClass
 
   cairo_surface_t *(*ref_cairo_surface) (GdkDrawable *drawable);
 
+  GdkDrawable *(*get_source_drawable) (GdkDrawable *drawable);
+
+  void         (*set_cairo_clip)      (GdkDrawable *drawable,
+				       cairo_t *cr);
   /* Padding for future expansion */
-  void         (*_gdk_reserved4)  (void);
-  void         (*_gdk_reserved5)  (void);
   void         (*_gdk_reserved6)  (void);
   void         (*_gdk_reserved7)  (void);
   void         (*_gdk_reserved9)  (void);
diff --git a/gdk/gdkevents.c b/gdk/gdkevents.c
index 24a29a1..0071401 100644
--- a/gdk/gdkevents.c
+++ b/gdk/gdkevents.c
@@ -121,6 +121,63 @@ _gdk_event_queue_append (GdkDisplay *display,
 }
 
 /**
+ * _gdk_event_queue_insert_after:
+ * @display: a #GdkDisplay
+ * @sibling: Append after this event.
+ * @event: Event to append.
+ *
+ * Appends an event after the specified event, or if it isn't in
+ * the queue, onto the tail of the event queue.
+ *
+ * Returns: the newly appended list node.
+ *
+ * Since: 2.16
+ */
+GList*
+_gdk_event_queue_insert_after (GdkDisplay *display,
+                               GdkEvent   *sibling,
+                               GdkEvent   *event)
+{
+  GList *prev = g_list_find (display->queued_events, sibling);
+  if (prev && prev->next)
+    {
+      display->queued_events = g_list_insert_before (display->queued_events, prev->next, event);
+      return prev->next;
+    }
+  else
+    return _gdk_event_queue_append (display, event);
+}
+
+/**
+ * _gdk_event_queue_insert_after:
+ * @display: a #GdkDisplay
+ * @sibling: Append after this event.
+ * @event: Event to append.
+ *
+ * Appends an event before the specified event, or if it isn't in
+ * the queue, onto the tail of the event queue.
+ *
+ * Returns: the newly appended list node.
+ *
+ * Since: 2.16
+ */
+GList*
+_gdk_event_queue_insert_before (GdkDisplay *display,
+				GdkEvent   *sibling,
+				GdkEvent   *event)
+{
+  GList *next = g_list_find (display->queued_events, sibling);
+  if (next)
+    {
+      display->queued_events = g_list_insert_before (display->queued_events, next, event);
+      return next->prev;
+    }
+  else
+    return _gdk_event_queue_append (display, event);
+}
+
+
+/**
  * _gdk_event_queue_remove_link:
  * @display: a #GdkDisplay
  * @node: node to remove
@@ -1101,13 +1158,16 @@ gdk_synthesize_click (GdkDisplay *display,
 		      gint	  nclicks)
 {
   GdkEvent temp_event;
+  GdkEvent *event_copy;
+  GList *link;
   
   g_return_if_fail (event != NULL);
   
   temp_event = *event;
   temp_event.type = (nclicks == 2) ? GDK_2BUTTON_PRESS : GDK_3BUTTON_PRESS;
-  
-  gdk_display_put_event (display, &temp_event);
+
+  event_copy = gdk_event_copy (&temp_event);
+  link = _gdk_event_queue_append (display, event_copy);
 }
 
 void
diff --git a/gdk/gdkevents.h b/gdk/gdkevents.h
index e64acb7..5d8e289 100644
--- a/gdk/gdkevents.h
+++ b/gdk/gdkevents.h
@@ -151,7 +151,8 @@ typedef enum
   GDK_SETTING           = 33,
   GDK_OWNER_CHANGE      = 34,
   GDK_GRAB_BROKEN       = 35,
-  GDK_DAMAGE            = 36
+  GDK_DAMAGE            = 36,
+  GDK_EVENT_LAST        /* helper variable for decls */
 } GdkEventType;
 
 /* Event masks. (Used to select what types of events a window
diff --git a/gdk/gdkgc.c b/gdk/gdkgc.c
index f3389c7..7b7e4ee 100644
--- a/gdk/gdkgc.c
+++ b/gdk/gdkgc.c
@@ -43,6 +43,8 @@ struct _GdkGCPrivate
 {
   GdkRegion *clip_region;
 
+  GdkSubwindowMode subwindow_mode;
+  
   GdkFill fill;
   GdkBitmap *stipple;
   GdkPixmap *tile;
@@ -172,6 +174,8 @@ _gdk_gc_init (GdkGC           *gc,
     priv->fg_pixel = values->foreground.pixel;
   if (values_mask & GDK_GC_BACKGROUND)
     priv->bg_pixel = values->background.pixel;
+  if (values_mask & GDK_GC_SUBWINDOW)
+    priv->subwindow_mode = values->subwindow_mode;
 
   gc->colormap = gdk_drawable_get_colormap (drawable);
   if (gc->colormap)
@@ -183,7 +187,7 @@ gdk_gc_finalize (GObject *object)
 {
   GdkGC *gc = GDK_GC (object);
   GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
-  
+
   if (priv->clip_region)
     gdk_region_destroy (priv->clip_region);
   if (gc->colormap)
@@ -313,6 +317,8 @@ gdk_gc_set_values (GdkGC           *gc,
     priv->fg_pixel = values->foreground.pixel;
   if (values_mask & GDK_GC_BACKGROUND)
     priv->bg_pixel = values->background.pixel;
+  if (values_mask & GDK_GC_SUBWINDOW)
+    priv->subwindow_mode = values->subwindow_mode;
   
   GDK_GC_GET_CLASS (gc)->set_values (gc, values, values_mask);
 }
@@ -542,9 +548,11 @@ gdk_gc_set_clip_mask (GdkGC	*gc,
   gdk_gc_set_values (gc, &values, GDK_GC_CLIP_MASK);
 }
 
-static void
+/* Takes ownership of passed in region */
+void
 _gdk_gc_set_clip_region_internal (GdkGC     *gc,
-				  GdkRegion *region)
+				  GdkRegion *region,
+				  gboolean reset_origin)
 {
   GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
 
@@ -553,7 +561,32 @@ _gdk_gc_set_clip_region_internal (GdkGC     *gc,
 
   priv->clip_region = region;
 
-  _gdk_windowing_gc_set_clip_region (gc, region);
+  _gdk_windowing_gc_set_clip_region (gc, region, reset_origin);
+}
+
+/* Takes ownership of passed in region, returns old clip region */
+void
+_gdk_gc_intersect_clip_region (GdkGC     *gc,
+			       GdkRegion *region,
+			       GdkRegion **old_clip_region)
+{
+  GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
+  GdkRegion *old_clip;
+
+  old_clip = priv->clip_region;
+
+  priv->clip_region = region;
+  if (old_clip)
+    gdk_region_intersect (region, old_clip);
+
+  if (old_clip_region)
+    *old_clip_region = old_clip;
+  else
+    gdk_region_destroy (old_clip);
+  
+  _gdk_windowing_gc_set_clip_region (gc, priv->clip_region, FALSE);
+  
+  return old_clip;
 }
 
 /**
@@ -578,7 +611,7 @@ gdk_gc_set_clip_rectangle (GdkGC              *gc,
   else
     region = NULL;
 
-  _gdk_gc_set_clip_region_internal (gc, region);
+  _gdk_gc_set_clip_region_internal (gc, region, TRUE);
 }
 
 /**
@@ -603,7 +636,7 @@ gdk_gc_set_clip_region (GdkGC           *gc,
   else
     copy = NULL;
 
-  _gdk_gc_set_clip_region_internal (gc, copy);
+  _gdk_gc_set_clip_region_internal (gc, copy, TRUE);
 }
 
 /**
@@ -723,13 +756,27 @@ gdk_gc_set_subwindow (GdkGC	       *gc,
 		      GdkSubwindowMode	mode)
 {
   GdkGCValues values;
+  GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
 
   g_return_if_fail (GDK_IS_GC (gc));
 
+  /* This could get called a lot to reset the subwindow mode in
+     the client side clipping, so bail out early */ 
+  if (priv->subwindow_mode == mode)
+    return;
+  
   values.subwindow_mode = mode;
   gdk_gc_set_values (gc, &values, GDK_GC_SUBWINDOW);
 }
 
+GdkSubwindowMode
+_gdk_gc_get_subwindow (GdkGC *gc)
+{
+  GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
+
+  return priv->subwindow_mode;
+}
+
 /**
  * gdk_gc_set_exposures:
  * @gc: a #GdkGC.
@@ -907,6 +954,7 @@ gdk_gc_copy (GdkGC *dst_gc,
 
   dst_priv->fg_pixel = src_priv->fg_pixel;
   dst_priv->bg_pixel = src_priv->bg_pixel;
+  dst_priv->subwindow_mode = src_priv->subwindow_mode;
 }
 
 /**
@@ -1117,6 +1165,8 @@ gc_get_background (GdkGC    *gc,
  *   the fill mode will be forced to %GDK_STIPPLED
  * @gc_changed: pass %FALSE if the @gc has not changed since the
  *     last call to this function
+ * @target_drawable: The drawable you're drawing in. If passed in
+ *     this is used for client side window clip emulation.
  * 
  * Set the attributes of a cairo context to match those of a #GdkGC
  * as far as possible. Some aspects of a #GdkGC, such as clip masks
@@ -1127,7 +1177,8 @@ _gdk_gc_update_context (GdkGC          *gc,
                         cairo_t        *cr,
                         const GdkColor *override_foreground,
                         GdkBitmap      *override_stipple,
-                        gboolean        gc_changed)
+                        gboolean        gc_changed,
+			GdkDrawable    *target_drawable)
 {
   GdkGCPrivate *priv;
   GdkFill fill;
@@ -1246,6 +1297,10 @@ _gdk_gc_update_context (GdkGC          *gc,
 
       cairo_clip (cr);
     }
+
+  /* The reset above resets the window clip rect, so we want to re-set that */
+  if (target_drawable && GDK_DRAWABLE_GET_CLASS (target_drawable)->set_cairo_clip)
+    GDK_DRAWABLE_GET_CLASS (target_drawable)->set_cairo_clip (target_drawable, cr);
 }
 
 
diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h
index 61a5433..b8fd252 100644
--- a/gdk/gdkinternals.h
+++ b/gdk/gdkinternals.h
@@ -182,15 +182,21 @@ extern gchar     *_gdk_display_arg_name;
 void      _gdk_events_queue  (GdkDisplay *display);
 GdkEvent* _gdk_event_unqueue (GdkDisplay *display);
 
-GList* _gdk_event_queue_find_first  (GdkDisplay *display);
-void   _gdk_event_queue_remove_link (GdkDisplay *display,
-				     GList      *node);
-GList*  _gdk_event_queue_prepend    (GdkDisplay *display,
-				     GdkEvent   *event);
-GList*  _gdk_event_queue_append     (GdkDisplay *display,
-				     GdkEvent   *event);
-void _gdk_event_button_generate     (GdkDisplay *display,
-				     GdkEvent   *event);
+GList* _gdk_event_queue_find_first   (GdkDisplay *display);
+void   _gdk_event_queue_remove_link  (GdkDisplay *display,
+				      GList      *node);
+GList* _gdk_event_queue_prepend      (GdkDisplay *display,
+				      GdkEvent   *event);
+GList* _gdk_event_queue_append       (GdkDisplay *display,
+				      GdkEvent   *event);
+GList* _gdk_event_queue_insert_after (GdkDisplay *display,
+                                      GdkEvent   *after_event,
+                                      GdkEvent   *event);
+GList* _gdk_event_queue_insert_before(GdkDisplay *display,
+                                      GdkEvent   *after_event,
+                                      GdkEvent   *event);
+void   _gdk_event_button_generate    (GdkDisplay *display,
+				      GdkEvent   *event);
 
 void _gdk_windowing_event_data_copy (const GdkEvent *src,
                                      GdkEvent       *dst);
@@ -227,6 +233,8 @@ GdkImage *_gdk_drawable_copy_to_image (GdkDrawable  *drawable,
 
 cairo_surface_t *_gdk_drawable_ref_cairo_surface (GdkDrawable *drawable);
 
+GdkDrawable *_gdk_drawable_get_source_drawable (GdkDrawable *drawable);
+
 /* GC caching */
 GdkGC *_gdk_drawable_get_scratch_gc (GdkDrawable *drawable,
 				     gboolean     graphics_exposures);
@@ -235,20 +243,41 @@ void _gdk_gc_update_context (GdkGC          *gc,
 			     cairo_t        *cr,
 			     const GdkColor *override_foreground,
 			     GdkBitmap      *override_stipple,
-			     gboolean        gc_changed);
+			     gboolean        gc_changed,
+			     GdkDrawable    *target_drawable);
 
 /*************************************
  * Interfaces used by windowing code *
  *************************************/
 
-GdkWindow *_gdk_window_new               (GdkWindow     *window,
-                                          GdkWindowAttr *attributes,
-                                          gint           attributes_mask);
-void       _gdk_window_destroy           (GdkWindow     *window,
-					  gboolean       foreign_destroy);
-void       _gdk_window_clear_update_area (GdkWindow     *window);
-
-void       _gdk_screen_close             (GdkScreen     *screen);
+GdkPixmap *_gdk_pixmap_new               (GdkDrawable    *drawable,
+                                          gint            width,
+                                          gint            height,
+                                          gint            depth);
+GdkPixmap *_gdk_pixmap_create_from_data  (GdkDrawable    *drawable,
+                                          const gchar    *data,
+                                          gint            width,
+                                          gint            height,
+                                          gint            depth,
+                                          const GdkColor *fg,
+                                          const GdkColor *bg);
+GdkPixmap *_gdk_bitmap_create_from_data  (GdkDrawable    *drawable,
+                                          const gchar    *data,
+                                          gint            width,
+                                          gint            height);
+
+void       _gdk_window_impl_new          (GdkWindow      *window,
+					  GdkScreen      *screen,
+					  GdkVisual      *visual,
+					  GdkEventMask    event_mask,
+                                          GdkWindowAttr  *attributes,
+                                          gint            attributes_mask);
+void       _gdk_window_destroy           (GdkWindow      *window,
+                                          gboolean        foreign_destroy);
+void       _gdk_window_clear_update_area (GdkWindow      *window);
+void       _gdk_window_update_size       (GdkWindow      *window);
+
+void       _gdk_screen_close             (GdkScreen      *screen);
 
 const char *_gdk_get_sm_client_id (void);
 
@@ -263,6 +292,13 @@ GdkPixmap *_gdk_gc_get_tile        (GdkGC *gc);
 GdkBitmap *_gdk_gc_get_stipple     (GdkGC *gc);
 guint32    _gdk_gc_get_fg_pixel    (GdkGC *gc);
 guint32    _gdk_gc_get_bg_pixel    (GdkGC *gc);
+void      _gdk_gc_intersect_clip_region     (GdkGC     *gc,
+					     GdkRegion *region,
+					     GdkRegion **old_region);
+void       _gdk_gc_set_clip_region_internal (GdkGC     *gc,
+					     GdkRegion *region,
+					     gboolean reset_origin);
+GdkSubwindowMode _gdk_gc_get_subwindow (GdkGC *gc);
 
 /*****************************************
  * Interfaces provided by windowing code *
@@ -306,21 +342,14 @@ GdkWindow* _gdk_windowing_window_at_pointer  (GdkDisplay       *display,
 gint _gdk_windowing_get_bits_for_depth (GdkDisplay *display,
 					gint        depth);
 
-void       _gdk_window_reparent                   (GdkWindow     *window,
-						   GdkWindow     *new_parent,
-						   gint           x,
-						   gint           y);
 
 #define GDK_WINDOW_IS_MAPPED(window) ((((GdkWindowObject*)window)->state & GDK_WINDOW_STATE_WITHDRAWN) == 0)
 
-/* Called before processing updates for a window. This gives the windowing
- * layer a chance to save the region for later use in avoiding duplicate
- * exposes. The return value indicates whether the function has a saved
- * the region; if the result is TRUE, then the windowing layer is responsible
- * for destroying the region later.
- */
-gboolean _gdk_windowing_window_queue_antiexpose (GdkWindow *window,
-						 GdkRegion *area);
+void _gdk_windowing_window_queue_translation (GdkWindow *window,
+					      GdkRegion *area,
+					      gint       dx,
+					      gint       dy);
+
 
 /* Called to do the windowing system specific part of gdk_window_destroy(),
  *
@@ -387,6 +416,7 @@ GType _gdk_pixmap_impl_get_type (void) G_GNUC_CONST;
  * _gdk_windowing_gc_set_clip_region:
  * @gc: a #GdkGC
  * @region: the new clip region
+ * @reset_origin: if TRUE, reset the clip_x/y_origin values to 0
  * 
  * Do any window-system specific processing necessary
  * for a change in clip region. Since the clip origin
@@ -398,7 +428,8 @@ GType _gdk_pixmap_impl_get_type (void) G_GNUC_CONST;
  * will already return the new region.
  **/
 void _gdk_windowing_gc_set_clip_region (GdkGC           *gc,
-					const GdkRegion *region);
+					const GdkRegion *region,
+					gboolean reset_origin);
 
 /**
  * _gdk_windowing_gc_copy:
@@ -435,6 +466,78 @@ char *_gdk_windowing_get_startup_notify_id (GAppLaunchContext *context,
 void  _gdk_windowing_launch_failed         (GAppLaunchContext *context, 
 				            const char        *startup_notify_id);
 
+void _gdk_windowing_grab_broken          (GdkDisplay *display);
+
+void _gdk_display_set_has_pointer_grab (GdkDisplay *display,
+					GdkWindow *window,
+					GdkWindow *native_window,
+					gboolean owner_events,
+					GdkEventMask event_mask,
+					unsigned long serial,
+					guint32 time,
+					gboolean implicit);
+void _gdk_display_unset_has_pointer_grab (GdkDisplay *display,
+					  gboolean implicit,
+					  gboolean do_grab_one_pointer_release_event,
+					  guint32 time);
+
+void _gdk_window_invalidate_for_expose (GdkWindow       *window,
+					const GdkRegion *region);
+
+void _gdk_windowing_set_cairo_surface_size (cairo_surface_t *surface,
+					    int width,
+					    int height);
+
+cairo_surface_t * _gdk_windowing_create_cairo_surface (GdkDrawable *drawable,
+						       int width,
+						       int height);
+GdkWindow * _gdk_window_find_descendant_at (GdkWindow *toplevel,
+					    double x, double y,
+					    double *found_x,
+					    double *found_y);
+
+void _gdk_window_add_damage (GdkWindow *toplevel,
+			     GdkRegion *damaged_region);
+
+GdkEvent * _gdk_make_event (GdkWindow    *window,
+			    GdkEventType  type,
+			    GdkEvent     *event_in_queue,
+			    gboolean      before_event);
+
+void _gdk_syntesize_crossing_events (GdkDisplay                 *display,
+				     GdkWindow                  *src,
+				     GdkWindow                  *dest,
+				     GdkCrossingMode             mode,
+				     gint                        toplevel_x,
+				     gint                        toplevel_y,
+				     GdkModifierType             mask,
+				     guint32                     time_,
+				     gboolean                    do_first,
+				     gboolean                    do_last);
+
+void _gdk_syntesize_crossing_events_for_geometry_change (GdkWindow *changed_window);
+
+GdkRegion *_gdk_window_calculate_full_clip_region    (GdkWindow     *window,
+                                                      GdkWindow     *base_window,
+                                                      gboolean       do_children,
+                                                      gint          *base_x_offset,
+                                                      gint          *base_y_offset);
+gboolean    _gdk_window_has_impl (GdkWindow *window);
+GdkWindow * _gdk_window_get_impl_window (GdkWindow *window);
+
+
+/*****************************
+ * offscreen window routines *
+ *****************************/
+GType gdk_offscreen_window_get_type (void);
+void       _gdk_offscreen_window_new                 (GdkWindow     *window,
+						      GdkScreen     *screen,
+						      GdkVisual     *visual,
+						      GdkWindowAttr *attributes,
+						      gint           attributes_mask);
+void       _gdk_offscreen_window_destroy             (GdkWindow     *window,
+                                                      gboolean       recursing);
+
 
 /************************************
  * Initialization and exit routines *
diff --git a/gdk/gdkoffscreenwindow.c b/gdk/gdkoffscreenwindow.c
new file mode 100644
index 0000000..4055c5a
--- /dev/null
+++ b/gdk/gdkoffscreenwindow.c
@@ -0,0 +1,1217 @@
+/* GDK - The GIMP Drawing Kit
+ * 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 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
+ * Lesser General Public License for more details.
+ *
+ * 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-2005.  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 <config.h>
+#include <math.h>
+#include "gdk.h"
+#include "gdkwindow.h"
+#include "gdkinternals.h"
+#include "gdkwindowimpl.h"
+#include "gdkpixmap.h"
+#include "gdkdrawable.h"
+#include "gdktypes.h"
+#include "gdkscreen.h"
+#include "gdkgc.h"
+#include "gdkcolor.h"
+#include "gdkcursor.h"
+#include "gdkalias.h"
+
+/* LIMITATIONS:
+ *
+ * Offscreen windows can't be the child of a foreign window,
+ *   nor contain foreign windows
+ * GDK_POINTER_MOTION_HINT_MASK isn't effective
+ */
+
+typedef struct _GdkOffscreenWindow      GdkOffscreenWindow;
+typedef struct _GdkOffscreenWindowClass GdkOffscreenWindowClass;
+
+struct _GdkOffscreenWindow
+{
+  GdkDrawable parent_instance;
+
+  GdkWindow *wrapper;
+  GdkCursor *cursor;
+  GdkColormap *colormap;
+  GdkScreen *screen;
+
+  GdkPixmap *pixmap;
+};
+
+struct _GdkOffscreenWindowClass
+{
+  GdkDrawableClass parent_class;
+};
+
+#define GDK_TYPE_OFFSCREEN_WINDOW            (gdk_offscreen_window_get_type())
+#define GDK_OFFSCREEN_WINDOW(object)         (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_OFFSCREEN_WINDOW, GdkOffscreenWindow))
+#define GDK_IS_OFFSCREEN_WINDOW(object)      (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_OFFSCREEN_WINDOW))
+#define GDK_OFFSCREEN_WINDOW_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_OFFSCREEN_WINDOW, GdkOffscreenWindowClass))
+#define GDK_IS_OFFSCREEN_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_OFFSCREEN_WINDOW))
+#define GDK_OFFSCREEN_WINDOW_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_OFFSCREEN_WINDOW, GdkOffscreenWindowClass))
+
+static void       gdk_offscreen_window_impl_iface_init    (GdkWindowImplIface         *iface);
+static void       gdk_offscreen_window_hide               (GdkWindow                  *window);
+static void       gdk_offscreen_window_clear_area         (GdkWindow                  *window,
+							   gint                        x,
+							   gint                        y,
+							   gint                        width,
+							   gint                        height,
+							   gboolean                    send_expose);
+
+
+G_DEFINE_TYPE_WITH_CODE (GdkOffscreenWindow,
+                         gdk_offscreen_window,
+                         GDK_TYPE_DRAWABLE,
+			 G_IMPLEMENT_INTERFACE (GDK_TYPE_WINDOW_IMPL,
+						gdk_offscreen_window_impl_iface_init));
+
+
+static void
+gdk_offscreen_window_finalize (GObject *object)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (object);
+
+  if (offscreen->cursor)
+    gdk_cursor_unref (offscreen->cursor);
+
+  offscreen->cursor = NULL;
+
+  gdk_pixmap_unref (offscreen->pixmap);
+  
+  G_OBJECT_CLASS (gdk_offscreen_window_parent_class)->finalize (object);
+}
+
+static void
+gdk_offscreen_window_init (GdkOffscreenWindow *window)
+{
+}
+
+void
+_gdk_offscreen_window_destroy (GdkWindow *window,
+                               gboolean   recursing)
+{
+  GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
+  GdkOffscreenWindow *offscreen;
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+  if (!recursing)
+    gdk_offscreen_window_hide (window);
+
+  g_object_unref (offscreen->colormap);
+  offscreen->colormap = NULL;
+}
+
+static gboolean
+is_parent_of (GdkWindow *parent,
+              GdkWindow *child)
+{
+  GdkWindow *w;
+
+  w = child;
+  while (w != NULL)
+    {
+      if (w == parent)
+	return TRUE;
+
+      w = gdk_window_get_parent (w);
+    }
+
+  return FALSE;
+}
+
+static GdkGC *
+gdk_offscreen_window_create_gc (GdkDrawable     *drawable,
+				GdkGCValues     *values,
+				GdkGCValuesMask  values_mask)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+  return gdk_gc_new_with_values (offscreen->pixmap, values, values_mask);
+}
+
+static GdkImage*
+gdk_offscreen_window_copy_to_image (GdkDrawable    *drawable,
+				    GdkImage       *image,
+				    gint            src_x,
+				    gint            src_y,
+				    gint            dest_x,
+				    gint            dest_y,
+				    gint            width,
+				    gint            height)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+  return gdk_drawable_copy_to_image (offscreen->pixmap,
+                                     image,
+                                     src_x,
+                                     src_y,
+                                     dest_x, dest_y,
+                                     width, height);
+}
+
+static cairo_surface_t *
+gdk_offscreen_window_ref_cairo_surface (GdkDrawable *drawable)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  
+  return _gdk_drawable_ref_cairo_surface (offscreen->pixmap);
+}
+
+static GdkColormap*
+gdk_offscreen_window_get_colormap (GdkDrawable *drawable)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+  return offscreen->colormap;
+}
+
+static void
+gdk_offscreen_window_set_colormap (GdkDrawable *drawable,
+				   GdkColormap*colormap)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+  if (colormap && GDK_WINDOW_DESTROYED (offscreen->wrapper))
+    return;
+
+  if (offscreen->colormap == colormap)
+    return;
+
+  if (offscreen->colormap)
+    g_object_unref (offscreen->colormap);
+
+  offscreen->colormap = colormap;
+  if (offscreen->colormap)
+    g_object_ref (offscreen->colormap);
+}
+
+
+static gint
+gdk_offscreen_window_get_depth (GdkDrawable *drawable)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+  return gdk_drawable_get_depth (offscreen->wrapper);
+}
+
+static GdkDrawable *
+gdk_offscreen_window_get_source_drawable (GdkDrawable  *drawable)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+  return _gdk_drawable_get_source_drawable (offscreen->pixmap);
+}
+
+static GdkDrawable *
+gdk_offscreen_window_get_composite_drawable (GdkDrawable *drawable,
+					     gint         x,
+					     gint         y,
+					     gint         width,
+					     gint         height,
+					     gint        *composite_x_offset,
+					     gint        *composite_y_offset)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+  return g_object_ref (offscreen->pixmap);
+}
+
+static GdkScreen*
+gdk_offscreen_window_get_screen (GdkDrawable *drawable)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+  return offscreen->screen;
+}
+
+static GdkVisual*
+gdk_offscreen_window_get_visual (GdkDrawable    *drawable)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+  return gdk_drawable_get_visual (offscreen->wrapper);
+}
+
+static void
+add_damage (GdkOffscreenWindow *offscreen,
+	    int x, int y,
+	    int w, int h)
+{
+  GdkRectangle rect;
+  GdkRegion *damage;
+  
+  rect.x = x;
+  rect.y = y;
+  rect.width = w;
+  rect.height = h;
+
+  damage = gdk_region_rectangle (&rect);
+  _gdk_window_add_damage (offscreen->wrapper, damage);
+  gdk_region_destroy (damage);
+}
+
+static void
+gdk_offscreen_window_draw_drawable (GdkDrawable *drawable,
+				    GdkGC       *gc,
+				    GdkPixmap   *src,
+				    gint         xsrc,
+				    gint         ysrc,
+				    gint         xdest,
+				    gint         ydest,
+				    gint         width,
+				    gint         height)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+  
+  gdk_draw_drawable (real_drawable, gc,
+		     src, xsrc, ysrc,
+		     xdest, ydest,
+		     width, height);
+
+  add_damage (offscreen, xdest, ydest, width, height);
+}
+
+static void
+gdk_offscreen_window_draw_rectangle (GdkDrawable  *drawable,
+				     GdkGC	  *gc,
+				     gboolean	   filled,
+				     gint	   x,
+				     gint	   y,
+				     gint	   width,
+				     gint	   height)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+
+  gdk_draw_rectangle (real_drawable,
+		      gc, filled, x, y, width, height);
+
+  add_damage (offscreen, x, y, width, height);
+  
+}
+
+static void
+gdk_offscreen_window_draw_arc (GdkDrawable  *drawable,
+			       GdkGC	       *gc,
+			       gboolean	filled,
+			       gint		x,
+			       gint		y,
+			       gint		width,
+			       gint		height,
+			       gint		angle1,
+			       gint		angle2)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+
+  gdk_draw_arc (real_drawable,
+		gc,
+		filled,
+		x,
+		y,
+		width,
+		height,
+		angle1,
+		angle2);
+  add_damage (offscreen, x, y, width, height);
+}
+
+static void
+gdk_offscreen_window_draw_polygon (GdkDrawable  *drawable,
+				   GdkGC	       *gc,
+				   gboolean	filled,
+				   GdkPoint     *points,
+				   gint		npoints)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+  
+  gdk_draw_polygon (real_drawable,
+		    gc,
+		    filled,
+		    points,
+		    npoints);
+
+  if (npoints > 0)
+    {
+      int min_x, min_y, max_x, max_y, i;
+      
+      min_x = max_x = points[0].x;
+      min_y = max_y = points[0].y;
+      
+	for (i = 1; i < npoints; i++)
+	  {
+	    min_x = MIN (min_x, points[i].x);
+	    max_x = MAX (max_x, points[i].x);
+	    min_y = MIN (min_y, points[i].y);
+	    max_y = MAX (max_y, points[i].y);
+	  }
+	
+	add_damage (offscreen, min_x, min_y,
+		    max_x - min_x,
+		    max_y - min_y);
+    }
+}
+
+static void
+gdk_offscreen_window_draw_text (GdkDrawable  *drawable,
+				GdkFont      *font,
+				GdkGC	       *gc,
+				gint		x,
+				gint		y,
+				const gchar  *text,
+				gint		text_length)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+  GdkWindowObject *private = GDK_WINDOW_OBJECT (offscreen->wrapper);
+
+  gdk_draw_text (real_drawable,
+		 font,
+		 gc,
+		 x,
+		 y,
+		 text,
+		 text_length);
+
+  /* Hard to compute the minimal size, not that often used anyway. */
+  add_damage (offscreen, 0, 0, private->width, private->height);
+}
+
+static void
+gdk_offscreen_window_draw_text_wc (GdkDrawable	 *drawable,
+				   GdkFont	 *font,
+				   GdkGC		 *gc,
+				   gint		  x,
+				   gint		  y,
+				   const GdkWChar *text,
+				   gint		  text_length)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+  GdkWindowObject *private = GDK_WINDOW_OBJECT (offscreen->wrapper);
+
+  gdk_draw_text_wc (real_drawable,
+		    font,
+		    gc,
+		    x,
+		    y,
+		    text,
+		    text_length);
+
+  /* Hard to compute the minimal size, not that often used anyway. */
+  add_damage (offscreen, 0, 0, private->width, private->height);
+}
+
+static void
+gdk_offscreen_window_draw_points (GdkDrawable  *drawable,
+				  GdkGC	       *gc,
+				  GdkPoint     *points,
+				  gint		npoints)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+
+  gdk_draw_points (real_drawable,
+		   gc,
+		   points,
+		   npoints);
+
+
+  if (npoints > 0)
+    {
+      int min_x, min_y, max_x, max_y, i;
+      
+      min_x = max_x = points[0].x;
+      min_y = max_y = points[0].y;
+      
+	for (i = 1; i < npoints; i++)
+	  {
+	    min_x = MIN (min_x, points[i].x);
+	    max_x = MAX (max_x, points[i].x);
+	    min_y = MIN (min_y, points[i].y);
+	    max_y = MAX (max_y, points[i].y);
+	  }
+	
+	add_damage (offscreen, min_x, min_y,
+		    max_x - min_x,
+		    max_y - min_y);
+    }
+}
+
+static void
+gdk_offscreen_window_draw_segments (GdkDrawable  *drawable,
+				    GdkGC	 *gc,
+				    GdkSegment   *segs,
+				    gint	  nsegs)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+
+  gdk_draw_segments (real_drawable,
+		     gc,
+		     segs,
+		     nsegs);
+
+  if (nsegs > 0)
+    {
+      int min_x, min_y, max_x, max_y, i;
+      
+      min_x = max_x = segs[0].x1;
+      min_y = max_y = segs[0].y1;
+      
+	for (i = 1; i < nsegs; i++)
+	  {
+	    min_x = MIN (min_x, segs[i].x1);
+	    max_x = MAX (max_x, segs[i].x1);
+	    min_x = MIN (min_x, segs[i].x2);
+	    max_x = MAX (max_x, segs[i].x2);
+	    min_y = MIN (min_y, segs[i].y1);
+	    max_y = MAX (max_y, segs[i].y1);
+	    min_y = MIN (min_y, segs[i].y2);
+	    max_y = MAX (max_y, segs[i].y2);
+	  }
+	
+	add_damage (offscreen, min_x, min_y,
+		    max_x - min_x,
+		    max_y - min_y);
+    }
+
+}
+
+static void
+gdk_offscreen_window_draw_lines (GdkDrawable  *drawable,
+				 GdkGC        *gc,
+				 GdkPoint     *points,
+				 gint          npoints)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+  GdkWindowObject *private = GDK_WINDOW_OBJECT (offscreen->wrapper);
+
+  gdk_draw_lines (real_drawable,
+		  gc,
+		  points,
+		  npoints);
+
+  /* Hard to compute the minimal size, as we don't know the line
+     width, and since joins are hard to calculate.
+     Its not that often used anyway, damage it all */
+  add_damage (offscreen, 0, 0, private->width, private->height);
+}
+
+static void
+gdk_offscreen_window_draw_image (GdkDrawable *drawable,
+				 GdkGC	      *gc,
+				 GdkImage    *image,
+				 gint	       xsrc,
+				 gint	       ysrc,
+				 gint	       xdest,
+				 gint	       ydest,
+				 gint	       width,
+				 gint	       height)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+
+  gdk_draw_image (real_drawable,
+		  gc,
+		  image,
+		  xsrc,
+		  ysrc,
+		  xdest,
+		  ydest,
+		  width,
+		  height);
+
+  add_damage (offscreen, xdest, ydest, width, height);
+}
+
+
+static void
+gdk_offscreen_window_draw_pixbuf (GdkDrawable *drawable,
+				  GdkGC       *gc,
+				  GdkPixbuf   *pixbuf,
+				  gint         src_x,
+				  gint         src_y,
+				  gint         dest_x,
+				  gint         dest_y,
+				  gint         width,
+				  gint         height,
+				  GdkRgbDither dither,
+				  gint         x_dither,
+				  gint         y_dither)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = GDK_DRAWABLE (offscreen->pixmap);
+  
+  gdk_draw_pixbuf (real_drawable,
+		   gc,
+		   pixbuf,
+		   src_x,
+		   src_y,
+		   dest_x,
+		   dest_y,
+		   width,
+		   height,
+		   dither,
+		   x_dither,
+		   y_dither);
+
+  add_damage (offscreen, dest_x, dest_y, width, height);
+
+}
+
+void 
+_gdk_offscreen_window_new (GdkWindow     *window,
+			   GdkScreen     *screen,
+			   GdkVisual     *visual,
+			   GdkWindowAttr *attributes,
+			   gint           attributes_mask)
+{
+  GdkWindowObject *parent_private;
+  GdkWindowObject *private;
+  GdkOffscreenWindow *offscreen;
+
+  g_return_if_fail (attributes != NULL);
+
+  if (attributes->wclass != GDK_INPUT_OUTPUT)
+    return; /* Can't support input only offscreens */
+  
+  private = (GdkWindowObject *)window;
+
+  if (private->parent != NULL && GDK_WINDOW_DESTROYED (private->parent))
+    return;
+
+  parent_private = (GdkWindowObject*) private->parent;
+  private->impl = g_object_new (GDK_TYPE_OFFSCREEN_WINDOW, NULL);
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+  offscreen->wrapper = window;
+
+  offscreen->screen = screen;
+
+  if (attributes_mask & GDK_WA_COLORMAP)
+    offscreen->colormap = g_object_ref (attributes->colormap);
+  else
+    {
+      if (gdk_screen_get_system_visual (screen) == visual)
+	{
+	  offscreen->colormap = gdk_screen_get_system_colormap (screen);
+	  g_object_ref (offscreen->colormap);
+	}
+      else
+	offscreen->colormap = gdk_colormap_new (visual, FALSE);
+    }
+
+  offscreen->pixmap = gdk_pixmap_new ((GdkDrawable *)private->parent,
+				      private->width,
+				      private->height,
+				      private->depth);
+}
+
+static gboolean
+gdk_offscreen_window_reparent (GdkWindow *window,
+			       GdkWindow *new_parent,
+			       gint       x,
+			       gint       y)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *new_parent_private = (GdkWindowObject *)new_parent;
+  GdkWindowObject *old_parent;
+  GdkOffscreenWindow *offscreen;
+  gboolean was_mapped;
+
+  if (new_parent)
+    {
+      /* No input-output children of input-only windows */
+      if (new_parent_private->input_only && !private->input_only)
+	return FALSE;
+      
+      /* Don't create loops in hierarchy */
+      if (is_parent_of (window, new_parent))
+	return FALSE;
+    }
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+  was_mapped = GDK_WINDOW_IS_MAPPED (window);
+
+  gdk_window_hide (window);
+
+  if (private->parent)
+    private->parent->children = g_list_remove (private->parent->children, window);
+
+  old_parent = private->parent;
+  private->parent = new_parent_private;
+  private->x = x;
+  private->y = y;
+
+  if (new_parent_private)
+    private->parent->children = g_list_prepend (private->parent->children, window);
+
+  _gdk_syntesize_crossing_events_for_geometry_change (window);
+  if (old_parent)
+    _gdk_syntesize_crossing_events_for_geometry_change (GDK_WINDOW (old_parent));
+  
+  return was_mapped;
+}
+
+static gint
+gdk_offscreen_window_get_origin (GdkWindow *window,
+				 gint      *x,
+				 gint      *y)
+{
+  if (x)
+    *x = 0;
+  if (y)
+    *y = 0;
+
+  return TRUE;
+}
+
+/**
+ * gdk_window_get_offscreen_pixmap:
+ * @window: a #GdkWindow
+ *
+ * Gets the offscreen pixmap that an offscreen window renders into. If
+ * you need to keep this around over window resizes, you need to add a
+ * reference to it.
+ *
+ * Returns: The offscreen pixmap, or NULL if not offscreen
+ **/
+GdkPixmap *
+gdk_window_get_offscreen_pixmap (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkOffscreenWindow *offscreen;
+  
+  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+
+  if (!GDK_IS_OFFSCREEN_WINDOW (private->impl))
+    return NULL;
+  
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+  return offscreen->pixmap;
+}
+
+static void
+gdk_offscreen_window_raise (GdkWindow *window)
+{
+  /* gdk_window_raise already changed the stacking order */
+  _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
+
+static void
+gdk_offscreen_window_lower (GdkWindow *window)
+{
+  /* gdk_window_lower already changed the stacking order */
+  _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
+
+static void
+gdk_offscreen_window_move_resize_internal (GdkWindow *window,
+					   gint       x,
+					   gint       y,
+					   gint       width,
+					   gint       height,
+					   gboolean   send_expose_events)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkOffscreenWindow *offscreen;
+  gint dx, dy, dw, dh;
+  GdkGC *gc;
+  GdkPixmap *old_pixmap;
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+  if (width < 1)
+    width = 1;
+  if (height < 1)
+    height = 1;
+
+  if (private->destroyed)
+    return;
+
+  dx = x - private->x;
+  dy = y - private->y;
+  dw = width - private->width;
+  dh = height - private->height;
+
+  private->x = x;
+  private->y = y;
+
+  if (private->width != width ||
+      private->height != height)
+    {
+      private->width = width;
+      private->height = height;
+      
+      old_pixmap = offscreen->pixmap;
+      offscreen->pixmap = gdk_pixmap_new (GDK_DRAWABLE (old_pixmap),
+					  width,
+					  height,
+					  private->depth);
+
+      gc = _gdk_drawable_get_scratch_gc (offscreen->pixmap, FALSE);
+      gdk_draw_drawable (offscreen->pixmap,
+			 gc,
+			 old_pixmap,
+			 0,0, 0, 0,
+			 -1, -1);
+      g_object_unref (old_pixmap);
+    }
+  
+  if (GDK_WINDOW_IS_MAPPED (private))
+    {
+      // TODO: Only invalidate new area, i.e. for larger windows
+      gdk_window_invalidate_rect (window, NULL, TRUE);
+      _gdk_syntesize_crossing_events_for_geometry_change (window);
+    }
+}
+
+static void
+gdk_offscreen_window_move_resize (GdkWindow *window,
+                                  gboolean   with_move,
+				  gint       x,
+                                  gint       y,
+				  gint       width,
+                                  gint       height)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkOffscreenWindow *offscreen;
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+  if (!with_move)
+    {
+      x = private->x;
+      y = private->y;
+    }
+
+  if (width < 0)
+    width = private->width;
+
+  if (height < 0)
+    height = private->height;
+
+  gdk_offscreen_window_move_resize_internal (window, x, y,
+					     width, height,
+					     TRUE);
+}
+
+static void
+gdk_offscreen_window_show (GdkWindow *window, gboolean raise)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkOffscreenWindow *offscreen;
+
+  if (GDK_WINDOW_IS_MAPPED (window))
+    return;
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+  private->state = 0;
+
+  /* gdk_window_show already changed the stacking order if needed */
+
+  if (private->event_mask & GDK_STRUCTURE_MASK)
+    _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
+  
+  if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+    _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
+
+  if (gdk_window_is_viewable (window))
+    _gdk_syntesize_crossing_events_for_geometry_change (window);
+  
+  gdk_window_clear_area_e (window, 0, 0,
+			   private->width, private->height);
+}
+
+
+static void
+gdk_offscreen_window_hide (GdkWindow *window)
+{
+  GdkWindowObject *private;
+  GdkOffscreenWindow *offscreen;
+  GdkDisplay *display;
+
+  g_return_if_fail (window != NULL);
+
+  private = (GdkWindowObject*) window;
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+  if (!GDK_WINDOW_IS_MAPPED (private))
+    return;
+  
+  /* May need to break grabs on children */
+  display = gdk_drawable_get_display (window);
+  
+  if (display->pointer_grab.window != NULL)
+    {
+      if (is_parent_of (window, display->pointer_grab.window))
+	{
+	  /* Call this ourselves, even though gdk_display_pointer_ungrab
+	     does so too, since we want to pass implicit == TRUE so the
+	     broken grab event is generated */
+	  _gdk_display_unset_has_pointer_grab (display,
+					       TRUE,
+					       FALSE,
+					       GDK_CURRENT_TIME);
+	  gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
+	}
+    }
+
+  if (private->event_mask & GDK_STRUCTURE_MASK)
+    _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
+  
+  if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+    _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
+  
+  private->state = GDK_WINDOW_STATE_WITHDRAWN;
+  
+  _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
+
+static void
+gdk_offscreen_window_withdraw (GdkWindow *window)
+{
+}
+
+static GdkEventMask
+gdk_offscreen_window_get_events (GdkWindow *window)
+{
+  return 0;
+}
+
+static void
+gdk_offscreen_window_set_events (GdkWindow       *window,
+				 GdkEventMask     event_mask)
+{
+}
+
+static GdkGC *
+setup_backing_rect_gc (GdkWindow *window, int x_offset, int y_offset)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkGC *gc;
+
+  if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
+    {
+      x_offset += private->x;
+      y_offset += private->y;
+      
+      return setup_backing_rect_gc (GDK_WINDOW (private->parent), x_offset, y_offset);
+    }
+  else if (private->bg_pixmap &&
+	   private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+	   private->bg_pixmap != GDK_NO_BG)
+    {
+      guint gc_mask;
+      GdkGCValues gc_values;
+
+      gc_values.fill = GDK_TILED;
+      gc_values.tile = private->bg_pixmap;
+      gc_values.ts_x_origin = -x_offset;
+      gc_values.ts_y_origin = -y_offset;
+
+      gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN;
+
+      return gdk_gc_new_with_values (window, &gc_values, gc_mask);
+    }
+  else
+    {
+      gc = _gdk_drawable_get_scratch_gc (window, FALSE);
+      g_object_ref (gc);
+      gdk_gc_set_foreground (gc, &private->bg_color);
+      return gc;
+    }
+}
+
+static void
+gdk_offscreen_window_clear_area (GdkWindow *window,
+				 gint       x,
+				 gint       y,
+				 gint       width,
+				 gint       height,
+				 gboolean   send_expose)
+{
+  GdkGC *gc;
+  
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
+  /* Actual drawing is done by gdkwindow.c */
+
+  gc = setup_backing_rect_gc (window, 0, 0);
+  gdk_draw_rectangle (window, gc, TRUE, x, y, width, height);
+  g_object_unref (gc);
+  
+  if (send_expose)
+    {
+      GdkRectangle visible, rect;
+
+      visible.x = visible.y = 0;
+      gdk_drawable_get_size (GDK_DRAWABLE (window), &visible.width, &visible.height);
+
+      rect.x = x;
+      rect.y = x;
+      rect.width = width;
+      rect.height = height;
+
+      gdk_rectangle_intersect (&rect, &visible, &rect);
+
+      gdk_window_invalidate_rect (window, &rect, TRUE);
+    }
+}
+
+static void
+gdk_offscreen_window_set_background (GdkWindow      *window,
+				     const GdkColor *color)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkColormap *colormap = gdk_drawable_get_colormap (window);
+
+  private->bg_color = *color;
+  gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
+
+  if (private->bg_pixmap &&
+      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+      private->bg_pixmap != GDK_NO_BG)
+    g_object_unref (private->bg_pixmap);
+
+  private->bg_pixmap = NULL;
+}
+
+static void
+gdk_offscreen_window_set_back_pixmap (GdkWindow *window,
+				      GdkPixmap *pixmap)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+
+  if (pixmap &&
+      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+      private->bg_pixmap != GDK_NO_BG &&
+      !gdk_drawable_get_colormap (pixmap))
+    {
+      g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
+      return;
+    }
+
+  if (private->bg_pixmap &&
+      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+      private->bg_pixmap != GDK_NO_BG)
+    g_object_unref (private->bg_pixmap);
+
+  private->bg_pixmap = pixmap;
+
+  if (pixmap &&
+      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+      private->bg_pixmap != GDK_NO_BG)
+    g_object_ref (pixmap);
+}
+
+static void
+gdk_offscreen_window_shape_combine_mask (GdkWindow *window,
+                                         GdkBitmap *mask,
+                                         gint       x,
+                                         gint       y)
+{
+}
+
+static void
+gdk_offscreen_window_shape_combine_region (GdkWindow       *window,
+                                           const GdkRegion *shape_region,
+                                           gint             offset_x,
+                                           gint             offset_y)
+{
+}
+
+static void
+gdk_offscreen_window_set_child_shapes (GdkWindow *window)
+{
+}
+
+static void
+gdk_offscreen_window_merge_child_shapes (GdkWindow *window)
+{
+}
+
+static gboolean
+gdk_offscreen_window_set_static_gravities (GdkWindow *window,
+					   gboolean   use_static)
+{
+  return TRUE;
+}
+
+static void
+gdk_offscreen_window_set_cursor (GdkWindow *window,
+				 GdkCursor *cursor)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkOffscreenWindow *offscreen;
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+  if (offscreen->cursor)
+    {
+      gdk_cursor_unref (offscreen->cursor);
+      offscreen->cursor = NULL;
+    }
+
+  if (cursor)
+    offscreen->cursor = gdk_cursor_ref (cursor);
+
+  /* TODO: The cursor is never actually used... */
+}
+
+static void
+gdk_offscreen_window_get_geometry (GdkWindow *window,
+				   gint      *x,
+				   gint      *y,
+				   gint      *width,
+				   gint      *height,
+				   gint      *depth)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkOffscreenWindow *offscreen;
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+  g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
+
+  if (!GDK_WINDOW_DESTROYED (window))
+    {
+      if (x)
+	*x = private->x;
+      if (y)
+	*y = private->y;
+      if (width)
+	*width = private->width;
+      if (height)
+	*height = private->height;
+      if (depth)
+	*depth = private->depth;
+    }
+}
+
+/**
+ * gdk_window_set_offscreen_hooks:
+ * @offscreen_window: a offscreen #GdkWindow
+ * @hooks:  a table of pointers to functions for handling offscreen
+ *          window coordinates translations
+ *
+ * Sets the parent-to-offscreen-child and offscreen-child-to-parent coordinate
+ * translation functions for offscreen windows.
+ *
+ * This function is useful for complex widgets employing
+ * offscreen windows.
+ *
+ * Since: 2.16
+ */
+void
+gdk_window_set_offscreen_hooks (GdkWindow  *offscreen_window,
+                                const GdkOffscreenChildHooks *hooks)
+{
+  GdkWindowObject *private;
+
+  g_return_if_fail (GDK_IS_WINDOW (offscreen_window));
+  g_return_if_fail (hooks != NULL);
+
+  private = (GdkWindowObject *) offscreen_window;
+
+  private->offscreen_hooks = hooks;
+}
+
+static gboolean
+gdk_offscreen_window_queue_antiexpose (GdkWindow *window,
+				       GdkRegion *area)
+{
+  return FALSE;
+}
+
+static void
+gdk_offscreen_window_class_init (GdkOffscreenWindowClass *klass)
+{
+  GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = gdk_offscreen_window_finalize;
+
+  drawable_class->create_gc = gdk_offscreen_window_create_gc;
+  drawable_class->_copy_to_image = gdk_offscreen_window_copy_to_image;
+  drawable_class->ref_cairo_surface = gdk_offscreen_window_ref_cairo_surface;
+  drawable_class->set_colormap = gdk_offscreen_window_set_colormap;
+  drawable_class->get_colormap = gdk_offscreen_window_get_colormap;
+  drawable_class->get_depth = gdk_offscreen_window_get_depth;
+  drawable_class->get_screen = gdk_offscreen_window_get_screen;
+  drawable_class->get_visual = gdk_offscreen_window_get_visual;
+  drawable_class->get_source_drawable = gdk_offscreen_window_get_source_drawable;
+  drawable_class->get_composite_drawable = gdk_offscreen_window_get_composite_drawable;
+
+  drawable_class->draw_rectangle = gdk_offscreen_window_draw_rectangle;
+  drawable_class->draw_arc = gdk_offscreen_window_draw_arc;
+  drawable_class->draw_polygon = gdk_offscreen_window_draw_polygon;
+  drawable_class->draw_text = gdk_offscreen_window_draw_text;
+  drawable_class->draw_text_wc = gdk_offscreen_window_draw_text_wc;
+  drawable_class->draw_drawable = gdk_offscreen_window_draw_drawable;
+  drawable_class->draw_points = gdk_offscreen_window_draw_points;
+  drawable_class->draw_segments = gdk_offscreen_window_draw_segments;
+  drawable_class->draw_lines = gdk_offscreen_window_draw_lines;
+  drawable_class->draw_image = gdk_offscreen_window_draw_image;
+  drawable_class->draw_pixbuf = gdk_offscreen_window_draw_pixbuf;
+}
+
+static void
+gdk_offscreen_window_impl_iface_init (GdkWindowImplIface *iface)
+{
+  iface->show = gdk_offscreen_window_show;
+  iface->hide = gdk_offscreen_window_hide;
+  iface->withdraw = gdk_offscreen_window_withdraw;
+  iface->raise = gdk_offscreen_window_raise;
+  iface->lower = gdk_offscreen_window_lower;
+  iface->move_resize = gdk_offscreen_window_move_resize;
+  iface->set_background = gdk_offscreen_window_set_background;
+  iface->set_back_pixmap = gdk_offscreen_window_set_back_pixmap;
+  iface->get_events = gdk_offscreen_window_get_events;
+  iface->set_events = gdk_offscreen_window_set_events;
+  iface->clear_area = gdk_offscreen_window_clear_area;
+  iface->reparent = gdk_offscreen_window_reparent;
+  iface->set_cursor = gdk_offscreen_window_set_cursor;
+  iface->get_geometry = gdk_offscreen_window_get_geometry;
+  iface->shape_combine_mask = gdk_offscreen_window_shape_combine_mask;
+  iface->shape_combine_region = gdk_offscreen_window_shape_combine_region;
+  iface->set_child_shapes = gdk_offscreen_window_set_child_shapes;
+  iface->merge_child_shapes = gdk_offscreen_window_merge_child_shapes;
+  iface->set_static_gravities = gdk_offscreen_window_set_static_gravities;
+  iface->queue_antiexpose = gdk_offscreen_window_queue_antiexpose;
+  iface->get_origin = gdk_offscreen_window_get_origin;
+}
+
+#define __GDK_OFFSCREEN_WINDOW_C__
+#include "gdkaliasdef.c"
diff --git a/gdk/gdkpango.c b/gdk/gdkpango.c
index a386403..24efca8 100644
--- a/gdk/gdkpango.c
+++ b/gdk/gdkpango.c
@@ -214,7 +214,8 @@ get_cairo_context (GdkPangoRenderer *gdk_renderer,
 				  priv->cr,
 				  color,
 				  priv->stipple[part],
-				  priv->gc_changed);
+				  priv->gc_changed,
+				  priv->drawable);
 	}
 
       priv->last_part = part;
diff --git a/gdk/gdkpixmap.c b/gdk/gdkpixmap.c
index c717b9a..806a5ca 100644
--- a/gdk/gdkpixmap.c
+++ b/gdk/gdkpixmap.c
@@ -229,6 +229,48 @@ gdk_pixmap_finalize (GObject *object)
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
+GdkPixmap *
+gdk_pixmap_new (GdkDrawable *drawable,
+                gint         width,
+                gint         height,
+                gint         depth)
+{
+  GdkDrawable *source_drawable;
+
+  source_drawable = _gdk_drawable_get_source_drawable (drawable);
+  return _gdk_pixmap_new (source_drawable, width, height, depth);
+}
+
+GdkPixmap *
+gdk_bitmap_create_from_data (GdkDrawable *drawable,
+                             const gchar *data,
+                             gint         width,
+                             gint         height)
+{
+  GdkDrawable *source_drawable;
+
+  source_drawable = _gdk_drawable_get_source_drawable (drawable);
+  return _gdk_bitmap_create_from_data (source_drawable, data, width, height);
+}
+
+GdkPixmap*
+gdk_pixmap_create_from_data (GdkDrawable    *drawable,
+                             const gchar    *data,
+                             gint            width,
+                             gint            height,
+                             gint            depth,
+                             const GdkColor *fg,
+                             const GdkColor *bg)
+{
+  GdkDrawable *source_drawable;
+
+  source_drawable = _gdk_drawable_get_source_drawable (drawable);
+  return _gdk_pixmap_create_from_data (source_drawable,
+                                       data, width, height,
+                                       depth, fg,bg);
+}
+
+
 static GdkGC *
 gdk_pixmap_create_gc (GdkDrawable     *drawable,
                       GdkGCValues     *values,
diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c
index 66b83ae..fabe972 100644
--- a/gdk/gdkwindow.c
+++ b/gdk/gdkwindow.c
@@ -35,9 +35,31 @@
 #include "gdkscreen.h"
 #include "gdkalias.h"
 
-#define USE_BACKING_STORE	/* Appears to work on Win32, too, now. */
+#ifdef GDK_WINDOWING_X11
+#include "x11/gdkx.h"           /* For workaround */
+#endif
 
-typedef struct _GdkWindowPaint GdkWindowPaint;
+#include "math.h"
+
+/* Not all GdkWindows have a corresponding native window.
+ * Instead some draw into the nearest parent that has whatss
+ * called an "impl", i.e. the implementation window.
+ * For toplevel window system windows the impl is always native
+ * window, but child windows can also have native windows as
+ * this is sometimes necessary. Furthermore, offscreen windows
+ * (type GDK_WINDOW_OFFSCREEN) have an impl of type
+ * GdkOffscreenWindow rather than a backend implementation native
+ * window. Such windows draw into an offscreen pixmap instead
+ * of a window and collect damage that lets you paint it where
+ * you want.
+ *
+ * All GdkWindow track their position, size, clip region and
+ * absolute position in the impl window. For child window with
+ * native windows the clip region is set on the native window
+ * as a window shape to make it clip against other non-native windows.
+ */  
+
+#define USE_BACKING_STORE	/* Appears to work on Win32, too, now. */
 
 struct _GdkWindowPaint
 {
@@ -46,27 +68,10 @@ struct _GdkWindowPaint
   gint x_offset;
   gint y_offset;
   cairo_surface_t *surface;
+  guint uses_implicit : 1;
 };
 
-typedef struct {
-  GdkRegion *old_region;
-  gint old_clip_x_origin;
-  gint old_clip_y_origin;
-  gint x_offset;
-  gint y_offset;
-} GdkWindowClipData;
-
-struct _GdkWindowRedirect
-{
-  GdkWindowObject *redirected;
-  GdkDrawable *pixmap;
-  gint src_x;
-  gint src_y;
-  gint dest_x;
-  gint dest_y;
-  gint width;
-  gint height;
-};
+/* Global info */
 
 static GdkGC *gdk_window_create_gc      (GdkDrawable     *drawable,
                                          GdkGCValues     *values,
@@ -180,6 +185,8 @@ static GdkImage* gdk_window_copy_to_image (GdkDrawable *drawable,
 					   gint         height);
 
 static cairo_surface_t *gdk_window_ref_cairo_surface (GdkDrawable *drawable);
+static void             gdk_window_set_cairo_clip    (GdkDrawable *drawable,
+						      cairo_t *cr);
 
 static void   gdk_window_real_get_size  (GdkDrawable     *drawable,
                                          gint            *width,
@@ -192,6 +199,7 @@ static void         gdk_window_real_set_colormap (GdkDrawable *drawable,
 						  GdkColormap *cmap);
 static GdkColormap* gdk_window_real_get_colormap (GdkDrawable *drawable);
 
+static GdkDrawable* gdk_window_get_source_drawable    (GdkDrawable *drawable);
 static GdkDrawable* gdk_window_get_composite_drawable (GdkDrawable *drawable,
 						       gint         x,
 						       gint         y,
@@ -212,26 +220,20 @@ static void gdk_window_clear_backing_rect (GdkWindow *window,
 					   gint       y,
 					   gint       width,
 					   gint       height);
-static void setup_redirect_clip           (GdkWindow         *window,
-					   GdkGC             *gc,
-					   GdkWindowClipData *data);
-static void reset_redirect_clip           (GdkWindow         *offscreen,
-					   GdkGC             *gc,
-					   GdkWindowClipData *data);
 static void gdk_window_redirect_free      (GdkWindowRedirect *redirect);
 static void apply_redirect_to_children    (GdkWindowObject   *private,
 					   GdkWindowRedirect *redirect);
 static void remove_redirect_from_children (GdkWindowObject   *private,
 					   GdkWindowRedirect *redirect);
-static GdkRegion *_gdk_window_calculate_full_clip_region (GdkWindow *window,
-							  GdkWindow *base_window,
-							  GdkGC *gc,
-							  gboolean do_children,
-							  gint *base_x_offset,
-							  gint *base_y_offset);
 
+static void recompute_visible_regions (GdkWindowObject *private,
+				       gboolean recalculate_siblings,
+				       gboolean recalculate_children);
+  
 static gpointer parent_class = NULL;
 
+static const cairo_user_data_key_t gdk_window_cairo_key;
+
 GType
 gdk_window_object_get_type (void)
 {
@@ -281,6 +283,9 @@ gdk_window_init (GdkWindowObject *window)
   window->window_type = GDK_WINDOW_CHILD;
 
   window->state = GDK_WINDOW_STATE_WITHDRAWN;
+  window->width = 1;
+  window->height = 1;
+  window->toplevel_window_type = -1;
 }
 
 static GQuark quark_pointer_window = 0;
@@ -318,9 +323,11 @@ gdk_window_class_init (GdkWindowObjectClass *klass)
   drawable_class->get_visual = gdk_window_real_get_visual;
   drawable_class->_copy_to_image = gdk_window_copy_to_image;
   drawable_class->ref_cairo_surface = gdk_window_ref_cairo_surface;
+  drawable_class->set_cairo_clip = gdk_window_set_cairo_clip;
   drawable_class->get_clip_region = gdk_window_get_clip_region;
   drawable_class->get_visible_region = gdk_window_get_visible_region;
   drawable_class->get_composite_drawable = gdk_window_get_composite_drawable;
+  drawable_class->get_source_drawable = gdk_window_get_source_drawable;
 
   quark_pointer_window = g_quark_from_static_string ("gtk-pointer-window");
 }
@@ -345,12 +352,264 @@ gdk_window_finalize (GObject *object)
 	_gdk_window_destroy (window, TRUE);
     }
 
-  g_object_unref (obj->impl);
-  obj->impl = NULL;
+  if (obj->impl)
+    {
+      g_object_unref (obj->impl);
+      obj->impl = NULL;
+    }
+
+  if (obj->cursor)
+    gdk_cursor_unref (obj->cursor);
+
+  if (obj->colormap)
+    g_object_unref (obj->colormap);
   
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
+static gboolean
+gdk_window_is_offscreen (GdkWindowObject *window)
+{
+  return GDK_WINDOW_TYPE (window) == GDK_WINDOW_OFFSCREEN;
+}
+
+static GdkWindowObject *
+gdk_window_get_impl_window (GdkWindowObject *window)
+{
+  while (window->parent->impl == window->impl)
+    window = window->parent;
+
+  return window;
+}
+
+GdkWindow *
+_gdk_window_get_impl_window (GdkWindow *window)
+{
+  return (GdkWindow *)gdk_window_get_impl_window ((GdkWindowObject *)window);
+}
+
+static gboolean
+gdk_window_has_impl (GdkWindowObject *window)
+{
+  return window->parent == NULL || window->parent->impl != window->impl;
+}
+
+gboolean
+_gdk_window_has_impl (GdkWindow *window)
+{
+  return gdk_window_has_impl ((GdkWindowObject *)window);
+}
+
+static gboolean
+gdk_window_has_no_impl (GdkWindowObject *window)
+{
+  return window->parent->impl == window->impl;
+}
+
+static void
+remove_child_area (GdkWindowObject *private,
+		   GdkWindowObject *until,
+		   GdkRegion *region)
+{
+  GdkWindowObject *child;
+  GdkRegion *child_region;
+  GdkRectangle r;
+  GList *l;
+  
+  for (l = private->children; l; l = l->next)
+    {
+      child = l->data;
+
+      if (child == until)
+	break;
+      
+      if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only)
+	continue;
+
+      /* Ignore offscreen children, as they don't draw in their parent and
+       * don't take part in the clipping */
+      if (gdk_window_is_offscreen (child))
+	continue;
+
+      r.x = child->x;
+      r.y = child->y;
+      r.width = child->width;
+      r.height = child->height;
+      
+      child_region = gdk_region_rectangle (&r);
+      gdk_region_subtract (region, child_region);
+      gdk_region_destroy (child_region);
+    }
+}
+
+static void
+recompute_visible_regions_internal (GdkWindowObject *private,
+				    gboolean recalculate_clip,
+				    gboolean recalculate_siblings,
+				    gboolean recalculate_children)
+{
+  GdkRectangle r;
+  GList *l;
+  GdkWindowObject *child;
+  GdkRegion *new_clip;
+  gboolean clip_region_changed;
+  gboolean abs_pos_changed;
+  int old_abs_x, old_abs_y;
+
+  old_abs_x = private->abs_x;
+  old_abs_y = private->abs_y;
+  
+  /* Update absolute position */
+  if (gdk_window_has_impl (private))
+    {
+      /* Native window starts here */
+      private->abs_x = 0;
+      private->abs_y = 0;
+    }
+  else
+    {
+      private->abs_x = private->parent->abs_x + private->x;
+      private->abs_y = private->parent->abs_y + private->y;
+    }
+
+  abs_pos_changed =
+    private->abs_x != old_abs_x ||
+    private->abs_y != old_abs_y;
+
+  /* Update clip region based on:
+   * parent clip
+   * window size
+   * siblings in parents above window
+   */
+  clip_region_changed = FALSE;
+  if (recalculate_clip)
+    {
+      /* Calculate visible region (sans children) in parent window coords */
+      r.x = private->x;
+      r.y = private->y;
+      r.width = private->width;
+      r.height = private->height;
+      new_clip = gdk_region_rectangle (&r);
+      
+      if (private->parent != NULL && GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
+	{
+	  gdk_region_intersect (new_clip, private->parent->clip_region);
+	  
+	  /* Remove all overlapping children from parent */
+	  remove_child_area (private->parent, private, new_clip);
+	}
+      
+      /* Convert from parent coords to window coords */
+      gdk_region_offset (new_clip, -private->x, -private->y);
+
+      if (private->clip_region == NULL ||
+	  !gdk_region_equal (private->clip_region, new_clip))
+	clip_region_changed = TRUE;
+	
+      if (private->clip_region)
+	gdk_region_destroy (private->clip_region);
+      private->clip_region = new_clip;
+
+      private->clip_region_with_children = gdk_region_copy (private->clip_region);
+      remove_child_area (private, NULL, private->clip_region_with_children);
+    }
+
+  /* Update all children, recursively. */
+  if (abs_pos_changed || clip_region_changed || recalculate_children)
+    {
+      for (l = private->children; l; l = l->next)
+	{
+	  child = l->data;
+	  /* Only recalculate clip if the the clip region changed, otherwise
+	   * there is no way the child clip region could change (its has not e.g. moved)
+	   * Except if recalculate_children is set to force child updates
+	   */
+	  recompute_visible_regions_internal (child, recalculate_clip && (clip_region_changed || recalculate_children), FALSE, FALSE);
+	}
+    }
+
+  if (clip_region_changed &&
+      gdk_window_has_impl (private) &&
+      /* Not for offscreens */
+      private->window_type != GDK_WINDOW_OFFSCREEN &&
+      /* or for toplevels */
+      private->parent != NULL &&
+      GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT
+      )
+    {
+      GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region ((GdkWindow *)private, private->clip_region, 0, 0);
+    }
+      
+  
+  if (recalculate_siblings &&
+      private->parent != NULL &&
+      GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
+    {
+      /* If we moved a child window in parent or changed the stacking order, then we
+       * need to recompute the visible area of all the other children in the parent
+       */
+      for (l = private->parent->children; l; l = l->next)
+	{
+	  child = l->data;
+
+	  if (child != private)
+	    recompute_visible_regions_internal (child, TRUE, FALSE, FALSE);
+	}
+
+      /* We also need to recompute the _with_children clip for the parent */
+      recompute_visible_regions_internal (private->parent, TRUE, FALSE, FALSE);
+    }
+
+  if (private->cairo_surface)
+    {
+      int width, height;
+
+      /* It would be nice if we had some cairo support here so we
+	 could set the clip rect on the cairo surface */
+      width = private->abs_x + private->width;
+      height = private->abs_y + private->height;
+
+      _gdk_windowing_set_cairo_surface_size (private->cairo_surface,
+					     width, height);
+      cairo_surface_set_device_offset (private->cairo_surface, 
+				       private->abs_x,
+				       private->abs_y);
+    }
+}
+
+/* Call this when private has changed in one or more of these ways:
+ *  size changed
+ *  window moved
+ *  new window added
+ *  stacking order of window changed
+ *  child deleted
+ *
+ * It will recalculate abs_x/y and the clip regions
+ *
+ * Unless the window didn't change stacking order or size/pos, pass in TRUE
+ * for recalculate_siblings. (Mostly used internally for the recursion)
+ * 
+ * If a child window was removed (and you can't use that child for
+ * recompute_visible_regions), pass in TRUE for recalculate_children on the parent
+ */
+static void
+recompute_visible_regions (GdkWindowObject *private,
+			   gboolean recalculate_siblings,
+			   gboolean recalculate_children)
+{
+  recompute_visible_regions_internal (private,
+				      TRUE,
+				      recalculate_siblings,
+				      recalculate_children);
+}
+
+void
+_gdk_window_update_size (GdkWindow *window)
+{
+  recompute_visible_regions ((GdkWindowObject *)window, TRUE, FALSE);
+}
+
+
 /**
  * gdk_window_new:
  * @parent: a #GdkWindow, or %NULL to create the window as a child of
@@ -371,25 +630,225 @@ gdk_window_new (GdkWindow     *parent,
 		gint           attributes_mask)
 {
   GdkWindow *window;
-  GdkWindowObject *private, *parent_private;
-
-  g_return_val_if_fail (parent == NULL || GDK_IS_WINDOW (parent), NULL);
+  GdkWindowObject *private;
+  GdkScreen *screen;
+  GdkVisual *visual;
+  int x, y, depth;
+  gboolean native;
+  GdkEventMask event_mask;
+  
   g_return_val_if_fail (attributes != NULL, NULL);
+  
+  if (!parent)
+    {
+      GDK_NOTE (MULTIHEAD,
+		g_warning ("gdk_window_new(): no parent specified reverting to parent = default root window"));
+      
+      screen = gdk_screen_get_default ();
+      parent = gdk_screen_get_root_window (screen);
+    }
+  else
+    screen = gdk_drawable_get_screen (parent);
+
+  g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
+  
+  if (GDK_WINDOW_DESTROYED (parent))
+    return NULL;
 
-  window = _gdk_window_new (parent, attributes, attributes_mask);
-  g_return_val_if_fail (window != NULL, window);
+  window = g_object_new (GDK_TYPE_WINDOW, NULL);
+  private = (GdkWindowObject *) window;
+
+  /* Windows with a foreign parent are treated as if they are children
+   * of the root window, except for actual creation.
+   */
+  if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
+    parent = gdk_screen_get_root_window (screen);
 
-  /* Inherit redirection from parent */
-  if (parent != NULL)
+  private->parent = (GdkWindowObject *)parent;
+
+  private->accept_focus = TRUE;
+  private->focus_on_map = TRUE;
+
+  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);
+
+#ifdef GDK_WINDOWING_X11
+  /* Work around a bug where Xorg refuses to map toplevel InputOnly windows 
+   * from an untrusted client: http://bugs.freedesktop.org/show_bug.cgi?id=6988
+   */
+  if (attributes->wclass == GDK_INPUT_ONLY &&
+      GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT &&
+      !G_LIKELY (GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (parent))->trusted_client))
+    {
+      g_warning ("Coercing GDK_INPUT_ONLY toplevel window to GDK_INPUT_OUTPUT to work around bug in Xorg server");
+      attributes->wclass = GDK_INPUT_OUTPUT;
+    }
+#endif
+  
+  if (attributes->wclass == GDK_INPUT_ONLY)
+    {
+      /* Backwards compatiblity - we've always ignored
+       * attributes->window_type for input-only windows
+       * before
+       */
+      if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
+	private->window_type = GDK_WINDOW_TEMP;
+      else
+	private->window_type = GDK_WINDOW_CHILD;
+    }
+  else
+    private->window_type = attributes->window_type;
+
+  /* Sanity checks */
+  switch (private->window_type)
+    {
+    case GDK_WINDOW_TOPLEVEL:
+    case GDK_WINDOW_DIALOG:
+    case GDK_WINDOW_TEMP:
+      if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
+	g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
+		   "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
+    case GDK_WINDOW_CHILD:
+    case GDK_WINDOW_OFFSCREEN:
+      break;
+    default:
+      g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
+      return NULL;
+    }
+  
+  if (attributes_mask & GDK_WA_VISUAL)
+    visual = attributes->visual;
+  else
+    visual = gdk_screen_get_system_visual (screen);
+
+  private->event_mask = attributes->event_mask;
+
+  if (attributes->wclass == GDK_INPUT_OUTPUT)
+    {
+      depth = visual->depth;
+
+      if (attributes_mask & GDK_WA_COLORMAP)
+	private->colormap = g_object_ref (attributes->colormap);
+      
+      private->input_only = FALSE;
+      private->depth = depth;
+  
+      private->bg_color.pixel = 0; // TODO: BlackPixel (xdisplay, screen_x11->screen_num);
+      private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
+
+      private->bg_pixmap = NULL;
+    }
+  else
+    {
+      depth = 0;
+      private->depth = 0;
+      private->input_only = TRUE;
+    }
+
+  if (private->parent)
+    private->parent->children = g_list_prepend (private->parent->children, window);
+
+  native = FALSE; /* Default */
+  if (GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
+    native = TRUE; /* Always use native windows for toplevels */
+
+  if (private->window_type == GDK_WINDOW_OFFSCREEN)
+    {
+      _gdk_offscreen_window_new (window, screen, visual, attributes, attributes_mask);
+    }
+  else if (native)
+    {
+      if (GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
+	event_mask =
+	  GDK_EXPOSURE_MASK |
+	  GDK_POINTER_MOTION_MASK |
+	  GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
+	  GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK |
+	  GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
+	  GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK |
+	  GDK_PROXIMITY_IN_MASK | GDK_PROXIMITY_OUT_MASK | GDK_SCROLL_MASK;
+      else
+	event_mask = GDK_EXPOSURE_MASK;
+      
+      /* Create the impl */
+      _gdk_window_impl_new (window, screen, visual, event_mask, attributes, attributes_mask);
+    }
+  else
     {
-      parent_private = GDK_WINDOW_OBJECT (parent);
-      private = GDK_WINDOW_OBJECT (window);
-      private->redirect = parent_private->redirect;
+      private->impl = private->parent->impl;
     }
+
+  recompute_visible_regions (private, TRUE, FALSE);
   
+  if (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
+    {
+      /* Inherit redirection from parent */
+      private->redirect = private->parent->redirect;
+    }
+    
   return window;
 }
 
+static gboolean
+is_parent_of (GdkWindow *parent,
+              GdkWindow *child)
+{
+  GdkWindow *w;
+
+  w = child;
+  while (w != NULL)
+    {
+      if (w == parent)
+	return TRUE;
+
+      w = gdk_window_get_parent (w);
+    }
+
+  return FALSE;
+}
+
+static void
+change_impl (GdkWindowObject *private,
+	     GdkDrawable *new)
+{
+  GList *l;
+  GdkWindowObject *child;
+  gboolean show;
+  GdkDrawable *old_impl;
+
+  old_impl = private->impl;
+  private->impl = new;
+  
+  for (l = private->children; l != NULL; l = l->next)
+    {
+      child = l->data;
+
+      if (child->impl == old_impl)
+	change_impl (child, new);
+      else
+	{
+	  show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent ((GdkWindow *)child,
+								      (GdkWindow *)private,
+								      child->x, child->y);
+	  if (show)
+	    gdk_window_show_unraised ((GdkWindow *)child);
+	}
+    }
+
+}
+
 /**
  * gdk_window_reparent:
  * @window: a #GdkWindow
@@ -408,19 +867,42 @@ gdk_window_reparent (GdkWindow *window,
 		     gint       y)
 {
   GdkWindowObject *private;
-  gboolean show;
-
+  GdkWindowObject *new_parent_private;
+  GdkWindowObject *old_parent;
+  gboolean show, was_toplevel, was_mapped;
+  
   g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
 
   if (GDK_WINDOW_DESTROYED (window) ||
       (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
-    {
-      return;
-    }
+    return;
 
+  if (!new_parent)
+    new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
+  
   private = (GdkWindowObject *) window;
+  new_parent_private = (GdkWindowObject *)new_parent;
+
+  /* No input-output children of input-only windows */
+  if (new_parent_private->input_only && !private->input_only)
+    return;
+
+  /* Don't create loops in hierarchy */
+  if (is_parent_of (window, new_parent))
+    return;
+  
+  if (private->cairo_surface)
+    {
+      /* This might be wrong in the new parent, e.g. for non-native surfaces.
+	 To make sure we're ok, just wipe it. */
+      cairo_surface_finish (private->cairo_surface);
+      cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
+				   NULL, NULL);
+    }
+  
+  old_parent = private->parent;
 
   /* Break up redirection if inherited */
   if (private->redirect && private->redirect->redirected != private)
@@ -428,8 +910,74 @@ gdk_window_reparent (GdkWindow *window,
       remove_redirect_from_children (private, private->redirect);
       private->redirect = NULL;
     }
+
+  was_toplevel = private->parent == NULL;
+  was_mapped = GDK_WINDOW_IS_MAPPED (window);
+  show = FALSE;
   
-  show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent (window, new_parent, x, y);
+  if (gdk_window_has_impl (private))
+    {
+      /* Native window */
+      show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent (window, new_parent, x, y);
+    }
+  else
+    {
+      if (new_parent_private->window_type == GDK_WINDOW_ROOT)
+	{
+	  /* TODO: We need to convert to a native window here */
+	  g_warning ("Reparenting client side windows to the root window not yet supported");
+	  return;
+	}
+
+      show = was_mapped;
+      gdk_window_hide (window);
+
+      change_impl (private, new_parent_private->impl);
+    }
+
+  /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
+   * the root window
+   */
+  if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
+    {
+      new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
+      new_parent_private = (GdkWindowObject *)new_parent;
+    }
+
+  private->parent = new_parent_private;
+  private->x = x;
+  private->y = y;
+
+  if (private->parent)
+    private->parent->children = g_list_remove (private->parent->children, window);
+  
+  new_parent_private->children = g_list_prepend (new_parent_private->children, window);
+  
+  /* Switch the window type as appropriate */
+
+  switch (GDK_WINDOW_TYPE (new_parent))
+    {
+    case GDK_WINDOW_ROOT:
+    case GDK_WINDOW_FOREIGN:
+      if (private->toplevel_window_type != -1)
+	GDK_WINDOW_TYPE (window) = private->toplevel_window_type;
+      else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
+	GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
+      break;
+    case GDK_WINDOW_OFFSCREEN:
+    case GDK_WINDOW_TOPLEVEL:
+    case GDK_WINDOW_CHILD:
+    case GDK_WINDOW_DIALOG:
+    case GDK_WINDOW_TEMP:
+      if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD)
+	{
+	  /* Save the original window type so we can restore it if the
+	   * window is reparented back to be a toplevel
+	   */
+	  private->toplevel_window_type = GDK_WINDOW_TYPE (window);
+	  GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
+	}
+    }
 
   /* Inherit parent redirect if we don't have our own */
   if (private->parent && private->redirect == NULL)
@@ -438,8 +986,85 @@ gdk_window_reparent (GdkWindow *window,
       apply_redirect_to_children (private, private->redirect);
     }
 
+  recompute_visible_regions (private, TRUE, FALSE);
+  if (old_parent && GDK_WINDOW_TYPE (old_parent) != GDK_WINDOW_ROOT)
+    recompute_visible_regions (old_parent, FALSE, TRUE);
+  
   if (show)
-    gdk_window_show (window);
+    gdk_window_show_unraised (window);
+  else
+    _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
+
+/**
+ * gdk_window_set_has_native:
+ * @window: a #GdkWindow
+ * @has_native: whethe the window should have a native window
+ *
+ * Tries to create or remove a window-system native window for this
+ * GdkWindow. This may fail in some situations. For instance:
+ *
+ * Toplevel and foreign windows must have a native window.
+ * Offscreen window and children of them can never have native windows.
+ * Some backends may not support native child windows.
+ * 
+ **/
+void
+gdk_window_set_has_native (GdkWindow *window, gboolean has_native)
+{
+  GdkWindowObject *private;
+  GdkWindowObject *impl_window;
+  GdkDrawable *new_impl, *old_impl;
+  GdkScreen *screen;
+  GdkVisual *visual;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
+
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
+  private = (GdkWindowObject *) window;
+  
+  if (has_native)
+    {
+      /* Create native window */
+
+      if (gdk_window_has_impl (private))
+	/* Already has an impl, either native (ok) or
+	   offscreen (not supported). Bail. */
+	return; 
+
+      impl_window = gdk_window_get_impl_window (private);
+      if (impl_window->window_type == GDK_WINDOW_OFFSCREEN)
+	return; /* native in offscreens not supported */
+
+      screen = gdk_drawable_get_screen (window);
+      visual = gdk_drawable_get_visual (window);
+
+      old_impl = private->impl;
+      _gdk_window_impl_new (window, screen, visual, GDK_EXPOSURE_MASK, NULL, 0);
+      new_impl = private->impl;
+      
+      private->impl = old_impl;
+      change_impl (private, new_impl);
+    }
+  else
+    {
+      /* Remove native window */
+
+      if (!gdk_window_has_impl (private))
+	return;  /* Not native, can't remove */
+
+      if (private->window_type == GDK_WINDOW_OFFSCREEN)
+	return; /* Not native, can't remove */
+      
+      if (private->parent == NULL ||
+	  GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
+	return; /* toplevel, must be native */
+      
+      /* TODO: remove native */
+    }
 }
 
 static void
@@ -513,6 +1138,7 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
     case GDK_WINDOW_DIALOG:
     case GDK_WINDOW_TEMP:
     case GDK_WINDOW_FOREIGN:
+    case GDK_WINDOW_OFFSCREEN:
       if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN && !foreign_destroy)
 	{
 	  /* Logically, it probably makes more sense to send
@@ -533,8 +1159,6 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
 	}
       else
 	{
-	  private->state |= GDK_WINDOW_STATE_WITHDRAWN;
-	  
 	  if (private->parent)
 	    {
 	      GdkWindowObject *parent_private = (GdkWindowObject *)private->parent;
@@ -542,7 +1166,6 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
 		parent_private->children = g_list_remove (parent_private->children, window);
 	    }
 
-	  _gdk_window_clear_update_area (window);
 	  gdk_window_free_paint_stack (window);
 	  
 	  if (private->bg_pixmap &&
@@ -573,8 +1196,32 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
 	      
 	      g_list_free (children);
 	    }
+
+	  _gdk_window_clear_update_area (window); 
 	  
-	  _gdk_windowing_window_destroy (window, recursing, foreign_destroy);
+	  if (private->cairo_surface)
+	    {
+	      cairo_surface_finish (private->cairo_surface);
+	      cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
+					   NULL, NULL);
+	    }
+
+	  if (gdk_window_has_impl (private))
+	    {
+	      if (gdk_window_is_offscreen (private))
+		_gdk_offscreen_window_destroy (window, recursing);
+	      else
+		_gdk_windowing_window_destroy (window, recursing, foreign_destroy);
+	    }
+	  else
+	    {
+	      /* hide to make sure we repaint and break grabs */
+	      gdk_window_hide (window);
+	      /* NULL out impl so we don't double free it on finalize */
+	      private->impl = NULL;
+	    }
+
+	  private->state |= GDK_WINDOW_STATE_WITHDRAWN;
 	  private->parent = NULL;
 	  private->destroyed = TRUE;
 
@@ -1036,6 +1683,119 @@ gdk_window_get_state (GdkWindow *window)
   return private->state;
 }
 
+
+/* This creates an empty "implicit" paint region for the impl window.
+ * By itself this does nothing, but real paints to this window
+ * or children of it can use this pixmap as backing to avoid allocating
+ * multiple pixmaps for subwindow rendering. When doing so they
+ * add to the region of the implicit paint region, which will be
+ * pushed to the window when the implicit paint region is ended.
+ * Such paints should not copy anything to the window on paint end, but
+ * should rely on the implicit paint end.
+ * The implicit paint will be automatically ended if someone draws
+ * directly to the window or a child window.
+ */
+static gboolean
+gdk_window_begin_implicit_paint (GdkWindow *window, GdkRectangle *rect)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowPaint *paint;
+
+  g_assert (gdk_window_has_impl (private));
+
+  if (GDK_IS_PAINTABLE (private->impl))
+    return FALSE; /* Implementation does double buffering */
+  
+  if (private->paint_stack != NULL ||
+      private->implicit_paint != NULL)
+    return FALSE; /* Don't stack implicit paints */
+
+  paint = g_new (GdkWindowPaint, 1);
+  paint->region = gdk_region_new (); /* Empty */
+  paint->x_offset = rect->x;
+  paint->y_offset = rect->y;
+  paint->uses_implicit = FALSE;
+  paint->surface = NULL;
+  paint->pixmap =
+    gdk_pixmap_new (window,
+		    MAX (rect->width, 1), MAX (rect->height, 1), -1);
+
+  private->implicit_paint = paint;
+  
+  return TRUE;
+}
+
+/* Ensure that all content related to this (sub)window is pushed to the
+   native region */
+static void
+gdk_window_flush_implicit_paint (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *impl_window;
+  GdkWindowPaint *paint;
+  GdkRegion *region;
+  GdkGC *tmp_gc;
+
+  /* Ensure that there is no explicit paint region. */
+  g_assert (private->paint_stack == NULL);
+  
+  impl_window = gdk_window_get_impl_window (private);
+  if (impl_window->implicit_paint == NULL)
+    return;
+
+  paint = impl_window->implicit_paint;
+  region = gdk_region_copy (private->clip_region_with_children);
+  gdk_region_offset (region, private->abs_x, private->abs_y);
+  gdk_region_intersect (region, paint->region);
+  
+  if (!gdk_region_empty (region))
+    {
+      /* Some regions are valid, push these to window now */
+      tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
+      _gdk_gc_set_clip_region_internal (tmp_gc, region, TRUE);
+      gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
+			 0, 0, paint->x_offset, paint->y_offset, -1, -1);
+      /* Reset clip region of the cached GdkGC */
+      gdk_gc_set_clip_region (tmp_gc, NULL);
+
+      /* Remove flushed region from the implicit paint */
+      gdk_region_subtract (paint->region, region);
+    }
+  else
+    gdk_region_destroy (region);
+}
+
+/* Ends an implicit paint, paired with gdk_window_begin_implicit_paint returning TRUE */
+static void
+gdk_window_end_implicit_paint (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowPaint *paint;
+  GdkGC *tmp_gc;
+
+  g_assert (gdk_window_has_impl (private));
+
+  g_assert (private->implicit_paint != NULL);
+
+  paint = private->implicit_paint;
+
+  private->implicit_paint = NULL;
+  
+  if (!gdk_region_empty (paint->region))
+    {
+      /* Some regions are valid, push these to window now */
+      tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
+      _gdk_gc_set_clip_region_internal (tmp_gc, paint->region, TRUE);
+      gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
+			 0, 0, paint->x_offset, paint->y_offset, -1, -1);
+      /* Reset clip region of the cached GdkGC */
+      gdk_gc_set_clip_region (tmp_gc, NULL);
+    }
+  
+  g_object_unref (paint->pixmap);
+  g_free (paint);
+}
+
 /**
  * gdk_window_begin_paint_rect:
  * @window: a #GdkWindow
@@ -1115,7 +1875,8 @@ gdk_window_begin_paint_region (GdkWindow       *window,
 #ifdef USE_BACKING_STORE
   GdkWindowObject *private = (GdkWindowObject *)window;
   GdkRectangle clip_box;
-  GdkWindowPaint *paint;
+  GdkWindowPaint *paint, *implicit_paint;
+  GdkWindowObject *impl_window;
   GSList *list;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
@@ -1129,24 +1890,59 @@ gdk_window_begin_paint_region (GdkWindow       *window,
 
       if (iface->begin_paint_region)
         iface->begin_paint_region ((GdkPaintable*)private->impl, region);
-
+      
       return;
     }
 
   gdk_region_get_clipbox (region, &clip_box);
 
+  impl_window = gdk_window_get_impl_window (private);
+  implicit_paint = impl_window->implicit_paint;
+
   paint = g_new (GdkWindowPaint, 1);
-  paint->region = gdk_region_copy (region);
-  paint->x_offset = clip_box.x;
-  paint->y_offset = clip_box.y;
-  paint->pixmap =
-    gdk_pixmap_new (window,
-		    MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1);
+  if (implicit_paint)
+    {
+      int width, height;
 
-  paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap);
-  cairo_surface_set_device_offset (paint->surface,
-				   - paint->x_offset, - paint->y_offset);
+      paint->uses_implicit = TRUE;
+      paint->pixmap = g_object_ref (implicit_paint->pixmap);
+      paint->x_offset = -private->abs_x + implicit_paint->x_offset;
+      paint->y_offset = -private->abs_y + implicit_paint->y_offset;
+      paint->region = gdk_region_copy (region);
+      gdk_region_intersect (paint->region, private->clip_region_with_children);
+
+      /* It would be nice if we had some cairo support here so we
+	 could set the clip rect on the cairo surface */
+      width = private->abs_x + private->width;
+      height = private->abs_y + private->height;
+      
+      paint->surface = _gdk_windowing_create_cairo_surface (((GdkPixmapObject *)paint->pixmap)->impl,
+							    width, height);
+      if (paint->surface)
+	cairo_surface_set_device_offset (paint->surface,
+					 - paint->x_offset, - paint->y_offset);
+
+      /* Mark the region as valid on the implicit paint */
+      gdk_region_offset (paint->region, private->abs_x, private->abs_y); 
+      gdk_region_union (implicit_paint->region, paint->region);
+      gdk_region_offset (paint->region, -private->abs_x, -private->abs_y); 
+    }
+  else
+    {
+      paint->uses_implicit = FALSE;
+      paint->region = gdk_region_copy (region);
+      paint->x_offset = clip_box.x;
+      paint->y_offset = clip_box.y;
+      paint->pixmap =
+	gdk_pixmap_new (window,
+			MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1);
+
+      paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap);
+      cairo_surface_set_device_offset (paint->surface,
+				       - paint->x_offset, - paint->y_offset);
+    }
   
+      
   for (list = private->paint_stack; list != NULL; list = list->next)
     {
       GdkWindowPaint *tmp_paint = list->data;
@@ -1156,7 +1952,7 @@ gdk_window_begin_paint_region (GdkWindow       *window,
   
   private->paint_stack = g_slist_prepend (private->paint_stack, paint);
 
-  if (!gdk_region_empty (region))
+  if (!gdk_region_empty (paint->region))
     {
       gdk_window_clear_backing_rect (window,
 				     clip_box.x, clip_box.y,
@@ -1165,6 +1961,55 @@ gdk_window_begin_paint_region (GdkWindow       *window,
 #endif /* USE_BACKING_STORE */
 }
 
+static void
+setup_redirect_clip (GdkWindow      *window,
+		     GdkGC          *gc,
+		     int            *x_offset_out,
+		     int            *y_offset_out)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkRegion *visible_region;
+  GdkRectangle dest_rect;
+  GdkRegion *tmpreg;
+  GdkWindow *toplevel;
+  int x_offset, y_offset;
+
+  toplevel = GDK_WINDOW (private->redirect->redirected);
+  
+  /* Get the clip region for gc clip rect + window hierarchy in
+     window relative coords */
+  visible_region =
+    _gdk_window_calculate_full_clip_region (window, toplevel,
+					    TRUE,
+					    &x_offset, 
+					    &y_offset);
+
+  /* Compensate for the source pos/size */
+  x_offset -= private->redirect->src_x;
+  y_offset -= private->redirect->src_y;
+  dest_rect.x = -x_offset;
+  dest_rect.y = -y_offset;
+  dest_rect.width = private->redirect->width;
+  dest_rect.height = private->redirect->height;
+  tmpreg = gdk_region_rectangle (&dest_rect);
+  gdk_region_intersect (visible_region, tmpreg);
+  gdk_region_destroy (tmpreg);
+
+  /* Compensate for the dest pos */
+  x_offset += private->redirect->dest_x;
+  y_offset += private->redirect->dest_y;
+
+  gdk_gc_set_clip_region (gc, visible_region); /* This resets clip origin! */
+
+  /* offset clip and tiles from window coords to pixmaps coords */
+  gdk_gc_offset (gc, -x_offset, -y_offset);
+
+  gdk_region_destroy (visible_region);
+
+  *x_offset_out = x_offset;
+  *y_offset_out = y_offset;
+}
+
 /**
  * gdk_window_end_paint:
  * @window: a #GdkWindow
@@ -1188,6 +2033,7 @@ gdk_window_end_paint (GdkWindow *window)
   GdkGC *tmp_gc;
   GdkRectangle clip_box;
   gint x_offset, y_offset;
+  GdkRegion *full_clip;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
@@ -1210,36 +2056,42 @@ gdk_window_end_paint (GdkWindow *window)
     }
 
   paint = private->paint_stack->data;
+
   private->paint_stack = g_slist_delete_link (private->paint_stack, 
-                                              private->paint_stack);
+					      private->paint_stack);
 
   gdk_region_get_clipbox (paint->region, &clip_box);
 
   tmp_gc = _gdk_drawable_get_scratch_gc (window, FALSE);
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (window, &x_offset, &y_offset);
-
-  gdk_gc_set_clip_region (tmp_gc, paint->region);
-  gdk_gc_set_clip_origin (tmp_gc, - x_offset, - y_offset);
-
-  gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
-                     clip_box.x - paint->x_offset,
-                     clip_box.y - paint->y_offset,
-                     clip_box.x - x_offset, clip_box.y - y_offset,
-                     clip_box.width, clip_box.height);
+  x_offset = -private->abs_x;
+  y_offset = -private->abs_y;
 
+  if (!paint->uses_implicit)
+    {
+      full_clip = gdk_region_copy (private->clip_region_with_children);
+      gdk_region_intersect (full_clip, paint->region);
+      _gdk_gc_set_clip_region_internal (tmp_gc, full_clip, TRUE); /* Takes ownership of full_clip */
+      gdk_gc_set_clip_origin (tmp_gc, - x_offset, - y_offset);
+      gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
+			 clip_box.x - paint->x_offset,
+			 clip_box.y - paint->y_offset,
+			 clip_box.x - x_offset, clip_box.y - y_offset,
+			 clip_box.width, clip_box.height);
+    }
+  
   if (private->redirect)
     {
-      GdkWindowClipData data;
-      
-      setup_redirect_clip (window, tmp_gc, &data);
+      int x_offset, y_offset;
+
+      /* TODO: Should also use paint->region for clipping */
+      setup_redirect_clip (window, tmp_gc, &x_offset, &y_offset);
       gdk_draw_drawable (private->redirect->pixmap, tmp_gc, paint->pixmap,
 			 clip_box.x - paint->x_offset,
 			 clip_box.y - paint->y_offset,
-			 clip_box.x + data.x_offset,
-			 clip_box.y + data.y_offset,
+			 clip_box.x + x_offset,
+			 clip_box.y + y_offset,
 			 clip_box.width, clip_box.height);
-      reset_redirect_clip (window, tmp_gc, &data);
     }
   
   /* Reset clip region of the cached GdkGC */
@@ -1321,7 +2173,10 @@ gdk_window_get_offsets (GdkWindow *window,
       *y_offset = paint->y_offset;
     }
   else
-    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (window, x_offset, y_offset);
+    {
+      *x_offset = -private->abs_x;
+      *y_offset = -private->abs_y;
+    }
 }
 
 /**
@@ -1380,6 +2235,48 @@ gdk_window_get_internal_paint_info (GdkWindow    *window,
     *y_offset = y_off;
 }
 
+static void
+setup_clip_for_draw (GdkDrawable *drawable,
+		     GdkGC *gc,
+		     int old_clip_x, int old_clip_y,
+		     GdkRegion **old_clip_region)
+{
+  GdkWindowObject *private = (GdkWindowObject *)drawable;
+  GdkRegion *clip;
+
+  if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
+    clip = gdk_region_copy (private->clip_region_with_children);
+  else
+    clip = gdk_region_copy (private->clip_region);
+    
+  /* There was a clip origin set appart from the window offset,
+     need to take this into consideration */
+  if (old_clip_x != 0 || old_clip_y != 0)
+    gdk_region_offset (clip, -old_clip_x, -old_clip_y);
+
+  _gdk_gc_intersect_clip_region (gc, clip, old_clip_region);
+}
+
+static void
+setup_clip_for_paint (GdkDrawable *drawable,
+		      GdkWindowPaint *paint,
+		      GdkGC *gc,
+		      int old_clip_x, int old_clip_y,
+		      GdkRegion **old_clip_region)
+{
+  GdkRegion *clip;
+
+  clip = gdk_region_copy (paint->region);
+  
+  /* There was a clip origin set appart from the window offset,
+     need to take this into consideration */
+  if (old_clip_x != 0 || old_clip_y != 0)
+    gdk_region_offset (clip, -old_clip_x, -old_clip_y);
+
+  _gdk_gc_intersect_clip_region (gc, clip, old_clip_region);
+}
+
+
 #define OFFSET_GC(gc)                                         \
     gint x_offset, y_offset; 				      \
     gint old_clip_x = gc->clip_x_origin;    \
@@ -1402,6 +2299,25 @@ gdk_window_get_internal_paint_info (GdkWindow    *window,
        gdk_gc_set_ts_origin (gc, old_ts_x, old_ts_y);       \
      }
 
+#define SETUP_PAINT_GC_CLIP(gc)                             \
+      GdkRegion *old_clip_region;                           \
+      if (paint->uses_implicit)        			    \
+	setup_clip_for_paint (drawable, paint, gc, old_clip_x,	\
+                              old_clip_y, &old_clip_region);
+
+#define RESTORE_PAINT_GC_CLIP(gc)                          \
+      if (paint->uses_implicit)    			   \
+        _gdk_gc_set_clip_region_internal (gc, old_clip_region, FALSE);
+
+
+#define SETUP_DIRECT_GC_CLIP(gc)                            \
+      GdkRegion *old_clip_region;                           \
+      gdk_window_flush_implicit_paint ((GdkWindow *)drawable);\
+      setup_clip_for_draw (drawable, gc, old_clip_x, old_clip_y, &old_clip_region);
+
+#define RESTORE_DIRECT_GC_CLIP(gc)                                 \
+      _gdk_gc_set_clip_region_internal (gc, old_clip_region, FALSE);
+
 static GdkGC *
 gdk_window_create_gc (GdkDrawable     *drawable,
                       GdkGCValues     *values,
@@ -1434,12 +2350,18 @@ gdk_window_draw_rectangle (GdkDrawable *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
+      SETUP_PAINT_GC_CLIP (gc);
       gdk_draw_rectangle (paint->pixmap, gc, filled,
                           x - x_offset, y - y_offset, width, height);
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_rectangle (private->impl, gc, filled,
-                        x - x_offset, y - y_offset, width, height);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_rectangle (private->impl, gc, filled,
+			  x - x_offset, y - y_offset, width, height);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
 
   RESTORE_GC (gc);
 }
@@ -1464,14 +2386,20 @@ gdk_window_draw_arc (GdkDrawable *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
+      SETUP_PAINT_GC_CLIP (gc);
       gdk_draw_arc (paint->pixmap, gc, filled,
 		    x - x_offset, y - y_offset,
 		    width, height, angle1, angle2);
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_arc (private->impl, gc, filled,
-                  x - x_offset, y - y_offset,
-                  width, height, angle1, angle2);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_arc (private->impl, gc, filled,
+		    x - x_offset, y - y_offset,
+		    width, height, angle1, angle2);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
   RESTORE_GC (gc);
 }
 
@@ -1507,11 +2435,16 @@ gdk_window_draw_polygon (GdkDrawable *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
+      SETUP_PAINT_GC_CLIP (gc);
       gdk_draw_polygon (paint->pixmap, gc, filled, new_points, npoints);
-
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_polygon (private->impl, gc, filled, new_points, npoints);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_polygon (private->impl, gc, filled, new_points, npoints);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
   
   if (new_points != points)
     g_free (new_points);
@@ -1537,13 +2470,19 @@ gdk_window_draw_text (GdkDrawable *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
+      SETUP_PAINT_GC_CLIP (gc);
       gdk_draw_text (paint->pixmap, font, gc, 
 		     x - x_offset, y - y_offset, text, text_length);
 
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_text (private->impl, font, gc,
-                   x - x_offset, y - y_offset, text, text_length);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_text (private->impl, font, gc,
+		     x - x_offset, y - y_offset, text, text_length);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
 
   RESTORE_GC (gc);
 }
@@ -1566,17 +2505,36 @@ gdk_window_draw_text_wc (GdkDrawable    *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
+      SETUP_PAINT_GC_CLIP (gc);
       gdk_draw_text_wc (paint->pixmap, font, gc, 
 			x - x_offset, y - y_offset, text, text_length);
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_text_wc (private->impl, font, gc,
-                      x - x_offset, y - y_offset, text, text_length);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_text_wc (private->impl, font, gc,
+			x - x_offset, y - y_offset, text, text_length);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
   
   RESTORE_GC (gc);
 }
 
-static GdkDrawable*
+static GdkDrawable *
+gdk_window_get_source_drawable (GdkDrawable *drawable)
+{
+  GdkWindow *window = GDK_WINDOW (drawable);
+  GdkWindowObject *private;
+
+  private = (GdkWindowObject *) window;
+  if (GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable)
+    return GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable (private->impl);
+  
+  return drawable;
+}
+
+static GdkDrawable *
 gdk_window_get_composite_drawable (GdkDrawable *drawable,
                                    gint         x,
                                    gint         y,
@@ -1591,19 +2549,17 @@ gdk_window_get_composite_drawable (GdkDrawable *drawable,
   GdkRectangle rect;
   GdkGC *tmp_gc;
   gboolean overlap_buffer;
+  GdkDrawable *source;
+  GdkWindowObject *impl_window;
+  GdkWindowPaint *implicit_paint;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (GDK_WINDOW (drawable),
-                                                          composite_x_offset,
-                                                          composite_y_offset);
-  
-  if ((GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable))
-      || private->paint_stack == NULL)
-    {
-      /* No backing store */
-      return g_object_ref (drawable);
-    }
+  *composite_x_offset = -private->abs_x;
+  *composite_y_offset = -private->abs_y;
+
+  if ((GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable)))
+    return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
 
-  /* See if the buffered part is overlapping the part we want
+  /* See if any buffered part is overlapping the part we want
    * to get
    */
   rect.x = x;
@@ -1612,14 +2568,14 @@ gdk_window_get_composite_drawable (GdkDrawable *drawable,
   rect.height = height;
 
   overlap_buffer = FALSE;
-  
+
   for (list = private->paint_stack; list != NULL; list = list->next)
     {
       GdkWindowPaint *paint = list->data;
       GdkOverlapType overlap;
-
+      
       overlap = gdk_region_rect_in (paint->region, &rect);
-
+      
       if (overlap == GDK_OVERLAP_RECTANGLE_IN)
 	{
 	  *composite_x_offset = paint->x_offset;
@@ -1634,26 +2590,65 @@ gdk_window_get_composite_drawable (GdkDrawable *drawable,
 	}
     }
 
-  if (!overlap_buffer)
-    return g_object_ref (drawable);
+  impl_window = gdk_window_get_impl_window (private);
+  implicit_paint = impl_window->implicit_paint;
+  if (implicit_paint)
+    {
+      GdkOverlapType overlap;
 
+      rect.x += private->abs_x;
+      rect.y += private->abs_y;
+      
+      overlap = gdk_region_rect_in (implicit_paint->region, &rect);
+      if (overlap == GDK_OVERLAP_RECTANGLE_IN)
+	{
+	  *composite_x_offset = -private->abs_x + implicit_paint->x_offset;
+	  *composite_y_offset = -private->abs_y + implicit_paint->y_offset;
+	  
+	  return g_object_ref (implicit_paint->pixmap);
+	}
+      else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
+	overlap_buffer = TRUE;
+    }
+
+  if (!overlap_buffer)
+    return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
+  
   tmp_pixmap = gdk_pixmap_new (drawable, width, height, -1);
   tmp_gc = _gdk_drawable_get_scratch_gc (tmp_pixmap, FALSE);
 
+  source = _gdk_drawable_get_source_drawable (drawable);
+  
   /* Copy the current window contents */
   gdk_draw_drawable (tmp_pixmap,
                      tmp_gc,
-                     private->impl,
+                     GDK_WINDOW_OBJECT (source)->impl,
                      x - *composite_x_offset,
                      y - *composite_y_offset,
                      0, 0,
                      width, height);
 
   /* paint the backing stores */
+  if (implicit_paint)
+    {
+      GdkWindowPaint *paint = list->data;
+      
+      gdk_gc_set_clip_region (tmp_gc, paint->region);
+      gdk_gc_set_clip_origin (tmp_gc, -x  - paint->x_offset, -y  - paint->y_offset);
+      
+      gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
+			 x - paint->x_offset,
+			 y - paint->y_offset,
+			 0, 0, width, height);
+    }
+  
   for (list = private->paint_stack; list != NULL; list = list->next)
     {
       GdkWindowPaint *paint = list->data;
 
+      if (paint->uses_implicit)
+	continue; /* We already copied this above */
+      
       gdk_gc_set_clip_region (tmp_gc, paint->region);
       gdk_gc_set_clip_origin (tmp_gc, -x, -y);
       
@@ -1662,7 +2657,7 @@ gdk_window_get_composite_drawable (GdkDrawable *drawable,
 			 y - paint->y_offset,
 			 0, 0, width, height);
     }
-
+  
   /* Reset clip region of the cached GdkGC */
   gdk_gc_set_clip_region (tmp_gc, NULL);
 
@@ -1679,7 +2674,7 @@ gdk_window_get_clip_region (GdkDrawable *drawable)
   GdkWindowObject *private = (GdkWindowObject *)drawable;
   GdkRegion *result;
 
-  result = gdk_drawable_get_clip_region (private->impl);
+  result = gdk_region_copy (private->clip_region);
 
   if (private->paint_stack)
     {
@@ -1706,8 +2701,8 @@ static GdkRegion*
 gdk_window_get_visible_region (GdkDrawable *drawable)
 {
   GdkWindowObject *private = (GdkWindowObject*) drawable;
-  
-  return gdk_drawable_get_visible_region (private->impl);
+
+  return gdk_region_copy (private->clip_region);
 }
 
 static void
@@ -1731,16 +2726,22 @@ gdk_window_draw_drawable (GdkDrawable *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
+      SETUP_PAINT_GC_CLIP (gc);
       gdk_draw_drawable (paint->pixmap, gc,
                          src, xsrc, ysrc,
 			 xdest - x_offset, ydest - y_offset, width, height);
 
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_drawable (private->impl, gc,
-                       src, xsrc, ysrc,
-                       xdest - x_offset, ydest - y_offset,
-                       width, height);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_drawable (private->impl, gc,
+			 src, xsrc, ysrc,
+			 xdest - x_offset, ydest - y_offset,
+			 width, height);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
 
   RESTORE_GC (gc);
 }
@@ -1776,10 +2777,16 @@ gdk_window_draw_points (GdkDrawable *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
+      SETUP_PAINT_GC_CLIP (gc);
       gdk_draw_points (paint->pixmap, gc, new_points, npoints);
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_points (private->impl, gc, points, npoints);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_points (private->impl, gc, points, npoints);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
 
   if (new_points != points)
     g_free (new_points);
@@ -1820,10 +2827,16 @@ gdk_window_draw_segments (GdkDrawable *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
+      SETUP_PAINT_GC_CLIP (gc);
       gdk_draw_segments (paint->pixmap, gc, new_segs, nsegs);
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_segments (private->impl, gc, new_segs, nsegs);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_segments (private->impl, gc, new_segs, nsegs);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
   
   if (new_segs != segs)
     g_free (new_segs);
@@ -1862,10 +2875,16 @@ gdk_window_draw_lines (GdkDrawable *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
+      SETUP_PAINT_GC_CLIP (gc);
       gdk_draw_lines (paint->pixmap, gc, new_points, npoints);
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_lines (private->impl, gc, new_points, npoints);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_lines (private->impl, gc, new_points, npoints);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
 
   if (new_points != points)
     g_free (new_points);
@@ -1892,11 +2911,17 @@ gdk_window_draw_glyphs (GdkDrawable      *drawable,
     {
       GdkWindowPaint *paint = private->paint_stack->data;
 
+      SETUP_PAINT_GC_CLIP (gc);
       gdk_draw_glyphs (paint->pixmap, gc, font, x - x_offset, y - y_offset, glyphs);
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_glyphs (private->impl, gc, font,
-                     x - x_offset, y - y_offset, glyphs);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_glyphs (private->impl, gc, font,
+		       x - x_offset, y - y_offset, glyphs);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
 
   RESTORE_GC (gc);
 }
@@ -1947,10 +2972,16 @@ gdk_window_draw_glyphs_transformed (GdkDrawable      *drawable,
     {
       GdkWindowPaint *paint = private->paint_stack->data;
 
+      SETUP_PAINT_GC_CLIP (gc);
       gdk_draw_glyphs_transformed (paint->pixmap, gc, matrix, font, x, y, glyphs);
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_glyphs_transformed (private->impl, gc, matrix, font, x, y, glyphs);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_glyphs_transformed (private->impl, gc, matrix, font, x, y, glyphs);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
 
   RESTORE_GC (gc);
 }
@@ -2116,16 +3147,16 @@ gdk_window_clear_backing_rect_redirect (GdkWindow *window,
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
+  clip_region = _gdk_window_calculate_full_clip_region (window,
+							GDK_WINDOW (redirect->redirected),
+							TRUE,
+							&x_offset, &y_offset);
+  
   paint.x_offset = x_offset;
   paint.y_offset = y_offset;
   paint.pixmap = redirect->pixmap;
   paint.surface = _gdk_drawable_ref_cairo_surface (redirect->pixmap);
   
-  clip_region = _gdk_window_calculate_full_clip_region (window,
-							GDK_WINDOW (redirect->redirected),
-							NULL, TRUE,
-							&x_offset, &y_offset);
-  
   method.cr = NULL;
   method.gc = NULL;
   setup_backing_rect_method (&method, window, &paint, 0, 0);
@@ -2156,6 +3187,54 @@ gdk_window_clear_backing_rect_redirect (GdkWindow *window,
   cairo_surface_destroy (paint.surface);
 }
 
+static void
+gdk_window_clear_backing_rect_direct (GdkWindow *window,
+				      gint       x,
+				      gint       y,
+				      gint       width,
+				      gint       height)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  BackingRectMethod method;
+  GdkWindowPaint paint;
+  
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
+  paint.x_offset = 0;
+  paint.y_offset = 0;
+  paint.pixmap = window;
+  paint.surface = _gdk_drawable_ref_cairo_surface (window);
+  
+  method.cr = NULL;
+  method.gc = NULL;
+  setup_backing_rect_method (&method, window, &paint, 0, 0);
+
+  if (method.cr)
+    {
+      g_assert (method.gc == NULL);
+
+      gdk_cairo_region (method.cr, private->clip_region_with_children);
+      cairo_clip (method.cr);
+      
+      cairo_rectangle (method.cr, x, y, width, height);
+      cairo_fill (method.cr);
+
+      cairo_destroy (method.cr);
+    }
+  else
+    {
+      g_assert (method.gc != NULL);
+
+      gdk_gc_set_clip_region (method.gc, private->clip_region_with_children);
+      gdk_draw_rectangle (window, method.gc, TRUE, x, y, width, height);
+      g_object_unref (method.gc);
+
+    }
+
+  cairo_surface_destroy (paint.surface);
+}
+
 
 /**
  * gdk_window_clear:
@@ -2176,6 +3255,43 @@ gdk_window_clear (GdkWindow *window)
                          width, height);
 }
 
+static void
+gdk_window_clear_area_internal (GdkWindow *window,
+				gint       x,
+				gint       y,
+				gint       width,
+				gint       height,
+				gboolean   send_expose)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  if (private->paint_stack)
+    gdk_window_clear_backing_rect (window, x, y, width, height);
+  else
+    {
+      if (private->redirect)
+	gdk_window_clear_backing_rect_redirect (window, x, y, width, height);
+
+      
+      
+      gdk_window_clear_backing_rect_direct (window, x, y, width, height);
+      if (send_expose)
+	{
+	  GdkRectangle rect;
+
+	  rect.x = x;
+	  rect.y = x;
+	  rect.width = width;
+	  rect.height = height;
+	  
+	  gdk_window_invalidate_rect (window, &rect, FALSE);
+	}
+    }
+}
+
+
 /**
  * gdk_window_clear_area:
  * @window: a #GdkWindow
@@ -2194,22 +3310,10 @@ gdk_window_clear_area (GdkWindow *window,
 		       gint       width,
 		       gint       height)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (private->paint_stack)
-    gdk_window_clear_backing_rect (window, x, y, width, height);
-  else
-    {
-      if (private->redirect)
-	gdk_window_clear_backing_rect_redirect (window, x, y, width, height);
-
-      GDK_WINDOW_IMPL_GET_IFACE (private->impl)->clear_area (window,
-                                                             x, y,
-                                                             width, height,
-                                                             FALSE);
-    }
+  gdk_window_clear_area_internal (window,
+				  x, y,
+				  width, height,
+				  FALSE);
 }
 
 /**
@@ -2234,20 +3338,10 @@ gdk_window_clear_area_e (GdkWindow *window,
 		         gint       width,
 		         gint       height)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (private->paint_stack)
-    gdk_window_clear_backing_rect (window, x, y, width, height);
-
-  if (private->redirect)
-    gdk_window_clear_backing_rect_redirect (window, x, y, width, height);
-
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->clear_area (window,
-                                                         x, y,
-                                                         width, height,
-                                                         TRUE);
+  gdk_window_clear_area_internal (window,
+				  x, y,
+				  width, height,
+				  TRUE);
 }
 
 static void
@@ -2271,15 +3365,21 @@ gdk_window_draw_image (GdkDrawable *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
+      SETUP_PAINT_GC_CLIP (gc);
       gdk_draw_image (paint->pixmap, gc, image, xsrc, ysrc,
                       xdest - x_offset, ydest - y_offset,
                       width, height);
 
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_image (private->impl, gc, image, xsrc, ysrc,
-                    xdest - x_offset, ydest - y_offset,
-                    width, height);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_image (private->impl, gc, image, xsrc, ysrc,
+		      xdest - x_offset, ydest - y_offset,
+		      width, height);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
 
   RESTORE_GC (gc);
 }
@@ -2310,16 +3410,22 @@ gdk_window_draw_pixbuf (GdkDrawable     *drawable,
       if (private->paint_stack)
 	{
 	  GdkWindowPaint *paint = private->paint_stack->data;
+	  SETUP_PAINT_GC_CLIP (gc);
 	  gdk_draw_pixbuf (paint->pixmap, gc, pixbuf, src_x, src_y,
 			   dest_x - x_offset, dest_y - y_offset,
 			   width, height,
 			   dither, x_dither - x_offset, y_dither - y_offset);
+	  RESTORE_PAINT_GC_CLIP (gc);
 	}
       else
-	gdk_draw_pixbuf (private->impl, gc, pixbuf, src_x, src_y,
-			 dest_x - x_offset, dest_y - y_offset,
-			 width, height,
-			 dither, x_dither, y_dither);
+	{
+	  SETUP_DIRECT_GC_CLIP(gc);
+	  gdk_draw_pixbuf (private->impl, gc, pixbuf, src_x, src_y,
+			   dest_x - x_offset, dest_y - y_offset,
+			   width, height,
+			   dither, x_dither, y_dither);
+	  RESTORE_DIRECT_GC_CLIP(gc);
+	}
       
       RESTORE_GC (gc);
     }
@@ -2331,16 +3437,20 @@ gdk_window_draw_pixbuf (GdkDrawable     *drawable,
       if (private->paint_stack)
 	{
 	  GdkWindowPaint *paint = private->paint_stack->data;
+	  /* TODO: Do paint clipping here... */
 	  gdk_draw_pixbuf (paint->pixmap, gc, pixbuf, src_x, src_y,
 			   dest_x - x_offset, dest_y - y_offset,
 			   width, height,
 			    dither, x_dither - x_offset, y_dither - y_offset);
 	}
       else
-	gdk_draw_pixbuf (private->impl, gc, pixbuf, src_x, src_y,
-			 dest_x - x_offset, dest_y - y_offset,
-			 width, height,
-			 dither, x_dither, y_dither);
+	{
+	  /* TODO: No GC passed in, but still want clipping here... */
+	  gdk_draw_pixbuf (private->impl, gc, pixbuf, src_x, src_y,
+			   dest_x - x_offset, dest_y - y_offset,
+			   width, height,
+			   dither, x_dither, y_dither);
+	}
     }
 }
 
@@ -2379,10 +3489,16 @@ gdk_window_draw_trapezoids (GdkDrawable   *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
+      SETUP_PAINT_GC_CLIP (gc);
       gdk_draw_trapezoids (paint->pixmap, gc, trapezoids, n_trapezoids);
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_trapezoids (private->impl, gc, trapezoids, n_trapezoids);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_trapezoids (private->impl, gc, trapezoids, n_trapezoids);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
   
   g_free (new_trapezoids);
 
@@ -2394,10 +3510,12 @@ gdk_window_real_get_size (GdkDrawable *drawable,
                           gint *width,
                           gint *height)
 {
-  g_return_if_fail (GDK_IS_WINDOW (drawable));
+  GdkWindowObject *private = (GdkWindowObject *)drawable;
 
-  gdk_drawable_get_size (GDK_WINDOW_OBJECT (drawable)->impl,
-                         width, height);
+  if (width)
+    *width = private->width;
+  if (height)
+    *height = private->height;
 }
 
 static GdkVisual*
@@ -2469,9 +3587,10 @@ gdk_window_copy_to_image (GdkDrawable     *drawable,
   /* If we're here, a composite image was not necessary, so
    * we can ignore the paint stack.
    */
-  
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (drawable,
-                                                          &x_offset, &y_offset);
+
+  /* TODO: Is this right? */
+  x_offset = 0;
+  y_offset = 0; 
   
   return gdk_drawable_copy_to_image (private->impl,
 				     image,
@@ -2481,6 +3600,14 @@ gdk_window_copy_to_image (GdkDrawable     *drawable,
 				     width, height);
 }
 
+static void
+gdk_window_cairo_surface_destroy (void *data)
+{
+  GdkWindowObject *private = (GdkWindowObject*) data;
+
+  private->cairo_surface = NULL;
+}
+
 static cairo_surface_t *
 gdk_window_ref_cairo_surface (GdkDrawable *drawable)
 {
@@ -2495,17 +3622,185 @@ gdk_window_ref_cairo_surface (GdkDrawable *drawable)
       cairo_surface_reference (surface);
     }
   else
-    surface = _gdk_drawable_ref_cairo_surface (private->impl);
+    {
+      
+      /* This will be drawing directly to the window, so flush implicit paint */
+      gdk_window_flush_implicit_paint ((GdkWindow *)drawable);
+      
+      if (!private->cairo_surface)
+	{
+	  int width, height;
+	  GdkDrawable *source;
+
+	  /* It would be nice if we had some cairo support here so we
+	     could set the clip rect on the cairo surface */
+	  width = private->abs_x + private->width;
+	  height = private->abs_y + private->height;
+
+	  source = _gdk_drawable_get_source_drawable (drawable);
+
+	  /* TODO: Avoid the typecheck crap by adding virtual call */
+	  private->cairo_surface = _gdk_windowing_create_cairo_surface (GDK_IS_PIXMAP (source) ? GDK_PIXMAP_OBJECT(source)->impl : GDK_WINDOW_OBJECT(source)->impl,
+									width, height);
+	  
+	  if (private->cairo_surface)
+	    {
+	      cairo_surface_set_device_offset (private->cairo_surface, 
+					       private->abs_x,
+					       private->abs_y);
+	      
+	      cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
+					   drawable, gdk_window_cairo_surface_destroy);
+	    }
+	}
+      else
+	cairo_surface_reference (private->cairo_surface);
+      
+      surface = private->cairo_surface;
+    }
 
   return surface;
 }
 
+static void
+gdk_window_set_cairo_clip (GdkDrawable *drawable,
+			   cairo_t *cr)
+{
+  GdkWindowObject *private = (GdkWindowObject*) drawable;
+
+  if (!private->paint_stack)
+    {
+      cairo_save (cr);
+      cairo_identity_matrix (cr);
+      
+      cairo_new_path (cr);
+      gdk_cairo_region (cr, private->clip_region);
+      
+      cairo_restore (cr);
+      cairo_clip (cr);
+    }
+  else
+    {
+      GdkWindowPaint *paint = private->paint_stack->data;
+
+      /* Only needs to clip to region if piggybacking
+	 on an implicit paint pixmap */
+      if (paint->uses_implicit)
+	{
+	  cairo_save (cr);
+	  cairo_identity_matrix (cr);
+	  
+	  cairo_new_path (cr);
+	  gdk_cairo_region (cr, paint->region);
+	  cairo_restore (cr);
+	  
+	  cairo_clip (cr);
+	}
+    }
+}
+
 /* Code for dirty-region queueing
  */
 static GSList *update_windows = NULL;
 static guint update_idle = 0;
 static gboolean debug_updates = FALSE;
 
+static inline gboolean
+gdk_window_is_ancestor (GdkWindow *window,
+                        GdkWindow *ancestor)
+{
+  while (window)
+    {
+      GdkWindow *parent = (GdkWindow*) ((GdkWindowObject*) window)->parent;
+
+      if (parent == ancestor)
+        return TRUE;
+
+      window = parent;
+    }
+
+  return FALSE;
+}
+
+static void
+gdk_window_add_update_window (GdkWindow *window)
+{
+  GSList *tmp;
+  GSList *prev = NULL;
+  gboolean has_ancestor_in_list = FALSE;
+
+  for (tmp = update_windows; tmp; tmp = tmp->next)
+    {
+      GdkWindowObject *parent = GDK_WINDOW_OBJECT (window)->parent;
+
+      /*  check if tmp is an ancestor of "window"; if it is, set a
+       *  flag indicating that all following windows are either
+       *  children of "window" or from a differen hierarchy
+       */
+      if (!has_ancestor_in_list && gdk_window_is_ancestor (window, tmp->data))
+        has_ancestor_in_list = TRUE;
+
+      /* insert in reverse stacking order when adding around siblings,
+       * so processing updates properly paints over lower stacked windows
+       */
+      if (parent == GDK_WINDOW_OBJECT (tmp->data)->parent)
+        {
+          gint index = g_list_index (parent->children, window);
+          for (; tmp && parent == GDK_WINDOW_OBJECT (tmp->data)->parent; tmp = tmp->next)
+            {
+              gint sibling_index = g_list_index (parent->children, tmp->data);
+              if (index > sibling_index)
+                break;
+              prev = tmp;
+            }
+          /* here, tmp got advanced past all lower stacked siblings */
+          tmp = g_slist_prepend (tmp, window);
+          if (prev)
+            prev->next = tmp;
+          else
+            update_windows = tmp;
+          return;
+        }
+
+      /*  if "window" has an ancestor in the list and tmp is one of
+       *  "window's" children, insert "window" before tmp
+       */
+      if (has_ancestor_in_list && gdk_window_is_ancestor (tmp->data, window))
+        {
+          tmp = g_slist_prepend (tmp, window);
+
+          if (prev)
+            prev->next = tmp;
+          else
+            update_windows = tmp;
+          return;
+        }
+
+      /*  if we're at the end of the list and had an ancestor it it,
+       *  append to the list
+       */
+      if (! tmp->next && has_ancestor_in_list)
+        {
+          tmp = g_slist_append (tmp, window);
+          return;
+        }
+
+      prev = tmp;
+    }
+
+  /*  if all above checks failed ("window" is from a different
+   *  hierarchy than what is already in the list) or the list is
+   *  empty, prepend
+   */
+  update_windows = g_slist_prepend (update_windows, window);
+}
+
+static void
+gdk_window_remove_update_window (GdkWindow *window)
+{
+  update_windows = g_slist_remove (update_windows, window);
+}
+
 static gboolean
 gdk_window_update_idle (gpointer data)
 {
@@ -2540,10 +3835,77 @@ gdk_window_schedule_update (GdkWindow *window)
 }
 
 static void
+gdk_window_process_updates_recurse (GdkWindow *window,
+				    GdkRegion *expose_region)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *child;
+  GdkRegion *child_region;
+  GdkRectangle r;
+  GList *l;
+
+  if (gdk_region_empty (expose_region))
+    return;
+  
+  /* Iterate over children, starting at topmost */
+  for (l = private->children; l != NULL; l = l->next)
+    {
+      child = l->data;
+      
+      if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only)
+	continue;
+
+      /* Ignore offscreen children, as they don't draw in their parent and
+       * don't take part in the clipping */
+      if (gdk_window_is_offscreen (child))
+	continue;
+
+      r.x = child->x;
+      r.y = child->y;
+      r.width = child->width;
+      r.height = child->height;
+      
+      child_region = gdk_region_rectangle (&r);
+      
+      if (child->impl == private->impl) 
+	{
+	  /* Client side child, expose */
+	  gdk_region_intersect (child_region, expose_region);
+	  gdk_region_subtract (expose_region, child_region);
+	  gdk_region_offset (child_region, -child->x, -child->y);
+	  gdk_window_process_updates_recurse ((GdkWindow *)child, child_region);
+	}
+      else 
+	{
+	  /* Native child, just remove area from expose region */
+	  gdk_region_subtract (expose_region, child_region);
+	}
+      gdk_region_destroy (child_region);
+    }
+
+  if (private->event_mask & GDK_EXPOSURE_MASK)
+    {
+      GdkEvent event;
+      
+      event.expose.type = GDK_EXPOSE;
+      event.expose.window = g_object_ref (window);
+      event.expose.send_event = FALSE;
+      event.expose.count = 0;
+      event.expose.region = expose_region;
+      gdk_region_get_clipbox (expose_region, &event.expose.area);
+      
+      (*_gdk_event_func) (&event, _gdk_event_data);
+      
+      g_object_unref (window);
+    }
+}
+
+static void
 gdk_window_process_updates_internal (GdkWindow *window)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
   gboolean save_region = FALSE;
+  GdkRectangle clip_box;
 
   /* If an update got queued during update processing, we can get a
    * window in the update queue that has an empty update_area.
@@ -2559,7 +3921,7 @@ gdk_window_process_updates_internal (GdkWindow *window)
 	  GdkRectangle window_rect;
 	  GdkRegion *expose_region;
 	  GdkRegion *window_region;
-          gint width, height;
+	  gboolean end_implicit;
 
           if (debug_updates)
             {
@@ -2567,43 +3929,29 @@ gdk_window_process_updates_internal (GdkWindow *window)
               gdk_display_sync (gdk_drawable_get_display (window));
               g_usleep (70000);
             }
-          
-	  save_region = _gdk_windowing_window_queue_antiexpose (window, update_area);
 
+	  save_region = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->queue_antiexpose (window, update_area);
 	  if (save_region)
 	    expose_region = gdk_region_copy (update_area);
 	  else
 	    expose_region = update_area;
 	  
-          gdk_drawable_get_size (GDK_DRAWABLE (private), &width, &height);
-
 	  window_rect.x = 0;
 	  window_rect.y = 0;
-	  window_rect.width = width;
-	  window_rect.height = height;
+	  window_rect.width = private->width;
+	  window_rect.height = private->height;
 
 	  window_region = gdk_region_rectangle (&window_rect);
 	  gdk_region_intersect (expose_region,
 				window_region);
 	  gdk_region_destroy (window_region);
-	  
-	  if (!gdk_region_empty (expose_region) &&
-	      (private->event_mask & GDK_EXPOSURE_MASK))
-	    {
-	      GdkEvent event;
-	      
-	      event.expose.type = GDK_EXPOSE;
-	      event.expose.window = g_object_ref (window);
-	      event.expose.send_event = FALSE;
-	      event.expose.count = 0;
-	      event.expose.region = expose_region;
-	      gdk_region_get_clipbox (expose_region, &event.expose.area);
-	      
-	      (*_gdk_event_func) (&event, _gdk_event_data);
-	      
-	      g_object_unref (window);
-	    }
 
+	  gdk_region_get_clipbox (expose_region, &clip_box);
+	  end_implicit = gdk_window_begin_implicit_paint (window, &clip_box);
+	  gdk_window_process_updates_recurse (window, expose_region);
+	  if (end_implicit)
+	    gdk_window_end_implicit_paint (window);
+	  
 	  if (expose_region != update_area)
 	    gdk_region_destroy (expose_region);
 	}
@@ -2663,7 +4011,7 @@ gdk_window_process_all_updates (void)
         {
 	  if (private->update_freeze_count ||
 	      gdk_window_is_toplevel_frozen (tmp_list->data))
-	    update_windows = g_slist_prepend (update_windows, private);
+	    gdk_window_add_update_window ((GdkWindow *) private);
 	  else
 	    gdk_window_process_updates_internal (tmp_list->data);
 	}
@@ -2697,6 +4045,7 @@ gdk_window_process_updates (GdkWindow *window,
 			    gboolean   update_children)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *impl_window;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
@@ -2709,23 +4058,24 @@ gdk_window_process_updates (GdkWindow *window,
 
       return;
     }
-  
-  if (private->update_area &&
-      !private->update_freeze_count &&
+
+  impl_window = gdk_window_get_impl_window (private);
+  if (impl_window->update_area &&
+      !impl_window->update_freeze_count &&
       !gdk_window_is_toplevel_frozen (window))
     {      
-      gdk_window_process_updates_internal (window);
-      update_windows = g_slist_remove (update_windows, window);
+      gdk_window_process_updates_internal ((GdkWindow *)impl_window);
+      gdk_window_remove_update_window ((GdkWindow *)impl_window);
     }
 
   if (update_children)
     {
-      GList *tmp_list = private->children;
-      while (tmp_list)
-	{
-	  gdk_window_process_updates (tmp_list->data, TRUE);
-	  tmp_list = tmp_list->next;
-	}
+      /* process updates in reverse stacking order so composition or
+       * painting over achieves the desired effect for offscreen windows
+       */
+      GList *node;
+      for (node = g_list_last (private->children); node; node = node->prev)
+        gdk_window_process_updates (node->data, TRUE);
     }
 }
 
@@ -2829,6 +4179,7 @@ gdk_window_invalidate_maybe_recurse (GdkWindow       *window,
 				     gpointer   user_data)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *impl_window;
   GdkRegion *visible_region;
   GList *tmp_list;
 
@@ -2850,18 +4201,7 @@ gdk_window_invalidate_maybe_recurse (GdkWindow       *window,
       return;
     }
 
-  /* windows that a redirection has ben setup for need to be considered
-   * fully visible, in order to avoid missing redirected paint ops
-   * anywhere in the window area.
-   */
-  if (private->redirect && private->redirect->redirected == private)
-    {
-      GdkRectangle visible_rect = { 0, 0, 0, 0 };
-      gdk_drawable_get_size (GDK_DRAWABLE (window), &visible_rect.width, &visible_rect.height);
-      visible_region = gdk_region_rectangle (&visible_rect);
-    }
-  else
-    visible_region = gdk_drawable_get_visible_region (window);
+  visible_region = gdk_drawable_get_visible_region (window);
   gdk_region_intersect (visible_region, region);
 
   tmp_list = private->children;
@@ -2873,17 +4213,17 @@ gdk_window_invalidate_maybe_recurse (GdkWindow       *window,
 	{
 	  GdkRegion *child_region;
 	  GdkRectangle child_rect;
-	  
-	  gdk_window_get_position ((GdkWindow *)child,
-				   &child_rect.x, &child_rect.y);
-	  gdk_drawable_get_size ((GdkDrawable *)child,
-				 &child_rect.width, &child_rect.height);
 
+	  child_rect.x = child->x;
+	  child_rect.y = child->y;
+	  child_rect.width = child->width;
+	  child_rect.height = child->height;
 	  child_region = gdk_region_rectangle (&child_rect);
 	  
 	  /* remove child area from the invalid area of the parent */
 	  if (GDK_WINDOW_IS_MAPPED (child) && !child->shaped &&
-	      !child->composited)
+	      !child->composited &&
+              !gdk_window_is_offscreen (child))
 	    gdk_region_subtract (visible_region, child_region);
 	  
 	  if (child_func && (*child_func) ((GdkWindow *)child, user_data))
@@ -2910,17 +4250,20 @@ gdk_window_invalidate_maybe_recurse (GdkWindow       *window,
     {
       if (debug_updates)
         draw_ugly_color (window, region);
-
-      if (private->update_area)
+      
+      /* Convert to impl coords */
+      impl_window = gdk_window_get_impl_window (private);
+      gdk_region_offset (visible_region, private->abs_x, private->abs_y);
+      if (impl_window->update_area)
 	{
-	  gdk_region_union (private->update_area, visible_region);
+	  gdk_region_union (impl_window->update_area, visible_region);
 	}
       else
 	{
-	  update_windows = g_slist_prepend (update_windows, window);
-	  private->update_area = gdk_region_copy (visible_region);
+	  gdk_window_add_update_window ((GdkWindow *)impl_window);
+	  impl_window->update_area = gdk_region_copy (visible_region);
 	  
-	  gdk_window_schedule_update (window);
+	  gdk_window_schedule_update ((GdkWindow *)impl_window);
 	}
     }
   
@@ -2970,6 +4313,38 @@ gdk_window_invalidate_region (GdkWindow       *window,
 }
 
 /**
+ * _gdk_window_invalidate_for_expose:
+ * @window: a #GdkWindow
+ * @region: a #GdkRegion
+ *
+ * Adds @region to the update area for @window. The update area is the
+ * region that needs to be redrawn, or "dirty region." The call
+ * gdk_window_process_updates() sends one or more expose events to the
+ * window, which together cover the entire update area. An
+ * application would normally redraw the contents of @window in
+ * response to those expose events.
+ *
+ * GDK will call gdk_window_process_all_updates() on your behalf
+ * whenever your program returns to the main loop and becomes idle, so
+ * normally there's no need to do that manually, you just need to
+ * invalidate regions that you know should be redrawn.
+ *
+ * This version of invalidation is used when you recieve expose events
+ * from the native window system. It exposes the native window, plus
+ * any non-native child windows (but not native child windows, as those would
+ * have gotten their own expose events). 
+ **/
+void
+_gdk_window_invalidate_for_expose (GdkWindow       *window,
+				   const GdkRegion *region)
+{
+  gdk_window_invalidate_maybe_recurse (window, region,
+				       (gboolean (*) (GdkWindow *, gpointer))gdk_window_has_no_impl,
+				       NULL);
+}
+
+
+/**
  * gdk_window_get_update_area:
  * @window: a #GdkWindow
  * 
@@ -2986,18 +4361,42 @@ GdkRegion *
 gdk_window_get_update_area (GdkWindow *window)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *impl_window;
   GdkRegion *tmp_region;
 
   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 
-  if (private->update_area)
+  impl_window = gdk_window_get_impl_window (private);
+  
+  if (impl_window->update_area)
     {
-      tmp_region = private->update_area;
-      private->update_area = NULL;
+      tmp_region = gdk_region_copy (private->clip_region_with_children);
+      /* Convert to impl coords */
+      gdk_region_offset (tmp_region, private->abs_x, private->abs_y);
+      gdk_region_intersect (tmp_region, impl_window->update_area);
 
-      update_windows = g_slist_remove (update_windows, window);
-      
-      return tmp_region;
+      if (gdk_region_empty (tmp_region))
+	{
+	  gdk_region_destroy (tmp_region);
+	  return NULL;
+	}
+      else
+	{
+	  gdk_region_subtract (impl_window->update_area, tmp_region);
+
+	  if (gdk_region_empty (impl_window->update_area))
+	    {
+	      gdk_region_destroy (impl_window->update_area);
+	      impl_window->update_area = NULL;
+	  
+	      gdk_window_remove_update_window ((GdkWindow *)impl_window);
+	    }
+	  
+	  /* Convert from impl coords */
+	  gdk_region_offset (tmp_region, -private->abs_x, -private->abs_y);
+	  return tmp_region;
+
+	}
     }
   else
     return NULL;
@@ -3019,8 +4418,8 @@ _gdk_window_clear_update_area (GdkWindow *window)
 
   if (private->update_area)
     {
-      update_windows = g_slist_remove (update_windows, window);
-      
+      gdk_window_remove_update_window (window);
+
       gdk_region_destroy (private->update_area);
       private->update_area = NULL;
     }
@@ -3040,10 +4439,12 @@ void
 gdk_window_freeze_updates (GdkWindow *window)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *impl_window;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  private->update_freeze_count++;
+  impl_window = gdk_window_get_impl_window (private);
+  impl_window->update_freeze_count++;
 }
 
 /**
@@ -3056,12 +4457,15 @@ void
 gdk_window_thaw_updates (GdkWindow *window)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *impl_window;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (private->update_freeze_count > 0);
 
-  if (--private->update_freeze_count == 0)
-    gdk_window_schedule_update (window);
+  impl_window = gdk_window_get_impl_window (private);
+  
+  if (--impl_window->update_freeze_count == 0)
+    gdk_window_schedule_update (GDK_WINDOW (impl_window));
 }
 
 /**
@@ -3389,6 +4793,101 @@ gdk_window_foreign_new (GdkNativeWindow anid)
   return gdk_window_foreign_new_for_display (gdk_display_get_default (), anid);
 }
 
+/* Called when window becomes viewable. Clears and sends exposes
+   for all the already mapped windows in the hierarchy */
+static void
+synthesize_clears (GdkWindowObject *window)
+{
+  GList *l;
+  
+  if (!gdk_window_has_impl (window) && !window->input_only)
+    {
+      gdk_window_clear_area_e (GDK_WINDOW (window),
+			       0, 0,
+			       window->width, window->height);
+    }
+  
+  for (l = window->children; l != NULL; l = l->next)
+    {
+      GdkWindow *child = GDK_WINDOW (l->data);
+      
+      if (GDK_WINDOW_IS_MAPPED (child))
+	synthesize_clears (GDK_WINDOW_OBJECT (child));
+    }
+}
+
+static inline void
+gdk_window_raise_internal (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *parent = private->parent;
+
+  if (parent)
+    {
+      parent->children = g_list_remove (parent->children, window);
+      parent->children = g_list_prepend (parent->children, window);
+    }
+}
+
+static void
+gdk_window_show_internal (GdkWindow *window, gboolean raise)
+{
+  GdkWindowObject *private;
+  gboolean was_mapped;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *) window;
+  if (private->destroyed)
+    return;
+
+  was_mapped = GDK_WINDOW_IS_MAPPED (window);
+  
+  if (raise)
+    {
+      /* Keep children in (reverse) stacking order */
+      gdk_window_raise_internal (window);
+    }
+
+  if (gdk_window_has_impl (private))
+    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show (window, raise);
+  else
+    {
+      if (GDK_WINDOW_IS_MAPPED (window))
+	{
+	  /* If we're raising, need to invalidate even if we're already shown */
+	  if (raise && gdk_window_is_viewable (window) && !private->input_only)
+	    gdk_window_invalidate_rect (window, NULL, TRUE);
+	}
+      else
+	{
+	  /* Wasn't visible already */
+	  private->state = 0;
+	}
+    }
+
+  if (!was_mapped)
+    {
+      if (private->event_mask & GDK_STRUCTURE_MASK)
+	_gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
+      
+      if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+	_gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
+    }
+  
+  if (!was_mapped || raise)
+    {
+      if (gdk_window_is_viewable (window))
+	_gdk_syntesize_crossing_events_for_geometry_change (window);
+      
+      recompute_visible_regions (private, TRUE, FALSE);
+    }
+  
+  if (!was_mapped && gdk_window_is_viewable (window))
+    synthesize_clears (private);
+  
+}
+  
 /**
  * gdk_window_show_unraised:
  * @window: a #GdkWindow
@@ -3404,28 +4903,7 @@ gdk_window_foreign_new (GdkNativeWindow anid)
 void
 gdk_window_show_unraised (GdkWindow *window)
 {
-  GdkWindowObject *private;
-
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
-    return;
-
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show (window, FALSE);
-}
-
-static inline void
-gdk_window_raise_internal (GdkWindow *window)
-{
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkWindowObject *parent = private->parent;
-
-  if (parent)
-    {
-      parent->children = g_list_remove (parent->children, window);
-      parent->children = g_list_prepend (parent->children, window);
-    }
+  gdk_window_show_internal (window, FALSE);
 }
 
 /**
@@ -3455,6 +4933,8 @@ gdk_window_raise (GdkWindow *window)
   gdk_window_raise_internal (window);
 
   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
+
+  recompute_visible_regions (private, TRUE, FALSE);
 }
 
 static void
@@ -3470,6 +4950,30 @@ gdk_window_lower_internal (GdkWindow *window)
     }
 }
 
+static void
+gdk_window_invalidate_in_parent (GdkWindowObject *private)
+{
+  GdkRectangle r, child;
+
+  if (private->parent == NULL ||
+      GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
+    return;
+  
+  /* get the visible rectangle of the parent */
+  r.x = r.y = 0;
+  r.width = private->parent->width;
+  r.height = private->parent->height;
+
+  child.x = private->x;
+  child.y = private->y;
+  child.width = private->width;
+  child.height = private->height;
+  gdk_rectangle_intersect (&r, &child, &r);
+
+  gdk_window_invalidate_rect (GDK_WINDOW (private->parent), &r, TRUE);
+}
+
+
 /**
  * gdk_window_lower:
  * @window: a #GdkWindow
@@ -3499,7 +5003,15 @@ gdk_window_lower (GdkWindow *window)
   /* Keep children in (reverse) stacking order */
   gdk_window_lower_internal (window);
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->lower (window);
+  if (gdk_window_has_impl (private))
+    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->lower (window);
+  else
+    {
+      gdk_window_invalidate_in_parent (private);
+      _gdk_syntesize_crossing_events_for_geometry_change (window);
+    }
+
+  recompute_visible_regions (private, TRUE, FALSE);
 }
 
 /**
@@ -3519,18 +5031,7 @@ gdk_window_lower (GdkWindow *window)
 void
 gdk_window_show (GdkWindow *window)
 {
-  GdkWindowObject *private;
-
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
-    return;
-
-  /* Keep children in (reverse) stacking order */
-  gdk_window_raise_internal (window);
-
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show (window, TRUE);
+  gdk_window_show_internal (window, TRUE);
 }
 
 /**
@@ -3546,6 +5047,7 @@ void
 gdk_window_hide (GdkWindow *window)
 {
   GdkWindowObject *private;
+  gboolean was_mapped;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
@@ -3553,7 +5055,50 @@ gdk_window_hide (GdkWindow *window)
   if (private->destroyed)
     return;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->hide (window);
+  was_mapped = GDK_WINDOW_IS_MAPPED (private);
+  
+  if (gdk_window_has_impl (private))
+    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->hide (window);
+  else if (was_mapped)
+    {
+      GdkDisplay *display;
+
+      /* May need to break grabs on children */
+      display = gdk_drawable_get_display (window);
+
+      if (display->pointer_grab.window != NULL)
+	{
+	  if (is_parent_of (window, display->pointer_grab.window))
+	    {
+	      /* Call this ourselves, even though gdk_display_pointer_ungrab
+		 does so too, since we want to pass implicit == TRUE so the
+		 broken grab event is generated */
+	      _gdk_display_unset_has_pointer_grab (display,
+						   TRUE,
+						   FALSE,
+						   GDK_CURRENT_TIME);
+	      gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
+	    }
+	}
+
+      private->state = GDK_WINDOW_STATE_WITHDRAWN;
+      
+      /* Invalidate the rect */
+      gdk_window_invalidate_in_parent (private);
+    }
+
+  if (was_mapped)
+    {
+      if (private->event_mask & GDK_STRUCTURE_MASK)
+	_gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
+      
+      if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+	_gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
+      
+      _gdk_syntesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
+    }
+  
+  recompute_visible_regions (private, TRUE, FALSE);
 }
 
 /**
@@ -3568,6 +5113,7 @@ void
 gdk_window_withdraw (GdkWindow *window)
 {
   GdkWindowObject *private;
+  gboolean was_mapped;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
@@ -3575,7 +5121,25 @@ gdk_window_withdraw (GdkWindow *window)
   if (private->destroyed)
     return;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->withdraw (window);
+  was_mapped = GDK_WINDOW_IS_MAPPED (private);
+  
+  if (gdk_window_has_impl (private))
+    {
+      GDK_WINDOW_IMPL_GET_IFACE (private->impl)->withdraw (window);
+      
+      if (was_mapped)
+	{
+	  if (private->event_mask & GDK_STRUCTURE_MASK)
+	    _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
+	  
+	  if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+	    _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
+	  
+	  _gdk_syntesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
+	}
+      
+      recompute_visible_regions (private, TRUE, FALSE);
+    }
 }
 
 /**
@@ -3600,7 +5164,7 @@ gdk_window_set_events (GdkWindow       *window,
   if (private->destroyed)
     return;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_events (window, event_mask);
+  private->event_mask = event_mask;
 }
 
 /**
@@ -3622,9 +5186,189 @@ gdk_window_get_events (GdkWindow *window)
   if (private->destroyed)
     return 0;
 
-  return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_events (window);
+  return private->event_mask;
+}
+
+static void
+move_native_children (GdkWindowObject *private)
+{
+  GList *l;
+  GdkWindowObject *child;
+  
+  for (l = private->children; l; l = l->next)
+    {
+      child = l->data;
+      
+      if (child->impl != private->impl)
+	GDK_WINDOW_IMPL_GET_IFACE (child->impl)->move_resize ((GdkWindow *)child, TRUE, child->x, child->y, child->width, child->height);
+      else
+	move_native_children  (child);
+    }
+}
+
+
+static void
+gdk_window_move_resize_internal (GdkWindow *window,
+				 gboolean   with_move,
+				 gint       x,
+				 gint       y,
+				 gint       width,
+				 gint       height)
+{
+  GdkWindowObject *private;
+  GdkRegion *old_region, *new_region, *copy_area;
+  GdkWindowObject *impl_window;
+  gboolean expose;
+  int old_x, old_y, old_abs_x, old_abs_y;
+  int dx, dy;
+  GdkRectangle copy_rect;
+  GdkGC *tmp_gc;
+  gboolean do_move_native_children;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *) window;
+  if (private->destroyed)
+    return;
+
+  do_move_native_children = FALSE;
+  expose = FALSE;
+  old_region = NULL;
+
+  impl_window = gdk_window_get_impl_window (private);
+
+  old_x = private->x;
+  old_y = private->y;
+  
+  if (gdk_window_has_impl (private))
+    {
+      if (GDK_WINDOW_IS_MAPPED (window))
+	{
+	  expose = TRUE;
+	  old_region = gdk_region_copy (private->clip_region);
+	  /* Adjust region to parent window coords */
+	  gdk_region_offset (old_region, private->x, private->y);
+	}
+      
+      GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, with_move, x, y, width, height);
+    }
+  else
+    {
+      if (GDK_WINDOW_IS_MAPPED (window))
+	{
+	  expose = TRUE;
+	  old_region = gdk_region_copy (private->clip_region);
+	  /* Adjust region to parent window coords */
+	  gdk_region_offset (old_region, private->x, private->y);
+	}
+
+      if (with_move)
+	{
+	  private->x = x;
+	  private->y = y;
+	}
+      if (!(width < 0 && height < 0))
+	{
+	  if (width < 1)
+	    width = 1;
+	  private->width = width;
+	  if (height < 1)
+	    height = 1;
+	  private->height = height;
+	}
+
+      do_move_native_children = TRUE;
+    }
+
+  dx = private->x - old_x;
+  dy = private->y - old_y;
+
+  old_abs_x = private->abs_x;
+  old_abs_y = private->abs_y;
+  
+  recompute_visible_regions (private, TRUE, FALSE);
+
+  if (do_move_native_children &&
+      (old_abs_x != private->abs_x ||
+       old_abs_y != private->abs_y))
+      move_native_children (private);
+  
+  if (expose)
+    {
+      new_region = gdk_region_copy (private->clip_region);
+      /* Adjust region to parent window coords */
+      gdk_region_offset (new_region, private->x, private->y);
+
+      /* copy_area:
+       * Part of the data at the new location can be copied from the
+       * old location, this area is the intersection of the old region
+       * moved as the copy will move it and then intersected with
+       * the new region.
+       *
+       * new_region:
+       * Everything in the old and new regions that is not copied must be
+       * invalidated (including children) as this is newly exposed 
+       */
+      copy_area = gdk_region_copy (new_region);
+	  
+      gdk_region_union (new_region, old_region);
+      
+      gdk_region_offset (old_region, dx, dy);
+      gdk_region_intersect (copy_area, old_region);
+      
+      gdk_region_subtract (new_region, copy_area);
+
+      /* Convert old region to impl coords */
+      gdk_region_offset (old_region, -dx + private->abs_x - private->x, -dy + private->abs_y - private->y);
+
+      /* The old_region area is moved and we queue translations for all expose events
+	 to it that will be sent before the copy operation */
+      /* TODO: Make queue_translation a vtable call instead of hardcoding this crap */
+      if (!gdk_window_is_offscreen (impl_window)) 
+	_gdk_windowing_window_queue_translation ((GdkWindow *)impl_window, old_region, dx, dy);
+      
+      /* convert from parent coords to real parent */
+      gdk_region_offset (copy_area, private->abs_x - private->x, private->abs_y - private->y);
+      gdk_region_get_clipbox (copy_area, &copy_rect);
+      tmp_gc = _gdk_drawable_get_scratch_gc (window, TRUE);
+      gdk_gc_set_clip_region (tmp_gc, copy_area);
+      gdk_draw_drawable (private->impl,
+			 tmp_gc,
+			 private->impl,
+			 copy_rect.x-dx, copy_rect.y-dy,
+			 copy_rect.x, copy_rect.y,
+			 copy_rect.width, copy_rect.height);
+      gdk_gc_set_clip_region (tmp_gc, NULL);
+
+      /* Move any old invalid regions in the copy source area by dx/dy */
+      if (impl_window->update_area)
+	{
+	  /* Convert from target to source */
+	  gdk_region_offset (copy_area, -dx, -dy);
+	  gdk_region_intersect (copy_area, impl_window->update_area);
+	  gdk_region_subtract (impl_window->update_area, copy_area);
+	  gdk_region_offset (copy_area, dx, dy);
+	  gdk_region_union (impl_window->update_area, copy_area);
+	}
+      
+      /* Invalidate affected part in the parent window
+       *  (no higher window should be affected)
+       * We also invalidate any children in that area, which could include
+       * this window if it still overlaps that area.
+       */
+      gdk_window_invalidate_region (GDK_WINDOW (private->parent), new_region, TRUE);
+
+      
+      gdk_region_destroy (old_region);
+      gdk_region_destroy (new_region);
+      gdk_region_destroy (copy_area);
+    }
+
+  _gdk_syntesize_crossing_events_for_geometry_change (window);
 }
 
+
+
 /**
  * gdk_window_move:
  * @window: a #GdkWindow
@@ -3645,15 +5389,7 @@ gdk_window_move (GdkWindow *window,
 		 gint       x,
 		 gint       y)
 {
-  GdkWindowObject *private;
-
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
-    return;
-
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, TRUE, x, y, -1, -1);
+  gdk_window_move_resize_internal (window, TRUE, x, y, -1, -1);
 }
 
 /**
@@ -3676,15 +5412,7 @@ gdk_window_resize (GdkWindow *window,
 		   gint       width,
 		   gint       height)
 {
-  GdkWindowObject *private;
-
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
-    return;
-
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, FALSE, 0, 0, width, height);
+  gdk_window_move_resize_internal (window, FALSE, 0, 0, width, height);
 }
 
 
@@ -3708,15 +5436,7 @@ gdk_window_move_resize (GdkWindow *window,
 			gint       width,
 			gint       height)
 {
-  GdkWindowObject *private;
-
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
-    return;
-
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, TRUE, x, y, width, height);
+  gdk_window_move_resize_internal (window, TRUE, x, y, width, height);
 }
 
 
@@ -3744,6 +5464,11 @@ gdk_window_scroll (GdkWindow *window,
 		   gint       dy)
 {
   GdkWindowObject *private = (GdkWindowObject *) window;
+  GdkWindowObject *impl_window;
+  GdkRegion *source_area, *copy_area, *noncopy_area;
+  GdkRectangle copy_rect;
+  GdkGC *tmp_gc;
+  GList *tmp_list;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
@@ -3753,7 +5478,88 @@ gdk_window_scroll (GdkWindow *window,
   if (private->destroyed)
     return;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->scroll (window, dx, dy);
+  /* First move all child windows, without causing invalidation */
+  
+  tmp_list = private->children;
+  while (tmp_list)
+    {
+      GdkWindow *child = GDK_WINDOW (tmp_list->data);
+      GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
+      
+      if (child_obj->impl == private->impl)
+	{
+	  /* Just update the positions, the bits will move with the copy */
+	  child_obj->x += dx;
+	  child_obj->y += dy;
+	}
+      else
+	{
+	  /* Native window, need to move it */
+	  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, TRUE, child_obj->x + dx, child_obj->y + dy, -1, -1);
+	}
+      
+      tmp_list = tmp_list->next;
+    }
+  
+  recompute_visible_regions (private, FALSE, TRUE);
+
+  /* Then copy the actual bits of the window w/ child windows */
+  
+  impl_window = gdk_window_get_impl_window (private);
+
+  /* Calculate the area that can be gotten by copying the old area */
+  copy_area = gdk_region_copy (private->clip_region);
+  gdk_region_offset (copy_area, dx, dy);
+  gdk_region_intersect (copy_area, private->clip_region);
+
+  /* And the rest need to be invalidated */
+  noncopy_area = gdk_region_copy (private->clip_region);
+  gdk_region_subtract (noncopy_area, copy_area);
+
+  /* Get window clip and convert to real window coords, this
+     area is moved and we queue translations for all expose events
+     to it that will be sent before the copy operation */
+  /* TODO: Make queue_translation a vtable call instead of hardcoding this crap */
+  if (!gdk_window_is_offscreen (impl_window))
+    {
+      source_area = gdk_region_copy (private->clip_region);
+      /* convert from window coords to real parent */
+      gdk_region_offset (source_area, private->abs_x, private->abs_y);
+      _gdk_windowing_window_queue_translation ((GdkWindow *)impl_window, source_area, dx, dy);
+      gdk_region_destroy (source_area);
+    }
+  
+  /* convert from window coords to real parent */
+  gdk_region_offset (copy_area, private->abs_x, private->abs_y);
+  gdk_region_get_clipbox (copy_area, &copy_rect);
+  tmp_gc = _gdk_drawable_get_scratch_gc (window, TRUE);
+  gdk_gc_set_clip_region (tmp_gc, copy_area);
+  gdk_draw_drawable (private->impl,
+		     tmp_gc,
+		     private->impl,
+		     copy_rect.x-dx, copy_rect.y-dy,
+		     copy_rect.x, copy_rect.y,
+		     copy_rect.width, copy_rect.height);
+  gdk_gc_set_clip_region (tmp_gc, NULL);
+
+  /* Move the current invalid region for the copy area */
+  if (private->update_area)
+    {
+      /* Convert from target to source */
+      gdk_region_offset (copy_area, -dx, -dy);
+      gdk_region_intersect (copy_area, impl_window->update_area);
+      gdk_region_subtract (impl_window->update_area, copy_area);
+      gdk_region_offset (copy_area, dx, dy);
+      gdk_region_union (impl_window->update_area, copy_area);
+    }
+  
+  /* Invalidate not copied regions */
+  gdk_window_invalidate_region (window, noncopy_area, TRUE);
+
+  gdk_region_destroy (noncopy_area);
+  gdk_region_destroy (copy_area);
+  
+  _gdk_syntesize_crossing_events_for_geometry_change (window);
 }
 
 /**
@@ -3778,6 +5584,13 @@ gdk_window_move_region (GdkWindow       *window,
 			gint             dy)
 {
   GdkWindowObject *private = (GdkWindowObject *) window;
+  GdkWindowObject *impl_window;
+  GdkRegion *source_area;
+  GdkRegion *nocopy_area;
+  GdkRegion *copy_area;
+  GdkRegion *moving_invalid_region;
+  GdkRectangle copy_rect;
+  GdkGC *tmp_gc;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (region != NULL);
@@ -3788,7 +5601,57 @@ gdk_window_move_region (GdkWindow       *window,
   if (private->destroyed)
     return;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_region (window, region, dx, dy);
+  impl_window = gdk_window_get_impl_window (private);
+  
+  /* compute source regions */
+  source_area = gdk_region_copy (region);
+  gdk_region_intersect (source_area, private->clip_region_with_children);
+
+  /* compute destination regions */
+  copy_area = gdk_region_copy (source_area);
+  gdk_region_offset (copy_area, dx, dy);
+  gdk_region_intersect (copy_area, private->clip_region_with_children);
+
+  /* Move the current invalid region for the copy area */
+  if (impl_window->update_area)
+    {
+      moving_invalid_region = gdk_region_copy (copy_area);
+      gdk_region_offset (moving_invalid_region, private->abs_x - dx, private->abs_y - dy);
+      gdk_region_intersect (moving_invalid_region, impl_window->update_area);
+      gdk_region_subtract (impl_window->update_area, moving_invalid_region);
+      gdk_region_offset (moving_invalid_region, dx, dy);
+      gdk_region_union (impl_window->update_area, moving_invalid_region);
+      gdk_region_destroy (moving_invalid_region);
+    }
+  
+  /* invalidate parts of the region not covered by the copy */
+  nocopy_area = gdk_region_copy (region);
+  gdk_region_offset (nocopy_area, dx, dy);
+  gdk_region_subtract (nocopy_area, copy_area);
+  gdk_window_invalidate_region (window, nocopy_area, FALSE);
+  gdk_region_destroy (nocopy_area);
+
+  /* TODO: Make queue_translation a vtable call instead of hardcoding this crap */
+  if (!gdk_window_is_offscreen (impl_window))
+    {
+      gdk_region_offset (source_area, private->abs_x, private->abs_y);
+      _gdk_windowing_window_queue_translation ((GdkWindow *)impl_window, source_area, dx, dy);
+    }
+
+  gdk_region_offset (copy_area, private->abs_x, private->abs_y);
+  gdk_region_get_clipbox (copy_area, &copy_rect);
+  tmp_gc = _gdk_drawable_get_scratch_gc (window, TRUE);
+  gdk_gc_set_clip_region (tmp_gc, copy_area);
+  gdk_draw_drawable (private->impl,
+		     tmp_gc,
+		     private->impl,
+		     copy_rect.x-dx, copy_rect.y-dy,
+		     copy_rect.x, copy_rect.y,
+		     copy_rect.width, copy_rect.height);
+  gdk_gc_set_clip_region (tmp_gc, NULL);
+
+  gdk_region_destroy (source_area);
+  gdk_region_destroy (copy_area);
 }
 
 /**
@@ -3811,12 +5674,24 @@ gdk_window_set_background (GdkWindow      *window,
 			   const GdkColor *color)
 {
   GdkWindowObject *private;
+  GdkColormap *colormap = gdk_drawable_get_colormap (window);
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
   private = (GdkWindowObject *) window;
+  
+  private->bg_color = *color;
+  gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, color);
+  if (private->bg_pixmap &&
+      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+      private->bg_pixmap != GDK_NO_BG)
+    g_object_unref (private->bg_pixmap);
+  
+  private->bg_pixmap = NULL;
+
+  if (!GDK_WINDOW_DESTROYED (window) && gdk_window_has_impl (private))
+    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, &private->bg_color);
 }
 
 /**
@@ -3858,7 +5733,26 @@ gdk_window_set_back_pixmap (GdkWindow *window,
 
   private = (GdkWindowObject *) window;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, pixmap, parent_relative);
+  if (pixmap && !gdk_drawable_get_colormap (pixmap))
+    {
+      g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
+      return;
+    }
+  
+  if (private->bg_pixmap &&
+      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+      private->bg_pixmap != GDK_NO_BG)
+    g_object_unref (private->bg_pixmap);
+
+  if (parent_relative)
+    private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
+  else if (pixmap)
+    private->bg_pixmap = g_object_ref (pixmap);
+  else
+    private->bg_pixmap = GDK_NO_BG;
+  
+  if (!GDK_WINDOW_DESTROYED (window) && gdk_window_has_impl (private))
+    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, private->bg_pixmap);
 }
 
 /**
@@ -3882,7 +5776,21 @@ gdk_window_set_cursor (GdkWindow *window,
 
   private = (GdkWindowObject *) window;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_cursor (window, cursor);
+  if (private->cursor)
+    {
+      gdk_cursor_unref (private->cursor);
+      private->cursor = NULL;
+    }
+
+  if (!GDK_WINDOW_DESTROYED (window))
+    {
+      if (cursor)
+	private->cursor = gdk_cursor_ref (cursor);
+
+      /* TODO: Track this via pointer_window 
+	 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_cursor (window, cursor);
+      */
+    }
 }
 
 /**
@@ -3941,9 +5849,23 @@ gdk_window_get_geometry (GdkWindow *window,
 
   if (!GDK_WINDOW_DESTROYED (window))
     {
-      GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_geometry (window, x, y,
-							       width, height,
-                                                               depth);
+      if (gdk_window_has_impl (private))
+	GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_geometry (window, x, y,
+								 width, height,
+								 depth);
+      else
+	{
+	  if (x)
+	    *x = private->x;
+	  if (y)
+	    *y = private->y;
+	  if (width)
+	    *width = private->width;
+	  if (height)
+	    *height = private->height;
+	  if (depth)
+	    *depth = private->depth;
+	}
     }
 }
 
@@ -3970,8 +5892,15 @@ gdk_window_get_origin (GdkWindow *window,
   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
 
   private = (GdkWindowObject *) window;
+  
+  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_origin (window, x, y);
 
-  return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_origin (window, x, y);
+  if (x)
+    *x += private->abs_x;
+  if (y)
+    *y += private->abs_y;
+  
+  return TRUE;
 }
 
 /**
@@ -4119,7 +6048,10 @@ gdk_window_set_static_gravities (GdkWindow *window,
 
   private = (GdkWindowObject *) window;
 
-  return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_static_gravities (window, use_static);
+  if (gdk_window_has_impl (private))
+    return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_static_gravities (window, use_static);
+  
+  return FALSE;
 }
 
 /**
@@ -4285,7 +6217,7 @@ gdk_window_redirect_to_drawable (GdkWindow   *window,
                                  gint         height)
 {
   GdkWindowObject *private;
-  
+
   g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
@@ -4322,20 +6254,22 @@ static void
 window_get_size_rectangle (GdkWindow    *window,
                            GdkRectangle *rect)
 {
+  GdkWindowObject *private = (GdkWindowObject *) window;
+  
   rect->x = rect->y = 0;
-  gdk_drawable_get_size (GDK_DRAWABLE (window), &rect->width, &rect->height);
+  rect->width = private->width;
+  rect->height = private->height;
 }
 
 /* Calculates the real clipping region for a window, in window coordinates,
  * taking into account other windows, gc clip region and gc clip mask.
  */
-static GdkRegion *
+GdkRegion *
 _gdk_window_calculate_full_clip_region (GdkWindow *window,
 					GdkWindow *base_window,
-					GdkGC *gc,
-					gboolean do_children,
-					gint *base_x_offset,
-					gint *base_y_offset)
+					gboolean   do_children,
+					gint      *base_x_offset,
+					gint      *base_y_offset)
 {
   GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
   GdkRectangle visible_rect;
@@ -4353,13 +6287,6 @@ _gdk_window_calculate_full_clip_region (GdkWindow *window,
 
   window_get_size_rectangle (window, &visible_rect);
 
-  /* windows that a redirection has ben setup for need to be considered
-   * fully visible, in order to avoid missing redirected paint ops
-   * anywhere in the window area.
-   */
-  if (private->redirect && private->redirect->redirected == private)
-    return gdk_region_rectangle (&visible_rect);
-
   /* real_clip_region is in window coordinates */
   real_clip_region = gdk_region_rectangle (&visible_rect);
 
@@ -4372,27 +6299,38 @@ _gdk_window_calculate_full_clip_region (GdkWindow *window,
     parentwin = lastwin->parent;
   
   /* Remove the areas of all overlapping windows above parentwin in the hiearachy */
-  for (; parentwin != NULL && (parentwin == private || lastwin != (GdkWindowObject *)base_window);
+  for (; parentwin != NULL &&
+         (parentwin == private || lastwin != (GdkWindowObject*) base_window);
        lastwin = parentwin, parentwin = lastwin->parent)
     {
       GList *cur;
       GdkRectangle real_clip_rect;
-      
+      gboolean is_offscreen;
+
       if (parentwin != private)
 	{
 	  x_offset += GDK_WINDOW_OBJECT (lastwin)->x;
 	  y_offset += GDK_WINDOW_OBJECT (lastwin)->y;
 	}
-      
+
+      is_offscreen = gdk_window_is_offscreen (parentwin);
+
       /* children is ordered in reverse stack order */
-      for (cur = GDK_WINDOW_OBJECT (parentwin)->children; cur && cur->data != lastwin; cur = cur->next)
+      for (cur = parentwin->children;
+           cur && cur->data != lastwin;
+           cur = cur->next)
 	{
 	  GdkWindow *child = cur->data;
 	  GdkWindowObject *child_private = (GdkWindowObject *)child;
-	  
+
 	  if (!GDK_WINDOW_IS_MAPPED (child) || child_private->input_only)
 	    continue;
 
+          /* Ignore offscreen children, as they don't draw in their parent and
+	   * don't take part in the clipping */
+	  if (gdk_window_is_offscreen (child_private))
+	    continue;
+
           window_get_size_rectangle (child, &visible_rect);
 
 	  /* Convert rect to "window" coords */
@@ -4423,24 +6361,6 @@ _gdk_window_calculate_full_clip_region (GdkWindow *window,
       gdk_region_destroy (tmpreg);
     }
 
-  if (gc)
-    {
-      GdkRegion *clip_region = _gdk_gc_get_clip_region (gc);
-      
-      if (clip_region)
-	{
-	  /* clip_region is relative to gc clip origin which is relative to the window */
-	  /* offset it to window relative: */
-	  tmpreg = gdk_region_copy (clip_region);
-	  gdk_region_offset (real_clip_region,
-			     gc->clip_x_origin,
-			     gc->clip_y_origin);
-	  /* Intersect it with window hierarchy cliprect: */
-	  gdk_region_intersect (real_clip_region, tmpreg);
-	  gdk_region_destroy (tmpreg);
-	}
-    }
-
   if (base_x_offset)
     *base_x_offset = x_offset;
   if (base_y_offset)
@@ -4449,9 +6369,9 @@ _gdk_window_calculate_full_clip_region (GdkWindow *window,
   return real_clip_region;
 }
 
-static void
-gdk_window_add_damage (GdkWindow *toplevel,
-		       GdkRegion *damaged_region)
+void
+_gdk_window_add_damage (GdkWindow *toplevel,
+			GdkRegion *damaged_region)
 {
   GdkDisplay *display;
   GdkEvent event = { 0, };
@@ -4465,80 +6385,903 @@ gdk_window_add_damage (GdkWindow *toplevel,
 }
 
 static void
-setup_redirect_clip (GdkWindow         *window,
-		     GdkGC             *gc,
-		     GdkWindowClipData *data)
+gdk_window_redirect_free (GdkWindowRedirect *redirect)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkRegion *visible_region;
-  GdkRectangle dest_rect;
-  GdkRegion *tmpreg;
-  GdkWindow *toplevel;
+  g_object_unref (redirect->pixmap);
+  g_free (redirect);
+}
 
-  data->old_region = _gdk_gc_get_clip_region (gc);
-  if (data->old_region) 
-    data->old_region = gdk_region_copy (data->old_region);
+static void
+convert_coords_to_child (GdkWindowObject *child,
+			 double x, double y,
+			 double *child_x, double *child_y)
+{
+  *child_x = x - child->x;
+  *child_y = y - child->y;
 
-  data->old_clip_x_origin = gc->clip_x_origin;
-  data->old_clip_y_origin = gc->clip_y_origin;
+  if (child->offscreen_hooks)
+    child->offscreen_hooks->from_parent ((GdkWindow *)child, x, y, child_x, child_y);
+}
 
-  toplevel = GDK_WINDOW (private->redirect->redirected);
+static gboolean
+point_in_window (GdkWindowObject *window,
+		 double x, double y)
+{
+  int w, h;
   
-  /* Get the clip region for gc clip rect + window hierarchy in
-     window relative coords */
-  visible_region =
-    _gdk_window_calculate_full_clip_region (window, toplevel,
-					    gc, TRUE,
-					    &data->x_offset, 
-					    &data->y_offset);
+  gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
+  
+  return
+    x >= 0 &&  x < w &&
+    y >= 0 && y < h;
+}
 
-  /* Compensate for the source pos/size */
-  data->x_offset -= private->redirect->src_x;
-  data->y_offset -= private->redirect->src_y;
-  dest_rect.x = -data->x_offset;
-  dest_rect.y = -data->y_offset;
-  dest_rect.width = private->redirect->width;
-  dest_rect.height = private->redirect->height;
-  tmpreg = gdk_region_rectangle (&dest_rect);
-  gdk_region_intersect (visible_region, tmpreg);
-  gdk_region_destroy (tmpreg);
+static void
+convert_toplevel_coords_to_window (GdkWindow *window,
+				   gdouble    toplevel_x,
+				   gdouble    toplevel_y,
+				   gdouble   *window_x,
+				   gdouble   *window_y)
+{
+  GdkWindowObject *private;
+  gdouble x, y;
+  GList *children, *l;
 
-  /* Compensate for the dest pos */
-  data->x_offset += private->redirect->dest_x;
-  data->y_offset += private->redirect->dest_y;
+  private = GDK_WINDOW_OBJECT (window);
+  
+  x = toplevel_x;
+  y = toplevel_y;
 
-  gdk_gc_set_clip_region (gc, visible_region); /* This resets clip origin! */
+  children = NULL;
+  while (private->parent != NULL &&
+	 (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT))
+    {
+      children = g_list_prepend (children, private);
+      private = private->parent;
+    }
 
-  /* offset clip and tiles from window coords to pixmaps coords */
-  gdk_gc_offset (gc, -data->x_offset, -data->y_offset);
+  for (l = children; l != NULL; l = l->next)
+    convert_coords_to_child (l->data, x, y, &x, &y);
+  
+  g_list_free (children);
+  
+  *window_x = x;
+  *window_y = y;
+}
+
+GdkWindow *
+_gdk_window_find_descendant_at (GdkWindow *toplevel,
+				double x, double y,
+				double *found_x,
+				double *found_y)
+{
+  GdkWindowObject *private, *sub;
+  double child_x, child_y;
+  GList *l;
 
-  /* Offset region to abs coords and add to damage */
-  gdk_region_offset (visible_region, data->x_offset, data->y_offset);
-  gdk_window_add_damage (toplevel, visible_region);
+  private = (GdkWindowObject *)toplevel;
   
-  gdk_region_destroy (visible_region);
+  if (point_in_window (private, x, y))
+    {
+      do 
+	{
+	  /* Children is ordered in reverse stack order, i.e. first is topmost */
+	  for (l = private->children; l != NULL; l = l->next)
+	    {
+	      sub = l->data;
+
+              if (!GDK_WINDOW_IS_MAPPED (sub))
+                continue;
+	      
+	      convert_coords_to_child (sub,
+				       x, y,
+				       &child_x, &child_y);
+	      if (point_in_window (sub, child_x, child_y))
+		{
+		  x = child_x;
+		  y = child_y;
+		  private = sub;
+		  break;
+		}
+	    }
+	}
+      while (l != NULL);
+    }
+  else
+    {
+      /* Not in window at all */
+      private = NULL;
+    }
+
+  if (found_x)
+    *found_x = x;
+  if (found_y)
+    *found_y = y;
+  
+  return (GdkWindow *)private;
 }
 
-static void
-reset_redirect_clip (GdkWindow         *offscreen,
-                     GdkGC             *gc,
-                     GdkWindowClipData *data)
+static const guint type_masks[] = {
+  GDK_SUBSTRUCTURE_MASK, /* GDK_DELETE                 = 0  */
+  GDK_STRUCTURE_MASK, /* GDK_DESTROY                   = 1  */
+  GDK_EXPOSURE_MASK, /* GDK_EXPOSE                     = 2  */
+  GDK_POINTER_MOTION_MASK, /* GDK_MOTION_NOTIFY        = 3  */
+  GDK_BUTTON_PRESS_MASK, /* GDK_BUTTON_PRESS           = 4  */
+  GDK_BUTTON_PRESS_MASK, /* GDK_2BUTTON_PRESS          = 5  */
+  GDK_BUTTON_PRESS_MASK, /* GDK_3BUTTON_PRESS          = 6  */
+  GDK_BUTTON_RELEASE_MASK, /* GDK_BUTTON_RELEASE       = 7  */
+  GDK_KEY_PRESS_MASK, /* GDK_KEY_PRESS                 = 8  */
+  GDK_KEY_RELEASE_MASK, /* GDK_KEY_RELEASE             = 9  */
+  GDK_ENTER_NOTIFY_MASK, /* GDK_ENTER_NOTIFY           = 10 */
+  GDK_LEAVE_NOTIFY_MASK, /* GDK_LEAVE_NOTIFY           = 11 */
+  GDK_FOCUS_CHANGE_MASK, /* GDK_FOCUS_CHANGE           = 12 */
+  GDK_STRUCTURE_MASK, /* GDK_CONFIGURE                 = 13 */
+  GDK_VISIBILITY_NOTIFY_MASK, /* GDK_MAP               = 14 */
+  GDK_VISIBILITY_NOTIFY_MASK, /* GDK_UNMAP             = 15 */
+  GDK_PROPERTY_CHANGE_MASK, /* GDK_PROPERTY_NOTIFY     = 16 */
+  GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_CLEAR     = 17 */
+  GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_REQUEST   = 18 */
+  GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_NOTIFY    = 19 */
+  GDK_PROXIMITY_IN_MASK, /* GDK_PROXIMITY_IN           = 20 */
+  GDK_PROXIMITY_OUT_MASK, /* GDK_PROXIMITY_OUT         = 21 */
+  GDK_ALL_EVENTS_MASK, /* GDK_DRAG_ENTER               = 22 */
+  GDK_ALL_EVENTS_MASK, /* GDK_DRAG_LEAVE               = 23 */
+  GDK_ALL_EVENTS_MASK, /* GDK_DRAG_MOTION              = 24 */
+  GDK_ALL_EVENTS_MASK, /* GDK_DRAG_STATUS              = 25 */
+  GDK_ALL_EVENTS_MASK, /* GDK_DROP_START               = 26 */
+  GDK_ALL_EVENTS_MASK, /* GDK_DROP_FINISHED            = 27 */
+  GDK_ALL_EVENTS_MASK, /* GDK_CLIENT_EVENT	       = 28 */
+  GDK_VISIBILITY_NOTIFY_MASK, /* GDK_VISIBILITY_NOTIFY = 29 */
+  GDK_EXPOSURE_MASK, /* GDK_NO_EXPOSE                  = 30 */
+  GDK_SCROLL_MASK | GDK_BUTTON_PRESS_MASK,/* GDK_SCROLL= 31 */
+  0, /* GDK_WINDOW_STATE = 32 */
+  0, /* GDK_SETTING = 33 */
+  0, /* GDK_OWNER_CHANGE = 34 */
+  0, /* GDK_GRAB_BROKEN = 35 */
+  0, /* GDK_DAMAGE = 36 */
+};
+G_STATIC_ASSERT (G_N_ELEMENTS (type_masks) == GDK_EVENT_LAST);
+
+/* send motion events if the right buttons are down */
+static guint
+update_evmask_for_button_motion (guint           evmask,
+                                 GdkModifierType mask)
+{
+  if (evmask & GDK_BUTTON_MOTION_MASK &&
+      mask & (GDK_BUTTON1_MASK |
+	      GDK_BUTTON2_MASK |
+	      GDK_BUTTON3_MASK |
+	      GDK_BUTTON4_MASK |
+	      GDK_BUTTON5_MASK))
+    evmask |= GDK_POINTER_MOTION_MASK;
+
+  if ((evmask & GDK_BUTTON1_MOTION_MASK && mask & GDK_BUTTON1_MASK) ||
+      (evmask & GDK_BUTTON2_MOTION_MASK && mask & GDK_BUTTON2_MASK) ||
+      (evmask & GDK_BUTTON3_MOTION_MASK && mask & GDK_BUTTON3_MASK))
+    evmask |= GDK_POINTER_MOTION_MASK;
+
+  return evmask;
+}
+
+static GdkWindow *
+get_target_window_for_pointer_event (GdkDisplay                 *display,
+				     GdkWindow                  *window,
+                                     GdkEventType                type,
+                                     GdkModifierType             mask)
+{
+  guint evmask;
+  gboolean crossing_event;
+  GdkWindow *w, *grab_window;
+
+  /* crossing events don't propagate up like other types of events */
+  crossing_event = (type == GDK_ENTER_NOTIFY || type == GDK_LEAVE_NOTIFY);
+
+  if ((display->pointer_grab.window != NULL && !display->pointer_grab.owner_events) ||
+      (type == GDK_BUTTON_RELEASE && display->pointer_grab.grab_one_pointer_release_event))
+    {
+      evmask = display->pointer_grab.event_mask;
+      evmask = update_evmask_for_button_motion (evmask, mask);
+
+      if (type == GDK_BUTTON_RELEASE &&
+	  display->pointer_grab.grab_one_pointer_release_event)
+	{
+	  grab_window = display->pointer_grab.grab_one_pointer_release_event;
+	  display->pointer_grab.grab_one_pointer_release_event = NULL;
+	}
+      else
+	grab_window = display->pointer_grab.window;
+
+      if ((evmask & type_masks[type]) &&
+          (!crossing_event || window == grab_window))
+	return grab_window;
+      else
+	return NULL;
+    }
+
+  w = window;
+  while (w != NULL)
+    {
+      evmask = GDK_WINDOW_OBJECT(window)->event_mask;
+      evmask = update_evmask_for_button_motion (evmask, mask);
+
+      if (evmask & type_masks[type])
+	return w;
+
+      if (crossing_event)
+	break;
+
+      w = gdk_window_get_parent (w);
+    }
+
+  if (display->pointer_grab.window != NULL &&
+      display->pointer_grab.owner_events)
+    {
+      evmask = display->pointer_grab.event_mask;
+      evmask = update_evmask_for_button_motion (evmask, mask);
+
+      if ((evmask & type_masks[type]) &&
+	  (!crossing_event || window == display->pointer_grab.window))
+	return display->pointer_grab.window;
+      else
+	return NULL;
+    }
+
+  return NULL;
+}
+
+
+static gboolean
+is_button_type (GdkEventType type)
 {
-  /* offset back */
-  gdk_gc_offset (gc, data->x_offset, data->y_offset);
+  return type == GDK_BUTTON_PRESS ||
+         type == GDK_2BUTTON_PRESS ||
+         type == GDK_3BUTTON_PRESS ||
+         type == GDK_BUTTON_RELEASE ||
+         type == GDK_SCROLL;
+}
 
-  /* reset old clip */
-  gdk_gc_set_clip_region (gc, data->old_region);
-  if (data->old_region)
-    gdk_region_destroy (data->old_region);
-  gdk_gc_set_clip_origin (gc, data->old_clip_x_origin, data->old_clip_y_origin);
+static gboolean
+is_motion_type (GdkEventType type)
+{
+  return type == GDK_MOTION_NOTIFY ||
+         type == GDK_ENTER_NOTIFY ||
+         type == GDK_LEAVE_NOTIFY;
 }
 
-static void
-gdk_window_redirect_free (GdkWindowRedirect *redirect)
+static GdkWindow *
+find_common_ancestor (GdkWindow *win1,
+		      GdkWindow *win2)
 {
-  g_object_unref (redirect->pixmap);
-  g_free (redirect);
+  GdkWindowObject *tmp;
+  GList *path1 = NULL, *path2 = NULL;
+  GList *list1, *list2;
+
+  tmp = GDK_WINDOW_OBJECT (win1);
+  while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
+    {
+      path1 = g_list_prepend (path1, tmp);
+      tmp = tmp->parent;
+    }
+
+  tmp = GDK_WINDOW_OBJECT (win2);
+  while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
+    {
+      path2 = g_list_prepend (path2, tmp);
+      tmp = tmp->parent;
+    }
+
+  list1 = path1;
+  list2 = path2;
+  tmp = NULL;
+  while (list1 && list2 && (list1->data == list2->data))
+    {
+      tmp = (GdkWindowObject *)list1->data;
+      list1 = g_list_next (list1);
+      list2 = g_list_next (list2);
+    }
+  g_list_free (path1);
+  g_list_free (path2);
+
+  return GDK_WINDOW (tmp);
+}
+
+GdkEvent *
+_gdk_make_event (GdkWindow    *window,
+		 GdkEventType  type,
+		 GdkEvent     *event_in_queue,
+		 gboolean      before_event)
+{
+  GdkEvent *event = gdk_event_new (type);
+  guint32 the_time;
+  GdkModifierType the_state;
+
+  the_time = gdk_event_get_time (event_in_queue);
+  gdk_event_get_state (event_in_queue, &the_state);
+
+  event->any.window = g_object_ref (window);
+  event->any.send_event = FALSE;
+
+  switch (type)
+    {
+    case GDK_MOTION_NOTIFY:
+      event->motion.time = the_time;
+      event->motion.axes = NULL;
+      event->motion.state = the_state;
+      break;
+
+    case GDK_BUTTON_PRESS:
+    case GDK_2BUTTON_PRESS:
+    case GDK_3BUTTON_PRESS:
+    case GDK_BUTTON_RELEASE:
+      event->button.time = the_time;
+      event->button.axes = NULL;
+      event->button.state = the_state;
+      break;
+
+    case GDK_SCROLL:
+      event->scroll.time = the_time;
+      event->scroll.state = the_state;
+      break;
+
+    case GDK_KEY_PRESS:
+    case GDK_KEY_RELEASE:
+      event->key.time = the_time;
+      event->key.state = the_state;
+      break;
+
+    case GDK_ENTER_NOTIFY:
+    case GDK_LEAVE_NOTIFY:
+      event->crossing.time = the_time;
+      event->crossing.state = the_state;
+      break;
+
+    case GDK_PROPERTY_NOTIFY:
+      event->property.time = the_time;
+      event->property.state = the_state;
+      break;
+
+    case GDK_SELECTION_CLEAR:
+    case GDK_SELECTION_REQUEST:
+    case GDK_SELECTION_NOTIFY:
+      event->selection.time = the_time;
+      break;
+
+    case GDK_PROXIMITY_IN:
+    case GDK_PROXIMITY_OUT:
+      event->proximity.time = the_time;
+      break;
+
+    case GDK_DRAG_ENTER:
+    case GDK_DRAG_LEAVE:
+    case GDK_DRAG_MOTION:
+    case GDK_DRAG_STATUS:
+    case GDK_DROP_START:
+    case GDK_DROP_FINISHED:
+      event->dnd.time = the_time;
+      break;
+
+    case GDK_FOCUS_CHANGE:
+    case GDK_CONFIGURE:
+    case GDK_MAP:
+    case GDK_UNMAP:
+    case GDK_CLIENT_EVENT:
+    case GDK_VISIBILITY_NOTIFY:
+    case GDK_NO_EXPOSE:
+    case GDK_DELETE:
+    case GDK_DESTROY:
+    case GDK_EXPOSE:
+    default:
+      break;
+    }
+
+  if (event_in_queue)
+    {
+    if (before_event)
+      _gdk_event_queue_insert_before (gdk_drawable_get_display (window), event_in_queue, event);
+    else
+      _gdk_event_queue_insert_after (gdk_drawable_get_display (window), event_in_queue, event);
+    }
+  else
+    _gdk_event_queue_append (gdk_drawable_get_display (window), event);
+
+  return event;
+}
+
+/* The coordinates are in the toplevel window that src/dest are in.
+ * src and dest are always (if != NULL) in the same toplevel, as
+ * we get a leave-notify and set the window_under_pointer to null
+ * before crossing to another toplevel.
+ */
+void
+_gdk_syntesize_crossing_events (GdkDisplay                 *display,
+				GdkWindow                  *src,
+				GdkWindow                  *dest,
+				GdkCrossingMode             mode,
+				gint                        toplevel_x,
+				gint                        toplevel_y,
+				GdkModifierType             mask,
+				guint32                     time_,
+				gboolean                    do_first,
+				gboolean                    do_last)
+{
+  GdkWindow *c;
+  GdkWindow *win, *last, *next;
+  GdkEvent *event;
+  GList *path, *list;
+  gboolean non_linear;
+  GdkWindow *a;
+  GdkWindow *b;
+  GdkWindow *event_win;
+
+  /* TODO: Don't send events to toplevel, as we get those from the windowing system */
+  
+  a = src;
+  b = dest;
+  if (a == b)
+    return; /* No crossings generated between src and dest */
+  
+  c = find_common_ancestor (a, b);
+  non_linear = (c != a) && (c != b);
+
+  if (a) /* There might not be a source (i.e. if no previous pointer_in_window) */
+    {
+      /* Traverse up from a to (excluding) c sending leave events */
+
+      event_win = get_target_window_for_pointer_event (display, a, GDK_LEAVE_NOTIFY, mask);
+      if (do_first && event_win)
+	{
+	  event = _gdk_make_event (event_win, GDK_LEAVE_NOTIFY, NULL, FALSE);
+	  event->crossing.time = time_;
+	  event->crossing.subwindow = NULL;
+	  convert_toplevel_coords_to_window (event_win,
+					     toplevel_x, toplevel_y,
+					     &event->crossing.x, &event->crossing.y);
+	  event->crossing.x_root = toplevel_x;
+	  event->crossing.y_root = toplevel_y;
+	  event->crossing.mode = mode;
+	  if (non_linear)
+	    event->crossing.detail = GDK_NOTIFY_NONLINEAR;
+	  else if (c == a)
+	    event->crossing.detail = GDK_NOTIFY_INFERIOR;
+	  else
+	    event->crossing.detail = GDK_NOTIFY_ANCESTOR;
+	  event->crossing.focus = FALSE;
+	  event->crossing.state = mask;
+	}
+      
+      if (c != a)
+	{
+	  last = a;
+	  win = GDK_WINDOW (GDK_WINDOW_OBJECT (a)->parent);
+	  while (win != c && GDK_WINDOW_TYPE (win) != GDK_WINDOW_ROOT)
+	    {
+	      event_win = get_target_window_for_pointer_event (display, win, GDK_LEAVE_NOTIFY, mask);
+	      if (event_win)
+		{
+		  event = _gdk_make_event (event_win, GDK_LEAVE_NOTIFY, NULL, FALSE);
+		  event->crossing.time = time_;
+		  event->crossing.subwindow = g_object_ref (last);
+		  convert_toplevel_coords_to_window (event_win,
+						     toplevel_x, toplevel_y,
+						     &event->crossing.x, &event->crossing.y);
+		  event->crossing.x_root = toplevel_x;
+		  event->crossing.y_root = toplevel_y;
+		  event->crossing.mode = mode;
+		  if (non_linear)
+		    event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
+		  else
+		    event->crossing.detail = GDK_NOTIFY_VIRTUAL;
+		  event->crossing.focus = FALSE;
+		  event->crossing.state = mask;
+		}
+	      last = win;
+	      win = GDK_WINDOW (GDK_WINDOW_OBJECT (win)->parent);
+	    }
+	}
+    }
+
+  if (b) /* Might not be a dest, e.g. if we're moving out of the window */
+    {
+      /* Traverse down from c to b */
+      if (c != b)
+	{
+	  path = NULL;
+	  win = GDK_WINDOW (GDK_WINDOW_OBJECT (b)->parent);
+	  while (win != c && GDK_WINDOW_TYPE (win) != GDK_WINDOW_ROOT)
+	    {
+	      path = g_list_prepend (path, win);
+	      win = GDK_WINDOW( GDK_WINDOW_OBJECT (win)->parent);
+	    }
+	  
+	  list = path;
+	  while (list)
+	    {
+	      win = (GdkWindow *)list->data;
+	      list = g_list_next (list);
+	      if (list)
+		next = (GdkWindow *)list->data;
+	      else
+		next = b;
+	      
+	      event_win = get_target_window_for_pointer_event (display, win, GDK_ENTER_NOTIFY, mask);
+	      if (event_win)
+		{
+		  event = _gdk_make_event (event_win, GDK_ENTER_NOTIFY, NULL, FALSE);
+		  event->crossing.time = time_;
+		  event->crossing.subwindow = g_object_ref (next);
+		  convert_toplevel_coords_to_window (event_win,
+						     toplevel_x, toplevel_y,
+						     &event->crossing.x, &event->crossing.y);
+		  event->crossing.x_root = toplevel_x;
+		  event->crossing.y_root = toplevel_y;
+		  event->crossing.mode = mode;
+		  if (non_linear)
+		    event->crossing.detail = GDK_NOTIFY_NONLINEAR_VIRTUAL;
+		  else
+		    event->crossing.detail = GDK_NOTIFY_VIRTUAL;
+		  event->crossing.focus = FALSE;
+		  event->crossing.state = mask;
+		}
+	    }
+	  g_list_free (path);
+	}
+      
+      event_win = get_target_window_for_pointer_event (display, b, GDK_ENTER_NOTIFY, mask);
+      if (do_last && event_win)
+	{
+	  event = _gdk_make_event (event_win, GDK_ENTER_NOTIFY, NULL, FALSE);
+	  event->crossing.time = time_;
+	  event->crossing.subwindow = NULL;
+	  convert_toplevel_coords_to_window (event_win,
+					     toplevel_x, toplevel_y,
+					     &event->crossing.x, &event->crossing.y);
+	  event->crossing.x_root = toplevel_x;
+	  event->crossing.y_root = toplevel_y;
+	  event->crossing.mode = mode;
+	  if (non_linear)
+	    event->crossing.detail = GDK_NOTIFY_NONLINEAR;
+	  else if (c == a)
+	    event->crossing.detail = GDK_NOTIFY_ANCESTOR;
+	  else
+	    event->crossing.detail = GDK_NOTIFY_INFERIOR;
+	  event->crossing.focus = FALSE;
+	  event->crossing.state = mask;
+	}
+    }
+
+}
+
+static GdkWindow *
+get_toplevel (GdkWindow *w)
+{
+  GdkWindowObject *private = GDK_WINDOW_OBJECT (w);
+  
+  while (private->parent != NULL &&
+	 (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT))
+    private = private->parent;
+
+  return GDK_WINDOW (private);
+}
+
+void
+_gdk_syntesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
+{
+  GdkDisplay *display;
+  GdkWindow *changed_toplevel;
+  GdkWindow *pointer_toplevel;
+  GdkWindow *new_window_under_pointer;
+
+  changed_toplevel = get_toplevel (changed_window);
+  
+  display = gdk_drawable_get_display (changed_window);
+  if (display->pointer_info.window_under_pointer)
+    {
+      pointer_toplevel = get_toplevel (display->pointer_info.window_under_pointer);
+
+      if (pointer_toplevel == changed_toplevel)
+	{
+	  new_window_under_pointer =
+	    _gdk_window_find_descendant_at (pointer_toplevel,
+					    display->pointer_info.toplevel_x,
+					    display->pointer_info.toplevel_y,
+					    NULL, NULL);
+	  if (new_window_under_pointer !=
+	      display->pointer_info.window_under_pointer)
+	    {
+	      _gdk_syntesize_crossing_events (display,
+					      display->pointer_info.window_under_pointer,
+					      new_window_under_pointer,
+					      GDK_CROSSING_NORMAL,
+					      display->pointer_info.toplevel_x,
+					      display->pointer_info.toplevel_y,
+					      display->pointer_info.state,
+					      GDK_CURRENT_TIME,
+					      TRUE, TRUE);
+	      
+	      if (display->pointer_info.window_under_pointer)
+		g_object_unref (display->pointer_info.window_under_pointer);
+	      display->pointer_info.window_under_pointer = NULL;
+	      if (new_window_under_pointer)
+		display->pointer_info.window_under_pointer = g_object_ref (new_window_under_pointer);
+	    }
+	}
+    }
+}
+
+static gboolean
+proxy_pointer_event (GdkDisplay                 *display,
+		     GdkWindow                  *pointer_window,
+		     gdouble                     toplevel_x,
+                     gdouble                     toplevel_y,
+		     GdkEvent                   *source_event)
+{
+  GdkWindow *event_window;
+  GdkWindow *event_win, *cursor_window;
+  gboolean crossing_event;
+  gboolean sent_motion;
+  GdkEvent *event;
+  guint state;
+  guint32 time_;
+
+  event_window = source_event->any.window;
+  
+  gdk_event_get_state (source_event, &state);
+  time_ = gdk_event_get_time (source_event);
+
+  crossing_event =
+    source_event->type == GDK_ENTER_NOTIFY ||
+    source_event->type == GDK_LEAVE_NOTIFY;
+
+  if (crossing_event)
+    {
+      GdkEventCrossing *crossing = &source_event->crossing;
+
+      if (crossing->mode == GDK_CROSSING_GRAB)
+	{
+	  if (crossing->type == GDK_LEAVE_NOTIFY &&
+	      display->pointer_info.window_under_pointer != NULL)
+	    {
+	      _gdk_syntesize_crossing_events (display,
+					      display->pointer_info.window_under_pointer,
+					      event_window,
+					      GDK_CROSSING_GRAB,
+					      toplevel_x, toplevel_y, state, time_,
+					      TRUE, FALSE);
+	    }
+
+	  if (crossing->type == GDK_ENTER_NOTIFY &&
+	      display->pointer_grab.window != NULL)
+	    {
+	      _gdk_syntesize_crossing_events (display,
+					      event_window,
+					      display->pointer_grab.window,
+					      GDK_CROSSING_GRAB,
+					      toplevel_x, toplevel_y, state, time_,
+					      FALSE, TRUE);
+	    }
+	}
+
+      if (crossing->mode == GDK_CROSSING_UNGRAB)
+	{
+	  if (crossing->type == GDK_LEAVE_NOTIFY &&
+	      display->pointer_grab.window != NULL)
+	    {
+	      _gdk_syntesize_crossing_events (display,
+					      display->pointer_grab.window,
+					      event_window,
+					      GDK_CROSSING_UNGRAB,
+					      toplevel_x, toplevel_y, state, time_,
+					      TRUE, FALSE);
+	    }
+
+	  if (crossing->type == GDK_ENTER_NOTIFY &&
+	      display->pointer_info.window_under_pointer != NULL)
+	    {
+	      _gdk_syntesize_crossing_events (display,
+					      event_window,
+					      display->pointer_info.window_under_pointer,
+					      GDK_CROSSING_UNGRAB,
+					      toplevel_x, toplevel_y, state, time_,
+					      FALSE, TRUE);
+	    }
+	}
+    }
+
+  cursor_window = pointer_window;
+  if (display->pointer_grab.window &&
+      (pointer_window == NULL ||
+       !is_parent_of (display->pointer_grab.window, pointer_window)))
+    cursor_window = display->pointer_grab.window;
+
+  /* TODO: set cursor from cursor_window, or grab cursor */
+
+  sent_motion = FALSE;
+  if (!crossing_event &&
+      (display->pointer_info.window_under_pointer == pointer_window ||
+       (display->pointer_grab.window != NULL &&
+	!display->pointer_grab.owner_events)))
+    {
+      /* send motion events */
+      event_win = get_target_window_for_pointer_event (display, pointer_window, GDK_MOTION_NOTIFY, state);
+      if (event_win)
+	{
+	  sent_motion = TRUE;
+	  event = _gdk_make_event (event_win, GDK_MOTION_NOTIFY, source_event, FALSE);
+	  event->motion.time = time_;
+	  convert_toplevel_coords_to_window (event_win,
+					     toplevel_x, toplevel_y,
+					     &event->motion.x, &event->motion.y);
+	  event->motion.x_root = toplevel_x; /* TODO: right? */
+	  event->motion.y_root = toplevel_y;
+	  event->motion.state = state;
+	  event->motion.is_hint = FALSE;
+	  event->motion.device = NULL;
+	  if (source_event && source_event->type == GDK_MOTION_NOTIFY)
+	    event->motion.device = source_event->motion.device;
+	}
+    }
+
+  _gdk_syntesize_crossing_events (display,
+				  display->pointer_info.window_under_pointer,
+				  pointer_window,
+				  GDK_CROSSING_NORMAL,
+				  toplevel_x, toplevel_y,
+				  state, time_,
+				  TRUE, TRUE);
+
+  /* unlink move event from parent if we sent a motion event */
+  return source_event->type == GDK_MOTION_NOTIFY && sent_motion;
+}
+
+static gboolean
+proxy_button_event (GdkWindow                  *pointer_window,
+		    gdouble                     toplevel_x,
+                    gdouble                     toplevel_y,
+		    GdkEvent                   *source_event)
+{
+  GdkWindow *event_win;
+  GdkEvent *event;
+  guint state;
+  guint32 time_;
+  GdkEventType type;
+  GdkDisplay *display;
+
+  type = source_event->any.type;
+  gdk_event_get_state (source_event, &state);
+  time_ = gdk_event_get_time (source_event);
+  display = gdk_drawable_get_display (source_event->any.window);
+  
+  if ((type == GDK_BUTTON_PRESS || type == GDK_SCROLL) &&
+      pointer_window != NULL &&
+      display->pointer_grab.window == source_event->any.window &&
+      display->pointer_grab.implicit &&
+      !display->pointer_grab.converted_implicit)
+    {
+      if (pointer_window != source_event->any.window)
+	_gdk_display_set_has_pointer_grab (display,
+					   pointer_window,
+					   display->pointer_grab.native_window,
+					   display->pointer_grab.owner_events,
+					   gdk_window_get_events (pointer_window),
+					   display->pointer_grab.serial,
+					   display->pointer_grab.time,
+					   display->pointer_grab.implicit);
+      display->pointer_grab.converted_implicit = TRUE;
+    }
+
+  event_win = get_target_window_for_pointer_event (display,
+						   pointer_window,
+                                                   type,
+                                                   state);
+
+  if (event_win == NULL)
+    return TRUE;
+  
+  if (event_win != source_event->any.window)
+    {
+       event = _gdk_make_event (event_win, type, source_event, FALSE);
+
+      switch (type)
+        {
+        case GDK_BUTTON_PRESS:
+        case GDK_BUTTON_RELEASE:
+          event->button.button = source_event->button.button;
+	  convert_toplevel_coords_to_window (event_win,
+					     toplevel_x, toplevel_y,
+					     &event->button.x, &event->button.y);
+          event->button.x_root = toplevel_x;
+          event->button.y_root = toplevel_y;
+          event->button.state = state;
+          event->button.device = source_event->button.device;
+
+	  if (type == GDK_BUTTON_PRESS)
+	    _gdk_event_button_generate (display, event);
+          return TRUE;
+
+        case GDK_SCROLL:
+          event->scroll.direction = source_event->scroll.direction;
+	  convert_toplevel_coords_to_window (event_win,
+					     toplevel_x, toplevel_y,
+					     &event->scroll.x, &event->scroll.y);
+          event->scroll.x_root = toplevel_x;
+          event->scroll.y_root = toplevel_y;
+          event->scroll.state = state;
+          event->scroll.device = source_event->scroll.device;
+          return TRUE;
+
+        default:
+          return FALSE;
+        }
+    }
+  else
+    {
+      /* Same window as original window, keep the event */
+      if (source_event->type == GDK_BUTTON_PRESS)
+	_gdk_event_button_generate (display, source_event);
+      return FALSE;
+    }
+}
+
+void
+_gdk_windowing_got_event (GdkDisplay *display,
+			  GList      *event_link,
+			  GdkEvent   *event)
+{
+  GdkWindow *event_window;
+  GdkWindow *pointer_window;
+  GdkWindowObject *event_private;
+  gdouble x, y, child_x, child_y;
+  gboolean unlink_event;
+
+  event_window = event->any.window;
+  if (!event_window)
+    return;
+  
+  event_private = GDK_WINDOW_OBJECT (event_window);
+
+  if (!(is_button_type (event->type) ||
+	is_motion_type (event->type)))
+    return;
+
+  /* We should only get these events on toplevel windows */
+  g_assert (GDK_WINDOW_TYPE (event_private->parent) == GDK_WINDOW_ROOT);
+  
+  gdk_event_get_coords (event, &x, &y);
+  pointer_window = _gdk_window_find_descendant_at (event_window, x, y,
+						   &child_x,
+						   &child_y);
+  unlink_event = FALSE;
+  if (is_motion_type (event->type))
+    unlink_event = proxy_pointer_event (display,
+					pointer_window,
+					x, y,
+                                        event);
+  else if (is_button_type (event->type))
+    unlink_event = proxy_button_event (pointer_window, x, y,
+                                       event);
+
+  if (unlink_event)
+    {
+      _gdk_event_queue_remove_link (display, event_link);
+      g_list_free_1 (event_link);
+      gdk_event_free (event);
+    }
+
+
+  /* Store last pointer window and position/state */
+
+  display->pointer_info.toplevel_x = x;
+  display->pointer_info.toplevel_y = y;
+  gdk_event_get_state (event, &display->pointer_info.state);
+  
+  if (pointer_window != display->pointer_info.window_under_pointer)
+    {
+      if (display->pointer_info.window_under_pointer)
+	g_object_unref (display->pointer_info.window_under_pointer);
+      display->pointer_info.window_under_pointer = NULL;
+      if (pointer_window)
+	display->pointer_info.window_under_pointer = g_object_ref (pointer_window);
+    }
 }
 
 #define __GDK_WINDOW_C__
diff --git a/gdk/gdkwindow.h b/gdk/gdkwindow.h
index 866bb69..706d768 100644
--- a/gdk/gdkwindow.h
+++ b/gdk/gdkwindow.h
@@ -37,10 +37,12 @@
 
 G_BEGIN_DECLS
 
-typedef struct _GdkGeometry           GdkGeometry;
-typedef struct _GdkWindowAttr	      GdkWindowAttr;
-typedef struct _GdkPointerHooks	      GdkPointerHooks;
-typedef struct _GdkWindowRedirect     GdkWindowRedirect;
+typedef struct _GdkGeometry                GdkGeometry;
+typedef struct _GdkWindowAttr              GdkWindowAttr;
+typedef struct _GdkPointerHooks            GdkPointerHooks;
+typedef struct _GdkOffscreenChildHooks     GdkOffscreenChildHooks;
+typedef struct _GdkWindowRedirect          GdkWindowRedirect;
+typedef struct _GdkWindowPaint             GdkWindowPaint;
 
 /* Classes of windows.
  *   InputOutput: Almost every window should be of this type. Such windows
@@ -77,7 +79,8 @@ typedef enum
   GDK_WINDOW_CHILD,
   GDK_WINDOW_DIALOG,
   GDK_WINDOW_TEMP,
-  GDK_WINDOW_FOREIGN
+  GDK_WINDOW_FOREIGN,
+  GDK_WINDOW_OFFSCREEN
 } GdkWindowType;
 
 /* Window attribute mask values.
@@ -248,6 +251,20 @@ struct _GdkPointerHooks
                                    gint            *win_y);
 };
 
+struct _GdkOffscreenChildHooks
+{
+  void       (*from_parent) (GdkWindow *offscreen_child,
+			     gdouble    parent_x,
+			     gdouble    parent_y,
+			     gdouble   *child_x,
+			     gdouble   *child_y);
+  void       (*to_parent)   (GdkWindow *offscreen_child,
+			     gdouble    child_x,
+			     gdouble    child_y,
+			     gdouble   *parent_x,
+			     gdouble   *parent_y);
+};
+
 typedef struct _GdkWindowObject GdkWindowObject;
 typedef struct _GdkWindowObjectClass GdkWindowObjectClass;
 
@@ -307,6 +324,19 @@ struct _GdkWindowObject
   guint update_and_descendants_freeze_count;
 
   GdkWindowRedirect *redirect;
+  const GdkOffscreenChildHooks *offscreen_hooks;
+
+  int abs_x, abs_y; /* Absolute offset in impl */
+  gint width, height;
+  GdkRegion *clip_region; /* Clip region (wrt toplevel) in window coords */
+  GdkRegion *clip_region_with_children; /* Clip region in window coords */
+  GdkColormap *colormap;
+  GdkCursor *cursor;
+  gint8 toplevel_window_type;
+
+  GdkWindowPaint *implicit_paint;
+  
+  cairo_surface_t *cairo_surface;
 };
 
 struct _GdkWindowObjectClass
@@ -645,12 +675,21 @@ GdkPointerHooks *gdk_set_pointer_hooks (const GdkPointerHooks *new_hooks);
 
 GdkWindow *gdk_get_default_root_window (void);
 
-void gdk_window_redirect_to_drawable (GdkWindow *window,
-				      GdkDrawable *drawable,
-				      gint src_x, gint src_y,
-				      gint dest_x, gint dest_y,
-				      gint width, gint height);
-void gdk_window_remove_redirection   (GdkWindow *window);
+/* Offscreen redirection */
+GdkPixmap *gdk_window_get_offscreen_pixmap   (GdkWindow     *window);
+
+void       gdk_window_redirect_to_drawable   (GdkWindow     *window,
+                                              GdkDrawable   *drawable,
+                                              gint           src_x,
+                                              gint           src_y,
+                                              gint           dest_x,
+                                              gint           dest_y,
+                                              gint           width,
+                                              gint           height);
+void       gdk_window_remove_redirection     (GdkWindow     *window);
+
+void       gdk_window_set_offscreen_hooks    (GdkWindow                    *offscreen_window,
+                                              const GdkOffscreenChildHooks *hooks);
 
 #ifndef GDK_DISABLE_DEPRECATED
 #define GDK_ROOT_PARENT()             (gdk_get_default_root_window ())
diff --git a/gdk/gdkwindowimpl.h b/gdk/gdkwindowimpl.h
index f9f97b6..f9218b9 100644
--- a/gdk/gdkwindowimpl.h
+++ b/gdk/gdkwindowimpl.h
@@ -56,14 +56,6 @@ struct _GdkWindowImplIface
                                          gint             y,
                                          gint             width,
                                          gint             height);
-  void         (* move_region)          (GdkWindow       *window,
-                                         const GdkRegion *region,
-                                         gint             dx,
-                                         gint             dy);
-  void         (* scroll)               (GdkWindow       *window,
-                                         gint             dx,
-                                         gint             dy);
-
   void         (* clear_area)           (GdkWindow       *window,
                                          gint             x,
                                          gint             y,
@@ -73,8 +65,7 @@ struct _GdkWindowImplIface
   void         (* set_background)       (GdkWindow       *window,
                                          const GdkColor  *color);
   void         (* set_back_pixmap)      (GdkWindow       *window,
-                                         GdkPixmap       *pixmap,
-                                         gboolean         parent_relative);
+                                         GdkPixmap       *pixmap);
 
   GdkEventMask (* get_events)           (GdkWindow       *window);
   void         (* set_events)           (GdkWindow       *window,
@@ -97,9 +88,6 @@ struct _GdkWindowImplIface
   gint         (* get_origin)           (GdkWindow       *window,
                                          gint            *x,
                                          gint            *y);
-  void         (* get_offsets)          (GdkWindow       *window,
-                                         gint            *x_offset,
-                                         gint            *y_offset);
 
   void         (* shape_combine_mask)   (GdkWindow       *window,
                                          GdkBitmap       *mask,
@@ -114,11 +102,38 @@ struct _GdkWindowImplIface
 
   gboolean     (* set_static_gravities) (GdkWindow       *window,
 				         gboolean         use_static);
+
+  /* Called before processing updates for a window. This gives the windowing
+   * layer a chance to save the region for later use in avoiding duplicate
+   * exposes. The return value indicates whether the function has a saved
+   * the region; if the result is TRUE, then the windowing layer is responsible
+   * for destroying the region later.
+   */
+  gboolean     (* queue_antiexpose)     (GdkWindow       *window,
+					 GdkRegion       *update_area);
 };
 
 /* Interface Functions */
 GType gdk_window_impl_get_type (void) G_GNUC_CONST;
 
+/* private definitions from gdkwindow.h */
+
+struct _GdkWindowRedirect
+{
+  GdkWindowObject *redirected;
+  GdkDrawable *pixmap;
+
+  gint src_x;
+  gint src_y;
+  gint dest_x;
+  gint dest_y;
+  gint width;
+  gint height;
+
+  GdkRegion *damage;
+  guint damage_idle;
+};
+
 G_END_DECLS
 
 #endif /* __GDK_WINDOW_IMPL_H__ */
diff --git a/gdk/quartz/gdkpixmap-quartz.c b/gdk/quartz/gdkpixmap-quartz.c
index e55ff9d..a743480 100644
--- a/gdk/quartz/gdkpixmap-quartz.c
+++ b/gdk/quartz/gdkpixmap-quartz.c
@@ -137,10 +137,10 @@ data_provider_release (void *info, const void *data, size_t size)
 }
 
 GdkPixmap*
-gdk_pixmap_new (GdkDrawable *drawable,
-		gint         width,
-		gint         height,
-		gint         depth)
+_gdk_pixmap_new (GdkDrawable *drawable,
+                 gint         width,
+                 gint         height,
+                 gint         depth)
 {
   GdkPixmap *pixmap;
   GdkDrawableImplQuartz *draw_impl;
@@ -224,10 +224,10 @@ gdk_pixmap_new (GdkDrawable *drawable,
 }
 
 GdkPixmap *
-gdk_bitmap_create_from_data (GdkDrawable *window,
-			     const gchar *data,
-			     gint         width,
-			     gint         height)
+_gdk_bitmap_create_from_data (GdkDrawable *window,
+                              const gchar *data,
+                              gint         width,
+                              gint         height)
 {
   GdkPixmap *pixmap;
   GdkPixmapImplQuartz *impl;
@@ -264,13 +264,13 @@ gdk_bitmap_create_from_data (GdkDrawable *window,
 }
 
 GdkPixmap*
-gdk_pixmap_create_from_data (GdkDrawable    *drawable,
-			     const gchar    *data,
-			     gint            width,
-			     gint            height,
-			     gint            depth,
-			     const GdkColor *fg,
-			     const GdkColor *bg)
+_gdk_pixmap_create_from_data (GdkDrawable    *drawable,
+                              const gchar    *data,
+                              gint            width,
+                              gint            height,
+                              gint            depth,
+                              const GdkColor *fg,
+                              const GdkColor *bg)
 {	
   /* FIXME: Implement */
   return NULL;
diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c
index c51a495..37199c3 100644
--- a/gdk/x11/gdkdisplay-x11.c
+++ b/gdk/x11/gdkdisplay-x11.c
@@ -600,7 +600,7 @@ _gdk_x11_display_is_root_window (GdkDisplay *display,
  */
 void
 gdk_display_pointer_ungrab (GdkDisplay *display,
-			    guint32     time)
+			    guint32     time_)
 {
   Display *xdisplay;
   GdkDisplayX11 *display_x11;
@@ -610,33 +610,19 @@ gdk_display_pointer_ungrab (GdkDisplay *display,
   display_x11 = GDK_DISPLAY_X11 (display);
   xdisplay = GDK_DISPLAY_XDISPLAY (display);
   
-  _gdk_input_ungrab_pointer (display, time);
-  XUngrabPointer (xdisplay, time);
+  _gdk_input_ungrab_pointer (display, time_);
+  XUngrabPointer (xdisplay, time_);
   XFlush (xdisplay);
 
-  if (time == GDK_CURRENT_TIME || 
-      display_x11->pointer_xgrab_time == GDK_CURRENT_TIME ||
-      !XSERVER_TIME_IS_LATER (display_x11->pointer_xgrab_time, time))
-    display_x11->pointer_xgrab_window = NULL;
-}
-
-/**
- * gdk_display_pointer_is_grabbed:
- * @display: a #GdkDisplay
- *
- * Test if the pointer is grabbed.
- *
- * Returns: %TRUE if an active X pointer grab is in effect
- *
- * Since: 2.2
- */
-gboolean
-gdk_display_pointer_is_grabbed (GdkDisplay *display)
-{
-  g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
-  
-  return (GDK_DISPLAY_X11 (display)->pointer_xgrab_window != NULL &&
-	  !GDK_DISPLAY_X11 (display)->pointer_xgrab_implicit);
+  if (time_ == GDK_CURRENT_TIME ||
+      display->pointer_grab.time == GDK_CURRENT_TIME ||
+      !XSERVER_TIME_IS_LATER (display->pointer_grab.time, time_))
+    {
+      _gdk_display_unset_has_pointer_grab (display,
+					   FALSE,
+					   FALSE,
+					   time_);
+    }
 }
 
 /**
@@ -1335,7 +1321,9 @@ gdk_display_store_clipboard (GdkDisplay    *display,
 {
   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
   Atom clipboard_manager, save_targets;
-  
+
+  g_return_if_fail (GDK_WINDOW_IS_X11 (clipboard_window));
+
   clipboard_manager = gdk_x11_get_xatom_by_name_for_display (display, "CLIPBOARD_MANAGER");
   save_targets = gdk_x11_get_xatom_by_name_for_display (display, "SAVE_TARGETS");
 
diff --git a/gdk/x11/gdkdisplay-x11.h b/gdk/x11/gdkdisplay-x11.h
index 0ade8f0..619a1ad 100644
--- a/gdk/x11/gdkdisplay-x11.h
+++ b/gdk/x11/gdkdisplay-x11.h
@@ -30,6 +30,7 @@
 #include <gdk/gdkdisplay.h>
 #include <gdk/gdkkeys.h>
 #include <gdk/gdkwindow.h>
+#include <gdk/gdkinternals.h>
 #include <gdk/gdk.h>		/* For gdk_get_program_class() */
 
 G_BEGIN_DECLS
@@ -93,17 +94,14 @@ struct _GdkDisplayX11
    * (grabs, properties etc.) Otherwise always TRUE. */
   gboolean trusted_client;
 
-  /* Information about current pointer and keyboard grabs held by this
-   * client. If gdk_pointer_xgrab_window or gdk_keyboard_xgrab_window
+  /* Information about current keyboard grabs held by this
+   * client. If gdk_keyboard_xgrab_window
    * window is NULL, then the other associated fields are ignored
+   * Pointer grab info is stored in GdkDisplay.
    */
-  GdkWindowObject *pointer_xgrab_window;
-  gulong pointer_xgrab_serial;
-  gboolean pointer_xgrab_owner_events;
-  gboolean pointer_xgrab_implicit;
-  guint32 pointer_xgrab_time;
 
   GdkWindowObject *keyboard_xgrab_window;
+  GdkWindowObject *keyboard_xgrab_native_window;
   gulong keyboard_xgrab_serial;
   gboolean keyboard_xgrab_owner_events;
   guint32 keyboard_xgrab_time;
@@ -169,6 +167,9 @@ struct _GdkDisplayX11
 
   /* Alpha mask picture format */
   XRenderPictFormat *mask_format;
+
+  /* The offscreen window that has the pointer in it (if any) */
+  GdkWindow *active_offscreen_window;
 };
 
 struct _GdkDisplayX11Class
diff --git a/gdk/x11/gdkdnd-x11.c b/gdk/x11/gdkdnd-x11.c
index 942ad91..a43bac0 100644
--- a/gdk/x11/gdkdnd-x11.c
+++ b/gdk/x11/gdkdnd-x11.c
@@ -2987,6 +2987,7 @@ gdk_drag_begin (GdkWindow     *window,
   GdkDragContext *new_context;
   
   g_return_val_if_fail (window != NULL, NULL);
+  g_return_val_if_fail (GDK_WINDOW_IS_X11 (window), NULL);
 
   new_context = gdk_drag_context_new ();
   new_context->is_source = TRUE;
@@ -3192,7 +3193,7 @@ gdk_drag_find_window_for_screen (GdkDragContext  *context,
   window_cache = drag_context_find_window_cache (context, screen);
 
   dest = get_client_window_at_coords (window_cache,
-				      drag_window ? 
+				      drag_window && GDK_WINDOW_IS_X11 (drag_window) ? 
 				      GDK_DRAWABLE_XID (drag_window) : None,
 				      x_root, y_root);
 
@@ -3262,6 +3263,7 @@ gdk_drag_motion (GdkDragContext *context,
   GdkDragContextPrivateX11 *private = PRIVATE_DATA (context);
 
   g_return_val_if_fail (context != NULL, FALSE);
+  g_return_val_if_fail (dest_window == NULL || GDK_WINDOW_IS_X11 (dest_window), FALSE);
 
   private->old_actions = context->actions;
   context->actions = possible_actions;
diff --git a/gdk/x11/gdkdrawable-x11.c b/gdk/x11/gdkdrawable-x11.c
index a19c7a2..1c40568 100644
--- a/gdk/x11/gdkdrawable-x11.c
+++ b/gdk/x11/gdkdrawable-x11.c
@@ -870,7 +870,17 @@ gdk_x11_drawable_get_xid (GdkDrawable *drawable)
   GdkDrawable *impl;
   
   if (GDK_IS_WINDOW (drawable))
-    impl = ((GdkPixmapObject *)drawable)->impl;
+    {
+      if (!GDK_WINDOW_IS_X11 (drawable))
+        {
+	  /* TODO: At this point we could convert a virtual window
+	     to a native one (unless its in an offscreen window) */
+          g_warning (G_STRLOC " drawable is not a native X11 window");
+          return None;
+        }
+
+      impl = ((GdkPixmapObject *)drawable)->impl;
+    }
   else if (GDK_IS_PIXMAP (drawable))
     impl = ((GdkPixmapObject *)drawable)->impl;
   else
@@ -1447,6 +1457,45 @@ gdk_x11_cairo_surface_destroy (void *data)
   impl->cairo_surface = NULL;
 }
 
+void
+_gdk_windowing_set_cairo_surface_size (cairo_surface_t *surface,
+				       int width,
+				       int height)
+{
+  cairo_xlib_surface_set_size (surface, width, height);
+}
+
+cairo_surface_t *
+_gdk_windowing_create_cairo_surface (GdkDrawable *drawable,
+				     int width,
+				     int height)
+{
+  GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
+  GdkVisual *visual;
+    
+  visual = gdk_drawable_get_visual (drawable);
+  if (visual) 
+    return cairo_xlib_surface_create (GDK_SCREEN_XDISPLAY (impl->screen),
+				      impl->xid,
+				      GDK_VISUAL_XVISUAL (visual),
+				      width, height);
+  else if (gdk_drawable_get_depth (drawable) == 1)
+    return cairo_xlib_surface_create_for_bitmap (GDK_SCREEN_XDISPLAY (impl->screen),
+						    impl->xid,
+						    GDK_SCREEN_XSCREEN (impl->screen),
+						    width, height);
+  else
+    {
+      g_warning ("Using Cairo rendering requires the drawable argument to\n"
+		 "have a specified colormap. All windows have a colormap,\n"
+		 "however, pixmaps only have colormap by default if they\n"
+		 "were created with a non-NULL window argument. Otherwise\n"
+		 "a colormap must be set on them with gdk_drawable_set_colormap");
+      return NULL;
+    }
+  
+}
+
 static cairo_surface_t *
 gdk_x11_ref_cairo_surface (GdkDrawable *drawable)
 {
@@ -1458,35 +1507,15 @@ gdk_x11_ref_cairo_surface (GdkDrawable *drawable)
 
   if (!impl->cairo_surface)
     {
-      GdkVisual *visual = NULL;
       int width, height;
   
-      visual = gdk_drawable_get_visual (drawable);
-
       gdk_drawable_get_size (drawable, &width, &height);
 
-      if (visual) 
-	impl->cairo_surface = cairo_xlib_surface_create (GDK_SCREEN_XDISPLAY (impl->screen),
-							 impl->xid,
-							 GDK_VISUAL_XVISUAL (visual),
-							 width, height);
-      else if (gdk_drawable_get_depth (drawable) == 1)
-	impl->cairo_surface = cairo_xlib_surface_create_for_bitmap (GDK_SCREEN_XDISPLAY (impl->screen),
-								    impl->xid,
-								    GDK_SCREEN_XSCREEN (impl->screen),
-								    width, height);
-      else
-	{
-	  g_warning ("Using Cairo rendering requires the drawable argument to\n"
-		     "have a specified colormap. All windows have a colormap,\n"
-		     "however, pixmaps only have colormap by default if they\n"
-		     "were created with a non-NULL window argument. Otherwise\n"
-		     "a colormap must be set on them with gdk_drawable_set_colormap");
-	  return NULL;
-	}
-
-      cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
-				   drawable, gdk_x11_cairo_surface_destroy);
+      impl->cairo_surface = _gdk_windowing_create_cairo_surface (drawable, width, height);
+      
+      if (impl->cairo_surface)
+	cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
+				     drawable, gdk_x11_cairo_surface_destroy);
     }
   else
     cairo_surface_reference (impl->cairo_surface);
diff --git a/gdk/x11/gdkevents-x11.c b/gdk/x11/gdkevents-x11.c
index 096c170..b2a438c 100644
--- a/gdk/x11/gdkevents-x11.c
+++ b/gdk/x11/gdkevents-x11.c
@@ -313,7 +313,7 @@ gdk_event_get_graphics_expose (GdkWindow *window)
   GdkEvent *event;
   
   g_return_val_if_fail (window != NULL, NULL);
-  
+
   XIfEvent (GDK_WINDOW_XDISPLAY (window), &xevent, 
 	    graphics_expose_predicate, (XPointer) window);
   
@@ -879,7 +879,6 @@ gdk_event_translate (GdkDisplay *display,
   GdkWindow *filter_window;
   GdkWindowImplX11 *window_impl = NULL;
   gboolean return_val;
-  gint xoffset, yoffset;
   GdkScreen *screen = NULL;
   GdkScreenX11 *screen_x11 = NULL;
   GdkToplevelX11 *toplevel = NULL;
@@ -942,6 +941,14 @@ gdk_event_translate (GdkDisplay *display,
     
   if (window != NULL)
     {
+      /* Rewrite keyboard grabs to offscreen windows */
+      if ((xevent->type == KeyPress || xevent->type == KeyRelease) &&
+          window_private == display_x11->keyboard_xgrab_native_window)
+        {
+          window_private = display_x11->keyboard_xgrab_window;
+          window = (GdkWindow *) window_private;
+        }
+
       window_impl = GDK_WINDOW_IMPL_X11 (window_private->impl);
       
       /* Move key events on focus window to the real toplevel, and
@@ -1041,16 +1048,6 @@ gdk_event_translate (GdkDisplay *display,
 
   return_val = TRUE;
 
-  if (window)
-    {
-      _gdk_x11_window_get_offsets (window, &xoffset, &yoffset);
-    }
-  else
-    {
-      xoffset = 0;
-      yoffset = 0;
-    }
-
   switch (xevent->type)
     {
     case KeyPress:
@@ -1129,8 +1126,8 @@ gdk_event_translate (GdkDisplay *display,
 
 	  event->scroll.window = window;
 	  event->scroll.time = xevent->xbutton.time;
-	  event->scroll.x = xevent->xbutton.x + xoffset;
-	  event->scroll.y = xevent->xbutton.y + yoffset;
+	  event->scroll.x = xevent->xbutton.x;
+	  event->scroll.y = xevent->xbutton.y;
 	  event->scroll.x_root = (gfloat)xevent->xbutton.x_root;
 	  event->scroll.y_root = (gfloat)xevent->xbutton.y_root;
 	  event->scroll.state = (GdkModifierType) xevent->xbutton.state;
@@ -1148,8 +1145,8 @@ gdk_event_translate (GdkDisplay *display,
 	  event->button.type = GDK_BUTTON_PRESS;
 	  event->button.window = window;
 	  event->button.time = xevent->xbutton.time;
-	  event->button.x = xevent->xbutton.x + xoffset;
-	  event->button.y = xevent->xbutton.y + yoffset;
+	  event->button.x = xevent->xbutton.x;
+	  event->button.y = xevent->xbutton.y;
 	  event->button.x_root = (gfloat)xevent->xbutton.x_root;
 	  event->button.y_root = (gfloat)xevent->xbutton.y_root;
 	  event->button.axes = NULL;
@@ -1162,8 +1159,6 @@ gdk_event_translate (GdkDisplay *display,
 	      return_val = FALSE;
 	      break;
 	    }
-
-	  _gdk_event_button_generate (display, event);
           break;
 	}
 
@@ -1192,14 +1187,14 @@ gdk_event_translate (GdkDisplay *display,
           xevent->xbutton.button == 6 || xevent->xbutton.button ==7)
 	{
 	  return_val = FALSE;
-	  break;
+	  goto release_out;
 	}
 
       event->button.type = GDK_BUTTON_RELEASE;
       event->button.window = window;
       event->button.time = xevent->xbutton.time;
-      event->button.x = xevent->xbutton.x + xoffset;
-      event->button.y = xevent->xbutton.y + yoffset;
+      event->button.x = xevent->xbutton.x;
+      event->button.y = xevent->xbutton.y;
       event->button.x_root = (gfloat)xevent->xbutton.x_root;
       event->button.y_root = (gfloat)xevent->xbutton.y_root;
       event->button.axes = NULL;
@@ -1210,9 +1205,10 @@ gdk_event_translate (GdkDisplay *display,
       if (!set_screen_from_root (display, event, xevent->xbutton.root))
 	{
 	  return_val = FALSE;
-	  break;
+	  goto release_out;
 	}
-
+      
+    release_out:
       _gdk_xgrab_check_button_event (window, xevent);
       break;
       
@@ -1234,8 +1230,8 @@ gdk_event_translate (GdkDisplay *display,
       event->motion.type = GDK_MOTION_NOTIFY;
       event->motion.window = window;
       event->motion.time = xevent->xmotion.time;
-      event->motion.x = xevent->xmotion.x + xoffset;
-      event->motion.y = xevent->xmotion.y + yoffset;
+      event->motion.x = xevent->xmotion.x;
+      event->motion.y = xevent->xmotion.y;
       event->motion.x_root = (gfloat)xevent->xmotion.x_root;
       event->motion.y_root = (gfloat)xevent->xmotion.y_root;
       event->motion.axes = NULL;
@@ -1304,8 +1300,8 @@ gdk_event_translate (GdkDisplay *display,
 	event->crossing.subwindow = NULL;
       
       event->crossing.time = xevent->xcrossing.time;
-      event->crossing.x = xevent->xcrossing.x + xoffset;
-      event->crossing.y = xevent->xcrossing.y + yoffset;
+      event->crossing.x = xevent->xcrossing.x;
+      event->crossing.y = xevent->xcrossing.y;
       event->crossing.x_root = xevent->xcrossing.x_root;
       event->crossing.y_root = xevent->xcrossing.y_root;
       
@@ -1399,8 +1395,8 @@ gdk_event_translate (GdkDisplay *display,
 	event->crossing.subwindow = NULL;
       
       event->crossing.time = xevent->xcrossing.time;
-      event->crossing.x = xevent->xcrossing.x + xoffset;
-      event->crossing.y = xevent->xcrossing.y + yoffset;
+      event->crossing.x = xevent->xcrossing.x;
+      event->crossing.y = xevent->xcrossing.y;
       event->crossing.x_root = xevent->xcrossing.x_root;
       event->crossing.y_root = xevent->xcrossing.y_root;
       
@@ -1596,8 +1592,8 @@ gdk_event_translate (GdkDisplay *display,
       {
 	GdkRectangle expose_rect;
 
-	expose_rect.x = xevent->xexpose.x + xoffset;
-	expose_rect.y = xevent->xexpose.y + yoffset;
+	expose_rect.x = xevent->xexpose.x;
+	expose_rect.y = xevent->xexpose.y;
 	expose_rect.width = xevent->xexpose.width;
 	expose_rect.height = xevent->xexpose.height;
 
@@ -1636,8 +1632,8 @@ gdk_event_translate (GdkDisplay *display,
             break;
           }
         
-	expose_rect.x = xevent->xgraphicsexpose.x + xoffset;
-	expose_rect.y = xevent->xgraphicsexpose.y + yoffset;
+	expose_rect.x = xevent->xgraphicsexpose.x;
+	expose_rect.y = xevent->xgraphicsexpose.y;
 	expose_rect.width = xevent->xgraphicsexpose.width;
 	expose_rect.height = xevent->xgraphicsexpose.height;
 	    
@@ -1826,9 +1822,9 @@ gdk_event_translate (GdkDisplay *display,
 			   : ""));
       if (window && GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT)
         { 
-	  window_impl->width = xevent->xconfigure.width;
-	  window_impl->height = xevent->xconfigure.height;
-	  
+	  window_private->width = xevent->xconfigure.width;
+	  window_private->height = xevent->xconfigure.height;
+
 	  _gdk_x11_drawable_update_size (window_private->impl);
 	  _gdk_x11_screen_size_changed (screen, xevent);
         }
@@ -1887,9 +1883,10 @@ gdk_event_translate (GdkDisplay *display,
 	    }
 	  window_private->x = event->configure.x;
 	  window_private->y = event->configure.y;
-	  window_impl->width = xevent->xconfigure.width;
-	  window_impl->height = xevent->xconfigure.height;
+	  window_private->width = xevent->xconfigure.width;
+	  window_private->height = xevent->xconfigure.height;
 	  
+	  _gdk_window_update_size (window);
 	  _gdk_x11_drawable_update_size (window_private->impl);
 	  
 	  if (window_private->resize_count >= 1)
@@ -2298,6 +2295,7 @@ _gdk_events_queue (GdkDisplay *display)
       if (gdk_event_translate (display, event, &xevent, FALSE))
 	{
 	  ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
+          _gdk_windowing_got_event (display, node, event);
 	}
       else
 	{
diff --git a/gdk/x11/gdkgc-x11.c b/gdk/x11/gdkgc-x11.c
index 8c3e340..0a6869a 100644
--- a/gdk/x11/gdkgc-x11.c
+++ b/gdk/x11/gdkgc-x11.c
@@ -608,7 +608,8 @@ gdk_x11_gc_values_to_xvalues (GdkGCValues    *values,
 
 void
 _gdk_windowing_gc_set_clip_region (GdkGC           *gc,
-				   const GdkRegion *region)
+				   const GdkRegion *region,
+				   gboolean reset_origin)
 {
   GdkGCX11 *x11_gc = GDK_GC_X11 (gc);
 
@@ -623,8 +624,11 @@ _gdk_windowing_gc_set_clip_region (GdkGC           *gc,
 
   x11_gc->have_clip_region = region != NULL;
 
-  gc->clip_x_origin = 0;
-  gc->clip_y_origin = 0;
+  if (reset_origin)
+    {
+      gc->clip_x_origin = 0;
+      gc->clip_y_origin = 0;
+    }
 
   x11_gc->dirty_mask |= GDK_GC_DIRTY_CLIP;
 }
diff --git a/gdk/x11/gdkgeometry-x11.c b/gdk/x11/gdkgeometry-x11.c
index 9271f09..47f210b 100644
--- a/gdk/x11/gdkgeometry-x11.c
+++ b/gdk/x11/gdkgeometry-x11.c
@@ -165,171 +165,14 @@ struct _GdkWindowQueueItem
   } u;
 };
 
-struct _GdkWindowParentPos
-{
-  gint x;
-  gint y;
-  gint x11_x;
-  gint x11_y;
-  GdkRectangle clip_rect;
-};
-
-static void gdk_window_compute_position   (GdkWindowImplX11      *window,
-					   GdkWindowParentPos *parent_pos,
-					   GdkXPositionInfo   *info);
-static void gdk_window_compute_parent_pos (GdkWindowImplX11      *window,
-					   GdkWindowParentPos *parent_pos);
-static void gdk_window_premove            (GdkWindow          *window,
-					   GdkWindowParentPos *parent_pos);
-static void gdk_window_postmove           (GdkWindow          *window,
-					   GdkWindowParentPos *parent_pos);
-static void gdk_window_queue_translation  (GdkWindow          *window,
-					   GdkRegion	      *area,
-					   gint                dx,
-					   gint                dy);
-static void gdk_window_clip_changed       (GdkWindow          *window,
-					   GdkRectangle       *old_clip,
-					   GdkRectangle       *new_clip);
-
-void
-_gdk_x11_window_get_offsets (GdkWindow *window,
-                             gint      *x_offset,
-                             gint      *y_offset)
-{
-  GdkWindowImplX11 *impl =
-    GDK_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (window)->impl);
-
-  *x_offset = impl->position_info.x_offset;
-  *y_offset = impl->position_info.y_offset;
-}
-
-void
-_gdk_window_init_position (GdkWindow *window)
-{
-  GdkWindowParentPos parent_pos;
-  GdkWindowImplX11 *impl;
-  
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  impl =
-    GDK_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (window)->impl);
-  
-  gdk_window_compute_parent_pos (impl, &parent_pos);
-  gdk_window_compute_position (impl, &parent_pos, &impl->position_info);
-}
-
-static void
-gdk_window_copy_area_scroll (GdkWindow    *window,
-			     GdkRectangle *dest_rect,
-			     gint          dx,
-			     gint          dy)
-{
-  GdkWindowObject *obj = GDK_WINDOW_OBJECT (window);
-  GList *l;
-
-  if (dest_rect->width > 0 && dest_rect->height > 0)
-    {
-      GdkGC *gc;
-
-      gc = _gdk_drawable_get_scratch_gc (window, TRUE);
-      
-      gdk_window_queue_translation (window, NULL, dx, dy);
-   
-      XCopyArea (GDK_WINDOW_XDISPLAY (window),
-		 GDK_WINDOW_XID (window),
-		 GDK_WINDOW_XID (window),
-		 gdk_x11_gc_get_xgc (gc),
-		 dest_rect->x - dx, dest_rect->y - dy,
-		 dest_rect->width, dest_rect->height,
-		 dest_rect->x, dest_rect->y);
-    }
-
-  for (l = obj->children; l; l = l->next)
-    {
-      GdkWindow *child = (GdkWindow*) l->data;
-      GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
-
-      gdk_window_move (child, child_obj->x + dx, child_obj->y + dy);
-    }
-}
-
-static void
-compute_intermediate_position (GdkXPositionInfo *position_info,
-			       GdkXPositionInfo *new_info,
-			       gint              d_xoffset,
-			       gint              d_yoffset,
-			       GdkRectangle     *new_position)
-{
-  gint new_x0, new_x1, new_y0, new_y1;
-  
-  /* Wrap d_xoffset, d_yoffset into [-32768,32767] range. For the
-   * purposes of subwindow movement, it doesn't matter if we are
-   * off by a factor of 65536, and if we don't do this range
-   * reduction, we'll end up with invalid widths.
-   */
-  d_xoffset = (gint16)d_xoffset;
-  d_yoffset = (gint16)d_yoffset;
-  
-  if (d_xoffset < 0)
-    {
-      new_x0 = position_info->x + d_xoffset;
-      new_x1 = position_info->x + position_info->width;
-    }
-  else
-    {
-      new_x0 = position_info->x;
-      new_x1 = position_info->x + new_info->width + d_xoffset;
-    }
-
-  new_position->x = new_x0;
-  new_position->width = new_x1 - new_x0;
-  
-  if (d_yoffset < 0)
-    {
-      new_y0 = position_info->y + d_yoffset;
-      new_y1 = position_info->y + position_info->height;
-    }
-  else
-    {
-      new_y0 = position_info->y;
-      new_y1 = position_info->y + new_info->height + d_yoffset;
-    }
-  
-  new_position->y = new_y0;
-  new_position->height = new_y1 - new_y0;
-}
-
 static void
-translate_pos (GdkWindowParentPos *dest, GdkWindowParentPos *src,
-               GdkWindowObject *obj, GdkXPositionInfo *pos_info,
-               gboolean set_clip)
-{
-  dest->x = src->x + obj->x;
-  dest->y = src->y + obj->y;
-  dest->x11_x = src->x11_x + pos_info->x;
-  dest->x11_y = src->x11_y + pos_info->y;
-
-  if (set_clip)
-      dest->clip_rect = pos_info->clip_rect;
-}
-
-static void
-move (GdkWindow *window, GdkXPositionInfo *pos)
+move (GdkWindow *window, GdkRectangle *pos)
 {
   XMoveWindow (GDK_WINDOW_XDISPLAY (window),
                GDK_WINDOW_XID (window), pos->x, pos->y);
 }
 
 static void
-move_relative (GdkWindow *window, GdkRectangle *rect,
-               gint dx, gint dy)
-{
-  XMoveWindow (GDK_WINDOW_XDISPLAY (window),
-               GDK_WINDOW_XID (window),
-               rect->x + dx, rect->y + dy);
-}
-
-static void
 move_resize (GdkWindow *window, GdkRectangle *pos)
 {
   XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
@@ -337,245 +180,6 @@ move_resize (GdkWindow *window, GdkRectangle *pos)
                      pos->x, pos->y, pos->width, pos->height);
 }
 
-static void
-gdk_window_guffaw_scroll (GdkWindow    *window,
-			  gint          dx,
-			  gint          dy)
-{
-  GdkWindowObject *obj = GDK_WINDOW_OBJECT (window);
-  GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-
-  gint d_xoffset = -dx;
-  gint d_yoffset = -dy;
-  GdkRectangle new_position;
-  GdkXPositionInfo new_info;
-  GdkWindowParentPos parent_pos;
-  GList *l;
-  
-  gdk_window_compute_parent_pos (impl, &parent_pos);
-  gdk_window_compute_position (impl, &parent_pos, &new_info);
-
-  translate_pos (&parent_pos, &parent_pos, obj, &new_info, TRUE);
-
-  _gdk_x11_window_tmp_unset_bg (window, FALSE);;
-
-  if (dx > 0 || dy > 0)
-    gdk_window_queue_translation (window, NULL, MAX (dx, 0), MAX (dy, 0));
-	
-  gdk_window_set_static_gravities (window, TRUE);
-
-  compute_intermediate_position (&impl->position_info, &new_info, d_xoffset, d_yoffset,
-				 &new_position);
-  
-  move_resize (window, &new_position);
-  
-  for (l = obj->children; l; l = l->next)
-    {
-      GdkWindow *child = (GdkWindow*) l->data;
-      GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
-
-      child_obj->x -= d_xoffset;
-      child_obj->y -= d_yoffset;
-
-      gdk_window_premove (child, &parent_pos);
-    }
-  
-  move_relative (window, &new_position, -d_xoffset, -d_yoffset);
-  
-  if (dx < 0 || dy < 0)
-    gdk_window_queue_translation (window, NULL, MIN (dx, 0), MIN (dy, 0));
-  
-  move_resize (window, (GdkRectangle *) &impl->position_info);
-  
-  if (impl->position_info.no_bg)
-    _gdk_x11_window_tmp_reset_bg (window, FALSE);
-  
-  impl->position_info = new_info;
-  
-  g_list_foreach (obj->children, (GFunc) gdk_window_postmove, &parent_pos);
-}
-
-void
-_gdk_x11_window_scroll (GdkWindow *window,
-                        gint       dx,
-                        gint       dy)
-{
-  gboolean can_guffaw_scroll = FALSE;
-  GdkRegion *invalidate_region;
-  GdkWindowImplX11 *impl;
-  GdkWindowObject *obj;
-  GdkRectangle src_rect, dest_rect;
-  
-  obj = GDK_WINDOW_OBJECT (window);
-  impl = GDK_WINDOW_IMPL_X11 (obj->impl);  
-
-  /* Move the current invalid region */
-  if (obj->update_area)
-    gdk_region_offset (obj->update_area, dx, dy);
-  
-  /* impl->position_info.clip_rect isn't meaningful for toplevels */
-  if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
-    src_rect = impl->position_info.clip_rect;
-  else
-    {
-      src_rect.x = 0;
-      src_rect.y = 0;
-      src_rect.width = impl->width;
-      src_rect.height = impl->height;
-    }
-  
-  invalidate_region = gdk_region_rectangle (&src_rect);
-
-  dest_rect = src_rect;
-  dest_rect.x += dx;
-  dest_rect.y += dy;
-  gdk_rectangle_intersect (&dest_rect, &src_rect, &dest_rect);
-
-  if (dest_rect.width > 0 && dest_rect.height > 0)
-    {
-      GdkRegion *tmp_region;
-
-      tmp_region = gdk_region_rectangle (&dest_rect);
-      gdk_region_subtract (invalidate_region, tmp_region);
-      gdk_region_destroy (tmp_region);
-    }
-  
-  gdk_window_invalidate_region (window, invalidate_region, TRUE);
-  gdk_region_destroy (invalidate_region);
-
-  /* We can guffaw scroll if we are a child window, and the parent
-   * does not extend beyond our edges. Otherwise, we use XCopyArea, then
-   * move any children later
-   */
-  if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
-    {
-      GdkWindowImplX11 *parent_impl = GDK_WINDOW_IMPL_X11 (obj->parent->impl);  
-      can_guffaw_scroll = ((dx == 0 || (obj->x <= 0 && obj->x + impl->width >= parent_impl->width)) &&
-			   (dy == 0 || (obj->y <= 0 && obj->y + impl->height >= parent_impl->height)));
-    }
-
-  if (!obj->children || !can_guffaw_scroll)
-    gdk_window_copy_area_scroll (window, &dest_rect, dx, dy);
-  else
-    gdk_window_guffaw_scroll (window, dx, dy);
-}
-
-void
-_gdk_x11_window_move_region (GdkWindow       *window,
-                             const GdkRegion *region,
-                             gint             dx,
-                             gint             dy)
-{
-  GdkWindowImplX11 *impl;
-  GdkWindowObject *private;
-  GdkRegion *window_clip;
-  GdkRegion *src_region;
-  GdkRegion *brought_in;
-  GdkRegion *dest_region;
-  GdkRegion *moving_invalid_region;
-  GdkRectangle dest_extents;
-  GdkGC *gc;
-  
-  private = GDK_WINDOW_OBJECT (window);
-  impl = GDK_WINDOW_IMPL_X11 (private->impl);  
-
-  window_clip = gdk_region_rectangle (&impl->position_info.clip_rect);
-
-  /* compute source regions */
-  src_region = gdk_region_copy (region);
-  brought_in = gdk_region_copy (region);
-  gdk_region_intersect (src_region, window_clip);
-
-  gdk_region_subtract (brought_in, src_region);
-  gdk_region_offset (brought_in, dx, dy);
-
-  /* compute destination regions */
-  dest_region = gdk_region_copy (src_region);
-  gdk_region_offset (dest_region, dx, dy);
-  gdk_region_intersect (dest_region, window_clip);
-  gdk_region_get_clipbox (dest_region, &dest_extents);
-
-  gdk_region_destroy (window_clip);
-
-  /* calculating moving part of current invalid area */
-  moving_invalid_region = NULL;
-  if (private->update_area)
-    {
-      moving_invalid_region = gdk_region_copy (private->update_area);
-      gdk_region_intersect (moving_invalid_region, src_region);
-      gdk_region_offset (moving_invalid_region, dx, dy);
-    }
-  
-  /* invalidate all of the src region */
-  gdk_window_invalidate_region (window, src_region, FALSE);
-
-  /* un-invalidate destination region */
-  if (private->update_area)
-    gdk_region_subtract (private->update_area, dest_region);
-  
-  /* invalidate moving parts of existing update area */
-  if (moving_invalid_region)
-    {
-      gdk_window_invalidate_region (window, moving_invalid_region, FALSE);
-      gdk_region_destroy (moving_invalid_region);
-    }
-
-  /* invalidate area brought in from off-screen */
-  gdk_window_invalidate_region (window, brought_in, FALSE);
-  gdk_region_destroy (brought_in);
-
-  /* Actually do the moving */
-  gdk_window_queue_translation (window, src_region, dx, dy);
-
-  gc = _gdk_drawable_get_scratch_gc (window, TRUE);
-  gdk_gc_set_clip_region (gc, dest_region);
-  
-  XCopyArea (GDK_WINDOW_XDISPLAY (window),
-	     GDK_WINDOW_XID (window),
-	     GDK_WINDOW_XID (window),
-	     GDK_GC_XGC (gc),
-	     dest_extents.x - dx, dest_extents.y - dy,
-	     dest_extents.width, dest_extents.height,
-	     dest_extents.x, dest_extents.y);
-
-  /* Unset clip region of cached GC */
-  gdk_gc_set_clip_region (gc, NULL);
-  
-  gdk_region_destroy (src_region);
-  gdk_region_destroy (dest_region);
-}
-
-static void
-reset_backgrounds (GdkWindow *window)
-{
-  GdkWindowObject *obj = (GdkWindowObject *)window;
-
-  _gdk_x11_window_tmp_reset_bg (window, FALSE);
-  
-  if (obj->parent)
-    _gdk_x11_window_tmp_reset_bg ((GdkWindow *)obj->parent, FALSE);
-}
-
-static void
-map_if_needed (GdkWindow *window, GdkXPositionInfo *pos_info)
-{
-  GdkWindowObject *obj = (GdkWindowObject *) window;
-  GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-
-  if (!impl->position_info.mapped && pos_info->mapped && GDK_WINDOW_IS_MAPPED (obj))
-    XMapWindow (GDK_DRAWABLE_XDISPLAY (window), GDK_DRAWABLE_XID (window));
-}
-
-static void
-unmap_if_needed (GdkWindow *window, GdkXPositionInfo *pos_info)
-{
-  GdkWindowObject *obj = (GdkWindowObject *) window;
-  GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-
-  if (impl->position_info.mapped && !pos_info->mapped)
-    XUnmapWindow (GDK_DRAWABLE_XDISPLAY (window), GDK_DRAWABLE_XID (window));
-}
-
 void
 _gdk_window_move_resize_child (GdkWindow *window,
 			       gint       x,
@@ -585,16 +189,12 @@ _gdk_window_move_resize_child (GdkWindow *window,
 {
   GdkWindowImplX11 *impl;
   GdkWindowObject *obj;
-  GdkXPositionInfo new_info;
-  GdkWindowParentPos parent_pos;
+  GdkRectangle new_info;
   
-  gint d_xoffset, d_yoffset;
   gint dx, dy;
   gboolean is_move;
   gboolean is_resize;
 
-  GdkRectangle old_pos;
-  
   g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window)); 
 
@@ -605,321 +205,27 @@ _gdk_window_move_resize_child (GdkWindow *window,
   dy = y - obj->y;
   
   is_move = dx != 0 || dy != 0;
-  is_resize = impl->width != width || impl->height != height;
+  is_resize = obj->width != width || obj->height != height;
 
+#if 0 /* Not right, doesn't take abs_x/y into consideration */
   if (!is_move && !is_resize)
     return;
+#endif
   
-  old_pos.x = obj->x;
-  old_pos.y = obj->y;
-  old_pos.width = impl->width;
-  old_pos.height = impl->height;
-
   obj->x = x;
   obj->y = y;
-  impl->width = width;
-  impl->height = height;
-
-  gdk_window_compute_parent_pos (impl, &parent_pos);
-  gdk_window_compute_position (impl, &parent_pos, &new_info);
-
-  gdk_window_clip_changed (window, &impl->position_info.clip_rect, &new_info.clip_rect);
-
-  translate_pos (&parent_pos, &parent_pos, obj, &new_info, TRUE);
-
-  d_xoffset = new_info.x_offset - impl->position_info.x_offset;
-  d_yoffset = new_info.y_offset - impl->position_info.y_offset;
-  
-  if (d_xoffset != 0 || d_yoffset != 0)
-    {
-      GdkRectangle new_position;
-
-      gdk_window_set_static_gravities (window, TRUE);
-
-      if (d_xoffset < 0 || d_yoffset < 0)
-	gdk_window_queue_translation (window, NULL, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
-
-      compute_intermediate_position (&impl->position_info, &new_info, d_xoffset, d_yoffset,
-				     &new_position);
-      
-      move_resize (window, &new_position);
-      
-      g_list_foreach (obj->children, (GFunc) gdk_window_premove, &parent_pos);
-
-      move_relative (window, &new_position, dx, dy);
-      
-      if (d_xoffset > 0 || d_yoffset > 0)
-	gdk_window_queue_translation (window, NULL, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
-      
-      move_resize (window, (GdkRectangle *) &new_info);
-
-      reset_backgrounds (window);
-
-      map_if_needed (window, &new_info);
-      
-      impl->position_info = new_info;
-      
-      g_list_foreach (obj->children, (GFunc) gdk_window_postmove, &parent_pos);
-    }
-  else
-    {
-      if (is_move && is_resize)
-	gdk_window_set_static_gravities (window, FALSE);
-
-      unmap_if_needed (window, &new_info);
-      
-      g_list_foreach (obj->children, (GFunc) gdk_window_premove, &parent_pos);
-
-      if (is_resize)
-          move_resize (window, (GdkRectangle *) &new_info);
-      else
-          move (window, &new_info);
-
-      g_list_foreach (obj->children, (GFunc) gdk_window_postmove, &parent_pos);
-
-      reset_backgrounds (window);
-      
-      map_if_needed (window, &new_info);
-
-      impl->position_info = new_info;
-    }
-
-  if (GDK_WINDOW_IS_MAPPED (obj) && obj->parent && !obj->input_only)
-    gdk_window_invalidate_rect ((GdkWindow *)obj->parent, &old_pos, FALSE);
-}
-
-static void
-gdk_window_compute_position (GdkWindowImplX11   *window,
-			     GdkWindowParentPos *parent_pos,
-			     GdkXPositionInfo   *info)
-{
-  GdkWindowObject *wrapper;
-  int parent_x_offset;
-  int parent_y_offset;
-
-  g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (window));
+  obj->width = width;
+  obj->height = height;
 
-  wrapper = GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_X11 (window)->wrapper);
-  
-  info->big = FALSE;
+  new_info.x = obj->x + obj->parent->abs_x;
+  new_info.y = obj->y + obj->parent->abs_y;
+  new_info.width = obj->width;
+  new_info.height = obj->height;
   
-  if (window->width <= 32767)
-    {
-      info->width = window->width;
-      info->x = parent_pos->x + wrapper->x - parent_pos->x11_x;
-    }
+  if (is_resize)
+    move_resize (window, &new_info);
   else
-    {
-      info->big = TRUE;
-      info->width = 32767;
-      if (parent_pos->x + wrapper->x < -16384)
-	{
-	  if (parent_pos->x + wrapper->x + window->width < 16384)
-	    info->x = parent_pos->x + wrapper->x + window->width - info->width - parent_pos->x11_x;
-	  else
-	    info->x = -16384 - parent_pos->x11_x;
-	}
-      else
-	info->x = parent_pos->x + wrapper->x - parent_pos->x11_x;
-    }
-
-  if (window->height <= 32767)
-    {
-      info->height = window->height;
-      info->y = parent_pos->y + wrapper->y - parent_pos->x11_y;
-    }
-  else
-    {
-      info->big = TRUE;
-      info->height = 32767;
-      if (parent_pos->y + wrapper->y < -16384)
-	{
-	  if (parent_pos->y + wrapper->y + window->height < 16384)
-	    info->y = parent_pos->y + wrapper->y + window->height - info->height - parent_pos->x11_y;
-	  else
-	    info->y = -16384 - parent_pos->x11_y;
-	}
-      else
-	info->y = parent_pos->y + wrapper->y - parent_pos->x11_y;
-    }
-
-  parent_x_offset = parent_pos->x11_x - parent_pos->x;
-  parent_y_offset = parent_pos->x11_y - parent_pos->y;
-  
-  info->x_offset = parent_x_offset + info->x - wrapper->x;
-  info->y_offset = parent_y_offset + info->y - wrapper->y;
-
-  /* We don't considering the clipping of toplevel windows and their immediate children
-   * by their parents, and simply always map those windows.
-   */
-  if (parent_pos->clip_rect.width == G_MAXINT)
-    info->mapped = TRUE;
-  /* Check if the window would wrap around into the visible space in either direction */
-  else if (info->x + parent_x_offset < parent_pos->clip_rect.x + parent_pos->clip_rect.width - 65536 ||
-      info->x + info->width + parent_x_offset > parent_pos->clip_rect.x + 65536 ||
-      info->y + parent_y_offset < parent_pos->clip_rect.y + parent_pos->clip_rect.height - 65536 ||
-      info->y + info->height + parent_y_offset  > parent_pos->clip_rect.y + 65536)
-    info->mapped = FALSE;
-  else
-    info->mapped = TRUE;
-
-  info->no_bg = FALSE;
-
-  if (GDK_WINDOW_TYPE (wrapper) == GDK_WINDOW_CHILD)
-    {
-      info->clip_rect.x = wrapper->x;
-      info->clip_rect.y = wrapper->y;
-      info->clip_rect.width = window->width;
-      info->clip_rect.height = window->height;
-      
-      gdk_rectangle_intersect (&info->clip_rect, &parent_pos->clip_rect, &info->clip_rect);
-
-      info->clip_rect.x -= wrapper->x;
-      info->clip_rect.y -= wrapper->y;
-    }
-  else
-    {
-      info->clip_rect.x = 0;
-      info->clip_rect.y = 0;
-      info->clip_rect.width = G_MAXINT;
-      info->clip_rect.height = G_MAXINT;
-    }
-}
-
-static void
-gdk_window_compute_parent_pos (GdkWindowImplX11      *window,
-			       GdkWindowParentPos *parent_pos)
-{
-  GdkWindowObject *wrapper;
-  GdkWindowObject *parent;
-  GdkRectangle tmp_clip;
-  
-  int clip_xoffset = 0;
-  int clip_yoffset = 0;
-
-  g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (window));
-
-  wrapper =
-    GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_X11 (window)->wrapper);
-  
-  parent_pos->x = 0;
-  parent_pos->y = 0;
-  parent_pos->x11_x = 0;
-  parent_pos->x11_y = 0;
-
-  /* We take a simple approach here and simply consider toplevel
-   * windows not to clip their children on the right/bottom, since the
-   * size of toplevel windows is not directly under our
-   * control. Clipping only really matters when scrolling and
-   * generally we aren't going to be moving the immediate child of a
-   * toplevel beyond the bounds of that toplevel.
-   *
-   * We could go ahead and recompute the clips of toplevel windows and
-   * their descendents when we receive size notification, but it would
-   * probably not be an improvement in most cases.
-   */
-  parent_pos->clip_rect.x = 0;
-  parent_pos->clip_rect.y = 0;
-  parent_pos->clip_rect.width = G_MAXINT;
-  parent_pos->clip_rect.height = G_MAXINT;
-
-  parent = (GdkWindowObject *)wrapper->parent;
-  while (parent && parent->window_type == GDK_WINDOW_CHILD)
-    {
-      GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (parent->impl);
-      
-      tmp_clip.x = - clip_xoffset;
-      tmp_clip.y = - clip_yoffset;
-      tmp_clip.width = impl->width;
-      tmp_clip.height = impl->height;
-
-      gdk_rectangle_intersect (&parent_pos->clip_rect, &tmp_clip, &parent_pos->clip_rect);
-
-      translate_pos (parent_pos, parent_pos, parent,
-                     &impl->position_info, FALSE);
-
-      clip_xoffset += parent->x;
-      clip_yoffset += parent->y;
-
-      parent = (GdkWindowObject *)parent->parent;
-    }
-}
-
-static void
-gdk_window_premove (GdkWindow          *window,
-		    GdkWindowParentPos *parent_pos)
-{
-  GdkWindowImplX11 *impl;
-  GdkWindowObject *obj;
-  GdkXPositionInfo new_info;
-  gint d_xoffset, d_yoffset;
-  GdkWindowParentPos this_pos;
-
-  obj = (GdkWindowObject *) window;
-  impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-  
-  gdk_window_compute_position (impl, parent_pos, &new_info);
-
-  gdk_window_clip_changed (window, &impl->position_info.clip_rect, &new_info.clip_rect);
-
-  translate_pos (&this_pos, parent_pos, obj, &new_info, TRUE);
-
-  unmap_if_needed (window, &new_info);
-
-  d_xoffset = new_info.x_offset - impl->position_info.x_offset;
-  d_yoffset = new_info.y_offset - impl->position_info.y_offset;
-  
-  if (d_xoffset != 0 || d_yoffset != 0)
-    {
-      GdkRectangle new_position;
-
-      if (d_xoffset < 0 || d_yoffset < 0)
-	gdk_window_queue_translation (window, NULL, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
-
-      compute_intermediate_position (&impl->position_info, &new_info, d_xoffset, d_yoffset,
-				     &new_position);
-
-      move_resize (window, &new_position);
-    }
-
-  g_list_foreach (obj->children, (GFunc) gdk_window_premove, &this_pos);
-}
-
-static void
-gdk_window_postmove (GdkWindow          *window,
-		     GdkWindowParentPos *parent_pos)
-{
-  GdkWindowImplX11 *impl;
-  GdkWindowObject *obj;
-  GdkXPositionInfo new_info;
-  gint d_xoffset, d_yoffset;
-  GdkWindowParentPos this_pos;
-
-  obj = (GdkWindowObject *) window;
-  impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-  
-  gdk_window_compute_position (impl, parent_pos, &new_info);
-
-  translate_pos (&this_pos, parent_pos, obj, &new_info, TRUE);
-
-  d_xoffset = new_info.x_offset - impl->position_info.x_offset;
-  d_yoffset = new_info.y_offset - impl->position_info.y_offset;
-  
-  if (d_xoffset != 0 || d_yoffset != 0)
-    {
-      if (d_xoffset > 0 || d_yoffset > 0)
-	gdk_window_queue_translation (window, NULL, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
-	
-      move_resize (window, (GdkRectangle *) &new_info);
-    }
-
-  map_if_needed (window, &new_info);
-
-  reset_backgrounds (window);
-
-  impl->position_info = new_info;
-
-  g_list_foreach (obj->children, (GFunc) gdk_window_postmove, &this_pos);
+    move (window, &new_info);
 }
 
 static Bool
@@ -1050,11 +356,11 @@ gdk_window_queue (GdkWindow          *window,
   g_queue_push_tail (display_x11->translate_queue, item);
 }
 
-static void
-gdk_window_queue_translation (GdkWindow *window,
-			      GdkRegion *area,
-			      gint       dx,
-			      gint       dy)
+void
+_gdk_windowing_window_queue_translation (GdkWindow *window,
+					 GdkRegion *area,
+					 gint       dx,
+					 gint       dy)
 {
   GdkWindowQueueItem *item = g_new (GdkWindowQueueItem, 1);
   item->type = GDK_WINDOW_QUEUE_TRANSLATE;
@@ -1066,8 +372,8 @@ gdk_window_queue_translation (GdkWindow *window,
 }
 
 gboolean
-_gdk_windowing_window_queue_antiexpose (GdkWindow *window,
-					GdkRegion *area)
+_gdk_x11_window_queue_antiexpose (GdkWindow *window,
+				  GdkRegion *area)
 {
   GdkWindowQueueItem *item = g_new (GdkWindowQueueItem, 1);
   item->type = GDK_WINDOW_QUEUE_ANTIEXPOSE;
@@ -1085,7 +391,6 @@ _gdk_window_process_expose (GdkWindow    *window,
 {
   GdkWindowImplX11 *impl;
   GdkRegion *invalidate_region = gdk_region_rectangle (area);
-  GdkRegion *clip_region;
   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
   impl = GDK_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (window)->impl);
 
@@ -1134,57 +439,10 @@ _gdk_window_process_expose (GdkWindow    *window,
 	}
     }
 
-  clip_region = gdk_region_rectangle (&impl->position_info.clip_rect);
-  gdk_region_intersect (invalidate_region, clip_region);
-
   if (!gdk_region_empty (invalidate_region))
-    gdk_window_invalidate_region (window, invalidate_region, FALSE);
+    _gdk_window_invalidate_for_expose (window, invalidate_region);
   
   gdk_region_destroy (invalidate_region);
-  gdk_region_destroy (clip_region);
-}
-
-static void
-gdk_window_clip_changed (GdkWindow *window, GdkRectangle *old_clip, GdkRectangle *new_clip)
-{
-  GdkWindowImplX11 *impl;
-  GdkWindowObject *obj;
-  GdkRegion *old_clip_region;
-  GdkRegion *new_clip_region;
-  
-  if (((GdkWindowObject *)window)->input_only)
-    return;
-
-  obj = (GdkWindowObject *) window;
-  impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-  
-  old_clip_region = gdk_region_rectangle (old_clip);
-  new_clip_region = gdk_region_rectangle (new_clip);
-
-  /* We need to update this here because gdk_window_invalidate_region makes
-   * use if it (through gdk_drawable_get_visible_region
-   */
-  impl->position_info.clip_rect = *new_clip;
-  
-  /* Trim invalid region of window to new clip rectangle
-   */
-  if (obj->update_area)
-    gdk_region_intersect (obj->update_area, new_clip_region);
-
-  /* Invalidate newly exposed portion of window
-   */
-  gdk_region_subtract (new_clip_region, old_clip_region);
-  if (!gdk_region_empty (new_clip_region))
-    {
-      _gdk_x11_window_tmp_unset_bg (window, FALSE);;
-      gdk_window_invalidate_region (window, new_clip_region, FALSE);
-    }
-
-  if (obj->parent)
-    _gdk_x11_window_tmp_unset_bg ((GdkWindow *)obj->parent, FALSE);
-  
-  gdk_region_destroy (new_clip_region);
-  gdk_region_destroy (old_clip_region);
 }
 
 #define __GDK_GEOMETRY_X11_C__
diff --git a/gdk/x11/gdkinput.c b/gdk/x11/gdkinput.c
index 0d48e13..87fe45c 100644
--- a/gdk/x11/gdkinput.c
+++ b/gdk/x11/gdkinput.c
@@ -251,7 +251,7 @@ gdk_device_get_history  (GdkDevice         *device,
   int tmp_n_events = 0;
   int i;
 
-  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+  g_return_val_if_fail (GDK_WINDOW_IS_X11 (window), FALSE);
 
   if (GDK_WINDOW_DESTROYED (window))
     /* Nothing */ ;
@@ -347,7 +347,7 @@ gdk_input_set_extension_events (GdkWindow *window, gint mask,
   GdkDisplayX11 *display_x11;
 
   g_return_if_fail (window != NULL);
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_WINDOW_IS_X11 (window));
 
   window_private = (GdkWindowObject*) window;
   display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
diff --git a/gdk/x11/gdkmain-x11.c b/gdk/x11/gdkmain-x11.c
index 7bede22..dd75b63 100644
--- a/gdk/x11/gdkmain-x11.c
+++ b/gdk/x11/gdkmain-x11.c
@@ -143,17 +143,17 @@ generate_grab_broken_event (GdkWindow *window,
 			    gboolean   implicit,
 			    GdkWindow *grab_window)
 {
+  g_return_if_fail (window != NULL);
+
   if (!GDK_WINDOW_DESTROYED (window))
     {
       GdkEvent event;
-  
       event.type = GDK_GRAB_BROKEN;
       event.grab_broken.window = window;
       event.grab_broken.send_event = 0;
       event.grab_broken.keyboard = keyboard;
       event.grab_broken.implicit = implicit;
       event.grab_broken.grab_window = grab_window;
-      
       gdk_event_put (&event);
     }
 }
@@ -191,6 +191,7 @@ gdk_pointer_grab (GdkWindow *	  window,
 {
   gint return_val;
   GdkCursorPrivate *cursor_private;
+  GdkWindow *native;
   GdkDisplayX11 *display_x11;
   guint xevent_mask;
   Window xwindow;
@@ -202,13 +203,18 @@ gdk_pointer_grab (GdkWindow *	  window,
   g_return_val_if_fail (window != NULL, 0);
   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
   g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
-  
-  display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
+
+  native = _gdk_window_get_impl_window (window);
+
+  if (confine_to)
+    confine_to = _gdk_window_get_impl_window (confine_to);
+
+  display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (native));
 
   cursor_private = (GdkCursorPrivate*) cursor;
   
-  xwindow = GDK_WINDOW_XID (window);
-  serial = NextRequest (GDK_WINDOW_XDISPLAY (window));
+  xwindow = GDK_WINDOW_XID (native);
+  serial = NextRequest (GDK_WINDOW_XDISPLAY (native));
   
   if (!confine_to || GDK_WINDOW_DESTROYED (confine_to))
     xconfine_to = None;
@@ -230,7 +236,7 @@ gdk_pointer_grab (GdkWindow *	  window,
 	xevent_mask |= _gdk_event_mask_table[i];
     }
   
-  return_val = _gdk_input_grab_pointer (window,
+  return_val = _gdk_input_grab_pointer (native,
 					owner_events,
 					event_mask,
 					confine_to,
@@ -239,14 +245,14 @@ gdk_pointer_grab (GdkWindow *	  window,
   if (return_val == GrabSuccess || 
       G_UNLIKELY (!display_x11->trusted_client && return_val == AlreadyGrabbed))
     {
-      if (!GDK_WINDOW_DESTROYED (window))
+      if (!GDK_WINDOW_DESTROYED (native))
 	{
 #ifdef G_ENABLE_DEBUG
 	  if (_gdk_debug_flags & GDK_DEBUG_NOGRABS)
 	    return_val = GrabSuccess;
 	  else
 #endif
-	    return_val = XGrabPointer (GDK_WINDOW_XDISPLAY (window),
+	    return_val = XGrabPointer (GDK_WINDOW_XDISPLAY (native),
 				       xwindow,
 				       owner_events,
 				       xevent_mask,
@@ -261,59 +267,19 @@ gdk_pointer_grab (GdkWindow *	  window,
   
   if (return_val == GrabSuccess)
     {
-      if (display_x11->pointer_xgrab_window != NULL &&
-	  display_x11->pointer_xgrab_window != (GdkWindowObject *)window)
-	generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_xgrab_window),
-				    FALSE, display_x11->pointer_xgrab_implicit,
-				    window);
-
-      display_x11->pointer_xgrab_window = (GdkWindowObject *)window;
-      display_x11->pointer_xgrab_serial = serial;
-      display_x11->pointer_xgrab_owner_events = owner_events;
-      display_x11->pointer_xgrab_time = time;
-      display_x11->pointer_xgrab_implicit = FALSE;
+      _gdk_display_set_has_pointer_grab (GDK_DISPLAY_OBJECT (display_x11),
+					 window,
+					 native,
+					 owner_events,
+					 event_mask,
+					 serial,
+					 time,
+					 FALSE);
     }
 
   return gdk_x11_convert_grab_status (return_val);
 }
 
-/**
- * gdk_pointer_grab_info_libgtk_only:
- * @display: the #GdkDisplay for which to get the grab information
- * @grab_window: location to store current grab window
- * @owner_events: location to store boolean indicating whether
- *   the @owner_events flag to gdk_pointer_grab() was %TRUE.
- * 
- * Determines information about the current pointer grab.
- * This is not public API and must not be used by applications.
- * 
- * Return value: %TRUE if this application currently has the
- *  pointer grabbed.
- **/
-gboolean
-gdk_pointer_grab_info_libgtk_only (GdkDisplay *display,
-				   GdkWindow **grab_window,
-				   gboolean   *owner_events)
-{
-  GdkDisplayX11 *display_x11;
-  
-  g_return_val_if_fail (GDK_IS_DISPLAY (display), False);
-
-  display_x11 = GDK_DISPLAY_X11 (display);
-
-  if (display_x11->pointer_xgrab_window)
-    {
-      if (grab_window)
-        *grab_window = (GdkWindow *)display_x11->pointer_xgrab_window;
-      if (owner_events)
-        *owner_events = display_x11->pointer_xgrab_owner_events;
-
-      return TRUE;
-    }
-  else
-    return FALSE;
-}
-
 /*
  *--------------------------------------------------------------
  * gdk_keyboard_grab
@@ -342,23 +308,28 @@ gdk_keyboard_grab (GdkWindow *	   window,
   gint return_val;
   unsigned long serial;
   GdkDisplayX11 *display_x11;
+  GdkWindow *native;
+
+  if (1) return 0; /* TODO: fix */
   
   g_return_val_if_fail (window != NULL, 0);
   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
-  
-  display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
 
-  serial = NextRequest (GDK_WINDOW_XDISPLAY (window));
+  native = _gdk_window_get_impl_window (window);
 
-  if (!GDK_WINDOW_DESTROYED (window))
+  display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (native));
+
+  serial = NextRequest (GDK_WINDOW_XDISPLAY (native));
+
+  if (!GDK_WINDOW_DESTROYED (native))
     {
 #ifdef G_ENABLE_DEBUG
       if (_gdk_debug_flags & GDK_DEBUG_NOGRABS)
 	return_val = GrabSuccess;
       else
 #endif
-	return_val = XGrabKeyboard (GDK_WINDOW_XDISPLAY (window),
-				    GDK_WINDOW_XID (window),
+	return_val = XGrabKeyboard (GDK_WINDOW_XDISPLAY (native),
+				    GDK_WINDOW_XID (native),
 				    owner_events,
 				    GrabModeAsync, GrabModeAsync,
 				    time);
@@ -378,6 +349,7 @@ gdk_keyboard_grab (GdkWindow *	   window,
 				    TRUE, FALSE, window);
       
       display_x11->keyboard_xgrab_window = (GdkWindowObject *)window;
+      display_x11->keyboard_xgrab_native_window = (GdkWindowObject *)native;
       display_x11->keyboard_xgrab_serial = serial;
       display_x11->keyboard_xgrab_owner_events = owner_events;
       display_x11->keyboard_xgrab_time = time;      
@@ -386,6 +358,24 @@ gdk_keyboard_grab (GdkWindow *	   window,
   return gdk_x11_convert_grab_status (return_val);
 }
 
+void
+_gdk_windowing_grab_broken (GdkDisplay *display)
+{
+  /* TODO: Move to common code */
+#if 0
+  GdkDisplayX11 *display_x11;
+
+  g_return_if_fail (display != NULL);
+
+  display_x11 = GDK_DISPLAY_X11 (display);
+  generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_grab.window),
+                              FALSE,
+                              display_x11->pointer_grab.implicit,
+                              NULL);
+  display_x11->pointer_grab.window = NULL;
+#endif
+}
+
 /**
  * gdk_keyboard_grab_info_libgtk_only:
  * @display: the display for which to get the grab information
@@ -437,24 +427,20 @@ void
 _gdk_xgrab_check_unmap (GdkWindow *window,
 			gulong     serial)
 {
-  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (gdk_drawable_get_display (window));
+  GdkDisplay *display = gdk_drawable_get_display (window);
+  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
   
-  if (display_x11->pointer_xgrab_window && 
-      serial >= display_x11->pointer_xgrab_serial)
+  if (display->pointer_grab.window && 
+      serial >= display->pointer_grab.serial)
     {
       GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
-      GdkWindowObject *tmp = display_x11->pointer_xgrab_window;
+      GdkWindowObject *tmp = GDK_WINDOW_OBJECT (display->pointer_grab.native_window);
 
       while (tmp && tmp != private)
 	tmp = tmp->parent;
 
       if (tmp)
-	{	  
-	  generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_xgrab_window),
-				      FALSE, display_x11->pointer_xgrab_implicit, 
-				      NULL);
-	  display_x11->pointer_xgrab_window = NULL;  
-	}
+	_gdk_display_unset_has_pointer_grab (display, TRUE, FALSE, GDK_CURRENT_TIME);
     }
 
   if (display_x11->keyboard_xgrab_window &&
@@ -486,17 +472,15 @@ _gdk_xgrab_check_unmap (GdkWindow *window,
 void
 _gdk_xgrab_check_destroy (GdkWindow *window)
 {
-  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (gdk_drawable_get_display (window));
+  GdkDisplay *display = gdk_drawable_get_display (window);
+  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
   
-  if ((GdkWindowObject *)window == display_x11->pointer_xgrab_window)
-    {
-      generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_xgrab_window),
-				  FALSE, display_x11->pointer_xgrab_implicit,
-				  NULL);
-      display_x11->pointer_xgrab_window = NULL;
-    }
+  if (window == display->pointer_grab.native_window &&
+      display->pointer_grab.window != NULL)
+    _gdk_display_unset_has_pointer_grab (display, TRUE, FALSE, GDK_CURRENT_TIME);
 
-  if ((GdkWindowObject *)window ==  display_x11->keyboard_xgrab_window)
+  if ((GdkWindowObject *)window == display_x11->keyboard_xgrab_native_window &&
+      display_x11->keyboard_xgrab_window != NULL)
     {
       generate_grab_broken_event (GDK_WINDOW (display_x11->keyboard_xgrab_window),
 				  TRUE, FALSE, NULL);
@@ -521,27 +505,31 @@ void
 _gdk_xgrab_check_button_event (GdkWindow *window, 
 			       XEvent *xevent)
 {
-  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (gdk_drawable_get_display (window));
+  GdkDisplay *display = gdk_drawable_get_display (window);
   
   /* track implicit grabs for button presses */
   switch (xevent->type)
     {
     case ButtonPress:
-      if (!display_x11->pointer_xgrab_window)
+      if (!display->pointer_grab.window)
 	{
-	  display_x11->pointer_xgrab_window = (GdkWindowObject *)window;
-	  display_x11->pointer_xgrab_serial = xevent->xany.serial;
-	  display_x11->pointer_xgrab_owner_events = FALSE;
-	  display_x11->pointer_xgrab_time = xevent->xbutton.time;
-	  display_x11->pointer_xgrab_implicit = TRUE;	  
+	  _gdk_display_set_has_pointer_grab (display,
+					     window,
+					     window,
+					     FALSE,
+					     gdk_window_get_events (window),
+					     xevent->xany.serial,
+					     xevent->xbutton.time,
+					     TRUE);
 	}
       break;
     case ButtonRelease:
-      if (display_x11->pointer_xgrab_window &&
-	  display_x11->pointer_xgrab_implicit &&
+      if (display->pointer_grab.window &&
+	  display->pointer_grab.implicit &&
 	  (xevent->xbutton.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (xevent->xbutton.button - 1))) == 0)
 	{
-	  display_x11->pointer_xgrab_window = NULL;
+	  _gdk_display_unset_has_pointer_grab (display, TRUE, TRUE,
+					       xevent->xbutton.time);
 	}
       break;
     default:
diff --git a/gdk/x11/gdkpixmap-x11.c b/gdk/x11/gdkpixmap-x11.c
index 7984b5a..1fcaf5a 100644
--- a/gdk/x11/gdkpixmap-x11.c
+++ b/gdk/x11/gdkpixmap-x11.c
@@ -137,10 +137,10 @@ gdk_pixmap_impl_x11_get_size   (GdkDrawable *drawable,
 }
 
 GdkPixmap*
-gdk_pixmap_new (GdkDrawable *drawable,
-		gint         width,
-		gint         height,
-		gint         depth)
+_gdk_pixmap_new (GdkDrawable *drawable,
+                 gint         width,
+                 gint         height,
+                 gint         depth)
 {
   GdkPixmap *pixmap;
   GdkDrawableImplX11 *draw_impl;
@@ -194,10 +194,10 @@ gdk_pixmap_new (GdkDrawable *drawable,
 }
 
 GdkPixmap *
-gdk_bitmap_create_from_data (GdkDrawable *drawable,
-			     const gchar *data,
-			     gint         width,
-			     gint         height)
+_gdk_bitmap_create_from_data (GdkDrawable *drawable,
+                              const gchar *data,
+                              gint         width,
+                              gint         height)
 {
   GdkPixmap *pixmap;
   GdkDrawableImplX11 *draw_impl;
@@ -238,13 +238,13 @@ gdk_bitmap_create_from_data (GdkDrawable *drawable,
 }
 
 GdkPixmap*
-gdk_pixmap_create_from_data (GdkDrawable    *drawable,
-			     const gchar    *data,
-			     gint            width,
-			     gint            height,
-			     gint            depth,
-			     const GdkColor *fg,
-			     const GdkColor *bg)
+_gdk_pixmap_create_from_data (GdkDrawable    *drawable,
+			      const gchar    *data,
+			      gint            width,
+			      gint            height,
+			      gint            depth,
+			      const GdkColor *fg,
+			      const GdkColor *bg)
 {
   GdkPixmap *pixmap;
   GdkDrawableImplX11 *draw_impl;
diff --git a/gdk/x11/gdkprivate-x11.h b/gdk/x11/gdkprivate-x11.h
index f24a0df..ad1dfca 100644
--- a/gdk/x11/gdkprivate-x11.h
+++ b/gdk/x11/gdkprivate-x11.h
@@ -118,7 +118,6 @@ GdkImage *_gdk_x11_copy_to_image       (GdkDrawable *drawable,
 Pixmap   _gdk_x11_image_get_shm_pixmap (GdkImage    *image);
 
 /* Routines from gdkgeometry-x11.c */
-void _gdk_window_init_position     (GdkWindow     *window);
 void _gdk_window_move_resize_child (GdkWindow     *window,
                                     gint           x,
                                     gint           y,
@@ -128,13 +127,9 @@ void _gdk_window_process_expose    (GdkWindow     *window,
                                     gulong         serial,
                                     GdkRectangle  *area);
 
-void _gdk_x11_window_scroll        (GdkWindow       *window,
-                                    gint             dx,
-                                    gint             dy);
-void _gdk_x11_window_move_region   (GdkWindow       *window,
-                                    const GdkRegion *region,
-                                    gint             dx,
-                                    gint             dy);
+gboolean _gdk_x11_window_queue_antiexpose (GdkWindow *window,
+					   GdkRegion *area);
+
 
 void     _gdk_selection_window_destroyed   (GdkWindow            *window);
 gboolean _gdk_selection_filter_clear_event (XSelectionClearEvent *event);
@@ -216,5 +211,6 @@ extern gboolean          _gdk_synchronize;
 #define GDK_WINDOW_DISPLAY(win)       (GDK_SCREEN_X11 (GDK_WINDOW_SCREEN (win))->display)
 #define GDK_WINDOW_XROOTWIN(win)      (GDK_SCREEN_X11 (GDK_WINDOW_SCREEN (win))->xroot_window)
 #define GDK_GC_DISPLAY(gc)            (GDK_SCREEN_DISPLAY (GDK_GC_X11(gc)->screen))
+#define GDK_WINDOW_IS_X11(win)        (GDK_IS_WINDOW_IMPL_X11 (((GdkWindowObject *)win)->impl))
 
 #endif /* __GDK_PRIVATE_X11_H__ */
diff --git a/gdk/x11/gdkproperty-x11.c b/gdk/x11/gdkproperty-x11.c
index 36b8e9f..0310a75 100644
--- a/gdk/x11/gdkproperty-x11.c
+++ b/gdk/x11/gdkproperty-x11.c
@@ -541,7 +541,7 @@ gdk_property_get (GdkWindow   *window,
   Atom xtype;
   int res;
 
-  g_return_val_if_fail (!window || GDK_IS_WINDOW (window), FALSE);
+  g_return_val_if_fail (!window || GDK_WINDOW_IS_X11 (window), FALSE);
 
   if (!window)
     {
@@ -550,6 +550,8 @@ gdk_property_get (GdkWindow   *window,
       
       GDK_NOTE (MULTIHEAD, g_message ("gdk_property_get(): window is NULL\n"));
     }
+  else if (!GDK_WINDOW_IS_X11 (window))
+    return FALSE;
 
   if (GDK_WINDOW_DESTROYED (window))
     return FALSE;
@@ -675,7 +677,7 @@ gdk_property_change (GdkWindow    *window,
   Atom xproperty;
   Atom xtype;
 
-  g_return_if_fail (!window || GDK_IS_WINDOW (window));
+  g_return_if_fail (!window || GDK_WINDOW_IS_X11 (window));
 
   if (!window)
     {
@@ -686,7 +688,8 @@ gdk_property_change (GdkWindow    *window,
       
       GDK_NOTE (MULTIHEAD, g_message ("gdk_property_change(): window is NULL\n"));
     }
-
+  else if (!GDK_WINDOW_IS_X11 (window))
+    return;
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
@@ -726,7 +729,7 @@ void
 gdk_property_delete (GdkWindow *window,
 		     GdkAtom    property)
 {
-  g_return_if_fail (!window || GDK_IS_WINDOW (window));
+  g_return_if_fail (!window || GDK_WINDOW_IS_X11 (window));
 
   if (!window)
     {
@@ -736,6 +739,8 @@ gdk_property_delete (GdkWindow *window,
       GDK_NOTE (MULTIHEAD, 
 		g_message ("gdk_property_delete(): window is NULL\n"));
     }
+  else if (!GDK_WINDOW_IS_X11 (window))
+    return;
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
diff --git a/gdk/x11/gdkselection-x11.c b/gdk/x11/gdkselection-x11.c
index fd482e2..d9ef881 100644
--- a/gdk/x11/gdkselection-x11.c
+++ b/gdk/x11/gdkselection-x11.c
@@ -141,7 +141,7 @@ gdk_selection_owner_set_for_display (GdkDisplay *display,
 
   if (owner) 
     {
-      if (GDK_WINDOW_DESTROYED (owner))
+      if (GDK_WINDOW_DESTROYED (owner) || !GDK_WINDOW_IS_X11 (owner))
 	return FALSE;
       
       xdisplay = GDK_WINDOW_XDISPLAY (owner);
@@ -231,7 +231,7 @@ gdk_selection_convert (GdkWindow *requestor,
 
   g_return_if_fail (selection != GDK_NONE);
   
-  if (GDK_WINDOW_DESTROYED (requestor))
+  if (GDK_WINDOW_DESTROYED (requestor) || !GDK_WINDOW_IS_X11 (requestor))
     return;
 
   display = GDK_WINDOW_DISPLAY (requestor);
@@ -279,10 +279,11 @@ gdk_selection_property_get (GdkWindow  *requestor,
 
   g_return_val_if_fail (requestor != NULL, 0);
   g_return_val_if_fail (GDK_IS_WINDOW (requestor), 0);
+  g_return_val_if_fail (GDK_WINDOW_IS_X11 (requestor), 0);
   
   display = GDK_WINDOW_DISPLAY (requestor);
 
-  if (GDK_WINDOW_DESTROYED (requestor))
+  if (GDK_WINDOW_DESTROYED (requestor) || !GDK_WINDOW_IS_X11 (requestor))
     goto err;
 
   t = NULL;
diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c
index a6d88b9..b5a3a3a 100644
--- a/gdk/x11/gdkwindow-x11.c
+++ b/gdk/x11/gdkwindow-x11.c
@@ -112,16 +112,13 @@ static void     move_to_current_desktop           (GdkWindow *window);
 static GdkColormap* gdk_window_impl_x11_get_colormap (GdkDrawable *drawable);
 static void         gdk_window_impl_x11_set_colormap (GdkDrawable *drawable,
 						      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_finalize   (GObject            *object);
 static void        gdk_window_impl_iface_init     (GdkWindowImplIface *iface);
 
-#define WINDOW_IS_TOPLEVEL(window)		   \
-  (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
-   GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
+#define WINDOW_IS_TOPLEVEL(window)		     \
+  (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&   \
+   GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN && \
+   GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
 
 /* Return whether time1 is considered later than time2 as far as xserver
  * time is concerned.  Accounts for wraparound.
@@ -146,8 +143,6 @@ _gdk_window_impl_get_type (void)
 static void
 gdk_window_impl_x11_init (GdkWindowImplX11 *impl)
 {  
-  impl->width = 1;
-  impl->height = 1;
   impl->toplevel_window_type = -1;
 }
 
@@ -181,11 +176,6 @@ gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
 
   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
@@ -237,7 +227,7 @@ tmp_unset_bg (GdkWindow *window)
   if (!(obj->event_mask & GDK_EXPOSURE_MASK))
     return;
     
-  impl->position_info.no_bg = TRUE;
+  impl->no_bg = TRUE;
 
   if (obj->bg_pixmap != GDK_NO_BG)
     XSetWindowBackgroundPixmap (GDK_DRAWABLE_XDISPLAY (window),
@@ -256,7 +246,7 @@ tmp_reset_bg (GdkWindow *window)
   if (!(obj->event_mask & GDK_EXPOSURE_MASK))
     return;
     
-  impl->position_info.no_bg = FALSE;
+  impl->no_bg = FALSE;
 
   if (obj->bg_pixmap == GDK_NO_BG)
     return;
@@ -300,7 +290,9 @@ _gdk_x11_window_tmp_unset_bg (GdkWindow *window,
 
   if (private->input_only || private->destroyed ||
       (private->window_type != GDK_WINDOW_ROOT &&
-       !GDK_WINDOW_IS_MAPPED (window)))
+       !GDK_WINDOW_IS_MAPPED (window)) ||
+      !_gdk_window_has_impl (window) ||
+      !GDK_WINDOW_IS_X11 (window))
     {
       return;
     }
@@ -332,7 +324,9 @@ _gdk_x11_window_tmp_reset_bg (GdkWindow *window,
 
   if (private->input_only || private->destroyed ||
       (private->window_type != GDK_WINDOW_ROOT &&
-       !GDK_WINDOW_IS_MAPPED (window)))
+       !GDK_WINDOW_IS_MAPPED (window)) ||
+      !_gdk_window_has_impl (window) ||
+      !GDK_WINDOW_IS_X11 (window))
     {
       return;
     }
@@ -409,35 +403,6 @@ gdk_window_impl_x11_set_colormap (GdkDrawable *drawable,
 }
 
 
-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_windowing_window_init (GdkScreen * screen)
 {
@@ -469,12 +434,14 @@ _gdk_windowing_window_init (GdkScreen * screen)
   
   private->window_type = GDK_WINDOW_ROOT;
   private->depth = DefaultDepthOfScreen (screen_x11->xscreen);
-  
-  impl->width = WidthOfScreen (screen_x11->xscreen);
-  impl->height = HeightOfScreen (screen_x11->xscreen);
-  
-  _gdk_window_init_position (GDK_WINDOW (private));
 
+  private->x = 0;
+  private->y = 0;
+  private->abs_x = 0;
+  private->abs_y = 0;
+  private->width = WidthOfScreen (screen_x11->xscreen);
+  private->height = HeightOfScreen (screen_x11->xscreen);
+  
   _gdk_xid_table_insert (screen_x11->display,
 			 &screen_x11->xroot_window,
 			 screen_x11->root_window);
@@ -589,7 +556,6 @@ setup_toplevel_window (GdkWindow *window,
 {
   GdkWindowObject *obj = (GdkWindowObject *)window;
   GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
-  GdkWindowImplX11 *impl = (GdkWindowImplX11 *)obj->impl;
   Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
   XID xid = GDK_WINDOW_XID (window);
   XID xparent = GDK_WINDOW_XID (parent);
@@ -619,8 +585,8 @@ setup_toplevel_window (GdkWindow *window,
    * correct value???
    */
   size_hints.flags = PSize;
-  size_hints.width = impl->width;
-  size_hints.height = impl->height;
+  size_hints.width = obj->width;
+  size_hints.height = obj->height;
   
   XSetWMNormalHints (xdisplay, xid, &size_hints);
   
@@ -656,19 +622,19 @@ setup_toplevel_window (GdkWindow *window,
   ensure_sync_counter (window);
 }
 
-GdkWindow *
-_gdk_window_new (GdkWindow     *parent,
-		 GdkWindowAttr *attributes,
-		 gint           attributes_mask)
+void
+_gdk_window_impl_new (GdkWindow     *window,
+		      GdkScreen     *screen,
+		      GdkVisual     *visual,
+		      GdkEventMask   event_mask,
+		      GdkWindowAttr *attributes,
+		      gint           attributes_mask)
 {
-  GdkWindow *window;
   GdkWindowObject *private;
   GdkWindowImplX11 *impl;
   GdkDrawableImplX11 *draw_impl;
   GdkScreenX11 *screen_x11;
-  GdkScreen *screen;
   
-  GdkVisual *visual;
   Window xparent;
   Visual *xvisual;
   Display *xdisplay;
@@ -677,117 +643,35 @@ _gdk_window_new (GdkWindow     *parent,
   XSetWindowAttributes xattributes;
   long xattributes_mask;
   XClassHint *class_hint;
-  int x, y, depth;
+  int depth;
   
   unsigned int class;
   const char *title;
   int i;
   
-  g_return_val_if_fail (attributes != NULL, NULL);
+  private = (GdkWindowObject *) window;
   
-  if (!parent)
-    {
-      GDK_NOTE (MULTIHEAD,
-		g_warning ("gdk_window_new(): no parent specified reverting to parent = default root window"));
-      
-      screen = gdk_screen_get_default ();
-      parent = gdk_screen_get_root_window (screen);
-    }
-  else
-    screen = gdk_drawable_get_screen (parent);
-
   screen_x11 = GDK_SCREEN_X11 (screen);
-
-  g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
-  
-  if (GDK_WINDOW_DESTROYED (parent))
-    return NULL;
+  xparent = GDK_WINDOW_XID (private->parent);
   
-  xparent = GDK_WINDOW_XID (parent);
-  
-  window = g_object_new (GDK_TYPE_WINDOW, NULL);
-
-  private = (GdkWindowObject *) window;
-  private->impl = g_object_new (_gdk_window_impl_get_type (), NULL);
-
-  impl = GDK_WINDOW_IMPL_X11 (private->impl);
-  draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
+  impl = g_object_new (_gdk_window_impl_get_type (), NULL);
+  private->impl = (GdkDrawable *)impl;
+  draw_impl = GDK_DRAWABLE_IMPL_X11 (impl);
   draw_impl->wrapper = GDK_DRAWABLE (window);
   
   draw_impl->screen = screen;
   xdisplay = screen_x11->xdisplay;
 
-  /* Windows with a foreign parent are treated as if they are children
-   * of the root window, except for actual creation.
-   */
-  if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
-    parent = gdk_screen_get_root_window (screen);
-  
-  private->parent = (GdkWindowObject *)parent;
-
-  private->accept_focus = TRUE;
-  private->focus_on_map = TRUE;
-
   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;
-  impl->width = (attributes->width > 1) ? (attributes->width) : (1);
-  impl->height = (attributes->height > 1) ? (attributes->height) : (1);
-
-  if (attributes->wclass == GDK_INPUT_ONLY)
-    {
-      /* Backwards compatiblity - we've always ignored
-       * attributes->window_type for input-only windows
-       * before
-       */
-      if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
-	private->window_type = GDK_WINDOW_TEMP;
-      else
-	private->window_type = GDK_WINDOW_CHILD;
-    }
-  else
-    private->window_type = attributes->window_type;
-
-  /* Work around a bug where Xorg refuses to map toplevel InputOnly windows 
-   * from an untrusted client: http://bugs.freedesktop.org/show_bug.cgi?id=6988
-   */
-  if (attributes->wclass == GDK_INPUT_ONLY &&
-      GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT &&
-      !G_LIKELY (GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (parent))->trusted_client))
-    {
-      g_warning ("Coercing GDK_INPUT_ONLY toplevel window to GDK_INPUT_OUTPUT to work around bug in Xorg server");
-      attributes->wclass = GDK_INPUT_OUTPUT;
-    }
 
-  _gdk_window_init_position (GDK_WINDOW (private));
-  if (impl->position_info.big)
-    private->guffaw_gravity = TRUE;
-  
-  if (attributes_mask & GDK_WA_VISUAL)
-    visual = attributes->visual;
-  else
-    visual = gdk_screen_get_system_visual (screen);
   xvisual = ((GdkVisualPrivate*) visual)->xvisual;
   
   xattributes.event_mask = StructureNotifyMask | PropertyChangeMask;
   for (i = 0; i < _gdk_nenvent_masks; i++)
     {
-      if (attributes->event_mask & (1 << (i + 1)))
+      if (event_mask & (1 << (i + 1)))
 	xattributes.event_mask |= _gdk_event_mask_table[i];
     }
-  private->event_mask = attributes->event_mask;
-  
   if (xattributes.event_mask)
     xattributes_mask |= CWEventMask;
   
@@ -814,31 +698,22 @@ _gdk_window_new (GdkWindow     *parent,
     case GDK_WINDOW_TOPLEVEL:
     case GDK_WINDOW_DIALOG:
     case GDK_WINDOW_TEMP:
-      if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
+      if (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
 	{
-	  g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
-		     "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
+	  /* The common code warns for this case */
 	  xparent = GDK_SCREEN_XROOTWIN (screen);
 	}
-    case GDK_WINDOW_CHILD:
-      break;
-    default:
-      g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
-      return NULL;
     }
 	  
-  if (attributes->wclass == GDK_INPUT_OUTPUT)
+  if (!private->input_only)
     {
       class = InputOutput;
       depth = visual->depth;
 
-      private->input_only = FALSE;
-      private->depth = depth;
-      
-      if (attributes_mask & GDK_WA_COLORMAP)
+      if (private->colormap)
         {
-          draw_impl->colormap = attributes->colormap;
-          g_object_ref (attributes->colormap);
+          draw_impl->colormap = private->colormap;
+          g_object_ref (private->colormap);
         }
       else
 	{
@@ -853,12 +728,8 @@ _gdk_window_new (GdkWindow     *parent,
             }
 	}
       
-      private->bg_color.pixel = BlackPixel (xdisplay, screen_x11->screen_num);
-      private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
       xattributes.background_pixel = private->bg_color.pixel;
 
-      private->bg_pixmap = NULL;
-      
       xattributes.border_pixel = BlackPixel (xdisplay, screen_x11->screen_num);
       xattributes_mask |= CWBorderPixel | CWBackPixel;
 
@@ -885,29 +756,25 @@ _gdk_window_new (GdkWindow     *parent,
   else
     {
       depth = 0;
-      private->depth = 0;
       class = InputOnly;
-      private->input_only = TRUE;
       draw_impl->colormap = gdk_screen_get_system_colormap (screen);
       g_object_ref (draw_impl->colormap);
     }
 
   xid = draw_impl->xid = XCreateWindow (xdisplay, xparent,
-					impl->position_info.x, impl->position_info.y,
-					impl->position_info.width, impl->position_info.height,
+					private->x + private->parent->abs_x,
+					private->y + private->parent->abs_y,
+					private->width, private->height,
 					0, depth, class, xvisual,
 					xattributes_mask, &xattributes);
 
   g_object_ref (window);
   _gdk_xid_table_insert (screen_x11->display, &draw_impl->xid, window);
-  
+
   gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
 				  (attributes->cursor) :
 				  NULL));
   
-  if (private->parent)
-    private->parent->children = g_list_prepend (private->parent->children, window);
-  
   switch (GDK_WINDOW_TYPE (private))
     {
     case GDK_WINDOW_DIALOG:
@@ -929,11 +796,11 @@ _gdk_window_new (GdkWindow     *parent,
 	  XFree (class_hint);
 	}
   
-      setup_toplevel_window (window, parent);
+      setup_toplevel_window (window, (GdkWindow *)private->parent);
       break;
 
     case GDK_WINDOW_CHILD:
-      if ((attributes->wclass == GDK_INPUT_OUTPUT) &&
+      if (!private->input_only &&
 	  (draw_impl->colormap != gdk_screen_get_system_colormap (screen)) &&
 	  (draw_impl->colormap != gdk_drawable_get_colormap (gdk_window_get_toplevel (window))))
 	{
@@ -948,8 +815,6 @@ _gdk_window_new (GdkWindow     *parent,
 
   if (attributes_mask & GDK_WA_TYPE_HINT)
     gdk_window_set_type_hint (window, attributes->type_hint);
-
-  return window;
 }
 
 static GdkEventMask
@@ -1044,8 +909,8 @@ gdk_window_foreign_new_for_display (GdkDisplay     *display,
 
   private->x = attrs.x;
   private->y = attrs.y;
-  impl->width = attrs.width;
-  impl->height = attrs.height;
+  private->width = attrs.width;
+  private->height = attrs.height;
   private->window_type = GDK_WINDOW_FOREIGN;
   private->destroyed = FALSE;
 
@@ -1058,8 +923,6 @@ gdk_window_foreign_new_for_display (GdkDisplay     *display,
 
   private->depth = attrs.depth;
   
-  _gdk_window_init_position (GDK_WINDOW (private));
-
   g_object_ref (window);
   _gdk_xid_table_insert (display, &GDK_WINDOW_XID (window), window);
   return window;
@@ -1215,8 +1078,6 @@ gdk_window_destroy_notify (GdkWindow *window)
 {
   GdkWindowImplX11 *window_impl;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
   window_impl = GDK_WINDOW_IMPL_X11 (((GdkWindowObject *)window)->impl);
 
   if (!GDK_WINDOW_DESTROYED (window))
@@ -1433,6 +1294,7 @@ gdk_window_x11_show (GdkWindow *window,
       GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
       Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
       Window xwindow = GDK_WINDOW_XID (window);
+      gboolean unset_bg;
       
       if (raise)
         XRaiseWindow (xdisplay, xwindow);
@@ -1460,23 +1322,20 @@ gdk_window_x11_show (GdkWindow *window,
 	    gdk_x11_window_set_user_time (window, display_x11->user_time);
 	}
 
-      if (impl->position_info.mapped)
+      unset_bg = !private->input_only &&
+	(private->window_type == GDK_WINDOW_CHILD ||
+	 impl->override_redirect) &&
+	gdk_window_is_viewable (window);
+      
+      if (unset_bg)
+	_gdk_x11_window_tmp_unset_bg (window, TRUE);
+      
+      XMapWindow (xdisplay, xwindow);
+      
+      if (unset_bg)
 	{
-	  gboolean unset_bg = !private->input_only &&
-	    (private->window_type == GDK_WINDOW_CHILD ||
-	     impl->override_redirect) &&
-	    gdk_window_is_viewable (window);
-
-	  if (unset_bg)
-	    _gdk_x11_window_tmp_unset_bg (window, TRUE);
-	  
-	  XMapWindow (xdisplay, xwindow);
-
-	  if (unset_bg)
-	    {
-	      _gdk_x11_window_tmp_reset_bg (window, TRUE);
-	      gdk_window_invalidate_rect (window, NULL, TRUE);
-	    }
+	  _gdk_x11_window_tmp_reset_bg (window, TRUE);
+	  gdk_window_invalidate_rect (window, NULL, TRUE);
 	}
     }
 }
@@ -1615,7 +1474,7 @@ window_x11_move (GdkWindow *window,
     {
       _gdk_window_move_resize_child (window,
                                      x, y,
-                                     impl->width, impl->height);
+                                     private->width, private->height);
     }
   else
     {
@@ -1649,7 +1508,6 @@ window_x11_resize (GdkWindow *window,
       _gdk_window_move_resize_child (window,
                                      private->x, private->y,
                                      width, height);
-      _gdk_x11_drawable_update_size (private->impl);
     }
   else
     {
@@ -1661,13 +1519,13 @@ window_x11_resize (GdkWindow *window,
 
       if (impl->override_redirect)
         {
-          impl->width = width;
-          impl->height = height;
+          private->width = width;
+          private->height = height;
           _gdk_x11_drawable_update_size (private->impl);
         }
       else
         {
-          if (width != impl->width || height != impl->height)
+          if (width != private->width || height != private->height)
             private->resize_count += 1;
         }
     }
@@ -1708,14 +1566,14 @@ window_x11_move_resize (GdkWindow *window,
           private->x = x;
           private->y = y;
 
-          impl->width = width;
-          impl->height = height;
+          private->width = width;
+          private->height = height;
 
           _gdk_x11_drawable_update_size (private->impl);
         }
       else
         {
-          if (width != impl->width || height != impl->height)
+          if (width != private->width || height != private->height)
             private->resize_count += 1;
         }
     }
@@ -1750,10 +1608,6 @@ gdk_window_x11_reparent (GdkWindow *window,
   GdkWindowObject *parent_private;
   GdkWindowObject *old_parent_private;
   GdkWindowImplX11 *impl;
-  gboolean was_toplevel;
-
-  if (!new_parent)
-    new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
 
   window_private = (GdkWindowObject*) window;
   old_parent_private = (GdkWindowObject*)window_private->parent;
@@ -1763,14 +1617,8 @@ gdk_window_x11_reparent (GdkWindow *window,
   XReparentWindow (GDK_WINDOW_XDISPLAY (window),
 		   GDK_WINDOW_XID (window),
 		   GDK_WINDOW_XID (new_parent),
-		   x, y);
+		   window_private->abs_x + x, window_private->abs_y + y);
 
-  window_private->x = x;
-  window_private->y = y;
-
-  /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
-   * the root window
-   */
   if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
     new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
 
@@ -1782,54 +1630,44 @@ gdk_window_x11_reparent (GdkWindow *window,
     {
     case GDK_WINDOW_ROOT:
     case GDK_WINDOW_FOREIGN:
-      was_toplevel = WINDOW_IS_TOPLEVEL (window);
-
-      if (impl->toplevel_window_type != -1)
-	GDK_WINDOW_TYPE (window) = impl->toplevel_window_type;
-      else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
-	GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
+      /* Reparenting to toplevel */
+      
+      if (!WINDOW_IS_TOPLEVEL (window) &&
+	  GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
+	{
+	  /* This is also done in common code at a later stage, but we
+	     need it in setup_toplevel, so do it here too */
+	  if (window_private->toplevel_window_type != -1)
+	    GDK_WINDOW_TYPE (window) = window_private->toplevel_window_type;
+	  else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
+	    GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
+	  
+	  /* Wasn't a toplevel, set up */
+	  setup_toplevel_window (window, new_parent);
+	}
 
-      if (WINDOW_IS_TOPLEVEL (window) && !was_toplevel)
-	setup_toplevel_window (window, new_parent);
       break;
+      
     case GDK_WINDOW_TOPLEVEL:
     case GDK_WINDOW_CHILD:
     case GDK_WINDOW_DIALOG:
     case GDK_WINDOW_TEMP:
-      if (WINDOW_IS_TOPLEVEL (window))
+      if (WINDOW_IS_TOPLEVEL (window) &&
+	  impl->toplevel)
 	{
-	  /* Save the original window type so we can restore it if the
-	   * window is reparented back to be a toplevel
-	   */
-	  impl->toplevel_window_type = GDK_WINDOW_TYPE (window);
-	  GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
-	  if (impl->toplevel)
+	  if (impl->toplevel->focus_window)
 	    {
-	      if (impl->toplevel->focus_window)
-		{
-		  XDestroyWindow (GDK_WINDOW_XDISPLAY (window), impl->toplevel->focus_window);
-		  _gdk_xid_table_remove (GDK_WINDOW_DISPLAY (window), impl->toplevel->focus_window);
-		}
-
-	      gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), 
-					      impl->toplevel);
-	      g_free (impl->toplevel);
-	      impl->toplevel = NULL;
+	      XDestroyWindow (GDK_WINDOW_XDISPLAY (window), impl->toplevel->focus_window);
+	      _gdk_xid_table_remove (GDK_WINDOW_DISPLAY (window), impl->toplevel->focus_window);
 	    }
+	  
+	  gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), 
+					  impl->toplevel);
+	  g_free (impl->toplevel);
+	  impl->toplevel = NULL;
 	}
     }
 
-  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);
-  _gdk_window_init_position (GDK_WINDOW (window_private));
-
   return FALSE;
 }
 
@@ -1959,10 +1797,11 @@ gdk_window_focus (GdkWindow *window,
                   guint32    timestamp)
 {
   GdkDisplay *display;
-  
-  g_return_if_fail (GDK_IS_WINDOW (window));
 
-  if (GDK_WINDOW_DESTROYED (window))
+  g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
+  
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   display = GDK_WINDOW_DISPLAY (window);
@@ -2032,9 +1871,8 @@ gdk_window_set_hints (GdkWindow *window,
 {
   XSizeHints size_hints;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
   
   size_hints.flags = 0;
@@ -2087,9 +1925,8 @@ gdk_window_set_type_hint (GdkWindow        *window,
   GdkDisplay *display;
   Atom atom;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   display = gdk_drawable_get_display (window);
@@ -2172,7 +2009,8 @@ gdk_window_get_type_hint (GdkWindow *window)
 
   g_return_val_if_fail (GDK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
 
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return GDK_WINDOW_TYPE_HINT_NORMAL;
 
   type = GDK_WINDOW_TYPE_HINT_NORMAL;
@@ -2273,9 +2111,8 @@ gdk_window_set_modal_hint (GdkWindow *window,
 {
   GdkWindowObject *private;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   private = (GdkWindowObject*) window;
@@ -2308,10 +2145,10 @@ gdk_window_set_skip_taskbar_hint (GdkWindow *window,
 {
   GdkToplevelX11 *toplevel;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
   
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   toplevel = _gdk_x11_window_get_toplevel (window);
@@ -2345,10 +2182,10 @@ gdk_window_set_skip_pager_hint (GdkWindow *window,
 {
   GdkToplevelX11 *toplevel;
     
-  g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
   
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   toplevel = _gdk_x11_window_get_toplevel (window);
@@ -2376,10 +2213,10 @@ gdk_window_set_urgency_hint (GdkWindow *window,
 {
   GdkToplevelX11 *toplevel;
     
-  g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
   
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   toplevel = _gdk_x11_window_get_toplevel (window);
@@ -2424,9 +2261,8 @@ gdk_window_set_geometry_hints (GdkWindow         *window,
 {
   XSizeHints size_hints;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
   
   size_hints.flags = 0;
@@ -2533,7 +2369,8 @@ gdk_window_get_geometry_hints (GdkWindow      *window,
 
   *geom_mask = 0;
   
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   size_hints = XAllocSizeHints ();
@@ -2688,10 +2525,10 @@ gdk_window_set_title (GdkWindow   *window,
   Display *xdisplay;
   Window xwindow;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (title != NULL);
 
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
   
   display = gdk_drawable_get_display (window);
@@ -2738,11 +2575,10 @@ gdk_window_set_role (GdkWindow   *window,
 {
   GdkDisplay *display;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
   display = gdk_drawable_get_display (window);
 
-  if (!GDK_WINDOW_DESTROYED (window))
+  if (!GDK_WINDOW_DESTROYED (window) &&
+      WINDOW_IS_TOPLEVEL (window))
     {
       if (role)
 	XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
@@ -2767,7 +2603,7 @@ gdk_window_set_role (GdkWindow   *window,
  **/
 void          
 gdk_window_set_startup_id (GdkWindow   *window,
-		     const gchar *startup_id)
+			   const gchar *startup_id)
 {
   GdkDisplay *display;
   
@@ -2775,7 +2611,8 @@ gdk_window_set_startup_id (GdkWindow   *window,
 
   display = gdk_drawable_get_display (window);
 
-  if (!GDK_WINDOW_DESTROYED (window))
+  if (!GDK_WINDOW_DESTROYED (window) &&
+      WINDOW_IS_TOPLEVEL (window))
     {
       if (startup_id)
 	XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
@@ -2806,9 +2643,8 @@ void
 gdk_window_set_transient_for (GdkWindow *window, 
 			      GdkWindow *parent)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (parent))
+  if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (parent) &&
+      WINDOW_IS_TOPLEVEL (window))
     XSetTransientForHint (GDK_WINDOW_XDISPLAY (window), 
 			  GDK_WINDOW_XID (window),
 			  GDK_WINDOW_XID (parent));
@@ -2818,62 +2654,22 @@ static void
 gdk_window_x11_set_background (GdkWindow      *window,
                                const GdkColor *color)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkColormap *colormap = gdk_drawable_get_colormap (window);
-  
-  if (!GDK_WINDOW_DESTROYED (window))
-    XSetWindowBackground (GDK_WINDOW_XDISPLAY (window),
-			  GDK_WINDOW_XID (window), color->pixel);
-
-  private->bg_color = *color;
-  gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
-
-  if (private->bg_pixmap &&
-      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
-      private->bg_pixmap != GDK_NO_BG)
-    g_object_unref (private->bg_pixmap);
-  
-  private->bg_pixmap = NULL;
+  XSetWindowBackground (GDK_WINDOW_XDISPLAY (window),
+			GDK_WINDOW_XID (window), color->pixel);
 }
 
 static void
 gdk_window_x11_set_back_pixmap (GdkWindow *window,
-                                GdkPixmap *pixmap,
-                                gboolean   parent_relative)
+                                GdkPixmap *pixmap)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
   Pixmap xpixmap;
   
-  if (pixmap && !gdk_drawable_get_colormap (pixmap))
-    {
-      g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
-      return;
-    }
-  
-  if (private->bg_pixmap &&
-      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
-      private->bg_pixmap != GDK_NO_BG)
-    g_object_unref (private->bg_pixmap);
-
-  if (parent_relative)
-    {
-      xpixmap = ParentRelative;
-      private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
-    }
+  if (pixmap == GDK_PARENT_RELATIVE_BG)
+    xpixmap = ParentRelative;
+  else if (pixmap == GDK_NO_BG)
+    xpixmap = None;
   else
-    {
-      if (pixmap)
-	{
-	  g_object_ref (pixmap);
-	  private->bg_pixmap = pixmap;
-	  xpixmap = GDK_PIXMAP_XID (pixmap);
-	}
-      else
-	{
-	  xpixmap = None;
-	  private->bg_pixmap = GDK_NO_BG;
-	}
-    }
+    xpixmap = GDK_PIXMAP_XID (pixmap);
   
   if (!GDK_WINDOW_DESTROYED (window))
     XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
@@ -3026,9 +2822,8 @@ gdk_window_get_deskrelative_origin (GdkWindow *window,
   gulong number_return, bytes_after_return;
   guchar *data_return;
   
-  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
-  
-  if (!GDK_WINDOW_DESTROYED (window))
+  if (!GDK_WINDOW_DESTROYED (window) &&
+      WINDOW_IS_TOPLEVEL (window))
     {
       atom = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
 						    "ENLIGHTENMENT_DESKTOP");
@@ -3092,8 +2887,9 @@ gdk_window_get_root_origin (GdkWindow *window,
 {
   GdkRectangle rect;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
+  if (!WINDOW_IS_TOPLEVEL (window))
+    return;
+  
   gdk_window_get_frame_extents (window, &rect);
 
   if (x)
@@ -3138,7 +2934,6 @@ gdk_window_get_frame_extents (GdkWindow    *window,
   gint wx, wy;
   gboolean got_frame_extents = FALSE;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (rect != NULL);
   
   private = (GdkWindowObject*) window;
@@ -3148,7 +2943,8 @@ gdk_window_get_frame_extents (GdkWindow    *window,
   rect->width = 1;
   rect->height = 1;
   
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
   
   while (private->parent && ((GdkWindowObject*) private->parent)->parent)
@@ -3343,12 +3139,9 @@ _gdk_windowing_window_get_pointer (GdkDisplay      *display,
   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);
   
-  _gdk_x11_window_get_offsets (window, &xoffset, &yoffset);
-
   return_val = NULL;
   if (!GDK_WINDOW_DESTROYED (window)) 
     {
@@ -3374,8 +3167,8 @@ _gdk_windowing_window_get_pointer (GdkDisplay      *display,
 	}
     }
   
-  *x = winx + xoffset;
-  *y = winy + yoffset;
+  *x = winx;
+  *y = winy;
   *mask = xmask;
   
   return return_val;
@@ -3562,8 +3355,8 @@ gdk_window_x11_set_events (GdkWindow    *window,
   
   if (!GDK_WINDOW_DESTROYED (window))
     {
-      GDK_WINDOW_OBJECT (window)->event_mask = event_mask;
       xevent_mask = StructureNotifyMask | PropertyChangeMask;
+
       for (i = 0; i < _gdk_nenvent_masks; i++)
 	{
 	  if (event_mask & (1 << (i + 1)))
@@ -3621,8 +3414,6 @@ gdk_window_add_colormap_windows (GdkWindow *window)
     XFree (old_windows);
 }
 
-#define WARN_SHAPE_TOO_BIG() g_warning ("GdkWindow is too large to allow the use of shape masks or shape regions.")
-
 /*
  * This needs the X11 shape extension.
  * If not available, shaped windows will look
@@ -3637,20 +3428,11 @@ do_shape_combine_mask (GdkWindow *window,
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
   Pixmap pixmap;
-  gint xoffset, yoffset;
   
 #ifdef HAVE_SHAPE_EXT
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
-  _gdk_x11_window_get_offsets (window, &xoffset, &yoffset);
-
-  if (xoffset != 0 || yoffset != 0)
-    {
-      WARN_SHAPE_TOO_BIG ();
-      return;
-    }
-  
   if (shape == ShapeBounding
       ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
       : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
@@ -3735,20 +3517,11 @@ do_shape_combine_region (GdkWindow       *window,
 			 gint             shape)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
-  gint xoffset, yoffset;
   
 #ifdef HAVE_SHAPE_EXT
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
-  _gdk_x11_window_get_offsets (window, &xoffset, &yoffset);
-
-  if (xoffset != 0 || yoffset != 0)
-    {
-      WARN_SHAPE_TOO_BIG ();
-      return;
-    }
-  
   if (shape_region == NULL)
     {
       /* Use NULL mask to unset the shape */
@@ -3850,9 +3623,8 @@ gdk_window_set_override_redirect (GdkWindow *window,
 {
   XSetWindowAttributes attr;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (!GDK_WINDOW_DESTROYED (window))
+  if (!GDK_WINDOW_DESTROYED (window) &&
+      WINDOW_IS_TOPLEVEL (window))
     {
       GdkWindowObject *private = (GdkWindowObject *)window;
       GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
@@ -3886,8 +3658,6 @@ gdk_window_set_accept_focus (GdkWindow *window,
 {
   GdkWindowObject *private;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
   private = (GdkWindowObject *)window;  
   
   accept_focus = accept_focus != FALSE;
@@ -3896,7 +3666,8 @@ gdk_window_set_accept_focus (GdkWindow *window,
     {
       private->accept_focus = accept_focus;
 
-      if (!GDK_WINDOW_DESTROYED (window))
+      if (!GDK_WINDOW_DESTROYED (window) &&
+	  WINDOW_IS_TOPLEVEL (window))
 	update_wm_hints (window, FALSE);
     }
 }
@@ -3923,8 +3694,6 @@ gdk_window_set_focus_on_map (GdkWindow *window,
 {
   GdkWindowObject *private;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
   private = (GdkWindowObject *)window;  
   
   focus_on_map = focus_on_map != FALSE;
@@ -3932,8 +3701,10 @@ gdk_window_set_focus_on_map (GdkWindow *window,
   if (private->focus_on_map != focus_on_map)
     {
       private->focus_on_map = focus_on_map;
-
-      if ((!GDK_WINDOW_DESTROYED (window)) && (!private->focus_on_map))
+      
+      if ((!GDK_WINDOW_DESTROYED (window)) &&
+	  (!private->focus_on_map) &&
+	  WINDOW_IS_TOPLEVEL (window))
 	gdk_x11_window_set_user_time (window, 0);
     }
 }
@@ -3968,9 +3739,8 @@ gdk_x11_window_set_user_time (GdkWindow *window,
   glong timestamp_long = (glong)timestamp;
   Window xid;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   display = gdk_drawable_get_display (window);
@@ -4038,9 +3808,8 @@ gdk_window_set_icon_list (GdkWindow *window,
   GdkDisplay *display;
   gint n;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   display = gdk_drawable_get_display (window);
@@ -4150,10 +3919,10 @@ gdk_window_set_icon (GdkWindow *window,
 {
   GdkToplevelX11 *toplevel;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
   
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   toplevel = _gdk_x11_window_get_toplevel (window);
@@ -4210,9 +3979,8 @@ gdk_window_set_icon_name (GdkWindow   *window,
 {
   GdkDisplay *display;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      WINDOW_IS_TOPLEVEL (window))
     return;
 
   display = gdk_drawable_get_display (window);
@@ -4245,9 +4013,8 @@ gdk_window_set_icon_name (GdkWindow   *window,
 void
 gdk_window_iconify (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (GDK_WINDOW_IS_MAPPED (window))
@@ -4279,9 +4046,8 @@ gdk_window_iconify (GdkWindow *window)
 void
 gdk_window_deiconify (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (GDK_WINDOW_IS_MAPPED (window))
@@ -4315,9 +4081,8 @@ gdk_window_deiconify (GdkWindow *window)
 void
 gdk_window_stick (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (GDK_WINDOW_IS_MAPPED (window))
@@ -4372,9 +4137,8 @@ gdk_window_stick (GdkWindow *window)
 void
 gdk_window_unstick (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (GDK_WINDOW_IS_MAPPED (window))
@@ -4416,9 +4180,8 @@ gdk_window_unstick (GdkWindow *window)
 void
 gdk_window_maximize (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (GDK_WINDOW_IS_MAPPED (window))
@@ -4451,9 +4214,8 @@ gdk_window_maximize (GdkWindow *window)
 void
 gdk_window_unmaximize (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (GDK_WINDOW_IS_MAPPED (window))
@@ -4489,9 +4251,8 @@ gdk_window_unmaximize (GdkWindow *window)
 void
 gdk_window_fullscreen (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (GDK_WINDOW_IS_MAPPED (window))
@@ -4525,9 +4286,8 @@ gdk_window_fullscreen (GdkWindow *window)
 void
 gdk_window_unfullscreen (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (GDK_WINDOW_IS_MAPPED (window))
@@ -4564,7 +4324,8 @@ gdk_window_set_keep_above (GdkWindow *window,
 {
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (GDK_WINDOW_IS_MAPPED (window))
@@ -4605,7 +4366,8 @@ gdk_window_set_keep_below (GdkWindow *window, gboolean setting)
 {
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (GDK_WINDOW_IS_MAPPED (window))
@@ -4639,10 +4401,10 @@ gdk_window_get_group (GdkWindow *window)
 {
   GdkToplevelX11 *toplevel;
   
-  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
   g_return_val_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD, NULL);
 
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return NULL;
   
   toplevel = _gdk_x11_window_get_toplevel (window);
@@ -4672,11 +4434,12 @@ gdk_window_set_group (GdkWindow *window,
 {
   GdkToplevelX11 *toplevel;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
-  g_return_if_fail (leader == NULL || GDK_IS_WINDOW (leader));
+  g_return_if_fail (leader == NULL);
 
-  if (GDK_WINDOW_DESTROYED (window) || (leader != NULL && GDK_WINDOW_DESTROYED (leader)))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      (leader != NULL && GDK_WINDOW_DESTROYED (leader)) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   toplevel = _gdk_x11_window_get_toplevel (window);
@@ -4801,8 +4564,10 @@ gdk_window_set_decorations (GdkWindow      *window,
 			    GdkWMDecoration decorations)
 {
   MotifWmHints hints;
-  
-  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
   
   /* initialize to zero to avoid writing uninitialized data to socket */
   memset(&hints, 0, sizeof(hints));
@@ -4827,8 +4592,10 @@ gdk_window_get_decorations(GdkWindow       *window,
   MotifWmHints *hints;
   gboolean result = FALSE;
 
-  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
-
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return FALSE;
+  
   hints = gdk_window_get_mwm_hints (window);
   
   if (hints)
@@ -4873,6 +4640,10 @@ gdk_window_set_functions (GdkWindow    *window,
   MotifWmHints hints;
   
   g_return_if_fail (GDK_IS_WINDOW (window));
+
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
   
   /* initialize to zero to avoid writing uninitialized data to socket */
   memset(&hints, 0, sizeof(hints));
@@ -5917,9 +5688,8 @@ gdk_window_begin_resize_drag (GdkWindow     *window,
                               gint           root_y,
                               guint32        timestamp)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
@@ -5952,9 +5722,8 @@ gdk_window_begin_move_drag (GdkWindow *window,
                             gint       root_y,
                             guint32    timestamp)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
@@ -5988,7 +5757,8 @@ gdk_window_enable_synchronized_configure (GdkWindow *window)
   GdkWindowObject *private = (GdkWindowObject *)window;
   GdkWindowImplX11 *impl;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  if (!WINDOW_IS_TOPLEVEL (window))
+    return;
 
   impl = GDK_WINDOW_IMPL_X11 (private->impl);
 	  
@@ -6019,7 +5789,8 @@ gdk_window_configure_finished (GdkWindow *window)
 {
   GdkWindowImplX11 *impl;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  if (!WINDOW_IS_TOPLEVEL (window))
+    return;
   
   impl = GDK_WINDOW_IMPL_X11 (((GdkWindowObject *)window)->impl);
   if (!impl->use_synchronized_configure)
@@ -6060,6 +5831,11 @@ gdk_window_beep (GdkWindow *window)
 {
   GdkDisplay *display;
 
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+  
   display = GDK_WINDOW_DISPLAY (window);
 
 #ifdef HAVE_XKB
@@ -6101,7 +5877,8 @@ gdk_window_set_opacity (GdkWindow *window,
   g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
 
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   display = gdk_drawable_get_display (window);
@@ -6171,8 +5948,6 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface)
   iface->raise = gdk_window_x11_raise;
   iface->lower = gdk_window_x11_lower;
   iface->move_resize = gdk_window_x11_move_resize;
-  iface->scroll = _gdk_x11_window_scroll;
-  iface->move_region = _gdk_x11_window_move_region;
   iface->set_background = gdk_window_x11_set_background;
   iface->set_back_pixmap = gdk_window_x11_set_back_pixmap;
   iface->reparent = gdk_window_x11_reparent;
@@ -6184,7 +5959,7 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface)
   iface->set_child_shapes = gdk_window_x11_set_child_shapes;
   iface->merge_child_shapes = gdk_window_x11_merge_child_shapes;
   iface->set_static_gravities = gdk_window_x11_set_static_gravities;
-  iface->get_offsets = _gdk_x11_window_get_offsets;
+  iface->queue_antiexpose = _gdk_x11_window_queue_antiexpose;
 }
 
 #define __GDK_WINDOW_X11_C__
diff --git a/gdk/x11/gdkwindow-x11.h b/gdk/x11/gdkwindow-x11.h
index 2a2799b..78c22aa 100644
--- a/gdk/x11/gdkwindow-x11.h
+++ b/gdk/x11/gdkwindow-x11.h
@@ -44,22 +44,6 @@ typedef struct _GdkWindowImplX11 GdkWindowImplX11;
 typedef struct _GdkWindowImplX11Class GdkWindowImplX11Class;
 typedef struct _GdkXPositionInfo GdkXPositionInfo;
 
-struct _GdkXPositionInfo
-{
-  gint x;
-  gint y;
-  gint width;
-  gint height;
-  gint x_offset;		/* Offsets to add to X coordinates within window */
-  gint y_offset;		/*   to get GDK coodinates within window */
-  guint big : 1;
-  guint mapped : 1;
-  guint no_bg : 1;	        /* Set when the window background is temporarily
-				 * unset during resizing and scaling */
-  GdkRectangle clip_rect;	/* visible rectangle of window */
-};
-
-
 /* Window implementation for X11
  */
 
@@ -74,10 +58,8 @@ struct _GdkWindowImplX11
 {
   GdkDrawableImplX11 parent_instance;
 
-  gint width;
-  gint height;
-  
-  GdkXPositionInfo position_info;
+  guint no_bg : 1;	        /* Set when the window background is temporarily
+				 * unset during resizing and scaling */
   GdkToplevelX11 *toplevel;	/* Toplevel-specific information */
   GdkCursor *cursor;
   gint8 toplevel_window_type;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]