Index: gdk/Makefile.am
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/Makefile.am,v
retrieving revision 1.120
diff -u -p -r1.120 Makefile.am
--- gdk/Makefile.am	9 Jul 2005 00:10:11 -0000	1.120
+++ gdk/Makefile.am	13 Oct 2005 20:59:01 -0000
@@ -85,6 +85,7 @@ gdk_public_h_sources =				\
 gdk_headers =                     \
 	$(gdk_public_h_sources)   \
 	gdkenumtypes.h		  \
+	gdkwindowimpl.h		  \
 	gdkprivate.h		  \
 	gdkalias.h
 
@@ -106,6 +107,7 @@ gdk_c_sources =                 \
 	gdkinternals.h  	\
 	gdkintl.h		\
 	gdkdisplaymanager.c	\
+	gdkoffscreenwindow.c	\
 	gdkpango.c		\
 	gdkpixbuf-drawable.c	\
 	gdkpixbuf-render.c	\
@@ -119,7 +121,9 @@ gdk_c_sources =                 \
 	gdkscreen.c		\
 	gdkselection.c		\
 	gdkvisual.c		\
-	gdkwindow.c
+	gdkwindow.c		\
+	gdkwindowimpl.c
+
 
 #
 # setup GDK sources and their dependencies
@@ -128,10 +132,10 @@ gdk_c_sources =                 \
 gdkincludedir = $(includedir)/gtk-2.0/gdk
 gdkinclude_HEADERS = $(gdk_headers)
 
-# gdkmarshalers.c is not here because it is currently an empty file
 common_sources =                \
 	$(gdk_c_sources)	\
 	gdkenumtypes.c		\
+	gdkmarshalers.c		\
 	gdkmarshalers.h
 
 libgdk_x11_2_0_la_SOURCES = $(common_sources)
Index: gdk/gdk.symbols
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdk.symbols,v
retrieving revision 1.27
diff -u -p -r1.27 gdk.symbols
--- gdk/gdk.symbols	24 Aug 2005 03:29:05 -0000	1.27
+++ gdk/gdk.symbols	13 Oct 2005 20:59:01 -0000
@@ -240,12 +240,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
@@ -629,6 +623,31 @@ gdk_window_impl_x11_get_type G_GNUC_CONS
 #if IN_HEADER(__GDK_WINDOW_H__)
 #if IN_FILE(__GDK_WINDOW_C__)
 gdk_get_default_root_window
+gdk_window_new
+gdk_window_show_unraised
+gdk_window_show
+gdk_window_hide
+gdk_window_withdraw
+gdk_window_get_events
+gdk_window_set_events
+gdk_window_raise
+gdk_window_lower
+gdk_window_move
+gdk_window_resize
+gdk_window_move_resize
+gdk_window_scroll
+gdk_window_move_region
+gdk_window_set_background
+gdk_window_set_back_pixmap
+gdk_window_reparent
+gdk_window_set_cursor
+gdk_window_get_geometry
+gdk_window_get_origin
+gdk_window_shape_combine_mask
+gdk_window_shape_combine_region
+gdk_window_set_child_shapes
+gdk_window_merge_child_shapes
+gdk_window_set_static_gravities
 gdk_window_add_filter
 gdk_window_at_pointer
 gdk_window_begin_paint_rect
@@ -678,29 +697,11 @@ gdk_window_register_dnd
 #endif
 
 #if IN_HEADER(__GDK_WINDOW_H__)
-#if IN_FILE(__GDK_GEOMETRY_X11_C__)
-gdk_window_scroll
-gdk_window_move_region
-#endif
-#endif
-
-#if IN_HEADER(__GDK_WINDOW_H__)
 #if IN_FILE(__GDK_WINDOW_X11_C__)
-gdk_window_new
 gdk_window_foreign_new_for_display
+gdk_window_focus
 gdk_window_lookup
 gdk_window_lookup_for_display
-gdk_window_show_unraised
-gdk_window_show
-gdk_window_hide
-gdk_window_withdraw
-gdk_window_move
-gdk_window_resize
-gdk_window_move_resize
-gdk_window_reparent
-gdk_window_raise
-gdk_window_lower
-gdk_window_focus
 #ifndef GDK_DISABLE_DEPRECATED
 gdk_window_set_hints
 gdk_window_get_deskrelative_origin
@@ -714,17 +715,8 @@ gdk_window_set_geometry_hints
 gdk_window_set_title
 gdk_window_set_role
 gdk_window_set_transient_for
-gdk_window_set_background
-gdk_window_set_back_pixmap
-gdk_window_set_cursor
-gdk_window_get_geometry
-gdk_window_get_origin
 gdk_window_get_root_origin
 gdk_window_get_frame_extents
-gdk_window_get_events
-gdk_window_set_events
-gdk_window_shape_combine_mask
-gdk_window_shape_combine_region
 gdk_window_set_override_redirect
 gdk_window_set_accept_focus
 gdk_window_set_focus_on_map
@@ -746,9 +738,6 @@ gdk_window_set_group
 gdk_window_get_decorations
 gdk_window_set_decorations
 gdk_window_set_functions
-gdk_window_set_child_shapes
-gdk_window_merge_child_shapes
-gdk_window_set_static_gravities
 gdk_window_begin_move_drag
 gdk_window_begin_resize_drag
 gdk_window_enable_synchronized_configure
@@ -882,6 +871,9 @@ gdk_pixbuf_render_to_drawable_alpha
 
 #if IN_HEADER(__GDK_PIXMAP_H__)
 #if IN_FILE(__GDK_PIXMAP_C__)
+gdk_pixmap_new
+gdk_pixmap_create_from_data
+gdk_bitmap_create_from_data
 gdk_pixmap_colormap_create_from_xpm
 gdk_pixmap_create_from_xpm
 gdk_pixmap_colormap_create_from_xpm_d
@@ -892,12 +884,10 @@ gdk_pixmap_get_type G_GNUC_CONST
 
 #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_lookup
 gdk_pixmap_lookup_for_display
-gdk_pixmap_new
 #endif
 #endif
 
Index: gdk/gdkdisplay.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdkdisplay.c,v
retrieving revision 1.27
diff -u -p -r1.27 gdkdisplay.c
--- gdk/gdkdisplay.c	16 Mar 2005 03:17:27 -0000	1.27
+++ gdk/gdkdisplay.c	13 Oct 2005 20:59:01 -0000
@@ -22,6 +22,7 @@
  */
 
 #include <config.h>
+#include <math.h>
 #include <glib.h>
 #include "gdk.h"		/* gdk_event_send_client_message() */
 #include "gdkdisplay.h"
@@ -29,6 +30,7 @@
 #include "gdkmarshalers.h"
 #include "gdkscreen.h"
 #include "gdkalias.h"
+#include "gdkwindowimpl.h"
 
 enum {
   CLOSED,
@@ -62,6 +64,14 @@ static GdkWindow* singlehead_default_win
 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 };
 
@@ -70,8 +80,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 = {
@@ -282,6 +292,7 @@ gdk_display_put_event (GdkDisplay *displ
   _gdk_event_queue_append (display, gdk_event_copy (event));
 }
 
+
 /**
  * gdk_pointer_ungrab:
  * @time_: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no 
@@ -490,6 +501,34 @@ gdk_display_get_pointer (GdkDisplay     
     *mask = tmp_mask;
 }
 
+static GdkWindow*
+gdk_display_real_get_window_at_pointer (GdkDisplay *display,
+					gint       *win_x,
+					gint       *win_y)
+{
+  GdkWindow *window;
+  
+  window =_gdk_windowing_window_at_pointer (display, win_x, win_y);
+  
+  if (window && GDK_WINDOW_OBJECT (window)->offscreen_children)
+    {
+      GdkWindow *child;
+      gdouble child_x, child_y;
+      
+      child =  _gdk_window_get_offscreen_window_child_at (window,
+							  *win_x, *win_y,
+							  &child_x, &child_y);
+      *win_x = floor (child_x + 0.5);
+      *win_y = floor (child_y + 0.5);
+      
+      return child;
+    }
+  
+  return window;
+}
+
+
+
 /**
  * gdk_display_get_window_at_pointer:
  * @display: a #GdkDisplay
@@ -595,14 +634,52 @@ singlehead_window_at_pointer   (GdkDispl
 							      win_x, win_y);
 }
 
+static GdkWindow *
+gdk_window_real_window_get_pointer (GdkDisplay       *display,
+				    GdkWindow        *window,
+				    gint             *x,
+				    gint             *y,
+				    GdkModifierType  *mask)
+{
+  GdkWindowObject *private;
+  GdkWindow *event_window;
+  GdkWindow *pointer_window;
+  gint tmpx, tmpy;
+  
+  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
+
+  private = (GdkWindowObject *) window;
+
+  event_window = _gdk_window_get_offscreen_event_window (window);
+
+  pointer_window = _gdk_windowing_window_get_pointer (display, event_window, &tmpx, &tmpy, mask);
+
+  /* Convert to offscreen if needed */
+  _gdk_offscreen_window_transform_coords (event_window,
+					  window,
+					  &tmpx, &tmpy);
+  if (x)
+    *x = tmpx;
+  if (y)
+    *y = tmpy;
+
+  /* If the pointer is in a window with offscreen children, recalculate pointer
+   * window, as the pointer it might be in an offscreen child.
+   */
+  if (pointer_window != NULL && GDK_WINDOW_OBJECT (pointer_window)->offscreen_children)
+    pointer_window = gdk_display_real_get_window_at_pointer (display, &tmpx, &tmpy);
+  
+  return pointer_window;
+}
+
 static GdkWindow*
 singlehead_default_window_get_pointer (GdkWindow       *window,
 				       gint            *x,
 				       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*
@@ -610,8 +687,8 @@ singlehead_default_window_at_pointer  (G
 				       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);
 }
 
 /**
Index: gdk/gdkdraw.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdkdraw.c,v
retrieving revision 1.61
diff -u -p -r1.61 gdkdraw.c
--- gdk/gdkdraw.c	15 Jul 2005 20:33:09 -0000	1.61
+++ gdk/gdkdraw.c	13 Oct 2005 20:59:01 -0000
@@ -48,6 +48,7 @@ static GdkDrawable* gdk_drawable_real_ge
 							      gint          height,
 							      gint         *composite_x_offset,
 							      gint         *composite_y_offset);
+static GdkDrawable* gdk_drawable_real_get_source_drawable    (GdkDrawable  *drawable);
 static GdkRegion *  gdk_drawable_real_get_visible_region     (GdkDrawable  *drawable);
 static void         gdk_drawable_real_draw_pixbuf            (GdkDrawable  *drawable,
 							      GdkGC        *gc,
@@ -98,6 +99,7 @@ gdk_drawable_class_init (GdkDrawableClas
 {
   klass->get_image = gdk_drawable_real_get_image;
   klass->get_composite_drawable = gdk_drawable_real_get_composite_drawable;
+  klass->get_source_drawable = gdk_drawable_real_get_source_drawable;
   /* Default implementation for clip and visible region is the same */
   klass->get_clip_region = gdk_drawable_real_get_visible_region;
   klass->get_visible_region = gdk_drawable_real_get_visible_region;
@@ -676,7 +678,6 @@ gdk_draw_drawable (GdkDrawable *drawable
                                                           &composite_x_offset,
                                                           &composite_y_offset);
 
-  
   GDK_DRAWABLE_GET_CLASS (drawable)->draw_drawable (drawable, gc, composite,
                                                     xsrc - composite_x_offset,
                                                     ysrc - composite_y_offset,
@@ -1196,6 +1197,12 @@ gdk_drawable_real_get_image (GdkDrawable
 }
 
 static GdkDrawable*
+gdk_drawable_real_get_source_drawable (GdkDrawable *drawable)
+{
+  return drawable;
+}
+
+static GdkDrawable*
 gdk_drawable_real_get_composite_drawable (GdkDrawable *drawable,
                                           gint         x,
                                           gint         y,
@@ -1733,6 +1740,22 @@ _gdk_drawable_get_scratch_gc (GdkDrawabl
       return screen->normal_gcs[depth];
     }
 }
+
+/**
+ * _gdk_drawable_get_source_drawable:
+ * @drawable: A #GdkDrawable
+ *
+ * Returns a drawable for this drawable that is guaranteed to be usable
+ * to create a pixmap. I.E. it won't be an offscreen window.
+ *
+ * Since: 2.10
+ */
+GdkDrawable *
+_gdk_drawable_get_source_drawable (GdkDrawable *drawable)
+{
+  return GDK_DRAWABLE_GET_CLASS (drawable)->get_source_drawable (drawable);  
+}
+
 
 #define __GDK_DRAW_C__
 #include "gdkaliasdef.c"
Index: gdk/gdkdrawable.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdkdrawable.h,v
retrieving revision 1.34
diff -u -p -r1.34 gdkdrawable.h
--- gdk/gdkdrawable.h	12 Jul 2005 04:29:47 -0000	1.34
+++ gdk/gdkdrawable.h	13 Oct 2005 20:59:01 -0000
@@ -194,9 +194,10 @@ struct _GdkDrawableClass 
 				   gint              n_trapezoids);
 
   cairo_surface_t *(*ref_cairo_surface) (GdkDrawable *drawable);
+  
+  GdkDrawable * (*get_source_drawable)  (GdkDrawable *drawable);
 
   /* Padding for future expansion */
-  void         (*_gdk_reserved4)  (void);
   void         (*_gdk_reserved5)  (void);
   void         (*_gdk_reserved6)  (void);
   void         (*_gdk_reserved7)  (void);
Index: gdk/gdkevents.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdkevents.c,v
retrieving revision 1.73
diff -u -p -r1.73 gdkevents.c
--- gdk/gdkevents.c	26 Jun 2005 07:06:13 -0000	1.73
+++ gdk/gdkevents.c	13 Oct 2005 20:59:01 -0000
@@ -102,6 +102,44 @@ _gdk_event_queue_append (GdkDisplay *dis
 }
 
 /**
+ * _gdk_event_queue_append_after:
+ * @display: a #GdkDisplay
+ * @after_event: 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.
+ **/
+GList *
+_gdk_event_queue_append_after (GdkDisplay *display,
+			       GdkEvent   *after_event,
+			       GdkEvent   *event)
+{
+  GList *tmp_list = display->queued_events;
+
+  while (tmp_list)
+    {
+      GdkEvent *list_event = tmp_list->data;
+
+      if (list_event == after_event)
+	{
+	  tmp_list->next = g_list_prepend (tmp_list->next, event);
+	  
+	  if (display->queued_tail == tmp_list)
+	    display->queued_tail = tmp_list->next;
+
+	  return tmp_list->next;
+	}
+      
+      tmp_list = g_list_next (tmp_list);
+    }
+
+  return _gdk_event_queue_append (display, event);
+}
+
+/**
  * _gdk_event_queue_remove_link:
  * @display: a #GdkDisplay
  * @node: node to remove
@@ -553,6 +591,7 @@ gdk_event_get_time (GdkEvent *event)
       case GDK_CONFIGURE:
       case GDK_FOCUS_CHANGE:
       case GDK_NOTHING:
+      case GDK_DAMAGE:
       case GDK_DELETE:
       case GDK_DESTROY:
       case GDK_EXPOSE:
@@ -623,6 +662,7 @@ gdk_event_get_state (GdkEvent        *ev
       case GDK_SELECTION_NOTIFY:
       case GDK_PROXIMITY_IN:
       case GDK_PROXIMITY_OUT:
+      case GDK_DAMAGE:
       case GDK_DRAG_ENTER:
       case GDK_DRAG_LEAVE:
       case GDK_DRAG_MOTION:
@@ -1024,13 +1064,18 @@ gdk_synthesize_click (GdkDisplay *displa
 		      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);
+  _gdk_event_rewrite_for_offscreen (display, link, event_copy);
 }
 
 void
Index: gdk/gdkevents.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdkevents.h,v
retrieving revision 1.28
diff -u -p -r1.28 gdkevents.h
--- gdk/gdkevents.h	12 Jul 2005 04:29:47 -0000	1.28
+++ gdk/gdkevents.h	13 Oct 2005 20:59:01 -0000
@@ -146,7 +146,8 @@ typedef enum
   GDK_WINDOW_STATE      = 32,
   GDK_SETTING           = 33,
   GDK_OWNER_CHANGE      = 34,
-  GDK_GRAB_BROKEN       = 35
+  GDK_GRAB_BROKEN       = 35,
+  GDK_DAMAGE            = 36
 } GdkEventType;
 
 /* Event masks. (Used to select what types of events a window
Index: gdk/gdkinternals.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdkinternals.h,v
retrieving revision 1.37
diff -u -p -r1.37 gdkinternals.h
--- gdk/gdkinternals.h	12 Jun 2005 05:32:24 -0000	1.37
+++ gdk/gdkinternals.h	13 Oct 2005 20:59:01 -0000
@@ -178,6 +178,9 @@ void   _gdk_event_queue_remove_link (Gdk
 				     GList      *node);
 GList*  _gdk_event_queue_append     (GdkDisplay *display,
 				     GdkEvent   *event);
+GList *_gdk_event_queue_append_after (GdkDisplay *display,
+				      GdkEvent   *after_event,
+				      GdkEvent   *event);
 void _gdk_event_button_generate     (GdkDisplay *display,
 				     GdkEvent   *event);
 
@@ -212,6 +215,8 @@ GdkImage *_gdk_drawable_copy_to_image (G
 
 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);
@@ -249,6 +254,25 @@ guint32    _gdk_gc_get_bg_pixel    (GdkG
  * Interfaces provided by windowing code *
  *****************************************/
 
+GdkWindow* _gdk_window_new              (GdkWindow      *parent,
+					 GdkWindowAttr  *attributes,
+					 gint            attributes_mask);
+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);
+
 /* Font/string functions implemented in module-specific code */
 gint _gdk_font_strlen (GdkFont *font, const char *str);
 void _gdk_font_destroy (GdkFont *font);
@@ -268,16 +292,6 @@ gchar *_gdk_windowing_substitute_screen_
 void     _gdk_windowing_window_get_offsets      (GdkWindow  *window,
 						 gint       *x_offset,
 						 gint       *y_offset);
-void     _gdk_windowing_window_clear_area       (GdkWindow  *window,
-						 gint        x,
-						 gint        y,
-						 gint        width,
-						 gint        height);
-void     _gdk_windowing_window_clear_area_e     (GdkWindow  *window,
-						 gint        x,
-						 gint        y,
-						 gint        width,
-						 gint        height);
 
 void       _gdk_windowing_get_pointer        (GdkDisplay       *display,
 					      GdkScreen       **screen,
@@ -375,6 +389,52 @@ void _gdk_windowing_gc_get_foreground (G
 /* Queries the current background color of a GdkGC */
 void _gdk_windowing_gc_get_background (GdkGC    *gc,
 				       GdkColor *color);
+
+void _gdk_windowing_grab_broken (GdkDisplay *display);
+void _gdk_windowing_update_implicit_grab (GdkWindow *old_grab, GdkWindow *new_grab, guint event_mask, guint32 time);
+
+/******************************
+ * offscreen window routines  *
+ ******************************/
+
+GdkWindow* _gdk_window_new_offscreen                (GdkWindow     *parent,
+						     GdkWindowAttr *attributes,
+						     gint           attributes_mask,
+						     gboolean       toplevel);
+void       _gdk_offscreen_window_destroy            (GdkWindow     *window,
+						     gboolean       recursing);
+void       _gdk_offscreen_window_set_pointer_grab   (GdkWindow     *old_grab_window,
+						     GdkWindow     *old_native_grab_window,
+						     GdkWindow     *grab_window,
+						     gboolean       owner_events,
+						     guint          event_mask,
+						     guint32        time);
+void       _gdk_offscreen_window_unset_pointer_grab (GdkWindow     *window,
+						     gboolean       regrab,
+						     gboolean       grab_one_button_release,
+						     guint32        time);
+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);
+void       _gdk_event_rewrite_for_offscreen         (GdkDisplay    *display,
+						     GList         *event_node,
+						     GdkEvent      *event);
+void       _gdk_window_add_offscreen_child          (GdkWindow     *window);
+void       _gdk_window_remove_offscreen_child       (GdkWindow     *window);
+GdkWindow *_gdk_window_get_offscreen_window_child_at (GdkWindow *parent,
+						      gdouble    x,
+						      gdouble    y,
+						      gdouble   *win_x_out,
+						      gdouble   *win_y_out);
+GdkWindow *_gdk_window_get_offscreen_event_window   (GdkWindow *window);
+void _gdk_offscreen_window_transform_coords (GdkWindow       *event_window,
+					     GdkWindow       *relative_window,
+					     gint            *x,
+					     gint            *y);
+gboolean _gdk_window_is_toplevel_offscreen (GdkWindow *child);
 
 /************************************
  * Initialization and exit routines *
Index: gdk/gdkmarshalers.list
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdkmarshalers.list,v
retrieving revision 1.2
diff -u -p -r1.2 gdkmarshalers.list
--- gdk/gdkmarshalers.list	1 Aug 2002 23:43:11 -0000	1.2
+++ gdk/gdkmarshalers.list	13 Oct 2005 20:59:01 -0000
@@ -1,2 +1,5 @@
 VOID:OBJECT
 VOID:BOOLEAN
+VOID:BOXED
+VOID:DOUBLE,DOUBLE,POINTER,POINTER
+OBJECT:DOUBLE,DOUBLE
Index: gdk/gdkoffscreenwindow.c
===================================================================
RCS file: gdk/gdkoffscreenwindow.c
diff -N gdk/gdkoffscreenwindow.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gdk/gdkoffscreenwindow.c	13 Oct 2005 20:59:02 -0000
@@ -0,0 +1,2500 @@
+/* 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 must be child windows
+ * Offscreen windows can't be the child of a foregin window, nor contain foreign windows
+ * All drawing must be within begin/end_paint
+ * The confine_window argument of pointer grabs doesn't work
+ * GDK_POINTER_MOTION_HINT_MASK isn't effective
+ * You can't reparent between offscreen windows and normal windows
+ */
+
+/* TODO:
+
+ * change expose order so that children are exposed before parent, to
+   avoid double drawing due to damage from children coming after parent expose.
+   Event with the right order we will expose twice, although both with an
+   uptodate pixmap.
+   Not sure how to fix this. Perhaps with a get_and_clear_damage() call?
+
+ * gtk_widget_reparent should unrealize/realize if the new parent GdkWindow is
+   offscreen and widget is not, or if the new parent is not offscreen and the
+   widget is. The problem is, how do you know what the new parent GdkWindow is
+   before gtk_container_add()?
+   
+ * Unite the API for all 3 kinds of redirection? how?
+
+ * support scroll button events
+
+ * support cursors in offscreen windows
+
+ * XIM support (is this possible?)
+
+ * Introduce generic "this point in the window in root/other window coords" operation in gtk
+
+ * dnd drop positions wrong with transformed windows. Needs above point transformation.
+
+ * various menu popup positions wrong with transformed widgets.  Needs above point transformation.
+ 
+ */
+
+typedef struct _GdkOffscreenWindow GdkOffscreenWindow;
+typedef struct _GdkOffscreenWindowClass GdkOffscreenWindowClass;
+
+struct _GdkOffscreenWindow
+{
+  GdkDrawable parent_instance;
+
+  GdkWindow *wrapper;
+  gint width, height;
+  GdkCursor *cursor;
+  GdkColormap *colormap;
+  GdkScreen *screen;
+
+  GdkOffscreenWindow *toplevel_offscreen; /* same window if this is the toplevel */
+  
+  /* computed position in pixmap:
+   *   abs: position of top left corner of window in pixmap
+   *   llim: lower limit of visible part of window
+   *         this can be != abs if the window is outside its parent
+   *   lim: upper limit of visible part of window
+   */
+  gint abs_x, abs_y, lim_x, lim_y, llim_x, llim_y; 
+};
+ 
+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       send_crossing_events                    (GdkWindowOffscreenChildren *offscreen_children,
+							   GdkWindow                  *event_window,
+							   GdkWindow                  *src,
+							   GdkWindow                  *dest,
+							   GdkCrossingMode             mode,
+							   int                         event_x,
+							   int                         event_y,
+							   GdkModifierType             mask,
+							   guint32                     time,
+							   gboolean                    do_first,
+							   gboolean                    do_last);
+static GdkWindow * gdk_offscreen_window_get_window_at (GdkWindow *window,
+						       gdouble x,  gdouble y,
+						       gdouble *win_x, gdouble *win_y);
+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);
+static GdkRegion *gdk_offscreen_window_get_visible_region (GdkDrawable                *drawable);
+static void convert_event_coords_to_window (GdkWindow *event_window,
+					    GdkWindow *window,
+					    gdouble event_x, gdouble event_y,
+					    gdouble *window_x, gdouble *window_y);
+
+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;
+}
+
+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 (offscreen->toplevel_offscreen == offscreen &&
+      private->parent)
+    _gdk_window_remove_offscreen_child (GDK_WINDOW (private->parent));
+  
+  if (!recursing)
+    {
+      gdk_offscreen_window_hide (window);
+    }
+
+  g_object_unref (offscreen->colormap);
+  offscreen->colormap = NULL;
+}
+
+
+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);
+  GdkWindowObject *private;
+
+  private = GDK_WINDOW_OBJECT (offscreen->wrapper);
+
+  return gdk_gc_new_with_values (private->redirect->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)
+{
+  /* TODO */
+  return NULL;
+}
+
+static cairo_surface_t *
+gdk_offscreen_window_ref_cairo_surface (GdkDrawable *drawable)
+{
+  g_error ("Attempt to get a cairo surface directly for an offscreen window. This is not supported, you must use gdk_window_begin_paint_region.");
+
+  return NULL;
+}
+
+
+
+static void
+gdk_offscreen_window_empty_draw_op (GdkDrawable *drawable)
+{
+  /* All actual rendering is done in gdkwindow.c */
+}
+
+static GdkWindow *
+find_offscreen_child (GdkWindow *window, double x, double y)
+{
+  GdkWindow *hit_window;
+  
+  hit_window = NULL;
+  g_signal_emit_by_name (window, "find_offscreen_child",
+			 x, y, &hit_window);
+  
+  return hit_window;
+}
+
+
+static void
+window_to_parent (GdkWindow *window, gdouble x, gdouble y,
+		  gdouble *parent_x, gdouble *parent_y)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+
+  /* Default value if no handler */
+  *parent_x = x + private->x;
+  *parent_y = y + private->y;
+  
+  g_signal_emit_by_name (window, "window_to_parent_coordinate",
+			 x, y, parent_x, parent_y);
+}
+
+static void
+parent_to_window (GdkWindow *window, gdouble x, gdouble y,
+		  gdouble *window_x, gdouble *window_y)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+
+  /* Default value if no handler */
+  *window_x = x - private->x;
+  *window_y = y - private->y;
+  
+  g_signal_emit_by_name (window, "parent_to_window_coordinate",
+			 x, y, window_x, window_y);
+}
+
+
+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 void
+gdk_offscreen_window_get_size (GdkDrawable *drawable,
+			       gint         *width,
+			       gint         *height)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+  if (width)
+    *width = offscreen->width;
+  if (height)
+    *height = offscreen->height;
+}
+
+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
+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_size = gdk_offscreen_window_get_size;
+  drawable_class->get_screen = gdk_offscreen_window_get_screen;
+  drawable_class->get_visual = gdk_offscreen_window_get_visual;
+  drawable_class->get_clip_region = gdk_offscreen_window_get_visible_region;
+  drawable_class->get_visible_region = gdk_offscreen_window_get_visible_region;
+
+  /* All actual rendering is done in gdkwindow.c with the redirect */
+  drawable_class->draw_drawable = (gpointer)gdk_offscreen_window_empty_draw_op;
+  drawable_class->draw_rectangle = (gpointer)gdk_offscreen_window_empty_draw_op;
+  drawable_class->draw_points = (gpointer)gdk_offscreen_window_empty_draw_op;
+  drawable_class->draw_arc = (gpointer)gdk_offscreen_window_empty_draw_op;
+  drawable_class->draw_polygon = (gpointer)gdk_offscreen_window_empty_draw_op;
+  drawable_class->draw_text = (gpointer)gdk_offscreen_window_empty_draw_op;
+  drawable_class->draw_text_wc = (gpointer)gdk_offscreen_window_empty_draw_op;
+  drawable_class->draw_segments = (gpointer)gdk_offscreen_window_empty_draw_op;
+  drawable_class->draw_lines = (gpointer)gdk_offscreen_window_empty_draw_op;
+  drawable_class->draw_image = (gpointer)gdk_offscreen_window_empty_draw_op;
+  drawable_class->draw_pixbuf = (gpointer)gdk_offscreen_window_empty_draw_op;
+}
+
+static void
+recompute_abs_positions(GdkWindow *window,
+			gint parent_x, gint parent_y,
+			gint parent_llim_x, gint parent_llim_y,
+			gint parent_lim_x, gint parent_lim_y)
+{
+  GList *l;
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkOffscreenWindow *offscreen;
+  int x, y;
+  
+  if (!GDK_WINDOW_IS_MAPPED (window))
+    return;
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+  
+  offscreen->abs_x = parent_x + private->x;
+  offscreen->abs_y = parent_y + private->y;
+  x = MAX (parent_llim_x, offscreen->abs_x);
+  x = MIN (x, parent_lim_x);
+  offscreen->llim_x = x;
+  y = MAX (parent_llim_y, offscreen->abs_y);
+  y = MIN (y, parent_lim_y);
+  offscreen->llim_y = y;
+  x = MIN (parent_lim_x, offscreen->abs_x + offscreen->width);
+  x = MAX (x, offscreen->llim_x);
+  offscreen->lim_x = x;
+  y = MIN (parent_lim_y,
+	   offscreen->abs_y + offscreen->height);
+  y = MAX (y, offscreen->llim_y);
+  offscreen->lim_y = y;
+  
+  g_assert (offscreen->llim_x <= offscreen->lim_x);
+  g_assert (offscreen->llim_y <= offscreen->lim_y);
+  
+  for (l = private->children; l; l = l->next)
+    recompute_abs_positions (l->data,
+			     offscreen->abs_x, offscreen->abs_y,
+			     offscreen->llim_x, offscreen->llim_y,
+			     offscreen->lim_x, offscreen->lim_y);
+}
+
+
+static void
+recompute_window (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkOffscreenWindow *offscreen, *parent_offscreen;
+  GdkWindowObject *parent_private;
+  GList *l;
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+  if (offscreen->toplevel_offscreen == offscreen)
+    {
+      offscreen->abs_x = 0;
+      offscreen->abs_y = 0;
+      offscreen->llim_x = 0;
+      offscreen->llim_y = 0;
+      offscreen->lim_x = offscreen->width;
+      offscreen->lim_y = offscreen->height;
+
+      for (l = private->children; l; l = l->next)
+	recompute_abs_positions (l->data,
+				 offscreen->abs_x, offscreen->abs_y,
+				 offscreen->llim_x, offscreen->llim_y,
+				 offscreen->lim_x, offscreen->lim_y);
+    }
+  else
+    {
+      parent_private = private->parent;
+      parent_offscreen = GDK_OFFSCREEN_WINDOW (parent_private->impl);
+      recompute_abs_positions (window,
+			       parent_offscreen->abs_x,
+			       parent_offscreen->abs_y,
+			       parent_offscreen->llim_x,
+			       parent_offscreen->llim_y,
+			       parent_offscreen->lim_x,
+			       parent_offscreen->lim_y);
+    }
+}
+
+
+/**
+ * gdk_window_new_offscreen:
+ * @parent: a #GdkWindow
+ * @attributes: attributes of the new window
+ * @attributes_mask: mask indicating which fields in @attributes are valid
+ * 
+ * Creates a new offscreen #GdkWindow child using the attributes from 
+ * @attributes. See #GdkWindowAttr and #GdkWindowAttributesType for
+ * more details.
+
+ * Being offscreen means that the window will not automatically
+ * rendered to the parent window, instead it is drawn to a pixmap that
+ * is availible with gdk_window_get_offscreen_pixmap(). You can use
+ * this pixmap to render the window however you want. When the
+ * offscreen pixmap is drawn into, damage events are sent to the
+ * window, so the GtkWidget::damage_event signal handler can be used
+ * to make sure the parent window is updated.
+ *
+ * All children of an offscreen window are automatically turned into
+ * offscreen windows that share the offscreen pixmap with the window
+ * created using gdk_window_new_offscreen(). You can nest offscreen
+ * windows, but at least one ancestor must be a non-offscreen window.
+ *
+ * To correctly support offscreen children a parent window should
+ * catch the GdkWindow::find-offscreen-child signal on the parent
+ * window. Additionally, if you render the child transformed you need
+ * to implement GdkWindow::parent-to-window-coordinate and
+ * GdkWindow::window-to-parent-coordinate to get coordinates correct
+ * in e.g. pointer events.
+ *
+ * Offscreen windows have some limitations:
+ * <itemizedlist>
+ * <listitem><para>They can't be toplevel windows.
+ * </para></listitem>
+ * <listitem><para>They can't contain foreign windows, nor be children
+ * of foreign windows. This means #GtkPlug/#GtkSocket doesn't work
+ * with them.
+ * </para></listitem>
+ * <listitem><para>X specific features like XVideo and GLX doesn't work.
+ * </para></listitem>
+ * <listitem><para>All rendering must be done inside 
+ * gdk_window_begin_paint_region()/gdk_window_end_paint() calls.
+ * </para></listitem>
+ * <listitem><para>The confine_window argument of pointer grabs doesn't work
+ * </para></listitem>
+ * <listitem><para>GDK_POINTER_MOTION_HINT_MASK isn't effective
+ * </para></listitem>
+ * <listitem><para>You can't reparent between offscreen windows and normal windows
+ * </para></listitem>
+ * </itemizedlist>
+ * 
+ * 
+ * Return value: the new #GdkWindow
+ **/
+GdkWindow*
+gdk_window_new_offscreen (GdkWindow     *parent,
+			  GdkWindowAttr *attributes,
+			  gint           attributes_mask)
+{
+  return _gdk_window_new_offscreen (parent, attributes, attributes_mask, TRUE);
+}
+
+GdkWindow*
+_gdk_window_new_offscreen (GdkWindow     *parent,
+			   GdkWindowAttr *attributes,
+			   gint           attributes_mask,
+			   gboolean       toplevel)
+{
+  GdkWindow *window;
+  GdkWindowObject *parent_private;
+  GdkWindowObject *private;
+  GdkOffscreenWindow *offscreen;
+  int x, y;
+  GdkScreen *screen;
+  GdkVisual *visual;
+
+  g_return_val_if_fail (attributes != NULL, NULL);
+  
+  if (parent == NULL ||
+      (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT) ||
+      (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN) ||
+      (attributes->window_type != GDK_WINDOW_CHILD) )
+    {
+      g_warning ("Only child offscreen windows allowed");
+      return NULL;
+    }
+
+  if (GDK_WINDOW_DESTROYED (parent))
+    return NULL;
+  
+  parent_private = (GdkWindowObject*)parent;
+  
+  window = g_object_new (GDK_TYPE_WINDOW, NULL);
+  private = (GdkWindowObject *)window;
+  private->impl = g_object_new (GDK_TYPE_OFFSCREEN_WINDOW, NULL);
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+  offscreen->wrapper = window;
+
+  private->parent = (GdkWindowObject *)parent;
+  
+  screen = gdk_drawable_get_screen (parent);
+
+  offscreen->screen = screen;
+  
+  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;
+  offscreen->width = (attributes->width > 1) ? (attributes->width) : (1);
+  offscreen->height = (attributes->height > 1) ? (attributes->height) : (1);
+
+  private->window_type = GDK_WINDOW_CHILD;
+
+  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)
+    {
+      private->input_only = FALSE;
+      private->depth = visual->depth;
+
+      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);
+            }
+	}
+
+      private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
+      private->bg_color.pixel = 0; 
+      private->bg_pixmap = NULL;
+    }
+  else
+    {
+      private->depth = 0;
+      private->input_only = TRUE;
+      offscreen->colormap = gdk_screen_get_system_colormap (screen);
+      g_object_ref (offscreen->colormap);
+    }
+
+  if (private->parent)
+    {
+      private->parent->children = g_list_prepend (private->parent->children, window);
+      
+      if (toplevel)
+	_gdk_window_add_offscreen_child (GDK_WINDOW (private->parent));
+    }
+  
+  /* Inherit redirection from parent */
+  private->redirect = private->parent->redirect;
+  
+  if (toplevel)
+    {
+      GdkPixmap *pixmap;
+      
+      offscreen->toplevel_offscreen = offscreen;
+      offscreen->abs_x = 0;
+      offscreen->abs_y = 0;
+      offscreen->llim_x = 0;
+      offscreen->llim_y = 0;
+      offscreen->lim_x = offscreen->width;
+      offscreen->lim_y = offscreen->height;
+
+      pixmap = gdk_pixmap_new (parent,
+			       offscreen->width,
+			       offscreen->height,
+			       private->depth);
+      gdk_window_redirect_to_drawable (window,
+				       pixmap, 0, 0, 0, 0,
+				       offscreen->width,
+				       offscreen->height);
+      g_object_unref (pixmap);
+    }
+  else
+    {
+      GdkOffscreenWindow *parent_offscreen = GDK_OFFSCREEN_WINDOW (parent_private->impl);
+
+      offscreen->toplevel_offscreen = parent_offscreen->toplevel_offscreen;
+      recompute_abs_positions (window,
+			       parent_offscreen->abs_x, parent_offscreen->abs_y,
+			       parent_offscreen->llim_x, parent_offscreen->llim_y,
+			       parent_offscreen->lim_x, parent_offscreen->lim_y);
+    }
+
+
+  return window;
+}
+
+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;
+  GdkOffscreenWindow *offscreen;
+  gboolean was_mapped;
+
+  /* Can't reparent offscreen window to toplevel */
+  if (!new_parent)
+    return FALSE;
+
+  if (!gdk_window_is_offscreen (new_parent))
+    {
+      g_warning ("Can't reparent offscreen window to native parent");
+      return FALSE;
+    }
+
+  /* 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);
+      if (offscreen->toplevel_offscreen == offscreen)
+	_gdk_window_remove_offscreen_child (GDK_WINDOW (private->parent));
+    }
+
+  private->parent = new_parent_private;
+  private->x = x;
+  private->y = y;
+  
+  private->parent->children = g_list_prepend (private->parent->children, window);
+  if (offscreen->toplevel_offscreen == offscreen)
+    _gdk_window_add_offscreen_child (GDK_WINDOW (private->parent));
+  else
+    {
+      GdkOffscreenWindow *parent_offscreen = GDK_OFFSCREEN_WINDOW (new_parent_private->impl);
+
+      offscreen->toplevel_offscreen = parent_offscreen->toplevel_offscreen;
+      recompute_abs_positions (window,
+			       parent_offscreen->abs_x, parent_offscreen->abs_y,
+			       parent_offscreen->llim_x, parent_offscreen->llim_y,
+			       parent_offscreen->lim_x, parent_offscreen->lim_y);
+    }
+
+  return was_mapped;
+}
+
+/**
+ * gdk_window_is_offscreen:
+ * @window: a #GdkWindow
+ *
+ * Returns: %TRUE if the window is an offscreen window
+ **/
+gboolean
+gdk_window_is_offscreen (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+
+  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+
+  return GDK_IS_OFFSCREEN_WINDOW (private->impl);
+}
+
+gboolean
+_gdk_window_is_toplevel_offscreen (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 FALSE;
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+  return offscreen->toplevel_offscreen == offscreen;
+}
+
+
+/**
+ * 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;
+
+  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+
+  if (!GDK_IS_OFFSCREEN_WINDOW (private->impl))
+    return NULL;
+  
+  return private->redirect->pixmap;
+}
+
+static void
+gdk_offscreen_window_get_visible_rect (GdkWindow *window,
+				       GdkRectangle *rect)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+  
+  rect->x = offscreen->llim_x - offscreen->abs_x;
+  rect->y = offscreen->llim_y - offscreen->abs_y;
+  rect->width = offscreen->lim_x - offscreen->llim_x;
+  rect->height = offscreen->lim_y - offscreen->llim_y;
+}
+
+static GdkRegion *
+gdk_offscreen_window_get_visible_region (GdkDrawable *drawable)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkRectangle rect;
+
+  gdk_offscreen_window_get_visible_rect (offscreen->wrapper, &rect);
+  return gdk_region_rectangle (&rect);
+}
+
+static void
+gdk_offscreen_window_invalidate_visible (GdkWindow *window)
+{
+  GdkRectangle r;
+
+  gdk_offscreen_window_get_visible_rect (window, &r);
+  gdk_window_invalidate_rect (window, &r, TRUE);
+}
+
+static void
+gdk_offscreen_window_raise (GdkWindow *window)
+{
+  /* gdk_window_raise already changed the stacking order */
+  gdk_offscreen_window_invalidate_visible (window);
+}
+
+static void
+gdk_offscreen_window_invalidate_in_parent (GdkWindowObject *private)
+{
+  GdkRectangle r, child;
+  GdkOffscreenWindow *offscreen;
+  
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+  
+  gdk_offscreen_window_get_visible_rect (GDK_WINDOW (private->parent), &r);
+  
+  child.x = private->x;
+  child.y = private->y;
+  child.width = offscreen->width;
+  child.height = offscreen->height;
+  
+  gdk_rectangle_intersect (&r, &child, &r);
+  
+  gdk_window_invalidate_rect (GDK_WINDOW (private->parent), &r, TRUE);
+}
+
+
+static void
+gdk_offscreen_window_lower (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkOffscreenWindow *offscreen;
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+  
+  /* gdk_window_lower already changed the stacking order */
+
+  /* Invalidate the rect */
+  if (offscreen->toplevel_offscreen != offscreen)
+    gdk_offscreen_window_invalidate_in_parent (private);
+}
+
+static void
+send_pointer_events_for_geometry_change (GdkWindow *window)
+{
+  GdkWindow *mousewin, *event_window;
+  GdkWindowOffscreenChildren *offscreen_children;
+  
+  event_window = _gdk_window_get_offscreen_event_window (window);
+  offscreen_children = GDK_WINDOW_OBJECT (event_window)->offscreen_children;
+  /* The window the pointer is in might have changed */
+  if (offscreen_children->window_under_pointer != NULL)
+    {
+      mousewin = _gdk_window_get_offscreen_window_child_at (event_window,
+							    offscreen_children->last_mouse_x,
+							    offscreen_children->last_mouse_y,
+							    NULL, NULL);
+      send_crossing_events (offscreen_children,
+			    event_window,
+			    offscreen_children->window_under_pointer, mousewin,
+			    GDK_CROSSING_NORMAL,
+			    offscreen_children->last_mouse_x, offscreen_children->last_mouse_y,
+			    offscreen_children->last_state, GDK_CURRENT_TIME,
+			    TRUE, TRUE);
+    }
+}
+
+static void
+gdk_offscreen_window_move_region (GdkWindow *window,
+				  GdkRegion *region,
+				  gint       dx,
+				  gint       dy)
+{
+  GdkRegion *dest_region;
+  
+  dest_region = gdk_region_copy (region);
+  gdk_region_offset (dest_region, dx, dy);
+
+  /* Really cheesy implementation that just exposes
+     both regions */
+  gdk_window_invalidate_region (window, region, FALSE);
+  gdk_window_invalidate_region (window, dest_region, FALSE);
+  
+}
+
+
+static void
+gdk_offscreen_window_scroll (GdkWindow *window,
+			     gint       dx,
+			     gint       dy)
+{
+  GdkWindowObject *obj = GDK_WINDOW_OBJECT (window);
+  GList *tmp_list;
+  
+  /* Move the current invalid region */
+  if (obj->update_area)
+    gdk_region_offset (obj->update_area, dx, dy);
+
+/* We currently scroll in a pretty lame way, we move all
+   the subwindows, then re-expose the whole window */
+  
+  tmp_list = obj->children;
+  while (tmp_list)
+    {
+      GdkWindow *child = GDK_WINDOW (tmp_list->data);
+      GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
+
+      child_obj->x += dx;
+      child_obj->y += dx;
+      recompute_window (child);
+      
+      tmp_list = tmp_list->next;
+    }
+  gdk_window_invalidate_rect (window, NULL, TRUE);
+  send_pointer_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, *toplevel;
+  gint dx, dy, dw, dh;
+  GdkRegion *old_region;
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+  toplevel = offscreen->toplevel_offscreen;
+
+  if (width < 1)
+    width = 1;
+  if (height < 1)
+    height = 1;
+
+  if (private->destroyed)
+    return;
+
+  if (private->input_only)
+    send_expose_events = FALSE;
+
+  old_region = NULL;
+  if (GDK_WINDOW_IS_MAPPED (private) && send_expose_events)
+    {
+      old_region = _gdk_window_calculate_full_clip_region (window,
+							   toplevel->wrapper,
+							   NULL, FALSE,
+							   NULL, NULL);
+      /* Adjust region to parent window coords */
+      gdk_region_offset (old_region, private->x, private->y);
+    }
+  
+  dx = x - private->x;
+  dy = y - private->y;
+  dw = width - offscreen->width;
+  dh = height - offscreen->height;
+  
+  private->x = x;
+  private->y = y;
+  offscreen->width = width;
+  offscreen->height = height;
+  
+  if (GDK_WINDOW_IS_MAPPED (private))
+    {
+      recompute_window (window);
+
+      if (send_expose_events)
+	{
+	  if (offscreen == toplevel)
+	    {
+	      if (dw != 0 || dh != 0)
+		{
+		  GdkGC *gc;
+		  GdkPixmap *old_pixmap;
+		  
+		  old_pixmap = private->redirect->pixmap;
+		  private->redirect->pixmap = gdk_pixmap_new (GDK_DRAWABLE (old_pixmap),
+							      offscreen->width,
+							      offscreen->height,
+							      private->depth);
+		  private->redirect->width = offscreen->width;
+		  private->redirect->height = offscreen->height;
+		  
+		  gc = _gdk_drawable_get_scratch_gc (private->redirect->pixmap, FALSE);
+		  gdk_draw_drawable (private->redirect->pixmap,
+				     gc,
+				     old_pixmap,
+				     0,0, 0, 0,
+				     -1, -1);
+		  g_object_unref (old_pixmap);
+		  
+		}
+	      gdk_window_invalidate_rect (window, NULL, TRUE);
+	    }
+	  else
+	    {
+	      GdkRegion *new_region;
+	      
+	      new_region = _gdk_window_calculate_full_clip_region (window,
+								   toplevel->wrapper,
+								   NULL, FALSE,
+								   NULL, NULL);
+	      /* Adjust region to parent window coords */
+	      gdk_region_offset (new_region, private->x, private->y);
+	      gdk_region_union (new_region, old_region);
+	      
+	      /* Here we could optimize by copying areas that overlaps both
+	       * new_region and old_region, but we just expose everything instead */
+	      
+	      /* Invalidate regions in new_region */
+	      gdk_window_invalidate_region (GDK_WINDOW (private->parent), new_region, TRUE);
+	      
+	      gdk_region_destroy (new_region);
+	    }
+	}
+
+      send_pointer_events_for_geometry_change (window);
+    }
+
+  if (old_region != NULL)
+    gdk_region_destroy (old_region);
+
+}
+
+static void
+gdk_offscreen_window_move (GdkWindow *window,
+			   gint x, gint y)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkOffscreenWindow *offscreen;
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+  
+  gdk_offscreen_window_move_resize_internal (window, x, y,
+					     offscreen->width,
+					     offscreen->height,
+					     TRUE);
+}
+
+static void
+gdk_offscreen_window_resize (GdkWindow *window,
+			     gint width, gint height)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkOffscreenWindow *offscreen;
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+  
+  gdk_offscreen_window_move_resize_internal (window,
+					     private->x, private->y,
+					     width,
+					     height,
+					     TRUE);
+}
+
+static void
+gdk_offscreen_window_move_resize (GdkWindow *window,
+				  gint x, gint y,
+				  gint width, gint height)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkOffscreenWindow *offscreen;
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+  
+  gdk_offscreen_window_move_resize_internal (window, x, y,
+					     width, height,
+					     TRUE);
+}
+
+static gboolean
+all_parents_shown (GdkWindowObject *private)
+{
+  private = (GdkWindowObject *)private->parent;
+  
+  while (private != NULL &&
+	 GDK_WINDOW_IS_MAPPED (private) &&
+	 GDK_IS_OFFSCREEN_WINDOW (private->impl))
+    {
+      private = (GdkWindowObject *)private->parent;
+    }
+
+  return
+    private == NULL || !GDK_IS_OFFSCREEN_WINDOW (private->impl);
+}
+
+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_SCROLL            = 31 */
+  /* Later additions: */
+  /* GDK_WINDOW_STATE      = 32 */
+  /* GDK_SETTING           = 33 */
+  /* GDK_OWNER_CHANGE      = 34 */
+  /* GDK_GRAB_BROKEN       = 35 */
+};
+
+static GdkWindow *
+get_target_window_for_event (GdkWindow *window,
+			     GdkEventType type,
+			     gboolean recurse)
+{
+  guint32 evmask;
+  GdkWindow *w;
+  gboolean was_offscreen;
+
+  w = window;
+  while (w != NULL && GDK_WINDOW_OBJECT (w)->window_type != GDK_WINDOW_ROOT)
+    {
+      evmask = GDK_WINDOW_OBJECT (w)->event_mask;
+
+      if (evmask & type_masks[type])
+	return w;
+
+      if (!recurse)
+	break;
+
+      /* skip over parent of toplevel, to avoid event recursion */
+      was_offscreen = gdk_window_is_offscreen (w);
+      w = gdk_window_get_parent (w);
+      if (was_offscreen && !gdk_window_is_offscreen (w))
+	w = gdk_window_get_parent (w);
+	
+    }
+  
+  return NULL;
+}
+
+/* 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 (GdkWindowOffscreenChildren *offscreen_children,
+				     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 ((offscreen_children->pointer_grab_window != NULL &&
+       !offscreen_children->pointer_grab_owner_events) ||
+      (type == GDK_BUTTON_RELEASE &&
+       offscreen_children->grab_one_pointer_release_event) )
+    {
+      evmask = offscreen_children->pointer_grab_event_mask;
+      evmask = update_evmask_for_button_motion (evmask, mask);
+
+      if (type == GDK_BUTTON_RELEASE &&
+	  offscreen_children->grab_one_pointer_release_event)
+	{
+	  grab_window = offscreen_children->grab_one_pointer_release_event;
+	  offscreen_children->grab_one_pointer_release_event = NULL;
+	}
+      else
+	grab_window = offscreen_children->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 (offscreen_children->pointer_grab_window != NULL &&
+      offscreen_children->pointer_grab_owner_events)
+    {
+      evmask = offscreen_children->pointer_grab_event_mask;
+      evmask = update_evmask_for_button_motion (evmask, mask);
+      
+      if ((evmask & type_masks[type]) &&
+	  (!crossing_event || window == offscreen_children->pointer_grab_window))
+	return offscreen_children->pointer_grab_window;
+      else
+	return NULL;
+    }
+ 
+  return NULL;
+}
+
+static GdkEvent *
+make_gdk_event (GdkWindow *window,
+		GdkEventType type,
+		GdkEvent *append_after)
+{
+  GdkEvent *event = gdk_event_new (type);
+  guint32 the_time;
+
+  /* TODO: This is not ideal, we should propagate the time too */
+  the_time = GDK_CURRENT_TIME;
+  
+  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;
+      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;
+      break;
+    case GDK_KEY_PRESS:
+    case GDK_KEY_RELEASE:
+      event->key.time = the_time;
+      break;
+    case GDK_ENTER_NOTIFY:
+    case GDK_LEAVE_NOTIFY:
+      event->crossing.time = the_time;
+      break;
+      
+    case GDK_PROPERTY_NOTIFY:
+      event->property.time = the_time;
+      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_SCROLL:
+    case GDK_DELETE:
+    case GDK_DESTROY:
+    case GDK_EXPOSE:
+    default:
+      break;
+    }
+
+  if (append_after)
+    _gdk_event_queue_append_after (gdk_drawable_get_display (window), append_after, event);
+  else
+    _gdk_event_queue_append (gdk_drawable_get_display (window), event);
+  
+  return event;
+}
+
+static void
+send_map_events (GdkWindowObject *private)
+{
+  GList *l;
+  GdkWindowObject *parent_private = private->parent;
+  GdkWindow *event_win;
+  GdkOffscreenWindow *offscreen, *parent_offscreen;
+  
+  if (!GDK_WINDOW_IS_MAPPED (private))
+    return;
+
+  event_win = get_target_window_for_event ((GdkWindow *)private, GDK_MAP, FALSE);
+  if (event_win)
+    make_gdk_event (event_win, GDK_MAP, NULL);
+  
+  if (private->input_only)
+    return;
+
+  if (!parent_private)
+    parent_private = private;
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+  if (GDK_IS_OFFSCREEN_WINDOW (parent_private->impl))
+    {
+      parent_offscreen = GDK_OFFSCREEN_WINDOW (parent_private->impl);
+      
+      if (((offscreen->abs_x > parent_offscreen->lim_x) ||
+	   (offscreen->abs_y > parent_offscreen->lim_y) ||
+	   (offscreen->lim_x < parent_offscreen->llim_x) ||
+	   (offscreen->lim_y < parent_offscreen->llim_y)))
+	return;
+    }
+
+  gdk_window_clear ((GdkWindow *)private);
+
+  for (l = private->children; l; l = l->next)
+    send_map_events (l->data);
+}
+
+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 (all_parents_shown (private))
+    {
+      recompute_window (window);
+      
+      send_map_events (private);
+
+      send_pointer_events_for_geometry_change (window);
+      
+      if (private->input_only)
+	return;
+
+      gdk_window_clear_area_e (window, 0, 0,
+			       offscreen->width, offscreen->height);
+    }
+}
+
+
+static void
+gdk_offscreen_window_hide (GdkWindow *window)
+{
+  GdkWindowObject *private;
+  GdkWindow *event_win;
+  GdkOffscreenWindow *offscreen;
+  GdkWindow *grab_window;
+  
+  g_return_if_fail (window != NULL);
+
+  private = (GdkWindowObject*) window;
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+  if (GDK_WINDOW_IS_MAPPED (private))
+    {
+      GdkEvent *event;
+      GdkRectangle r;
+      GdkDisplay *display;
+
+      /* May need to break grabs on children */
+      display = gdk_drawable_get_display (window);
+      if (gdk_pointer_grab_info_libgtk_only (display,
+					     &grab_window, NULL))
+	{
+	  if (is_parent_of (window, grab_window))
+	    {
+	      _gdk_offscreen_window_unset_pointer_grab (grab_window, FALSE, FALSE, GDK_CURRENT_TIME);
+	      gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
+	      _gdk_windowing_grab_broken (display);
+	    }
+	}
+      
+      event_win = get_target_window_for_event (window, GDK_UNMAP, FALSE);
+      if (event_win)
+	event = make_gdk_event (event_win, GDK_UNMAP, NULL);
+      
+      r.x = offscreen->llim_x;
+      r.y = offscreen->llim_y;
+      r.width = offscreen->lim_x - r.x;
+      r.height = offscreen->lim_y - r.y;
+
+      private->state = GDK_WINDOW_STATE_WITHDRAWN;
+
+      send_pointer_events_for_geometry_change (window);
+      
+      /* Invalidate the rect */
+      if (offscreen->toplevel_offscreen != offscreen)
+	gdk_offscreen_window_invalidate_in_parent (private);
+    }
+}
+
+static void
+gdk_offscreen_window_withdraw (GdkWindow *window)
+{
+}
+
+static GdkEventMask  
+gdk_offscreen_window_get_events (GdkWindow *window)
+{
+  return GDK_WINDOW_OBJECT (window)->event_mask;
+}
+
+static void          
+gdk_offscreen_window_set_events (GdkWindow       *window,
+				 GdkEventMask     event_mask)
+{
+  GDK_WINDOW_OBJECT (window)->event_mask = event_mask;
+}
+
+
+static void
+gdk_offscreen_window_clear_area (GdkWindow *window,
+				 gint       x,
+				 gint       y,
+				 gint       width,
+				 gint       height,
+				 gboolean   send_expose)
+{
+  GdkRectangle visible, rect;
+
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
+  /* Actual drawing is done by gdkwindow.c */
+  
+  if (send_expose)
+    {
+      gdk_offscreen_window_get_visible_rect (window, &visible);
+      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,
+				      gboolean   parent_relative)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (pixmap == NULL || !parent_relative);
+  g_return_if_fail (pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap));
+
+  if (pixmap && !gdk_drawable_get_colormap (pixmap))
+    {
+      g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
+      return;
+    }
+  
+  if (private->bg_pixmap &&
+      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+      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)
+	{
+	  g_object_ref (pixmap);
+	  private->bg_pixmap = pixmap;
+	}
+      else
+	{
+	  private->bg_pixmap = GDK_NO_BG;
+	}
+    }
+}
+
+static void
+gdk_offscreen_window_get_offsets (GdkWindow *window,
+				  gint      *x_offset,
+				  gint      *y_offset)
+{
+
+  *x_offset = 0;
+  *y_offset = 0;
+}
+
+static GdkWindow *
+gdk_offscreen_window_get_window_at (GdkWindow *window,
+				    gdouble x,  gdouble y,
+				    gdouble *win_x, gdouble *win_y)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkOffscreenWindow *offscreen;
+  GdkWindow *return_val;
+
+  g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+  
+  return_val = NULL;
+  
+  if ((x >= 0) && (x < offscreen->width) &&
+      (y >= 0) && (y < offscreen->height))
+    {
+      GdkWindowObject *sub;
+      GdkOffscreenWindow *sub_offscreen;
+      gdouble subx = x, suby = y;
+
+      for (sub = private; sub; private = sub)
+	{
+	  GList *ltmp;
+
+	  /* This assumes children is ordered in reverse stack order */
+	  for (ltmp = private->children; ltmp; ltmp = ltmp->next)
+	    {
+	      sub = ltmp->data;
+
+	      if (!GDK_WINDOW_IS_MAPPED (sub))
+		continue;
+
+	      sub_offscreen = GDK_OFFSCREEN_WINDOW (sub->impl);
+	      
+	      if (subx >= sub->x &&
+		  (subx < (sub_offscreen->width + sub->x)) &&
+		  (suby >= sub->y) &&
+		  (suby < (sub_offscreen->height + sub->y)))
+		{
+		  subx -= sub->x;
+		  suby -= sub->y;
+		  break;
+		}
+	    }
+
+	  if (!ltmp)
+	    {
+	      sub = NULL;
+	      break;
+	    }
+	}
+
+      if (win_x)
+	*win_x = subx;
+      if (win_y)
+	*win_y = suby;
+
+      return_val = (GdkWindow *)private;
+    }
+  
+  return return_val;
+}
+
+GdkWindow *
+_gdk_window_get_offscreen_window_child_at (GdkWindow *parent,
+					   gdouble    x,
+					   gdouble    y,
+					   gdouble   *win_x_out,
+					   gdouble   *win_y_out)
+{
+  GdkWindow *target;
+  GdkWindow *child;
+  GdkWindowObject *parent_private;
+  gdouble win_x, win_y;
+
+  parent_private = GDK_WINDOW_OBJECT (parent);
+  if (parent_private && parent_private->offscreen_children)
+    {
+      child = find_offscreen_child (parent, x, y);
+      if (child)
+	{
+	  parent_to_window (child, x, y, &win_x, &win_y);
+	  target = gdk_offscreen_window_get_window_at (child, win_x, win_y, &win_x, &win_y);
+	  return _gdk_window_get_offscreen_window_child_at (target, win_x, win_y, win_x_out, win_y_out);
+	}
+    }
+  if (win_x_out)
+    *win_x_out = x;
+  if (win_y_out)
+    *win_y_out = y;
+  
+  return parent;
+}
+
+static GdkWindow *
+find_common_ancestor (GdkWindow *win1,
+		      GdkWindow *win2)
+{
+  GdkWindowObject *tmp;
+  GList *path1 = NULL, *path2 = NULL;
+  GList *list1, *list2;
+  
+  tmp = GDK_WINDOW_OBJECT (win1);
+  while (tmp) 
+    {
+      path1 = g_list_prepend (path1, tmp);
+      tmp = tmp->parent;
+    }
+
+  tmp = GDK_WINDOW_OBJECT (win2);
+  while (tmp) 
+    {
+      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);
+}
+
+
+/* x, y are in toplevel coords */
+static void
+send_crossing_events (GdkWindowOffscreenChildren *offscreen_children,
+		      GdkWindow *event_window,
+		      GdkWindow *src,
+		      GdkWindow *dest,
+		      GdkCrossingMode mode,
+		      int event_x, int event_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;
+
+  if ((mode == GDK_CROSSING_NORMAL) &&
+      (dest == offscreen_children->window_under_pointer))
+    return;
+
+  if (src)
+    a = src;
+  else
+    a = event_window;
+
+  if (dest)
+    b = dest;
+  else
+    b = event_window;
+
+  if (a==b)
+    return;
+
+  c = find_common_ancestor (a, b);
+
+  if (c == NULL)
+    return;
+
+  non_linear = (c != a) && (c != b);
+
+  event_win = get_target_window_for_pointer_event (offscreen_children, a, GDK_LEAVE_NOTIFY, mask);
+  if (do_first && event_win)
+    {
+      event = make_gdk_event (event_win, GDK_LEAVE_NOTIFY, NULL);
+      event->crossing.time = time;
+      event->crossing.subwindow = NULL;
+      convert_event_coords_to_window (event_window,
+				      event_win, event_x, event_y,
+				      &event->crossing.x, &event->crossing.y);
+      event->crossing.x_root = event_x;
+      event->crossing.y_root = event_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;
+    }
+  
+  /* Traverse up from a to (excluding) c */
+  if (c != a)
+    {
+      last = a;
+      win = GDK_WINDOW (GDK_WINDOW_OBJECT (a)->parent);
+      while (win != c)
+	{
+	  event_win = get_target_window_for_pointer_event (offscreen_children, win, GDK_LEAVE_NOTIFY, mask);
+	  if (event_win)
+	    {
+	      event = make_gdk_event (event_win, GDK_LEAVE_NOTIFY, NULL);
+	      event->crossing.time = time;
+	      event->crossing.subwindow = g_object_ref (last);
+	      convert_event_coords_to_window (event_window,
+					      event_win, event_x, event_y,
+					      &event->crossing.x, &event->crossing.y);
+	      event->crossing.x_root = event_x;
+	      event->crossing.y_root = event_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);
+	}
+    }
+  
+  /* Traverse down from c to b */
+  if (c != b) 
+    {
+      path = NULL;
+      win = GDK_WINDOW (GDK_WINDOW_OBJECT (b)->parent);
+      while (win != c)
+	{
+	  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 (offscreen_children, win, GDK_ENTER_NOTIFY, mask);
+	  if (event_win)
+	    {
+	      event = make_gdk_event (event_win, GDK_ENTER_NOTIFY, NULL);
+	      event->crossing.time = time;
+	      event->crossing.subwindow = g_object_ref (next);
+	      convert_event_coords_to_window (event_window,
+					      event_win, event_x, event_y,
+					      &event->crossing.x, &event->crossing.y);
+	      event->crossing.x_root = event_x;
+	      event->crossing.y_root = event_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 (offscreen_children, b, GDK_ENTER_NOTIFY, mask);
+  if (do_last && event_win)
+    {
+      event = make_gdk_event (event_win, GDK_ENTER_NOTIFY, NULL);
+      event->crossing.time = time;
+      event->crossing.subwindow = NULL;
+      convert_event_coords_to_window (event_window,
+				      event_win, event_x, event_y,
+				      &event->crossing.x, &event->crossing.y);
+      event->crossing.x_root = event_x;
+      event->crossing.y_root = event_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;
+    }
+
+  if (mode != GDK_CROSSING_GRAB &&
+      mode != GDK_CROSSING_UNGRAB &&
+      dest != offscreen_children->window_under_pointer)
+    {
+      if (offscreen_children->window_under_pointer)
+	g_object_unref (offscreen_children->window_under_pointer);
+      offscreen_children->window_under_pointer = NULL;
+      if (dest)
+	offscreen_children->window_under_pointer = g_object_ref (dest);
+    }
+}
+
+/* Find the first enclosing non-offscreen window.
+ * This window is the one used to get events to the
+ * offscreen windows
+ */
+GdkWindow *
+_gdk_window_get_offscreen_event_window (GdkWindow *window)
+{
+  GdkWindowObject *private;
+  GdkOffscreenWindow *offscreen;
+  GdkWindow *toplevel;
+
+  while (window != NULL && gdk_window_is_offscreen (window))
+    {
+      private = (GdkWindowObject *)window;
+      offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+      toplevel = offscreen->toplevel_offscreen->wrapper;
+      window = GDK_WINDOW (GDK_WINDOW_OBJECT (toplevel)->parent);
+    }
+  
+  return window;
+}
+
+static void
+convert_event_coords_to_window (GdkWindow *event_window,
+				GdkWindow *window,
+				gdouble event_x, gdouble event_y,
+				gdouble *window_x, gdouble *window_y)
+{
+  GdkOffscreenWindow *offscreen, *toplevel_offscreen;
+  GdkWindow *toplevel_parent;
+
+  if (event_window == window)
+    {
+      *window_x = event_x;
+      *window_y = event_y;
+      return;
+    }
+  
+  offscreen = GDK_OFFSCREEN_WINDOW (GDK_WINDOW_OBJECT (window)->impl);
+  
+  toplevel_offscreen = offscreen->toplevel_offscreen;
+  toplevel_parent = GDK_WINDOW (GDK_WINDOW_OBJECT (toplevel_offscreen->wrapper)->parent);
+  if (toplevel_parent != event_window)
+    convert_event_coords_to_window (event_window,
+				    toplevel_parent,
+				    event_x, event_y,
+				    &event_x, &event_y);
+  
+  /* Convert to toplevel coords */
+  parent_to_window (toplevel_offscreen->wrapper, event_x, event_y,
+		    &event_x, &event_y);
+  /* Convert to window coords */
+  *window_x = event_x - offscreen->abs_x;
+  *window_y = event_y - offscreen->abs_y;
+}
+
+static void
+convert_window_coords_to_event (GdkWindow *event_window,
+				GdkWindow *window,
+				gdouble window_x, gdouble window_y,
+				gdouble *event_x, gdouble *event_y)
+{
+  GdkOffscreenWindow *offscreen, *toplevel_offscreen;
+  GdkWindow *toplevel_parent;
+
+  offscreen = GDK_OFFSCREEN_WINDOW (GDK_WINDOW_OBJECT (window)->impl);
+  toplevel_offscreen = offscreen->toplevel_offscreen;
+  toplevel_parent = GDK_WINDOW (GDK_WINDOW_OBJECT (toplevel_offscreen->wrapper)->parent);
+  /* Convert to toplevel coords */
+  window_x += offscreen->abs_x;
+  window_y += offscreen->abs_y;
+  /* Convert to parent toplevel coords */
+  window_to_parent (toplevel_offscreen->wrapper,
+		    window_x, window_y,
+		    &window_x, &window_y);
+  if (toplevel_parent != event_window)
+    convert_window_coords_to_event (event_window,
+				    toplevel_parent,
+				    window_x, window_y,
+				    &window_x, &window_y);
+  *event_x = window_x;
+  *event_y = window_y;
+}
+
+
+static gboolean
+proxy_pointer_event (GdkWindow *pointer_window,
+		     gdouble event_x, gdouble event_y,
+		     GdkEvent *source_event,
+		     GdkWindowOffscreenChildren *offscreen_children)
+{
+  GdkWindow *event_win, *cursor_window;
+  gboolean crossing_event;
+  gboolean sent_motion;
+  GdkEvent *event;
+  guint state;
+  guint32 time;
+  
+  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 &&
+	      offscreen_children->window_under_pointer != NULL)
+	    {
+	      send_crossing_events (offscreen_children, source_event->any.window,
+				    offscreen_children->window_under_pointer,
+				    NULL,
+				    GDK_CROSSING_GRAB,
+				    event_x, event_y, state, time,
+				    TRUE, FALSE);
+	    }
+	  if (crossing->type == GDK_ENTER_NOTIFY &&
+	      offscreen_children->pointer_grab_window != NULL)
+	    {
+	      send_crossing_events (offscreen_children, source_event->any.window,
+				    NULL, offscreen_children->pointer_grab_window,
+				    GDK_CROSSING_GRAB,
+				    event_x, event_y, state, time,
+				    FALSE, TRUE);
+	    }
+	}
+      
+      if (crossing->mode == GDK_CROSSING_UNGRAB)
+	{
+	  if (crossing->type == GDK_LEAVE_NOTIFY &&
+	      offscreen_children->pointer_grab_window != NULL)
+	    {
+	      send_crossing_events (offscreen_children, source_event->any.window,
+				    offscreen_children->pointer_grab_window,
+				    NULL,
+				    GDK_CROSSING_UNGRAB,
+				    event_x, event_y, state, time,
+				    TRUE, FALSE);
+	    }
+	  if (crossing->type == GDK_ENTER_NOTIFY &&
+	      offscreen_children->window_under_pointer != NULL)
+	    {
+	      send_crossing_events (offscreen_children, source_event->any.window,
+				    NULL,
+				    offscreen_children->window_under_pointer,
+				    GDK_CROSSING_UNGRAB,
+				    event_x, event_y, state, time,
+				    FALSE, TRUE);
+	    }
+	}
+    }
+  
+  cursor_window = pointer_window;
+  if (offscreen_children->pointer_grab_window &&
+      (pointer_window == NULL ||
+       !is_parent_of (offscreen_children->pointer_grab_window, pointer_window)))
+    cursor_window = offscreen_children->pointer_grab_window;
+  
+  /* TODO: set cursor from cursor_window, or grab cursor */
+
+  sent_motion = FALSE;
+  if (!crossing_event &&
+      (offscreen_children->window_under_pointer == pointer_window ||
+       (offscreen_children->pointer_grab_window != NULL &&
+	!offscreen_children->pointer_grab_owner_events)))
+    {
+      /* send motion events */
+      event_win = get_target_window_for_pointer_event (offscreen_children, pointer_window, GDK_MOTION_NOTIFY, state);
+      if (event_win)
+	{
+	  sent_motion = TRUE;
+	  event = make_gdk_event (event_win, GDK_MOTION_NOTIFY, source_event);
+	  event->motion.time = time;
+	  convert_event_coords_to_window (source_event->any.window,
+					  event_win, event_x, event_y,
+					  &event->motion.x, &event->motion.y);
+	  event->motion.x_root = event_x; /* TODO: right? */
+	  event->motion.y_root = event_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;
+	}
+    }
+
+  send_crossing_events (offscreen_children,
+			source_event->any.window,
+			offscreen_children->window_under_pointer,
+			pointer_window,
+			GDK_CROSSING_NORMAL,
+			event_x, event_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
+is_button_type (GdkEventType type)
+{
+  return
+    type == GDK_BUTTON_PRESS ||
+    type == GDK_2BUTTON_PRESS ||
+    type == GDK_3BUTTON_PRESS ||
+    type == GDK_BUTTON_RELEASE;
+}
+
+static gboolean
+is_motion_type (GdkEventType type)
+{
+  return
+    type == GDK_MOTION_NOTIFY ||
+    type == GDK_ENTER_NOTIFY ||
+    type == GDK_LEAVE_NOTIFY;
+}
+
+static gboolean
+proxy_button_event (GdkWindow *pointer_window,
+		    gdouble event_x, gint event_y,
+		    GdkEvent *source_event,
+		    GdkWindowOffscreenChildren *offscreen_children)
+{
+  GdkWindow *event_win;
+  GdkEvent *event;
+  guint state;
+  guint32 time;
+  GdkEventType type;
+  
+  type = source_event->any.type;
+  gdk_event_get_state (source_event, &state);
+  time = gdk_event_get_time (source_event);
+
+  if (type == GDK_BUTTON_PRESS &&
+      pointer_window != NULL)
+    {
+      _gdk_windowing_update_implicit_grab (source_event->any.window, pointer_window,
+					   gdk_window_get_events (pointer_window), time);
+    }
+  
+  event_win = get_target_window_for_pointer_event (offscreen_children, pointer_window, type, state);
+  if (event_win && event_win != source_event->any.window)
+    {
+      event = make_gdk_event (event_win, type, source_event);
+      event->button.time = time;
+      event->button.button = source_event->button.button;
+      convert_event_coords_to_window (source_event->any.window,
+				      event_win, event_x, event_y,
+				      &event->button.x, &event->button.y);
+      event->button.x_root = event_x;
+      event->button.y_root = event_y;
+      event->button.state = state;
+      event->button.device = NULL;
+      if (source_event && is_button_type (type))
+	event->button.device = source_event->button.device;
+      return TRUE;
+    }
+  return FALSE;
+}
+
+static gint
+gdk_offscreen_window_get_origin (GdkWindow *window,
+				 gint      *x,
+				 gint      *y)
+{
+  GdkWindow *event_window;
+  int parent_x, parent_y;
+  gdouble event_x, event_y;
+
+  event_window = _gdk_window_get_offscreen_event_window (window);
+
+  convert_window_coords_to_event (event_window, window,
+				  0.0, 0.0, &event_x, &event_y);
+  
+  gdk_window_get_origin (event_window, &parent_x, &parent_y);
+
+  if (x)
+    *x = floor (event_x + 0.5) + parent_x;
+  if (y)
+    *y = floor (event_y + 0.5) + parent_y;
+  
+  return TRUE;
+}
+
+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,
+					   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 = offscreen->width;
+      if (height)
+	*height = offscreen->width;
+      if (depth)
+	*depth = private->depth;
+    }
+}
+
+void
+_gdk_offscreen_window_transform_coords (GdkWindow       *event_window,
+					GdkWindow       *relative_window,
+					gint            *x,
+					gint            *y)
+{
+  gdouble window_x, window_y;
+  
+  if (relative_window != event_window)
+    {
+      /* The relative window is an offscreen window */
+      convert_event_coords_to_window (event_window, relative_window,
+				      *x, *y,
+				      &window_x, &window_y);
+      *x = floor (window_x + 0.5);
+      *y = floor (window_y + 0.5);
+    }
+}
+
+void
+_gdk_offscreen_window_set_pointer_grab (GdkWindow *old_grab_window,
+					GdkWindow *old_native_grab_window,
+					GdkWindow *grab_window,
+					gboolean owner_events,
+					guint event_mask,
+					guint32 time)
+{
+  GdkDisplay *display;
+  GdkWindow *crossing_start, *event_window;
+  GdkWindowOffscreenChildren *offscreen_children;
+  gint wx, wy;
+
+  display = gdk_drawable_get_display (grab_window);
+  event_window = _gdk_window_get_offscreen_event_window (grab_window);
+  offscreen_children = GDK_WINDOW_OBJECT (event_window)->offscreen_children;
+
+  /* Normal GRAB events are sent by listening for enter and leave
+   * events on the parent of the toplevel, which is then proxied
+   * into the offscreen where we create them. However, there are two
+   * cases where X will not send these events:
+   * * When there is already a grab on the parent of the toplevel
+   *   offscreen grab window 
+   * * When there is no grab, but the pointer is already in the
+   *   parent of the toplevel offscreen grab window
+   * In these cases we need to generate our own grab crossing events.
+   */
+  crossing_start = NULL;
+  if (old_grab_window != NULL &&
+      old_native_grab_window == event_window)
+    crossing_start = old_grab_window;
+  
+  if (old_grab_window == NULL &&
+      _gdk_windowing_window_at_pointer (display, &wx, &wy) == event_window)
+    crossing_start = offscreen_children->window_under_pointer;
+  
+  if (crossing_start != NULL)
+    {
+      /* TODO: Hmmm, is this totally right if start is in another toplevel */
+      send_crossing_events (offscreen_children,
+			    event_window,
+			    crossing_start, 
+			    grab_window,
+			    GDK_CROSSING_GRAB,
+			    /* These may be stale... */
+			    offscreen_children->last_mouse_x,
+			    offscreen_children->last_mouse_y,
+			    offscreen_children->last_state,
+			    time, TRUE, TRUE);
+    }
+
+
+  /* TODO: What about the case of grabbing the toplevel parent, when
+     an offscreen child of it is grabbed or has the pointer? */
+  
+  if (offscreen_children->pointer_grab_window != NULL)
+    g_object_unref (offscreen_children->pointer_grab_window);
+  offscreen_children->pointer_grab_window = g_object_ref (grab_window);
+  offscreen_children->pointer_grab_owner_events = owner_events;
+  offscreen_children->pointer_grab_event_mask = event_mask;
+}
+
+void
+_gdk_offscreen_window_unset_pointer_grab (GdkWindow *window,
+					  gboolean regrab,
+					  gboolean grab_one_pointer_release_event,
+					  guint32 time)
+{
+  GdkWindow *event_window;
+  GdkWindowOffscreenChildren *offscreen_children;
+  GdkDisplay *display;
+  gint wx, wy;
+
+  display = gdk_drawable_get_display (window);
+  event_window = _gdk_window_get_offscreen_event_window (window);
+  offscreen_children = GDK_WINDOW_OBJECT (event_window)->offscreen_children;
+
+  g_assert (offscreen_children->pointer_grab_window != NULL);
+
+  if (grab_one_pointer_release_event)
+    offscreen_children->grab_one_pointer_release_event = offscreen_children->pointer_grab_window;
+  g_object_unref (offscreen_children->pointer_grab_window);
+  offscreen_children->pointer_grab_window = NULL;
+
+  /* Normal UNGRAB events are sent by listening for enter and leave
+   * events on the parent of the toplevel, which is then proxied
+   * into the offscreen where we create them. However, there are two
+   * cases where X will not send these events:
+   * * When this ungrab is due to a new grab on the parent of the toplevel
+   *   offscreen grab window.
+   * * When there is no new grab, and the pointer is already in the
+   *   parent of the toplevel offscreen 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 (!regrab &&
+      _gdk_windowing_window_at_pointer (display, &wx, &wy) == event_window)
+    {
+      GdkWindow *crossing_end = offscreen_children->window_under_pointer;
+      
+      send_crossing_events (offscreen_children, event_window,
+			    window, 
+			    crossing_end,
+			    GDK_CROSSING_UNGRAB,
+			    /* These may be stale... */
+			    offscreen_children->last_mouse_x,
+			    offscreen_children->last_mouse_y,
+			    offscreen_children->last_state,
+			    time, TRUE, TRUE);
+    }
+}
+
+void
+_gdk_event_rewrite_for_offscreen (GdkDisplay *display,
+				  GList *event_link,
+				  GdkEvent *event)
+{
+  GdkWindow *event_window;
+  GdkWindow *pointer_window;
+  GdkWindowObject *event_private;
+  GdkWindowOffscreenChildren *offscreen_children;
+  gboolean is_grab;
+  gdouble x,y;
+  gboolean unlink_event;
+  
+  event_window = event->any.window;
+  event_private = GDK_WINDOW_OBJECT (event_window);
+  if (!event_window ||
+      !event_private->offscreen_children)
+    return;
+
+  if (!(is_button_type (event->type) ||
+	is_motion_type (event->type)))
+    return;
+
+  offscreen_children = event_private->offscreen_children;
+
+  gdk_event_get_coords (event, &x, &y);
+  offscreen_children->last_mouse_x = x;
+  offscreen_children->last_mouse_y = y;
+  
+  gdk_event_get_state (event,
+		       &offscreen_children->last_state);
+
+  pointer_window = _gdk_window_get_offscreen_window_child_at (event_window, x, y, NULL, NULL);
+  if (pointer_window == event_window)
+    pointer_window = NULL;
+  
+  is_grab = FALSE;
+  if (offscreen_children->pointer_grab_window)
+    is_grab = TRUE;
+
+  unlink_event = FALSE;
+  if (is_motion_type (event->type))
+    {
+      unlink_event = proxy_pointer_event (pointer_window, x, y, event, offscreen_children);
+    }
+
+  if (is_button_type (event->type))
+    {
+      unlink_event = proxy_button_event (pointer_window, x, y, event, offscreen_children);
+    }
+
+  if (unlink_event)
+    {
+      _gdk_event_queue_remove_link (display, event_link);
+      g_list_free_1 (event_link);
+      gdk_event_free (event);
+    }
+}
+
+static void
+gdk_offscreen_window_impl_iface_init (GdkWindowImplIface *iface)
+{
+  iface->get_visible_rect = gdk_offscreen_window_get_visible_rect;
+  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 = gdk_offscreen_window_move;
+  iface->resize = gdk_offscreen_window_resize;
+  iface->move_resize = gdk_offscreen_window_move_resize;
+  iface->scroll = gdk_offscreen_window_scroll;
+  iface->move_region = gdk_offscreen_window_move_region;
+  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->get_origin = gdk_offscreen_window_get_origin;
+  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->get_offsets = gdk_offscreen_window_get_offsets;
+}
Index: gdk/gdkpixmap.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdkpixmap.c,v
retrieving revision 1.56
diff -u -p -r1.56 gdkpixmap.c
--- gdk/gdkpixmap.c	17 Mar 2005 01:54:38 -0000	1.56
+++ gdk/gdkpixmap.c	13 Oct 2005 20:59:02 -0000
@@ -240,6 +240,42 @@ gdk_pixmap_finalize (GObject *object)
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
+GdkPixmap*
+gdk_pixmap_new (GdkDrawable *drawable,
+		gint         width,
+		gint         height,
+		gint         depth)
+{
+  drawable = _gdk_drawable_get_source_drawable (drawable);  
+  return _gdk_pixmap_new (drawable, width, height, depth);
+}
+
+GdkPixmap *
+gdk_bitmap_create_from_data (GdkDrawable *drawable,
+			     const gchar *data,
+			     gint         width,
+			     gint         height)
+{
+  return _gdk_bitmap_create_from_data (_gdk_drawable_get_source_drawable (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)
+{
+  return _gdk_pixmap_create_from_data (_gdk_drawable_get_source_drawable (drawable),
+				       data, width, height,
+				       depth, fg,bg);
+}
+
+
+
 static GdkGC *
 gdk_pixmap_create_gc (GdkDrawable     *drawable,
                       GdkGCValues     *values,
Index: gdk/gdkwindow.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdkwindow.c,v
retrieving revision 1.177.2.1
diff -u -p -r1.177.2.1 gdkwindow.c
--- gdk/gdkwindow.c	26 Sep 2005 20:28:34 -0000	1.177.2.1
+++ gdk/gdkwindow.c	13 Oct 2005 20:59:02 -0000
@@ -26,7 +26,9 @@
 
 #include <config.h>
 #include "gdkwindow.h"
+#include "gdkwindowimpl.h"
 #include "gdkinternals.h"
+#include "gdkmarshalers.h"
 #include "gdk.h"		/* For gdk_rectangle_union() */
 #include "gdkpixmap.h"
 #include "gdkdrawable.h"
@@ -36,6 +38,14 @@
 
 #define USE_BACKING_STORE	/* Appears to work on Win32, too, now. */
 
+enum {
+  PARENT_TO_WINDOW_COORDINATE,
+  WINDOW_TO_PARENT_COORDINATE,
+  FIND_OFFSCREEN_CHILD,
+  LAST_SIGNAL
+};
+
+
 typedef struct _GdkWindowPaint GdkWindowPaint;
 
 struct _GdkWindowPaint
@@ -47,6 +57,14 @@ struct _GdkWindowPaint
   cairo_surface_t *surface;
 };
 
+typedef struct {
+  GdkRegion *old_region;
+  gint old_clip_x_origin;
+  gint old_clip_y_origin;
+  gint x_offset;
+  gint y_offset;
+} GdkWindowClipData;
+
 static GdkGC *gdk_window_create_gc      (GdkDrawable     *drawable,
                                          GdkGCValues     *values,
                                          GdkGCValuesMask  mask);
@@ -171,6 +189,7 @@ static void         gdk_window_real_set_
 						  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,
@@ -182,6 +201,7 @@ static GdkRegion*   gdk_window_get_clip_
 static GdkRegion*   gdk_window_get_visible_region     (GdkDrawable *drawable);
 
 static void gdk_window_free_paint_stack (GdkWindow *window);
+static void gdk_window_raise_internal   (GdkWindow *window);
 
 static void gdk_window_init       (GdkWindowObject      *window);
 static void gdk_window_class_init (GdkWindowObjectClass *klass);
@@ -192,6 +212,19 @@ static void gdk_window_clear_backing_rec
 					   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 guint signals[LAST_SIGNAL] = { 0 };
 static gpointer parent_class = NULL;
 
 GType
@@ -230,8 +263,6 @@ gdk_window_init (GdkWindowObject *window
   window->window_type = GDK_WINDOW_CHILD;
 
   window->state = GDK_WINDOW_STATE_WITHDRAWN;
-  
-  window->impl = g_object_new (_gdk_window_impl_get_type (), NULL);
 }
 
 static void
@@ -270,6 +301,101 @@ gdk_window_class_init (GdkWindowObjectCl
   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;
+
+  /**
+   * GdkWindow::parent-to-window-coordinate:
+   * @window: an offscreen window
+   * @x: x position in parent window coordinates
+   * @y: y position in parent window coordinates
+   * @window_x: store window coordinate x position here
+   * @window_y: store window coordinate y position here
+   *
+   * This is emitted on an offscreen window created with
+   * gdk_window_new_offscreen() to convert a position in
+   * the parent window coordinate space to the coordinate
+   * space of the child window.
+   *
+   * If this signal is not handled, by default the transform
+   * used will be the normal window position one.
+   *
+   * Since: 2.10
+   */
+  signals[PARENT_TO_WINDOW_COORDINATE] =
+    g_signal_new ("parent_to_window_coordinate",
+		  G_OBJECT_CLASS_TYPE (object_class),
+		  G_SIGNAL_RUN_FIRST,
+		  0,
+		  NULL, NULL,
+		  gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
+		  G_TYPE_NONE,
+		  4,
+		  G_TYPE_DOUBLE,
+		  G_TYPE_DOUBLE,
+		  G_TYPE_POINTER,
+		  G_TYPE_POINTER);
+  /**
+   * GdkWindow::window-to-parent-coordinate:
+   * @window: an offscreen window
+   * @x: x position in child window coordinates
+   * @y: y position in child window coordinates
+   * @window_x: store parent window coordinate x position here
+   * @window_y: store parent window coordinate y position here
+   *
+   * This is emitted on an offscreen window created with
+   * gdk_window_new_offscreen() to convert a position in
+   * the window coordinate space to the coordinate space
+   * of the parent window.
+   *
+   * If this signal is not handled, by default the transform
+   * used will be the normal window position one.
+   *
+   * Since: 2.10
+   */
+  signals[WINDOW_TO_PARENT_COORDINATE] =
+    g_signal_new ("window_to_parent_coordinate",
+		  G_OBJECT_CLASS_TYPE (object_class),
+		  G_SIGNAL_RUN_FIRST,
+		  0,
+		  NULL, NULL,
+		  gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
+		  G_TYPE_NONE,
+		  4,
+		  G_TYPE_DOUBLE,
+		  G_TYPE_DOUBLE,
+		  G_TYPE_POINTER,
+		  G_TYPE_POINTER);
+  /**
+   * GdkWindow::find-offscreen-child:
+   * @window: a window with offscreen children
+   * @x: x position in @window
+   * @y: y position in @window
+   *
+   * This is emitted when the child window in a specific
+   * point in a window is required. This happens for instance
+   * when handling pointer events.
+   *
+   * The implementation should find the offscreen window
+   * child that contains the given point and return it.
+   * If the point isn't in an offscreen child (e.g. it is
+   * outside of all offscreen windows, or the offscreen window
+   * is obscured by something) then return NULL
+   *
+   * Returns: The window at the specified point, or NULL 
+   *
+   * Since: 2.10
+   */
+  signals[FIND_OFFSCREEN_CHILD] =
+    g_signal_new ("find_offscreen_child",
+		  G_OBJECT_CLASS_TYPE (object_class),
+		  G_SIGNAL_RUN_LAST,
+		  0,
+		  NULL, NULL,
+		  gdk_marshal_OBJECT__DOUBLE_DOUBLE,
+		  G_TYPE_OBJECT,
+		  2,
+		  G_TYPE_DOUBLE,
+		  G_TYPE_DOUBLE);
 }
 
 static void
@@ -416,14 +542,22 @@ _gdk_window_destroy_hierarchy (GdkWindow
 	      
 	      g_list_free (children);
 	    }
-	  
-	  _gdk_windowing_window_destroy (window, recursing, foreign_destroy);
+
+	  if (gdk_window_is_offscreen (window))
+	    _gdk_offscreen_window_destroy (window, recursing);
+	  else
+	    _gdk_windowing_window_destroy (window, recursing, foreign_destroy);
 	  private->parent = NULL;
 	  private->destroyed = TRUE;
 
 	  window_remove_filters (window);
 
           gdk_drawable_set_colormap (GDK_DRAWABLE (window), NULL);
+
+	  /* If we own the redirect, free it */
+	  if (private->redirect && private->redirect->redirected == private)
+	    gdk_window_redirect_free (private->redirect);
+	  private->redirect = NULL;
 	}
       break;
       
@@ -1038,7 +1172,7 @@ gdk_window_end_paint (GdkWindow *window)
 
   tmp_gc = _gdk_drawable_get_scratch_gc (window, FALSE);
 
-  _gdk_windowing_window_get_offsets (window, &x_offset, &y_offset);
+  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);
@@ -1049,6 +1183,20 @@ gdk_window_end_paint (GdkWindow *window)
                      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);
+      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.width, clip_box.height);
+      reset_redirect_clip (window, tmp_gc, &data);
+    }
+  
   /* Reset clip region of the cached GdkGC */
   gdk_gc_set_clip_region (tmp_gc, NULL);
 
@@ -1100,7 +1248,7 @@ gdk_window_get_offsets (GdkWindow *windo
       *y_offset = paint->y_offset;
     }
   else
-    _gdk_windowing_window_get_offsets (window, x_offset, y_offset);
+    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (window, x_offset, y_offset);
 }
 
 /**
@@ -1218,7 +1366,7 @@ gdk_window_draw_rectangle (GdkDrawable *
     }
   else
     gdk_draw_rectangle (private->impl, gc, filled,
-                        x - x_offset, y - y_offset, width, height);
+			x - x_offset, y - y_offset, width, height);
 
   RESTORE_GC (gc);
 }
@@ -1356,6 +1504,15 @@ gdk_window_draw_text_wc (GdkDrawable    
 }
 
 static GdkDrawable*
+gdk_window_get_source_drawable (GdkDrawable *drawable)
+{
+  GdkWindow *window = GDK_WINDOW (drawable);
+  if (gdk_window_is_offscreen (window))
+    return gdk_window_get_offscreen_pixmap (window);
+  return drawable;
+}
+
+static GdkDrawable*
 gdk_window_get_composite_drawable (GdkDrawable *drawable,
                                    gint         x,
                                    gint         y,
@@ -1370,13 +1527,15 @@ gdk_window_get_composite_drawable (GdkDr
   GdkRectangle rect;
   GdkGC *tmp_gc;
   gboolean overlap_buffer;
+  gboolean is_offscreen;
 
-  _gdk_windowing_window_get_offsets (drawable,
-				     composite_x_offset,
-				     composite_y_offset);
-  
+  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (GDK_WINDOW (drawable),
+							  composite_x_offset,
+							  composite_y_offset);
+
+  is_offscreen = gdk_window_is_offscreen (GDK_WINDOW (drawable));
   if ((GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable))
-      || private->paint_stack == NULL)
+      || (!is_offscreen && private->paint_stack == NULL))
     {
       /* No backing store */
       return g_object_ref (drawable);
@@ -1413,7 +1572,7 @@ gdk_window_get_composite_drawable (GdkDr
 	}
     }
 
-  if (!overlap_buffer)
+  if (!overlap_buffer && !is_offscreen)
     return g_object_ref (drawable);
 
   tmp_pixmap = gdk_pixmap_new (drawable, width, height, -1);
@@ -1517,10 +1676,9 @@ gdk_window_draw_drawable (GdkDrawable *d
     }
   else
     gdk_draw_drawable (private->impl, gc,
-                       src, xsrc, ysrc,
-                       xdest - x_offset, ydest - y_offset,
-                       width, height);
-
+		       src, xsrc, ysrc,
+		       xdest - x_offset, ydest - y_offset,
+		       width, height);
   RESTORE_GC (gc);
 }
 
@@ -1792,6 +1950,48 @@ gdk_window_clear_backing_rect (GdkWindow
   cairo_destroy (cr);
 }
 
+static void
+gdk_window_clear_backing_rect_redirect (GdkWindow *window,
+					gint       x,
+					gint       y,
+					gint       width,
+					gint       height)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowRedirect *redirect = private->redirect;
+  GdkRegion *clip_region;
+  cairo_t *cr;
+  cairo_surface_t *surface;
+  gint x_offset, y_offset;
+
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
+  clip_region = _gdk_window_calculate_full_clip_region (window,
+							GDK_WINDOW (redirect->redirected),
+							NULL, TRUE,
+							&x_offset, &y_offset);
+  
+  surface = _gdk_drawable_ref_cairo_surface (redirect->pixmap);
+  cairo_surface_set_device_offset (surface,
+				   x_offset, y_offset);
+  cr = cairo_create (surface);
+
+  gdk_window_set_bg_pattern (window, cr, 0, 0);
+
+  cairo_rectangle (cr, x, y, width, height);
+  cairo_clip (cr);
+
+  gdk_cairo_region (cr, clip_region);
+  cairo_fill (cr);
+  
+  cairo_destroy (cr);
+
+  gdk_region_destroy (clip_region);
+  cairo_surface_destroy (surface);
+}
+
+
 /**
  * gdk_window_clear:
  * @window: a #GdkWindow
@@ -1838,7 +2038,12 @@ gdk_window_clear_area (GdkWindow *window
   if (private->paint_stack)
     gdk_window_clear_backing_rect (window, x, y, width, height);
   else
-    _gdk_windowing_window_clear_area (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, FALSE);
+    }
 }
 
 /**
@@ -1871,7 +2076,10 @@ gdk_window_clear_area_e (GdkWindow *wind
   if (private->paint_stack)
     gdk_window_clear_backing_rect (window, x, y, width, height);
 
-  _gdk_windowing_window_clear_area_e (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);
 }
 
 static void
@@ -2083,6 +2291,7 @@ gdk_window_copy_to_image (GdkDrawable   
 			  gint             width,
 			  gint             height)
 {
+  GdkWindowObject *private = (GdkWindowObject *)drawable;
   gint x_offset, y_offset;
   
   g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
@@ -2094,9 +2303,10 @@ gdk_window_copy_to_image (GdkDrawable   
    * we can ignore the paint stack.
    */
   
-  _gdk_windowing_window_get_offsets (drawable, &x_offset, &y_offset);
+  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (drawable,
+							  &x_offset, &y_offset);
   
-  return gdk_drawable_copy_to_image (((GdkWindowObject*)drawable)->impl,
+  return gdk_drawable_copy_to_image (private->impl,
 				     image,
 				     src_x - x_offset,
 				     src_y - y_offset,
@@ -2180,8 +2390,9 @@ gdk_window_process_updates_internal (Gdk
               gdk_display_sync (gdk_drawable_get_display (window));
               g_usleep (70000);
             }
-          
-	  save_region = _gdk_windowing_window_queue_antiexpose (window, update_area);
+
+	  if (!gdk_window_is_offscreen (window))
+	    save_region = _gdk_windowing_window_queue_antiexpose (window, update_area);
 
 	  if (save_region)
 	    expose_region = gdk_region_copy (update_area);
@@ -2449,8 +2660,10 @@ gdk_window_invalidate_maybe_recurse (Gdk
 
 	  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)
+	  /* remove child area from the invalid area of the parent, unless
+	   * the child is a toplevel offscreen window */
+	  if (GDK_WINDOW_IS_MAPPED (child) && !child->shaped &&
+	      !_gdk_window_is_toplevel_offscreen (GDK_WINDOW (child)))
 	    gdk_region_subtract (visible_region, child_region);
 	  
 	  if (child_func && (*child_func) ((GdkWindow *)child, user_data))
@@ -2903,6 +3116,1244 @@ gdk_window_foreign_new (GdkNativeWindow 
 {
   return gdk_window_foreign_new_for_display (gdk_display_get_default (), anid);
 }
+
+/**
+ * gdk_window_new:
+ * @parent: a #GdkWindow, or %NULL to create the window as a child of
+ *   the default root window for the default display.
+ * @attributes: attributes of the new window
+ * @attributes_mask: mask indicating which fields in @attributes are valid
+ * 
+ * Creates a new #GdkWindow using the attributes from
+ * @attributes. See #GdkWindowAttr and #GdkWindowAttributesType for
+ * more details.  Note: to use this on displays other than the default
+ * display, @parent must be specified.
+ * 
+ * Return value: the new #GdkWindow
+ **/
+GdkWindow*
+gdk_window_new (GdkWindow     *parent,
+		GdkWindowAttr *attributes,
+		gint           attributes_mask)
+{
+  GdkWindow *window;
+  GdkWindowObject *private, *parent_private;
+  
+  g_return_val_if_fail (attributes != NULL, NULL);
+
+  if (parent && gdk_window_is_offscreen (parent))
+    window = _gdk_window_new_offscreen (parent, attributes, attributes_mask, FALSE);
+  else
+    window = _gdk_window_new (parent, attributes, attributes_mask);
+
+  /* Inherit redirection from parent */
+  if (parent != NULL)
+    {
+      parent_private = GDK_WINDOW_OBJECT (parent);
+      private = GDK_WINDOW_OBJECT (window);
+      private->redirect = parent_private->redirect;
+    }
+  
+  return window;
+}
+
+/**
+ * gdk_window_show_unraised:
+ * @window: a #GdkWindow
+ *
+ * Shows a #GdkWindow onscreen, but does not modify its stacking
+ * order. In contrast, gdk_window_show() will raise the window
+ * to the top of the window stack.
+ *
+ * On the X11 platform, in Xlib terms, this function calls
+ * XMapWindow() (it also updates some internal GDK state, which means
+ * that you can't really use XMapWindow() directly on a GDK window).
+ * 
+ **/
+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);
+}
+
+/**
+ * gdk_window_show:
+ * @window: a #GdkWindow
+ *
+ * Like gdk_window_show_unraised(), but also raises the window to the
+ * top of the window stack (moves the window to the front of the
+ * Z-order).
+ *
+ * This function maps a window so it's visible onscreen. Its opposite
+ * is gdk_window_hide().
+ *
+ * When implementing a #GtkWidget, you should call this function on the widget's
+ * #GdkWindow as part of the "map" method.
+ * 
+ **/
+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_hide:
+ * @window: a #GdkWindow
+ *
+ * For toplevel windows, withdraws them, so they will no longer be
+ * known to the window manager; for all windows, unmaps them, so
+ * they won't be displayed. Normally done automatically as
+ * part of gtk_widget_hide().
+ * 
+ **/
+void
+gdk_window_hide (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)->hide (window);
+}
+
+/**
+ * gdk_window_withdraw:
+ * @window: a toplevel #GdkWindow
+ * 
+ * Withdraws a window (unmaps it and asks the window manager to forget about it).
+ * This function is not really useful as gdk_window_hide() automatically
+ * withdraws toplevel windows before hiding them.
+ * 
+ **/
+void
+gdk_window_withdraw (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)->withdraw (window);
+}
+
+/**
+ * gdk_window_set_events:
+ * @window: a #GdkWindow
+ * @event_mask: event mask for @window
+ *
+ * The event mask for a window determines which events will be reported
+ * for that window. For example, an event mask including #GDK_BUTTON_PRESS_MASK
+ * means the window should report button press events. The event mask
+ * is the bitwise OR of values from the #GdkEventMask enumeration.
+ * 
+ **/
+void          
+gdk_window_set_events (GdkWindow       *window,
+		       GdkEventMask     event_mask)
+{
+  GdkWindowObject *private;
+  
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *) window;
+  if (private->destroyed)
+    return;
+
+  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_events (window, event_mask);
+}
+
+
+/**
+ * gdk_window_get_events:
+ * @window: a #GdkWindow
+ * 
+ * Gets the event mask for @window. See gdk_window_set_events().
+ * 
+ * Return value: event mask for @window
+ **/
+GdkEventMask  
+gdk_window_get_events (GdkWindow *window)
+{
+  GdkWindowObject *private;
+  
+  g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
+
+  private = (GdkWindowObject *) window;
+  if (private->destroyed)
+    return 0;
+
+  return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_events (window);
+}
+
+static void
+gdk_window_raise_internal (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *parent;
+
+  parent = private->parent;
+
+  if (parent)
+    {
+      parent->children = g_list_remove (parent->children, window);
+      parent->children = g_list_prepend (parent->children, window);
+    }
+}
+
+/**
+ * gdk_window_raise:
+ * @window: a #GdkWindow
+ * 
+ * Raises @window to the top of the Z-order (stacking order), so that
+ * other windows with the same parent window appear below @window.
+ * This is true whether or not the windows are visible.
+ *
+ * If @window is a toplevel, the window manager may choose to deny the
+ * request to move the window in the Z-order, gdk_window_raise() only
+ * requests the restack, does not guarantee it.
+ * 
+ **/
+void
+gdk_window_raise (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)->raise (window);
+}
+
+static void
+gdk_window_lower_internal (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *parent;
+
+  parent = private->parent;
+  if (parent)
+    {
+      parent->children = g_list_remove (parent->children, window);
+      parent->children = g_list_append (parent->children, window);
+    }
+}
+
+/**
+ * gdk_window_lower:
+ * @window: a #GdkWindow
+ * 
+ * Lowers @window to the bottom of the Z-order (stacking order), so that
+ * other windows with the same parent window appear above @window.
+ * This is true whether or not the other windows are visible.
+ *
+ * If @window is a toplevel, the window manager may choose to deny the
+ * request to move the window in the Z-order, gdk_window_lower() only
+ * requests the restack, does not guarantee it.
+ *
+ * Note that gdk_window_show() raises the window again, so don't call this
+ * function before gdk_window_show(). (Try gdk_window_show_unraised().)
+ * 
+ **/
+void
+gdk_window_lower (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_lower_internal (window);
+  
+  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->lower (window);
+}
+
+/**
+ * gdk_window_move:
+ * @window: a #GdkWindow
+ * @x: X coordinate relative to window's parent
+ * @y: Y coordinate relative to window's parent
+ *
+ * Repositions a window relative to its parent window.
+ * For toplevel windows, window managers may ignore or modify the move;
+ * you should probably use gtk_window_move() on a #GtkWindow widget
+ * anyway, instead of using GDK functions. For child windows,
+ * the move will reliably succeed.
+ *
+ * If you're also planning to resize the window, use gdk_window_move_resize()
+ * to both move and resize simultaneously, for a nicer visual effect.
+ **/
+void
+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 (window, x, y);
+}
+
+/**
+ * gdk_window_resize:
+ * @window: a #GdkWindow
+ * @width: new width of the window
+ * @height: new height of the window
+ *
+ * Resizes @window; for toplevel windows, asks the window manager to resize
+ * the window. The window manager may not allow the resize. When using GTK+,
+ * use gtk_window_resize() instead of this low-level GDK function.
+ *
+ * Windows may not be resized below 1x1.
+ * 
+ * If you're also planning to move the window, use gdk_window_move_resize()
+ * to both move and resize simultaneously, for a nicer visual effect.
+ **/
+void
+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)->resize (window, width, height);
+}
+
+
+/**
+ * gdk_window_move_resize:
+ * @window: a #GdkWindow
+ * @x: new X position relative to window's parent
+ * @y: new Y position relative to window's parent
+ * @width: new width
+ * @height: new height
+ *
+ * Equivalent to calling gdk_window_move() and gdk_window_resize(),
+ * except that both operations are performed at once, avoiding strange
+ * visual effects. (i.e. the user may be able to see the window first
+ * move, then resize, if you don't use gdk_window_move_resize().)
+ **/
+void
+gdk_window_move_resize (GdkWindow *window,
+			gint       x,
+			gint       y,
+			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, x, y, width, height);
+}
+
+
+/**
+ * gdk_window_scroll:
+ * @window: a #GdkWindow
+ * @dx: Amount to scroll in the X direction
+ * @dy: Amount to scroll in the Y direction
+ * 
+ * Scroll the contents of @window, both pixels and children, by the given
+ * amount. @window itself does not move.  Portions of the window that the scroll
+ * operation brings in from offscreen areas are invalidated. The invalidated
+ * region may be bigger than what would strictly be necessary.  (For X11, a
+ * minimum area will be invalidated if the window has no subwindows, or if the
+ * edges of the window's parent do not extend beyond the edges of the window. In
+ * other cases, a multi-step process is used to scroll the window which may
+ * produce temporary visual artifacts and unnecessary invalidations.)
+ **/
+void
+gdk_window_scroll (GdkWindow *window,
+		   gint       dx,
+		   gint       dy)
+{
+  GdkWindowObject *private = (GdkWindowObject *) window;
+  
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  if (dx == 0 && dy == 0)
+    return;
+  
+  if (private->destroyed)
+    return;
+  
+  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->scroll (window, dx, dy);
+}
+
+/**
+ * gdk_window_move_region:
+ * @window: a #GdkWindow
+ * @region: The #GdkRegion to move
+ * @dx: Amount to move in the X direction
+ * @dy: Amount to move in the Y direction
+ * 
+ * Move the part of @window indicated by @region by @dy pixels in the Y 
+ * direction and @dx pixels in the X direction. The portions of @region 
+ * that not covered by the new position of @region are invalidated.
+ * 
+ * Child windows are not moved.
+ * 
+ * Since: 2.8
+ **/
+void
+gdk_window_move_region (GdkWindow *window,
+			GdkRegion *region,
+			gint       dx,
+			gint       dy)
+{
+  GdkWindowObject *private = (GdkWindowObject *) window;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (region != NULL);
+
+  if (dx == 0 && dy == 0)
+    return;
+
+  if (private->destroyed)
+    return;
+  
+  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_region (window, region, dx, dy);
+}
+
+
+/**
+ * gdk_window_set_background:
+ * @window: a #GdkWindow
+ * @color: an allocated #GdkColor
+ *
+ * Sets the background color of @window. (However, when using GTK+,
+ * set the background of a widget with gtk_widget_modify_bg() - if
+ * you're an application - or gtk_style_set_background() - if you're
+ * implementing a custom widget.)
+ *
+ * The @color must be allocated; gdk_rgb_find_color() is the best way
+ * to allocate a color.
+ *
+ * See also gdk_window_set_back_pixmap().
+ * 
+ **/
+void
+gdk_window_set_background (GdkWindow      *window,
+			   const GdkColor *color)
+{
+  GdkWindowObject *private;
+  
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *) window;
+  
+  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, color);
+}
+
+/**
+ * gdk_window_set_back_pixmap:
+ * @window: a #GdkWindow
+ * @pixmap: a #GdkPixmap, or %NULL
+ * @parent_relative: whether the tiling origin is at the origin of @window's parent
+ *
+ * Sets the background pixmap of @window. May also be used to set a background of
+ * "None" on @window, by setting a background pixmap of %NULL.
+ * A background pixmap will be tiled, positioning the first tile at the origin of
+ * @window, or if @parent_relative is %TRUE, the tiling will be done based on the
+ * origin of the parent window (useful to align tiles in a parent with tiles
+ * in a child).
+ *
+ * A background pixmap of %NULL means that the window will have no
+ * background.  A window with no background will never have its
+ * background filled by the windowing system, instead the window will
+ * contain whatever pixels were already in the corresponding area of
+ * the display.
+ *
+ * The windowing system will normally fill a window with its background
+ * when the window is obscured then exposed, and when you call
+ * gdk_window_clear().
+ * 
+ **/
+void
+gdk_window_set_back_pixmap (GdkWindow *window,
+			    GdkPixmap *pixmap,
+			    gboolean   parent_relative)
+{
+  GdkWindowObject *private;
+  
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *) window;
+  
+  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, pixmap, parent_relative);
+}
+
+/**
+ * gdk_window_reparent:
+ * @window: a #GdkWindow
+ * @new_parent: new parent to move @window into
+ * @x: X location inside the new parent
+ * @y: Y location inside the new parent
+ *
+ * Reparents @window into the given @new_parent. The window being
+ * reparented will be unmapped as a side effect.
+ * 
+ **/
+void
+gdk_window_reparent (GdkWindow *window,
+		     GdkWindow *new_parent,
+		     gint       x,
+		     gint       y)
+{
+  GdkWindowObject *private;
+  gboolean show;
+  
+  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;
+    }
+
+  private = (GdkWindowObject *) window;
+
+  /* Break up redirection if inherited */
+  if (private->redirect && private->redirect->redirected != private)
+    {
+      remove_redirect_from_children (private, private->redirect);
+      private->redirect = NULL;
+    }
+  
+  show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent (window, new_parent, x, y);
+
+  /* Inherit parent redirect if we don't have our own */
+  if (private->parent && private->redirect == NULL)
+    {
+      private->redirect = private->parent->redirect;
+      apply_redirect_to_children (private, private->redirect);
+    }
+  if (show)
+    gdk_window_show (window);
+}
+
+/**
+ * gdk_window_set_cursor:
+ * @window: a #GdkWindow
+ * @cursor: a cursor
+ *
+ * Sets the mouse pointer for a #GdkWindow. Use gdk_cursor_new() or
+ * gdk_cursor_new_from_pixmap() to create the cursor.
+ * To make the cursor invisible, use gdk_cursor_new_from_pixmap() to create
+ * a cursor with no pixels in it. Passing %NULL for the @cursor argument
+ * to gdk_window_set_cursor() means that @window will use the cursor of
+ * its parent window. Most windows should use this default.
+ * 
+ **/
+void
+gdk_window_set_cursor (GdkWindow *window,
+		       GdkCursor *cursor)
+{
+  GdkWindowObject *private;
+  
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *) window;
+  
+  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_cursor (window, cursor);
+}
+
+/**
+ * gdk_window_get_geometry:
+ * @window: a #GdkWindow
+ * @x: return location for X coordinate of window (relative to its parent)
+ * @y: return location for Y coordinate of window (relative to its parent)
+ * @width: return location for width of window
+ * @height: return location for height of window
+ * @depth: return location for bit depth of window
+ *
+ * Any of the return location arguments to this function may be %NULL,
+ * if you aren't interested in getting the value of that field.
+ *
+ * The X and Y coordinates returned are relative to the parent window
+ * of @window, which for toplevels usually means relative to the
+ * window decorations (titlebar, etc.) rather than relative to the
+ * root window (screen-size background window).
+ *
+ * On the X11 platform, the geometry is obtained from the X server,
+ * so reflects the latest position of @window; this may be out-of-sync
+ * with the position of @window delivered in the most-recently-processed
+ * #GdkEventConfigure. gdk_window_get_position() in contrast gets the
+ * position from the most recent configure event.
+ * 
+ * <note>
+ * If @window is not a toplevel, it is <emphasis>much</emphasis> better 
+ * to call gdk_window_get_position() and gdk_drawable_get_size() instead, 
+ * because it avoids the roundtrip to the X server and because 
+ * gdk_drawable_get_size() supports the full 32-bit coordinate space,
+ * whereas gdk_window_get_geometry() is restricted to the 16-bit
+ * coordinates of X11.
+ *</note>
+ **/
+void
+gdk_window_get_geometry (GdkWindow *window,
+			 gint      *x,
+			 gint      *y,
+			 gint      *width,
+			 gint      *height,
+			 gint      *depth)
+{
+  GdkWindowObject *private;
+  
+  if (!window)
+    {
+      GDK_NOTE (MULTIHEAD,
+		g_message ("gdk_window_get_geometry(): Window needs to be non-NULL to be multi head safe"));
+      window = gdk_screen_get_root_window ((gdk_screen_get_default ()));
+    }
+  
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *) window;
+  
+  if (!GDK_WINDOW_DESTROYED (window))
+    {
+      GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_geometry (window, x, y,
+							       width, height, depth);
+    }
+}
+
+/**
+ * gdk_window_get_origin:
+ * @window: a #GdkWindow
+ * @x: return location for X coordinate
+ * @y: return location for Y coordinate
+ * 
+ * Obtains the position of a window in root window coordinates.
+ * (Compare with gdk_window_get_position() and
+ * gdk_window_get_geometry() which return the position of a window
+ * relative to its parent window.)
+ * 
+ * Return value: not meaningful, ignore
+ **/
+gint
+gdk_window_get_origin (GdkWindow *window,
+		       gint      *x,
+		       gint      *y)
+{
+  GdkWindowObject *private;
+
+  g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
+
+  private = (GdkWindowObject *) window;
+  
+  return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_origin (window, x, y);
+}
+
+/**
+ * gdk_window_shape_combine_mask:
+ * @window: a #GdkWindow
+ * @mask: shape mask
+ * @x: X position of shape mask with respect to @window
+ * @y: Y position of shape mask with respect to @window
+ *
+ * Applies a shape mask to @window. Pixels in @window corresponding to
+ * set bits in the @mask will be visible; pixels in @window
+ * corresponding to unset bits in the @mask will be transparent. This
+ * gives a non-rectangular window.
+ *
+ * If @mask is %NULL, the shape mask will be unset, and the @x/@y
+ * parameters are not used.
+ *
+ * On the X11 platform, this uses an X server extension which is
+ * widely available on most common platforms, but not available on
+ * very old X servers, and occasionally the implementation will be
+ * buggy. On servers without the shape extension, this function
+ * will do nothing.
+ *
+ * This function works on both toplevel and child windows.
+ * 
+ **/
+void
+gdk_window_shape_combine_mask (GdkWindow *window,
+			       GdkBitmap *mask,
+			       gint x, gint y)
+{
+  GdkWindowObject *private;
+  
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *) window;
+  
+  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_mask (window, mask, x, y);
+}
+
+/**
+ * gdk_window_shape_combine_region:
+ * @window: a #GdkWindow
+ * @shape_region: region of window to be non-transparent
+ * @offset_x: X position of @shape_region in @window coordinates
+ * @offset_y: Y position of @shape_region in @window coordinates
+ *
+ * Makes pixels in @window outside @shape_region be transparent,
+ * so that the window may be nonrectangular. See also
+ * gdk_window_shape_combine_mask() to use a bitmap as the mask.
+ *
+ * If @shape_region is %NULL, the shape will be unset, so the whole
+ * window will be opaque again. @offset_x and @offset_y are ignored
+ * if @shape_region is %NULL.
+ * 
+ * On the X11 platform, this uses an X server extension which is
+ * widely available on most common platforms, but not available on
+ * very old X servers, and occasionally the implementation will be
+ * buggy. On servers without the shape extension, this function
+ * will do nothing.
+ *
+ * This function works on both toplevel and child windows.
+ * 
+ **/
+void
+gdk_window_shape_combine_region (GdkWindow *window,
+                                 GdkRegion *shape_region,
+                                 gint       offset_x,
+                                 gint       offset_y)
+{
+  GdkWindowObject *private;
+  
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *) window;
+  
+  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region (window, shape_region, offset_x, offset_y);
+}
+
+/**
+ * gdk_window_set_child_shapes:
+ * @window: a #GdkWindow
+ * 
+ * Sets the shape mask of @window to the union of shape masks
+ * for all children of @window, ignoring the shape mask of @window
+ * itself. Contrast with gdk_window_merge_child_shapes() which includes
+ * the shape mask of @window in the masks to be merged.
+ **/
+void
+gdk_window_set_child_shapes (GdkWindow *window)
+{
+  GdkWindowObject *private;
+  
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *) window;
+  
+  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_child_shapes (window);
+}
+
+/**
+ * gdk_window_merge_child_shapes:
+ * @window: a #GdkWindow
+ * 
+ * Merges the shape masks for any child windows into the
+ * shape mask for @window. i.e. the union of all masks
+ * for @window and its children will become the new mask
+ * for @window. See gdk_window_shape_combine_mask().
+ *
+ * This function is distinct from gdk_window_set_child_shapes()
+ * because it includes @window's shape mask in the set of shapes to
+ * be merged.
+ * 
+ **/
+void
+gdk_window_merge_child_shapes (GdkWindow *window)
+{
+  GdkWindowObject *private;
+  
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *) window;
+  
+  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->merge_child_shapes (window);
+}
+
+
+/**
+ * gdk_window_set_static_gravities:
+ * @window: a #GdkWindow
+ * @use_static: %TRUE to turn on static gravity
+ *
+ * Set the bit gravity of the given window to static, and flag it so
+ * all children get static subwindow gravity. This is used if you are
+ * implementing scary features that involve deep knowledge of the
+ * windowing system. Don't worry about it unless you have to.
+ * 
+ * Return value: %TRUE if the server supports static gravity
+ **/
+gboolean 
+gdk_window_set_static_gravities (GdkWindow *window,
+				 gboolean   use_static)
+{
+  GdkWindowObject *private;
+  
+  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+
+  private = (GdkWindowObject *) window;
+  
+  return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_static_gravities (window, use_static);
+}
+
+static void
+remove_redirect_from_children (GdkWindowObject *private, GdkWindowRedirect *redirect)
+{
+  GList *l;
+  GdkWindowObject *child;
+
+  for (l = private->children; l != NULL; l = l->next)
+    {
+      child = l->data;
+
+      /* Don't redirect this child if it already has another redirect */
+      if (child->redirect == redirect)
+	{
+	  child->redirect = NULL;
+	  remove_redirect_from_children (child, redirect);
+	}
+    }
+}
+
+/**
+ * gdk_window_remove_redirection:
+ * @window: a #GdkWindow
+ *
+ * Removes and active redirection started by
+ * gdk_window_redirect_to_drawable().
+ **/
+void
+gdk_window_remove_redirection (GdkWindow *window)
+{
+  GdkWindowObject *private;
+  
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *) window;
+
+  if (private->redirect &&
+      private->redirect->redirected == private)
+    {
+      remove_redirect_from_children (private, private->redirect);
+      gdk_window_redirect_free (private->redirect);
+      private->redirect = NULL;
+    }
+}
+
+static void
+apply_redirect_to_children (GdkWindowObject *private, GdkWindowRedirect *redirect)
+{
+  GList *l;
+  GdkWindowObject *child;
+
+  for (l = private->children; l != NULL; l = l->next)
+    {
+      child = l->data;
+
+      /* Don't redirect this child if it already has another redirect */
+      if (!child->redirect)
+	{
+	  child->redirect = redirect;
+	  apply_redirect_to_children (child, redirect);
+	}
+    }
+}
+
+/**
+ * gdk_window_redirect_to_drawable:
+ * @window: a #GdkWindow
+ * @drawable: a #GdkDrawable
+ * src_x: x position in @window
+ * src_y: y position in @window
+ * dest_x: x position in @drawable
+ * dest_y: y position in @drawable
+ * width: width of redirection
+ * height: height of redirection
+ *
+ * Redirects drawing into @windows so that drawing to the
+ * window in the rectangle specified by @src_x, @src_y,
+ * @width and @height is also drawn into @drawable at
+ * @dest_x, @dest_y.
+ *
+ * Only drawing between gdk_window_begin_paint_region() and
+ * gdk_window_end_paint() is redirected.
+ *
+ * Redirection is active until gdk_window_remove_redirection()
+ * is called.
+ *
+ * This function should not be used on windows created by
+ * gdk_window_new_offscreen(), as that is implemented using
+ * redirection.
+ **/
+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)
+{
+  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);
+
+  private = (GdkWindowObject *) window;
+
+  if (private->redirect)
+    gdk_window_remove_redirection (window);
+
+  if (width == -1 || height == -1)
+    {
+      gint w, h;
+      gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
+      if (width == -1)
+	width = w;
+      if (height == -1)
+	height = h;
+    }
+  
+  private->redirect = g_new0 (GdkWindowRedirect, 1);
+  private->redirect->redirected = private;
+  private->redirect->pixmap = g_object_ref (drawable);
+  private->redirect->src_x = src_x;
+  private->redirect->src_y = src_y;
+  private->redirect->dest_x = dest_x;
+  private->redirect->dest_y = dest_y;
+  private->redirect->width = width;
+  private->redirect->height = height;
+
+  apply_redirect_to_children (private, private->redirect);
+}
+
+/* Calculates the real clipping region for a window, in window coordinates,
+ * taking into account other windows, gc clip region and gc clip mask.
+ */
+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)
+{
+  GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
+  GdkRectangle visible_rect;
+  GdkRegion *real_clip_region, *tmpreg;
+  gint x_offset, y_offset;
+  GdkWindowObject *parentwin, *lastwin;
+
+  if (base_x_offset)
+    *base_x_offset = 0;
+  if (base_y_offset)
+    *base_y_offset = 0;
+  
+  if (!GDK_WINDOW_IS_MAPPED (window) || private->input_only)
+      return gdk_region_new ();
+  
+  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_visible_rect (window, &visible_rect);
+
+  /* real_clip_region is in window coordinates */
+  real_clip_region = gdk_region_rectangle (&visible_rect);
+
+  x_offset = y_offset = 0;
+
+  lastwin = private;
+  if (do_children)
+    parentwin = lastwin;
+  else
+    parentwin = lastwin->parent;
+  
+  /* Remove the areas of all overlapping windows above parentwin in the hiearachy */
+  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 (GDK_WINDOW (parentwin));
+      
+      /* children is ordered in reverse stack order */
+      for (cur = GDK_WINDOW_OBJECT (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 toplevel offscreen children */
+	  if (_gdk_window_is_toplevel_offscreen (child))
+	    continue;
+	  
+	  GDK_WINDOW_IMPL_GET_IFACE (child_private->impl)->get_visible_rect (child, &visible_rect);
+	  
+	  /* Convert rect to "window" coords */
+	  visible_rect.x += child_private->x - x_offset;
+	  visible_rect.y += child_private->y - y_offset;
+	  
+	  /* This shortcut is really necessary for performance when there are a lot of windows */
+	  gdk_region_get_clipbox (real_clip_region, &real_clip_rect);
+	  if (visible_rect.x >= real_clip_rect.x + real_clip_rect.width ||
+	      visible_rect.x + visible_rect.width <= real_clip_rect.x ||
+	      visible_rect.y >= real_clip_rect.y + real_clip_rect.height ||
+	      visible_rect.y + visible_rect.height <= real_clip_rect.y)
+	    continue;
+	  
+	  tmpreg = gdk_region_rectangle (&visible_rect);
+	  gdk_region_subtract (real_clip_region, tmpreg);
+	  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)
+    *base_y_offset = y_offset;
+
+  return real_clip_region;
+}
+
+static gboolean
+send_damage_idle_callback (gpointer data)
+{
+  GdkWindow *toplevel = data;
+  GdkWindowObject *private = GDK_WINDOW_OBJECT (toplevel);
+  
+  GDK_THREADS_ENTER ();
+
+  if (_gdk_event_func)
+    {
+      GdkEvent event;
+      
+      event.expose.type = GDK_DAMAGE;
+      event.expose.window = g_object_ref (toplevel);
+      event.expose.send_event = FALSE;
+      event.expose.region = private->redirect->damage;
+      gdk_region_get_clipbox (private->redirect->damage,
+			      &event.expose.area);
+
+      (*_gdk_event_func) (&event, _gdk_event_data);
+      
+      g_object_unref (toplevel);
+    }
+  
+  gdk_region_destroy (private->redirect->damage);
+  private->redirect->damage = NULL;
+  private->redirect->damage_idle = 0;
+
+  GDK_THREADS_LEAVE ();
+  
+  return FALSE;
+}
+
+static void
+gdk_window_add_damage (GdkWindow *toplevel, GdkRegion *damaged_region)
+{
+  GdkWindowObject *private = GDK_WINDOW_OBJECT (toplevel);
+
+  if (private->redirect->damage)
+    gdk_region_union (private->redirect->damage, damaged_region);
+  else
+    private->redirect->damage = gdk_region_copy (damaged_region);
+
+  if (private->redirect->damage_idle == 0)
+    private->redirect->damage_idle = g_idle_add_full (GDK_PRIORITY_REDRAW,
+						      send_damage_idle_callback,
+						      toplevel, NULL);
+}
+  
+static void
+setup_redirect_clip (GdkWindow *window, GdkGC *gc, GdkWindowClipData *data)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkRegion *visible_region;
+  GdkRectangle dest_rect;
+  GdkRegion *tmpreg;
+  GdkWindow *toplevel;
+
+  data->old_region = _gdk_gc_get_clip_region (gc);
+  if (data->old_region) 
+    data->old_region = gdk_region_copy (data->old_region);
+
+  data->old_clip_x_origin = gc->clip_x_origin;
+  data->old_clip_y_origin = gc->clip_y_origin;
+
+  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,
+					    gc, TRUE,
+					    &data->x_offset, 
+					    &data->y_offset);
+
+  /* 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);
+
+  /* Compensate for the dest pos */
+  data->x_offset += private->redirect->dest_x;
+  data->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, -data->x_offset, -data->y_offset);
+
+  /* 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);
+  
+  gdk_region_destroy (visible_region);
+}
+
+static void
+reset_redirect_clip (GdkWindow *offscreen, GdkGC *gc, GdkWindowClipData *data)
+{
+  /* offset back */
+  gdk_gc_offset (gc, data->x_offset, data->y_offset);
+
+  /* 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 void
+gdk_window_redirect_free (GdkWindowRedirect *redirect)
+{
+  g_object_unref (redirect->pixmap);
+  if (redirect->damage_idle)
+    g_source_remove (redirect->damage_idle);
+  if (redirect->damage)
+    gdk_region_destroy (redirect->damage);
+  g_free (redirect);
+}
+
+void
+_gdk_window_add_offscreen_child (GdkWindow *window)
+{
+  GdkWindowObject *obj = (GdkWindowObject*) window;
+
+  if (obj->offscreen_children)
+    obj->offscreen_children->n_offscreen_children++;
+  else
+    {
+      obj->offscreen_children = g_new0 (GdkWindowOffscreenChildren, 1);
+      obj->offscreen_children->n_offscreen_children = 1;
+    }
+}
+
+void
+_gdk_window_remove_offscreen_child (GdkWindow *window)
+{
+  GdkWindowObject *obj = (GdkWindowObject*) window;
+
+  g_return_if_fail (obj->offscreen_children != NULL);
+  
+  if (obj->offscreen_children)
+    {
+      g_return_if_fail (obj->offscreen_children->n_offscreen_children > 0);
+      
+      obj->offscreen_children->n_offscreen_children--;
+      if (obj->offscreen_children->n_offscreen_children == 0)
+	{
+	  g_free (obj->offscreen_children);
+	  obj->offscreen_children = NULL;
+	}
+    }
+}
+ 
 
 #define __GDK_WINDOW_C__
 #include "gdkaliasdef.c"
Index: gdk/gdkwindow.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/gdkwindow.h,v
retrieving revision 1.55.2.1
diff -u -p -r1.55.2.1 gdkwindow.h
--- gdk/gdkwindow.h	26 Sep 2005 20:28:34 -0000	1.55.2.1
+++ gdk/gdkwindow.h	13 Oct 2005 20:59:02 -0000
@@ -36,6 +36,9 @@ G_BEGIN_DECLS
 typedef struct _GdkGeometry           GdkGeometry;
 typedef struct _GdkWindowAttr	      GdkWindowAttr;
 typedef struct _GdkPointerHooks	      GdkPointerHooks;
+typedef struct _GdkCoordinateHooks    GdkCoordinateHooks;
+typedef struct _GdkWindowRedirect     GdkWindowRedirect;
+typedef struct _GdkWindowOffscreenChildren GdkWindowOffscreenChildren;
 
 /* Classes of windows.
  *   InputOutput: Almost every window should be of this type. Such windows
@@ -236,9 +239,56 @@ struct _GdkPointerHooks 
                                    gint            *win_y);
 };
 
+struct _GdkCoordinateHooks
+{
+  void (*to_window) (GdkWindow	   *window,
+		     int            parent_x,
+		     int            parent_y,
+		     int           *window_x,
+		     int    	   *window_y);
+  void (*from_window) (GdkWindow   *window,
+		       int          window_x,
+		       int          window_y,
+		       int         *parent_x,
+		       int         *parent_y);
+};
+
+
 typedef struct _GdkWindowObject GdkWindowObject;
 typedef struct _GdkWindowObjectClass GdkWindowObjectClass;
 
+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;
+};
+
+struct _GdkWindowOffscreenChildren
+{
+  gint n_offscreen_children;
+  
+  /* The window with the mouse in it, or NULL if the pointer is not inside
+   *  an offscreen child. A pointer grab doesn't affect this.
+   */
+  GdkWindow *window_under_pointer;
+  gdouble last_mouse_x, last_mouse_y;
+  guint32 last_state;
+  GdkWindow *pointer_grab_window;
+  gboolean pointer_grab_owner_events;
+  GdkWindow *grab_one_pointer_release_event;
+  guint pointer_grab_event_mask;
+};
+
+
 #define GDK_TYPE_WINDOW              (gdk_window_object_get_type ())
 #define GDK_WINDOW(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WINDOW, GdkWindow))
 #define GDK_WINDOW_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_WINDOW, GdkWindowObjectClass))
@@ -290,6 +340,9 @@ struct _GdkWindowObject
   guint shaped : 1;
   
   GdkEventMask event_mask;
+  
+  GdkWindowRedirect *redirect;
+  GdkWindowOffscreenChildren *offscreen_children;
 };
 
 struct _GdkWindowObjectClass
@@ -362,6 +415,8 @@ void	      gdk_window_move_region       
 						GdkRegion *region,
 						gint       dx,
 						gint       dy);
+gboolean   gdk_window_is_offscreen             (GdkWindow          *window);
+GdkPixmap *gdk_window_get_offscreen_pixmap     (GdkWindow          *window);
 
 /* 
  * This allows for making shaped (partially transparent) windows
@@ -603,6 +658,16 @@ GdkPointerHooks *gdk_set_pointer_hooks (
 #endif /* GDK_MULTIHEAD_SAFE */
 
 GdkWindow *gdk_get_default_root_window (void);
+
+GdkWindow *gdk_window_new_offscreen         (GdkWindow     *parent,
+					     GdkWindowAttr *attributes,
+					     gint           attributes_mask);
+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);
 
 #ifndef GDK_DISABLE_DEPRECATED
 #define GDK_ROOT_PARENT()             (gdk_get_default_root_window ())
Index: gdk/gdkwindowimpl.c
===================================================================
RCS file: gdk/gdkwindowimpl.c
diff -N gdk/gdkwindowimpl.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gdk/gdkwindowimpl.c	13 Oct 2005 20:59:02 -0000
@@ -0,0 +1,62 @@
+/* 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-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+#include <config.h>
+#include "gdkwindowimpl.h"
+#include "gdkinternals.h"
+
+static void
+gdk_window_impl_base_init (gpointer g_class)
+{
+}
+
+GType                   
+gdk_window_impl_get_type (void)
+{
+  static GType type = 0;
+
+  if (!type)
+    {
+      static const GTypeInfo info = {
+	sizeof (GdkWindowImplIface),
+	gdk_window_impl_base_init,
+	NULL,
+	NULL,
+	NULL,
+	NULL,
+	0,
+	0,
+	NULL
+      };
+      
+      type = g_type_register_static (G_TYPE_INTERFACE, 
+				     "GdkWindowImpl",
+				     &info, 0);
+      g_type_interface_add_prerequisite (type, G_TYPE_OBJECT);
+    }
+  
+  return type;
+}
Index: gdk/gdkwindowimpl.h
===================================================================
RCS file: gdk/gdkwindowimpl.h
diff -N gdk/gdkwindowimpl.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gdk/gdkwindowimpl.h	13 Oct 2005 20:59:02 -0000
@@ -0,0 +1,110 @@
+/* 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-2000.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+#ifndef __GDK_WINDOW_IMPL_H__
+#define __GDK_WINDOW_IMPL_H__
+
+#include <gdk/gdkwindow.h>
+
+G_BEGIN_DECLS
+
+#define GDK_TYPE_WINDOW_IMPL           (gdk_window_impl_get_type ())
+#define GDK_WINDOW_IMPL(obj)           (G_TYPE_CHECK_INSTANCE_CAST ((obj), GDK_TYPE_WINDOW_IMPL, GdkWindowImpl))
+#define GDK_IS_WINDOW_IMPL(obj)        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GDK_TYPE_WINDOW_IMPL))
+#define GDK_WINDOW_IMPL_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), GDK_TYPE_WINDOW_IMPL, GdkWindowImplIface))
+
+typedef struct _GdkWindowImpl       GdkWindowImpl;
+typedef struct _GdkWindowImplIface  GdkWindowImplIface;
+
+struct _GdkWindowImplIface {
+  GTypeInterface g_iface;
+
+  void (*get_visible_rect) (GdkWindow *window, GdkRectangle *rect);
+  void (*show) (GdkWindow *window, gboolean raise);
+  void (*hide) (GdkWindow *window);
+  void (*withdraw) (GdkWindow *window);
+  void (*raise) (GdkWindow *window);
+  void (*lower) (GdkWindow *window);
+  void (*move) (GdkWindow *window, gint x, gint y);
+  void (*resize) (GdkWindow *window, gint width, gint height);
+  void (*move_resize) (GdkWindow *window, gint x, gint y, gint width, gint height);
+  void (*scroll) (GdkWindow *window, gint dx, gint dy);
+  void (*move_region) (GdkWindow *window,
+		       GdkRegion *region,
+		       gint       dx,
+		       gint       dy);
+  
+  void (*set_background) (GdkWindow *window, const GdkColor *color);
+  void (*set_back_pixmap) (GdkWindow *window,
+			   GdkPixmap *pixmap,
+			   gboolean   parent_relative);
+  GdkEventMask (*get_events) (GdkWindow *window);
+  void (*set_events) (GdkWindow *window, GdkEventMask event_mask);
+  void (*clear_area) (GdkWindow *window,
+		      gint x, gint y,
+		      gint width, gint height,
+		      gboolean send_expose);
+  gboolean (*reparent) (GdkWindow *window,
+			GdkWindow *new_parent,
+			gint       x,
+			gint       y);
+  void (*set_cursor) (GdkWindow *window,
+		      GdkCursor *cursor);
+  void (*get_geometry) (GdkWindow *window,
+			gint      *x,
+			gint      *y,
+			gint      *width,
+			gint      *height,
+			gint      *depth);
+  gint (*get_origin) (GdkWindow *window,
+		      gint      *x,
+		      gint      *y);
+  
+  void (*shape_combine_mask) (GdkWindow *window,
+			      GdkBitmap *mask,
+			      gint x, gint y);
+  void (*shape_combine_region) (GdkWindow *window,
+				GdkRegion *shape_region,
+				gint       offset_x,
+				gint       offset_y);
+  void (*set_child_shapes) (GdkWindow *window);
+  void (*merge_child_shapes) (GdkWindow *window);
+  gboolean (*set_static_gravities) (GdkWindow *window,
+				    gboolean   use_static);
+  void (*get_offsets) (GdkWindow *window,
+		       gint      *x_offset,
+		       gint      *y_offset);
+};
+
+/* Interface Functions */
+GType                   gdk_window_impl_get_type       (void);
+
+G_END_DECLS
+
+
+
+#endif /* __GDK_WINDOW_IMPL_H__ */
+
Index: gdk/x11/gdkdisplay-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkdisplay-x11.c,v
retrieving revision 1.60
diff -u -p -r1.60 gdkdisplay-x11.c
--- gdk/x11/gdkdisplay-x11.c	30 Jun 2005 03:35:30 -0000	1.60
+++ gdk/x11/gdkdisplay-x11.c	13 Oct 2005 20:59:02 -0000
@@ -521,7 +521,11 @@ gdk_display_pointer_ungrab (GdkDisplay *
   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;
+    {
+      if (gdk_window_is_offscreen (GDK_WINDOW (display_x11->pointer_xgrab_window)))
+	_gdk_offscreen_window_unset_pointer_grab (GDK_WINDOW (display_x11->pointer_xgrab_window), FALSE, FALSE, time);
+      display_x11->pointer_xgrab_window = NULL;
+    }
 }
 
 /**
@@ -1164,6 +1168,11 @@ gdk_display_store_clipboard (GdkDisplay 
 {
   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
   Atom clipboard_manager, save_targets;
+
+  g_return_if_fail (!gdk_window_is_offscreen (clipboard_window));
+
+  if (gdk_window_is_offscreen (clipboard_window))
+    return;
   
   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");
Index: gdk/x11/gdkdisplay-x11.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkdisplay-x11.h,v
retrieving revision 1.23
diff -u -p -r1.23 gdkdisplay-x11.h
--- gdk/x11/gdkdisplay-x11.h	30 Jun 2005 03:35:30 -0000	1.23
+++ gdk/x11/gdkdisplay-x11.h	13 Oct 2005 20:59:02 -0000
@@ -86,12 +86,14 @@ struct _GdkDisplayX11
    * window is NULL, then the other associated fields are ignored
    */
   GdkWindowObject *pointer_xgrab_window;
+  GdkWindowObject *pointer_xgrab_native_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;
@@ -154,6 +156,9 @@ struct _GdkDisplayX11
 
   /* Alpha mask picture format */
   XRenderPictFormat *mask_format;
+
+  /* the offscreen window that has the mouse in it (if any) */
+  GdkWindow *active_offscreen_window;
 };
 
 struct _GdkDisplayX11Class
Index: gdk/x11/gdkdnd-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkdnd-x11.c,v
retrieving revision 1.83
diff -u -p -r1.83 gdkdnd-x11.c
--- gdk/x11/gdkdnd-x11.c	19 Aug 2005 13:46:11 -0000	1.83
+++ gdk/x11/gdkdnd-x11.c	13 Oct 2005 20:59:02 -0000
@@ -2994,6 +2994,10 @@ gdk_drag_begin (GdkWindow     *window,
   GdkDragContext *new_context;
   
   g_return_val_if_fail (window != NULL, NULL);
+  g_return_val_if_fail (!gdk_window_is_offscreen (window), NULL);
+
+  if (gdk_window_is_offscreen (window))
+    return NULL;
 
   new_context = gdk_drag_context_new ();
   new_context->is_source = TRUE;
@@ -3188,7 +3192,14 @@ gdk_drag_find_window_for_screen (GdkDrag
   Window dest;
 
   g_return_if_fail (context != NULL);
+  g_return_if_fail (!gdk_window_is_offscreen (drag_window));
 
+  if (gdk_window_is_offscreen (drag_window))
+    {
+      *dest_window = NULL;
+      return;
+    }
+  
   display = GDK_WINDOW_DISPLAY (context->source_window);
 
   window_cache = drag_context_find_window_cache (context, screen);
@@ -3264,6 +3275,10 @@ 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 || !gdk_window_is_offscreen (dest_window), FALSE);
+
+  if (dest_window && gdk_window_is_offscreen (dest_window))
+    return FALSE;
 
   private->old_actions = context->actions;
   context->actions = possible_actions;
Index: gdk/x11/gdkdrawable-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkdrawable-x11.c,v
retrieving revision 1.58
diff -u -p -r1.58 gdkdrawable-x11.c
--- gdk/x11/gdkdrawable-x11.c	15 Aug 2005 19:04:54 -0000	1.58
+++ gdk/x11/gdkdrawable-x11.c	13 Oct 2005 20:59:02 -0000
@@ -894,9 +894,16 @@ XID
 gdk_x11_drawable_get_xid (GdkDrawable *drawable)
 {
   GdkDrawable *impl;
-  
+
   if (GDK_IS_WINDOW (drawable))
-    impl = ((GdkPixmapObject *)drawable)->impl;
+    {
+      if (gdk_window_is_offscreen (GDK_WINDOW (drawable)))
+	{
+	  g_warning (G_STRLOC " drawable is offscreen window");
+	  return None;
+	}
+      impl = ((GdkPixmapObject *)drawable)->impl;
+    }
   else if (GDK_IS_PIXMAP (drawable))
     impl = ((GdkPixmapObject *)drawable)->impl;
   else
Index: gdk/x11/gdkevents-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkevents-x11.c,v
retrieving revision 1.154
diff -u -p -r1.154 gdkevents-x11.c
--- gdk/x11/gdkevents-x11.c	19 Aug 2005 05:46:06 -0000	1.154
+++ gdk/x11/gdkevents-x11.c	13 Oct 2005 20:59:03 -0000
@@ -292,6 +292,8 @@ gdk_event_get_graphics_expose (GdkWindow
   GdkEvent *event;
   
   g_return_val_if_fail (window != NULL, NULL);
+
+  window = _gdk_window_get_offscreen_event_window (window);
   
   XIfEvent (GDK_WINDOW_XDISPLAY (window), &xevent, 
 	    graphics_expose_predicate, (XPointer) window);
@@ -916,6 +918,16 @@ 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
@@ -1017,7 +1029,7 @@ gdk_event_translate (GdkDisplay *display
 
   if (window)
     {
-      _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
+      _gdk_x11_window_get_offsets (window, &xoffset, &yoffset);
     }
   else
     {
@@ -2225,6 +2237,7 @@ _gdk_events_queue (GdkDisplay *display)
       if (gdk_event_translate (display, event, &xevent, FALSE))
 	{
 	  ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
+	  _gdk_event_rewrite_for_offscreen (display, node, event);
 	}
       else
 	{
Index: gdk/x11/gdkgeometry-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkgeometry-x11.c,v
retrieving revision 1.26
diff -u -p -r1.26 gdkgeometry-x11.c
--- gdk/x11/gdkgeometry-x11.c	21 Jun 2005 04:09:51 -0000	1.26
+++ gdk/x11/gdkgeometry-x11.c	13 Oct 2005 20:59:03 -0000
@@ -192,9 +192,9 @@ static void gdk_window_clip_changed     
 					   GdkRectangle       *new_clip);
 
 void
-_gdk_windowing_window_get_offsets (GdkWindow *window,
-				   gint      *x_offset,
-				   gint      *y_offset)
+_gdk_x11_window_get_offsets (GdkWindow *window,
+			     gint      *x_offset,
+			     gint      *y_offset)
 {
   GdkWindowImplX11 *impl =
     GDK_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (window)->impl);
@@ -375,25 +375,10 @@ gdk_window_guffaw_scroll (GdkWindow    *
     }
 }
 
-/**
- * gdk_window_scroll:
- * @window: a #GdkWindow
- * @dx: Amount to scroll in the X direction
- * @dy: Amount to scroll in the Y direction
- * 
- * Scroll the contents of @window, both pixels and children, by the given
- * amount. @window itself does not move.  Portions of the window that the scroll
- * operation brings in from offscreen areas are invalidated. The invalidated
- * region may be bigger than what would strictly be necessary.  (For X11, a
- * minimum area will be invalidated if the window has no subwindows, or if the
- * edges of the window's parent do not extend beyond the edges of the window. In
- * other cases, a multi-step process is used to scroll the window which may
- * produce temporary visual artifacts and unnecessary invalidations.)
- **/
 void
-gdk_window_scroll (GdkWindow *window,
-		   gint       dx,
-		   gint       dy)
+_gdk_window_x11_scroll (GdkWindow *window,
+			gint       dx,
+			gint       dy)
 {
   gboolean can_guffaw_scroll = FALSE;
   GdkRegion *invalidate_region;
@@ -401,17 +386,9 @@ gdk_window_scroll (GdkWindow *window,
   GdkWindowObject *obj;
   GdkRectangle src_rect, dest_rect;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
-    return;
-  
   obj = GDK_WINDOW_OBJECT (window);
   impl = GDK_WINDOW_IMPL_X11 (obj->impl);  
 
-  if (dx == 0 && dy == 0)
-    return;
-  
   /* Move the current invalid region */
   if (obj->update_area)
     gdk_region_offset (obj->update_area, dx, dy);
@@ -463,26 +440,11 @@ gdk_window_scroll (GdkWindow *window,
     gdk_window_guffaw_scroll (window, dx, dy);
 }
 
-/**
- * gdk_window_move_region:
- * @window: a #GdkWindow
- * @region: The #GdkRegion to move
- * @dx: Amount to move in the X direction
- * @dy: Amount to move in the Y direction
- * 
- * Move the part of @window indicated by @region by @dy pixels in the Y 
- * direction and @dx pixels in the X direction. The portions of @region 
- * that not covered by the new position of @region are invalidated.
- * 
- * Child windows are not moved.
- * 
- * Since: 2.8
- **/
 void
-gdk_window_move_region (GdkWindow *window,
-			GdkRegion *region,
-			gint       dx,
-			gint       dy)
+_gdk_window_x11_move_region (GdkWindow *window,
+			     GdkRegion *region,
+			     gint       dx,
+			     gint       dy)
 {
   GdkWindowImplX11 *impl;
   GdkWindowObject *private;
@@ -494,18 +456,9 @@ gdk_window_move_region (GdkWindow *windo
   GdkRectangle dest_extents;
   GdkGC *gc;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  g_return_if_fail (region != NULL);
-  
-  if (GDK_WINDOW_DESTROYED (window))
-    return;
-  
   private = GDK_WINDOW_OBJECT (window);
   impl = GDK_WINDOW_IMPL_X11 (private->impl);  
 
-  if (dx == 0 && dy == 0)
-    return;
-
   window_clip = gdk_region_rectangle (&impl->position_info.clip_rect);
 
   /* compute source regions */
@@ -884,6 +837,9 @@ gdk_window_premove (GdkWindow          *
   gint d_xoffset, d_yoffset;
   GdkWindowParentPos this_pos;
 
+  if (gdk_window_is_offscreen (window))
+    return;
+  
   obj = (GdkWindowObject *) window;
   impl = GDK_WINDOW_IMPL_X11 (obj->impl);
   
@@ -937,6 +893,9 @@ gdk_window_postmove (GdkWindow          
   gint d_xoffset, d_yoffset;
   GdkWindowParentPos this_pos;
 
+  if (gdk_window_is_offscreen (window))
+    return;
+  
   obj = (GdkWindowObject *) window;
   impl = GDK_WINDOW_IMPL_X11 (obj->impl);
   
Index: gdk/x11/gdkinput.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkinput.c,v
retrieving revision 1.33
diff -u -p -r1.33 gdkinput.c
--- gdk/x11/gdkinput.c	16 Mar 2005 03:17:27 -0000	1.33
+++ gdk/x11/gdkinput.c	13 Oct 2005 20:59:03 -0000
@@ -207,9 +207,9 @@ gdk_device_get_history  (GdkDevice      
   int tmp_n_events = 0;
   int i;
 
-  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+  g_return_val_if_fail (GDK_IS_ONSCREEN_WINDOW (window), FALSE);
 
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) || gdk_window_is_offscreen (window))
     /* Nothing */ ;
   else if (GDK_IS_CORE (device))
     {
@@ -303,11 +303,11 @@ gdk_input_set_extension_events (GdkWindo
   GdkDisplayX11 *display_x11;
 
   g_return_if_fail (window != NULL);
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
 
   window_private = (GdkWindowObject*) window;
   display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) || gdk_window_is_offscreen (window))
     return;
 
   if (mode == GDK_EXTENSION_EVENTS_NONE)
Index: gdk/x11/gdkmain-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkmain-x11.c,v
retrieving revision 1.171
diff -u -p -r1.171 gdkmain-x11.c
--- gdk/x11/gdkmain-x11.c	7 Jul 2005 19:05:33 -0000	1.171
+++ gdk/x11/gdkmain-x11.c	13 Oct 2005 20:59:03 -0000
@@ -191,6 +191,7 @@ gdk_pointer_grab (GdkWindow *	  window,
 {
   gint return_val;
   GdkCursorPrivate *cursor_private;
+  GdkWindow *native;
   guint xevent_mask;
   Window xwindow;
   Window xconfine_to;
@@ -201,11 +202,16 @@ 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);
+
+  native = _gdk_window_get_offscreen_event_window (window);
+
+  if (confine_to != NULL)
+    confine_to = _gdk_window_get_offscreen_event_window (confine_to);
   
   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;
@@ -227,7 +233,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,
@@ -235,14 +241,14 @@ gdk_pointer_grab (GdkWindow *	  window,
 
   if (return_val == GrabSuccess)
     {
-      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,
@@ -257,14 +263,30 @@ gdk_pointer_grab (GdkWindow *	  window,
   
   if (return_val == GrabSuccess)
     {
-      GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
+      GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (native));
+
       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);
+	{
+	  if (gdk_window_is_offscreen (GDK_WINDOW (display_x11->pointer_xgrab_window)))
+	    _gdk_offscreen_window_unset_pointer_grab (GDK_WINDOW (display_x11->pointer_xgrab_window),
+						      TRUE, FALSE, time);
+	  
+	  generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_xgrab_window),
+				      FALSE, display_x11->pointer_xgrab_implicit,
+				      window);
+	}
+	  
 
+      if (gdk_window_is_offscreen (window))
+	_gdk_offscreen_window_set_pointer_grab (GDK_WINDOW (display_x11->pointer_xgrab_window),
+						GDK_WINDOW (display_x11->pointer_xgrab_native_window),
+						window,
+						owner_events, event_mask,
+						time);
+      
       display_x11->pointer_xgrab_window = (GdkWindowObject *)window;
+      display_x11->pointer_xgrab_native_window = (GdkWindowObject *)native;
       display_x11->pointer_xgrab_serial = serial;
       display_x11->pointer_xgrab_owner_events = owner_events;
       display_x11->pointer_xgrab_time = time;
@@ -338,21 +360,24 @@ gdk_keyboard_grab (GdkWindow *	   window
 {
   gint return_val;
   unsigned long serial;
+  GdkWindow *native;
   
   g_return_val_if_fail (window != NULL, 0);
   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
-  
-  serial = NextRequest (GDK_WINDOW_XDISPLAY (window));
 
-  if (!GDK_WINDOW_DESTROYED (window))
+  native = _gdk_window_get_offscreen_event_window (window);
+  
+  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);
@@ -362,13 +387,14 @@ gdk_keyboard_grab (GdkWindow *	   window
 
   if (return_val == GrabSuccess)
     {
-      GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (gdk_drawable_get_display (window));
+      GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (gdk_drawable_get_display (native));
       if (display_x11->keyboard_xgrab_window != NULL &&
 	  display_x11->keyboard_xgrab_window != (GdkWindowObject *)window)
 	generate_grab_broken_event (GDK_WINDOW (display_x11->keyboard_xgrab_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;      
@@ -414,6 +440,18 @@ gdk_keyboard_grab_info_libgtk_only (GdkD
     return FALSE;
 }
 
+void
+_gdk_windowing_grab_broken (GdkDisplay *display)
+{
+  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
+  
+  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_xgrab_check_unmap:
  * @window: a #GdkWindow
@@ -434,13 +472,15 @@ _gdk_xgrab_check_unmap (GdkWindow *windo
       serial >= display_x11->pointer_xgrab_serial)
     {
       GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
-      GdkWindowObject *tmp = display_x11->pointer_xgrab_window;
+      GdkWindowObject *tmp = display_x11->pointer_xgrab_native_window;
 
       while (tmp && tmp != private)
 	tmp = tmp->parent;
 
       if (tmp)
 	{	  
+	  if (gdk_window_is_offscreen (GDK_WINDOW (display_x11->pointer_xgrab_window)))
+	    _gdk_offscreen_window_unset_pointer_grab (GDK_WINDOW (display_x11->pointer_xgrab_window), FALSE, FALSE, GDK_CURRENT_TIME);
 	  generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_xgrab_window),
 				      FALSE, display_x11->pointer_xgrab_implicit, 
 				      NULL);
@@ -479,15 +519,19 @@ _gdk_xgrab_check_destroy (GdkWindow *win
 {
   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (gdk_drawable_get_display (window));
   
-  if ((GdkWindowObject *)window == display_x11->pointer_xgrab_window)
+  if ((GdkWindowObject *)window == display_x11->pointer_xgrab_native_window &&
+      display_x11->pointer_xgrab_window != NULL)
     {
+      if (gdk_window_is_offscreen (GDK_WINDOW (display_x11->pointer_xgrab_window)))
+	_gdk_offscreen_window_unset_pointer_grab (GDK_WINDOW (display_x11->pointer_xgrab_window), FALSE, FALSE, GDK_CURRENT_TIME);
       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 ((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);
@@ -515,6 +559,7 @@ _gdk_xgrab_check_button_event (GdkWindow
       if (!display_x11->pointer_xgrab_window)
 	{
 	  display_x11->pointer_xgrab_window = (GdkWindowObject *)window;
+	  display_x11->pointer_xgrab_native_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;
@@ -526,6 +571,8 @@ _gdk_xgrab_check_button_event (GdkWindow
 	  display_x11->pointer_xgrab_implicit &&
 	  (xevent->xbutton.state & ~(GDK_BUTTON1_MASK << (xevent->xbutton.button - 1))) == 0)
 	{
+	  if (gdk_window_is_offscreen (GDK_WINDOW (display_x11->pointer_xgrab_window)))
+	    _gdk_offscreen_window_unset_pointer_grab (GDK_WINDOW (display_x11->pointer_xgrab_window), FALSE, TRUE, xevent->xbutton.time);
 	  display_x11->pointer_xgrab_window = NULL;
 	}
       break;
@@ -533,6 +580,23 @@ _gdk_xgrab_check_button_event (GdkWindow
       g_assert_not_reached ();
     }
 }
+
+void
+_gdk_windowing_update_implicit_grab (GdkWindow *old_grab, GdkWindow *new_grab, guint event_mask, guint32 time)
+{
+  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (gdk_drawable_get_display (old_grab));
+
+  if (display_x11->pointer_xgrab_window == GDK_WINDOW_OBJECT (old_grab) &&
+      display_x11->pointer_xgrab_implicit)
+    {
+      if (gdk_window_is_offscreen (new_grab))
+	_gdk_offscreen_window_set_pointer_grab (GDK_WINDOW (display_x11->pointer_xgrab_window),
+						GDK_WINDOW (display_x11->pointer_xgrab_native_window),
+						new_grab, FALSE, event_mask, time);
+      display_x11->pointer_xgrab_window = GDK_WINDOW_OBJECT (new_grab);
+    }
+}
+
 
 void
 _gdk_windowing_display_set_sm_client_id (GdkDisplay  *display,
Index: gdk/x11/gdkpixmap-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkpixmap-x11.c,v
retrieving revision 1.65
diff -u -p -r1.65 gdkpixmap-x11.c
--- gdk/x11/gdkpixmap-x11.c	14 May 2005 01:04:15 -0000	1.65
+++ gdk/x11/gdkpixmap-x11.c	13 Oct 2005 20:59:03 -0000
@@ -156,7 +156,7 @@ gdk_pixmap_impl_x11_get_size   (GdkDrawa
 }
 
 GdkPixmap*
-gdk_pixmap_new (GdkDrawable *drawable,
+_gdk_pixmap_new (GdkDrawable *drawable,
 		gint         width,
 		gint         height,
 		gint         depth)
@@ -213,10 +213,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;
@@ -257,13 +257,13 @@ gdk_bitmap_create_from_data (GdkDrawable
 }
 
 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;
Index: gdk/x11/gdkprivate-x11.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkprivate-x11.h,v
retrieving revision 1.41
diff -u -p -r1.41 gdkprivate-x11.h
--- gdk/x11/gdkprivate-x11.h	21 Jul 2005 13:59:22 -0000	1.41
+++ gdk/x11/gdkprivate-x11.h	13 Oct 2005 20:59:03 -0000
@@ -122,6 +122,13 @@ void _gdk_window_move_resize_child (GdkW
                                     gint           y,
                                     gint           width,
                                     gint           height);
+void _gdk_window_x11_scroll        (GdkWindow     *window,
+				    gint           dx,
+				    gint           dy);
+void _gdk_window_x11_move_region   (GdkWindow     *window,
+				    GdkRegion     *region,
+				    gint           dx,
+				    gint           dy);
 void _gdk_window_process_expose    (GdkWindow     *window,
                                     gulong         serial,
                                     GdkRectangle  *area);
@@ -199,5 +206,7 @@ extern gboolean          _gdk_synchroniz
 #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_IS_ONSCREEN_WINDOW(win)   (GDK_IS_WINDOW (win) && !gdk_window_is_offscreen (win))
 
 #endif /* __GDK_PRIVATE_X11_H__ */
Index: gdk/x11/gdkproperty-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkproperty-x11.c,v
retrieving revision 1.46.2.1
diff -u -p -r1.46.2.1 gdkproperty-x11.c
--- gdk/x11/gdkproperty-x11.c	27 Aug 2005 04:23:04 -0000	1.46.2.1
+++ gdk/x11/gdkproperty-x11.c	13 Oct 2005 20:59:03 -0000
@@ -500,7 +500,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_IS_ONSCREEN_WINDOW (window)), FALSE);
 
   if (!window)
     {
@@ -509,6 +509,8 @@ gdk_property_get (GdkWindow   *window,
       
       GDK_NOTE (MULTIHEAD, g_message ("gdk_property_get(): window is NULL\n"));
     }
+  else if (gdk_window_is_offscreen (window))
+    return FALSE;
 
   if (GDK_WINDOW_DESTROYED (window))
     return FALSE;
@@ -634,7 +636,7 @@ gdk_property_change (GdkWindow    *windo
   Atom xproperty;
   Atom xtype;
 
-  g_return_if_fail (!window || GDK_IS_WINDOW (window));
+  g_return_if_fail (!window || (GDK_IS_ONSCREEN_WINDOW (window)));
 
   if (!window)
     {
@@ -645,7 +647,8 @@ gdk_property_change (GdkWindow    *windo
       
       GDK_NOTE (MULTIHEAD, g_message ("gdk_property_change(): window is NULL\n"));
     }
-
+  else if (gdk_window_is_offscreen (window))
+    return;
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
@@ -685,7 +688,7 @@ void
 gdk_property_delete (GdkWindow *window,
 		     GdkAtom    property)
 {
-  g_return_if_fail (!window || GDK_IS_WINDOW (window));
+  g_return_if_fail (!window || (GDK_IS_ONSCREEN_WINDOW (window)));
 
   if (!window)
     {
@@ -695,6 +698,8 @@ gdk_property_delete (GdkWindow *window,
       GDK_NOTE (MULTIHEAD, 
 		g_message ("gdk_property_delete(): window is NULL\n"));
     }
+  else if (gdk_window_is_offscreen (window))
+    return;
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
Index: gdk/x11/gdkselection-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkselection-x11.c,v
retrieving revision 1.45
diff -u -p -r1.45 gdkselection-x11.c
--- gdk/x11/gdkselection-x11.c	16 Mar 2005 03:17:27 -0000	1.45
+++ gdk/x11/gdkselection-x11.c	13 Oct 2005 20:59:03 -0000
@@ -141,7 +141,7 @@ gdk_selection_owner_set_for_display (Gdk
 
   if (owner) 
     {
-      if (GDK_WINDOW_DESTROYED (owner))
+      if (GDK_WINDOW_DESTROYED (owner) || gdk_window_is_offscreen (owner))
 	return FALSE;
       
       xdisplay = GDK_WINDOW_XDISPLAY (owner);
@@ -231,7 +231,7 @@ gdk_selection_convert (GdkWindow *reques
 
   g_return_if_fail (selection != GDK_NONE);
   
-  if (GDK_WINDOW_DESTROYED (requestor))
+  if (GDK_WINDOW_DESTROYED (requestor) || gdk_window_is_offscreen (requestor))
     return;
 
   display = GDK_WINDOW_DISPLAY (requestor);
@@ -278,11 +278,11 @@ gdk_selection_property_get (GdkWindow  *
   GdkDisplay *display; 
 
   g_return_val_if_fail (requestor != NULL, 0);
-  g_return_val_if_fail (GDK_IS_WINDOW (requestor), 0);
+  g_return_val_if_fail (GDK_IS_ONSCREEN_WINDOW (requestor), 0);
   
   display = GDK_WINDOW_DISPLAY (requestor);
 
-  if (GDK_WINDOW_DESTROYED (requestor))
+  if (GDK_WINDOW_DESTROYED (requestor) || gdk_window_is_offscreen (requestor))
     goto err;
 
   t = NULL;
Index: gdk/x11/gdkwindow-x11.c
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkwindow-x11.c,v
retrieving revision 1.248.2.1
diff -u -p -r1.248.2.1 gdkwindow-x11.c
--- gdk/x11/gdkwindow-x11.c	26 Sep 2005 20:28:35 -0000	1.248.2.1
+++ gdk/x11/gdkwindow-x11.c	13 Oct 2005 20:59:03 -0000
@@ -35,6 +35,7 @@
 #include "gdk.h"
 
 #include "gdkwindow.h"
+#include "gdkwindowimpl.h"
 #include "gdkasync.h"
 #include "gdkinputprivate.h"
 #include "gdkdisplay-x11.h"
@@ -100,6 +101,7 @@ static GdkRegion*  gdk_window_impl_x11_g
 static void gdk_window_impl_x11_init       (GdkWindowImplX11      *window);
 static void gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass);
 static void gdk_window_impl_x11_finalize   (GObject            *object);
+static void gdk_window_impl_iface_init     (GdkWindowImplIface *iface);
 
 static gpointer parent_class = NULL;
 
@@ -134,10 +136,15 @@ gdk_window_impl_x11_get_type (void)
         0,              /* n_preallocs */
         (GInstanceInitFunc) gdk_window_impl_x11_init,
       };
+      static const GInterfaceInfo interface_info =
+      {
+	(GInterfaceInitFunc) gdk_window_impl_iface_init
+      };					
       
       object_type = g_type_register_static (GDK_TYPE_DRAWABLE_IMPL_X11,
                                             "GdkWindowImplX11",
                                             &object_info, 0);
+      g_type_add_interface_static (object_type, GDK_TYPE_WINDOW_IMPL, &interface_info);
     }
   
   return object_type;
@@ -302,7 +309,8 @@ _gdk_x11_window_tmp_unset_bg (GdkWindow 
 
   if (private->input_only || private->destroyed ||
       (private->window_type != GDK_WINDOW_ROOT &&
-       !GDK_WINDOW_IS_MAPPED (window)))
+       !GDK_WINDOW_IS_MAPPED (window)) ||
+      gdk_window_is_offscreen (window))
     {
       return;
     }
@@ -334,7 +342,8 @@ _gdk_x11_window_tmp_reset_bg (GdkWindow 
 
   if (private->input_only || private->destroyed ||
       (private->window_type != GDK_WINDOW_ROOT &&
-       !GDK_WINDOW_IS_MAPPED (window)))
+       !GDK_WINDOW_IS_MAPPED (window)) ||
+      gdk_window_is_offscreen (window))
     {
       return;
     }
@@ -428,6 +437,20 @@ gdk_window_impl_x11_get_size (GdkDrawabl
     *height = GDK_WINDOW_IMPL_X11 (drawable)->height;
 }
 
+static void
+gdk_window_x11_get_visible_rect (GdkWindow *window, GdkRectangle *rect)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
+
+  rect->x = 0;
+  rect->y = 0;
+  rect->width = impl->width;
+  rect->height = impl->height;
+
+  gdk_rectangle_intersect (rect, &impl->position_info.clip_rect, rect);
+}
+
 static GdkRegion*
 gdk_window_impl_x11_get_visible_region (GdkDrawable *drawable)
 {
@@ -461,6 +484,7 @@ _gdk_windowing_window_init (GdkScreen * 
 
   screen_x11->root_window = g_object_new (GDK_TYPE_WINDOW, NULL);
   private = (GdkWindowObject *)screen_x11->root_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);
   
@@ -647,24 +671,10 @@ setup_toplevel_window (GdkWindow *window
   ensure_sync_counter (window);
 }
 
-/**
- * gdk_window_new:
- * @parent: a #GdkWindow, or %NULL to create the window as a child of
- *   the default root window for the default display.
- * @attributes: attributes of the new window
- * @attributes_mask: mask indicating which fields in @attributes are valid
- * 
- * Creates a new #GdkWindow using the attributes from
- * @attributes. See #GdkWindowAttr and #GdkWindowAttributesType for
- * more details.  Note: to use this on displays other than the default
- * display, @parent must be specified.
- * 
- * Return value: the new #GdkWindow
- **/
 GdkWindow*
-gdk_window_new (GdkWindow     *parent,
-		GdkWindowAttr *attributes,
-		gint           attributes_mask)
+_gdk_window_new (GdkWindow     *parent,
+		 GdkWindowAttr *attributes,
+		 gint           attributes_mask)
 {
   GdkWindow *window;
   GdkWindowObject *private;
@@ -712,6 +722,7 @@ gdk_window_new (GdkWindow     *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);
   draw_impl->wrapper = GDK_DRAWABLE (window);
@@ -1013,6 +1024,7 @@ gdk_window_foreign_new_for_display (GdkD
   
   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);
   draw_impl->wrapper = GDK_DRAWABLE (window);
@@ -1199,7 +1211,7 @@ gdk_window_destroy_notify (GdkWindow *wi
 {
   GdkWindowImplX11 *window_impl;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
   
   window_impl = GDK_WINDOW_IMPL_X11 (((GdkWindowObject *)window)->impl);
 
@@ -1399,8 +1411,8 @@ set_initial_hints (GdkWindow *window)
 }
 
 static void
-show_window_internal (GdkWindow *window,
-                      gboolean   raise)
+gdk_window_x11_show (GdkWindow *window,
+		     gboolean   raise)
 {
   GdkWindowObject *private;
   GdkDisplay *display;
@@ -1463,50 +1475,6 @@ show_window_internal (GdkWindow *window,
     }
 }
 
-/**
- * gdk_window_show_unraised:
- * @window: a #GdkWindow
- *
- * Shows a #GdkWindow onscreen, but does not modify its stacking
- * order. In contrast, gdk_window_show() will raise the window
- * to the top of the window stack.
- *
- * On the X11 platform, in Xlib terms, this function calls
- * XMapWindow() (it also updates some internal GDK state, which means
- * that you can't really use XMapWindow() directly on a GDK window).
- * 
- **/
-void
-gdk_window_show_unraised (GdkWindow *window)
-{
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  show_window_internal (window, FALSE);
-}
-
-/**
- * gdk_window_show:
- * @window: a #GdkWindow
- *
- * Like gdk_window_show_unraised(), but also raises the window to the
- * top of the window stack (moves the window to the front of the
- * Z-order).
- *
- * This function maps a window so it's visible onscreen. Its opposite
- * is gdk_window_hide().
- *
- * When implementing a #GtkWidget, you should call this function on the widget's
- * #GdkWindow as part of the "map" method.
- * 
- **/
-void
-gdk_window_show (GdkWindow *window)
-{
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  show_window_internal (window, TRUE);
-}
-
 static void
 pre_unmap (GdkWindow *window)
 {
@@ -1556,18 +1524,8 @@ post_unmap (GdkWindow *window)
     }
 }
 
-/**
- * gdk_window_hide:
- * @window: a #GdkWindow
- *
- * For toplevel windows, withdraws them, so they will no longer be
- * known to the window manager; for all windows, unmaps them, so
- * they won't be displayed. Normally done automatically as
- * part of gtk_widget_hide().
- * 
- **/
-void
-gdk_window_hide (GdkWindow *window)
+static void
+gdk_window_x11_hide (GdkWindow *window)
 {
   GdkWindowObject *private;
   
@@ -1618,17 +1576,8 @@ gdk_window_hide (GdkWindow *window)
     }
 }
 
-/**
- * gdk_window_withdraw:
- * @window: a toplevel #GdkWindow
- * 
- * Withdraws a window (unmaps it and asks the window manager to forget about it).
- * This function is not really useful as gdk_window_hide() automatically
- * withdraws toplevel windows before hiding them.
- * 
- **/
-void
-gdk_window_withdraw (GdkWindow *window)
+static void
+gdk_window_x11_withdraw (GdkWindow *window)
 {
   GdkWindowObject *private;
   
@@ -1653,79 +1602,42 @@ gdk_window_withdraw (GdkWindow *window)
     }
 }
 
-/**
- * gdk_window_move:
- * @window: a #GdkWindow
- * @x: X coordinate relative to window's parent
- * @y: Y coordinate relative to window's parent
- *
- * Repositions a window relative to its parent window.
- * For toplevel windows, window managers may ignore or modify the move;
- * you should probably use gtk_window_move() on a #GtkWindow widget
- * anyway, instead of using GDK functions. For child windows,
- * the move will reliably succeed.
- *
- * If you're also planning to resize the window, use gdk_window_move_resize()
- * to both move and resize simultaneously, for a nicer visual effect.
- **/
-void
-gdk_window_move (GdkWindow *window,
-		 gint       x,
-		 gint       y)
+static void
+gdk_window_x11_move (GdkWindow *window,
+		     gint       x,
+		     gint       y)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
   GdkWindowImplX11 *impl;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
   impl = GDK_WINDOW_IMPL_X11 (private->impl);
 	  
-  if (!GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_TYPE (private) == GDK_WINDOW_CHILD)
     {
-      if (GDK_WINDOW_TYPE (private) == GDK_WINDOW_CHILD)
-	{
-	  _gdk_window_move_resize_child (window, x, y,
-					 impl->width, impl->height);
-	}
-      else
+      _gdk_window_move_resize_child (window, x, y,
+				     impl->width, impl->height);
+    }
+  else
+    {
+      XMoveWindow (GDK_WINDOW_XDISPLAY (window),
+		   GDK_WINDOW_XID (window),
+		   x, y);
+      
+      if (impl->override_redirect)
 	{
-	  XMoveWindow (GDK_WINDOW_XDISPLAY (window),
-		       GDK_WINDOW_XID (window),
-		       x, y);
-
-	  if (impl->override_redirect)
-	    {
-	      private->x = x;
-	      private->y = y;
-	    }
+	  private->x = x;
+	  private->y = y;
 	}
     }
 }
 
-/**
- * gdk_window_resize:
- * @window: a #GdkWindow
- * @width: new width of the window
- * @height: new height of the window
- *
- * Resizes @window; for toplevel windows, asks the window manager to resize
- * the window. The window manager may not allow the resize. When using GTK+,
- * use gtk_window_resize() instead of this low-level GDK function.
- *
- * Windows may not be resized below 1x1.
- * 
- * If you're also planning to move the window, use gdk_window_move_resize()
- * to both move and resize simultaneously, for a nicer visual effect.
- **/
-void
-gdk_window_resize (GdkWindow *window,
-		   gint       width,
-		   gint       height)
+static void
+gdk_window_x11_resize (GdkWindow *window,
+		       gint       width,
+		       gint       height)
 {
   GdkWindowObject *private;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
   if (width < 1)
     width = 1;
   if (height < 1)
@@ -1733,63 +1645,45 @@ gdk_window_resize (GdkWindow *window,
 
   private = (GdkWindowObject*) window;
   
-  if (!GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_TYPE (private) == GDK_WINDOW_CHILD)
+    {
+      _gdk_window_move_resize_child (window, private->x, private->y,
+				     width, height);
+      _gdk_x11_drawable_update_size (private->impl);
+    }
+  else
     {
-      if (GDK_WINDOW_TYPE (private) == GDK_WINDOW_CHILD)
+      GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
+      
+      XResizeWindow (GDK_WINDOW_XDISPLAY (window),
+		     GDK_WINDOW_XID (window),
+		     width, height);
+      
+      if (impl->override_redirect)
 	{
-	  _gdk_window_move_resize_child (window, private->x, private->y,
-					 width, height);
+	  impl->width = width;
+	  impl->height = height;
 	  _gdk_x11_drawable_update_size (private->impl);
 	}
       else
 	{
-	  GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
-
-	  XResizeWindow (GDK_WINDOW_XDISPLAY (window),
-			 GDK_WINDOW_XID (window),
-			 width, height);
-
-	  if (impl->override_redirect)
-	    {
-	      impl->width = width;
-	      impl->height = height;
-	      _gdk_x11_drawable_update_size (private->impl);
-	    }
-	  else
-	    {
-	      if (width != impl->width || height != impl->height)
-		private->resize_count += 1;
-	    }
+	  if (width != impl->width || height != impl->height)
+	    private->resize_count += 1;
 	}
-
-      _gdk_x11_drawable_update_size (private->impl);
     }
+  
+  _gdk_x11_drawable_update_size (private->impl);
 }
 
-/**
- * gdk_window_move_resize:
- * @window: a #GdkWindow
- * @x: new X position relative to window's parent
- * @y: new Y position relative to window's parent
- * @width: new width
- * @height: new height
- *
- * Equivalent to calling gdk_window_move() and gdk_window_resize(),
- * except that both operations are performed at once, avoiding strange
- * visual effects. (i.e. the user may be able to see the window first
- * move, then resize, if you don't use gdk_window_move_resize().)
- **/
-void
-gdk_window_move_resize (GdkWindow *window,
-			gint       x,
-			gint       y,
-			gint       width,
-			gint       height)
+static void
+gdk_window_x11_move_resize (GdkWindow *window,
+			    gint       x,
+			    gint       y,
+			    gint       width,
+			    gint       height)
 {
   GdkWindowObject *private;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
   if (width < 1)
     width = 1;
   if (height < 1)
@@ -1797,54 +1691,40 @@ gdk_window_move_resize (GdkWindow *windo
   
   private = (GdkWindowObject*) window;
 
-  if (!GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_TYPE (private) == GDK_WINDOW_CHILD)
+    {
+      _gdk_window_move_resize_child (window, x, y, width, height);
+      _gdk_x11_drawable_update_size (private->impl);
+    }
+  else
     {
-      if (GDK_WINDOW_TYPE (private) == GDK_WINDOW_CHILD)
+      GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
+      
+      XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
+			 GDK_WINDOW_XID (window),
+			 x, y, width, height);
+      if (impl->override_redirect)
 	{
-	  _gdk_window_move_resize_child (window, x, y, width, height);
+	  private->x = x;
+	  private->y = y;
+	  impl->width = width;
+	  impl->height = height;
+	  
 	  _gdk_x11_drawable_update_size (private->impl);
 	}
       else
 	{
-	  GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
-
-	  XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
-			     GDK_WINDOW_XID (window),
-			     x, y, width, height);
-	  if (impl->override_redirect)
-	    {
-	      private->x = x;
-	      private->y = y;
-	      impl->width = width;
-	      impl->height = height;
-
-	      _gdk_x11_drawable_update_size (private->impl);
-	    }
-	  else
-	    {
-	      if (width != impl->width || height != impl->height)
-		private->resize_count += 1;
-	    }
+	  if (width != impl->width || height != impl->height)
+	    private->resize_count += 1;
 	}
     }
 }
 
-/**
- * gdk_window_reparent:
- * @window: a #GdkWindow
- * @new_parent: new parent to move @window into
- * @x: X location inside the new parent
- * @y: Y location inside the new parent
- *
- * Reparents @window into the given @new_parent. The window being
- * reparented will be unmapped as a side effect.
- * 
- **/
-void
-gdk_window_reparent (GdkWindow *window,
-		     GdkWindow *new_parent,
-		     gint       x,
-		     gint       y)
+static gboolean
+gdk_window_x11_reparent (GdkWindow *window,
+			 GdkWindow *new_parent,
+			 gint       x,
+			 gint       y)
 {
   GdkDisplay *display;
   GdkWindowObject *window_private;
@@ -1852,15 +1732,11 @@ gdk_window_reparent (GdkWindow *window,
   GdkWindowObject *old_parent_private;
   GdkWindowImplX11 *impl;
   gboolean was_toplevel;
-  
-  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)))
+  if (gdk_window_is_offscreen (new_parent))
     {
-      return;
+      g_warning ("Can't reparent X11 window to offscreen parent");
+      return FALSE;
     }
   
   if (!new_parent)
@@ -1942,82 +1818,35 @@ gdk_window_reparent (GdkWindow *window,
   
   parent_private->children = g_list_prepend (parent_private->children, window);
   _gdk_window_init_position (GDK_WINDOW (window_private));
-}
 
-void
-_gdk_windowing_window_clear_area (GdkWindow *window,
-				  gint       x,
-				  gint       y,
-				  gint       width,
-				  gint       height)
-{
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  if (!GDK_WINDOW_DESTROYED (window))
-    XClearArea (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
-		x, y, width, height, False);
+  return FALSE;
 }
 
-void
-_gdk_windowing_window_clear_area_e (GdkWindow *window,
-				    gint       x,
-				    gint       y,
-				    gint       width,
-				    gint       height)
+static void
+gdk_window_x11_clear_area (GdkWindow *window,
+			   gint       x,
+			   gint       y,
+			   gint       width,
+			   gint       height,
+			   gboolean   send_expose)
 {
   g_return_if_fail (GDK_IS_WINDOW (window));
   
   if (!GDK_WINDOW_DESTROYED (window))
     XClearArea (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
-		x, y, width, height, True);
+		x, y, width, height, send_expose);
 }
 
-
-/**
- * gdk_window_raise:
- * @window: a #GdkWindow
- * 
- * Raises @window to the top of the Z-order (stacking order), so that
- * other windows with the same parent window appear below @window.
- * This is true whether or not the windows are visible.
- *
- * If @window is a toplevel, the window manager may choose to deny the
- * request to move the window in the Z-order, gdk_window_raise() only
- * requests the restack, does not guarantee it.
- * 
- **/
-void
-gdk_window_raise (GdkWindow *window)
+static void
+gdk_window_x11_raise (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  if (!GDK_WINDOW_DESTROYED (window))
-    XRaiseWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
+  XRaiseWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
 }
 
-/**
- * gdk_window_lower:
- * @window: a #GdkWindow
- * 
- * Lowers @window to the bottom of the Z-order (stacking order), so that
- * other windows with the same parent window appear above @window.
- * This is true whether or not the other windows are visible.
- *
- * If @window is a toplevel, the window manager may choose to deny the
- * request to move the window in the Z-order, gdk_window_lower() only
- * requests the restack, does not guarantee it.
- *
- * Note that gdk_window_show() raises the window again, so don't call this
- * function before gdk_window_show(). (Try gdk_window_show_unraised().)
- * 
- **/
-void
-gdk_window_lower (GdkWindow *window)
+static void
+gdk_window_x11_lower (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  if (!GDK_WINDOW_DESTROYED (window))
-    XLowerWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
+  XLowerWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
 }
 
 /**
@@ -2104,13 +1933,13 @@ gdk_x11_window_move_to_current_desktop (
  **/
 void
 gdk_window_focus (GdkWindow *window,
-                  guint32    timestamp)
+		  guint32    timestamp)
 {
   GdkDisplay *display;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
 
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) || gdk_window_is_offscreen (window))
     return;
 
   display = GDK_WINDOW_DISPLAY (window);
@@ -2181,9 +2010,9 @@ gdk_window_set_hints (GdkWindow *window,
 {
   XSizeHints size_hints;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
   
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) || gdk_window_is_offscreen (window))
     return;
   
   size_hints.flags = 0;
@@ -2236,9 +2065,9 @@ gdk_window_set_type_hint (GdkWindow     
   GdkDisplay *display;
   Atom atom;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
   
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) || gdk_window_is_offscreen (window))
     return;
 
   display = gdk_drawable_get_display (window);
@@ -2330,9 +2159,9 @@ gdk_window_set_modal_hint (GdkWindow *wi
 {
   GdkWindowObject *private;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
   
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) || gdk_window_is_offscreen (window))
     return;
 
   private = (GdkWindowObject*) window;
@@ -2365,7 +2194,7 @@ gdk_window_set_skip_taskbar_hint (GdkWin
 {
   GdkToplevelX11 *toplevel;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
   
   if (GDK_WINDOW_DESTROYED (window))
@@ -2402,7 +2231,7 @@ gdk_window_set_skip_pager_hint (GdkWindo
 {
   GdkToplevelX11 *toplevel;
     
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
   
   if (GDK_WINDOW_DESTROYED (window))
@@ -2433,7 +2262,7 @@ gdk_window_set_urgency_hint (GdkWindow *
 {
   GdkToplevelX11 *toplevel;
     
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
   
   if (GDK_WINDOW_DESTROYED (window))
@@ -2481,7 +2310,7 @@ gdk_window_set_geometry_hints (GdkWindow
 {
   XSizeHints size_hints;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
   
   if (GDK_WINDOW_DESTROYED (window))
     return;
@@ -2739,7 +2568,7 @@ gdk_window_set_title (GdkWindow   *windo
   Display *xdisplay;
   Window xwindow;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
   g_return_if_fail (title != NULL);
 
   if (GDK_WINDOW_DESTROYED (window))
@@ -2789,7 +2618,7 @@ gdk_window_set_role (GdkWindow   *window
 {
   GdkDisplay *display;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
 
   display = gdk_drawable_get_display (window);
 
@@ -2826,7 +2655,7 @@ gdk_window_set_transient_for (GdkWindow 
   GdkWindowObject *private;
   GdkWindowObject *parent_private;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
   
   private = (GdkWindowObject*) window;
   parent_private = (GdkWindowObject*) parent;
@@ -2837,25 +2666,9 @@ gdk_window_set_transient_for (GdkWindow 
 			  GDK_WINDOW_XID (parent));
 }
 
-/**
- * gdk_window_set_background:
- * @window: a #GdkWindow
- * @color: an allocated #GdkColor
- *
- * Sets the background color of @window. (However, when using GTK+,
- * set the background of a widget with gtk_widget_modify_bg() - if
- * you're an application - or gtk_style_set_background() - if you're
- * implementing a custom widget.)
- *
- * The @color must be allocated; gdk_rgb_find_color() is the best way
- * to allocate a color.
- *
- * See also gdk_window_set_back_pixmap().
- * 
- **/
-void
-gdk_window_set_background (GdkWindow      *window,
-			   const GdkColor *color)
+static void
+gdk_window_x11_set_background (GdkWindow      *window,
+			       const GdkColor *color)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
   GdkColormap *colormap = gdk_drawable_get_colormap (window);
@@ -2877,34 +2690,10 @@ gdk_window_set_background (GdkWindow    
   private->bg_pixmap = NULL;
 }
 
-/**
- * gdk_window_set_back_pixmap:
- * @window: a #GdkWindow
- * @pixmap: a #GdkPixmap, or %NULL
- * @parent_relative: whether the tiling origin is at the origin of @window's parent
- *
- * Sets the background pixmap of @window. May also be used to set a background of
- * "None" on @window, by setting a background pixmap of %NULL.
- * A background pixmap will be tiled, positioning the first tile at the origin of
- * @window, or if @parent_relative is %TRUE, the tiling will be done based on the
- * origin of the parent window (useful to align tiles in a parent with tiles
- * in a child).
- *
- * A background pixmap of %NULL means that the window will have no
- * background.  A window with no background will never have its
- * background filled by the windowing system, instead the window will
- * contain whatever pixels were already in the corresponding area of
- * the display.
- *
- * The windowing system will normally fill a window with its background
- * when the window is obscured then exposed, and when you call
- * gdk_window_clear().
- * 
- **/
-void
-gdk_window_set_back_pixmap (GdkWindow *window,
-			    GdkPixmap *pixmap,
-			    gboolean   parent_relative)
+static void
+gdk_window_x11_set_back_pixmap (GdkWindow *window,
+				GdkPixmap *pixmap,
+				gboolean   parent_relative)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
   Pixmap xpixmap;
@@ -2949,22 +2738,9 @@ gdk_window_set_back_pixmap (GdkWindow *w
 				GDK_WINDOW_XID (window), xpixmap);
 }
 
-/**
- * gdk_window_set_cursor:
- * @window: a #GdkWindow
- * @cursor: a cursor
- *
- * Sets the mouse pointer for a #GdkWindow. Use gdk_cursor_new() or
- * gdk_cursor_new_from_pixmap() to create the cursor.
- * To make the cursor invisible, use gdk_cursor_new_from_pixmap() to create
- * a cursor with no pixels in it. Passing %NULL for the @cursor argument
- * to gdk_window_set_cursor() means that @window will use the cursor of
- * its parent window. Most windows should use this default.
- * 
- **/
-void
-gdk_window_set_cursor (GdkWindow *window,
-		       GdkCursor *cursor)
+static void
+gdk_window_x11_set_cursor (GdkWindow *window,
+			   GdkCursor *cursor)
 {
   GdkWindowObject *private;
   GdkWindowImplX11 *impl;
@@ -3016,45 +2792,13 @@ _gdk_x11_window_get_cursor (GdkWindow *w
   return impl->cursor;
 }
 
-/**
- * gdk_window_get_geometry:
- * @window: a #GdkWindow
- * @x: return location for X coordinate of window (relative to its parent)
- * @y: return location for Y coordinate of window (relative to its parent)
- * @width: return location for width of window
- * @height: return location for height of window
- * @depth: return location for bit depth of window
- *
- * Any of the return location arguments to this function may be %NULL,
- * if you aren't interested in getting the value of that field.
- *
- * The X and Y coordinates returned are relative to the parent window
- * of @window, which for toplevels usually means relative to the
- * window decorations (titlebar, etc.) rather than relative to the
- * root window (screen-size background window).
- *
- * On the X11 platform, the geometry is obtained from the X server,
- * so reflects the latest position of @window; this may be out-of-sync
- * with the position of @window delivered in the most-recently-processed
- * #GdkEventConfigure. gdk_window_get_position() in contrast gets the
- * position from the most recent configure event.
- * 
- * <note>
- * If @window is not a toplevel, it is <emphasis>much</emphasis> better 
- * to call gdk_window_get_position() and gdk_drawable_get_size() instead, 
- * because it avoids the roundtrip to the X server and because 
- * gdk_drawable_get_size() supports the full 32-bit coordinate space,
- * whereas gdk_window_get_geometry() is restricted to the 16-bit
- * coordinates of X11.
- *</note>
- **/
-void
-gdk_window_get_geometry (GdkWindow *window,
-			 gint      *x,
-			 gint      *y,
-			 gint      *width,
-			 gint      *height,
-			 gint      *depth)
+static void
+gdk_window_x11_get_geometry (GdkWindow *window,
+			     gint      *x,
+			     gint      *y,
+			     gint      *width,
+			     gint      *height,
+			     gint      *depth)
 {
   Window root;
   gint tx;
@@ -3066,13 +2810,6 @@ gdk_window_get_geometry (GdkWindow *wind
   
   g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
   
-  if (!window)
-    {
-      GDK_NOTE (MULTIHEAD,
-		g_message ("gdk_window_get_geometry(): Window needs to be non-NULL to be multi head safe"));
-      window = gdk_screen_get_root_window ((gdk_screen_get_default ()));
-    }
-
   if (!GDK_WINDOW_DESTROYED (window))
     {
       XGetGeometry (GDK_WINDOW_XDISPLAY (window),
@@ -3092,23 +2829,10 @@ gdk_window_get_geometry (GdkWindow *wind
     }
 }
 
-/**
- * gdk_window_get_origin:
- * @window: a #GdkWindow
- * @x: return location for X coordinate
- * @y: return location for Y coordinate
- * 
- * Obtains the position of a window in root window coordinates.
- * (Compare with gdk_window_get_position() and
- * gdk_window_get_geometry() which return the position of a window
- * relative to its parent window.)
- * 
- * Return value: not meaningful, ignore
- **/
-gint
-gdk_window_get_origin (GdkWindow *window,
-		       gint      *x,
-		       gint      *y)
+static gint
+gdk_window_x11_get_origin (GdkWindow *window,
+			   gint      *x,
+			   gint      *y)
 {
   gint return_val;
   Window child;
@@ -3166,7 +2890,7 @@ gdk_window_get_deskrelative_origin (GdkW
   gulong number_return, bytes_after_return;
   guchar *data_return;
   
-  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+  g_return_val_if_fail (GDK_IS_ONSCREEN_WINDOW (window), FALSE);
   
   if (!GDK_WINDOW_DESTROYED (window))
     {
@@ -3232,7 +2956,7 @@ gdk_window_get_root_origin (GdkWindow *w
 {
   GdkRectangle rect;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
 
   gdk_window_get_frame_extents (window, &rect);
 
@@ -3276,7 +3000,7 @@ gdk_window_get_frame_extents (GdkWindow 
   guint ww, wh, wb, wd;
   gint wx, wy;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
   g_return_if_fail (rect != NULL);
   
   private = (GdkWindowObject*) window;
@@ -3419,7 +3143,7 @@ _gdk_windowing_window_get_pointer (GdkDi
 
   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
   
-  _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
+  _gdk_x11_window_get_offsets (window, &xoffset, &yoffset);
 
   return_val = NULL;
   if (!GDK_WINDOW_DESTROYED (window) &&
@@ -3525,71 +3249,40 @@ _gdk_windowing_window_at_pointer (GdkDis
   return window;
 }
 
-/**
- * gdk_window_get_events:
- * @window: a #GdkWindow
- * 
- * Gets the event mask for @window. See gdk_window_set_events().
- * 
- * Return value: event mask for @window
- **/
-GdkEventMask  
-gdk_window_get_events (GdkWindow *window)
+static GdkEventMask  
+gdk_window_x11_get_events (GdkWindow *window)
 {
   XWindowAttributes attrs;
   GdkEventMask event_mask;
-  
-  g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
 
-  if (GDK_WINDOW_DESTROYED (window))
-    return 0;
-  else
-    {
-      XGetWindowAttributes (GDK_WINDOW_XDISPLAY (window),
-			    GDK_WINDOW_XID (window), 
-			    &attrs);
-      
-      event_mask = x_event_mask_to_gdk_event_mask (attrs.your_event_mask);
-      GDK_WINDOW_OBJECT (window)->event_mask = event_mask;
+  XGetWindowAttributes (GDK_WINDOW_XDISPLAY (window),
+			GDK_WINDOW_XID (window), 
+			&attrs);
   
-      return event_mask;
-    }
+  event_mask = x_event_mask_to_gdk_event_mask (attrs.your_event_mask);
+  GDK_WINDOW_OBJECT (window)->event_mask = event_mask;
+  
+  return event_mask;
 }
 
-/**
- * gdk_window_set_events:
- * @window: a #GdkWindow
- * @event_mask: event mask for @window
- *
- * The event mask for a window determines which events will be reported
- * for that window. For example, an event mask including #GDK_BUTTON_PRESS_MASK
- * means the window should report button press events. The event mask
- * is the bitwise OR of values from the #GdkEventMask enumeration.
- * 
- **/
-void          
-gdk_window_set_events (GdkWindow       *window,
-		       GdkEventMask     event_mask)
+static void          
+gdk_window_x11_set_events (GdkWindow       *window,
+			   GdkEventMask     event_mask)
 {
   long xevent_mask;
   int i;
   
-  g_return_if_fail (GDK_IS_WINDOW (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++)
     {
-      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)))
-	    xevent_mask |= _gdk_event_mask_table[i];
-	}
-      
-      XSelectInput (GDK_WINDOW_XDISPLAY (window),
-		    GDK_WINDOW_XID (window),
-		    xevent_mask);
+      if (event_mask & (1 << (i + 1)))
+	xevent_mask |= _gdk_event_mask_table[i];
     }
+  
+  XSelectInput (GDK_WINDOW_XDISPLAY (window),
+		GDK_WINDOW_XID (window),
+		xevent_mask);
 }
 
 static void
@@ -3656,34 +3349,11 @@ gdk_window_have_shape_ext (GdkDisplay *d
  * If not available, shaped windows will look
  * ugly, but programs still work.    Stefan Wille
  */
-/**
- * gdk_window_shape_combine_mask:
- * @window: a #GdkWindow
- * @mask: shape mask
- * @x: X position of shape mask with respect to @window
- * @y: Y position of shape mask with respect to @window
- *
- * Applies a shape mask to @window. Pixels in @window corresponding to
- * set bits in the @mask will be visible; pixels in @window
- * corresponding to unset bits in the @mask will be transparent. This
- * gives a non-rectangular window.
- *
- * If @mask is %NULL, the shape mask will be unset, and the @x/@y
- * parameters are not used.
- *
- * On the X11 platform, this uses an X server extension which is
- * widely available on most common platforms, but not available on
- * very old X servers, and occasionally the implementation will be
- * buggy. On servers without the shape extension, this function
- * will do nothing.
- *
- * This function works on both toplevel and child windows.
- * 
- **/
-void
-gdk_window_shape_combine_mask (GdkWindow *window,
-			       GdkBitmap *mask,
-			       gint x, gint y)
+
+static void
+gdk_window_x11_shape_combine_mask (GdkWindow *window,
+				   GdkBitmap *mask,
+				   gint x, gint y)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
   Pixmap pixmap;
@@ -3695,7 +3365,7 @@ gdk_window_shape_combine_mask (GdkWindow
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
-  _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
+  _gdk_x11_window_get_offsets (window, &xoffset, &yoffset);
 
   if (xoffset != 0 || yoffset != 0)
     {
@@ -3730,36 +3400,12 @@ gdk_window_shape_combine_mask (GdkWindow
 #endif /* HAVE_SHAPE_EXT */
 }
 
-/**
- * gdk_window_shape_combine_region:
- * @window: a #GdkWindow
- * @shape_region: region of window to be non-transparent
- * @offset_x: X position of @shape_region in @window coordinates
- * @offset_y: Y position of @shape_region in @window coordinates
- *
- * Makes pixels in @window outside @shape_region be transparent,
- * so that the window may be nonrectangular. See also
- * gdk_window_shape_combine_mask() to use a bitmap as the mask.
- *
- * If @shape_region is %NULL, the shape will be unset, so the whole
- * window will be opaque again. @offset_x and @offset_y are ignored
- * if @shape_region is %NULL.
- * 
- * On the X11 platform, this uses an X server extension which is
- * widely available on most common platforms, but not available on
- * very old X servers, and occasionally the implementation will be
- * buggy. On servers without the shape extension, this function
- * will do nothing.
- *
- * This function works on both toplevel and child windows.
- * 
- **/
-void
-gdk_window_shape_combine_region (GdkWindow *window,
-                                 GdkRegion *shape_region,
-                                 gint       offset_x,
-                                 gint       offset_y)
-{ 
+static void
+gdk_window_x11_shape_combine_region (GdkWindow *window,
+				     GdkRegion *shape_region,
+				     gint       offset_x,
+				     gint       offset_y)
+{
   GdkWindowObject *private = (GdkWindowObject *)window;
   gint xoffset, yoffset;
   
@@ -3769,7 +3415,7 @@ gdk_window_shape_combine_region (GdkWind
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
-  _gdk_windowing_window_get_offsets (window, &xoffset, &yoffset);
+  _gdk_x11_window_get_offsets (window, &xoffset, &yoffset);
 
   if (xoffset != 0 || yoffset != 0)
     {
@@ -3830,7 +3476,7 @@ gdk_window_set_override_redirect (GdkWin
 {
   XSetWindowAttributes attr;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
 
   if (!GDK_WINDOW_DESTROYED (window))
     {
@@ -3866,7 +3512,7 @@ gdk_window_set_accept_focus (GdkWindow *
 {
   GdkWindowObject *private;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
 
   private = (GdkWindowObject *)window;  
   
@@ -3903,7 +3549,7 @@ gdk_window_set_focus_on_map (GdkWindow *
 {
   GdkWindowObject *private;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
 
   private = (GdkWindowObject *)window;  
   
@@ -3947,7 +3593,7 @@ gdk_x11_window_set_user_time (GdkWindow 
   GdkToplevelX11 *toplevel;
   glong timestamp_long = (glong)timestamp;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
@@ -3996,7 +3642,7 @@ gdk_window_set_icon_list (GdkWindow *win
   gint n_channels;
   GdkDisplay *display;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
@@ -4099,7 +3745,7 @@ gdk_window_set_icon (GdkWindow *window, 
 {
   GdkToplevelX11 *toplevel;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
   
   if (GDK_WINDOW_DESTROYED (window))
@@ -4159,7 +3805,7 @@ gdk_window_set_icon_name (GdkWindow   *w
 {
   GdkDisplay *display;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
@@ -4196,7 +3842,7 @@ gdk_window_iconify (GdkWindow *window)
 {
   GdkWindowObject *private;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
@@ -4234,7 +3880,7 @@ gdk_window_deiconify (GdkWindow *window)
 {
   GdkWindowObject *private;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
@@ -4272,7 +3918,7 @@ gdk_window_deiconify (GdkWindow *window)
 void
 gdk_window_stick (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
@@ -4330,7 +3976,7 @@ gdk_window_stick (GdkWindow *window)
 void
 gdk_window_unstick (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
@@ -4414,7 +4060,7 @@ gdk_window_unstick (GdkWindow *window)
 void
 gdk_window_maximize (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
@@ -4449,7 +4095,7 @@ gdk_window_maximize (GdkWindow *window)
 void
 gdk_window_unmaximize (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
@@ -4487,7 +4133,7 @@ gdk_window_unmaximize (GdkWindow *window
 void
 gdk_window_fullscreen (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
@@ -4523,7 +4169,7 @@ gdk_window_fullscreen (GdkWindow *window
 void
 gdk_window_unfullscreen (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
@@ -4559,7 +4205,7 @@ gdk_window_unfullscreen (GdkWindow *wind
 void
 gdk_window_set_keep_above (GdkWindow *window, gboolean setting)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
@@ -4600,7 +4246,7 @@ gdk_window_set_keep_above (GdkWindow *wi
 void
 gdk_window_set_keep_below (GdkWindow *window, gboolean setting)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
@@ -4636,7 +4282,7 @@ gdk_window_get_group (GdkWindow *window)
 {
   GdkToplevelX11 *toplevel;
   
-  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
+  g_return_val_if_fail (GDK_IS_ONSCREEN_WINDOW (window), NULL);
   g_return_val_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD, NULL);
 
   if (GDK_WINDOW_DESTROYED (window))
@@ -4669,9 +4315,9 @@ gdk_window_set_group (GdkWindow *window,
 {
   GdkToplevelX11 *toplevel;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_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 || GDK_IS_ONSCREEN_WINDOW (leader));
 
   if (GDK_WINDOW_DESTROYED (window) || (leader != NULL && GDK_WINDOW_DESTROYED (leader)))
     return;
@@ -4799,7 +4445,7 @@ gdk_window_set_decorations (GdkWindow   
 {
   MotifWmHints hints;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
   
   hints.flags = MWM_HINTS_DECORATIONS;
   hints.decorations = decorations;
@@ -4822,7 +4468,7 @@ gdk_window_get_decorations(GdkWindow    
   MotifWmHints *hints;
   gboolean result = FALSE;
 
-  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+  g_return_val_if_fail (GDK_IS_ONSCREEN_WINDOW (window), FALSE);
 
   hints = gdk_window_get_mwm_hints (window);
   
@@ -4865,7 +4511,7 @@ gdk_window_set_functions (GdkWindow    *
 {
   MotifWmHints hints;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
   
   hints.flags = MWM_HINTS_FUNCTIONS;
   hints.functions = functions;
@@ -5189,17 +4835,8 @@ gdk_propagate_shapes (Display *disp,
 
 #endif /* HAVE_SHAPE_EXT */
 
-/**
- * gdk_window_set_child_shapes:
- * @window: a #GdkWindow
- * 
- * Sets the shape mask of @window to the union of shape masks
- * for all children of @window, ignoring the shape mask of @window
- * itself. Contrast with gdk_window_merge_child_shapes() which includes
- * the shape mask of @window in the masks to be merged.
- **/
-void
-gdk_window_set_child_shapes (GdkWindow *window)
+static void
+gdk_window_x11_set_child_shapes (GdkWindow *window)
 {
   g_return_if_fail (GDK_IS_WINDOW (window));
   
@@ -5211,22 +4848,8 @@ gdk_window_set_child_shapes (GdkWindow *
 #endif   
 }
 
-/**
- * gdk_window_merge_child_shapes:
- * @window: a #GdkWindow
- * 
- * Merges the shape masks for any child windows into the
- * shape mask for @window. i.e. the union of all masks
- * for @window and its children will become the new mask
- * for @window. See gdk_window_shape_combine_mask().
- *
- * This function is distinct from gdk_window_set_child_shapes()
- * because it includes @window's shape mask in the set of shapes to
- * be merged.
- * 
- **/
-void
-gdk_window_merge_child_shapes (GdkWindow *window)
+static void
+gdk_window_x11_merge_child_shapes (GdkWindow *window)
 {
   g_return_if_fail (GDK_IS_WINDOW (window));
   
@@ -5273,27 +4896,13 @@ gdk_window_set_static_win_gravity (GdkWi
 			   CWWinGravity,  &xattributes);
 }
 
-/**
- * gdk_window_set_static_gravities:
- * @window: a #GdkWindow
- * @use_static: %TRUE to turn on static gravity
- *
- * Set the bit gravity of the given window to static, and flag it so
- * all children get static subwindow gravity. This is used if you are
- * implementing scary features that involve deep knowledge of the
- * windowing system. Don't worry about it unless you have to.
- * 
- * Return value: %TRUE if the server supports static gravity
- **/
-gboolean 
-gdk_window_set_static_gravities (GdkWindow *window,
-				 gboolean   use_static)
+static gboolean 
+gdk_window_x11_set_static_gravities (GdkWindow *window,
+				     gboolean   use_static)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
   GList *tmp_list;
   
-  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
-
   if (!use_static == !private->guffaw_gravity)
     return TRUE;
 
@@ -5306,7 +4915,8 @@ gdk_window_set_static_gravities (GdkWind
       tmp_list = private->children;
       while (tmp_list)
 	{
-	  gdk_window_set_static_win_gravity (tmp_list->data, use_static);
+	  if (!gdk_window_is_offscreen (tmp_list->data))
+	    gdk_window_set_static_win_gravity (tmp_list->data, use_static);
 	  
 	  tmp_list = tmp_list->next;
 	}
@@ -5883,7 +5493,7 @@ gdk_window_begin_resize_drag (GdkWindow 
                               gint           root_y,
                               guint32        timestamp)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
@@ -5918,7 +5528,7 @@ gdk_window_begin_move_drag (GdkWindow *w
                             gint       root_y,
                             guint32    timestamp)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
@@ -5954,7 +5564,7 @@ gdk_window_enable_synchronized_configure
   GdkWindowObject *private = (GdkWindowObject *)window;
   GdkWindowImplX11 *impl;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
 
   impl = GDK_WINDOW_IMPL_X11 (private->impl);
 	  
@@ -5985,7 +5595,7 @@ gdk_window_configure_finished (GdkWindow
 {
   GdkWindowImplX11 *impl;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_IS_ONSCREEN_WINDOW (window));
   
   impl = GDK_WINDOW_IMPL_X11 (((GdkWindowObject *)window)->impl);
   if (!impl->use_synchronized_configure)
@@ -6009,6 +5619,37 @@ gdk_window_configure_finished (GdkWindow
 	}
     }
 #endif
+}
+
+static void
+gdk_window_impl_iface_init (GdkWindowImplIface *iface)
+{
+  iface->get_visible_rect = gdk_window_x11_get_visible_rect;
+  iface->show = gdk_window_x11_show;
+  iface->hide = gdk_window_x11_hide;
+  iface->withdraw = gdk_window_x11_withdraw;
+  iface->set_events = gdk_window_x11_set_events;
+  iface->get_events = gdk_window_x11_get_events;
+  iface->clear_area = gdk_window_x11_clear_area;
+  iface->raise = gdk_window_x11_raise;
+  iface->lower = gdk_window_x11_lower;
+  iface->move = gdk_window_x11_move;
+  iface->resize = gdk_window_x11_resize;
+  iface->move_resize = gdk_window_x11_move_resize;
+  iface->scroll = _gdk_window_x11_scroll;
+  iface->move_region = _gdk_window_x11_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;
+  iface->set_cursor = gdk_window_x11_set_cursor;
+  iface->get_geometry = gdk_window_x11_get_geometry;
+  iface->get_origin = gdk_window_x11_get_origin;
+  iface->shape_combine_mask = gdk_window_x11_shape_combine_mask;
+  iface->shape_combine_region = gdk_window_x11_shape_combine_region;
+  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;
 }
 
 #define __GDK_WINDOW_X11_C__
Index: gdk/x11/gdkwindow-x11.h
===================================================================
RCS file: /cvs/gnome/gtk+/gdk/x11/gdkwindow-x11.h,v
retrieving revision 1.21
diff -u -p -r1.21 gdkwindow-x11.h
--- gdk/x11/gdkwindow-x11.h	17 Jun 2005 20:19:30 -0000	1.21
+++ gdk/x11/gdkwindow-x11.h	13 Oct 2005 20:59:03 -0000
@@ -161,6 +161,9 @@ void            _gdk_x11_window_tmp_rese
 
 
 GdkCursor      *_gdk_x11_window_get_cursor    (GdkWindow *window);
+void            _gdk_x11_window_get_offsets   (GdkWindow *window,
+					       gint      *x_offset,
+					       gint      *y_offset);
 
 G_END_DECLS
 
Index: gtk/gtkmain.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkmain.c,v
retrieving revision 1.263.2.2
diff -u -p -r1.263.2.2 gtkmain.c
--- gtk/gtkmain.c	28 Sep 2005 23:41:27 -0000	1.263.2.2
+++ gtk/gtkmain.c	13 Oct 2005 20:59:03 -0000
@@ -1381,6 +1381,7 @@ gtk_main_do_event (GdkEvent *event)
     case GDK_VISIBILITY_NOTIFY:
     case GDK_WINDOW_STATE:
     case GDK_GRAB_BROKEN:
+    case GDK_DAMAGE:
       gtk_widget_event (event_widget, event);
       break;
 
Index: gtk/gtkwidget.c
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwidget.c,v
retrieving revision 1.412.2.1
diff -u -p -r1.412.2.1 gtkwidget.c
--- gtk/gtkwidget.c	22 Sep 2005 14:48:10 -0000	1.412.2.1
+++ gtk/gtkwidget.c	13 Oct 2005 20:59:04 -0000
@@ -121,6 +121,7 @@ enum {
   SCREEN_CHANGED,
   CAN_ACTIVATE_ACCEL,
   GRAB_BROKEN,
+  DAMAGE_EVENT,
   LAST_SIGNAL
 };
 
@@ -401,6 +402,7 @@ gtk_widget_class_init (GtkWidgetClass *k
   klass->screen_changed = NULL;
   klass->can_activate_accel = gtk_widget_real_can_activate_accel;
   klass->grab_broken_event = NULL;
+  klass->damage_event = NULL;
 
   klass->show_help = gtk_widget_real_show_help;
   
@@ -1353,6 +1355,29 @@ gtk_widget_class_init (GtkWidgetClass *k
 		  _gtk_marshal_BOOLEAN__BOXED,
 		  G_TYPE_BOOLEAN, 1,
 		  GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
+  /**
+   * GtkWidget::damage-event:
+   * @widget: the object which received the signal
+   * @event: the #GdkEventExpose event
+   *
+   * Emitted when a redirected window belonging to @widget gets drawn into.
+   * The region/area members of the event shows what area of the redirected
+   * drawable was drawn into.
+   *
+   * Returns: %TRUE to stop other handlers from being invoked for the event. 
+   *   %FALSE to propagate the event further.
+   *
+   * Since: 2.10
+   */
+  widget_signals[DAMAGE_EVENT] =
+    g_signal_new ("damage_event",
+		  G_TYPE_FROM_CLASS (gobject_class),
+		  G_SIGNAL_RUN_LAST,
+		  G_STRUCT_OFFSET (GtkWidgetClass, damage_event),
+		  _gtk_boolean_handled_accumulator, NULL,
+		  _gtk_marshal_BOOLEAN__BOXED,
+		  G_TYPE_BOOLEAN, 1,
+		  GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
 /**
  * GtkWidget::popup-menu
  * @widget: the object which received the signal
@@ -2791,7 +2816,7 @@ gtk_widget_queue_shallow_draw (GtkWidget
       rect.x += wx;
       rect.y += wy;
     }
-  
+
   region = gdk_region_rectangle (&rect);
   gtk_widget_invalidate_widget_windows (widget, region);
   gdk_region_destroy (region);
@@ -3726,6 +3751,9 @@ gtk_widget_event_internal (GtkWidget *wi
 	case GDK_GRAB_BROKEN:
 	  signal_num = GRAB_BROKEN;
 	  break;
+	case GDK_DAMAGE:
+	  signal_num = DAMAGE_EVENT;
+	  break;
 	default:
 	  g_warning ("gtk_widget_event(): unhandled event type: %d", event->type);
 	  signal_num = -1;
Index: gtk/gtkwidget.h
===================================================================
RCS file: /cvs/gnome/gtk+/gtk/gtkwidget.h,v
retrieving revision 1.157
diff -u -p -r1.157 gtkwidget.h
--- gtk/gtkwidget.h	26 Jul 2005 15:02:23 -0000	1.157
+++ gtk/gtkwidget.h	13 Oct 2005 20:59:04 -0000
@@ -407,8 +407,11 @@ struct _GtkWidgetClass
   gboolean (*grab_broken_event) (GtkWidget	     *widget,
                                  GdkEventGrabBroken  *event);
 
+  /* Sent when a redirected window is drawn into */
+  gboolean (*damage_event) (GtkWidget	   *widget,
+			    GdkEventExpose *event);
+  
   /* Padding for future expansion */
-  void (*_gtk_reserved3) (void);
   void (*_gtk_reserved4) (void);
   void (*_gtk_reserved5) (void);
   void (*_gtk_reserved6) (void);
