]> Pileus Git - ~andy/gtk/blobdiff - gdk/gdkwindow.c
Warn when a parent is destroyed
[~andy/gtk] / gdk / gdkwindow.c
index 764e3da54aedf0dad6e76587a73576f3d6ffddb7..3acf0ff4af84366be2513ef7c8bc9a841e136dfb 100644 (file)
@@ -32,6 +32,7 @@
 #include "gdk.h"               /* For gdk_rectangle_union() */
 #include "gdkpixmap.h"
 #include "gdkdrawable.h"
+#include "gdkintl.h"
 #include "gdkscreen.h"
 #include "gdkmarshalers.h"
 #include "gdkalias.h"
@@ -128,6 +129,11 @@ enum {
   LAST_SIGNAL
 };
 
+enum {
+  PROP_0,
+  PROP_CURSOR
+};
+
 struct _GdkWindowPaint
 {
   GdkRegion *region;
@@ -293,6 +299,16 @@ 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,
+                                     guint         prop_id,
+                                     const GValue *value,
+                                     GParamSpec   *pspec);
+static void gdk_window_get_property (GObject      *object,
+                                     guint         prop_id,
+                                     GValue       *value,
+                                     GParamSpec   *pspec);
+
 static void gdk_window_clear_backing_region (GdkWindow *window,
                                             GdkRegion *region);
 static void gdk_window_redirect_free      (GdkWindowRedirect *redirect);
@@ -313,6 +329,7 @@ static void do_move_region_bits_on_impl (GdkWindowObject *private,
 static void gdk_window_invalidate_in_parent (GdkWindowObject *private);
 static void move_native_children (GdkWindowObject *private);
 static void update_cursor (GdkDisplay *display);
+static void gdk_window_region_move_free (GdkWindowRegionMove *move);
 
 static guint signals[LAST_SIGNAL] = { 0 };
 
@@ -410,6 +427,8 @@ gdk_window_class_init (GdkWindowObjectClass *klass)
   parent_class = g_type_class_peek_parent (klass);
 
   object_class->finalize = gdk_window_finalize;
+  object_class->set_property = gdk_window_set_property;
+  object_class->get_property = gdk_window_get_property;
 
   drawable_class->create_gc = gdk_window_create_gc;
   drawable_class->draw_rectangle = gdk_window_draw_rectangle;
@@ -444,6 +463,14 @@ gdk_window_class_init (GdkWindowObjectClass *klass)
   quark_pointer_window = g_quark_from_static_string ("gtk-pointer-window");
 
 
+  /* Properties */
+  g_object_class_install_property (object_class,
+                                   PROP_CURSOR,
+                                   g_param_spec_pointer ("cursor",
+                                                         P_("Cursor"),
+                                                         P_("Cursor"),
+                                                         G_PARAM_READWRITE));
+
   /**
    * GdkWindow::pick-embedded-child:
    * @window: the window on which the signal is emitted
@@ -568,6 +595,46 @@ gdk_window_finalize (GObject *object)
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
+static void
+gdk_window_set_property (GObject      *object,
+                         guint         prop_id,
+                         const GValue *value,
+                         GParamSpec   *pspec)
+{
+  GdkWindow *window = (GdkWindow *)object;
+
+  switch (prop_id)
+    {
+    case PROP_CURSOR:
+      gdk_window_set_cursor (window, g_value_get_pointer (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+gdk_window_get_property (GObject    *object,
+                         guint       prop_id,
+                         GValue     *value,
+                         GParamSpec *pspec)
+{
+  GdkWindow *window = (GdkWindow *) object;
+
+  switch (prop_id)
+    {
+    case PROP_CURSOR:
+      g_value_set_pointer (value, gdk_window_get_cursor (window));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
 static gboolean
 gdk_window_is_offscreen (GdkWindowObject *window)
 {
@@ -783,33 +850,40 @@ recompute_visible_regions_internal (GdkWindowObject *private,
    * siblings in parents above window
    */
   clip_region_changed = FALSE;
-  if (recalculate_clip && private->viewable)
+  if (recalculate_clip)
     {
-      /* Calculate visible region (sans children) in parent window coords */
-      r.x = private->x;
-      r.y = private->y;
-      r.width = private->width;
-      r.height = private->height;
-      new_clip = gdk_region_rectangle (&r);
-
-      if (private->parent != NULL &&
-         private->parent->window_type != GDK_WINDOW_ROOT &&
-         /* For foreign children, don't remove local parents, as parent
-            may not be mapped yet, and the non-native parents are not really
-            enforced for it anyways. */
-         private->window_type != GDK_WINDOW_FOREIGN)
+      if (private->viewable)
        {
-         gdk_region_intersect (new_clip, private->parent->clip_region);
-
-         /* Remove all overlapping children from parent */
-         remove_child_area (private->parent, private, FALSE, new_clip);
-       }
+         /* Calculate visible region (sans children) in parent window coords */
+         r.x = private->x;
+         r.y = private->y;
+         r.width = private->width;
+         r.height = private->height;
+         new_clip = gdk_region_rectangle (&r);
+
+         if (private->parent != NULL &&
+             private->parent->window_type != GDK_WINDOW_ROOT)
+           {
+             gdk_region_intersect (new_clip, private->parent->clip_region);
+
+             /* Remove all overlapping children from parent.
+              * Unless we're all native, because then we don't need to take
+              * siblings into account since X does that clipping for us.
+              * This makes things like SWT that modify the raw X stacking
+              * order without GDKs knowledge work.
+              */
+             if (!_gdk_native_windows)
+               remove_child_area (private->parent, private, FALSE, new_clip);
+           }
 
-      /* Convert from parent coords to window coords */
-      gdk_region_offset (new_clip, -private->x, -private->y);
+         /* Convert from parent coords to window coords */
+         gdk_region_offset (new_clip, -private->x, -private->y);
 
-      if (private->shape)
-       gdk_region_intersect (new_clip, private->shape);
+         if (private->shape)
+           gdk_region_intersect (new_clip, private->shape);
+       }
+      else
+       new_clip = gdk_region_new ();
 
       if (private->clip_region == NULL ||
          !gdk_region_equal (private->clip_region, new_clip))
@@ -839,23 +913,26 @@ recompute_visible_regions_internal (GdkWindowObject *private,
 
       if (gdk_region_empty (private->clip_region))
        visibility = GDK_VISIBILITY_FULLY_OBSCURED;
-      else {
-       if (private->shape)
-         fully_visible = gdk_region_equal (private->clip_region,
-                                           private->shape);
-       else
-         {
-           r.x = 0;
-           r.y = 0;
-           r.width = private->width;
-           r.height = private->height;
-           fully_visible = gdk_region_rect_equal (private->clip_region, &r);
-         }
-
-       if (fully_visible)
-         visibility = GDK_VISIBILITY_UNOBSCURED;
-       else
-         visibility = GDK_VISIBILITY_PARTIAL;
+      else
+        {
+          if (private->shape)
+            {
+             fully_visible = gdk_region_equal (private->clip_region,
+                                               private->shape);
+            }
+          else
+            {
+             r.x = 0;
+             r.y = 0;
+             r.width = private->width;
+             r.height = private->height;
+             fully_visible = gdk_region_rect_equal (private->clip_region, &r);
+           }
+
+         if (fully_visible)
+           visibility = GDK_VISIBILITY_UNOBSCURED;
+         else
+           visibility = GDK_VISIBILITY_PARTIAL;
        }
 
       if (private->visibility != visibility)
@@ -1025,8 +1102,11 @@ find_native_sibling_above (GdkWindowObject *parent,
 static GdkEventMask
 get_native_event_mask (GdkWindowObject *private)
 {
-  if (private->window_type != GDK_WINDOW_ROOT &&
-      private->window_type != GDK_WINDOW_FOREIGN)
+  if (_gdk_native_windows ||
+      private->window_type == GDK_WINDOW_ROOT ||
+      private->window_type == GDK_WINDOW_FOREIGN)
+    return private->event_mask;
+  else
     {
       return
        /* We need thse for all native window so we can emulate
@@ -1048,13 +1128,13 @@ get_native_event_mask (GdkWindowObject *private)
           GDK_BUTTON2_MOTION_MASK |
           GDK_BUTTON3_MOTION_MASK));
     }
-  else
-    return private->event_mask;
 }
 
 /* Puts the native window in the right order wrt the other native windows
-   in the hierarchy, given the position it has in the client side data.
-   This is useful if some operation changed the stacking order. */
+ * in the hierarchy, given the position it has in the client side data.
+ * This is useful if some operation changed the stacking order.
+ * This calls assumes the native window is now topmost in its native parent.
+ */
 static void
 sync_native_window_stack_position (GdkWindow *window)
 {
@@ -1117,7 +1197,17 @@ gdk_window_new (GdkWindow     *parent,
   g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
 
   if (GDK_WINDOW_DESTROYED (parent))
-    return NULL;
+    {
+      g_warning ("gdk_window_new(): parent is destroyed\n");
+      return NULL;
+    }
+
+  if (attributes->window_type == GDK_WINDOW_OFFSCREEN &&
+      _gdk_native_windows)
+    {
+      g_warning ("Offscreen windows not supported with native-windows gdk");
+      return NULL;
+    }
 
   window = g_object_new (GDK_TYPE_WINDOW, NULL);
   private = (GdkWindowObject *) window;
@@ -1206,7 +1296,7 @@ gdk_window_new (GdkWindow     *parent,
       private->input_only = FALSE;
       private->depth = visual->depth;
 
-      private->bg_color.pixel = 0; // TODO: BlackPixel (xdisplay, screen_x11->screen_num);
+      private->bg_color.pixel = 0; /* TODO: BlackPixel (xdisplay, screen_x11->screen_num); */
       private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
 
       private->bg_pixmap = NULL;
@@ -1220,7 +1310,7 @@ gdk_window_new (GdkWindow     *parent,
   if (private->parent)
     private->parent->children = g_list_prepend (private->parent->children, window);
 
-  native = FALSE; /* Default */
+  native = _gdk_native_windows; /* Default */
   if (private->parent->window_type == GDK_WINDOW_ROOT)
     native = TRUE; /* Always use native windows for toplevels */
   else if (!private->input_only &&
@@ -1245,7 +1335,8 @@ gdk_window_new (GdkWindow     *parent,
 
       /* 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 */
-      sync_native_window_stack_position (window);
+      if (!_gdk_window_has_impl (real_parent))
+       sync_native_window_stack_position (window);
     }
   else
     {
@@ -1364,8 +1455,9 @@ gdk_window_reparent (GdkWindow *window,
   GdkWindowObject *new_parent_private;
   GdkWindowObject *old_parent;
   GdkScreen *screen;
-  gboolean show, was_toplevel, was_mapped;
+  gboolean show, was_mapped;
   gboolean do_reparent_to_impl;
+  GdkEventMask old_native_event_mask;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
@@ -1408,7 +1500,6 @@ gdk_window_reparent (GdkWindow *window,
       private->redirect = NULL;
     }
 
-  was_toplevel = private->parent == NULL;
   was_mapped = GDK_WINDOW_IS_MAPPED (window);
   show = FALSE;
 
@@ -1417,9 +1508,11 @@ gdk_window_reparent (GdkWindow *window,
       new_parent_private->window_type == GDK_WINDOW_FOREIGN)
     gdk_window_ensure_native (window);
 
+  old_native_event_mask = 0;
   do_reparent_to_impl = FALSE;
   if (gdk_window_has_impl (private))
     {
+      old_native_event_mask = get_native_event_mask (private);
       /* Native window */
       show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent (window, new_parent, x, y);
     }
@@ -1486,7 +1579,13 @@ gdk_window_reparent (GdkWindow *window,
   /* 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))
-    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_events (window, get_native_event_mask (private));
+    {
+      GdkEventMask native_event_mask = get_native_event_mask (private);
+
+      if (native_event_mask != old_native_event_mask)
+       GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_events (window,
+                                                              native_event_mask);
+    }
 
   /* Inherit parent redirect if we don't have our own */
   if (private->parent && private->redirect == NULL)
@@ -1508,7 +1607,8 @@ gdk_window_reparent (GdkWindow *window,
       /* 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 */
-      sync_native_window_stack_position (window);
+      if (!gdk_window_has_impl (new_parent_private))
+       sync_native_window_stack_position (window);
     }
 
   if (show)
@@ -1577,8 +1677,9 @@ gdk_window_ensure_native (GdkWindow *window)
   change_impl (private, private, new_impl);
 
   /* Native window creation 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 */
+   * 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);
   if (above)
     {
@@ -1593,8 +1694,7 @@ gdk_window_ensure_native (GdkWindow *window)
 
   /* The shape may not have been set, as the clip region doesn't actually
      change, so do it here manually */
-  if (private->viewable)
-    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region ((GdkWindow *)private, private->clip_region, 0, 0);
+  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region ((GdkWindow *)private, private->clip_region, 0, 0);
 
   reparent_to_impl (private);
 
@@ -1801,6 +1901,25 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
              g_object_unref (display->pointer_info.toplevel_under_pointer);
              display->pointer_info.toplevel_under_pointer = NULL;
            }
+
+         if (private->clip_region)
+           {
+             gdk_region_destroy (private->clip_region);
+             private->clip_region = NULL;
+           }
+
+         if (private->clip_region_with_children)
+           {
+             gdk_region_destroy (private->clip_region_with_children);
+             private->clip_region_with_children = NULL;
+           }
+
+         if (private->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;
+           }
        }
       break;
     }
@@ -2275,6 +2394,9 @@ gdk_window_begin_implicit_paint (GdkWindow *window, GdkRectangle *rect)
 
   g_assert (gdk_window_has_impl (private));
 
+  if (_gdk_native_windows)
+    return FALSE; /* No need for implicit paints since we can't merge draws anyway */
+
   if (GDK_IS_PAINTABLE (private->impl))
     return FALSE; /* Implementation does double buffering */
 
@@ -2501,13 +2623,8 @@ gdk_window_begin_paint_region (GdkWindow       *window,
       paint->x_offset = -private->abs_x + implicit_paint->x_offset;
       paint->y_offset = -private->abs_y + implicit_paint->y_offset;
 
-      /* It would be nice if we had some cairo support here so we
-        could set the clip rect on the cairo surface */
-      width = private->abs_x + private->width;
-      height = private->abs_y + private->height;
-
+      gdk_drawable_get_size (paint->pixmap, &width, &height);
       paint->surface = _gdk_drawable_create_cairo_surface (paint->pixmap, width, height);
-
     }
   else
     {
@@ -2767,16 +2884,16 @@ do_move_region_bits_on_impl (GdkWindowObject *impl_window,
     }
   tmp_gc = _gdk_drawable_get_subwindow_scratch_gc ((GdkWindow *)private);
 
+  gdk_region_get_clipbox (dest_region, &copy_rect);
+  gdk_gc_set_clip_region (tmp_gc, dest_region);
+
   /* The region area is moved and we queue translations for all expose events
      to the source area that were sent prior to the copy */
-  gdk_region_offset (dest_region, -dx, -dy); /* Temporarily move to source area */
+  gdk_region_offset (dest_region, -dx, -dy); /* Move to source region */
   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->queue_translation ((GdkWindow *)impl_window,
+                                                               tmp_gc,
                                                                dest_region, dx, dy);
-  gdk_region_offset (dest_region, dx, dy); /* back to dest area */
-
-  gdk_region_get_clipbox (dest_region, &copy_rect);
 
-  gdk_gc_set_clip_region (tmp_gc, dest_region);
   gdk_draw_drawable (impl_window->impl,
                     tmp_gc,
                     private->impl,
@@ -2920,8 +3037,8 @@ append_move_region (GdkWindowObject *impl_window,
     }
 }
 
-/* Moves bits and update area by dx/dy in impl window,
-   takes ownership of region */
+/* 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 *private,
                     GdkRegion *region, /* In impl window coords */
@@ -2947,7 +3064,10 @@ move_region_on_impl (GdkWindowObject *private,
       /* Convert from target to source */
       gdk_region_offset (update_area, -dx, -dy);
       gdk_region_intersect (update_area, impl_window->update_area);
-      gdk_region_subtract (impl_window->update_area, update_area);
+      /* We only copy the area, so keep the old update area invalid.
+        It would be safe to remove it too, as code that uses
+        move_region_on_impl generally also invalidate the source
+        area. However, it would just use waste cycles. */
 
       /* Convert back */
       gdk_region_offset (update_area, dx, dy);
@@ -3179,8 +3299,8 @@ start_draw_helper (GdkDrawable *drawable,
         guarantee ordering. */
       gdk_window_flush ((GdkWindow *)drawable);
 
-      /* Don't clip when drawing to root */
-      if (private->window_type != GDK_WINDOW_ROOT)
+      /* Don't clip when drawing to root or all native */
+      if (!_gdk_native_windows && private->window_type != GDK_WINDOW_ROOT)
        {
          if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
            clip = private->clip_region_with_children;
@@ -3549,8 +3669,14 @@ gdk_window_draw_drawable (GdkDrawable *drawable,
 
   BEGIN_DRAW;
 
-  gdk_draw_drawable (impl, gc, src, xsrc, ysrc,
-                    xdest - x_offset, ydest - y_offset, width, height);
+  /* Call the method directly to avoid getting the composite drawable again */
+  GDK_DRAWABLE_GET_CLASS (impl)->draw_drawable_with_src (impl, gc,
+                                                        src,
+                                                        xsrc, ysrc,
+                                                        xdest - x_offset,
+                                                        ydest - y_offset,
+                                                        width, height,
+                                                        original_src);
 
   if (!private->paint_stack)
     {
@@ -4065,6 +4191,24 @@ gdk_window_clear (GdkWindow *window)
                         width, height);
 }
 
+static gboolean
+clears_on_native (GdkWindowObject *private)
+{
+  GdkWindowObject *next;
+
+  next = private;
+  do
+    {
+      private = next;
+      if (gdk_window_has_impl (private))
+       return TRUE;
+      next = private->parent;
+    }
+  while (private->bg_pixmap == GDK_PARENT_RELATIVE_BG &&
+        next && next->window_type != GDK_WINDOW_ROOT);
+  return FALSE;
+}
+
 static void
 gdk_window_clear_region_internal (GdkWindow *window,
                                  GdkRegion *region,
@@ -4080,7 +4224,7 @@ gdk_window_clear_region_internal (GdkWindow *window,
        gdk_window_clear_backing_region_redirect (window, region);
 
       if (GDK_WINDOW_IMPL_GET_IFACE (private->impl)->clear_region &&
-         gdk_window_has_impl (private))
+         clears_on_native (private))
        {
          GdkRegion *copy;
          copy = gdk_region_copy (region);
@@ -4225,6 +4369,7 @@ gdk_window_draw_pixbuf (GdkDrawable     *drawable,
                        gint             y_dither)
 {
   GdkWindowObject *private = (GdkWindowObject *)drawable;
+  GdkDrawableClass *klass;
 
   if (GDK_WINDOW_DESTROYED (drawable))
     return;
@@ -4235,16 +4380,19 @@ gdk_window_draw_pixbuf (GdkDrawable     *drawable,
     gc = _gdk_drawable_get_scratch_gc (drawable, FALSE);
 
   BEGIN_DRAW;
+
+  klass = GDK_DRAWABLE_GET_CLASS (impl);
+
   if (private->paint_stack)
-    gdk_draw_pixbuf (impl, gc, pixbuf, src_x, src_y,
-                    dest_x - x_offset, dest_y - y_offset,
-                    width, height,
-                    dither, x_dither - x_offset, y_dither - y_offset);
+    klass->draw_pixbuf (impl, gc, pixbuf, src_x, src_y,
+                       dest_x - x_offset, dest_y - y_offset,
+                       width, height,
+                       dither, x_dither - x_offset, y_dither - y_offset);
   else
-    gdk_draw_pixbuf (impl, gc, pixbuf, src_x, src_y,
-                    dest_x - x_offset, dest_y - y_offset,
-                    width, height,
-                    dither, x_dither, y_dither);
+    klass->draw_pixbuf (impl, gc, pixbuf, src_x, src_y,
+                       dest_x - x_offset, dest_y - y_offset,
+                       width, height,
+                       dither, x_dither, y_dither);
   END_DRAW;
 }
 
@@ -4469,11 +4617,11 @@ gdk_window_set_cairo_clip (GdkDrawable *drawable,
 
   if (!private->paint_stack)
     {
+      cairo_reset_clip (cr);
+
       cairo_save (cr);
       cairo_identity_matrix (cr);
 
-      cairo_reset_clip (cr);
-
       cairo_new_path (cr);
       gdk_cairo_region (cr, private->clip_region_with_children);
 
@@ -4486,13 +4634,12 @@ gdk_window_set_cairo_clip (GdkDrawable *drawable,
 
       /* Only needs to clip to region if piggybacking
         on an implicit paint pixmap */
+      cairo_reset_clip (cr);
       if (paint->uses_implicit)
        {
          cairo_save (cr);
          cairo_identity_matrix (cr);
 
-         cairo_reset_clip (cr);
-
          cairo_new_path (cr);
          gdk_cairo_region (cr, paint->region);
          cairo_restore (cr);
@@ -4645,17 +4792,21 @@ _gdk_window_process_updates_recurse (GdkWindow *window,
   GdkWindowObject *child;
   GdkRegion *child_region;
   GdkRectangle r;
-  GList *l;
+  GList *l, *children;
 
   if (gdk_region_empty (expose_region))
     return;
 
+  /* Make this reentrancy safe for expose handlers freeing windows */
+  children = g_list_copy (private->children);
+  g_list_foreach (children, (GFunc)g_object_ref, NULL);
+
   /* Iterate over children, starting at topmost */
-  for (l = private->children; l != NULL; l = l->next)
+  for (l = children; l != NULL; l = l->next)
     {
       child = l->data;
 
-      if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
+      if (child->destroyed || !GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
        continue;
 
       /* Ignore offscreen children, as they don't draw in their parent and
@@ -4693,7 +4844,11 @@ _gdk_window_process_updates_recurse (GdkWindow *window,
       gdk_region_destroy (child_region);
     }
 
-  if (!gdk_region_empty (expose_region))
+  g_list_foreach (children, (GFunc)g_object_unref, NULL);
+  g_list_free (children);
+
+  if (!gdk_region_empty (expose_region) &&
+      !private->destroyed)
     {
       if (private->event_mask & GDK_EXPOSURE_MASK)
        {
@@ -4726,6 +4881,13 @@ _gdk_window_process_updates_recurse (GdkWindow *window,
     }
 }
 
+/* Process and remove any invalid area on the native window by creating
+ * expose events for the window and all non-native descendants.
+ * Also processes any outstanding moves on the window before doing
+ * any drawing. Note that its possible to have outstanding moves without
+ * any invalid area as we use the update idle mechanism to coalesce
+ * multiple moves as well as multiple invalidations.
+ */
 static void
 gdk_window_process_updates_internal (GdkWindow *window)
 {
@@ -4733,6 +4895,9 @@ gdk_window_process_updates_internal (GdkWindow *window)
   gboolean save_region = FALSE;
   GdkRectangle clip_box;
 
+  /* Ensure the window lives while updating it */
+  g_object_ref (window);
+
   /* If an update got queued during update processing, we can get a
    * window in the update queue that has an empty update_area.
    * just ignore it.
@@ -4745,9 +4910,7 @@ gdk_window_process_updates_internal (GdkWindow *window)
       if (_gdk_event_func && gdk_window_is_viewable (window)  &&
          private->window_type != GDK_WINDOW_FOREIGN)
        {
-         GdkRectangle window_rect;
          GdkRegion *expose_region;
-         GdkRegion *window_region;
          gboolean end_implicit;
 
          /* Clip to part visible in toplevel */
@@ -4760,24 +4923,12 @@ gdk_window_process_updates_internal (GdkWindow *window)
              g_usleep (70000);
            }
 
-         save_region = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->queue_antiexpose (window, update_area);
-         if (save_region)
-           expose_region = gdk_region_copy (update_area);
-         else
-           expose_region = update_area;
-
-         window_rect.x = 0;
-         window_rect.y = 0;
-         window_rect.width = private->width;
-         window_rect.height = private->height;
-
-         window_region = gdk_region_rectangle (&window_rect);
-         gdk_region_intersect (expose_region,
-                               window_region);
-         gdk_region_destroy (window_region);
-
-
-         /* No need to do any moves that will end up over the update area */
+         /* At this point we will be completely redrawing all of update_area.
+          * If we have any outstanding moves that end up moving stuff inside
+          * this area we don't actually need to move that as that part would
+          * 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)
            {
              GdkWindowRegionMove *move;
@@ -4785,10 +4936,13 @@ gdk_window_process_updates_internal (GdkWindow *window)
              GList *l, *prev;
 
              remove = gdk_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)
                {
                  prev = l->prev;
                  move = l->data;
+
                  /* Don't need this area */
                  gdk_region_subtract (move->dest_region, remove);
 
@@ -4804,26 +4958,82 @@ gdk_window_process_updates_internal (GdkWindow *window)
                      private->outstanding_moves =
                        g_list_delete_link (private->outstanding_moves, l);
                    }
-                 else
+                 else /* move back */
                    gdk_region_offset (move->dest_region, move->dx, move->dy);
                }
              gdk_region_destroy (remove);
            }
 
-         gdk_region_get_clipbox (expose_region, &clip_box);
+         /* By now we a set of window moves that should be applied, and then
+          * an update region that should be repainted. A trivial implementation
+          * would just do that in order, however in order to get nicer drawing
+          * we do some tricks:
+          *
+          * First of all, each subwindow expose may be double buffered by
+          * itself (depending on widget setting) via
+          * gdk_window_begin/end_paint(). But we also do an "implicit" paint,
+          * creating a single pixmap the size of the invalid area on the
+          * native window which all the individual normal paints will draw
+          * into. This way in the normal case there will be only one pixmap
+          * allocated and only once pixmap draw done for all the windows
+          * in this native window.
+          * There are a couple of reasons this may fail, for instance, some
+          * backends (like quartz) do its own double buffering, so we disable
+          * gdk double buffering there. Secondly, some subwindow could be
+          * non-double buffered and draw directly to the window outside a
+          * begin/end_paint pair. That will be lead to a gdk_window_flush
+          * which immediately executes all outstanding moves and paints+removes
+          * the implicit paint (further paints will allocate their own pixmap).
+          *
+          * Secondly, in the case of implicit double buffering we expose all
+          * the child windows into the implicit pixmap before we execute
+          * the outstanding moves. This way we minimize the time between
+          * doing the moves and rendering the new update area, thus minimizing
+          * flashing. Of course, if any subwindow is non-double buffered we
+          * well flush earlier than that.
+          *
+          * Thirdly, after having done the outstanding moves we queue an
+          * "antiexpose" on the area that will be drawn by the expose, which
+          * means that any invalid region on the native window side before
+          * the first expose drawing operation will be discarded, as it
+          * has by then been overdrawn with valid data. This means we can
+          * avoid doing the unnecessary repaint any outstanding expose events.
+          */
+
+         gdk_region_get_clipbox (update_area, &clip_box);
          end_implicit = gdk_window_begin_implicit_paint (window, &clip_box);
-         if (end_implicit) /* rendering is not double buffered, do moves now */
+         expose_region = gdk_region_copy (update_area);
+         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);
+             save_region = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->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);
+
          if (end_implicit)
            {
-             /* Do moves right before exposes are rendered */
+             /* Do moves right before exposes are rendered to the window */
              gdk_window_flush_outstanding_moves (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) /* didn't flush implicit paint */
+               save_region = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->queue_antiexpose (window, update_area);
+
              gdk_window_end_implicit_paint (window);
            }
-
-         if (expose_region != update_area)
-           gdk_region_destroy (expose_region);
+         gdk_region_destroy (expose_region);
        }
       if (!save_region)
        gdk_region_destroy (update_area);
@@ -4835,6 +5045,8 @@ gdk_window_process_updates_internal (GdkWindow *window)
         no actual invalid area */
       gdk_window_flush_outstanding_moves (window);
     }
+
+  g_object_unref (window);
 }
 
 static void
@@ -4938,6 +5150,12 @@ gdk_window_process_updates (GdkWindow *window,
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
+  /* Make sure the window lives during the expose callouts */
+  g_object_ref (window);
+
   impl_window = gdk_window_get_impl_window (private);
   if ((impl_window->update_area ||
        impl_window->outstanding_moves) &&
@@ -4953,10 +5171,21 @@ gdk_window_process_updates (GdkWindow *window,
       /* process updates in reverse stacking order so composition or
        * painting over achieves the desired effect for offscreen windows
        */
-      GList *node;
-      for (node = g_list_last (private->children); node; node = node->prev)
-       gdk_window_process_updates (node->data, TRUE);
+      GList *node, *children;
+
+      children = g_list_copy (private->children);
+      g_list_foreach (children, (GFunc)g_object_ref, NULL);
+
+      for (node = g_list_last (children); node; node = node->prev)
+       {
+         gdk_window_process_updates (node->data, TRUE);
+         g_object_unref (node->data);
+       }
+
+      g_list_free (children);
     }
+
+  g_object_unref (window);
 }
 
 /**
@@ -5070,7 +5299,8 @@ gdk_window_invalidate_maybe_recurse (GdkWindow       *window,
 
   if (private->input_only ||
       !private->viewable ||
-      gdk_region_empty (region))
+      gdk_region_empty (region) ||
+      private->window_type == GDK_WINDOW_ROOT)
     return;
 
   visible_region = gdk_drawable_get_visible_region (window);
@@ -5213,8 +5443,37 @@ gdk_window_invalidate_region (GdkWindow       *window,
  **/
 void
 _gdk_window_invalidate_for_expose (GdkWindow       *window,
-                                  const GdkRegion *region)
+                                  GdkRegion       *region)
 {
+  GdkWindowObject *private = (GdkWindowObject *) window;
+  GdkWindowRegionMove *move;
+  GdkRegion *move_region;
+  GList *l;
+
+  /* Any invalidations comming from the windowing system will
+     be in areas that may be moved by outstanding moves,
+     so we need to modify the expose region correspondingly,
+     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)
+    {
+      move = l->data;
+
+      /* covert to move source region */
+      move_region = gdk_region_copy (move->dest_region);
+      gdk_region_offset (move_region, -move->dx, -move->dy);
+
+      /* Move area of region that intersects with move source
+        by dx, dy of the move*/
+      gdk_region_intersect (move_region, region);
+      gdk_region_subtract (region, move_region);
+      gdk_region_offset (move_region, move->dx, move->dy);
+      gdk_region_union (region, move_region);
+
+      gdk_region_destroy (move_region);
+    }
+
   gdk_window_invalidate_maybe_recurse (window, region,
                                       (gboolean (*) (GdkWindow *, gpointer))gdk_window_has_no_impl,
                                       NULL);
@@ -5710,7 +5969,13 @@ gdk_window_raise_internal (GdkWindow *window)
 
   /* Just do native raise for toplevels */
   if (private->parent == NULL ||
-      private->parent->window_type == GDK_WINDOW_ROOT)
+      private->parent->window_type == GDK_WINDOW_ROOT ||
+      /* 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_IMPL_GET_IFACE (private->impl)->raise (window);
     }
@@ -5752,40 +6017,22 @@ gdk_window_raise_internal (GdkWindow *window)
     }
 }
 
-/* Showing a non-native parent may cause children to become visible,
-   we need to handle this by manually showing them then. To simplify
-   things we hide them all when they are not visible. */
-static void
-show_all_visible_impls (GdkWindowObject *private, gboolean already_mapped)
-{
-  GdkWindowObject *child;
-  GList *l;
-
-  for (l = private->children; l != NULL; l = l->next)
-    {
-      child = l->data;
-
-      /* For foreign windows, only show if if was
-        explicitly hidden, otherwise we might cause
-        suprising things to happen to the other client. */
-      if (GDK_WINDOW_IS_MAPPED (child) &&
-         child->window_type != GDK_WINDOW_FOREIGN)
-       show_all_visible_impls (child, FALSE);
-    }
-
-  if (gdk_window_has_impl (private))
-    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show ((GdkWindow *)private, already_mapped);
-}
-
-static void
+/* Returns TRUE If the native window was mapped or unmapped */
+static gboolean
 set_viewable (GdkWindowObject *w,
              gboolean val)
 {
   GdkWindowObject *child;
   GList *l;
 
+  if (w->viewable == val)
+    return FALSE;
+
   w->viewable = val;
 
+  if (val)
+    recompute_visible_regions (w, FALSE, FALSE);
+
   for (l = w->children; l != NULL; l = l->next)
     {
       child = l->data;
@@ -5794,9 +6041,48 @@ set_viewable (GdkWindowObject *w,
          child->window_type != GDK_WINDOW_FOREIGN)
        set_viewable (child, val);
     }
+
+  if (gdk_window_has_impl (w)  &&
+      w->window_type != GDK_WINDOW_FOREIGN &&
+      w->parent != NULL &&
+      w->parent->window_type != GDK_WINDOW_ROOT)
+    {
+      /* For most native windows we show/hide them not when they are
+       * mapped/unmapped, because that may not produce the correct results.
+       * For instance, if a native window have a non-native parent which is
+       * hidden, but its native parent is viewable then showing the window
+       * would make it viewable to X but its not viewable wrt the non-native
+       * hierarchy. In order to handle this we track the gdk side viewability
+       * and only map really viewable windows.
+       *
+       * There are two exceptions though:
+       *
+       * For foreign windows we don't want ever change the mapped state
+       * except when explicitly done via gdk_window_show/hide, as this may
+       * cause problems for client owning the foreign window when its window
+       * is suddenly mapped or unmapped.
+       *
+       * For toplevel windows embedded in a foreign window (e.g. a plug)
+       * we sometimes synthesize a map of a window, but the native
+       * window is really shown by the embedder, so we don't want to
+       * do the show ourselves. We can't really tell this case from the normal
+       * toplevel show as such toplevels are seen by gdk as parents of the
+       * root window, so we make an exception for all toplevels.
+       */
+
+      if (val)
+       GDK_WINDOW_IMPL_GET_IFACE (w->impl)->show ((GdkWindow *)w, FALSE);
+      else
+       GDK_WINDOW_IMPL_GET_IFACE (w->impl)->hide ((GdkWindow *)w);
+
+      return TRUE;
+    }
+
+  return FALSE;
 }
 
-void
+/* Returns TRUE If the native window was mapped or unmapped */
+gboolean
 _gdk_window_update_viewable (GdkWindow *window)
 {
   GdkWindowObject *priv = (GdkWindowObject *)window;
@@ -5812,15 +6098,15 @@ _gdk_window_update_viewable (GdkWindow *window)
   else
     viewable = FALSE;
 
-  if (priv->viewable != viewable)
-    set_viewable (priv, viewable);
+  return set_viewable (priv, viewable);
 }
 
 static void
 gdk_window_show_internal (GdkWindow *window, gboolean raise)
 {
   GdkWindowObject *private;
-  gboolean was_mapped;
+  gboolean was_mapped, was_viewable;
+  gboolean did_show;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
@@ -5829,6 +6115,7 @@ gdk_window_show_internal (GdkWindow *window, gboolean raise)
     return;
 
   was_mapped = GDK_WINDOW_IS_MAPPED (window);
+  was_viewable = private->viewable;
 
   if (raise)
     /* Keep children in (reverse) stacking order */
@@ -5846,10 +6133,17 @@ gdk_window_show_internal (GdkWindow *window, gboolean raise)
       private->state = 0;
     }
 
-  _gdk_window_update_viewable (window);
+  did_show = _gdk_window_update_viewable (window);
 
-  if (gdk_window_is_viewable (window))
-    show_all_visible_impls (private, was_mapped);
+  /* If it was already viewable the backend show op won't be called, call it
+     again to ensure things happen right if the mapped tracking was not right
+     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))
+    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show ((GdkWindow *)private,
+                                                    !did_show ?
+                                                    was_mapped : TRUE);
 
   if (!was_mapped && !gdk_window_has_impl (private))
     {
@@ -5909,6 +6203,7 @@ void
 gdk_window_raise (GdkWindow *window)
 {
   GdkWindowObject *private;
+  GdkRegion *old_region, *new_region;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
@@ -5916,12 +6211,26 @@ gdk_window_raise (GdkWindow *window)
   if (private->destroyed)
     return;
 
+  old_region = NULL;
+  if (gdk_window_is_viewable (window) &&
+      !private->input_only)
+    old_region = gdk_region_copy (private->clip_region);
+
   /* Keep children in (reverse) stacking order */
   gdk_window_raise_internal (window);
 
   recompute_visible_regions (private, TRUE, FALSE);
 
-  gdk_window_invalidate_rect (window, NULL, TRUE);
+  if (old_region)
+    {
+      new_region = gdk_region_copy (private->clip_region);
+
+      gdk_region_subtract (new_region, old_region);
+      gdk_window_invalidate_region (window, new_region, TRUE);
+
+      gdk_region_destroy (old_region);
+      gdk_region_destroy (new_region);
+    }
 }
 
 static void
@@ -5941,7 +6250,13 @@ gdk_window_lower_internal (GdkWindow *window)
 
   /* Just do native lower for toplevels */
   if (private->parent == NULL ||
-      private->parent->window_type == GDK_WINDOW_ROOT)
+      private->parent->window_type == GDK_WINDOW_ROOT ||
+      /* 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_IMPL_GET_IFACE (private->impl)->lower (window);
     }
@@ -6062,33 +6377,6 @@ gdk_window_show (GdkWindow *window)
   gdk_window_show_internal (window, TRUE);
 }
 
-/* Hiding a non-native parent may cause parents to become non-visible,
-   even if their parent native window is visible. We need to handle this
-   by manually hiding them then. To simplify things we hide them all
-   when they are not visible. */
-static void
-hide_all_visible_impls (GdkWindowObject *private)
-{
-  GdkWindowObject *child;
-  GList *l;
-
-  for (l = private->children; l != NULL; l = l->next)
-    {
-      child = l->data;
-
-      /* For foreign windows, only hide if if was
-        explicitly hidden, otherwise we might cause
-        suprising things to happen to the other client. */
-      if (GDK_WINDOW_IS_MAPPED (child) &&
-         child->window_type != GDK_WINDOW_FOREIGN)
-       hide_all_visible_impls (child);
-    }
-
-  if (gdk_window_has_impl (private))
-    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->hide ((GdkWindow *)private);
-}
-
-
 /**
  * gdk_window_hide:
  * @window: a #GdkWindow
@@ -6102,7 +6390,7 @@ void
 gdk_window_hide (GdkWindow *window)
 {
   GdkWindowObject *private;
-  gboolean was_mapped, was_viewable;
+  gboolean was_mapped, did_hide;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
@@ -6111,7 +6399,6 @@ gdk_window_hide (GdkWindow *window)
     return;
 
   was_mapped = GDK_WINDOW_IS_MAPPED (private);
-  was_viewable = gdk_window_is_viewable (window);
 
   if (gdk_window_has_impl (private))
     {
@@ -6150,10 +6437,11 @@ gdk_window_hide (GdkWindow *window)
       private->state = GDK_WINDOW_STATE_WITHDRAWN;
     }
 
-  _gdk_window_update_viewable (window);
+  did_hide = _gdk_window_update_viewable (window);
 
-  if (was_viewable)
-    hide_all_visible_impls (private);
+  /* Hide foreign window as those are not handled by update_viewable. */
+  if (gdk_window_has_impl (private) && (!did_hide))
+    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->hide ((GdkWindow *)private);
 
   recompute_visible_regions (private, TRUE, FALSE);
 
@@ -6827,17 +7115,19 @@ gdk_window_move_region (GdkWindow       *window,
   gdk_region_offset (copy_area, dx, dy);
   gdk_region_intersect (copy_area, private->clip_region_with_children);
 
-  /* invalidate parts of the region not covered by the copy */
+  /* Invalidate parts of the region (source and dest) not covered
+     by the copy */
   nocopy_area = gdk_region_copy (region);
   gdk_region_offset (nocopy_area, dx, dy);
+  gdk_region_union (nocopy_area, region);
   gdk_region_subtract (nocopy_area, copy_area);
-  gdk_window_invalidate_region (window, nocopy_area, FALSE);
-  gdk_region_destroy (nocopy_area);
 
   /* convert from window coords to impl */
   gdk_region_offset (copy_area, private->abs_x, private->abs_y);
-
   move_region_on_impl (impl_window, copy_area, dx, dy); /* Takes ownership of copy_area */
+
+  gdk_window_invalidate_region (window, nocopy_area, FALSE);
+  gdk_region_destroy (nocopy_area);
 }
 
 /**
@@ -6945,6 +7235,34 @@ gdk_window_set_back_pixmap (GdkWindow *window,
     GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, private->bg_pixmap);
 }
 
+/**
+ * gdk_window_get_cursor:
+ * @window: a #GdkWindow
+ * @cursor: a cursor
+ *
+ * Retrieves a #GdkCursor pointer for the cursor currently set on the
+ * specified #GdkWindow, or %NULL.  If the return value is %NULL then
+ * there is no custom cursor set on the specified window, and it is
+ * using the cursor for its parent window.
+ *
+ * Return value: a #GdkCursor, or %NULL. The returned object is owned
+ *   by the #GdkWindow and should not be unreferenced directly. Use
+ *   gdk_window_set_cursor() to unset the cursor of the window
+ *
+ * Since: 2.18
+ */
+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;
+}
+
 /**
  * gdk_window_set_cursor:
  * @window: a #GdkWindow
@@ -6979,8 +7297,14 @@ gdk_window_set_cursor (GdkWindow *window,
       if (cursor)
        private->cursor = gdk_cursor_ref (cursor);
 
-      if (_gdk_window_event_parent_of (window, display->pointer_info.window_under_pointer))
+      if (_gdk_native_windows ||
+         private->window_type == GDK_WINDOW_ROOT ||
+          private->window_type == GDK_WINDOW_FOREIGN)
+        GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_cursor (window, cursor);
+      else if (_gdk_window_event_parent_of (window, display->pointer_info.window_under_pointer))
        update_cursor (display);
+
+      g_object_notify (G_OBJECT (window), "cursor");
     }
 }
 
@@ -7024,7 +7348,7 @@ gdk_window_get_geometry (GdkWindow *window,
                         gint      *height,
                         gint      *depth)
 {
-  GdkWindowObject *private;
+  GdkWindowObject *private, *parent;
 
   if (!window)
     {
@@ -7041,9 +7365,21 @@ gdk_window_get_geometry (GdkWindow *window,
   if (!GDK_WINDOW_DESTROYED (window))
     {
       if (gdk_window_has_impl (private))
-       GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_geometry (window, x, y,
-                                                                width, height,
-                                                                depth);
+       {
+         GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_geometry (window, x, y,
+                                                                  width, height,
+                                                                  depth);
+         /* 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;
+         if (parent && !gdk_window_has_impl (parent))
+           {
+             if (x)
+               *x -= parent->abs_x;
+             if (y)
+               *y -= parent->abs_y;
+           }
+       }
       else
        {
          if (x)
@@ -7279,7 +7615,7 @@ gdk_window_shape_combine_region (GdkWindow       *window,
     gdk_region_destroy (private->shape);
 
   old_region = NULL;
-  if (private->viewable)
+  if (GDK_WINDOW_IS_MAPPED (window))
     old_region = gdk_region_copy (private->clip_region);
 
   if (shape_region)
@@ -7389,7 +7725,7 @@ gdk_window_merge_child_shapes (GdkWindow *window)
 /**
  * gdk_window_input_shape_combine_mask:
  * @window: a #GdkWindow
- * @mask: shape mask
+ * @mask: shape mask, or %NULL
  * @x: X position of shape mask with respect to @window
  * @y: Y position of shape mask with respect to @window
  *
@@ -7434,7 +7770,8 @@ gdk_window_input_shape_combine_mask (GdkWindow *window,
                                         region,
                                         x, y);
 
-  gdk_region_destroy (region);
+  if (region != NULL)
+    gdk_region_destroy (region);
 }
 
 /**
@@ -8259,7 +8596,7 @@ gdk_window_beep (GdkWindow *window)
   toplevel = get_event_toplevel (window);
   display = gdk_drawable_get_display (GDK_DRAWABLE (window));
 
-  if (toplevel && gdk_window_is_offscreen ((GdkWindowObject *)toplevel))
+  if (toplevel && !gdk_window_is_offscreen ((GdkWindowObject *)toplevel))
     _gdk_windowing_window_beep (toplevel);
   else
     gdk_display_beep (display);
@@ -8397,6 +8734,8 @@ _gdk_make_event (GdkWindow    *window,
 
   event->any.window = g_object_ref (window);
   event->any.send_event = FALSE;
+  if (event_in_queue && event_in_queue->any.send_event)
+    event->any.send_event = TRUE;
 
   switch (type)
     {
@@ -8724,6 +9063,11 @@ _gdk_display_set_window_under_pointer (GdkDisplay *display,
 {
   GdkWindowObject *private;
 
+  /* We don't track this if all native, and it can cause issues
+     with the update_cursor call below */
+  if (_gdk_native_windows)
+    return;
+
   private = (GdkWindowObject *)window;
 
   if (display->pointer_info.window_under_pointer)
@@ -8792,7 +9136,10 @@ gdk_pointer_grab (GdkWindow *      window,
       !gdk_window_is_viewable (window))
     return GDK_GRAB_NOT_VIEWABLE;
 
-  native = gdk_window_get_toplevel (window);
+  if (_gdk_native_windows)
+    native = window;
+  else
+    native = gdk_window_get_toplevel (window);
   while (gdk_window_is_offscreen ((GdkWindowObject *)native))
     {
       native = gdk_offscreen_window_get_embedder (native);
@@ -8897,6 +9244,9 @@ _gdk_synthesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
   GdkWindow *toplevel;
   GdkWindowObject *toplevel_priv;
 
+  if (_gdk_native_windows)
+    return; /* We use the native crossing events if all native */
+
   display = gdk_drawable_get_display (changed_window);
 
   toplevel = get_event_toplevel (changed_window);
@@ -9369,6 +9719,42 @@ _gdk_windowing_got_event (GdkDisplay *display,
   if (!event_window)
     return;
 
+  if (_gdk_native_windows)
+    {
+      if (event->type == GDK_BUTTON_PRESS &&
+         _gdk_display_has_pointer_grab (display, serial) == NULL)
+       {
+         _gdk_display_add_pointer_grab  (display,
+                                         event_window,
+                                         event_window,
+                                         FALSE,
+                                         gdk_window_get_events (event_window),
+                                         serial,
+                                         gdk_event_get_time (event),
+                                         TRUE);
+         _gdk_display_pointer_grab_update (display,
+                                           serial);
+       }
+      if (event->type == GDK_BUTTON_RELEASE)
+       {
+         button_release_grab =
+           _gdk_display_has_pointer_grab (display, serial);
+         if (button_release_grab &&
+             button_release_grab->implicit &&
+             (event->button.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
+           {
+             button_release_grab->serial_end = serial;
+             button_release_grab->implicit_ungrab = TRUE;
+             _gdk_display_pointer_grab_update (display, serial);
+           }
+       }
+
+      if (event->type == GDK_BUTTON_PRESS)
+       _gdk_event_button_generate (display, event);
+
+      return;
+    }
+
   event_private = GDK_WINDOW_OBJECT (event_window);
 
 #ifdef DEBUG_WINDOW_PRINTING