]> Pileus Git - ~andy/gtk/blobdiff - gdk/gdkwindow.c
API: gdk: Remove gdk_set_pointer_hooks()
[~andy/gtk] / gdk / gdkwindow.c
index 0da0fbf45bace5d30d63698dcf9644e2d11715b5..260746c99047dfa86c9e16df4b492fa52f4fba84 100644 (file)
 
 #include "config.h"
 
-#include "gdkwindow.h"
+#include <cairo-gobject.h>
 
-#ifdef GDK_WINDOWING_X11
-#include "x11/gdkx.h"           /* For workaround */
-#endif
-#include "math.h"
+#include "gdkwindow.h"
 
-#include "gdk.h"                /* For gdk_rectangle_union() */
+#include "gdkrectangle.h"
 #include "gdkinternals.h"
 #include "gdkintl.h"
-#include "gdkscreen.h"
+#include "gdkscreenprivate.h"
+#include "gdkdisplayprivate.h"
 #include "gdkdeviceprivate.h"
-#include "gdkdrawable.h"
+#include "gdkvisualprivate.h"
 #include "gdkmarshalers.h"
-#include "gdkscreen.h"
 #include "gdkwindowimpl.h"
 
+#include <math.h>
+
 #undef DEBUG_WINDOW_PRINTING
 
 
@@ -185,6 +184,7 @@ enum {
   PICK_EMBEDDED_CHILD, /* only called if children are embedded */
   TO_EMBEDDER,
   FROM_EMBEDDER,
+  CREATE_SURFACE,
   LAST_SIGNAL
 };
 
@@ -215,27 +215,10 @@ typedef struct {
 
 /* Global info */
 
-static cairo_surface_t *gdk_window_ref_cairo_surface (GdkDrawable *drawable);
-static cairo_surface_t *gdk_window_create_cairo_surface (GdkDrawable *drawable,
-                                                        int width,
-                                                        int height);
-static void             gdk_window_drop_cairo_surface (GdkWindowObject *private);
-static void             gdk_window_set_cairo_clip    (GdkDrawable *drawable,
-                                                     cairo_t *cr);
-
-static void   gdk_window_real_get_size  (GdkDrawable     *drawable,
-                                        gint            *width,
-                                        gint            *height);
-
-static GdkColormap* gdk_window_real_get_colormap (GdkDrawable *drawable);
-
-static cairo_region_t*   gdk_window_get_clip_region        (GdkDrawable *drawable);
-static cairo_region_t*   gdk_window_get_visible_region     (GdkDrawable *drawable);
+static void             gdk_window_drop_cairo_surface (GdkWindow *private);
 
 static void gdk_window_free_paint_stack (GdkWindow *window);
 
-static void gdk_window_init       (GdkWindowObject      *window);
-static void gdk_window_class_init (GdkWindowObjectClass *klass);
 static void gdk_window_finalize   (GObject              *object);
 
 static void gdk_window_set_property (GObject      *object,
@@ -250,19 +233,19 @@ static void gdk_window_get_property (GObject      *object,
 static void gdk_window_clear_backing_region (GdkWindow *window,
                                             cairo_region_t *region);
 
-static void recompute_visible_regions   (GdkWindowObject *private,
+static void recompute_visible_regions   (GdkWindow *private,
                                         gboolean recalculate_siblings,
                                         gboolean recalculate_children);
 static void gdk_window_flush_outstanding_moves (GdkWindow *window);
-static void gdk_window_flush_recursive  (GdkWindowObject *window);
-static void do_move_region_bits_on_impl (GdkWindowObject *private,
+static void gdk_window_flush_recursive  (GdkWindow *window);
+static void do_move_region_bits_on_impl (GdkWindow *window,
                                         cairo_region_t *region, /* In impl window coords */
                                         int dx, int dy);
-static void gdk_window_invalidate_in_parent (GdkWindowObject *private);
-static void move_native_children        (GdkWindowObject *private);
+static void gdk_window_invalidate_in_parent (GdkWindow *private);
+static void move_native_children        (GdkWindow *private);
 static void update_cursor               (GdkDisplay *display,
                                          GdkDevice  *device);
-static void impl_window_add_update_area (GdkWindowObject *impl_window,
+static void impl_window_add_update_area (GdkWindow *impl_window,
                                         cairo_region_t *region);
 static void gdk_window_region_move_free (GdkWindowRegionMove *move);
 static void gdk_window_invalidate_region_full (GdkWindow       *window,
@@ -288,22 +271,7 @@ new_region_tag (void)
   return ++tag;
 }
 
-GType
-gdk_window_object_get_type (void)
-{
-  static GType object_type = 0;
-
-  if (!object_type)
-    object_type = g_type_register_static_simple (GDK_TYPE_DRAWABLE,
-                                                "GdkWindow",
-                                                sizeof (GdkWindowObjectClass),
-                                                (GClassInitFunc) gdk_window_class_init,
-                                                sizeof (GdkWindowObject),
-                                                (GInstanceInitFunc) gdk_window_init,
-                                                0);
-
-  return object_type;
-}
+G_DEFINE_ABSTRACT_TYPE (GdkWindow, gdk_window, G_TYPE_OBJECT)
 
 GType
 _gdk_paintable_get_type (void)
@@ -330,7 +298,7 @@ _gdk_paintable_get_type (void)
 }
 
 static void
-gdk_window_init (GdkWindowObject *window)
+gdk_window_init (GdkWindow *window)
 {
   /* 0-initialization is good for all other fields. */
 
@@ -359,13 +327,24 @@ accumulate_get_window (GSignalInvocationHint *ihint,
   return g_value_get_object (handler_return) == NULL;
 }
 
+static gboolean
+create_surface_accumulator (GSignalInvocationHint *ihint,
+                            GValue                *return_accu,
+                            const GValue          *handler_return,
+                            gpointer               data)
+{
+  g_value_copy (handler_return, return_accu);
+
+  /* Stop on the first non-NULL return value */
+  return g_value_get_boxed (handler_return) == NULL;
+}
+
 static GQuark quark_pointer_window = 0;
 
 static void
-gdk_window_class_init (GdkWindowObjectClass *klass)
+gdk_window_class_init (GdkWindowClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
-  GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
 
   parent_class = g_type_class_peek_parent (klass);
 
@@ -373,13 +352,7 @@ gdk_window_class_init (GdkWindowObjectClass *klass)
   object_class->set_property = gdk_window_set_property;
   object_class->get_property = gdk_window_get_property;
 
-  drawable_class->get_size = gdk_window_real_get_size;
-  drawable_class->get_colormap = gdk_window_real_get_colormap;
-  drawable_class->ref_cairo_surface = gdk_window_ref_cairo_surface;
-  drawable_class->create_cairo_surface = gdk_window_create_cairo_surface;
-  drawable_class->set_cairo_clip = gdk_window_set_cairo_clip;
-  drawable_class->get_clip_region = gdk_window_get_clip_region;
-  drawable_class->get_visible_region = gdk_window_get_visible_region;
+  klass->create_surface = _gdk_offscreen_window_create_surface;
 
   quark_pointer_window = g_quark_from_static_string ("gtk-pointer-window");
 
@@ -396,11 +369,11 @@ gdk_window_class_init (GdkWindowObjectClass *klass)
    */
   g_object_class_install_property (object_class,
                                    PROP_CURSOR,
-                                   g_param_spec_boxed ("cursor",
-                                                       P_("Cursor"),
-                                                       P_("Cursor"),
-                                                       GDK_TYPE_CURSOR,
-                                                       G_PARAM_READWRITE));
+                                   g_param_spec_object ("cursor",
+                                                        P_("Cursor"),
+                                                        P_("Cursor"),
+                                                        GDK_TYPE_CURSOR,
+                                                        G_PARAM_READWRITE));
 
   /**
    * GdkWindow::pick-embedded-child:
@@ -419,7 +392,7 @@ gdk_window_class_init (GdkWindowObjectClass *klass)
     g_signal_new (g_intern_static_string ("pick-embedded-child"),
                  G_OBJECT_CLASS_TYPE (object_class),
                  G_SIGNAL_RUN_LAST,
-                 0,
+                  G_STRUCT_OFFSET (GdkWindowClass, pick_embedded_child),
                  accumulate_get_window, NULL,
                  _gdk_marshal_OBJECT__DOUBLE_DOUBLE,
                  GDK_TYPE_WINDOW,
@@ -446,7 +419,7 @@ gdk_window_class_init (GdkWindowObjectClass *klass)
     g_signal_new (g_intern_static_string ("to-embedder"),
                  G_OBJECT_CLASS_TYPE (object_class),
                  G_SIGNAL_RUN_LAST,
-                 0,
+                  G_STRUCT_OFFSET (GdkWindowClass, to_embedder),
                  NULL, NULL,
                  _gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
                  G_TYPE_NONE,
@@ -475,7 +448,7 @@ gdk_window_class_init (GdkWindowObjectClass *klass)
     g_signal_new (g_intern_static_string ("from-embedder"),
                  G_OBJECT_CLASS_TYPE (object_class),
                  G_SIGNAL_RUN_LAST,
-                 0,
+                  G_STRUCT_OFFSET (GdkWindowClass, from_embedder),
                  NULL, NULL,
                  _gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
                  G_TYPE_NONE,
@@ -484,6 +457,39 @@ gdk_window_class_init (GdkWindowObjectClass *klass)
                  G_TYPE_DOUBLE,
                  G_TYPE_POINTER,
                  G_TYPE_POINTER);
+
+  /**
+   * GdkWindow::create-surface:
+   * @window: the offscreen window on which the signal is emitted
+   * @width: the width of the offscreen surface to create
+   * @height: the height of the offscreen surface to create
+   *
+   * The ::create-surface signal is emitted when an offscreen window
+   * needs its surface (re)created, which happens either when the the
+   * window is first drawn to, or when the window is being
+   * resized. The first signal handler that returns a non-%NULL
+   * surface will stop any further signal emission, and its surface
+   * will be used.
+   *
+   * Note that it is not possible to access the window's previous
+   * surface from within any callback of this signal. Calling
+   * gdk_offscreen_window_get_surface() will lead to a crash.
+   *
+   * Returns: the newly created #cairo_surface_t for the offscreen window
+   *
+   * Since: 3.0
+   */
+  signals[CREATE_SURFACE] =
+    g_signal_new (g_intern_static_string ("create-surface"),
+                  G_OBJECT_CLASS_TYPE (object_class),
+                  G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (GdkWindowClass, create_surface),
+                  create_surface_accumulator, NULL,
+                  _gdk_marshal_BOXED__INT_INT,
+                  CAIRO_GOBJECT_TYPE_SURFACE,
+                  2,
+                  G_TYPE_INT,
+                  G_TYPE_INT);
 }
 
 static void
@@ -491,22 +497,17 @@ device_removed_cb (GdkDeviceManager *device_manager,
                    GdkDevice        *device,
                    GdkWindow        *window)
 {
-  GdkWindowObject *private;
-
-  private = (GdkWindowObject *) window;
+  window->devices_inside = g_list_remove (window->devices_inside, device);
+  g_hash_table_remove (window->device_cursor, device);
 
-  private->devices_inside = g_list_remove (private->devices_inside, device);
-  g_hash_table_remove (private->device_cursor, device);
-
-  if (private->device_events)
-    g_hash_table_remove (private->device_events, device);
+  if (window->device_events)
+    g_hash_table_remove (window->device_events, device);
 }
 
 static void
 gdk_window_finalize (GObject *object)
 {
   GdkWindow *window = GDK_WINDOW (object);
-  GdkWindowObject *obj = (GdkWindowObject *) object;
   GdkDeviceManager *device_manager;
 
   device_manager = gdk_display_get_device_manager (gdk_window_get_display (window));
@@ -526,35 +527,40 @@ gdk_window_finalize (GObject *object)
        _gdk_window_destroy (window, TRUE);
     }
 
-  if (obj->impl)
+  gdk_window_drop_cairo_surface (window);
+
+  if (window->impl)
     {
-      g_object_unref (obj->impl);
-      obj->impl = NULL;
+      g_object_unref (window->impl);
+      window->impl = NULL;
     }
 
-  if (obj->impl_window != obj)
+  if (window->impl_window != window)
     {
-      g_object_unref (obj->impl_window);
-      obj->impl_window = NULL;
+      g_object_unref (window->impl_window);
+      window->impl_window = NULL;
     }
 
-  if (obj->shape)
-    cairo_region_destroy (obj->shape);
+  if (window->shape)
+    cairo_region_destroy (window->shape);
 
-  if (obj->input_shape)
-    cairo_region_destroy (obj->input_shape);
+  if (window->input_shape)
+    cairo_region_destroy (window->input_shape);
 
-  if (obj->cursor)
-    gdk_cursor_unref (obj->cursor);
+  if (window->cursor)
+    g_object_unref (window->cursor);
 
-  if (obj->device_cursor)
-    g_hash_table_destroy (obj->device_cursor);
+  if (window->device_cursor)
+    g_hash_table_destroy (window->device_cursor);
 
-  if (obj->device_events)
-    g_hash_table_destroy (obj->device_events);
+  if (window->device_events)
+    g_hash_table_destroy (window->device_events);
 
-  if (obj->devices_inside)
-    g_list_free (obj->devices_inside);
+  if (window->source_event_masks)
+    g_hash_table_destroy (window->source_event_masks);
+
+  if (window->devices_inside)
+    g_list_free (window->devices_inside);
 
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
@@ -570,7 +576,7 @@ gdk_window_set_property (GObject      *object,
   switch (prop_id)
     {
     case PROP_CURSOR:
-      gdk_window_set_cursor (window, g_value_get_boxed (value));
+      gdk_window_set_cursor (window, g_value_get_object (value));
       break;
 
     default:
@@ -590,7 +596,7 @@ gdk_window_get_property (GObject    *object,
   switch (prop_id)
     {
     case PROP_CURSOR:
-      g_value_set_boxed (value, gdk_window_get_cursor (window));
+      g_value_set_object (value, gdk_window_get_cursor (window));
       break;
 
     default:
@@ -600,13 +606,13 @@ gdk_window_get_property (GObject    *object,
 }
 
 static gboolean
-gdk_window_is_offscreen (GdkWindowObject *window)
+gdk_window_is_offscreen (GdkWindow *window)
 {
   return window->window_type == GDK_WINDOW_OFFSCREEN;
 }
 
-static GdkWindowObject *
-gdk_window_get_impl_window (GdkWindowObject *window)
+static GdkWindow *
+gdk_window_get_impl_window (GdkWindow *window)
 {
   return window->impl_window;
 }
@@ -614,17 +620,17 @@ gdk_window_get_impl_window (GdkWindowObject *window)
 GdkWindow *
 _gdk_window_get_impl_window (GdkWindow *window)
 {
-  return (GdkWindow *)gdk_window_get_impl_window ((GdkWindowObject *)window);
+  return gdk_window_get_impl_window (window);
 }
 
 static gboolean
-gdk_window_has_impl (GdkWindowObject *window)
+gdk_window_has_impl (GdkWindow *window)
 {
   return window->impl_window == window;
 }
 
 static gboolean
-gdk_window_is_toplevel (GdkWindowObject *window)
+gdk_window_is_toplevel (GdkWindow *window)
 {
   return
     window->parent == NULL ||
@@ -634,22 +640,22 @@ gdk_window_is_toplevel (GdkWindowObject *window)
 gboolean
 _gdk_window_has_impl (GdkWindow *window)
 {
-  return gdk_window_has_impl ((GdkWindowObject *)window);
+  return gdk_window_has_impl (window);
 }
 
 static gboolean
-gdk_window_has_no_impl (GdkWindowObject *window)
+gdk_window_has_no_impl (GdkWindow *window)
 {
   return window->impl_window != window;
 }
 
 static void
-remove_child_area (GdkWindowObject *private,
-                  GdkWindowObject *until,
+remove_child_area (GdkWindow *private,
+                  GdkWindow *until,
                   gboolean for_input,
                   cairo_region_t *region)
 {
-  GdkWindowObject *child;
+  GdkWindow *child;
   cairo_region_t *child_region;
   GdkRectangle r;
   GList *l;
@@ -695,7 +701,7 @@ remove_child_area (GdkWindowObject *private,
        }
       else if (private->window_type == GDK_WINDOW_FOREIGN)
        {
-         shape = _gdk_windowing_window_get_shape ((GdkWindow *)child);
+         shape = GDK_WINDOW_IMPL_GET_CLASS (child)->get_shape (child);
          if (shape)
            {
              cairo_region_intersect (child_region, shape);
@@ -709,7 +715,7 @@ remove_child_area (GdkWindowObject *private,
            cairo_region_intersect (child_region, child->input_shape);
          else if (private->window_type == GDK_WINDOW_FOREIGN)
            {
-             shape = _gdk_windowing_window_get_input_shape ((GdkWindow *)child);
+             shape = GDK_WINDOW_IMPL_GET_CLASS (child)->get_input_shape (child);
              if (shape)
                {
                  cairo_region_intersect (child_region, shape);
@@ -725,40 +731,40 @@ remove_child_area (GdkWindowObject *private,
 }
 
 static GdkVisibilityState
-effective_visibility (GdkWindowObject *private)
+effective_visibility (GdkWindow *window)
 {
   GdkVisibilityState native;
 
-  if (!gdk_window_is_viewable ((GdkWindow *)private))
+  if (!gdk_window_is_viewable (window))
     return GDK_VISIBILITY_NOT_VIEWABLE;
 
-  native = private->impl_window->native_visibility;
+  native = window->impl_window->native_visibility;
 
   if (native == GDK_VISIBILITY_FULLY_OBSCURED ||
-      private->visibility == GDK_VISIBILITY_FULLY_OBSCURED)
+      window->visibility == GDK_VISIBILITY_FULLY_OBSCURED)
     return GDK_VISIBILITY_FULLY_OBSCURED;
   else if (native == GDK_VISIBILITY_UNOBSCURED)
-    return private->visibility;
+    return window->visibility;
   else /* native PARTIAL, private partial or unobscured  */
     return GDK_VISIBILITY_PARTIAL;
 }
 
 static void
-gdk_window_update_visibility (GdkWindowObject *private)
+gdk_window_update_visibility (GdkWindow *window)
 {
   GdkVisibilityState new_visibility;
   GdkEvent *event;
 
-  new_visibility = effective_visibility (private);
+  new_visibility = effective_visibility (window);
 
-  if (new_visibility != private->effective_visibility)
+  if (new_visibility != window->effective_visibility)
     {
-      private->effective_visibility = new_visibility;
+      window->effective_visibility = new_visibility;
 
       if (new_visibility != GDK_VISIBILITY_NOT_VIEWABLE &&
-         private->event_mask & GDK_VISIBILITY_NOTIFY)
+         window->event_mask & GDK_VISIBILITY_NOTIFY)
        {
-         event = _gdk_make_event ((GdkWindow *)private, GDK_VISIBILITY_NOTIFY,
+         event = _gdk_make_event (window, GDK_VISIBILITY_NOTIFY,
                                   NULL, FALSE);
          event->visibility.state = new_visibility;
        }
@@ -766,14 +772,14 @@ gdk_window_update_visibility (GdkWindowObject *private)
 }
 
 static void
-gdk_window_update_visibility_recursively (GdkWindowObject *private,
-                                         GdkWindowObject *only_for_impl)
+gdk_window_update_visibility_recursively (GdkWindow *window,
+                                         GdkWindow *only_for_impl)
 {
-  GdkWindowObject *child;
+  GdkWindow *child;
   GList *l;
 
-  gdk_window_update_visibility (private);
-  for (l = private->children; l != NULL; l = l->next)
+  gdk_window_update_visibility (window);
+  for (l = window->children; l != NULL; l = l->next)
     {
       child = l->data;
       if ((only_for_impl == NULL) ||
@@ -783,39 +789,39 @@ gdk_window_update_visibility_recursively (GdkWindowObject *private,
 }
 
 static gboolean
-should_apply_clip_as_shape (GdkWindowObject *private)
+should_apply_clip_as_shape (GdkWindow *window)
 {
   return
-    gdk_window_has_impl (private) &&
+    gdk_window_has_impl (window) &&
     /* Not for offscreens */
-    !gdk_window_is_offscreen (private) &&
+    !gdk_window_is_offscreen (window) &&
     /* or for toplevels */
-    !gdk_window_is_toplevel (private) &&
+    !gdk_window_is_toplevel (window) &&
     /* or for foreign windows */
-    private->window_type != GDK_WINDOW_FOREIGN &&
+    window->window_type != GDK_WINDOW_FOREIGN &&
     /* or for the root window */
-    private->window_type != GDK_WINDOW_ROOT;
+    window->window_type != GDK_WINDOW_ROOT;
 }
 
 static void
-apply_shape (GdkWindowObject *private,
+apply_shape (GdkWindow *window,
             cairo_region_t *region)
 {
-  GdkWindowImplIface *impl_iface;
+  GdkWindowImplClass *impl_class;
 
   /* We trash whether we applied a shape so that
      we can avoid unsetting it many times, which
      could happen in e.g. apply_clip_as_shape as
      windows get resized */
-  impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
+  impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
   if (region)
-    impl_iface->shape_combine_region ((GdkWindow *)private,
+    impl_class->shape_combine_region (window,
                                      region, 0, 0);
-  else if (private->applied_shape)
-    impl_iface->shape_combine_region ((GdkWindow *)private,
+  else if (window->applied_shape)
+    impl_class->shape_combine_region (window,
                                      NULL, 0, 0);
 
-  private->applied_shape = region != NULL;
+  window->applied_shape = region != NULL;
 }
 
 static gboolean
@@ -836,33 +842,33 @@ region_rect_equal (const cairo_region_t *region,
 }
 
 static void
-apply_clip_as_shape (GdkWindowObject *private)
+apply_clip_as_shape (GdkWindow *window)
 {
   GdkRectangle r;
 
   r.x = r.y = 0;
-  r.width = private->width;
-  r.height = private->height;
+  r.width = window->width;
+  r.height = window->height;
 
   /* We only apply the clip region if would differ
      from the actual clip region implied by the size
      of the window. This is to avoid unneccessarily
      adding meaningless shapes to all native subwindows */
-  if (!region_rect_equal (private->clip_region, &r))
-    apply_shape (private, private->clip_region);
+  if (!region_rect_equal (window->clip_region, &r))
+    apply_shape (window, window->clip_region);
   else
-    apply_shape (private, NULL);
+    apply_shape (window, NULL);
 }
 
 static void
-recompute_visible_regions_internal (GdkWindowObject *private,
-                                   gboolean recalculate_clip,
-                                   gboolean recalculate_siblings,
-                                   gboolean recalculate_children)
+recompute_visible_regions_internal (GdkWindow *private,
+                                   gboolean   recalculate_clip,
+                                   gboolean   recalculate_siblings,
+                                   gboolean   recalculate_children)
 {
   GdkRectangle r;
   GList *l;
-  GdkWindowObject *child;
+  GdkWindow *child;
   cairo_region_t *new_clip, *old_clip_region_with_children;
   gboolean clip_region_changed;
   gboolean abs_pos_changed;
@@ -1024,15 +1030,17 @@ recompute_visible_regions_internal (GdkWindowObject *private,
       recompute_visible_regions_internal (private->parent, TRUE, FALSE, FALSE);
     }
 
-  if (private->cairo_surface &&
-      (!gdk_window_has_impl (private) ||
-       !_gdk_windowing_set_cairo_surface_size (private->cairo_surface,
-                                               private->width,
-                                               private->height)))
+  if (private->cairo_surface && gdk_window_has_impl (private))
     {
-      cairo_surface_destroy (private->cairo_surface);
-      private->cairo_surface = NULL;
+      GdkWindowImplClass *iface = GDK_WINDOW_IMPL_GET_CLASS (private->impl);
+
+      private->cairo_surface = iface->resize_cairo_surface (private,
+                                                            private->cairo_surface,
+                                                            private->width,
+                                                            private->height);
     }
+  else if (private->cairo_surface)
+    gdk_window_drop_cairo_surface (private);
 }
 
 /* Call this when private has changed in one or more of these ways:
@@ -1051,7 +1059,7 @@ recompute_visible_regions_internal (GdkWindowObject *private,
  * recompute_visible_regions), pass in TRUE for recalculate_children on the parent
  */
 static void
-recompute_visible_regions (GdkWindowObject *private,
+recompute_visible_regions (GdkWindow *private,
                           gboolean recalculate_siblings,
                           gboolean recalculate_children)
 {
@@ -1064,7 +1072,7 @@ recompute_visible_regions (GdkWindowObject *private,
 void
 _gdk_window_update_size (GdkWindow *window)
 {
-  recompute_visible_regions ((GdkWindowObject *)window, TRUE, FALSE);
+  recompute_visible_regions (window, TRUE, FALSE);
 }
 
 /* Find the native window that would be just above "child"
@@ -1073,11 +1081,11 @@ _gdk_window_update_size (GdkWindow *window)
  * window inside this native parent then NULL is returned.
  * If child is NULL, find lowest native window in parent.
  */
-static GdkWindowObject *
-find_native_sibling_above_helper (GdkWindowObject *parent,
-                                 GdkWindowObject *child)
+static GdkWindow *
+find_native_sibling_above_helper (GdkWindow *parent,
+                                 GdkWindow *child)
 {
-  GdkWindowObject *w;
+  GdkWindow *w;
   GList *l;
 
   if (child)
@@ -1106,11 +1114,11 @@ find_native_sibling_above_helper (GdkWindowObject *parent,
 }
 
 
-static GdkWindowObject *
-find_native_sibling_above (GdkWindowObject *parent,
-                          GdkWindowObject *child)
+static GdkWindow *
+find_native_sibling_above (GdkWindow *parent,
+                          GdkWindow *child)
 {
-  GdkWindowObject *w;
+  GdkWindow *w;
 
   w = find_native_sibling_above_helper (parent, child);
   if (w)
@@ -1123,8 +1131,8 @@ find_native_sibling_above (GdkWindowObject *parent,
 }
 
 static GdkEventMask
-get_native_device_event_mask (GdkWindowObject *private,
-                              GdkDevice       *device)
+get_native_device_event_mask (GdkWindow *private,
+                              GdkDevice *device)
 {
   GdkEventMask event_mask;
 
@@ -1199,7 +1207,7 @@ get_native_grab_event_mask (GdkEventMask grab_mask)
 }
 
 static GdkEventMask
-get_native_event_mask (GdkWindowObject *private)
+get_native_event_mask (GdkWindow *private)
 {
   return get_native_device_event_mask (private, NULL);
 }
@@ -1212,20 +1220,17 @@ get_native_event_mask (GdkWindowObject *private)
 static void
 sync_native_window_stack_position (GdkWindow *window)
 {
-  GdkWindowObject *above;
-  GdkWindowObject *private;
-  GdkWindowImplIface *impl_iface;
+  GdkWindow *above;
+  GdkWindowImplClass *impl_class;
   GList listhead = {0};
 
-  private = (GdkWindowObject *) window;
-  impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
+  impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 
-  above = find_native_sibling_above (private->parent, private);
+  above = find_native_sibling_above (window->parent, window);
   if (above)
     {
       listhead.data = window;
-      impl_iface->restack_under ((GdkWindow *)above,
-                                &listhead);
+      impl_class->restack_under (above, &listhead);
     }
 }
 
@@ -1249,8 +1254,8 @@ gdk_window_new (GdkWindow     *parent,
                gint           attributes_mask)
 {
   GdkWindow *window;
-  GdkWindowObject *private;
   GdkScreen *screen;
+  GdkDisplay *display;
   int x, y;
   gboolean native;
   GdkEventMask event_mask;
@@ -1285,8 +1290,9 @@ gdk_window_new (GdkWindow     *parent,
       return NULL;
     }
 
-  window = g_object_new (GDK_TYPE_WINDOW, NULL);
-  private = (GdkWindowObject *) window;
+  display = gdk_screen_get_display (screen);
+
+  window = _gdk_display_create_window (display);
 
   /* Windows with a foreign parent are treated as if they are children
    * of the root window, except for actual creation.
@@ -1295,10 +1301,10 @@ gdk_window_new (GdkWindow     *parent,
   if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
     parent = gdk_screen_get_root_window (screen);
 
-  private->parent = (GdkWindowObject *)parent;
+  window->parent = parent;
 
-  private->accept_focus = TRUE;
-  private->focus_on_map = TRUE;
+  window->accept_focus = TRUE;
+  window->focus_on_map = TRUE;
 
   if (attributes_mask & GDK_WA_X)
     x = attributes->x;
@@ -1310,23 +1316,10 @@ gdk_window_new (GdkWindow     *parent,
   else
     y = 0;
 
-  private->x = x;
-  private->y = y;
-  private->width = (attributes->width > 1) ? (attributes->width) : (1);
-  private->height = (attributes->height > 1) ? (attributes->height) : (1);
-
-#ifdef GDK_WINDOWING_X11
-  /* Work around a bug where Xorg refuses to map toplevel InputOnly windows
-   * from an untrusted client: http://bugs.freedesktop.org/show_bug.cgi?id=6988
-   */
-  if (attributes->wclass == GDK_INPUT_ONLY &&
-      private->parent->window_type == GDK_WINDOW_ROOT &&
-      !G_LIKELY (GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (parent))->trusted_client))
-    {
-      g_warning ("Coercing GDK_INPUT_ONLY toplevel window to GDK_INPUT_OUTPUT to work around bug in Xorg server");
-      attributes->wclass = GDK_INPUT_OUTPUT;
-    }
-#endif
+  window->x = x;
+  window->y = y;
+  window->width = (attributes->width > 1) ? (attributes->width) : (1);
+  window->height = (attributes->height > 1) ? (attributes->height) : (1);
 
   if (attributes->wclass == GDK_INPUT_ONLY)
     {
@@ -1335,15 +1328,15 @@ gdk_window_new (GdkWindow     *parent,
        * before
        */
       if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
-       private->window_type = GDK_WINDOW_TEMP;
+       window->window_type = GDK_WINDOW_TEMP;
       else
-       private->window_type = GDK_WINDOW_CHILD;
+       window->window_type = GDK_WINDOW_CHILD;
     }
   else
-    private->window_type = attributes->window_type;
+    window->window_type = attributes->window_type;
 
   /* Sanity checks */
-  switch (private->window_type)
+  switch (window->window_type)
     {
     case GDK_WINDOW_TOPLEVEL:
     case GDK_WINDOW_TEMP:
@@ -1355,56 +1348,57 @@ gdk_window_new (GdkWindow     *parent,
       break;
       break;
     default:
-      g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
+      g_warning (G_STRLOC "cannot make windows of type %d", window->window_type);
       return NULL;
     }
 
   if (attributes_mask & GDK_WA_VISUAL)
-    private->visual = attributes->visual;
+    window->visual = attributes->visual;
   else
-    private->visual = gdk_screen_get_system_visual (screen);
+    window->visual = gdk_screen_get_system_visual (screen);
 
-  private->event_mask = attributes->event_mask;
+  window->event_mask = attributes->event_mask;
 
   if (attributes->wclass == GDK_INPUT_OUTPUT)
     {
-      private->input_only = FALSE;
-      private->depth = private->visual->depth;
+      window->input_only = FALSE;
+      window->depth = window->visual->depth;
 
       /* XXX: Cache this somehow? */
-      private->background = cairo_pattern_create_rgb (0, 0, 0);
+      window->background = cairo_pattern_create_rgb (0, 0, 0);
     }
   else
     {
-      private->depth = 0;
-      private->input_only = TRUE;
+      window->depth = 0;
+      window->input_only = TRUE;
     }
 
-  if (private->parent)
-    private->parent->children = g_list_prepend (private->parent->children, window);
+  if (window->parent)
+    window->parent->children = g_list_prepend (window->parent->children, window);
+
+  window->device_cursor = g_hash_table_new_full (NULL, NULL,
+                                                 NULL, g_object_unref);
 
   native = _gdk_native_windows; /* Default */
-  if (private->parent->window_type == GDK_WINDOW_ROOT)
+  if (window->parent->window_type == GDK_WINDOW_ROOT)
     native = TRUE; /* Always use native windows for toplevels */
-  else if (!private->input_only &&
-          ((attributes_mask & GDK_WA_COLORMAP &&
-            attributes->colormap != gdk_drawable_get_colormap ((GdkDrawable *)private->parent)) ||
-           (attributes_mask & GDK_WA_VISUAL &&
-            attributes->visual != gdk_window_get_visual (GDK_WINDOW (private->parent)))))
-    native = TRUE; /* InputOutput window with different colormap or visual than parent, needs native window */
+  else if (!window->input_only &&
+          (attributes_mask & GDK_WA_VISUAL &&
+           attributes->visual != gdk_window_get_visual (window->parent)))
+    native = TRUE; /* InputOutput window with different visual than parent, needs native window */
 
-  if (gdk_window_is_offscreen (private))
+  if (gdk_window_is_offscreen (window))
     {
-      _gdk_offscreen_window_new (window, screen, attributes, attributes_mask);
-      private->impl_window = private;
+      _gdk_offscreen_window_new (window, attributes, attributes_mask);
+      window->impl_window = window;
     }
   else if (native)
     {
-      event_mask = get_native_event_mask (private);
+      event_mask = get_native_event_mask (window);
 
       /* Create the impl */
-      _gdk_window_impl_new (window, real_parent, screen, event_mask, attributes, attributes_mask);
-      private->impl_window = private;
+      _gdk_display_create_window_impl (display, window, real_parent, screen, event_mask, attributes, attributes_mask);
+      window->impl_window = window;
 
       /* This will put the native window topmost in the native parent, which may
        * be wrong wrt other native windows in the non-native hierarchy, so restack */
@@ -1413,19 +1407,16 @@ gdk_window_new (GdkWindow     *parent,
     }
   else
     {
-      private->impl_window = g_object_ref (private->parent->impl_window);
-      private->impl = g_object_ref (private->impl_window->impl);
+      window->impl_window = g_object_ref (window->parent->impl_window);
+      window->impl = g_object_ref (window->impl_window->impl);
     }
 
-  recompute_visible_regions (private, TRUE, FALSE);
+  recompute_visible_regions (window, TRUE, FALSE);
 
   gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
                                  (attributes->cursor) :
                                  NULL));
 
-  private->device_cursor = g_hash_table_new_full (NULL, NULL, NULL,
-                                                  (GDestroyNotify) gdk_cursor_unref);
-
   device_manager = gdk_display_get_device_manager (gdk_window_get_display (parent));
   g_signal_connect (device_manager, "device-removed",
                     G_CALLBACK (device_removed_cb), window);
@@ -1452,14 +1443,14 @@ is_parent_of (GdkWindow *parent,
 }
 
 static void
-change_impl (GdkWindowObject *private,
-            GdkWindowObject *impl_window,
-            GdkDrawable *new)
+change_impl (GdkWindow *private,
+            GdkWindow *impl_window,
+            GdkWindowImpl *new)
 {
   GList *l;
-  GdkWindowObject *child;
-  GdkDrawable *old_impl;
-  GdkWindowObject *old_impl_window;
+  GdkWindow *child;
+  GdkWindowImpl *old_impl;
+  GdkWindow *old_impl_window;
 
   old_impl = private->impl;
   old_impl_window = private->impl_window;
@@ -1482,14 +1473,14 @@ change_impl (GdkWindowObject *private,
 }
 
 static void
-reparent_to_impl (GdkWindowObject *private)
+reparent_to_impl (GdkWindow *private)
 {
   GList *l;
-  GdkWindowObject *child;
+  GdkWindow *child;
   gboolean show;
-  GdkWindowImplIface *impl_iface;
+  GdkWindowImplClass *impl_class;
 
-  impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
+  impl_class = GDK_WINDOW_IMPL_GET_CLASS (private->impl);
 
   /* Enumerate in reverse order so we get the right order for the native
      windows (first in childrens list is topmost, and reparent places on top) */
@@ -1501,7 +1492,7 @@ reparent_to_impl (GdkWindowObject *private)
        reparent_to_impl (child);
       else
        {
-         show = impl_iface->reparent ((GdkWindow *)child,
+         show = impl_class->reparent ((GdkWindow *)child,
                                       (GdkWindow *)private,
                                       child->x, child->y);
          if (show)
@@ -1528,14 +1519,12 @@ gdk_window_reparent (GdkWindow *window,
                     gint       x,
                     gint       y)
 {
-  GdkWindowObject *private;
-  GdkWindowObject *new_parent_private;
-  GdkWindowObject *old_parent;
+  GdkWindow *old_parent;
   GdkScreen *screen;
   gboolean show, was_mapped, applied_clip_as_shape;
   gboolean do_reparent_to_impl;
   GdkEventMask old_native_event_mask;
-  GdkWindowImplIface *impl_iface;
+  GdkWindowImplClass *impl_class;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
@@ -1549,11 +1538,8 @@ gdk_window_reparent (GdkWindow *window,
   if (!new_parent)
     new_parent = gdk_screen_get_root_window (screen);
 
-  private = (GdkWindowObject *) window;
-  new_parent_private = (GdkWindowObject *)new_parent;
-
   /* No input-output children of input-only windows */
-  if (new_parent_private->input_only && !private->input_only)
+  if (new_parent->input_only && !window->input_only)
     return;
 
   /* Don't create loops in hierarchy */
@@ -1562,42 +1548,42 @@ gdk_window_reparent (GdkWindow *window,
 
   /* This might be wrong in the new parent, e.g. for non-native surfaces.
      To make sure we're ok, just wipe it. */
-  gdk_window_drop_cairo_surface (private);
+  gdk_window_drop_cairo_surface (window);
 
-  impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
-  old_parent = private->parent;
+  impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
+  old_parent = window->parent;
 
   was_mapped = GDK_WINDOW_IS_MAPPED (window);
   show = FALSE;
 
   /* Reparenting to toplevel. Ensure we have a native window so this can work */
-  if (new_parent_private->window_type == GDK_WINDOW_ROOT ||
-      new_parent_private->window_type == GDK_WINDOW_FOREIGN)
+  if (new_parent->window_type == GDK_WINDOW_ROOT ||
+      new_parent->window_type == GDK_WINDOW_FOREIGN)
     gdk_window_ensure_native (window);
 
-  applied_clip_as_shape = should_apply_clip_as_shape (private);
+  applied_clip_as_shape = should_apply_clip_as_shape (window);
 
   old_native_event_mask = 0;
   do_reparent_to_impl = FALSE;
-  if (gdk_window_has_impl (private))
+  if (gdk_window_has_impl (window))
     {
-      old_native_event_mask = get_native_event_mask (private);
+      old_native_event_mask = get_native_event_mask (window);
       /* Native window */
-      show = impl_iface->reparent (window, new_parent, x, y);
+      show = impl_class->reparent (window, new_parent, x, y);
     }
   else
     {
       /* This shouldn't happen, as we created a native in this case, check anyway to see if that ever fails */
-      g_assert (new_parent_private->window_type != GDK_WINDOW_ROOT &&
-               new_parent_private->window_type != GDK_WINDOW_FOREIGN);
+      g_assert (new_parent->window_type != GDK_WINDOW_ROOT &&
+               new_parent->window_type != GDK_WINDOW_FOREIGN);
 
       show = was_mapped;
       gdk_window_hide (window);
 
       do_reparent_to_impl = TRUE;
-      change_impl (private,
-                  new_parent_private->impl_window,
-                  new_parent_private->impl);
+      change_impl (window,
+                  new_parent->impl_window,
+                  new_parent->impl);
     }
 
   /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
@@ -1606,17 +1592,16 @@ gdk_window_reparent (GdkWindow *window,
   if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
     {
       new_parent = gdk_screen_get_root_window (screen);
-      new_parent_private = (GdkWindowObject *)new_parent;
     }
 
   if (old_parent)
     old_parent->children = g_list_remove (old_parent->children, window);
 
-  private->parent = new_parent_private;
-  private->x = x;
-  private->y = y;
+  window->parent = new_parent;
+  window->x = x;
+  window->y = y;
 
-  new_parent_private->children = g_list_prepend (new_parent_private->children, window);
+  new_parent->children = g_list_prepend (new_parent->children, window);
 
   /* Switch the window type as appropriate */
 
@@ -1624,8 +1609,8 @@ gdk_window_reparent (GdkWindow *window,
     {
     case GDK_WINDOW_ROOT:
     case GDK_WINDOW_FOREIGN:
-      if (private->toplevel_window_type != -1)
-       GDK_WINDOW_TYPE (window) = private->toplevel_window_type;
+      if (window->toplevel_window_type != -1)
+       GDK_WINDOW_TYPE (window) = window->toplevel_window_type;
       else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
        GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
       break;
@@ -1639,42 +1624,42 @@ gdk_window_reparent (GdkWindow *window,
          /* Save the original window type so we can restore it if the
           * window is reparented back to be a toplevel
           */
-         private->toplevel_window_type = GDK_WINDOW_TYPE (window);
+         window->toplevel_window_type = GDK_WINDOW_TYPE (window);
          GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
        }
     }
 
   /* We might have changed window type for a native windows, so we
      need to change the event mask too. */
-  if (gdk_window_has_impl (private))
+  if (gdk_window_has_impl (window))
     {
-      GdkEventMask native_event_mask = get_native_event_mask (private);
+      GdkEventMask native_event_mask = get_native_event_mask (window);
 
       if (native_event_mask != old_native_event_mask)
-       impl_iface->set_events (window, native_event_mask);
+       impl_class->set_events (window, native_event_mask);
     }
 
   _gdk_window_update_viewable (window);
 
-  recompute_visible_regions (private, TRUE, FALSE);
+  recompute_visible_regions (window, TRUE, FALSE);
   if (old_parent && GDK_WINDOW_TYPE (old_parent) != GDK_WINDOW_ROOT)
     recompute_visible_regions (old_parent, FALSE, TRUE);
 
   /* We used to apply the clip as the shape, but no more.
      Reset this to the real shape */
-  if (gdk_window_has_impl (private) &&
+  if (gdk_window_has_impl (window) &&
       applied_clip_as_shape &&
-      !should_apply_clip_as_shape (private))
-    apply_shape (private, private->shape);
+      !should_apply_clip_as_shape (window))
+    apply_shape (window, window->shape);
 
   if (do_reparent_to_impl)
-    reparent_to_impl (private);
+    reparent_to_impl (window);
   else
     {
       /* The reparent will have put the native window topmost in the native parent,
        * which may be wrong wrt other native windows in the non-native hierarchy,
        * so restack */
-      if (!gdk_window_has_impl (new_parent_private))
+      if (!gdk_window_has_impl (new_parent))
        sync_native_window_stack_position (window);
     }
 
@@ -1684,67 +1669,6 @@ gdk_window_reparent (GdkWindow *window,
     _gdk_synthesize_crossing_events_for_geometry_change (window);
 }
 
-static gboolean
-temporary_disable_extension_events (GdkWindowObject *window)
-{
-  GdkWindowObject *child;
-  GList *l;
-  gboolean res;
-
-  if (window->extension_events != 0)
-    {
-      g_object_set_data (G_OBJECT (window),
-                        "gdk-window-extension-events",
-                        GINT_TO_POINTER (window->extension_events));
-      gdk_input_set_extension_events ((GdkWindow *)window, 0,
-                                     GDK_EXTENSION_EVENTS_NONE);
-    }
-  else
-    res = FALSE;
-
-  for (l = window->children; l != NULL; l = l->next)
-    {
-      child = l->data;
-
-      if (window->impl_window == child->impl_window)
-       res |= temporary_disable_extension_events (child);
-    }
-
-  return res;
-}
-
-static void
-reenable_extension_events (GdkWindowObject *window)
-{
-  GdkWindowObject *child;
-  GList *l;
-  int mask;
-
-  mask = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window),
-                                             "gdk-window-extension-events"));
-
-  if (mask != 0)
-    {
-      /* We don't have the mode here, so we pass in cursor.
-        This works with the current code since mode is not
-        stored except as part of the mask, and cursor doesn't
-        change the mask. */
-      gdk_input_set_extension_events ((GdkWindow *)window, mask,
-                                     GDK_EXTENSION_EVENTS_CURSOR);
-      g_object_set_data (G_OBJECT (window),
-                        "gdk-window-extension-events",
-                        NULL);
-    }
-
-  for (l = window->children; l != NULL; l = l->next)
-    {
-      child = l->data;
-
-      if (window->impl_window == child->impl_window)
-       reenable_extension_events (window);
-    }
-}
-
 /**
  * gdk_window_ensure_native:
  * @window: a #GdkWindow
@@ -1763,15 +1687,13 @@ reenable_extension_events (GdkWindowObject *window)
 gboolean
 gdk_window_ensure_native (GdkWindow *window)
 {
-  GdkWindowObject *private;
-  GdkWindowObject *impl_window;
-  GdkDrawable *new_impl, *old_impl;
+  GdkWindow *impl_window;
+  GdkWindowImpl *new_impl, *old_impl;
+  GdkDisplay *display;
   GdkScreen *screen;
-  GdkWindowAttr attributes;
-  GdkWindowObject *above;
+  GdkWindow *above;
   GList listhead;
-  GdkWindowImplIface *impl_iface;
-  gboolean disabled_extension_events;
+  GdkWindowImplClass *impl_class;
 
   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
@@ -1779,100 +1701,122 @@ gdk_window_ensure_native (GdkWindow *window)
       GDK_WINDOW_DESTROYED (window))
     return FALSE;
 
-  private = (GdkWindowObject *) window;
-
-  impl_window = gdk_window_get_impl_window (private);
+  impl_window = gdk_window_get_impl_window (window);
 
   if (gdk_window_is_offscreen (impl_window))
     return FALSE; /* native in offscreens not supported */
 
-  if (impl_window == private)
+  if (impl_window == window)
     /* Already has an impl, and its not offscreen . */
     return TRUE;
 
   /* Need to create a native window */
 
-  /* First we disable any extension events on the window or its
-     descendants to handle the native input window moving */
-  disabled_extension_events = FALSE;
-  if (impl_window->input_window)
-    disabled_extension_events = temporary_disable_extension_events (private);
-
-  gdk_window_drop_cairo_surface (private);
+  gdk_window_drop_cairo_surface (window);
 
   screen = gdk_window_get_screen (window);
+  display = gdk_screen_get_display (screen);
 
-  attributes.colormap = gdk_drawable_get_colormap (window);
+  old_impl = window->impl;
+  _gdk_display_create_window_impl (display,
+                                   window, window->parent,
+                                   screen,
+                                   get_native_event_mask (window),
+                                   NULL, 0);
+  new_impl = window->impl;
 
-  old_impl = private->impl;
-  _gdk_window_impl_new (window, (GdkWindow *)private->parent,
-                       screen,
-                       get_native_event_mask (private),
-                       &attributes, GDK_WA_COLORMAP);
-  new_impl = private->impl;
-
-  private->impl = old_impl;
-  change_impl (private, private, new_impl);
+  window->impl = old_impl;
+  change_impl (window, window, new_impl);
 
-  impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
+  impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 
   /* Native window creation will put the native window topmost in the
    * native parent, which may be wrong wrt the position of the previous
    * non-native window wrt to the other non-native children, so correct this.
    */
-  above = find_native_sibling_above (private->parent, private);
+  above = find_native_sibling_above (window->parent, window);
   if (above)
     {
       listhead.data = window;
       listhead.prev = NULL;
       listhead.next = NULL;
-      impl_iface->restack_under ((GdkWindow *)above, &listhead);
+      impl_class->restack_under ((GdkWindow *)above, &listhead);
     }
 
-  recompute_visible_regions (private, FALSE, FALSE);
+  recompute_visible_regions (window, FALSE, FALSE);
 
   /* The shape may not have been set, as the clip region doesn't actually
      change, so do it here manually */
-  if (should_apply_clip_as_shape (private))
-    apply_clip_as_shape (private);
+  if (should_apply_clip_as_shape (window))
+    apply_clip_as_shape (window);
 
-  reparent_to_impl (private);
+  reparent_to_impl (window);
 
-  if (!private->input_only)
-    {
-      impl_iface->set_background (window, private->background);
-    }
+  if (!window->input_only)
+    impl_class->set_background (window, window->background);
 
-  impl_iface->input_shape_combine_region (window,
-                                         private->input_shape,
-                                         0, 0);
+  impl_class->input_shape_combine_region (window,
+                                          window->input_shape,
+                                          0, 0);
 
   if (gdk_window_is_viewable (window))
-    impl_iface->show (window, FALSE);
-
-  if (disabled_extension_events)
-    reenable_extension_events (private);
+    impl_class->show (window, FALSE);
 
   return TRUE;
 }
 
-static void
-window_remove_filters (GdkWindow *window)
+/**
+ * _gdk_event_filter_unref:
+ * @window: A #GdkWindow, or %NULL to be the global window
+ * @filter: A window filter
+ *
+ * Release a reference to @filter.  Note this function may
+ * mutate the list storage, so you need to handle this
+ * if iterating over a list of filters.
+ */
+void
+_gdk_event_filter_unref (GdkWindow       *window,
+                        GdkEventFilter  *filter)
 {
-  GdkWindowObject *obj = (GdkWindowObject*) window;
+  GList **filters;
+  GList *tmp_list;
+
+  if (window == NULL)
+    filters = &_gdk_default_filters;
+  else
+    filters = &window->filters;
 
-  if (obj->filters)
+  tmp_list = *filters;
+  while (tmp_list)
     {
-      GList *tmp_list;
+      GdkEventFilter *iter_filter = tmp_list->data;
+      GList *node;
 
-      for (tmp_list = obj->filters; tmp_list; tmp_list = tmp_list->next)
-       g_free (tmp_list->data);
+      node = tmp_list;
+      tmp_list = tmp_list->next;
+
+      if (iter_filter != filter)
+       continue;
 
-      g_list_free (obj->filters);
-      obj->filters = NULL;
+      g_assert (iter_filter->ref_count > 0);
+
+      filter->ref_count--;
+      if (filter->ref_count != 0)
+       continue;
+
+      *filters = g_list_remove_link (*filters, node);
+      g_free (filter);
+      g_list_free_1 (node);
     }
 }
 
+static void
+window_remove_filters (GdkWindow *window)
+{
+  while (window->filters)
+    _gdk_event_filter_unref (window, window->filters->data);
+}
+
 static void
 update_pointer_info_foreach (GdkDisplay           *display,
                              GdkDevice            *device,
@@ -1921,9 +1865,7 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
                               gboolean   recursing_native,
                               gboolean   foreign_destroy)
 {
-  GdkWindowObject *private;
-  GdkWindowObject *temp_private;
-  GdkWindowImplIface *impl_iface;
+  GdkWindowImplClass *impl_class;
   GdkWindow *temp_window;
   GdkScreen *screen;
   GdkDisplay *display;
@@ -1932,8 +1874,6 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  private = (GdkWindowObject*) window;
-
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
@@ -1944,7 +1884,7 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
     g_object_set_qdata (G_OBJECT (screen), quark_pointer_window, NULL);
 
 
-  switch (private->window_type)
+  switch (window->window_type)
     {
     case GDK_WINDOW_ROOT:
       if (!screen->closed)
@@ -1958,7 +1898,7 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
     case GDK_WINDOW_TEMP:
     case GDK_WINDOW_FOREIGN:
     case GDK_WINDOW_OFFSCREEN:
-      if (private->window_type == GDK_WINDOW_FOREIGN && !foreign_destroy)
+      if (window->window_type == GDK_WINDOW_FOREIGN && !foreign_destroy)
        {
          /* Logically, it probably makes more sense to send
           * a "destroy yourself" message to the foreign window
@@ -1966,8 +1906,13 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
           * reasons, we only send "destroy yourself" messages to
           * foreign windows in our hierarchy.
           */
-         if (private->parent)
-           _gdk_windowing_window_destroy_foreign (window);
+         if (window->parent)
+            {
+              impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
+
+              if (gdk_window_has_impl (window))
+                impl_class->destroy_foreign (window);
+            }
 
          /* Also for historical reasons, we remove any filters
           * on a foreign window when it or a parent is destroyed;
@@ -1978,48 +1923,43 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
        }
       else
        {
-         if (private->parent)
+         if (window->parent)
            {
-             GdkWindowObject *parent_private = (GdkWindowObject *)private->parent;
-
-             if (parent_private->children)
-               parent_private->children = g_list_remove (parent_private->children, window);
+             if (window->parent->children)
+               window->parent->children = g_list_remove (window->parent->children, window);
 
              if (!recursing &&
                  GDK_WINDOW_IS_MAPPED (window))
                {
-                 recompute_visible_regions (private, TRUE, FALSE);
-                 gdk_window_invalidate_in_parent (private);
+                 recompute_visible_regions (window, TRUE, FALSE);
+                 gdk_window_invalidate_in_parent (window);
                }
            }
 
          gdk_window_free_paint_stack (window);
 
-          gdk_window_set_background_pattern (window, NULL);
-
-          if (private->background)
+          if (window->background)
             {
-              cairo_pattern_destroy (private->background);
-              private->background = NULL;
+              cairo_pattern_destroy (window->background);
+              window->background = NULL;
             }
 
-         if (private->window_type == GDK_WINDOW_FOREIGN)
-           g_assert (private->children == NULL);
+         if (window->window_type == GDK_WINDOW_FOREIGN)
+           g_assert (window->children == NULL);
          else
            {
-             children = tmp = private->children;
-             private->children = NULL;
+             children = tmp = window->children;
+             window->children = NULL;
 
              while (tmp)
                {
                  temp_window = tmp->data;
                  tmp = tmp->next;
 
-                 temp_private = (GdkWindowObject*) temp_window;
-                 if (temp_private)
+                 if (temp_window)
                    _gdk_window_destroy_hierarchy (temp_window,
                                                   TRUE,
-                                                  recursing_native || gdk_window_has_impl (private),
+                                                  recursing_native || gdk_window_has_impl (window),
                                                   foreign_destroy);
                }
 
@@ -2028,12 +1968,12 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
 
          _gdk_window_clear_update_area (window);
 
-         gdk_window_drop_cairo_surface (private);
+         gdk_window_drop_cairo_surface (window);
 
-         impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
+         impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 
-         if (gdk_window_has_impl (private))
-           impl_iface->destroy (window, recursing_native,
+         if (gdk_window_has_impl (window))
+           impl_class->destroy (window, recursing_native,
                                 foreign_destroy);
          else
            {
@@ -2041,31 +1981,31 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
              gdk_window_hide (window);
            }
 
-         private->state |= GDK_WINDOW_STATE_WITHDRAWN;
-         private->parent = NULL;
-         private->destroyed = TRUE;
+         window->state |= GDK_WINDOW_STATE_WITHDRAWN;
+         window->parent = NULL;
+         window->destroyed = TRUE;
 
          window_remove_filters (window);
 
          window_remove_from_pointer_info (window, display);
 
-         if (private->clip_region)
+         if (window->clip_region)
            {
-             cairo_region_destroy (private->clip_region);
-             private->clip_region = NULL;
+             cairo_region_destroy (window->clip_region);
+             window->clip_region = NULL;
            }
 
-         if (private->clip_region_with_children)
+         if (window->clip_region_with_children)
            {
-             cairo_region_destroy (private->clip_region_with_children);
-             private->clip_region_with_children = NULL;
+             cairo_region_destroy (window->clip_region_with_children);
+             window->clip_region_with_children = NULL;
            }
 
-         if (private->outstanding_moves)
+         if (window->outstanding_moves)
            {
-             g_list_foreach (private->outstanding_moves, (GFunc)gdk_window_region_move_free, NULL);
-             g_list_free (private->outstanding_moves);
-             private->outstanding_moves = NULL;
+             g_list_foreach (window->outstanding_moves, (GFunc)gdk_window_region_move_free, NULL);
+             g_list_free (window->outstanding_moves);
+             window->outstanding_moves = NULL;
            }
        }
       break;
@@ -2129,7 +2069,7 @@ gdk_window_set_user_data (GdkWindow *window,
 {
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  ((GdkWindowObject*)window)->user_data = user_data;
+  window->user_data = user_data;
 }
 
 /**
@@ -2147,7 +2087,7 @@ gdk_window_get_user_data (GdkWindow *window,
 {
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  *data = ((GdkWindowObject*)window)->user_data;
+  *data = window->user_data;
 }
 
 /**
@@ -2172,18 +2112,16 @@ gdk_window_get_window_type (GdkWindow *window)
  * 
  * Gets the #GdkVisual describing the pixel format of @window.
  * 
- * Return value: a #GdkVisual
+ * Return value: (transfer none): a #GdkVisual
+ *
+ * Since: 2.24
  **/
 GdkVisual*
 gdk_window_get_visual (GdkWindow *window)
 {
-  GdkWindowObject *private;
-
   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
   
-  private = (GdkWindowObject *) window;
-
-  return private->visual;
+  return window->visual;
 }
 
 /**
@@ -2192,18 +2130,16 @@ gdk_window_get_visual (GdkWindow *window)
  * 
  * Gets the #GdkScreen associated with a #GdkWindow.
  * 
- * Return value: the #GdkScreen associated with @window
+ * Return value: (transfer none): the #GdkScreen associated with @window
+ *
+ * Since: 2.24
  **/
 GdkScreen*
 gdk_window_get_screen (GdkWindow *window)
 {
-  GdkWindowObject *private;
-
   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 
-  private = (GdkWindowObject *) window;
-
-  return gdk_visual_get_screen (private->visual);
+  return gdk_visual_get_screen (window->visual);
 }
 
 /**
@@ -2212,18 +2148,16 @@ gdk_window_get_screen (GdkWindow *window)
  * 
  * Gets the #GdkDisplay associated with a #GdkWindow.
  * 
- * Return value: the #GdkDisplay associated with @window
+ * Return value: (transfer none): the #GdkDisplay associated with @window
+ *
+ * Since: 2.24
  **/
 GdkDisplay *
 gdk_window_get_display (GdkWindow *window)
 {
-  GdkWindowObject *private;
-
   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 
-  private = (GdkWindowObject *) window;
-
-  return gdk_screen_get_display (gdk_visual_get_screen (private->visual));
+  return gdk_screen_get_display (gdk_visual_get_screen (window->visual));
 }
 /**
  * gdk_window_is_destroyed:
@@ -2242,11 +2176,11 @@ gdk_window_is_destroyed (GdkWindow *window)
 }
 
 static void
-to_embedder (GdkWindowObject *window,
-             gdouble          offscreen_x,
-             gdouble          offscreen_y,
-             gdouble         *embedder_x,
-             gdouble         *embedder_y)
+to_embedder (GdkWindow *window,
+             gdouble    offscreen_x,
+             gdouble    offscreen_y,
+             gdouble   *embedder_x,
+             gdouble   *embedder_y)
 {
   g_signal_emit (window, signals[TO_EMBEDDER], 0,
                  offscreen_x, offscreen_y,
@@ -2254,11 +2188,11 @@ to_embedder (GdkWindowObject *window,
 }
 
 static void
-from_embedder (GdkWindowObject *window,
-               gdouble          embedder_x,
-               gdouble          embedder_y,
-               gdouble         *offscreen_x,
-               gdouble         *offscreen_y)
+from_embedder (GdkWindow *window,
+               gdouble    embedder_x,
+               gdouble    embedder_y,
+               gdouble   *offscreen_x,
+               gdouble   *offscreen_y)
 {
   g_signal_emit (window, signals[FROM_EMBEDDER], 0,
                  embedder_x, embedder_y,
@@ -2279,20 +2213,16 @@ from_embedder (GdkWindowObject *window,
 gboolean
 gdk_window_has_native (GdkWindow *window)
 {
-  GdkWindowObject *w;
-
   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
-  w = GDK_WINDOW_OBJECT (window);
-
-  return w->parent == NULL || w->parent->impl != w->impl;
+  return window->parent == NULL || window->parent->impl != window->impl;
 }
 
 /**
  * gdk_window_get_position:
  * @window: a #GdkWindow
- * @x: X coordinate of window
- * @y: Y coordinate of window
+ * @x: (out) (allow-none): X coordinate of window
+ * @y: (out) (allow-none): Y coordinate of window
  *
  * Obtains the position of the window as reported in the
  * most-recently-processed #GdkEventConfigure. Contrast with
@@ -2308,16 +2238,12 @@ gdk_window_get_position (GdkWindow *window,
                         gint      *x,
                         gint      *y)
 {
-  GdkWindowObject *obj;
-
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  obj = (GdkWindowObject*) window;
-
   if (x)
-    *x = obj->x;
+    *x = window->x;
   if (y)
-    *y = obj->y;
+    *y = window->y;
 }
 
 /**
@@ -2343,7 +2269,7 @@ gdk_window_get_parent (GdkWindow *window)
 {
   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 
-  return (GdkWindow*) ((GdkWindowObject*) window)->parent;
+  return window->parent;
 }
 
 /**
@@ -2363,16 +2289,12 @@ gdk_window_get_parent (GdkWindow *window)
 GdkWindow *
 gdk_window_get_effective_parent (GdkWindow *window)
 {
-  GdkWindowObject *obj;
-
   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 
-  obj = (GdkWindowObject *)window;
-
-  if (gdk_window_is_offscreen (obj))
+  if (gdk_window_is_offscreen (window))
     return gdk_offscreen_window_get_embedder (window);
   else
-    return (GdkWindow *) obj->parent;
+    return window->parent;
 }
 
 /**
@@ -2395,20 +2317,16 @@ gdk_window_get_effective_parent (GdkWindow *window)
 GdkWindow *
 gdk_window_get_toplevel (GdkWindow *window)
 {
-  GdkWindowObject *obj;
-
   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 
-  obj = (GdkWindowObject *)window;
-
-  while (obj->window_type == GDK_WINDOW_CHILD)
+  while (window->window_type == GDK_WINDOW_CHILD)
     {
-      if (gdk_window_is_toplevel (obj))
+      if (gdk_window_is_toplevel (window))
        break;
-      obj = obj->parent;
+      window = window->parent;
     }
 
-  return GDK_WINDOW (obj);
+  return window;
 }
 
 /**
@@ -2463,7 +2381,7 @@ gdk_window_get_children (GdkWindow *window)
   if (GDK_WINDOW_DESTROYED (window))
     return NULL;
 
-  return g_list_copy (GDK_WINDOW_OBJECT (window)->children);
+  return g_list_copy (window->children);
 }
 
 /**
@@ -2484,7 +2402,7 @@ gdk_window_peek_children (GdkWindow *window)
   if (GDK_WINDOW_DESTROYED (window))
     return NULL;
 
-  return GDK_WINDOW_OBJECT (window)->children;
+  return window->children;
 }
 
 /**
@@ -2507,14 +2425,12 @@ gdk_window_add_filter (GdkWindow     *window,
                       GdkFilterFunc  function,
                       gpointer       data)
 {
-  GdkWindowObject *private;
   GList *tmp_list;
   GdkEventFilter *filter;
 
   g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
 
-  private = (GdkWindowObject*) window;
-  if (private && GDK_WINDOW_DESTROYED (window))
+  if (window && GDK_WINDOW_DESTROYED (window))
     return;
 
   /* Filters are for the native events on the native window, so
@@ -2522,8 +2438,8 @@ gdk_window_add_filter (GdkWindow     *window,
   if (window)
     gdk_window_ensure_native (window);
 
-  if (private)
-    tmp_list = private->filters;
+  if (window)
+    tmp_list = window->filters;
   else
     tmp_list = _gdk_default_filters;
 
@@ -2531,16 +2447,21 @@ gdk_window_add_filter (GdkWindow     *window,
     {
       filter = (GdkEventFilter *)tmp_list->data;
       if ((filter->function == function) && (filter->data == data))
-       return;
+        {
+          filter->ref_count++;
+          return;
+        }
       tmp_list = tmp_list->next;
     }
 
   filter = g_new (GdkEventFilter, 1);
   filter->function = function;
   filter->data = data;
+  filter->ref_count = 1;
+  filter->flags = 0;
 
-  if (private)
-    private->filters = g_list_append (private->filters, filter);
+  if (window)
+    window->filters = g_list_append (window->filters, filter);
   else
     _gdk_default_filters = g_list_append (_gdk_default_filters, filter);
 }
@@ -2559,16 +2480,13 @@ gdk_window_remove_filter (GdkWindow     *window,
                          GdkFilterFunc  function,
                          gpointer       data)
 {
-  GdkWindowObject *private;
   GList *tmp_list, *node;
   GdkEventFilter *filter;
 
   g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
 
-  private = (GdkWindowObject*) window;
-
-  if (private)
-    tmp_list = private->filters;
+  if (window)
+    tmp_list = window->filters;
   else
     tmp_list = _gdk_default_filters;
 
@@ -2580,12 +2498,9 @@ gdk_window_remove_filter (GdkWindow     *window,
 
       if ((filter->function == function) && (filter->data == data))
        {
-         if (private)
-           private->filters = g_list_remove_link (private->filters, node);
-         else
-           _gdk_default_filters = g_list_remove_link (_gdk_default_filters, node);
-         g_list_free_1 (node);
-         g_free (filter);
+          filter->flags |= GDK_EVENT_FILTER_REMOVED;
+
+         _gdk_event_filter_unref (window, filter);
 
          return;
        }
@@ -2619,10 +2534,10 @@ gdk_screen_get_toplevel_windows (GdkScreen *screen)
 
   root_window = gdk_screen_get_root_window (screen);
 
-  tmp_list = ((GdkWindowObject *)root_window)->children;
+  tmp_list = root_window->children;
   while (tmp_list)
     {
-      GdkWindowObject *w = tmp_list->data;
+      GdkWindow *w = tmp_list->data;
 
       if (w->window_type != GDK_WINDOW_FOREIGN)
        new_list = g_list_prepend (new_list, w);
@@ -2663,14 +2578,12 @@ gdk_window_is_visible (GdkWindow *window)
 gboolean
 gdk_window_is_viewable (GdkWindow *window)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-
   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
-  if (private->destroyed)
+  if (window->destroyed)
     return FALSE;
 
-  return private->viewable;
+  return window->viewable;
 }
 
 /**
@@ -2685,11 +2598,9 @@ gdk_window_is_viewable (GdkWindow *window)
 GdkWindowState
 gdk_window_get_state (GdkWindow *window)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-
   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
-  return private->state;
+  return window->state;
 }
 
 static cairo_content_t
@@ -2700,7 +2611,7 @@ gdk_window_get_content (GdkWindow *window)
 
   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
 
-  surface = _gdk_drawable_ref_cairo_surface (window);
+  surface = _gdk_window_ref_cairo_surface (window);
   content = cairo_surface_get_content (surface);
   cairo_surface_destroy (surface);
 
@@ -2721,30 +2632,26 @@ gdk_window_get_content (GdkWindow *window)
 static gboolean
 gdk_window_begin_implicit_paint (GdkWindow *window, GdkRectangle *rect)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
   GdkWindowPaint *paint;
 
-  g_assert (gdk_window_has_impl (private));
+  g_assert (gdk_window_has_impl (window));
 
   if (_gdk_native_windows)
     return FALSE; /* No need for implicit paints since we can't merge draws anyway */
 
-  if (GDK_IS_PAINTABLE (private->impl))
+  if (GDK_IS_PAINTABLE (window->impl))
     return FALSE; /* Implementation does double buffering */
 
-  if (private->paint_stack != NULL ||
-      private->implicit_paint != NULL)
+  if (window->paint_stack != NULL ||
+      window->implicit_paint != NULL)
     return FALSE; /* Don't stack implicit paints */
 
-  if (private->outstanding_surfaces != 0)
-    return FALSE; /* May conflict with direct drawing to cairo surface */
-
   /* Never do implicit paints for foreign windows, they don't need
    * double buffer combination since they have no client side children,
    * and creating surfaces for them is risky since they could disappear
    * at any time
    */
-  if (private->window_type == GDK_WINDOW_FOREIGN)
+  if (window->window_type == GDK_WINDOW_FOREIGN)
     return FALSE;
 
   paint = g_new (GdkWindowPaint, 1);
@@ -2757,41 +2664,60 @@ gdk_window_begin_implicit_paint (GdkWindow *window, GdkRectangle *rect)
                                                       MAX (rect->height, 1));
   cairo_surface_set_device_offset (paint->surface, -rect->x, -rect->y);
 
-  private->implicit_paint = paint;
+  window->implicit_paint = paint;
 
   return TRUE;
 }
 
+static cairo_surface_t *
+gdk_window_ref_impl_surface (GdkWindow *window)
+{
+  return GDK_WINDOW_IMPL_GET_CLASS (window->impl)->ref_cairo_surface (window);
+}
+
+static cairo_t *
+gdk_cairo_create_for_impl (GdkWindow *window)
+{
+  cairo_surface_t *surface;
+  cairo_t *cr;
+
+  surface = gdk_window_ref_impl_surface (window);
+  cr = cairo_create (surface);
+
+  cairo_surface_destroy (surface);
+
+  return cr;
+}
+
 /* Ensure that all content related to this (sub)window is pushed to the
    native region. If there is an active paint then that area is not
    pushed, in order to not show partially finished double buffers. */
 static void
 gdk_window_flush_implicit_paint (GdkWindow *window)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkWindowObject *impl_window;
+  GdkWindow *impl_window;
   GdkWindowPaint *paint;
   cairo_region_t *region;
   GSList *list;
 
-  impl_window = gdk_window_get_impl_window (private);
+  impl_window = gdk_window_get_impl_window (window);
   if (impl_window->implicit_paint == NULL)
     return;
 
   paint = impl_window->implicit_paint;
   paint->flushed = TRUE;
-  region = cairo_region_copy (private->clip_region_with_children);
+  region = cairo_region_copy (window->clip_region_with_children);
 
   /* Don't flush active double buffers, as that may show partially done
    * rendering */
-  for (list = private->paint_stack; list != NULL; list = list->next)
+  for (list = window->paint_stack; list != NULL; list = list->next)
     {
       GdkWindowPaint *tmp_paint = list->data;
 
       cairo_region_subtract (region, tmp_paint->region);
     }
 
-  cairo_region_translate (region, -private->abs_x, -private->abs_y);
+  cairo_region_translate (region, -window->abs_x, -window->abs_y);
   cairo_region_intersect (region, paint->region);
 
   if (!GDK_WINDOW_DESTROYED (window) && !cairo_region_is_empty (region))
@@ -2802,7 +2728,7 @@ gdk_window_flush_implicit_paint (GdkWindow *window)
       cairo_region_subtract (paint->region, region);
 
       /* Some regions are valid, push these to window now */
-      cr = gdk_cairo_create (private->impl);
+      cr = gdk_cairo_create_for_impl (window);
       gdk_cairo_region (cr, region);
       cairo_clip (cr);
       cairo_set_source_surface (cr, paint->surface, 0, 0);
@@ -2818,23 +2744,22 @@ gdk_window_flush_implicit_paint (GdkWindow *window)
 static void
 gdk_window_end_implicit_paint (GdkWindow *window)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
   GdkWindowPaint *paint;
 
-  g_assert (gdk_window_has_impl (private));
+  g_assert (gdk_window_has_impl (window));
 
-  g_assert (private->implicit_paint != NULL);
+  g_assert (window->implicit_paint != NULL);
 
-  paint = private->implicit_paint;
+  paint = window->implicit_paint;
 
-  private->implicit_paint = NULL;
+  window->implicit_paint = NULL;
 
   if (!GDK_WINDOW_DESTROYED (window) && !cairo_region_is_empty (paint->region))
     {
       cairo_t *cr;
 
       /* Some regions are valid, push these to window now */
-      cr = gdk_cairo_create (private->impl);
+      cr = gdk_cairo_create_for_impl (window);
       gdk_cairo_region (cr, paint->region);
       cairo_clip (cr);
       cairo_set_source_surface (cr, paint->surface, 0, 0);
@@ -2922,10 +2847,9 @@ gdk_window_begin_paint_region (GdkWindow       *window,
                               const cairo_region_t *region)
 {
 #ifdef USE_BACKING_STORE
-  GdkWindowObject *private = (GdkWindowObject *)window;
   GdkRectangle clip_box;
   GdkWindowPaint *paint, *implicit_paint;
-  GdkWindowObject *impl_window;
+  GdkWindow *impl_window;
   GSList *list;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
@@ -2933,27 +2857,27 @@ gdk_window_begin_paint_region (GdkWindow       *window,
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
-  if (GDK_IS_PAINTABLE (private->impl))
+  if (GDK_IS_PAINTABLE (window->impl))
     {
-      GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
+      GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (window->impl);
 
       if (iface->begin_paint_region)
-       iface->begin_paint_region ((GdkPaintable*)private->impl, window, region);
+       iface->begin_paint_region ((GdkPaintable*)window->impl, window, region);
 
       return;
     }
 
-  impl_window = gdk_window_get_impl_window (private);
+  impl_window = gdk_window_get_impl_window (window);
   implicit_paint = impl_window->implicit_paint;
 
   paint = g_new (GdkWindowPaint, 1);
   paint->region = cairo_region_copy (region);
   paint->region_tag = new_region_tag ();
 
-  cairo_region_intersect (paint->region, private->clip_region_with_children);
+  cairo_region_intersect (paint->region, window->clip_region_with_children);
   cairo_region_get_extents (paint->region, &clip_box);
 
-  cairo_region_translate (paint->region, private->abs_x, private->abs_y);
+  cairo_region_translate (paint->region, window->abs_x, window->abs_y);
 
   /* Mark the region as valid on the implicit paint */
 
@@ -2961,14 +2885,14 @@ gdk_window_begin_paint_region (GdkWindow       *window,
     cairo_region_union (implicit_paint->region, paint->region);
 
   /* Convert back to normal coords */
-  cairo_region_translate (paint->region, -private->abs_x, -private->abs_y);
+  cairo_region_translate (paint->region, -window->abs_x, -window->abs_y);
 
   if (implicit_paint)
     {
       paint->uses_implicit = TRUE;
       paint->surface = cairo_surface_create_for_rectangle (implicit_paint->surface,
-                                                           private->abs_x + clip_box.x,
-                                                           private->abs_y + clip_box.y,
+                                                           window->abs_x + clip_box.x,
+                                                           window->abs_y + clip_box.y,
                                                           MAX (clip_box.width, 1),
                                                            MAX (clip_box.height, 1));
     }
@@ -2982,14 +2906,14 @@ gdk_window_begin_paint_region (GdkWindow       *window,
     }
   cairo_surface_set_device_offset (paint->surface, -clip_box.x, -clip_box.y);
 
-  for (list = private->paint_stack; list != NULL; list = list->next)
+  for (list = window->paint_stack; list != NULL; list = list->next)
     {
       GdkWindowPaint *tmp_paint = list->data;
 
       cairo_region_subtract (tmp_paint->region, paint->region);
     }
 
-  private->paint_stack = g_slist_prepend (private->paint_stack, paint);
+  window->paint_stack = g_slist_prepend (window->paint_stack, paint);
 
   if (!cairo_region_is_empty (paint->region))
     {
@@ -3017,8 +2941,7 @@ void
 gdk_window_end_paint (GdkWindow *window)
 {
 #ifdef USE_BACKING_STORE
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkWindowObject *composited;
+  GdkWindow *composited;
   GdkWindowPaint *paint;
   GdkRectangle clip_box;
   cairo_region_t *full_clip;
@@ -3028,25 +2951,25 @@ gdk_window_end_paint (GdkWindow *window)
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
-  if (GDK_IS_PAINTABLE (private->impl))
+  if (GDK_IS_PAINTABLE (window->impl))
     {
-      GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
+      GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (window->impl);
 
       if (iface->end_paint)
-       iface->end_paint ((GdkPaintable*)private->impl);
+       iface->end_paint ((GdkPaintable*)window->impl);
       return;
     }
 
-  if (private->paint_stack == NULL)
+  if (window->paint_stack == NULL)
     {
       g_warning (G_STRLOC": no preceding call to gdk_window_begin_paint_region(), see documentation");
       return;
     }
 
-  paint = private->paint_stack->data;
+  paint = window->paint_stack->data;
 
-  private->paint_stack = g_slist_delete_link (private->paint_stack,
-                                             private->paint_stack);
+  window->paint_stack = g_slist_delete_link (window->paint_stack,
+                                            window->paint_stack);
 
   cairo_region_get_extents (paint->region, &clip_box);
 
@@ -3056,7 +2979,7 @@ gdk_window_end_paint (GdkWindow *window)
 
       gdk_window_flush_outstanding_moves (window);
 
-      full_clip = cairo_region_copy (private->clip_region_with_children);
+      full_clip = cairo_region_copy (window->clip_region_with_children);
       cairo_region_intersect (full_clip, paint->region);
 
       cr = gdk_cairo_create (window);
@@ -3078,19 +3001,14 @@ gdk_window_end_paint (GdkWindow *window)
    * stop if parent becomes NULL since then we'd have nowhere
    * to draw (ie: 'composited' will always be non-NULL here).
    */
-  for (composited = private;
+  for (composited = window;
        composited->parent;
        composited = composited->parent)
     {
-      int width, height;
-
-      gdk_drawable_get_size (GDK_DRAWABLE (composited->parent),
-                            &width, &height);
-
       clip_box.x += composited->x;
       clip_box.y += composited->y;
-      clip_box.width = MIN (clip_box.width, width - clip_box.x);
-      clip_box.height = MIN (clip_box.height, height - clip_box.y);
+      clip_box.width = MIN (clip_box.width, composited->parent->width - clip_box.x);
+      clip_box.height = MIN (clip_box.height, composited->parent->height - clip_box.y);
 
       if (composited->composited)
        {
@@ -3105,17 +3023,15 @@ gdk_window_end_paint (GdkWindow *window)
 static void
 gdk_window_free_paint_stack (GdkWindow *window)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-
-  if (private->paint_stack)
+  if (window->paint_stack)
     {
-      GSList *tmp_list = private->paint_stack;
+      GSList *tmp_list = window->paint_stack;
 
       while (tmp_list)
        {
          GdkWindowPaint *paint = tmp_list->data;
 
-         if (tmp_list == private->paint_stack)
+         if (tmp_list == window->paint_stack)
            cairo_surface_destroy (paint->surface);
 
          cairo_region_destroy (paint->region);
@@ -3124,21 +3040,21 @@ gdk_window_free_paint_stack (GdkWindow *window)
          tmp_list = tmp_list->next;
        }
 
-      g_slist_free (private->paint_stack);
-      private->paint_stack = NULL;
+      g_slist_free (window->paint_stack);
+      window->paint_stack = NULL;
     }
 }
 
 static void
-do_move_region_bits_on_impl (GdkWindowObject *impl_window,
+do_move_region_bits_on_impl (GdkWindow *impl_window,
                             cairo_region_t *dest_region, /* In impl window coords */
                             int dx, int dy)
 {
-  GdkWindowImplIface *impl_iface;
+  GdkWindowImplClass *impl_class;
 
-  impl_iface = GDK_WINDOW_IMPL_GET_IFACE (impl_window->impl);
+  impl_class = GDK_WINDOW_IMPL_GET_CLASS (impl_window->impl);
 
-  impl_iface->translate ((GdkWindow *) impl_window, dest_region, dx, dy);
+  impl_class->translate (impl_window, dest_region, dx, dy);
 }
 
 static GdkWindowRegionMove *
@@ -3163,7 +3079,7 @@ gdk_window_region_move_free (GdkWindowRegionMove *move)
 }
 
 static void
-append_move_region (GdkWindowObject *impl_window,
+append_move_region (GdkWindow *impl_window,
                    cairo_region_t *new_dest_region,
                    int dx, int dy)
 {
@@ -3278,7 +3194,7 @@ append_move_region (GdkWindowObject *impl_window,
 /* Moves bits and update area by dx/dy in impl window.
    Takes ownership of region to avoid copy (because we may change it) */
 static void
-move_region_on_impl (GdkWindowObject *impl_window,
+move_region_on_impl (GdkWindow *impl_window,
                     cairo_region_t *region, /* In impl window coords */
                     int dx, int dy)
 {
@@ -3333,11 +3249,7 @@ move_region_on_impl (GdkWindowObject *impl_window,
       cairo_region_destroy (exposing);
     }
 
-  if (impl_window->outstanding_surfaces == 0) /* Enable flicker free handling of moves. */
-    append_move_region (impl_window, region, dx, dy);
-  else
-    do_move_region_bits_on_impl (impl_window,
-                                region, dx, dy);
+  append_move_region (impl_window, region, dx, dy);
 
   cairo_region_destroy (region);
 }
@@ -3348,14 +3260,11 @@ move_region_on_impl (GdkWindowObject *impl_window,
 static void
 gdk_window_flush_outstanding_moves (GdkWindow *window)
 {
-  GdkWindowObject *private;
-  GdkWindowObject *impl_window;
+  GdkWindow *impl_window;
   GList *l, *outstanding;
   GdkWindowRegionMove *move;
 
-  private = (GdkWindowObject *) window;
-
-  impl_window = gdk_window_get_impl_window (private);
+  impl_window = gdk_window_get_impl_window (window);
   outstanding = impl_window->outstanding_moves;
   impl_window->outstanding_moves = NULL;
 
@@ -3412,11 +3321,9 @@ gdk_window_flush (GdkWindow *window)
 static void
 gdk_window_flush_if_exposing (GdkWindow *window)
 {
-  GdkWindowObject *private;
-  GdkWindowObject *impl_window;
+  GdkWindow *impl_window;
 
-  private = (GdkWindowObject *) window;
-  impl_window = gdk_window_get_impl_window (private);
+  impl_window = gdk_window_get_impl_window (window);
 
   /* If we're in an implicit paint (i.e. in an expose handler, flush
      all the already finished exposes to get things to an uptodate state. */
@@ -3426,10 +3333,10 @@ gdk_window_flush_if_exposing (GdkWindow *window)
 
 
 static void
-gdk_window_flush_recursive_helper (GdkWindowObject *window,
-                                  GdkWindow *impl)
+gdk_window_flush_recursive_helper (GdkWindow *window,
+                                  GdkWindowImpl *impl)
 {
-  GdkWindowObject *child;
+  GdkWindow *child;
   GList *l;
 
   for (l = window->children; l != NULL; l = l->next)
@@ -3445,24 +3352,38 @@ gdk_window_flush_recursive_helper (GdkWindowObject *window,
 }
 
 static void
-gdk_window_flush_recursive (GdkWindowObject *window)
+gdk_window_flush_recursive (GdkWindow *window)
 {
-  gdk_window_flush ((GdkWindow *)window);
+  gdk_window_flush (window);
   gdk_window_flush_recursive_helper (window, window->impl);
 }
 
-static cairo_region_t*
-gdk_window_get_clip_region (GdkDrawable *drawable)
+/**
+ * gdk_window_get_clip_region:
+ * @window: a #GdkWindow
+ * 
+ * Computes the region of a window that potentially can be written
+ * to by drawing primitives. This region may not take into account
+ * other factors such as if the window is obscured by other windows,
+ * but no area outside of this region will be affected by drawing
+ * primitives.
+ * 
+ * Returns: a #cairo_region_t. This must be freed with cairo_region_destroy()
+ *          when you are done.
+ **/
+cairo_region_t*
+gdk_window_get_clip_region (GdkWindow *window)
 {
-  GdkWindowObject *private = (GdkWindowObject *)drawable;
   cairo_region_t *result;
 
-  result = cairo_region_copy (private->clip_region);
+  g_return_val_if_fail (GDK_WINDOW (window), NULL);
 
-  if (private->paint_stack)
+  result = cairo_region_copy (window->clip_region);
+
+  if (window->paint_stack)
     {
       cairo_region_t *paint_region = cairo_region_create ();
-      GSList *tmp_list = private->paint_stack;
+      GSList *tmp_list = window->paint_stack;
 
       while (tmp_list)
        {
@@ -3480,33 +3401,44 @@ gdk_window_get_clip_region (GdkDrawable *drawable)
   return result;
 }
 
-static cairo_region_t*
-gdk_window_get_visible_region (GdkDrawable *drawable)
+/**
+ * gdk_window_get_visible_region:
+ * @window: a #GdkWindow
+ * 
+ * Computes the region of the @window that is potentially visible.
+ * This does not necessarily take into account if the window is
+ * obscured by other windows, but no area outside of this region
+ * is visible.
+ * 
+ * Returns: a #cairo_region_t. This must be freed with cairo_region_destroy()
+ *          when you are done.
+ **/
+cairo_region_t *
+gdk_window_get_visible_region (GdkWindow *window)
 {
-  GdkWindowObject *private = (GdkWindowObject*) drawable;
+  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 
-  return cairo_region_copy (private->clip_region);
+  return cairo_region_copy (window->clip_region);
 }
 
 static cairo_t *
 setup_backing_rect (GdkWindow *window, GdkWindowPaint *paint, int x_offset_cairo, int y_offset_cairo)
 {
-  GdkWindowObject *private = (GdkWindowObject *) window;
-  GdkWindowObject *bg_private;
+  GdkWindow *bg_window;
   cairo_pattern_t *pattern = NULL;
   int x_offset = 0, y_offset = 0;
   cairo_t *cr;
 
   cr = cairo_create (paint->surface);
 
-  for (bg_private = private; bg_private; bg_private = bg_private->parent)
+  for (bg_window = window; bg_window; bg_window = bg_window->parent)
     {
-      pattern = gdk_window_get_background_pattern ((GdkWindow *) bg_private);
+      pattern = gdk_window_get_background_pattern (bg_window);
       if (pattern)
         break;
 
-      x_offset += bg_private->x;
-      y_offset += bg_private->y;
+      x_offset += bg_window->x;
+      y_offset += bg_window->y;
     }
 
   if (pattern)
@@ -3525,8 +3457,7 @@ static void
 gdk_window_clear_backing_region (GdkWindow *window,
                                 cairo_region_t *region)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkWindowPaint *paint = private->paint_stack->data;
+  GdkWindowPaint *paint = window->paint_stack->data;
   cairo_region_t *clip;
   GdkRectangle clipbox;
   cairo_t *cr;
@@ -3552,7 +3483,6 @@ static void
 gdk_window_clear_backing_region_direct (GdkWindow *window,
                                        cairo_region_t *region)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
   GdkWindowPaint paint;
   cairo_region_t *clip;
   GdkRectangle clipbox;
@@ -3561,11 +3491,11 @@ gdk_window_clear_backing_region_direct (GdkWindow *window,
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
-  paint.surface = _gdk_drawable_ref_cairo_surface (window);
+  paint.surface = _gdk_window_ref_cairo_surface (window);
 
   cr = setup_backing_rect (window, &paint, 0, 0);
 
-  clip = cairo_region_copy (private->clip_region_with_children);
+  clip = cairo_region_copy (window->clip_region_with_children);
   cairo_region_intersect (clip, region);
   cairo_region_get_extents (clip, &clipbox);
 
@@ -3579,137 +3509,50 @@ gdk_window_clear_backing_region_direct (GdkWindow *window,
 }
 
 
-/**
- * gdk_window_clear:
- * @window: a #GdkWindow
- *
- * Clears an entire @window to the background pattern.
- **/
-void
-gdk_window_clear (GdkWindow *window)
-{
-  gint width, height;
-
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height);
-
-  gdk_window_clear_area (window, 0, 0,
-                        width, height);
-}
-
 static void
 gdk_window_clear_region_internal (GdkWindow *window,
                                  cairo_region_t *region)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-
-  if (private->paint_stack)
+  if (window->paint_stack)
     gdk_window_clear_backing_region (window, region);
   else
     gdk_window_clear_backing_region_direct (window, region);
 }
 
-/**
- * gdk_window_clear_area:
- * @window: a #GdkWindow
- * @x: x coordinate of rectangle to clear
- * @y: y coordinate of rectangle to clear
- * @width: width of rectangle to clear
- * @height: height of rectangle to clear
- *
- * Clears an area of @window to the background pattern.
- **/
-void
-gdk_window_clear_area (GdkWindow *window,
-                      gint       x,
-                      gint       y,
-                      gint       width,
-                      gint       height)
-{
-  GdkRectangle rect;
-  cairo_region_t *region;
-
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
-    return;
-
-  /* Terminate early to avoid weird interpretation of
-     zero width/height by XClearArea */
-  if (width == 0 || height == 0)
-    return;
-
-  rect.x = x;
-  rect.y = y;
-  rect.width = width;
-  rect.height = height;
-
-  region = cairo_region_create_rectangle (&rect);
-  gdk_window_clear_region_internal (window,
-                                   region);
-  cairo_region_destroy (region);
-}
-
-static void
-gdk_window_real_get_size (GdkDrawable *drawable,
-                         gint *width,
-                         gint *height)
-{
-  GdkWindowObject *private = (GdkWindowObject *)drawable;
-
-  if (width)
-    *width = private->width;
-  if (height)
-    *height = private->height;
-}
-
-static GdkColormap*
-gdk_window_real_get_colormap (GdkDrawable *drawable)
-{
-  g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
-
-  if (GDK_WINDOW_DESTROYED (drawable))
-    return NULL;
-
-  return gdk_drawable_get_colormap (((GdkWindowObject*)drawable)->impl);
-}
-
 static void
-gdk_window_drop_cairo_surface (GdkWindowObject *private)
+gdk_window_drop_cairo_surface (GdkWindow *window)
 {
-  if (private->cairo_surface)
+  if (window->cairo_surface)
     {
-      cairo_surface_finish (private->cairo_surface);
-      cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
+      cairo_surface_finish (window->cairo_surface);
+      cairo_surface_set_user_data (window->cairo_surface, &gdk_window_cairo_key,
                                   NULL, NULL);
+      window->cairo_surface = NULL;
     }
 }
 
 static void
 gdk_window_cairo_surface_destroy (void *data)
 {
-  GdkWindowObject *private = (GdkWindowObject*) data;
+  GdkWindow *window = data;
 
-  private->cairo_surface = NULL;
-  private->impl_window->outstanding_surfaces--;
+  window->cairo_surface = NULL;
 }
 
 static cairo_surface_t *
-gdk_window_create_cairo_surface (GdkDrawable *drawable,
+gdk_window_create_cairo_surface (GdkWindow *window,
                                 int width,
                                 int height)
 {
-  GdkWindowObject *private = GDK_WINDOW_OBJECT(drawable);
   cairo_surface_t *surface, *subsurface;
   
-  surface =_gdk_drawable_ref_cairo_surface (private->impl);
-  if (gdk_window_has_impl (private))
+  surface = gdk_window_ref_impl_surface (window);
+  if (gdk_window_has_impl (window))
     return surface;
 
   subsurface = cairo_surface_create_for_rectangle (surface,
-                                                   private->abs_x,
-                                                   private->abs_y,
+                                                   window->abs_x,
+                                                   window->abs_y,
                                                    width,
                                                    height);
   cairo_surface_destroy (surface);
@@ -3717,15 +3560,16 @@ gdk_window_create_cairo_surface (GdkDrawable *drawable,
 }
 
 
-static cairo_surface_t *
-gdk_window_ref_cairo_surface (GdkDrawable *drawable)
+cairo_surface_t *
+_gdk_window_ref_cairo_surface (GdkWindow *window)
 {
-  GdkWindowObject *private = (GdkWindowObject*) drawable;
   cairo_surface_t *surface;
 
-  if (private->paint_stack)
+  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
+
+  if (window->paint_stack)
     {
-      GdkWindowPaint *paint = private->paint_stack->data;
+      GdkWindowPaint *paint = window->paint_stack->data;
 
       surface = paint->surface;
       cairo_surface_reference (surface);
@@ -3734,69 +3578,77 @@ gdk_window_ref_cairo_surface (GdkDrawable *drawable)
     {
 
       /* This will be drawing directly to the window, so flush implicit paint */
-      gdk_window_flush ((GdkWindow *)drawable);
+      gdk_window_flush (window);
 
-      if (!private->cairo_surface)
+      if (!window->cairo_surface)
        {
-         private->cairo_surface = _gdk_drawable_create_cairo_surface (drawable,
-                                                                       private->width,
-                                                                       private->height);
+         window->cairo_surface = gdk_window_create_cairo_surface (window,
+                                                                   window->width,
+                                                                   window->height);
 
-         if (private->cairo_surface)
+         if (window->cairo_surface)
            {
-             private->impl_window->outstanding_surfaces++;
-
-             cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
-                                          drawable, gdk_window_cairo_surface_destroy);
+             cairo_surface_set_user_data (window->cairo_surface, &gdk_window_cairo_key,
+                                          window, gdk_window_cairo_surface_destroy);
            }
        }
       else
-       cairo_surface_reference (private->cairo_surface);
+       cairo_surface_reference (window->cairo_surface);
 
-      surface = private->cairo_surface;
+      surface = window->cairo_surface;
     }
 
   return surface;
 }
 
-static void
-gdk_window_set_cairo_clip (GdkDrawable *drawable,
-                          cairo_t *cr)
+/**
+ * gdk_cairo_create:
+ * @window: a #GdkWindow
+ * 
+ * Creates a Cairo context for drawing to @window.
+ *
+ * <note><warning>
+ * Note that calling cairo_reset_clip() on the resulting #cairo_t will
+ * produce undefined results, so avoid it at all costs.
+ * </warning></note>
+ *
+ * Return value: A newly created Cairo context. Free with
+ *  cairo_destroy() when you are done drawing.
+ * 
+ * Since: 2.8
+ **/
+cairo_t *
+gdk_cairo_create (GdkWindow *window)
 {
-  GdkWindowObject *private = (GdkWindowObject*) drawable;
-
-  if (!private->paint_stack)
-    {
-      cairo_reset_clip (cr);
-
-      cairo_save (cr);
-      cairo_identity_matrix (cr);
+  cairo_surface_t *surface;
+  cairo_t *cr;
+    
+  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 
-      cairo_new_path (cr);
-      gdk_cairo_region (cr, private->clip_region_with_children);
+  surface = _gdk_window_ref_cairo_surface (window);
+  cr = cairo_create (surface);
 
-      cairo_restore (cr);
+  if (!window->paint_stack)
+    {
+      gdk_cairo_region (cr, window->clip_region_with_children);
       cairo_clip (cr);
     }
   else
     {
-      GdkWindowPaint *paint = private->paint_stack->data;
+      GdkWindowPaint *paint = window->paint_stack->data;
 
       /* Only needs to clip to region if piggybacking
         on an implicit paint */
-      cairo_reset_clip (cr);
       if (paint->uses_implicit)
        {
-         cairo_save (cr);
-         cairo_identity_matrix (cr);
-
-         cairo_new_path (cr);
          gdk_cairo_region (cr, paint->region);
-         cairo_restore (cr);
-
          cairo_clip (cr);
        }
     }
+    
+  cairo_surface_destroy (surface);
+
+  return cr;
 }
 
 /* Code for dirty-region queueing
@@ -3811,7 +3663,7 @@ gdk_window_is_ancestor (GdkWindow *window,
 {
   while (window)
     {
-      GdkWindow *parent = (GdkWindow*) ((GdkWindowObject*) window)->parent;
+      GdkWindow *parent = window->parent;
 
       if (parent == ancestor)
        return TRUE;
@@ -3831,7 +3683,7 @@ gdk_window_add_update_window (GdkWindow *window)
 
   for (tmp = update_windows; tmp; tmp = tmp->next)
     {
-      GdkWindowObject *parent = GDK_WINDOW_OBJECT (window)->parent;
+      GdkWindow *parent = window->parent;
 
       /*  check if tmp is an ancestor of "window"; if it is, set a
        *  flag indicating that all following windows are either
@@ -3843,10 +3695,10 @@ gdk_window_add_update_window (GdkWindow *window)
       /* insert in reverse stacking order when adding around siblings,
        * so processing updates properly paints over lower stacked windows
        */
-      if (parent == GDK_WINDOW_OBJECT (tmp->data)->parent)
+      if (parent == GDK_WINDOW (tmp->data)->parent)
        {
          gint index = g_list_index (parent->children, window);
-         for (; tmp && parent == GDK_WINDOW_OBJECT (tmp->data)->parent; tmp = tmp->next)
+         for (; tmp && parent == GDK_WINDOW (tmp->data)->parent; tmp = tmp->next)
            {
              gint sibling_index = g_list_index (parent->children, tmp->data);
              if (index > sibling_index)
@@ -3912,9 +3764,9 @@ gdk_window_update_idle (gpointer data)
 static gboolean
 gdk_window_is_toplevel_frozen (GdkWindow *window)
 {
-  GdkWindowObject *toplevel;
+  GdkWindow *toplevel;
 
-  toplevel = (GdkWindowObject *)gdk_window_get_toplevel (window);
+  toplevel = gdk_window_get_toplevel (window);
 
   return toplevel->update_and_descendants_freeze_count > 0;
 }
@@ -3923,7 +3775,7 @@ static void
 gdk_window_schedule_update (GdkWindow *window)
 {
   if (window &&
-      (GDK_WINDOW_OBJECT (window)->update_freeze_count ||
+      (window->update_freeze_count ||
        gdk_window_is_toplevel_frozen (window)))
     return;
 
@@ -3938,8 +3790,7 @@ void
 _gdk_window_process_updates_recurse (GdkWindow *window,
                                     cairo_region_t *expose_region)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkWindowObject *child;
+  GdkWindow *child;
   cairo_region_t *child_region;
   GdkRectangle r;
   GList *l, *children;
@@ -3947,12 +3798,12 @@ _gdk_window_process_updates_recurse (GdkWindow *window,
   if (cairo_region_is_empty (expose_region))
     return;
 
-  if (gdk_window_is_offscreen (private->impl_window) &&
-      private == private->impl_window)
-    _gdk_window_add_damage ((GdkWindow *) private->impl_window, expose_region);
+  if (gdk_window_is_offscreen (window->impl_window) &&
+      window == window->impl_window)
+    _gdk_window_add_damage ((GdkWindow *) window->impl_window, expose_region);
 
   /* Make this reentrancy safe for expose handlers freeing windows */
-  children = g_list_copy (private->children);
+  children = g_list_copy (window->children);
   g_list_foreach (children, (GFunc)g_object_ref, NULL);
 
   /* Iterate over children, starting at topmost */
@@ -3982,7 +3833,7 @@ _gdk_window_process_updates_recurse (GdkWindow *window,
          cairo_region_translate (child->shape, -child->x, -child->y);
        }
 
-      if (child->impl == private->impl)
+      if (child->impl == window->impl)
        {
          /* Client side child, expose */
          cairo_region_intersect (child_region, expose_region);
@@ -4002,9 +3853,9 @@ _gdk_window_process_updates_recurse (GdkWindow *window,
   g_list_free (children);
 
   if (!cairo_region_is_empty (expose_region) &&
-      !private->destroyed)
+      !window->destroyed)
     {
-      if (private->event_mask & GDK_EXPOSURE_MASK)
+      if (window->event_mask & GDK_EXPOSURE_MASK)
        {
          GdkEvent event;
 
@@ -4015,11 +3866,11 @@ _gdk_window_process_updates_recurse (GdkWindow *window,
          event.expose.region = expose_region;
          cairo_region_get_extents (expose_region, &event.expose.area);
 
-         (*_gdk_event_func) (&event, _gdk_event_data);
+          _gdk_event_emit (&event);
 
          g_object_unref (window);
        }
-      else if (private->window_type != GDK_WINDOW_FOREIGN)
+      else if (window->window_type != GDK_WINDOW_FOREIGN)
        {
          /* No exposure mask set, so nothing will be drawn, the
           * app relies on the background being what it specified
@@ -4049,8 +3900,7 @@ _gdk_window_process_updates_recurse (GdkWindow *window,
 static void
 gdk_window_process_updates_internal (GdkWindow *window)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkWindowImplIface *impl_iface;
+  GdkWindowImplClass *impl_class;
   gboolean save_region = FALSE;
   GdkRectangle clip_box;
 
@@ -4061,18 +3911,18 @@ gdk_window_process_updates_internal (GdkWindow *window)
    * window in the update queue that has an empty update_area.
    * just ignore it.
    */
-  if (private->update_area)
+  if (window->update_area)
     {
-      cairo_region_t *update_area = private->update_area;
-      private->update_area = NULL;
+      cairo_region_t *update_area = window->update_area;
+      window->update_area = NULL;
 
-      if (_gdk_event_func && gdk_window_is_viewable (window))
+      if (gdk_window_is_viewable (window))
        {
          cairo_region_t *expose_region;
          gboolean end_implicit;
 
          /* Clip to part visible in toplevel */
-         cairo_region_intersect (update_area, private->clip_region);
+         cairo_region_intersect (update_area, window->clip_region);
 
          if (debug_updates)
            {
@@ -4087,7 +3937,7 @@ gdk_window_process_updates_internal (GdkWindow *window)
           * be overdrawn by the expose anyway. So, in order to copy less data
           * we remove these areas from the outstanding moves.
           */
-         if (private->outstanding_moves)
+         if (window->outstanding_moves)
            {
              GdkWindowRegionMove *move;
              cairo_region_t *remove;
@@ -4096,7 +3946,7 @@ gdk_window_process_updates_internal (GdkWindow *window)
              remove = cairo_region_copy (update_area);
              /* We iterate backwards, starting from the state that would be
                 if we had applied all the moves. */
-             for (l = g_list_last (private->outstanding_moves); l != NULL; l = prev)
+             for (l = g_list_last (window->outstanding_moves); l != NULL; l = prev)
                {
                  prev = l->prev;
                  move = l->data;
@@ -4113,8 +3963,8 @@ gdk_window_process_updates_internal (GdkWindow *window)
                  if (cairo_region_is_empty (move->dest_region))
                    {
                      gdk_window_region_move_free (move);
-                     private->outstanding_moves =
-                       g_list_delete_link (private->outstanding_moves, l);
+                     window->outstanding_moves =
+                       g_list_delete_link (window->outstanding_moves, l);
                    }
                  else /* move back */
                    cairo_region_translate (move->dest_region, move->dx, move->dy);
@@ -4161,19 +4011,18 @@ gdk_window_process_updates_internal (GdkWindow *window)
          cairo_region_get_extents (update_area, &clip_box);
          end_implicit = gdk_window_begin_implicit_paint (window, &clip_box);
          expose_region = cairo_region_copy (update_area);
+         impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
          if (!end_implicit)
            {
              /* Rendering is not double buffered by gdk, do outstanding
               * moves and queue antiexposure immediately. No need to do
               * any tricks */
              gdk_window_flush_outstanding_moves (window);
-             impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
-             save_region = impl_iface->queue_antiexpose (window, update_area);
+             save_region = impl_class->queue_antiexpose (window, update_area);
            }
-
          /* Render the invalid areas to the implicit paint, by sending exposes.
           * May flush if non-double buffered widget draw. */
-         _gdk_windowing_window_process_updates_recurse (window, expose_region);
+          impl_class->process_updates_recurse (window, expose_region);
 
          if (end_implicit)
            {
@@ -4182,17 +4031,12 @@ gdk_window_process_updates_internal (GdkWindow *window)
 
              /* By this time we know that any outstanding expose for this
               * area is invalid and we can avoid it, so queue an antiexpose.
-              * However, it may be that due to an non-double buffered expose
               * we have already started drawing to the window, so it would
               * be to late to anti-expose now. Since this is merely an
               * optimization we just avoid doing it at all in that case.
               */
-             if (private->implicit_paint != NULL &&
-                 !private->implicit_paint->flushed)
-               {
-                 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
-                 save_region = impl_iface->queue_antiexpose (window, update_area);
-               }
+             if (window->implicit_paint != NULL && !window->implicit_paint->flushed)
+                save_region = impl_class->queue_antiexpose (window, update_area);
 
              gdk_window_end_implicit_paint (window);
            }
@@ -4202,7 +4046,7 @@ gdk_window_process_updates_internal (GdkWindow *window)
        cairo_region_destroy (update_area);
     }
 
-  if (private->outstanding_moves)
+  if (window->outstanding_moves)
     {
       /* Flush any outstanding moves, may happen if we moved a window but got
         no actual invalid area */
@@ -4215,11 +4059,39 @@ gdk_window_process_updates_internal (GdkWindow *window)
 static void
 flush_all_displays (void)
 {
-  GSList *displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
-  GSList *tmp_list;
+  GSList *displays, *l;
+
+  displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
+  for (l = displays; l; l = l->next)
+    gdk_display_flush (l->data);
+
+  g_slist_free (displays);
+}
+
+static void
+before_process_all_updates (void)
+{
+  GSList *displays, *l;
+  GdkDisplayClass *display_class;
+
+  displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
+  display_class = GDK_DISPLAY_GET_CLASS (displays->data);
+  for (l = displays; l; l = l->next)
+    display_class->before_process_all_updates (l->data);
+
+  g_slist_free (displays);
+}
+
+static void
+after_process_all_updates (void)
+{
+  GSList *displays, *l;
+  GdkDisplayClass *display_class;
 
-  for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
-    gdk_display_flush (tmp_list->data);
+  displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
+  display_class = GDK_DISPLAY_GET_CLASS (displays->data);
+  for (l = displays; l; l = l->next)
+    display_class->after_process_all_updates (l->data);
 
   g_slist_free (displays);
 }
@@ -4267,24 +4139,24 @@ gdk_window_process_all_updates (void)
   update_windows = NULL;
   update_idle = 0;
 
-  _gdk_windowing_before_process_all_updates ();
+  before_process_all_updates ();
 
   g_slist_foreach (old_update_windows, (GFunc)g_object_ref, NULL);
 
   while (tmp_list)
     {
-      GdkWindowObject *private = (GdkWindowObject *)tmp_list->data;
+      GdkWindow *window = tmp_list->data;
 
-      if (!GDK_WINDOW_DESTROYED (tmp_list->data))
+      if (!GDK_WINDOW_DESTROYED (window))
        {
-         if (private->update_freeze_count ||
-             gdk_window_is_toplevel_frozen (tmp_list->data))
-           gdk_window_add_update_window ((GdkWindow *) private);
+         if (window->update_freeze_count ||
+             gdk_window_is_toplevel_frozen (window))
+           gdk_window_add_update_window (window);
          else
-           gdk_window_process_updates_internal (tmp_list->data);
+           gdk_window_process_updates_internal (window);
        }
 
-      g_object_unref (tmp_list->data);
+      g_object_unref (window);
       tmp_list = tmp_list->next;
     }
 
@@ -4292,7 +4164,7 @@ gdk_window_process_all_updates (void)
 
   flush_all_displays ();
 
-  _gdk_windowing_after_process_all_updates ();
+  after_process_all_updates ();
 
   in_process_all_updates = FALSE;
 
@@ -4326,8 +4198,7 @@ void
 gdk_window_process_updates (GdkWindow *window,
                            gboolean   update_children)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkWindowObject *impl_window;
+  GdkWindow *impl_window;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
@@ -4337,7 +4208,7 @@ gdk_window_process_updates (GdkWindow *window,
   /* Make sure the window lives during the expose callouts */
   g_object_ref (window);
 
-  impl_window = gdk_window_get_impl_window (private);
+  impl_window = gdk_window_get_impl_window (window);
   if ((impl_window->update_area ||
        impl_window->outstanding_moves) &&
       !impl_window->update_freeze_count &&
@@ -4358,7 +4229,7 @@ gdk_window_process_updates (GdkWindow *window,
        */
       GList *node, *children;
 
-      children = g_list_copy (private->children);
+      children = g_list_copy (window->children);
       g_list_foreach (children, (GFunc)g_object_ref, NULL);
 
       for (node = g_list_last (children); node; node = node->prev)
@@ -4381,23 +4252,21 @@ gdk_window_invalidate_rect_full (GdkWindow          *window,
 {
   GdkRectangle window_rect;
   cairo_region_t *region;
-  GdkWindowObject *private = (GdkWindowObject *)window;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
-  if (private->input_only || !private->viewable)
+  if (window->input_only || !window->viewable)
     return;
 
   if (!rect)
     {
       window_rect.x = 0;
       window_rect.y = 0;
-      gdk_drawable_get_size (GDK_DRAWABLE (window),
-                            &window_rect.width,
-                            &window_rect.height);
+      window_rect.width = window->width;
+      window_rect.height = window->height;
       rect = &window_rect;
     }
 
@@ -4441,16 +4310,16 @@ draw_ugly_color (GdkWindow       *window,
 }
 
 static void
-impl_window_add_update_area (GdkWindowObject *impl_window,
+impl_window_add_update_area (GdkWindow *impl_window,
                             cairo_region_t *region)
 {
   if (impl_window->update_area)
     cairo_region_union (impl_window->update_area, region);
   else
     {
-      gdk_window_add_update_window ((GdkWindow *)impl_window);
+      gdk_window_add_update_window (impl_window);
       impl_window->update_area = cairo_region_copy (region);
-      gdk_window_schedule_update ((GdkWindow *)impl_window);
+      gdk_window_schedule_update (impl_window);
     }
 }
 
@@ -4465,15 +4334,13 @@ impl_window_add_update_area (GdkWindowObject *impl_window,
  * system has already cleared the area).
  */
 static void
-gdk_window_invalidate_maybe_recurse_full (GdkWindow       *window,
+gdk_window_invalidate_maybe_recurse_full (GdkWindow            *window,
                                          const cairo_region_t *region,
-                                         ClearBg          clear_bg,
-                                         gboolean       (*child_func) (GdkWindow *,
-                                                                       gpointer),
-                                         gpointer   user_data)
+                                         ClearBg               clear_bg,
+                                          GdkWindowChildFunc    child_func,
+                                         gpointer              user_data)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkWindowObject *impl_window;
+  GdkWindow *impl_window;
   cairo_region_t *visible_region;
   GList *tmp_list;
 
@@ -4482,19 +4349,19 @@ gdk_window_invalidate_maybe_recurse_full (GdkWindow       *window,
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
-  if (private->input_only ||
-      !private->viewable ||
+  if (window->input_only ||
+      !window->viewable ||
       cairo_region_is_empty (region) ||
-      private->window_type == GDK_WINDOW_ROOT)
+      window->window_type == GDK_WINDOW_ROOT)
     return;
 
-  visible_region = gdk_drawable_get_visible_region (window);
+  visible_region = gdk_window_get_visible_region (window);
   cairo_region_intersect (visible_region, region);
 
-  tmp_list = private->children;
+  tmp_list = window->children;
   while (tmp_list)
     {
-      GdkWindowObject *child = tmp_list->data;
+      GdkWindow *child = tmp_list->data;
 
       if (!child->input_only)
        {
@@ -4533,7 +4400,7 @@ gdk_window_invalidate_maybe_recurse_full (GdkWindow       *window,
       tmp_list = tmp_list->next;
     }
 
-  impl_window = gdk_window_get_impl_window (private);
+  impl_window = gdk_window_get_impl_window (window);
 
   if (!cairo_region_is_empty (visible_region)  ||
       /* Even if we're not exposing anything, make sure we process
@@ -4545,13 +4412,13 @@ gdk_window_invalidate_maybe_recurse_full (GdkWindow       *window,
        draw_ugly_color (window, region);
 
       /* Convert to impl coords */
-      cairo_region_translate (visible_region, private->abs_x, private->abs_y);
+      cairo_region_translate (visible_region, window->abs_x, window->abs_y);
 
       /* Only invalidate area if app requested expose events or if
         we need to clear the area (by request or to emulate background
         clearing for non-native windows or native windows with no support
         for window backgrounds */
-      if (private->event_mask & GDK_EXPOSURE_MASK ||
+      if (window->event_mask & GDK_EXPOSURE_MASK ||
          clear_bg == CLEAR_BG_ALL ||
          clear_bg == CLEAR_BG_WINCLEARED)
        impl_window_add_update_area (impl_window, visible_region);
@@ -4586,11 +4453,10 @@ gdk_window_invalidate_maybe_recurse_full (GdkWindow       *window,
  * invalidated.
  **/
 void
-gdk_window_invalidate_maybe_recurse (GdkWindow       *window,
+gdk_window_invalidate_maybe_recurse (GdkWindow            *window,
                                     const cairo_region_t *region,
-                                    gboolean       (*child_func) (GdkWindow *,
-                                                                  gpointer),
-                                    gpointer   user_data)
+                                     GdkWindowChildFunc    child_func,
+                                    gpointer              user_data)
 {
   gdk_window_invalidate_maybe_recurse_full (window, region, CLEAR_BG_NONE,
                                            child_func, user_data);
@@ -4676,7 +4542,6 @@ void
 _gdk_window_invalidate_for_expose (GdkWindow       *window,
                                   cairo_region_t       *region)
 {
-  GdkWindowObject *private = (GdkWindowObject *) window;
   GdkWindowRegionMove *move;
   cairo_region_t *move_region;
   GList *l;
@@ -4687,7 +4552,7 @@ _gdk_window_invalidate_for_expose (GdkWindow       *window,
      otherwise we would expose in the wrong place, as the
      outstanding moves will be copied before we draw the
      exposes. */
-  for (l = private->outstanding_moves; l != NULL; l = l->next)
+  for (l = window->outstanding_moves; l != NULL; l = l->next)
     {
       move = l->data;
 
@@ -4727,19 +4592,18 @@ _gdk_window_invalidate_for_expose (GdkWindow       *window,
 cairo_region_t *
 gdk_window_get_update_area (GdkWindow *window)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkWindowObject *impl_window;
+  GdkWindow *impl_window;
   cairo_region_t *tmp_region;
 
   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 
-  impl_window = gdk_window_get_impl_window (private);
+  impl_window = gdk_window_get_impl_window (window);
 
   if (impl_window->update_area)
     {
-      tmp_region = cairo_region_copy (private->clip_region_with_children);
+      tmp_region = cairo_region_copy (window->clip_region_with_children);
       /* Convert to impl coords */
-      cairo_region_translate (tmp_region, private->abs_x, private->abs_y);
+      cairo_region_translate (tmp_region, window->abs_x, window->abs_y);
       cairo_region_intersect (tmp_region, impl_window->update_area);
 
       if (cairo_region_is_empty (tmp_region))
@@ -4761,7 +4625,7 @@ gdk_window_get_update_area (GdkWindow *window)
            }
 
          /* Convert from impl coords */
-         cairo_region_translate (tmp_region, -private->abs_x, -private->abs_y);
+         cairo_region_translate (tmp_region, -window->abs_x, -window->abs_y);
          return tmp_region;
 
        }
@@ -4780,16 +4644,14 @@ gdk_window_get_update_area (GdkWindow *window)
 void
 _gdk_window_clear_update_area (GdkWindow *window)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  if (private->update_area)
+  if (window->update_area)
     {
       gdk_window_remove_update_window (window);
 
-      cairo_region_destroy (private->update_area);
-      private->update_area = NULL;
+      cairo_region_destroy (window->update_area);
+      window->update_area = NULL;
     }
 }
 
@@ -4806,12 +4668,11 @@ _gdk_window_clear_update_area (GdkWindow *window)
 void
 gdk_window_freeze_updates (GdkWindow *window)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkWindowObject *impl_window;
+  GdkWindow *impl_window;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  impl_window = gdk_window_get_impl_window (private);
+  impl_window = gdk_window_get_impl_window (window);
   impl_window->update_freeze_count++;
 }
 
@@ -4824,12 +4685,11 @@ gdk_window_freeze_updates (GdkWindow *window)
 void
 gdk_window_thaw_updates (GdkWindow *window)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkWindowObject *impl_window;
+  GdkWindow *impl_window;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  impl_window = gdk_window_get_impl_window (private);
+  impl_window = gdk_window_get_impl_window (window);
 
   g_return_if_fail (impl_window->update_freeze_count > 0);
 
@@ -4855,12 +4715,10 @@ gdk_window_thaw_updates (GdkWindow *window)
 void
 gdk_window_freeze_toplevel_updates_libgtk_only (GdkWindow *window)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-
   g_return_if_fail (GDK_IS_WINDOW (window));
-  g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
+  g_return_if_fail (window->window_type != GDK_WINDOW_CHILD);
 
-  private->update_and_descendants_freeze_count++;
+  window->update_and_descendants_freeze_count++;
 }
 
 /**
@@ -4876,13 +4734,11 @@ gdk_window_freeze_toplevel_updates_libgtk_only (GdkWindow *window)
 void
 gdk_window_thaw_toplevel_updates_libgtk_only (GdkWindow *window)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-
   g_return_if_fail (GDK_IS_WINDOW (window));
-  g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
-  g_return_if_fail (private->update_and_descendants_freeze_count > 0);
+  g_return_if_fail (window->window_type != GDK_WINDOW_CHILD);
+  g_return_if_fail (window->update_and_descendants_freeze_count > 0);
 
-  private->update_and_descendants_freeze_count--;
+  window->update_and_descendants_freeze_count--;
 
   gdk_window_schedule_update (window);
 }
@@ -5085,7 +4941,7 @@ gdk_window_get_pointer (GdkWindow   *window,
 /**
  * gdk_window_get_device_position:
  * @window: a #GdkWindow.
- * @device: #GdkDevice to query to.
+ * @device: pointer #GdkDevice to query to.
  * @x: (out) (allow-none): return location for the X coordinate of @device, or %NULL.
  * @y: (out) (allow-none): return location for the Y coordinate of @device, or %NULL.
  * @mask: (out) (allow-none): return location for the modifier mask, or %NULL.
@@ -5095,8 +4951,7 @@ gdk_window_get_pointer (GdkWindow   *window,
  * corner of @window.
  *
  * Return value: (transfer none): The window underneath @device (as with
- * gdk_display_get_window_at_device_position()), or %NULL if the
- * window is not known to GDK.
+ * gdk_device_get_window_at_position()), or %NULL if the window is not known to GDK.
  *
  * Since: 3.0
  **/
@@ -5114,6 +4969,10 @@ gdk_window_get_device_position (GdkWindow       *window,
 
   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
   g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
+  g_return_val_if_fail (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD, NULL);
+
+  tmp_x = 0;
+  tmp_y = 0;
 
   display = gdk_window_get_display (window);
   child = display->device_hooks->window_get_device_position (display, device, window,
@@ -5147,7 +5006,7 @@ gdk_window_get_device_position (GdkWindow       *window,
  *
  * Return value: (transfer none): window under the mouse pointer
  *
- * Deprecated: 3.0: Use gdk_display_get_window_at_device_position() instead.
+ * Deprecated: 3.0: Use gdk_device_get_window_at_position() instead.
  **/
 GdkWindow*
 gdk_window_at_pointer (gint *win_x,
@@ -5162,7 +5021,7 @@ gdk_window_at_pointer (gint *win_x,
  * Obtains the root window (parent all other windows are inside)
  * for the default display and screen.
  *
- * Return value: the default root window
+ * Return value: (transfer none): the default root window
  **/
 GdkWindow *
 gdk_get_default_root_window (void)
@@ -5170,33 +5029,14 @@ gdk_get_default_root_window (void)
   return gdk_screen_get_root_window (gdk_screen_get_default ());
 }
 
-/**
- * gdk_window_foreign_new:
- * @anid: a native window handle.
- *
- * Wraps a native window for the default display in a #GdkWindow.
- * This may fail if the window has been destroyed.
- *
- * For example in the X backend, a native window handle is an Xlib
- * <type>XID</type>.
- *
- * Return value: the newly-created #GdkWindow wrapper for the
- *    native window or %NULL if the window has been destroyed.
- **/
-GdkWindow *
-gdk_window_foreign_new (GdkNativeWindow anid)
-{
-  return gdk_window_foreign_new_for_display (gdk_display_get_default (), anid);
-}
-
 static void
-get_all_native_children (GdkWindowObject *private,
+get_all_native_children (GdkWindow *window,
                         GList **native)
 {
-  GdkWindowObject *child;
+  GdkWindow *child;
   GList *l;
 
-  for (l = private->children; l != NULL; l = l->next)
+  for (l = window->children; l != NULL; l = l->next)
     {
       child = l->data;
 
@@ -5211,12 +5051,11 @@ get_all_native_children (GdkWindowObject *private,
 static inline void
 gdk_window_raise_internal (GdkWindow *window)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkWindowObject *parent = private->parent;
-  GdkWindowObject *above;
+  GdkWindow *parent = window->parent;
+  GdkWindow *above;
   GList *native_children;
   GList *l, listhead;
-  GdkWindowImplIface *impl_iface;
+  GdkWindowImplClass *impl_class;
 
   if (parent)
     {
@@ -5224,48 +5063,47 @@ gdk_window_raise_internal (GdkWindow *window)
       parent->children = g_list_prepend (parent->children, window);
     }
 
-  impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
+  impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
   /* Just do native raise for toplevels */
-  if (gdk_window_is_toplevel (private) ||
+  if (gdk_window_is_toplevel (window) ||
       /* The restack_under codepath should work correctly even if the parent
         is native, but it relies on the order of ->children to be correct,
         and some apps like SWT reorder the x windows without gdks knowledge,
         so we use raise directly in order to make these behave as before
         when using native windows */
-      (gdk_window_has_impl (private) && gdk_window_has_impl (parent)))
+      (gdk_window_has_impl (window) && gdk_window_has_impl (parent)))
     {
-      impl_iface->raise (window);
+      impl_class->raise (window);
     }
-  else if (gdk_window_has_impl (private))
+  else if (gdk_window_has_impl (window))
     {
-      above = find_native_sibling_above (parent, private);
+      above = find_native_sibling_above (parent, window);
       if (above)
        {
          listhead.data = window;
          listhead.next = NULL;
          listhead.prev = NULL;
-         impl_iface->restack_under ((GdkWindow *)above,
+         impl_class->restack_under ((GdkWindow *)above,
                                     &listhead);
        }
       else
-       impl_iface->raise (window);
+       impl_class->raise (window);
     }
   else
     {
       native_children = NULL;
-      get_all_native_children (private, &native_children);
+      get_all_native_children (window, &native_children);
       if (native_children != NULL)
        {
-         above = find_native_sibling_above (parent, private);
+         above = find_native_sibling_above (parent, window);
 
          if (above)
-           impl_iface->restack_under ((GdkWindow *)above,
-                                      native_children);
+           impl_class->restack_under (above, native_children);
          else
            {
              /* Right order, since native_children is bottom-topmost first */
              for (l = native_children; l != NULL; l = l->next)
-               impl_iface->raise (l->data);
+               impl_class->raise (l->data);
            }
 
          g_list_free (native_children);
@@ -5276,11 +5114,11 @@ gdk_window_raise_internal (GdkWindow *window)
 
 /* Returns TRUE If the native window was mapped or unmapped */
 static gboolean
-set_viewable (GdkWindowObject *w,
+set_viewable (GdkWindow *w,
              gboolean val)
 {
-  GdkWindowObject *child;
-  GdkWindowImplIface *impl_iface;
+  GdkWindow *child;
+  GdkWindowImplClass *impl_class;
   GList *l;
 
   if (w->viewable == val)
@@ -5331,11 +5169,11 @@ set_viewable (GdkWindowObject *w,
        * like this, so we just always show/hide directly.
        */
 
-      impl_iface = GDK_WINDOW_IMPL_GET_IFACE (w->impl);
+      impl_class = GDK_WINDOW_IMPL_GET_CLASS (w->impl);
       if (val)
-       impl_iface->show ((GdkWindow *)w, FALSE);
+       impl_class->show ((GdkWindow *)w, FALSE);
       else
-       impl_iface->hide ((GdkWindow *)w);
+       impl_class->hide ((GdkWindow *)w);
 
       return TRUE;
     }
@@ -5347,43 +5185,40 @@ set_viewable (GdkWindowObject *w,
 gboolean
 _gdk_window_update_viewable (GdkWindow *window)
 {
-  GdkWindowObject *priv = (GdkWindowObject *)window;
   gboolean viewable;
 
-  if (priv->window_type == GDK_WINDOW_FOREIGN ||
-      priv->window_type == GDK_WINDOW_ROOT)
+  if (window->window_type == GDK_WINDOW_FOREIGN ||
+      window->window_type == GDK_WINDOW_ROOT)
     viewable = TRUE;
-  else if (gdk_window_is_toplevel (priv) ||
-          priv->parent->viewable)
-    viewable = GDK_WINDOW_IS_MAPPED (priv);
+  else if (gdk_window_is_toplevel (window) ||
+          window->parent->viewable)
+    viewable = GDK_WINDOW_IS_MAPPED (window);
   else
     viewable = FALSE;
 
-  return set_viewable (priv, viewable);
+  return set_viewable (window, viewable);
 }
 
 static void
 gdk_window_show_internal (GdkWindow *window, gboolean raise)
 {
-  GdkWindowObject *private;
-  GdkWindowImplIface *impl_iface;
+  GdkWindowImplClass *impl_class;
   gboolean was_mapped, was_viewable;
   gboolean did_show;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
+  if (window->destroyed)
     return;
 
   was_mapped = GDK_WINDOW_IS_MAPPED (window);
-  was_viewable = private->viewable;
+  was_viewable = window->viewable;
 
   if (raise)
     /* Keep children in (reverse) stacking order */
     gdk_window_raise_internal (window);
 
-  if (gdk_window_has_impl (private))
+  if (gdk_window_has_impl (window))
     {
       if (!was_mapped)
        gdk_synthesize_window_state (window,
@@ -5392,7 +5227,7 @@ gdk_window_show_internal (GdkWindow *window, gboolean raise)
     }
   else
     {
-      private->state = 0;
+      window->state = 0;
     }
 
   did_show = _gdk_window_update_viewable (window);
@@ -5402,28 +5237,27 @@ gdk_window_show_internal (GdkWindow *window, gboolean raise)
      for e.g. a foreign window.
      Dunno if this is strictly needed but its what happened pre-csw.
      Also show if not done by gdk_window_update_viewable. */
-  if (gdk_window_has_impl (private) && (was_viewable || !did_show))
+  if (gdk_window_has_impl (window) && (was_viewable || !did_show))
     {
-      impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
-      impl_iface->show ((GdkWindow *)private,
-                       !did_show ? was_mapped : TRUE);
+      impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
+      impl_class->show (window, !did_show ? was_mapped : TRUE);
     }
 
-  if (!was_mapped && !gdk_window_has_impl (private))
+  if (!was_mapped && !gdk_window_has_impl (window))
     {
-      if (private->event_mask & GDK_STRUCTURE_MASK)
-       _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
+      if (window->event_mask & GDK_STRUCTURE_MASK)
+       _gdk_make_event (window, GDK_MAP, NULL, FALSE);
 
-      if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
-       _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
+      if (window->parent && window->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+       _gdk_make_event (window, GDK_MAP, NULL, FALSE);
     }
 
   if (!was_mapped || raise)
     {
-      recompute_visible_regions (private, TRUE, FALSE);
+      recompute_visible_regions (window, TRUE, FALSE);
 
       /* If any decendants became visible we need to send visibility notify */
-      gdk_window_update_visibility_recursively (private, NULL);
+      gdk_window_update_visibility_recursively (window, NULL);
 
       if (gdk_window_is_viewable (window))
        {
@@ -5466,30 +5300,28 @@ gdk_window_show_unraised (GdkWindow *window)
 void
 gdk_window_raise (GdkWindow *window)
 {
-  GdkWindowObject *private;
   cairo_region_t *old_region, *new_region;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
+  if (window->destroyed)
     return;
 
   gdk_window_flush_if_exposing (window);
 
   old_region = NULL;
   if (gdk_window_is_viewable (window) &&
-      !private->input_only)
-    old_region = cairo_region_copy (private->clip_region);
+      !window->input_only)
+    old_region = cairo_region_copy (window->clip_region);
 
   /* Keep children in (reverse) stacking order */
   gdk_window_raise_internal (window);
 
-  recompute_visible_regions (private, TRUE, FALSE);
+  recompute_visible_regions (window, TRUE, FALSE);
 
   if (old_region)
     {
-      new_region = cairo_region_copy (private->clip_region);
+      new_region = cairo_region_copy (window->clip_region);
 
       cairo_region_subtract (new_region, old_region);
       gdk_window_invalidate_region_full (window, new_region, TRUE, CLEAR_BG_ALL);
@@ -5502,10 +5334,9 @@ gdk_window_raise (GdkWindow *window)
 static void
 gdk_window_lower_internal (GdkWindow *window)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkWindowObject *parent = private->parent;
-  GdkWindowImplIface *impl_iface;
-  GdkWindowObject *above;
+  GdkWindow *parent = window->parent;
+  GdkWindowImplClass *impl_class;
+  GdkWindow *above;
   GList *native_children;
   GList *l, listhead;
 
@@ -5515,47 +5346,47 @@ gdk_window_lower_internal (GdkWindow *window)
       parent->children = g_list_append (parent->children, window);
     }
 
-  impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
+  impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
   /* Just do native lower for toplevels */
-  if (gdk_window_is_toplevel (private) ||
+  if (gdk_window_is_toplevel (window) ||
       /* The restack_under codepath should work correctly even if the parent
         is native, but it relies on the order of ->children to be correct,
         and some apps like SWT reorder the x windows without gdks knowledge,
         so we use lower directly in order to make these behave as before
         when using native windows */
-      (gdk_window_has_impl (private) && gdk_window_has_impl (parent)))
+      (gdk_window_has_impl (window) && gdk_window_has_impl (parent)))
     {
-      impl_iface->lower (window);
+      impl_class->lower (window);
     }
-  else if (gdk_window_has_impl (private))
+  else if (gdk_window_has_impl (window))
     {
-      above = find_native_sibling_above (parent, private);
+      above = find_native_sibling_above (parent, window);
       if (above)
        {
          listhead.data = window;
          listhead.next = NULL;
          listhead.prev = NULL;
-         impl_iface->restack_under ((GdkWindow *)above, &listhead);
+         impl_class->restack_under ((GdkWindow *)above, &listhead);
        }
       else
-       impl_iface->raise (window);
+       impl_class->raise (window);
     }
   else
     {
       native_children = NULL;
-      get_all_native_children (private, &native_children);
+      get_all_native_children (window, &native_children);
       if (native_children != NULL)
        {
-         above = find_native_sibling_above (parent, private);
+         above = find_native_sibling_above (parent, window);
 
          if (above)
-           impl_iface->restack_under ((GdkWindow *)above,
+           impl_class->restack_under ((GdkWindow *)above,
                                       native_children);
          else
            {
              /* Right order, since native_children is bottom-topmost first */
              for (l = native_children; l != NULL; l = l->next)
-               impl_iface->raise (l->data);
+               impl_class->raise (l->data);
            }
 
          g_list_free (native_children);
@@ -5565,7 +5396,7 @@ gdk_window_lower_internal (GdkWindow *window)
 }
 
 static void
-gdk_window_invalidate_in_parent (GdkWindowObject *private)
+gdk_window_invalidate_in_parent (GdkWindow *private)
 {
   GdkRectangle r, child;
 
@@ -5583,7 +5414,7 @@ gdk_window_invalidate_in_parent (GdkWindowObject *private)
   child.height = private->height;
   gdk_rectangle_intersect (&r, &child, &r);
 
-  gdk_window_invalidate_rect_full (GDK_WINDOW (private->parent), &r, TRUE, CLEAR_BG_ALL);
+  gdk_window_invalidate_rect_full (private->parent, &r, TRUE, CLEAR_BG_ALL);
 }
 
 
@@ -5605,12 +5436,9 @@ gdk_window_invalidate_in_parent (GdkWindowObject *private)
 void
 gdk_window_lower (GdkWindow *window)
 {
-  GdkWindowObject *private;
-
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
+  if (window->destroyed)
     return;
 
   gdk_window_flush_if_exposing (window);
@@ -5618,10 +5446,10 @@ gdk_window_lower (GdkWindow *window)
   /* Keep children in (reverse) stacking order */
   gdk_window_lower_internal (window);
 
-  recompute_visible_regions (private, TRUE, FALSE);
+  recompute_visible_regions (window, TRUE, FALSE);
 
   _gdk_synthesize_crossing_events_for_geometry_change (window);
-  gdk_window_invalidate_in_parent (private);
+  gdk_window_invalidate_in_parent (window);
 }
 
 /**
@@ -5648,10 +5476,9 @@ gdk_window_restack (GdkWindow     *window,
                    GdkWindow     *sibling,
                    gboolean       above)
 {
-  GdkWindowObject *private;
-  GdkWindowImplIface *impl_iface;
-  GdkWindowObject *parent;
-  GdkWindowObject *above_native;
+  GdkWindowImplClass *impl_class;
+  GdkWindow *parent;
+  GdkWindow *above_native;
   GList *sibling_link;
   GList *native_children;
   GList *l, listhead;
@@ -5659,8 +5486,7 @@ gdk_window_restack (GdkWindow     *window,
   g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (sibling == NULL || GDK_IS_WINDOW (sibling));
 
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
+  if (window->destroyed)
     return;
 
   if (sibling == NULL)
@@ -5674,15 +5500,15 @@ gdk_window_restack (GdkWindow     *window,
 
   gdk_window_flush_if_exposing (window);
 
-  if (gdk_window_is_toplevel (private))
+  if (gdk_window_is_toplevel (window))
     {
-      g_return_if_fail (gdk_window_is_toplevel (GDK_WINDOW_OBJECT (sibling)));
-      impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
-      impl_iface->restack_toplevel (window, sibling, above);
+      g_return_if_fail (gdk_window_is_toplevel (sibling));
+      impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
+      impl_class->restack_toplevel (window, sibling, above);
       return;
     }
 
-  parent = private->parent;
+  parent = window->parent;
   if (parent)
     {
       sibling_link = g_list_find (parent->children, sibling);
@@ -5700,35 +5526,35 @@ gdk_window_restack (GdkWindow     *window,
                                                 sibling_link->next,
                                                 window);
 
-      impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
-      if (gdk_window_has_impl (private))
+      impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
+      if (gdk_window_has_impl (window))
        {
-         above_native = find_native_sibling_above (parent, private);
+         above_native = find_native_sibling_above (parent, window);
          if (above_native)
            {
              listhead.data = window;
              listhead.next = NULL;
              listhead.prev = NULL;
-             impl_iface->restack_under ((GdkWindow *)above_native, &listhead);
+             impl_class->restack_under (above_native, &listhead);
            }
          else
-           impl_iface->raise (window);
+           impl_class->raise (window);
        }
       else
        {
          native_children = NULL;
-         get_all_native_children (private, &native_children);
+         get_all_native_children (window, &native_children);
          if (native_children != NULL)
            {
-             above_native = find_native_sibling_above (parent, private);
+             above_native = find_native_sibling_above (parent, window);
              if (above_native)
-               impl_iface->restack_under ((GdkWindow *)above_native,
+               impl_class->restack_under (above_native,
                                           native_children);
              else
                {
                  /* Right order, since native_children is bottom-topmost first */
                  for (l = native_children; l != NULL; l = l->next)
-                   impl_iface->raise (l->data);
+                   impl_class->raise (l->data);
                }
 
              g_list_free (native_children);
@@ -5736,10 +5562,10 @@ gdk_window_restack (GdkWindow     *window,
        }
     }
 
-  recompute_visible_regions (private, TRUE, FALSE);
+  recompute_visible_regions (window, TRUE, FALSE);
 
   _gdk_synthesize_crossing_events_for_geometry_change (window);
-  gdk_window_invalidate_in_parent (private);
+  gdk_window_invalidate_in_parent (window);
 }
 
 
@@ -5775,19 +5601,17 @@ gdk_window_show (GdkWindow *window)
 void
 gdk_window_hide (GdkWindow *window)
 {
-  GdkWindowObject *private;
-  GdkWindowImplIface *impl_iface;
+  GdkWindowImplClass *impl_class;
   gboolean was_mapped, did_hide;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
+  if (window->destroyed)
     return;
 
-  was_mapped = GDK_WINDOW_IS_MAPPED (private);
+  was_mapped = GDK_WINDOW_IS_MAPPED (window);
 
-  if (gdk_window_has_impl (private))
+  if (gdk_window_has_impl (window))
     {
 
       if (GDK_WINDOW_IS_MAPPED (window))
@@ -5814,45 +5638,46 @@ gdk_window_hide (GdkWindow *window)
         {
           GdkDevice *device = d->data;
 
-          if (_gdk_display_end_device_grab (display, device,
-                                            _gdk_windowing_window_get_next_serial (display),
+          if (_gdk_display_end_device_grab (display,
+                                            device,
+                                            _gdk_display_get_next_serial (display),
                                             window,
                                             TRUE))
             gdk_device_ungrab (device, GDK_CURRENT_TIME);
         }
 
-      private->state = GDK_WINDOW_STATE_WITHDRAWN;
+      window->state = GDK_WINDOW_STATE_WITHDRAWN;
       g_list_free (devices);
     }
 
   did_hide = _gdk_window_update_viewable (window);
 
   /* Hide foreign window as those are not handled by update_viewable. */
-  if (gdk_window_has_impl (private) && (!did_hide))
+  if (gdk_window_has_impl (window) && (!did_hide))
     {
-      impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
-      impl_iface->hide (window);
+      impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
+      impl_class->hide (window);
     }
 
-  recompute_visible_regions (private, TRUE, FALSE);
+  recompute_visible_regions (window, TRUE, FALSE);
 
   /* all decendants became non-visible, we need to send visibility notify */
-  gdk_window_update_visibility_recursively (private, NULL);
+  gdk_window_update_visibility_recursively (window, NULL);
 
-  if (was_mapped && !gdk_window_has_impl (private))
+  if (was_mapped && !gdk_window_has_impl (window))
     {
-      if (private->event_mask & GDK_STRUCTURE_MASK)
-       _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
+      if (window->event_mask & GDK_STRUCTURE_MASK)
+       _gdk_make_event (window, GDK_UNMAP, NULL, FALSE);
 
-      if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
-       _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
+      if (window->parent && window->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+       _gdk_make_event (window, GDK_UNMAP, NULL, FALSE);
 
-      _gdk_synthesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
+      _gdk_synthesize_crossing_events_for_geometry_change (window->parent);
     }
 
   /* Invalidate the rect */
   if (was_mapped)
-    gdk_window_invalidate_in_parent (private);
+    gdk_window_invalidate_in_parent (window);
 }
 
 /**
@@ -5866,35 +5691,33 @@ gdk_window_hide (GdkWindow *window)
 void
 gdk_window_withdraw (GdkWindow *window)
 {
-  GdkWindowObject *private;
-  GdkWindowImplIface *impl_iface;
+  GdkWindowImplClass *impl_class;
   gboolean was_mapped;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
+  if (window->destroyed)
     return;
 
-  was_mapped = GDK_WINDOW_IS_MAPPED (private);
+  was_mapped = GDK_WINDOW_IS_MAPPED (window);
 
-  if (gdk_window_has_impl (private))
+  if (gdk_window_has_impl (window))
     {
-      impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
-      impl_iface->withdraw (window);
+      impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
+      impl_class->withdraw (window);
 
       if (was_mapped)
        {
-         if (private->event_mask & GDK_STRUCTURE_MASK)
-           _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
+         if (window->event_mask & GDK_STRUCTURE_MASK)
+           _gdk_make_event (window, GDK_UNMAP, NULL, FALSE);
 
-         if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
-           _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
+         if (window->parent && window->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+           _gdk_make_event (window, GDK_UNMAP, NULL, FALSE);
 
-         _gdk_synthesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
+         _gdk_synthesize_crossing_events_for_geometry_change (window->parent);
        }
 
-      recompute_visible_regions (private, TRUE, FALSE);
+      recompute_visible_regions (window, TRUE, FALSE);
     }
 }
 
@@ -5913,22 +5736,20 @@ void
 gdk_window_set_events (GdkWindow       *window,
                       GdkEventMask     event_mask)
 {
-  GdkWindowObject *private;
-  GdkWindowImplIface *impl_iface;
+  GdkWindowImplClass *impl_class;
   GdkDisplay *display;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
+  if (window->destroyed)
     return;
 
   /* If motion hint is disabled, enable motion events again */
   display = gdk_window_get_display (window);
-  if ((private->event_mask & GDK_POINTER_MOTION_HINT_MASK) &&
+  if ((window->event_mask & GDK_POINTER_MOTION_HINT_MASK) &&
       !(event_mask & GDK_POINTER_MOTION_HINT_MASK))
     {
-      GList *devices = private->devices_inside;
+      GList *devices = window->devices_inside;
 
       while (devices)
         {
@@ -5937,13 +5758,13 @@ gdk_window_set_events (GdkWindow       *window,
         }
     }
 
-  private->event_mask = event_mask;
+  window->event_mask = event_mask;
 
-  if (gdk_window_has_impl (private))
+  if (gdk_window_has_impl (window))
     {
-      impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
-      impl_iface->set_events (window,
-                             get_native_event_mask (private));
+      impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
+      impl_class->set_events (window,
+                             get_native_event_mask (window));
     }
 
 }
@@ -5960,15 +5781,12 @@ gdk_window_set_events (GdkWindow       *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)
+  if (window->destroyed)
     return 0;
 
-  return private->event_mask;
+  return window->event_mask;
 }
 
 /**
@@ -5991,7 +5809,6 @@ gdk_window_set_device_events (GdkWindow    *window,
                               GdkEventMask  event_mask)
 {
   GdkEventMask device_mask;
-  GdkWindowObject *private;
   GdkDisplay *display;
   GdkWindow *native;
 
@@ -6001,26 +5818,24 @@ gdk_window_set_device_events (GdkWindow    *window,
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
-  private = (GdkWindowObject *) window;
-
   /* If motion hint is disabled, enable motion events again */
   display = gdk_window_get_display (window);
-  if ((private->event_mask & GDK_POINTER_MOTION_HINT_MASK) &&
+  if ((window->event_mask & GDK_POINTER_MOTION_HINT_MASK) &&
       !(event_mask & GDK_POINTER_MOTION_HINT_MASK))
     _gdk_display_enable_motion_hints (display, device);
 
-  if (G_UNLIKELY (!private->device_events))
-    private->device_events = g_hash_table_new (NULL, NULL);
+  if (G_UNLIKELY (!window->device_events))
+    window->device_events = g_hash_table_new (NULL, NULL);
 
   if (event_mask == 0)
     {
       /* FIXME: unsetting events on a master device
-       * would restore private->event_mask
+       * would restore window->event_mask
        */
-      g_hash_table_remove (private->device_events, device);
+      g_hash_table_remove (window->device_events, device);
     }
   else
-    g_hash_table_insert (private->device_events, device,
+    g_hash_table_insert (window->device_events, device,
                          GINT_TO_POINTER (event_mask));
 
   if (_gdk_native_windows)
@@ -6028,7 +5843,7 @@ gdk_window_set_device_events (GdkWindow    *window,
   else
     native = gdk_window_get_toplevel (window);
 
-  while (gdk_window_is_offscreen ((GdkWindowObject *)native))
+  while (gdk_window_is_offscreen (native))
     {
       native = gdk_offscreen_window_get_embedder (native);
 
@@ -6040,7 +5855,7 @@ gdk_window_set_device_events (GdkWindow    *window,
       native = gdk_window_get_toplevel (native);
     }
 
-  device_mask = get_native_device_event_mask (private, device);
+  device_mask = get_native_device_event_mask (window, device);
   GDK_DEVICE_GET_CLASS (device)->select_window_events (device, native, device_mask);
 }
 
@@ -6059,7 +5874,6 @@ GdkEventMask
 gdk_window_get_device_events (GdkWindow *window,
                               GdkDevice *device)
 {
-  GdkWindowObject *private;
   GdkEventMask mask;
 
   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
@@ -6068,14 +5882,12 @@ gdk_window_get_device_events (GdkWindow *window,
   if (GDK_WINDOW_DESTROYED (window))
     return 0;
 
-  private = (GdkWindowObject *) window;
-
-  if (!private->device_events)
+  if (!window->device_events)
     return 0;
 
-  mask = GPOINTER_TO_INT (g_hash_table_lookup (private->device_events, device));
+  mask = GPOINTER_TO_INT (g_hash_table_lookup (window->device_events, device));
 
-  /* FIXME: device could be controlled by private->event_mask */
+  /* FIXME: device could be controlled by window->event_mask */
 
   return mask;
 }
@@ -6088,47 +5900,44 @@ gdk_window_move_resize_toplevel (GdkWindow *window,
                                 gint       width,
                                 gint       height)
 {
-  GdkWindowObject *private;
   cairo_region_t *old_region, *new_region;
-  GdkWindowImplIface *impl_iface;
+  GdkWindowImplClass *impl_class;
   gboolean expose;
   int old_x, old_y, old_abs_x, old_abs_y;
   int dx, dy;
   gboolean is_resize;
 
-  private = (GdkWindowObject *) window;
-
   expose = FALSE;
   old_region = NULL;
 
-  old_x = private->x;
-  old_y = private->y;
+  old_x = window->x;
+  old_y = window->y;
 
   is_resize = (width != -1) || (height != -1);
 
   if (gdk_window_is_viewable (window) &&
-      !private->input_only)
+      !window->input_only)
     {
       expose = TRUE;
-      old_region = cairo_region_copy (private->clip_region);
+      old_region = cairo_region_copy (window->clip_region);
     }
 
-  impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
-  impl_iface->move_resize (window, with_move, x, y, width, height);
+  impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
+  impl_class->move_resize (window, with_move, x, y, width, height);
 
-  dx = private->x - old_x;
-  dy = private->y - old_y;
+  dx = window->x - old_x;
+  dy = window->y - old_y;
 
-  old_abs_x = private->abs_x;
-  old_abs_y = private->abs_y;
+  old_abs_x = window->abs_x;
+  old_abs_y = window->abs_y;
 
   /* Avoid recomputing for pure toplevel moves, for performance reasons */
   if (is_resize)
-    recompute_visible_regions (private, TRUE, FALSE);
+    recompute_visible_regions (window, TRUE, FALSE);
 
   if (expose)
     {
-      new_region = cairo_region_copy (private->clip_region);
+      new_region = cairo_region_copy (window->clip_region);
 
       /* This is the newly exposed area (due to any resize),
        * X will expose it, but lets do that without the
@@ -6146,11 +5955,11 @@ gdk_window_move_resize_toplevel (GdkWindow *window,
 
 
 static void
-move_native_children (GdkWindowObject *private)
+move_native_children (GdkWindow *private)
 {
   GList *l;
-  GdkWindowObject *child;
-  GdkWindowImplIface *impl_iface;
+  GdkWindow *child;
+  GdkWindowImplClass *impl_class;
 
   for (l = private->children; l; l = l->next)
     {
@@ -6158,8 +5967,8 @@ move_native_children (GdkWindowObject *private)
 
       if (child->impl != private->impl)
        {
-         impl_iface = GDK_WINDOW_IMPL_GET_IFACE (child->impl);
-         impl_iface->move_resize ((GdkWindow *)child, TRUE,
+         impl_class = GDK_WINDOW_IMPL_GET_CLASS (child->impl);
+         impl_class->move_resize (child, TRUE,
                                   child->x, child->y,
                                   child->width, child->height);
        }
@@ -6169,13 +5978,13 @@ move_native_children (GdkWindowObject *private)
 }
 
 static gboolean
-collect_native_child_region_helper (GdkWindowObject *window,
-                                   GdkWindow *impl,
+collect_native_child_region_helper (GdkWindow *window,
+                                   GdkWindowImpl *impl,
                                    cairo_region_t **region,
                                    int x_offset,
                                    int y_offset)
 {
-  GdkWindowObject *child;
+  GdkWindow *child;
   cairo_region_t *tmp;
   GList *l;
 
@@ -6210,7 +6019,7 @@ collect_native_child_region_helper (GdkWindowObject *window,
 }
 
 static cairo_region_t *
-collect_native_child_region (GdkWindowObject *window,
+collect_native_child_region (GdkWindow *window,
                             gboolean include_this)
 {
   cairo_region_t *region;
@@ -6234,33 +6043,31 @@ gdk_window_move_resize_internal (GdkWindow *window,
                                 gint       width,
                                 gint       height)
 {
-  GdkWindowObject *private;
   cairo_region_t *old_region, *new_region, *copy_area;
   cairo_region_t *old_native_child_region, *new_native_child_region;
-  GdkWindowObject *impl_window;
-  GdkWindowImplIface *impl_iface;
+  GdkWindow *impl_window;
+  GdkWindowImplClass *impl_class;
   gboolean expose;
   int old_x, old_y, old_abs_x, old_abs_y;
   int dx, dy;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
+  if (window->destroyed)
     return;
 
-  if (gdk_window_is_toplevel (private))
+  if (gdk_window_is_toplevel (window))
     {
       gdk_window_move_resize_toplevel (window, with_move, x, y, width, height);
       return;
     }
 
   /* Bail early if no change */
-  if (private->width == width &&
-      private->height == height &&
+  if (window->width == width &&
+      window->height == height &&
       (!with_move ||
-       (private->x == x &&
-       private->y == y)))
+       (window->x == x &&
+       window->y == y)))
     return;
 
   gdk_window_flush_if_exposing (window);
@@ -6270,26 +6077,26 @@ gdk_window_move_resize_internal (GdkWindow *window,
   expose = FALSE;
   old_region = NULL;
 
-  impl_window = gdk_window_get_impl_window (private);
+  impl_window = gdk_window_get_impl_window (window);
 
-  old_x = private->x;
-  old_y = private->y;
+  old_x = window->x;
+  old_y = window->y;
 
   old_native_child_region = NULL;
   if (gdk_window_is_viewable (window) &&
-      !private->input_only)
+      !window->input_only)
     {
       expose = TRUE;
 
-      old_region = cairo_region_copy (private->clip_region);
+      old_region = cairo_region_copy (window->clip_region);
       /* Adjust region to parent window coords */
-      cairo_region_translate (old_region, private->x, private->y);
+      cairo_region_translate (old_region, window->x, window->y);
 
-      old_native_child_region = collect_native_child_region (private, TRUE);
+      old_native_child_region = collect_native_child_region (window, TRUE);
       if (old_native_child_region)
        {
          /* Adjust region to parent window coords */
-         cairo_region_translate (old_native_child_region, private->x, private->y);
+         cairo_region_translate (old_native_child_region, window->x, window->y);
 
          /* Any native window move will immediately copy stuff to the destination, which may overwrite a
           * source or destination for a delayed GdkWindowRegionMove. So, we need
@@ -6297,61 +6104,61 @@ gdk_window_move_resize_internal (GdkWindow *window,
           * of it. And we need to do this before setting the new clips as those will be
           * affecting this.
           */
-         gdk_window_flush_recursive (private->parent);
+         gdk_window_flush_recursive (window->parent);
        }
     }
 
   /* Set the new position and size */
   if (with_move)
     {
-      private->x = x;
-      private->y = y;
+      window->x = x;
+      window->y = y;
     }
   if (!(width < 0 && height < 0))
     {
       if (width < 1)
        width = 1;
-      private->width = width;
+      window->width = width;
       if (height < 1)
        height = 1;
-      private->height = height;
+      window->height = height;
     }
 
-  dx = private->x - old_x;
-  dy = private->y - old_y;
+  dx = window->x - old_x;
+  dy = window->y - old_y;
 
-  old_abs_x = private->abs_x;
-  old_abs_y = private->abs_y;
+  old_abs_x = window->abs_x;
+  old_abs_y = window->abs_y;
 
-  recompute_visible_regions (private, TRUE, FALSE);
+  recompute_visible_regions (window, TRUE, FALSE);
 
   new_native_child_region = NULL;
   if (old_native_child_region)
     {
-      new_native_child_region = collect_native_child_region (private, TRUE);
+      new_native_child_region = collect_native_child_region (window, TRUE);
       /* Adjust region to parent window coords */
-      cairo_region_translate (new_native_child_region, private->x, private->y);
+      cairo_region_translate (new_native_child_region, window->x, window->y);
     }
 
-  if (gdk_window_has_impl (private))
+  if (gdk_window_has_impl (window))
     {
-      impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
+      impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 
       /* Do the actual move after recomputing things, as this will have set the shape to
         the now correct one, thus avoiding copying regions that should not be copied. */
-      impl_iface->move_resize (window, TRUE,
-                              private->x, private->y,
-                              private->width, private->height);
+      impl_class->move_resize (window, TRUE,
+                              window->x, window->y,
+                              window->width, window->height);
     }
-  else if (old_abs_x != private->abs_x ||
-          old_abs_y != private->abs_y)
-    move_native_children (private);
+  else if (old_abs_x != window->abs_x ||
+          old_abs_y != window->abs_y)
+    move_native_children (window);
 
   if (expose)
     {
-      new_region = cairo_region_copy (private->clip_region);
+      new_region = cairo_region_copy (window->clip_region);
       /* Adjust region to parent window coords */
-      cairo_region_translate (new_region, private->x, private->y);
+      cairo_region_translate (new_region, window->x, window->y);
 
       /* copy_area:
        * Part of the data at the new location can be copied from the
@@ -6390,10 +6197,10 @@ gdk_window_move_resize_internal (GdkWindow *window,
       cairo_region_subtract (new_region, copy_area);
 
       /* Convert old region to impl coords */
-      cairo_region_translate (old_region, -dx + private->abs_x - private->x, -dy + private->abs_y - private->y);
+      cairo_region_translate (old_region, -dx + window->abs_x - window->x, -dy + window->abs_y - window->y);
 
       /* convert from parent coords to impl */
-      cairo_region_translate (copy_area, private->abs_x - private->x, private->abs_y - private->y);
+      cairo_region_translate (copy_area, window->abs_x - window->x, window->abs_y - window->y);
 
       move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
 
@@ -6409,7 +6216,7 @@ gdk_window_move_resize_internal (GdkWindow *window,
          cairo_region_intersect (old_native_child_region, new_native_child_region);
          cairo_region_subtract (new_region, old_native_child_region);
        }
-      gdk_window_invalidate_region_full (GDK_WINDOW (private->parent), new_region, TRUE, CLEAR_BG_ALL);
+      gdk_window_invalidate_region_full (window->parent, new_region, TRUE, CLEAR_BG_ALL);
 
       cairo_region_destroy (old_region);
       cairo_region_destroy (new_region);
@@ -6520,8 +6327,7 @@ gdk_window_scroll (GdkWindow *window,
                   gint       dx,
                   gint       dy)
 {
-  GdkWindowObject *private = (GdkWindowObject *) window;
-  GdkWindowObject *impl_window;
+  GdkWindow *impl_window;
   cairo_region_t *copy_area, *noncopy_area;
   cairo_region_t *old_native_child_region, *new_native_child_region;
   GList *tmp_list;
@@ -6531,12 +6337,12 @@ gdk_window_scroll (GdkWindow *window,
   if (dx == 0 && dy == 0)
     return;
 
-  if (private->destroyed)
+  if (window->destroyed)
     return;
 
   gdk_window_flush_if_exposing (window);
 
-  old_native_child_region = collect_native_child_region (private, FALSE);
+  old_native_child_region = collect_native_child_region (window, FALSE);
   if (old_native_child_region)
     {
       /* Any native window move will immediately copy stuff to the destination, which may overwrite a
@@ -6545,39 +6351,38 @@ gdk_window_scroll (GdkWindow *window,
        * of it. And we need to do this before setting the new clips as those will be
        * affecting this.
        */
-      gdk_window_flush_recursive (private);
+      gdk_window_flush_recursive (window);
     }
 
 
   /* First move all child windows, without causing invalidation */
 
-  tmp_list = private->children;
+  tmp_list = window->children;
   while (tmp_list)
     {
       GdkWindow *child = GDK_WINDOW (tmp_list->data);
-      GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
 
       /* Just update the positions, the bits will move with the copy */
-      child_obj->x += dx;
-      child_obj->y += dy;
+      child->x += dx;
+      child->y += dy;
 
       tmp_list = tmp_list->next;
     }
 
-  recompute_visible_regions (private, FALSE, TRUE);
+  recompute_visible_regions (window, FALSE, TRUE);
 
   new_native_child_region = NULL;
   if (old_native_child_region)
-    new_native_child_region = collect_native_child_region (private, FALSE);
+    new_native_child_region = collect_native_child_region (window, FALSE);
 
-  move_native_children (private);
+  move_native_children (window);
 
   /* Then copy the actual bits of the window w/ child windows */
 
-  impl_window = gdk_window_get_impl_window (private);
+  impl_window = gdk_window_get_impl_window (window);
 
   /* Calculate the area that can be gotten by copying the old area */
-  copy_area = cairo_region_copy (private->clip_region);
+  copy_area = cairo_region_copy (window->clip_region);
   if (old_native_child_region)
     {
       /* Don't copy from inside native children, as this is copied by
@@ -6590,14 +6395,14 @@ gdk_window_scroll (GdkWindow *window,
       cairo_region_subtract (copy_area, new_native_child_region);
     }
   cairo_region_translate (copy_area, dx, dy);
-  cairo_region_intersect (copy_area, private->clip_region);
+  cairo_region_intersect (copy_area, window->clip_region);
 
   /* And the rest need to be invalidated */
-  noncopy_area = cairo_region_copy (private->clip_region);
+  noncopy_area = cairo_region_copy (window->clip_region);
   cairo_region_subtract (noncopy_area, copy_area);
 
   /* convert from window coords to impl */
-  cairo_region_translate (copy_area, private->abs_x, private->abs_y);
+  cairo_region_translate (copy_area, window->abs_x, window->abs_y);
 
   move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
 
@@ -6643,8 +6448,7 @@ gdk_window_move_region (GdkWindow       *window,
                        gint             dx,
                        gint             dy)
 {
-  GdkWindowObject *private = (GdkWindowObject *) window;
-  GdkWindowObject *impl_window;
+  GdkWindow *impl_window;
   cairo_region_t *nocopy_area;
   cairo_region_t *copy_area;
 
@@ -6654,18 +6458,18 @@ gdk_window_move_region (GdkWindow       *window,
   if (dx == 0 && dy == 0)
     return;
 
-  if (private->destroyed)
+  if (window->destroyed)
     return;
 
-  impl_window = gdk_window_get_impl_window (private);
+  impl_window = gdk_window_get_impl_window (window);
 
   /* compute source regions */
   copy_area = cairo_region_copy (region);
-  cairo_region_intersect (copy_area, private->clip_region_with_children);
+  cairo_region_intersect (copy_area, window->clip_region_with_children);
 
   /* compute destination regions */
   cairo_region_translate (copy_area, dx, dy);
-  cairo_region_intersect (copy_area, private->clip_region_with_children);
+  cairo_region_intersect (copy_area, window->clip_region_with_children);
 
   /* Invalidate parts of the region (source and dest) not covered
      by the copy */
@@ -6675,7 +6479,7 @@ gdk_window_move_region (GdkWindow       *window,
   cairo_region_subtract (nocopy_area, copy_area);
 
   /* convert from window coords to impl */
-  cairo_region_translate (copy_area, private->abs_x, private->abs_y);
+  cairo_region_translate (copy_area, window->abs_x, window->abs_y);
   move_region_on_impl (impl_window, copy_area, dx, dy); /* Takes ownership of copy_area */
 
   gdk_window_invalidate_region_full (window, nocopy_area, FALSE, CLEAR_BG_ALL);
@@ -6711,6 +6515,32 @@ gdk_window_set_background (GdkWindow      *window,
   cairo_pattern_destroy (pattern);
 }
 
+/**
+ * gdk_window_set_background_rgba:
+ * @window: a #GdkWindow
+ * @rgba: a #GdkRGBA color
+ *
+ * Sets the background color of @window.
+ *
+ * See also gdk_window_set_background_pattern().
+ **/
+void
+gdk_window_set_background_rgba (GdkWindow *window,
+                                GdkRGBA   *rgba)
+{
+  cairo_pattern_t *pattern;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (rgba != NULL);
+
+  pattern = cairo_pattern_create_rgba (rgba->red, rgba->green,
+                                       rgba->blue, rgba->alpha);
+
+  gdk_window_set_background_pattern (window, pattern);
+
+  cairo_pattern_destroy (pattern);
+}
+
 /**
  * gdk_window_set_background_pattern:
  * @window: a #GdkWindow
@@ -6722,30 +6552,25 @@ gdk_window_set_background (GdkWindow      *window,
  * background form its parent window.
  *
  * 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().
+ * when the window is obscured then exposed.
  */
 void
 gdk_window_set_background_pattern (GdkWindow *window,
                                    cairo_pattern_t *pattern)
 {
-  GdkWindowObject *private;
-
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  private = (GdkWindowObject *) window;
-
   if (pattern)
     cairo_pattern_reference (pattern);
-  if (private->background)
-    cairo_pattern_destroy (private->background);
-  private->background = pattern;
+  if (window->background)
+    cairo_pattern_destroy (window->background);
+  window->background = pattern;
 
-  if (gdk_window_has_impl (private) &&
-      !private->input_only)
+  if (gdk_window_has_impl (window) &&
+      !window->input_only)
     {
-      GdkWindowImplIface *impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
-      impl_iface->set_background (window, pattern);
+      GdkWindowImplClass *impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
+      impl_class->set_background (window, pattern);
     }
 }
 
@@ -6765,11 +6590,9 @@ gdk_window_set_background_pattern (GdkWindow *window,
 cairo_pattern_t *
 gdk_window_get_background_pattern (GdkWindow *window)
 {
-  GdkWindowObject *private = (GdkWindowObject *) window;
-
   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 
-  return private->background;
+  return window->background;
 }
 
 static void
@@ -6779,12 +6602,11 @@ update_cursor_foreach (GdkDisplay           *display,
                        gpointer              user_data)
 {
   GdkWindow *window = user_data;
-  GdkWindowObject *private = (GdkWindowObject *) window;
 
   if (_gdk_native_windows ||
-      private->window_type == GDK_WINDOW_ROOT ||
-      private->window_type == GDK_WINDOW_FOREIGN)
-    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_device_cursor (window, device, private->cursor);
+      window->window_type == GDK_WINDOW_ROOT ||
+      window->window_type == GDK_WINDOW_FOREIGN)
+    GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_device_cursor (window, device, window->cursor);
   else if (_gdk_window_event_parent_of (window, pointer_info->window_under_pointer))
     update_cursor (display, device);
 }
@@ -6807,13 +6629,9 @@ update_cursor_foreach (GdkDisplay           *display,
 GdkCursor *
 gdk_window_get_cursor (GdkWindow *window)
 {
-  GdkWindowObject *private;
-
   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 
-  private = (GdkWindowObject *) window;
-
-  return private->cursor;
+  return window->cursor;
 }
 
 /**
@@ -6831,24 +6649,22 @@ void
 gdk_window_set_cursor (GdkWindow *window,
                       GdkCursor *cursor)
 {
-  GdkWindowObject *private;
   GdkDisplay *display;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  private = (GdkWindowObject *) window;
   display = gdk_window_get_display (window);
 
-  if (private->cursor)
+  if (window->cursor)
     {
-      gdk_cursor_unref (private->cursor);
-      private->cursor = NULL;
+      g_object_unref (window->cursor);
+      window->cursor = NULL;
     }
 
   if (!GDK_WINDOW_DESTROYED (window))
     {
       if (cursor)
-       private->cursor = gdk_cursor_ref (cursor);
+       window->cursor = g_object_ref (cursor);
 
       _gdk_display_pointer_info_foreach (display,
                                          update_cursor_foreach,
@@ -6861,7 +6677,7 @@ gdk_window_set_cursor (GdkWindow *window,
 /**
  * gdk_window_get_device_cursor:
  * @window: a #GdkWindow.
- * @device: a #GdkDevice.
+ * @device: a master, pointer #GdkDevice.
  *
  * Retrieves a #GdkCursor pointer for the @device currently set on the
  * specified #GdkWindow, or %NULL.  If the return value is %NULL then
@@ -6878,20 +6694,18 @@ GdkCursor *
 gdk_window_get_device_cursor (GdkWindow *window,
                               GdkDevice *device)
 {
-  GdkWindowObject *private;
-
   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
   g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
+  g_return_val_if_fail (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD, NULL);
+  g_return_val_if_fail (gdk_device_get_device_type (device) == GDK_DEVICE_TYPE_MASTER, NULL);
 
-  private = (GdkWindowObject *) window;
-
-  return g_hash_table_lookup (private->device_cursor, device);
+  return g_hash_table_lookup (window->device_cursor, device);
 }
 
 /**
  * gdk_window_set_device_cursor:
  * @window: a #Gdkwindow
- * @device: a #GdkDevice
+ * @device: a master, pointer #GdkDevice
  * @cursor: a #GdkCursor
  *
  * Sets a specific #GdkCursor for a given device when it gets inside @window.
@@ -6908,19 +6722,19 @@ gdk_window_set_device_cursor (GdkWindow *window,
                               GdkDevice *device,
                               GdkCursor *cursor)
 {
-  GdkWindowObject *private;
   GdkDisplay *display;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (GDK_IS_DEVICE (device));
+  g_return_if_fail (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD);
+  g_return_if_fail (gdk_device_get_device_type (device) == GDK_DEVICE_TYPE_MASTER);
 
-  private = (GdkWindowObject *) window;
   display = gdk_window_get_display (window);
 
   if (!cursor)
-    g_hash_table_remove (private->device_cursor, device);
+    g_hash_table_remove (window->device_cursor, device);
   else
-    g_hash_table_replace (private->device_cursor, device, gdk_cursor_ref (cursor));
+    g_hash_table_replace (window->device_cursor, device, g_object_ref (cursor));
 
   if (!GDK_WINDOW_DESTROYED (window))
     {
@@ -6936,11 +6750,10 @@ gdk_window_set_device_cursor (GdkWindow *window,
 /**
  * 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
+ * @x: (out) (allow-none): return location for X coordinate of window (relative to its parent)
+ * @y: (out) (allow-none): return location for Y coordinate of window (relative to its parent)
+ * @width: (out) (allow-none): return location for width of window
+ * @height: (out) (allow-none): return location for height 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.
@@ -6958,11 +6771,11 @@ gdk_window_set_device_cursor (GdkWindow *window,
  *
  * <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.
+ * to call gdk_window_get_position(), gdk_window_get_width() and
+ * gdk_window_get_height() instead, because it avoids the roundtrip to
+ * the X server and because these functions support the full 32-bit
+ * coordinate space, whereas gdk_window_get_geometry() is restricted to
+ * the 16-bit coordinates of X11.
  *</note>
  **/
 void
@@ -6970,11 +6783,10 @@ gdk_window_get_geometry (GdkWindow *window,
                         gint      *x,
                         gint      *y,
                         gint      *width,
-                        gint      *height,
-                        gint      *depth)
+                        gint      *height)
 {
-  GdkWindowObject *private, *parent;
-  GdkWindowImplIface *impl_iface;
+  GdkWindow *parent;
+  GdkWindowImplClass *impl_class;
 
   if (!window)
     {
@@ -6986,19 +6798,16 @@ gdk_window_get_geometry (GdkWindow *window,
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  private = (GdkWindowObject *) window;
-
   if (!GDK_WINDOW_DESTROYED (window))
     {
-      if (gdk_window_has_impl (private))
+      if (gdk_window_has_impl (window))
        {
-         impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
-         impl_iface->get_geometry (window, x, y,
-                                   width, height,
-                                   depth);
+         impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
+         impl_class->get_geometry (window, x, y,
+                                   width, height);
          /* This reports the position wrt to the native parent, we need to convert
             it to be relative to the client side parent */
-         parent = private->parent;
+         parent = window->parent;
          if (parent && !gdk_window_has_impl (parent))
            {
              if (x)
@@ -7010,24 +6819,66 @@ gdk_window_get_geometry (GdkWindow *window,
       else
        {
           if (x)
-            *x = private->x;
+            *x = window->x;
           if (y)
-            *y = private->y;
+            *y = window->y;
          if (width)
-           *width = private->width;
+           *width = window->width;
          if (height)
-           *height = private->height;
-         if (depth)
-           *depth = private->depth;
+           *height = window->height;
        }
     }
 }
 
+/**
+ * gdk_window_get_width:
+ * @window: a #GdkWindow
+ *
+ * Returns the width of the given @window.
+ *
+ * On the X11 platform the returned size is the size reported in the
+ * most-recently-processed configure event, rather than the current
+ * size on the X server.
+ *
+ * Returns: The width of @window
+ *
+ * Since: 2.24
+ */
+int
+gdk_window_get_width (GdkWindow *window)
+{
+  g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
+
+  return window->width;
+}
+
+/**
+ * gdk_window_get_height:
+ * @window: a #GdkWindow
+ *
+ * Returns the height of the given @window.
+ *
+ * On the X11 platform the returned size is the size reported in the
+ * most-recently-processed configure event, rather than the current
+ * size on the X server.
+ *
+ * Returns: The height of @window
+ *
+ * Since: 2.24
+ */
+int
+gdk_window_get_height (GdkWindow *window)
+{
+  g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
+
+  return window->height;
+}
+
 /**
  * gdk_window_get_origin:
  * @window: a #GdkWindow
- * @x: return location for X coordinate
- * @y: return location for Y coordinate
+ * @x: (out) (allow-none): return location for X coordinate
+ * @y: (out) (allow-none): return location for Y coordinate
  *
  * Obtains the position of a window in root window coordinates.
  * (Compare with gdk_window_get_position() and
@@ -7041,8 +6892,7 @@ gdk_window_get_origin (GdkWindow *window,
                       gint      *x,
                       gint      *y)
 {
-  GdkWindowObject *private;
-  GdkWindowImplIface *impl_iface;
+  GdkWindowImplClass *impl_class;
 
   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
 
@@ -7054,13 +6904,11 @@ gdk_window_get_origin (GdkWindow *window,
        *y = 0;
       return 0;
     }
-  
-  private = (GdkWindowObject *) window;
 
-  impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
-  impl_iface->get_root_coords (window,
-                              private->abs_x,
-                              private->abs_y,
+  impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
+  impl_class->get_root_coords (window,
+                              window->abs_x,
+                              window->abs_y,
                               x, y);
 
   return TRUE;
@@ -7088,13 +6936,10 @@ gdk_window_get_root_coords (GdkWindow *window,
                            gint      *root_x,
                            gint      *root_y)
 {
-  GdkWindowObject *private;
-  GdkWindowImplIface *impl_iface;
+  GdkWindowImplClass *impl_class;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  private = (GdkWindowObject *) window;
-
   if (GDK_WINDOW_DESTROYED (window))
     {
       if (x)
@@ -7104,10 +6949,10 @@ gdk_window_get_root_coords (GdkWindow *window,
       return;
     }
   
-  impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
-  impl_iface->get_root_coords (window,
-                              x + private->abs_x,
-                              y + private->abs_y,
+  impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
+  impl_class->get_root_coords (window,
+                              x + window->abs_x,
+                              y + window->abs_y,
                               root_x, root_y);
 }
 
@@ -7147,17 +6992,13 @@ gdk_window_coords_to_parent (GdkWindow *window,
                              gdouble   *parent_x,
                              gdouble   *parent_y)
 {
-  GdkWindowObject *obj;
-
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  obj = (GdkWindowObject *) window;
-
-  if (gdk_window_is_offscreen (obj))
+  if (gdk_window_is_offscreen (window))
     {
       gdouble px, py;
 
-      to_embedder (obj, x, y, &px, &py);
+      to_embedder (window, x, y, &px, &py);
 
       if (parent_x)
         *parent_x = px;
@@ -7168,10 +7009,10 @@ gdk_window_coords_to_parent (GdkWindow *window,
   else
     {
       if (parent_x)
-        *parent_x = x + obj->x;
+        *parent_x = x + window->x;
 
       if (parent_y)
-        *parent_y = y + obj->y;
+        *parent_y = y + window->y;
     }
 }
 
@@ -7209,17 +7050,13 @@ gdk_window_coords_from_parent (GdkWindow *window,
                                gdouble   *x,
                                gdouble   *y)
 {
-  GdkWindowObject *obj;
-
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  obj = (GdkWindowObject *) window;
-
-  if (gdk_window_is_offscreen (obj))
+  if (gdk_window_is_offscreen (window))
     {
       gdouble cx, cy;
 
-      from_embedder (obj, parent_x, parent_y, &cx, &cy);
+      from_embedder (window, parent_x, parent_y, &cx, &cy);
 
       if (x)
         *x = cx;
@@ -7230,10 +7067,10 @@ gdk_window_coords_from_parent (GdkWindow *window,
   else
     {
       if (x)
-        *x = parent_x - obj->x;
+        *x = parent_x - window->x;
 
       if (y)
-        *y = parent_y - obj->y;
+        *y = parent_y - window->y;
     }
 }
 
@@ -7265,42 +7102,42 @@ gdk_window_shape_combine_region (GdkWindow       *window,
                                 gint             offset_x,
                                 gint             offset_y)
 {
-  GdkWindowObject *private;
   cairo_region_t *old_region, *new_region, *diff;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  private = (GdkWindowObject *) window;
-
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
-  private->shaped = (shape_region != NULL);
+  if (!window->shape && shape_region == NULL)
+    return;
+
+  window->shaped = (shape_region != NULL);
 
-  if (private->shape)
-    cairo_region_destroy (private->shape);
+  if (window->shape)
+    cairo_region_destroy (window->shape);
 
   old_region = NULL;
   if (GDK_WINDOW_IS_MAPPED (window))
-    old_region = cairo_region_copy (private->clip_region);
+    old_region = cairo_region_copy (window->clip_region);
 
   if (shape_region)
     {
-      private->shape = cairo_region_copy (shape_region);
-      cairo_region_translate (private->shape, offset_x, offset_y);
+      window->shape = cairo_region_copy (shape_region);
+      cairo_region_translate (window->shape, offset_x, offset_y);
     }
   else
-    private->shape = NULL;
+    window->shape = NULL;
 
-  recompute_visible_regions (private, TRUE, FALSE);
+  recompute_visible_regions (window, TRUE, FALSE);
 
-  if (gdk_window_has_impl (private) &&
-      !should_apply_clip_as_shape (private))
-    apply_shape (private, private->shape);
+  if (gdk_window_has_impl (window) &&
+      !should_apply_clip_as_shape (window))
+    apply_shape (window, window->shape);
 
   if (old_region)
     {
-      new_region = cairo_region_copy (private->clip_region);
+      new_region = cairo_region_copy (window->clip_region);
 
       /* New area in the window, needs invalidation */
       diff = cairo_region_copy (new_region);
@@ -7310,16 +7147,16 @@ gdk_window_shape_combine_region (GdkWindow       *window,
 
       cairo_region_destroy (diff);
 
-      if (!gdk_window_is_toplevel (private))
+      if (!gdk_window_is_toplevel (window))
        {
          /* New area in the non-root parent window, needs invalidation */
          diff = cairo_region_copy (old_region);
          cairo_region_subtract (diff, new_region);
 
          /* Adjust region to parent window coords */
-         cairo_region_translate (diff, private->x, private->y);
+         cairo_region_translate (diff, window->x, window->y);
 
-         gdk_window_invalidate_region_full (GDK_WINDOW (private->parent), diff, TRUE, CLEAR_BG_ALL);
+         gdk_window_invalidate_region_full (window->parent, diff, TRUE, CLEAR_BG_ALL);
 
          cairo_region_destroy (diff);
        }
@@ -7333,22 +7170,19 @@ static void
 do_child_shapes (GdkWindow *window,
                 gboolean merge)
 {
-  GdkWindowObject *private;
   GdkRectangle r;
   cairo_region_t *region;
 
-  private = (GdkWindowObject *) window;
-
   r.x = 0;
   r.y = 0;
-  r.width = private->width;
-  r.height = private->height;
+  r.width = window->width;
+  r.height = window->height;
 
   region = cairo_region_create_rectangle (&r);
-  remove_child_area (private, NULL, FALSE, region);
+  remove_child_area (window, NULL, FALSE, region);
 
-  if (merge && private->shape)
-    cairo_region_subtract (region, private->shape);
+  if (merge && window->shape)
+    cairo_region_subtract (region, window->shape);
 
   gdk_window_shape_combine_region (window, region, 0, 0);
 }
@@ -7423,31 +7257,28 @@ gdk_window_input_shape_combine_region (GdkWindow       *window,
                                       gint             offset_x,
                                       gint             offset_y)
 {
-  GdkWindowObject *private;
-  GdkWindowImplIface *impl_iface;
+  GdkWindowImplClass *impl_class;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  private = (GdkWindowObject *) window;
-
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
-  if (private->input_shape)
-    cairo_region_destroy (private->input_shape);
+  if (window->input_shape)
+    cairo_region_destroy (window->input_shape);
 
   if (shape_region)
     {
-      private->input_shape = cairo_region_copy (shape_region);
-      cairo_region_translate (private->input_shape, offset_x, offset_y);
+      window->input_shape = cairo_region_copy (shape_region);
+      cairo_region_translate (window->input_shape, offset_x, offset_y);
     }
   else
-    private->input_shape = NULL;
+    window->input_shape = NULL;
 
-  if (gdk_window_has_impl (private))
+  if (gdk_window_has_impl (window))
     {
-      impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
-      impl_iface->input_shape_combine_region (window, private->input_shape, 0, 0);
+      impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
+      impl_class->input_shape_combine_region (window, window->input_shape, 0, 0);
     }
 
   /* Pointer may have e.g. moved outside window due to the input mask change */
@@ -7458,24 +7289,21 @@ static void
 do_child_input_shapes (GdkWindow *window,
                       gboolean merge)
 {
-  GdkWindowObject *private;
   GdkRectangle r;
   cairo_region_t *region;
 
-  private = (GdkWindowObject *) window;
-
   r.x = 0;
   r.y = 0;
-  r.width = private->width;
-  r.height = private->height;
+  r.width = window->width;
+  r.height = window->height;
 
   region = cairo_region_create_rectangle (&r);
-  remove_child_area (private, NULL, TRUE, region);
+  remove_child_area (window, NULL, TRUE, region);
 
-  if (merge && private->shape)
-    cairo_region_subtract (region, private->shape);
-  if (merge && private->input_shape)
-    cairo_region_subtract (region, private->input_shape);
+  if (merge && window->shape)
+    cairo_region_subtract (region, window->shape);
+  if (merge && window->input_shape)
+    cairo_region_subtract (region, window->input_shape);
 
   gdk_window_input_shape_combine_region (window, region, 0, 0);
 }
@@ -7540,17 +7368,14 @@ gboolean
 gdk_window_set_static_gravities (GdkWindow *window,
                                 gboolean   use_static)
 {
-  GdkWindowObject *private;
-  GdkWindowImplIface *impl_iface;
+  GdkWindowImplClass *impl_class;
 
   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
-  private = (GdkWindowObject *) window;
-
-  if (gdk_window_has_impl (private))
+  if (gdk_window_has_impl (window))
     {
-      impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
-      return impl_iface->set_static_gravities (window, use_static);
+      impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
+      return impl_class->set_static_gravities (window, use_static);
     }
 
   return FALSE;
@@ -7571,13 +7396,9 @@ gdk_window_set_static_gravities (GdkWindow *window,
 gboolean
 gdk_window_get_composited (GdkWindow *window)
 {
-  GdkWindowObject *private;
-
   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
-  private = (GdkWindowObject *)window;
-
-  return private->composited;
+  return window->composited;
 }
 
 /**
@@ -7615,14 +7436,14 @@ void
 gdk_window_set_composited (GdkWindow *window,
                           gboolean   composited)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
   GdkDisplay *display;
+  GdkWindowImplClass *impl_class;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
   composited = composited != FALSE;
 
-  if (private->composited == composited)
+  if (window->composited == composited)
     return;
 
   if (composited)
@@ -7630,21 +7451,23 @@ gdk_window_set_composited (GdkWindow *window,
 
   display = gdk_window_get_display (window);
 
-  if (!gdk_display_supports_composite (display) && composited)
+  impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
+
+  if (composited && (!gdk_display_supports_composite (display) || !impl_class->set_composited))
     {
       g_warning ("gdk_window_set_composited called but "
-                "compositing is not supported");
+                 "compositing is not supported");
       return;
     }
 
-  _gdk_windowing_window_set_composited (window, composited);
+  impl_class->set_composited (window, composited);
 
-  recompute_visible_regions (private, TRUE, FALSE);
+  recompute_visible_regions (window, TRUE, FALSE);
 
   if (GDK_WINDOW_IS_MAPPED (window))
-    gdk_window_invalidate_in_parent (private);
+    gdk_window_invalidate_in_parent (window);
 
-  private->composited = composited;
+  window->composited = composited;
 }
 
 /**
@@ -7661,13 +7484,9 @@ gdk_window_set_composited (GdkWindow *window,
 gboolean
 gdk_window_get_modal_hint (GdkWindow *window)
 {
-  GdkWindowObject *private;
-
   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
-  private = (GdkWindowObject*) window;
-
-  return private->modal_hint;
+  return window->modal_hint;
 }
 
 /**
@@ -7684,13 +7503,9 @@ gdk_window_get_modal_hint (GdkWindow *window)
 gboolean
 gdk_window_get_accept_focus (GdkWindow *window)
 {
-  GdkWindowObject *private;
-
   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
-  private = (GdkWindowObject *)window;
-
-  return private->accept_focus;
+  return window->accept_focus;
 }
 
 /**
@@ -7708,13 +7523,9 @@ gdk_window_get_accept_focus (GdkWindow *window)
 gboolean
 gdk_window_get_focus_on_map (GdkWindow *window)
 {
-  GdkWindowObject *private;
-
   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
-  private = (GdkWindowObject *)window;
-
-  return private->focus_on_map;
+  return window->focus_on_map;
 }
 
 /**
@@ -7730,13 +7541,9 @@ gdk_window_get_focus_on_map (GdkWindow *window)
 gboolean
 gdk_window_is_input_only (GdkWindow *window)
 {
-  GdkWindowObject *private;
-
   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
-  private = (GdkWindowObject *)window;
-
-  return private->input_only;
+  return window->input_only;
 }
 
 /**
@@ -7752,24 +7559,18 @@ gdk_window_is_input_only (GdkWindow *window)
 gboolean
 gdk_window_is_shaped (GdkWindow *window)
 {
-  GdkWindowObject *private;
-
   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
-  private = (GdkWindowObject *)window;
-
-  return private->shaped;
+  return window->shaped;
 }
 
 static void
 window_get_size_rectangle (GdkWindow    *window,
                           GdkRectangle *rect)
 {
-  GdkWindowObject *private = (GdkWindowObject *) window;
-
   rect->x = rect->y = 0;
-  rect->width = private->width;
-  rect->height = private->height;
+  rect->width = window->width;
+  rect->height = window->height;
 }
 
 /* Calculates the real clipping region for a window, in window coordinates,
@@ -7782,18 +7583,17 @@ _gdk_window_calculate_full_clip_region (GdkWindow *window,
                                        gint      *base_x_offset,
                                        gint      *base_y_offset)
 {
-  GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
   GdkRectangle visible_rect;
   cairo_region_t *real_clip_region;
   gint x_offset, y_offset;
-  GdkWindowObject *parentwin, *lastwin;
+  GdkWindow *parentwin, *lastwin;
 
   if (base_x_offset)
     *base_x_offset = 0;
   if (base_y_offset)
     *base_y_offset = 0;
 
-  if (!private->viewable || private->input_only)
+  if (!window->viewable || window->input_only)
     return cairo_region_create ();
 
   window_get_size_rectangle (window, &visible_rect);
@@ -7803,7 +7603,7 @@ _gdk_window_calculate_full_clip_region (GdkWindow *window,
 
   x_offset = y_offset = 0;
 
-  lastwin = private;
+  lastwin = window;
   if (do_children)
     parentwin = lastwin;
   else
@@ -7811,16 +7611,16 @@ _gdk_window_calculate_full_clip_region (GdkWindow *window,
 
   /* Remove the areas of all overlapping windows above parentwin in the hiearachy */
   for (; parentwin != NULL &&
-        (parentwin == private || lastwin != (GdkWindowObject*) base_window);
+        (parentwin == window || lastwin != base_window);
        lastwin = parentwin, parentwin = lastwin->parent)
     {
       GList *cur;
       GdkRectangle real_clip_rect;
 
-      if (parentwin != private)
+      if (parentwin != window)
        {
-         x_offset += GDK_WINDOW_OBJECT (lastwin)->x;
-         y_offset += GDK_WINDOW_OBJECT (lastwin)->y;
+         x_offset += lastwin->x;
+         y_offset += lastwin->y;
        }
 
       /* children is ordered in reverse stack order */
@@ -7829,21 +7629,20 @@ _gdk_window_calculate_full_clip_region (GdkWindow *window,
           cur = cur->next)
        {
          GdkWindow *child = cur->data;
-         GdkWindowObject *child_private = (GdkWindowObject *)child;
 
-         if (!GDK_WINDOW_IS_MAPPED (child) || child_private->input_only)
+         if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only)
            continue;
 
          /* Ignore offscreen children, as they don't draw in their parent and
           * don't take part in the clipping */
-         if (gdk_window_is_offscreen (child_private))
+         if (gdk_window_is_offscreen (child))
            continue;
 
          window_get_size_rectangle (child, &visible_rect);
 
          /* Convert rect to "window" coords */
-         visible_rect.x += child_private->x - x_offset;
-         visible_rect.y += child_private->y - y_offset;
+         visible_rect.x += child->x - x_offset;
+         visible_rect.y += child->y - y_offset;
 
          /* This shortcut is really necessary for performance when there are a lot of windows */
          cairo_region_get_extents (real_clip_region, &real_clip_rect);
@@ -7890,11 +7689,11 @@ _gdk_window_add_damage (GdkWindow *toplevel,
 
 /* Gets the toplevel for a window as used for events,
    i.e. including offscreen parents */
-static GdkWindowObject *
-get_event_parent (GdkWindowObject *window)
+static GdkWindow *
+get_event_parent (GdkWindow *window)
 {
   if (gdk_window_is_offscreen (window))
-    return (GdkWindowObject *)gdk_offscreen_window_get_embedder ((GdkWindow *)window);
+    return gdk_offscreen_window_get_embedder ((GdkWindow *)window);
   else
     return window->parent;
 }
@@ -7903,16 +7702,15 @@ get_event_parent (GdkWindowObject *window)
    i.e. including offscreen parents going up to the native
    toplevel */
 static GdkWindow *
-get_event_toplevel (GdkWindow *w)
+get_event_toplevel (GdkWindow *window)
 {
-  GdkWindowObject *private = GDK_WINDOW_OBJECT (w);
-  GdkWindowObject *parent;
+  GdkWindow *parent;
 
-  while ((parent = get_event_parent (private)) != NULL &&
+  while ((parent = get_event_parent (window)) != NULL &&
         (parent->window_type != GDK_WINDOW_ROOT))
-    private = parent;
+    window = parent;
 
-  return GDK_WINDOW (private);
+  return window;
 }
 
 gboolean
@@ -7927,7 +7725,7 @@ _gdk_window_event_parent_of (GdkWindow *parent,
       if (w == parent)
        return TRUE;
 
-      w = (GdkWindow *)get_event_parent ((GdkWindowObject *)w);
+      w = get_event_parent (w);
     }
 
   return FALSE;
@@ -7937,9 +7735,9 @@ static void
 update_cursor (GdkDisplay *display,
                GdkDevice  *device)
 {
-  GdkWindowObject *cursor_window, *parent, *toplevel;
+  GdkWindow *cursor_window, *parent, *toplevel;
   GdkWindow *pointer_window;
-  GdkWindowImplIface *impl_iface;
+  GdkWindowImplClass *impl_class;
   GdkPointerWindowInfo *pointer_info;
   GdkDeviceGrabInfo *grab;
   GdkCursor *cursor;
@@ -7956,12 +7754,12 @@ update_cursor (GdkDisplay *display,
       !_gdk_window_event_parent_of (grab->window, pointer_window))
     {
       /* use the cursor from the grab window */
-      cursor_window = (GdkWindowObject *) grab->window;
+      cursor_window = grab->window;
     }
   else
     {
       /* otherwise use the cursor from the pointer window */
-      cursor_window = (GdkWindowObject *) pointer_window;
+      cursor_window = pointer_window;
     }
 
   /* Find the first window with the cursor actually set, as
@@ -7978,15 +7776,15 @@ update_cursor (GdkDisplay *display,
 
   /* Set all cursors on toplevel, otherwise its tricky to keep track of
    * which native window has what cursor set. */
-  toplevel = (GdkWindowObject *) get_event_toplevel (pointer_window);
-  impl_iface = GDK_WINDOW_IMPL_GET_IFACE (toplevel->impl);
-  impl_iface->set_device_cursor ((GdkWindow *) toplevel, device, cursor);
+  toplevel = get_event_toplevel (pointer_window);
+  impl_class = GDK_WINDOW_IMPL_GET_CLASS (toplevel->impl);
+  impl_class->set_device_cursor (toplevel, device, cursor);
 }
 
 static gboolean
-point_in_window (GdkWindowObject *window,
-                gdouble          x,
-                 gdouble          y)
+point_in_window (GdkWindow *window,
+                gdouble    x,
+                 gdouble    y)
 {
   return
     x >= 0 && x < window->width &&
@@ -8006,23 +7804,22 @@ convert_native_coords_to_toplevel (GdkWindow *window,
                                   gdouble   *toplevel_x,
                                    gdouble   *toplevel_y)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
   gdouble x, y;
 
   x = child_x;
   y = child_y;
 
-  while (!gdk_window_is_toplevel (private))
+  while (!gdk_window_is_toplevel (window))
     {
-      x += private->x;
-      y += private->y;
-      private = private->parent;
+      x += window->x;
+      y += window->y;
+      window = window->parent;
     }
 
   *toplevel_x = x;
   *toplevel_y = y;
 
-  return (GdkWindow *)private;
+  return window;
 }
 
 static void
@@ -8032,22 +7829,19 @@ convert_toplevel_coords_to_window (GdkWindow *window,
                                   gdouble   *window_x,
                                   gdouble   *window_y)
 {
-  GdkWindowObject *private;
-  GdkWindowObject *parent;
+  GdkWindow *parent;
   gdouble x, y;
   GList *children, *l;
 
-  private = GDK_WINDOW_OBJECT (window);
-
   x = toplevel_x;
   y = toplevel_y;
 
   children = NULL;
-  while ((parent = get_event_parent (private)) != NULL &&
+  while ((parent = get_event_parent (window)) != NULL &&
         (parent->window_type != GDK_WINDOW_ROOT))
     {
-      children = g_list_prepend (children, private);
-      private = parent;
+      children = g_list_prepend (children, window);
+      window = parent;
     }
 
   for (l = children; l != NULL; l = l->next)
@@ -8059,12 +7853,12 @@ convert_toplevel_coords_to_window (GdkWindow *window,
   *window_y = y;
 }
 
-static GdkWindowObject *
-pick_embedded_child (GdkWindowObject *window,
-                    gdouble          x,
-                     gdouble          y)
+static GdkWindow *
+pick_embedded_child (GdkWindow *window,
+                    gdouble    x,
+                     gdouble    y)
 {
-  GdkWindowObject *res;
+  GdkWindow *res;
 
   res = NULL;
   g_signal_emit (window,
@@ -8079,16 +7873,14 @@ _gdk_window_find_child_at (GdkWindow *window,
                           int        x,
                            int        y)
 {
-  GdkWindowObject *private, *sub;
+  GdkWindow *sub;
   double child_x, child_y;
   GList *l;
 
-  private = (GdkWindowObject *)window;
-
-  if (point_in_window (private, x, y))
+  if (point_in_window (window, x, y))
     {
       /* Children is ordered in reverse stack order, i.e. first is topmost */
-      for (l = private->children; l != NULL; l = l->next)
+      for (l = window->children; l != NULL; l = l->next)
        {
          sub = l->data;
 
@@ -8102,9 +7894,9 @@ _gdk_window_find_child_at (GdkWindow *window,
            return (GdkWindow *)sub;
        }
 
-      if (private->num_offscreen_children > 0)
+      if (window->num_offscreen_children > 0)
        {
-         sub = pick_embedded_child (private,
+         sub = pick_embedded_child (window,
                                     x, y);
          if (sub)
            return (GdkWindow *)sub;
@@ -8115,26 +7907,24 @@ _gdk_window_find_child_at (GdkWindow *window,
 }
 
 GdkWindow *
-_gdk_window_find_descendant_at (GdkWindow *toplevel,
+_gdk_window_find_descendant_at (GdkWindow *window,
                                gdouble    x,
                                 gdouble    y,
                                gdouble   *found_x,
                                gdouble   *found_y)
 {
-  GdkWindowObject *private, *sub;
+  GdkWindow *sub;
   gdouble child_x, child_y;
   GList *l;
   gboolean found;
 
-  private = (GdkWindowObject *)toplevel;
-
-  if (point_in_window (private, x, y))
+  if (point_in_window (window, x, y))
     {
       do
        {
          found = FALSE;
          /* Children is ordered in reverse stack order, i.e. first is topmost */
-         for (l = private->children; l != NULL; l = l->next)
+         for (l = window->children; l != NULL; l = l->next)
            {
              sub = l->data;
 
@@ -8148,20 +7938,20 @@ _gdk_window_find_descendant_at (GdkWindow *toplevel,
                {
                  x = child_x;
                  y = child_y;
-                 private = sub;
+                 window = sub;
                  found = TRUE;
                  break;
                }
            }
          if (!found &&
-             private->num_offscreen_children > 0)
+             window->num_offscreen_children > 0)
            {
-             sub = pick_embedded_child (private,
+             sub = pick_embedded_child (window,
                                         x, y);
              if (sub)
                {
                  found = TRUE;
-                 private = sub;
+                 window = sub;
                  from_embedder (sub, x, y, &x, &y);
                }
            }
@@ -8171,7 +7961,7 @@ _gdk_window_find_descendant_at (GdkWindow *toplevel,
   else
     {
       /* Not in window at all */
-      private = NULL;
+      window = NULL;
     }
 
   if (found_x)
@@ -8179,7 +7969,7 @@ _gdk_window_find_descendant_at (GdkWindow *toplevel,
   if (found_y)
     *found_y = y;
 
-  return (GdkWindow *)private;
+  return window;
 }
 
 /**
@@ -8206,10 +7996,14 @@ gdk_window_beep (GdkWindow *window)
   toplevel = get_event_toplevel (window);
   display = gdk_window_get_display (window);
 
-  if (toplevel && !gdk_window_is_offscreen ((GdkWindowObject *)toplevel))
-    _gdk_windowing_window_beep (toplevel);
-  else
-    gdk_display_beep (display);
+  if (toplevel)
+    {
+      if (GDK_WINDOW_IMPL_GET_CLASS (toplevel->impl)->beep (window))
+        return;
+    }
+  
+  /* If windows fail to beep, we beep the display. */
+  gdk_display_beep (display);
 }
 
 /**
@@ -8228,17 +8022,15 @@ void
 gdk_window_set_support_multidevice (GdkWindow *window,
                                     gboolean   support_multidevice)
 {
-  GdkWindowObject *private = (GdkWindowObject *) window;
-
   g_return_if_fail (GDK_IS_WINDOW (window));
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
-  if (private->support_multidevice == support_multidevice)
+  if (window->support_multidevice == support_multidevice)
     return;
 
-  private->support_multidevice = support_multidevice;
+  window->support_multidevice = support_multidevice;
 
   /* FIXME: What to do if called when some pointers are inside the window ? */
 }
@@ -8257,14 +8049,12 @@ gdk_window_set_support_multidevice (GdkWindow *window,
 gboolean
 gdk_window_get_support_multidevice (GdkWindow *window)
 {
-  GdkWindowObject *private = (GdkWindowObject *) window;
-
   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
   if (GDK_WINDOW_DESTROYED (window))
     return FALSE;
 
-  return private->support_multidevice;
+  return window->support_multidevice;
 }
 
 static const guint type_masks[] = {
@@ -8347,11 +8137,11 @@ is_motion_type (GdkEventType type)
         type == GDK_LEAVE_NOTIFY;
 }
 
-static GdkWindowObject *
-find_common_ancestor (GdkWindowObject *win1,
-                     GdkWindowObject *win2)
+static GdkWindow *
+find_common_ancestor (GdkWindow *win1,
+                     GdkWindow *win2)
 {
-  GdkWindowObject *tmp;
+  GdkWindow *tmp;
   GList *path1 = NULL, *path2 = NULL;
   GList *list1, *list2;
 
@@ -8374,7 +8164,7 @@ find_common_ancestor (GdkWindowObject *win1,
   tmp = NULL;
   while (list1 && list2 && (list1->data == list2->data))
     {
-      tmp = (GdkWindowObject *)list1->data;
+      tmp = list1->data;
       list1 = g_list_next (list1);
       list2 = g_list_next (list2);
     }
@@ -8467,7 +8257,6 @@ _gdk_make_event (GdkWindow    *window,
     case GDK_UNMAP:
     case GDK_CLIENT_EVENT:
     case GDK_VISIBILITY_NOTIFY:
-    case GDK_NO_EXPOSE:
     case GDK_DELETE:
     case GDK_DESTROY:
     case GDK_EXPOSE:
@@ -8490,13 +8279,14 @@ _gdk_make_event (GdkWindow    *window,
 
 static void
 send_crossing_event (GdkDisplay                 *display,
-                    GdkWindowObject            *toplevel,
-                    GdkWindowObject            *window,
+                    GdkWindow                  *toplevel,
+                    GdkWindow                  *window,
                     GdkEventType                type,
                     GdkCrossingMode             mode,
                     GdkNotifyType               notify_type,
                     GdkWindow                  *subwindow,
                      GdkDevice                  *device,
+                     GdkDevice                  *source_device,
                     gint                        toplevel_x,
                     gint                        toplevel_y,
                     GdkModifierType             mask,
@@ -8544,7 +8334,7 @@ send_crossing_event (GdkDisplay                 *display,
         }
 
       if (gdk_device_get_device_type (device) == GDK_DEVICE_TYPE_MASTER &&
-          device->mode != GDK_MODE_DISABLED &&
+          gdk_device_get_mode (device) != GDK_MODE_DISABLED &&
           !g_list_find (window->devices_inside, device))
         window->devices_inside = g_list_prepend (window->devices_inside, device);
     }
@@ -8556,6 +8346,10 @@ send_crossing_event (GdkDisplay                 *display,
     {
       event = _gdk_make_event ((GdkWindow *)window, type, event_in_queue, TRUE);
       gdk_event_set_device (event, device);
+
+      if (source_device)
+        gdk_event_set_source_device (event, source_device);
+
       event->crossing.time = time_;
       event->crossing.subwindow = subwindow;
       if (subwindow)
@@ -8583,6 +8377,7 @@ _gdk_synthesize_crossing_events (GdkDisplay                 *display,
                                 GdkWindow                  *src,
                                 GdkWindow                  *dest,
                                  GdkDevice                  *device,
+                                 GdkDevice                  *source_device,
                                 GdkCrossingMode             mode,
                                 gint                        toplevel_x,
                                 gint                        toplevel_y,
@@ -8592,19 +8387,19 @@ _gdk_synthesize_crossing_events (GdkDisplay                 *display,
                                 gulong                      serial,
                                 gboolean                    non_linear)
 {
-  GdkWindowObject *c;
-  GdkWindowObject *win, *last, *next;
+  GdkWindow *c;
+  GdkWindow *win, *last, *next;
   GList *path, *list;
-  GdkWindowObject *a;
-  GdkWindowObject *b;
-  GdkWindowObject *toplevel;
+  GdkWindow *a;
+  GdkWindow *b;
+  GdkWindow *toplevel;
   GdkNotifyType notify_type;
 
   /* TODO: Don't send events to toplevel, as we get those from the windowing system */
 
-  a = (GdkWindowObject *)src;
-  b = (GdkWindowObject *)dest;
-  if (a == b)
+  a = src;
+  b = dest;
+  if (src == dest)
     return; /* No crossings generated between src and dest */
 
   if (gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_MASTER)
@@ -8625,7 +8420,7 @@ _gdk_synthesize_crossing_events (GdkDisplay                 *display,
 
   if (a) /* There might not be a source (i.e. if no previous pointer_in_window) */
     {
-      toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)a);
+      toplevel = gdk_window_get_toplevel (a);
 
       /* Traverse up from a to (excluding) c sending leave events */
       if (non_linear)
@@ -8638,7 +8433,7 @@ _gdk_synthesize_crossing_events (GdkDisplay                 *display,
                           a, GDK_LEAVE_NOTIFY,
                           mode,
                           notify_type,
-                          NULL, device,
+                          NULL, device, source_device,
                           toplevel_x, toplevel_y,
                           mask, time_,
                           event_in_queue,
@@ -8660,7 +8455,7 @@ _gdk_synthesize_crossing_events (GdkDisplay                 *display,
                                   mode,
                                   notify_type,
                                   (GdkWindow *)last,
-                                   device,
+                                  device, source_device,
                                   toplevel_x, toplevel_y,
                                   mask, time_,
                                   event_in_queue,
@@ -8674,7 +8469,7 @@ _gdk_synthesize_crossing_events (GdkDisplay                 *display,
 
   if (b) /* Might not be a dest, e.g. if we're moving out of the window */
     {
-      toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)b);
+      toplevel = gdk_window_get_toplevel ((GdkWindow *)b);
 
       /* Traverse down from c to b */
       if (c != b)
@@ -8695,10 +8490,10 @@ _gdk_synthesize_crossing_events (GdkDisplay                 *display,
          list = path;
          while (list)
            {
-             win = (GdkWindowObject *)list->data;
+             win = list->data;
              list = g_list_next (list);
              if (list)
-               next = (GdkWindowObject *)list->data;
+               next = list->data;
              else
                next = b;
 
@@ -8707,7 +8502,7 @@ _gdk_synthesize_crossing_events (GdkDisplay                 *display,
                                   mode,
                                   notify_type,
                                   (GdkWindow *)next,
-                                   device,
+                                  device, source_device,
                                   toplevel_x, toplevel_y,
                                   mask, time_,
                                   event_in_queue,
@@ -8729,7 +8524,7 @@ _gdk_synthesize_crossing_events (GdkDisplay                 *display,
                           mode,
                           notify_type,
                           NULL,
-                           device,
+                           device, source_device,
                           toplevel_x, toplevel_y,
                           mask, time_,
                           event_in_queue,
@@ -8829,8 +8624,7 @@ _gdk_display_set_window_under_pointer (GdkDisplay *display,
  * Pointer grabs are used for operations which need complete control over mouse
  * events, even if the mouse leaves the application.
  * For example in GTK+ it is used for Drag and Drop, for dragging the handle in
- * the #GtkHPaned and #GtkVPaned widgets, and for resizing columns in #GtkCList
- * widgets.
+ * the #GtkHPaned and #GtkVPaned widgets.
  *
  * Note that if the event mask of an X window has selected both button press and
  * button release events, then a button press event will cause an automatic
@@ -8887,7 +8681,7 @@ gdk_pointer_grab (GdkWindow *       window,
     native = window;
   else
     native = gdk_window_get_toplevel (window);
-  while (gdk_window_is_offscreen ((GdkWindowObject *)native))
+  while (gdk_window_is_offscreen (native))
     {
       native = gdk_offscreen_window_get_embedder (native);
 
@@ -8901,7 +8695,7 @@ gdk_pointer_grab (GdkWindow *       window,
 
   display = gdk_window_get_display (window);
 
-  serial = _gdk_windowing_window_get_next_serial (display);
+  serial = _gdk_display_get_next_serial (display);
   device_manager = gdk_display_get_device_manager (display);
   devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
 
@@ -8911,17 +8705,16 @@ gdk_pointer_grab (GdkWindow *     window,
     {
       device = dev->data;
 
-      if (device->source != GDK_SOURCE_MOUSE)
+      if (gdk_device_get_source (device) != GDK_SOURCE_MOUSE)
         continue;
 
-      res = _gdk_windowing_device_grab (device,
-                                        window,
-                                        native,
-                                        owner_events,
-                                        get_native_grab_event_mask (event_mask),
-                                        confine_to,
-                                        cursor,
-                                        time);
+      res = GDK_DEVICE_GET_CLASS (device)->grab (device,
+                                                 native,
+                                                 owner_events,
+                                                 get_native_grab_event_mask (event_mask),
+                                                 confine_to,
+                                                 cursor,
+                                                 time);
 
       if (res == GDK_GRAB_SUCCESS)
         _gdk_display_add_device_grab (display,
@@ -8947,13 +8740,13 @@ gdk_pointer_grab (GdkWindow *     window,
  * gdk_keyboard_grab:
  * @window: the #GdkWindow which will own the grab (the grab window).
  * @owner_events: if %FALSE then all keyboard events are reported with respect to
- *                @window. If %TRUE then keyboard events for this application are
- *                reported as normal, but keyboard events outside this application
- *                are reported with respect to @window. Both key press and key
- *                release events are always reported, independant of the event mask
- *                set by the application.
- * @time: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no timestamp is
-available.
+ *   @window. If %TRUE then keyboard events for this application are
+ *   reported as normal, but keyboard events outside this application
+ *   are reported with respect to @window. Both key press and key
+ *   release events are always reported, independant of the event mask
+ *   set by the application.
+ * @time_: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no timestamp is
+ *   available.
  *
  * Grabs the keyboard so that all events are passed to this
  * application until the keyboard is ungrabbed with gdk_keyboard_ungrab().
@@ -8992,7 +8785,7 @@ gdk_keyboard_grab (GdkWindow *window,
   else
     native = gdk_window_get_toplevel (window);
 
-  while (gdk_window_is_offscreen ((GdkWindowObject *)native))
+  while (gdk_window_is_offscreen (native))
     {
       native = gdk_offscreen_window_get_embedder (native);
 
@@ -9005,8 +8798,7 @@ gdk_keyboard_grab (GdkWindow *window,
     }
 
   display = gdk_window_get_display (window);
-
-  serial = _gdk_windowing_window_get_next_serial (display);
+  serial = _gdk_display_get_next_serial (display);
   device_manager = gdk_display_get_device_manager (display);
   devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
 
@@ -9016,17 +8808,16 @@ gdk_keyboard_grab (GdkWindow *window,
     {
       device = dev->data;
 
-      if (device->source != GDK_SOURCE_KEYBOARD)
+      if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD)
         continue;
 
-      res = _gdk_windowing_device_grab (device,
-                                        window,
-                                        native,
-                                        owner_events,
-                                        GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK,
-                                        NULL,
-                                        NULL,
-                                        time);
+      res = GDK_DEVICE_GET_CLASS (device)->grab (device,
+                                                 native,
+                                                 owner_events,
+                                                 GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK,
+                                                 NULL,
+                                                 NULL,
+                                                 time);
 
       if (res == GDK_GRAB_SUCCESS)
         _gdk_display_add_device_grab (display,
@@ -9063,26 +8854,161 @@ gdk_window_geometry_changed (GdkWindow *window)
   _gdk_synthesize_crossing_events_for_geometry_change (window);
 }
 
+static void
+source_events_device_added (GdkDeviceManager *device_manager,
+                            GdkDevice        *device,
+                            gpointer          user_data)
+{
+  GdkWindow *window;
+  GdkEventMask event_mask;
+  GdkInputSource source;
+
+  if (gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_FLOATING)
+    return;
+
+  window = user_data;
+  source = gdk_device_get_source (device);
+
+  event_mask = GPOINTER_TO_INT (g_hash_table_lookup (window->source_event_masks,
+                                                     GINT_TO_POINTER (source)));
+  if (event_mask)
+    gdk_window_set_device_events (window, device, event_mask);
+}
+
+static void
+source_events_device_changed (GdkDeviceManager *device_manager,
+                              GdkDevice        *device,
+                              gpointer          user_data)
+{
+  GdkDeviceType type;
+  GdkInputSource source;
+  GdkEventMask event_mask;
+  GdkWindow *window;
+
+  window = user_data;
+  type = gdk_device_get_device_type (device);
+  source = gdk_device_get_source (device);
+
+  event_mask = GPOINTER_TO_INT (g_hash_table_lookup (window->source_event_masks,
+                                                     GINT_TO_POINTER (source)));
+
+  if (!event_mask)
+    return;
+
+  if (type == GDK_DEVICE_TYPE_FLOATING)
+    {
+      /* The device was just floated, enable its event mask */
+      gdk_window_set_device_events (window, device, event_mask);
+    }
+  else if (type == GDK_DEVICE_TYPE_SLAVE)
+    gdk_window_set_device_events (window, device, 0);
+}
+
+/**
+ * gdk_window_set_source_events:
+ * @window: a #GdkWindow
+ * @source: a #GdkInputSource to define the source class.
+ * @event_mask: event mask for @window
+ *
+ * Sets the event mask for any floating device (i.e. not attached to any
+ * visible pointer) that has the source defined as @source. This event
+ * mask will be applied both to currently existing, newly added devices
+ * after this call, and devices being attached/detached.
+ *
+ * Since: 3.0
+ **/
+void
+gdk_window_set_source_events (GdkWindow      *window,
+                              GdkInputSource  source,
+                              GdkEventMask    event_mask)
+{
+  GdkDeviceManager *device_manager;
+  GdkDisplay *display;
+  GList *devices, *d;
+  guint size;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  display = gdk_window_get_display (window);
+  device_manager = gdk_display_get_device_manager (display);
+
+  devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING);
+
+  /* Set event mask for existing devices */
+  for (d = devices; d; d = d->next)
+    {
+      GdkDevice *device = d->data;
+
+      if (source == gdk_device_get_source (device))
+        gdk_window_set_device_events (window, device, event_mask);
+    }
+
+  /* Update accounting */
+  if (G_UNLIKELY (!window->source_event_masks))
+    window->source_event_masks = g_hash_table_new (NULL, NULL);
+
+  if (event_mask)
+    g_hash_table_insert (window->source_event_masks,
+                         GUINT_TO_POINTER (source),
+                         GUINT_TO_POINTER (event_mask));
+  else
+    g_hash_table_remove (window->source_event_masks,
+                         GUINT_TO_POINTER (source));
+
+  size = g_hash_table_size (window->source_event_masks);
+
+  /* Update handler if needed */
+  if (!window->device_added_handler_id && size > 0)
+    {
+      window->device_added_handler_id =
+        g_signal_connect (device_manager, "device-added",
+                          G_CALLBACK (source_events_device_added), window);
+      window->device_changed_handler_id =
+        g_signal_connect (device_manager, "device-changed",
+                          G_CALLBACK (source_events_device_changed), window);
+    }
+  else if (window->device_added_handler_id && size == 0)
+    g_signal_handler_disconnect (device_manager, window->device_added_handler_id);
+}
+
+/**
+ * gdk_window_get_source_events:
+ * @window: a #GdkWindow
+ * @source: a #GdkInputSource to define the source class.
+ *
+ * Returns the event mask for @window corresponding to the device class specified
+ * by @source.
+ *
+ * Returns: source event mask for @window
+ **/
+GdkEventMask
+gdk_window_get_source_events (GdkWindow      *window,
+                              GdkInputSource  source)
+{
+  g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
+
+  return GPOINTER_TO_UINT (g_hash_table_lookup (window->source_event_masks,
+                                                GUINT_TO_POINTER (source)));
+}
+
 static gboolean
 do_synthesize_crossing_event (gpointer data)
 {
   GdkDisplay *display;
   GdkWindow *changed_toplevel;
-  GdkWindowObject *changed_toplevel_priv;
   GHashTableIter iter;
   gpointer key, value;
   gulong serial;
 
   changed_toplevel = data;
-  changed_toplevel_priv = (GdkWindowObject *)changed_toplevel;
 
-  changed_toplevel_priv->synthesize_crossing_event_queued = FALSE;
+  changed_toplevel->synthesize_crossing_event_queued = FALSE;
 
   if (GDK_WINDOW_DESTROYED (changed_toplevel))
     return FALSE;
 
   display = gdk_window_get_display (changed_toplevel);
-  serial = _gdk_windowing_window_get_next_serial (display);
+  serial = _gdk_display_get_next_serial (display);
   g_hash_table_iter_init (&iter, display->pointers_info);
 
   while (g_hash_table_iter_next (&iter, &key, &value))
@@ -9104,7 +9030,7 @@ do_synthesize_crossing_event (gpointer data)
               _gdk_synthesize_crossing_events (display,
                                                pointer_info->window_under_pointer,
                                                new_window_under_pointer,
-                                               device,
+                                               device, NULL,
                                                GDK_CROSSING_NORMAL,
                                                pointer_info->toplevel_x,
                                                pointer_info->toplevel_y,
@@ -9126,7 +9052,6 @@ _gdk_synthesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
 {
   GdkDisplay *display;
   GdkWindow *toplevel;
-  GdkWindowObject *toplevel_priv;
 
   if (_gdk_native_windows)
     return; /* We use the native crossing events if all native */
@@ -9134,11 +9059,10 @@ _gdk_synthesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
   display = gdk_window_get_display (changed_window);
 
   toplevel = get_event_toplevel (changed_window);
-  toplevel_priv = (GdkWindowObject *) toplevel;
 
-  if (!toplevel_priv->synthesize_crossing_event_queued)
+  if (!toplevel->synthesize_crossing_event_queued)
     {
-      toplevel_priv->synthesize_crossing_event_queued = TRUE;
+      toplevel->synthesize_crossing_event_queued = TRUE;
 
       gdk_threads_add_idle_full (GDK_PRIORITY_EVENTS - 1,
                                  do_synthesize_crossing_event,
@@ -9159,7 +9083,6 @@ get_event_window (GdkDisplay                 *display,
 {
   guint evmask;
   GdkWindow *grab_window;
-  GdkWindowObject *w;
   GdkDeviceGrabInfo *grab;
 
   grab = _gdk_display_has_device_grab (display, device, serial);
@@ -9181,20 +9104,19 @@ get_event_window (GdkDisplay                 *display,
        return NULL;
     }
 
-  w = (GdkWindowObject *)pointer_window;
-  while (w != NULL)
+  while (pointer_window != NULL)
     {
-      evmask = w->event_mask;
+      evmask = pointer_window->event_mask;
       evmask = update_evmask_for_button_motion (evmask, mask);
 
       if (evmask & type_masks[type])
        {
          if (evmask_out)
            *evmask_out = evmask;
-         return (GdkWindow *)w;
+         return pointer_window;
        }
 
-      w = get_event_parent (w);
+      pointer_window = get_event_parent (pointer_window);
     }
 
   if (grab != NULL &&
@@ -9224,7 +9146,7 @@ proxy_pointer_event (GdkDisplay                 *display,
   GdkWindow *toplevel_window, *event_window;
   GdkWindow *pointer_window;
   GdkPointerWindowInfo *pointer_info;
-  GdkDevice *device;
+  GdkDevice *device, *source_device;
   GdkEvent *event;
   guint state;
   gdouble toplevel_x, toplevel_y;
@@ -9236,6 +9158,7 @@ proxy_pointer_event (GdkDisplay                 *display,
   gdk_event_get_state (source_event, &state);
   time_ = gdk_event_get_time (source_event);
   device = gdk_event_get_device (source_event);
+  source_device = gdk_event_get_source_device (source_event);
   pointer_info = _gdk_display_get_pointer_info (display, device);
   toplevel_window = convert_native_coords_to_toplevel (event_window,
                                                       toplevel_x, toplevel_y,
@@ -9269,7 +9192,7 @@ proxy_pointer_event (GdkDisplay                 *display,
       _gdk_synthesize_crossing_events (display,
                                       pointer_info->window_under_pointer,
                                       event_window,
-                                       device,
+                                       device, source_device,
                                       source_event->crossing.mode,
                                       toplevel_x, toplevel_y,
                                       state, time_,
@@ -9279,13 +9202,13 @@ proxy_pointer_event (GdkDisplay                 *display,
 
       /* Send subwindow == NULL event */
       send_crossing_event (display,
-                          (GdkWindowObject *)toplevel_window,
-                          (GdkWindowObject *)event_window,
+                          toplevel_window,
+                          event_window,
                           source_event->type,
                           source_event->crossing.mode,
                           source_event->crossing.detail,
                           NULL,
-                           device,
+                           device, source_device,
                           toplevel_x, toplevel_y,
                           state, time_,
                           source_event,
@@ -9309,13 +9232,13 @@ proxy_pointer_event (GdkDisplay                 *display,
 
       /* Send subwindow == NULL event */
       send_crossing_event (display,
-                          (GdkWindowObject *)toplevel_window,
-                          (GdkWindowObject *)event_window,
+                          toplevel_window,
+                          event_window,
                           source_event->type,
                           source_event->crossing.mode,
                           source_event->crossing.detail,
                           NULL,
-                           device,
+                           device, source_device,
                           toplevel_x, toplevel_y,
                           state, time_,
                           source_event,
@@ -9325,7 +9248,7 @@ proxy_pointer_event (GdkDisplay                 *display,
       _gdk_synthesize_crossing_events (display,
                                       event_window,
                                       pointer_window,
-                                       device,
+                                       device, source_device,
                                       source_event->crossing.mode,
                                       toplevel_x, toplevel_y,
                                       state, time_,
@@ -9344,7 +9267,7 @@ proxy_pointer_event (GdkDisplay                 *display,
       _gdk_synthesize_crossing_events (display,
                                       pointer_info->window_under_pointer,
                                       pointer_window,
-                                       device,
+                                       device, source_device,
                                       GDK_CROSSING_NORMAL,
                                       toplevel_x, toplevel_y,
                                       state, time_,
@@ -9404,7 +9327,8 @@ proxy_pointer_event (GdkDisplay                 *display,
          event->motion.is_hint = is_hint;
          event->motion.device = source_event->motion.device;
           event->motion.axes = g_memdup (source_event->motion.axes,
-                                         sizeof (gdouble) * source_event->motion.device->num_axes);
+                                         sizeof (gdouble) * gdk_device_get_n_axes (source_event->motion.device));
+          gdk_event_set_source_device (event, source_device);
        }
     }
 
@@ -9426,15 +9350,15 @@ proxy_button_event (GdkEvent *source_event,
   GdkWindow *toplevel_window, *event_window;
   GdkWindow *event_win;
   GdkWindow *pointer_window;
-  GdkWindowObject *parent;
+  GdkWindow *parent;
   GdkEvent *event;
   guint state;
   guint32 time_;
   GdkEventType type;
   gdouble toplevel_x, toplevel_y;
   GdkDisplay *display;
-  GdkWindowObject *w;
-  GdkDevice *device;
+  GdkWindow *w;
+  GdkDevice *device, *source_device;
 
   type = source_event->any.type;
   event_window = source_event->any.window;
@@ -9442,6 +9366,7 @@ proxy_button_event (GdkEvent *source_event,
   gdk_event_get_state (source_event, &state);
   time_ = gdk_event_get_time (source_event);
   device = gdk_event_get_device (source_event);
+  source_device = gdk_event_get_source_device (source_event);
   display = gdk_window_get_display (source_event->any.window);
   toplevel_window = convert_native_coords_to_toplevel (event_window,
                                                       toplevel_x, toplevel_y,
@@ -9457,7 +9382,7 @@ proxy_button_event (GdkEvent *source_event,
                                        NULL, NULL);
 
       /* Find the event window, that gets the grab */
-      w = (GdkWindowObject *)pointer_window;
+      w = pointer_window;
       while (w != NULL &&
             (parent = get_event_parent (w)) != NULL &&
             parent->window_type != GDK_WINDOW_ROOT)
@@ -9478,7 +9403,7 @@ proxy_button_event (GdkEvent *source_event,
                                      serial,
                                      time_,
                                      TRUE);
-      _gdk_display_device_grab_update (display, device, serial);
+      _gdk_display_device_grab_update (display, device, source_device, serial);
     }
 
   pointer_window = get_pointer_window (display, toplevel_window, device,
@@ -9513,7 +9438,9 @@ proxy_button_event (GdkEvent *source_event,
       event->button.state = state;
       event->button.device = source_event->button.device;
       event->button.axes = g_memdup (source_event->button.axes,
-                                     sizeof (gdouble) * source_event->button.device->num_axes);
+                                     sizeof (gdouble) * gdk_device_get_n_axes (source_event->button.device));
+
+      gdk_event_set_source_device (event, source_device);
 
       if (type == GDK_BUTTON_PRESS)
        _gdk_event_button_generate (display, event);
@@ -9528,6 +9455,7 @@ proxy_button_event (GdkEvent *source_event,
       event->scroll.y_root = source_event->scroll.y_root;
       event->scroll.state = state;
       event->scroll.device = source_event->scroll.device;
+      gdk_event_set_source_device (event, source_device);
       return TRUE;
 
     default:
@@ -9539,7 +9467,7 @@ proxy_button_event (GdkEvent *source_event,
 
 #ifdef DEBUG_WINDOW_PRINTING
 static void
-gdk_window_print (GdkWindowObject *window,
+gdk_window_print (GdkWindow *window,
                  int indent)
 {
   GdkRectangle r;
@@ -9562,7 +9490,7 @@ gdk_window_print (GdkWindowObject *window,
   if (gdk_window_has_impl (window))
     {
 #ifdef GDK_WINDOWING_X11
-      g_print (" impl(0x%lx)", gdk_x11_drawable_get_xid (GDK_DRAWABLE (window)));
+      g_print (" impl(0x%lx)", gdk_x11_window_get_xid (window));
 #endif
     }
 
@@ -9596,17 +9524,14 @@ gdk_window_print_tree (GdkWindow *window,
                       int indent,
                       gboolean include_input_only)
 {
-  GdkWindowObject *private;
   GList *l;
 
-  private = (GdkWindowObject *)window;
-
-  if (private->input_only && !include_input_only)
+  if (window->input_only && !include_input_only)
     return;
 
-  gdk_window_print (private, indent);
+  gdk_window_print (window, indent);
 
-  for (l = private->children; l != NULL; l = l->next)
+  for (l = window->children; l != NULL; l = l->next)
     gdk_window_print_tree (l->data, indent + 4, include_input_only);
 }
 
@@ -9619,26 +9544,26 @@ _gdk_windowing_got_event (GdkDisplay *display,
                          gulong      serial)
 {
   GdkWindow *event_window;
-  GdkWindowObject *event_private;
   gdouble x, y;
   gboolean unlink_event;
   guint old_state, old_button;
   GdkDeviceGrabInfo *button_release_grab;
   GdkPointerWindowInfo *pointer_info;
-  GdkDevice *device;
+  GdkDevice *device, *source_device;
   gboolean is_toplevel;
 
   if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
     display->last_event_time = gdk_event_get_time (event);
 
   device = gdk_event_get_device (event);
+  source_device = gdk_event_get_source_device (event);
 
   if (device)
     {
       GdkInputMode mode;
 
       g_object_get (device, "input-mode", &mode, NULL);
-      _gdk_display_device_grab_update (display, device, serial);
+      _gdk_display_device_grab_update (display, device, source_device, serial);
 
       if (mode == GDK_MODE_DISABLED ||
           !_gdk_display_check_grab_ownership (display, device, serial))
@@ -9656,7 +9581,6 @@ _gdk_windowing_got_event (GdkDisplay *display,
     return;
 
   pointer_info = _gdk_display_get_pointer_info (display, device);
-  event_private = GDK_WINDOW_OBJECT (event_window);
 
 #ifdef DEBUG_WINDOW_PRINTING
   if (event->type == GDK_KEY_PRESS &&
@@ -9684,7 +9608,7 @@ _gdk_windowing_got_event (GdkDisplay *display,
                                          serial,
                                          gdk_event_get_time (event),
                                          TRUE);
-         _gdk_display_device_grab_update (display, device, serial);
+         _gdk_display_device_grab_update (display, device, source_device, serial);
        }
       if (event->type == GDK_BUTTON_RELEASE &&
          !event->any.send_event)
@@ -9697,7 +9621,7 @@ _gdk_windowing_got_event (GdkDisplay *display,
            {
              button_release_grab->serial_end = serial;
              button_release_grab->implicit_ungrab = FALSE;
-             _gdk_display_device_grab_update (display, device, serial);
+             _gdk_display_device_grab_update (display, device, source_device, serial);
            }
        }
 
@@ -9709,18 +9633,18 @@ _gdk_windowing_got_event (GdkDisplay *display,
 
   if (event->type == GDK_VISIBILITY_NOTIFY)
     {
-      event_private->native_visibility = event->visibility.state;
-      gdk_window_update_visibility_recursively (event_private,
-                                               event_private);
+      event_window->native_visibility = event->visibility.state;
+      gdk_window_update_visibility_recursively (event_window,
+                                               event_window);
       return;
     }
 
   if (!(is_button_type (event->type) ||
        is_motion_type (event->type)) ||
-      event_private->window_type == GDK_WINDOW_ROOT)
+      event_window->window_type == GDK_WINDOW_ROOT)
     return;
 
-  is_toplevel = gdk_window_is_toplevel (event_private);
+  is_toplevel = gdk_window_is_toplevel (event_window);
 
   if ((event->type == GDK_ENTER_NOTIFY ||
        event->type == GDK_LEAVE_NOTIFY) &&
@@ -9819,7 +9743,7 @@ _gdk_windowing_got_event (GdkDisplay *display,
        {
          button_release_grab->serial_end = serial;
          button_release_grab->implicit_ungrab = FALSE;
-         _gdk_display_device_grab_update (display, device, serial);
+         _gdk_display_device_grab_update (display, device, source_device, serial);
        }
     }
 
@@ -9832,89 +9756,6 @@ _gdk_windowing_got_event (GdkDisplay *display,
     }
 }
 
-
-static GdkWindow *
-get_extension_event_window (GdkDisplay                 *display,
-                           GdkWindow                  *pointer_window,
-                           GdkEventType                type,
-                           gulong                      serial)
-{
-  guint evmask;
-  GdkWindow *grab_window;
-  GdkWindowObject *w;
-  GdkDeviceGrabInfo *grab;
-
-  /* FIXME: which device? */
-  grab = _gdk_display_has_device_grab (display, display->core_pointer, serial);
-
-  if (grab != NULL && !grab->owner_events)
-    {
-      evmask = grab->event_mask;
-
-      grab_window = grab->window;
-
-      if (evmask & type_masks[type])
-       return grab_window;
-      else
-       return NULL;
-    }
-
-  w = (GdkWindowObject *)pointer_window;
-  while (w != NULL)
-    {
-      evmask = w->extension_events;
-
-      if (evmask & type_masks[type])
-       return (GdkWindow *)w;
-
-      w = get_event_parent (w);
-    }
-
-  if (grab != NULL &&
-      grab->owner_events)
-    {
-      evmask = grab->event_mask;
-
-      if (evmask & type_masks[type])
-       return grab->window;
-      else
-       return NULL;
-    }
-
-  return NULL;
-}
-
-
-GdkWindow *
-_gdk_window_get_input_window_for_event (GdkWindow *native_window,
-                                       GdkEventType event_type,
-                                       int x, int y,
-                                       gulong serial)
-{
-  GdkDisplay *display;
-  GdkWindow *toplevel_window;
-  GdkWindow *pointer_window;
-  GdkWindow *event_win;
-  gdouble toplevel_x, toplevel_y;
-
-  toplevel_x = x;
-  toplevel_y = y;
-
-  display = gdk_window_get_display (native_window);
-  toplevel_window = convert_native_coords_to_toplevel (native_window,
-                                                      toplevel_x, toplevel_y,
-                                                      &toplevel_x, &toplevel_y);
-  /* FIXME: which device? */
-  pointer_window = get_pointer_window (display, toplevel_window, NULL,
-                                      toplevel_x, toplevel_y, serial);
-  event_win = get_extension_event_window (display,
-                                         pointer_window,
-                                         event_type,
-                                         serial);
-
-  return event_win;
-}
-
 /**
  * gdk_window_create_similar_surface:
  * @window: window to make new surface similar to
@@ -9952,7 +9793,7 @@ gdk_window_create_similar_surface (GdkWindow *     window,
 
   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
   
-  window_surface = _gdk_drawable_ref_cairo_surface (window);
+  window_surface = _gdk_window_ref_cairo_surface (window);
 
   surface = cairo_surface_create_similar (window_surface,
                                           content,
@@ -9963,3 +9804,1131 @@ gdk_window_create_similar_surface (GdkWindow *     window,
   return surface;
 }
 
+/**
+ * gdk_window_focus:
+ * @window: a #GdkWindow
+ * @timestamp: timestamp of the event triggering the window focus
+ *
+ * Sets keyboard focus to @window. In most cases, gtk_window_present()
+ * should be used on a #GtkWindow, rather than calling this function.
+ *
+ **/
+void
+gdk_window_focus (GdkWindow *window,
+                  guint32    timestamp)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->focus (window, timestamp);
+}
+
+/**
+ * gdk_window_set_type_hint:
+ * @window: A toplevel #GdkWindow
+ * @hint: A hint of the function this window will have
+ *
+ * The application can use this call to provide a hint to the window
+ * manager about the functionality of a window. The window manager
+ * can use this information when determining the decoration and behaviour
+ * of the window.
+ *
+ * The hint must be set before the window is mapped.
+ **/
+void
+gdk_window_set_type_hint (GdkWindow        *window,
+                         GdkWindowTypeHint hint)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_type_hint (window, hint);
+}
+
+/**
+ * gdk_window_get_type_hint:
+ * @window: A toplevel #GdkWindow
+ *
+ * This function returns the type hint set for a window.
+ *
+ * Return value: The type hint set for @window
+ *
+ * Since: 2.10
+ **/
+GdkWindowTypeHint
+gdk_window_get_type_hint (GdkWindow *window)
+{
+  return GDK_WINDOW_IMPL_GET_CLASS (window->impl)->get_type_hint (window);
+}
+
+/**
+ * gdk_window_set_modal_hint:
+ * @window: A toplevel #GdkWindow
+ * @modal: %TRUE if the window is modal, %FALSE otherwise.
+ *
+ * The application can use this hint to tell the window manager
+ * that a certain window has modal behaviour. The window manager
+ * can use this information to handle modal windows in a special
+ * way.
+ *
+ * You should only use this on windows for which you have
+ * previously called gdk_window_set_transient_for()
+ **/
+void
+gdk_window_set_modal_hint (GdkWindow *window,
+                          gboolean   modal)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_modal_hint (window, modal);
+}
+
+/**
+ * gdk_window_set_skip_taskbar_hint:
+ * @window: a toplevel #GdkWindow
+ * @skips_taskbar: %TRUE to skip the taskbar
+ *
+ * Toggles whether a window should appear in a task list or window
+ * list. If a window's semantic type as specified with
+ * gdk_window_set_type_hint() already fully describes the window, this
+ * function should <emphasis>not</emphasis> be called in addition,
+ * instead you should allow the window to be treated according to
+ * standard policy for its semantic type.
+ *
+ * Since: 2.2
+ **/
+void
+gdk_window_set_skip_taskbar_hint (GdkWindow *window,
+                                  gboolean   skips_taskbar)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_skip_taskbar_hint (window, skips_taskbar);
+}
+
+/**
+ * gdk_window_set_skip_pager_hint:
+ * @window: a toplevel #GdkWindow
+ * @skips_pager: %TRUE to skip the pager
+ *
+ * Toggles whether a window should appear in a pager (workspace
+ * switcher, or other desktop utility program that displays a small
+ * thumbnail representation of the windows on the desktop). If a
+ * window's semantic type as specified with gdk_window_set_type_hint()
+ * already fully describes the window, this function should
+ * <emphasis>not</emphasis> be called in addition, instead you should
+ * allow the window to be treated according to standard policy for
+ * its semantic type.
+ *
+ * Since: 2.2
+ **/
+void
+gdk_window_set_skip_pager_hint (GdkWindow *window,
+                                gboolean   skips_pager)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_skip_pager_hint (window, skips_pager);
+}
+
+/**
+ * gdk_window_set_urgency_hint:
+ * @window: a toplevel #GdkWindow
+ * @urgent: %TRUE if the window is urgent
+ *
+ * Toggles whether a window needs the user's
+ * urgent attention.
+ *
+ * Since: 2.8
+ **/
+void
+gdk_window_set_urgency_hint (GdkWindow *window,
+                            gboolean   urgent)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_urgency_hint (window, urgent);
+}
+
+/**
+ * gdk_window_set_geometry_hints:
+ * @window: a toplevel #GdkWindow
+ * @geometry: geometry hints
+ * @geom_mask: bitmask indicating fields of @geometry to pay attention to
+ *
+ * Sets the geometry hints for @window. Hints flagged in @geom_mask
+ * are set, hints not flagged in @geom_mask are unset.
+ * To unset all hints, use a @geom_mask of 0 and a @geometry of %NULL.
+ *
+ * This function provides hints to the windowing system about
+ * acceptable sizes for a toplevel window. The purpose of
+ * this is to constrain user resizing, but the windowing system
+ * will typically  (but is not required to) also constrain the
+ * current size of the window to the provided values and
+ * constrain programatic resizing via gdk_window_resize() or
+ * gdk_window_move_resize().
+ *
+ * Note that on X11, this effect has no effect on windows
+ * of type %GDK_WINDOW_TEMP or windows where override redirect
+ * has been turned on via gdk_window_set_override_redirect()
+ * since these windows are not resizable by the user.
+ *
+ * Since you can't count on the windowing system doing the
+ * constraints for programmatic resizes, you should generally
+ * call gdk_window_constrain_size() yourself to determine
+ * appropriate sizes.
+ *
+ **/
+void
+gdk_window_set_geometry_hints (GdkWindow         *window,
+                              const GdkGeometry *geometry,
+                              GdkWindowHints     geom_mask)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_geometry_hints (window, geometry, geom_mask);
+}
+
+/**
+ * gdk_window_set_title:
+ * @window: a toplevel #GdkWindow
+ * @title: title of @window
+ *
+ * Sets the title of a toplevel window, to be displayed in the titlebar.
+ * If you haven't explicitly set the icon name for the window
+ * (using gdk_window_set_icon_name()), the icon name will be set to
+ * @title as well. @title must be in UTF-8 encoding (as with all
+ * user-readable strings in GDK/GTK+). @title may not be %NULL.
+ **/
+void
+gdk_window_set_title (GdkWindow   *window,
+                     const gchar *title)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_title (window, title);
+}
+
+/**
+ * gdk_window_set_role:
+ * @window: a toplevel #GdkWindow
+ * @role: a string indicating its role
+ *
+ * When using GTK+, typically you should use gtk_window_set_role() instead
+ * of this low-level function.
+ *
+ * The window manager and session manager use a window's role to
+ * distinguish it from other kinds of window in the same application.
+ * When an application is restarted after being saved in a previous
+ * session, all windows with the same title and role are treated as
+ * interchangeable.  So if you have two windows with the same title
+ * that should be distinguished for session management purposes, you
+ * should set the role on those windows. It doesn't matter what string
+ * you use for the role, as long as you have a different role for each
+ * non-interchangeable kind of window.
+ *
+ **/
+void
+gdk_window_set_role (GdkWindow   *window,
+                    const gchar *role)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_role (window, role);
+}
+
+/**
+ * gdk_window_set_startup_id:
+ * @window: a toplevel #GdkWindow
+ * @startup_id: a string with startup-notification identifier
+ *
+ * When using GTK+, typically you should use gtk_window_set_startup_id()
+ * instead of this low-level function.
+ *
+ * Since: 2.12
+ *
+ **/
+void
+gdk_window_set_startup_id (GdkWindow   *window,
+                          const gchar *startup_id)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_startup_id (window, startup_id);
+}
+
+/**
+ * gdk_window_set_transient_for:
+ * @window: a toplevel #GdkWindow
+ * @parent: another toplevel #GdkWindow
+ *
+ * Indicates to the window manager that @window is a transient dialog
+ * associated with the application window @parent. This allows the
+ * window manager to do things like center @window on @parent and
+ * keep @window above @parent.
+ *
+ * See gtk_window_set_transient_for() if you're using #GtkWindow or
+ * #GtkDialog.
+ **/
+void
+gdk_window_set_transient_for (GdkWindow *window,
+                             GdkWindow *parent)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_transient_for (window, parent);
+}
+
+/**
+ * gdk_window_get_root_origin:
+ * @window: a toplevel #GdkWindow
+ * @x: return location for X position of window frame
+ * @y: return location for Y position of window frame
+ *
+ * Obtains the top-left corner of the window manager frame in root
+ * window coordinates.
+ *
+ **/
+void
+gdk_window_get_root_origin (GdkWindow *window,
+                           gint      *x,
+                           gint      *y)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->get_root_origin (window, x, y);
+}
+
+/**
+ * gdk_window_get_frame_extents:
+ * @window: a toplevel #GdkWindow
+ * @rect: rectangle to fill with bounding box of the window frame
+ *
+ * Obtains the bounding box of the window, including window manager
+ * titlebar/borders if any. The frame position is given in root window
+ * coordinates. To get the position of the window itself (rather than
+ * the frame) in root window coordinates, use gdk_window_get_origin().
+ *
+ **/
+void
+gdk_window_get_frame_extents (GdkWindow    *window,
+                              GdkRectangle *rect)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->get_frame_extents (window, rect);
+}
+
+/**
+ * gdk_window_set_override_redirect:
+ * @window: a toplevel #GdkWindow
+ * @override_redirect: %TRUE if window should be override redirect
+ *
+ * An override redirect window is not under the control of the window manager.
+ * This means it won't have a titlebar, won't be minimizable, etc. - it will
+ * be entirely under the control of the application. The window manager
+ * can't see the override redirect window at all.
+ *
+ * Override redirect should only be used for short-lived temporary
+ * windows, such as popup menus. #GtkMenu uses an override redirect
+ * window in its implementation, for example.
+ *
+ **/
+void
+gdk_window_set_override_redirect (GdkWindow *window,
+                                 gboolean override_redirect)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_override_redirect (window, override_redirect);
+}
+
+/**
+ * gdk_window_set_accept_focus:
+ * @window: a toplevel #GdkWindow
+ * @accept_focus: %TRUE if the window should receive input focus
+ *
+ * Setting @accept_focus to %FALSE hints the desktop environment that the
+ * window doesn't want to receive input focus.
+ *
+ * On X, it is the responsibility of the window manager to interpret this
+ * hint. ICCCM-compliant window manager usually respect it.
+ *
+ * Since: 2.4
+ **/
+void
+gdk_window_set_accept_focus (GdkWindow *window,
+                            gboolean accept_focus)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_accept_focus (window, accept_focus);
+}
+
+/**
+ * gdk_window_set_focus_on_map:
+ * @window: a toplevel #GdkWindow
+ * @focus_on_map: %TRUE if the window should receive input focus when mapped
+ *
+ * Setting @focus_on_map to %FALSE hints the desktop environment that the
+ * window doesn't want to receive input focus when it is mapped.
+ * focus_on_map should be turned off for windows that aren't triggered
+ * interactively (such as popups from network activity).
+ *
+ * On X, it is the responsibility of the window manager to interpret
+ * this hint. Window managers following the freedesktop.org window
+ * manager extension specification should respect it.
+ *
+ * Since: 2.6
+ **/
+void
+gdk_window_set_focus_on_map (GdkWindow *window,
+                            gboolean focus_on_map)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_focus_on_map (window, focus_on_map);
+}
+
+/**
+ * gdk_window_set_icon_list:
+ * @window: The #GdkWindow toplevel window to set the icon of.
+ * @pixbufs: (transfer none) (element-type GdkPixbuf):
+ *     A list of pixbufs, of different sizes.
+ *
+ * Sets a list of icons for the window. One of these will be used
+ * to represent the window when it has been iconified. The icon is
+ * usually shown in an icon box or some sort of task bar. Which icon
+ * size is shown depends on the window manager. The window manager
+ * can scale the icon  but setting several size icons can give better
+ * image quality since the window manager may only need to scale the
+ * icon by a small amount or not at all.
+ *
+ **/
+void
+gdk_window_set_icon_list (GdkWindow *window,
+                         GList     *pixbufs)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_icon_list (window, pixbufs);
+}
+
+/**
+ * gdk_window_set_icon_name:
+ * @window: a toplevel #GdkWindow
+ * @name: name of window while iconified (minimized)
+ *
+ * Windows may have a name used while minimized, distinct from the
+ * name they display in their titlebar. Most of the time this is a bad
+ * idea from a user interface standpoint. But you can set such a name
+ * with this function, if you like.
+ *
+ * After calling this with a non-%NULL @name, calls to gdk_window_set_title()
+ * will not update the icon title.
+ *
+ * Using %NULL for @name unsets the icon title; further calls to
+ * gdk_window_set_title() will again update the icon title as well.
+ **/
+void
+gdk_window_set_icon_name (GdkWindow   *window,
+                         const gchar *name)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_icon_name (window, name);
+}
+
+/**
+ * gdk_window_iconify:
+ * @window: a toplevel #GdkWindow
+ *
+ * Asks to iconify (minimize) @window. The window manager may choose
+ * to ignore the request, but normally will honor it. Using
+ * gtk_window_iconify() is preferred, if you have a #GtkWindow widget.
+ *
+ * This function only makes sense when @window is a toplevel window.
+ *
+ **/
+void
+gdk_window_iconify (GdkWindow *window)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->iconify (window);
+}
+
+/**
+ * gdk_window_deiconify:
+ * @window: a toplevel #GdkWindow
+ *
+ * Attempt to deiconify (unminimize) @window. On X11 the window manager may
+ * choose to ignore the request to deiconify. When using GTK+,
+ * use gtk_window_deiconify() instead of the #GdkWindow variant. Or better yet,
+ * you probably want to use gtk_window_present(), which raises the window, focuses it,
+ * unminimizes it, and puts it on the current desktop.
+ *
+ **/
+void
+gdk_window_deiconify (GdkWindow *window)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->deiconify (window);
+}
+
+/**
+ * gdk_window_stick:
+ * @window: a toplevel #GdkWindow
+ *
+ * "Pins" a window such that it's on all workspaces and does not scroll
+ * with viewports, for window managers that have scrollable viewports.
+ * (When using #GtkWindow, gtk_window_stick() may be more useful.)
+ *
+ * On the X11 platform, this function depends on window manager
+ * support, so may have no effect with many window managers. However,
+ * GDK will do the best it can to convince the window manager to stick
+ * the window. For window managers that don't support this operation,
+ * there's nothing you can do to force it to happen.
+ *
+ **/
+void
+gdk_window_stick (GdkWindow *window)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->stick (window);
+}
+
+/**
+ * gdk_window_unstick:
+ * @window: a toplevel #GdkWindow
+ *
+ * Reverse operation for gdk_window_stick(); see gdk_window_stick(),
+ * and gtk_window_unstick().
+ *
+ **/
+void
+gdk_window_unstick (GdkWindow *window)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->unstick (window);
+}
+
+/**
+ * gdk_window_maximize:
+ * @window: a toplevel #GdkWindow
+ *
+ * Maximizes the window. If the window was already maximized, then
+ * this function does nothing.
+ *
+ * On X11, asks the window manager to maximize @window, if the window
+ * manager supports this operation. Not all window managers support
+ * this, and some deliberately ignore it or don't have a concept of
+ * "maximized"; so you can't rely on the maximization actually
+ * happening. But it will happen with most standard window managers,
+ * and GDK makes a best effort to get it to happen.
+ *
+ * On Windows, reliably maximizes the window.
+ *
+ **/
+void
+gdk_window_maximize (GdkWindow *window)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->maximize (window);
+}
+
+/**
+ * gdk_window_unmaximize:
+ * @window: a toplevel #GdkWindow
+ *
+ * Unmaximizes the window. If the window wasn't maximized, then this
+ * function does nothing.
+ *
+ * On X11, asks the window manager to unmaximize @window, if the
+ * window manager supports this operation. Not all window managers
+ * support this, and some deliberately ignore it or don't have a
+ * concept of "maximized"; so you can't rely on the unmaximization
+ * actually happening. But it will happen with most standard window
+ * managers, and GDK makes a best effort to get it to happen.
+ *
+ * On Windows, reliably unmaximizes the window.
+ *
+ **/
+void
+gdk_window_unmaximize (GdkWindow *window)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->unmaximize (window);
+}
+
+/**
+ * gdk_window_fullscreen:
+ * @window: a toplevel #GdkWindow
+ *
+ * Moves the window into fullscreen mode. This means the
+ * window covers the entire screen and is above any panels
+ * or task bars.
+ *
+ * If the window was already fullscreen, then this function does nothing.
+ *
+ * On X11, asks the window manager to put @window in a fullscreen
+ * state, if the window manager supports this operation. Not all
+ * window managers support this, and some deliberately ignore it or
+ * don't have a concept of "fullscreen"; so you can't rely on the
+ * fullscreenification actually happening. But it will happen with
+ * most standard window managers, and GDK makes a best effort to get
+ * it to happen.
+ *
+ * Since: 2.2
+ **/
+void
+gdk_window_fullscreen (GdkWindow *window)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->fullscreen (window);
+}
+
+/**
+ * gdk_window_unfullscreen:
+ * @window: a toplevel #GdkWindow
+ *
+ * Moves the window out of fullscreen mode. If the window was not
+ * fullscreen, does nothing.
+ *
+ * On X11, asks the window manager to move @window out of the fullscreen
+ * state, if the window manager supports this operation. Not all
+ * window managers support this, and some deliberately ignore it or
+ * don't have a concept of "fullscreen"; so you can't rely on the
+ * unfullscreenification actually happening. But it will happen with
+ * most standard window managers, and GDK makes a best effort to get
+ * it to happen.
+ *
+ * Since: 2.2
+ **/
+void
+gdk_window_unfullscreen (GdkWindow *window)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->unfullscreen (window);
+}
+
+/**
+ * gdk_window_set_keep_above:
+ * @window: a toplevel #GdkWindow
+ * @setting: whether to keep @window above other windows
+ *
+ * Set if @window must be kept above other windows. If the
+ * window was already above, then this function does nothing.
+ *
+ * On X11, asks the window manager to keep @window above, if the window
+ * manager supports this operation. Not all window managers support
+ * this, and some deliberately ignore it or don't have a concept of
+ * "keep above"; so you can't rely on the window being kept above.
+ * But it will happen with most standard window managers,
+ * and GDK makes a best effort to get it to happen.
+ *
+ * Since: 2.4
+ **/
+void
+gdk_window_set_keep_above (GdkWindow *window,
+                           gboolean   setting)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_keep_above (window, setting);
+}
+
+/**
+ * gdk_window_set_keep_below:
+ * @window: a toplevel #GdkWindow
+ * @setting: whether to keep @window below other windows
+ *
+ * Set if @window must be kept below other windows. If the
+ * window was already below, then this function does nothing.
+ *
+ * On X11, asks the window manager to keep @window below, if the window
+ * manager supports this operation. Not all window managers support
+ * this, and some deliberately ignore it or don't have a concept of
+ * "keep below"; so you can't rely on the window being kept below.
+ * But it will happen with most standard window managers,
+ * and GDK makes a best effort to get it to happen.
+ *
+ * Since: 2.4
+ **/
+void
+gdk_window_set_keep_below (GdkWindow *window, gboolean setting)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_keep_below (window, setting);
+}
+
+/**
+ * gdk_window_get_group:
+ * @window: a toplevel #GdkWindow
+ *
+ * Returns the group leader window for @window. See gdk_window_set_group().
+ *
+ * Return value: (transfer none): the group leader window for @window
+ *
+ * Since: 2.4
+ **/
+GdkWindow *
+gdk_window_get_group (GdkWindow *window)
+{
+  return GDK_WINDOW_IMPL_GET_CLASS (window->impl)->get_group (window);
+}
+
+/**
+ * gdk_window_set_group:
+ * @window: a toplevel #GdkWindow
+ * @leader: group leader window, or %NULL to restore the default group leader window
+ *
+ * Sets the group leader window for @window. By default,
+ * GDK sets the group leader for all toplevel windows
+ * to a global window implicitly created by GDK. With this function
+ * you can override this default.
+ *
+ * The group leader window allows the window manager to distinguish
+ * all windows that belong to a single application. It may for example
+ * allow users to minimize/unminimize all windows belonging to an
+ * application at once. You should only set a non-default group window
+ * if your application pretends to be multiple applications.
+ **/
+void
+gdk_window_set_group (GdkWindow *window,
+                     GdkWindow *leader)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_group (window, leader);
+}
+
+/**
+ * gdk_window_set_decorations:
+ * @window: a toplevel #GdkWindow
+ * @decorations: decoration hint mask
+ *
+ * "Decorations" are the features the window manager adds to a toplevel #GdkWindow.
+ * This function sets the traditional Motif window manager hints that tell the
+ * window manager which decorations you would like your window to have.
+ * Usually you should use gtk_window_set_decorated() on a #GtkWindow instead of
+ * using the GDK function directly.
+ *
+ * The @decorations argument is the logical OR of the fields in
+ * the #GdkWMDecoration enumeration. If #GDK_DECOR_ALL is included in the
+ * mask, the other bits indicate which decorations should be turned off.
+ * If #GDK_DECOR_ALL is not included, then the other bits indicate
+ * which decorations should be turned on.
+ *
+ * Most window managers honor a decorations hint of 0 to disable all decorations,
+ * but very few honor all possible combinations of bits.
+ *
+ **/
+void
+gdk_window_set_decorations (GdkWindow      *window,
+                           GdkWMDecoration decorations)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_decorations (window, decorations);
+}
+
+/**
+ * gdk_window_get_decorations:
+ * @window: The toplevel #GdkWindow to get the decorations from
+ * @decorations: The window decorations will be written here
+ *
+ * Returns the decorations set on the GdkWindow with
+ * gdk_window_set_decorations().
+ *
+ * Returns: %TRUE if the window has decorations set, %FALSE otherwise.
+ **/
+gboolean
+gdk_window_get_decorations(GdkWindow       *window,
+                          GdkWMDecoration *decorations)
+{
+  return GDK_WINDOW_IMPL_GET_CLASS (window->impl)->get_decorations (window, decorations);
+}
+
+/**
+ * gdk_window_set_functions:
+ * @window: a toplevel #GdkWindow
+ * @functions: bitmask of operations to allow on @window
+ *
+ * Sets hints about the window management functions to make available
+ * via buttons on the window frame.
+ *
+ * On the X backend, this function sets the traditional Motif window
+ * manager hint for this purpose. However, few window managers do
+ * anything reliable or interesting with this hint. Many ignore it
+ * entirely.
+ *
+ * The @functions argument is the logical OR of values from the
+ * #GdkWMFunction enumeration. If the bitmask includes #GDK_FUNC_ALL,
+ * then the other bits indicate which functions to disable; if
+ * it doesn't include #GDK_FUNC_ALL, it indicates which functions to
+ * enable.
+ *
+ **/
+void
+gdk_window_set_functions (GdkWindow    *window,
+                         GdkWMFunction functions)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_functions (window, functions);
+}
+
+/**
+ * gdk_window_begin_resize_drag:
+ * @window: a toplevel #GdkWindow
+ * @edge: the edge or corner from which the drag is started
+ * @button: the button being used to drag
+ * @root_x: root window X coordinate of mouse click that began the drag
+ * @root_y: root window Y coordinate of mouse click that began the drag
+ * @timestamp: timestamp of mouse click that began the drag (use gdk_event_get_time())
+ *
+ * Begins a window resize operation (for a toplevel window).
+ * You might use this function to implement a "window resize grip," for
+ * example; in fact #GtkStatusbar uses it. The function works best
+ * with window managers that support the <ulink url="http://www.freedesktop.org/Standards/wm-spec">Extended Window Manager Hints</ulink>, but has a
+ * fallback implementation for other window managers.
+ *
+ **/
+void
+gdk_window_begin_resize_drag (GdkWindow     *window,
+                              GdkWindowEdge  edge,
+                              gint           button,
+                              gint           root_x,
+                              gint           root_y,
+                              guint32        timestamp)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->begin_resize_drag (window, edge, button, root_x, root_y, timestamp);
+}
+
+/**
+ * gdk_window_begin_move_drag:
+ * @window: a toplevel #GdkWindow
+ * @button: the button being used to drag
+ * @root_x: root window X coordinate of mouse click that began the drag
+ * @root_y: root window Y coordinate of mouse click that began the drag
+ * @timestamp: timestamp of mouse click that began the drag
+ *
+ * Begins a window move operation (for a toplevel window).  You might
+ * use this function to implement a "window move grip," for
+ * example. The function works best with window managers that support
+ * the <ulink url="http://www.freedesktop.org/Standards/wm-spec">Extended
+ * Window Manager Hints</ulink>, but has a fallback implementation for
+ * other window managers.
+ *
+ **/
+void
+gdk_window_begin_move_drag (GdkWindow *window,
+                            gint       button,
+                            gint       root_x,
+                            gint       root_y,
+                            guint32    timestamp)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->begin_move_drag (window, button, root_x, root_y, timestamp);
+}
+
+/**
+ * gdk_window_enable_synchronized_configure:
+ * @window: a toplevel #GdkWindow
+ *
+ * Indicates that the application will cooperate with the window
+ * system in synchronizing the window repaint with the window
+ * manager during resizing operations. After an application calls
+ * this function, it must call gdk_window_configure_finished() every
+ * time it has finished all processing associated with a set of
+ * Configure events. Toplevel GTK+ windows automatically use this
+ * protocol.
+ *
+ * On X, calling this function makes @window participate in the
+ * _NET_WM_SYNC_REQUEST window manager protocol.
+ *
+ * Since: 2.6
+ **/
+void
+gdk_window_enable_synchronized_configure (GdkWindow *window)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->enable_synchronized_configure (window);
+}
+
+/**
+ * gdk_window_configure_finished:
+ * @window: a toplevel #GdkWindow
+ * 
+ * Signal to the window system that the application has finished
+ * handling Configure events it has received. Window Managers can
+ * use this to better synchronize the frame repaint with the
+ * application. GTK+ applications will automatically call this
+ * function when appropriate.
+ *
+ * This function can only be called if gdk_window_enable_synchronized_configure()
+ * was called previously.
+ *
+ * Since: 2.6
+ **/
+void
+gdk_window_configure_finished (GdkWindow *window)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->configure_finished (window);
+}
+
+/**
+ * gdk_window_set_opacity:
+ * @window: a top-level #GdkWindow
+ * @opacity: opacity
+ *
+ * Request the windowing system to make @window partially transparent,
+ * with opacity 0 being fully transparent and 1 fully opaque. (Values
+ * of the opacity parameter are clamped to the [0,1] range.) 
+ *
+ * On X11, this works only on X screens with a compositing manager 
+ * running.
+ *
+ * For setting up per-pixel alpha, see gdk_screen_get_rgba_visual().
+ * For making non-toplevel windows translucent, see 
+ * gdk_window_set_composited().
+ *
+ * Since: 2.12
+ */
+void
+gdk_window_set_opacity (GdkWindow *window,
+                       gdouble    opacity)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_opacity (window, opacity);
+}
+
+/* This function is called when the XWindow is really gone.
+ */
+void
+gdk_window_destroy_notify (GdkWindow *window)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->destroy_notify (window);
+}
+
+/**
+ * gdk_window_register_dnd:
+ * @window: a #GdkWindow.
+ *
+ * Registers a window as a potential drop destination.
+ */
+void
+gdk_window_register_dnd (GdkWindow *window)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->register_dnd (window);
+}
+
+/**
+ * gdk_drag_begin:
+ * @window: the source window for this drag.
+ * @targets: (transfer none) (element-type GdkAtom): the offered targets,
+ *     as list of #GdkAtoms
+ *
+ * Starts a drag and creates a new drag context for it.
+ * This function assumes that the drag is controlled by the
+ * client pointer device, use gdk_drag_begin_for_device() to
+ * begin a drag with a different device.
+ *
+ * This function is called by the drag source.
+ *
+ * Return value: (transfer full): a newly created #GdkDragContext
+ */
+GdkDragContext *
+gdk_drag_begin (GdkWindow     *window,
+                GList         *targets)
+{
+  GdkDeviceManager *device_manager;
+  GdkDevice *device;
+
+  device_manager = gdk_display_get_device_manager (gdk_window_get_display (window));
+  device = gdk_device_manager_get_client_pointer (device_manager);
+
+  return gdk_drag_begin_for_device (window, device, targets);
+}
+
+/**
+ * gdk_drag_begin_for_device:
+ * @window: the source window for this drag
+ * @device: the device that controls this drag
+ * @targets: (transfer none) (element-type GdkAtom): the offered targets,
+ *     as list of #GdkAtoms
+ *
+ * Starts a drag and creates a new drag context for it.
+ *
+ * This function is called by the drag source.
+ *
+ * Return value: (transfer full): a newly created #GdkDragContext
+ */
+GdkDragContext *
+gdk_drag_begin_for_device (GdkWindow     *window,
+                           GdkDevice     *device,
+                           GList         *targets)
+{
+  return GDK_WINDOW_IMPL_GET_CLASS (window->impl)->drag_begin (window, device, targets);
+}
+
+/**
+ * gdk_test_render_sync:
+ * @window: a mapped #GdkWindow
+ *
+ * Retrieves a pixel from @window to force the windowing
+ * system to carry out any pending rendering commands.
+ *
+ * This function is intended to be used to synchronize with rendering
+ * pipelines, to benchmark windowing system rendering operations.
+ *
+ * Since: 2.14
+ **/
+void
+gdk_test_render_sync (GdkWindow *window)
+{
+  return GDK_WINDOW_IMPL_GET_CLASS (window->impl)->sync_rendering (window);
+}
+
+/**
+ * gdk_test_simulate_key:
+ * @window: a #GdkWindow to simulate a key event for
+ * @x:      x coordinate within @window for the key event
+ * @y:      y coordinate within @window for the key event
+ * @keyval: A GDK keyboard value
+ * @modifiers: Keyboard modifiers the event is setup with
+ * @key_pressrelease: either %GDK_KEY_PRESS or %GDK_KEY_RELEASE
+ *
+ * This function is intended to be used in GTK+ test programs.
+ * If (@x,@y) are > (-1,-1), it will warp the mouse pointer to
+ * the given (@x,@y) coordinates within @window and simulate a
+ * key press or release event.
+ *
+ * When the mouse pointer is warped to the target location, use
+ * of this function outside of test programs that run in their
+ * own virtual windowing system (e.g. Xvfb) is not recommended.
+ * If (@x,@y) are passed as (-1,-1), the mouse pointer will not
+ * be warped and @window origin will be used as mouse pointer
+ * location for the event.
+ *
+ * Also, gdk_test_simulate_key() is a fairly low level function,
+ * for most testing purposes, gtk_test_widget_send_key() is the
+ * right function to call which will generate a key press event
+ * followed by its accompanying key release event.
+ *
+ * Returns: whether all actions necessary for a key event simulation
+ *     were carried out successfully
+ *
+ * Since: 2.14
+ */
+gboolean
+gdk_test_simulate_key (GdkWindow      *window,
+                       gint            x,
+                       gint            y,
+                       guint           keyval,
+                       GdkModifierType modifiers,
+                       GdkEventType    key_pressrelease)
+{
+  return GDK_WINDOW_IMPL_GET_CLASS (window->impl)
+    ->simulate_key (window, x, y, keyval, modifiers, key_pressrelease);
+}
+
+/**
+ * gdk_test_simulate_button:
+ * @window: a #GdkWindow to simulate a button event for
+ * @x:      x coordinate within @window for the button event
+ * @y:      y coordinate within @window for the button event
+ * @button: Number of the pointer button for the event, usually 1, 2 or 3
+ * @modifiers: Keyboard modifiers the event is setup with
+ * @button_pressrelease: either %GDK_BUTTON_PRESS or %GDK_BUTTON_RELEASE
+ *
+ * This function is intended to be used in GTK+ test programs.
+ * It will warp the mouse pointer to the given (@x,@y) coordinates
+ * within @window and simulate a button press or release event.
+ * Because the mouse pointer needs to be warped to the target
+ * location, use of this function outside of test programs that
+ * run in their own virtual windowing system (e.g. Xvfb) is not
+ * recommended.
+ *
+* Also, gdk_test_simulate_button() is a fairly low level function,
+ * for most testing purposes, gtk_test_widget_click() is the right
+ * function to call which will generate a button press event followed
+ * by its accompanying button release event.
+ *
+ * Returns: whether all actions necessary for a button event simulation
+ *     were carried out successfully
+ *
+ * Since: 2.14
+ */
+gboolean
+gdk_test_simulate_button (GdkWindow      *window,
+                          gint            x,
+                          gint            y,
+                          guint           button, /*1..3*/
+                          GdkModifierType modifiers,
+                          GdkEventType    button_pressrelease)
+{
+  return GDK_WINDOW_IMPL_GET_CLASS (window->impl)
+    ->simulate_button (window, x, y, button, modifiers, button_pressrelease);
+}
+
+/**
+ * gdk_property_get:
+ * @window: a #GdkWindow
+ * @property: the property to retrieve
+ * @type: the desired property type, or %GDK_NONE, if any type of data
+ *   is acceptable. If this does not match the actual
+ *   type, then @actual_format and @actual_length will
+ *   be filled in, a warning will be printed to stderr
+ *   and no data will be returned.
+ * @offset: the offset into the property at which to begin
+ *   retrieving data, in 4 byte units.
+ * @length: the length of the data to retrieve in bytes.  Data is
+ *   considered to be retrieved in 4 byte chunks, so @length
+ *   will be rounded up to the next highest 4 byte boundary
+ *   (so be careful not to pass a value that might overflow
+ *   when rounded up).
+ * @pdelete: if %TRUE, delete the property after retrieving the
+ *   data.
+ * @actual_property_type: location to store the actual type of
+*   the property.
+ * @actual_format: location to store the actual return format of the
+ *   data; either 8, 16 or 32 bits.
+ * @actual_length: location to store the length of the retrieved data, in
+ *   bytes.  Data returned in the 32 bit format is stored
+ *   in a long variable, so the actual number of 32 bit
+ *   elements should be be calculated via
+ *   @actual_length / sizeof(glong) to ensure portability to
+ *   64 bit systems.
+ * @data: location to store a pointer to the data. The retrieved
+ *   data should be freed with g_free() when you are finished
+ *   using it.
+ *
+ * Retrieves a portion of the contents of a property. If the
+ * property does not exist, then the function returns %FALSE,
+ * and %GDK_NONE will be stored in @actual_property_type.
+ *
+ * <note>
+ * <para>
+ * The XGetWindowProperty() function that gdk_property_get()
+ * uses has a very confusing and complicated set of semantics.
+ * uses has a very confusing and complicated set of semantics.
+ * Unfortunately, gdk_property_get() makes the situation
+ * worse instead of better (the semantics should be considered
+ * undefined), and also prints warnings to stderr in cases where it
+ * should return a useful error to the program. You are advised to use
+ * XGetWindowProperty() directly until a replacement function for
+ * gdk_property_get()
+ * is provided.
+ * </para>
+ * </note>
+ *
+ * Returns: %TRUE if data was successfully received and stored
+ *   in @data, otherwise %FALSE.
+ */
+gboolean
+gdk_property_get (GdkWindow  *window,
+                  GdkAtom     property,
+                  GdkAtom     type,
+                  gulong      offset,
+                  gulong      length,
+                  gint        pdelete,
+                  GdkAtom    *actual_property_type,
+                  gint       *actual_format_type,
+                  gint       *actual_length,
+                  guchar    **data)
+{
+  return GDK_WINDOW_IMPL_GET_CLASS (window->impl)
+    ->get_property (window, property, type, offset, length, pdelete,
+                    actual_property_type, actual_format_type,
+                    actual_length, data);
+}
+
+/**
+ * gdk_property_change:
+ * @window: a #GdkWindow
+ * @property: the property to change
+ * @type: the new type for the property. If @mode is
+ *   %GDK_PROP_MODE_PREPEND or %GDK_PROP_MODE_APPEND, then this
+ *   must match the existing type or an error will occur.
+ * @format: the new format for the property. If @mode is
+ *   %GDK_PROP_MODE_PREPEND or %GDK_PROP_MODE_APPEND, then this
+ *   must match the existing format or an error will occur.
+ * @mode: a value describing how the new data is to be combined
+ *   with the current data.
+ * @data: the data (a <literal>guchar *</literal>
+ *   <literal>gushort *</literal>, or <literal>gulong *</literal>,
+ *   depending on @format), cast to a <literal>guchar *</literal>.
+ * @nelements: the number of elements of size determined by the format,
+ *   contained in @data.
+ *
+ * Changes the contents of a property on a window.
+ */
+void
+gdk_property_change (GdkWindow    *window,
+                     GdkAtom       property,
+                     GdkAtom       type,
+                     gint          format,
+                     GdkPropMode   mode,
+                     const guchar *data,
+                     gint          nelements)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)
+    ->change_property (window, property, type, format, mode, data, nelements);
+}
+
+/**
+ * gdk_property_delete:
+ * @window: a #GdkWindow
+ * @property: the property to delete
+ *
+ * Deletes a property from a window.
+ */
+void
+gdk_property_delete (GdkWindow *window,
+                     GdkAtom    property)
+{
+  GDK_WINDOW_IMPL_GET_CLASS (window->impl)->delete_property (window, property);
+}