]> Pileus Git - ~andy/gtk/commitdiff
Merge branch 'master' into client-side-windows
authorAlexander Larsson <alexl@redhat.com>
Wed, 17 Jun 2009 10:56:05 +0000 (12:56 +0200)
committerAlexander Larsson <alexl@redhat.com>
Wed, 17 Jun 2009 10:56:05 +0000 (12:56 +0200)
This updates client-side-windows to the the latest soname
change for easier testing.

Conflicts:
gdk/x11/gdkwindow-x11.c
tests/Makefile.am

77 files changed:
docs/reference/gdk/tmpl/events.sgml
docs/reference/gdk/tmpl/windows.sgml
gdk/Makefile.am
gdk/gdk.symbols
gdk/gdkcairo.c
gdk/gdkdisplay.c
gdk/gdkdisplay.h
gdk/gdkdraw.c
gdk/gdkdrawable.h
gdk/gdkevents.c
gdk/gdkevents.h
gdk/gdkgc.c
gdk/gdkinternals.h
gdk/gdkmarshalers.list
gdk/gdkoffscreenwindow.c [new file with mode: 0644]
gdk/gdkpango.c
gdk/gdkpixmap.c
gdk/gdkregion-generic.c
gdk/gdkregion.h
gdk/gdkscreen.h
gdk/gdkwindow.c
gdk/gdkwindow.h
gdk/gdkwindowimpl.h
gdk/quartz/GdkQuartzView.c
gdk/quartz/GdkQuartzView.h
gdk/quartz/GdkQuartzWindow.c
gdk/quartz/gdkdisplay-quartz.c
gdk/quartz/gdkdrawable-quartz.c
gdk/quartz/gdkevents-quartz.c
gdk/quartz/gdkgc-quartz.c
gdk/quartz/gdkgeometry-quartz.c
gdk/quartz/gdkinput.c
gdk/quartz/gdkpixmap-quartz.c
gdk/quartz/gdkprivate-quartz.h
gdk/quartz/gdkwindow-quartz.c
gdk/quartz/gdkwindow-quartz.h
gdk/win32/gdkdisplay-win32.c
gdk/win32/gdkdrawable-win32.c
gdk/win32/gdkdrawable-win32.h
gdk/win32/gdkevents-win32.c
gdk/win32/gdkgc-win32.c
gdk/win32/gdkgeometry-win32.c
gdk/win32/gdkinput-win32.c
gdk/win32/gdkmain-win32.c
gdk/win32/gdkpixmap-win32.c
gdk/win32/gdkprivate-win32.h
gdk/win32/gdkwindow-win32.c
gdk/win32/gdkwindow-win32.h
gdk/x11/gdkasync.c
gdk/x11/gdkasync.h
gdk/x11/gdkdisplay-x11.c
gdk/x11/gdkdisplay-x11.h
gdk/x11/gdkdnd-x11.c
gdk/x11/gdkdrawable-x11.c
gdk/x11/gdkevents-x11.c
gdk/x11/gdkgc-x11.c
gdk/x11/gdkgeometry-x11.c
gdk/x11/gdkinput-none.c
gdk/x11/gdkinput-x11.c
gdk/x11/gdkinput-xfree.c
gdk/x11/gdkinput.c
gdk/x11/gdkinputprivate.h
gdk/x11/gdkmain-x11.c
gdk/x11/gdkpixmap-x11.c
gdk/x11/gdkprivate-x11.h
gdk/x11/gdkproperty-x11.c
gdk/x11/gdkselection-x11.c
gdk/x11/gdkwindow-x11.c
gdk/x11/gdkwindow-x11.h
gtk/gtkcombobox.c
tests/Makefile.am
tests/flicker.c [new file with mode: 0644]
tests/gtkoffscreenbox.c [new file with mode: 0644]
tests/gtkoffscreenbox.h [new file with mode: 0644]
tests/testclientmessage.c
tests/testoffscreen.c [new file with mode: 0644]
tests/testwindows.c [new file with mode: 0644]

index b4dff1b5ef7d76ac91f782eb8d003389bb160f5b..2c39b5ef66e256fdd8e483dca242c56e716500af 100644 (file)
@@ -94,6 +94,7 @@ for the possible window states
   was added in 2.8.
 @GDK_DAMAGE: the content of the window has been changed. This event type
   was added in 2.14.
+@GDK_EVENT_LAST: 
 
 <!-- ##### ENUM GdkEventMask ##### -->
 <para>
index 195aabb6a4a9bad02422bf6efa49a8176e4f5f69..2ecae48d1ff93a627ab2945258af200b14abfc1c 100644 (file)
@@ -200,6 +200,7 @@ Describes the kind of window.
 @GDK_WINDOW_DIALOG: useless/deprecated compatibility type
 @GDK_WINDOW_TEMP: override redirect temporary window (used to implement #GtkMenu)
 @GDK_WINDOW_FOREIGN: foreign window (see gdk_window_foreign_new())
+@GDK_WINDOW_OFFSCREEN: 
 
 <!-- ##### ENUM GdkWindowClass ##### -->
 <para>
index 52a5bf04608f9e6b0d4ee3f270a292f4877ab456..c3c8afa4bc2750390071ff8a654c5cb75fe4a821 100644 (file)
@@ -120,6 +120,7 @@ gdk_c_sources =                 \
        gdkintl.h               \
        gdkkeys.c               \
        gdkkeyuni.c             \
+       gdkoffscreenwindow.c    \
        gdkpango.c              \
        gdkpixbuf-drawable.c    \
        gdkpixbuf-render.c      \
@@ -151,10 +152,10 @@ gdk_built_sources =                               \
 gdkincludedir = $(includedir)/gtk-2.0/gdk
 gdkinclude_HEADERS = $(gdk_public_h_sources) $(gdk_built_public_sources)
 
-# gdkmarshalers.c is not here because it is currently an empty file
 common_sources =                \
        $(gdk_c_sources)        \
        gdkenumtypes.c          \
+       gdkmarshalers.c         \
        gdkmarshalers.h
 
 libgdk_directfb_2_0_la_SOURCES = $(common_sources) 
index cfb54c202368b824f32cc21ee9f88efd5f8077ca..b94a4dc5fa3e964c8740f01dab40fb3134dde798 100644 (file)
@@ -69,9 +69,6 @@ gdk_get_use_xshm
 gdk_set_use_xshm
 #endif
 gdk_keyboard_grab
-gdk_keyboard_grab_info_libgtk_only
-gdk_pointer_grab
-gdk_pointer_grab_info_libgtk_only
 #endif
 #endif
 
@@ -85,6 +82,9 @@ gdk_pointer_is_grabbed
 gdk_pointer_ungrab
 gdk_event_send_client_message
 gdk_event_send_clientmessage_toall
+gdk_keyboard_grab_info_libgtk_only
+gdk_pointer_grab_info_libgtk_only
+gdk_display_pointer_is_grabbed
 #endif
 #endif
 
@@ -254,12 +254,6 @@ gdk_visual_type_get_type G_GNUC_CONST
 #endif
 #endif
 
-#if IN_HEADER(__GDK_PIXMAP_H__)
-#if IN_FILE(__GDK_PIXMAP_X11_C__)
-gdk_bitmap_create_from_data
-#endif
-#endif
-
 #if IN_HEADER(__GDK_FONT_H__)
 #if IN_FILE(__GDK_FONT_C__)
 #ifndef GDK_DISABLE_DEPRECATED
@@ -466,7 +460,6 @@ gdk_display_get_default_screen
 gdk_display_get_name
 gdk_display_get_n_screens
 gdk_display_get_screen
-gdk_display_pointer_is_grabbed
 gdk_display_pointer_ungrab
 gdk_display_keyboard_ungrab
 gdk_display_open
@@ -667,10 +660,15 @@ gdk_window_set_back_pixmap
 gdk_window_set_cursor
 gdk_window_get_geometry
 gdk_window_get_origin
+gdk_window_get_deskrelative_origin
 gdk_window_shape_combine_mask
 gdk_window_shape_combine_region
 gdk_window_set_child_shapes
 gdk_window_merge_child_shapes
+gdk_window_input_shape_combine_mask
+gdk_window_input_shape_combine_region
+gdk_window_set_child_input_shapes
+gdk_window_merge_child_input_shapes
 gdk_window_set_static_gravities
 gdk_window_reparent
 gdk_window_add_filter
@@ -716,6 +714,14 @@ gdk_window_set_user_data
 gdk_window_thaw_toplevel_updates_libgtk_only
 gdk_window_thaw_updates
 gdk_window_set_composited
+gdk_pointer_grab
+gdk_window_beep
+#endif
+#endif
+
+#if IN_HEADER(__GDK_WINDOW_H__)
+#if IN_FILE(__GDK_OFFSCREEN_WINDOW_C__)
+gdk_window_get_offscreen_pixmap
 #endif
 #endif
 
@@ -733,7 +739,6 @@ gdk_window_lookup
 gdk_window_lookup_for_display
 #ifndef GDK_DISABLE_DEPRECATED
 gdk_window_set_hints
-gdk_window_get_deskrelative_origin
 #endif
 gdk_window_get_type_hint
 gdk_window_set_type_hint
@@ -748,15 +753,12 @@ gdk_window_set_startup_id
 gdk_window_set_transient_for
 gdk_window_get_root_origin
 gdk_window_get_frame_extents
-gdk_window_input_shape_combine_mask
-gdk_window_input_shape_combine_region
 gdk_window_set_override_redirect
 gdk_window_set_accept_focus
 gdk_window_set_focus_on_map
 gdk_window_set_icon_list
 gdk_window_set_icon
 gdk_window_set_icon_name
-gdk_window_beep
 gdk_window_set_opacity
 gdk_window_iconify
 gdk_window_deiconify
@@ -773,8 +775,6 @@ gdk_window_set_group
 gdk_window_get_decorations
 gdk_window_set_decorations
 gdk_window_set_functions
-gdk_window_set_child_input_shapes
-gdk_window_merge_child_input_shapes
 gdk_window_begin_move_drag
 gdk_window_begin_resize_drag
 gdk_window_enable_synchronized_configure
@@ -925,23 +925,24 @@ gdk_pixbuf_render_to_drawable_alpha
 
 #if IN_HEADER(__GDK_PIXMAP_H__)
 #if IN_FILE(__GDK_PIXMAP_C__)
+gdk_bitmap_create_from_data
 gdk_pixmap_colormap_create_from_xpm
+gdk_pixmap_create_from_data
 gdk_pixmap_create_from_xpm
 gdk_pixmap_colormap_create_from_xpm_d
 gdk_pixmap_create_from_xpm_d
 gdk_pixmap_get_type G_GNUC_CONST
+gdk_pixmap_new
 #endif
 #endif
 
 #if IN_HEADER(__GDK_PIXMAP_H__)
 #if IN_FILE(__GDK_PIXMAP_X11_C__)
-gdk_pixmap_create_from_data
 gdk_pixmap_foreign_new
 gdk_pixmap_foreign_new_for_display
 gdk_pixmap_foreign_new_for_screen
 gdk_pixmap_lookup
 gdk_pixmap_lookup_for_display
-gdk_pixmap_new
 #endif
 #endif
 
index 6e83f53a375f30c8786fc59cbbc67077cf104cb3..9d3ce2d6491407830ab332738b8a7d96f100951e 100644 (file)
@@ -50,6 +50,10 @@ gdk_cairo_create (GdkDrawable *drawable)
 
   surface = _gdk_drawable_ref_cairo_surface (drawable);
   cr = cairo_create (surface);
+
+  if (GDK_DRAWABLE_GET_CLASS (drawable)->set_cairo_clip)
+    GDK_DRAWABLE_GET_CLASS (drawable)->set_cairo_clip (drawable, cr);
+    
   cairo_surface_destroy (surface);
 
   return cr;
index 9417c4e9475b2bb7d6846fbd2db72e59b3cd3350..e69d07ab934aca9fb656039773ce143d0a98ffd3 100644 (file)
  */
 
 #include "config.h"
+#include <math.h>
 #include <glib.h>
 #include "gdk.h"               /* gdk_event_send_client_message() */
 #include "gdkdisplay.h"
+#include "gdkwindowimpl.h"
 #include "gdkinternals.h"
 #include "gdkmarshalers.h"
 #include "gdkscreen.h"
@@ -60,6 +62,14 @@ static GdkWindow* singlehead_default_window_get_pointer (GdkWindow       *window
 static GdkWindow* singlehead_default_window_at_pointer  (GdkScreen       *screen,
                                                         gint            *win_x,
                                                         gint            *win_y);
+static GdkWindow *gdk_window_real_window_get_pointer     (GdkDisplay       *display,
+                                                          GdkWindow        *window,
+                                                          gint             *x,
+                                                          gint             *y,
+                                                          GdkModifierType  *mask);
+static GdkWindow *gdk_display_real_get_window_at_pointer (GdkDisplay       *display,
+                                                          gint             *win_x,
+                                                          gint             *win_y);
 
 static guint signals[LAST_SIGNAL] = { 0 };
 
@@ -67,8 +77,8 @@ static char *gdk_sm_client_id;
 
 static const GdkDisplayPointerHooks default_pointer_hooks = {
   _gdk_windowing_get_pointer,
-  _gdk_windowing_window_get_pointer,
-  _gdk_windowing_window_at_pointer
+  gdk_window_real_window_get_pointer,
+  gdk_display_real_get_window_at_pointer
 };
 
 static const GdkDisplayPointerHooks singlehead_pointer_hooks = {
@@ -434,6 +444,25 @@ _gdk_get_sm_client_id (void)
   return gdk_sm_client_id;
 }
 
+void
+_gdk_display_enable_motion_hints (GdkDisplay *display)
+{
+  gulong serial;
+  
+  if (display->pointer_info.motion_hint_serial != 0)
+    {
+      serial = _gdk_windowing_window_get_next_serial (display);
+      /* We might not actually generate the next request, so
+        make sure this triggers always, this may cause it to
+        trigger slightly to early, but this is just a hint
+        anyway. */
+      if (serial > 0)
+       serial--;
+      if (serial < display->pointer_info.motion_hint_serial)
+       display->pointer_info.motion_hint_serial = serial;
+    }
+}
+
 /**
  * gdk_display_get_pointer:
  * @display: a #GdkDisplay
@@ -473,6 +502,68 @@ gdk_display_get_pointer (GdkDisplay      *display,
     *mask = tmp_mask;
 }
 
+static GdkWindow *
+gdk_display_real_get_window_at_pointer (GdkDisplay *display,
+                                        gint       *win_x,
+                                        gint       *win_y)
+{
+  GdkWindow *window;
+  gint x, y;
+
+  window = _gdk_windowing_window_at_pointer (display, &x, &y, NULL);
+
+  /* This might need corrections, as the native window returned
+     may contain client side children */
+  if (window)
+    {
+      double xx, yy;
+
+      window = _gdk_window_find_descendant_at (window,
+                                              x, y,
+                                              &xx, &yy);
+      x = floor (xx + 0.5);
+      y = floor (yy + 0.5);
+    }
+
+  *win_x = x;
+  *win_y = y;
+
+  return window;
+}
+
+static GdkWindow *
+gdk_window_real_window_get_pointer (GdkDisplay       *display,
+                                    GdkWindow        *window,
+                                    gint             *x,
+                                    gint             *y,
+                                    GdkModifierType  *mask)
+{
+  GdkWindowObject *private;
+  gint tmpx, tmpy;
+  GdkModifierType tmp_mask;
+  gboolean normal_child;
+
+  private = (GdkWindowObject *) window;
+
+  normal_child = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_pointer (window,
+                                                                        &tmpx, &tmpy,
+                                                                        &tmp_mask);
+  /* We got the coords on the impl, conver to the window */
+  tmpx -= private->abs_x;
+  tmpy -= private->abs_y;
+
+  if (x)
+    *x = tmpx;
+  if (y)
+    *y = tmpy;
+  if (mask)
+    *mask = tmp_mask;
+
+  if (normal_child)
+    return _gdk_window_find_child_at (window, tmpx, tmpy);
+  return NULL;
+}
+
 /**
  * gdk_display_get_window_at_pointer:
  * @display: a #GdkDisplay
@@ -586,8 +677,8 @@ singlehead_default_window_get_pointer (GdkWindow       *window,
                                       gint            *y,
                                       GdkModifierType *mask)
 {
-  return _gdk_windowing_window_get_pointer (gdk_drawable_get_display (window),
-                                           window, x, y, mask);
+  return gdk_window_real_window_get_pointer (gdk_drawable_get_display (window),
+                                             window, x, y, mask);
 }
 
 static GdkWindow*
@@ -595,8 +686,8 @@ singlehead_default_window_at_pointer  (GdkScreen       *screen,
                                       gint            *win_x,
                                       gint            *win_y)
 {
-  return _gdk_windowing_window_at_pointer (gdk_screen_get_display (screen),
-                                          win_x, win_y);
+  return gdk_display_real_get_window_at_pointer (gdk_screen_get_display (screen),
+                                                 win_x, win_y);
 }
 
 /**
@@ -632,5 +723,587 @@ gdk_set_pointer_hooks (const GdkPointerHooks *new_hooks)
   return (GdkPointerHooks *)result;
 }
 
+static void
+generate_grab_broken_event (GdkWindow *window,
+                           gboolean   keyboard,
+                           gboolean   implicit,
+                           GdkWindow *grab_window)
+{
+  g_return_if_fail (window != NULL);
+
+  if (!GDK_WINDOW_DESTROYED (window))
+    {
+      GdkEvent event;
+      event.type = GDK_GRAB_BROKEN;
+      event.grab_broken.window = window;
+      event.grab_broken.send_event = 0;
+      event.grab_broken.keyboard = keyboard;
+      event.grab_broken.implicit = implicit;
+      event.grab_broken.grab_window = grab_window;
+      gdk_event_put (&event);
+    }
+}
+
+GdkPointerGrabInfo *
+_gdk_display_get_last_pointer_grab (GdkDisplay *display)
+{
+  GList *l;
+
+  l = display->pointer_grabs;
+
+  if (l == NULL)
+    return NULL;
+
+  while (l->next != NULL)
+    l = l->next;
+
+  return (GdkPointerGrabInfo *)l->data;
+}
+
+
+GdkPointerGrabInfo *
+_gdk_display_add_pointer_grab (GdkDisplay *display,
+                              GdkWindow *window,
+                              GdkWindow *native_window,
+                              gboolean owner_events,
+                              GdkEventMask event_mask,
+                              unsigned long serial_start,
+                              guint32 time,
+                              gboolean implicit)
+{
+  GdkPointerGrabInfo *info, *other_info;
+  GList *l;
+
+  info = g_new0 (GdkPointerGrabInfo, 1);
+
+  info->window = g_object_ref (window);
+  info->native_window = g_object_ref (native_window);
+  info->serial_start = serial_start;
+  info->serial_end = G_MAXULONG;
+  info->owner_events = owner_events;
+  info->event_mask = event_mask;
+  info->time = time;
+  info->implicit = implicit;
+
+  /* Find the first grab that has a larger start time (if any) and insert
+   * before that. I.E we insert after already existing grabs with same
+   * start time */
+  for (l = display->pointer_grabs; l != NULL; l = l->next)
+    {
+      other_info = l->data;
+      
+      if (info->serial_start < other_info->serial_start)
+       break;
+    }
+  display->pointer_grabs =
+    g_list_insert_before (display->pointer_grabs, l, info);
+
+  /* Make sure the new grab end before next grab */
+  if (l)
+    {
+      other_info = l->data;
+      info->serial_end = other_info->serial_start;
+    }
+  
+  /* Find any previous grab and update its end time */
+  l = g_list_find  (display->pointer_grabs, info);
+  l = l->prev;
+  if (l)
+    {
+      other_info = l->data;
+      other_info->serial_end = serial_start;
+    }
+
+  return info;
+}
+
+static void
+free_pointer_grab (GdkPointerGrabInfo *info)
+{
+  g_object_unref (info->window);
+  g_object_unref (info->native_window);
+  g_free (info);
+}
+
+/* _gdk_syntesize_crossing_events only works inside one toplevel.
+   This function splits things into two calls if needed, converting the
+   coordinates to the right toplevel */
+static void
+synthesize_crossing_events (GdkDisplay *display,
+                           GdkWindow *src_window,
+                           GdkWindow *dest_window,
+                           GdkCrossingMode crossing_mode,
+                           guint32 time,
+                           gulong serial)
+{
+  GdkWindow *src_toplevel, *dest_toplevel;
+  GdkModifierType state;
+  int x, y;
+  
+  if (src_window)
+    src_toplevel = gdk_window_get_toplevel (src_window);
+  else
+    src_toplevel = NULL;
+  if (dest_window)
+    dest_toplevel = gdk_window_get_toplevel (dest_window);
+  else
+    dest_toplevel = NULL;
+
+  if (src_toplevel == NULL && dest_toplevel == NULL)
+    return;
+  
+  if (src_toplevel == NULL ||
+      src_toplevel == dest_toplevel)
+    {
+      /* Same toplevels */
+      gdk_window_get_pointer (dest_toplevel,
+                             &x, &y, &state);
+      _gdk_syntesize_crossing_events (display,
+                                     src_window,
+                                     dest_window,
+                                     crossing_mode,
+                                     x, y, state,
+                                     time,
+                                     NULL,
+                                     serial);
+    }
+  else if (dest_toplevel == NULL)
+    {
+      gdk_window_get_pointer (src_toplevel,
+                             &x, &y, &state);
+      _gdk_syntesize_crossing_events (display,
+                                     src_window,
+                                     NULL,
+                                     crossing_mode,
+                                     x, y, state,
+                                     time,
+                                     NULL,
+                                     serial);
+    }
+  else
+    {
+      /* Different toplevels */
+      gdk_window_get_pointer (src_toplevel,
+                             &x, &y, &state);
+      _gdk_syntesize_crossing_events (display,
+                                     src_window,
+                                     NULL,
+                                     crossing_mode,
+                                     x, y, state,
+                                     time,
+                                     NULL,
+                                     serial);
+      gdk_window_get_pointer (dest_toplevel,
+                             &x, &y, &state);
+      _gdk_syntesize_crossing_events (display,
+                                     NULL,
+                                     dest_window,
+                                     crossing_mode,
+                                     x, y, state,
+                                     time,
+                                     NULL,
+                                     serial);
+    }
+}
+
+static void
+switch_to_pointer_grab (GdkDisplay *display,
+                       GdkPointerGrabInfo *grab,
+                       GdkPointerGrabInfo *last_grab,
+                       guint32 time,
+                       gulong serial)
+{
+  GdkWindow *src_window, *pointer_window;
+  GdkWindowObject *w;
+  GList *old_grabs;
+  GdkModifierType state;
+  int x, y;
+
+  /* Temporarily unset pointer to make sure we send the crossing events below */
+  old_grabs = display->pointer_grabs;
+  display->pointer_grabs = NULL;
+  
+  if (grab)
+    {
+      /* New grab is in effect */
+      
+      /* We need to generate crossing events for the grab.
+       * However, there are never any crossing events for implicit grabs
+       * TODO: ... Actually, this could happen if the pointer window
+       *           doesn't have button mask so a parent gets the event... 
+       */
+      if (!grab->implicit)
+       {
+         /* We send GRAB crossing events from the window under the pointer to the
+            grab window. Except if there is an old grab then we start from that */
+         if (last_grab)
+           src_window = last_grab->window;
+         else
+           src_window = display->pointer_info.window_under_pointer;
+         
+         if (src_window != grab->window)
+           {
+             synthesize_crossing_events (display,
+                                         src_window, grab->window,
+                                         GDK_CROSSING_GRAB, time, serial);
+           }
+         
+         /* !owner_event Grabbing a window that we're not inside, current status is
+            now NULL (i.e. outside grabbed window) */
+         if (!grab->owner_events && display->pointer_info.window_under_pointer != grab->window)
+           _gdk_display_set_window_under_pointer (display, NULL);
+       }
+  
+      grab->activated = TRUE;
+    }
+  else if (last_grab)
+    {
+      pointer_window = _gdk_windowing_window_at_pointer (display,  &x, &y, &state);
+      if (pointer_window != NULL &&
+         (GDK_WINDOW_DESTROYED (pointer_window) ||
+          GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_ROOT ||
+          GDK_WINDOW_TYPE (pointer_window) == GDK_WINDOW_FOREIGN))
+       pointer_window = NULL;
+      
+      /* We force checked what window we're in, so we need to
+       * update the toplevel_under_pointer info, as that won't get told of
+       * this change.
+       */
+      if (display->pointer_info.toplevel_under_pointer)
+       g_object_unref (display->pointer_info.toplevel_under_pointer);
+      display->pointer_info.toplevel_under_pointer = NULL;
+      
+      if (pointer_window)
+       {
+         /* Convert to toplevel */
+         w = (GdkWindowObject *)pointer_window;
+         while (/*w->parent != NULL && */
+                w->parent->window_type != GDK_WINDOW_ROOT)
+           {
+             x += w->x;
+             y += w->y;
+             w = w->parent;
+           }
+         
+         /* w is now toplevel and x,y in toplevel coords */
+         display->pointer_info.toplevel_under_pointer = g_object_ref (w);
+         
+         /* Find (possibly virtual) child window */
+         pointer_window =
+           _gdk_window_find_descendant_at ((GdkWindow *)w,
+                                           x, y,
+                                           NULL, NULL);
+       }
+
+      if (pointer_window != last_grab->window)
+       synthesize_crossing_events (display,
+                                   last_grab->window, pointer_window,
+                                   GDK_CROSSING_UNGRAB, time, serial);
+      
+      /* We're now ungrabbed, update the window_under_pointer */
+      _gdk_display_set_window_under_pointer (display, pointer_window);
+      
+      if (last_grab->implicit_ungrab)
+       generate_grab_broken_event (last_grab->window,
+                                   FALSE, TRUE, 
+                                   NULL);
+    }
+  
+  display->pointer_grabs = old_grabs;
+
+}
+
+void
+_gdk_display_pointer_grab_update (GdkDisplay *display,
+                                 gulong current_serial)
+{
+  GdkPointerGrabInfo *current_grab, *next_grab;
+  guint32 time;
+  
+  time = display->last_event_time;
+
+  while (display->pointer_grabs != NULL)
+    {
+      current_grab = display->pointer_grabs->data;
+
+      if (current_grab->serial_start > current_serial)
+       return; /* Hasn't started yet */
+      
+      if (current_grab->serial_end > current_serial ||
+         (current_grab->serial_end == current_serial &&
+          current_grab->grab_one_pointer_release_event))
+       {
+         /* This one hasn't ended yet.
+            its the currently active one or scheduled to be active */
+
+         if (!current_grab->activated)
+           switch_to_pointer_grab (display, current_grab, NULL, time, current_serial);
+         
+         break;
+       }
+
+
+      next_grab = NULL;
+      if (display->pointer_grabs->next)
+       {
+         /* This is the next active grab */
+         next_grab = display->pointer_grabs->next->data;
+         
+         if (next_grab->serial_start > current_serial)
+           next_grab = NULL; /* Actually its not yet active */
+       }
+
+      if (next_grab == NULL ||
+         current_grab->window != next_grab->window)
+       generate_grab_broken_event (GDK_WINDOW (current_grab->window),
+                                   FALSE, current_grab->implicit,
+                                   next_grab? next_grab->window : NULL);
+
+
+      /* Remove old grab */
+      display->pointer_grabs =
+       g_list_delete_link (display->pointer_grabs,
+                           display->pointer_grabs);
+      
+      switch_to_pointer_grab (display,
+                             next_grab, current_grab,
+                             time, current_serial);
+      
+      free_pointer_grab (current_grab);
+    }
+}
+
+static GdkWindow *
+gdk_window_get_offscreen_parent (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindow *res;
+
+  res = NULL;
+  g_signal_emit_by_name (private->impl_window,
+                        "get-offscreen-parent",
+                        &res);
+
+  return res;
+}
+
+/* Gets the toplevel for a window as used for events,
+   i.e. including offscreen parents */
+static GdkWindowObject *
+get_event_parent (GdkWindowObject *window)
+{
+  if (window->window_type ==GDK_WINDOW_OFFSCREEN)
+    return (GdkWindowObject *)gdk_window_get_offscreen_parent ((GdkWindow *)window);
+  else
+    return window->parent;
+}
+
+is_event_parent_of (GdkWindow *parent,
+                   GdkWindow *child)
+{
+  GdkWindow *w;
+
+  w = child;
+  while (w != NULL)
+    {
+      if (w == parent)
+       return TRUE;
+
+      w = (GdkWindow *)get_event_parent ((GdkWindowObject *)w);
+    }
+
+  return FALSE;
+}
+
+static GList *
+find_pointer_grab (GdkDisplay *display,
+                  gulong serial)
+{
+  GdkPointerGrabInfo *grab;
+  GList *l;
+
+  for (l = display->pointer_grabs; l != NULL; l = l->next)
+    {
+      grab = l->data;
+
+      if (serial >= grab->serial_start && serial < grab->serial_end)
+       return l;
+    }
+  
+  return NULL;
+}
+
+
+
+GdkPointerGrabInfo *
+_gdk_display_has_pointer_grab (GdkDisplay *display,
+                              gulong serial)
+{
+  GList *l;
+
+  l = find_pointer_grab (display, serial);
+  if (l)
+    return l->data;
+  
+  return NULL;
+}
+
+/* Returns true if last grab was ended */
+gboolean
+_gdk_display_end_pointer_grab (GdkDisplay *display,
+                              gulong serial,
+                              GdkWindow *if_child,
+                              gboolean implicit)
+{
+  GdkPointerGrabInfo *grab;
+  GList *l;
+
+  l = find_pointer_grab (display, serial);
+  
+  if (l == NULL)
+    return FALSE;
+
+  grab = l->data;
+  if (grab &&
+      (if_child == NULL ||
+       is_event_parent_of (grab->window, if_child)))
+    {
+      grab->serial_end = serial;
+      grab->implicit_ungrab = implicit;
+      return l->next == NULL;
+    }
+  
+  return FALSE;
+}
+
+void
+_gdk_display_set_has_keyboard_grab (GdkDisplay *display,
+                                   GdkWindow *window,
+                                   GdkWindow *native_window,
+                                   gboolean owner_events,
+                                   unsigned long serial,
+                                   guint32 time)
+{
+  if (display->keyboard_grab.window != NULL &&
+      display->keyboard_grab.window != window)
+    generate_grab_broken_event (display->keyboard_grab.window,
+                               TRUE, FALSE, window);
+  
+  display->keyboard_grab.window = window;
+  display->keyboard_grab.native_window = native_window;
+  display->keyboard_grab.owner_events = owner_events;
+  display->keyboard_grab.serial = serial;
+  display->keyboard_grab.time = time;      
+}
+
+void
+_gdk_display_unset_has_keyboard_grab (GdkDisplay *display,
+                                     gboolean implicit)
+{
+  if (implicit)
+    generate_grab_broken_event (display->keyboard_grab.window,
+                               TRUE, FALSE, NULL);
+  display->keyboard_grab.window = NULL;  
+}
+
+/**
+ * gdk_keyboard_grab_info_libgtk_only:
+ * @display: the display for which to get the grab information
+ * @grab_window: location to store current grab window
+ * @owner_events: location to store boolean indicating whether
+ *   the @owner_events flag to gdk_keyboard_grab() was %TRUE.
+ * 
+ * Determines information about the current keyboard grab.
+ * This is not public API and must not be used by applications.
+ * 
+ * Return value: %TRUE if this application currently has the
+ *  keyboard grabbed.
+ **/
+gboolean
+gdk_keyboard_grab_info_libgtk_only (GdkDisplay *display,
+                                   GdkWindow **grab_window,
+                                   gboolean   *owner_events)
+{
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
+
+  if (display->keyboard_grab.window)
+    {
+      if (grab_window)
+        *grab_window = display->keyboard_grab.window;
+      if (owner_events)
+        *owner_events = display->keyboard_grab.owner_events;
+
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+/**
+ * gdk_pointer_grab_info_libgtk_only:
+ * @display: the #GdkDisplay for which to get the grab information
+ * @grab_window: location to store current grab window
+ * @owner_events: location to store boolean indicating whether
+ *   the @owner_events flag to gdk_pointer_grab() was %TRUE.
+ * 
+ * Determines information about the current pointer grab.
+ * This is not public API and must not be used by applications.
+ * 
+ * Return value: %TRUE if this application currently has the
+ *  pointer grabbed.
+ **/
+gboolean
+gdk_pointer_grab_info_libgtk_only (GdkDisplay *display,
+                                  GdkWindow **grab_window,
+                                  gboolean   *owner_events)
+{
+  GdkPointerGrabInfo *info;
+  
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), FALSE);
+
+  /* What we're interested in is the steady state (ie last grab),
+     because we're interested e.g. if we grabbed so that we
+     can ungrab, even if our grab is not active just yet. */
+  info = _gdk_display_get_last_pointer_grab (display);
+  
+  if (info)
+    {
+      if (grab_window)
+        *grab_window = info->window;
+      if (owner_events)
+        *owner_events = info->owner_events;
+
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+
+/**
+ * gdk_display_pointer_is_grabbed:
+ * @display: a #GdkDisplay
+ *
+ * Test if the pointer is grabbed.
+ *
+ * Returns: %TRUE if an active X pointer grab is in effect
+ *
+ * Since: 2.2
+ */
+gboolean
+gdk_display_pointer_is_grabbed (GdkDisplay *display)
+{
+  GdkPointerGrabInfo *info;
+  
+  g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
+
+  /* What we're interested in is the steady state (ie last grab),
+     because we're interested e.g. if we grabbed so that we
+     can ungrab, even if our grab is not active just yet. */
+  info = _gdk_display_get_last_pointer_grab (display);
+  
+  return (info && !info->implicit);
+}
+
 #define __GDK_DISPLAY_C__
 #include "gdkaliasdef.c"
index 04bf1831bbfc48c817d705989f2ee0fa3b031fc3..2838d44a02752bec47186c50d8638b9803bb174c 100644 (file)
@@ -43,6 +43,33 @@ typedef struct _GdkDisplayPointerHooks GdkDisplayPointerHooks;
 #define GDK_IS_DISPLAY_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_DISPLAY))
 #define GDK_DISPLAY_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_DISPLAY, GdkDisplayClass))
 
+/* Tracks information about the keyboard grab on this display */
+typedef struct
+{
+  GdkWindow *window;
+  GdkWindow *native_window;
+  gulong serial;
+  gboolean owner_events;
+  guint32 time;
+} GdkKeyboardGrabInfo;
+
+/* Tracks information about which window and position the pointer last was in.
+ * This is useful when we need to synthesize events later.
+ * Note that we track toplevel_under_pointer using enter/leave events,
+ * so in the case of a grab, either with owner_events==FALSE or with the
+ * pointer in no clients window the x/y coordinates may actually be outside
+ * the window.
+ */
+typedef struct
+{
+  GdkWindow *toplevel_under_pointer; /* The toplevel window with mouse inside, tracked via native events */
+  GdkWindow *window_under_pointer; /* The window that last got sent a normal enter event */
+  gdouble toplevel_x, toplevel_y; 
+  guint32 state;
+  guint32 button;
+  gulong motion_hint_serial; /* 0 == didn't deliver hinted motion event */
+} GdkPointerWindowInfo;
+
 struct _GdkDisplay
 {
   GObject parent_instance;
@@ -64,10 +91,18 @@ struct _GdkDisplay
   const GdkDisplayPointerHooks *pointer_hooks; /* Current hooks for querying pointer */
   
   guint closed : 1;            /* Whether this display has been closed */
+  guint ignore_core_events : 1; /* Don't send core motion and button event */
 
   guint double_click_distance; /* Maximum distance between clicks in pixels */
   gint button_x[2];             /* The last 2 button click positions. */
   gint button_y[2];
+
+  GList *pointer_grabs;
+  GdkKeyboardGrabInfo keyboard_grab;
+  GdkPointerWindowInfo pointer_info;
+
+  /* Last reported event time from server */
+  guint32 last_event_time;
 };
 
 struct _GdkDisplayClass
index 81e6e08390a500a25b160d74f730669e1d2b4f69..321b883cb32dd7084865290e4fe0cd958010a623 100644 (file)
@@ -150,7 +150,8 @@ gdk_drawable_get_size (GdkDrawable *drawable,
 {
   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
 
-  GDK_DRAWABLE_GET_CLASS (drawable)->get_size (drawable, width, height);  
+  if (GDK_DRAWABLE_GET_CLASS (drawable)->get_size != NULL)
+    GDK_DRAWABLE_GET_CLASS (drawable)->get_size (drawable, width, height);  
 }
 
 /**
@@ -623,7 +624,7 @@ gdk_draw_drawable (GdkDrawable *drawable,
                   gint         width,
                   gint         height)
 {
-  GdkDrawable *composite;
+  GdkDrawable *composite, *composite_impl;
   gint composite_x_offset = 0;
   gint composite_y_offset = 0;
 
@@ -652,13 +653,28 @@ gdk_draw_drawable (GdkDrawable *drawable,
                                                           &composite_x_offset,
                                                           &composite_y_offset);
 
-  
-  GDK_DRAWABLE_GET_CLASS (drawable)->draw_drawable (drawable, gc, composite,
+  /* The draw_drawable call below is will recurse into gdk_draw_drawable again,
+   * specifying the right impl for the destination. This means the composite
+   * we got here will be fed to get_composite_drawable again, which is a problem
+   * for window as that causes double the composite offset. Avoid this by passing
+   * in the impl directly.
+   */
+  if (GDK_IS_WINDOW (composite))
+    composite_impl = GDK_WINDOW_OBJECT (src)->impl;
+  else
+    composite_impl = composite;
+
+  /* TODO: For non-native windows this may copy stuff from other overlapping
+     windows. We should clip that and (for windows with bg != None) clear that
+     area in the destination instead. */
+
+  GDK_DRAWABLE_GET_CLASS (drawable)->draw_drawable (drawable, gc,
+                                                   composite_impl, src,
                                                     xsrc - composite_x_offset,
                                                     ysrc - composite_y_offset,
                                                     xdest, ydest,
                                                     width, height);
-  
+
   g_object_unref (composite);
 }
 
@@ -871,7 +887,7 @@ real_draw_glyphs (GdkDrawable       *drawable,
   cairo_t *cr;
 
   cr = gdk_cairo_create (drawable);
-  _gdk_gc_update_context (gc, cr, NULL, NULL, TRUE);
+  _gdk_gc_update_context (gc, cr, NULL, NULL, TRUE, drawable);
 
   if (matrix)
     {
@@ -995,7 +1011,7 @@ gdk_draw_trapezoids (GdkDrawable        *drawable,
   g_return_if_fail (n_trapezoids == 0 || trapezoids != NULL);
 
   cr = gdk_cairo_create (drawable);
-  _gdk_gc_update_context (gc, cr, NULL, NULL, TRUE);
+  _gdk_gc_update_context (gc, cr, NULL, NULL, TRUE, drawable);
   
   for (i = 0; i < n_trapezoids; i++)
     {
@@ -1185,7 +1201,7 @@ gdk_drawable_real_get_image (GdkDrawable     *drawable,
   return gdk_drawable_copy_to_image (drawable, NULL, x, y, 0, 0, width, height);
 }
 
-static GdkDrawable*
+static GdkDrawable *
 gdk_drawable_real_get_composite_drawable (GdkDrawable *drawable,
                                           gint         x,
                                           gint         y,
@@ -1771,5 +1787,81 @@ _gdk_drawable_get_scratch_gc (GdkDrawable *drawable,
     }
 }
 
+/**
+ * _gdk_drawable_get_subwindow_scratch_gc:
+ * @drawable: A #GdkDrawable
+ * 
+ * Returns a #GdkGC suitable for drawing on @drawable. The #GdkGC has
+ * the standard values for @drawable, except for the graphics_exposures
+ * field which is %TRUE and the subwindow mode which is %GDK_INCLUDE_INFERIORS.
+ *
+ * The foreground color of the returned #GdkGC is undefined. The #GdkGC
+ * must not be altered in any way, except to change its foreground color.
+ * 
+ * Return value: A #GdkGC suitable for drawing on @drawable
+ * 
+ * Since: 2.18
+ **/
+GdkGC *
+_gdk_drawable_get_subwindow_scratch_gc (GdkDrawable *drawable)
+{
+  GdkScreen *screen;
+  gint depth;
+
+  g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
+
+  screen = gdk_drawable_get_screen (drawable);
+
+  g_return_val_if_fail (!screen->closed, NULL);
+
+  depth = gdk_drawable_get_depth (drawable) - 1;
+
+  if (!screen->subwindow_gcs[depth])
+    {
+      GdkGCValues values;
+      GdkGCValuesMask mask;
+      
+      values.graphics_exposures = TRUE;
+      values.subwindow_mode = GDK_INCLUDE_INFERIORS;
+      mask = GDK_GC_EXPOSURES | GDK_GC_SUBWINDOW;  
+      
+      screen->subwindow_gcs[depth] =
+       gdk_gc_new_with_values (drawable, &values, mask);
+    }
+  
+  return screen->subwindow_gcs[depth];
+}
+
+
+/**
+ * _gdk_drawable_get_source_drawable:
+ * @drawable: a #GdkDrawable
+ *
+ * Returns a drawable for the passed @drawable that is guaranteed to be
+ * usable to create a pixmap (e.g.: not an offscreen window).
+ *
+ * Since: 2.16
+ */
+GdkDrawable *
+_gdk_drawable_get_source_drawable (GdkDrawable *drawable)
+{
+  g_return_val_if_fail (GDK_IS_DRAWABLE (drawable), NULL);
+
+  if (GDK_DRAWABLE_GET_CLASS (drawable)->get_source_drawable)
+    return GDK_DRAWABLE_GET_CLASS (drawable)->get_source_drawable (drawable);
+
+  return drawable;
+}
+
+cairo_surface_t *
+_gdk_drawable_create_cairo_surface (GdkDrawable *drawable,
+                                   int width,
+                                   int height)
+{
+  return GDK_DRAWABLE_GET_CLASS (drawable)->create_cairo_surface (drawable,
+                                                                 width, height);
+}
+
+
 #define __GDK_DRAW_C__
 #include "gdkaliasdef.c"
index 508bf86fcfd2027816c687c524dd2c471a566dd1..1d8d69471d7c93af4a909f504ca39691e8350072 100644 (file)
@@ -100,6 +100,7 @@ struct _GdkDrawableClass
   void (*draw_drawable)  (GdkDrawable  *drawable,
                          GdkGC        *gc,
                          GdkDrawable  *src,
+                         GdkDrawable  *original_src,
                          gint          xsrc,
                          gint          ysrc,
                          gint          xdest,
@@ -200,10 +201,16 @@ struct _GdkDrawableClass
 
   cairo_surface_t *(*ref_cairo_surface) (GdkDrawable *drawable);
 
+  GdkDrawable *(*get_source_drawable) (GdkDrawable *drawable);
+
+  void         (*set_cairo_clip)      (GdkDrawable *drawable,
+                                      cairo_t *cr);
+
+  cairo_surface_t * (*create_cairo_surface) (GdkDrawable *drawable,
+                                            int width,
+                                            int height);
+
   /* Padding for future expansion */
-  void         (*_gdk_reserved4)  (void);
-  void         (*_gdk_reserved5)  (void);
-  void         (*_gdk_reserved6)  (void);
   void         (*_gdk_reserved7)  (void);
   void         (*_gdk_reserved9)  (void);
   void         (*_gdk_reserved10) (void);
index 24a29a1fd96e8b560f380ed4175e7cae3cf2707b..3af4195cc93b6e28159eb179faa89eec283cda80 100644 (file)
@@ -120,6 +120,63 @@ _gdk_event_queue_append (GdkDisplay *display,
   return display->queued_tail;
 }
 
+/**
+ * _gdk_event_queue_insert_after:
+ * @display: a #GdkDisplay
+ * @sibling: Append after this event.
+ * @event: Event to append.
+ *
+ * Appends an event after the specified event, or if it isn't in
+ * the queue, onto the tail of the event queue.
+ *
+ * Returns: the newly appended list node.
+ *
+ * Since: 2.16
+ */
+GList*
+_gdk_event_queue_insert_after (GdkDisplay *display,
+                               GdkEvent   *sibling,
+                               GdkEvent   *event)
+{
+  GList *prev = g_list_find (display->queued_events, sibling);
+  if (prev && prev->next)
+    {
+      display->queued_events = g_list_insert_before (display->queued_events, prev->next, event);
+      return prev->next;
+    }
+  else
+    return _gdk_event_queue_append (display, event);
+}
+
+/**
+ * _gdk_event_queue_insert_after:
+ * @display: a #GdkDisplay
+ * @sibling: Append after this event.
+ * @event: Event to append.
+ *
+ * Appends an event before the specified event, or if it isn't in
+ * the queue, onto the tail of the event queue.
+ *
+ * Returns: the newly appended list node.
+ *
+ * Since: 2.16
+ */
+GList*
+_gdk_event_queue_insert_before (GdkDisplay *display,
+                               GdkEvent   *sibling,
+                               GdkEvent   *event)
+{
+  GList *next = g_list_find (display->queued_events, sibling);
+  if (next)
+    {
+      display->queued_events = g_list_insert_before (display->queued_events, next, event);
+      return next->prev;
+    }
+  else
+    return _gdk_event_queue_append (display, event);
+}
+
+
 /**
  * _gdk_event_queue_remove_link:
  * @display: a #GdkDisplay
@@ -575,6 +632,7 @@ gdk_event_get_time (const GdkEvent *event)
       case GDK_SETTING:
       case GDK_OWNER_CHANGE:
       case GDK_GRAB_BROKEN:
+      case GDK_EVENT_LAST:
         /* return current time */
         break;
       }
@@ -653,6 +711,7 @@ gdk_event_get_state (const GdkEvent        *event,
       case GDK_SETTING:
       case GDK_OWNER_CHANGE:
       case GDK_GRAB_BROKEN:
+      case GDK_EVENT_LAST:
         /* no state field */
         break;
       }
@@ -884,9 +943,17 @@ gdk_event_get_axis (const GdkEvent *event,
 void
 gdk_event_request_motions (const GdkEventMotion *event)
 {
+  GdkDisplay *display;
+  
   g_return_if_fail (event != NULL);
+  
   if (event->type == GDK_MOTION_NOTIFY && event->is_hint)
-    gdk_device_get_state (event->device, event->window, NULL, NULL);
+    {
+      gdk_device_get_state (event->device, event->window, NULL, NULL);
+      
+      display = gdk_drawable_get_display (event->window);
+      _gdk_display_enable_motion_hints (display);
+    }
 }
 
 /**
@@ -1101,13 +1168,16 @@ gdk_synthesize_click (GdkDisplay *display,
                      gint        nclicks)
 {
   GdkEvent temp_event;
+  GdkEvent *event_copy;
+  GList *link;
   
   g_return_if_fail (event != NULL);
   
   temp_event = *event;
   temp_event.type = (nclicks == 2) ? GDK_2BUTTON_PRESS : GDK_3BUTTON_PRESS;
-  
-  gdk_display_put_event (display, &temp_event);
+
+  event_copy = gdk_event_copy (&temp_event);
+  link = _gdk_event_queue_append (display, event_copy);
 }
 
 void
index e64acb7b9f7f2a631d9d18476a2df364a99d75ad..5d8e28915ba71d5f45a832f9b0ade0a8ab90b912 100644 (file)
@@ -151,7 +151,8 @@ typedef enum
   GDK_SETTING           = 33,
   GDK_OWNER_CHANGE      = 34,
   GDK_GRAB_BROKEN       = 35,
-  GDK_DAMAGE            = 36
+  GDK_DAMAGE            = 36,
+  GDK_EVENT_LAST        /* helper variable for decls */
 } GdkEventType;
 
 /* Event masks. (Used to select what types of events a window
index f3389c70eaef2a855ba00615a7efd0b6eb0bd787..78967ff34389b68f0170d5fc0d0c704e2aaa586a 100644 (file)
@@ -43,12 +43,24 @@ struct _GdkGCPrivate
 {
   GdkRegion *clip_region;
 
-  GdkFill fill;
+  guint32 region_tag_applied;
+  int region_tag_offset_x;
+  int region_tag_offset_y;
+
+  GdkRegion *old_clip_region;
+  GdkPixmap *old_clip_mask;
+
   GdkBitmap *stipple;
   GdkPixmap *tile;
-  
+
+  GdkPixmap *clip_mask;
+
   guint32 fg_pixel;
   guint32 bg_pixel;
+
+  guint subwindow_mode : 1;
+  guint fill : 2;
+  guint exposures : 2;
 };
 
 #define GDK_GC_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDK_TYPE_GC, GdkGCPrivate))
@@ -150,6 +162,8 @@ _gdk_gc_init (GdkGC           *gc,
     gc->clip_x_origin = values->clip_x_origin;
   if (values_mask & GDK_GC_CLIP_Y_ORIGIN)
     gc->clip_y_origin = values->clip_y_origin;
+  if ((values_mask & GDK_GC_CLIP_MASK) && values->clip_mask)
+    priv->clip_mask = g_object_ref (values->clip_mask);
   if (values_mask & GDK_GC_TS_X_ORIGIN)
     gc->ts_x_origin = values->ts_x_origin;
   if (values_mask & GDK_GC_TS_Y_ORIGIN)
@@ -172,6 +186,12 @@ _gdk_gc_init (GdkGC           *gc,
     priv->fg_pixel = values->foreground.pixel;
   if (values_mask & GDK_GC_BACKGROUND)
     priv->bg_pixel = values->background.pixel;
+  if (values_mask & GDK_GC_SUBWINDOW)
+    priv->subwindow_mode = values->subwindow_mode;
+  if (values_mask & GDK_GC_EXPOSURES)
+    priv->exposures = values->graphics_exposures;
+  else
+    priv->exposures = TRUE;
 
   gc->colormap = gdk_drawable_get_colormap (drawable);
   if (gc->colormap)
@@ -183,9 +203,15 @@ gdk_gc_finalize (GObject *object)
 {
   GdkGC *gc = GDK_GC (object);
   GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
-  
+
   if (priv->clip_region)
     gdk_region_destroy (priv->clip_region);
+  if (priv->old_clip_region)
+    gdk_region_destroy (priv->old_clip_region);
+  if (priv->clip_mask)
+    g_object_unref (priv->clip_mask);
+  if (priv->old_clip_mask)
+    g_object_unref (priv->old_clip_mask);
   if (gc->colormap)
     g_object_unref (gc->colormap);
   if (priv->tile)
@@ -269,6 +295,12 @@ gdk_gc_set_values (GdkGC           *gc,
 
   priv = GDK_GC_GET_PRIVATE (gc);
 
+  if ((values_mask & GDK_GC_CLIP_X_ORIGIN) ||
+      (values_mask & GDK_GC_CLIP_Y_ORIGIN) ||
+      (values_mask & GDK_GC_CLIP_MASK) ||
+      (values_mask & GDK_GC_SUBWINDOW))
+    _gdk_gc_remove_drawable_clip (gc);
+  
   if (values_mask & GDK_GC_CLIP_X_ORIGIN)
     gc->clip_x_origin = values->clip_x_origin;
   if (values_mask & GDK_GC_CLIP_Y_ORIGIN)
@@ -279,6 +311,14 @@ gdk_gc_set_values (GdkGC           *gc,
     gc->ts_y_origin = values->ts_y_origin;
   if (values_mask & GDK_GC_CLIP_MASK)
     {
+      if (priv->clip_mask)
+       {
+         g_object_unref (priv->clip_mask);
+         priv->clip_mask = NULL;
+       }
+      if (values->clip_mask)
+       priv->clip_mask = g_object_ref (values->clip_mask);
+      
       if (priv->clip_region)
        {
          gdk_region_destroy (priv->clip_region);
@@ -313,6 +353,10 @@ gdk_gc_set_values (GdkGC           *gc,
     priv->fg_pixel = values->foreground.pixel;
   if (values_mask & GDK_GC_BACKGROUND)
     priv->bg_pixel = values->background.pixel;
+  if (values_mask & GDK_GC_SUBWINDOW)
+    priv->subwindow_mode = values->subwindow_mode;
+  if (values_mask & GDK_GC_EXPOSURES)
+    priv->exposures = values->graphics_exposures;
   
   GDK_GC_GET_CLASS (gc)->set_values (gc, values, values_mask);
 }
@@ -542,18 +586,121 @@ gdk_gc_set_clip_mask (GdkGC      *gc,
   gdk_gc_set_values (gc, &values, GDK_GC_CLIP_MASK);
 }
 
+/* Takes ownership of passed in region */
 static void
-_gdk_gc_set_clip_region_internal (GdkGC     *gc,
-                                 GdkRegion *region)
+_gdk_gc_set_clip_region_real (GdkGC     *gc,
+                             GdkRegion *region,
+                             gboolean reset_origin)
 {
   GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
 
+  if (priv->clip_mask)
+    {
+      g_object_unref (priv->clip_mask);
+      priv->clip_mask = NULL;
+    }
+  
   if (priv->clip_region)
     gdk_region_destroy (priv->clip_region);
 
   priv->clip_region = region;
 
-  _gdk_windowing_gc_set_clip_region (gc, region);
+  _gdk_windowing_gc_set_clip_region (gc, region, reset_origin);
+}
+
+/* Doesn't copy region, allows not to reset origin */
+void
+_gdk_gc_set_clip_region_internal (GdkGC     *gc,
+                                 GdkRegion *region,
+                                 gboolean reset_origin)
+{
+  _gdk_gc_remove_drawable_clip (gc);
+  _gdk_gc_set_clip_region_real (gc, region, reset_origin);
+}
+
+
+/* returns old clip region */
+void
+_gdk_gc_add_drawable_clip (GdkGC     *gc,
+                          guint32    region_tag,
+                          GdkRegion *region,
+                          int        offset_x,
+                          int        offset_y)
+{
+  GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
+
+  if (priv->region_tag_applied == region_tag &&
+      offset_x == priv->region_tag_offset_x &&
+      offset_y == priv->region_tag_offset_y)
+    return; /* Already appied this drawable region */
+  
+  if (priv->region_tag_applied)
+    _gdk_gc_remove_drawable_clip (gc);
+
+  region = gdk_region_copy (region);
+  if (offset_x != 0 || offset_y != 0)
+    gdk_region_offset (region, offset_x, offset_y);
+
+  if (priv->clip_mask)
+    {
+      int w, h;
+      GdkPixmap *new_mask;
+      GdkGC *tmp_gc;
+      GdkColor black = {0, 0, 0, 0};
+      
+      priv->old_clip_mask = g_object_ref (priv->clip_mask);
+      gdk_drawable_get_size (priv->old_clip_mask, &w, &h);
+
+      new_mask = gdk_pixmap_new        (priv->old_clip_mask, w, h, -1);
+      tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)new_mask, FALSE);
+
+      gdk_gc_set_foreground (tmp_gc, &black);
+      gdk_draw_rectangle (new_mask, tmp_gc, TRUE, 0, 0, -1, -1);
+      _gdk_gc_set_clip_region_internal (tmp_gc, region, TRUE); /* Takes ownership of region */
+      gdk_draw_drawable  (new_mask,
+                         tmp_gc,
+                         priv->old_clip_mask,
+                         0, 0,
+                         0, 0,
+                         -1, -1);
+      gdk_gc_set_clip_region (tmp_gc, NULL);
+      gdk_gc_set_clip_mask (gc, new_mask);
+    }
+  else
+    {
+      priv->old_clip_region = priv->clip_region;
+      priv->clip_region = region;
+      if (priv->old_clip_region)
+       gdk_region_intersect (region, priv->old_clip_region);
+      
+      _gdk_windowing_gc_set_clip_region (gc, priv->clip_region, FALSE);
+    }
+
+  priv->region_tag_applied = region_tag;
+  priv->region_tag_offset_x = offset_x;
+  priv->region_tag_offset_y = offset_y;
+}
+
+void
+_gdk_gc_remove_drawable_clip (GdkGC *gc)
+{
+  GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
+
+  if (priv->region_tag_applied)
+    {
+      priv->region_tag_applied = 0;
+      if (priv->old_clip_mask)
+       {
+         gdk_gc_set_clip_mask (gc, priv->old_clip_mask);
+         g_object_unref (priv->old_clip_mask);
+         priv->old_clip_mask = NULL;
+       }
+      else
+       {
+         _gdk_gc_set_clip_region_real (gc, priv->old_clip_region, FALSE);
+         priv->old_clip_region = NULL;
+       }
+    }
 }
 
 /**
@@ -573,12 +720,14 @@ gdk_gc_set_clip_rectangle (GdkGC              *gc,
   
   g_return_if_fail (GDK_IS_GC (gc));
 
+  _gdk_gc_remove_drawable_clip (gc);
+  
   if (rectangle)
     region = gdk_region_rectangle (rectangle);
   else
     region = NULL;
 
-  _gdk_gc_set_clip_region_internal (gc, region);
+  _gdk_gc_set_clip_region_real (gc, region, TRUE);
 }
 
 /**
@@ -598,12 +747,14 @@ gdk_gc_set_clip_region (GdkGC           *gc,
 
   g_return_if_fail (GDK_IS_GC (gc));
 
+  _gdk_gc_remove_drawable_clip (gc);
+  
   if (region)
     copy = gdk_region_copy (region);
   else
     copy = NULL;
 
-  _gdk_gc_set_clip_region_internal (gc, copy);
+  _gdk_gc_set_clip_region_real (gc, copy, TRUE);
 }
 
 /**
@@ -640,6 +791,14 @@ _gdk_gc_get_fill (GdkGC *gc)
   return GDK_GC_GET_PRIVATE (gc)->fill;
 }
 
+gboolean
+_gdk_gc_get_exposures (GdkGC *gc)
+{
+  g_return_val_if_fail (GDK_IS_GC (gc), FALSE);
+
+  return GDK_GC_GET_PRIVATE (gc)->exposures;
+}
+
 /**
  * _gdk_gc_get_tile:
  * @gc: a #GdkGC
@@ -723,13 +882,27 @@ gdk_gc_set_subwindow (GdkGC              *gc,
                      GdkSubwindowMode  mode)
 {
   GdkGCValues values;
+  GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
 
   g_return_if_fail (GDK_IS_GC (gc));
 
+  /* This could get called a lot to reset the subwindow mode in
+     the client side clipping, so bail out early */ 
+  if (priv->subwindow_mode == mode)
+    return;
+  
   values.subwindow_mode = mode;
   gdk_gc_set_values (gc, &values, GDK_GC_SUBWINDOW);
 }
 
+GdkSubwindowMode
+_gdk_gc_get_subwindow (GdkGC *gc)
+{
+  GdkGCPrivate *priv = GDK_GC_GET_PRIVATE (gc);
+
+  return priv->subwindow_mode;
+}
+
 /**
  * gdk_gc_set_exposures:
  * @gc: a #GdkGC.
@@ -890,6 +1063,26 @@ gdk_gc_copy (GdkGC *dst_gc,
     dst_priv->clip_region = gdk_region_copy (src_priv->clip_region);
   else
     dst_priv->clip_region = NULL;
+
+  dst_priv->region_tag_applied = src_priv->region_tag_applied;
+  
+  if (dst_priv->old_clip_region)
+    gdk_region_destroy (dst_priv->old_clip_region);
+
+  if (src_priv->old_clip_region)
+    dst_priv->old_clip_region = gdk_region_copy (src_priv->old_clip_region);
+  else
+    dst_priv->old_clip_region = NULL;
+
+  if (src_priv->clip_mask)
+    dst_priv->clip_mask = g_object_ref (src_priv->clip_mask);
+  else
+    dst_priv->clip_mask = NULL;
+  
+  if (src_priv->old_clip_mask)
+    dst_priv->old_clip_mask = g_object_ref (src_priv->old_clip_mask);
+  else
+    dst_priv->old_clip_mask = NULL;
   
   dst_priv->fill = src_priv->fill;
   
@@ -907,6 +1100,8 @@ gdk_gc_copy (GdkGC *dst_gc,
 
   dst_priv->fg_pixel = src_priv->fg_pixel;
   dst_priv->bg_pixel = src_priv->bg_pixel;
+  dst_priv->subwindow_mode = src_priv->subwindow_mode;
+  dst_priv->exposures = src_priv->exposures;
 }
 
 /**
@@ -1117,6 +1312,8 @@ gc_get_background (GdkGC    *gc,
  *   the fill mode will be forced to %GDK_STIPPLED
  * @gc_changed: pass %FALSE if the @gc has not changed since the
  *     last call to this function
+ * @target_drawable: The drawable you're drawing in. If passed in
+ *     this is used for client side window clip emulation.
  * 
  * Set the attributes of a cairo context to match those of a #GdkGC
  * as far as possible. Some aspects of a #GdkGC, such as clip masks
@@ -1127,7 +1324,8 @@ _gdk_gc_update_context (GdkGC          *gc,
                         cairo_t        *cr,
                         const GdkColor *override_foreground,
                         GdkBitmap      *override_stipple,
-                        gboolean        gc_changed)
+                        gboolean        gc_changed,
+                       GdkDrawable    *target_drawable)
 {
   GdkGCPrivate *priv;
   GdkFill fill;
@@ -1246,6 +1444,10 @@ _gdk_gc_update_context (GdkGC          *gc,
 
       cairo_clip (cr);
     }
+
+  /* The reset above resets the window clip rect, so we want to re-set that */
+  if (target_drawable && GDK_DRAWABLE_GET_CLASS (target_drawable)->set_cairo_clip)
+    GDK_DRAWABLE_GET_CLASS (target_drawable)->set_cairo_clip (target_drawable, cr);
 }
 
 
index 61a5433e2aade64525ee7cfef3789105878b722e..4f0d6669815b921b83acd46c291c03a98319da3b 100644 (file)
@@ -170,6 +170,110 @@ struct _GdkEventPrivate
   gpointer   windowing_data;
 };
 
+/* Tracks information about the pointer grab on this display */
+typedef struct
+{
+  GdkWindow *window;
+  GdkWindow *native_window;
+  gulong serial_start;
+  gulong serial_end; /* exclusive, i.e. not active on serial_end */
+  gboolean owner_events;
+  guint event_mask;
+  gboolean implicit;
+  guint32 time;
+
+  gboolean activated;
+  gboolean implicit_ungrab;
+  gboolean grab_one_pointer_release_event;
+} GdkPointerGrabInfo;
+
+typedef struct _GdkInputWindow GdkInputWindow;
+
+/* Private version of GdkWindowObject. The initial part of this strucuture
+   is public for historical reasons. Don't change that part */
+typedef struct _GdkWindowPaint             GdkWindowPaint;
+
+struct _GdkWindowObject
+{
+  /* vvvvvvv THIS PART IS PUBLIC. DON'T CHANGE vvvvvvvvvvvvvv */
+  GdkDrawable parent_instance;
+
+  GdkDrawable *impl; /* window-system-specific delegate object */  
+  
+  GdkWindowObject *parent;
+
+  gpointer user_data;
+
+  gint x;
+  gint y;
+  
+  gint extension_events;
+
+  GList *filters;
+  GList *children;
+
+  GdkColor bg_color;
+  GdkPixmap *bg_pixmap;
+  
+  GSList *paint_stack;
+  
+  GdkRegion *update_area;
+  guint update_freeze_count;
+  
+  guint8 window_type;
+  guint8 depth;
+  guint8 resize_count;
+
+  GdkWindowState state;
+  
+  guint guffaw_gravity : 1;
+  guint input_only : 1;
+  guint modal_hint : 1;
+  guint composited : 1;
+  
+  guint destroyed : 2;
+
+  guint accept_focus : 1;
+  guint focus_on_map : 1;
+  guint shaped : 1;
+  
+  GdkEventMask event_mask;
+
+  guint update_and_descendants_freeze_count;
+
+  GdkWindowRedirect *redirect;
+
+  /* ^^^^^^^^^^ THIS PART IS PUBLIC. DON'T CHANGE ^^^^^^^^^^ */
+  
+  /* The GdkWindowObject that has the impl, ref:ed if another window.
+   * This ref is required to keep the wrapper of the impl window alive
+   * for as long as any GdkWindow references the impl. */
+  GdkWindowObject *impl_window; 
+  int abs_x, abs_y; /* Absolute offset in impl */
+  gint width, height;
+  guint32 clip_tag;
+  GdkRegion *clip_region; /* Clip region (wrt toplevel) in window coords */
+  GdkRegion *clip_region_with_children; /* Clip region in window coords */
+  GdkCursor *cursor;
+  gint8 toplevel_window_type;
+  guint synthesize_crossing_event_queued : 1;
+  guint effective_visibility : 2;
+  guint visibility : 2; /* The visibility wrt the toplevel (i.e. based on clip_region) */
+  guint native_visibility : 2; /* the native visibility of a impl windows */
+  guint has_offscreen_children : 1;
+
+  GdkWindowPaint *implicit_paint;
+  GdkInputWindow *input_window; /* only set for impl windows */
+
+  GList *outstanding_moves;
+
+  GdkRegion *shape;
+  GdkRegion *input_shape;
+  
+  cairo_surface_t *cairo_surface;
+};
+
+
 extern GdkEventFunc   _gdk_event_func;    /* Callback for events */
 extern gpointer       _gdk_event_data;
 extern GDestroyNotify _gdk_event_notify;
@@ -182,15 +286,21 @@ extern gchar     *_gdk_display_arg_name;
 void      _gdk_events_queue  (GdkDisplay *display);
 GdkEvent* _gdk_event_unqueue (GdkDisplay *display);
 
-GList* _gdk_event_queue_find_first  (GdkDisplay *display);
-void   _gdk_event_queue_remove_link (GdkDisplay *display,
-                                    GList      *node);
-GList*  _gdk_event_queue_prepend    (GdkDisplay *display,
-                                    GdkEvent   *event);
-GList*  _gdk_event_queue_append     (GdkDisplay *display,
-                                    GdkEvent   *event);
-void _gdk_event_button_generate     (GdkDisplay *display,
-                                    GdkEvent   *event);
+GList* _gdk_event_queue_find_first   (GdkDisplay *display);
+void   _gdk_event_queue_remove_link  (GdkDisplay *display,
+                                     GList      *node);
+GList* _gdk_event_queue_prepend      (GdkDisplay *display,
+                                     GdkEvent   *event);
+GList* _gdk_event_queue_append       (GdkDisplay *display,
+                                     GdkEvent   *event);
+GList* _gdk_event_queue_insert_after (GdkDisplay *display,
+                                      GdkEvent   *after_event,
+                                      GdkEvent   *event);
+GList* _gdk_event_queue_insert_before(GdkDisplay *display,
+                                      GdkEvent   *after_event,
+                                      GdkEvent   *event);
+void   _gdk_event_button_generate    (GdkDisplay *display,
+                                     GdkEvent   *event);
 
 void _gdk_windowing_event_data_copy (const GdkEvent *src,
                                      GdkEvent       *dst);
@@ -227,28 +337,59 @@ GdkImage *_gdk_drawable_copy_to_image (GdkDrawable  *drawable,
 
 cairo_surface_t *_gdk_drawable_ref_cairo_surface (GdkDrawable *drawable);
 
+GdkDrawable *_gdk_drawable_get_source_drawable (GdkDrawable *drawable);
+cairo_surface_t * _gdk_drawable_create_cairo_surface (GdkDrawable *drawable,
+                                                     int width,
+                                                     int height);
+
 /* GC caching */
 GdkGC *_gdk_drawable_get_scratch_gc (GdkDrawable *drawable,
                                     gboolean     graphics_exposures);
+GdkGC *_gdk_drawable_get_subwindow_scratch_gc (GdkDrawable *drawable);
 
 void _gdk_gc_update_context (GdkGC          *gc,
                             cairo_t        *cr,
                             const GdkColor *override_foreground,
                             GdkBitmap      *override_stipple,
-                            gboolean        gc_changed);
+                            gboolean        gc_changed,
+                            GdkDrawable    *target_drawable);
 
 /*************************************
  * Interfaces used by windowing code *
  *************************************/
 
-GdkWindow *_gdk_window_new               (GdkWindow     *window,
-                                          GdkWindowAttr *attributes,
-                                          gint           attributes_mask);
-void       _gdk_window_destroy           (GdkWindow     *window,
-                                         gboolean       foreign_destroy);
-void       _gdk_window_clear_update_area (GdkWindow     *window);
-
-void       _gdk_screen_close             (GdkScreen     *screen);
+GdkPixmap *_gdk_pixmap_new               (GdkDrawable    *drawable,
+                                          gint            width,
+                                          gint            height,
+                                          gint            depth);
+GdkPixmap *_gdk_pixmap_create_from_data  (GdkDrawable    *drawable,
+                                          const gchar    *data,
+                                          gint            width,
+                                          gint            height,
+                                          gint            depth,
+                                          const GdkColor *fg,
+                                          const GdkColor *bg);
+GdkPixmap *_gdk_bitmap_create_from_data  (GdkDrawable    *drawable,
+                                          const gchar    *data,
+                                          gint            width,
+                                          gint            height);
+
+void       _gdk_window_impl_new          (GdkWindow      *window,
+                                         GdkWindow      *real_parent,
+                                         GdkScreen      *screen,
+                                         GdkVisual      *visual,
+                                         GdkEventMask    event_mask,
+                                          GdkWindowAttr  *attributes,
+                                          gint            attributes_mask);
+void       _gdk_window_destroy           (GdkWindow      *window,
+                                          gboolean        foreign_destroy);
+void       _gdk_window_clear_update_area (GdkWindow      *window);
+void       _gdk_window_update_size       (GdkWindow      *window);
+
+void       _gdk_window_process_updates_recurse (GdkWindow *window,
+                                                GdkRegion *expose_region);
+
+void       _gdk_screen_close             (GdkScreen      *screen);
 
 const char *_gdk_get_sm_client_id (void);
 
@@ -258,11 +399,22 @@ void _gdk_gc_init (GdkGC           *gc,
                   GdkGCValuesMask  values_mask);
 
 GdkRegion *_gdk_gc_get_clip_region (GdkGC *gc);
+gboolean   _gdk_gc_get_exposures   (GdkGC *gc);
 GdkFill    _gdk_gc_get_fill        (GdkGC *gc);
 GdkPixmap *_gdk_gc_get_tile        (GdkGC *gc);
 GdkBitmap *_gdk_gc_get_stipple     (GdkGC *gc);
 guint32    _gdk_gc_get_fg_pixel    (GdkGC *gc);
 guint32    _gdk_gc_get_bg_pixel    (GdkGC *gc);
+void      _gdk_gc_add_drawable_clip     (GdkGC     *gc,
+                                        guint32    region_tag,
+                                        GdkRegion *region,
+                                        int        offset_x,
+                                        int        offset_y);
+void      _gdk_gc_remove_drawable_clip  (GdkGC     *gc);
+void       _gdk_gc_set_clip_region_internal (GdkGC     *gc,
+                                            GdkRegion *region,
+                                            gboolean reset_origin);
+GdkSubwindowMode _gdk_gc_get_subwindow (GdkGC *gc);
 
 /*****************************************
  * Interfaces provided by windowing code *
@@ -284,60 +436,49 @@ void     _gdk_windowing_set_default_display     (GdkDisplay *display);
 gchar *_gdk_windowing_substitute_screen_number (const gchar *display_name,
                                                gint         screen_number);
 
+gulong   _gdk_windowing_window_get_next_serial  (GdkDisplay *display);
 void     _gdk_windowing_window_get_offsets      (GdkWindow  *window,
                                                 gint       *x_offset,
                                                 gint       *y_offset);
+GdkRegion *_gdk_windowing_window_get_shape      (GdkWindow  *window);
+GdkRegion *_gdk_windowing_window_get_input_shape(GdkWindow  *window);
+GdkRegion *_gdk_windowing_get_shape_for_mask    (GdkBitmap *mask);
+void     _gdk_windowing_window_beep             (GdkWindow *window);
+
 
 void       _gdk_windowing_get_pointer        (GdkDisplay       *display,
                                              GdkScreen       **screen,
                                              gint             *x,
                                              gint             *y,
                                              GdkModifierType  *mask);
-GdkWindow* _gdk_windowing_window_get_pointer (GdkDisplay       *display,
-                                             GdkWindow        *window,
-                                             gint             *x,
-                                             gint             *y,
-                                             GdkModifierType  *mask);
 GdkWindow* _gdk_windowing_window_at_pointer  (GdkDisplay       *display,
                                              gint             *win_x,
-                                             gint             *win_y);
+                                             gint             *win_y,
+                                             GdkModifierType  *mask);
+GdkGrabStatus _gdk_windowing_pointer_grab    (GdkWindow        *window,
+                                             GdkWindow        *native,
+                                             gboolean          owner_events,
+                                             GdkEventMask      event_mask,
+                                             GdkWindow        *confine_to,
+                                             GdkCursor        *cursor,
+                                             guint32           time);
+void _gdk_windowing_got_event                (GdkDisplay       *display,
+                                             GList            *event_link,
+                                             GdkEvent         *event,
+                                             gulong            serial);
+
+void _gdk_windowing_window_process_updates_recurse (GdkWindow *window,
+                                                    GdkRegion *expose_region);
+void _gdk_windowing_before_process_all_updates     (void);
+void _gdk_windowing_after_process_all_updates      (void);
 
 /* Return the number of bits-per-pixel for images of the specified depth. */
 gint _gdk_windowing_get_bits_for_depth (GdkDisplay *display,
                                        gint        depth);
 
-void       _gdk_window_reparent                   (GdkWindow     *window,
-                                                  GdkWindow     *new_parent,
-                                                  gint           x,
-                                                  gint           y);
 
 #define GDK_WINDOW_IS_MAPPED(window) ((((GdkWindowObject*)window)->state & GDK_WINDOW_STATE_WITHDRAWN) == 0)
 
-/* Called before processing updates for a window. This gives the windowing
- * layer a chance to save the region for later use in avoiding duplicate
- * exposes. The return value indicates whether the function has a saved
- * the region; if the result is TRUE, then the windowing layer is responsible
- * for destroying the region later.
- */
-gboolean _gdk_windowing_window_queue_antiexpose (GdkWindow *window,
-                                                GdkRegion *area);
-
-/* Called to do the windowing system specific part of gdk_window_destroy(),
- *
- * window: The window being destroyed
- * recursing: If TRUE, then this is being called because a parent
- *            was destroyed. This generally means that the call to the windowing system
- *            to destroy the window can be omitted, since it will be destroyed as a result
- *            of the parent being destroyed. Unless @foreign_destroy
- *            
- * foreign_destroy: If TRUE, the window or a parent was destroyed by some external 
- *            agency. The window has already been destroyed and no windowing
- *            system calls should be made. (This may never happen for some
- *            windowing systems.)
- */
-void _gdk_windowing_window_destroy (GdkWindow *window,
-                                   gboolean   recursing,
-                                   gboolean   foreign_destroy);
 
 /* Called when gdk_window_destroy() is called on a foreign window
  * or an ancestor of the foreign window. It should generally reparent
@@ -365,15 +506,9 @@ struct _GdkPaintableIface
   GTypeInterface g_iface;
   
   void (* begin_paint_region)       (GdkPaintable    *paintable,
+                                     GdkWindow       *window,
                                      const GdkRegion *region);
   void (* end_paint)                (GdkPaintable    *paintable);
-
-  void (* invalidate_maybe_recurse) (GdkPaintable    *paintable,
-                                    const GdkRegion *region,
-                                    gboolean       (*child_func) (GdkWindow *, gpointer),
-                                    gpointer         user_data);
-  void (* process_updates)          (GdkPaintable    *paintable,
-                                    gboolean         update_children);
 };
 
 GType _gdk_paintable_get_type (void) G_GNUC_CONST;
@@ -387,6 +522,7 @@ GType _gdk_pixmap_impl_get_type (void) G_GNUC_CONST;
  * _gdk_windowing_gc_set_clip_region:
  * @gc: a #GdkGC
  * @region: the new clip region
+ * @reset_origin: if TRUE, reset the clip_x/y_origin values to 0
  * 
  * Do any window-system specific processing necessary
  * for a change in clip region. Since the clip origin
@@ -398,7 +534,8 @@ GType _gdk_pixmap_impl_get_type (void) G_GNUC_CONST;
  * will already return the new region.
  **/
 void _gdk_windowing_gc_set_clip_region (GdkGC           *gc,
-                                       const GdkRegion *region);
+                                       const GdkRegion *region,
+                                       gboolean reset_origin);
 
 /**
  * _gdk_windowing_gc_copy:
@@ -435,6 +572,99 @@ char *_gdk_windowing_get_startup_notify_id (GAppLaunchContext *context,
 void  _gdk_windowing_launch_failed         (GAppLaunchContext *context, 
                                            const char        *startup_notify_id);
 
+GdkPointerGrabInfo *_gdk_display_get_active_pointer_grab (GdkDisplay *display);
+void _gdk_display_pointer_grab_update                    (GdkDisplay *display,
+                                                         gulong current_serial);
+GdkPointerGrabInfo *_gdk_display_get_last_pointer_grab (GdkDisplay *display);
+GdkPointerGrabInfo *_gdk_display_add_pointer_grab  (GdkDisplay *display,
+                                                   GdkWindow *window,
+                                                   GdkWindow *native_window,
+                                                   gboolean owner_events,
+                                                   GdkEventMask event_mask,
+                                                   unsigned long serial_start,
+                                                   guint32 time,
+                                                   gboolean implicit);
+GdkPointerGrabInfo * _gdk_display_has_pointer_grab (GdkDisplay *display,
+                                                   gulong serial);
+gboolean _gdk_display_end_pointer_grab (GdkDisplay *display,
+                                       gulong serial,
+                                       GdkWindow *if_child,
+                                       gboolean implicit);
+void _gdk_display_set_has_keyboard_grab (GdkDisplay *display,
+                                        GdkWindow *window,
+                                        GdkWindow *native_window,
+                                        gboolean owner_events,
+                                        unsigned long serial,
+                                        guint32 time);
+void _gdk_display_unset_has_keyboard_grab (GdkDisplay *display,
+                                          gboolean implicit);
+void _gdk_display_enable_motion_hints     (GdkDisplay *display);
+
+
+void _gdk_window_invalidate_for_expose (GdkWindow       *window,
+                                       const GdkRegion *region);
+
+void _gdk_windowing_set_cairo_surface_size (cairo_surface_t *surface,
+                                           int width,
+                                           int height);
+
+cairo_surface_t * _gdk_windowing_create_cairo_surface (GdkDrawable *drawable,
+                                                      int width,
+                                                      int height);
+GdkWindow * _gdk_window_find_child_at (GdkWindow *window,
+                                      int x, int y);
+GdkWindow * _gdk_window_find_descendant_at (GdkWindow *toplevel,
+                                           double x, double y,
+                                           double *found_x,
+                                           double *found_y);
+
+void _gdk_window_add_damage (GdkWindow *toplevel,
+                            GdkRegion *damaged_region);
+
+GdkEvent * _gdk_make_event (GdkWindow    *window,
+                           GdkEventType  type,
+                           GdkEvent     *event_in_queue,
+                           gboolean      before_event);
+
+void _gdk_syntesize_crossing_events (GdkDisplay                 *display,
+                                    GdkWindow                  *src,
+                                    GdkWindow                  *dest,
+                                    GdkCrossingMode             mode,
+                                    gint                        toplevel_x,
+                                    gint                        toplevel_y,
+                                    GdkModifierType             mask,
+                                    guint32                     time_,
+                                    GdkEvent                   *event_in_queue,
+                                    gulong                      serial);
+void _gdk_display_set_window_under_pointer (GdkDisplay *display,
+                                           GdkWindow *window);
+
+
+void _gdk_syntesize_crossing_events_for_geometry_change (GdkWindow *changed_window);
+
+GdkRegion *_gdk_window_calculate_full_clip_region    (GdkWindow     *window,
+                                                      GdkWindow     *base_window,
+                                                      gboolean       do_children,
+                                                      gint          *base_x_offset,
+                                                      gint          *base_y_offset);
+gboolean    _gdk_window_has_impl (GdkWindow *window);
+GdkWindow * _gdk_window_get_impl_window (GdkWindow *window);
+GdkWindow *_gdk_window_get_input_window_for_event (GdkWindow *native_window,
+                                                  GdkEventType event_type,
+                                                  int x, int y,
+                                                  gulong serial);
+GdkRegion  *_gdk_region_new_from_yxbanded_rects (GdkRectangle *rects, int n_rects);
+
+/*****************************
+ * offscreen window routines *
+ *****************************/
+GType gdk_offscreen_window_get_type (void);
+void       _gdk_offscreen_window_new                 (GdkWindow     *window,
+                                                     GdkScreen     *screen,
+                                                     GdkVisual     *visual,
+                                                     GdkWindowAttr *attributes,
+                                                     gint           attributes_mask);
+
 
 /************************************
  * Initialization and exit routines *
index 3c0b1ff6c187d5c4fb6405395cc83f73b371361b..ea36baeb8894189a1b08f0b045902a9c2a148747 100644 (file)
@@ -1,2 +1,6 @@
 VOID:OBJECT
 VOID:BOOLEAN
+VOID:POINTER,POINTER,POINTER
+OBJECT:VOID
+OBJECT:DOUBLE,DOUBLE
+VOID:DOUBLE,DOUBLE,POINTER,POINTER
diff --git a/gdk/gdkoffscreenwindow.c b/gdk/gdkoffscreenwindow.c
new file mode 100644 (file)
index 0000000..6e92f62
--- /dev/null
@@ -0,0 +1,1229 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-2005.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
+ */
+
+#include <config.h>
+#include <math.h>
+#include "gdk.h"
+#include "gdkwindow.h"
+#include "gdkinternals.h"
+#include "gdkwindowimpl.h"
+#include "gdkpixmap.h"
+#include "gdkdrawable.h"
+#include "gdktypes.h"
+#include "gdkscreen.h"
+#include "gdkgc.h"
+#include "gdkcolor.h"
+#include "gdkcursor.h"
+#include "gdkalias.h"
+
+/* LIMITATIONS:
+ *
+ * Offscreen windows can't be the child of a foreign window,
+ *   nor contain foreign windows
+ * GDK_POINTER_MOTION_HINT_MASK isn't effective
+ */
+
+typedef struct _GdkOffscreenWindow      GdkOffscreenWindow;
+typedef struct _GdkOffscreenWindowClass GdkOffscreenWindowClass;
+
+struct _GdkOffscreenWindow
+{
+  GdkDrawable parent_instance;
+
+  GdkWindow *wrapper;
+  GdkCursor *cursor;
+  GdkColormap *colormap;
+  GdkScreen *screen;
+
+  GdkPixmap *pixmap;
+};
+
+struct _GdkOffscreenWindowClass
+{
+  GdkDrawableClass parent_class;
+};
+
+#define GDK_TYPE_OFFSCREEN_WINDOW            (gdk_offscreen_window_get_type())
+#define GDK_OFFSCREEN_WINDOW(object)         (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_OFFSCREEN_WINDOW, GdkOffscreenWindow))
+#define GDK_IS_OFFSCREEN_WINDOW(object)      (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_OFFSCREEN_WINDOW))
+#define GDK_OFFSCREEN_WINDOW_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_OFFSCREEN_WINDOW, GdkOffscreenWindowClass))
+#define GDK_IS_OFFSCREEN_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_OFFSCREEN_WINDOW))
+#define GDK_OFFSCREEN_WINDOW_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_OFFSCREEN_WINDOW, GdkOffscreenWindowClass))
+
+static void       gdk_offscreen_window_impl_iface_init    (GdkWindowImplIface         *iface);
+static void       gdk_offscreen_window_hide               (GdkWindow                  *window);
+
+G_DEFINE_TYPE_WITH_CODE (GdkOffscreenWindow,
+                        gdk_offscreen_window,
+                        GDK_TYPE_DRAWABLE,
+                        G_IMPLEMENT_INTERFACE (GDK_TYPE_WINDOW_IMPL,
+                                               gdk_offscreen_window_impl_iface_init));
+
+
+static void
+gdk_offscreen_window_finalize (GObject *object)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (object);
+
+  if (offscreen->cursor)
+    gdk_cursor_unref (offscreen->cursor);
+
+  offscreen->cursor = NULL;
+
+  gdk_pixmap_unref (offscreen->pixmap);
+
+  G_OBJECT_CLASS (gdk_offscreen_window_parent_class)->finalize (object);
+}
+
+static void
+gdk_offscreen_window_init (GdkOffscreenWindow *window)
+{
+}
+
+static void
+gdk_offscreen_window_destroy (GdkWindow *window,
+                             gboolean   recursing,
+                             gboolean   foreign_destroy)
+{
+  GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
+  GdkOffscreenWindow *offscreen;
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+  if (!recursing)
+    gdk_offscreen_window_hide (window);
+
+  g_object_unref (offscreen->colormap);
+  offscreen->colormap = NULL;
+}
+
+static gboolean
+is_parent_of (GdkWindow *parent,
+             GdkWindow *child)
+{
+  GdkWindow *w;
+
+  w = child;
+  while (w != NULL)
+    {
+      if (w == parent)
+       return TRUE;
+
+      w = gdk_window_get_parent (w);
+    }
+
+  return FALSE;
+}
+
+static GdkGC *
+gdk_offscreen_window_create_gc (GdkDrawable     *drawable,
+                               GdkGCValues     *values,
+                               GdkGCValuesMask  values_mask)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+  return gdk_gc_new_with_values (offscreen->pixmap, values, values_mask);
+}
+
+static GdkImage*
+gdk_offscreen_window_copy_to_image (GdkDrawable    *drawable,
+                                   GdkImage       *image,
+                                   gint            src_x,
+                                   gint            src_y,
+                                   gint            dest_x,
+                                   gint            dest_y,
+                                   gint            width,
+                                   gint            height)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+  return gdk_drawable_copy_to_image (offscreen->pixmap,
+                                    image,
+                                    src_x,
+                                    src_y,
+                                    dest_x, dest_y,
+                                    width, height);
+}
+
+static cairo_surface_t *
+gdk_offscreen_window_ref_cairo_surface (GdkDrawable *drawable)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+  return _gdk_drawable_ref_cairo_surface (offscreen->pixmap);
+}
+
+static GdkColormap*
+gdk_offscreen_window_get_colormap (GdkDrawable *drawable)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+  return offscreen->colormap;
+}
+
+static void
+gdk_offscreen_window_set_colormap (GdkDrawable *drawable,
+                                  GdkColormap*colormap)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+  if (colormap && GDK_WINDOW_DESTROYED (offscreen->wrapper))
+    return;
+
+  if (offscreen->colormap == colormap)
+    return;
+
+  if (offscreen->colormap)
+    g_object_unref (offscreen->colormap);
+
+  offscreen->colormap = colormap;
+  if (offscreen->colormap)
+    g_object_ref (offscreen->colormap);
+}
+
+
+static gint
+gdk_offscreen_window_get_depth (GdkDrawable *drawable)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+  return gdk_drawable_get_depth (offscreen->wrapper);
+}
+
+static GdkDrawable *
+gdk_offscreen_window_get_source_drawable (GdkDrawable  *drawable)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+  return _gdk_drawable_get_source_drawable (offscreen->pixmap);
+}
+
+static GdkDrawable *
+gdk_offscreen_window_get_composite_drawable (GdkDrawable *drawable,
+                                            gint         x,
+                                            gint         y,
+                                            gint         width,
+                                            gint         height,
+                                            gint        *composite_x_offset,
+                                            gint        *composite_y_offset)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+  return g_object_ref (offscreen->pixmap);
+}
+
+static GdkScreen*
+gdk_offscreen_window_get_screen (GdkDrawable *drawable)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+  return offscreen->screen;
+}
+
+static GdkVisual*
+gdk_offscreen_window_get_visual (GdkDrawable    *drawable)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+
+  return gdk_drawable_get_visual (offscreen->wrapper);
+}
+
+static void
+add_damage (GdkOffscreenWindow *offscreen,
+           int x, int y,
+           int w, int h)
+{
+  GdkRectangle rect;
+  GdkRegion *damage;
+
+  rect.x = x;
+  rect.y = y;
+  rect.width = w;
+  rect.height = h;
+
+  damage = gdk_region_rectangle (&rect);
+  _gdk_window_add_damage (offscreen->wrapper, damage);
+  gdk_region_destroy (damage);
+}
+
+static GdkDrawable *
+get_real_drawable (GdkOffscreenWindow *offscreen)
+{
+  GdkPixmapObject *pixmap;
+  pixmap = (GdkPixmapObject *) offscreen->pixmap;
+  return GDK_DRAWABLE (pixmap->impl);
+}
+
+static void
+gdk_offscreen_window_draw_drawable (GdkDrawable *drawable,
+                                   GdkGC       *gc,
+                                   GdkPixmap   *src,
+                                   GdkDrawable *original_src,
+                                   gint         xsrc,
+                                   gint         ysrc,
+                                   gint         xdest,
+                                   gint         ydest,
+                                   gint         width,
+                                   gint         height)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = get_real_drawable (offscreen);
+
+  gdk_draw_drawable (real_drawable, gc,
+                    src, xsrc, ysrc,
+                    xdest, ydest,
+                    width, height);
+
+  add_damage (offscreen, xdest, ydest, width, height);
+}
+
+static void
+gdk_offscreen_window_draw_rectangle (GdkDrawable  *drawable,
+                                    GdkGC        *gc,
+                                    gboolean      filled,
+                                    gint          x,
+                                    gint          y,
+                                    gint          width,
+                                    gint          height)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = get_real_drawable (offscreen);
+
+  gdk_draw_rectangle (real_drawable,
+                     gc, filled, x, y, width, height);
+
+  add_damage (offscreen, x, y, width, height);
+
+}
+
+static void
+gdk_offscreen_window_draw_arc (GdkDrawable  *drawable,
+                              GdkGC           *gc,
+                              gboolean filled,
+                              gint             x,
+                              gint             y,
+                              gint             width,
+                              gint             height,
+                              gint             angle1,
+                              gint             angle2)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = get_real_drawable (offscreen);
+
+  gdk_draw_arc (real_drawable,
+               gc,
+               filled,
+               x,
+               y,
+               width,
+               height,
+               angle1,
+               angle2);
+  add_damage (offscreen, x, y, width, height);
+}
+
+static void
+gdk_offscreen_window_draw_polygon (GdkDrawable  *drawable,
+                                  GdkGC               *gc,
+                                  gboolean     filled,
+                                  GdkPoint     *points,
+                                  gint         npoints)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = get_real_drawable (offscreen);
+
+  gdk_draw_polygon (real_drawable,
+                   gc,
+                   filled,
+                   points,
+                   npoints);
+
+  if (npoints > 0)
+    {
+      int min_x, min_y, max_x, max_y, i;
+
+      min_x = max_x = points[0].x;
+      min_y = max_y = points[0].y;
+
+       for (i = 1; i < npoints; i++)
+         {
+           min_x = MIN (min_x, points[i].x);
+           max_x = MAX (max_x, points[i].x);
+           min_y = MIN (min_y, points[i].y);
+           max_y = MAX (max_y, points[i].y);
+         }
+
+       add_damage (offscreen, min_x, min_y,
+                   max_x - min_x,
+                   max_y - min_y);
+    }
+}
+
+static void
+gdk_offscreen_window_draw_text (GdkDrawable  *drawable,
+                               GdkFont      *font,
+                               GdkGC          *gc,
+                               gint            x,
+                               gint            y,
+                               const gchar  *text,
+                               gint            text_length)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = get_real_drawable (offscreen);
+  GdkWindowObject *private = GDK_WINDOW_OBJECT (offscreen->wrapper);
+
+  gdk_draw_text (real_drawable,
+                font,
+                gc,
+                x,
+                y,
+                text,
+                text_length);
+
+  /* Hard to compute the minimal size, not that often used anyway. */
+  add_damage (offscreen, 0, 0, private->width, private->height);
+}
+
+static void
+gdk_offscreen_window_draw_text_wc (GdkDrawable  *drawable,
+                                  GdkFont       *font,
+                                  GdkGC                 *gc,
+                                  gint           x,
+                                  gint           y,
+                                  const GdkWChar *text,
+                                  gint           text_length)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = get_real_drawable (offscreen);
+  GdkWindowObject *private = GDK_WINDOW_OBJECT (offscreen->wrapper);
+
+  gdk_draw_text_wc (real_drawable,
+                   font,
+                   gc,
+                   x,
+                   y,
+                   text,
+                   text_length);
+
+  /* Hard to compute the minimal size, not that often used anyway. */
+  add_damage (offscreen, 0, 0, private->width, private->height);
+}
+
+static void
+gdk_offscreen_window_draw_points (GdkDrawable  *drawable,
+                                 GdkGC        *gc,
+                                 GdkPoint     *points,
+                                 gint          npoints)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = get_real_drawable (offscreen);
+
+  gdk_draw_points (real_drawable,
+                  gc,
+                  points,
+                  npoints);
+
+
+  if (npoints > 0)
+    {
+      int min_x, min_y, max_x, max_y, i;
+
+      min_x = max_x = points[0].x;
+      min_y = max_y = points[0].y;
+
+       for (i = 1; i < npoints; i++)
+         {
+           min_x = MIN (min_x, points[i].x);
+           max_x = MAX (max_x, points[i].x);
+           min_y = MIN (min_y, points[i].y);
+           max_y = MAX (max_y, points[i].y);
+         }
+
+       add_damage (offscreen, min_x, min_y,
+                   max_x - min_x,
+                   max_y - min_y);
+    }
+}
+
+static void
+gdk_offscreen_window_draw_segments (GdkDrawable  *drawable,
+                                   GdkGC        *gc,
+                                   GdkSegment   *segs,
+                                   gint          nsegs)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = get_real_drawable (offscreen);
+
+  gdk_draw_segments (real_drawable,
+                    gc,
+                    segs,
+                    nsegs);
+
+  if (nsegs > 0)
+    {
+      int min_x, min_y, max_x, max_y, i;
+
+      min_x = max_x = segs[0].x1;
+      min_y = max_y = segs[0].y1;
+
+       for (i = 1; i < nsegs; i++)
+         {
+           min_x = MIN (min_x, segs[i].x1);
+           max_x = MAX (max_x, segs[i].x1);
+           min_x = MIN (min_x, segs[i].x2);
+           max_x = MAX (max_x, segs[i].x2);
+           min_y = MIN (min_y, segs[i].y1);
+           max_y = MAX (max_y, segs[i].y1);
+           min_y = MIN (min_y, segs[i].y2);
+           max_y = MAX (max_y, segs[i].y2);
+         }
+
+       add_damage (offscreen, min_x, min_y,
+                   max_x - min_x,
+                   max_y - min_y);
+    }
+
+}
+
+static void
+gdk_offscreen_window_draw_lines (GdkDrawable  *drawable,
+                                GdkGC        *gc,
+                                GdkPoint     *points,
+                                gint          npoints)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = get_real_drawable (offscreen);
+  GdkWindowObject *private = GDK_WINDOW_OBJECT (offscreen->wrapper);
+
+  gdk_draw_lines (real_drawable,
+                 gc,
+                 points,
+                 npoints);
+
+  /* Hard to compute the minimal size, as we don't know the line
+     width, and since joins are hard to calculate.
+     Its not that often used anyway, damage it all */
+  add_damage (offscreen, 0, 0, private->width, private->height);
+}
+
+static void
+gdk_offscreen_window_draw_image (GdkDrawable *drawable,
+                                GdkGC        *gc,
+                                GdkImage    *image,
+                                gint          xsrc,
+                                gint          ysrc,
+                                gint          xdest,
+                                gint          ydest,
+                                gint          width,
+                                gint          height)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = get_real_drawable (offscreen);
+
+  gdk_draw_image (real_drawable,
+                 gc,
+                 image,
+                 xsrc,
+                 ysrc,
+                 xdest,
+                 ydest,
+                 width,
+                 height);
+
+  add_damage (offscreen, xdest, ydest, width, height);
+}
+
+
+static void
+gdk_offscreen_window_draw_pixbuf (GdkDrawable *drawable,
+                                 GdkGC       *gc,
+                                 GdkPixbuf   *pixbuf,
+                                 gint         src_x,
+                                 gint         src_y,
+                                 gint         dest_x,
+                                 gint         dest_y,
+                                 gint         width,
+                                 gint         height,
+                                 GdkRgbDither dither,
+                                 gint         x_dither,
+                                 gint         y_dither)
+{
+  GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
+  GdkDrawable *real_drawable = get_real_drawable (offscreen);
+
+  gdk_draw_pixbuf (real_drawable,
+                  gc,
+                  pixbuf,
+                  src_x,
+                  src_y,
+                  dest_x,
+                  dest_y,
+                  width,
+                  height,
+                  dither,
+                  x_dither,
+                  y_dither);
+
+  add_damage (offscreen, dest_x, dest_y, width, height);
+
+}
+
+void
+_gdk_offscreen_window_new (GdkWindow     *window,
+                          GdkScreen     *screen,
+                          GdkVisual     *visual,
+                          GdkWindowAttr *attributes,
+                          gint           attributes_mask)
+{
+  GdkWindowObject *parent_private;
+  GdkWindowObject *private;
+  GdkOffscreenWindow *offscreen;
+
+  g_return_if_fail (attributes != NULL);
+
+  if (attributes->wclass != GDK_INPUT_OUTPUT)
+    return; /* Can't support input only offscreens */
+
+  private = (GdkWindowObject *)window;
+
+  if (private->parent != NULL && GDK_WINDOW_DESTROYED (private->parent))
+    return;
+
+  parent_private = (GdkWindowObject*) private->parent;
+  private->impl = g_object_new (GDK_TYPE_OFFSCREEN_WINDOW, NULL);
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+  offscreen->wrapper = window;
+
+  offscreen->screen = screen;
+
+  if (attributes_mask & GDK_WA_COLORMAP)
+    offscreen->colormap = g_object_ref (attributes->colormap);
+  else
+    {
+      if (gdk_screen_get_system_visual (screen) == visual)
+       {
+         offscreen->colormap = gdk_screen_get_system_colormap (screen);
+         g_object_ref (offscreen->colormap);
+       }
+      else
+       offscreen->colormap = gdk_colormap_new (visual, FALSE);
+    }
+
+  offscreen->pixmap = gdk_pixmap_new ((GdkDrawable *)private->parent,
+                                     private->width,
+                                     private->height,
+                                     private->depth);
+}
+
+static gboolean
+gdk_offscreen_window_reparent (GdkWindow *window,
+                              GdkWindow *new_parent,
+                              gint       x,
+                              gint       y)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *new_parent_private = (GdkWindowObject *)new_parent;
+  GdkWindowObject *old_parent;
+  GdkOffscreenWindow *offscreen;
+  gboolean was_mapped;
+
+  if (new_parent)
+    {
+      /* No input-output children of input-only windows */
+      if (new_parent_private->input_only && !private->input_only)
+       return FALSE;
+
+      /* Don't create loops in hierarchy */
+      if (is_parent_of (window, new_parent))
+       return FALSE;
+    }
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+  was_mapped = GDK_WINDOW_IS_MAPPED (window);
+
+  gdk_window_hide (window);
+
+  if (private->parent)
+    private->parent->children = g_list_remove (private->parent->children, window);
+
+  old_parent = private->parent;
+  private->parent = new_parent_private;
+  private->x = x;
+  private->y = y;
+
+  if (new_parent_private)
+    private->parent->children = g_list_prepend (private->parent->children, window);
+
+  _gdk_syntesize_crossing_events_for_geometry_change (window);
+  if (old_parent)
+    _gdk_syntesize_crossing_events_for_geometry_change (GDK_WINDOW (old_parent));
+
+  return was_mapped;
+}
+
+
+static GdkWindow *
+get_offscreen_parent (GdkWindow *window)
+{
+  GdkWindowObject *private;
+  GdkWindow *res;
+
+  private = (GdkWindowObject *)window;
+
+  res = NULL;
+  g_signal_emit_by_name (private->impl_window,
+                        "get-offscreen-parent",
+                        &res);
+
+  return res;
+}
+
+static void
+from_parent (GdkWindow *window,
+            double parent_x, double parent_y,
+            double *offscreen_x, double *offscreen_y)
+{
+  GdkWindowObject *private;
+
+  private = (GdkWindowObject *)window;
+
+  g_signal_emit_by_name (private->impl_window,
+                        "from_parent",
+                        parent_x, parent_y,
+                        offscreen_x, offscreen_y,
+                        NULL);
+}
+
+static void
+to_parent (GdkWindow *window,
+          double offscreen_x, double offscreen_y,
+          double *parent_x, double *parent_y)
+{
+  GdkWindowObject *private;
+
+  private = (GdkWindowObject *)window;
+
+  g_signal_emit_by_name (private->impl_window,
+                        "to_parent",
+                        offscreen_x, offscreen_y,
+                        parent_x, parent_y,
+                        NULL);
+}
+
+static gint
+gdk_offscreen_window_get_root_coords (GdkWindow *window,
+                                     gint       x,
+                                     gint       y,
+                                     gint      *root_x,
+                                     gint      *root_y)
+{
+  GdkWindow *parent;
+  int tmpx, tmpy;
+
+  tmpx = x;
+  tmpy = y;
+
+  parent = get_offscreen_parent (window);
+  if (parent)
+    {
+      double dx, dy;
+      to_parent (window,
+                x, y,
+                &dx, &dy);
+      tmpx = floor (dx + 0.5);
+      tmpy = floor (dy + 0.5);
+      gdk_window_get_root_coords (parent,
+                                 tmpx, tmpy,
+                                 &tmpx, &tmpy);
+
+    }
+
+  if (root_x)
+    *root_x = tmpx;
+  if (root_y)
+    *root_y = tmpy;
+
+  return TRUE;
+}
+
+static gint
+gdk_offscreen_window_get_deskrelative_origin (GdkWindow *window,
+                                             gint      *x,
+                                             gint      *y)
+{
+  GdkWindow *parent;
+  int tmpx, tmpy;
+
+  tmpx = 0;
+  tmpy = 0;
+
+  parent = get_offscreen_parent (window);
+  if (parent)
+    {
+      double dx, dy;
+      gdk_window_get_deskrelative_origin (parent,
+                                         &tmpx, &tmpy);
+
+      to_parent (window,
+                0, 0,
+                &dx, &dy);
+      tmpx = floor (tmpx + dx + 0.5);
+      tmpy = floor (tmpy + dy + 0.5);
+    }
+
+
+  if (x)
+    *x = tmpx;
+  if (y)
+    *y = tmpy;
+
+  return TRUE;
+}
+
+static gboolean
+gdk_offscreen_window_get_pointer (GdkWindow       *window,
+                                 gint            *x,
+                                 gint            *y,
+                                 GdkModifierType *mask)
+{
+  int tmpx, tmpy;
+  double dtmpx, dtmpy;
+  GdkModifierType tmpmask;
+  GdkWindow *parent;
+
+  tmpx = 0;
+  tmpy = 0;
+  tmpmask = 0;
+
+  parent = get_offscreen_parent (window);
+  if (parent != NULL)
+    {
+      gdk_window_get_pointer (parent, &tmpx, &tmpy, &tmpmask);
+      from_parent (window,
+                  tmpx, tmpy,
+                  &dtmpx, &dtmpy);
+      tmpx = floor (dtmpx + 0.5);
+      tmpy = floor (dtmpy + 0.5);
+    }
+
+  if (x)
+    *x = tmpx;
+  if (y)
+    *y = tmpy;
+  if (mask)
+    *mask = tmpmask;
+  return TRUE;
+}
+
+/**
+ * gdk_window_get_offscreen_pixmap:
+ * @window: a #GdkWindow
+ *
+ * Gets the offscreen pixmap that an offscreen window renders into. If
+ * you need to keep this around over window resizes, you need to add a
+ * reference to it.
+ *
+ * Returns: The offscreen pixmap, or NULL if not offscreen
+ **/
+GdkPixmap *
+gdk_window_get_offscreen_pixmap (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkOffscreenWindow *offscreen;
+
+  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+
+  if (!GDK_IS_OFFSCREEN_WINDOW (private->impl))
+    return NULL;
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+  return offscreen->pixmap;
+}
+
+static void
+gdk_offscreen_window_raise (GdkWindow *window)
+{
+  /* gdk_window_raise already changed the stacking order */
+  _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
+
+static void
+gdk_offscreen_window_lower (GdkWindow *window)
+{
+  /* gdk_window_lower already changed the stacking order */
+  _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
+
+static void
+gdk_offscreen_window_move_resize_internal (GdkWindow *window,
+                                          gint       x,
+                                          gint       y,
+                                          gint       width,
+                                          gint       height,
+                                          gboolean   send_expose_events)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkOffscreenWindow *offscreen;
+  gint dx, dy, dw, dh;
+  GdkGC *gc;
+  GdkPixmap *old_pixmap;
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+  if (width < 1)
+    width = 1;
+  if (height < 1)
+    height = 1;
+
+  if (private->destroyed)
+    return;
+
+  dx = x - private->x;
+  dy = y - private->y;
+  dw = width - private->width;
+  dh = height - private->height;
+
+  private->x = x;
+  private->y = y;
+
+  if (private->width != width ||
+      private->height != height)
+    {
+      private->width = width;
+      private->height = height;
+
+      old_pixmap = offscreen->pixmap;
+      offscreen->pixmap = gdk_pixmap_new (GDK_DRAWABLE (old_pixmap),
+                                         width,
+                                         height,
+                                         private->depth);
+
+      gc = _gdk_drawable_get_scratch_gc (offscreen->pixmap, FALSE);
+      gdk_draw_drawable (offscreen->pixmap,
+                        gc,
+                        old_pixmap,
+                        0,0, 0, 0,
+                        -1, -1);
+      g_object_unref (old_pixmap);
+    }
+
+  if (GDK_WINDOW_IS_MAPPED (private))
+    {
+      // TODO: Only invalidate new area, i.e. for larger windows
+      gdk_window_invalidate_rect (window, NULL, TRUE);
+      _gdk_syntesize_crossing_events_for_geometry_change (window);
+    }
+}
+
+static void
+gdk_offscreen_window_move_resize (GdkWindow *window,
+                                 gboolean   with_move,
+                                 gint       x,
+                                 gint       y,
+                                 gint       width,
+                                 gint       height)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkOffscreenWindow *offscreen;
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+  if (!with_move)
+    {
+      x = private->x;
+      y = private->y;
+    }
+
+  if (width < 0)
+    width = private->width;
+
+  if (height < 0)
+    height = private->height;
+
+  gdk_offscreen_window_move_resize_internal (window, x, y,
+                                            width, height,
+                                            TRUE);
+}
+
+static void
+gdk_offscreen_window_show (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+
+  gdk_window_clear_area_e (window, 0, 0,
+                          private->width, private->height);
+}
+
+
+static void
+gdk_offscreen_window_hide (GdkWindow *window)
+{
+  GdkWindowObject *private;
+  GdkOffscreenWindow *offscreen;
+  GdkDisplay *display;
+
+  g_return_if_fail (window != NULL);
+
+  private = (GdkWindowObject*) window;
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+  /* May need to break grabs on children */
+  display = gdk_drawable_get_display (window);
+
+  /* TODO: This needs updating to the new grab world */
+#if 0
+  if (display->pointer_grab.window != NULL)
+    {
+      if (is_parent_of (window, display->pointer_grab.window))
+       {
+         /* Call this ourselves, even though gdk_display_pointer_ungrab
+            does so too, since we want to pass implicit == TRUE so the
+            broken grab event is generated */
+         _gdk_display_unset_has_pointer_grab (display,
+                                              TRUE,
+                                              FALSE,
+                                              GDK_CURRENT_TIME);
+         gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
+       }
+    }
+#endif
+}
+
+static void
+gdk_offscreen_window_withdraw (GdkWindow *window)
+{
+}
+
+static GdkEventMask
+gdk_offscreen_window_get_events (GdkWindow *window)
+{
+  return 0;
+}
+
+static void
+gdk_offscreen_window_set_events (GdkWindow       *window,
+                                GdkEventMask     event_mask)
+{
+}
+
+static void
+gdk_offscreen_window_set_background (GdkWindow      *window,
+                                    const GdkColor *color)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkColormap *colormap = gdk_drawable_get_colormap (window);
+
+  private->bg_color = *color;
+  gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
+
+  if (private->bg_pixmap &&
+      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+      private->bg_pixmap != GDK_NO_BG)
+    g_object_unref (private->bg_pixmap);
+
+  private->bg_pixmap = NULL;
+}
+
+static void
+gdk_offscreen_window_set_back_pixmap (GdkWindow *window,
+                                     GdkPixmap *pixmap)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+
+  if (pixmap &&
+      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+      private->bg_pixmap != GDK_NO_BG &&
+      !gdk_drawable_get_colormap (pixmap))
+    {
+      g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
+      return;
+    }
+
+  if (private->bg_pixmap &&
+      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+      private->bg_pixmap != GDK_NO_BG)
+    g_object_unref (private->bg_pixmap);
+
+  private->bg_pixmap = pixmap;
+
+  if (pixmap &&
+      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+      private->bg_pixmap != GDK_NO_BG)
+    g_object_ref (pixmap);
+}
+
+static void
+gdk_offscreen_window_shape_combine_region (GdkWindow       *window,
+                                          const GdkRegion *shape_region,
+                                          gint             offset_x,
+                                          gint             offset_y)
+{
+}
+
+static void
+gdk_offscreen_window_input_shape_combine_region (GdkWindow       *window,
+                                                const GdkRegion *shape_region,
+                                                gint             offset_x,
+                                                gint             offset_y)
+{
+}
+
+static gboolean
+gdk_offscreen_window_set_static_gravities (GdkWindow *window,
+                                          gboolean   use_static)
+{
+  return TRUE;
+}
+
+static void
+gdk_offscreen_window_set_cursor (GdkWindow *window,
+                                GdkCursor *cursor)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkOffscreenWindow *offscreen;
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+  if (offscreen->cursor)
+    {
+      gdk_cursor_unref (offscreen->cursor);
+      offscreen->cursor = NULL;
+    }
+
+  if (cursor)
+    offscreen->cursor = gdk_cursor_ref (cursor);
+
+  /* TODO: The cursor is never actually used... */
+}
+
+static void
+gdk_offscreen_window_get_geometry (GdkWindow *window,
+                                  gint      *x,
+                                  gint      *y,
+                                  gint      *width,
+                                  gint      *height,
+                                  gint      *depth)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkOffscreenWindow *offscreen;
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+  g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
+
+  if (!GDK_WINDOW_DESTROYED (window))
+    {
+      if (x)
+       *x = private->x;
+      if (y)
+       *y = private->y;
+      if (width)
+       *width = private->width;
+      if (height)
+       *height = private->height;
+      if (depth)
+       *depth = private->depth;
+    }
+}
+
+static gboolean
+gdk_offscreen_window_queue_antiexpose (GdkWindow *window,
+                                      GdkRegion *area)
+{
+  return FALSE;
+}
+
+static void
+gdk_offscreen_window_queue_translation (GdkWindow *window,
+                                       GdkRegion *area,
+                                       gint       dx,
+                                       gint       dy)
+{
+}
+
+
+static void
+gdk_offscreen_window_class_init (GdkOffscreenWindowClass *klass)
+{
+  GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = gdk_offscreen_window_finalize;
+
+  drawable_class->create_gc = gdk_offscreen_window_create_gc;
+  drawable_class->_copy_to_image = gdk_offscreen_window_copy_to_image;
+  drawable_class->ref_cairo_surface = gdk_offscreen_window_ref_cairo_surface;
+  drawable_class->set_colormap = gdk_offscreen_window_set_colormap;
+  drawable_class->get_colormap = gdk_offscreen_window_get_colormap;
+  drawable_class->get_depth = gdk_offscreen_window_get_depth;
+  drawable_class->get_screen = gdk_offscreen_window_get_screen;
+  drawable_class->get_visual = gdk_offscreen_window_get_visual;
+  drawable_class->get_source_drawable = gdk_offscreen_window_get_source_drawable;
+  drawable_class->get_composite_drawable = gdk_offscreen_window_get_composite_drawable;
+
+  drawable_class->draw_rectangle = gdk_offscreen_window_draw_rectangle;
+  drawable_class->draw_arc = gdk_offscreen_window_draw_arc;
+  drawable_class->draw_polygon = gdk_offscreen_window_draw_polygon;
+  drawable_class->draw_text = gdk_offscreen_window_draw_text;
+  drawable_class->draw_text_wc = gdk_offscreen_window_draw_text_wc;
+  drawable_class->draw_drawable = gdk_offscreen_window_draw_drawable;
+  drawable_class->draw_points = gdk_offscreen_window_draw_points;
+  drawable_class->draw_segments = gdk_offscreen_window_draw_segments;
+  drawable_class->draw_lines = gdk_offscreen_window_draw_lines;
+  drawable_class->draw_image = gdk_offscreen_window_draw_image;
+  drawable_class->draw_pixbuf = gdk_offscreen_window_draw_pixbuf;
+}
+
+static void
+gdk_offscreen_window_impl_iface_init (GdkWindowImplIface *iface)
+{
+  iface->show = gdk_offscreen_window_show;
+  iface->hide = gdk_offscreen_window_hide;
+  iface->withdraw = gdk_offscreen_window_withdraw;
+  iface->raise = gdk_offscreen_window_raise;
+  iface->lower = gdk_offscreen_window_lower;
+  iface->move_resize = gdk_offscreen_window_move_resize;
+  iface->set_background = gdk_offscreen_window_set_background;
+  iface->set_back_pixmap = gdk_offscreen_window_set_back_pixmap;
+  iface->get_events = gdk_offscreen_window_get_events;
+  iface->set_events = gdk_offscreen_window_set_events;
+  iface->reparent = gdk_offscreen_window_reparent;
+  iface->set_cursor = gdk_offscreen_window_set_cursor;
+  iface->get_geometry = gdk_offscreen_window_get_geometry;
+  iface->shape_combine_region = gdk_offscreen_window_shape_combine_region;
+  iface->input_shape_combine_region = gdk_offscreen_window_input_shape_combine_region;
+  iface->set_static_gravities = gdk_offscreen_window_set_static_gravities;
+  iface->queue_antiexpose = gdk_offscreen_window_queue_antiexpose;
+  iface->queue_translation = gdk_offscreen_window_queue_translation;
+  iface->get_root_coords = gdk_offscreen_window_get_root_coords;
+  iface->get_deskrelative_origin = gdk_offscreen_window_get_deskrelative_origin;
+  iface->get_pointer = gdk_offscreen_window_get_pointer;
+  iface->destroy = gdk_offscreen_window_destroy;
+}
+
+#define __GDK_OFFSCREEN_WINDOW_C__
+#include "gdkaliasdef.c"
index a38640374b66dcf694d5b6a83d90d80198e691b5..24efca8b2918dbff6420745fad7dfd363773b69c 100644 (file)
@@ -214,7 +214,8 @@ get_cairo_context (GdkPangoRenderer *gdk_renderer,
                                  priv->cr,
                                  color,
                                  priv->stipple[part],
-                                 priv->gc_changed);
+                                 priv->gc_changed,
+                                 priv->drawable);
        }
 
       priv->last_part = part;
index c717b9afb825c57a0e96ebff257d33a886c2f53d..e4d8869286b5ac3118c0922900e9f5a0e26df7bf 100644 (file)
@@ -72,6 +72,7 @@ static void   gdk_pixmap_draw_text_wc   (GdkDrawable     *drawable,
 static void   gdk_pixmap_draw_drawable  (GdkDrawable     *drawable,
                                         GdkGC           *gc,
                                         GdkPixmap       *src,
+                                        GdkPixmap       *original_src,
                                         gint             xsrc,
                                         gint             ysrc,
                                         gint             xdest,
@@ -145,6 +146,9 @@ static GdkImage* gdk_pixmap_copy_to_image (GdkDrawable *drawable,
                                           gint         height);
 
 static cairo_surface_t *gdk_pixmap_ref_cairo_surface (GdkDrawable *drawable);
+static cairo_surface_t *gdk_pixmap_create_cairo_surface (GdkDrawable *drawable,
+                                                        int width,
+                                                        int height);
 
 static GdkVisual*   gdk_pixmap_real_get_visual   (GdkDrawable *drawable);
 static gint         gdk_pixmap_real_get_depth    (GdkDrawable *drawable);
@@ -216,6 +220,7 @@ gdk_pixmap_class_init (GdkPixmapObjectClass *klass)
   drawable_class->get_visual = gdk_pixmap_real_get_visual;
   drawable_class->_copy_to_image = gdk_pixmap_copy_to_image;
   drawable_class->ref_cairo_surface = gdk_pixmap_ref_cairo_surface;
+  drawable_class->create_cairo_surface = gdk_pixmap_create_cairo_surface;
 }
 
 static void
@@ -229,6 +234,54 @@ gdk_pixmap_finalize (GObject *object)
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
+GdkPixmap *
+gdk_pixmap_new (GdkDrawable *drawable,
+                gint         width,
+                gint         height,
+                gint         depth)
+{
+  GdkDrawable *source_drawable;
+
+  if (drawable)
+    source_drawable = _gdk_drawable_get_source_drawable (drawable);
+  else
+    source_drawable = NULL;
+  return _gdk_pixmap_new (source_drawable, width, height, depth);
+}
+
+GdkPixmap *
+gdk_bitmap_create_from_data (GdkDrawable *drawable,
+                             const gchar *data,
+                             gint         width,
+                             gint         height)
+{
+  GdkDrawable *source_drawable;
+
+  if (drawable)
+    source_drawable = _gdk_drawable_get_source_drawable (drawable);
+  else
+    source_drawable = NULL;
+  return _gdk_bitmap_create_from_data (source_drawable, data, width, height);
+}
+
+GdkPixmap*
+gdk_pixmap_create_from_data (GdkDrawable    *drawable,
+                             const gchar    *data,
+                             gint            width,
+                             gint            height,
+                             gint            depth,
+                             const GdkColor *fg,
+                             const GdkColor *bg)
+{
+  GdkDrawable *source_drawable;
+
+  source_drawable = _gdk_drawable_get_source_drawable (drawable);
+  return _gdk_pixmap_create_from_data (source_drawable,
+                                       data, width, height,
+                                       depth, fg,bg);
+}
+
+
 static GdkGC *
 gdk_pixmap_create_gc (GdkDrawable     *drawable,
                       GdkGCValues     *values,
@@ -249,6 +302,7 @@ gdk_pixmap_draw_rectangle (GdkDrawable *drawable,
 {
   GdkPixmapObject *private = (GdkPixmapObject *)drawable;
 
+  _gdk_gc_remove_drawable_clip (gc);  
   gdk_draw_rectangle (private->impl, gc, filled,
                       x, y, width, height);
 }
@@ -266,6 +320,7 @@ gdk_pixmap_draw_arc (GdkDrawable *drawable,
 {
   GdkPixmapObject *private = (GdkPixmapObject *)drawable;
 
+  _gdk_gc_remove_drawable_clip (gc);  
   gdk_draw_arc (private->impl, gc, filled,
                 x, y,
                 width, height, angle1, angle2);
@@ -280,6 +335,7 @@ gdk_pixmap_draw_polygon (GdkDrawable *drawable,
 {
   GdkPixmapObject *private = (GdkPixmapObject *)drawable;
 
+  _gdk_gc_remove_drawable_clip (gc);  
   gdk_draw_polygon (private->impl, gc, filled, points, npoints);
 }
 
@@ -294,6 +350,7 @@ gdk_pixmap_draw_text (GdkDrawable *drawable,
 {
   GdkPixmapObject *private = (GdkPixmapObject *)drawable;
 
+  _gdk_gc_remove_drawable_clip (gc);  
   gdk_draw_text (private->impl, font, gc,
                  x, y, text, text_length);
 }
@@ -309,6 +366,7 @@ gdk_pixmap_draw_text_wc (GdkDrawable    *drawable,
 {
   GdkPixmapObject *private = (GdkPixmapObject *)drawable;
 
+  _gdk_gc_remove_drawable_clip (gc);  
   gdk_draw_text_wc (private->impl, font, gc,
                     x, y, text, text_length);
 }
@@ -317,6 +375,7 @@ static void
 gdk_pixmap_draw_drawable (GdkDrawable *drawable,
                          GdkGC       *gc,
                          GdkPixmap   *src,
+                         GdkPixmap   *original_src,
                          gint         xsrc,
                          gint         ysrc,
                          gint         xdest,
@@ -326,6 +385,7 @@ gdk_pixmap_draw_drawable (GdkDrawable *drawable,
 {
   GdkPixmapObject *private = (GdkPixmapObject *)drawable;
 
+  _gdk_gc_remove_drawable_clip (gc);  
   gdk_draw_drawable (private->impl, gc, src, xsrc, ysrc,
                      xdest, ydest,
                      width, height);
@@ -339,6 +399,7 @@ gdk_pixmap_draw_points (GdkDrawable *drawable,
 {
   GdkPixmapObject *private = (GdkPixmapObject *)drawable;
 
+  _gdk_gc_remove_drawable_clip (gc);  
   gdk_draw_points (private->impl, gc, points, npoints);
 }
 
@@ -350,6 +411,7 @@ gdk_pixmap_draw_segments (GdkDrawable *drawable,
 {
   GdkPixmapObject *private = (GdkPixmapObject *)drawable;
 
+  _gdk_gc_remove_drawable_clip (gc);  
   gdk_draw_segments (private->impl, gc, segs, nsegs);
 }
 
@@ -361,6 +423,7 @@ gdk_pixmap_draw_lines (GdkDrawable *drawable,
 {
   GdkPixmapObject *private = (GdkPixmapObject *)drawable;
 
+  _gdk_gc_remove_drawable_clip (gc);  
   gdk_draw_lines (private->impl, gc, points, npoints);
 }
 
@@ -374,6 +437,7 @@ gdk_pixmap_draw_glyphs (GdkDrawable      *drawable,
 {
   GdkPixmapObject *private = (GdkPixmapObject *)drawable;
 
+  _gdk_gc_remove_drawable_clip (gc);  
   gdk_draw_glyphs (private->impl, gc, font, x, y, glyphs);
 }
 
@@ -388,6 +452,7 @@ gdk_pixmap_draw_glyphs_transformed (GdkDrawable      *drawable,
 {
   GdkPixmapObject *private = (GdkPixmapObject *)drawable;
 
+  _gdk_gc_remove_drawable_clip (gc);  
   gdk_draw_glyphs_transformed (private->impl, gc, matrix, font, x, y, glyphs);
 }
 
@@ -404,6 +469,7 @@ gdk_pixmap_draw_image (GdkDrawable     *drawable,
 {
   GdkPixmapObject *private = (GdkPixmapObject *)drawable;
 
+  _gdk_gc_remove_drawable_clip (gc);  
   gdk_draw_image (private->impl, gc, image, xsrc, ysrc, xdest, ydest,
                   width, height);
 }
@@ -424,6 +490,8 @@ gdk_pixmap_draw_pixbuf (GdkDrawable     *drawable,
 {
   GdkPixmapObject *private = (GdkPixmapObject *)drawable;
 
+  if (gc)
+    _gdk_gc_remove_drawable_clip (gc);  
   gdk_draw_pixbuf (private->impl, gc, pixbuf,
                   src_x, src_y, dest_x, dest_y, width, height,
                   dither, x_dither, y_dither);
@@ -437,6 +505,7 @@ gdk_pixmap_draw_trapezoids (GdkDrawable     *drawable,
 {
   GdkPixmapObject *private = (GdkPixmapObject *)drawable;
 
+  _gdk_gc_remove_drawable_clip (gc);  
   gdk_draw_trapezoids (private->impl, gc, trapezoids, n_trapezoids);
 }
 
@@ -515,6 +584,17 @@ gdk_pixmap_ref_cairo_surface (GdkDrawable *drawable)
   return _gdk_drawable_ref_cairo_surface (((GdkPixmapObject*)drawable)->impl);
 }
 
+static cairo_surface_t *
+gdk_pixmap_create_cairo_surface (GdkDrawable *drawable,
+                                int width,
+                                int height)
+{
+  return _gdk_windowing_create_cairo_surface (GDK_PIXMAP_OBJECT(drawable)->impl,
+                                             width, height);
+}
+
+
+
 static GdkBitmap *
 make_solid_mask (GdkScreen *screen, gint width, gint height)
 {
index f835ab7d6f656b886c695acc4510d9dc52dc8a71..d98dc8822db262a409e57654d2ac8e0db3b20770 100644 (file)
@@ -96,6 +96,7 @@ static void miRegionOp   (GdkRegion       *newReg,
                          overlapFunc      overlapFn,
                          nonOverlapFunc   nonOverlap1Fn,
                          nonOverlapFunc   nonOverlap2Fn);
+static void miSetExtents (GdkRegion       *pReg);
 
 /**
  * gdk_region_new:
@@ -122,6 +123,31 @@ gdk_region_new (void)
   return temp;
 }
 
+GdkRegion *
+_gdk_region_new_from_yxbanded_rects (GdkRectangle *rects,
+                                    int num_rects)
+{
+  GdkRegion *temp;
+  int i;
+
+  temp = g_slice_new (GdkRegion);
+
+  temp->rects = g_new (GdkRegionBox, num_rects);
+  temp->size = num_rects;
+  temp->numRects = num_rects;
+  for (i = 0; i < num_rects; i++)
+    {
+      temp->rects[i].x1 = rects[i].x;
+      temp->rects[i].y1 = rects[i].y;
+      temp->rects[i].x2 = rects[i].x + rects[i].width;
+      temp->rects[i].y2 = rects[i].y + rects[i].height;
+    }
+  miSetExtents (temp);  
+  
+  return temp;
+}
+
+
 /**
  * gdk_region_rectangle:
  * @rectangle: a #GdkRectangle
@@ -1555,6 +1581,32 @@ gdk_region_equal (const GdkRegion *region1,
   return TRUE;
 }
 
+/**
+ * gdk_region_rect_equal:
+ * @region: a #GdkRegion
+ * @rectangle: a #GdkRectangle
+ *
+ * Finds out if a regions is the same as a rectangle.
+ *
+ * Returns: %TRUE if @region and @rectangle are equal.
+ *
+ * Since: 2.18
+ */
+gboolean
+gdk_region_rect_equal (const GdkRegion    *region,
+                      const GdkRectangle *rectangle)
+{
+  g_return_val_if_fail (region != NULL, FALSE);
+  g_return_val_if_fail (rectangle != NULL, FALSE);
+
+  if (region->numRects != 1) return FALSE;
+  else if (region->extents.x1 != rectangle->x) return FALSE;
+  else if (region->extents.y1 != rectangle->y) return FALSE;
+  else if (region->extents.x2 != rectangle->x + rectangle->width) return FALSE;
+  else if (region->extents.y2 != rectangle->y + rectangle->height) return FALSE;
+  return TRUE;
+}
+
 /**
  * gdk_region_point_in:
  * @region: a #GdkRegion
index b7381eaf4dccc6b0af07d3996b37087191744c35..415cd24b77c6d00185cfa5d706c4dd2ef692d13e 100644 (file)
@@ -77,6 +77,8 @@ void           gdk_region_get_rectangles  (const GdkRegion    *region,
 gboolean       gdk_region_empty           (const GdkRegion    *region);
 gboolean       gdk_region_equal           (const GdkRegion    *region1,
                                            const GdkRegion    *region2);
+gboolean       gdk_region_rect_equal      (const GdkRegion    *region1,
+                                           const GdkRectangle *rectangle);
 gboolean       gdk_region_point_in        (const GdkRegion    *region,
                                            int                 x,
                                            int                 y);
index b1f3b8e8a7fb908c53b060333284d149acf1f09c..96ff8d44a2f112ac7194f2fc28111ddaeae2681e 100644 (file)
@@ -51,6 +51,7 @@ struct _GdkScreen
 
   GdkGC *normal_gcs[32];
   GdkGC *exposure_gcs[32];
+  GdkGC *subwindow_gcs[32];
 
   cairo_font_options_t *font_options;
   double resolution;           /* pixels/points scale factor for fonts */
index 76a2ec618d665b2c08a082df610ccfebb452e3b9..ce478b54210db0aa47e532c2a45cde29d6081d5f 100644 (file)
@@ -22,7 +22,7 @@
  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
  * file for a list of people on the GTK+ Team.  See the ChangeLog
  * files for a list of changes.  These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
  */
 
 #include "config.h"
 #include "gdkpixmap.h"
 #include "gdkdrawable.h"
 #include "gdkscreen.h"
+#include "gdkmarshalers.h"
 #include "gdkalias.h"
 
+#undef DEBUG_WINDOW_PRINTING
+
+#ifdef GDK_WINDOWING_X11
+#include "x11/gdkx.h"           /* For workaround */
+#endif
+
+#include "math.h"
+
+/* Historically a GdkWindow always matches a platform native window,
+ * be it a toplevel window or a child window. In this setup the
+ * GdkWindow (and other GdkDrawables) were platform independent classes,
+ * and the actual platform specific implementation was in a delegate
+ * object availible as "impl" in the window object.
+ *
+ * With the addition of client side windows and offscreen windows this
+ * changes a bit. The application-visible GdkWindow object behaves as
+ * it did before, but not all such windows now have a corresponding native
+ * window. Instead windows that are "client side" are emulated by the gdk
+ * code such that clipping, drawing, moving, events etc work as expected.
+ *
+ * For GdkWindows that have a native window the "impl" object is the
+ * same as before. However, for all client side windows the impl object
+ * is shared with its parent (i.e. all client windows descendants of one
+ * native window has the same impl.
+ *
+ * Additionally there is a new type of platform independent impl object,
+ * GdkOffscreenWindow. All windows of type GDK_WINDOW_OFFSCREEN get an impl
+ * of this type (while their children are generally GDK_WINDOW_CHILD virtual
+ * windows). Such windows work by allocating a GdkPixmap as the backing store
+ * for drawing operations, which is resized with the window.
+ *
+ * GdkWindows have a pointer to the "impl window" they are in, i.e.
+ * the topmost GdkWindow which have the same "impl" value. This is stored
+ * in impl_window, which is different from the window itself only for client
+ * side windows.
+ * All GdkWindows (native or not) track the position of the window in the parent
+ * (x, y), the size of the window (width, height), the position of the window
+ * with respect to the impl window (abs_x, abs_y). We also track the clip
+ * region of the window wrt parent windows and siblings, in window-relative
+ * coordinates with and without child windows included (clip_region,
+ * clip_region_with_children).
+ *
+ * All toplevel windows are native windows, but also child windows can be
+ * native (although not children of offscreens). We always listen to
+ * a basic set of events (see get_native_event_mask) for these windows
+ * so that we can emulate events for any client side children.
+ *
+ * For native windows we apply the calculated clip region as a window shape
+ * so that eg. client side siblings that overlap the native child properly
+ * draws over the native child window.
+ *
+ * In order to minimize flicker and for performance we use a couple of cacheing
+ * tricks. First of all, every time we do a window to window copy area, for instance
+ * when moving a client side window or when scrolling/moving a region in a window
+ * we store this in outstanding_moves instead of applying immediately. We then
+ * delay this move until we really need it (because something depends on being
+ * able to read it), or until we're handing a redraw from an expose/invalidation
+ * (actually we delay it past redraw, but before blitting the double buffer pixmap
+ * to the window). This gives us two advantages. First of all it minimizes the time
+ * from the window is moved to the exposes related to that move, secondly it allows
+ * us to be smart about how to do the copy. We combine multiple moves into one (when
+ * possible) and we don't actually do copies to anything that is or will be
+ * invalidated and exposed anyway.
+ *
+ * Secondly, we use something called a "implicit paint" during repaint handling.
+ * An implicit paint is similar to a regular paint for the paint stack, but it is
+ * not put on the stack. Instead, it is set on the impl window, and later when
+ * regular gdk_window_begin_paint_region()  happen on a window of this impl window
+ * we reuse the pixmap from the implicit paint. During repaint we create and at the
+ * end flush an implicit paint, which means we can collect all the paints on
+ * multiple client side windows in the same backing store pixmap.
+ *
+ * All drawing to windows are wrapped with macros that set up the GC such that
+ * the offsets and clip region is right for drawing to the paint object or
+ * directly to the emulated window. It also automatically handles any flushing
+ * needed when drawing directly to a window. Adding window/paint clipping is
+ * done using _gdk_gc_add_drawable_clip which lets us efficiently add and then
+ * remove a custom clip region.
+ */
+
 #define USE_BACKING_STORE      /* Appears to work on Win32, too, now. */
 
-typedef struct _GdkWindowPaint GdkWindowPaint;
+/* This adds a local value to the GdkVisibilityState enum */
+#define GDK_VISIBILITY_NOT_VIEWABLE 3
+
+enum {
+  GET_OFFSCREEN_PARENT,
+  PICK_OFFSCREEN_CHILD, /* only called if has_offscreen_children */
+  TO_PARENT,
+  FROM_PARENT,
+  LAST_SIGNAL
+};
 
 struct _GdkWindowPaint
 {
@@ -46,83 +136,74 @@ struct _GdkWindowPaint
   gint x_offset;
   gint y_offset;
   cairo_surface_t *surface;
+  guint uses_implicit : 1;
+  guint32 region_tag;
 };
 
 typedef struct {
-  GdkRegion *old_region;
-  gint old_clip_x_origin;
-  gint old_clip_y_origin;
-  gint x_offset;
-  gint y_offset;
-} GdkWindowClipData;
-
-struct _GdkWindowRedirect
-{
-  GdkWindowObject *redirected;
-  GdkDrawable *pixmap;
-  gint src_x;
-  gint src_y;
-  gint dest_x;
-  gint dest_y;
-  gint width;
-  gint height;
-};
+  GdkRegion *dest_region; /* The destination region */
+  int dx, dy; /* The amount that the source was moved to reach dest_region */
+} GdkWindowRegionMove;
+
+
+/* Global info */
 
 static GdkGC *gdk_window_create_gc      (GdkDrawable     *drawable,
-                                         GdkGCValues     *values,
-                                         GdkGCValuesMask  mask);
+                                        GdkGCValues     *values,
+                                        GdkGCValuesMask  mask);
 static void   gdk_window_draw_rectangle (GdkDrawable     *drawable,
-                                         GdkGC           *gc,
-                                         gboolean         filled,
-                                         gint             x,
-                                         gint             y,
-                                         gint             width,
-                                         gint             height);
+                                        GdkGC           *gc,
+                                        gboolean         filled,
+                                        gint             x,
+                                        gint             y,
+                                        gint             width,
+                                        gint             height);
 static void   gdk_window_draw_arc       (GdkDrawable     *drawable,
-                                         GdkGC           *gc,
-                                         gboolean         filled,
-                                         gint             x,
-                                         gint             y,
-                                         gint             width,
-                                         gint             height,
-                                         gint             angle1,
-                                         gint             angle2);
+                                        GdkGC           *gc,
+                                        gboolean         filled,
+                                        gint             x,
+                                        gint             y,
+                                        gint             width,
+                                        gint             height,
+                                        gint             angle1,
+                                        gint             angle2);
 static void   gdk_window_draw_polygon   (GdkDrawable     *drawable,
-                                         GdkGC           *gc,
-                                         gboolean         filled,
-                                         GdkPoint        *points,
-                                         gint             npoints);
+                                        GdkGC           *gc,
+                                        gboolean         filled,
+                                        GdkPoint        *points,
+                                        gint             npoints);
 static void   gdk_window_draw_text      (GdkDrawable     *drawable,
-                                         GdkFont         *font,
-                                         GdkGC           *gc,
-                                         gint             x,
-                                         gint             y,
-                                         const gchar     *text,
-                                         gint             text_length);
+                                        GdkFont         *font,
+                                        GdkGC           *gc,
+                                        gint             x,
+                                        gint             y,
+                                        const gchar     *text,
+                                        gint             text_length);
 static void   gdk_window_draw_text_wc   (GdkDrawable     *drawable,
-                                         GdkFont         *font,
-                                         GdkGC           *gc,
-                                         gint             x,
-                                         gint             y,
-                                         const GdkWChar  *text,
-                                         gint             text_length);
+                                        GdkFont         *font,
+                                        GdkGC           *gc,
+                                        gint             x,
+                                        gint             y,
+                                        const GdkWChar  *text,
+                                        gint             text_length);
 static void   gdk_window_draw_drawable  (GdkDrawable     *drawable,
-                                         GdkGC           *gc,
-                                         GdkPixmap       *src,
-                                         gint             xsrc,
-                                         gint             ysrc,
-                                         gint             xdest,
-                                         gint             ydest,
-                                         gint             width,
-                                         gint             height);
+                                        GdkGC           *gc,
+                                        GdkPixmap       *src,
+                                        GdkDrawable     *original_src,
+                                        gint             xsrc,
+                                        gint             ysrc,
+                                        gint             xdest,
+                                        gint             ydest,
+                                        gint             width,
+                                        gint             height);
 static void   gdk_window_draw_points    (GdkDrawable     *drawable,
-                                         GdkGC           *gc,
-                                         GdkPoint        *points,
-                                         gint             npoints);
+                                        GdkGC           *gc,
+                                        GdkPoint        *points,
+                                        gint             npoints);
 static void   gdk_window_draw_segments  (GdkDrawable     *drawable,
-                                         GdkGC           *gc,
-                                         GdkSegment      *segs,
-                                         gint             nsegs);
+                                        GdkGC           *gc,
+                                        GdkSegment      *segs,
+                                        gint             nsegs);
 static void   gdk_window_draw_lines     (GdkDrawable     *drawable,
                                         GdkGC           *gc,
                                         GdkPoint        *points,
@@ -143,14 +224,14 @@ static void gdk_window_draw_glyphs_transformed (GdkDrawable      *drawable,
                                                PangoGlyphString *glyphs);
 
 static void   gdk_window_draw_image     (GdkDrawable     *drawable,
-                                         GdkGC           *gc,
-                                         GdkImage        *image,
-                                         gint             xsrc,
-                                         gint             ysrc,
-                                         gint             xdest,
-                                         gint             ydest,
-                                         gint             width,
-                                         gint             height);
+                                        GdkGC           *gc,
+                                        GdkImage        *image,
+                                        gint             xsrc,
+                                        gint             ysrc,
+                                        gint             xdest,
+                                        gint             ydest,
+                                        gint             width,
+                                        gint             height);
 
 static void gdk_window_draw_pixbuf (GdkDrawable     *drawable,
                                    GdkGC           *gc,
@@ -180,10 +261,15 @@ static GdkImage* gdk_window_copy_to_image (GdkDrawable *drawable,
                                           gint         height);
 
 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_set_cairo_clip    (GdkDrawable *drawable,
+                                                     cairo_t *cr);
 
 static void   gdk_window_real_get_size  (GdkDrawable     *drawable,
-                                         gint            *width,
-                                         gint            *height);
+                                        gint            *width,
+                                        gint            *height);
 
 static GdkVisual*   gdk_window_real_get_visual   (GdkDrawable *drawable);
 static gint         gdk_window_real_get_depth    (GdkDrawable *drawable);
@@ -192,6 +278,7 @@ static void         gdk_window_real_set_colormap (GdkDrawable *drawable,
                                                  GdkColormap *cmap);
 static GdkColormap* gdk_window_real_get_colormap (GdkDrawable *drawable);
 
+static GdkDrawable* gdk_window_get_source_drawable    (GdkDrawable *drawable);
 static GdkDrawable* gdk_window_get_composite_drawable (GdkDrawable *drawable,
                                                       gint         x,
                                                       gint         y,
@@ -207,31 +294,44 @@ 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_clear_backing_rect (GdkWindow *window,
-                                          gint       x,
-                                          gint       y,
-                                          gint       width,
-                                          gint       height);
-static void setup_redirect_clip           (GdkWindow         *window,
-                                          GdkGC             *gc,
-                                          GdkWindowClipData *data);
-static void reset_redirect_clip           (GdkWindow         *offscreen,
-                                          GdkGC             *gc,
-                                          GdkWindowClipData *data);
+static void gdk_window_clear_backing_region (GdkWindow *window,
+                                            GdkRegion *region);
 static void gdk_window_redirect_free      (GdkWindowRedirect *redirect);
 static void apply_redirect_to_children    (GdkWindowObject   *private,
                                           GdkWindowRedirect *redirect);
 static void remove_redirect_from_children (GdkWindowObject   *private,
                                           GdkWindowRedirect *redirect);
-static GdkRegion *_gdk_window_calculate_full_clip_region (GdkWindow *window,
-                                                         GdkWindow *base_window,
-                                                         GdkGC *gc,
-                                                         gboolean do_children,
-                                                         gint *base_x_offset,
-                                                         gint *base_y_offset);
+
+static void recompute_visible_regions   (GdkWindowObject *private,
+                                        gboolean recalculate_siblings,
+                                        gboolean recalculate_children);
+static void gdk_window_flush_outstanding_moves (GdkWindow *window);
+static void gdk_window_flush            (GdkWindow *window);
+static void gdk_window_flush_recursive  (GdkWindowObject *window);
+static void do_move_region_bits_on_impl (GdkWindowObject *private,
+                                        GdkRegion *region, /* In impl window coords */
+                                        int dx, int dy);
+static void gdk_window_invalidate_in_parent (GdkWindowObject *private);
+static GdkWindow *gdk_window_get_offscreen_parent (GdkWindow *window);
+static void move_native_children (GdkWindowObject *private);
+static void update_cursor (GdkDisplay *display);
+static gboolean is_event_parent_of (GdkWindow *parent,
+                                   GdkWindow *child);
+
+static guint signals[LAST_SIGNAL] = { 0 };
 
 static gpointer parent_class = NULL;
 
+static const cairo_user_data_key_t gdk_window_cairo_key;
+
+static guint32
+new_region_tag (void)
+{
+  static guint32 tag = 0;
+
+  return ++tag;
+}
+
 GType
 gdk_window_object_get_type (void)
 {
@@ -245,7 +345,7 @@ gdk_window_object_get_type (void)
                                                 sizeof (GdkWindowObject),
                                                 (GInstanceInitFunc) gdk_window_init,
                                                 0);
-  
+
   return object_type;
 }
 
@@ -281,6 +381,26 @@ gdk_window_init (GdkWindowObject *window)
   window->window_type = GDK_WINDOW_CHILD;
 
   window->state = GDK_WINDOW_STATE_WITHDRAWN;
+  window->width = 1;
+  window->height = 1;
+  window->toplevel_window_type = -1;
+  /* starts hidden */
+  window->effective_visibility = GDK_VISIBILITY_NOT_VIEWABLE;
+  window->visibility = GDK_VISIBILITY_FULLY_OBSCURED;
+  /* Default to unobscured since some backends don't send visibility events */
+  window->native_visibility = GDK_VISIBILITY_UNOBSCURED;
+}
+
+/* Stop and return on the first non-NULL parent */
+static gboolean
+accumulate_get_parent  (GSignalInvocationHint *ihint,
+                        GValue                *return_accu,
+                        const GValue          *handler_return,
+                        gpointer               data)
+{
+  g_value_copy (handler_return, return_accu);
+  /* Continue while returning NULL */
+  return g_value_get_object (handler_return) == NULL;
 }
 
 static GQuark quark_pointer_window = 0;
@@ -290,7 +410,7 @@ gdk_window_class_init (GdkWindowObjectClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
   GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
-  
+
   parent_class = g_type_class_peek_parent (klass);
 
   object_class->finalize = gdk_window_finalize;
@@ -318,11 +438,62 @@ gdk_window_class_init (GdkWindowObjectClass *klass)
   drawable_class->get_visual = gdk_window_real_get_visual;
   drawable_class->_copy_to_image = gdk_window_copy_to_image;
   drawable_class->ref_cairo_surface = gdk_window_ref_cairo_surface;
+  drawable_class->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;
   drawable_class->get_composite_drawable = gdk_window_get_composite_drawable;
+  drawable_class->get_source_drawable = gdk_window_get_source_drawable;
 
   quark_pointer_window = g_quark_from_static_string ("gtk-pointer-window");
+
+
+  signals[GET_OFFSCREEN_PARENT] =
+    g_signal_new (g_intern_static_string ("get-offscreen-parent"),
+                 G_OBJECT_CLASS_TYPE (object_class),
+                 G_SIGNAL_RUN_LAST,
+                 0,
+                 accumulate_get_parent, NULL,
+                 gdk_marshal_OBJECT__VOID,
+                 GDK_TYPE_WINDOW,
+                 0);
+  signals[PICK_OFFSCREEN_CHILD] =
+    g_signal_new (g_intern_static_string ("pick-offscreen-child"),
+                 G_OBJECT_CLASS_TYPE (object_class),
+                 G_SIGNAL_RUN_LAST,
+                 0,
+                 accumulate_get_parent, NULL,
+                 gdk_marshal_OBJECT__DOUBLE_DOUBLE,
+                 GDK_TYPE_WINDOW,
+                 2,
+                 G_TYPE_DOUBLE,
+                 G_TYPE_DOUBLE);
+  signals[TO_PARENT] =
+    g_signal_new (g_intern_static_string ("to-parent"),
+                 G_OBJECT_CLASS_TYPE (object_class),
+                 G_SIGNAL_RUN_LAST,
+                 0,
+                 NULL, NULL,
+                 gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
+                 G_TYPE_NONE,
+                 4,
+                 G_TYPE_DOUBLE,
+                 G_TYPE_DOUBLE,
+                 G_TYPE_POINTER,
+                 G_TYPE_POINTER);
+  signals[FROM_PARENT] =
+    g_signal_new (g_intern_static_string ("from-parent"),
+                 G_OBJECT_CLASS_TYPE (object_class),
+                 G_SIGNAL_RUN_LAST,
+                 0,
+                 NULL, NULL,
+                 gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
+                 G_TYPE_NONE,
+                 4,
+                 G_TYPE_DOUBLE,
+                 G_TYPE_DOUBLE,
+                 G_TYPE_POINTER,
+                 G_TYPE_POINTER);
 }
 
 static void
@@ -330,7 +501,7 @@ gdk_window_finalize (GObject *object)
 {
   GdkWindow *window = GDK_WINDOW (object);
   GdkWindowObject *obj = (GdkWindowObject *) object;
-  
+
   if (!GDK_WINDOW_DESTROYED (window))
     {
       if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
@@ -345,4210 +516,8950 @@ gdk_window_finalize (GObject *object)
        _gdk_window_destroy (window, TRUE);
     }
 
-  g_object_unref (obj->impl);
-  obj->impl = NULL;
-  
+  if (obj->impl)
+    {
+      g_object_unref (obj->impl);
+      obj->impl = NULL;
+    }
+
+  if (obj->impl_window != obj)
+    {
+      g_object_unref (obj->impl_window);
+      obj->impl_window = NULL;
+    }
+
+  if (obj->shape)
+    gdk_region_destroy (obj->shape);
+
+  if (obj->input_shape)
+    gdk_region_destroy (obj->input_shape);
+
+  if (obj->cursor)
+    gdk_cursor_unref (obj->cursor);
+
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
-/**
- * gdk_window_new:
- * @parent: a #GdkWindow, or %NULL to create the window as a child of
- *   the default root window for the default display.
- * @attributes: attributes of the new window
- * @attributes_mask: mask indicating which fields in @attributes are valid
- * 
- * Creates a new #GdkWindow using the attributes from
- * @attributes. See #GdkWindowAttr and #GdkWindowAttributesType for
- * more details.  Note: to use this on displays other than the default
- * display, @parent must be specified.
- * 
- * Return value: the new #GdkWindow
- **/
-GdkWindow*
-gdk_window_new (GdkWindow     *parent,
-               GdkWindowAttr *attributes,
-               gint           attributes_mask)
+static gboolean
+gdk_window_is_offscreen (GdkWindowObject *window)
 {
-  GdkWindow *window;
-  GdkWindowObject *private, *parent_private;
+  return GDK_WINDOW_TYPE (window) == GDK_WINDOW_OFFSCREEN;
+}
 
-  g_return_val_if_fail (parent == NULL || GDK_IS_WINDOW (parent), NULL);
-  g_return_val_if_fail (attributes != NULL, NULL);
+static GdkWindowObject *
+gdk_window_get_impl_window (GdkWindowObject *window)
+{
+  return window->impl_window;
+}
 
-  window = _gdk_window_new (parent, attributes, attributes_mask);
-  g_return_val_if_fail (window != NULL, window);
+GdkWindow *
+_gdk_window_get_impl_window (GdkWindow *window)
+{
+  return (GdkWindow *)gdk_window_get_impl_window ((GdkWindowObject *)window);
+}
 
-  /* Inherit redirection from parent */
-  if (parent != NULL)
-    {
-      parent_private = GDK_WINDOW_OBJECT (parent);
-      private = GDK_WINDOW_OBJECT (window);
-      private->redirect = parent_private->redirect;
-    }
-  
-  return window;
+static gboolean
+gdk_window_has_impl (GdkWindowObject *window)
+{
+  return window->impl_window == window;
 }
 
-/**
- * gdk_window_reparent:
- * @window: a #GdkWindow
- * @new_parent: new parent to move @window into
- * @x: X location inside the new parent
- * @y: Y location inside the new parent
- *
- * Reparents @window into the given @new_parent. The window being
- * reparented will be unmapped as a side effect.
- * 
- **/
-void
-gdk_window_reparent (GdkWindow *window,
-                    GdkWindow *new_parent,
-                    gint       x,
-                    gint       y)
+gboolean
+_gdk_window_has_impl (GdkWindow *window)
 {
-  GdkWindowObject *private;
-  gboolean show;
+  return gdk_window_has_impl ((GdkWindowObject *)window);
+}
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
-  g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
+static gboolean
+gdk_window_has_no_impl (GdkWindowObject *window)
+{
+  return window->impl_window != window;
+}
 
-  if (GDK_WINDOW_DESTROYED (window) ||
-      (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
+static void
+remove_child_area (GdkWindowObject *private,
+                  GdkWindowObject *until,
+                  gboolean for_input,
+                  GdkRegion *region)
+{
+  GdkWindowObject *child;
+  GdkRegion *child_region;
+  GdkRectangle r;
+  GList *l;
+  GdkRegion *shape;
+
+  for (l = private->children; l; l = l->next)
     {
-      return;
-    }
+      child = l->data;
 
-  private = (GdkWindowObject *) window;
+      if (child == until)
+       break;
+
+      if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
+       continue;
+
+      /* Ignore offscreen children, as they don't draw in their parent and
+       * don't take part in the clipping */
+      if (gdk_window_is_offscreen (child))
+       continue;
+
+      r.x = child->x;
+      r.y = child->y;
+      r.width = child->width;
+      r.height = child->height;
+
+      child_region = gdk_region_rectangle (&r);
+
+      if (child->shape)
+       gdk_region_intersect (child_region, child->shape);
+      else if (private->window_type == GDK_WINDOW_FOREIGN)
+       {
+         shape = _gdk_windowing_window_get_shape ((GdkWindow *)child);
+         if (shape)
+           {
+             gdk_region_intersect (child_region, shape);
+             gdk_region_destroy (shape);
+           }
+       }
+
+      if (for_input)
+       {
+         if (child->input_shape)
+           gdk_region_intersect (child_region, child->input_shape);
+         else if (private->window_type == GDK_WINDOW_FOREIGN)
+           {
+             shape = _gdk_windowing_window_get_input_shape ((GdkWindow *)child);
+             if (shape)
+               {
+                 gdk_region_intersect (child_region, shape);
+                 gdk_region_destroy (shape);
+               }
+           }
+       }
+
+      gdk_region_subtract (region, child_region);
+      gdk_region_destroy (child_region);
 
-  /* Break up redirection if inherited */
-  if (private->redirect && private->redirect->redirected != private)
-    {
-      remove_redirect_from_children (private, private->redirect);
-      private->redirect = NULL;
     }
-  
-  show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent (window, new_parent, x, y);
+}
 
-  /* Inherit parent redirect if we don't have our own */
-  if (private->parent && private->redirect == NULL)
+static GdkVisibilityState
+effective_visibility (GdkWindowObject *private)
+{
+  GdkVisibilityState native;
+
+  if (!gdk_window_is_viewable ((GdkWindow *)private))
+    return GDK_VISIBILITY_NOT_VIEWABLE;
+
+  native = private->impl_window->native_visibility;
+
+  if (native == GDK_VISIBILITY_FULLY_OBSCURED ||
+      private->visibility == GDK_VISIBILITY_FULLY_OBSCURED)
+    return GDK_VISIBILITY_FULLY_OBSCURED;
+  else if (native == GDK_VISIBILITY_UNOBSCURED)
+    return private->visibility;
+  else /* native PARTIAL, private partial or unobscured  */
+    return GDK_VISIBILITY_PARTIAL;
+}
+
+static void
+gdk_window_update_visibility (GdkWindowObject *private)
+{
+  GdkVisibilityState new_visibility;
+  GdkEvent *event;
+
+  new_visibility = effective_visibility (private);
+
+  if (new_visibility != private->effective_visibility)
     {
-      private->redirect = private->parent->redirect;
-      apply_redirect_to_children (private, private->redirect);
-    }
+      private->effective_visibility = new_visibility;
 
-  if (show)
-    gdk_window_show (window);
+      if (new_visibility != GDK_VISIBILITY_NOT_VIEWABLE &&
+         private->event_mask & GDK_VISIBILITY_NOTIFY)
+       {
+         event = _gdk_make_event ((GdkWindow *)private, GDK_VISIBILITY_NOTIFY,
+                                  NULL, FALSE);
+         event->visibility.state = new_visibility;
+       }
+    }
 }
 
 static void
-window_remove_filters (GdkWindow *window)
+gdk_window_update_visibility_recursively (GdkWindowObject *private,
+                                         GdkWindowObject *only_for_impl)
 {
-  GdkWindowObject *obj = (GdkWindowObject*) window;
+  GdkWindowObject *child;
+  GList *l;
 
-  if (obj->filters)
+  gdk_window_update_visibility (private);
+  for (l = private->children; l != NULL; l = l->next)
     {
-      GList *tmp_list;
-      
-      for (tmp_list = obj->filters; tmp_list; tmp_list = tmp_list->next)
-       g_free (tmp_list->data);
-    
-      g_list_free (obj->filters);
-      obj->filters = NULL;
+      child = l->data;
+      if ((only_for_impl == NULL) ||
+         (only_for_impl == child->impl_window))
+       gdk_window_update_visibility_recursively (child, only_for_impl);
     }
 }
 
-/**
- * _gdk_window_destroy_hierarchy:
- * @window: a #GdkWindow
- * @recursing: If TRUE, then this is being called because a parent
- *            was destroyed. This generally means that the call to the 
- *            windowing system to destroy the window can be omitted, since
- *            it will be destroyed as a result of the parent being destroyed.
- *            Unless @foreign_destroy.           
- * @foreign_destroy: If TRUE, the window or a parent was destroyed by some 
- *            external agency. The window has already been destroyed and no 
- *            windowing system calls should be made. (This may never happen
- *            for some windowing systems.)
- *
- * Internal function to destroy a window. Like gdk_window_destroy(),
- * but does not drop the reference count created by gdk_window_new().
- **/
 static void
-_gdk_window_destroy_hierarchy (GdkWindow *window,
-                              gboolean   recursing,
-                              gboolean   foreign_destroy)
+recompute_visible_regions_internal (GdkWindowObject *private,
+                                   gboolean recalculate_clip,
+                                   gboolean recalculate_siblings,
+                                   gboolean recalculate_children)
 {
-  GdkWindowObject *private;
-  GdkWindowObject *temp_private;
-  GdkWindow *temp_window;
-  GdkScreen *screen;
-  GList *children;
-  GList *tmp;
+  GdkRectangle r;
+  GList *l;
+  GdkWindowObject *child;
+  GdkRegion *new_clip, *old_clip_region_with_children;
+  gboolean clip_region_changed;
+  gboolean abs_pos_changed;
+  int old_abs_x, old_abs_y;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  old_abs_x = private->abs_x;
+  old_abs_y = private->abs_y;
 
-  private = (GdkWindowObject*) window;
-  
-  if (GDK_WINDOW_DESTROYED (window))
-    return;
-    
-  screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
-  temp_window = g_object_get_qdata (G_OBJECT (screen), quark_pointer_window);
-  if (temp_window == window)
-    g_object_set_qdata (G_OBJECT (screen), quark_pointer_window, NULL);
+  /* Update absolute position */
+  if (gdk_window_has_impl (private))
+    {
+      /* Native window starts here */
+      private->abs_x = 0;
+      private->abs_y = 0;
+    }
+  else
+    {
+      private->abs_x = private->parent->abs_x + private->x;
+      private->abs_y = private->parent->abs_y + private->y;
+    }
 
-  switch (GDK_WINDOW_TYPE (window))
+  abs_pos_changed =
+    private->abs_x != old_abs_x ||
+    private->abs_y != old_abs_y;
+
+  /* Update clip region based on:
+   * parent clip
+   * window size
+   * siblings in parents above window
+   */
+  clip_region_changed = FALSE;
+  if (recalculate_clip)
     {
-    case GDK_WINDOW_ROOT:
-      if (!screen->closed)
-       {
-         g_error ("attempted to destroy root window");
-         break;
-       }
-      /* else fall thru */
-    case GDK_WINDOW_TOPLEVEL:
-    case GDK_WINDOW_CHILD:
-    case GDK_WINDOW_DIALOG:
-    case GDK_WINDOW_TEMP:
-    case GDK_WINDOW_FOREIGN:
-      if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN && !foreign_destroy)
+      /* Calculate visible region (sans children) in parent window coords */
+      r.x = private->x;
+      r.y = private->y;
+      r.width = private->width;
+      r.height = private->height;
+      new_clip = gdk_region_rectangle (&r);
+
+      if (private->parent != NULL && GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
        {
-         /* Logically, it probably makes more sense to send
-          * a "destroy yourself" message to the foreign window
-          * whether or not it's in our hierarchy; but for historical
-          * reasons, we only send "destroy yourself" messages to
-          * foreign windows in our hierarchy.
-          */
-         if (private->parent)
-           _gdk_windowing_window_destroy_foreign (window);
+         gdk_region_intersect (new_clip, private->parent->clip_region);
 
-         /* Also for historical reasons, we remove any filters
-          * on a foreign window when it or a parent is destroyed;
-          * this likely causes problems if two separate portions
-          * of code are maintaining filter lists on a foreign window.
-          */
-         window_remove_filters (window);
+         /* Remove all overlapping children from parent */
+         remove_child_area (private->parent, private, FALSE, new_clip);
        }
-      else
-       {
-         private->state |= GDK_WINDOW_STATE_WITHDRAWN;
-         
-         if (private->parent)
-           {
-             GdkWindowObject *parent_private = (GdkWindowObject *)private->parent;
-             if (parent_private->children)
-               parent_private->children = g_list_remove (parent_private->children, window);
-           }
 
-         _gdk_window_clear_update_area (window);
-         gdk_window_free_paint_stack (window);
-         
-         if (private->bg_pixmap &&
-              private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
-              private->bg_pixmap != GDK_NO_BG)
-           {
-             g_object_unref (private->bg_pixmap);
-             private->bg_pixmap = NULL;
-           }
-         
-         if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN)
-           g_assert (private->children == NULL);
-         else
-           {
-             children = tmp = private->children;
-             private->children = NULL;
-             
-             while (tmp)
-               {
-                 temp_window = tmp->data;
-                 tmp = tmp->next;
-                 
-                 temp_private = (GdkWindowObject*) temp_window;
-                 if (temp_private)
-                   _gdk_window_destroy_hierarchy (temp_window,
-                                                   TRUE, foreign_destroy);
-               }
-             
-             g_list_free (children);
-           }
-         
-         _gdk_windowing_window_destroy (window, recursing, foreign_destroy);
-         private->parent = NULL;
-         private->destroyed = TRUE;
+      /* Convert from parent coords to window coords */
+      gdk_region_offset (new_clip, -private->x, -private->y);
 
-         window_remove_filters (window);
+      if (private->shape)
+       gdk_region_intersect (new_clip, private->shape);
 
-          gdk_drawable_set_colormap (GDK_DRAWABLE (window), NULL);
+      if (private->clip_region == NULL ||
+         !gdk_region_equal (private->clip_region, new_clip))
+       clip_region_changed = TRUE;
 
-         /* If we own the redirect, free it */
-         if (private->redirect && private->redirect->redirected == private)
-           gdk_window_redirect_free (private->redirect);
+      if (private->clip_region)
+       gdk_region_destroy (private->clip_region);
+      private->clip_region = new_clip;
 
-         private->redirect = NULL;
+      old_clip_region_with_children = private->clip_region_with_children;
+      private->clip_region_with_children = gdk_region_copy (private->clip_region);
+      remove_child_area (private, NULL, FALSE, private->clip_region_with_children);
+
+      if (clip_region_changed ||
+         !gdk_region_equal (private->clip_region_with_children, old_clip_region_with_children))
+         private->clip_tag = new_region_tag ();
+
+      if (old_clip_region_with_children)
+       gdk_region_destroy (old_clip_region_with_children);
+    }
+
+  if (clip_region_changed)
+    {
+      GdkVisibilityState visibility;
+      gboolean fully_visible;
+
+      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;
+       }
+
+      if (private->visibility != visibility)
+       {
+         private->visibility = visibility;
+         gdk_window_update_visibility (private);
        }
-      break;
     }
-}
 
-/**
- * _gdk_window_destroy:
- * @window: a #GdkWindow
- * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
- *            external agency. The window has already been destroyed and no
- *            windowing system calls should be made. (This may never happen
- *            for some windowing systems.)
- *
- * Internal function to destroy a window. Like gdk_window_destroy(),
- * but does not drop the reference count created by gdk_window_new().
- **/
-void
-_gdk_window_destroy (GdkWindow *window,
-                    gboolean   foreign_destroy)
-{
-  _gdk_window_destroy_hierarchy (window, FALSE, foreign_destroy);
+  /* Update all children, recursively. */
+  if (abs_pos_changed || clip_region_changed || recalculate_children)
+    {
+      for (l = private->children; l; l = l->next)
+       {
+         child = l->data;
+         /* Only recalculate clip if the the clip region changed, otherwise
+          * there is no way the child clip region could change (its has not e.g. moved)
+          * Except if recalculate_children is set to force child updates
+          */
+         recompute_visible_regions_internal (child, recalculate_clip && (clip_region_changed || recalculate_children), FALSE, FALSE);
+       }
+    }
+
+  if (clip_region_changed &&
+      gdk_window_has_impl (private) &&
+      /* Not for offscreens */
+      private->window_type != GDK_WINDOW_OFFSCREEN &&
+      /* or for non-shaped toplevels */
+      (private->shaped ||
+       (private->parent != NULL &&
+       GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)) &&
+      /* or for foreign windows */
+      GDK_WINDOW_TYPE (private) != GDK_WINDOW_FOREIGN
+      )
+    {
+      GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region ((GdkWindow *)private, private->clip_region, 0, 0);
+    }
+
+  if (recalculate_siblings &&
+      private->parent != NULL &&
+      GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
+    {
+      /* If we moved a child window in parent or changed the stacking order, then we
+       * need to recompute the visible area of all the other children in the parent
+       */
+      for (l = private->parent->children; l; l = l->next)
+       {
+         child = l->data;
+
+         if (child != private)
+           recompute_visible_regions_internal (child, TRUE, FALSE, FALSE);
+       }
+
+      /* We also need to recompute the _with_children clip for the parent */
+      recompute_visible_regions_internal (private->parent, TRUE, FALSE, FALSE);
+    }
+
+  if (private->cairo_surface)
+    {
+      int width, height;
+
+      /* It would be nice if we had some cairo support here so we
+        could set the clip rect on the cairo surface */
+      width = private->abs_x + private->width;
+      height = private->abs_y + private->height;
+
+      _gdk_windowing_set_cairo_surface_size (private->cairo_surface,
+                                            width, height);
+      cairo_surface_set_device_offset (private->cairo_surface,
+                                      private->abs_x,
+                                      private->abs_y);
+    }
 }
 
-/**
- * gdk_window_destroy:
- * @window: a #GdkWindow
+/* Call this when private has changed in one or more of these ways:
+ *  size changed
+ *  window moved
+ *  new window added
+ *  stacking order of window changed
+ *  child deleted
  *
- * Destroys the window system resources associated with @window and decrements @window's
- * reference count. The window system resources for all children of @window are also
- * destroyed, but the children's reference counts are not decremented.
+ * It will recalculate abs_x/y and the clip regions
  *
- * Note that a window will not be destroyed automatically when its reference count
- * reaches zero. You must call this function yourself before that happens.
+ * Unless the window didn't change stacking order or size/pos, pass in TRUE
+ * for recalculate_siblings. (Mostly used internally for the recursion)
  *
- **/
-void
-gdk_window_destroy (GdkWindow *window)
+ * If a child window was removed (and you can't use that child for
+ * recompute_visible_regions), pass in TRUE for recalculate_children on the parent
+ */
+static void
+recompute_visible_regions (GdkWindowObject *private,
+                          gboolean recalculate_siblings,
+                          gboolean recalculate_children)
 {
-  _gdk_window_destroy_hierarchy (window, FALSE, FALSE);
-  g_object_unref (window);
+  recompute_visible_regions_internal (private,
+                                     TRUE,
+                                     recalculate_siblings,
+                                     recalculate_children);
 }
 
-/**
- * gdk_window_set_user_data:
- * @window: a #GdkWindow
- * @user_data: user data
- *
- * For most purposes this function is deprecated in favor of
- * g_object_set_data(). However, for historical reasons GTK+ stores
- * the #GtkWidget that owns a #GdkWindow as user data on the
- * #GdkWindow. So, custom widget implementations should use
- * this function for that. If GTK+ receives an event for a #GdkWindow,
- * and the user data for the window is non-%NULL, GTK+ will assume the
- * user data is a #GtkWidget, and forward the event to that widget.
- * 
- **/
 void
-gdk_window_set_user_data (GdkWindow *window,
-                         gpointer   user_data)
+_gdk_window_update_size (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  ((GdkWindowObject*)window)->user_data = user_data;
+  recompute_visible_regions ((GdkWindowObject *)window, TRUE, FALSE);
 }
 
-/**
- * gdk_window_get_user_data:
- * @window: a #GdkWindow
- * @data: return location for user data
- *
- * Retrieves the user data for @window, which is normally the widget
- * that @window belongs to. See gdk_window_set_user_data().
- * 
- **/
-void
-gdk_window_get_user_data (GdkWindow *window,
-                         gpointer  *data)
+/* Find the native window that would be just above "child"
+ * in the native stacking order if "child" was a native window
+ * (it doesn't have to be native). If there is no such native
+ * 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)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  GdkWindowObject *w;
+  GList *l;
 
-  *data = ((GdkWindowObject*)window)->user_data;
-}
+  if (child)
+    {
+      l = g_list_find (parent->children, child);
+      g_assert (l != NULL); /* Better be a child of its parent... */
+      l = l->prev; /* Start looking at the one above the child */
+    }
+  else
+    l = g_list_last (parent->children);
 
-/**
- * gdk_window_get_window_type:
- * @window: a #GdkWindow
- * 
- * Gets the type of the window. See #GdkWindowType.
- * 
- * Return value: type of window
- **/
-GdkWindowType
-gdk_window_get_window_type (GdkWindow *window)
-{
-  g_return_val_if_fail (GDK_IS_WINDOW (window), (GdkWindowType) -1);
-  
-  return GDK_WINDOW_TYPE (window);
+  for (; l != NULL; l = l->prev)
+    {
+      w = l->data;
+
+      if (gdk_window_has_impl (w))
+       return w;
+
+      g_assert (parent != w);
+      w = find_native_sibling_above_helper (w, NULL);
+      if (w)
+       return w;
+    }
+
+  return NULL;
 }
 
-/**
- * gdk_window_get_position:
- * @window: a #GdkWindow
- * @x: X coordinate of window
- * @y: Y coordinate of window
- *
- * Obtains the position of the window as reported in the
- * most-recently-processed #GdkEventConfigure. Contrast with
- * gdk_window_get_geometry() which queries the X server for the
- * current window position, regardless of which events have been
- * received or processed.
- *
- * The position coordinates are relative to the window's parent window.
- * 
- **/
-void
-gdk_window_get_position (GdkWindow *window,
-                        gint      *x,
-                        gint      *y)
+
+static GdkWindowObject *
+find_native_sibling_above (GdkWindowObject *parent,
+                          GdkWindowObject *child)
 {
-  GdkWindowObject *obj;
-  
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  obj = (GdkWindowObject*) window;
-  
-  if (x)
-    *x = obj->x;
-  if (y)
-    *y = obj->y;
+  GdkWindowObject *w;
+
+  w = find_native_sibling_above_helper (parent, child);
+  if (w)
+    return w;
+
+  if (gdk_window_has_impl (parent))
+    return NULL;
+  else
+    return find_native_sibling_above (parent->parent, parent);
 }
 
-/**
- * gdk_window_get_parent:
- * @window: a #GdkWindow
- * 
- * Obtains the parent of @window, as known to GDK. Does not query the
- * X server; thus this returns the parent as passed to gdk_window_new(),
- * not the actual parent. This should never matter unless you're using
- * Xlib calls mixed with GDK calls on the X11 platform. It may also
- * matter for toplevel windows, because the window manager may choose
- * to reparent them.
- * 
- * Return value: parent of @window
- **/
-GdkWindow*
-gdk_window_get_parent (GdkWindow *window)
+static GdkEventMask
+get_native_event_mask (GdkWindowObject *private)
 {
-  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
-  
-  return (GdkWindow*) ((GdkWindowObject*) window)->parent;
+  if (private->window_type != GDK_WINDOW_ROOT &&
+      private->window_type != GDK_WINDOW_FOREIGN)
+    {
+      return
+       /* We need thse for all native window so we can emulate
+          events on children: */
+       GDK_EXPOSURE_MASK |
+       GDK_VISIBILITY_NOTIFY_MASK |
+       GDK_POINTER_MOTION_MASK |
+       GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
+       GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
+       GDK_SCROLL_MASK |
+       /* Then do whatever the app asks to, since the app
+        * may be asking for weird things for native windows,
+        * but filter out things that override the above
+        * requests somehow. */
+       (private->event_mask &
+        ~(GDK_POINTER_MOTION_HINT_MASK |
+          GDK_BUTTON_MOTION_MASK |
+          GDK_BUTTON1_MOTION_MASK |
+          GDK_BUTTON2_MOTION_MASK |
+          GDK_BUTTON3_MOTION_MASK));
+    }
+  else
+    return private->event_mask;
 }
 
 /**
- * gdk_window_get_toplevel:
- * @window: a #GdkWindow
- * 
- * Gets the toplevel window that's an ancestor of @window.
- * 
- * Return value: the toplevel window containing @window
+ * gdk_window_new:
+ * @parent: a #GdkWindow, or %NULL to create the window as a child of
+ *   the default root window for the default display.
+ * @attributes: attributes of the new window
+ * @attributes_mask: mask indicating which fields in @attributes are valid
+ *
+ * Creates a new #GdkWindow using the attributes from
+ * @attributes. See #GdkWindowAttr and #GdkWindowAttributesType for
+ * more details.  Note: to use this on displays other than the default
+ * display, @parent must be specified.
+ *
+ * Return value: the new #GdkWindow
  **/
 GdkWindow*
-gdk_window_get_toplevel (GdkWindow *window)
+gdk_window_new (GdkWindow     *parent,
+               GdkWindowAttr *attributes,
+               gint           attributes_mask)
 {
-  GdkWindowObject *obj;
-  
-  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
+  GdkWindow *window;
+  GdkWindowObject *private;
+  GdkScreen *screen;
+  GdkVisual *visual;
+  int x, y;
+  gboolean native;
+  GdkEventMask event_mask;
+  GdkWindow *real_parent;
 
-  obj = (GdkWindowObject *)window;
-  while (GDK_WINDOW_TYPE (obj) == GDK_WINDOW_CHILD)
-    obj = (GdkWindowObject *)obj->parent;
-  
-  return GDK_WINDOW (obj);
-}
+  g_return_val_if_fail (attributes != NULL, NULL);
 
-/**
- * gdk_window_get_children:
- * @window: a #GdkWindow
- * 
- * Gets the list of children of @window known to GDK.
- * This function only returns children created via GDK,
- * so for example it's useless when used with the root window;
- * it only returns windows an application created itself.
- *
- * The returned list must be freed, but the elements in the
- * list need not be.
- * 
- * Return value: list of child windows inside @window
- **/
-GList*
-gdk_window_get_children (GdkWindow *window)
-{
-  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
+  if (!parent)
+    {
+      GDK_NOTE (MULTIHEAD,
+               g_warning ("gdk_window_new(): no parent specified reverting to parent = default root window"));
 
-  if (GDK_WINDOW_DESTROYED (window))
-    return NULL;
+      screen = gdk_screen_get_default ();
+      parent = gdk_screen_get_root_window (screen);
+    }
+  else
+    screen = gdk_drawable_get_screen (parent);
 
-  return g_list_copy (GDK_WINDOW_OBJECT (window)->children);
-}
+  g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
 
-/**
- * gdk_window_peek_children:
- * @window: a #GdkWindow
- * 
- * Like gdk_window_get_children(), but does not copy the list of
- * children, so the list does not need to be freed.
- * 
- * Return value: a reference to the list of child windows in @window
- **/
-GList *
-gdk_window_peek_children (GdkWindow *window)
-{
-  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
+  if (GDK_WINDOW_DESTROYED (parent))
+    return NULL;
 
-  if (GDK_WINDOW_DESTROYED (window))
-    return NULL;
+  window = g_object_new (GDK_TYPE_WINDOW, NULL);
+  private = (GdkWindowObject *) window;
 
-  return GDK_WINDOW_OBJECT (window)->children;
-}
+  /* Windows with a foreign parent are treated as if they are children
+   * of the root window, except for actual creation.
+   */
+  real_parent = parent;
+  if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
+    parent = gdk_screen_get_root_window (screen);
 
-/**
- * gdk_window_add_filter:
- * @window: a #GdkWindow
- * @function: filter callback
- * @data: data to pass to filter callback
- *
- * Adds an event filter to @window, allowing you to intercept events
- * before they reach GDK. This is a low-level operation and makes it
- * easy to break GDK and/or GTK+, so you have to know what you're
- * doing. Pass %NULL for @window to get all events for all windows,
- * instead of events for a specific window.
- *
- * See gdk_display_add_client_message_filter() if you are interested
- * in X ClientMessage events.
- **/
-void          
-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->parent = (GdkWindowObject *)parent;
 
-  private = (GdkWindowObject*) window;
-  if (private && GDK_WINDOW_DESTROYED (window))
-    return;
-  
-  if (private)
-    tmp_list = private->filters;
+  private->accept_focus = TRUE;
+  private->focus_on_map = TRUE;
+
+  if (attributes_mask & GDK_WA_X)
+    x = attributes->x;
   else
-    tmp_list = _gdk_default_filters;
-  
-  while (tmp_list)
+    x = 0;
+
+  if (attributes_mask & GDK_WA_Y)
+    y = attributes->y;
+  else
+    y = 0;
+
+  private->x = x;
+  private->y = y;
+  private->width = (attributes->width > 1) ? (attributes->width) : (1);
+  private->height = (attributes->height > 1) ? (attributes->height) : (1);
+
+#ifdef GDK_WINDOWING_X11
+  /* Work around a bug where Xorg refuses to map toplevel InputOnly windows
+   * from an untrusted client: http://bugs.freedesktop.org/show_bug.cgi?id=6988
+   */
+  if (attributes->wclass == GDK_INPUT_ONLY &&
+      GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT &&
+      !G_LIKELY (GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (parent))->trusted_client))
     {
-      filter = (GdkEventFilter *)tmp_list->data;
-      if ((filter->function == function) && (filter->data == data))
-       return;
-      tmp_list = tmp_list->next;
+      g_warning ("Coercing GDK_INPUT_ONLY toplevel window to GDK_INPUT_OUTPUT to work around bug in Xorg server");
+      attributes->wclass = GDK_INPUT_OUTPUT;
+    }
+#endif
+
+  if (attributes->wclass == GDK_INPUT_ONLY)
+    {
+      /* Backwards compatiblity - we've always ignored
+       * attributes->window_type for input-only windows
+       * before
+       */
+      if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
+       private->window_type = GDK_WINDOW_TEMP;
+      else
+       private->window_type = GDK_WINDOW_CHILD;
     }
-  
-  filter = g_new (GdkEventFilter, 1);
-  filter->function = function;
-  filter->data = data;
-  
-  if (private)
-    private->filters = g_list_append (private->filters, filter);
   else
-    _gdk_default_filters = g_list_append (_gdk_default_filters, filter);
-}
+    private->window_type = attributes->window_type;
 
-/**
- * gdk_window_remove_filter:
- * @window: a #GdkWindow
- * @function: previously-added filter function
- * @data: user data for previously-added filter function
- *
- * Remove a filter previously added with gdk_window_add_filter().
- * 
- **/
-void
-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));
+  /* Sanity checks */
+  switch (private->window_type)
+    {
+    case GDK_WINDOW_TOPLEVEL:
+    case GDK_WINDOW_DIALOG:
+    case GDK_WINDOW_TEMP:
+    case GDK_WINDOW_OFFSCREEN:
+      if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
+       g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
+                  "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
+    case GDK_WINDOW_CHILD:
+      break;
+      break;
+    default:
+      g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
+      return NULL;
+    }
 
-  private = (GdkWindowObject*) window;
-  
-  if (private)
-    tmp_list = private->filters;
+  if (attributes_mask & GDK_WA_VISUAL)
+    visual = attributes->visual;
   else
-    tmp_list = _gdk_default_filters;
-  
-  while (tmp_list)
+    visual = gdk_screen_get_system_visual (screen);
+
+  private->event_mask = attributes->event_mask;
+
+  if (attributes->wclass == GDK_INPUT_OUTPUT)
     {
-      filter = (GdkEventFilter *)tmp_list->data;
-      node = tmp_list;
-      tmp_list = tmp_list->next;
-      
-      if ((filter->function == function) && (filter->data == data))
+      private->input_only = FALSE;
+      private->depth = visual->depth;
+
+      private->bg_color.pixel = 0; // TODO: BlackPixel (xdisplay, screen_x11->screen_num);
+      private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
+
+      private->bg_pixmap = NULL;
+    }
+  else
+    {
+      private->depth = 0;
+      private->input_only = TRUE;
+    }
+
+  if (private->parent)
+    private->parent->children = g_list_prepend (private->parent->children, window);
+
+  native = FALSE; /* Default */
+  if (GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
+    native = TRUE; /* Always use native windows for toplevels */
+  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_drawable_get_visual ((GdkDrawable *)private->parent))))
+    native = TRUE; /* InputOutput window with different colormap or visual than parent, needs native window */
+
+  if (private->window_type == GDK_WINDOW_OFFSCREEN)
+    {
+      _gdk_offscreen_window_new (window, screen, visual, attributes, attributes_mask);
+      private->impl_window = private;
+    }
+  else if (native)
+    {
+      GdkWindowObject *above;
+      GList listhead = {0};
+
+      event_mask = get_native_event_mask (private);
+
+      /* Create the impl */
+      _gdk_window_impl_new (window, real_parent, screen, visual, event_mask, attributes, attributes_mask);
+      private->impl_window = private;
+
+      /* 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 */
+      above = find_native_sibling_above (private->parent, private);
+      if (above)
        {
-         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);
-         
-         return;
+         listhead.data = window;
+         GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
+                                                                   &listhead);
        }
+
+    }
+  else
+    {
+      private->impl_window = g_object_ref (private->parent->impl_window);
+      private->impl = g_object_ref (private->impl_window->impl);
     }
-}
 
-/**
- * gdk_screen_get_toplevel_windows:
- * @screen: The #GdkScreen where the toplevels are located.
- * 
- * Obtains a list of all toplevel windows known to GDK on the screen @screen.
- * A toplevel window is a child of the root window (see
- * gdk_get_default_root_window()).
- *
- * The returned list should be freed with g_list_free(), but
- * its elements need not be freed.
- * 
- * Return value: list of toplevel windows, free with g_list_free()
- *
- * Since: 2.2
- **/
-GList *
-gdk_screen_get_toplevel_windows (GdkScreen *screen)
-{
-  GdkWindow * root_window;
-  GList *new_list = NULL;
-  GList *tmp_list;
-  
-  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
-  
-  root_window = gdk_screen_get_root_window (screen);
+  recompute_visible_regions (private, TRUE, FALSE);
 
-  tmp_list = ((GdkWindowObject *)root_window)->children;
-  while (tmp_list)
+  if (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
     {
-      if (GDK_WINDOW_TYPE (tmp_list->data) != GDK_WINDOW_FOREIGN)
-       new_list = g_list_prepend (new_list, tmp_list->data);
-      tmp_list = tmp_list->next;
+      /* Inherit redirection from parent */
+      private->redirect = private->parent->redirect;
     }
-  
-  return new_list;
-}
 
-/**
- * gdk_window_get_toplevels:
- * 
- * Obtains a list of all toplevel windows known to GDK on the default
- * screen (see gdk_screen_get_toplevel_windows()).
- * A toplevel window is a child of the root window (see
- * gdk_get_default_root_window()).
- *
- * The returned list should be freed with g_list_free(), but
- * its elements need not be freed.
- * 
- * Return value: list of toplevel windows, free with g_list_free()
- *
- * Deprecated: 2.16: Use gdk_screen_get_toplevel_windows() instead.
- **/
-GList *
-gdk_window_get_toplevels (void)
-{
-  return gdk_screen_get_toplevel_windows (gdk_screen_get_default ());
+  gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
+                                 (attributes->cursor) :
+                                 NULL));
+
+  return window;
 }
 
-/**
- * gdk_window_is_visible:
- * @window: a #GdkWindow
- * 
- * Checks whether the window has been mapped (with gdk_window_show() or
- * gdk_window_show_unraised()).
- * 
- * Return value: %TRUE if the window is mapped
- **/
-gboolean 
-gdk_window_is_visible (GdkWindow *window)
+static gboolean
+is_parent_of (GdkWindow *parent,
+             GdkWindow *child)
 {
-  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
-  
-  return GDK_WINDOW_IS_MAPPED (window);
+  GdkWindow *w;
+
+  w = child;
+  while (w != NULL)
+    {
+      if (w == parent)
+       return TRUE;
+
+      w = gdk_window_get_parent (w);
+    }
+
+  return FALSE;
 }
 
-/**
- * gdk_window_is_viewable:
- * @window: a #GdkWindow
- * 
- * Check if the window and all ancestors of the window are
- * mapped. (This is not necessarily "viewable" in the X sense, since
- * we only check as far as we have GDK window parents, not to the root
- * window.)
- *
- * Return value: %TRUE if the window is viewable
- **/
-gboolean 
-gdk_window_is_viewable (GdkWindow *window)
+static void
+change_impl (GdkWindowObject *private,
+            GdkWindowObject *impl_window,
+            GdkDrawable *new)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkScreen *screen;
-  GdkWindow *root_window;
+  GList *l;
+  GdkWindowObject *child;
+  GdkDrawable *old_impl;
+  GdkWindowObject *old_impl_window;
 
-  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+  old_impl = private->impl;
+  old_impl_window = private->impl_window;
+  if (private != impl_window)
+    private->impl_window = g_object_ref (impl_window);
+  else
+    private->impl_window = private;
+  private->impl = g_object_ref (new);
+  if (old_impl_window != private)
+    g_object_unref (old_impl_window);
+  g_object_unref (old_impl);
 
-  screen = gdk_drawable_get_screen (window);
-  root_window = gdk_screen_get_root_window (screen);
-  
-  while (private && 
-        (private != (GdkWindowObject *)root_window) &&
-        (GDK_WINDOW_TYPE (private) != GDK_WINDOW_FOREIGN))
+  for (l = private->children; l != NULL; l = l->next)
     {
-      if (GDK_WINDOW_DESTROYED (private) || !GDK_WINDOW_IS_MAPPED (private))
-       return FALSE;
-      
-      private = (GdkWindowObject *)private->parent;
+      child = l->data;
+
+      if (child->impl == old_impl)
+       change_impl (child, impl_window, new);
     }
-  
-  return TRUE;
 }
 
-/**
- * gdk_window_get_state:
- * @window: a #GdkWindow
- * 
- * Gets the bitwise OR of the currently active window state flags,
- * from the #GdkWindowState enumeration.
- * 
- * Return value: window state bitfield
- **/
-GdkWindowState
-gdk_window_get_state (GdkWindow *window)
+static void
+reparent_to_impl (GdkWindowObject *private)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  
-  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
-  
-  return private->state;
+  GList *l;
+  GdkWindowObject *child;
+  gboolean show;
+
+  /* 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) */
+  for (l = g_list_last (private->children); l != NULL; l = l->prev)
+    {
+      child = l->data;
+
+      if (child->impl == private->impl)
+       reparent_to_impl (child);
+      else
+       {
+         show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent ((GdkWindow *)child,
+                                                                     (GdkWindow *)private,
+                                                                     child->x, child->y);
+         if (show)
+           gdk_window_show_unraised ((GdkWindow *)child);
+       }
+    }
 }
 
+
 /**
- * gdk_window_begin_paint_rect:
+ * gdk_window_reparent:
  * @window: a #GdkWindow
- * @rectangle: rectangle you intend to draw to
+ * @new_parent: new parent to move @window into
+ * @x: X location inside the new parent
+ * @y: Y location inside the new parent
+ *
+ * Reparents @window into the given @new_parent. The window being
+ * reparented will be unmapped as a side effect.
  *
- * A convenience wrapper around gdk_window_begin_paint_region() which
- * creates a rectangular region for you. See
- * gdk_window_begin_paint_region() for details.
- * 
  **/
 void
-gdk_window_begin_paint_rect (GdkWindow          *window,
-                             const GdkRectangle *rectangle)
-{
-  GdkRegion *region;
+gdk_window_reparent (GdkWindow *window,
+                    GdkWindow *new_parent,
+                    gint       x,
+                    gint       y)
+{
+  GdkWindowObject *private;
+  GdkWindowObject *new_parent_private;
+  GdkWindowObject *old_parent;
+  gboolean show, was_toplevel, was_mapped;
+  gboolean do_reparent_to_impl;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
+  g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
 
-  region = gdk_region_rectangle (rectangle);
-  gdk_window_begin_paint_region (window, region);
-  gdk_region_destroy (region);
-}
+  if (GDK_WINDOW_DESTROYED (window) ||
+      (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
+    return;
 
-#ifdef GDK_WINDOWING_X11
-#include "x11/gdkx.h"
-#endif
+  if (!new_parent)
+    new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
 
-/**
- * gdk_window_begin_paint_region:
- * @window: a #GdkWindow
- * @region: region you intend to draw to
- *
- * Indicates that you are beginning the process of redrawing @region.
- * A backing store (offscreen buffer) large enough to contain @region
- * will be created. The backing store will be initialized with the
- * background color or background pixmap for @window. Then, all
- * drawing operations performed on @window will be diverted to the
- * backing store.  When you call gdk_window_end_paint(), the backing
- * store will be copied to @window, making it visible onscreen. Only
- * the part of @window contained in @region will be modified; that is,
- * drawing operations are clipped to @region.
- *
- * The net result of all this is to remove flicker, because the user
- * sees the finished product appear all at once when you call
- * gdk_window_end_paint(). If you draw to @window directly without
- * calling gdk_window_begin_paint_region(), the user may see flicker
- * as individual drawing operations are performed in sequence.  The
- * clipping and background-initializing features of
- * gdk_window_begin_paint_region() are conveniences for the
- * programmer, so you can avoid doing that work yourself.
- *
- * When using GTK+, the widget system automatically places calls to
- * gdk_window_begin_paint_region() and gdk_window_end_paint() around
- * emissions of the expose_event signal. That is, if you're writing an
- * expose event handler, you can assume that the exposed area in
- * #GdkEventExpose has already been cleared to the window background,
- * is already set as the clip region, and already has a backing store.
- * Therefore in most cases, application code need not call
- * gdk_window_begin_paint_region(). (You can disable the automatic
- * calls around expose events on a widget-by-widget basis by calling
- * gtk_widget_set_double_buffered().)
- *
- * If you call this function multiple times before calling the
- * matching gdk_window_end_paint(), the backing stores are pushed onto
- * a stack. gdk_window_end_paint() copies the topmost backing store
- * onscreen, subtracts the topmost region from all other regions in
- * the stack, and pops the stack. All drawing operations affect only
- * the topmost backing store in the stack. One matching call to
- * gdk_window_end_paint() is required for each call to
- * gdk_window_begin_paint_region().
- * 
- **/
-void         
-gdk_window_begin_paint_region (GdkWindow       *window,
-                               const GdkRegion *region)
-{
-#ifdef USE_BACKING_STORE
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkRectangle clip_box;
-  GdkWindowPaint *paint;
-  GSList *list;
+  private = (GdkWindowObject *) window;
+  new_parent_private = (GdkWindowObject *)new_parent;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  /* No input-output children of input-only windows */
+  if (new_parent_private->input_only && !private->input_only)
+    return;
 
-  if (GDK_WINDOW_DESTROYED (window))
+  /* Don't create loops in hierarchy */
+  if (is_parent_of (window, new_parent))
     return;
 
-  if (GDK_IS_PAINTABLE (private->impl)) 
+  if (private->cairo_surface)
     {
-      GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
+      /* This might be wrong in the new parent, e.g. for non-native surfaces.
+        To make sure we're ok, just wipe it. */
+      cairo_surface_finish (private->cairo_surface);
+      cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
+                                  NULL, NULL);
+    }
 
-      if (iface->begin_paint_region)
-        iface->begin_paint_region ((GdkPaintable*)private->impl, region);
+  old_parent = private->parent;
 
-      return;
+  /* Break up redirection if inherited */
+  if (private->redirect && private->redirect->redirected != private)
+    {
+      remove_redirect_from_children (private, private->redirect);
+      private->redirect = NULL;
     }
 
-  gdk_region_get_clipbox (region, &clip_box);
+  was_toplevel = private->parent == NULL;
+  was_mapped = GDK_WINDOW_IS_MAPPED (window);
+  show = FALSE;
 
-  paint = g_new (GdkWindowPaint, 1);
-  paint->region = gdk_region_copy (region);
-  paint->x_offset = clip_box.x;
-  paint->y_offset = clip_box.y;
-  paint->pixmap =
-    gdk_pixmap_new (window,
-                   MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1);
+  /* 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)
+    gdk_window_ensure_native (window);
 
-  paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap);
-  cairo_surface_set_device_offset (paint->surface,
-                                  - paint->x_offset, - paint->y_offset);
-  
-  for (list = private->paint_stack; list != NULL; list = list->next)
+  do_reparent_to_impl = FALSE;
+  if (gdk_window_has_impl (private))
     {
-      GdkWindowPaint *tmp_paint = list->data;
+      /* Native window */
+      show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->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);
 
-      gdk_region_subtract (tmp_paint->region, paint->region);
+      show = was_mapped;
+      gdk_window_hide (window);
+
+      do_reparent_to_impl = TRUE;
+      change_impl (private,
+                  new_parent_private->impl_window,
+                  new_parent_private->impl);
     }
-  
-  private->paint_stack = g_slist_prepend (private->paint_stack, paint);
 
-  if (!gdk_region_empty (region))
+  /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
+   * the root window
+   */
+  if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
     {
-      gdk_window_clear_backing_rect (window,
-                                    clip_box.x, clip_box.y,
-                                    clip_box.width, clip_box.height);
+      new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
+      new_parent_private = (GdkWindowObject *)new_parent;
     }
-#endif /* USE_BACKING_STORE */
-}
 
-/**
- * gdk_window_end_paint:
- * @window: a #GdkWindow
- *
- * Indicates that the backing store created by the most recent call to
- * gdk_window_begin_paint_region() should be copied onscreen and
- * deleted, leaving the next-most-recent backing store or no backing
- * store at all as the active paint region. See
- * gdk_window_begin_paint_region() for full details. It is an error to
- * call this function without a matching
- * gdk_window_begin_paint_region() first.
- * 
- **/
-void
-gdk_window_end_paint (GdkWindow *window)
-{
-#ifdef USE_BACKING_STORE
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkWindowObject *composited;
-  GdkWindowPaint *paint;
-  GdkGC *tmp_gc;
-  GdkRectangle clip_box;
-  gint x_offset, y_offset;
+  if (old_parent)
+    old_parent->children = g_list_remove (old_parent->children, window);
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  private->parent = new_parent_private;
+  private->x = x;
+  private->y = y;
 
-  if (GDK_WINDOW_DESTROYED (window))
-    return;
+  new_parent_private->children = g_list_prepend (new_parent_private->children, window);
 
-  if (GDK_IS_PAINTABLE (private->impl))
+  /* Switch the window type as appropriate */
+
+  switch (GDK_WINDOW_TYPE (new_parent))
     {
-      GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
+    case GDK_WINDOW_ROOT:
+    case GDK_WINDOW_FOREIGN:
+      if (private->toplevel_window_type != -1)
+       GDK_WINDOW_TYPE (window) = private->toplevel_window_type;
+      else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
+       GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
+      break;
+    case GDK_WINDOW_OFFSCREEN:
+    case GDK_WINDOW_TOPLEVEL:
+    case GDK_WINDOW_CHILD:
+    case GDK_WINDOW_DIALOG:
+    case GDK_WINDOW_TEMP:
+      if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
+         GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
+       {
+         /* Save the original window type so we can restore it if the
+          * window is reparented back to be a toplevel
+          */
+         private->toplevel_window_type = GDK_WINDOW_TYPE (window);
+         GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
+       }
+    }
 
-      if (iface->end_paint)
-        iface->end_paint ((GdkPaintable*)private->impl);
-      return;
+  /* 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));
+
+  /* Inherit parent redirect if we don't have our own */
+  if (private->parent && private->redirect == NULL)
+    {
+      private->redirect = private->parent->redirect;
+      apply_redirect_to_children (private, private->redirect);
     }
 
-  if (private->paint_stack == NULL)
+  recompute_visible_regions (private, TRUE, FALSE);
+  if (old_parent && GDK_WINDOW_TYPE (old_parent) != GDK_WINDOW_ROOT)
+    recompute_visible_regions (old_parent, FALSE, TRUE);
+
+  if (do_reparent_to_impl)
+    reparent_to_impl (private);
+  else
     {
-      g_warning (G_STRLOC": no preceding call to gdk_window_begin_paint_region(), see documentation");
-      return;
+      GdkWindowObject *above;
+      GList listhead = {0};
+
+      /* 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 */
+      above = find_native_sibling_above (private->parent, private);
+      if (above)
+       {
+         listhead.data = window;
+         GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
+                                                                   &listhead);
+       }
     }
 
-  paint = private->paint_stack->data;
-  private->paint_stack = g_slist_delete_link (private->paint_stack, 
-                                              private->paint_stack);
+  if (show)
+    gdk_window_show_unraised (window);
+  else
+    _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
 
-  gdk_region_get_clipbox (paint->region, &clip_box);
+/**
+ * gdk_window_ensure_native:
+ * @window: a #GdkWindow
+ *
+ * Tries to ensure that there is a window-system native window for this
+ * GdkWindow. This may fail in some situations, returning %FALSE.
+ *
+ * Offscreen window and children of them can never have native windows.
+ *
+ * Some backends may not support native child windows.
+ *
+ * Returns: %TRUE if the window has a native window, %FALSE otherwise
+ *
+ * Since: 2.18
+ **/
+gboolean
+gdk_window_ensure_native (GdkWindow *window)
+{
+  GdkWindowObject *private;
+  GdkWindowObject *impl_window;
+  GdkDrawable *new_impl, *old_impl;
+  GdkScreen *screen;
+  GdkVisual *visual;
+  GdkWindowAttr attributes;
+  GdkWindowObject *above;
+  GList listhead;
 
-  tmp_gc = _gdk_drawable_get_scratch_gc (window, FALSE);
+  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (window, &x_offset, &y_offset);
+  if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT ||
+      GDK_WINDOW_DESTROYED (window))
+    return FALSE;
 
-  gdk_gc_set_clip_region (tmp_gc, paint->region);
-  gdk_gc_set_clip_origin (tmp_gc, - x_offset, - y_offset);
+  private = (GdkWindowObject *) window;
 
-  gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
-                     clip_box.x - paint->x_offset,
-                     clip_box.y - paint->y_offset,
-                     clip_box.x - x_offset, clip_box.y - y_offset,
-                     clip_box.width, clip_box.height);
+  impl_window = gdk_window_get_impl_window (private);
 
-  if (private->redirect)
-    {
-      GdkWindowClipData data;
-      
-      setup_redirect_clip (window, tmp_gc, &data);
-      gdk_draw_drawable (private->redirect->pixmap, tmp_gc, paint->pixmap,
-                        clip_box.x - paint->x_offset,
-                        clip_box.y - paint->y_offset,
-                        clip_box.x + data.x_offset,
-                        clip_box.y + data.y_offset,
-                        clip_box.width, clip_box.height);
-      reset_redirect_clip (window, tmp_gc, &data);
-    }
-  
-  /* Reset clip region of the cached GdkGC */
-  gdk_gc_set_clip_region (tmp_gc, NULL);
+  if (impl_window->window_type == GDK_WINDOW_OFFSCREEN)
+    return FALSE; /* native in offscreens not supported */
 
-  cairo_surface_destroy (paint->surface);
-  g_object_unref (paint->pixmap);
-  gdk_region_destroy (paint->region);
-  g_free (paint);
+  if (impl_window == private)
+    /* Already has an impl, and its not offscreen . */
+    return TRUE;
 
-  /* find a composited window in our hierarchy to signal its
-   * parent to redraw, calculating the clip box as we go...
-   *
-   * stop if parent becomes NULL since then we'd have nowhere
-   * to draw (ie: 'composited' will always be non-NULL here).
-   */
-  for (composited = private;
-       composited->parent;
-       composited = composited->parent)
-    {
-      int width, height;
+  /* Need to create a native window */
 
-      gdk_drawable_get_size (GDK_DRAWABLE (composited->parent),
-                            &width, &height);
+  screen = gdk_drawable_get_screen (window);
+  visual = gdk_drawable_get_visual (window);
 
-      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);
+  attributes.colormap = gdk_drawable_get_colormap (window);
 
-      if (composited->composited)
-       {
-         gdk_window_invalidate_rect (GDK_WINDOW (composited->parent),
-                                     &clip_box, FALSE);
-         break;
-       }
-    }
-#endif /* USE_BACKING_STORE */
-}
+  old_impl = private->impl;
+  _gdk_window_impl_new (window, (GdkWindow *)private->parent, screen, visual,
+                       get_native_event_mask (private), &attributes, GDK_WA_COLORMAP);
+  new_impl = private->impl;
 
-static void
-gdk_window_free_paint_stack (GdkWindow *window)
-{
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  
-  if (private->paint_stack)
+  private->impl = old_impl;
+  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 */
+  above = find_native_sibling_above (private->parent, private);
+  if (above)
     {
-      GSList *tmp_list = private->paint_stack;
+      listhead.data = window;
+      listhead.prev = NULL;
+      listhead.next = NULL;
+      GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
+                                                               &listhead);
+    }
 
-      while (tmp_list)
-       {
-         GdkWindowPaint *paint = tmp_list->data;
+  recompute_visible_regions (private, FALSE, FALSE);
 
-         if (tmp_list == private->paint_stack)
-           g_object_unref (paint->pixmap);
-                 
-         gdk_region_destroy (paint->region);
-         g_free (paint);
+  /* The shape may not have been set, as the clip region doesn't actually
+     change, so do it here manually */
+  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region ((GdkWindow *)private, private->clip_region, 0, 0);
 
-         tmp_list = tmp_list->next;
-       }
+  reparent_to_impl (private);
 
-      g_slist_free (private->paint_stack);
-      private->paint_stack = NULL;
+  if (!private->input_only)
+    {
+      GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, &private->bg_color);
+      if (private->bg_pixmap != NULL)
+       GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, private->bg_pixmap);
     }
+
+  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_shape_combine_region ((GdkWindow *)private, private->input_shape, 0, 0);
+
+  if (gdk_window_is_viewable (window))
+    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show (window, FALSE);
+
+  return TRUE;
 }
 
 static void
-gdk_window_get_offsets (GdkWindow *window,
-                       gint      *x_offset,
-                       gint      *y_offset)
+window_remove_filters (GdkWindow *window)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *obj = (GdkWindowObject*) window;
 
-  if (private->paint_stack)
+  if (obj->filters)
     {
-      GdkWindowPaint *paint = private->paint_stack->data;
-      *x_offset = paint->x_offset;
-      *y_offset = paint->y_offset;
+      GList *tmp_list;
+
+      for (tmp_list = obj->filters; tmp_list; tmp_list = tmp_list->next)
+       g_free (tmp_list->data);
+
+      g_list_free (obj->filters);
+      obj->filters = NULL;
     }
-  else
-    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (window, x_offset, y_offset);
 }
 
 /**
- * gdk_window_get_internal_paint_info:
+ * _gdk_window_destroy_hierarchy:
  * @window: a #GdkWindow
- * @real_drawable: location to store the drawable to which drawing should be 
- *            done.
- * @x_offset: location to store the X offset between coordinates in @window,
- *            and the underlying window system primitive coordinates for 
- *            *@real_drawable.
- * @y_offset: location to store the Y offset between coordinates in @window,
- *            and the underlying window system primitive coordinates for
- *            *@real_drawable.
- * 
- * If you bypass the GDK layer and use windowing system primitives to
- * draw directly onto a #GdkWindow, then you need to deal with two
- * details: there may be an offset between GDK coordinates and windowing
- * system coordinates, and GDK may have redirected drawing to a offscreen
- * pixmap as the result of a gdk_window_begin_paint_region() calls.
- * This function allows retrieving the information you need to compensate
- * for these effects.
+ * @recursing: If TRUE, then this is being called because a parent
+ *            was destroyed.
+ * @recursing_native: If TRUE, then this is being called because a native parent
+ *            was destroyed. This generally means that the call to the
+ *            windowing system to destroy the window can be omitted, since
+ *            it will be destroyed as a result of the parent being destroyed.
+ *            Unless @foreign_destroy.
+ * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
+ *            external agency. The window has already been destroyed and no
+ *            windowing system calls should be made. (This may never happen
+ *            for some windowing systems.)
  *
- * This function exposes details of the GDK implementation, and is thus
- * likely to change in future releases of GDK.
+ * Internal function to destroy a window. Like gdk_window_destroy(),
+ * but does not drop the reference count created by gdk_window_new().
  **/
-void
-gdk_window_get_internal_paint_info (GdkWindow    *window,
-                                   GdkDrawable **real_drawable,
-                                   gint         *x_offset,
-                                   gint         *y_offset)
+static void
+_gdk_window_destroy_hierarchy (GdkWindow *window,
+                              gboolean   recursing,
+                              gboolean   recursing_native,
+                              gboolean   foreign_destroy)
 {
-  gint x_off, y_off;
-  
   GdkWindowObject *private;
+  GdkWindowObject *temp_private;
+  GdkWindow *temp_window;
+  GdkScreen *screen;
+  GdkDisplay *display;
+  GList *children;
+  GList *tmp;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  private = (GdkWindowObject *)window;
+  private = (GdkWindowObject*) window;
 
-  if (real_drawable)
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
+  display = gdk_drawable_get_display (GDK_DRAWABLE (window));
+  screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
+  temp_window = g_object_get_qdata (G_OBJECT (screen), quark_pointer_window);
+  if (temp_window == window)
+    g_object_set_qdata (G_OBJECT (screen), quark_pointer_window, NULL);
+
+
+  switch (GDK_WINDOW_TYPE (window))
     {
-      if (private->paint_stack)
+    case GDK_WINDOW_ROOT:
+      if (!screen->closed)
        {
-         GdkWindowPaint *paint = private->paint_stack->data;
-         *real_drawable = paint->pixmap;
+         g_error ("attempted to destroy root window");
+         break;
+       }
+      /* else fall thru */
+    case GDK_WINDOW_TOPLEVEL:
+    case GDK_WINDOW_CHILD:
+    case GDK_WINDOW_DIALOG:
+    case GDK_WINDOW_TEMP:
+    case GDK_WINDOW_FOREIGN:
+    case GDK_WINDOW_OFFSCREEN:
+      if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN && !foreign_destroy)
+       {
+         /* Logically, it probably makes more sense to send
+          * a "destroy yourself" message to the foreign window
+          * whether or not it's in our hierarchy; but for historical
+          * reasons, we only send "destroy yourself" messages to
+          * foreign windows in our hierarchy.
+          */
+         if (private->parent)
+           _gdk_windowing_window_destroy_foreign (window);
+
+         /* Also for historical reasons, we remove any filters
+          * on a foreign window when it or a parent is destroyed;
+          * this likely causes problems if two separate portions
+          * of code are maintaining filter lists on a foreign window.
+          */
+         window_remove_filters (window);
        }
       else
-       *real_drawable = window;
-    }
+       {
+         if (private->parent)
+           {
+             GdkWindowObject *parent_private = (GdkWindowObject *)private->parent;
 
-  gdk_window_get_offsets (window, &x_off, &y_off);
+             if (parent_private->children)
+               parent_private->children = g_list_remove (parent_private->children, window);
 
-  if (x_offset)
-    *x_offset = x_off;
-  if (y_offset)
-    *y_offset = y_off;
-}
+             if (!recursing &&
+                 GDK_WINDOW_IS_MAPPED (window))
+               {
+                 recompute_visible_regions (private, TRUE, FALSE);
+                 gdk_window_invalidate_in_parent (private);
+               }
+           }
 
-#define OFFSET_GC(gc)                                         \
-    gint x_offset, y_offset;                                 \
-    gint old_clip_x = gc->clip_x_origin;    \
-    gint old_clip_y = gc->clip_y_origin;    \
-    gint old_ts_x = gc->ts_x_origin;        \
-    gint old_ts_y = gc->ts_y_origin;        \
-    gdk_window_get_offsets (drawable, &x_offset, &y_offset);  \
-    if (x_offset != 0 || y_offset != 0)                      \
-      {                                                       \
-        gdk_gc_set_clip_origin (gc, old_clip_x - x_offset,    \
-                               old_clip_y - y_offset);       \
-        gdk_gc_set_ts_origin (gc, old_ts_x - x_offset,        \
-                             old_ts_y - y_offset);           \
-      }
-
-#define RESTORE_GC(gc)                                      \
-    if (x_offset != 0 || y_offset != 0)                    \
-     {                                                      \
-       gdk_gc_set_clip_origin (gc, old_clip_x, old_clip_y); \
-       gdk_gc_set_ts_origin (gc, old_ts_x, old_ts_y);       \
-     }
+         gdk_window_free_paint_stack (window);
 
-static GdkGC *
-gdk_window_create_gc (GdkDrawable     *drawable,
-                      GdkGCValues     *values,
-                      GdkGCValuesMask  mask)
-{
-  g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
-  
-  if (GDK_WINDOW_DESTROYED (drawable))
-    return NULL;
+         if (private->bg_pixmap &&
+             private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+             private->bg_pixmap != GDK_NO_BG)
+           {
+             g_object_unref (private->bg_pixmap);
+             private->bg_pixmap = NULL;
+           }
 
-  return gdk_gc_new_with_values (((GdkWindowObject *) drawable)->impl,
-                                 values, mask);
-}
+         if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN)
+           g_assert (private->children == NULL);
+         else
+           {
+             children = tmp = private->children;
+             private->children = NULL;
 
-static void
-gdk_window_draw_rectangle (GdkDrawable *drawable,
-                          GdkGC       *gc,
-                          gboolean     filled,
-                          gint         x,
-                          gint         y,
-                          gint         width,
-                          gint         height)
-{
-  GdkWindowObject *private = (GdkWindowObject *)drawable;
-  OFFSET_GC (gc);
+             while (tmp)
+               {
+                 temp_window = tmp->data;
+                 tmp = tmp->next;
 
-  if (GDK_WINDOW_DESTROYED (drawable))
-    return;
-  
-  if (private->paint_stack)
-    {
-      GdkWindowPaint *paint = private->paint_stack->data;
-      gdk_draw_rectangle (paint->pixmap, gc, filled,
-                          x - x_offset, y - y_offset, width, height);
-    }
-  else
-    gdk_draw_rectangle (private->impl, gc, filled,
-                        x - x_offset, y - y_offset, width, height);
+                 temp_private = (GdkWindowObject*) temp_window;
+                 if (temp_private)
+                   _gdk_window_destroy_hierarchy (temp_window,
+                                                  TRUE,
+                                                  recursing_native || gdk_window_has_impl (private),
+                                                  foreign_destroy);
+               }
 
-  RESTORE_GC (gc);
-}
+             g_list_free (children);
+           }
 
-static void
-gdk_window_draw_arc (GdkDrawable *drawable,
-                    GdkGC       *gc,
-                    gboolean     filled,
-                    gint         x,
-                    gint         y,
-                    gint         width,
-                    gint         height,
-                    gint         angle1,
-                    gint         angle2)
-{
-  GdkWindowObject *private = (GdkWindowObject *)drawable;
-  OFFSET_GC (gc);
+         _gdk_window_clear_update_area (window);
 
-  if (GDK_WINDOW_DESTROYED (drawable))
-    return;
-  
-  if (private->paint_stack)
-    {
-      GdkWindowPaint *paint = private->paint_stack->data;
-      gdk_draw_arc (paint->pixmap, gc, filled,
-                   x - x_offset, y - y_offset,
-                   width, height, angle1, angle2);
-    }
-  else
-    gdk_draw_arc (private->impl, gc, filled,
-                  x - x_offset, y - y_offset,
-                  width, height, angle1, angle2);
-  RESTORE_GC (gc);
-}
+         if (private->cairo_surface)
+           {
+             cairo_surface_finish (private->cairo_surface);
+             cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
+                                          NULL, NULL);
+           }
 
-static void
-gdk_window_draw_polygon (GdkDrawable *drawable,
-                        GdkGC       *gc,
-                        gboolean     filled,
-                        GdkPoint    *points,
-                        gint         npoints)
-{
-  GdkWindowObject *private = (GdkWindowObject *)drawable;
-  GdkPoint *new_points;
-  
-  OFFSET_GC (gc);
 
-  if (GDK_WINDOW_DESTROYED (drawable))
-    return;
-  
-  if (x_offset != 0 || y_offset != 0)
-    {
-      int i;
-      
-      new_points = g_new (GdkPoint, npoints);
-      for (i=0; i<npoints; i++)
-       {
-         new_points[i].x = points[i].x - x_offset;
-         new_points[i].y = points[i].y - y_offset;
-       }
-    }
-  else
-    new_points = points;
+         if (private->extension_events)
+           GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_window_destroy (window);
 
-  if (private->paint_stack)
-    {
-      GdkWindowPaint *paint = private->paint_stack->data;
-      gdk_draw_polygon (paint->pixmap, gc, filled, new_points, npoints);
+         if (gdk_window_has_impl (private))
+           {
+             GDK_WINDOW_IMPL_GET_IFACE (private->impl)->destroy (window, recursing_native, foreign_destroy);
+           }
+         else
+           {
+             /* hide to make sure we repaint and break grabs */
+             gdk_window_hide (window);
+           }
 
-    }
-  else
-    gdk_draw_polygon (private->impl, gc, filled, new_points, npoints);
-  
-  if (new_points != points)
-    g_free (new_points);
+         private->state |= GDK_WINDOW_STATE_WITHDRAWN;
+         private->parent = NULL;
+         private->destroyed = TRUE;
 
-  RESTORE_GC (gc);
-}
+         window_remove_filters (window);
 
-static void
-gdk_window_draw_text (GdkDrawable *drawable,
-                     GdkFont     *font,
-                     GdkGC       *gc,
-                     gint         x,
-                     gint         y,
-                     const gchar *text,
-                     gint         text_length)
-{
-  GdkWindowObject *private = (GdkWindowObject *)drawable;
-  OFFSET_GC (gc);
+         gdk_drawable_set_colormap (GDK_DRAWABLE (window), NULL);
 
-  if (GDK_WINDOW_DESTROYED (drawable))
-    return;
-  
-  if (private->paint_stack)
-    {
-      GdkWindowPaint *paint = private->paint_stack->data;
-      gdk_draw_text (paint->pixmap, font, gc, 
-                    x - x_offset, y - y_offset, text, text_length);
+         /* If we own the redirect, free it */
+         if (private->redirect && private->redirect->redirected == private)
+           gdk_window_redirect_free (private->redirect);
 
-    }
-  else
-    gdk_draw_text (private->impl, font, gc,
-                   x - x_offset, y - y_offset, text, text_length);
+         private->redirect = NULL;
 
-  RESTORE_GC (gc);
+         if (display->pointer_info.toplevel_under_pointer == window)
+           {
+             g_object_unref (display->pointer_info.toplevel_under_pointer);
+             display->pointer_info.toplevel_under_pointer = NULL;
+           }
+       }
+      break;
+    }
 }
 
-static void
-gdk_window_draw_text_wc (GdkDrawable    *drawable,
-                        GdkFont        *font,
-                        GdkGC          *gc,
-                        gint            x,
-                        gint            y,
-                        const GdkWChar *text,
-                        gint            text_length)
-{
-  GdkWindowObject *private = (GdkWindowObject *)drawable;
-  OFFSET_GC (gc);
-
-  if (GDK_WINDOW_DESTROYED (drawable))
-    return;
-  
+/**
+ * _gdk_window_destroy:
+ * @window: a #GdkWindow
+ * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
+ *            external agency. The window has already been destroyed and no
+ *            windowing system calls should be made. (This may never happen
+ *            for some windowing systems.)
+ *
+ * Internal function to destroy a window. Like gdk_window_destroy(),
+ * but does not drop the reference count created by gdk_window_new().
+ **/
+void
+_gdk_window_destroy (GdkWindow *window,
+                    gboolean   foreign_destroy)
+{
+  _gdk_window_destroy_hierarchy (window, FALSE, FALSE, foreign_destroy);
+}
+
+/**
+ * gdk_window_destroy:
+ * @window: a #GdkWindow
+ *
+ * Destroys the window system resources associated with @window and decrements @window's
+ * reference count. The window system resources for all children of @window are also
+ * destroyed, but the children's reference counts are not decremented.
+ *
+ * Note that a window will not be destroyed automatically when its reference count
+ * reaches zero. You must call this function yourself before that happens.
+ *
+ **/
+void
+gdk_window_destroy (GdkWindow *window)
+{
+  _gdk_window_destroy_hierarchy (window, FALSE, FALSE, FALSE);
+  g_object_unref (window);
+}
+
+/**
+ * gdk_window_set_user_data:
+ * @window: a #GdkWindow
+ * @user_data: user data
+ *
+ * For most purposes this function is deprecated in favor of
+ * g_object_set_data(). However, for historical reasons GTK+ stores
+ * the #GtkWidget that owns a #GdkWindow as user data on the
+ * #GdkWindow. So, custom widget implementations should use
+ * this function for that. If GTK+ receives an event for a #GdkWindow,
+ * and the user data for the window is non-%NULL, GTK+ will assume the
+ * user data is a #GtkWidget, and forward the event to that widget.
+ *
+ **/
+void
+gdk_window_set_user_data (GdkWindow *window,
+                         gpointer   user_data)
+{
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  ((GdkWindowObject*)window)->user_data = user_data;
+}
+
+/**
+ * gdk_window_get_user_data:
+ * @window: a #GdkWindow
+ * @data: return location for user data
+ *
+ * Retrieves the user data for @window, which is normally the widget
+ * that @window belongs to. See gdk_window_set_user_data().
+ *
+ **/
+void
+gdk_window_get_user_data (GdkWindow *window,
+                         gpointer  *data)
+{
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  *data = ((GdkWindowObject*)window)->user_data;
+}
+
+/**
+ * gdk_window_get_window_type:
+ * @window: a #GdkWindow
+ *
+ * Gets the type of the window. See #GdkWindowType.
+ *
+ * Return value: type of window
+ **/
+GdkWindowType
+gdk_window_get_window_type (GdkWindow *window)
+{
+  g_return_val_if_fail (GDK_IS_WINDOW (window), (GdkWindowType) -1);
+
+  return GDK_WINDOW_TYPE (window);
+}
+
+/**
+ * gdk_window_get_position:
+ * @window: a #GdkWindow
+ * @x: X coordinate of window
+ * @y: Y coordinate of window
+ *
+ * Obtains the position of the window as reported in the
+ * most-recently-processed #GdkEventConfigure. Contrast with
+ * gdk_window_get_geometry() which queries the X server for the
+ * current window position, regardless of which events have been
+ * received or processed.
+ *
+ * The position coordinates are relative to the window's parent window.
+ *
+ **/
+void
+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;
+  if (y)
+    *y = obj->y;
+}
+
+/**
+ * gdk_window_get_parent:
+ * @window: a #GdkWindow
+ *
+ * Obtains the parent of @window, as known to GDK. Does not query the
+ * X server; thus this returns the parent as passed to gdk_window_new(),
+ * not the actual parent. This should never matter unless you're using
+ * Xlib calls mixed with GDK calls on the X11 platform. It may also
+ * matter for toplevel windows, because the window manager may choose
+ * to reparent them.
+ *
+ * Return value: parent of @window
+ **/
+GdkWindow*
+gdk_window_get_parent (GdkWindow *window)
+{
+  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
+
+  return (GdkWindow*) ((GdkWindowObject*) window)->parent;
+}
+
+/**
+ * gdk_window_get_toplevel:
+ * @window: a #GdkWindow
+ *
+ * Gets the toplevel window that's an ancestor of @window.
+ *
+ * Any window type but %GDK_WINDOW_CHILD is considered a
+ * toplevel window, as is a %GDK_WINDOW_CHILD window that
+ * has a root window as parent.
+ *
+ * Return value: the toplevel window containing @window
+ **/
+GdkWindow*
+gdk_window_get_toplevel (GdkWindow *window)
+{
+  GdkWindowObject *obj;
+
+  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
+
+  obj = (GdkWindowObject *)window;
+
+  while (GDK_WINDOW_TYPE (obj) == GDK_WINDOW_CHILD)
+    {
+      if (obj->parent == NULL ||
+         GDK_WINDOW_TYPE (obj->parent) == GDK_WINDOW_ROOT)
+       break;
+      obj = obj->parent;
+    }
+
+  return GDK_WINDOW (obj);
+}
+
+/**
+ * gdk_window_get_children:
+ * @window: a #GdkWindow
+ *
+ * Gets the list of children of @window known to GDK.
+ * This function only returns children created via GDK,
+ * so for example it's useless when used with the root window;
+ * it only returns windows an application created itself.
+ *
+ * The returned list must be freed, but the elements in the
+ * list need not be.
+ *
+ * Return value: list of child windows inside @window
+ **/
+GList*
+gdk_window_get_children (GdkWindow *window)
+{
+  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
+
+  if (GDK_WINDOW_DESTROYED (window))
+    return NULL;
+
+  return g_list_copy (GDK_WINDOW_OBJECT (window)->children);
+}
+
+/**
+ * gdk_window_peek_children:
+ * @window: a #GdkWindow
+ *
+ * Like gdk_window_get_children(), but does not copy the list of
+ * children, so the list does not need to be freed.
+ *
+ * Return value: a reference to the list of child windows in @window
+ **/
+GList *
+gdk_window_peek_children (GdkWindow *window)
+{
+  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
+
+  if (GDK_WINDOW_DESTROYED (window))
+    return NULL;
+
+  return GDK_WINDOW_OBJECT (window)->children;
+}
+
+/**
+ * gdk_window_add_filter:
+ * @window: a #GdkWindow
+ * @function: filter callback
+ * @data: data to pass to filter callback
+ *
+ * Adds an event filter to @window, allowing you to intercept events
+ * before they reach GDK. This is a low-level operation and makes it
+ * easy to break GDK and/or GTK+, so you have to know what you're
+ * doing. Pass %NULL for @window to get all events for all windows,
+ * instead of events for a specific window.
+ *
+ * See gdk_display_add_client_message_filter() if you are interested
+ * in X ClientMessage events.
+ **/
+void
+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))
+    return;
+
+  /* Filters are for the native events on the native window, so
+     ensure there is a native window. */
+  if (window)
+    gdk_window_ensure_native (window);
+
+  if (private)
+    tmp_list = private->filters;
+  else
+    tmp_list = _gdk_default_filters;
+
+  while (tmp_list)
+    {
+      filter = (GdkEventFilter *)tmp_list->data;
+      if ((filter->function == function) && (filter->data == data))
+       return;
+      tmp_list = tmp_list->next;
+    }
+
+  filter = g_new (GdkEventFilter, 1);
+  filter->function = function;
+  filter->data = data;
+
+  if (private)
+    private->filters = g_list_append (private->filters, filter);
+  else
+    _gdk_default_filters = g_list_append (_gdk_default_filters, filter);
+}
+
+/**
+ * gdk_window_remove_filter:
+ * @window: a #GdkWindow
+ * @function: previously-added filter function
+ * @data: user data for previously-added filter function
+ *
+ * Remove a filter previously added with gdk_window_add_filter().
+ *
+ **/
+void
+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;
+  else
+    tmp_list = _gdk_default_filters;
+
+  while (tmp_list)
+    {
+      filter = (GdkEventFilter *)tmp_list->data;
+      node = tmp_list;
+      tmp_list = tmp_list->next;
+
+      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);
+
+         return;
+       }
+    }
+}
+
+/**
+ * gdk_screen_get_toplevel_windows:
+ * @screen: The #GdkScreen where the toplevels are located.
+ *
+ * Obtains a list of all toplevel windows known to GDK on the screen @screen.
+ * A toplevel window is a child of the root window (see
+ * gdk_get_default_root_window()).
+ *
+ * The returned list should be freed with g_list_free(), but
+ * its elements need not be freed.
+ *
+ * Return value: list of toplevel windows, free with g_list_free()
+ *
+ * Since: 2.2
+ **/
+GList *
+gdk_screen_get_toplevel_windows (GdkScreen *screen)
+{
+  GdkWindow * root_window;
+  GList *new_list = NULL;
+  GList *tmp_list;
+
+  g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
+
+  root_window = gdk_screen_get_root_window (screen);
+
+  tmp_list = ((GdkWindowObject *)root_window)->children;
+  while (tmp_list)
+    {
+      if (GDK_WINDOW_TYPE (tmp_list->data) != GDK_WINDOW_FOREIGN)
+       new_list = g_list_prepend (new_list, tmp_list->data);
+      tmp_list = tmp_list->next;
+    }
+
+  return new_list;
+}
+
+/**
+ * gdk_window_get_toplevels:
+ *
+ * Obtains a list of all toplevel windows known to GDK on the default
+ * screen (see gdk_screen_get_toplevel_windows()).
+ * A toplevel window is a child of the root window (see
+ * gdk_get_default_root_window()).
+ *
+ * The returned list should be freed with g_list_free(), but
+ * its elements need not be freed.
+ *
+ * Return value: list of toplevel windows, free with g_list_free()
+ *
+ * Deprecated: 2.16: Use gdk_screen_get_toplevel_windows() instead.
+ **/
+GList *
+gdk_window_get_toplevels (void)
+{
+  return gdk_screen_get_toplevel_windows (gdk_screen_get_default ());
+}
+
+/**
+ * gdk_window_is_visible:
+ * @window: a #GdkWindow
+ *
+ * Checks whether the window has been mapped (with gdk_window_show() or
+ * gdk_window_show_unraised()).
+ *
+ * Return value: %TRUE if the window is mapped
+ **/
+gboolean
+gdk_window_is_visible (GdkWindow *window)
+{
+  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+
+  return GDK_WINDOW_IS_MAPPED (window);
+}
+
+/**
+ * gdk_window_is_viewable:
+ * @window: a #GdkWindow
+ *
+ * Check if the window and all ancestors of the window are
+ * mapped. (This is not necessarily "viewable" in the X sense, since
+ * we only check as far as we have GDK window parents, not to the root
+ * window.)
+ *
+ * Return value: %TRUE if the window is viewable
+ **/
+gboolean
+gdk_window_is_viewable (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkScreen *screen;
+  GdkWindow *root_window;
+
+  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+
+  screen = gdk_drawable_get_screen (window);
+  root_window = gdk_screen_get_root_window (screen);
+
+  while (private &&
+        (private != (GdkWindowObject *)root_window) &&
+        (GDK_WINDOW_TYPE (private) != GDK_WINDOW_FOREIGN))
+    {
+      if (GDK_WINDOW_DESTROYED (private) || !GDK_WINDOW_IS_MAPPED (private))
+       return FALSE;
+
+      private = (GdkWindowObject *)private->parent;
+    }
+
+  return TRUE;
+}
+
+/**
+ * gdk_window_get_state:
+ * @window: a #GdkWindow
+ *
+ * Gets the bitwise OR of the currently active window state flags,
+ * from the #GdkWindowState enumeration.
+ *
+ * Return value: window state bitfield
+ **/
+GdkWindowState
+gdk_window_get_state (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+
+  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+
+  return private->state;
+}
+
+
+/* This creates an empty "implicit" paint region for the impl window.
+ * By itself this does nothing, but real paints to this window
+ * or children of it can use this pixmap as backing to avoid allocating
+ * multiple pixmaps for subwindow rendering. When doing so they
+ * add to the region of the implicit paint region, which will be
+ * pushed to the window when the implicit paint region is ended.
+ * Such paints should not copy anything to the window on paint end, but
+ * should rely on the implicit paint end.
+ * The implicit paint will be automatically ended if someone draws
+ * directly to the window or a child window.
+ */
+static gboolean
+gdk_window_begin_implicit_paint (GdkWindow *window, GdkRectangle *rect)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowPaint *paint;
+
+  g_assert (gdk_window_has_impl (private));
+
+  if (GDK_IS_PAINTABLE (private->impl))
+    return FALSE; /* Implementation does double buffering */
+
+  if (private->paint_stack != NULL ||
+      private->implicit_paint != NULL)
+    return FALSE; /* Don't stack implicit paints */
+
+  paint = g_new (GdkWindowPaint, 1);
+  paint->region = gdk_region_new (); /* Empty */
+  paint->x_offset = rect->x;
+  paint->y_offset = rect->y;
+  paint->uses_implicit = FALSE;
+  paint->surface = NULL;
+  paint->pixmap =
+    gdk_pixmap_new (window,
+                   MAX (rect->width, 1), MAX (rect->height, 1), -1);
+
+  private->implicit_paint = paint;
+
+  return TRUE;
+}
+
+/* Ensure that all content related to this (sub)window is pushed to the
+   native region. 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;
+  GdkWindowPaint *paint;
+  GdkRegion *region;
+  GdkGC *tmp_gc;
+  GSList *list;
+
+  impl_window = gdk_window_get_impl_window (private);
+  if (impl_window->implicit_paint == NULL)
+    return;
+
+  paint = impl_window->implicit_paint;
+  region = gdk_region_copy (private->clip_region_with_children);
+
+  /* Don't flush active double buffers, as that may show partially done
+   * rendering */
+  for (list = private->paint_stack; list != NULL; list = list->next)
+    {
+      GdkWindowPaint *tmp_paint = list->data;
+
+      gdk_region_subtract (region, tmp_paint->region);
+    }
+
+  gdk_region_offset (region, private->abs_x, private->abs_y);
+  gdk_region_intersect (region, paint->region);
+
+  if (!gdk_region_empty (region))
+    {
+      /* Some regions are valid, push these to window now */
+      tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
+      _gdk_gc_set_clip_region_internal (tmp_gc, region, TRUE);
+      gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
+                        0, 0, paint->x_offset, paint->y_offset, -1, -1);
+      /* Reset clip region of the cached GdkGC */
+      gdk_gc_set_clip_region (tmp_gc, NULL);
+
+      /* Remove flushed region from the implicit paint */
+      gdk_region_subtract (paint->region, region);
+    }
+  else
+    gdk_region_destroy (region);
+}
+
+/* Ends an implicit paint, paired with gdk_window_begin_implicit_paint returning TRUE */
+static void
+gdk_window_end_implicit_paint (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowPaint *paint;
+  GdkGC *tmp_gc;
+
+  g_assert (gdk_window_has_impl (private));
+
+  g_assert (private->implicit_paint != NULL);
+
+  paint = private->implicit_paint;
+
+  private->implicit_paint = NULL;
+
+  if (!gdk_region_empty (paint->region))
+    {
+      /* Some regions are valid, push these to window now */
+      tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
+      _gdk_gc_set_clip_region_internal (tmp_gc, paint->region, TRUE);
+      gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
+                        0, 0, paint->x_offset, paint->y_offset, -1, -1);
+      /* Reset clip region of the cached GdkGC */
+      gdk_gc_set_clip_region (tmp_gc, NULL);
+    }
+
+  g_object_unref (paint->pixmap);
+  g_free (paint);
+}
+
+/**
+ * gdk_window_begin_paint_rect:
+ * @window: a #GdkWindow
+ * @rectangle: rectangle you intend to draw to
+ *
+ * A convenience wrapper around gdk_window_begin_paint_region() which
+ * creates a rectangular region for you. See
+ * gdk_window_begin_paint_region() for details.
+ *
+ **/
+void
+gdk_window_begin_paint_rect (GdkWindow          *window,
+                            const GdkRectangle *rectangle)
+{
+  GdkRegion *region;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  region = gdk_region_rectangle (rectangle);
+  gdk_window_begin_paint_region (window, region);
+  gdk_region_destroy (region);
+}
+
+#ifdef GDK_WINDOWING_X11
+#include "x11/gdkx.h"
+#endif
+
+/**
+ * gdk_window_begin_paint_region:
+ * @window: a #GdkWindow
+ * @region: region you intend to draw to
+ *
+ * Indicates that you are beginning the process of redrawing @region.
+ * A backing store (offscreen buffer) large enough to contain @region
+ * will be created. The backing store will be initialized with the
+ * background color or background pixmap for @window. Then, all
+ * drawing operations performed on @window will be diverted to the
+ * backing store.  When you call gdk_window_end_paint(), the backing
+ * store will be copied to @window, making it visible onscreen. Only
+ * the part of @window contained in @region will be modified; that is,
+ * drawing operations are clipped to @region.
+ *
+ * The net result of all this is to remove flicker, because the user
+ * sees the finished product appear all at once when you call
+ * gdk_window_end_paint(). If you draw to @window directly without
+ * calling gdk_window_begin_paint_region(), the user may see flicker
+ * as individual drawing operations are performed in sequence.  The
+ * clipping and background-initializing features of
+ * gdk_window_begin_paint_region() are conveniences for the
+ * programmer, so you can avoid doing that work yourself.
+ *
+ * When using GTK+, the widget system automatically places calls to
+ * gdk_window_begin_paint_region() and gdk_window_end_paint() around
+ * emissions of the expose_event signal. That is, if you're writing an
+ * expose event handler, you can assume that the exposed area in
+ * #GdkEventExpose has already been cleared to the window background,
+ * is already set as the clip region, and already has a backing store.
+ * Therefore in most cases, application code need not call
+ * gdk_window_begin_paint_region(). (You can disable the automatic
+ * calls around expose events on a widget-by-widget basis by calling
+ * gtk_widget_set_double_buffered().)
+ *
+ * If you call this function multiple times before calling the
+ * matching gdk_window_end_paint(), the backing stores are pushed onto
+ * a stack. gdk_window_end_paint() copies the topmost backing store
+ * onscreen, subtracts the topmost region from all other regions in
+ * the stack, and pops the stack. All drawing operations affect only
+ * the topmost backing store in the stack. One matching call to
+ * gdk_window_end_paint() is required for each call to
+ * gdk_window_begin_paint_region().
+ *
+ **/
+void
+gdk_window_begin_paint_region (GdkWindow       *window,
+                              const GdkRegion *region)
+{
+#ifdef USE_BACKING_STORE
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkRectangle clip_box;
+  GdkWindowPaint *paint, *implicit_paint;
+  GdkWindowObject *impl_window;
+  GSList *list;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
+  if (GDK_IS_PAINTABLE (private->impl))
+    {
+      GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
+
+      if (iface->begin_paint_region)
+       iface->begin_paint_region ((GdkPaintable*)private->impl, window, region);
+
+      return;
+    }
+
+  impl_window = gdk_window_get_impl_window (private);
+  implicit_paint = impl_window->implicit_paint;
+
+  paint = g_new (GdkWindowPaint, 1);
+  paint->region = gdk_region_copy (region);
+  paint->region_tag = new_region_tag ();
+
+  gdk_region_intersect (paint->region, private->clip_region_with_children);
+  gdk_region_get_clipbox (paint->region, &clip_box);
+
+  /* Convert to impl coords */
+  gdk_region_offset (paint->region, private->abs_x, private->abs_y);
+
+  /* Mark the region as valid on the implicit paint */
+
+  if (implicit_paint)
+    gdk_region_union (implicit_paint->region, paint->region);
+
+  /* Convert back to normal coords */
+  gdk_region_offset (paint->region, -private->abs_x, -private->abs_y);
+
+  if (implicit_paint)
+    {
+      int width, height;
+
+      paint->uses_implicit = TRUE;
+      paint->pixmap = g_object_ref (implicit_paint->pixmap);
+      paint->x_offset = -private->abs_x + implicit_paint->x_offset;
+      paint->y_offset = -private->abs_y + implicit_paint->y_offset;
+
+      /* It would be nice if we had some cairo support here so we
+        could set the clip rect on the cairo surface */
+      width = private->abs_x + private->width;
+      height = private->abs_y + private->height;
+
+      paint->surface = _gdk_drawable_create_cairo_surface (paint->pixmap, width, height);
+
+    }
+  else
+    {
+      paint->uses_implicit = FALSE;
+      paint->x_offset = clip_box.x;
+      paint->y_offset = clip_box.y;
+      paint->pixmap =
+       gdk_pixmap_new (window,
+                       MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1);
+      paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap);
+    }
+
+  if (paint->surface)
+    cairo_surface_set_device_offset (paint->surface,
+                                    -paint->x_offset, -paint->y_offset);
+
+  for (list = private->paint_stack; list != NULL; list = list->next)
+    {
+      GdkWindowPaint *tmp_paint = list->data;
+
+      gdk_region_subtract (tmp_paint->region, paint->region);
+    }
+
+  private->paint_stack = g_slist_prepend (private->paint_stack, paint);
+
+  if (!gdk_region_empty (paint->region))
+    {
+      gdk_window_clear_backing_region (window,
+                                      paint->region);
+    }
+
+#endif /* USE_BACKING_STORE */
+}
+
+static void
+setup_redirect_clip (GdkWindow      *window,
+                    GdkGC          *gc,
+                    int            *x_offset_out,
+                    int            *y_offset_out)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkRegion *visible_region;
+  GdkRectangle dest_rect;
+  GdkRegion *tmpreg;
+  GdkWindow *toplevel;
+  int x_offset, y_offset;
+
+  toplevel = GDK_WINDOW (private->redirect->redirected);
+
+  /* Get the clip region for gc clip rect + window hierarchy in
+     window relative coords */
+  visible_region =
+    _gdk_window_calculate_full_clip_region (window, toplevel,
+                                           TRUE,
+                                           &x_offset,
+                                           &y_offset);
+
+  /* Compensate for the source pos/size */
+  x_offset -= private->redirect->src_x;
+  y_offset -= private->redirect->src_y;
+  dest_rect.x = -x_offset;
+  dest_rect.y = -y_offset;
+  dest_rect.width = private->redirect->width;
+  dest_rect.height = private->redirect->height;
+  tmpreg = gdk_region_rectangle (&dest_rect);
+  gdk_region_intersect (visible_region, tmpreg);
+  gdk_region_destroy (tmpreg);
+
+  /* Compensate for the dest pos */
+  x_offset += private->redirect->dest_x;
+  y_offset += private->redirect->dest_y;
+
+  gdk_gc_set_clip_region (gc, visible_region); /* This resets clip origin! */
+
+  /* offset clip and tiles from window coords to pixmaps coords */
+  gdk_gc_offset (gc, -x_offset, -y_offset);
+
+  gdk_region_destroy (visible_region);
+
+  *x_offset_out = x_offset;
+  *y_offset_out = y_offset;
+}
+
+/**
+ * gdk_window_end_paint:
+ * @window: a #GdkWindow
+ *
+ * Indicates that the backing store created by the most recent call to
+ * gdk_window_begin_paint_region() should be copied onscreen and
+ * deleted, leaving the next-most-recent backing store or no backing
+ * store at all as the active paint region. See
+ * gdk_window_begin_paint_region() for full details. It is an error to
+ * call this function without a matching
+ * gdk_window_begin_paint_region() first.
+ *
+ **/
+void
+gdk_window_end_paint (GdkWindow *window)
+{
+#ifdef USE_BACKING_STORE
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *composited;
+  GdkWindowPaint *paint;
+  GdkGC *tmp_gc;
+  GdkRectangle clip_box;
+  gint x_offset, y_offset;
+  GdkRegion *full_clip;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
+  if (GDK_IS_PAINTABLE (private->impl))
+    {
+      GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
+
+      if (iface->end_paint)
+       iface->end_paint ((GdkPaintable*)private->impl);
+      return;
+    }
+
+  if (private->paint_stack == NULL)
+    {
+      g_warning (G_STRLOC": no preceding call to gdk_window_begin_paint_region(), see documentation");
+      return;
+    }
+
+  paint = private->paint_stack->data;
+
+  private->paint_stack = g_slist_delete_link (private->paint_stack,
+                                             private->paint_stack);
+
+  gdk_region_get_clipbox (paint->region, &clip_box);
+
+  tmp_gc = _gdk_drawable_get_scratch_gc (window, FALSE);
+
+  x_offset = -private->abs_x;
+  y_offset = -private->abs_y;
+
+  if (!paint->uses_implicit)
+    {
+      gdk_window_flush_outstanding_moves (window);
+
+      full_clip = gdk_region_copy (private->clip_region_with_children);
+      gdk_region_intersect (full_clip, paint->region);
+      _gdk_gc_set_clip_region_internal (tmp_gc, full_clip, TRUE); /* Takes ownership of full_clip */
+      gdk_gc_set_clip_origin (tmp_gc, - x_offset, - y_offset);
+      gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
+                        clip_box.x - paint->x_offset,
+                        clip_box.y - paint->y_offset,
+                        clip_box.x - x_offset, clip_box.y - y_offset,
+                        clip_box.width, clip_box.height);
+    }
+
+  if (private->redirect)
+    {
+      int x_offset, y_offset;
+
+      /* TODO: Should also use paint->region for clipping */
+      setup_redirect_clip (window, tmp_gc, &x_offset, &y_offset);
+      gdk_draw_drawable (private->redirect->pixmap, tmp_gc, paint->pixmap,
+                        clip_box.x - paint->x_offset,
+                        clip_box.y - paint->y_offset,
+                        clip_box.x + x_offset,
+                        clip_box.y + y_offset,
+                        clip_box.width, clip_box.height);
+    }
+
+  /* Reset clip region of the cached GdkGC */
+  gdk_gc_set_clip_region (tmp_gc, NULL);
+
+  cairo_surface_destroy (paint->surface);
+  g_object_unref (paint->pixmap);
+  gdk_region_destroy (paint->region);
+  g_free (paint);
+
+  /* find a composited window in our hierarchy to signal its
+   * parent to redraw, calculating the clip box as we go...
+   *
+   * stop if parent becomes NULL since then we'd have nowhere
+   * to draw (ie: 'composited' will always be non-NULL here).
+   */
+  for (composited = private;
+       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);
+
+      if (composited->composited)
+       {
+         gdk_window_invalidate_rect (GDK_WINDOW (composited->parent),
+                                     &clip_box, FALSE);
+         break;
+       }
+    }
+#endif /* USE_BACKING_STORE */
+}
+
+static void
+gdk_window_free_paint_stack (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+
+  if (private->paint_stack)
+    {
+      GSList *tmp_list = private->paint_stack;
+
+      while (tmp_list)
+       {
+         GdkWindowPaint *paint = tmp_list->data;
+
+         if (tmp_list == private->paint_stack)
+           g_object_unref (paint->pixmap);
+
+         gdk_region_destroy (paint->region);
+         g_free (paint);
+
+         tmp_list = tmp_list->next;
+       }
+
+      g_slist_free (private->paint_stack);
+      private->paint_stack = NULL;
+    }
+}
+
+static void
+do_move_region_bits_on_impl (GdkWindowObject *impl_window,
+                            GdkRegion *dest_region, /* In impl window coords */
+                            int dx, int dy)
+{
+  GdkGC *tmp_gc;
+  GdkRectangle copy_rect;
+  GdkWindowObject *private;
+
+  /* We need to get data from subwindows here, because we might have
+   * shaped a native window over the moving region (with bg none,
+   * so the pixels are still there). In fact we might need to get data
+   * from overlapping native window that are not children of this window,
+   * so we copy from the toplevel with INCLUDE_INFERIORS.
+   */
+  private = impl_window;
+  while (private->parent != NULL &&
+        GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
+    {
+      dx -= private->parent->abs_x + private->x;
+      dy -= private->parent->abs_y + private->y;
+      private = gdk_window_get_impl_window (private->parent);
+    }
+  tmp_gc = _gdk_drawable_get_subwindow_scratch_gc ((GdkWindow *)private);
+
+  /* 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_WINDOW_IMPL_GET_IFACE (private->impl)->queue_translation ((GdkWindow *)impl_window,
+                                                               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,
+                    copy_rect.x-dx, copy_rect.y-dy,
+                    copy_rect.x, copy_rect.y,
+                    copy_rect.width, copy_rect.height);
+  gdk_gc_set_clip_region (tmp_gc, NULL);
+}
+
+static GdkWindowRegionMove *
+gdk_window_region_move_new (GdkRegion *region,
+                           int dx, int dy)
+{
+  GdkWindowRegionMove *move;
+
+  move = g_slice_new (GdkWindowRegionMove);
+  move->dest_region  = gdk_region_copy (region);
+  move->dx = dx;
+  move->dy = dy;
+
+  return move;
+}
+
+static void
+gdk_window_region_move_free (GdkWindowRegionMove *move)
+{
+  gdk_region_destroy (move->dest_region);
+  g_slice_free (GdkWindowRegionMove, move);
+}
+
+static void
+append_move_region (GdkWindowObject *impl_window,
+                   GdkRegion *new_dest_region,
+                   int dx, int dy)
+{
+  GdkWindowRegionMove *move, *old_move;
+  GdkRegion *new_total_region, *old_total_region;
+  GdkRegion *source_overlaps_destination;
+  GdkRegion *non_overwritten;
+  gboolean added_move;
+  GList *l, *prev;
+
+  if (gdk_region_empty (new_dest_region))
+    return;
+
+  /* In principle this could just append the move to the list of outstanding
+     moves that will be replayed before drawing anything when we're handling
+     exposes. However, we'd like to do a bit better since its commonly the case
+     that we get multiple copies where A is copied to B and then B is copied
+     to C, and we'd like to express this as a simple copy A to C operation. */
+
+  /* We approach this by taking the new move and pushing it ahead of moves
+     starting at the end of the list and stopping when its not safe to do so.
+     Its not safe to push past a move is either the source of the new move
+     is in the destination of the old move, or if the destination of the new
+     move is in the source of the new move, or if the destination of the new
+     move overlaps the destination of the old move. We simplify this by
+     just comparing the total regions (src + dest) */
+  new_total_region = gdk_region_copy (new_dest_region);
+  gdk_region_offset (new_total_region, -dx, -dy);
+  gdk_region_union (new_total_region, new_dest_region);
+
+  added_move = FALSE;
+  for (l = g_list_last (impl_window->outstanding_moves); l != NULL; l = prev)
+    {
+      prev = l->prev;
+      old_move = l->data;
+
+      old_total_region = gdk_region_copy (old_move->dest_region);
+      gdk_region_offset (old_total_region, -old_move->dx, -old_move->dy);
+      gdk_region_union (old_total_region, old_move->dest_region);
+
+      gdk_region_intersect (old_total_region, new_total_region);
+      /* If these regions intersect then its not safe to push the
+        new region before the old one */
+      if (!gdk_region_empty (old_total_region))
+       {
+         /* The area where the new moves source overlaps the old ones
+            destination */
+         source_overlaps_destination = gdk_region_copy (new_dest_region);
+         gdk_region_offset (source_overlaps_destination, -dx, -dy);
+         gdk_region_intersect (source_overlaps_destination, old_move->dest_region);
+         gdk_region_offset (source_overlaps_destination, dx, dy);
+
+         /* We can do all sort of optimizations here, but to do things safely it becomes
+            quite complicated. However, a very common case is that you copy something first,
+            then copy all that or a subset of it to a new location (i.e. if you scroll twice
+            in the same direction). We'd like to detect this case and optimize it to one
+            copy. */
+         if (gdk_region_equal (source_overlaps_destination, new_dest_region))
+           {
+             /* This means we might be able to replace the old move and the new one
+                with the new one read from the old ones source, and a second copy of
+                the non-overwritten parts of the old move. However, such a split
+                is only valid if the source in the old move isn't overwritten
+                by the destination of the new one */
+
+             /* the new destination of old move if split is ok: */
+             non_overwritten = gdk_region_copy (old_move->dest_region);
+             gdk_region_subtract (non_overwritten, new_dest_region);
+             /* move to source region */
+             gdk_region_offset (non_overwritten, -old_move->dx, -old_move->dy);
+
+             gdk_region_intersect (non_overwritten, new_dest_region);
+             if (gdk_region_empty (non_overwritten))
+               {
+                 added_move = TRUE;
+                 move = gdk_window_region_move_new (new_dest_region,
+                                                    dx + old_move->dx,
+                                                    dy + old_move->dy);
+
+                 impl_window->outstanding_moves =
+                   g_list_insert_before (impl_window->outstanding_moves,
+                                         l, move);
+                 gdk_region_subtract (old_move->dest_region, new_dest_region);
+               }
+             gdk_region_destroy (non_overwritten);
+           }
+
+         gdk_region_destroy (source_overlaps_destination);
+         gdk_region_destroy (old_total_region);
+         break;
+       }
+      gdk_region_destroy (old_total_region);
+    }
+
+  gdk_region_destroy (new_total_region);
+
+  if (!added_move)
+    {
+      move = gdk_window_region_move_new (new_dest_region, dx, dy);
+
+      if (l == NULL)
+       impl_window->outstanding_moves =
+         g_list_prepend (impl_window->outstanding_moves,
+                         move);
+      else
+       impl_window->outstanding_moves =
+         g_list_insert_before (impl_window->outstanding_moves,
+                               l->next, move);
+    }
+}
+
+/* Moves bits and update area by dx/dy in impl window,
+   takes ownership of region */
+static void
+move_region_on_impl (GdkWindowObject *private,
+                    GdkRegion *region, /* In impl window coords */
+                    int dx, int dy)
+{
+  GdkWindowObject *impl_window;
+
+  if ((dx == 0 && dy == 0) ||
+      gdk_region_empty (region))
+    {
+      gdk_region_destroy (region);
+      return;
+    }
+
+  impl_window = gdk_window_get_impl_window (private);
+
+  /* Move any old invalid regions in the copy source area by dx/dy */
+  if (impl_window->update_area)
+    {
+      GdkRegion *update_area;
+      update_area = gdk_region_copy (region);
+
+      /* 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);
+
+      /* Convert back */
+      gdk_region_offset (update_area, dx, dy);
+      gdk_region_union (impl_window->update_area, update_area);
+
+      /* This area of the destination is now invalid,
+        so no need to copy to it.  */
+      gdk_region_subtract (region, update_area);
+
+      gdk_region_destroy (update_area);
+    }
+
+  if (1) /* 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);
+
+  gdk_region_destroy (region);
+}
+
+/* Flushes all outstanding changes to the window, call this
+ * before drawing directly to the window (i.e. outside a begin/end_paint pair).
+ */
+static void
+gdk_window_flush_outstanding_moves (GdkWindow *window)
+{
+  GdkWindowObject *private;
+  GdkWindowObject *impl_window;
+  GList *l;
+  GdkWindowRegionMove *move;
+
+  private = (GdkWindowObject *) window;
+
+  impl_window = gdk_window_get_impl_window (private);
+
+  for (l = impl_window->outstanding_moves; l != NULL; l = l->next)
+    {
+      move = l->data;
+
+      do_move_region_bits_on_impl (impl_window,
+                                  move->dest_region, move->dx, move->dy);
+
+      gdk_window_region_move_free (move);
+    }
+
+  g_list_free (impl_window->outstanding_moves);
+  impl_window->outstanding_moves = NULL;
+}
+
+static void
+gdk_window_flush (GdkWindow *window)
+{
+  gdk_window_flush_outstanding_moves (window);
+  gdk_window_flush_implicit_paint (window);
+}
+
+static void
+gdk_window_flush_recursive_helper (GdkWindowObject *window,
+                                  GdkWindow *impl)
+{
+  GdkWindowObject *child;
+  GList *l;
+
+  for (l = window->children; l != NULL; l = l->next)
+    {
+      child = l->data;
+
+      if (child->impl == impl)
+       /* Same impl, ignore */
+       gdk_window_flush_recursive_helper (child, impl);
+      else
+       gdk_window_flush_recursive (child);
+    }
+}
+
+static void
+gdk_window_flush_recursive (GdkWindowObject *window)
+{
+  gdk_window_flush ((GdkWindow *)window);
+  gdk_window_flush_recursive_helper (window, window->impl);
+}
+
+static void
+gdk_window_get_offsets (GdkWindow *window,
+                       gint      *x_offset,
+                       gint      *y_offset)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+
+  if (private->paint_stack)
+    {
+      GdkWindowPaint *paint = private->paint_stack->data;
+      *x_offset = paint->x_offset;
+      *y_offset = paint->y_offset;
+    }
+  else
+    {
+      *x_offset = -private->abs_x;
+      *y_offset = -private->abs_y;
+    }
+}
+
+/**
+ * gdk_window_get_internal_paint_info:
+ * @window: a #GdkWindow
+ * @real_drawable: location to store the drawable to which drawing should be
+ *            done.
+ * @x_offset: location to store the X offset between coordinates in @window,
+ *            and the underlying window system primitive coordinates for
+ *            *@real_drawable.
+ * @y_offset: location to store the Y offset between coordinates in @window,
+ *            and the underlying window system primitive coordinates for
+ *            *@real_drawable.
+ *
+ * If you bypass the GDK layer and use windowing system primitives to
+ * draw directly onto a #GdkWindow, then you need to deal with two
+ * details: there may be an offset between GDK coordinates and windowing
+ * system coordinates, and GDK may have redirected drawing to a offscreen
+ * pixmap as the result of a gdk_window_begin_paint_region() calls.
+ * This function allows retrieving the information you need to compensate
+ * for these effects.
+ *
+ * This function exposes details of the GDK implementation, and is thus
+ * likely to change in future releases of GDK.
+ **/
+void
+gdk_window_get_internal_paint_info (GdkWindow    *window,
+                                   GdkDrawable **real_drawable,
+                                   gint         *x_offset,
+                                   gint         *y_offset)
+{
+  gint x_off, y_off;
+
+  GdkWindowObject *private;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *)window;
+
+  if (real_drawable)
+    {
+      if (private->paint_stack)
+       {
+         GdkWindowPaint *paint = private->paint_stack->data;
+         *real_drawable = paint->pixmap;
+       }
+      else
+       {
+         /* This means you're probably gonna be doing some weird shit
+            directly to the window, so we flush all outstanding stuff */
+         gdk_window_flush (window);
+         *real_drawable = window;
+       }
+    }
+
+  gdk_window_get_offsets (window, &x_off, &y_off);
+
+  if (x_offset)
+    *x_offset = x_off;
+  if (y_offset)
+    *y_offset = y_off;
+}
+
+static GdkDrawable *
+start_draw_helper (GdkDrawable *drawable,
+                  GdkGC *gc,
+                  gint *x_offset_out,
+                  gint *y_offset_out)
+{
+  GdkWindowObject *private = (GdkWindowObject *)drawable;
+  gint x_offset, y_offset;
+  GdkDrawable *impl;
+  gint old_clip_x = gc->clip_x_origin;
+  gint old_clip_y = gc->clip_y_origin;
+  GdkRegion *clip;
+  guint32 clip_region_tag;
+  GdkWindowPaint *paint;
+
+  paint = NULL;
+  if (private->paint_stack)
+    paint = private->paint_stack->data;
+
+  if (paint)
+    {
+      x_offset = paint->x_offset;
+      y_offset = paint->y_offset;
+    }
+  else
+    {
+      x_offset = -private->abs_x;
+      y_offset = -private->abs_y;
+    }
+
+  if (x_offset != 0 || y_offset != 0)
+    {
+      gdk_gc_set_clip_origin (gc,
+                             old_clip_x - x_offset,
+                             old_clip_y - y_offset);
+      gdk_gc_set_ts_origin (gc,
+                           gc->ts_x_origin - x_offset,
+                           gc->ts_y_origin - y_offset);
+    }
+
+  *x_offset_out = x_offset;
+  *y_offset_out = y_offset;
+
+  /* Add client side window clip region to gc */
+  clip = NULL;
+  if (paint)
+    {
+      /* Only need clipping if using implicit paint, otherwise
+        the pixmap is clipped when copying to the window in end_paint */
+      if (paint->uses_implicit)
+       {
+         /* This includes the window clip */
+         clip = paint->region;
+       }
+      clip_region_tag = paint->region_tag;
+
+      /* After having set up the drawable clip rect on a GC we need to make sure
+       * that we draw to th the impl, otherwise the pixmap code will reset the
+       * drawable clip. */
+      impl = ((GdkPixmapObject *)(paint->pixmap))->impl;
+    }
+  else
+    {
+      /* Drawing directly to the window, flush anything outstanding to
+        guarantee ordering. */
+      gdk_window_flush ((GdkWindow *)drawable);
+
+      /* Don't clip when drawing to root */
+      if (private->window_type != GDK_WINDOW_ROOT)
+       {
+         if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
+           clip = private->clip_region_with_children;
+         else
+           clip = private->clip_region;
+       }
+      clip_region_tag = private->clip_tag;
+      impl = private->impl;
+    }
+
+  if (clip)
+    _gdk_gc_add_drawable_clip (gc,
+                              clip_region_tag, clip,
+                              /* If there was a clip origin set appart from the
+                               * window offset, need to take that into
+                               * consideration */
+                              -old_clip_x, -old_clip_y);
+
+  return impl;
+}
+
+#define BEGIN_DRAW                                     \
+  {                                                    \
+    GdkDrawable *impl;                                 \
+    gint x_offset, y_offset;                           \
+    gint old_clip_x = gc->clip_x_origin;               \
+    gint old_clip_y = gc->clip_y_origin;               \
+    gint old_ts_x = gc->ts_x_origin;                   \
+    gint old_ts_y = gc->ts_y_origin;                   \
+    impl = start_draw_helper (drawable, gc,            \
+                             &x_offset, &y_offset);
+
+#define END_DRAW                                           \
+    if (x_offset != 0 || y_offset != 0)                            \
+     {                                                      \
+       gdk_gc_set_clip_origin (gc, old_clip_x, old_clip_y); \
+       gdk_gc_set_ts_origin (gc, old_ts_x, old_ts_y);       \
+     }                                                      \
+  }
+
+static GdkGC *
+gdk_window_create_gc (GdkDrawable     *drawable,
+                     GdkGCValues     *values,
+                     GdkGCValuesMask  mask)
+{
+  g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
+
+  if (GDK_WINDOW_DESTROYED (drawable))
+    return NULL;
+
+  return gdk_gc_new_with_values (((GdkWindowObject *) drawable)->impl,
+                                values, mask);
+}
+
+static void
+gdk_window_draw_rectangle (GdkDrawable *drawable,
+                          GdkGC       *gc,
+                          gboolean     filled,
+                          gint         x,
+                          gint         y,
+                          gint         width,
+                          gint         height)
+{
+  if (GDK_WINDOW_DESTROYED (drawable))
+    return;
+
+  BEGIN_DRAW;
+  gdk_draw_rectangle (impl, gc, filled,
+                     x - x_offset, y - y_offset, width, height);
+  END_DRAW;
+}
+
+static void
+gdk_window_draw_arc (GdkDrawable *drawable,
+                    GdkGC       *gc,
+                    gboolean     filled,
+                    gint         x,
+                    gint         y,
+                    gint         width,
+                    gint         height,
+                    gint         angle1,
+                    gint         angle2)
+{
+  if (GDK_WINDOW_DESTROYED (drawable))
+    return;
+
+  BEGIN_DRAW;
+  gdk_draw_arc (impl, gc, filled,
+               x - x_offset, y - y_offset,
+               width, height, angle1, angle2);
+  END_DRAW;
+}
+
+static void
+gdk_window_draw_polygon (GdkDrawable *drawable,
+                        GdkGC       *gc,
+                        gboolean     filled,
+                        GdkPoint    *points,
+                        gint         npoints)
+{
+  GdkPoint *new_points;
+
+  if (GDK_WINDOW_DESTROYED (drawable))
+    return;
+
+  BEGIN_DRAW;
+
+  if (x_offset != 0 || y_offset != 0)
+    {
+      int i;
+
+      new_points = g_new (GdkPoint, npoints);
+      for (i=0; i<npoints; i++)
+       {
+         new_points[i].x = points[i].x - x_offset;
+         new_points[i].y = points[i].y - y_offset;
+       }
+    }
+  else
+    new_points = points;
+
+  gdk_draw_polygon (impl, gc, filled, new_points, npoints);
+
+  if (new_points != points)
+    g_free (new_points);
+
+  END_DRAW;
+}
+
+static void
+gdk_window_draw_text (GdkDrawable *drawable,
+                     GdkFont     *font,
+                     GdkGC       *gc,
+                     gint         x,
+                     gint         y,
+                     const gchar *text,
+                     gint         text_length)
+{
+  if (GDK_WINDOW_DESTROYED (drawable))
+    return;
+
+  BEGIN_DRAW;
+  gdk_draw_text (impl, font, gc,
+                x - x_offset, y - y_offset, text, text_length);
+  END_DRAW;
+}
+
+static void
+gdk_window_draw_text_wc (GdkDrawable    *drawable,
+                        GdkFont        *font,
+                        GdkGC          *gc,
+                        gint            x,
+                        gint            y,
+                        const GdkWChar *text,
+                        gint            text_length)
+{
+  if (GDK_WINDOW_DESTROYED (drawable))
+    return;
+
+  BEGIN_DRAW;
+  gdk_draw_text_wc (impl, font, gc,
+                   x - x_offset, y - y_offset, text, text_length);
+  END_DRAW;
+}
+
+static GdkDrawable *
+gdk_window_get_source_drawable (GdkDrawable *drawable)
+{
+  GdkWindow *window = GDK_WINDOW (drawable);
+  GdkWindowObject *private;
+
+  private = (GdkWindowObject *) window;
+  if (GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable)
+    return GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable (private->impl);
+
+  return drawable;
+}
+
+static GdkDrawable *
+gdk_window_get_composite_drawable (GdkDrawable *drawable,
+                                  gint         x,
+                                  gint         y,
+                                  gint         width,
+                                  gint         height,
+                                  gint        *composite_x_offset,
+                                  gint        *composite_y_offset)
+{
+  GdkWindowObject *private = (GdkWindowObject *)drawable;
+  GSList *list;
+  GdkPixmap *tmp_pixmap;
+  GdkRectangle rect;
+  GdkGC *tmp_gc;
+  gboolean overlap_buffer;
+  GdkDrawable *source;
+  GdkWindowObject *impl_window;
+  GdkWindowPaint *implicit_paint;
+
+  *composite_x_offset = -private->abs_x;
+  *composite_y_offset = -private->abs_y;
+
+  if ((GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable)))
+    return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
+
+  /* See if any buffered part is overlapping the part we want
+   * to get
+   */
+  rect.x = x;
+  rect.y = y;
+  rect.width = width;
+  rect.height = height;
+
+  overlap_buffer = FALSE;
+
+  for (list = private->paint_stack; list != NULL; list = list->next)
+    {
+      GdkWindowPaint *paint = list->data;
+      GdkOverlapType overlap;
+
+      overlap = gdk_region_rect_in (paint->region, &rect);
+
+      if (overlap == GDK_OVERLAP_RECTANGLE_IN)
+       {
+         *composite_x_offset = paint->x_offset;
+         *composite_y_offset = paint->y_offset;
+
+         return g_object_ref (paint->pixmap);
+       }
+      else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
+       {
+         overlap_buffer = TRUE;
+         break;
+       }
+    }
+
+  impl_window = gdk_window_get_impl_window (private);
+  implicit_paint = impl_window->implicit_paint;
+  if (implicit_paint)
+    {
+      GdkOverlapType overlap;
+
+      rect.x += private->abs_x;
+      rect.y += private->abs_y;
+
+      overlap = gdk_region_rect_in (implicit_paint->region, &rect);
+      if (overlap == GDK_OVERLAP_RECTANGLE_IN)
+       {
+         *composite_x_offset = -private->abs_x + implicit_paint->x_offset;
+         *composite_y_offset = -private->abs_y + implicit_paint->y_offset;
+
+         return g_object_ref (implicit_paint->pixmap);
+       }
+      else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
+       overlap_buffer = TRUE;
+    }
+
+  if (!overlap_buffer)
+    return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
+
+  tmp_pixmap = gdk_pixmap_new (drawable, width, height, -1);
+  tmp_gc = _gdk_drawable_get_scratch_gc (tmp_pixmap, FALSE);
+
+  source = _gdk_drawable_get_source_drawable (drawable);
+
+  /* Copy the current window contents */
+  gdk_draw_drawable (tmp_pixmap,
+                    tmp_gc,
+                    GDK_WINDOW_OBJECT (source)->impl,
+                    x - *composite_x_offset,
+                    y - *composite_y_offset,
+                    0, 0,
+                    width, height);
+
+  /* paint the backing stores */
+  if (implicit_paint)
+    {
+      GdkWindowPaint *paint = list->data;
+
+      gdk_gc_set_clip_region (tmp_gc, paint->region);
+      gdk_gc_set_clip_origin (tmp_gc, -x  - paint->x_offset, -y  - paint->y_offset);
+
+      gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
+                        x - paint->x_offset,
+                        y - paint->y_offset,
+                        0, 0, width, height);
+    }
+
+  for (list = private->paint_stack; list != NULL; list = list->next)
+    {
+      GdkWindowPaint *paint = list->data;
+
+      if (paint->uses_implicit)
+       continue; /* We already copied this above */
+
+      gdk_gc_set_clip_region (tmp_gc, paint->region);
+      gdk_gc_set_clip_origin (tmp_gc, -x, -y);
+
+      gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
+                        x - paint->x_offset,
+                        y - paint->y_offset,
+                        0, 0, width, height);
+    }
+
+  /* Reset clip region of the cached GdkGC */
+  gdk_gc_set_clip_region (tmp_gc, NULL);
+
+  /* Set these to location of tmp_pixmap within the window */
+  *composite_x_offset = x;
+  *composite_y_offset = y;
+
+  return tmp_pixmap;
+}
+
+static GdkRegion*
+gdk_window_get_clip_region (GdkDrawable *drawable)
+{
+  GdkWindowObject *private = (GdkWindowObject *)drawable;
+  GdkRegion *result;
+
+  result = gdk_region_copy (private->clip_region);
+
+  if (private->paint_stack)
+    {
+      GdkRegion *paint_region = gdk_region_new ();
+      GSList *tmp_list = private->paint_stack;
+
+      while (tmp_list)
+       {
+         GdkWindowPaint *paint = tmp_list->data;
+
+         gdk_region_union (paint_region, paint->region);
+
+         tmp_list = tmp_list->next;
+       }
+
+      gdk_region_intersect (result, paint_region);
+      gdk_region_destroy (paint_region);
+    }
+
+  return result;
+}
+
+static GdkRegion*
+gdk_window_get_visible_region (GdkDrawable *drawable)
+{
+  GdkWindowObject *private = (GdkWindowObject*) drawable;
+
+  return gdk_region_copy (private->clip_region);
+}
+
+static void
+gdk_window_draw_drawable (GdkDrawable *drawable,
+                         GdkGC       *gc,
+                         GdkPixmap   *src,
+                         GdkDrawable *original_src,
+                         gint         xsrc,
+                         gint         ysrc,
+                         gint         xdest,
+                         gint         ydest,
+                         gint         width,
+                         gint         height)
+{
+  GdkWindowObject *private = (GdkWindowObject *)drawable;
+
+  if (GDK_WINDOW_DESTROYED (drawable))
+    return;
+
+  BEGIN_DRAW;
+
+  gdk_draw_drawable (impl, gc, src, xsrc, ysrc,
+                    xdest - x_offset, ydest - y_offset, width, height);
+
+  if (!private->paint_stack)
+    {
+      /* We might have drawn from an obscured part of a client
+        side window, if so we need to send graphics exposures */
+      if (_gdk_gc_get_exposures (gc) &&
+         GDK_IS_WINDOW (original_src))
+       {
+         GdkRegion *exposure_region;
+         GdkRegion *clip;
+         GdkRectangle r;
+
+         r.x = xdest;
+         r.y = ydest;
+         r.width = width;
+         r.height = height;
+         exposure_region = gdk_region_rectangle (&r);
+
+         if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
+           clip = private->clip_region_with_children;
+         else
+           clip = private->clip_region;
+         gdk_region_intersect (exposure_region, clip);
+
+         clip = _gdk_gc_get_clip_region (gc);
+         if (clip)
+           {
+             gdk_region_offset (exposure_region,
+                                old_clip_x,
+                                old_clip_y);
+             gdk_region_intersect (exposure_region, clip);
+             gdk_region_offset (exposure_region,
+                                -old_clip_x,
+                                -old_clip_y);
+           }
+
+         /* Note: We don't clip by the clip mask if set, so this
+            may invalidate to much */
+
+         /* Remove the area that is correctly copied from the src.
+          * Note that xsrc/ysrc has been corrected for abs_x/y offsets already,
+          * which need to be undone */
+         clip = gdk_drawable_get_visible_region (original_src);
+         gdk_region_offset (clip,
+                            xdest - (xsrc - GDK_WINDOW_OBJECT (original_src)->abs_x),
+                            ydest - (ysrc - GDK_WINDOW_OBJECT (original_src)->abs_y));
+         gdk_region_subtract (exposure_region, clip);
+         gdk_region_destroy (clip);
+
+         gdk_window_invalidate_region (GDK_WINDOW (private),
+                                       exposure_region,
+                                       _gdk_gc_get_subwindow (gc) == GDK_INCLUDE_INFERIORS);
+
+         gdk_region_destroy (exposure_region);
+       }
+    }
+
+  END_DRAW;
+}
+
+static void
+gdk_window_draw_points (GdkDrawable *drawable,
+                       GdkGC       *gc,
+                       GdkPoint    *points,
+                       gint         npoints)
+{
+  GdkPoint *new_points;
+
+  if (GDK_WINDOW_DESTROYED (drawable))
+    return;
+
+  BEGIN_DRAW;
+
+  if (x_offset != 0 || y_offset != 0)
+    {
+      gint i;
+
+      new_points = g_new (GdkPoint, npoints);
+      for (i=0; i<npoints; i++)
+       {
+         new_points[i].x = points[i].x - x_offset;
+         new_points[i].y = points[i].y - y_offset;
+       }
+    }
+  else
+    new_points = points;
+
+  gdk_draw_points (impl, gc, new_points, npoints);
+
+  if (new_points != points)
+    g_free (new_points);
+
+  END_DRAW;
+}
+
+static void
+gdk_window_draw_segments (GdkDrawable *drawable,
+                         GdkGC       *gc,
+                         GdkSegment  *segs,
+                         gint         nsegs)
+{
+  GdkSegment *new_segs;
+
+  if (GDK_WINDOW_DESTROYED (drawable))
+    return;
+
+  BEGIN_DRAW;
+
+  if (x_offset != 0 || y_offset != 0)
+    {
+      gint i;
+
+      new_segs = g_new (GdkSegment, nsegs);
+      for (i=0; i<nsegs; i++)
+       {
+         new_segs[i].x1 = segs[i].x1 - x_offset;
+         new_segs[i].y1 = segs[i].y1 - y_offset;
+         new_segs[i].x2 = segs[i].x2 - x_offset;
+         new_segs[i].y2 = segs[i].y2 - y_offset;
+       }
+    }
+  else
+    new_segs = segs;
+
+  gdk_draw_segments (impl, gc, new_segs, nsegs);
+
+  if (new_segs != segs)
+    g_free (new_segs);
+
+  END_DRAW;
+}
+
+static void
+gdk_window_draw_lines (GdkDrawable *drawable,
+                      GdkGC       *gc,
+                      GdkPoint    *points,
+                      gint         npoints)
+{
+  GdkPoint *new_points;
+
+  if (GDK_WINDOW_DESTROYED (drawable))
+    return;
+
+  BEGIN_DRAW;
+
+  if (x_offset != 0 || y_offset != 0)
+    {
+      gint i;
+
+      new_points = g_new (GdkPoint, npoints);
+      for (i=0; i<npoints; i++)
+       {
+         new_points[i].x = points[i].x - x_offset;
+         new_points[i].y = points[i].y - y_offset;
+       }
+    }
+  else
+    new_points = points;
+
+  gdk_draw_lines (impl, gc, new_points, npoints);
+
+  if (new_points != points)
+    g_free (new_points);
+
+  END_DRAW;
+}
+
+static void
+gdk_window_draw_glyphs (GdkDrawable      *drawable,
+                       GdkGC            *gc,
+                       PangoFont        *font,
+                       gint              x,
+                       gint              y,
+                       PangoGlyphString *glyphs)
+{
+  if (GDK_WINDOW_DESTROYED (drawable))
+    return;
+
+  BEGIN_DRAW;
+  gdk_draw_glyphs (impl, gc, font,
+                  x - x_offset, y - y_offset, glyphs);
+  END_DRAW;
+}
+
+static void
+gdk_window_draw_glyphs_transformed (GdkDrawable      *drawable,
+                                   GdkGC            *gc,
+                                   PangoMatrix      *matrix,
+                                   PangoFont        *font,
+                                   gint              x,
+                                   gint              y,
+                                   PangoGlyphString *glyphs)
+{
+  PangoMatrix tmp_matrix;
+
+  if (GDK_WINDOW_DESTROYED (drawable))
+    return;
+
+  BEGIN_DRAW;
+
+  if (x_offset != 0 || y_offset != 0)
+    {
+      if (matrix)
+       {
+         tmp_matrix = *matrix;
+         tmp_matrix.x0 -= x_offset;
+         tmp_matrix.y0 -= y_offset;
+         matrix = &tmp_matrix;
+       }
+      else if (GDK_PANGO_UNITS_OVERFLOWS (x_offset, y_offset))
+       {
+         PangoMatrix identity = PANGO_MATRIX_INIT;
+
+         tmp_matrix = identity;
+         tmp_matrix.x0 -= x_offset;
+         tmp_matrix.y0 -= y_offset;
+         matrix = &tmp_matrix;
+       }
+      else
+       {
+         x -= x_offset * PANGO_SCALE;
+         y -= y_offset * PANGO_SCALE;
+       }
+    }
+
+  gdk_draw_glyphs_transformed (impl, gc, matrix, font, x, y, glyphs);
+
+  END_DRAW;
+}
+
+typedef struct {
+  cairo_t *cr; /* if non-null, it means use this cairo context */
+  GdkGC *gc;   /* if non-null, it means use this GC instead */
+} BackingRectMethod;
+
+static void
+setup_backing_rect_method (BackingRectMethod *method, GdkWindow *window, GdkWindowPaint *paint, int x_offset_cairo, int y_offset_cairo)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+
+  if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
+    {
+      GdkWindowPaint tmp_paint;
+
+      tmp_paint = *paint;
+      tmp_paint.x_offset += private->x;
+      tmp_paint.y_offset += private->y;
+
+      x_offset_cairo += private->x;
+      y_offset_cairo += private->y;
+
+      setup_backing_rect_method (method, GDK_WINDOW (private->parent), &tmp_paint, x_offset_cairo, y_offset_cairo);
+    }
+  else if (private->bg_pixmap &&
+          private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+          private->bg_pixmap != GDK_NO_BG)
+    {
+/* This is a workaround for https://bugs.freedesktop.org/show_bug.cgi?id=4320.
+ * In it, using a pixmap as a repeating pattern in Cairo, and painting it to a
+ * pixmap destination surface, can be very slow (on the order of seconds for a
+ * whole-screen copy).  The workaround is to use pretty much the same code that
+ * we used in GTK+ 2.6 (pre-Cairo), which clears the double-buffer pixmap with
+ * a tiled GC XFillRectangle().
+ */
+
+/* Actually computing this flag is left as an exercise for the reader */
+#if defined (G_OS_UNIX)
+#  define GDK_CAIRO_REPEAT_IS_FAST 0
+#else
+#  define GDK_CAIRO_REPEAT_IS_FAST 1
+#endif
+
+#if GDK_CAIRO_REPEAT_IS_FAST
+      cairo_surface_t *surface = _gdk_drawable_ref_cairo_surface (private->bg_pixmap);
+      cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
+      cairo_surface_destroy (surface);
+
+      if (x_offset_cairo != 0 || y_offset_cairo != 0)
+       {
+         cairo_matrix_t matrix;
+         cairo_matrix_init_translate (&matrix, x_offset_cairo, y_offset_cairo);
+         cairo_pattern_set_matrix (pattern, &matrix);
+       }
+
+      cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
+
+      method->cr = cairo_create (paint->surface);
+      method->gc = NULL;
+
+      cairo_set_source (method->cr, pattern);
+      cairo_pattern_destroy (pattern);
+#else
+      guint gc_mask;
+      GdkGCValues gc_values;
+
+      gc_values.fill = GDK_TILED;
+      gc_values.tile = private->bg_pixmap;
+      gc_values.ts_x_origin = -x_offset_cairo;
+      gc_values.ts_y_origin = -y_offset_cairo;
+
+      gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN;
+
+      method->gc = gdk_gc_new_with_values (paint->pixmap, &gc_values, gc_mask);
+#endif
+    }
+  else
+    {
+      method->cr = cairo_create (paint->surface);
+
+      gdk_cairo_set_source_color (method->cr, &private->bg_color);
+    }
+}
+
+static void
+gdk_window_clear_backing_region (GdkWindow *window,
+                                GdkRegion *region)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowPaint *paint = private->paint_stack->data;
+  BackingRectMethod method;
+  GdkRegion *clip;
+  GdkRectangle clipbox;
+#if 0
+  GTimer *timer;
+  double elapsed;
+#endif
+
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
+#if 0
+  timer = g_timer_new ();
+#endif
+
+  method.cr = NULL;
+  method.gc = NULL;
+  setup_backing_rect_method (&method, window, paint, 0, 0);
+
+  clip = gdk_region_copy (paint->region);
+  gdk_region_intersect (clip, region);
+  gdk_region_get_clipbox (clip, &clipbox);
+
+
+  if (method.cr)
+    {
+      g_assert (method.gc == NULL);
+
+      gdk_cairo_region (method.cr, clip);
+      cairo_fill (method.cr);
+
+      cairo_destroy (method.cr);
+#if 0
+      elapsed = g_timer_elapsed (timer, NULL);
+      g_print ("Draw the background with Cairo: %fs\n", elapsed);
+#endif
+    }
+  else
+    {
+      g_assert (method.gc != NULL);
+
+      gdk_gc_set_clip_region (method.gc, clip);
+      gdk_draw_rectangle (window, method.gc, TRUE,
+                         clipbox.x, clipbox.y,
+                         clipbox.width, clipbox.height);
+      g_object_unref (method.gc);
+
+#if 0
+      elapsed = g_timer_elapsed (timer, NULL);
+      g_print ("Draw the background with GDK: %fs\n", elapsed);
+#endif
+    }
+
+  gdk_region_destroy (clip);
+
+#if 0
+  g_timer_destroy (timer);
+#endif
+}
+
+static void
+gdk_window_clear_backing_region_redirect (GdkWindow *window,
+                                         GdkRegion *region)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowRedirect *redirect = private->redirect;
+  GdkRegion *clip_region;
+  GdkRectangle clipbox;
+  gint x_offset, y_offset;
+  BackingRectMethod method;
+  GdkWindowPaint paint;
+
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
+  clip_region = _gdk_window_calculate_full_clip_region (window,
+                                                       GDK_WINDOW (redirect->redirected),
+                                                       TRUE,
+                                                       &x_offset, &y_offset);
+  gdk_region_intersect (clip_region, region);
+
+  /* offset is from redirected window origin to window origin, convert to
+     the offset from the redirected pixmap origin to the window origin */
+  x_offset += redirect->dest_x - redirect->src_x;
+  y_offset += redirect->dest_y - redirect->src_y;
+
+  /* Convert region to pixmap coords */
+  gdk_region_offset (clip_region, x_offset, y_offset);
+
+  paint.x_offset = 0;
+  paint.y_offset = 0;
+  paint.pixmap = redirect->pixmap;
+  paint.surface = _gdk_drawable_ref_cairo_surface (redirect->pixmap);
+
+  method.cr = NULL;
+  method.gc = NULL;
+  setup_backing_rect_method (&method, window, &paint, -x_offset, -y_offset);
+
+  if (method.cr)
+    {
+      g_assert (method.gc == NULL);
+
+      gdk_cairo_region (method.cr, clip_region);
+      cairo_fill (method.cr);
+
+      cairo_destroy (method.cr);
+    }
+  else
+    {
+      g_assert (method.gc != NULL);
+
+      gdk_region_get_clipbox (clip_region, &clipbox);
+      gdk_gc_set_clip_region (method.gc, clip_region);
+      gdk_draw_rectangle (redirect->pixmap, method.gc, TRUE,
+                         clipbox.x, clipbox.y,
+                         clipbox.width, clipbox.height);
+      g_object_unref (method.gc);
+
+    }
+
+  gdk_region_destroy (clip_region);
+  cairo_surface_destroy (paint.surface);
+}
+
+static void
+gdk_window_clear_backing_region_direct (GdkWindow *window,
+                                       GdkRegion *region)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  BackingRectMethod method;
+  GdkWindowPaint paint;
+  GdkRegion *clip;
+  GdkRectangle clipbox;
+
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
+  paint.x_offset = 0;
+  paint.y_offset = 0;
+  paint.pixmap = window;
+  paint.surface = _gdk_drawable_ref_cairo_surface (window);
+
+  method.cr = NULL;
+  method.gc = NULL;
+  setup_backing_rect_method (&method, window, &paint, 0, 0);
+
+  clip = gdk_region_copy (private->clip_region_with_children);
+  gdk_region_intersect (clip, region);
+  gdk_region_get_clipbox (clip, &clipbox);
+
+  if (method.cr)
+    {
+      g_assert (method.gc == NULL);
+
+      gdk_cairo_region (method.cr, clip);
+      cairo_fill (method.cr);
+
+      cairo_destroy (method.cr);
+    }
+  else
+    {
+      g_assert (method.gc != NULL);
+
+      gdk_gc_set_clip_region (method.gc, clip);
+      gdk_draw_rectangle (window, method.gc, TRUE,
+                         clipbox.x, clipbox.y,
+                         clipbox.width, clipbox.height);
+      g_object_unref (method.gc);
+
+    }
+
+  gdk_region_destroy (clip);
+  cairo_surface_destroy (paint.surface);
+}
+
+
+/**
+ * gdk_window_clear:
+ * @window: a #GdkWindow
+ *
+ * Clears an entire @window to the background color or background pixmap.
+ **/
+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,
+                                 GdkRegion *region,
+                                 gboolean   send_expose)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+
+  if (private->paint_stack)
+    gdk_window_clear_backing_region (window, region);
+  else
+    {
+      if (private->redirect)
+       gdk_window_clear_backing_region_redirect (window, region);
+
+      gdk_window_clear_backing_region_direct (window, region);
+      if (send_expose)
+       gdk_window_invalidate_region (window, region, FALSE);
+    }
+}
+
+static void
+gdk_window_clear_area_internal (GdkWindow *window,
+                               gint       x,
+                               gint       y,
+                               gint       width,
+                               gint       height,
+                               gboolean   send_expose)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkRectangle rect;
+  GdkRegion *region;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  /* This is what XClearArea does, and e.g. GtkCList uses it,
+     so we need to duplicate that */
+  if (width == 0)
+    width = private->width - x;
+  if (height == 0)
+    height = private->height - y;
+
+  rect.x = x;
+  rect.y = y;
+  rect.width = width;
+  rect.height = height;
+
+  region = gdk_region_rectangle (&rect);
+  gdk_window_clear_region_internal (window,
+                                   region,
+                                   FALSE);
+  gdk_region_destroy (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 color or background pixmap.
+ *
+ **/
+void
+gdk_window_clear_area (GdkWindow *window,
+                      gint       x,
+                      gint       y,
+                      gint       width,
+                      gint       height)
+{
+  gdk_window_clear_area_internal (window,
+                                 x, y,
+                                 width, height,
+                                 FALSE);
+}
+
+/**
+ * gdk_window_clear_area_e:
+ * @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
+ *
+ * Like gdk_window_clear_area(), but also generates an expose event for
+ * the cleared area.
+ *
+ * This function has a stupid name because it dates back to the mists
+ * time, pre-GDK-1.0.
+ *
+ **/
+void
+gdk_window_clear_area_e (GdkWindow *window,
+                        gint       x,
+                        gint       y,
+                        gint       width,
+                        gint       height)
+{
+  gdk_window_clear_area_internal (window,
+                                 x, y,
+                                 width, height,
+                                 TRUE);
+}
+
+static void
+gdk_window_draw_image (GdkDrawable *drawable,
+                      GdkGC       *gc,
+                      GdkImage    *image,
+                      gint         xsrc,
+                      gint         ysrc,
+                      gint         xdest,
+                      gint         ydest,
+                      gint         width,
+                      gint         height)
+{
+  if (GDK_WINDOW_DESTROYED (drawable))
+    return;
+
+  BEGIN_DRAW;
+  gdk_draw_image (impl, gc, image, xsrc, ysrc,
+                 xdest - x_offset, ydest - y_offset,
+                 width, height);
+  END_DRAW;
+}
+
+static void
+gdk_window_draw_pixbuf (GdkDrawable     *drawable,
+                       GdkGC           *gc,
+                       GdkPixbuf       *pixbuf,
+                       gint             src_x,
+                       gint             src_y,
+                       gint             dest_x,
+                       gint             dest_y,
+                       gint             width,
+                       gint             height,
+                       GdkRgbDither     dither,
+                       gint             x_dither,
+                       gint             y_dither)
+{
+  GdkWindowObject *private = (GdkWindowObject *)drawable;
+
+  if (GDK_WINDOW_DESTROYED (drawable))
+    return;
+
+  /* If no gc => no user clipping, but we need clipping
+     for window emulation, so use a scratch gc */
+  if (!gc)
+    gc = _gdk_drawable_get_scratch_gc (drawable, FALSE);
+
+  BEGIN_DRAW;
+  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);
+  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);
+  END_DRAW;
+}
+
+static void
+gdk_window_draw_trapezoids (GdkDrawable   *drawable,
+                           GdkGC         *gc,
+                           GdkTrapezoid  *trapezoids,
+                           gint           n_trapezoids)
+{
+  GdkTrapezoid *new_trapezoids = NULL;
+
+  if (GDK_WINDOW_DESTROYED (drawable))
+    return;
+
+  BEGIN_DRAW;
+
+  if (x_offset != 0 || y_offset != 0)
+    {
+      gint i;
+
+      new_trapezoids = g_new (GdkTrapezoid, n_trapezoids);
+      for (i=0; i < n_trapezoids; i++)
+       {
+         new_trapezoids[i].y1 = trapezoids[i].y1 - y_offset;
+         new_trapezoids[i].x11 = trapezoids[i].x11 - x_offset;
+         new_trapezoids[i].x21 = trapezoids[i].x21 - x_offset;
+         new_trapezoids[i].y2 = trapezoids[i].y2 - y_offset;
+         new_trapezoids[i].x12 = trapezoids[i].x12 - x_offset;
+         new_trapezoids[i].x22 = trapezoids[i].x22 - x_offset;
+       }
+
+      trapezoids = new_trapezoids;
+    }
+
+  gdk_draw_trapezoids (impl, gc, trapezoids, n_trapezoids);
+
+  g_free (new_trapezoids);
+
+  END_DRAW;
+}
+
+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 GdkVisual*
+gdk_window_real_get_visual (GdkDrawable *drawable)
+{
+  GdkColormap *colormap;
+
+  g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
+
+  colormap = gdk_drawable_get_colormap (drawable);
+  return colormap ? gdk_colormap_get_visual (colormap) : NULL;
+}
+
+static gint
+gdk_window_real_get_depth (GdkDrawable *drawable)
+{
+  g_return_val_if_fail (GDK_IS_WINDOW (drawable), 0);
+
+  return ((GdkWindowObject *)GDK_WINDOW (drawable))->depth;
+}
+
+static GdkScreen*
+gdk_window_real_get_screen (GdkDrawable *drawable)
+{
+  return gdk_drawable_get_screen (GDK_WINDOW_OBJECT (drawable)->impl);
+}
+
+static void
+gdk_window_real_set_colormap (GdkDrawable *drawable,
+                             GdkColormap *cmap)
+{
+  GdkWindowObject *private;
+
+  g_return_if_fail (GDK_IS_WINDOW (drawable));
+
+  if (GDK_WINDOW_DESTROYED (drawable))
+    return;
+
+  private = (GdkWindowObject *)drawable;
+
+  /* different colormap than parent, requires native window */
+  if (!private->input_only &&
+      cmap != gdk_drawable_get_colormap ((GdkDrawable *)(private->parent)))
+    gdk_window_ensure_native ((GdkWindow *)drawable);
+
+  gdk_drawable_set_colormap (private->impl, cmap);
+}
+
+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 GdkImage*
+gdk_window_copy_to_image (GdkDrawable     *drawable,
+                         GdkImage        *image,
+                         gint             src_x,
+                         gint             src_y,
+                         gint             dest_x,
+                         gint             dest_y,
+                         gint             width,
+                         gint             height)
+{
+  GdkWindowObject *private = (GdkWindowObject *) drawable;
+  gint x_offset, y_offset;
+
+  g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
+
+  if (GDK_WINDOW_DESTROYED (drawable))
+    return NULL;
+
+  /* If we're here, a composite image was not necessary, so
+   * we can ignore the paint stack.
+   */
+
+  /* TODO: Is this right? */
+  x_offset = 0;
+  y_offset = 0;
+
+  return gdk_drawable_copy_to_image (private->impl,
+                                    image,
+                                    src_x - x_offset,
+                                    src_y - y_offset,
+                                    dest_x, dest_y,
+                                    width, height);
+}
+
+static void
+gdk_window_cairo_surface_destroy (void *data)
+{
+  GdkWindowObject *private = (GdkWindowObject*) data;
+
+  private->cairo_surface = NULL;
+}
+
+static cairo_surface_t *
+gdk_window_create_cairo_surface (GdkDrawable *drawable,
+                                int width,
+                                int height)
+{
+  return _gdk_windowing_create_cairo_surface (GDK_WINDOW_OBJECT(drawable)->impl,
+                                             width, height);
+}
+
+
+static cairo_surface_t *
+gdk_window_ref_cairo_surface (GdkDrawable *drawable)
+{
+  GdkWindowObject *private = (GdkWindowObject*) drawable;
+  cairo_surface_t *surface;
+
   if (private->paint_stack)
     {
-      GdkWindowPaint *paint = private->paint_stack->data;
-      gdk_draw_text_wc (paint->pixmap, font, gc, 
-                       x - x_offset, y - y_offset, text, text_length);
+      GdkWindowPaint *paint = private->paint_stack->data;
+
+      surface = paint->surface;
+      cairo_surface_reference (surface);
+    }
+  else
+    {
+
+      /* This will be drawing directly to the window, so flush implicit paint */
+      gdk_window_flush ((GdkWindow *)drawable);
+
+      if (!private->cairo_surface)
+       {
+         int width, height;
+         GdkDrawable *source;
+
+         /* It would be nice if we had some cairo support here so we
+            could set the clip rect on the cairo surface */
+         width = private->abs_x + private->width;
+         height = private->abs_y + private->height;
+
+         source = _gdk_drawable_get_source_drawable (drawable);
+
+         /* TODO: Avoid the typecheck crap by adding virtual call */
+         private->cairo_surface = _gdk_drawable_create_cairo_surface (source, width, height);
+
+         if (private->cairo_surface)
+           {
+             cairo_surface_set_device_offset (private->cairo_surface,
+                                              private->abs_x,
+                                              private->abs_y);
+
+             cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
+                                          drawable, gdk_window_cairo_surface_destroy);
+           }
+       }
+      else
+       cairo_surface_reference (private->cairo_surface);
+
+      surface = private->cairo_surface;
+    }
+
+  return surface;
+}
+
+static void
+gdk_window_set_cairo_clip (GdkDrawable *drawable,
+                          cairo_t *cr)
+{
+  GdkWindowObject *private = (GdkWindowObject*) drawable;
+
+  if (!private->paint_stack)
+    {
+      cairo_save (cr);
+      cairo_identity_matrix (cr);
+
+      cairo_reset_clip (cr);
+
+      cairo_new_path (cr);
+      gdk_cairo_region (cr, private->clip_region);
+
+      cairo_restore (cr);
+      cairo_clip (cr);
+    }
+  else
+    {
+      GdkWindowPaint *paint = private->paint_stack->data;
+
+      /* Only needs to clip to region if piggybacking
+        on an implicit paint pixmap */
+      if (paint->uses_implicit)
+       {
+         cairo_save (cr);
+         cairo_identity_matrix (cr);
+
+         cairo_reset_clip (cr);
+
+         cairo_new_path (cr);
+         gdk_cairo_region (cr, paint->region);
+         cairo_restore (cr);
+
+         cairo_clip (cr);
+       }
+    }
+}
+
+/* Code for dirty-region queueing
+ */
+static GSList *update_windows = NULL;
+static guint update_idle = 0;
+static gboolean debug_updates = FALSE;
+
+static inline gboolean
+gdk_window_is_ancestor (GdkWindow *window,
+                       GdkWindow *ancestor)
+{
+  while (window)
+    {
+      GdkWindow *parent = (GdkWindow*) ((GdkWindowObject*) window)->parent;
+
+      if (parent == ancestor)
+       return TRUE;
+
+      window = parent;
+    }
+
+  return FALSE;
+}
+
+static void
+gdk_window_add_update_window (GdkWindow *window)
+{
+  GSList *tmp;
+  GSList *prev = NULL;
+  gboolean has_ancestor_in_list = FALSE;
+
+  for (tmp = update_windows; tmp; tmp = tmp->next)
+    {
+      GdkWindowObject *parent = GDK_WINDOW_OBJECT (window)->parent;
+
+      /*  check if tmp is an ancestor of "window"; if it is, set a
+       *  flag indicating that all following windows are either
+       *  children of "window" or from a differen hierarchy
+       */
+      if (!has_ancestor_in_list && gdk_window_is_ancestor (window, tmp->data))
+       has_ancestor_in_list = TRUE;
+
+      /* insert in reverse stacking order when adding around siblings,
+       * so processing updates properly paints over lower stacked windows
+       */
+      if (parent == GDK_WINDOW_OBJECT (tmp->data)->parent)
+       {
+         gint index = g_list_index (parent->children, window);
+         for (; tmp && parent == GDK_WINDOW_OBJECT (tmp->data)->parent; tmp = tmp->next)
+           {
+             gint sibling_index = g_list_index (parent->children, tmp->data);
+             if (index > sibling_index)
+               break;
+             prev = tmp;
+           }
+         /* here, tmp got advanced past all lower stacked siblings */
+         tmp = g_slist_prepend (tmp, window);
+         if (prev)
+           prev->next = tmp;
+         else
+           update_windows = tmp;
+         return;
+       }
+
+      /*  if "window" has an ancestor in the list and tmp is one of
+       *  "window's" children, insert "window" before tmp
+       */
+      if (has_ancestor_in_list && gdk_window_is_ancestor (tmp->data, window))
+       {
+         tmp = g_slist_prepend (tmp, window);
+
+         if (prev)
+           prev->next = tmp;
+         else
+           update_windows = tmp;
+         return;
+       }
+
+      /*  if we're at the end of the list and had an ancestor it it,
+       *  append to the list
+       */
+      if (! tmp->next && has_ancestor_in_list)
+       {
+         tmp = g_slist_append (tmp, window);
+         return;
+       }
+
+      prev = tmp;
+    }
+
+  /*  if all above checks failed ("window" is from a different
+   *  hierarchy than what is already in the list) or the list is
+   *  empty, prepend
+   */
+  update_windows = g_slist_prepend (update_windows, window);
+}
+
+static void
+gdk_window_remove_update_window (GdkWindow *window)
+{
+  update_windows = g_slist_remove (update_windows, window);
+}
+
+static gboolean
+gdk_window_update_idle (gpointer data)
+{
+  gdk_window_process_all_updates ();
+
+  return FALSE;
+}
+
+static gboolean
+gdk_window_is_toplevel_frozen (GdkWindow *window)
+{
+  GdkWindowObject *toplevel;
+
+  toplevel = (GdkWindowObject *)gdk_window_get_toplevel (window);
+
+  return toplevel->update_and_descendants_freeze_count > 0;
+}
+
+static void
+gdk_window_schedule_update (GdkWindow *window)
+{
+  if (window &&
+      (GDK_WINDOW_OBJECT (window)->update_freeze_count ||
+       gdk_window_is_toplevel_frozen (window)))
+    return;
+
+  if (!update_idle)
+    {
+      update_idle = gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
+                                    gdk_window_update_idle, NULL, NULL);
+    }
+}
+
+void
+_gdk_window_process_updates_recurse (GdkWindow *window,
+                                    GdkRegion *expose_region)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *child;
+  GdkRegion *child_region;
+  GdkRectangle r;
+  GList *l;
+
+  if (gdk_region_empty (expose_region))
+    return;
+
+  /* Iterate over children, starting at topmost */
+  for (l = private->children; l != NULL; l = l->next)
+    {
+      child = l->data;
+
+      if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
+       continue;
+
+      /* Ignore offscreen children, as they don't draw in their parent and
+       * don't take part in the clipping */
+      if (gdk_window_is_offscreen (child))
+       continue;
+
+      r.x = child->x;
+      r.y = child->y;
+      r.width = child->width;
+      r.height = child->height;
+
+      child_region = gdk_region_rectangle (&r);
+      if (child->shape)
+       gdk_region_intersect (child_region, child->shape);
+
+      if (child->impl == private->impl)
+       {
+         /* Client side child, expose */
+         gdk_region_intersect (child_region, expose_region);
+         gdk_region_subtract (expose_region, child_region);
+         gdk_region_offset (child_region, -child->x, -child->y);
+         _gdk_window_process_updates_recurse ((GdkWindow *)child, child_region);
+       }
+      else
+       {
+         /* Native child, just remove area from expose region */
+         gdk_region_subtract (expose_region, child_region);
+       }
+      gdk_region_destroy (child_region);
+    }
+
+  if (!gdk_region_empty (expose_region))
+    {
+      if (private->event_mask & GDK_EXPOSURE_MASK)
+       {
+         GdkEvent event;
+
+         event.expose.type = GDK_EXPOSE;
+         event.expose.window = g_object_ref (window);
+         event.expose.send_event = FALSE;
+         event.expose.count = 0;
+         event.expose.region = expose_region;
+         gdk_region_get_clipbox (expose_region, &event.expose.area);
+
+         (*_gdk_event_func) (&event, _gdk_event_data);
+
+         g_object_unref (window);
+       }
+      else if (private->bg_pixmap != GDK_NO_BG)
+       {
+         /* No exposure mask set, so nothing will be drawn, the
+          * app relies on the background being what it specified
+          * for the window. So, we need to clear this manually.
+          *
+          * We use begin/end_paint around the clear so that we can
+          * piggyback on the implicit paint */
+
+         gdk_window_begin_paint_region (window, expose_region);
+         gdk_window_clear_region_internal (window, expose_region, FALSE);
+         gdk_window_end_paint (window);
+       }
+    }
+}
+
+static void
+gdk_window_process_updates_internal (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  gboolean save_region = FALSE;
+  GdkRectangle clip_box;
+
+  /* If an update got queued during update processing, we can get a
+   * window in the update queue that has an empty update_area.
+   * just ignore it.
+   */
+  if (private->update_area)
+    {
+      GdkRegion *update_area = private->update_area;
+      private->update_area = NULL;
+
+      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 */
+         gdk_region_intersect (update_area, private->clip_region);
+
+         if (debug_updates)
+           {
+             /* Make sure we see the red invalid area before redrawing. */
+             gdk_display_sync (gdk_drawable_get_display (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 */
+         if (private->outstanding_moves)
+           {
+             GdkWindowRegionMove *move;
+             GdkRegion *remove;
+             GList *l, *prev;
+
+             remove = gdk_region_copy (update_area);
+             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);
+
+                 /* However if any of the destination we do need has a source
+                    in the updated region we do need that as a destination for
+                    the earlier moves */
+                 gdk_region_offset (move->dest_region, -move->dx, -move->dy);
+                 gdk_region_subtract (remove, move->dest_region);
+
+                 if (gdk_region_empty (move->dest_region))
+                   {
+                     gdk_window_region_move_free (move);
+                     private->outstanding_moves =
+                       g_list_delete_link (private->outstanding_moves, l);
+                   }
+                 else
+                   gdk_region_offset (move->dest_region, move->dx, move->dy);
+               }
+             gdk_region_destroy (remove);
+           }
+
+         gdk_region_get_clipbox (expose_region, &clip_box);
+         end_implicit = gdk_window_begin_implicit_paint (window, &clip_box);
+         if (end_implicit) /* rendering is not double buffered, do moves now */
+             gdk_window_flush_outstanding_moves (window);
+         _gdk_windowing_window_process_updates_recurse (window, expose_region);
+         if (end_implicit)
+           {
+             /* Do moves right before exposes are rendered */
+             gdk_window_flush_outstanding_moves (window);
+             gdk_window_end_implicit_paint (window);
+           }
+
+         if (expose_region != update_area)
+           gdk_region_destroy (expose_region);
+       }
+      if (!save_region)
+       gdk_region_destroy (update_area);
+    }
+
+  if (private->outstanding_moves)
+    {
+      /* Flush any outstanding moves, may happen if we moved a window but got
+        no actual invalid area */
+      gdk_window_flush_outstanding_moves (window);
+    }
+}
+
+static void
+flush_all_displays (void)
+{
+  GSList *displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
+  GSList *tmp_list;
+
+  for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
+    gdk_display_flush (tmp_list->data);
+
+  g_slist_free (displays);
+}
+
+/* Currently it is not possible to override
+ * gdk_window_process_all_updates in the same manner as
+ * gdk_window_process_updates and gdk_window_invalidate_maybe_recurse
+ * by implementing the GdkPaintable interface.  If in the future a
+ * backend would need this, the right solution would be to add a
+ * method to GdkDisplay that can be optionally
+ * NULL. gdk_window_process_all_updates can then walk the list of open
+ * displays and call the mehod.
+ */
+
+/**
+ * gdk_window_process_all_updates:
+ *
+ * Calls gdk_window_process_updates() for all windows (see #GdkWindow)
+ * in the application.
+ *
+ **/
+void
+gdk_window_process_all_updates (void)
+{
+  GSList *old_update_windows = update_windows;
+  GSList *tmp_list = update_windows;
+  static gboolean in_process_all_updates = FALSE;
+
+  if (in_process_all_updates)
+    return;
+
+  in_process_all_updates = TRUE;
+
+  if (update_idle)
+    g_source_remove (update_idle);
+
+  update_windows = NULL;
+  update_idle = 0;
+
+  _gdk_windowing_before_process_all_updates ();
+
+  g_slist_foreach (old_update_windows, (GFunc)g_object_ref, NULL);
+
+  while (tmp_list)
+    {
+      GdkWindowObject *private = (GdkWindowObject *)tmp_list->data;
+
+      if (!GDK_WINDOW_DESTROYED (tmp_list->data))
+       {
+         if (private->update_freeze_count ||
+             gdk_window_is_toplevel_frozen (tmp_list->data))
+           gdk_window_add_update_window ((GdkWindow *) private);
+         else
+           gdk_window_process_updates_internal (tmp_list->data);
+       }
+
+      g_object_unref (tmp_list->data);
+      tmp_list = tmp_list->next;
+    }
+
+  g_slist_free (old_update_windows);
+
+  flush_all_displays ();
+
+  _gdk_windowing_after_process_all_updates ();
+
+  in_process_all_updates = FALSE;
+}
+
+/**
+ * gdk_window_process_updates:
+ * @window: a #GdkWindow
+ * @update_children: whether to also process updates for child windows
+ *
+ * Sends one or more expose events to @window. The areas in each
+ * expose event will cover the entire update area for the window (see
+ * gdk_window_invalidate_region() for details). Normally GDK calls
+ * gdk_window_process_all_updates() on your behalf, so there's no
+ * need to call this function unless you want to force expose events
+ * to be delivered immediately and synchronously (vs. the usual
+ * case, where GDK delivers them in an idle handler). Occasionally
+ * this is useful to produce nicer scrolling behavior, for example.
+ *
+ **/
+void
+gdk_window_process_updates (GdkWindow *window,
+                           gboolean   update_children)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *impl_window;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  impl_window = gdk_window_get_impl_window (private);
+  if ((impl_window->update_area ||
+       impl_window->outstanding_moves) &&
+      !impl_window->update_freeze_count &&
+      !gdk_window_is_toplevel_frozen (window))
+    {
+      gdk_window_process_updates_internal ((GdkWindow *)impl_window);
+      gdk_window_remove_update_window ((GdkWindow *)impl_window);
+    }
+
+  if (update_children)
+    {
+      /* 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);
+    }
+}
+
+/**
+ * gdk_window_invalidate_rect:
+ * @window: a #GdkWindow
+ * @rect: rectangle to invalidate or %NULL to invalidate the whole
+ *      window
+ * @invalidate_children: whether to also invalidate child windows
+ *
+ * A convenience wrapper around gdk_window_invalidate_region() which
+ * invalidates a rectangular region. See
+ * gdk_window_invalidate_region() for details.
+ **/
+void
+gdk_window_invalidate_rect (GdkWindow          *window,
+                           const GdkRectangle *rect,
+                           gboolean            invalidate_children)
+{
+  GdkRectangle window_rect;
+  GdkRegion *region;
+  GdkWindowObject *private = (GdkWindowObject *)window;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
+  if (private->input_only || !GDK_WINDOW_IS_MAPPED (window))
+    return;
+
+  if (!rect)
+    {
+      window_rect.x = 0;
+      window_rect.y = 0;
+      gdk_drawable_get_size (GDK_DRAWABLE (window),
+                            &window_rect.width,
+                            &window_rect.height);
+      rect = &window_rect;
+    }
+
+  region = gdk_region_rectangle (rect);
+  gdk_window_invalidate_region (window, region, invalidate_children);
+  gdk_region_destroy (region);
+}
+
+static void
+draw_ugly_color (GdkWindow       *window,
+                const GdkRegion *region)
+{
+  /* Draw ugly color all over the newly-invalid region */
+  GdkColor ugly_color = { 0, 50000, 10000, 10000 };
+  GdkGC *ugly_gc;
+  GdkRectangle clipbox;
+
+  ugly_gc = gdk_gc_new (window);
+  gdk_gc_set_rgb_fg_color (ugly_gc, &ugly_color);
+  gdk_gc_set_clip_region (ugly_gc, region);
+
+  gdk_region_get_clipbox (region, &clipbox);
+
+  gdk_draw_rectangle (window,
+                     ugly_gc,
+                     TRUE,
+                     clipbox.x, clipbox.y,
+                     clipbox.width, clipbox.height);
+
+  g_object_unref (ugly_gc);
+}
+
+/**
+ * gdk_window_invalidate_maybe_recurse:
+ * @window: a #GdkWindow
+ * @region: a #GdkRegion
+ * @child_func: function to use to decide if to recurse to a child,
+ *              %NULL means never recurse.
+ * @user_data: data passed to @child_func
+ *
+ * Adds @region to the update area for @window. The update area is the
+ * region that needs to be redrawn, or "dirty region." The call
+ * gdk_window_process_updates() sends one or more expose events to the
+ * window, which together cover the entire update area. An
+ * application would normally redraw the contents of @window in
+ * response to those expose events.
+ *
+ * GDK will call gdk_window_process_all_updates() on your behalf
+ * whenever your program returns to the main loop and becomes idle, so
+ * normally there's no need to do that manually, you just need to
+ * invalidate regions that you know should be redrawn.
+ *
+ * The @child_func parameter controls whether the region of
+ * each child window that intersects @region will also be invalidated.
+ * Only children for which @child_func returns TRUE will have the area
+ * invalidated.
+ **/
+void
+gdk_window_invalidate_maybe_recurse (GdkWindow       *window,
+                                    const GdkRegion *region,
+                                    gboolean       (*child_func) (GdkWindow *,
+                                                                  gpointer),
+                                    gpointer   user_data)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *impl_window;
+  GdkRegion *visible_region;
+  GList *tmp_list;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
+  if (private->input_only ||
+      !GDK_WINDOW_IS_MAPPED (window) ||
+      gdk_region_empty (region))
+    return;
+
+  visible_region = gdk_drawable_get_visible_region (window);
+  gdk_region_intersect (visible_region, region);
+
+  tmp_list = private->children;
+  while (tmp_list)
+    {
+      GdkWindowObject *child = tmp_list->data;
+
+      if (!child->input_only)
+       {
+         GdkRegion *child_region;
+         GdkRectangle child_rect;
+
+         child_rect.x = child->x;
+         child_rect.y = child->y;
+         child_rect.width = child->width;
+         child_rect.height = child->height;
+         child_region = gdk_region_rectangle (&child_rect);
+
+         /* remove child area from the invalid area of the parent */
+         if (GDK_WINDOW_IS_MAPPED (child) && !child->shaped &&
+             !child->composited &&
+             !gdk_window_is_offscreen (child))
+           gdk_region_subtract (visible_region, child_region);
+
+         if (child_func && (*child_func) ((GdkWindow *)child, user_data))
+           {
+             GdkRegion *tmp = gdk_region_copy (region);
+
+             gdk_region_offset (tmp, - child_rect.x, - child_rect.y);
+             gdk_region_offset (child_region, - child_rect.x, - child_rect.y);
+             gdk_region_intersect (child_region, tmp);
+
+             gdk_window_invalidate_maybe_recurse ((GdkWindow *)child,
+                                                  child_region, child_func, user_data);
+
+             gdk_region_destroy (tmp);
+           }
+
+         gdk_region_destroy (child_region);
+       }
+
+      tmp_list = tmp_list->next;
+    }
+
+  impl_window = gdk_window_get_impl_window (private);
+
+  if (!gdk_region_empty (visible_region)  ||
+      /* Even if we're not exposing anything, make sure we process
+        idles for windows with outstanding moves */
+      (impl_window->outstanding_moves != NULL &&
+       impl_window->update_area == NULL))
+    {
+      if (debug_updates)
+       draw_ugly_color (window, region);
+
+      /* Convert to impl coords */
+      gdk_region_offset (visible_region, private->abs_x, private->abs_y);
+      if (impl_window->update_area)
+       {
+         gdk_region_union (impl_window->update_area, visible_region);
+       }
+      else
+       {
+         gdk_window_add_update_window ((GdkWindow *)impl_window);
+         impl_window->update_area = gdk_region_copy (visible_region);
+
+         gdk_window_schedule_update ((GdkWindow *)impl_window);
+       }
+    }
+
+  gdk_region_destroy (visible_region);
+}
+
+static gboolean
+true_predicate (GdkWindow *window,
+               gpointer   user_data)
+{
+  return TRUE;
+}
+
+/**
+ * gdk_window_invalidate_region:
+ * @window: a #GdkWindow
+ * @region: a #GdkRegion
+ * @invalidate_children: %TRUE to also invalidate child windows
+ *
+ * Adds @region to the update area for @window. The update area is the
+ * region that needs to be redrawn, or "dirty region." The call
+ * gdk_window_process_updates() sends one or more expose events to the
+ * window, which together cover the entire update area. An
+ * application would normally redraw the contents of @window in
+ * response to those expose events.
+ *
+ * GDK will call gdk_window_process_all_updates() on your behalf
+ * whenever your program returns to the main loop and becomes idle, so
+ * normally there's no need to do that manually, you just need to
+ * invalidate regions that you know should be redrawn.
+ *
+ * The @invalidate_children parameter controls whether the region of
+ * each child window that intersects @region will also be invalidated.
+ * If %FALSE, then the update area for child windows will remain
+ * unaffected. See gdk_window_invalidate_maybe_recurse if you need
+ * fine grained control over which children are invalidated.
+ **/
+void
+gdk_window_invalidate_region (GdkWindow       *window,
+                             const GdkRegion *region,
+                             gboolean         invalidate_children)
+{
+  gdk_window_invalidate_maybe_recurse (window, region,
+                                      invalidate_children ?
+                                        true_predicate : (gboolean (*) (GdkWindow *, gpointer))NULL,
+                                      NULL);
+}
+
+/**
+ * _gdk_window_invalidate_for_expose:
+ * @window: a #GdkWindow
+ * @region: a #GdkRegion
+ *
+ * Adds @region to the update area for @window. The update area is the
+ * region that needs to be redrawn, or "dirty region." The call
+ * gdk_window_process_updates() sends one or more expose events to the
+ * window, which together cover the entire update area. An
+ * application would normally redraw the contents of @window in
+ * response to those expose events.
+ *
+ * GDK will call gdk_window_process_all_updates() on your behalf
+ * whenever your program returns to the main loop and becomes idle, so
+ * normally there's no need to do that manually, you just need to
+ * invalidate regions that you know should be redrawn.
+ *
+ * This version of invalidation is used when you recieve expose events
+ * from the native window system. It exposes the native window, plus
+ * any non-native child windows (but not native child windows, as those would
+ * have gotten their own expose events).
+ **/
+void
+_gdk_window_invalidate_for_expose (GdkWindow       *window,
+                                  const GdkRegion *region)
+{
+  gdk_window_invalidate_maybe_recurse (window, region,
+                                      (gboolean (*) (GdkWindow *, gpointer))gdk_window_has_no_impl,
+                                      NULL);
+}
+
+
+/**
+ * gdk_window_get_update_area:
+ * @window: a #GdkWindow
+ *
+ * Transfers ownership of the update area from @window to the caller
+ * of the function. That is, after calling this function, @window will
+ * no longer have an invalid/dirty region; the update area is removed
+ * from @window and handed to you. If a window has no update area,
+ * gdk_window_get_update_area() returns %NULL. You are responsible for
+ * calling gdk_region_destroy() on the returned region if it's non-%NULL.
+ *
+ * Return value: the update area for @window
+ **/
+GdkRegion *
+gdk_window_get_update_area (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *impl_window;
+  GdkRegion *tmp_region;
+
+  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
+
+  impl_window = gdk_window_get_impl_window (private);
+
+  if (impl_window->update_area)
+    {
+      tmp_region = gdk_region_copy (private->clip_region_with_children);
+      /* Convert to impl coords */
+      gdk_region_offset (tmp_region, private->abs_x, private->abs_y);
+      gdk_region_intersect (tmp_region, impl_window->update_area);
+
+      if (gdk_region_empty (tmp_region))
+       {
+         gdk_region_destroy (tmp_region);
+         return NULL;
+       }
+      else
+       {
+         gdk_region_subtract (impl_window->update_area, tmp_region);
+
+         if (gdk_region_empty (impl_window->update_area) &&
+             impl_window->outstanding_moves == NULL)
+           {
+             gdk_region_destroy (impl_window->update_area);
+             impl_window->update_area = NULL;
+
+             gdk_window_remove_update_window ((GdkWindow *)impl_window);
+           }
+
+         /* Convert from impl coords */
+         gdk_region_offset (tmp_region, -private->abs_x, -private->abs_y);
+         return tmp_region;
+
+       }
+    }
+  else
+    return NULL;
+}
+
+/**
+ * _gdk_window_clear_update_area:
+ * @window: a #GdkWindow.
+ *
+ * Internal function to clear the update area for a window. This
+ * is called when the window is hidden or destroyed.
+ **/
+void
+_gdk_window_clear_update_area (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  if (private->update_area)
+    {
+      gdk_window_remove_update_window (window);
+
+      gdk_region_destroy (private->update_area);
+      private->update_area = NULL;
+    }
+}
+
+/**
+ * gdk_window_freeze_updates:
+ * @window: a #GdkWindow
+ *
+ * Temporarily freezes a window such that it won't receive expose
+ * events.  The window will begin receiving expose events again when
+ * gdk_window_thaw_updates() is called. If gdk_window_freeze_updates()
+ * has been called more than once, gdk_window_thaw_updates() must be called
+ * an equal number of times to begin processing exposes.
+ **/
+void
+gdk_window_freeze_updates (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *impl_window;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  impl_window = gdk_window_get_impl_window (private);
+  impl_window->update_freeze_count++;
+}
+
+/**
+ * gdk_window_thaw_updates:
+ * @window: a #GdkWindow
+ *
+ * Thaws a window frozen with gdk_window_freeze_updates().
+ **/
+void
+gdk_window_thaw_updates (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *impl_window;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  impl_window = gdk_window_get_impl_window (private);
+
+  g_return_if_fail (impl_window->update_freeze_count > 0);
+
+  if (--impl_window->update_freeze_count == 0)
+    gdk_window_schedule_update (GDK_WINDOW (impl_window));
+}
+
+/**
+ * gdk_window_freeze_toplevel_updates_libgtk_only:
+ * @window: a #GdkWindow
+ *
+ * Temporarily freezes a window and all its descendants such that it won't
+ * receive expose events.  The window will begin receiving expose events
+ * again when gdk_window_thaw_toplevel_updates_libgtk_only() is called. If
+ * gdk_window_freeze_toplevel_updates_libgtk_only()
+ * has been called more than once,
+ * gdk_window_thaw_toplevel_updates_libgtk_only() must be called
+ * an equal number of times to begin processing exposes.
+ *
+ * This function is not part of the GDK public API and is only
+ * for use by GTK+.
+ **/
+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);
+
+  private->update_and_descendants_freeze_count++;
+}
+
+/**
+ * gdk_window_thaw_toplevel_updates_libgtk_only:
+ * @window: a #GdkWindow
+ *
+ * Thaws a window frozen with
+ * gdk_window_freeze_toplevel_updates_libgtk_only().
+ *
+ * This function is not part of the GDK public API and is only
+ * for use by GTK+.
+ **/
+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);
+
+  private->update_and_descendants_freeze_count--;
+
+  gdk_window_schedule_update (window);
+}
+
+/**
+ * gdk_window_set_debug_updates:
+ * @setting: %TRUE to turn on update debugging
+ *
+ * With update debugging enabled, calls to
+ * gdk_window_invalidate_region() clear the invalidated region of the
+ * screen to a noticeable color, and GDK pauses for a short time
+ * before sending exposes to windows during
+ * gdk_window_process_updates().  The net effect is that you can see
+ * the invalid region for each window and watch redraws as they
+ * occur. This allows you to diagnose inefficiencies in your application.
+ *
+ * In essence, because the GDK rendering model prevents all flicker,
+ * if you are redrawing the same region 400 times you may never
+ * notice, aside from noticing a speed problem. Enabling update
+ * debugging causes GTK to flicker slowly and noticeably, so you can
+ * see exactly what's being redrawn when, in what order.
+ *
+ * The --gtk-debug=updates command line option passed to GTK+ programs
+ * enables this debug option at application startup time. That's
+ * usually more useful than calling gdk_window_set_debug_updates()
+ * yourself, though you might want to use this function to enable
+ * updates sometime after application startup time.
+ *
+ **/
+void
+gdk_window_set_debug_updates (gboolean setting)
+{
+  debug_updates = setting;
+}
+
+/**
+ * gdk_window_constrain_size:
+ * @geometry: a #GdkGeometry structure
+ * @flags: a mask indicating what portions of @geometry are set
+ * @width: desired width of window
+ * @height: desired height of the window
+ * @new_width: location to store resulting width
+ * @new_height: location to store resulting height
+ *
+ * Constrains a desired width and height according to a
+ * set of geometry hints (such as minimum and maximum size).
+ */
+void
+gdk_window_constrain_size (GdkGeometry *geometry,
+                          guint        flags,
+                          gint         width,
+                          gint         height,
+                          gint        *new_width,
+                          gint        *new_height)
+{
+  /* This routine is partially borrowed from fvwm.
+   *
+   * Copyright 1993, Robert Nation
+   *     You may use this code for any purpose, as long as the original
+   *     copyright remains in the source code and all documentation
+   *
+   * which in turn borrows parts of the algorithm from uwm
+   */
+  gint min_width = 0;
+  gint min_height = 0;
+  gint base_width = 0;
+  gint base_height = 0;
+  gint xinc = 1;
+  gint yinc = 1;
+  gint max_width = G_MAXINT;
+  gint max_height = G_MAXINT;
+
+#define FLOOR(value, base)     ( ((gint) ((value) / (base))) * (base) )
+
+  if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
+    {
+      base_width = geometry->base_width;
+      base_height = geometry->base_height;
+      min_width = geometry->min_width;
+      min_height = geometry->min_height;
+    }
+  else if (flags & GDK_HINT_BASE_SIZE)
+    {
+      base_width = geometry->base_width;
+      base_height = geometry->base_height;
+      min_width = geometry->base_width;
+      min_height = geometry->base_height;
+    }
+  else if (flags & GDK_HINT_MIN_SIZE)
+    {
+      base_width = geometry->min_width;
+      base_height = geometry->min_height;
+      min_width = geometry->min_width;
+      min_height = geometry->min_height;
+    }
+
+  if (flags & GDK_HINT_MAX_SIZE)
+    {
+      max_width = geometry->max_width ;
+      max_height = geometry->max_height;
+    }
+
+  if (flags & GDK_HINT_RESIZE_INC)
+    {
+      xinc = MAX (xinc, geometry->width_inc);
+      yinc = MAX (yinc, geometry->height_inc);
+    }
+
+  /* clamp width and height to min and max values
+   */
+  width = CLAMP (width, min_width, max_width);
+  height = CLAMP (height, min_height, max_height);
+
+  /* shrink to base + N * inc
+   */
+  width = base_width + FLOOR (width - base_width, xinc);
+  height = base_height + FLOOR (height - base_height, yinc);
+
+  /* constrain aspect ratio, according to:
+   *
+   *                width
+   * min_aspect <= -------- <= max_aspect
+   *                height
+   */
+
+  if (flags & GDK_HINT_ASPECT &&
+      geometry->min_aspect > 0 &&
+      geometry->max_aspect > 0)
+    {
+      gint delta;
+
+      if (geometry->min_aspect * height > width)
+       {
+         delta = FLOOR (height - width / geometry->min_aspect, yinc);
+         if (height - delta >= min_height)
+           height -= delta;
+         else
+           {
+             delta = FLOOR (height * geometry->min_aspect - width, xinc);
+             if (width + delta <= max_width)
+               width += delta;
+           }
+       }
+
+      if (geometry->max_aspect * height < width)
+       {
+         delta = FLOOR (width - height * geometry->max_aspect, xinc);
+         if (width - delta >= min_width)
+           width -= delta;
+         else
+           {
+             delta = FLOOR (width / geometry->max_aspect - height, yinc);
+             if (height + delta <= max_height)
+               height += delta;
+           }
+       }
+    }
+
+#undef FLOOR
+
+  *new_width = width;
+  *new_height = height;
+}
+
+/**
+ * gdk_window_get_pointer:
+ * @window: a #GdkWindow
+ * @x: return location for X coordinate of pointer or %NULL to not
+ *      return the X coordinate
+ * @y: return location for Y coordinate of pointer or %NULL to not
+ *      return the Y coordinate
+ * @mask: return location for modifier mask or %NULL to not return the
+ *      modifier mask
+ *
+ * Obtains the current pointer position and modifier state.
+ * The position is given in coordinates relative to the upper left
+ * corner of @window.
+ *
+ * Return value: the window containing the pointer (as with
+ * gdk_window_at_pointer()), or %NULL if the window containing the
+ * pointer isn't known to GDK
+ **/
+GdkWindow*
+gdk_window_get_pointer (GdkWindow        *window,
+                       gint              *x,
+                       gint              *y,
+                       GdkModifierType   *mask)
+{
+  GdkDisplay *display;
+  gint tmp_x, tmp_y;
+  GdkModifierType tmp_mask;
+  GdkWindow *child;
+
+  g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
+
+  if (window)
+    {
+      display = gdk_drawable_get_display (window);
+    }
+  else
+    {
+      GdkScreen *screen = gdk_screen_get_default ();
+
+      display = gdk_screen_get_display (screen);
+      window = gdk_screen_get_root_window (screen);
+
+      GDK_NOTE (MULTIHEAD,
+               g_message ("Passing NULL for window to gdk_window_get_pointer()\n"
+                          "is not multihead safe"));
+    }
+
+  child = display->pointer_hooks->window_get_pointer (display, window, &tmp_x, &tmp_y, &tmp_mask);
+
+  if (x)
+    *x = tmp_x;
+  if (y)
+    *y = tmp_y;
+  if (mask)
+    *mask = tmp_mask;
+
+  _gdk_display_enable_motion_hints (display);
+
+  return child;
+}
+
+/**
+ * gdk_window_at_pointer:
+ * @win_x: return location for origin of the window under the pointer
+ * @win_y: return location for origin of the window under the pointer
+ *
+ * Obtains the window underneath the mouse pointer, returning the
+ * location of that window in @win_x, @win_y. Returns %NULL if the
+ * window under the mouse pointer is not known to GDK (if the window
+ * belongs to another application and a #GdkWindow hasn't been created
+ * for it with gdk_window_foreign_new())
+ *
+ * NOTE: For multihead-aware widgets or applications use
+ * gdk_display_get_window_at_pointer() instead.
+ *
+ * Return value: window under the mouse pointer
+ **/
+GdkWindow*
+gdk_window_at_pointer (gint *win_x,
+                      gint *win_y)
+{
+  return gdk_display_get_window_at_pointer (gdk_display_get_default (), win_x, win_y);
+}
+
+/**
+ * gdk_get_default_root_window:
+ *
+ * Obtains the root window (parent all other windows are inside)
+ * for the default display and screen.
+ *
+ * Return value: the default root window
+ **/
+GdkWindow *
+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,
+                        GList **native)
+{
+  GdkWindowObject *child;
+  GList *l;
+
+  for (l = private->children; l != NULL; l = l->next)
+    {
+      child = l->data;
+
+      if (gdk_window_has_impl (child))
+       *native = g_list_prepend (*native, child);
+      else
+       get_all_native_children (child, native);
+    }
+}
+
+
+static inline void
+gdk_window_raise_internal (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *parent = private->parent;
+  GdkWindowObject *above;
+  GList *native_children;
+  GList *l, listhead;
+
+  if (parent)
+    {
+      parent->children = g_list_remove (parent->children, window);
+      parent->children = g_list_prepend (parent->children, window);
+    }
+
+  /* Just do native raise for toplevels */
+  if (private->parent == NULL ||
+      GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
+    {
+      GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
+    }
+  else if (gdk_window_has_impl (private))
+    {
+      above = find_native_sibling_above (parent, private);
+      if (above)
+       {
+         listhead.data = window;
+         listhead.next = NULL;
+         listhead.prev = NULL;
+         GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
+                                                                   &listhead);
+       }
+      else
+       GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
+    }
+  else
+    {
+      native_children = NULL;
+      get_all_native_children (private, &native_children);
+      if (native_children != NULL)
+       {
+         above = find_native_sibling_above (parent, private);
+
+         if (above)
+           GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
+                                                                     native_children);
+         else
+           {
+             /* Right order, since native_chilren is bottom-opmost first */
+             for (l = native_children; l != NULL; l = l->next)
+               GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (l->data);
+           }
+
+         g_list_free (native_children);
+       }
+
+    }
+}
+
+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;
+      if (GDK_WINDOW_IS_MAPPED (child))
+       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
+gdk_window_show_internal (GdkWindow *window, gboolean raise)
+{
+  GdkWindowObject *private;
+  gboolean was_mapped;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *) window;
+  if (private->destroyed)
+    return;
+
+  was_mapped = GDK_WINDOW_IS_MAPPED (window);
+
+  if (raise)
+    /* Keep children in (reverse) stacking order */
+    gdk_window_raise_internal (window);
+
+  if (gdk_window_has_impl (private))
+    {
+      if (!was_mapped)
+       gdk_synthesize_window_state (window,
+                                    GDK_WINDOW_STATE_WITHDRAWN,
+                                    0);
+    }
+  else
+    {
+      private->state = 0;
+    }
+
+  if (gdk_window_is_viewable (window))
+    show_all_visible_impls (private, was_mapped);
+
+  if (!was_mapped)
+    {
+      if (private->event_mask & GDK_STRUCTURE_MASK)
+       _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
+
+      if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+       _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
+    }
+
+  if (!was_mapped || raise)
+    {
+      recompute_visible_regions (private, TRUE, FALSE);
+
+      /* If any decendants became visible we need to send visibility notify */
+      gdk_window_update_visibility_recursively (private, NULL);
+
+      if (gdk_window_is_viewable (window))
+       {
+         _gdk_syntesize_crossing_events_for_geometry_change (window);
+         gdk_window_invalidate_rect (window, NULL, TRUE);
+       }
+    }
+}
+
+/**
+ * gdk_window_show_unraised:
+ * @window: a #GdkWindow
+ *
+ * Shows a #GdkWindow onscreen, but does not modify its stacking
+ * order. In contrast, gdk_window_show() will raise the window
+ * to the top of the window stack.
+ *
+ * On the X11 platform, in Xlib terms, this function calls
+ * XMapWindow() (it also updates some internal GDK state, which means
+ * that you can't really use XMapWindow() directly on a GDK window).
+ */
+void
+gdk_window_show_unraised (GdkWindow *window)
+{
+  gdk_window_show_internal (window, FALSE);
+}
+
+/**
+ * gdk_window_raise:
+ * @window: a #GdkWindow
+ *
+ * Raises @window to the top of the Z-order (stacking order), so that
+ * other windows with the same parent window appear below @window.
+ * This is true whether or not the windows are visible.
+ *
+ * If @window is a toplevel, the window manager may choose to deny the
+ * request to move the window in the Z-order, gdk_window_raise() only
+ * requests the restack, does not guarantee it.
+ */
+void
+gdk_window_raise (GdkWindow *window)
+{
+  GdkWindowObject *private;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *) window;
+  if (private->destroyed)
+    return;
+
+  /* Keep children in (reverse) stacking order */
+  gdk_window_raise_internal (window);
+
+  recompute_visible_regions (private, TRUE, FALSE);
+
+  gdk_window_invalidate_rect (window, NULL, TRUE);
+}
+
+static void
+gdk_window_lower_internal (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *parent = private->parent;
+  GdkWindowObject *above;
+  GList *native_children;
+  GList *l, listhead;
+
+  if (parent)
+    {
+      parent->children = g_list_remove (parent->children, window);
+      parent->children = g_list_append (parent->children, window);
+    }
+
+  /* Just do native lower for toplevels */
+  if (private->parent == NULL ||
+      GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
+    {
+      GDK_WINDOW_IMPL_GET_IFACE (private->impl)->lower (window);
+    }
+  else if (gdk_window_has_impl (private))
+    {
+      above = find_native_sibling_above (parent, private);
+      if (above)
+       {
+         listhead.data = window;
+         listhead.next = NULL;
+         listhead.prev = NULL;
+         GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
+                                                                   &listhead);
+       }
+      else
+       GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
     }
   else
-    gdk_draw_text_wc (private->impl, font, gc,
-                      x - x_offset, y - y_offset, text, text_length);
-  
-  RESTORE_GC (gc);
+    {
+      native_children = NULL;
+      get_all_native_children (private, &native_children);
+      if (native_children != NULL)
+       {
+         above = find_native_sibling_above (parent, private);
+
+         if (above)
+           GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
+                                                                     native_children);
+         else
+           {
+             /* Right order, since native_chilren is bottom-opmost first */
+             for (l = native_children; l != NULL; l = l->next)
+               GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (l->data);
+           }
+
+         g_list_free (native_children);
+       }
+
+    }
+}
+
+static void
+gdk_window_invalidate_in_parent (GdkWindowObject *private)
+{
+  GdkRectangle r, child;
+
+  if (private->parent == NULL ||
+      GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
+    return;
+
+  /* get the visible rectangle of the parent */
+  r.x = r.y = 0;
+  r.width = private->parent->width;
+  r.height = private->parent->height;
+
+  child.x = private->x;
+  child.y = private->y;
+  child.width = private->width;
+  child.height = private->height;
+  gdk_rectangle_intersect (&r, &child, &r);
+
+  gdk_window_invalidate_rect (GDK_WINDOW (private->parent), &r, TRUE);
+}
+
+
+/**
+ * gdk_window_lower:
+ * @window: a #GdkWindow
+ *
+ * Lowers @window to the bottom of the Z-order (stacking order), so that
+ * other windows with the same parent window appear above @window.
+ * This is true whether or not the other windows are visible.
+ *
+ * If @window is a toplevel, the window manager may choose to deny the
+ * request to move the window in the Z-order, gdk_window_lower() only
+ * requests the restack, does not guarantee it.
+ *
+ * Note that gdk_window_show() raises the window again, so don't call this
+ * function before gdk_window_show(). (Try gdk_window_show_unraised().)
+ */
+void
+gdk_window_lower (GdkWindow *window)
+{
+  GdkWindowObject *private;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *) window;
+  if (private->destroyed)
+    return;
+
+  /* Keep children in (reverse) stacking order */
+  gdk_window_lower_internal (window);
+
+  recompute_visible_regions (private, TRUE, FALSE);
+
+  _gdk_syntesize_crossing_events_for_geometry_change (window);
+  gdk_window_invalidate_in_parent (private);
 }
 
-static GdkDrawable*
-gdk_window_get_composite_drawable (GdkDrawable *drawable,
-                                   gint         x,
-                                   gint         y,
-                                   gint         width,
-                                   gint         height,
-                                   gint        *composite_x_offset,
-                                   gint        *composite_y_offset)
+/**
+ * gdk_window_show:
+ * @window: a #GdkWindow
+ *
+ * Like gdk_window_show_unraised(), but also raises the window to the
+ * top of the window stack (moves the window to the front of the
+ * Z-order).
+ *
+ * This function maps a window so it's visible onscreen. Its opposite
+ * is gdk_window_hide().
+ *
+ * When implementing a #GtkWidget, you should call this function on the widget's
+ * #GdkWindow as part of the "map" method.
+ */
+void
+gdk_window_show (GdkWindow *window)
 {
-  GdkWindowObject *private = (GdkWindowObject *)drawable;
-  GSList *list;
-  GdkPixmap *tmp_pixmap;
-  GdkRectangle rect;
-  GdkGC *tmp_gc;
-  gboolean overlap_buffer;
+  gdk_window_show_internal (window, TRUE);
+}
+
+static void
+hide_all_visible_impls (GdkWindowObject *private)
+{
+  GdkWindowObject *child;
+  GList *l;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (GDK_WINDOW (drawable),
-                                                          composite_x_offset,
-                                                          composite_y_offset);
-  
-  if ((GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable))
-      || private->paint_stack == NULL)
+  for (l = private->children; l != NULL; l = l->next)
     {
-      /* No backing store */
-      return g_object_ref (drawable);
+      child = l->data;
+
+      if (GDK_WINDOW_IS_MAPPED (child))
+       hide_all_visible_impls (child);
     }
 
-  /* See if the buffered part is overlapping the part we want
-   * to get
-   */
-  rect.x = x;
-  rect.y = y;
-  rect.width = width;
-  rect.height = height;
+  if (gdk_window_has_impl (private))
+    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->hide ((GdkWindow *)private);
+}
 
-  overlap_buffer = FALSE;
-  
-  for (list = private->paint_stack; list != NULL; list = list->next)
+
+/**
+ * gdk_window_hide:
+ * @window: a #GdkWindow
+ *
+ * For toplevel windows, withdraws them, so they will no longer be
+ * known to the window manager; for all windows, unmaps them, so
+ * they won't be displayed. Normally done automatically as
+ * part of gtk_widget_hide().
+ */
+void
+gdk_window_hide (GdkWindow *window)
+{
+  GdkWindowObject *private;
+  gboolean was_mapped, was_viewable;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *) window;
+  if (private->destroyed)
+    return;
+
+  was_mapped = GDK_WINDOW_IS_MAPPED (private);
+  was_viewable = gdk_window_is_viewable (window);
+
+  if (gdk_window_has_impl (private))
     {
-      GdkWindowPaint *paint = list->data;
-      GdkOverlapType overlap;
 
-      overlap = gdk_region_rect_in (paint->region, &rect);
+      if (GDK_WINDOW_IS_MAPPED (window))
+       gdk_synthesize_window_state (window,
+                                    0,
+                                    GDK_WINDOW_STATE_WITHDRAWN);
+    }
+  else if (was_mapped)
+    {
+      GdkDisplay *display;
 
-      if (overlap == GDK_OVERLAP_RECTANGLE_IN)
-       {
-         *composite_x_offset = paint->x_offset;
-         *composite_y_offset = paint->y_offset;
-         
-         return g_object_ref (paint->pixmap);
-       }
-      else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
+      /* May need to break grabs on children */
+      display = gdk_drawable_get_display (window);
+
+      if (_gdk_display_end_pointer_grab (display,
+                                        _gdk_windowing_window_get_next_serial (display),
+                                        window,
+                                        TRUE))
+       gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
+
+      if (display->keyboard_grab.window != NULL)
        {
-         overlap_buffer = TRUE;
-         break;
+         if (is_parent_of (window, display->keyboard_grab.window))
+           {
+             /* Call this ourselves, even though gdk_display_keyboard_ungrab
+                does so too, since we want to pass implicit == TRUE so the
+                broken grab event is generated */
+             _gdk_display_unset_has_keyboard_grab (display,
+                                                   TRUE);
+             gdk_display_keyboard_ungrab (display, GDK_CURRENT_TIME);
+           }
        }
+
+      private->state = GDK_WINDOW_STATE_WITHDRAWN;
     }
 
-  if (!overlap_buffer)
-    return g_object_ref (drawable);
+  if (was_viewable)
+    hide_all_visible_impls (private);
 
-  tmp_pixmap = gdk_pixmap_new (drawable, width, height, -1);
-  tmp_gc = _gdk_drawable_get_scratch_gc (tmp_pixmap, FALSE);
+  recompute_visible_regions (private, TRUE, FALSE);
 
-  /* Copy the current window contents */
-  gdk_draw_drawable (tmp_pixmap,
-                     tmp_gc,
-                     private->impl,
-                     x - *composite_x_offset,
-                     y - *composite_y_offset,
-                     0, 0,
-                     width, height);
+  /* all decendants became non-visible, we need to send visibility notify */
+  gdk_window_update_visibility_recursively (private, NULL);
 
-  /* paint the backing stores */
-  for (list = private->paint_stack; list != NULL; list = list->next)
+  if (was_mapped)
     {
-      GdkWindowPaint *paint = list->data;
-
-      gdk_gc_set_clip_region (tmp_gc, paint->region);
-      gdk_gc_set_clip_origin (tmp_gc, -x, -y);
-      
-      gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
-                        x - paint->x_offset,
-                        y - paint->y_offset,
-                        0, 0, width, height);
-    }
+      if (private->event_mask & GDK_STRUCTURE_MASK)
+       _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
 
-  /* Reset clip region of the cached GdkGC */
-  gdk_gc_set_clip_region (tmp_gc, NULL);
+      if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+       _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
 
-  /* Set these to location of tmp_pixmap within the window */
-  *composite_x_offset = x;
-  *composite_y_offset = y;
+      _gdk_syntesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
+    }
 
-  return tmp_pixmap;
+  /* Invalidate the rect */
+  gdk_window_invalidate_in_parent (private);
 }
 
-static GdkRegion*
-gdk_window_get_clip_region (GdkDrawable *drawable)
+/**
+ * gdk_window_withdraw:
+ * @window: a toplevel #GdkWindow
+ *
+ * Withdraws a window (unmaps it and asks the window manager to forget about it).
+ * This function is not really useful as gdk_window_hide() automatically
+ * withdraws toplevel windows before hiding them.
+ **/
+void
+gdk_window_withdraw (GdkWindow *window)
 {
-  GdkWindowObject *private = (GdkWindowObject *)drawable;
-  GdkRegion *result;
+  GdkWindowObject *private;
+  gboolean was_mapped;
 
-  result = gdk_drawable_get_clip_region (private->impl);
+  g_return_if_fail (GDK_IS_WINDOW (window));
 
-  if (private->paint_stack)
+  private = (GdkWindowObject *) window;
+  if (private->destroyed)
+    return;
+
+  was_mapped = GDK_WINDOW_IS_MAPPED (private);
+
+  if (gdk_window_has_impl (private))
     {
-      GdkRegion *paint_region = gdk_region_new ();
-      GSList *tmp_list = private->paint_stack;
+      GDK_WINDOW_IMPL_GET_IFACE (private->impl)->withdraw (window);
 
-      while (tmp_list)
+      if (was_mapped)
        {
-         GdkWindowPaint *paint = tmp_list->data;
-         
-         gdk_region_union (paint_region, paint->region);
+         if (private->event_mask & GDK_STRUCTURE_MASK)
+           _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
+
+         if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+           _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
 
-          tmp_list = tmp_list->next;
+         _gdk_syntesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
        }
 
-      gdk_region_intersect (result, paint_region);
-      gdk_region_destroy (paint_region);
+      recompute_visible_regions (private, TRUE, FALSE);
     }
-
-  return result;
 }
 
-static GdkRegion*
-gdk_window_get_visible_region (GdkDrawable *drawable)
+/**
+ * gdk_window_set_events:
+ * @window: a #GdkWindow
+ * @event_mask: event mask for @window
+ *
+ * The event mask for a window determines which events will be reported
+ * for that window. For example, an event mask including #GDK_BUTTON_PRESS_MASK
+ * means the window should report button press events. The event mask
+ * is the bitwise OR of values from the #GdkEventMask enumeration.
+ **/
+void
+gdk_window_set_events (GdkWindow       *window,
+                      GdkEventMask     event_mask)
 {
-  GdkWindowObject *private = (GdkWindowObject*) drawable;
-  
-  return gdk_drawable_get_visible_region (private->impl);
+  GdkWindowObject *private;
+  GdkDisplay *display;
+
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *) window;
+  if (private->destroyed)
+    return;
+
+  /* If motion hint is disabled, enable motion events again */
+  display = gdk_drawable_get_display (window);
+  if ((private->event_mask & GDK_POINTER_MOTION_HINT_MASK) &&
+      !(event_mask & GDK_POINTER_MOTION_HINT_MASK))
+    _gdk_display_enable_motion_hints (display);
+
+  private->event_mask = event_mask;
+
+  if (gdk_window_has_impl (private))
+    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_events (window,
+                                                          get_native_event_mask (private));
+
 }
 
-static void
-gdk_window_draw_drawable (GdkDrawable *drawable,
-                         GdkGC       *gc,
-                         GdkPixmap   *src,
-                         gint         xsrc,
-                         gint         ysrc,
-                         gint         xdest,
-                         gint         ydest,
-                         gint         width,
-                         gint         height)
+/**
+ * gdk_window_get_events:
+ * @window: a #GdkWindow
+ *
+ * Gets the event mask for @window. See gdk_window_set_events().
+ *
+ * Return value: event mask for @window
+ **/
+GdkEventMask
+gdk_window_get_events (GdkWindow *window)
 {
-  GdkWindowObject *private = (GdkWindowObject *)drawable;
-  OFFSET_GC (gc);
-  
-  if (GDK_WINDOW_DESTROYED (drawable))
-    return;
+  GdkWindowObject *private;
 
-  /* If we have a backing pixmap draw to that */
-  if (private->paint_stack)
-    {
-      GdkWindowPaint *paint = private->paint_stack->data;
-      gdk_draw_drawable (paint->pixmap, gc,
-                         src, xsrc, ysrc,
-                        xdest - x_offset, ydest - y_offset, width, height);
+  g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
 
-    }
-  else
-    gdk_draw_drawable (private->impl, gc,
-                       src, xsrc, ysrc,
-                       xdest - x_offset, ydest - y_offset,
-                       width, height);
+  private = (GdkWindowObject *) window;
+  if (private->destroyed)
+    return 0;
 
-  RESTORE_GC (gc);
+  return private->event_mask;
 }
 
 static void
-gdk_window_draw_points (GdkDrawable *drawable,
-                       GdkGC       *gc,
-                       GdkPoint    *points,
-                       gint         npoints)
+gdk_window_move_resize_toplevel (GdkWindow *window,
+                                gboolean   with_move,
+                                gint       x,
+                                gint       y,
+                                gint       width,
+                                gint       height)
 {
-  GdkWindowObject *private = (GdkWindowObject *)drawable;
-  GdkPoint *new_points;
-  
-  OFFSET_GC (gc);
+  GdkWindowObject *private;
+  GdkRegion *old_region, *new_region;
+  GdkWindowObject *impl_window;
+  gboolean expose;
+  int old_x, old_y, old_abs_x, old_abs_y;
+  int dx, dy;
+  gboolean is_resize;
 
-  if (GDK_WINDOW_DESTROYED (drawable))
-    return;
-  
-  if (x_offset != 0 || y_offset != 0)
-    {
-      gint i;
+  private = (GdkWindowObject *) window;
 
-      new_points = g_new (GdkPoint, npoints);
-      for (i=0; i<npoints; i++)
-       {
-         new_points[i].x = points[i].x - x_offset;
-         new_points[i].y = points[i].y - y_offset;
-       }
+  expose = FALSE;
+  old_region = NULL;
+
+  impl_window = gdk_window_get_impl_window (private);
+
+  old_x = private->x;
+  old_y = private->y;
+
+  is_resize = (width != -1) || (height != -1);
+
+  if (GDK_WINDOW_IS_MAPPED (window) &&
+      !private->input_only)
+    {
+      expose = TRUE;
+      old_region = gdk_region_copy (private->clip_region);
     }
-  else
-    new_points = points;
 
-  if (private->paint_stack)
+  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, with_move, x, y, width, height);
+
+  dx = private->x - old_x;
+  dy = private->y - old_y;
+
+  old_abs_x = private->abs_x;
+  old_abs_y = private->abs_y;
+
+  /* Avoid recomputing for pure toplevel moves, for performance reasons */
+  if (is_resize)
+    recompute_visible_regions (private, TRUE, FALSE);
+
+  if (expose)
     {
-      GdkWindowPaint *paint = private->paint_stack->data;
-      gdk_draw_points (paint->pixmap, gc, new_points, npoints);
+      new_region = gdk_region_copy (private->clip_region);
+
+      /* This is the newly exposed area (due to any resize),
+       * X will expose it, but lets do that without the
+       * roundtrip
+       */
+      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);
     }
-  else
-    gdk_draw_points (private->impl, gc, points, npoints);
 
-  if (new_points != points)
-    g_free (new_points);
+  _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
+
+
+static void
+move_native_children (GdkWindowObject *private)
+{
+  GList *l;
+  GdkWindowObject *child;
+
+  for (l = private->children; l; l = l->next)
+    {
+      child = l->data;
 
-  RESTORE_GC (gc);
+      if (child->impl != private->impl)
+       GDK_WINDOW_IMPL_GET_IFACE (child->impl)->move_resize ((GdkWindow *)child, TRUE, child->x, child->y, child->width, child->height);
+      else
+       move_native_children  (child);
+    }
 }
 
-static void
-gdk_window_draw_segments (GdkDrawable *drawable,
-                         GdkGC       *gc,
-                         GdkSegment  *segs,
-                         gint         nsegs)
+static gboolean
+collect_native_child_region_helper (GdkWindowObject *window,
+                                   GdkWindow *impl,
+                                   GdkRegion **region,
+                                   int x_offset,
+                                   int y_offset)
 {
-  GdkWindowObject *private = (GdkWindowObject *)drawable;
-  GdkSegment *new_segs;
-
-  OFFSET_GC (gc);
+  GdkWindowObject *child;
+  GdkRegion *tmp;
+  GList *l;
 
-  if (GDK_WINDOW_DESTROYED (drawable))
-    return;
-  
-  if (x_offset != 0 || y_offset != 0)
+  for (l = window->children; l != NULL; l = l->next)
     {
-      gint i;
+      child = l->data;
 
-      new_segs = g_new (GdkSegment, nsegs);
-      for (i=0; i<nsegs; i++)
+      if (child->impl != impl)
        {
-         new_segs[i].x1 = segs[i].x1 - x_offset;
-         new_segs[i].y1 = segs[i].y1 - y_offset;
-         new_segs[i].x2 = segs[i].x2 - x_offset;
-         new_segs[i].y2 = segs[i].y2 - y_offset;
+         tmp = gdk_region_copy (child->clip_region);
+         gdk_region_offset (tmp,
+                            x_offset + child->x,
+                            y_offset + child->y);
+         if (*region == NULL)
+           *region = tmp;
+         else
+           {
+             gdk_region_union (*region, tmp);
+             gdk_region_destroy (tmp);
+           }
        }
+      else
+       collect_native_child_region_helper (child, impl, region,
+                                           x_offset + child->x,
+                                           y_offset + child->y);
     }
-  else
-    new_segs = segs;
 
-  if (private->paint_stack)
-    {
-      GdkWindowPaint *paint = private->paint_stack->data;
-      gdk_draw_segments (paint->pixmap, gc, new_segs, nsegs);
-    }
-  else
-    gdk_draw_segments (private->impl, gc, new_segs, nsegs);
-  
-  if (new_segs != segs)
-    g_free (new_segs);
+  return FALSE;
+}
+
+static GdkRegion *
+collect_native_child_region (GdkWindowObject *window,
+                            gboolean include_this)
+{
+  GdkRegion *region;
+
+  if (include_this && gdk_window_has_impl (window))
+    return gdk_region_copy (window->clip_region);
+
+  region = NULL;
+
+  collect_native_child_region_helper (window, window->impl, &region, 0, 0);
 
-  RESTORE_GC (gc);
+  return region;
 }
 
+
 static void
-gdk_window_draw_lines (GdkDrawable *drawable,
-                      GdkGC       *gc,
-                      GdkPoint    *points,
-                      gint         npoints)
+gdk_window_move_resize_internal (GdkWindow *window,
+                                gboolean   with_move,
+                                gint       x,
+                                gint       y,
+                                gint       width,
+                                gint       height)
 {
-  GdkWindowObject *private = (GdkWindowObject *)drawable;
-  GdkPoint *new_points;
+  GdkWindowObject *private;
+  GdkRegion *old_region, *new_region, *copy_area;
+  GdkRegion *old_native_child_region, *new_native_child_region;
+  GdkWindowObject *impl_window;
+  gboolean expose;
+  int old_x, old_y, old_abs_x, old_abs_y;
+  int dx, dy;
 
-  OFFSET_GC (gc);
+  g_return_if_fail (GDK_IS_WINDOW (window));
 
-  if (GDK_WINDOW_DESTROYED (drawable))
+  private = (GdkWindowObject *) window;
+  if (private->destroyed)
     return;
-  
-  if (x_offset != 0 || y_offset != 0)
-    {
-      gint i;
-
-      new_points = g_new (GdkPoint, npoints);
-      for (i=0; i<npoints; i++)
-       {
-         new_points[i].x = points[i].x - x_offset;
-         new_points[i].y = points[i].y - y_offset;
-       }
-    }
-  else
-    new_points = points;
 
-  if (private->paint_stack)
+  if (private->parent == NULL ||
+      GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
     {
-      GdkWindowPaint *paint = private->paint_stack->data;
-      gdk_draw_lines (paint->pixmap, gc, new_points, npoints);
+      gdk_window_move_resize_toplevel (window, with_move, x, y, width, height);
+      return;
     }
-  else
-    gdk_draw_lines (private->impl, gc, new_points, npoints);
 
-  if (new_points != points)
-    g_free (new_points);
+  /* Handle child windows */
 
-  RESTORE_GC (gc);
-}
+  expose = FALSE;
+  old_region = NULL;
 
-static void
-gdk_window_draw_glyphs (GdkDrawable      *drawable,
-                       GdkGC            *gc,
-                       PangoFont        *font,
-                       gint              x,
-                       gint              y,
-                       PangoGlyphString *glyphs)
-{
-  GdkWindowObject *private = (GdkWindowObject *)drawable;
+  impl_window = gdk_window_get_impl_window (private);
 
-  OFFSET_GC (gc);
+  old_x = private->x;
+  old_y = private->y;
 
-  if (GDK_WINDOW_DESTROYED (drawable))
-    return;
-  
-  if (private->paint_stack)
+  if (GDK_WINDOW_IS_MAPPED (window) &&
+      !private->input_only)
     {
-      GdkWindowPaint *paint = private->paint_stack->data;
+      expose = TRUE;
 
-      gdk_draw_glyphs (paint->pixmap, gc, font, x - x_offset, y - y_offset, glyphs);
+      old_region = gdk_region_copy (private->clip_region);
+      /* Adjust region to parent window coords */
+      gdk_region_offset (old_region, private->x, private->y);
     }
-  else
-    gdk_draw_glyphs (private->impl, gc, font,
-                     x - x_offset, y - y_offset, glyphs);
 
-  RESTORE_GC (gc);
-}
+  old_native_child_region = collect_native_child_region (private, TRUE);
+  if (old_native_child_region)
+    {
+      /* Adjust region to parent window coords */
+      gdk_region_offset (old_native_child_region, private->x, private->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
+       * to flush those here for the parent window and all overlapped subwindows
+       * 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);
+    }
 
-static void
-gdk_window_draw_glyphs_transformed (GdkDrawable      *drawable,
-                                   GdkGC            *gc,
-                                   PangoMatrix      *matrix,
-                                   PangoFont        *font,
-                                   gint              x,
-                                   gint              y,
-                                   PangoGlyphString *glyphs)
-{
-  GdkWindowObject *private = (GdkWindowObject *)drawable;
-  PangoMatrix tmp_matrix;
+  /* Set the new position and size */
+  if (with_move)
+    {
+      private->x = x;
+      private->y = y;
+    }
+  if (!(width < 0 && height < 0))
+    {
+      if (width < 1)
+       width = 1;
+      private->width = width;
+      if (height < 1)
+       height = 1;
+      private->height = height;
+    }
 
-  OFFSET_GC (gc);
+  dx = private->x - old_x;
+  dy = private->y - old_y;
 
-  if (GDK_WINDOW_DESTROYED (drawable))
-    return;
+  old_abs_x = private->abs_x;
+  old_abs_y = private->abs_y;
 
-  if (x_offset != 0 || y_offset != 0)
+  recompute_visible_regions (private, TRUE, FALSE);
+
+  new_native_child_region = NULL;
+  if (old_native_child_region)
     {
-      if (matrix)
-       {
-         tmp_matrix = *matrix;
-         tmp_matrix.x0 -= x_offset;
-         tmp_matrix.y0 -= y_offset;
-         matrix = &tmp_matrix;
-       }
-      else if (GDK_PANGO_UNITS_OVERFLOWS (x_offset, y_offset))
+      new_native_child_region = collect_native_child_region (private, TRUE);
+      /* Adjust region to parent window coords */
+      gdk_region_offset (new_native_child_region, private->x, private->y);
+    }
+
+  if (gdk_window_has_impl (private))
+    {
+      /* 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. */
+      GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, TRUE, private->x, private->y, private->width, private->height);
+    }
+  else if (old_abs_x != private->abs_x ||
+          old_abs_y != private->abs_y)
+    move_native_children (private);
+
+  if (expose)
+    {
+      new_region = gdk_region_copy (private->clip_region);
+      /* Adjust region to parent window coords */
+      gdk_region_offset (new_region, private->x, private->y);
+
+      /* copy_area:
+       * Part of the data at the new location can be copied from the
+       * old location, this area is the intersection of the old region
+       * moved as the copy will move it and then intersected with
+       * the new region.
+       *
+       * new_region:
+       * Everything in the old and new regions that is not copied must be
+       * invalidated (including children) as this is newly exposed
+       */
+      copy_area = gdk_region_copy (new_region);
+
+      gdk_region_union (new_region, old_region);
+
+      if (old_native_child_region)
        {
-         PangoMatrix identity = PANGO_MATRIX_INIT;
-         
-         tmp_matrix = identity;
-         tmp_matrix.x0 -= x_offset;
-         tmp_matrix.y0 -= y_offset;
-         matrix = &tmp_matrix;
+         /* Don't copy from inside native children, as this is copied by
+          * the native window move.
+          */
+         gdk_region_subtract (old_region, old_native_child_region);
        }
-      else
+      gdk_region_offset (old_region, dx, dy);
+
+      gdk_region_intersect (copy_area, old_region);
+
+      if (new_native_child_region)
        {
-         x -= x_offset * PANGO_SCALE;
-         y -= y_offset * PANGO_SCALE;
+         /* Don't copy any bits that would cause a read from the moved
+            native windows, as we can't read that data */
+         gdk_region_offset (new_native_child_region, dx, dy);
+         gdk_region_subtract (copy_area, new_native_child_region);
        }
+
+      gdk_region_subtract (new_region, copy_area);
+
+      /* Convert old region to impl coords */
+      gdk_region_offset (old_region, -dx + private->abs_x - private->x, -dy + private->abs_y - private->y);
+
+      /* convert from parent coords to impl */
+      gdk_region_offset (copy_area, private->abs_x - private->x, private->abs_y - private->y);
+
+      move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
+
+      /* Invalidate affected part in the parent window
+       *  (no higher window should be affected)
+       * We also invalidate any children in that area, which could include
+       * this window if it still overlaps that area.
+       */
+      gdk_window_invalidate_region (GDK_WINDOW (private->parent), new_region, TRUE);
+
+      gdk_region_destroy (old_region);
+      gdk_region_destroy (new_region);
     }
-  
-  if (private->paint_stack)
-    {
-      GdkWindowPaint *paint = private->paint_stack->data;
 
-      gdk_draw_glyphs_transformed (paint->pixmap, gc, matrix, font, x, y, glyphs);
+  if (old_native_child_region)
+    {
+      gdk_region_destroy (old_native_child_region);
+      gdk_region_destroy (new_native_child_region);
     }
-  else
-    gdk_draw_glyphs_transformed (private->impl, gc, matrix, font, x, y, glyphs);
 
-  RESTORE_GC (gc);
+  _gdk_syntesize_crossing_events_for_geometry_change (window);
 }
 
-typedef struct {
-  cairo_t *cr; /* if non-null, it means use this cairo context */
-  GdkGC *gc;   /* if non-null, it means use this GC instead */
-} BackingRectMethod;
 
-static void
-setup_backing_rect_method (BackingRectMethod *method, GdkWindow *window, GdkWindowPaint *paint, int x_offset_cairo, int y_offset_cairo)
+
+/**
+ * gdk_window_move:
+ * @window: a #GdkWindow
+ * @x: X coordinate relative to window's parent
+ * @y: Y coordinate relative to window's parent
+ *
+ * Repositions a window relative to its parent window.
+ * For toplevel windows, window managers may ignore or modify the move;
+ * you should probably use gtk_window_move() on a #GtkWindow widget
+ * anyway, instead of using GDK functions. For child windows,
+ * the move will reliably succeed.
+ *
+ * If you're also planning to resize the window, use gdk_window_move_resize()
+ * to both move and resize simultaneously, for a nicer visual effect.
+ **/
+void
+gdk_window_move (GdkWindow *window,
+                gint       x,
+                gint       y)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
+  gdk_window_move_resize_internal (window, TRUE, x, y, -1, -1);
+}
+
+/**
+ * gdk_window_resize:
+ * @window: a #GdkWindow
+ * @width: new width of the window
+ * @height: new height of the window
+ *
+ * Resizes @window; for toplevel windows, asks the window manager to resize
+ * the window. The window manager may not allow the resize. When using GTK+,
+ * use gtk_window_resize() instead of this low-level GDK function.
+ *
+ * Windows may not be resized below 1x1.
+ *
+ * If you're also planning to move the window, use gdk_window_move_resize()
+ * to both move and resize simultaneously, for a nicer visual effect.
+ **/
+void
+gdk_window_resize (GdkWindow *window,
+                  gint       width,
+                  gint       height)
+{
+  gdk_window_move_resize_internal (window, FALSE, 0, 0, width, height);
+}
+
+
+/**
+ * gdk_window_move_resize:
+ * @window: a #GdkWindow
+ * @x: new X position relative to window's parent
+ * @y: new Y position relative to window's parent
+ * @width: new width
+ * @height: new height
+ *
+ * Equivalent to calling gdk_window_move() and gdk_window_resize(),
+ * except that both operations are performed at once, avoiding strange
+ * visual effects. (i.e. the user may be able to see the window first
+ * move, then resize, if you don't use gdk_window_move_resize().)
+ **/
+void
+gdk_window_move_resize (GdkWindow *window,
+                       gint       x,
+                       gint       y,
+                       gint       width,
+                       gint       height)
+{
+  gdk_window_move_resize_internal (window, TRUE, x, y, width, height);
+}
+
+
+/**
+ * gdk_window_scroll:
+ * @window: a #GdkWindow
+ * @dx: Amount to scroll in the X direction
+ * @dy: Amount to scroll in the Y direction
+ *
+ * Scroll the contents of @window, both pixels and children, by the
+ * given amount. @window itself does not move. Portions of the window
+ * that the scroll operation brings in from offscreen areas are
+ * invalidated. The invalidated region may be bigger than what would
+ * strictly be necessary.
+ *
+ * For X11, a minimum area will be invalidated if the window has no
+ * subwindows, or if the edges of the window's parent do not extend
+ * beyond the edges of the window. In other cases, a multi-step process
+ * is used to scroll the window which may produce temporary visual
+ * artifacts and unnecessary invalidations.
+ **/
+void
+gdk_window_scroll (GdkWindow *window,
+                  gint       dx,
+                  gint       dy)
+{
+  GdkWindowObject *private = (GdkWindowObject *) window;
+  GdkWindowObject *impl_window;
+  GdkRegion *copy_area, *noncopy_area;
+  GdkRegion *old_native_child_region, *new_native_child_region;
+  GList *tmp_list;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  if (dx == 0 && dy == 0)
+    return;
 
-  if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
+  if (private->destroyed)
+    return;
+
+  old_native_child_region = collect_native_child_region (private, FALSE);
+  if (old_native_child_region)
     {
-      GdkWindowPaint tmp_paint;
+      /* 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
+       * to flush those here for the window and all overlapped subwindows
+       * of it. And we need to do this before setting the new clips as those will be
+       * affecting this.
+       */
+      gdk_window_flush_recursive (private);
+    }
 
-      tmp_paint = *paint;
-      tmp_paint.x_offset += private->x;
-      tmp_paint.y_offset += private->y;
 
-      x_offset_cairo += private->x;
-      y_offset_cairo += private->y;
+  /* First move all child windows, without causing invalidation */
 
-      setup_backing_rect_method (method, GDK_WINDOW (private->parent), &tmp_paint, x_offset_cairo, y_offset_cairo);
-    }
-  else if (private->bg_pixmap &&
-          private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
-          private->bg_pixmap != GDK_NO_BG)
+  tmp_list = private->children;
+  while (tmp_list)
     {
-/* This is a workaround for https://bugs.freedesktop.org/show_bug.cgi?id=4320.
- * In it, using a pixmap as a repeating pattern in Cairo, and painting it to a
- * pixmap destination surface, can be very slow (on the order of seconds for a
- * whole-screen copy).  The workaround is to use pretty much the same code that
- * we used in GTK+ 2.6 (pre-Cairo), which clears the double-buffer pixmap with
- * a tiled GC XFillRectangle().
- */
-
-/* Actually computing this flag is left as an exercise for the reader */
-#if defined (G_OS_UNIX)
-#  define GDK_CAIRO_REPEAT_IS_FAST 0
-#else
-#  define GDK_CAIRO_REPEAT_IS_FAST 1
-#endif
+      GdkWindow *child = GDK_WINDOW (tmp_list->data);
+      GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
 
-#if GDK_CAIRO_REPEAT_IS_FAST
-      cairo_surface_t *surface = _gdk_drawable_ref_cairo_surface (private->bg_pixmap);
-      cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
-      cairo_surface_destroy (surface);
+      /* Just update the positions, the bits will move with the copy */
+      child_obj->x += dx;
+      child_obj->y += dy;
 
-      if (x_offset_cairo != 0 || y_offset_cairo != 0)
-       {
-         cairo_matrix_t matrix;
-         cairo_matrix_init_translate (&matrix, x_offset_cairo, y_offset_cairo);
-         cairo_pattern_set_matrix (pattern, &matrix);
-       }
+      tmp_list = tmp_list->next;
+    }
 
-      cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
+  recompute_visible_regions (private, FALSE, TRUE);
 
-      method->cr = cairo_create (paint->surface);
-      method->gc = NULL;
+  new_native_child_region = NULL;
+  if (old_native_child_region)
+    new_native_child_region = collect_native_child_region (private, FALSE);
 
-      cairo_set_source (method->cr, pattern);
-      cairo_pattern_destroy (pattern);
-#else
-      guint gc_mask;
-      GdkGCValues gc_values;
+  move_native_children (private);
 
-      gc_values.fill = GDK_TILED;
-      gc_values.tile = private->bg_pixmap;
-      gc_values.ts_x_origin = -x_offset_cairo;
-      gc_values.ts_y_origin = -y_offset_cairo;
+  /* Then copy the actual bits of the window w/ child windows */
 
-      gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN;
+  impl_window = gdk_window_get_impl_window (private);
 
-      method->gc = gdk_gc_new_with_values (paint->pixmap, &gc_values, gc_mask);
-#endif
-    }
-  else
+  /* Calculate the area that can be gotten by copying the old area */
+  copy_area = gdk_region_copy (private->clip_region);
+  if (old_native_child_region)
     {
-      method->cr = cairo_create (paint->surface);
-
-      gdk_cairo_set_source_color (method->cr, &private->bg_color);
+      /* Don't copy from inside native children, as this is copied by
+       * the native window move.
+       */
+      gdk_region_subtract (copy_area, old_native_child_region);
+
+      /* Don't copy any bits that would cause a read from the moved
+        native windows, as we can't read that data */
+      gdk_region_subtract (copy_area, new_native_child_region);
     }
-}
-
-static void
-gdk_window_clear_backing_rect (GdkWindow *window,
-                              gint       x,
-                              gint       y,
-                              gint       width,
-                              gint       height)
-{
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkWindowPaint *paint = private->paint_stack->data;
-  BackingRectMethod method;
-#if 0
-  GTimer *timer;
-  double elapsed;
-#endif
-
-  if (GDK_WINDOW_DESTROYED (window))
-    return;
+  gdk_region_offset (copy_area, dx, dy);
+  gdk_region_intersect (copy_area, private->clip_region);
 
-#if 0
-  timer = g_timer_new ();
-#endif
+  /* And the rest need to be invalidated */
+  noncopy_area = gdk_region_copy (private->clip_region);
+  gdk_region_subtract (noncopy_area, copy_area);
 
-  method.cr = NULL;
-  method.gc = NULL;
-  setup_backing_rect_method (&method, window, paint, 0, 0);
+  /* convert from window coords to impl */
+  gdk_region_offset (copy_area, private->abs_x, private->abs_y);
 
-  if (method.cr)
-    {
-      g_assert (method.gc == NULL);
+  move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
 
-      cairo_rectangle (method.cr, x, y, width, height);
-      cairo_clip (method.cr);
+  /* Invalidate not copied regions */
+  gdk_window_invalidate_region (window, noncopy_area, TRUE);
 
-      gdk_cairo_region (method.cr, paint->region);
-      cairo_fill (method.cr);
+  gdk_region_destroy (noncopy_area);
 
-      cairo_destroy (method.cr);
-#if 0
-      elapsed = g_timer_elapsed (timer, NULL);
-      g_print ("Draw the background with Cairo: %fs\n", elapsed);
-#endif
-    }
-  else
+  if (old_native_child_region)
     {
-      g_assert (method.gc != NULL);
-
-      gdk_gc_set_clip_region (method.gc, paint->region);
-      gdk_draw_rectangle (window, method.gc, TRUE, x, y, width, height);
-      g_object_unref (method.gc);
-
-#if 0
-      elapsed = g_timer_elapsed (timer, NULL);
-      g_print ("Draw the background with GDK: %fs\n", elapsed);
-#endif
+      gdk_region_destroy (old_native_child_region);
+      gdk_region_destroy (new_native_child_region);
     }
 
-#if 0
-  g_timer_destroy (timer);
-#endif
+  _gdk_syntesize_crossing_events_for_geometry_change (window);
 }
 
-static void
-gdk_window_clear_backing_rect_redirect (GdkWindow *window,
-                                       gint       x,
-                                       gint       y,
-                                       gint       width,
-                                       gint       height)
+/**
+ * gdk_window_move_region:
+ * @window: a #GdkWindow
+ * @region: The #GdkRegion to move
+ * @dx: Amount to move in the X direction
+ * @dy: Amount to move in the Y direction
+ *
+ * Move the part of @window indicated by @region by @dy pixels in the Y
+ * direction and @dx pixels in the X direction. The portions of @region
+ * that not covered by the new position of @region are invalidated.
+ *
+ * Child windows are not moved.
+ *
+ * Since: 2.8
+ */
+void
+gdk_window_move_region (GdkWindow       *window,
+                       const GdkRegion *region,
+                       gint             dx,
+                       gint             dy)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkWindowRedirect *redirect = private->redirect;
-  GdkRegion *clip_region;
-  gint x_offset, y_offset;
-  BackingRectMethod method;
-  GdkWindowPaint paint;
-  
-  if (GDK_WINDOW_DESTROYED (window))
-    return;
-
-  paint.x_offset = 0;
-  paint.y_offset = 0;
-  paint.pixmap = redirect->pixmap;
-  paint.surface = _gdk_drawable_ref_cairo_surface (redirect->pixmap);
-  
-  clip_region = _gdk_window_calculate_full_clip_region (window,
-                                                       GDK_WINDOW (redirect->redirected),
-                                                       NULL, TRUE,
-                                                       &x_offset, &y_offset);
-  /* offset is from redirected window origin to window origin, convert to
-     the offset from the redirected pixmap origin to the window origin */
-  x_offset += redirect->dest_x - redirect->src_x;
-  y_offset += redirect->dest_y - redirect->src_y;
+  GdkWindowObject *private = (GdkWindowObject *) window;
+  GdkWindowObject *impl_window;
+  GdkRegion *nocopy_area;
+  GdkRegion *copy_area;
 
-  /* Convert region and rect to pixmap coords */
-  gdk_region_offset (clip_region, x_offset, y_offset);
-  x += x_offset;
-  y += y_offset;
+  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (region != NULL);
 
-  method.cr = NULL;
-  method.gc = NULL;
-  setup_backing_rect_method (&method, window, &paint, -x_offset, -y_offset);
+  if (dx == 0 && dy == 0)
+    return;
 
-  if (method.cr)
-    {
-      g_assert (method.gc == NULL);
+  if (private->destroyed)
+    return;
 
-      cairo_rectangle (method.cr, x, y, width, height);
-      cairo_clip (method.cr);
+  impl_window = gdk_window_get_impl_window (private);
 
-      gdk_cairo_region (method.cr, clip_region);
-      cairo_fill (method.cr);
+  /* compute source regions */
+  copy_area = gdk_region_copy (region);
+  gdk_region_intersect (copy_area, private->clip_region_with_children);
 
-      cairo_destroy (method.cr);
-    }
-  else
-    {
-      g_assert (method.gc != NULL);
+  /* compute destination regions */
+  gdk_region_offset (copy_area, dx, dy);
+  gdk_region_intersect (copy_area, private->clip_region_with_children);
 
-      gdk_gc_set_clip_region (method.gc, clip_region);
-      gdk_draw_rectangle (redirect->pixmap, method.gc, TRUE, x, y, width, height);
-      g_object_unref (method.gc);
+  /* invalidate parts of the region not covered by the copy */
+  nocopy_area = gdk_region_copy (region);
+  gdk_region_offset (nocopy_area, dx, dy);
+  gdk_region_subtract (nocopy_area, copy_area);
+  gdk_window_invalidate_region (window, nocopy_area, FALSE);
+  gdk_region_destroy (nocopy_area);
 
-    }
+  /* convert from window coords to impl */
+  gdk_region_offset (copy_area, private->abs_x, private->abs_y);
 
-  gdk_region_destroy (clip_region);
-  cairo_surface_destroy (paint.surface);
+  move_region_on_impl (impl_window, copy_area, dx, dy); /* Takes ownership of copy_area */
 }
 
-
 /**
- * gdk_window_clear:
+ * gdk_window_set_background:
  * @window: a #GdkWindow
- * 
- * Clears an entire @window to the background color or background pixmap.
- **/
+ * @color: an allocated #GdkColor
+ *
+ * Sets the background color of @window. (However, when using GTK+,
+ * set the background of a widget with gtk_widget_modify_bg() - if
+ * you're an application - or gtk_style_set_background() - if you're
+ * implementing a custom widget.)
+ *
+ * The @color must be allocated; gdk_rgb_find_color() is the best way
+ * to allocate a color.
+ *
+ * See also gdk_window_set_back_pixmap().
+ */
 void
-gdk_window_clear (GdkWindow *window)
+gdk_window_set_background (GdkWindow      *window,
+                          const GdkColor *color)
 {
-  gint width, height;
+  GdkWindowObject *private;
+  GdkColormap *colormap = gdk_drawable_get_colormap (window);
 
   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);
+  private = (GdkWindowObject *) window;
+
+  private->bg_color = *color;
+  gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
+
+  if (private->bg_pixmap &&
+      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+      private->bg_pixmap != GDK_NO_BG)
+    g_object_unref (private->bg_pixmap);
+
+  private->bg_pixmap = NULL;
+
+  if (!GDK_WINDOW_DESTROYED (window) &&
+      gdk_window_has_impl (private) &&
+      !private->input_only)
+    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, &private->bg_color);
 }
 
 /**
- * gdk_window_clear_area:
+ * gdk_window_set_back_pixmap:
  * @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
+ * @pixmap: a #GdkPixmap, or %NULL
+ * @parent_relative: whether the tiling origin is at the origin of
+ *   @window's parent
  *
- * Clears an area of @window to the background color or background pixmap.
- * 
- **/
+ * Sets the background pixmap of @window. May also be used to set a
+ * background of "None" on @window, by setting a background pixmap
+ * of %NULL.
+ *
+ * A background pixmap will be tiled, positioning the first tile at
+ * the origin of @window, or if @parent_relative is %TRUE, the tiling
+ * will be done based on the origin of the parent window (useful to
+ * align tiles in a parent with tiles in a child).
+ *
+ * A background pixmap of %NULL means that the window will have no
+ * background.  A window with no background will never have its
+ * background filled by the windowing system, instead the window will
+ * contain whatever pixels were already in the corresponding area of
+ * the display.
+ *
+ * The windowing system will normally fill a window with its background
+ * when the window is obscured then exposed, and when you call
+ * gdk_window_clear().
+ */
 void
-gdk_window_clear_area (GdkWindow *window,
-                      gint       x,
-                      gint       y,
-                      gint       width,
-                      gint       height)
+gdk_window_set_back_pixmap (GdkWindow *window,
+                           GdkPixmap *pixmap,
+                           gboolean   parent_relative)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *private;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (pixmap == NULL || !parent_relative);
+  g_return_if_fail (pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap));
 
-  if (private->paint_stack)
-    gdk_window_clear_backing_rect (window, x, y, width, height);
-  else
+  private = (GdkWindowObject *) window;
+
+  if (pixmap && !gdk_drawable_get_colormap (pixmap))
     {
-      if (private->redirect)
-       gdk_window_clear_backing_rect_redirect (window, x, y, width, height);
+      g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
+      return;
+    }
+
+  if (private->bg_pixmap &&
+      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+      private->bg_pixmap != GDK_NO_BG)
+    g_object_unref (private->bg_pixmap);
+
+  if (parent_relative)
+    private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
+  else if (pixmap)
+    private->bg_pixmap = g_object_ref (pixmap);
+  else
+    private->bg_pixmap = GDK_NO_BG;
 
-      GDK_WINDOW_IMPL_GET_IFACE (private->impl)->clear_area (window,
-                                                             x, y,
-                                                             width, height,
-                                                             FALSE);
-    }
+  if (!GDK_WINDOW_DESTROYED (window) &&
+      gdk_window_has_impl (private) &&
+      !private->input_only)
+    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, private->bg_pixmap);
 }
 
 /**
- * gdk_window_clear_area_e:
+ * gdk_window_set_cursor:
  * @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
- *
- * Like gdk_window_clear_area(), but also generates an expose event for
- * the cleared area.
+ * @cursor: a cursor
  *
- * This function has a stupid name because it dates back to the mists
- * time, pre-GDK-1.0.
- * 
- **/
+ * Sets the mouse pointer for a #GdkWindow. Use gdk_cursor_new_for_display()
+ * or gdk_cursor_new_from_pixmap() to create the cursor. To make the cursor
+ * invisible, use %GDK_BLANK_CURSOR. Passing %NULL for the @cursor argument
+ * to gdk_window_set_cursor() means that @window will use the cursor of its
+ * parent window. Most windows should use this default.
+ */
 void
-gdk_window_clear_area_e (GdkWindow *window,
-                        gint       x,
-                        gint       y,
-                        gint       width,
-                        gint       height)
+gdk_window_set_cursor (GdkWindow *window,
+                      GdkCursor *cursor)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *private;
+  GdkDisplay *display;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  if (private->paint_stack)
-    gdk_window_clear_backing_rect (window, x, y, width, height);
-
-  if (private->redirect)
-    gdk_window_clear_backing_rect_redirect (window, x, y, width, height);
-
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->clear_area (window,
-                                                         x, y,
-                                                         width, height,
-                                                         TRUE);
-}
-
-static void
-gdk_window_draw_image (GdkDrawable *drawable,
-                       GdkGC       *gc,
-                       GdkImage    *image,
-                       gint         xsrc,
-                       gint         ysrc,
-                       gint         xdest,
-                       gint         ydest,
-                       gint         width,
-                       gint         height)
-{
-  GdkWindowObject *private = (GdkWindowObject *)drawable;
+  private = (GdkWindowObject *) window;
+  display = gdk_drawable_get_display (window);
 
-  OFFSET_GC (gc);
+  if (private->cursor)
+    {
+      gdk_cursor_unref (private->cursor);
+      private->cursor = NULL;
+    }
 
-  if (GDK_WINDOW_DESTROYED (drawable))
-    return;
-  
-  if (private->paint_stack)
+  if (!GDK_WINDOW_DESTROYED (window))
     {
-      GdkWindowPaint *paint = private->paint_stack->data;
-      gdk_draw_image (paint->pixmap, gc, image, xsrc, ysrc,
-                      xdest - x_offset, ydest - y_offset,
-                      width, height);
+      if (cursor)
+       private->cursor = gdk_cursor_ref (cursor);
 
+      if (is_event_parent_of (window, display->pointer_info.window_under_pointer))
+       update_cursor (display);
     }
-  else
-    gdk_draw_image (private->impl, gc, image, xsrc, ysrc,
-                    xdest - x_offset, ydest - y_offset,
-                    width, height);
-
-  RESTORE_GC (gc);
 }
 
-static void
-gdk_window_draw_pixbuf (GdkDrawable     *drawable,
-                       GdkGC           *gc,
-                       GdkPixbuf       *pixbuf,
-                       gint             src_x,
-                       gint             src_y,
-                       gint             dest_x,
-                       gint             dest_y,
-                       gint             width,
-                       gint             height,
-                       GdkRgbDither     dither,
-                       gint             x_dither,
-                       gint             y_dither)
+/**
+ * gdk_window_get_geometry:
+ * @window: a #GdkWindow
+ * @x: return location for X coordinate of window (relative to its parent)
+ * @y: return location for Y coordinate of window (relative to its parent)
+ * @width: return location for width of window
+ * @height: return location for height of window
+ * @depth: return location for bit depth of window
+ *
+ * Any of the return location arguments to this function may be %NULL,
+ * if you aren't interested in getting the value of that field.
+ *
+ * The X and Y coordinates returned are relative to the parent window
+ * of @window, which for toplevels usually means relative to the
+ * window decorations (titlebar, etc.) rather than relative to the
+ * root window (screen-size background window).
+ *
+ * On the X11 platform, the geometry is obtained from the X server,
+ * so reflects the latest position of @window; this may be out-of-sync
+ * with the position of @window delivered in the most-recently-processed
+ * #GdkEventConfigure. gdk_window_get_position() in contrast gets the
+ * position from the most recent configure event.
+ *
+ * <note>
+ * If @window is not a toplevel, it is <emphasis>much</emphasis> better
+ * to call gdk_window_get_position() and gdk_drawable_get_size() instead,
+ * because it avoids the roundtrip to the X server and because
+ * gdk_drawable_get_size() supports the full 32-bit coordinate space,
+ * whereas gdk_window_get_geometry() is restricted to the 16-bit
+ * coordinates of X11.
+ *</note>
+ **/
+void
+gdk_window_get_geometry (GdkWindow *window,
+                        gint      *x,
+                        gint      *y,
+                        gint      *width,
+                        gint      *height,
+                        gint      *depth)
 {
-  GdkWindowObject *private = (GdkWindowObject *)drawable;
+  GdkWindowObject *private;
 
-  if (GDK_WINDOW_DESTROYED (drawable))
-    return;
-  
-  if (gc)
-    {
-      OFFSET_GC (gc);
-  
-      if (private->paint_stack)
-       {
-         GdkWindowPaint *paint = private->paint_stack->data;
-         gdk_draw_pixbuf (paint->pixmap, gc, pixbuf, src_x, src_y,
-                          dest_x - x_offset, dest_y - y_offset,
-                          width, height,
-                          dither, x_dither - x_offset, y_dither - y_offset);
-       }
-      else
-       gdk_draw_pixbuf (private->impl, gc, pixbuf, src_x, src_y,
-                        dest_x - x_offset, dest_y - y_offset,
-                        width, height,
-                        dither, x_dither, y_dither);
-      
-      RESTORE_GC (gc);
-    }
-  else
+  if (!window)
     {
-      gint x_offset, y_offset;
-      gdk_window_get_offsets (drawable, &x_offset, &y_offset);
-      
-      if (private->paint_stack)
-       {
-         GdkWindowPaint *paint = private->paint_stack->data;
-         gdk_draw_pixbuf (paint->pixmap, gc, pixbuf, src_x, src_y,
-                          dest_x - x_offset, dest_y - y_offset,
-                          width, height,
-                           dither, x_dither - x_offset, y_dither - y_offset);
-       }
-      else
-       gdk_draw_pixbuf (private->impl, gc, pixbuf, src_x, src_y,
-                        dest_x - x_offset, dest_y - y_offset,
-                        width, height,
-                        dither, x_dither, y_dither);
+      GDK_NOTE (MULTIHEAD,
+               g_message ("gdk_window_get_geometry(): Window needs "
+                          "to be non-NULL to be multi head safe"));
+      window = gdk_screen_get_root_window ((gdk_screen_get_default ()));
     }
-}
 
-static void
-gdk_window_draw_trapezoids (GdkDrawable   *drawable,
-                           GdkGC         *gc,
-                           GdkTrapezoid  *trapezoids,
-                           gint           n_trapezoids)
-{
-  GdkWindowObject *private = (GdkWindowObject *)drawable;
-  GdkTrapezoid *new_trapezoids = NULL;
+  g_return_if_fail (GDK_IS_WINDOW (window));
 
-  OFFSET_GC (gc);
+  private = (GdkWindowObject *) window;
 
-  if (GDK_WINDOW_DESTROYED (drawable))
-    return;
-  
-  if (x_offset != 0 || y_offset != 0)
+  if (!GDK_WINDOW_DESTROYED (window))
     {
-      gint i;
-
-      new_trapezoids = g_new (GdkTrapezoid, n_trapezoids);
-      for (i=0; i < n_trapezoids; i++)
+      if (gdk_window_has_impl (private))
+       GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_geometry (window, x, y,
+                                                                width, height,
+                                                                depth);
+      else
        {
-         new_trapezoids[i].y1 = trapezoids[i].y1 - y_offset;
-         new_trapezoids[i].x11 = trapezoids[i].x11 - x_offset;
-         new_trapezoids[i].x21 = trapezoids[i].x21 - x_offset;
-         new_trapezoids[i].y2 = trapezoids[i].y2 - y_offset;
-         new_trapezoids[i].x12 = trapezoids[i].x12 - x_offset;
-         new_trapezoids[i].x22 = trapezoids[i].x22 - x_offset;
+         if (x)
+           *x = private->x;
+         if (y)
+           *y = private->y;
+         if (width)
+           *width = private->width;
+         if (height)
+           *height = private->height;
+         if (depth)
+           *depth = private->depth;
        }
-
-      trapezoids = new_trapezoids;
-    }
-
-  if (private->paint_stack)
-    {
-      GdkWindowPaint *paint = private->paint_stack->data;
-      gdk_draw_trapezoids (paint->pixmap, gc, trapezoids, n_trapezoids);
     }
-  else
-    gdk_draw_trapezoids (private->impl, gc, trapezoids, n_trapezoids);
-  
-  g_free (new_trapezoids);
-
-  RESTORE_GC (gc);
-}
-
-static void
-gdk_window_real_get_size (GdkDrawable *drawable,
-                          gint *width,
-                          gint *height)
-{
-  g_return_if_fail (GDK_IS_WINDOW (drawable));
-
-  gdk_drawable_get_size (GDK_WINDOW_OBJECT (drawable)->impl,
-                         width, height);
 }
 
-static GdkVisual*
-gdk_window_real_get_visual (GdkDrawable *drawable)
+/**
+ * gdk_window_get_origin:
+ * @window: a #GdkWindow
+ * @x: return location for X coordinate
+ * @y: return location for Y coordinate
+ *
+ * Obtains the position of a window in root window coordinates.
+ * (Compare with gdk_window_get_position() and
+ * gdk_window_get_geometry() which return the position of a window
+ * relative to its parent window.)
+ *
+ * Return value: not meaningful, ignore
+ */
+gint
+gdk_window_get_origin (GdkWindow *window,
+                      gint      *x,
+                      gint      *y)
 {
-  GdkColormap *colormap;
+  GdkWindowObject *private;
 
-  g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
+  g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
 
-  colormap = gdk_drawable_get_colormap (drawable);
-  return colormap ? gdk_colormap_get_visual (colormap) : NULL;
-}
+  private = (GdkWindowObject *) window;
 
-static gint
-gdk_window_real_get_depth (GdkDrawable *drawable)
-{
-  g_return_val_if_fail (GDK_IS_WINDOW (drawable), 0);
+  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_root_coords (window,
+                                                             private->abs_x,
+                                                             private->abs_y,
+                                                             x, y);
 
-  return ((GdkWindowObject *)GDK_WINDOW (drawable))->depth;
+  return TRUE;
 }
 
-static GdkScreen*
-gdk_window_real_get_screen (GdkDrawable *drawable)
+/**
+ * gdk_window_get_root_coords:
+ * @window: a #GdkWindow
+ * @x: X coordinate in window
+ * @y: Y coordinate in window
+ * @root_x: return location for X coordinate
+ * @root_y: return location for Y coordinate
+ *
+ * Obtains the position of a window position in root
+ * window coordinates. This is similar to
+ * gdk_window_get_origin() but allows you go pass
+ * in any position in the window, not just the origin.
+ *
+ * Return value: not meaningful, ignore
+ */
+gint
+gdk_window_get_root_coords (GdkWindow *window,
+                           gint       x,
+                           gint       y,
+                           gint      *root_x,
+                           gint      *root_y)
 {
-  return gdk_drawable_get_screen (GDK_WINDOW_OBJECT (drawable)->impl);
-}
+  GdkWindowObject *private;
 
-static void
-gdk_window_real_set_colormap (GdkDrawable *drawable,
-                              GdkColormap *cmap)
-{
-  g_return_if_fail (GDK_IS_WINDOW (drawable));  
+  g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
 
-  if (GDK_WINDOW_DESTROYED (drawable))
-    return;
-  
-  gdk_drawable_set_colormap (((GdkWindowObject*)drawable)->impl, cmap);
-}
+  private = (GdkWindowObject *) window;
 
-static GdkColormap*
-gdk_window_real_get_colormap (GdkDrawable *drawable)
-{
-  g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
+  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_root_coords (window,
+                                                             x + private->abs_x,
+                                                             y + private->abs_y,
+                                                             root_x, root_y);
 
-  if (GDK_WINDOW_DESTROYED (drawable))
-    return NULL;
-  
-  return gdk_drawable_get_colormap (((GdkWindowObject*)drawable)->impl);
+  return TRUE;
 }
-                      
-static GdkImage*
-gdk_window_copy_to_image (GdkDrawable     *drawable,
-                         GdkImage        *image,
-                         gint             src_x,
-                         gint             src_y,
-                         gint             dest_x,
-                         gint             dest_y,
-                         gint             width,
-                         gint             height)
-{
-  GdkWindowObject *private = (GdkWindowObject *) drawable;
-  gint x_offset, y_offset;
-  
-  g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
-  
-  if (GDK_WINDOW_DESTROYED (drawable))
-    return NULL;
 
-  /* If we're here, a composite image was not necessary, so
-   * we can ignore the paint stack.
-   */
-  
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (drawable,
-                                                          &x_offset, &y_offset);
-  
-  return gdk_drawable_copy_to_image (private->impl,
-                                    image,
-                                    src_x - x_offset,
-                                    src_y - y_offset,
-                                    dest_x, dest_y,
-                                    width, height);
-}
 
-static cairo_surface_t *
-gdk_window_ref_cairo_surface (GdkDrawable *drawable)
+/**
+ * gdk_window_get_deskrelative_origin:
+ * @window: a toplevel #GdkWindow
+ * @x: return location for X coordinate
+ * @y: return location for Y coordinate
+ *
+ * This gets the origin of a #GdkWindow relative to
+ * an Enlightenment-window-manager desktop. As long as you don't
+ * assume that the user's desktop/workspace covers the entire
+ * root window (i.e. you don't assume that the desktop begins
+ * at root window coordinate 0,0) this function is not necessary.
+ * It's deprecated for that reason.
+ *
+ * Return value: not meaningful
+ **/
+gboolean
+gdk_window_get_deskrelative_origin (GdkWindow *window,
+                                   gint      *x,
+                                   gint      *y)
 {
-  GdkWindowObject *private = (GdkWindowObject*) drawable;
-  cairo_surface_t *surface;
+  GdkWindowObject *private;
+  gboolean return_val = FALSE;
+  gint tx = 0;
+  gint ty = 0;
 
-  if (private->paint_stack)
+  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+
+  private = (GdkWindowObject *) window;
+
+  if (!GDK_WINDOW_DESTROYED (window))
     {
-      GdkWindowPaint *paint = private->paint_stack->data;
+      return_val = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_deskrelative_origin (window, &tx, &ty);
 
-      surface = paint->surface;
-      cairo_surface_reference (surface);
+      if (x)
+       *x = tx + private->abs_x;
+      if (y)
+       *y = ty + private->abs_y;
     }
-  else
-    surface = _gdk_drawable_ref_cairo_surface (private->impl);
 
-  return surface;
+  return return_val;
 }
 
-/* Code for dirty-region queueing
+/**
+ * gdk_window_shape_combine_mask:
+ * @window: a #GdkWindow
+ * @mask: shape mask
+ * @x: X position of shape mask with respect to @window
+ * @y: Y position of shape mask with respect to @window
+ *
+ * Applies a shape mask to @window. Pixels in @window corresponding to
+ * set bits in the @mask will be visible; pixels in @window
+ * corresponding to unset bits in the @mask will be transparent. This
+ * gives a non-rectangular window.
+ *
+ * If @mask is %NULL, the shape mask will be unset, and the @x/@y
+ * parameters are not used.
+ *
+ * On the X11 platform, this uses an X server extension which is
+ * widely available on most common platforms, but not available on
+ * very old X servers, and occasionally the implementation will be
+ * buggy. On servers without the shape extension, this function
+ * will do nothing.
+ *
+ * This function works on both toplevel and child windows.
  */
-static GSList *update_windows = NULL;
-static guint update_idle = 0;
-static gboolean debug_updates = FALSE;
-
-static gboolean
-gdk_window_update_idle (gpointer data)
+void
+gdk_window_shape_combine_mask (GdkWindow *window,
+                              GdkBitmap *mask,
+                              gint       x,
+                              gint       y)
 {
-  gdk_window_process_all_updates ();
-  
-  return FALSE;
-}
+  GdkWindowObject *private;
+  GdkRegion *region;
 
-static gboolean
-gdk_window_is_toplevel_frozen (GdkWindow *window)
-{
-  GdkWindowObject *toplevel;
+  g_return_if_fail (GDK_IS_WINDOW (window));
 
-  toplevel = (GdkWindowObject *)gdk_window_get_toplevel (window);
+  private = (GdkWindowObject *) window;
 
-  return toplevel->update_and_descendants_freeze_count > 0;
+  if (mask)
+    region = _gdk_windowing_get_shape_for_mask (mask);
+  else
+    region = NULL;
+
+  gdk_window_shape_combine_region (window,
+                                  region,
+                                  x, y);
+
+  if (region)
+    gdk_region_destroy (region);
 }
 
-static void
-gdk_window_schedule_update (GdkWindow *window)
+/**
+ * gdk_window_shape_combine_region:
+ * @window: a #GdkWindow
+ * @shape_region: region of window to be non-transparent
+ * @offset_x: X position of @shape_region in @window coordinates
+ * @offset_y: Y position of @shape_region in @window coordinates
+ *
+ * Makes pixels in @window outside @shape_region be transparent,
+ * so that the window may be nonrectangular. See also
+ * gdk_window_shape_combine_mask() to use a bitmap as the mask.
+ *
+ * If @shape_region is %NULL, the shape will be unset, so the whole
+ * window will be opaque again. @offset_x and @offset_y are ignored
+ * if @shape_region is %NULL.
+ *
+ * On the X11 platform, this uses an X server extension which is
+ * widely available on most common platforms, but not available on
+ * very old X servers, and occasionally the implementation will be
+ * buggy. On servers without the shape extension, this function
+ * will do nothing.
+ *
+ * This function works on both toplevel and child windows.
+ */
+void
+gdk_window_shape_combine_region (GdkWindow       *window,
+                                const GdkRegion *shape_region,
+                                gint             offset_x,
+                                gint             offset_y)
 {
-  if (window &&
-      (GDK_WINDOW_OBJECT (window)->update_freeze_count ||
-       gdk_window_is_toplevel_frozen (window)))
+  GdkWindowObject *private;
+  GdkRegion *old_region, *new_region, *diff;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *) window;
+
+  if (GDK_WINDOW_DESTROYED (window))
     return;
 
-  if (!update_idle)
+  private->shaped = (shape_region != NULL);
+
+  if (private->shape)
+    gdk_region_destroy (private->shape);
+
+  old_region = NULL;
+  if (GDK_WINDOW_IS_MAPPED (window))
+    old_region = gdk_region_copy (private->clip_region);
+
+  if (shape_region)
     {
-      update_idle = gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
-                                    gdk_window_update_idle, NULL, NULL);
+      private->shape = gdk_region_copy (shape_region);
+      gdk_region_offset (private->shape, offset_x, offset_y);
     }
-}
+  else
+    private->shape = NULL;
 
-static void
-gdk_window_process_updates_internal (GdkWindow *window)
-{
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  gboolean save_region = FALSE;
+  recompute_visible_regions (private, TRUE, FALSE);
 
-  /* 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.
-   */
-  if (private->update_area)
+  if (old_region)
     {
-      GdkRegion *update_area = private->update_area;
-      private->update_area = NULL;
-      
-      if (_gdk_event_func && gdk_window_is_viewable (window))
-       {
-         GdkRectangle window_rect;
-         GdkRegion *expose_region;
-         GdkRegion *window_region;
-          gint width, height;
+      new_region = gdk_region_copy (private->clip_region);
 
-          if (debug_updates)
-            {
-              /* Make sure we see the red invalid area before redrawing. */
-              gdk_display_sync (gdk_drawable_get_display (window));
-              g_usleep (70000);
-            }
-          
-         save_region = _gdk_windowing_window_queue_antiexpose (window, update_area);
+      /* New area in the window, needs invalidation */
+      diff = gdk_region_copy (new_region);
+      gdk_region_subtract (diff, old_region);
 
-         if (save_region)
-           expose_region = gdk_region_copy (update_area);
-         else
-           expose_region = update_area;
-         
-          gdk_drawable_get_size (GDK_DRAWABLE (private), &width, &height);
+      gdk_window_invalidate_region (window, diff, TRUE);
 
-         window_rect.x = 0;
-         window_rect.y = 0;
-         window_rect.width = width;
-         window_rect.height = height;
+      gdk_region_destroy (diff);
 
-         window_region = gdk_region_rectangle (&window_rect);
-         gdk_region_intersect (expose_region,
-                               window_region);
-         gdk_region_destroy (window_region);
-         
-         if (!gdk_region_empty (expose_region) &&
-             (private->event_mask & GDK_EXPOSURE_MASK))
-           {
-             GdkEvent event;
-             
-             event.expose.type = GDK_EXPOSE;
-             event.expose.window = g_object_ref (window);
-             event.expose.send_event = FALSE;
-             event.expose.count = 0;
-             event.expose.region = expose_region;
-             gdk_region_get_clipbox (expose_region, &event.expose.area);
-             
-             (*_gdk_event_func) (&event, _gdk_event_data);
-             
-             g_object_unref (window);
-           }
+      if (private->parent != NULL &&
+         GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
+       {
+         /* New area in the non-root parent window, needs invalidation */
+         diff = gdk_region_copy (old_region);
+         gdk_region_subtract (diff, new_region);
 
-         if (expose_region != update_area)
-           gdk_region_destroy (expose_region);
+         /* Adjust region to parent window coords */
+         gdk_region_offset (diff, private->x, private->y);
+
+         gdk_window_invalidate_region (GDK_WINDOW (private->parent), diff, TRUE);
+
+         gdk_region_destroy (diff);
        }
-      if (!save_region)
-       gdk_region_destroy (update_area);
+
+      gdk_region_destroy (new_region);
+      gdk_region_destroy (old_region);
     }
 }
 
 static void
-flush_all_displays (void)
+do_child_shapes (GdkWindow *window,
+                gboolean merge)
 {
-  GSList *displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
-  GSList *tmp_list;
+  GdkWindowObject *private;
+  GdkRectangle r;
+  GdkRegion *region;
 
-  for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
-    gdk_display_flush (tmp_list->data);
+  private = (GdkWindowObject *) window;
 
-  g_slist_free (displays);
-}
+  r.x = 0;
+  r.y = 0;
+  r.width = private->width;
+  r.height = private->height;
 
-/* Currently it is not possible to override
- * gdk_window_process_all_updates in the same manner as
- * gdk_window_process_updates and gdk_window_invalidate_maybe_recurse
- * by implementing the GdkPaintable interface.  If in the future a
- * backend would need this, the right solution would be to add a
- * method to GdkDisplay that can be optionally
- * NULL. gdk_window_process_all_updates can then walk the list of open
- * displays and call the mehod.
- */
+  region = gdk_region_rectangle (&r);
+  remove_child_area (private, NULL, FALSE, region);
+
+  if (merge && private->shape)
+    gdk_region_subtract (region, private->shape);
+
+  gdk_window_shape_combine_region (window, region, 0, 0);
+}
 
 /**
- * gdk_window_process_all_updates:
+ * gdk_window_set_child_shapes:
+ * @window: a #GdkWindow
  *
- * Calls gdk_window_process_updates() for all windows (see #GdkWindow)
- * in the application.
- * 
+ * Sets the shape mask of @window to the union of shape masks
+ * for all children of @window, ignoring the shape mask of @window
+ * itself. Contrast with gdk_window_merge_child_shapes() which includes
+ * the shape mask of @window in the masks to be merged.
  **/
 void
-gdk_window_process_all_updates (void)
+gdk_window_set_child_shapes (GdkWindow *window)
 {
-  GSList *old_update_windows = update_windows;
-  GSList *tmp_list = update_windows;
-
-  if (update_idle)
-    g_source_remove (update_idle);
-  
-  update_windows = NULL;
-  update_idle = 0;
-
-  g_slist_foreach (old_update_windows, (GFunc)g_object_ref, NULL);
-  
-  while (tmp_list)
-    {
-      GdkWindowObject *private = (GdkWindowObject *)tmp_list->data;
-      
-      if (!GDK_WINDOW_DESTROYED (tmp_list->data))
-        {
-         if (private->update_freeze_count ||
-             gdk_window_is_toplevel_frozen (tmp_list->data))
-           update_windows = g_slist_prepend (update_windows, private);
-         else
-           gdk_window_process_updates_internal (tmp_list->data);
-       }
-
-      g_object_unref (tmp_list->data);
-      tmp_list = tmp_list->next;
-    }
-
-  g_slist_free (old_update_windows);
+  g_return_if_fail (GDK_IS_WINDOW (window));
 
-  flush_all_displays ();
+  do_child_shapes (window, FALSE);
 }
 
 /**
- * gdk_window_process_updates:
+ * gdk_window_merge_child_shapes:
  * @window: a #GdkWindow
- * @update_children: whether to also process updates for child windows
  *
- * Sends one or more expose events to @window. The areas in each 
- * expose event will cover the entire update area for the window (see
- * gdk_window_invalidate_region() for details). Normally GDK calls
- * gdk_window_process_all_updates() on your behalf, so there's no
- * need to call this function unless you want to force expose events
- * to be delivered immediately and synchronously (vs. the usual
- * case, where GDK delivers them in an idle handler). Occasionally
- * this is useful to produce nicer scrolling behavior, for example.
- * 
- **/
+ * Merges the shape masks for any child windows into the
+ * shape mask for @window. i.e. the union of all masks
+ * for @window and its children will become the new mask
+ * for @window. See gdk_window_shape_combine_mask().
+ *
+ * This function is distinct from gdk_window_set_child_shapes()
+ * because it includes @window's shape mask in the set of shapes to
+ * be merged.
+ */
 void
-gdk_window_process_updates (GdkWindow *window,
-                           gboolean   update_children)
+gdk_window_merge_child_shapes (GdkWindow *window)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  if (GDK_IS_PAINTABLE (private->impl))
-    {
-      GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
-
-      if (iface->process_updates)
-        iface->process_updates ((GdkPaintable*)private->impl, update_children);
-
-      return;
-    }
-  
-  if (private->update_area &&
-      !private->update_freeze_count &&
-      !gdk_window_is_toplevel_frozen (window))
-    {      
-      gdk_window_process_updates_internal (window);
-      update_windows = g_slist_remove (update_windows, window);
-    }
-
-  if (update_children)
-    {
-      GList *tmp_list = private->children;
-      while (tmp_list)
-       {
-         gdk_window_process_updates (tmp_list->data, TRUE);
-         tmp_list = tmp_list->next;
-       }
-    }
+  do_child_shapes (window, TRUE);
 }
 
 /**
- * gdk_window_invalidate_rect:
+ * gdk_window_input_shape_combine_mask:
  * @window: a #GdkWindow
- * @rect: rectangle to invalidate or %NULL to invalidate the whole
- *      window
- * @invalidate_children: whether to also invalidate child windows
+ * @mask: shape mask
+ * @x: X position of shape mask with respect to @window
+ * @y: Y position of shape mask with respect to @window
  *
- * A convenience wrapper around gdk_window_invalidate_region() which
- * invalidates a rectangular region. See
- * gdk_window_invalidate_region() for details.
- **/
+ * Like gdk_window_shape_combine_mask(), but the shape applies
+ * only to event handling. Mouse events which happen while
+ * the pointer position corresponds to an unset bit in the
+ * mask will be passed on the window below @window.
+ *
+ * An input shape is typically used with RGBA windows.
+ * The alpha channel of the window defines which pixels are
+ * invisible and allows for nicely antialiased borders,
+ * and the input shape controls where the window is
+ * "clickable".
+ *
+ * On the X11 platform, this requires version 1.1 of the
+ * shape extension.
+ *
+ * On the Win32 platform, this functionality is not present and the
+ * function does nothing.
+ *
+ * Since: 2.10
+ */
 void
-gdk_window_invalidate_rect (GdkWindow          *window,
-                            const GdkRectangle *rect,
-                            gboolean            invalidate_children)
+gdk_window_input_shape_combine_mask (GdkWindow *window,
+                                    GdkBitmap *mask,
+                                    gint       x,
+                                    gint       y)
 {
-  GdkRectangle window_rect;
+  GdkWindowObject *private;
   GdkRegion *region;
-  GdkWindowObject *private = (GdkWindowObject *)window;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  if (GDK_WINDOW_DESTROYED (window))
-    return;
-  
-  if (private->input_only || !GDK_WINDOW_IS_MAPPED (window))
-    return;
-
-  if (!rect)
-    {
-      window_rect.x = 0;
-      window_rect.y = 0;
-      gdk_drawable_get_size (GDK_DRAWABLE (window),
-                             &window_rect.width,
-                             &window_rect.height);
-      rect = &window_rect;
-    }
+  private = (GdkWindowObject *) window;
 
-  region = gdk_region_rectangle (rect);
-  gdk_window_invalidate_region (window, region, invalidate_children);
-  gdk_region_destroy (region);
-}
+  if (mask)
+    region = _gdk_windowing_get_shape_for_mask (mask);
+  else
+    region = NULL;
 
-static void
-draw_ugly_color (GdkWindow       *window,
-                 const GdkRegion *region)
-{
-  /* Draw ugly color all over the newly-invalid region */
-  GdkColor ugly_color = { 0, 50000, 10000, 10000 };
-  GdkGC *ugly_gc;
-  GdkRectangle clipbox;
-    
-  ugly_gc = gdk_gc_new (window);
-  gdk_gc_set_rgb_fg_color (ugly_gc, &ugly_color);
-  gdk_gc_set_clip_region (ugly_gc, region);
+  gdk_window_input_shape_combine_region (window,
+                                        region,
+                                        x, y);
 
-  gdk_region_get_clipbox (region, &clipbox);
-  
-  gdk_draw_rectangle (window,
-                     ugly_gc,
-                     TRUE,
-                     clipbox.x, clipbox.y,
-                     clipbox.width, clipbox.height);
-  
-  g_object_unref (ugly_gc);
+  gdk_region_destroy (region);
 }
 
 /**
- * gdk_window_invalidate_maybe_recurse:
+ * gdk_window_input_shape_combine_region:
  * @window: a #GdkWindow
- * @region: a #GdkRegion
- * @child_func: function to use to decide if to recurse to a child,
- *              %NULL means never recurse.
- * @user_data: data passed to @child_func
+ * @shape_region: region of window to be non-transparent
+ * @offset_x: X position of @shape_region in @window coordinates
+ * @offset_y: Y position of @shape_region in @window coordinates
  *
- * Adds @region to the update area for @window. The update area is the
- * region that needs to be redrawn, or "dirty region." The call
- * gdk_window_process_updates() sends one or more expose events to the
- * window, which together cover the entire update area. An
- * application would normally redraw the contents of @window in
- * response to those expose events.
+ * Like gdk_window_shape_combine_region(), but the shape applies
+ * only to event handling. Mouse events which happen while
+ * the pointer position corresponds to an unset bit in the
+ * mask will be passed on the window below @window.
  *
- * GDK will call gdk_window_process_all_updates() on your behalf
- * whenever your program returns to the main loop and becomes idle, so
- * normally there's no need to do that manually, you just need to
- * invalidate regions that you know should be redrawn.
+ * An input shape is typically used with RGBA windows.
+ * The alpha channel of the window defines which pixels are
+ * invisible and allows for nicely antialiased borders,
+ * and the input shape controls where the window is
+ * "clickable".
  *
- * The @child_func parameter controls whether the region of
- * each child window that intersects @region will also be invalidated.
- * Only children for which @child_func returns TRUE will have the area
- * invalidated.
- **/
+ * On the X11 platform, this requires version 1.1 of the
+ * shape extension.
+ *
+ * On the Win32 platform, this functionality is not present and the
+ * function does nothing.
+ *
+ * Since: 2.10
+ */
 void
-gdk_window_invalidate_maybe_recurse (GdkWindow       *window,
-                                     const GdkRegion *region,
-                                     gboolean       (*child_func) (GdkWindow *,
-                                                                   gpointer),
-                                    gpointer   user_data)
+gdk_window_input_shape_combine_region (GdkWindow       *window,
+                                      const GdkRegion *shape_region,
+                                      gint             offset_x,
+                                      gint             offset_y)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkRegion *visible_region;
-  GList *tmp_list;
+  GdkWindowObject *private;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
+  private = (GdkWindowObject *) window;
+
   if (GDK_WINDOW_DESTROYED (window))
     return;
-  
-  if (private->input_only || !GDK_WINDOW_IS_MAPPED (window))
-    return;
-
-  if (GDK_IS_PAINTABLE (private->impl))
-    {
-      GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
 
-      if (iface->invalidate_maybe_recurse)
-        iface->invalidate_maybe_recurse ((GdkPaintable*)private->impl, 
-                                         region, child_func, user_data);
-      return;
-    }
+  if (private->input_shape)
+    gdk_region_destroy (private->input_shape);
 
-  /* windows that a redirection has ben setup for need to be considered
-   * fully visible, in order to avoid missing redirected paint ops
-   * anywhere in the window area.
-   */
-  if (private->redirect && private->redirect->redirected == private)
+  if (shape_region)
     {
-      GdkRectangle visible_rect = { 0, 0, 0, 0 };
-      gdk_drawable_get_size (GDK_DRAWABLE (window), &visible_rect.width, &visible_rect.height);
-      visible_region = gdk_region_rectangle (&visible_rect);
+      private->input_shape = gdk_region_copy (shape_region);
+      gdk_region_offset (private->input_shape, offset_x, offset_y);
     }
   else
-    visible_region = gdk_drawable_get_visible_region (window);
-  gdk_region_intersect (visible_region, region);
+    private->input_shape = NULL;
 
-  tmp_list = private->children;
-  while (tmp_list)
-    {
-      GdkWindowObject *child = tmp_list->data;
-      
-      if (!child->input_only)
-       {
-         GdkRegion *child_region;
-         GdkRectangle child_rect;
-         
-         gdk_window_get_position ((GdkWindow *)child,
-                                  &child_rect.x, &child_rect.y);
-         gdk_drawable_get_size ((GdkDrawable *)child,
-                                &child_rect.width, &child_rect.height);
+  if (gdk_window_has_impl (private))
+    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_shape_combine_region ((GdkWindow *)private, private->input_shape, 0, 0);
 
-         child_region = gdk_region_rectangle (&child_rect);
-         
-         /* remove child area from the invalid area of the parent */
-         if (GDK_WINDOW_IS_MAPPED (child) && !child->shaped &&
-             !child->composited)
-           gdk_region_subtract (visible_region, child_region);
-         
-         if (child_func && (*child_func) ((GdkWindow *)child, user_data))
-           {
-              GdkRegion *tmp = gdk_region_copy (region);
+  /* Pointer may have e.g. moved outside window due to the input mask change */
+  _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
 
-             gdk_region_offset (tmp, - child_rect.x, - child_rect.y);
-             gdk_region_offset (child_region, - child_rect.x, - child_rect.y);
-             gdk_region_intersect (child_region, tmp);
-             
-             gdk_window_invalidate_maybe_recurse ((GdkWindow *)child,
-                                                  child_region, child_func, user_data);
-             
-             gdk_region_destroy (tmp);
-           }
+static void
+do_child_input_shapes (GdkWindow *window,
+                      gboolean merge)
+{
+  GdkWindowObject *private;
+  GdkRectangle r;
+  GdkRegion *region;
 
-         gdk_region_destroy (child_region);
-       }
+  private = (GdkWindowObject *) window;
 
-      tmp_list = tmp_list->next;
-    }
-  
-  if (!gdk_region_empty (visible_region))
-    {
-      if (debug_updates)
-        draw_ugly_color (window, region);
+  r.x = 0;
+  r.y = 0;
+  r.width = private->width;
+  r.height = private->height;
 
-      if (private->update_area)
-       {
-         gdk_region_union (private->update_area, visible_region);
-       }
-      else
-       {
-         update_windows = g_slist_prepend (update_windows, window);
-         private->update_area = gdk_region_copy (visible_region);
-         
-         gdk_window_schedule_update (window);
-       }
-    }
-  
-  gdk_region_destroy (visible_region);
+  region = gdk_region_rectangle (&r);
+  remove_child_area (private, NULL, TRUE, region);
+
+  if (merge && private->shape)
+    gdk_region_subtract (region, private->shape);
+  if (merge && private->input_shape)
+    gdk_region_subtract (region, private->input_shape);
+
+  gdk_window_input_shape_combine_region (window, region, 0, 0);
 }
 
-static gboolean
-true_predicate (GdkWindow *window,
-               gpointer   user_data)
+
+/**
+ * gdk_window_set_child_input_shapes:
+ * @window: a #GdkWindow
+ *
+ * Sets the input shape mask of @window to the union of input shape masks
+ * for all children of @window, ignoring the input shape mask of @window
+ * itself. Contrast with gdk_window_merge_child_input_shapes() which includes
+ * the input shape mask of @window in the masks to be merged.
+ *
+ * Since: 2.10
+ **/
+void
+gdk_window_set_child_input_shapes (GdkWindow *window)
 {
-  return TRUE;
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  do_child_input_shapes (window, FALSE);
 }
 
 /**
- * gdk_window_invalidate_region:
+ * gdk_window_merge_child_input_shapes:
  * @window: a #GdkWindow
- * @region: a #GdkRegion
- * @invalidate_children: %TRUE to also invalidate child windows 
  *
- * Adds @region to the update area for @window. The update area is the
- * region that needs to be redrawn, or "dirty region." The call
- * gdk_window_process_updates() sends one or more expose events to the
- * window, which together cover the entire update area. An
- * application would normally redraw the contents of @window in
- * response to those expose events.
+ * Merges the input shape masks for any child windows into the
+ * input shape mask for @window. i.e. the union of all input masks
+ * for @window and its children will become the new input mask
+ * for @window. See gdk_window_input_shape_combine_mask().
  *
- * GDK will call gdk_window_process_all_updates() on your behalf
- * whenever your program returns to the main loop and becomes idle, so
- * normally there's no need to do that manually, you just need to
- * invalidate regions that you know should be redrawn.
+ * This function is distinct from gdk_window_set_child_input_shapes()
+ * because it includes @window's input shape mask in the set of
+ * shapes to be merged.
  *
- * The @invalidate_children parameter controls whether the region of
- * each child window that intersects @region will also be invalidated.
- * If %FALSE, then the update area for child windows will remain
- * unaffected. See gdk_window_invalidate_maybe_recurse if you need
- * fine grained control over which children are invalidated.
+ * Since: 2.10
  **/
 void
-gdk_window_invalidate_region (GdkWindow       *window,
-                             const GdkRegion *region,
-                             gboolean         invalidate_children)
+gdk_window_merge_child_input_shapes (GdkWindow *window)
 {
-  gdk_window_invalidate_maybe_recurse (window, region,
-                                      invalidate_children ?
-                                        true_predicate : (gboolean (*) (GdkWindow *, gpointer))NULL,
-                                      NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  do_child_input_shapes (window, TRUE);
 }
 
+
 /**
- * gdk_window_get_update_area:
+ * gdk_window_set_static_gravities:
  * @window: a #GdkWindow
- * 
- * Transfers ownership of the update area from @window to the caller
- * of the function. That is, after calling this function, @window will
- * no longer have an invalid/dirty region; the update area is removed
- * from @window and handed to you. If a window has no update area,
- * gdk_window_get_update_area() returns %NULL. You are responsible for
- * calling gdk_region_destroy() on the returned region if it's non-%NULL.
- * 
- * Return value: the update area for @window
- **/
-GdkRegion *
-gdk_window_get_update_area (GdkWindow *window)
+ * @use_static: %TRUE to turn on static gravity
+ *
+ * Set the bit gravity of the given window to static, and flag it so
+ * all children get static subwindow gravity. This is used if you are
+ * implementing scary features that involve deep knowledge of the
+ * windowing system. Don't worry about it unless you have to.
+ *
+ * Return value: %TRUE if the server supports static gravity
+ */
+gboolean
+gdk_window_set_static_gravities (GdkWindow *window,
+                                gboolean   use_static)
+{
+  GdkWindowObject *private;
+
+  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+
+  private = (GdkWindowObject *) window;
+
+  if (gdk_window_has_impl (private))
+    return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_static_gravities (window, use_static);
+
+  return FALSE;
+}
+
+/**
+ * gdk_window_set_composited:
+ * @window: a #GdkWindow
+ * @composited: %TRUE to set the window as composited
+ *
+ * Sets a #GdkWindow as composited, or unsets it. Composited
+ * windows do not automatically have their contents drawn to
+ * the screen. Drawing is redirected to an offscreen buffer
+ * and an expose event is emitted on the parent of the composited
+ * window. It is the responsibility of the parent's expose handler
+ * to manually merge the off-screen content onto the screen in
+ * whatever way it sees fit. See <xref linkend="composited-window-example"/>
+ * for an example.
+ *
+ * It only makes sense for child windows to be composited; see
+ * gdk_window_set_opacity() if you need translucent toplevel
+ * windows.
+ *
+ * An additional effect of this call is that the area of this
+ * window is no longer clipped from regions marked for
+ * invalidation on its parent. Draws done on the parent
+ * window are also no longer clipped by the child.
+ *
+ * This call is only supported on some systems (currently,
+ * only X11 with new enough Xcomposite and Xdamage extensions).
+ * You must call gdk_display_supports_composite() to check if
+ * setting a window as composited is supported before
+ * attempting to do so.
+ *
+ * Since: 2.12
+ */
+void
+gdk_window_set_composited (GdkWindow *window,
+                          gboolean   composited)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkRegion *tmp_region;
+  GdkDisplay *display;
 
-  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
+  g_return_if_fail (GDK_IS_WINDOW (window));
 
-  if (private->update_area)
+  composited = composited != FALSE;
+
+  if (private->composited == composited)
+    return;
+
+  if (composited)
+    gdk_window_ensure_native (window);
+
+  display = gdk_drawable_get_display (GDK_DRAWABLE (window));
+
+  if (!gdk_display_supports_composite (display) && composited)
     {
-      tmp_region = private->update_area;
-      private->update_area = NULL;
+      g_warning ("gdk_window_set_composited called but "
+                "compositing is not supported");
+      return;
+    }
+
+  _gdk_windowing_window_set_composited (window, composited);
+
+  recompute_visible_regions (private, TRUE, FALSE);
+
+  if (GDK_WINDOW_IS_MAPPED (window))
+    gdk_window_invalidate_in_parent (private);
 
-      update_windows = g_slist_remove (update_windows, window);
-      
-      return tmp_region;
-    }
-  else
-    return NULL;
+  private->composited = composited;
 }
 
-/**
- * _gdk_window_clear_update_area:
- * @window: a #GdkWindow.
- * 
- * Internal function to clear the update area for a window. This
- * is called when the window is hidden or destroyed.
- **/
-void
-_gdk_window_clear_update_area (GdkWindow *window)
-{
-  GdkWindowObject *private = (GdkWindowObject *)window;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+static void
+remove_redirect_from_children (GdkWindowObject   *private,
+                              GdkWindowRedirect *redirect)
+{
+  GList *l;
+  GdkWindowObject *child;
 
-  if (private->update_area)
+  for (l = private->children; l != NULL; l = l->next)
     {
-      update_windows = g_slist_remove (update_windows, window);
-      
-      gdk_region_destroy (private->update_area);
-      private->update_area = NULL;
+      child = l->data;
+
+      /* Don't redirect this child if it already has another redirect */
+      if (child->redirect == redirect)
+       {
+         child->redirect = NULL;
+         remove_redirect_from_children (child, redirect);
+       }
     }
 }
 
 /**
- * gdk_window_freeze_updates:
+ * gdk_window_remove_redirection:
  * @window: a #GdkWindow
- * 
- * Temporarily freezes a window such that it won't receive expose
- * events.  The window will begin receiving expose events again when
- * gdk_window_thaw_updates() is called. If gdk_window_freeze_updates()
- * has been called more than once, gdk_window_thaw_updates() must be called
- * an equal number of times to begin processing exposes.
+ *
+ * Removes any active redirection started by
+ * gdk_window_redirect_to_drawable().
+ *
+ * Since: 2.14
  **/
 void
-gdk_window_freeze_updates (GdkWindow *window)
+gdk_window_remove_redirection (GdkWindow *window)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *private;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  private->update_freeze_count++;
+  private = (GdkWindowObject *) window;
+
+  if (private->redirect &&
+      private->redirect->redirected == private)
+    {
+      remove_redirect_from_children (private, private->redirect);
+      gdk_window_redirect_free (private->redirect);
+      private->redirect = NULL;
+    }
 }
 
-/**
- * gdk_window_thaw_updates:
- * @window: a #GdkWindow
- * 
- * Thaws a window frozen with gdk_window_freeze_updates().
- **/
-void
-gdk_window_thaw_updates (GdkWindow *window)
+static void
+apply_redirect_to_children (GdkWindowObject   *private,
+                           GdkWindowRedirect *redirect)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
+  GList *l;
+  GdkWindowObject *child;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  g_return_if_fail (private->update_freeze_count > 0);
+  for (l = private->children; l != NULL; l = l->next)
+    {
+      child = l->data;
 
-  if (--private->update_freeze_count == 0)
-    gdk_window_schedule_update (window);
+      /* Don't redirect this child if it already has another redirect */
+      if (!child->redirect)
+       {
+         child->redirect = redirect;
+         apply_redirect_to_children (child, redirect);
+       }
+    }
 }
 
 /**
- * gdk_window_freeze_toplevel_updates_libgtk_only:
+ * gdk_window_redirect_to_drawable:
  * @window: a #GdkWindow
+ * @drawable: a #GdkDrawable
+ * @src_x: x position in @window
+ * @src_y: y position in @window
+ * @dest_x: x position in @drawable
+ * @dest_y: y position in @drawable
+ * @width: width of redirection
+ * @height: height of redirection
  *
- * Temporarily freezes a window and all its descendants such that it won't
- * receive expose events.  The window will begin receiving expose events
- * again when gdk_window_thaw_toplevel_updates_libgtk_only() is called. If
- * gdk_window_freeze_toplevel_updates_libgtk_only()
- * has been called more than once,
- * gdk_window_thaw_toplevel_updates_libgtk_only() must be called
- * an equal number of times to begin processing exposes.
+ * Redirects drawing into @window so that drawing to the
+ * window in the rectangle specified by @src_x, @src_y,
+ * @width and @height is also drawn into @drawable at
+ * @dest_x, @dest_y.
  *
- * This function is not part of the GDK public API and is only
- * for use by GTK+.
+ * Only drawing between gdk_window_begin_paint_region() or
+ * gdk_window_begin_paint_rect() and gdk_window_end_paint() is
+ * redirected.
+ *
+ * Redirection is active until gdk_window_remove_redirection()
+ * is called.
+ *
+ * Since: 2.14
  **/
 void
-gdk_window_freeze_toplevel_updates_libgtk_only (GdkWindow *window)
+gdk_window_redirect_to_drawable (GdkWindow   *window,
+                                GdkDrawable *drawable,
+                                gint         src_x,
+                                gint         src_y,
+                                gint         dest_x,
+                                gint         dest_y,
+                                gint         width,
+                                gint         height)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *private;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
-  g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
+  g_return_if_fail (GDK_IS_DRAWABLE (drawable));
+  g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
 
-  private->update_and_descendants_freeze_count++;
-}
+  private = (GdkWindowObject *) window;
 
-/**
- * gdk_window_thaw_toplevel_updates_libgtk_only:
- * @window: a #GdkWindow
- * 
- * Thaws a window frozen with
- * gdk_window_freeze_toplevel_updates_libgtk_only().
- *
- * This function is not part of the GDK public API and is only
- * for use by GTK+.
- **/
-void
-gdk_window_thaw_toplevel_updates_libgtk_only (GdkWindow *window)
-{
-  GdkWindowObject *private = (GdkWindowObject *)window;
+  if (private->redirect)
+    gdk_window_remove_redirection (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);
+  if (width == -1 || height == -1)
+    {
+      gint w, h;
+      gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
+      if (width == -1)
+       width = w;
+      if (height == -1)
+       height = h;
+    }
 
-  private->update_and_descendants_freeze_count--;
+  private->redirect = g_new0 (GdkWindowRedirect, 1);
+  private->redirect->redirected = private;
+  private->redirect->pixmap = g_object_ref (drawable);
+  private->redirect->src_x = src_x;
+  private->redirect->src_y = src_y;
+  private->redirect->dest_x = dest_x;
+  private->redirect->dest_y = dest_y;
+  private->redirect->width = width;
+  private->redirect->height = height;
 
-  gdk_window_schedule_update (window);
+  apply_redirect_to_children (private, private->redirect);
 }
 
-/**
- * gdk_window_set_debug_updates:
- * @setting: %TRUE to turn on update debugging
- *
- * With update debugging enabled, calls to
- * gdk_window_invalidate_region() clear the invalidated region of the
- * screen to a noticeable color, and GDK pauses for a short time
- * before sending exposes to windows during
- * gdk_window_process_updates().  The net effect is that you can see
- * the invalid region for each window and watch redraws as they
- * occur. This allows you to diagnose inefficiencies in your application.
- *
- * In essence, because the GDK rendering model prevents all flicker,
- * if you are redrawing the same region 400 times you may never
- * notice, aside from noticing a speed problem. Enabling update
- * debugging causes GTK to flicker slowly and noticeably, so you can
- * see exactly what's being redrawn when, in what order.
- *
- * The --gtk-debug=updates command line option passed to GTK+ programs
- * enables this debug option at application startup time. That's
- * usually more useful than calling gdk_window_set_debug_updates()
- * yourself, though you might want to use this function to enable
- * updates sometime after application startup time.
- * 
- **/
-void
-gdk_window_set_debug_updates (gboolean setting)
+static void
+window_get_size_rectangle (GdkWindow    *window,
+                          GdkRectangle *rect)
 {
-  debug_updates = setting;
+  GdkWindowObject *private = (GdkWindowObject *) window;
+
+  rect->x = rect->y = 0;
+  rect->width = private->width;
+  rect->height = private->height;
 }
 
-/**
- * gdk_window_constrain_size:
- * @geometry: a #GdkGeometry structure
- * @flags: a mask indicating what portions of @geometry are set
- * @width: desired width of window
- * @height: desired height of the window
- * @new_width: location to store resulting width
- * @new_height: location to store resulting height
- * 
- * Constrains a desired width and height according to a 
- * set of geometry hints (such as minimum and maximum size).
+/* Calculates the real clipping region for a window, in window coordinates,
+ * taking into account other windows, gc clip region and gc clip mask.
  */
-void
-gdk_window_constrain_size (GdkGeometry *geometry,
-                          guint        flags,
-                          gint         width,
-                          gint         height,
-                          gint        *new_width,
-                          gint        *new_height)
-{
-  /* This routine is partially borrowed from fvwm.
-   *
-   * Copyright 1993, Robert Nation
-   *     You may use this code for any purpose, as long as the original
-   *     copyright remains in the source code and all documentation
-   *
-   * which in turn borrows parts of the algorithm from uwm
-   */
-  gint min_width = 0;
-  gint min_height = 0;
-  gint base_width = 0;
-  gint base_height = 0;
-  gint xinc = 1;
-  gint yinc = 1;
-  gint max_width = G_MAXINT;
-  gint max_height = G_MAXINT;
-  
-#define FLOOR(value, base)     ( ((gint) ((value) / (base))) * (base) )
-
-  if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
-    {
-      base_width = geometry->base_width;
-      base_height = geometry->base_height;
-      min_width = geometry->min_width;
-      min_height = geometry->min_height;
-    }
-  else if (flags & GDK_HINT_BASE_SIZE)
-    {
-      base_width = geometry->base_width;
-      base_height = geometry->base_height;
-      min_width = geometry->base_width;
-      min_height = geometry->base_height;
-    }
-  else if (flags & GDK_HINT_MIN_SIZE)
-    {
-      base_width = geometry->min_width;
-      base_height = geometry->min_height;
-      min_width = geometry->min_width;
-      min_height = geometry->min_height;
-    }
+GdkRegion *
+_gdk_window_calculate_full_clip_region (GdkWindow *window,
+                                       GdkWindow *base_window,
+                                       gboolean   do_children,
+                                       gint      *base_x_offset,
+                                       gint      *base_y_offset)
+{
+  GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
+  GdkRectangle visible_rect;
+  GdkRegion *real_clip_region, *tmpreg;
+  gint x_offset, y_offset;
+  GdkWindowObject *parentwin, *lastwin;
 
-  if (flags & GDK_HINT_MAX_SIZE)
-    {
-      max_width = geometry->max_width ;
-      max_height = geometry->max_height;
-    }
+  if (base_x_offset)
+    *base_x_offset = 0;
+  if (base_y_offset)
+    *base_y_offset = 0;
 
-  if (flags & GDK_HINT_RESIZE_INC)
-    {
-      xinc = MAX (xinc, geometry->width_inc);
-      yinc = MAX (yinc, geometry->height_inc);
-    }
-  
-  /* clamp width and height to min and max values
-   */
-  width = CLAMP (width, min_width, max_width);
-  height = CLAMP (height, min_height, max_height);
-  
-  /* shrink to base + N * inc
-   */
-  width = base_width + FLOOR (width - base_width, xinc);
-  height = base_height + FLOOR (height - base_height, yinc);
+  if (!GDK_WINDOW_IS_MAPPED (window) || private->input_only)
+    return gdk_region_new ();
 
-  /* constrain aspect ratio, according to:
-   *
-   *                width     
-   * min_aspect <= -------- <= max_aspect
-   *                height    
-   */
-  
-  if (flags & GDK_HINT_ASPECT &&
-      geometry->min_aspect > 0 &&
-      geometry->max_aspect > 0)
+  window_get_size_rectangle (window, &visible_rect);
+
+  /* real_clip_region is in window coordinates */
+  real_clip_region = gdk_region_rectangle (&visible_rect);
+
+  x_offset = y_offset = 0;
+
+  lastwin = private;
+  if (do_children)
+    parentwin = lastwin;
+  else
+    parentwin = lastwin->parent;
+
+  /* Remove the areas of all overlapping windows above parentwin in the hiearachy */
+  for (; parentwin != NULL &&
+        (parentwin == private || lastwin != (GdkWindowObject*) base_window);
+       lastwin = parentwin, parentwin = lastwin->parent)
     {
-      gint delta;
+      GList *cur;
+      GdkRectangle real_clip_rect;
+      gboolean is_offscreen;
 
-      if (geometry->min_aspect * height > width)
+      if (parentwin != private)
        {
-         delta = FLOOR (height - width / geometry->min_aspect, yinc);
-         if (height - delta >= min_height)
-           height -= delta;
-         else
-           { 
-             delta = FLOOR (height * geometry->min_aspect - width, xinc);
-             if (width + delta <= max_width) 
-               width += delta;
-           }
+         x_offset += GDK_WINDOW_OBJECT (lastwin)->x;
+         y_offset += GDK_WINDOW_OBJECT (lastwin)->y;
        }
-      
-      if (geometry->max_aspect * height < width)
+
+      is_offscreen = gdk_window_is_offscreen (parentwin);
+
+      /* children is ordered in reverse stack order */
+      for (cur = parentwin->children;
+          cur && cur->data != lastwin;
+          cur = cur->next)
        {
-         delta = FLOOR (width - height * geometry->max_aspect, xinc);
-         if (width - delta >= min_width) 
-           width -= delta;
-         else
-           {
-             delta = FLOOR (width / geometry->max_aspect - height, yinc);
-             if (height + delta <= max_height)
-               height += delta;
-           }
-       }
-    }
+         GdkWindow *child = cur->data;
+         GdkWindowObject *child_private = (GdkWindowObject *)child;
 
-#undef FLOOR
-  
-  *new_width = width;
-  *new_height = height;
-}
+         if (!GDK_WINDOW_IS_MAPPED (child) || child_private->input_only)
+           continue;
 
-/**
- * gdk_window_get_pointer:
- * @window: a #GdkWindow
- * @x: return location for X coordinate of pointer or %NULL to not
- *      return the X coordinate
- * @y: return location for Y coordinate of pointer or %NULL to not
- *      return the Y coordinate
- * @mask: return location for modifier mask or %NULL to not return the
- *      modifier mask
- *
- * Obtains the current pointer position and modifier state.
- * The position is given in coordinates relative to the upper left 
- * corner of @window.
- * 
- * Return value: the window containing the pointer (as with
- * gdk_window_at_pointer()), or %NULL if the window containing the
- * pointer isn't known to GDK
- **/
-GdkWindow*
-gdk_window_get_pointer (GdkWindow        *window,
-                       gint              *x,
-                       gint              *y,
-                       GdkModifierType   *mask)
-{
-  GdkDisplay *display;
-  gint tmp_x, tmp_y;
-  GdkModifierType tmp_mask;
-  GdkWindow *child;
-  
-  g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
+         /* Ignore offscreen children, as they don't draw in their parent and
+          * don't take part in the clipping */
+         if (gdk_window_is_offscreen (child_private))
+           continue;
 
-  if (window)
-    {
-      display = gdk_drawable_get_display (window);
-    }
-  else
-    {
-      GdkScreen *screen = gdk_screen_get_default ();
+         window_get_size_rectangle (child, &visible_rect);
 
-      display = gdk_screen_get_display (screen);
-      window = gdk_screen_get_root_window (screen);
-      
-      GDK_NOTE (MULTIHEAD,
-               g_message ("Passing NULL for window to gdk_window_get_pointer()\n"
-                          "is not multihead safe"));
-    }
+         /* Convert rect to "window" coords */
+         visible_rect.x += child_private->x - x_offset;
+         visible_rect.y += child_private->y - y_offset;
 
-  child = display->pointer_hooks->window_get_pointer (display, window, &tmp_x, &tmp_y, &tmp_mask);
+         /* This shortcut is really necessary for performance when there are a lot of windows */
+         gdk_region_get_clipbox (real_clip_region, &real_clip_rect);
+         if (visible_rect.x >= real_clip_rect.x + real_clip_rect.width ||
+             visible_rect.x + visible_rect.width <= real_clip_rect.x ||
+             visible_rect.y >= real_clip_rect.y + real_clip_rect.height ||
+             visible_rect.y + visible_rect.height <= real_clip_rect.y)
+           continue;
 
-  if (x)
-    *x = tmp_x;
-  if (y)
-    *y = tmp_y;
-  if (mask)
-    *mask = tmp_mask;
+         tmpreg = gdk_region_rectangle (&visible_rect);
+         gdk_region_subtract (real_clip_region, tmpreg);
+         gdk_region_destroy (tmpreg);
+       }
 
-  return child;
-}
+      /* Clip to the parent */
+      window_get_size_rectangle ((GdkWindow *)parentwin, &visible_rect);
+      /* Convert rect to "window" coords */
+      visible_rect.x += - x_offset;
+      visible_rect.y += - y_offset;
 
-/**
- * gdk_window_at_pointer:
- * @win_x: return location for origin of the window under the pointer
- * @win_y: return location for origin of the window under the pointer
- * 
- * Obtains the window underneath the mouse pointer, returning the
- * location of that window in @win_x, @win_y. Returns %NULL if the
- * window under the mouse pointer is not known to GDK (if the window
- * belongs to another application and a #GdkWindow hasn't been created
- * for it with gdk_window_foreign_new())
- *
- * NOTE: For multihead-aware widgets or applications use
- * gdk_display_get_window_at_pointer() instead.
- * 
- * Return value: window under the mouse pointer
- **/
-GdkWindow*
-gdk_window_at_pointer (gint *win_x,
-                      gint *win_y)
-{
-  return gdk_display_get_window_at_pointer (gdk_display_get_default (), win_x, win_y);
+      tmpreg = gdk_region_rectangle (&visible_rect);
+      gdk_region_intersect (real_clip_region, tmpreg);
+      gdk_region_destroy (tmpreg);
+    }
+
+  if (base_x_offset)
+    *base_x_offset = x_offset;
+  if (base_y_offset)
+    *base_y_offset = y_offset;
+
+  return real_clip_region;
 }
 
-/**
- * gdk_get_default_root_window:
- * 
- * Obtains the root window (parent all other windows are inside)
- * for the default display and screen.
- * 
- * Return value: the default root window
- **/
-GdkWindow *
-gdk_get_default_root_window (void)
+void
+_gdk_window_add_damage (GdkWindow *toplevel,
+                       GdkRegion *damaged_region)
 {
-  return gdk_screen_get_root_window (gdk_screen_get_default ());
+  GdkDisplay *display;
+  GdkEvent event = { 0, };
+  event.expose.type = GDK_DAMAGE;
+  event.expose.window = toplevel;
+  event.expose.send_event = FALSE;
+  event.expose.region = damaged_region;
+  gdk_region_get_clipbox (event.expose.region, &event.expose.area);
+  display = gdk_drawable_get_display (event.expose.window);
+  _gdk_event_queue_append (display, gdk_event_copy (&event));
 }
 
-/**
- * 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)
+static void
+gdk_window_redirect_free (GdkWindowRedirect *redirect)
 {
-  return gdk_window_foreign_new_for_display (gdk_display_get_default (), anid);
+  g_object_unref (redirect->pixmap);
+  g_free (redirect);
 }
 
-/**
- * gdk_window_show_unraised:
- * @window: a #GdkWindow
- *
- * Shows a #GdkWindow onscreen, but does not modify its stacking
- * order. In contrast, gdk_window_show() will raise the window
- * to the top of the window stack.
- *
- * On the X11 platform, in Xlib terms, this function calls
- * XMapWindow() (it also updates some internal GDK state, which means
- * that you can't really use XMapWindow() directly on a GDK window).
- */
-void
-gdk_window_show_unraised (GdkWindow *window)
+/* Gets the toplevel for a window as used for events,
+   i.e. including offscreen parents */
+static GdkWindowObject *
+get_event_parent (GdkWindowObject *window)
 {
-  GdkWindowObject *private;
-
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
-    return;
-
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show (window, FALSE);
+  if (window->window_type ==GDK_WINDOW_OFFSCREEN)
+    return (GdkWindowObject *)gdk_window_get_offscreen_parent ((GdkWindow *)window);
+  else
+    return window->parent;
 }
 
-static inline void
-gdk_window_raise_internal (GdkWindow *window)
+/* Gets the toplevel for a window as used for events,
+   i.e. including offscreen parents going up to the native
+   toplevel */
+static GdkWindow *
+get_event_toplevel (GdkWindow *w)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkWindowObject *parent = private->parent;
+  GdkWindowObject *private = GDK_WINDOW_OBJECT (w);
+  GdkWindowObject *parent;
 
-  if (parent)
-    {
-      parent->children = g_list_remove (parent->children, window);
-      parent->children = g_list_prepend (parent->children, window);
-    }
+  while ((parent = get_event_parent (private)) != NULL &&
+        (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT))
+    private = parent;
+
+  return GDK_WINDOW (private);
 }
 
-/**
- * gdk_window_raise:
- * @window: a #GdkWindow
- *
- * Raises @window to the top of the Z-order (stacking order), so that
- * other windows with the same parent window appear below @window.
- * This is true whether or not the windows are visible.
- *
- * If @window is a toplevel, the window manager may choose to deny the
- * request to move the window in the Z-order, gdk_window_raise() only
- * requests the restack, does not guarantee it.
- */
-void
-gdk_window_raise (GdkWindow *window)
+static gboolean
+is_event_parent_of (GdkWindow *parent,
+                   GdkWindow *child)
 {
-  GdkWindowObject *private;
+  GdkWindow *w;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  w = child;
+  while (w != NULL)
+    {
+      if (w == parent)
+       return TRUE;
 
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
-    return;
+      w = (GdkWindow *)get_event_parent ((GdkWindowObject *)w);
+    }
 
-  /* Keep children in (reverse) stacking order */
-  gdk_window_raise_internal (window);
+  return FALSE;
+}
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
+static void
+update_cursor (GdkDisplay *display)
+{
+  GdkWindowObject *pointer_window, *cursor_window, *parent, *toplevel;
+  GdkPointerGrabInfo *grab;
+
+  pointer_window = (GdkWindowObject *)display->pointer_info.window_under_pointer;
+
+  cursor_window = pointer_window;
+  while (cursor_window->cursor == NULL &&
+        (parent = get_event_parent (cursor_window)) != NULL &&
+        parent->window_type != GDK_WINDOW_ROOT)
+    cursor_window = parent;
+
+  /* We ignore the serials here and just pick the last grab
+     we've sent, as that would shortly be used anyway. */
+  grab = _gdk_display_get_last_pointer_grab (display);
+  if (grab != NULL &&
+      !is_event_parent_of (grab->window, (GdkWindow *)cursor_window))
+    cursor_window = (GdkWindowObject *)grab->window;
+
+  /* Set all cursors on toplevel, otherwise its tricky to keep track of
+   * which native window has what cursor set. */
+  toplevel = (GdkWindowObject *)get_event_toplevel ((GdkWindow *)pointer_window);
+  GDK_WINDOW_IMPL_GET_IFACE (toplevel->impl)->set_cursor
+    ((GdkWindow *)toplevel, cursor_window->cursor);
 }
 
 static void
-gdk_window_lower_internal (GdkWindow *window)
+from_parent (GdkWindowObject *window,
+            double parent_x, double parent_y,
+            double *offscreen_x, double *offscreen_y)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkWindowObject *parent = private->parent;
+  g_signal_emit_by_name (window,
+                        "from_parent",
+                        parent_x, parent_y,
+                        offscreen_x, offscreen_y,
+                        NULL);
+}
 
-  if (parent)
+static void
+convert_coords_to_child (GdkWindowObject *child,
+                        double x, double y,
+                        double *child_x, double *child_y)
+{
+  if (gdk_window_is_offscreen (child))
     {
-      parent->children = g_list_remove (parent->children, window);
-      parent->children = g_list_append (parent->children, window);
+      from_parent (child, x, y,
+                  child_x, child_y);
+    }
+  else
+    {
+      *child_x = x - child->x;
+      *child_y = y - child->y;
     }
 }
 
-/**
- * gdk_window_lower:
- * @window: a #GdkWindow
- *
- * Lowers @window to the bottom of the Z-order (stacking order), so that
- * other windows with the same parent window appear above @window.
- * This is true whether or not the other windows are visible.
- *
- * If @window is a toplevel, the window manager may choose to deny the
- * request to move the window in the Z-order, gdk_window_lower() only
- * requests the restack, does not guarantee it.
- *
- * Note that gdk_window_show() raises the window again, so don't call this
- * function before gdk_window_show(). (Try gdk_window_show_unraised().)
- */
-void
-gdk_window_lower (GdkWindow *window)
+static gboolean
+point_in_window (GdkWindowObject *window,
+                double x, double y)
 {
-  GdkWindowObject *private;
+  return
+    x >= 0 && x < window->width &&
+    y >= 0 && y < window->height &&
+    (window->shape == NULL ||
+     gdk_region_point_in (window->shape,
+                         x, y)) &&
+    (window->input_shape == NULL ||
+     gdk_region_point_in (window->input_shape,
+                         x, y));
+}
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+static GdkWindow *
+convert_native_coords_to_toplevel (GdkWindow *window,
+                                  double child_x, double child_y,
+                                  double *toplevel_x, double *toplevel_y)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  gdouble x, y;
 
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
-    return;
+  x = child_x;
+  y = child_y;
 
-  /* Keep children in (reverse) stacking order */
-  gdk_window_lower_internal (window);
+  while (private->parent != NULL &&
+        (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT))
+    {
+      x += private->x;
+      y += private->y;
+      private = private->parent;
+    }
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->lower (window);
+  *toplevel_x = x;
+  *toplevel_y = y;
+
+  return (GdkWindow *)private;
 }
 
-/**
- * gdk_window_show:
- * @window: a #GdkWindow
- *
- * Like gdk_window_show_unraised(), but also raises the window to the
- * top of the window stack (moves the window to the front of the
- * Z-order).
- *
- * This function maps a window so it's visible onscreen. Its opposite
- * is gdk_window_hide().
- *
- * When implementing a #GtkWidget, you should call this function on the widget's
- * #GdkWindow as part of the "map" method.
- */
-void
-gdk_window_show (GdkWindow *window)
+static void
+convert_toplevel_coords_to_window (GdkWindow *window,
+                                  gdouble    toplevel_x,
+                                  gdouble    toplevel_y,
+                                  gdouble   *window_x,
+                                  gdouble   *window_y)
 {
   GdkWindowObject *private;
+  GdkWindowObject *parent;
+  gdouble x, y;
+  GList *children, *l;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  private = GDK_WINDOW_OBJECT (window);
 
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
-    return;
+  x = toplevel_x;
+  y = toplevel_y;
 
-  /* Keep children in (reverse) stacking order */
-  gdk_window_raise_internal (window);
+  children = NULL;
+  while ((parent = get_event_parent (private)) != NULL &&
+        (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT))
+    {
+      children = g_list_prepend (children, private);
+      private = parent;
+    }
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show (window, TRUE);
+  for (l = children; l != NULL; l = l->next)
+    convert_coords_to_child (l->data, x, y, &x, &y);
+
+  g_list_free (children);
+
+  *window_x = x;
+  *window_y = y;
 }
 
-/**
- * gdk_window_hide:
- * @window: a #GdkWindow
- *
- * For toplevel windows, withdraws them, so they will no longer be
- * known to the window manager; for all windows, unmaps them, so
- * they won't be displayed. Normally done automatically as
- * part of gtk_widget_hide().
- */
-void
-gdk_window_hide (GdkWindow *window)
+static GdkWindowObject *
+pick_offscreen_child (GdkWindowObject *window,
+                     double x, double y)
 {
-  GdkWindowObject *private;
-
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  GdkWindowObject *res;
 
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
-    return;
+  res = NULL;
+  g_signal_emit_by_name (window,
+                        "pick-offscreen-child",
+                        x, y, &res);
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->hide (window);
+  return res;
 }
 
-/**
- * gdk_window_withdraw:
- * @window: a toplevel #GdkWindow
- *
- * Withdraws a window (unmaps it and asks the window manager to forget about it).
- * This function is not really useful as gdk_window_hide() automatically
- * withdraws toplevel windows before hiding them.
- **/
-void
-gdk_window_withdraw (GdkWindow *window)
+GdkWindow *
+_gdk_window_find_child_at (GdkWindow *window,
+                          int x, int y)
 {
-  GdkWindowObject *private;
-
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  GdkWindowObject *private, *sub;
+  double child_x, child_y;
+  GList *l;
 
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
-    return;
+  private = (GdkWindowObject *)window;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->withdraw (window);
-}
+  if (point_in_window (private, x, y))
+    {
+      /* Children is ordered in reverse stack order, i.e. first is topmost */
+      for (l = private->children; l != NULL; l = l->next)
+       {
+         sub = l->data;
 
-/**
- * gdk_window_set_events:
- * @window: a #GdkWindow
- * @event_mask: event mask for @window
- *
- * The event mask for a window determines which events will be reported
- * for that window. For example, an event mask including #GDK_BUTTON_PRESS_MASK
- * means the window should report button press events. The event mask
- * is the bitwise OR of values from the #GdkEventMask enumeration.
- **/
-void
-gdk_window_set_events (GdkWindow       *window,
-                      GdkEventMask     event_mask)
-{
-  GdkWindowObject *private;
+         if (!GDK_WINDOW_IS_MAPPED (sub))
+           continue;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+         convert_coords_to_child (sub,
+                                  x, y,
+                                  &child_x, &child_y);
+         if (point_in_window (sub, child_x, child_y))
+           return (GdkWindow *)sub;
+       }
 
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
-    return;
+      if (private->has_offscreen_children)
+       {
+         sub = pick_offscreen_child (private,
+                                     x, y);
+         if (sub)
+           return (GdkWindow *)sub;
+       }
+    }
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_events (window, event_mask);
+  return NULL;
 }
 
-/**
- * gdk_window_get_events:
- * @window: a #GdkWindow
- *
- * Gets the event mask for @window. See gdk_window_set_events().
- *
- * Return value: event mask for @window
- **/
-GdkEventMask
-gdk_window_get_events (GdkWindow *window)
+GdkWindow *
+_gdk_window_find_descendant_at (GdkWindow *toplevel,
+                               double x, double y,
+                               double *found_x,
+                               double *found_y)
 {
-  GdkWindowObject *private;
+  GdkWindowObject *private, *sub;
+  double child_x, child_y;
+  GList *l;
+  gboolean found;
 
-  g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
+  private = (GdkWindowObject *)toplevel;
 
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
-    return 0;
+  if (point_in_window (private, 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)
+           {
+             sub = l->data;
+
+             if (!GDK_WINDOW_IS_MAPPED (sub))
+               continue;
+
+             convert_coords_to_child (sub,
+                                      x, y,
+                                      &child_x, &child_y);
+             if (point_in_window (sub, child_x, child_y))
+               {
+                 x = child_x;
+                 y = child_y;
+                 private = sub;
+                 found = TRUE;
+                 break;
+               }
+           }
+         if (!found &&
+             private->has_offscreen_children)
+           {
+             sub = pick_offscreen_child (private,
+                                         x, y);
+             if (sub)
+               {
+                 found = TRUE;
+                 private = sub;
+                 from_parent (sub, x, y, &x, &y);
+               }
+           }
+       }
+      while (found);
+    }
+  else
+    {
+      /* Not in window at all */
+      private = NULL;
+    }
+
+  if (found_x)
+    *found_x = x;
+  if (found_y)
+    *found_y = y;
 
-  return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_events (window);
+  return (GdkWindow *)private;
 }
 
 /**
- * gdk_window_move:
- * @window: a #GdkWindow
- * @x: X coordinate relative to window's parent
- * @y: Y coordinate relative to window's parent
+ * gdk_window_beep:
+ * @window: a toplevel #GdkWindow
  *
- * Repositions a window relative to its parent window.
- * For toplevel windows, window managers may ignore or modify the move;
- * you should probably use gtk_window_move() on a #GtkWindow widget
- * anyway, instead of using GDK functions. For child windows,
- * the move will reliably succeed.
+ * Emits a short beep associated to @window in the appropriate
+ * display, if supported. Otherwise, emits a short beep on
+ * the display just as gdk_display_beep().
  *
- * If you're also planning to resize the window, use gdk_window_move_resize()
- * to both move and resize simultaneously, for a nicer visual effect.
+ * Since: 2.12
  **/
 void
-gdk_window_move (GdkWindow *window,
-                gint       x,
-                gint       y)
+gdk_window_beep (GdkWindow *window)
 {
-  GdkWindowObject *private;
+  GdkDisplay *display;
+  GdkWindow *toplevel;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
+  if (GDK_WINDOW_DESTROYED (window))
     return;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, TRUE, x, y, -1, -1);
+  toplevel = get_event_toplevel (window);
+  display = gdk_drawable_get_display (GDK_DRAWABLE (window));
+
+  if (toplevel && gdk_window_is_offscreen ((GdkWindowObject *)toplevel))
+    _gdk_windowing_window_beep (toplevel);
+  else
+    gdk_display_beep (display);
 }
 
-/**
- * gdk_window_resize:
- * @window: a #GdkWindow
- * @width: new width of the window
- * @height: new height of the window
- *
- * Resizes @window; for toplevel windows, asks the window manager to resize
- * the window. The window manager may not allow the resize. When using GTK+,
- * use gtk_window_resize() instead of this low-level GDK function.
- *
- * Windows may not be resized below 1x1.
- *
- * If you're also planning to move the window, use gdk_window_move_resize()
- * to both move and resize simultaneously, for a nicer visual effect.
- **/
-void
-gdk_window_resize (GdkWindow *window,
-                  gint       width,
-                  gint       height)
+static const guint type_masks[] = {
+  GDK_SUBSTRUCTURE_MASK, /* GDK_DELETE                 = 0  */
+  GDK_STRUCTURE_MASK, /* GDK_DESTROY                   = 1  */
+  GDK_EXPOSURE_MASK, /* GDK_EXPOSE                     = 2  */
+  GDK_POINTER_MOTION_MASK, /* GDK_MOTION_NOTIFY        = 3  */
+  GDK_BUTTON_PRESS_MASK, /* GDK_BUTTON_PRESS           = 4  */
+  GDK_BUTTON_PRESS_MASK, /* GDK_2BUTTON_PRESS          = 5  */
+  GDK_BUTTON_PRESS_MASK, /* GDK_3BUTTON_PRESS          = 6  */
+  GDK_BUTTON_RELEASE_MASK, /* GDK_BUTTON_RELEASE       = 7  */
+  GDK_KEY_PRESS_MASK, /* GDK_KEY_PRESS                 = 8  */
+  GDK_KEY_RELEASE_MASK, /* GDK_KEY_RELEASE             = 9  */
+  GDK_ENTER_NOTIFY_MASK, /* GDK_ENTER_NOTIFY           = 10 */
+  GDK_LEAVE_NOTIFY_MASK, /* GDK_LEAVE_NOTIFY           = 11 */
+  GDK_FOCUS_CHANGE_MASK, /* GDK_FOCUS_CHANGE           = 12 */
+  GDK_STRUCTURE_MASK, /* GDK_CONFIGURE                 = 13 */
+  GDK_VISIBILITY_NOTIFY_MASK, /* GDK_MAP               = 14 */
+  GDK_VISIBILITY_NOTIFY_MASK, /* GDK_UNMAP             = 15 */
+  GDK_PROPERTY_CHANGE_MASK, /* GDK_PROPERTY_NOTIFY     = 16 */
+  GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_CLEAR     = 17 */
+  GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_REQUEST   = 18 */
+  GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_NOTIFY    = 19 */
+  GDK_PROXIMITY_IN_MASK, /* GDK_PROXIMITY_IN           = 20 */
+  GDK_PROXIMITY_OUT_MASK, /* GDK_PROXIMITY_OUT         = 21 */
+  GDK_ALL_EVENTS_MASK, /* GDK_DRAG_ENTER               = 22 */
+  GDK_ALL_EVENTS_MASK, /* GDK_DRAG_LEAVE               = 23 */
+  GDK_ALL_EVENTS_MASK, /* GDK_DRAG_MOTION              = 24 */
+  GDK_ALL_EVENTS_MASK, /* GDK_DRAG_STATUS              = 25 */
+  GDK_ALL_EVENTS_MASK, /* GDK_DROP_START               = 26 */
+  GDK_ALL_EVENTS_MASK, /* GDK_DROP_FINISHED            = 27 */
+  GDK_ALL_EVENTS_MASK, /* GDK_CLIENT_EVENT            = 28 */
+  GDK_VISIBILITY_NOTIFY_MASK, /* GDK_VISIBILITY_NOTIFY = 29 */
+  GDK_EXPOSURE_MASK, /* GDK_NO_EXPOSE                  = 30 */
+  GDK_SCROLL_MASK | GDK_BUTTON_PRESS_MASK,/* GDK_SCROLL= 31 */
+  0, /* GDK_WINDOW_STATE = 32 */
+  0, /* GDK_SETTING = 33 */
+  0, /* GDK_OWNER_CHANGE = 34 */
+  0, /* GDK_GRAB_BROKEN = 35 */
+  0, /* GDK_DAMAGE = 36 */
+};
+G_STATIC_ASSERT (G_N_ELEMENTS (type_masks) == GDK_EVENT_LAST);
+
+/* send motion events if the right buttons are down */
+static guint
+update_evmask_for_button_motion (guint           evmask,
+                                GdkModifierType mask)
 {
-  GdkWindowObject *private;
+  if (evmask & GDK_BUTTON_MOTION_MASK &&
+      mask & (GDK_BUTTON1_MASK |
+             GDK_BUTTON2_MASK |
+             GDK_BUTTON3_MASK |
+             GDK_BUTTON4_MASK |
+             GDK_BUTTON5_MASK))
+    evmask |= GDK_POINTER_MOTION_MASK;
+
+  if ((evmask & GDK_BUTTON1_MOTION_MASK && mask & GDK_BUTTON1_MASK) ||
+      (evmask & GDK_BUTTON2_MOTION_MASK && mask & GDK_BUTTON2_MASK) ||
+      (evmask & GDK_BUTTON3_MOTION_MASK && mask & GDK_BUTTON3_MASK))
+    evmask |= GDK_POINTER_MOTION_MASK;
+
+  return evmask;
+}
+
+static gboolean
+is_button_type (GdkEventType type)
+{
+  return type == GDK_BUTTON_PRESS ||
+        type == GDK_2BUTTON_PRESS ||
+        type == GDK_3BUTTON_PRESS ||
+        type == GDK_BUTTON_RELEASE ||
+        type == GDK_SCROLL;
+}
+
+static gboolean
+is_motion_type (GdkEventType type)
+{
+  return type == GDK_MOTION_NOTIFY ||
+        type == GDK_ENTER_NOTIFY ||
+        type == GDK_LEAVE_NOTIFY;
+}
+
+static GdkWindowObject *
+find_common_ancestor (GdkWindowObject *win1,
+                     GdkWindowObject *win2)
+{
+  GdkWindowObject *tmp;
+  GList *path1 = NULL, *path2 = NULL;
+  GList *list1, *list2;
+
+  tmp = win1;
+  while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
+    {
+      path1 = g_list_prepend (path1, tmp);
+      tmp = get_event_parent (tmp);
+    }
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  tmp = win2;
+  while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
+    {
+      path2 = g_list_prepend (path2, tmp);
+      tmp = get_event_parent (tmp);
+    }
 
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
-    return;
+  list1 = path1;
+  list2 = path2;
+  tmp = NULL;
+  while (list1 && list2 && (list1->data == list2->data))
+    {
+      tmp = (GdkWindowObject *)list1->data;
+      list1 = g_list_next (list1);
+      list2 = g_list_next (list2);
+    }
+  g_list_free (path1);
+  g_list_free (path2);
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, FALSE, 0, 0, width, height);
+  return tmp;
 }
 
-
-/**
- * gdk_window_move_resize:
- * @window: a #GdkWindow
- * @x: new X position relative to window's parent
- * @y: new Y position relative to window's parent
- * @width: new width
- * @height: new height
- *
- * Equivalent to calling gdk_window_move() and gdk_window_resize(),
- * except that both operations are performed at once, avoiding strange
- * visual effects. (i.e. the user may be able to see the window first
- * move, then resize, if you don't use gdk_window_move_resize().)
- **/
-void
-gdk_window_move_resize (GdkWindow *window,
-                       gint       x,
-                       gint       y,
-                       gint       width,
-                       gint       height)
+GdkEvent *
+_gdk_make_event (GdkWindow    *window,
+                GdkEventType  type,
+                GdkEvent     *event_in_queue,
+                gboolean      before_event)
 {
-  GdkWindowObject *private;
+  GdkEvent *event = gdk_event_new (type);
+  guint32 the_time;
+  GdkModifierType the_state;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  the_time = gdk_event_get_time (event_in_queue);
+  gdk_event_get_state (event_in_queue, &the_state);
 
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
-    return;
+  event->any.window = g_object_ref (window);
+  event->any.send_event = FALSE;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, TRUE, x, y, width, height);
-}
+  switch (type)
+    {
+    case GDK_MOTION_NOTIFY:
+      event->motion.time = the_time;
+      event->motion.axes = NULL;
+      event->motion.state = the_state;
+      break;
 
+    case GDK_BUTTON_PRESS:
+    case GDK_2BUTTON_PRESS:
+    case GDK_3BUTTON_PRESS:
+    case GDK_BUTTON_RELEASE:
+      event->button.time = the_time;
+      event->button.axes = NULL;
+      event->button.state = the_state;
+      break;
 
-/**
- * gdk_window_scroll:
- * @window: a #GdkWindow
- * @dx: Amount to scroll in the X direction
- * @dy: Amount to scroll in the Y direction
- *
- * Scroll the contents of @window, both pixels and children, by the
- * given amount. @window itself does not move. Portions of the window
- * that the scroll operation brings in from offscreen areas are
- * invalidated. The invalidated region may be bigger than what would
- * strictly be necessary.
- *
- * For X11, a minimum area will be invalidated if the window has no
- * subwindows, or if the edges of the window's parent do not extend
- * beyond the edges of the window. In other cases, a multi-step process
- * is used to scroll the window which may produce temporary visual
- * artifacts and unnecessary invalidations.
- **/
-void
-gdk_window_scroll (GdkWindow *window,
-                  gint       dx,
-                  gint       dy)
-{
-  GdkWindowObject *private = (GdkWindowObject *) window;
+    case GDK_SCROLL:
+      event->scroll.time = the_time;
+      event->scroll.state = the_state;
+      break;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+    case GDK_KEY_PRESS:
+    case GDK_KEY_RELEASE:
+      event->key.time = the_time;
+      event->key.state = the_state;
+      break;
 
-  if (dx == 0 && dy == 0)
-    return;
+    case GDK_ENTER_NOTIFY:
+    case GDK_LEAVE_NOTIFY:
+      event->crossing.time = the_time;
+      event->crossing.state = the_state;
+      break;
 
-  if (private->destroyed)
-    return;
+    case GDK_PROPERTY_NOTIFY:
+      event->property.time = the_time;
+      event->property.state = the_state;
+      break;
+
+    case GDK_SELECTION_CLEAR:
+    case GDK_SELECTION_REQUEST:
+    case GDK_SELECTION_NOTIFY:
+      event->selection.time = the_time;
+      break;
+
+    case GDK_PROXIMITY_IN:
+    case GDK_PROXIMITY_OUT:
+      event->proximity.time = the_time;
+      break;
+
+    case GDK_DRAG_ENTER:
+    case GDK_DRAG_LEAVE:
+    case GDK_DRAG_MOTION:
+    case GDK_DRAG_STATUS:
+    case GDK_DROP_START:
+    case GDK_DROP_FINISHED:
+      event->dnd.time = the_time;
+      break;
+
+    case GDK_FOCUS_CHANGE:
+    case GDK_CONFIGURE:
+    case GDK_MAP:
+    case GDK_UNMAP:
+    case GDK_CLIENT_EVENT:
+    case GDK_VISIBILITY_NOTIFY:
+    case GDK_NO_EXPOSE:
+    case GDK_DELETE:
+    case GDK_DESTROY:
+    case GDK_EXPOSE:
+    default:
+      break;
+    }
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->scroll (window, dx, dy);
+  if (event_in_queue)
+    {
+    if (before_event)
+      _gdk_event_queue_insert_before (gdk_drawable_get_display (window), event_in_queue, event);
+    else
+      _gdk_event_queue_insert_after (gdk_drawable_get_display (window), event_in_queue, event);
+    }
+  else
+    _gdk_event_queue_append (gdk_drawable_get_display (window), event);
+
+  return event;
 }
 
-/**
- * gdk_window_move_region:
- * @window: a #GdkWindow
- * @region: The #GdkRegion to move
- * @dx: Amount to move in the X direction
- * @dy: Amount to move in the Y direction
- *
- * Move the part of @window indicated by @region by @dy pixels in the Y
- * direction and @dx pixels in the X direction. The portions of @region
- * that not covered by the new position of @region are invalidated.
- *
- * Child windows are not moved.
- *
- * Since: 2.8
- */
-void
-gdk_window_move_region (GdkWindow       *window,
-                       const GdkRegion *region,
-                       gint             dx,
-                       gint             dy)
+static void
+send_crossing_event (GdkDisplay                 *display,
+                    GdkWindowObject            *toplevel,
+                    GdkWindowObject            *window,
+                    GdkEventType                type,
+                    GdkCrossingMode             mode,
+                    GdkNotifyType               notify_type,
+                    GdkWindow                  *subwindow,
+                    gint                        toplevel_x,
+                    gint                        toplevel_y,
+                    GdkModifierType             mask,
+                    guint32                     time_,
+                    GdkEvent                   *event_in_queue,
+                    gulong                      serial)
 {
-  GdkWindowObject *private = (GdkWindowObject *) window;
+  GdkEvent *event;
+  guint32 event_mask;
+  GdkPointerGrabInfo *grab;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  g_return_if_fail (region != NULL);
+  grab = _gdk_display_has_pointer_grab (display, serial);
 
-  if (dx == 0 && dy == 0)
+  if (grab != NULL &&
+      !grab->owner_events &&
+      (GdkWindow *)window != grab->window)
     return;
 
-  if (private->destroyed)
-    return;
+  if (type == GDK_LEAVE_NOTIFY)
+    event_mask = GDK_LEAVE_NOTIFY_MASK;
+  else
+    event_mask = GDK_ENTER_NOTIFY_MASK;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_region (window, region, dx, dy);
+  if (window->extension_events != 0)
+    GDK_WINDOW_IMPL_GET_IFACE (window->impl)->input_window_crossing ((GdkWindow *)window,
+                                                                    type == GDK_ENTER_NOTIFY);
+
+  if (window->event_mask & event_mask)
+    {
+      event = _gdk_make_event ((GdkWindow *)window, type, event_in_queue, TRUE);
+      event->crossing.time = time_;
+      event->crossing.subwindow = subwindow;
+      if (subwindow)
+       g_object_ref (subwindow);
+      convert_toplevel_coords_to_window ((GdkWindow *)window,
+                                        toplevel_x, toplevel_y,
+                                        &event->crossing.x, &event->crossing.y);
+      event->crossing.x_root = toplevel_x + toplevel->x;
+      event->crossing.y_root = toplevel_y + toplevel->y;
+      event->crossing.mode = mode;
+      event->crossing.detail = notify_type;
+      event->crossing.focus = FALSE;
+      event->crossing.state = mask;
+    }
 }
 
-/**
- * gdk_window_set_background:
- * @window: a #GdkWindow
- * @color: an allocated #GdkColor
- *
- * Sets the background color of @window. (However, when using GTK+,
- * set the background of a widget with gtk_widget_modify_bg() - if
- * you're an application - or gtk_style_set_background() - if you're
- * implementing a custom widget.)
- *
- * The @color must be allocated; gdk_rgb_find_color() is the best way
- * to allocate a color.
- *
- * See also gdk_window_set_back_pixmap().
+
+/* The coordinates are in the toplevel window that src/dest are in.
+ * src and dest are always (if != NULL) in the same toplevel, as
+ * we get a leave-notify and set the window_under_pointer to null
+ * before crossing to another toplevel.
  */
 void
-gdk_window_set_background (GdkWindow      *window,
-                          const GdkColor *color)
+_gdk_syntesize_crossing_events (GdkDisplay                 *display,
+                               GdkWindow                  *src,
+                               GdkWindow                  *dest,
+                               GdkCrossingMode             mode,
+                               gint                        toplevel_x,
+                               gint                        toplevel_y,
+                               GdkModifierType             mask,
+                               guint32                     time_,
+                               GdkEvent                   *event_in_queue,
+                               gulong                      serial)
 {
-  GdkWindowObject *private;
+  GdkWindowObject *c;
+  GdkWindowObject *win, *last, *next;
+  GList *path, *list;
+  gboolean non_linear;
+  GdkWindowObject *a;
+  GdkWindowObject *b;
+  GdkWindowObject *toplevel;
+  GdkNotifyType notify_type;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  /* TODO: Don't send events to toplevel, as we get those from the windowing system */
 
-  private = (GdkWindowObject *) window;
+  a = (GdkWindowObject *)src;
+  b = (GdkWindowObject *)dest;
+  if (a == b)
+    return; /* No crossings generated between src and dest */
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, color);
-}
+  c = find_common_ancestor (a, b);
 
-/**
- * gdk_window_set_back_pixmap:
- * @window: a #GdkWindow
- * @pixmap: a #GdkPixmap, or %NULL
- * @parent_relative: whether the tiling origin is at the origin of
- *   @window's parent
- *
- * Sets the background pixmap of @window. May also be used to set a
- * background of "None" on @window, by setting a background pixmap
- * of %NULL.
- *
- * A background pixmap will be tiled, positioning the first tile at
- * the origin of @window, or if @parent_relative is %TRUE, the tiling
- * will be done based on the origin of the parent window (useful to
- * align tiles in a parent with tiles in a child).
- *
- * A background pixmap of %NULL means that the window will have no
- * background.  A window with no background will never have its
- * background filled by the windowing system, instead the window will
- * contain whatever pixels were already in the corresponding area of
- * the display.
- *
- * The windowing system will normally fill a window with its background
- * when the window is obscured then exposed, and when you call
- * gdk_window_clear().
- */
-void
-gdk_window_set_back_pixmap (GdkWindow *window,
-                           GdkPixmap *pixmap,
-                           gboolean   parent_relative)
-{
-  GdkWindowObject *private;
+  non_linear = (c != a) && (c != b);
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  g_return_if_fail (pixmap == NULL || !parent_relative);
-  g_return_if_fail (pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap));
+  if (a) /* There might not be a source (i.e. if no previous pointer_in_window) */
+    {
+      toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)a);
 
-  private = (GdkWindowObject *) window;
+      /* Traverse up from a to (excluding) c sending leave events */
+      if (non_linear)
+       notify_type = GDK_NOTIFY_NONLINEAR;
+      else if (c == a)
+       notify_type = GDK_NOTIFY_INFERIOR;
+      else
+       notify_type = GDK_NOTIFY_ANCESTOR;
+      send_crossing_event (display, toplevel,
+                          a, GDK_LEAVE_NOTIFY,
+                          mode,
+                          notify_type,
+                          NULL,
+                          toplevel_x, toplevel_y,
+                          mask, time_,
+                          event_in_queue,
+                          serial);
+
+      if (c != a)
+       {
+         if (non_linear)
+           notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
+         else
+           notify_type = GDK_NOTIFY_VIRTUAL;
+
+         last = a;
+         win = get_event_parent (a);
+         while (win != c && GDK_WINDOW_TYPE (win) != GDK_WINDOW_ROOT)
+           {
+             send_crossing_event (display, toplevel,
+                                  win, GDK_LEAVE_NOTIFY,
+                                  mode,
+                                  notify_type,
+                                  (GdkWindow *)last,
+                                  toplevel_x, toplevel_y,
+                                  mask, time_,
+                                  event_in_queue,
+                                  serial);
+
+             last = win;
+             win = get_event_parent (win);
+           }
+       }
+    }
+
+  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);
+
+      /* Traverse down from c to b */
+      if (c != b)
+       {
+         path = NULL;
+         win = get_event_parent (b);
+         while (win != c && GDK_WINDOW_TYPE (win) != GDK_WINDOW_ROOT)
+           {
+             path = g_list_prepend (path, win);
+             win = get_event_parent (win);
+           }
+
+         if (non_linear)
+           notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
+         else
+           notify_type = GDK_NOTIFY_VIRTUAL;
+
+         list = path;
+         while (list)
+           {
+             win = (GdkWindowObject *)list->data;
+             list = g_list_next (list);
+             if (list)
+               next = (GdkWindowObject *)list->data;
+             else
+               next = b;
+
+             send_crossing_event (display, toplevel,
+                                  win, GDK_ENTER_NOTIFY,
+                                  mode,
+                                  notify_type,
+                                  (GdkWindow *)next,
+                                  toplevel_x, toplevel_y,
+                                  mask, time_,
+                                  event_in_queue,
+                                  serial);
+           }
+         g_list_free (path);
+       }
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, pixmap, parent_relative);
+
+      if (non_linear)
+       notify_type = GDK_NOTIFY_NONLINEAR;
+      else if (c == a)
+       notify_type = GDK_NOTIFY_ANCESTOR;
+      else
+       notify_type = GDK_NOTIFY_INFERIOR;
+
+      send_crossing_event (display, toplevel,
+                          b, GDK_ENTER_NOTIFY,
+                          mode,
+                          notify_type,
+                          NULL,
+                          toplevel_x, toplevel_y,
+                          mask, time_,
+                          event_in_queue,
+                          serial);
+    }
 }
 
-/**
- * gdk_window_set_cursor:
- * @window: a #GdkWindow
- * @cursor: a cursor
- *
- * Sets the mouse pointer for a #GdkWindow. Use gdk_cursor_new_for_display() 
- * or gdk_cursor_new_from_pixmap() to create the cursor. To make the cursor 
- * invisible, use %GDK_BLANK_CURSOR. Passing %NULL for the @cursor argument 
- * to gdk_window_set_cursor() means that @window will use the cursor of its 
- * parent window. Most windows should use this default.
+/* Returns the window inside the event window with the pointer in it
+ * at the specified coordinates, or NULL if its not in any child of
+ * the toplevel. It also takes into account !owner_events grabs.
  */
-void
-gdk_window_set_cursor (GdkWindow *window,
-                      GdkCursor *cursor)
+static GdkWindow *
+get_pointer_window (GdkDisplay *display,
+                   GdkWindow *event_window,
+                   gdouble toplevel_x,
+                   gdouble toplevel_y,
+                   gulong serial)
 {
-  GdkWindowObject *private;
-
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  GdkWindow *pointer_window;
+  GdkPointerGrabInfo *grab;
+
+  if (event_window == display->pointer_info.toplevel_under_pointer)
+    pointer_window =
+      _gdk_window_find_descendant_at (event_window,
+                                     toplevel_x, toplevel_y,
+                                     NULL, NULL);
+  else
+    pointer_window = NULL;
 
-  private = (GdkWindowObject *) window;
+  grab = _gdk_display_has_pointer_grab (display, serial);
+  if (grab != NULL &&
+      !grab->owner_events &&
+      pointer_window != grab->window)
+    pointer_window = NULL;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_cursor (window, cursor);
+  return pointer_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
- *
- * Any of the return location arguments to this function may be %NULL,
- * if you aren't interested in getting the value of that field.
- *
- * The X and Y coordinates returned are relative to the parent window
- * of @window, which for toplevels usually means relative to the
- * window decorations (titlebar, etc.) rather than relative to the
- * root window (screen-size background window).
- *
- * On the X11 platform, the geometry is obtained from the X server,
- * so reflects the latest position of @window; this may be out-of-sync
- * with the position of @window delivered in the most-recently-processed
- * #GdkEventConfigure. gdk_window_get_position() in contrast gets the
- * position from the most recent configure event.
- *
- * <note>
- * If @window is not a toplevel, it is <emphasis>much</emphasis> better
- * to call gdk_window_get_position() and gdk_drawable_get_size() instead,
- * because it avoids the roundtrip to the X server and because
- * gdk_drawable_get_size() supports the full 32-bit coordinate space,
- * whereas gdk_window_get_geometry() is restricted to the 16-bit
- * coordinates of X11.
- *</note>
- **/
 void
-gdk_window_get_geometry (GdkWindow *window,
-                        gint      *x,
-                        gint      *y,
-                        gint      *width,
-                        gint      *height,
-                        gint      *depth)
+_gdk_display_set_window_under_pointer (GdkDisplay *display,
+                                      GdkWindow *window)
 {
   GdkWindowObject *private;
 
-  if (!window)
-    {
-      GDK_NOTE (MULTIHEAD,
-               g_message ("gdk_window_get_geometry(): Window needs "
-                           "to be non-NULL to be multi head safe"));
-      window = gdk_screen_get_root_window ((gdk_screen_get_default ()));
-    }
+  private = (GdkWindowObject *)window;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  if (display->pointer_info.window_under_pointer)
+    g_object_unref (display->pointer_info.window_under_pointer);
+  display->pointer_info.window_under_pointer = window;
+  if (window)
+    g_object_ref (window);
 
-  private = (GdkWindowObject *) window;
+  if (window)
+    update_cursor (display);
 
-  if (!GDK_WINDOW_DESTROYED (window))
-    {
-      GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_geometry (window, x, y,
-                                                              width, height,
-                                                               depth);
-    }
+  _gdk_display_enable_motion_hints (display);
 }
 
-/**
- * gdk_window_get_origin:
- * @window: a #GdkWindow
- * @x: return location for X coordinate
- * @y: return location for Y coordinate
- *
- * Obtains the position of a window in root window coordinates.
- * (Compare with gdk_window_get_position() and
- * gdk_window_get_geometry() which return the position of a window
- * relative to its parent window.)
- *
- * Return value: not meaningful, ignore
- */
-gint
-gdk_window_get_origin (GdkWindow *window,
-                      gint      *x,
-                      gint      *y)
+static GdkWindow *
+gdk_window_get_offscreen_parent (GdkWindow *window)
 {
-  GdkWindowObject *private;
-
-  g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindow *res;
 
-  private = (GdkWindowObject *) window;
+  res = NULL;
+  g_signal_emit_by_name (private->impl_window,
+                        "get-offscreen-parent",
+                        &res);
 
-  return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_origin (window, x, y);
+  return res;
 }
 
-/**
- * gdk_window_shape_combine_mask:
- * @window: a #GdkWindow
- * @mask: shape mask
- * @x: X position of shape mask with respect to @window
- * @y: Y position of shape mask with respect to @window
+/*
+ *--------------------------------------------------------------
+ * gdk_pointer_grab
  *
- * Applies a shape mask to @window. Pixels in @window corresponding to
- * set bits in the @mask will be visible; pixels in @window
- * corresponding to unset bits in the @mask will be transparent. This
- * gives a non-rectangular window.
+ *   Grabs the pointer to a specific window
  *
- * If @mask is %NULL, the shape mask will be unset, and the @x/@y
- * parameters are not used.
+ * Arguments:
+ *   "window" is the window which will receive the grab
+ *   "owner_events" specifies whether events will be reported as is,
+ *     or relative to "window"
+ *   "event_mask" masks only interesting events
+ *   "confine_to" limits the cursor movement to the specified window
+ *   "cursor" changes the cursor for the duration of the grab
+ *   "time" specifies the time
  *
- * On the X11 platform, this uses an X server extension which is
- * widely available on most common platforms, but not available on
- * very old X servers, and occasionally the implementation will be
- * buggy. On servers without the shape extension, this function
- * will do nothing.
+ * Results:
  *
- * This function works on both toplevel and child windows.
+ * Side effects:
+ *   requires a corresponding call to gdk_pointer_ungrab
+ *
+ *--------------------------------------------------------------
  */
-void
-gdk_window_shape_combine_mask (GdkWindow *window,
-                              GdkBitmap *mask,
-                              gint       x,
-                               gint       y)
+GdkGrabStatus
+gdk_pointer_grab (GdkWindow *    window,
+                 gboolean        owner_events,
+                 GdkEventMask    event_mask,
+                 GdkWindow *     confine_to,
+                 GdkCursor *     cursor,
+                 guint32         time)
 {
-  GdkWindowObject *private;
+  GdkWindow *native;
+  GdkDisplay *display;
+  GdkGrabStatus res;
+  gulong serial;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_val_if_fail (window != NULL, 0);
+  g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
+  g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
 
-  private = (GdkWindowObject *) window;
+  /* We need a native window for confine to to work, ensure we have one */
+  if (confine_to)
+    {
+      if (!gdk_window_ensure_native (confine_to))
+       {
+         g_warning ("Can't confine to grabbed window, not native");
+         confine_to = NULL;
+       }
+    }
+
+  /* Non-viewable client side window => fail */
+  if (!_gdk_window_has_impl (window) &&
+      !gdk_window_is_viewable (window))
+    return GDK_GRAB_NOT_VIEWABLE;
+
+  native = gdk_window_get_toplevel (window);
+  while (gdk_window_is_offscreen ((GdkWindowObject *)native))
+    {
+      native = gdk_window_get_offscreen_parent (native);
+
+      if (native == NULL ||
+         (!_gdk_window_has_impl (native) &&
+          !gdk_window_is_viewable (native)))
+       return GDK_GRAB_NOT_VIEWABLE;
+
+      native = gdk_window_get_toplevel (native);
+    }
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_mask (window, mask, x, y);
+  display = gdk_drawable_get_display (window);
+
+  serial = _gdk_windowing_window_get_next_serial (display);
+
+  res = _gdk_windowing_pointer_grab (window,
+                                    native,
+                                    owner_events,
+                                    event_mask,
+                                    confine_to,
+                                    cursor,
+                                    time);
+
+  if (res == GDK_GRAB_SUCCESS)
+    _gdk_display_add_pointer_grab (display,
+                                  window,
+                                  native,
+                                  owner_events,
+                                  event_mask,
+                                  serial,
+                                  time,
+                                  FALSE);
+
+  return res;
 }
 
-/**
- * gdk_window_shape_combine_region:
- * @window: a #GdkWindow
- * @shape_region: region of window to be non-transparent
- * @offset_x: X position of @shape_region in @window coordinates
- * @offset_y: Y position of @shape_region in @window coordinates
- *
- * Makes pixels in @window outside @shape_region be transparent,
- * so that the window may be nonrectangular. See also
- * gdk_window_shape_combine_mask() to use a bitmap as the mask.
- *
- * If @shape_region is %NULL, the shape will be unset, so the whole
- * window will be opaque again. @offset_x and @offset_y are ignored
- * if @shape_region is %NULL.
- *
- * On the X11 platform, this uses an X server extension which is
- * widely available on most common platforms, but not available on
- * very old X servers, and occasionally the implementation will be
- * buggy. On servers without the shape extension, this function
- * will do nothing.
- *
- * This function works on both toplevel and child windows.
- */
 void
-gdk_window_shape_combine_region (GdkWindow       *window,
-                                 const GdkRegion *shape_region,
-                                 gint             offset_x,
-                                 gint             offset_y)
+gdk_window_set_has_offscreen_children (GdkWindow *window,
+                                      gboolean has_offscreen_children)
 {
-  GdkWindowObject *private;
+  GdkWindowObject *private = (GdkWindowObject *)window;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  private->has_offscreen_children = !!has_offscreen_children;
+}
 
-  private = (GdkWindowObject *) window;
+gboolean
+gdk_window_get_has_offscreen_children (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region (window, shape_region, offset_x, offset_y);
+  return private->has_offscreen_children;
 }
 
-/**
- * gdk_window_set_child_shapes:
- * @window: a #GdkWindow
- *
- * Sets the shape mask of @window to the union of shape masks
- * for all children of @window, ignoring the shape mask of @window
- * itself. Contrast with gdk_window_merge_child_shapes() which includes
- * the shape mask of @window in the masks to be merged.
- **/
 void
-gdk_window_set_child_shapes (GdkWindow *window)
+gdk_window_offscreen_children_changed (GdkWindow *window)
 {
-  GdkWindowObject *private;
+  _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+static gboolean
+do_synthesize_crossing_event (gpointer data)
+{
+  GdkDisplay *display;
+  GdkWindow *changed_toplevel;
+  GdkWindowObject *changed_toplevel_priv;
+  GdkWindow *new_window_under_pointer;
+  gulong serial;
 
-  private = (GdkWindowObject *) window;
+  changed_toplevel = data;
+  changed_toplevel_priv = (GdkWindowObject *)changed_toplevel;
+
+  changed_toplevel_priv->synthesize_crossing_event_queued = FALSE;
+
+  if (GDK_WINDOW_DESTROYED (changed_toplevel))
+    return FALSE;
+
+  display = gdk_drawable_get_display (changed_toplevel);
+  serial = _gdk_windowing_window_get_next_serial (display);
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_child_shapes (window);
+  if (changed_toplevel == display->pointer_info.toplevel_under_pointer)
+    {
+      new_window_under_pointer =
+       get_pointer_window (display, changed_toplevel,
+                           display->pointer_info.toplevel_x,
+                           display->pointer_info.toplevel_y,
+                           serial);
+      if (new_window_under_pointer !=
+         display->pointer_info.window_under_pointer)
+       {
+         _gdk_syntesize_crossing_events (display,
+                                         display->pointer_info.window_under_pointer,
+                                         new_window_under_pointer,
+                                         GDK_CROSSING_NORMAL,
+                                         display->pointer_info.toplevel_x,
+                                         display->pointer_info.toplevel_y,
+                                         display->pointer_info.state,
+                                         GDK_CURRENT_TIME,
+                                         NULL,
+                                         serial);
+         _gdk_display_set_window_under_pointer (display, new_window_under_pointer);
+       }
+    }
+
+  return FALSE;
 }
 
-/**
- * gdk_window_merge_child_shapes:
- * @window: a #GdkWindow
- *
- * Merges the shape masks for any child windows into the
- * shape mask for @window. i.e. the union of all masks
- * for @window and its children will become the new mask
- * for @window. See gdk_window_shape_combine_mask().
- *
- * This function is distinct from gdk_window_set_child_shapes()
- * because it includes @window's shape mask in the set of shapes to
- * be merged.
- */
 void
-gdk_window_merge_child_shapes (GdkWindow *window)
+_gdk_syntesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
 {
-  GdkWindowObject *private;
+  GdkDisplay *display;
+  GdkWindow *toplevel;
+  GdkWindowObject *toplevel_priv;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  display = gdk_drawable_get_display (changed_window);
 
-  private = (GdkWindowObject *) window;
+  toplevel = get_event_toplevel (changed_window);
+  toplevel_priv = (GdkWindowObject *)toplevel;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->merge_child_shapes (window);
+  if (toplevel == display->pointer_info.toplevel_under_pointer &&
+      !toplevel_priv->synthesize_crossing_event_queued)
+    {
+      toplevel_priv->synthesize_crossing_event_queued = TRUE;
+      g_idle_add_full (GDK_PRIORITY_EVENTS - 1,
+                      do_synthesize_crossing_event,
+                      g_object_ref (toplevel),
+                      g_object_unref);
+    }
 }
 
-
-/**
- * gdk_window_set_static_gravities:
- * @window: a #GdkWindow
- * @use_static: %TRUE to turn on static gravity
- *
- * Set the bit gravity of the given window to static, and flag it so
- * all children get static subwindow gravity. This is used if you are
- * implementing scary features that involve deep knowledge of the
- * windowing system. Don't worry about it unless you have to.
- *
- * Return value: %TRUE if the server supports static gravity
- */
-gboolean
-gdk_window_set_static_gravities (GdkWindow *window,
-                                gboolean   use_static)
+/* Don't use for crossing events */
+static GdkWindow *
+get_event_window (GdkDisplay                 *display,
+                 GdkWindow                  *pointer_window,
+                 GdkEventType                type,
+                 GdkModifierType             mask,
+                 guint                      *evmask_out,
+                 gulong                      serial)
 {
-  GdkWindowObject *private;
+  guint evmask;
+  GdkWindow *grab_window;
+  GdkWindowObject *w;
+  GdkPointerGrabInfo *grab;
 
-  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+  grab = _gdk_display_has_pointer_grab (display, serial);
 
-  private = (GdkWindowObject *) window;
+  if (grab != NULL && !grab->owner_events)
+    {
+      evmask = grab->event_mask;
+      evmask = update_evmask_for_button_motion (evmask, mask);
 
-  return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_static_gravities (window, use_static);
-}
+      grab_window = grab->window;
 
-/**
- * gdk_window_set_composited:
- * @window: a #GdkWindow
- * @composited: %TRUE to set the window as composited
- *
- * Sets a #GdkWindow as composited, or unsets it. Composited 
- * windows do not automatically have their contents drawn to 
- * the screen. Drawing is redirected to an offscreen buffer 
- * and an expose event is emitted on the parent of the composited 
- * window. It is the responsibility of the parent's expose handler
- * to manually merge the off-screen content onto the screen in
- * whatever way it sees fit. See <xref linkend="composited-window-example"/>
- * for an example.
- *
- * It only makes sense for child windows to be composited; see
- * gdk_window_set_opacity() if you need translucent toplevel
- * windows.
- *
- * An additional effect of this call is that the area of this
- * window is no longer clipped from regions marked for
- * invalidation on its parent. Draws done on the parent
- * window are also no longer clipped by the child.
- *
- * This call is only supported on some systems (currently,
- * only X11 with new enough Xcomposite and Xdamage extensions). 
- * You must call gdk_display_supports_composite() to check if
- * setting a window as composited is supported before
- * attempting to do so.
- *
- * Since: 2.12
- */
-void
-gdk_window_set_composited (GdkWindow *window,
-                           gboolean   composited)
-{
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkDisplay *display;
+      if (evmask & type_masks[type])
+       {
+         if (evmask_out)
+           *evmask_out = evmask;
+         return grab_window;
+       }
+      else
+       return NULL;
+    }
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  w = (GdkWindowObject *)pointer_window;
+  while (w != NULL)
+    {
+      evmask = w->event_mask;
+      evmask = update_evmask_for_button_motion (evmask, mask);
 
-  composited = composited != FALSE;
+      if (evmask & type_masks[type])
+       {
+         if (evmask_out)
+           *evmask_out = evmask;
+         return (GdkWindow *)w;
+       }
 
-  if (private->composited == composited)
-    return;
+      w = get_event_parent (w);
+    }
 
-  display = gdk_drawable_get_display (GDK_DRAWABLE (window));
+  if (grab != NULL &&
+      grab->owner_events)
+    {
+      evmask = grab->event_mask;
+      evmask = update_evmask_for_button_motion (evmask, mask);
 
-  if (!gdk_display_supports_composite (display) && composited)
+      if (evmask & type_masks[type])
+       {
+         if (evmask_out)
+           *evmask_out = evmask;
+         return grab->window;
+       }
+      else
+       return NULL;
+    }
+
+  return NULL;
+}
+
+static gboolean
+proxy_pointer_event (GdkDisplay                 *display,
+                    GdkEvent                   *source_event,
+                    gulong                      serial)
+{
+  GdkWindow *toplevel_window, *event_window;
+  GdkWindow *pointer_window;
+  GdkEvent *event;
+  guint state;
+  gdouble toplevel_x, toplevel_y;
+  guint32 time_;
+
+  event_window = source_event->any.window;
+  gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
+  gdk_event_get_state (source_event, &state);
+  time_ = gdk_event_get_time (source_event);
+  toplevel_window = convert_native_coords_to_toplevel (event_window,
+                                                      toplevel_x, toplevel_y,
+                                                      &toplevel_x, &toplevel_y);
+
+
+  /* If we get crossing events with subwindow unexpectedly being NULL
+     that means there is a native subwindow that gdk doesn't know about.
+     We track these and forward them, with the correct virtual window
+     events inbetween.
+     This is important to get right, as metacity uses gdk for the frame
+     windows, but gdk doesn't know about the client windows reparented
+     into the frame. */
+  if (((source_event->type == GDK_LEAVE_NOTIFY &&
+       source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
+       (source_event->type == GDK_ENTER_NOTIFY &&
+       (source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
+        source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
+      source_event->crossing.subwindow == NULL)
     {
-      g_warning ("gdk_window_set_composited called but "
-                "compositing is not supported");
-      return;
+      /* Left for an unknown (to gdk) subwindow */
+
+      /* Send leave events from window under pointer to event window
+        that will get the subwindow == NULL window */
+      _gdk_syntesize_crossing_events (display,
+                                     display->pointer_info.window_under_pointer,
+                                     event_window,
+                                     source_event->crossing.mode,
+                                     toplevel_x, toplevel_y,
+                                     state, time_,
+                                     source_event,
+                                     serial);
+
+      /* Send subwindow == NULL event */
+      send_crossing_event (display,
+                          (GdkWindowObject *)toplevel_window,
+                          (GdkWindowObject *)event_window,
+                          source_event->type,
+                          source_event->crossing.mode,
+                          source_event->crossing.detail,
+                          NULL,
+                          toplevel_x,   toplevel_y,
+                          state, time_,
+                          source_event,
+                          serial);
+
+      _gdk_display_set_window_under_pointer (display, NULL);
+      return TRUE;
     }
 
-  _gdk_windowing_window_set_composited (window, composited);
+  pointer_window = get_pointer_window (display, toplevel_window,
+                                      toplevel_x, toplevel_y, serial);
 
-  private->composited = composited;
+  if (((source_event->type == GDK_ENTER_NOTIFY &&
+       source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
+       (source_event->type == GDK_LEAVE_NOTIFY &&
+       (source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
+        source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
+      source_event->crossing.subwindow == NULL)
+    {
+      /* Entered from an unknown (to gdk) subwindow */
+
+      /* Send subwindow == NULL event */
+      send_crossing_event (display,
+                          (GdkWindowObject *)toplevel_window,
+                          (GdkWindowObject *)event_window,
+                          source_event->type,
+                          source_event->crossing.mode,
+                          source_event->crossing.detail,
+                          NULL,
+                          toplevel_x,   toplevel_y,
+                          state, time_,
+                          source_event,
+                          serial);
+
+      /* Send enter events from event window to pointer_window */
+      _gdk_syntesize_crossing_events (display,
+                                     event_window,
+                                     pointer_window,
+                                     source_event->crossing.mode,
+                                     toplevel_x, toplevel_y,
+                                     state, time_,
+                                     source_event,
+                                     serial);
+      _gdk_display_set_window_under_pointer (display, pointer_window);
+      return TRUE;
+    }
+
+  if (display->pointer_info.window_under_pointer != pointer_window)
+    {
+      /* Either a toplevel crossing notify that ended up inside a child window,
+        or a motion notify that got into another child window  */
+
+      /* Different than last time, send crossing events */
+      _gdk_syntesize_crossing_events (display,
+                                     display->pointer_info.window_under_pointer,
+                                     pointer_window,
+                                     GDK_CROSSING_NORMAL,
+                                     toplevel_x, toplevel_y,
+                                     state, time_,
+                                     source_event,
+                                     serial);
+      _gdk_display_set_window_under_pointer (display, pointer_window);
+    }
+  else if (source_event->type == GDK_MOTION_NOTIFY)
+    {
+      GdkWindow *event_win;
+      guint evmask;
+      gboolean is_hint;
+
+      event_win = get_event_window (display,
+                                   pointer_window,
+                                   source_event->type,
+                                   state,
+                                   &evmask,
+                                   serial);
+
+      is_hint = FALSE;
+
+      if (event_win &&
+         (evmask & GDK_POINTER_MOTION_HINT_MASK))
+       {
+         if (display->pointer_info.motion_hint_serial != 0 &&
+             serial < display->pointer_info.motion_hint_serial)
+           event_win = NULL; /* Ignore event */
+         else
+           {
+             is_hint = TRUE;
+             display->pointer_info.motion_hint_serial = G_MAXULONG;
+           }
+       }
+
+      if (event_win && !display->ignore_core_events)
+       {
+         event = _gdk_make_event (event_win, GDK_MOTION_NOTIFY, source_event, FALSE);
+         event->motion.time = time_;
+         convert_toplevel_coords_to_window (event_win,
+                                            toplevel_x, toplevel_y,
+                                            &event->motion.x, &event->motion.y);
+         event->motion.x_root = source_event->motion.x_root;
+         event->motion.y_root = source_event->motion.y_root;;
+         event->motion.state = state;
+         event->motion.is_hint = is_hint;
+         event->motion.device = NULL;
+         event->motion.device = source_event->motion.device;
+       }
+    }
+
+  /* unlink all move events from queue.
+     We handle our own, including our emulated masks. */
+  return TRUE;
 }
 
+#define GDK_ANY_BUTTON_MASK (GDK_BUTTON1_MASK | \
+                            GDK_BUTTON2_MASK | \
+                            GDK_BUTTON3_MASK | \
+                            GDK_BUTTON4_MASK | \
+                            GDK_BUTTON5_MASK)
 
-static void
-remove_redirect_from_children (GdkWindowObject   *private,
-                               GdkWindowRedirect *redirect)
+static gboolean
+proxy_button_event (GdkEvent *source_event,
+                   gulong serial)
 {
-  GList *l;
-  GdkWindowObject *child;
-
-  for (l = private->children; l != NULL; l = l->next)
+  GdkWindow *toplevel_window, *event_window;
+  GdkWindow *event_win;
+  GdkWindow *pointer_window;
+  GdkWindowObject *parent;
+  GdkEvent *event;
+  guint state;
+  guint32 time_;
+  GdkEventType type;
+  gdouble toplevel_x, toplevel_y;
+  GdkDisplay *display;
+  GdkWindowObject *w;
+
+  type = source_event->any.type;
+  event_window = source_event->any.window;
+  gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
+  gdk_event_get_state (source_event, &state);
+  time_ = gdk_event_get_time (source_event);
+  display = gdk_drawable_get_display (source_event->any.window);
+  toplevel_window = convert_native_coords_to_toplevel (event_window,
+                                                      toplevel_x, toplevel_y,
+                                                      &toplevel_x, &toplevel_y);
+
+  if (type == GDK_BUTTON_PRESS &&
+      _gdk_display_has_pointer_grab (display, serial) == NULL)
     {
-      child = l->data;
-
-      /* Don't redirect this child if it already has another redirect */
-      if (child->redirect == redirect)
+      pointer_window =
+       _gdk_window_find_descendant_at (toplevel_window,
+                                       toplevel_x, toplevel_y,
+                                       NULL, NULL);
+
+      /* Find the event window, that gets the grab */
+      w = (GdkWindowObject *)pointer_window;
+      while (w != NULL &&
+            (parent = get_event_parent (w)) != NULL &&
+            parent->window_type != GDK_WINDOW_ROOT)
        {
-         child->redirect = NULL;
-         remove_redirect_from_children (child, redirect);
+         if (w->event_mask & GDK_BUTTON_PRESS_MASK)
+           break;
+         w = parent;
        }
+      pointer_window = (GdkWindow *)w;
+
+      _gdk_display_add_pointer_grab  (display,
+                                     pointer_window,
+                                     toplevel_window,
+                                     FALSE,
+                                     gdk_window_get_events (pointer_window),
+                                     serial,
+                                     time_,
+                                     TRUE);
+      _gdk_display_pointer_grab_update (display, serial);
     }
-}
 
-/**
- * gdk_window_remove_redirection:
- * @window: a #GdkWindow
- *
- * Removes any active redirection started by
- * gdk_window_redirect_to_drawable().
- *
- * Since: 2.14
- **/
-void
-gdk_window_remove_redirection (GdkWindow *window)
-{
-  GdkWindowObject *private;
+  pointer_window = get_pointer_window (display, toplevel_window,
+                                      toplevel_x, toplevel_y,
+                                      serial);
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  event_win = get_event_window (display,
+                               pointer_window,
+                               type, state,
+                               NULL, serial);
 
-  private = (GdkWindowObject *) window;
+  if (event_win == NULL || display->ignore_core_events)
+    return TRUE;
 
-  if (private->redirect &&
-      private->redirect->redirected == private)
+  event = _gdk_make_event (event_win, type, source_event, FALSE);
+
+  switch (type)
     {
-      remove_redirect_from_children (private, private->redirect);
-      gdk_window_redirect_free (private->redirect);
-      private->redirect = NULL;
+    case GDK_BUTTON_PRESS:
+    case GDK_BUTTON_RELEASE:
+      event->button.button = source_event->button.button;
+      convert_toplevel_coords_to_window (event_win,
+                                        toplevel_x, toplevel_y,
+                                        &event->button.x, &event->button.y);
+      event->button.x_root = source_event->button.x_root;
+      event->button.y_root = source_event->button.y_root;
+      event->button.state = state;
+      event->button.device = source_event->button.device;
+
+      if (type == GDK_BUTTON_PRESS)
+       _gdk_event_button_generate (display, event);
+      return TRUE;
+
+    case GDK_SCROLL:
+      event->scroll.direction = source_event->scroll.direction;
+      convert_toplevel_coords_to_window (event_win,
+                                        toplevel_x, toplevel_y,
+                                        &event->scroll.x, &event->scroll.y);
+      event->scroll.x_root = source_event->scroll.x_root;
+      event->scroll.y_root = source_event->scroll.y_root;
+      event->scroll.state = state;
+      event->scroll.device = source_event->scroll.device;
+      return TRUE;
+
+    default:
+      return FALSE;
     }
+
+  return TRUE; /* Always unlink original, we want to obey the emulated event mask */
 }
 
+#ifdef DEBUG_WINDOW_PRINTING
 static void
-apply_redirect_to_children (GdkWindowObject   *private,
-                            GdkWindowRedirect *redirect)
+gdk_window_print (GdkWindowObject *window,
+                 int indent)
 {
-  GList *l;
-  GdkWindowObject *child;
+  GdkRectangle r;
 
-  for (l = private->children; l != NULL; l = l->next)
-    {
-      child = l->data;
+  g_print ("%*s%p: [%s] %d,%d %dx%d", indent, "", window,
+          window->user_data ? g_type_name_from_instance (window->user_data) : "no widget",
+          window->x, window->y,
+          window->width, window->height
+          );
 
-      /* Don't redirect this child if it already has another redirect */
-      if (!child->redirect)
-       {
-         child->redirect = redirect;
-         apply_redirect_to_children (child, redirect);
-       }
+  if (gdk_window_has_impl (window))
+    {
+#ifdef GDK_WINDOWING_X11
+      g_print (" impl(0x%lx)", gdk_x11_drawable_get_xid (GDK_DRAWABLE (window)));
+#endif
     }
+
+  if (window->input_only)
+    g_print (" input-only");
+
+  if (!gdk_window_is_visible ((GdkWindow *)window))
+    g_print (" hidden");
+
+  g_print (" abs[%d,%d]",
+          window->abs_x, window->abs_y);
+
+  gdk_region_get_clipbox (window->clip_region, &r);
+  if (gdk_region_empty (window->clip_region))
+    g_print (" clipbox[empty]");
+  else
+    g_print (" clipbox[%d,%d %dx%d]", r.x, r.y, r.width, r.height);
+
+  g_print ("\n");
 }
 
-/**
- * gdk_window_redirect_to_drawable:
- * @window: a #GdkWindow
- * @drawable: a #GdkDrawable
- * @src_x: x position in @window
- * @src_y: y position in @window
- * @dest_x: x position in @drawable
- * @dest_y: y position in @drawable
- * @width: width of redirection
- * @height: height of redirection
- *
- * Redirects drawing into @window so that drawing to the
- * window in the rectangle specified by @src_x, @src_y,
- * @width and @height is also drawn into @drawable at
- * @dest_x, @dest_y.
- *
- * Only drawing between gdk_window_begin_paint_region() or
- * gdk_window_begin_paint_rect() and gdk_window_end_paint() is
- * redirected.
- *
- * Redirection is active until gdk_window_remove_redirection()
- * is called.
- *
- * Since: 2.14
- **/
-void
-gdk_window_redirect_to_drawable (GdkWindow   *window,
-                                GdkDrawable *drawable,
-                                gint         src_x,
-                                 gint         src_y,
-                                gint         dest_x,
-                                 gint         dest_y,
-                                gint         width,
-                                 gint         height)
+
+static void
+gdk_window_print_tree (GdkWindow *window,
+                      int indent,
+                      gboolean include_input_only)
 {
   GdkWindowObject *private;
-  
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  g_return_if_fail (GDK_IS_DRAWABLE (drawable));
-  g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
+  GList *l;
 
-  private = (GdkWindowObject *) window;
+  private = (GdkWindowObject *)window;
 
-  if (private->redirect)
-    gdk_window_remove_redirection (window);
+  if (private->input_only && !include_input_only)
+    return;
 
-  if (width == -1 || height == -1)
-    {
-      gint w, h;
-      gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
-      if (width == -1)
-       width = w;
-      if (height == -1)
-       height = h;
-    }
-  
-  private->redirect = g_new0 (GdkWindowRedirect, 1);
-  private->redirect->redirected = private;
-  private->redirect->pixmap = g_object_ref (drawable);
-  private->redirect->src_x = src_x;
-  private->redirect->src_y = src_y;
-  private->redirect->dest_x = dest_x;
-  private->redirect->dest_y = dest_y;
-  private->redirect->width = width;
-  private->redirect->height = height;
+  gdk_window_print (private, indent);
 
-  apply_redirect_to_children (private, private->redirect);
+  for (l = private->children; l != NULL; l = l->next)
+    gdk_window_print_tree (l->data, indent + 4, include_input_only);
 }
 
-static void
-window_get_size_rectangle (GdkWindow    *window,
-                           GdkRectangle *rect)
+#endif /* DEBUG_WINDOW_PRINTING */
+
+static gboolean
+is_input_event (GdkDisplay *display,
+               GdkEvent *event)
 {
-  rect->x = rect->y = 0;
-  gdk_drawable_get_size (GDK_DRAWABLE (window), &rect->width, &rect->height);
+  GdkDevice *core_pointer;
+
+  core_pointer = gdk_display_get_core_pointer (display);
+  if ((event->type == GDK_MOTION_NOTIFY &&
+       event->motion.device != core_pointer) ||
+      ((event->type == GDK_BUTTON_PRESS ||
+       event->type == GDK_BUTTON_RELEASE) &&
+       event->button.device != core_pointer))
+    return TRUE;
+  return FALSE;
 }
 
-/* Calculates the real clipping region for a window, in window coordinates,
- * taking into account other windows, gc clip region and gc clip mask.
- */
-static GdkRegion *
-_gdk_window_calculate_full_clip_region (GdkWindow *window,
-                                       GdkWindow *base_window,
-                                       GdkGC *gc,
-                                       gboolean do_children,
-                                       gint *base_x_offset,
-                                       gint *base_y_offset)
+void
+_gdk_windowing_got_event (GdkDisplay *display,
+                         GList      *event_link,
+                         GdkEvent   *event,
+                         gulong      serial)
 {
-  GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
-  GdkRectangle visible_rect;
-  GdkRegion *real_clip_region, *tmpreg;
-  gint x_offset, y_offset;
-  GdkWindowObject *parentwin, *lastwin;
+  GdkWindow *event_window;
+  GdkWindowObject *event_private;
+  gdouble x, y;
+  gboolean unlink_event;
+  guint old_state, old_button;
+  GdkPointerGrabInfo *button_release_grab;
+  gboolean is_toplevel;
+
+  if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
+    display->last_event_time = gdk_event_get_time (event);
+
+  _gdk_display_pointer_grab_update (display,
+                                   serial);
+
+  event_window = event->any.window;
+  if (!event_window)
+    return;
 
-  if (base_x_offset)
-    *base_x_offset = 0;
-  if (base_y_offset)
-    *base_y_offset = 0;
-  
-  if (!GDK_WINDOW_IS_MAPPED (window) || private->input_only)
-    return gdk_region_new ();
+  event_private = GDK_WINDOW_OBJECT (event_window);
 
-  window_get_size_rectangle (window, &visible_rect);
+#ifdef DEBUG_WINDOW_PRINTING
+  if (event->type == GDK_KEY_PRESS &&
+      (event->key.keyval == 0xa7 ||
+       event->key.keyval == 0xbd))
+    {
+      gdk_window_print_tree (event_window, 0,
+                            event->key.keyval == 0xbd);
+    }
+#endif
 
-  /* windows that a redirection has ben setup for need to be considered
-   * fully visible, in order to avoid missing redirected paint ops
-   * anywhere in the window area.
-   */
-  if (private->redirect && private->redirect->redirected == private)
-    return gdk_region_rectangle (&visible_rect);
+  if (event->type == GDK_VISIBILITY_NOTIFY)
+    {
+      event_private->native_visibility = event->visibility.state;
+      gdk_window_update_visibility_recursively (event_private,
+                                               event_private);
+      return;
+    }
 
-  /* real_clip_region is in window coordinates */
-  real_clip_region = gdk_region_rectangle (&visible_rect);
+  if (is_input_event (display, event))
+    return;
 
-  x_offset = y_offset = 0;
+  if (!(is_button_type (event->type) ||
+       is_motion_type (event->type)) ||
+      GDK_WINDOW_TYPE (event_private) == GDK_WINDOW_ROOT)
+    return;
 
-  lastwin = private;
-  if (do_children)
-    parentwin = lastwin;
-  else
-    parentwin = lastwin->parent;
-  
-  /* Remove the areas of all overlapping windows above parentwin in the hiearachy */
-  for (; parentwin != NULL && (parentwin == private || lastwin != (GdkWindowObject *)base_window);
-       lastwin = parentwin, parentwin = lastwin->parent)
+  is_toplevel =
+    event_private->parent == NULL ||
+    GDK_WINDOW_TYPE (event_private->parent) == GDK_WINDOW_ROOT;
+
+  if ((event->type == GDK_ENTER_NOTIFY ||
+       event->type == GDK_LEAVE_NOTIFY) &&
+      (event->crossing.mode == GDK_CROSSING_GRAB ||
+       event->crossing.mode == GDK_CROSSING_UNGRAB) &&
+      (_gdk_display_has_pointer_grab (display, serial) ||
+       event->crossing.detail == GDK_NOTIFY_INFERIOR))
     {
-      GList *cur;
-      GdkRectangle real_clip_rect;
-      
-      if (parentwin != private)
+      /* We synthesize all crossing events due to grabs outselves,
+       * so we ignore the native ones caused by our native pointer_grab
+       * calls. Otherwise we would proxy these crossing event and cause
+       * multiple copies of crossing events for grabs.
+       *
+       * We do want to handle grabs from other clients though, as for
+       * instance alt-tab in metacity causes grabs like these and
+       * we want to handle those. Thus the has_pointer_grab check.
+       *
+       * Implicit grabs on child windows create some grabbing events
+       * that are sent before the button press. This means we can't
+       * detect these with the has_pointer_grab check (as the implicit
+       * grab is only noticed when we get button press event), so we
+       * detect these events by checking for INFERIOR enter or leave
+       * events. These should never be a problem to filter out.
+       */
+
+      /* We ended up in this window after some (perhaps other clients)
+        grab, so update the toplevel_under_window state */
+      if (is_toplevel &&
+         event->type == GDK_ENTER_NOTIFY &&
+         event->crossing.mode == GDK_CROSSING_UNGRAB)
        {
-         x_offset += GDK_WINDOW_OBJECT (lastwin)->x;
-         y_offset += GDK_WINDOW_OBJECT (lastwin)->y;
+         if (display->pointer_info.toplevel_under_pointer)
+           g_object_unref (display->pointer_info.toplevel_under_pointer);
+         display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
        }
-      
-      /* children is ordered in reverse stack order */
-      for (cur = GDK_WINDOW_OBJECT (parentwin)->children; cur && cur->data != lastwin; cur = cur->next)
-       {
-         GdkWindow *child = cur->data;
-         GdkWindowObject *child_private = (GdkWindowObject *)child;
-         
-         if (!GDK_WINDOW_IS_MAPPED (child) || child_private->input_only)
-           continue;
 
-          window_get_size_rectangle (child, &visible_rect);
+      unlink_event = TRUE;
+      goto out;
+    }
 
-         /* Convert rect to "window" coords */
-         visible_rect.x += child_private->x - x_offset;
-         visible_rect.y += child_private->y - y_offset;
-         
-         /* This shortcut is really necessary for performance when there are a lot of windows */
-         gdk_region_get_clipbox (real_clip_region, &real_clip_rect);
-         if (visible_rect.x >= real_clip_rect.x + real_clip_rect.width ||
-             visible_rect.x + visible_rect.width <= real_clip_rect.x ||
-             visible_rect.y >= real_clip_rect.y + real_clip_rect.height ||
-             visible_rect.y + visible_rect.height <= real_clip_rect.y)
-           continue;
-         
-         tmpreg = gdk_region_rectangle (&visible_rect);
-         gdk_region_subtract (real_clip_region, tmpreg);
-         gdk_region_destroy (tmpreg);
+  /* Track toplevel_under_pointer */
+  if (is_toplevel)
+    {
+      if (event->type == GDK_ENTER_NOTIFY &&
+         event->crossing.detail != GDK_NOTIFY_INFERIOR)
+       {
+         if (display->pointer_info.toplevel_under_pointer)
+           g_object_unref (display->pointer_info.toplevel_under_pointer);
+         display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
+       }
+      else if (event->type == GDK_LEAVE_NOTIFY &&
+              event->crossing.detail != GDK_NOTIFY_INFERIOR &&
+              display->pointer_info.toplevel_under_pointer == event_window)
+       {
+         if (display->pointer_info.toplevel_under_pointer)
+           g_object_unref (display->pointer_info.toplevel_under_pointer);
+         display->pointer_info.toplevel_under_pointer = NULL;
        }
-      
-      /* Clip to the parent */
-      window_get_size_rectangle ((GdkWindow *)parentwin, &visible_rect);
-      /* Convert rect to "window" coords */
-      visible_rect.x += - x_offset;
-      visible_rect.y += - y_offset;
-      
-      tmpreg = gdk_region_rectangle (&visible_rect);
-      gdk_region_intersect (real_clip_region, tmpreg);
-      gdk_region_destroy (tmpreg);
     }
 
-  if (gc)
+  /* Store last pointer window and position/state */
+  old_state = display->pointer_info.state;
+  old_button = display->pointer_info.button;
+
+  gdk_event_get_coords (event, &x, &y);
+  convert_native_coords_to_toplevel (event_window, x, y,  &x, &y);
+  display->pointer_info.toplevel_x = x;
+  display->pointer_info.toplevel_y = y;
+  gdk_event_get_state (event, &display->pointer_info.state);
+  if (event->type == GDK_BUTTON_PRESS ||
+      event->type == GDK_BUTTON_RELEASE)
+    display->pointer_info.button = event->button.button;
+
+  if (display->pointer_info.state != old_state ||
+      display->pointer_info.button != old_button)
+    _gdk_display_enable_motion_hints (display);
+
+  unlink_event = FALSE;
+  if (is_motion_type (event->type))
+    unlink_event = proxy_pointer_event (display,
+                                       event,
+                                       serial);
+  else if (is_button_type (event->type))
+    unlink_event = proxy_button_event (event,
+                                      serial);
+
+  if (event->type == GDK_BUTTON_RELEASE)
     {
-      GdkRegion *clip_region = _gdk_gc_get_clip_region (gc);
-      
-      if (clip_region)
+      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)
        {
-         /* clip_region is relative to gc clip origin which is relative to the window */
-         /* offset it to window relative: */
-         tmpreg = gdk_region_copy (clip_region);
-         gdk_region_offset (real_clip_region,
-                            gc->clip_x_origin,
-                            gc->clip_y_origin);
-         /* Intersect it with window hierarchy cliprect: */
-         gdk_region_intersect (real_clip_region, tmpreg);
-         gdk_region_destroy (tmpreg);
+         button_release_grab->serial_end = serial;
+         button_release_grab->implicit_ungrab = TRUE;
+         _gdk_display_pointer_grab_update (display, serial);
        }
     }
 
-  if (base_x_offset)
-    *base_x_offset = x_offset;
-  if (base_y_offset)
-    *base_y_offset = y_offset;
-
-  return real_clip_region;
+ out:
+  if (unlink_event)
+    {
+      _gdk_event_queue_remove_link (display, event_link);
+      g_list_free_1 (event_link);
+      gdk_event_free (event);
+    }
 }
 
-static void
-gdk_window_add_damage (GdkWindow *toplevel,
-                      GdkRegion *damaged_region)
-{
-  GdkDisplay *display;
-  GdkEvent event = { 0, };
-  event.expose.type = GDK_DAMAGE;
-  event.expose.window = toplevel;
-  event.expose.send_event = FALSE;
-  event.expose.region = damaged_region;
-  gdk_region_get_clipbox (event.expose.region, &event.expose.area);
-  display = gdk_drawable_get_display (event.expose.window);
-  _gdk_event_queue_append (display, gdk_event_copy (&event));
-}
 
-static void
-setup_redirect_clip (GdkWindow         *window,
-                    GdkGC             *gc,
-                    GdkWindowClipData *data)
+static GdkWindow *
+get_extension_event_window (GdkDisplay                 *display,
+                           GdkWindow                  *pointer_window,
+                           GdkEventType                type,
+                           gulong                      serial)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkRegion *visible_region;
-  GdkRectangle dest_rect;
-  GdkRegion *tmpreg;
-  GdkWindow *toplevel;
+  guint evmask;
+  GdkWindow *grab_window;
+  GdkWindowObject *w;
+  GdkPointerGrabInfo *grab;
 
-  data->old_region = _gdk_gc_get_clip_region (gc);
-  if (data->old_region) 
-    data->old_region = gdk_region_copy (data->old_region);
+  grab = _gdk_display_has_pointer_grab (display, serial);
 
-  data->old_clip_x_origin = gc->clip_x_origin;
-  data->old_clip_y_origin = gc->clip_y_origin;
+  if (grab != NULL && !grab->owner_events)
+    {
+      evmask = grab->event_mask;
 
-  toplevel = GDK_WINDOW (private->redirect->redirected);
-  
-  /* Get the clip region for gc clip rect + window hierarchy in
-     window relative coords */
-  visible_region =
-    _gdk_window_calculate_full_clip_region (window, toplevel,
-                                           gc, TRUE,
-                                           &data->x_offset, 
-                                           &data->y_offset);
+      grab_window = grab->window;
 
-  /* Compensate for the source pos/size */
-  data->x_offset -= private->redirect->src_x;
-  data->y_offset -= private->redirect->src_y;
-  dest_rect.x = -data->x_offset;
-  dest_rect.y = -data->y_offset;
-  dest_rect.width = private->redirect->width;
-  dest_rect.height = private->redirect->height;
-  tmpreg = gdk_region_rectangle (&dest_rect);
-  gdk_region_intersect (visible_region, tmpreg);
-  gdk_region_destroy (tmpreg);
+      if (evmask & type_masks[type])
+       return grab_window;
+      else
+       return NULL;
+    }
 
-  /* Compensate for the dest pos */
-  data->x_offset += private->redirect->dest_x;
-  data->y_offset += private->redirect->dest_y;
+  w = (GdkWindowObject *)pointer_window;
+  while (w != NULL)
+    {
+      evmask = w->extension_events;
 
-  gdk_gc_set_clip_region (gc, visible_region); /* This resets clip origin! */
+      if (evmask & type_masks[type])
+       return (GdkWindow *)w;
 
-  /* offset clip and tiles from window coords to pixmaps coords */
-  gdk_gc_offset (gc, -data->x_offset, -data->y_offset);
+      w = get_event_parent (w);
+    }
 
-  /* Offset region to abs coords and add to damage */
-  gdk_region_offset (visible_region, data->x_offset, data->y_offset);
-  gdk_window_add_damage (toplevel, visible_region);
-  
-  gdk_region_destroy (visible_region);
-}
+  if (grab != NULL &&
+      grab->owner_events)
+    {
+      evmask = grab->event_mask;
 
-static void
-reset_redirect_clip (GdkWindow         *offscreen,
-                     GdkGC             *gc,
-                     GdkWindowClipData *data)
-{
-  /* offset back */
-  gdk_gc_offset (gc, data->x_offset, data->y_offset);
+      if (evmask & type_masks[type])
+       return grab->window;
+      else
+       return NULL;
+    }
 
-  /* reset old clip */
-  gdk_gc_set_clip_region (gc, data->old_region);
-  if (data->old_region)
-    gdk_region_destroy (data->old_region);
-  gdk_gc_set_clip_origin (gc, data->old_clip_x_origin, data->old_clip_y_origin);
+  return NULL;
 }
 
-static void
-gdk_window_redirect_free (GdkWindowRedirect *redirect)
+
+GdkWindow *
+_gdk_window_get_input_window_for_event (GdkWindow *native_window,
+                                       GdkEventType event_type,
+                                       int x, int y,
+                                       gulong serial)
 {
-  g_object_unref (redirect->pixmap);
-  g_free (redirect);
+  GdkDisplay *display;
+  GdkWindow *toplevel_window;
+  GdkWindow *pointer_window;
+  GdkWindow *event_win;
+  gdouble toplevel_x, toplevel_y;
+
+  toplevel_x = x;
+  toplevel_y = y;
+
+  display = gdk_drawable_get_display (native_window);
+  toplevel_window = convert_native_coords_to_toplevel (native_window,
+                                                      toplevel_x, toplevel_y,
+                                                      &toplevel_x, &toplevel_y);
+  pointer_window = get_pointer_window (display, toplevel_window,
+                                      toplevel_x, toplevel_y, serial);
+  event_win = get_extension_event_window (display,
+                                         pointer_window,
+                                         event_type,
+                                         serial);
+
+  return event_win;
 }
 
+
 #define __GDK_WINDOW_C__
 #include "gdkaliasdef.c"
index 866bb694675b3115f7090c04dd89eecb88839ebd..752f6b66cb26a5c651fbc23b454473566b9cdaab 100644 (file)
 
 G_BEGIN_DECLS
 
-typedef struct _GdkGeometry           GdkGeometry;
-typedef struct _GdkWindowAttr        GdkWindowAttr;
-typedef struct _GdkPointerHooks              GdkPointerHooks;
-typedef struct _GdkWindowRedirect     GdkWindowRedirect;
+typedef struct _GdkGeometry          GdkGeometry;
+typedef struct _GdkWindowAttr        GdkWindowAttr;
+typedef struct _GdkPointerHooks      GdkPointerHooks;
+typedef struct _GdkWindowRedirect    GdkWindowRedirect;
 
 /* Classes of windows.
  *   InputOutput: Almost every window should be of this type. Such windows
@@ -77,7 +77,8 @@ typedef enum
   GDK_WINDOW_CHILD,
   GDK_WINDOW_DIALOG,
   GDK_WINDOW_TEMP,
-  GDK_WINDOW_FOREIGN
+  GDK_WINDOW_FOREIGN,
+  GDK_WINDOW_OFFSCREEN
 } GdkWindowType;
 
 /* Window attribute mask values.
@@ -259,6 +260,12 @@ typedef struct _GdkWindowObjectClass GdkWindowObjectClass;
 #define GDK_WINDOW_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WINDOW, GdkWindowObjectClass))
 #define GDK_WINDOW_OBJECT(object)    ((GdkWindowObject *) GDK_WINDOW (object))
 
+#ifndef GDK_COMPILATION
+/* We used to export all of GdkWindowObject, but we don't want to keep doing so.
+   However, there are various parts of it accessed by macros and other code,
+   so we keep the old exported version public, but in reality it is larger. */
+
+/**** DON'T CHANGE THIS STRUCT, the real version is in gdkinternals.h ****/
 struct _GdkWindowObject
 {
   GdkDrawable parent_instance;
@@ -308,6 +315,7 @@ struct _GdkWindowObject
 
   GdkWindowRedirect *redirect;
 };
+#endif
 
 struct _GdkWindowObjectClass
 {
@@ -379,6 +387,7 @@ void              gdk_window_move_region           (GdkWindow       *window,
                                                const GdkRegion *region,
                                                gint             dx,
                                                gint             dy);
+gboolean      gdk_window_ensure_native        (GdkWindow       *window);
 
 /* 
  * This allows for making shaped (partially transparent) windows
@@ -522,6 +531,11 @@ void             gdk_window_get_position    (GdkWindow       *window,
 gint         gdk_window_get_origin      (GdkWindow       *window,
                                          gint            *x,
                                          gint            *y);
+gint         gdk_window_get_root_coords (GdkWindow       *window,
+                                         gint             x,
+                                         gint             y,
+                                         gint            *root_x,
+                                         gint            *root_y);
 
 #if !defined (GDK_DISABLE_DEPRECATED) || defined (GTK_COMPILATION)
 /* Used by gtk_handle_box_button_changed () */
@@ -645,12 +659,22 @@ GdkPointerHooks *gdk_set_pointer_hooks (const GdkPointerHooks *new_hooks);
 
 GdkWindow *gdk_get_default_root_window (void);
 
-void gdk_window_redirect_to_drawable (GdkWindow *window,
-                                     GdkDrawable *drawable,
-                                     gint src_x, gint src_y,
-                                     gint dest_x, gint dest_y,
-                                     gint width, gint height);
-void gdk_window_remove_redirection   (GdkWindow *window);
+/* Offscreen redirection */
+GdkPixmap *gdk_window_get_offscreen_pixmap   (GdkWindow     *window);
+void       gdk_window_set_has_offscreen_children (GdkWindow     *window,
+                                                 gboolean       has_offscreen_children);
+gboolean   gdk_window_get_has_offscreen_children (GdkWindow     *window);
+void       gdk_window_offscreen_children_changed (GdkWindow     *window);
+
+void       gdk_window_redirect_to_drawable   (GdkWindow     *window,
+                                              GdkDrawable   *drawable,
+                                              gint           src_x,
+                                              gint           src_y,
+                                              gint           dest_x,
+                                              gint           dest_y,
+                                              gint           width,
+                                              gint           height);
+void       gdk_window_remove_redirection     (GdkWindow     *window);
 
 #ifndef GDK_DISABLE_DEPRECATED
 #define GDK_ROOT_PARENT()             (gdk_get_default_root_window ())
index f9f97b6fa0d84ca5a6f8ce12fc20c1bcc46c7291..5905de80f3f9f21693a54dc19a8b8efca73b949b 100644 (file)
@@ -44,11 +44,13 @@ struct _GdkWindowImplIface
   GTypeInterface g_iface;
 
   void         (* show)                 (GdkWindow       *window,
-                                         gboolean         raise);
+                                        gboolean         already_mapped);
   void         (* hide)                 (GdkWindow       *window);
   void         (* withdraw)             (GdkWindow       *window);
   void         (* raise)                (GdkWindow       *window);
   void         (* lower)                (GdkWindow       *window);
+  void         (* restack_under)        (GdkWindow       *window,
+                                        GList           *native_siblings);
 
   void         (* move_resize)          (GdkWindow       *window,
                                          gboolean         with_move,
@@ -56,25 +58,10 @@ struct _GdkWindowImplIface
                                          gint             y,
                                          gint             width,
                                          gint             height);
-  void         (* move_region)          (GdkWindow       *window,
-                                         const GdkRegion *region,
-                                         gint             dx,
-                                         gint             dy);
-  void         (* scroll)               (GdkWindow       *window,
-                                         gint             dx,
-                                         gint             dy);
-
-  void         (* clear_area)           (GdkWindow       *window,
-                                         gint             x,
-                                         gint             y,
-                                         gint             width,
-                                         gint             height,
-                                         gboolean         send_expose);
   void         (* set_background)       (GdkWindow       *window,
                                          const GdkColor  *color);
   void         (* set_back_pixmap)      (GdkWindow       *window,
-                                         GdkPixmap       *pixmap,
-                                         gboolean         parent_relative);
+                                         GdkPixmap       *pixmap);
 
   GdkEventMask (* get_events)           (GdkWindow       *window);
   void         (* set_events)           (GdkWindow       *window,
@@ -94,31 +81,87 @@ struct _GdkWindowImplIface
                                          gint            *width,
                                          gint            *height,
                                          gint            *depth);
-  gint         (* get_origin)           (GdkWindow       *window,
+  gint         (* get_root_coords)      (GdkWindow       *window,
+                                        gint             x,
+                                        gint             y,
+                                         gint            *root_x,
+                                         gint            *root_y);
+  gint         (* get_deskrelative_origin) (GdkWindow       *window,
                                          gint            *x,
                                          gint            *y);
-  void         (* get_offsets)          (GdkWindow       *window,
-                                         gint            *x_offset,
-                                         gint            *y_offset);
+  gboolean     (* get_pointer)          (GdkWindow       *window,
+                                         gint            *x,
+                                         gint            *y,
+                                        GdkModifierType  *mask);
 
-  void         (* shape_combine_mask)   (GdkWindow       *window,
-                                         GdkBitmap       *mask,
-                                         gint             x,
-                                         gint             y);
   void         (* shape_combine_region) (GdkWindow       *window,
                                          const GdkRegion *shape_region,
                                          gint             offset_x,
                                          gint             offset_y);
-  void         (* set_child_shapes)     (GdkWindow       *window);
-  void         (* merge_child_shapes)   (GdkWindow       *window);
+  void         (* input_shape_combine_region) (GdkWindow       *window,
+                                              const GdkRegion *shape_region,
+                                              gint             offset_x,
+                                              gint             offset_y);
 
   gboolean     (* set_static_gravities) (GdkWindow       *window,
                                         gboolean         use_static);
+
+  /* Called before processing updates for a window. This gives the windowing
+   * layer a chance to save the region for later use in avoiding duplicate
+   * exposes. The return value indicates whether the function has a saved
+   * the region; if the result is TRUE, then the windowing layer is responsible
+   * for destroying the region later.
+   */
+  gboolean     (* queue_antiexpose)     (GdkWindow       *window,
+                                        GdkRegion       *update_area);
+  void         (* queue_translation)    (GdkWindow       *window,
+                                        GdkRegion       *area,
+                                        gint            dx,
+                                        gint            dy);
+
+/* Called to do the windowing system specific part of gdk_window_destroy(),
+ *
+ * window: The window being destroyed
+ * recursing: If TRUE, then this is being called because a parent
+ *            was destroyed. This generally means that the call to the windowing system
+ *            to destroy the window can be omitted, since it will be destroyed as a result
+ *            of the parent being destroyed. Unless @foreign_destroy
+ *            
+ * foreign_destroy: If TRUE, the window or a parent was destroyed by some external 
+ *            agency. The window has already been destroyed and no windowing
+ *            system calls should be made. (This may never happen for some
+ *            windowing systems.)
+ */
+  void         (* destroy)              (GdkWindow       *window,
+                                        gboolean         recursing,
+                                        gboolean         foreign_destroy);
+
+  void         (* input_window_destroy) (GdkWindow       *window);
+  void         (* input_window_crossing)(GdkWindow       *window,
+                                        gboolean         enter);
 };
 
 /* Interface Functions */
 GType gdk_window_impl_get_type (void) G_GNUC_CONST;
 
+/* private definitions from gdkwindow.h */
+
+struct _GdkWindowRedirect
+{
+  GdkWindowObject *redirected;
+  GdkDrawable *pixmap;
+
+  gint src_x;
+  gint src_y;
+  gint dest_x;
+  gint dest_y;
+  gint width;
+  gint height;
+
+  GdkRegion *damage;
+  guint damage_idle;
+};
+
 G_END_DECLS
 
 #endif /* __GDK_WINDOW_IMPL_H__ */
index 3cc0f2e1240861d376e72d34329f89b38ea3eb10..761b07fb304a2cf89048b2141f3ca612d38868b5 100644 (file)
   return gdk_window;
 }
 
+-(NSTrackingRectTag)trackingRect
+{
+  return trackingRect;
+}
+
 -(BOOL)isFlipped
 {
   return YES;
   if (NSEqualRects (rect, NSZeroRect))
     return;
 
-  GDK_QUARTZ_ALLOC_POOL;
-
   [self getRectsBeingDrawn:&drawn_rects count:&count];
 
-  region = gdk_region_new ();
-
-  for (i = 0; i < count; i++)
-    {
-      gdk_rect.x = drawn_rects[i].origin.x;
-      gdk_rect.y = drawn_rects[i].origin.y;
-      gdk_rect.width = drawn_rects[i].size.width;
-      gdk_rect.height = drawn_rects[i].size.height;
-
-      gdk_region_union_with_rect (region, &gdk_rect);
-    }
-
-  if (!gdk_region_empty (region))
+  /* Note: arbitrary limit here to not degrade performace too much. It would
+   * be better to optimize the construction of the region below, by using
+   * _gdk_region_new_from_yxbanded_rects.
+   */
+  if (count > 25)
     {
-      GdkEvent event;
-      
       gdk_rect.x = rect.origin.x;
       gdk_rect.y = rect.origin.y;
       gdk_rect.width = rect.size.width;
       gdk_rect.height = rect.size.height;
-      
-      event.expose.type = GDK_EXPOSE;
-      event.expose.window = g_object_ref (gdk_window);
-      event.expose.send_event = FALSE;
-      event.expose.count = 0;
-      event.expose.region = region;
-      event.expose.area = gdk_rect;
-      
-      impl->in_paint_rect_count++;
 
-      (*_gdk_event_func) (&event, _gdk_event_data);
+      region = gdk_region_rectangle (&gdk_rect);
+    }
+  else
+    {
+      region = gdk_region_new ();
 
-      impl->in_paint_rect_count--;
+      for (i = 0; i < count; i++)
+        {
+          gdk_rect.x = drawn_rects[i].origin.x;
+          gdk_rect.y = drawn_rects[i].origin.y;
+          gdk_rect.width = drawn_rects[i].size.width;
+          gdk_rect.height = drawn_rects[i].size.height;
 
-      g_object_unref (gdk_window);
+          gdk_region_union_with_rect (region, &gdk_rect);
+        }
     }
 
+  impl->in_paint_rect_count++;
+  _gdk_window_process_updates_recurse (gdk_window, region);
+  impl->in_paint_rect_count--;
+
   gdk_region_destroy (region);
 
   if (needsInvalidateShadow)
       [[self window] invalidateShadow];
       needsInvalidateShadow = NO;
     }
-
-  GDK_QUARTZ_RELEASE_POOL;
 }
 
 -(void)setNeedsInvalidateShadow:(BOOL)invalidate
   GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
   NSRect rect;
 
+  if (!impl->toplevel)
+    return;
+
   if (trackingRect)
     {
       [self removeTrackingRect:trackingRect];
index 752c3989b38a719643e523303981bea27c43df1e..f9c9a9cabe6b793c138aa4ad039a52b7b358d875 100644 (file)
@@ -29,6 +29,7 @@
 
 -(void)setGdkWindow:(GdkWindow *)window;
 -(GdkWindow *)gdkWindow;
+-(NSTrackingRectTag)trackingRect;
 -(void)setNeedsInvalidateShadow:(BOOL)invalidate;
 
 @end
index 3f1681511046a9fa727cb1b59a76ae8d2199c9b4..282b65b75945bc1aed37f5d2f50562c3a4f40056 100644 (file)
   NSRect content_rect = [self contentRectForFrameRect:[self frame]];
   GdkWindow *window = [[self contentView] gdkWindow];
   GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
   GdkEvent *event;
 
-  /* Ignore new position during showing/hiding the window, otherwise we
-   * would get the off-screen position that is used for hidden windows to
-   * get reliable MouseEntered events when showing them again. See comments
-   * in show() and hide().
-   */
-  if (inShowOrHide)
-    return;
-
   private->x = content_rect.origin.x;
   private->y = _gdk_quartz_window_get_inverted_screen_y (content_rect.origin.y + content_rect.size.height);
 
   event->configure.window = g_object_ref (window);
   event->configure.x = private->x;
   event->configure.y = private->y;
-  event->configure.width = impl->width;
-  event->configure.height = impl->height;
+  event->configure.width = private->width;
+  event->configure.height = private->height;
 
   _gdk_event_queue_append (gdk_display_get_default (), event);
 }
   NSRect content_rect = [self contentRectForFrameRect:[self frame]];
   GdkWindow *window = [[self contentView] gdkWindow];
   GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
   GdkEvent *event;
 
-  impl->width = content_rect.size.width;
-  impl->height = content_rect.size.height;
+  private->width = content_rect.size.width;
+  private->height = content_rect.size.height;
+
+  [[self contentView] setFrame:NSMakeRect (0, 0, private->width, private->height)];
 
-  [[self contentView] setFrame:NSMakeRect (0, 0, impl->width, impl->height)];
+  _gdk_window_update_size (window);
 
   /* Synthesize a configure event */
   event = gdk_event_new (GDK_CONFIGURE);
   event->configure.window = g_object_ref (window);
   event->configure.x = private->x;
   event->configure.y = private->y;
-  event->configure.width = impl->width;
-  event->configure.height = impl->height;
+  event->configure.width = private->width;
+  event->configure.height = private->height;
 
   _gdk_event_queue_append (gdk_display_get_default (), event);
 }
   GdkWindow *window = [[self contentView] gdkWindow];
   GdkWindowObject *private = (GdkWindowObject *)window;
   GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
-  gboolean was_hidden;
-  int requested_x = 0, requested_y = 0;
 
   inShowOrHide = YES;
-  was_hidden = FALSE;
-
-  if (!GDK_WINDOW_IS_MAPPED (window))
-    {
-      NSRect content_rect;
-      NSRect frame_rect;
-
-      was_hidden = TRUE;
-
-      /* We move the window in place if it's not mapped. See comment in
-       * hide().
-       */
-      content_rect =
-        NSMakeRect (private->x,
-                    _gdk_quartz_window_get_inverted_screen_y (private->y) - impl->height,
-                    impl->width, impl->height);
-      frame_rect = [impl->toplevel frameRectForContentRect:content_rect];
-      [impl->toplevel setFrame:frame_rect display:NO];
-
-      requested_x = frame_rect.origin.x;
-      requested_y = frame_rect.origin.y;
-    }
 
   if (makeKey)
     [impl->toplevel makeKeyAndOrderFront:impl->toplevel];
     [impl->toplevel orderFront:nil];
 
   inShowOrHide = NO;
-
-  /* When the window manager didn't allow our request, update the position
-   * to what it really ended up as.
-   */
-  if (was_hidden)
-    {
-      NSRect frame_rect;
-
-      frame_rect = [impl->toplevel frame];
-      if (requested_x != frame_rect.origin.x || requested_y != frame_rect.origin.y)
-        {
-          [self windowDidMove:nil];
-        }
-    }
 }
 
 - (void)hide
   GdkWindow *window = [[self contentView] gdkWindow];
   GdkWindowObject *private = (GdkWindowObject *)window;
   GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
-  NSRect content_rect;
-  NSRect frame_rect;
 
   inShowOrHide = YES;
-
-  /* We move the window away when hiding, to make it possible to move it in
-   * place when showing to get reliable tracking rect events (which are used
-   * to generate crossing events). We have to do this, probably a bug in
-   * quartz.
-   */
-  content_rect = NSMakeRect (-500 - impl->width, -500 - impl->height,
-                             impl->width, impl->height);
-  frame_rect = [impl->toplevel frameRectForContentRect:content_rect];
-  [impl->toplevel setFrame:frame_rect display:NO];
-
   [impl->toplevel orderOut:nil];
-
   inShowOrHide = NO;
 }
 
index 9b83b13b72e81952f32124cfeba6388b1188c9bb..9dbd93f18e6b170404a9a8802437d85435259e81 100644 (file)
@@ -178,3 +178,9 @@ gdk_display_supports_composite (GdkDisplay *display)
   /* FIXME: Implement */
   return FALSE;
 }
+
+gulong
+_gdk_windowing_window_get_next_serial (GdkDisplay *display)
+{
+  return 0;
+}
index 9ad9c66d2e7e70f63b8b04cd6d2c6c0723c5d236..673da0647710a49b55a59916e7838e8cf3f2eaab 100644 (file)
@@ -19,6 +19,7 @@
  */
 
 #include "config.h"
+#include <sys/time.h>
 #include <cairo-quartz.h>
 #include "gdkprivate-quartz.h"
 
@@ -31,20 +32,56 @@ typedef struct {
   CGContextRef  cg_context;
 } GdkQuartzCairoSurfaceData;
 
+void
+_gdk_windowing_set_cairo_surface_size (cairo_surface_t *surface,
+                                      int              width,
+                                      int              height)
+{
+  /* This is not supported with quartz surfaces. */
+}
+
 static void
 gdk_quartz_cairo_surface_destroy (void *data)
 {
   GdkQuartzCairoSurfaceData *surface_data = data;
   GdkDrawableImplQuartz *impl = GDK_DRAWABLE_IMPL_QUARTZ (surface_data->drawable);
 
-  gdk_quartz_drawable_release_context (surface_data->drawable, 
-                                      surface_data->cg_context);
-
   impl->cairo_surface = NULL;
 
+  gdk_quartz_drawable_release_context (surface_data->drawable,
+                                       surface_data->cg_context);
+
   g_free (surface_data);
 }
 
+cairo_surface_t *
+_gdk_windowing_create_cairo_surface (GdkDrawable *drawable,
+                                    int          width,
+                                    int          height)
+{
+  CGContextRef cg_context;
+  GdkQuartzCairoSurfaceData *surface_data;
+  cairo_surface_t *surface;
+
+  cg_context = gdk_quartz_drawable_get_context (drawable, TRUE);
+
+  if (!cg_context)
+    return NULL;
+
+  surface_data = g_new (GdkQuartzCairoSurfaceData, 1);
+  surface_data->drawable = drawable;
+  surface_data->cg_context = cg_context;
+
+  surface = cairo_quartz_surface_create_for_cg_context (cg_context,
+                                                        width, height);
+
+  cairo_surface_set_user_data (surface, &gdk_quartz_cairo_key,
+                               surface_data,
+                               gdk_quartz_cairo_surface_destroy);
+
+  return surface;
+}
+
 static cairo_surface_t *
 gdk_quartz_ref_cairo_surface (GdkDrawable *drawable)
 {
@@ -56,24 +93,11 @@ gdk_quartz_ref_cairo_surface (GdkDrawable *drawable)
 
   if (!impl->cairo_surface)
     {
-      CGContextRef cg_context;
       int width, height;
-      GdkQuartzCairoSurfaceData *surface_data;
-
-      cg_context = gdk_quartz_drawable_get_context (drawable, TRUE);
-      if (!cg_context)
-       return NULL;
 
       gdk_drawable_get_size (drawable, &width, &height);
-
-      impl->cairo_surface = cairo_quartz_surface_create_for_cg_context (cg_context, width, height);
-
-      surface_data = g_new (GdkQuartzCairoSurfaceData, 1);
-      surface_data->drawable = drawable;
-      surface_data->cg_context = cg_context;
-
-      cairo_surface_set_user_data (impl->cairo_surface, &gdk_quartz_cairo_key,
-                                  surface_data, gdk_quartz_cairo_surface_destroy);
+      impl->cairo_surface = _gdk_windowing_create_cairo_surface (drawable,
+                                                                 width, height);
     }
   else
     cairo_surface_reference (impl->cairo_surface);
@@ -183,8 +207,6 @@ gdk_quartz_draw_arc (GdkDrawable *drawable,
                                    GDK_QUARTZ_CONTEXT_FILL :
                                    GDK_QUARTZ_CONTEXT_STROKE);
 
-  CGContextSaveGState (context);
-
   start_angle = angle1 * 2.0 * G_PI / 360.0 / 64.0;
   end_angle = start_angle + angle2 * 2.0 * G_PI / 360.0 / 64.0;
 
@@ -233,8 +255,6 @@ gdk_quartz_draw_arc (GdkDrawable *drawable,
       CGContextStrokePath (context);
     }
 
-  CGContextRestoreGState (context);
-
   gdk_quartz_drawable_release_context (drawable, context);
 }
 
@@ -306,6 +326,7 @@ static void
 gdk_quartz_draw_drawable (GdkDrawable *drawable,
                          GdkGC       *gc,
                          GdkPixmap   *src,
+                         GdkDrawable *original_src,
                          gint         xsrc,
                          gint         ysrc,
                          gint         xdest,
@@ -317,49 +338,69 @@ gdk_quartz_draw_drawable (GdkDrawable *drawable,
   int dest_depth = gdk_drawable_get_depth (drawable);
   GdkDrawableImplQuartz *src_impl;
 
-  if (GDK_IS_DRAWABLE_IMPL_QUARTZ (src))
+  if (GDK_IS_WINDOW_IMPL_QUARTZ (src))
+    {
+      GdkWindowImplQuartz *window_impl;
+
+      window_impl = GDK_WINDOW_IMPL_QUARTZ (src);
+
+      /* We do support moving areas on the same drawable, if it can be done
+       * by using a scroll. FIXME: We need to check that the params support
+       * this hack, and make sure it's done properly with any offsets etc?
+       */
+      if (drawable == (GdkDrawable *)window_impl)
+        {
+          [window_impl->view scrollRect:NSMakeRect (xsrc, ysrc, width, height)
+                                     by:NSMakeSize (xdest - xsrc, ydest - ysrc)];
+
+
+        }
+      else
+        g_warning ("Drawing with window source != dest is not supported");
+
+      return;
+    }
+  else if (GDK_IS_DRAWABLE_IMPL_QUARTZ (src))
     src_impl = GDK_DRAWABLE_IMPL_QUARTZ (src);
   else if (GDK_IS_PIXMAP (src))
     src_impl = GDK_DRAWABLE_IMPL_QUARTZ (GDK_PIXMAP_OBJECT (src)->impl);
-  else if (GDK_IS_WINDOW (src))
+  else
     {
-      src_impl = GDK_DRAWABLE_IMPL_QUARTZ (GDK_WINDOW_OBJECT (src)->impl);
-      /* FIXME: Implement drawing a window. */
+      g_warning ("Unsupported source %s", G_OBJECT_TYPE_NAME (src));
       return;
     }
-  else
-    g_assert_not_reached ();
-  
+
+  /* Handle drawable and pixmap sources. */
   if (src_depth == 1)
     {
       /* FIXME: src depth 1 is not supported yet */
+      g_warning ("Source with depth 1 unsupported");
     }
   else if (dest_depth != 0 && src_depth == dest_depth)
     {
+      GdkPixmapImplQuartz *pixmap_impl = GDK_PIXMAP_IMPL_QUARTZ (src_impl);
       CGContextRef context = gdk_quartz_drawable_get_context (drawable, FALSE);
 
       if (!context)
-       return;
+        return;
 
       _gdk_quartz_gc_update_cg_context (gc, drawable, context,
-                                       GDK_QUARTZ_CONTEXT_STROKE);
+                                        GDK_QUARTZ_CONTEXT_STROKE);
 
       CGContextClipToRect (context, CGRectMake (xdest, ydest, width, height));
       CGContextTranslateCTM (context, xdest - xsrc, ydest - ysrc +
-                             GDK_PIXMAP_IMPL_QUARTZ (src_impl)->height);
+                             pixmap_impl->height);
       CGContextScaleCTM (context, 1.0, -1.0);
 
-      CGContextDrawImage (context, 
-                         CGRectMake(0, 0, 
-                                    GDK_PIXMAP_IMPL_QUARTZ (src_impl)->width, 
-                                    GDK_PIXMAP_IMPL_QUARTZ (src_impl)->height), 
-                         GDK_PIXMAP_IMPL_QUARTZ (src_impl)->image);
+      CGContextDrawImage (context,
+                          CGRectMake (0, 0, pixmap_impl->width, pixmap_impl->height),
+                          pixmap_impl->image);
 
       gdk_quartz_drawable_release_context (drawable, context);
     }
   else
     g_warning ("Attempt to draw a drawable with depth %d to a drawable with depth %d",
-              src_depth, dest_depth);
+               src_depth, dest_depth);
 }
 
 static void
@@ -681,6 +722,51 @@ gdk_quartz_drawable_get_context (GdkDrawable *drawable,
   return GDK_DRAWABLE_IMPL_QUARTZ_GET_CLASS (drawable)->get_context (drawable, antialias);
 }
 
+/* Help preventing "beam sync penalty" where CG makes all graphics code
+ * block until the next vsync if we try to flush (including call display on
+ * a view) too often. We do this by limiting the manual flushing done
+ * outside of expose calls to less than some frequency when measured over
+ * the last 4 flushes. This is a bit arbitray, but seems to make it possible
+ * for some quick manual flushes (such as gtkruler or gimp's marching ants)
+ * without hitting the max flush frequency.
+ *
+ * If drawable NULL, no flushing is done, only registering that a flush was
+ * done externally.
+ */
+void
+_gdk_quartz_drawable_flush (GdkDrawable *drawable)
+{
+  static struct timeval prev_tv;
+  static gint intervals[4];
+  static gint index;
+  struct timeval tv;
+  gint ms;
+
+  gettimeofday (&tv, NULL);
+  ms = (tv.tv_sec - prev_tv.tv_sec) * 1000 + (tv.tv_usec - prev_tv.tv_usec) / 1000;
+  intervals[index++ % 4] = ms;
+
+  if (drawable)
+    {
+      ms = intervals[0] + intervals[1] + intervals[2] + intervals[3];
+
+      /* ~25Hz on average. */
+      if (ms > 4*40)
+        {
+          if (GDK_IS_WINDOW_IMPL_QUARTZ (drawable))
+            {
+              GdkWindowImplQuartz *window_impl = GDK_WINDOW_IMPL_QUARTZ (drawable);
+
+              [window_impl->toplevel flushWindow];
+            }
+
+          prev_tv = tv;
+        }
+    }
+  else
+    prev_tv = tv;
+}
+
 void
 gdk_quartz_drawable_release_context (GdkDrawable  *drawable, 
                                     CGContextRef  cg_context)
@@ -694,7 +780,10 @@ gdk_quartz_drawable_release_context (GdkDrawable  *drawable,
 
       /* See comment in gdk_quartz_drawable_get_context(). */
       if (window_impl->in_paint_rect_count == 0)
-        [window_impl->view unlockFocus];
+        {
+          _gdk_quartz_drawable_flush (drawable);
+          [window_impl->view unlockFocus];
+        }
     }
   else if (GDK_IS_PIXMAP_IMPL_QUARTZ (drawable))
     CGContextRelease (cg_context);
index bc301955dab33ee5ff5ac618bf9be67a1f36dcd3..db73a11c321f4bb954c99e5f252b497f5bbf4743 100644 (file)
 #include "gdkkeysyms.h"
 #include "gdkprivate-quartz.h"
 
-/* This is the window the mouse is currently over */
-static GdkWindow   *current_mouse_window;
-
 /* This is the window corresponding to the key window */
 static GdkWindow   *current_keyboard_window;
 
-/* This is the pointer grab window */
-GdkWindow          *_gdk_quartz_pointer_grab_window;
-static gboolean     pointer_grab_owner_events;
-static GdkEventMask pointer_grab_event_mask;
-static gboolean     pointer_grab_implicit;
-
-/* This is the keyboard grab window */
-GdkWindow *         _gdk_quartz_keyboard_grab_window;
-static gboolean     keyboard_grab_owner_events;
-
 /* This is the event mask and button state from the last event */
 static GdkEventMask current_event_mask;
 static int          current_button_state;
 
-static void get_child_coordinates_from_ancestor (GdkWindow *ancestor_window,
-                                                 gint       ancestor_x,
-                                                 gint       ancestor_y,
-                                                 GdkWindow *child_window, 
-                                                 gint      *child_x, 
-                                                 gint      *child_y);
-static void get_ancestor_coordinates_from_child (GdkWindow *child_window,
-                                                 gint       child_x,
-                                                 gint       child_y,
-                                                 GdkWindow *ancestor_window, 
-                                                 gint      *ancestor_x, 
-                                                 gint      *ancestor_y);
-static void get_converted_window_coordinates    (GdkWindow *in_window,
-                                                 gint       in_x,
-                                                 gint       in_y,
-                                                 GdkWindow *out_window, 
-                                                 gint      *out_x, 
-                                                 gint      *out_y);
 static void append_event                        (GdkEvent  *event);
 
-static const gchar *
-which_window_is_this (GdkWindow *window)
-{
-  static gchar buf[256];
-  const gchar *name = NULL;
-  gpointer widget;
-
-  /* Get rid of compiler warning. */
-  if (0) which_window_is_this (window);
-
-  if (window == _gdk_root)
-    name = "root";
-  else if (window == NULL)
-    name = "null";
-
-  if (window)
-    {
-      gdk_window_get_user_data (window, &widget);
-      if (widget)
-        name = G_OBJECT_TYPE_NAME (widget);
-    }
-
-  if (!name)
-    name = "unknown";
-
-  snprintf (buf, 256, "<%s (%p)%s>", 
-            name, window, 
-            window == current_mouse_window ? ", is mouse" : "");
-
-  return buf;
-}
-
 NSEvent *
 gdk_quartz_event_get_nsevent (GdkEvent *event)
 {
@@ -112,12 +49,11 @@ gdk_quartz_event_get_nsevent (GdkEvent *event)
   return ((GdkEventPrivate *) event)->windowing_data;
 }
 
-void 
+void
 _gdk_events_init (void)
 {
   _gdk_quartz_event_loop_init ();
 
-  current_mouse_window = g_object_ref (_gdk_root);
   current_keyboard_window = g_object_ref (_gdk_root);
 }
 
@@ -135,45 +71,26 @@ gdk_event_get_graphics_expose (GdkWindow *window)
   return NULL;
 }
 
-static void
-generate_grab_broken_event (GdkWindow *window,
-                           gboolean   keyboard,
-                           gboolean   implicit,
-                           GdkWindow *grab_window)
-{
-  if (!GDK_WINDOW_DESTROYED (window))
-    {
-      GdkEvent *event = gdk_event_new (GDK_GRAB_BROKEN);
-
-      event->grab_broken.window = window;
-      event->grab_broken.send_event = 0;
-      event->grab_broken.keyboard = keyboard;
-      event->grab_broken.implicit = implicit;
-      event->grab_broken.grab_window = grab_window;
-      
-      append_event (event);
-    }
-}
-
 GdkGrabStatus
 gdk_keyboard_grab (GdkWindow  *window,
                   gint        owner_events,
                   guint32     time)
 {
+  GdkDisplay *display;
+  GdkWindow  *toplevel;
+
   g_return_val_if_fail (window != NULL, 0);
   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
 
-  if (_gdk_quartz_keyboard_grab_window)
-    {
-      if (_gdk_quartz_keyboard_grab_window != window)
-       generate_grab_broken_event (_gdk_quartz_keyboard_grab_window,
-                                   TRUE, FALSE, window);
-      
-      g_object_unref (_gdk_quartz_keyboard_grab_window);
-    }
+  display = gdk_drawable_get_display (window);
+  toplevel = gdk_window_get_toplevel (window);
 
-  _gdk_quartz_keyboard_grab_window = g_object_ref (window);
-  keyboard_grab_owner_events = owner_events;
+  _gdk_display_set_has_keyboard_grab (display,
+                                      window,
+                                      toplevel,
+                                      owner_events,
+                                      0,
+                                      time);
 
   return GDK_GRAB_SUCCESS;
 }
@@ -182,95 +99,20 @@ void
 gdk_display_keyboard_ungrab (GdkDisplay *display,
                             guint32     time)
 {
-  if (_gdk_quartz_keyboard_grab_window)
-    g_object_unref (_gdk_quartz_keyboard_grab_window);
-  _gdk_quartz_keyboard_grab_window = NULL;
-}
-
-gboolean
-gdk_keyboard_grab_info_libgtk_only (GdkDisplay *display,
-                                   GdkWindow **grab_window,
-                                   gboolean   *owner_events)
-{
-  if (_gdk_quartz_keyboard_grab_window) 
-    {
-      if (grab_window)
-       *grab_window = _gdk_quartz_keyboard_grab_window;
-      if (owner_events)
-       *owner_events = keyboard_grab_owner_events;
-
-      return TRUE;
-    }
-
-  return FALSE;
-}
-
-static void
-pointer_ungrab_internal (gboolean only_if_implicit)
-{
-  if (!_gdk_quartz_pointer_grab_window)
-    return;
-
-  if (only_if_implicit && !pointer_grab_implicit)
-    return;
-
-  g_object_unref (_gdk_quartz_pointer_grab_window);
-  _gdk_quartz_pointer_grab_window = NULL;
-
-  pointer_grab_owner_events = FALSE;
-  pointer_grab_event_mask = 0;
-  pointer_grab_implicit = FALSE;
-
-  /* FIXME: Send crossing events */
-}
-
-gboolean
-gdk_display_pointer_is_grabbed (GdkDisplay *display)
-{
-  return (_gdk_quartz_pointer_grab_window != NULL && 
-          !pointer_grab_implicit);
-}
-
-gboolean
-gdk_pointer_grab_info_libgtk_only (GdkDisplay *display,
-                                  GdkWindow **grab_window,
-                                  gboolean   *owner_events)
-{
-  if (!_gdk_quartz_pointer_grab_window)
-    return FALSE;
-
-  if (grab_window)
-    *grab_window = _gdk_quartz_pointer_grab_window;
-
-  if (owner_events)
-    *owner_events = pointer_grab_owner_events;
-
-  return TRUE;
+  _gdk_display_unset_has_keyboard_grab (display, FALSE);
 }
 
 void
 gdk_display_pointer_ungrab (GdkDisplay *display,
                            guint32     time)
 {
-  pointer_ungrab_internal (FALSE);
-}
+  GdkPointerGrabInfo *grab;
 
-static GdkGrabStatus
-pointer_grab_internal (GdkWindow    *window,
-                      gboolean      owner_events,
-                      GdkEventMask  event_mask,
-                      GdkWindow    *confine_to,
-                      GdkCursor    *cursor,
-                      gboolean      implicit)
-{
-  /* FIXME: Send crossing events */
-  
-  _gdk_quartz_pointer_grab_window = g_object_ref (window);
-  pointer_grab_owner_events = owner_events;
-  pointer_grab_event_mask = event_mask;
-  pointer_grab_implicit = implicit;
+  grab = _gdk_display_get_last_pointer_grab (display);
+  if (grab)
+    grab->serial_end = 0;
 
-  return GDK_GRAB_SUCCESS;
+  _gdk_display_pointer_grab_update (display, 0);
 }
 
 GdkGrabStatus
@@ -281,45 +123,49 @@ gdk_pointer_grab (GdkWindow    *window,
                  GdkCursor    *cursor,
                  guint32       time)
 {
+  GdkWindow *native;
+
   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
   g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
 
-  if (_gdk_quartz_pointer_grab_window)
-    {
-      if (_gdk_quartz_pointer_grab_window != window)
-        generate_grab_broken_event (_gdk_quartz_pointer_grab_window,
-                                    FALSE, pointer_grab_implicit, window);
+  native = gdk_window_get_toplevel (window);
 
-      pointer_ungrab_internal (FALSE);
-    }
+  /* TODO: What do we do for offscreens and  their children? We need to proxy the grab somehow */
+  if (!GDK_IS_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (native)->impl))
+    return GDK_GRAB_SUCCESS;
 
-  return pointer_grab_internal (window, owner_events, event_mask, 
-                               confine_to, cursor, FALSE);
+  if (!_gdk_window_has_impl (window) &&
+      !gdk_window_is_viewable (window))
+    return GDK_GRAB_NOT_VIEWABLE;
+
+  _gdk_display_add_pointer_grab (_gdk_display,
+                                 window,
+                                 native,
+                                 owner_events,
+                                 event_mask,
+                                 0,
+                                 time,
+                                 FALSE);
+
+  return GDK_GRAB_SUCCESS;
 }
 
-/* This is used to break any grabs in the case where we have to due to
- * the grab emulation. Instead of enforcing the desktop wide grab, we
- * break it when the app loses focus for example.
- */
 static void
-break_all_grabs (void)
+break_all_grabs (guint32 time)
 {
-  if (_gdk_quartz_keyboard_grab_window)
-    {
-      generate_grab_broken_event (_gdk_quartz_keyboard_grab_window,
-                                  TRUE, FALSE,
-                                  NULL);
-      g_object_unref (_gdk_quartz_keyboard_grab_window);
-      _gdk_quartz_keyboard_grab_window = NULL;
-    }
+  GdkPointerGrabInfo *grab;
+
+  if (_gdk_display->keyboard_grab.window)
+    _gdk_display_unset_has_keyboard_grab (_gdk_display, FALSE);
 
-  if (_gdk_quartz_pointer_grab_window)
+  grab = _gdk_display_get_last_pointer_grab (_gdk_display);
+  if (grab)
     {
-      generate_grab_broken_event (_gdk_quartz_pointer_grab_window,
-                                  FALSE, pointer_grab_implicit,
-                                  NULL);
-      pointer_ungrab_internal (FALSE);
+      grab->serial_end = 0;
+      grab->implicit_ungrab = TRUE;
     }
+
+  _gdk_display_pointer_grab_update (_gdk_display, 0);
 }
 
 static void
@@ -341,81 +187,27 @@ append_event (GdkEvent *event)
   _gdk_event_queue_append (_gdk_display, event);
 }
 
-static GdkFilterReturn
-apply_filters (GdkWindow  *window,
-              NSEvent    *nsevent,
-              GList      *filters)
+static gint
+gdk_event_apply_filters (NSEvent *nsevent,
+                        GdkEvent *event,
+                        GList *filters)
 {
-  GdkFilterReturn result = GDK_FILTER_CONTINUE;
-  GdkEvent *event;
-  GList *node;
   GList *tmp_list;
-
-  event = gdk_event_new (GDK_NOTHING);
-  if (window != NULL)
-    event->any.window = g_object_ref (window);
-  ((GdkEventPrivate *)event)->flags |= GDK_EVENT_PENDING;
-
-  /* I think GdkFilterFunc semantics require the passed-in event
-   * to already be in the queue. The filter func can generate
-   * more events and append them after it if it likes.
-   */
-  node = _gdk_event_queue_append (_gdk_display, event);
+  GdkFilterReturn result;
   
   tmp_list = filters;
+
   while (tmp_list)
     {
-      GdkEventFilter *filter = (GdkEventFilter *) tmp_list->data;
+      GdkEventFilter *filter = (GdkEventFilter*) tmp_list->data;
       
       tmp_list = tmp_list->next;
       result = filter->function (nsevent, event, filter->data);
-      if (result != GDK_FILTER_CONTINUE)
-       break;
-    }
-
-  if (result == GDK_FILTER_CONTINUE || result == GDK_FILTER_REMOVE)
-    {
-      _gdk_event_queue_remove_link (_gdk_display, node);
-      g_list_free_1 (node);
-      gdk_event_free (event);
-    }
-  else /* GDK_FILTER_TRANSLATE */
-    {
-      ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
-      fixup_event (event);
-    }
-  return result;
-}
-
-/* Checks if the passed in window is interested in the event mask, and
- * if so, it's returned. If not, the event can be propagated through
- * its ancestors until one with the right event mask is found, up to
- * the nearest toplevel.
- */
-static GdkWindow *
-find_window_interested_in_event_mask (GdkWindow    *window, 
-                                     GdkEventMask  event_mask,
-                                     gboolean      propagate)
-{
-  GdkWindowObject *private;
-
-  private = GDK_WINDOW_OBJECT (window);
-  while (private)
-    {
-      if (private->event_mask & event_mask)
-       return (GdkWindow *)private;
-
-      if (!propagate)
-       return NULL;
-
-      /* Don't traverse beyond toplevels. */
-      if (GDK_WINDOW_TYPE (private) != GDK_WINDOW_CHILD)
-       break;
-
-      private = private->parent;
+      if (result !=  GDK_FILTER_CONTINUE)
+       return result;
     }
 
-  return NULL;
+  return GDK_FILTER_CONTINUE;
 }
 
 static guint32
@@ -540,6 +332,14 @@ get_event_mask_from_ns_event (NSEvent *nsevent)
            g_assert_not_reached ();
          }
       }
+      break;
+
+    case NSMouseEntered:
+      return GDK_ENTER_NOTIFY_MASK;
+
+    case NSMouseExited:
+      return GDK_LEAVE_NOTIFY_MASK;
+
     default:
       g_assert_not_reached ();
     }
@@ -585,708 +385,64 @@ _gdk_quartz_events_update_focus_window (GdkWindow *window,
   if (got_focus)
     {
       if (current_keyboard_window)
-       {
-         event = create_focus_event (current_keyboard_window, FALSE);
-         append_event (event);
-         g_object_unref (current_keyboard_window);
-         current_keyboard_window = NULL;
-       }
-      
-      event = create_focus_event (window, TRUE);
-      append_event (event);
-      current_keyboard_window = g_object_ref (window);
-    }
-}
-
-static void
-convert_window_coordinates_to_root (GdkWindow *window,
-                                   gdouble    x,
-                                   gdouble    y,
-                                   gdouble   *x_root,
-                                   gdouble   *y_root)
-{
-  gint ox, oy;
-
-  *x_root = x;
-  *y_root = y;
-  
-  if (gdk_window_get_origin (window, &ox, &oy))
-    {
-      *x_root += ox;
-      *y_root += oy;
-    }
-}
-
-/* FIXME: Refactor and share with scroll event. */
-static GdkEvent *
-create_crossing_event (GdkWindow      *window, 
-                      NSEvent        *nsevent, 
-                      GdkEventType    event_type,
-                      GdkCrossingMode mode, 
-                      GdkNotifyType   detail)
-{
-  GdkEvent *event;
-  gint x_tmp, y_tmp;
-
-  event = gdk_event_new (event_type);
-
-  event->crossing.window = window;
-  event->crossing.subwindow = NULL; /* FIXME */
-  event->crossing.time = get_time_from_ns_event (nsevent);
-
-  /* Split out this block: */
-  {
-    NSWindow *nswindow;
-    GdkWindow *toplevel;
-    GdkWindowImplQuartz *impl;
-    NSPoint point;
-
-    nswindow = [nsevent window];
-    point = [nsevent locationInWindow];
-
-    toplevel = [(GdkQuartzView *)[nswindow contentView] gdkWindow];
-
-    impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (toplevel)->impl);
-
-    x_tmp = point.x;
-    y_tmp = impl->height - point.y;
-
-    get_converted_window_coordinates (toplevel,
-                                      x_tmp, y_tmp,
-                                      window,
-                                      &x_tmp, &y_tmp);
-    }
-
-  event->crossing.x = x_tmp;
-  event->crossing.y = y_tmp;
-
-  convert_window_coordinates_to_root (window, 
-                                      event->crossing.x, 
-                                      event->crossing.y, 
-                                     &event->crossing.x_root,
-                                     &event->crossing.y_root);
-
-  event->crossing.mode = mode;
-  event->crossing.detail = detail;
-  event->crossing.state = get_keyboard_modifiers_from_ns_event (nsevent);
-
-  /* FIXME: focus and button state */
-
-  return event;
-}
-
-static void
-synthesize_enter_event (GdkWindow      *window,
-                       NSEvent        *nsevent,
-                       GdkCrossingMode mode,
-                       GdkNotifyType   detail)
-{
-  GdkEvent *event;
-
-  if (_gdk_quartz_pointer_grab_window != NULL && 
-      !pointer_grab_owner_events && 
-      !(pointer_grab_event_mask & GDK_ENTER_NOTIFY_MASK))
-    return;
-
-  if (!(GDK_WINDOW_OBJECT (window)->event_mask & GDK_ENTER_NOTIFY_MASK))
-    return;
-
-  event = create_crossing_event (window, nsevent, GDK_ENTER_NOTIFY,
-                                mode, detail);
-
-  append_event (event);
-}
-  
-static void
-synthesize_enter_events (GdkWindow      *from,
-                        GdkWindow      *to,
-                        NSEvent        *nsevent,
-                        GdkCrossingMode mode,
-                        GdkNotifyType   detail)
-{
-  GdkWindow *prev = gdk_window_get_parent (to);
-
-  if (prev != from)
-    synthesize_enter_events (from, prev, nsevent, mode, detail);
-  synthesize_enter_event (to, nsevent, mode, detail);
-}
-
-static void
-synthesize_leave_event (GdkWindow      *window,
-                       NSEvent        *nsevent,
-                       GdkCrossingMode mode,
-                       GdkNotifyType   detail)
-{
-  GdkEvent *event;
-
-  if (_gdk_quartz_pointer_grab_window != NULL && 
-      !pointer_grab_owner_events && 
-      !(pointer_grab_event_mask & GDK_LEAVE_NOTIFY_MASK))
-    return;
-
-  if (!(GDK_WINDOW_OBJECT (window)->event_mask & GDK_LEAVE_NOTIFY_MASK))
-    return;
-
-  event = create_crossing_event (window, nsevent, GDK_LEAVE_NOTIFY,
-                                mode, detail);
-
-  append_event (event);
-}
-                        
-static void
-synthesize_leave_events (GdkWindow     *from,
-                        GdkWindow      *to,
-                        NSEvent        *nsevent,
-                        GdkCrossingMode mode,
-                        GdkNotifyType   detail)
-{
-  GdkWindow *next = gdk_window_get_parent (from);
-  
-  synthesize_leave_event (from, nsevent, mode, detail);
-  if (next != to)
-    synthesize_leave_events (next, to, nsevent, mode, detail);
-}
-                        
-static void
-synthesize_crossing_events (GdkWindow      *window,
-                           GdkCrossingMode mode,
-                           NSEvent        *nsevent,
-                           gint            x,
-                           gint            y)
-{
-  GdkWindow *intermediate, *tem, *common_ancestor;
-
-  if (window == current_mouse_window)
-    return;
-
-  if (_gdk_quartz_window_is_ancestor (current_mouse_window, window))
-    {
-      /* Pointer has moved to an inferior window. */
-      synthesize_leave_event (current_mouse_window, nsevent, mode, GDK_NOTIFY_INFERIOR);
-
-      /* If there are intermediate windows, generate ENTER_NOTIFY
-       * events for them
-       */
-      intermediate = gdk_window_get_parent (window);
-
-      if (intermediate != current_mouse_window)
-       {
-         synthesize_enter_events (current_mouse_window, intermediate, nsevent, mode, GDK_NOTIFY_VIRTUAL);
-       }
-
-      synthesize_enter_event (window, nsevent, mode, GDK_NOTIFY_ANCESTOR);
-    }
-  else if (_gdk_quartz_window_is_ancestor (window, current_mouse_window))
-    {
-      /* Pointer has moved to an ancestor window. */
-      synthesize_leave_event (current_mouse_window, nsevent, mode, GDK_NOTIFY_ANCESTOR);
-      
-      /* If there are intermediate windows, generate LEAVE_NOTIFY
-       * events for them
-       */
-      intermediate = gdk_window_get_parent (current_mouse_window);
-      if (intermediate != window)
-       {
-         synthesize_leave_events (intermediate, window, nsevent, mode, GDK_NOTIFY_VIRTUAL);
-       }
-
-      synthesize_enter_event (window, nsevent, mode, GDK_NOTIFY_INFERIOR);
-    }
-  else if (current_mouse_window)
-    {
-      /* Find least common ancestor of current_mouse_window and window */
-      tem = current_mouse_window;
-      do {
-       common_ancestor = gdk_window_get_parent (tem);
-       tem = common_ancestor;
-      } while (common_ancestor &&
-              !_gdk_quartz_window_is_ancestor (common_ancestor, window));
-      if (common_ancestor)
-       {
-         synthesize_leave_event (current_mouse_window, nsevent, mode, GDK_NOTIFY_NONLINEAR);
-         intermediate = gdk_window_get_parent (current_mouse_window);
-         if (intermediate != common_ancestor)
-           {
-             synthesize_leave_events (intermediate, common_ancestor,
-                                      nsevent, mode, GDK_NOTIFY_NONLINEAR_VIRTUAL);
-           }
-         intermediate = gdk_window_get_parent (window);
-         if (intermediate != common_ancestor)
-           {
-             synthesize_enter_events (common_ancestor, intermediate,
-                                      nsevent, mode, GDK_NOTIFY_NONLINEAR_VIRTUAL);
-           }
-         synthesize_enter_event (window, nsevent, mode, GDK_NOTIFY_NONLINEAR);
-       }
-    }
-  else
-    {
-      /* This means we have no current_mouse_window, which probably
-       * means that there is a bug somewhere, we should always have
-       * the root in we don't have another window. Does this ever
-       * happen?
-       */
-      g_warning ("Trying to create crossing event when current_mouse_window is NULL");
-    }
-
-  _gdk_quartz_events_update_mouse_window (window);
-
-  /* FIXME: This does't work when someone calls gdk_window_set_cursor
-   * during a grab. The right behavior is that the cursor doesn't
-   * change when a grab is in effect, but in that case it does.
-   */
-  if (window && !_gdk_quartz_pointer_grab_window)
-    _gdk_quartz_events_update_cursor (window);
-}
-
-void 
-_gdk_quartz_events_send_map_events (GdkWindow *window)
-{
-  GList *list;
-  GdkWindow *interested_window;
-  GdkWindowObject *private = (GdkWindowObject *)window;
-
-  interested_window = find_window_interested_in_event_mask (window, 
-                                                           GDK_STRUCTURE_MASK,
-                                                           TRUE);
-  
-  if (interested_window)
-    {
-      GdkEvent *event = gdk_event_new (GDK_MAP);
-      event->any.window = interested_window;
-      append_event (event);
-    }
-
-  for (list = private->children; list != NULL; list = list->next)
-    _gdk_quartz_events_send_map_events ((GdkWindow *)list->data);
-}
-
-/* Get current mouse window */
-GdkWindow *
-_gdk_quartz_events_get_mouse_window (gboolean consider_grabs)
-{
-  if (!consider_grabs)
-    return current_mouse_window;
-
-  if (_gdk_quartz_pointer_grab_window && !pointer_grab_owner_events)
-    return _gdk_quartz_pointer_grab_window;
-  
-  return current_mouse_window;
-}
-
-/* Update mouse window */
-void 
-_gdk_quartz_events_update_mouse_window (GdkWindow *window)
-{
-  if (window == current_mouse_window)
-    return;
-
-#ifdef G_ENABLE_DEBUG
-  if (_gdk_debug_flags & GDK_DEBUG_EVENTS)
-    _gdk_quartz_window_debug_highlight (window, 0);
-#endif /* G_ENABLE_DEBUG */  
-
-  if (window)
-    g_object_ref (window);
-  if (current_mouse_window)
-    g_object_unref (current_mouse_window);
-
-  current_mouse_window = window;
-}
-
-/* Update current cursor */
-void
-_gdk_quartz_events_update_cursor (GdkWindow *window)
-{
-  GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
-  NSCursor *nscursor = nil;
-
-  while (private)
-    {
-      GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
-
-      nscursor = impl->nscursor;
-      if (nscursor)
-        break;
-
-      private = private->parent;
-    }
-
-  GDK_QUARTZ_ALLOC_POOL;
-
-  if (!nscursor)
-    nscursor = [NSCursor arrowCursor];
-
-  if ([NSCursor currentCursor] != nscursor)
-    [nscursor set];
-
-  GDK_QUARTZ_RELEASE_POOL;
-}
-
-/* Translates coordinates from an ancestor window + coords, to
- * coordinates that are relative the child window.
- */
-static void
-get_child_coordinates_from_ancestor (GdkWindow *ancestor_window,
-                                    gint       ancestor_x,
-                                    gint       ancestor_y,
-                                    GdkWindow *child_window, 
-                                    gint      *child_x, 
-                                    gint      *child_y)
-{
-  GdkWindowObject *ancestor_private = GDK_WINDOW_OBJECT (ancestor_window);
-  GdkWindowObject *child_private = GDK_WINDOW_OBJECT (child_window);
-
-  while (child_private != ancestor_private)
-    {
-      ancestor_x -= child_private->x;
-      ancestor_y -= child_private->y;
-
-      child_private = child_private->parent;
-    }
-
-  *child_x = ancestor_x;
-  *child_y = ancestor_y;
-}
-
-/* Translates coordinates from a child window + coords, to
- * coordinates that are relative the ancestor window.
- */
-static void
-get_ancestor_coordinates_from_child (GdkWindow *child_window,
-                                    gint       child_x,
-                                    gint       child_y,
-                                    GdkWindow *ancestor_window, 
-                                    gint      *ancestor_x, 
-                                    gint      *ancestor_y)
-{
-  GdkWindowObject *child_private = GDK_WINDOW_OBJECT (child_window);
-  GdkWindowObject *ancestor_private = GDK_WINDOW_OBJECT (ancestor_window);
-
-  while (child_private != ancestor_private)
-    {
-      child_x += child_private->x;
-      child_y += child_private->y;
-
-      child_private = child_private->parent;
-    }
-
-  *ancestor_x = child_x;
-  *ancestor_y = child_y;
-}
-
-/* Translates coordinates relative to one window (in_window) into
- * coordinates relative to another window (out_window).
- */
-static void
-get_converted_window_coordinates (GdkWindow *in_window,
-                                  gint       in_x,
-                                  gint       in_y,
-                                  GdkWindow *out_window, 
-                                  gint      *out_x, 
-                                  gint      *out_y)
-{
-  GdkWindow *in_toplevel;
-  GdkWindow *out_toplevel;
-  int in_origin_x, in_origin_y;
-  int out_origin_x, out_origin_y;
-
-  if (in_window == out_window)
-    {
-      *out_x = in_x;
-      *out_y = in_y;
-      return;
-    }
-
-  /* First translate to "in" toplevel coordinates, then on to "out"
-   * toplevel coordinates, and finally to "out" child (the passed in
-   * window) coordinates.
-   */
-
-  in_toplevel = gdk_window_get_toplevel (in_window);
-  out_toplevel  = gdk_window_get_toplevel (out_window);
-
-  /* Translate in_x, in_y to "in" toplevel coordinates. */
-  get_ancestor_coordinates_from_child (in_window, in_x, in_y,
-                                       in_toplevel, &in_x, &in_y);
-
-  gdk_window_get_origin (in_toplevel, &in_origin_x, &in_origin_y);
-  gdk_window_get_origin (out_toplevel, &out_origin_x, &out_origin_y);
-
-  /* Translate in_x, in_y to "out" toplevel coordinates. */
-  in_x -= out_origin_x - in_origin_x;
-  in_y -= out_origin_y - in_origin_y;
-
-  get_child_coordinates_from_ancestor (out_toplevel, 
-                                       in_x, in_y,
-                                       out_window,
-                                       out_x, out_y);
-}
-
-/* Given a mouse NSEvent (must be a mouse event for a GDK window),
- * finds the subwindow over which the pointer is located. Returns
- * coordinates relative to the found window. If no window is found,
- * returns the root window, and root window coordinates.
- */
-static GdkWindow *
-find_mouse_window_for_ns_event (NSEvent *nsevent,
-                                gint    *x_ret,
-                                gint    *y_ret)
-{
-  GdkWindow *event_toplevel;
-  GdkWindowImplQuartz *impl;
-  GdkWindow *mouse_toplevel;
-  GdkWindow *mouse_window;
-  NSPoint point;
-  gint x_tmp, y_tmp;
-
-  event_toplevel = [(GdkQuartzView *)[[nsevent window] contentView] gdkWindow];
-  impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (event_toplevel)->impl);
-  point = [nsevent locationInWindow];
-
-  x_tmp = point.x;
-  y_tmp = impl->height - point.y;
-
-  mouse_toplevel = gdk_window_get_toplevel (current_mouse_window);
-
-  get_converted_window_coordinates (event_toplevel,
-                                    x_tmp, y_tmp,
-                                    mouse_toplevel,
-                                    &x_tmp, &y_tmp);
-
-  mouse_window = _gdk_quartz_window_find_child (mouse_toplevel, x_tmp, y_tmp);
-  if (mouse_window && mouse_window != mouse_toplevel)
-    {
-      get_child_coordinates_from_ancestor (mouse_toplevel,
-                                           x_tmp, y_tmp,
-                                           mouse_window,
-                                           &x_tmp, &y_tmp);
-    }
-  else if (!mouse_window)
-    {
-      /* This happens for events on the window title buttons and the
-       * desktop, treat those as being on the root window.
-       */
-      get_converted_window_coordinates (mouse_toplevel,
-                                        x_tmp, y_tmp,
-                                        _gdk_root,
-                                        &x_tmp, &y_tmp);
-      mouse_window = _gdk_root;
+       {
+         event = create_focus_event (current_keyboard_window, FALSE);
+         append_event (event);
+         g_object_unref (current_keyboard_window);
+         current_keyboard_window = NULL;
+       }
+      
+      event = create_focus_event (window, TRUE);
+      append_event (event);
+      current_keyboard_window = g_object_ref (window);
     }
-
-  *x_ret = x_tmp;
-  *y_ret = y_tmp;
-
-  return mouse_window;
 }
 
-/* Trigger crossing events if necessary. This is used when showing a new
- * window, since the tracking rect API doesn't work reliably when a window
- * shows up under the mouse cursor. It's done by finding the topmost window
- * under the mouse pointer and synthesizing crossing events into that
- * window.
- */
 void
-_gdk_quartz_events_trigger_crossing_events (gboolean defer_to_mainloop)
+_gdk_quartz_events_send_map_event (GdkWindow *window)
 {
-  NSPoint point;
-  gint x, y; 
-  gint x_toplevel, y_toplevel;
-  GdkWindow *mouse_window;
-  GdkWindow *toplevel;
-  GdkWindowImplQuartz *impl;
-  guint flags = 0;
-  NSTimeInterval timestamp = 0;
-  NSEvent *current_event;
-  NSEvent *nsevent;
-
-  if (defer_to_mainloop)
-    {
-      nsevent = [NSEvent otherEventWithType:NSApplicationDefined
-                                   location:NSZeroPoint
-                              modifierFlags:0
-                                  timestamp:0
-                               windowNumber:0
-                                    context:nil
-                                    subtype:GDK_QUARTZ_EVENT_SUBTYPE_FAKE_CROSSING
-                                      data1:0
-                                      data2:0];
-      [NSApp postEvent:nsevent atStart:NO];
-      return;
-    }
-
-  point = [NSEvent mouseLocation];
-  x = point.x;
-  y = _gdk_quartz_window_get_inverted_screen_y (point.y);
-
-  mouse_window = _gdk_quartz_window_find_child (_gdk_root, x, y);
-  if (!mouse_window || mouse_window == _gdk_root)
-    return;
-
-  toplevel = gdk_window_get_toplevel (mouse_window);
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
 
-  /* We ignore crossing within the same toplevel since that is already
-   * handled elsewhere.
-   */
-  if (toplevel == gdk_window_get_toplevel (current_mouse_window))
+  if (!impl->toplevel)
     return;
 
-  get_converted_window_coordinates (_gdk_root,
-                                    x, y,
-                                    toplevel,
-                                    &x_toplevel, &y_toplevel);
-
-  get_converted_window_coordinates (_gdk_root,
-                                    x, y,
-                                    mouse_window,
-                                    &x, &y);
-
-  /* Fix up the event to be less fake if possible. */
-  current_event = [NSApp currentEvent];
-  if (current_event)
+  if (private->event_mask & GDK_STRUCTURE_MASK)
     {
-      flags = [current_event modifierFlags];
-      timestamp = [current_event timestamp];
-    }
+      GdkEvent event;
 
-  if (timestamp == 0)
-    timestamp = GetCurrentEventTime ();
-
-  impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (toplevel)->impl);
-  nsevent = [NSEvent otherEventWithType:NSApplicationDefined
-                               location:NSMakePoint (x_toplevel, impl->height - y_toplevel)
-                          modifierFlags:flags
-                              timestamp:timestamp
-                           windowNumber:[impl->toplevel windowNumber]
-                                context:nil
-                                subtype:GDK_QUARTZ_EVENT_SUBTYPE_FAKE_CROSSING
-                                  data1:0
-                                  data2:0];
-
-#ifdef G_ENABLE_DEBUG
-  /*_gdk_quartz_window_debug_highlight (mouse_window, 0);*/
-#endif
-
-  synthesize_crossing_events (mouse_window, GDK_CROSSING_NORMAL, nsevent, x, y);
+      event.any.type = GDK_MAP;
+      event.any.window = window;
+  
+      gdk_event_put (&event);
+    }
 }
 
-/* Synthesizes crossing events if necessary, based on the passed in
- * NSEvent. Uses NSMouseEntered and NSMouseExisted for toplevels and
- * the mouse moved/dragged events for child windows, to see if the
- * mouse window has changed.
- */
-static void
-synthesize_crossing_events_for_ns_event (NSEvent *nsevent)
+static GdkWindow *
+find_toplevel_under_pointer (GdkDisplay *display,
+                             NSPoint     screen_point,
+                             gint       *x,
+                             gint       *y)
 {
-  NSEventType event_type;
-  GdkWindow *mouse_window;
-  gint x; 
-  gint y;
-
-  event_type = [nsevent type];
+  GdkWindow *toplevel;
 
-  switch (event_type)
+  toplevel = display->pointer_info.toplevel_under_pointer;
+  if (toplevel)
     {
-    case NSMouseMoved:
-    case NSLeftMouseDragged:
-    case NSRightMouseDragged:
-    case NSOtherMouseDragged:
-      /* We only handle moving the pointer to another GDK window.
-       * Leaving to a non-GDK toplevel window (or window title bar or
-       * the desktop) is covered by NSMouseExited events.
-       */
-      mouse_window = find_mouse_window_for_ns_event (nsevent, &x, &y);
-      if (mouse_window != _gdk_root)
-        synthesize_crossing_events (mouse_window, GDK_CROSSING_NORMAL, nsevent, x, y);
-
-      break;
-
-    case NSMouseEntered:
-      {
-       GdkWindow *event_toplevel;
-        GdkWindowImplQuartz *impl;
-        NSPoint point;
+      GdkWindowObject *private;
+      NSWindow *nswindow;
+      NSPoint point;
 
-        /* This is the only case where we actually use the window from
-         * the event since we need to know which toplevel we entered
-         * so it can be tracked properly.
-         */
-        event_toplevel = [(GdkQuartzView *)[[nsevent window] contentView] gdkWindow];
-        impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (event_toplevel)->impl);
+      private = (GdkWindowObject *)toplevel;
+      nswindow = ((GdkWindowImplQuartz *)private->impl)->toplevel;
 
-        point = [nsevent locationInWindow];
+      point = [nswindow convertScreenToBase:screen_point];
 
-        x = point.x;
-        y = impl->height - point.y;
-
-       mouse_window = _gdk_quartz_window_find_child (event_toplevel, x, y);
-
-        /* Treat unknown windows (like the title bar buttons or
-         * desktop) as the root window.
-         */
-        if (!mouse_window)
-          mouse_window = _gdk_root;
-
-        if (mouse_window != event_toplevel)
-          get_converted_window_coordinates (event_toplevel,
-                                            x, y,
-                                            mouse_window,
-                                            &x, &y);
-
-        synthesize_crossing_events (mouse_window, GDK_CROSSING_NORMAL, nsevent, x, y);
-      }
-      break;
-
-    case NSMouseExited:
-      {
-       GdkWindow *event_toplevel;
-        GdkWindowImplQuartz *impl;
-        NSPoint point;
-
-        /* We only use NSMouseExited when leaving to the root
-         * window. The other cases are handled above by checking the
-         * motion/button events, or getting a NSMouseEntered for
-         * another GDK window. The reason we don't use NSMouseExited
-         * for other windows is that quartz first delivers the entered
-         * event and then the exited which is the opposite from what
-         * we need.
-         */
-        event_toplevel = [(GdkQuartzView *)[[nsevent window] contentView] gdkWindow];
-        impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (event_toplevel)->impl);
-        point = [nsevent locationInWindow];
-
-        x = point.x;
-        y = impl->height - point.y;
-
-        x += GDK_WINDOW_OBJECT (event_toplevel)->x;
-        y += GDK_WINDOW_OBJECT (event_toplevel)->y;
-
-        /* If there is a window other than the root window at this
-         * position, it means we didn't exit to the root window and we
-         * ignore the event. (Note that we can get NULL here when swithing
-         * spaces for example.)
-         *
-         * FIXME: This is not enough, it doesn't catch the case where
-         * we leave a GDK window to a non-GDK window that has GDK
-         * windows below it.
-         */
-        mouse_window = _gdk_quartz_window_find_child (_gdk_root, x, y);
-
-        if (!mouse_window ||
-            gdk_window_get_toplevel (mouse_window) ==
-            gdk_window_get_toplevel (current_mouse_window))
-          {
-            mouse_window = _gdk_root;
-          }
-
-        if (mouse_window == _gdk_root)
-          synthesize_crossing_events (_gdk_root, GDK_CROSSING_NORMAL, nsevent, x, y);
-      }
-      break;
-
-    default:
-      break;
+      *x = point.x;
+      *y = private->height - point.y;
     }
+
+  return toplevel;
 }
 
 /* This function finds the correct window to send an event to, taking
@@ -1295,10 +451,31 @@ synthesize_crossing_events_for_ns_event (NSEvent *nsevent)
 static GdkWindow *
 find_window_for_ns_event (NSEvent *nsevent, 
                           gint    *x, 
-                          gint    *y)
+                          gint    *y,
+                          gint    *x_root,
+                          gint    *y_root)
 {
+  GdkQuartzView *view;
+  GdkWindow *toplevel;
+  GdkWindowObject *private;
+  NSPoint point;
+  NSPoint screen_point;
   NSEventType event_type;
 
+  view = (GdkQuartzView *)[[nsevent window] contentView];
+
+  toplevel = [view gdkWindow];
+  private = GDK_WINDOW_OBJECT (toplevel);
+
+  point = [nsevent locationInWindow];
+  screen_point = [[nsevent window] convertBaseToScreen:point];
+
+  *x = point.x;
+  *y = private->height - point.y;
+
+  *x_root = screen_point.x;
+  *y_root = _gdk_quartz_window_get_inverted_screen_y (screen_point.y);
+
   event_type = [nsevent type];
 
   switch (event_type)
@@ -1315,9 +492,10 @@ find_window_for_ns_event (NSEvent *nsevent,
     case NSRightMouseDragged:
     case NSOtherMouseDragged:
       {
-       GdkWindow *mouse_window;
-       GdkEventMask event_mask;
-       GdkWindow *real_window;
+       GdkDisplay *display;
+        GdkPointerGrabInfo *grab;
+
+        display = gdk_drawable_get_display (toplevel);
 
        /* From the docs for XGrabPointer:
         *
@@ -1327,53 +505,53 @@ find_window_for_ns_event (NSEvent *nsevent,
         * the grab_window and is reported only if selected by
         * event_mask. For either value of owner_events, unreported
         * events are discarded.
-        *
-        * This means we first try the owner, then the grab window,
-        * then give up.
         */
-       if (_gdk_quartz_pointer_grab_window)
+        grab = _gdk_display_get_last_pointer_grab (display);
+       if (grab)
          {
-           if (pointer_grab_owner_events)
-             {
-                mouse_window = find_mouse_window_for_ns_event (nsevent, x, y);
-               event_mask = get_event_mask_from_ns_event (nsevent);
-               real_window = find_window_interested_in_event_mask (mouse_window, event_mask, TRUE);
-               
-               if (mouse_window && real_window && mouse_window != real_window)
-                 get_ancestor_coordinates_from_child (mouse_window,
-                                                      *x, *y,
-                                                      real_window,
-                                                      x, y);
-
-               if (real_window)
-                 return real_window;
-             }
-
-           /* Finally check the grab window. */
-           if (pointer_grab_event_mask & get_event_mask_from_ns_event (nsevent))
-             {
-                GdkWindow *event_toplevel;
+           if ((grab->event_mask & get_event_mask_from_ns_event (nsevent)) == 0)
+              return NULL;
+
+            if (grab->owner_events)
+              {
+                /* For owner events, we need to use the toplevel under the
+                 * pointer, not the window from the NSEvent, since that is
+                 * reported with respect to the key window, which could be
+                 * wrong.
+                 */
+                GdkWindow *toplevel_under_pointer;
+                gint x_tmp, y_tmp;
+
+                toplevel_under_pointer = find_toplevel_under_pointer (display,
+                                                                      screen_point,
+                                                                      &x_tmp, &y_tmp);
+                if (toplevel_under_pointer)
+                  {
+                    toplevel = toplevel_under_pointer;
+                    *x = x_tmp;
+                    *y = y_tmp;
+                  }
+
+                return toplevel;
+              }
+            else
+              {
+                /* Finally check the grab window. */
                GdkWindow *grab_toplevel;
-               NSPoint point;
-               int x_tmp, y_tmp;
+                GdkWindowObject *grab_private;
+                NSWindow *grab_nswindow;
 
-                event_toplevel = [(GdkQuartzView *)[[nsevent window] contentView] gdkWindow];
-               grab_toplevel = gdk_window_get_toplevel (_gdk_quartz_pointer_grab_window);
-               point = [nsevent locationInWindow];
+               grab_toplevel = gdk_window_get_toplevel (grab->window);
+                grab_private = (GdkWindowObject *)grab_toplevel;
 
-               x_tmp = point.x;
-               y_tmp = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (grab_toplevel)->impl)->height - point.y;
+                grab_nswindow = ((GdkWindowImplQuartz *)grab_private->impl)->toplevel;
+                point = [grab_nswindow convertScreenToBase:screen_point];
 
-                /* Translate the coordinates so they are relative to
-                 * the grab window instead of the event toplevel for
-                 * the cases where they are not the same.
-                 */
-                get_converted_window_coordinates (event_toplevel,
-                                                  x_tmp, y_tmp,
-                                                  _gdk_quartz_pointer_grab_window,
-                                                  x, y);
+                /* Note: x_root and y_root are already right. */
+                *x = point.x;
+                *y = grab_private->height - point.y;
 
-               return _gdk_quartz_pointer_grab_window;
+               return grab_toplevel;
              }
 
            return NULL;
@@ -1381,42 +559,55 @@ find_window_for_ns_event (NSEvent *nsevent,
        else 
          {
            /* The non-grabbed case. */
-            mouse_window = find_mouse_window_for_ns_event (nsevent, x, y);
-           event_mask = get_event_mask_from_ns_event (nsevent);
-           real_window = find_window_interested_in_event_mask (mouse_window, event_mask, TRUE);
-           
-           /* We have to translate the coordinates if the actual
-            * window is different from the mouse window.
-            */
-           if (mouse_window && real_window && mouse_window != real_window)
-             get_ancestor_coordinates_from_child (mouse_window,
-                                                  *x, *y,
-                                                  real_window,
-                                                  x, y);
-
-           return real_window;
+            GdkWindow *toplevel_under_pointer;
+            gint x_tmp, y_tmp;
+
+            /* Ignore all events but mouse moved that might be on the title
+             * bar (above the content view). The reason is that otherwise
+             * gdk gets confused about getting e.g. button presses with no
+             * window (the title bar is not known to it).
+             */
+            if (event_type != NSMouseMoved)
+              if (*y < 0)
+                return NULL;
+
+            /* FIXME: Also need to leave resize events to cocoa somehow? */
+
+            /* As for owner events, we need to use the toplevel under the
+             * pointer, not the window from the NSEvent.
+             */
+            toplevel_under_pointer = find_toplevel_under_pointer (display,
+                                                                  screen_point,
+                                                                  &x_tmp, &y_tmp);
+            if (toplevel_under_pointer)
+              {
+                toplevel = toplevel_under_pointer;
+                *x = x_tmp;
+                *y = y_tmp;
+              }
+
+            return toplevel;
          }
       }
       break;
       
     case NSMouseEntered:
     case NSMouseExited:
-      /* Already handled in synthesize_crossing_events_for_ns_event. */
-      break;
+      /* Only handle our own entered/exited events, not the ones for the
+       * titlebar buttons.
+       */
+      if ([view trackingRect] == [nsevent trackingNumber])
+        return toplevel;
+      else
+        return NULL;
 
     case NSKeyDown:
     case NSKeyUp:
     case NSFlagsChanged:
-      {
-       GdkEventMask event_mask;
+      if (_gdk_display->keyboard_grab.window && !_gdk_display->keyboard_grab.owner_events)
+        return gdk_window_get_toplevel (_gdk_display->keyboard_grab.window);
 
-       if (_gdk_quartz_keyboard_grab_window && !keyboard_grab_owner_events)
-         return _gdk_quartz_keyboard_grab_window;
-
-       event_mask = get_event_mask_from_ns_event (nsevent);
-       return find_window_interested_in_event_mask (current_keyboard_window, event_mask, TRUE);
-      }
-      break;
+      return toplevel;
 
     default:
       /* Ignore everything else. */
@@ -1426,13 +617,42 @@ find_window_for_ns_event (NSEvent *nsevent,
   return NULL;
 }
 
-static GdkEvent *
-create_button_event (GdkWindow *window, 
-                     NSEvent   *nsevent,
-                    gint       x,
-                     gint       y)
+static void
+fill_crossing_event (GdkWindow       *toplevel,
+                     GdkEvent        *event,
+                     NSEvent         *nsevent,
+                     gint             x,
+                     gint             y,
+                     gint             x_root,
+                     gint             y_root,
+                     GdkEventType     event_type,
+                     GdkCrossingMode  mode,
+                     GdkNotifyType    detail)
+{
+  event->any.type = event_type;
+  event->crossing.window = toplevel;
+  event->crossing.subwindow = NULL;
+  event->crossing.time = get_time_from_ns_event (nsevent);
+  event->crossing.x = x;
+  event->crossing.y = y;
+  event->crossing.x_root = x_root;
+  event->crossing.y_root = y_root;
+  event->crossing.mode = mode;
+  event->crossing.detail = detail;
+  event->crossing.state = get_keyboard_modifiers_from_ns_event (nsevent);
+
+  /* FIXME: Focus and button state? */
+}
+
+static void
+fill_button_event (GdkWindow *window,
+                   GdkEvent  *event,
+                   NSEvent   *nsevent,
+                   gint       x,
+                   gint       y,
+                   gint       x_root,
+                   gint       y_root)
 {
-  GdkEvent *event;
   GdkEventType type;
   gint state;
   gint button;
@@ -1458,110 +678,105 @@ create_button_event (GdkWindow *window,
   
   button = get_mouse_button_from_ns_event (nsevent);
 
-  event = gdk_event_new (type);
+  event->any.type = type;
   event->button.window = window;
   event->button.time = get_time_from_ns_event (nsevent);
   event->button.x = x;
   event->button.y = y;
+  event->button.x_root = x_root;
+  event->button.y_root = y_root;
   /* FIXME event->axes */
   event->button.state = state;
   event->button.button = button;
   event->button.device = _gdk_display->core_pointer;
-  convert_window_coordinates_to_root (window, x, y, 
-                                     &event->button.x_root,
-                                     &event->button.y_root);
-
-  return event;
 }
 
-static GdkEvent *
-create_motion_event (GdkWindow *window, 
-                     NSEvent   *nsevent, 
-                     gint       x, 
-                     gint       y)
+static void
+fill_motion_event (GdkWindow *window,
+                   GdkEvent  *event,
+                   NSEvent   *nsevent,
+                   gint       x,
+                   gint       y,
+                   gint       x_root,
+                   gint       y_root)
 {
-  GdkEvent *event;
-  GdkEventType type;
-  GdkModifierType state = 0;
+  GdkModifierType state;
+
+  state = get_keyboard_modifiers_from_ns_event (nsevent);
 
   switch ([nsevent type])
     {
     case NSLeftMouseDragged:
     case NSRightMouseDragged:
     case NSOtherMouseDragged:
-      state = get_mouse_button_modifiers_from_ns_event (nsevent);
-      /* Fall through */
+      state |= get_mouse_button_modifiers_from_ns_event (nsevent);
+      break;
+
     case NSMouseMoved:
-      type = GDK_MOTION_NOTIFY;
       break;
-    default:
-      g_assert_not_reached ();
     }
 
-  state |= get_keyboard_modifiers_from_ns_event (nsevent);
-
-  event = gdk_event_new (type);
+  event->any.type = GDK_MOTION_NOTIFY;
   event->motion.window = window;
   event->motion.time = get_time_from_ns_event (nsevent);
   event->motion.x = x;
   event->motion.y = y;
+  event->motion.x_root = x_root;
+  event->motion.y_root = y_root;
   /* FIXME event->axes */
   event->motion.state = state;
   event->motion.is_hint = FALSE;
   event->motion.device = _gdk_display->core_pointer;
-  convert_window_coordinates_to_root (window, x, y,
-                                     &event->motion.x_root, &event->motion.y_root);
-  
-  return event;
 }
 
-static GdkEvent *
-create_scroll_event (GdkWindow          *window, 
-                     NSEvent            *nsevent, 
-                     GdkScrollDirection  direction)
+static void
+fill_scroll_event (GdkWindow          *window,
+                   GdkEvent           *event,
+                   NSEvent            *nsevent,
+                   gint                x,
+                   gint                y,
+                   gint                x_root,
+                   gint                y_root,
+                   GdkScrollDirection  direction)
 {
-  GdkEvent *event;
+  GdkWindowObject *private;
   NSPoint point;
-  
-  event = gdk_event_new (GDK_SCROLL);
-  event->scroll.window = window;
-  event->scroll.time = get_time_from_ns_event (nsevent);
+
+  private = GDK_WINDOW_OBJECT (window);
 
   point = [nsevent locationInWindow];
-  event->scroll.x = point.x;
-  event->scroll.y = point.y;
-  event->scroll.state = get_keyboard_modifiers_from_ns_event (nsevent);
-  convert_window_coordinates_to_root (window, event->scroll.x, event->scroll.y, 
-                                     &event->scroll.x_root,
-                                     &event->scroll.y_root);
 
+  event->any.type = GDK_SCROLL;
+  event->scroll.window = window;
+  event->scroll.time = get_time_from_ns_event (nsevent);
+  event->scroll.x = x;
+  event->scroll.y = y;
+  event->scroll.x_root = x_root;
+  event->scroll.y_root = y_root;
+  event->scroll.state = get_keyboard_modifiers_from_ns_event (nsevent);
   event->scroll.direction = direction;
   event->scroll.device = _gdk_display->core_pointer;
-  
-  return event;
 }
 
-static GdkEvent *
-create_key_event (GdkWindow    *window, 
-                  NSEvent      *nsevent, 
-                  GdkEventType  type)
+static void
+fill_key_event (GdkWindow    *window,
+                GdkEvent     *event,
+                NSEvent      *nsevent,
+                GdkEventType  type)
 {
-  GdkEvent *event;
   GdkEventPrivate *priv;
   gchar buf[7];
   gunichar c = 0;
 
-  event = gdk_event_new (type);
-
   priv = (GdkEventPrivate *) event;
   priv->windowing_data = [nsevent retain];
 
+  event->any.type = type;
   event->key.window = window;
   event->key.time = get_time_from_ns_event (nsevent);
   event->key.state = get_keyboard_modifiers_from_ns_event (nsevent);
   event->key.hardware_keycode = [nsevent keyCode];
   event->key.group = ([nsevent modifierFlags] & NSAlternateKeyMask) ? 1 : 0;
-
   event->key.keyval = GDK_VoidSymbol;
   
   gdk_keymap_translate_keyboard_state (NULL,
@@ -1620,7 +835,7 @@ create_key_event (GdkWindow    *window,
   if (event->key.keyval != GDK_VoidSymbol)
     c = gdk_keyval_to_unicode (event->key.keyval);
 
-    if (c)
+  if (c)
     {
       gsize bytes_written;
       gint len;
@@ -1658,7 +873,59 @@ create_key_event (GdkWindow    *window,
          event->key.window,
          event->key.keyval ? gdk_keyval_name (event->key.keyval) : "(none)",
          event->key.keyval));
-  return event;
+}
+
+static gboolean
+synthesize_crossing_event (GdkWindow *window,
+                           GdkEvent  *event,
+                           NSEvent   *nsevent,
+                           gint       x,
+                           gint       y,
+                           gint       x_root,
+                           gint       y_root)
+{
+  GdkWindowObject *private;
+
+  private = GDK_WINDOW_OBJECT (window);
+
+  switch ([nsevent type])
+    {
+    case NSMouseEntered:
+      /* Enter events are considered always to be from the root window as we
+       * can't know for sure from what window we enter.
+       */
+      if (!(private->event_mask & GDK_ENTER_NOTIFY_MASK))
+        return FALSE;
+
+      fill_crossing_event (window, event, nsevent,
+                           x, y,
+                           x_root, y_root,
+                           GDK_ENTER_NOTIFY,
+                           GDK_CROSSING_NORMAL,
+                           GDK_NOTIFY_ANCESTOR);
+      return TRUE;
+
+    case NSMouseExited:
+      /* Exited always is to the root window as far as we are concerned,
+       * since there is no way to reliably get information about what new
+       * window is entered when exiting one.
+       */
+      if (!(private->event_mask & GDK_LEAVE_NOTIFY_MASK))
+        return FALSE;
+
+      fill_crossing_event (window, event, nsevent,
+                           x, y,
+                           x_root, y_root,
+                           GDK_LEAVE_NOTIFY,
+                           GDK_CROSSING_NORMAL,
+                           GDK_NOTIFY_ANCESTOR);
+      return TRUE;
+
+    default:
+      break;
+    }
+
+  return FALSE;
 }
 
 GdkEventMask 
@@ -1668,40 +935,38 @@ _gdk_quartz_events_get_current_event_mask (void)
 }
 
 static gboolean
-gdk_event_translate (NSEvent *nsevent)
+gdk_event_translate (GdkEvent *event,
+                     NSEvent  *nsevent)
 {
+  NSEventType event_type;
   NSWindow *nswindow;
   GdkWindow *window;
-  GdkFilterReturn result;
-  GdkEvent *event;
   int x, y;
+  int x_root, y_root;
+  gboolean return_val;
 
   /* There is no support for real desktop wide grabs, so we break
    * grabs when the application loses focus (gets deactivated).
    */
-  if ([nsevent type] == NSAppKitDefined)
+  event_type = [nsevent type];
+  if (event_type == NSAppKitDefined)
     {
       if ([nsevent subtype] == NSApplicationDeactivatedEventType)
-        break_all_grabs ();
+        break_all_grabs (get_time_from_ns_event (nsevent));
 
       /* This could potentially be used to break grabs when clicking
        * on the title. The subtype 20 is undocumented so it's probably
        * not a good idea: else if (subtype == 20) break_all_grabs ();
        */
-    }
 
-  /* Handle our generated "fake" crossing events. */
-  if ([nsevent type] == NSApplicationDefined && 
-      [nsevent subtype] == GDK_QUARTZ_EVENT_SUBTYPE_FAKE_CROSSING)
-    {
-      _gdk_quartz_events_trigger_crossing_events (FALSE);
-      return TRUE;
+      /* Leave all AppKit events to AppKit. */
+      return FALSE;
     }
 
   /* Keep track of button state, since we don't get that information
    * for key events. 
    */
-  switch ([nsevent type])
+  switch (event_type)
     {
     case NSLeftMouseDown:
     case NSRightMouseDown:
@@ -1717,21 +982,21 @@ gdk_event_translate (NSEvent *nsevent)
       break;
     }
 
-  nswindow = [nsevent window];
-
-  /* Apply any global filters. */
   if (_gdk_default_filters)
     {
-      result = apply_filters (NULL, nsevent, _gdk_default_filters);
+      /* Apply global filters */
+      GdkFilterReturn result;
 
-      /* If result is GDK_FILTER_CONTINUE, we continue as if nothing
-       * happened. If it is GDK_FILTER_REMOVE,
-       * we return TRUE and won't send the message to Quartz.
-       */
-      if (result == GDK_FILTER_REMOVE)
-       return TRUE;
+      result = gdk_event_apply_filters (nsevent, event, _gdk_default_filters);
+      if (result != GDK_FILTER_CONTINUE)
+        {
+          return_val = (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
+          goto done;
+        }
     }
 
+  nswindow = [nsevent window];
+
   /* Ignore events for no window or ones not created by GDK. */
   if (!nswindow || ![[nswindow contentView] isKindOfClass:[GdkQuartzView class]])
     return FALSE;
@@ -1742,84 +1007,86 @@ gdk_event_translate (NSEvent *nsevent)
    */
   if ([(GdkQuartzWindow *)nswindow isInMove])
     {
-      break_all_grabs ();
+      break_all_grabs (get_time_from_ns_event (nsevent));
       return FALSE;
     }
 
-  /* Take care of NSMouseEntered/Exited events and mouse movements
-   * events and emit the right GDK crossing events.
-   */
-  synthesize_crossing_events_for_ns_event (nsevent);
-
   /* Find the right GDK window to send the event to, taking grabs and
    * event masks into consideration.
    */
-  window = find_window_for_ns_event (nsevent, &x, &y);
+  window = find_window_for_ns_event (nsevent, &x, &y, &x_root, &y_root);
   if (!window)
     return FALSE;
 
   /* Apply any window filters. */
-  result = apply_filters (window, nsevent, ((GdkWindowObject *) window)->filters);
-  if (result == GDK_FILTER_REMOVE)
-    return TRUE;
-
-  /* We need the appliction to be activated on clicks so that popups
-   * like context menus get events routed properly. This is handled
-   * automatically for left mouse button presses but not other
-   * buttons, so we do it here.
+  if (GDK_IS_WINDOW (window))
+    {
+      GdkWindowObject *filter_private = (GdkWindowObject *) window;
+      GdkFilterReturn result;
+
+      if (filter_private->filters)
+       {
+         g_object_ref (window);
+
+         result = gdk_event_apply_filters (nsevent, event, filter_private->filters);
+
+         g_object_unref (window);
+
+         if (result != GDK_FILTER_CONTINUE)
+           {
+             return_val = (result == GDK_FILTER_TRANSLATE) ? TRUE : FALSE;
+             goto done;
+           }
+       }
+    }
+
+  /* If the app is not active leave the event to AppKit so the window gets
+   * focused correctly and don't do click-through (so we behave like most
+   * native apps). If the app is active, we focus the window and then handle
+   * the event, also to match native apps.
    */
-  if ([nsevent type] == NSRightMouseDown || [nsevent type] == NSOtherMouseDown)
+  if ((event_type == NSRightMouseDown ||
+       event_type == NSOtherMouseDown ||
+       event_type == NSLeftMouseDown))
     {
+      GdkWindowObject *private = (GdkWindowObject *)window;
+      GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
+
       if (![NSApp isActive])
-        [NSApp activateIgnoringOtherApps:YES];
+        {
+          [NSApp activateIgnoringOtherApps:YES];
+          return FALSE;
+        }
+      else if (![impl->toplevel isKeyWindow])
+        {
+          GdkPointerGrabInfo *grab;
+
+          grab = _gdk_display_get_last_pointer_grab (_gdk_display);
+          if (!grab)
+            [impl->toplevel makeKeyWindow];
+        }
     }
 
   current_event_mask = get_event_mask_from_ns_event (nsevent);
 
-  switch ([nsevent type])
+  return_val = TRUE;
+
+  switch (event_type)
     {
     case NSLeftMouseDown:
     case NSRightMouseDown:
     case NSOtherMouseDown:
-      {
-       GdkEventMask event_mask;
-
-       /* Emulate implicit grab, when the window has both PRESS and RELEASE
-        * in its mask, like X.
-        */
-       event_mask = (GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
-       if (!_gdk_quartz_pointer_grab_window &&
-           (GDK_WINDOW_OBJECT (window)->event_mask & event_mask) == event_mask)
-         {
-           pointer_grab_internal (window, FALSE,
-                                  GDK_WINDOW_OBJECT (window)->event_mask,
-                                  NULL, NULL, TRUE);
-         }
-      }
-      
-      event = create_button_event (window, nsevent, x, y);
-      append_event (event);
-      
-      _gdk_event_button_generate (_gdk_display, event);
-      break;
-
     case NSLeftMouseUp:
     case NSRightMouseUp:
     case NSOtherMouseUp:
-      event = create_button_event (window, nsevent, x, y);
-      append_event (event);
-      
-      /* Ungrab implicit grab */
-      if (_gdk_quartz_pointer_grab_window && pointer_grab_implicit)
-       pointer_ungrab_internal (TRUE);
+      fill_button_event (window, event, nsevent, x, y, x_root, y_root);
       break;
 
     case NSLeftMouseDragged:
     case NSRightMouseDragged:
     case NSOtherMouseDragged:
     case NSMouseMoved:
-      event = create_motion_event (window, nsevent, x, y);
-      append_event (event);
+      fill_motion_event (window, event, nsevent, x, y, x_root, y_root);
       break;
 
     case NSScrollWheel:
@@ -1828,51 +1095,33 @@ gdk_event_translate (NSEvent *nsevent)
        float dy = [nsevent deltaY];
        GdkScrollDirection direction;
 
-       /* The delta is how much the mouse wheel has moved. Since there's no such thing in GTK+
-        * we accomodate by sending a different number of scroll wheel events.
-        */
-
-       /* First do y events */
-       if (dy < 0.0)
-         {
-           dy = -dy;
-           direction = GDK_SCROLL_DOWN;
-         }
-       else
-         direction = GDK_SCROLL_UP;
-
-       while (dy > 0.0)
-         {
-           event = create_scroll_event (window, nsevent, direction);
-           append_event (event);
-           dy--;
-
-            /* Ignore the delta for now, things get too slow when the events queue up. */
-            break;
-         }
+        if (dy != 0)
+          {
+            if (dy < 0.0)
+              direction = GDK_SCROLL_DOWN;
+            else
+              direction = GDK_SCROLL_UP;
 
-       /* Now do x events */
-       if (dx < 0.0)
-         {
-           dx = -dx;
-           direction = GDK_SCROLL_RIGHT;
-         }
-       else
-         direction = GDK_SCROLL_LEFT;
+            fill_scroll_event (window, event, nsevent, x, y, x_root, y_root, direction);
+          }
 
-       while (dx > 0.0)
-         {
-           event = create_scroll_event (window, nsevent, direction);
-           append_event (event);
-           dx--;
-            
-            /* Ignore the delta for now, things get too slow when the events queue up. */
-            break;
-         }
+        if (dx != 0)
+          {
+            if (dx < 0.0)
+              direction = GDK_SCROLL_RIGHT;
+            else
+              direction = GDK_SCROLL_LEFT;
 
+            fill_scroll_event (window, event, nsevent, x, y, x_root, y_root, direction);
+          }
       }
       break;
 
+    case NSMouseEntered:
+    case NSMouseExited:
+      return_val = synthesize_crossing_event (window, event, nsevent, x, y, x_root, y_root);
+      break;
+
     case NSKeyDown:
     case NSKeyUp:
     case NSFlagsChanged:
@@ -1881,38 +1130,75 @@ gdk_event_translate (NSEvent *nsevent)
 
         type = _gdk_quartz_keys_event_type (nsevent);
         if (type == GDK_NOTHING)
-          return FALSE;
-        
-        event = create_key_event (window, nsevent, type);
-        append_event (event);
-        return TRUE;
+          return_val = FALSE;
+        else
+          fill_key_event (window, event, nsevent, type);
       }
       break;
 
     default:
       /* Ignore everything elsee. */
+      return_val = FALSE;
       break;
     }
 
-  return FALSE;
+ done:
+  if (return_val)
+    {
+      if (event->any.window)
+       g_object_ref (event->any.window);
+      if (((event->any.type == GDK_ENTER_NOTIFY) ||
+          (event->any.type == GDK_LEAVE_NOTIFY)) &&
+         (event->crossing.subwindow != NULL))
+       g_object_ref (event->crossing.subwindow);
+    }
+  else
+    {
+      /* Mark this event as having no resources to be freed */
+      event->any.window = NULL;
+      event->any.type = GDK_NOTHING;
+    }
+
+  return return_val;
 }
 
 void
 _gdk_events_queue (GdkDisplay *display)
 {  
-  NSEvent *event;
+  NSEvent *nsevent;
 
-  event = _gdk_quartz_event_loop_get_pending ();
-  if (event)
+  nsevent = _gdk_quartz_event_loop_get_pending ();
+  if (nsevent)
     {
-      if (!gdk_event_translate (event))
+      GdkEvent *event;
+      GList *node;
+
+      event = gdk_event_new (GDK_NOTHING);
+
+      event->any.window = NULL;
+      event->any.send_event = FALSE;
+
+      ((GdkEventPrivate *)event)->flags |= GDK_EVENT_PENDING;
+
+      node = _gdk_event_queue_append (display, event);
+
+      if (gdk_event_translate (event, nsevent))
+        {
+         ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
+          _gdk_windowing_got_event (display, node, event, 0);
+        }
+      else
         {
+         _gdk_event_queue_remove_link (display, node);
+         g_list_free_1 (node);
+         gdk_event_free (event);
+
           GDK_THREADS_LEAVE ();
-          [NSApp sendEvent:event];
+          [NSApp sendEvent:nsevent];
           GDK_THREADS_ENTER ();
         }
 
-      _gdk_quartz_event_loop_release_event (event);
+      _gdk_quartz_event_loop_release_event (nsevent);
     }
 }
 
@@ -1922,7 +1208,7 @@ gdk_flush (void)
   /* Not supported. */
 }
 
-void 
+void
 gdk_display_add_client_message_filter (GdkDisplay   *display,
                                       GdkAtom       message_type,
                                       GdkFilterFunc func,
@@ -1931,7 +1217,7 @@ gdk_display_add_client_message_filter (GdkDisplay   *display,
   /* Not supported. */
 }
 
-void 
+void
 gdk_add_client_message_filter (GdkAtom       message_type,
                               GdkFilterFunc func,
                               gpointer      data)
index ea773791012472ee2cd4bbac6751526b1cd744b9..c4da89328cdf7be4b2fb76346cc5658f3d89b23c 100644 (file)
@@ -208,7 +208,8 @@ _gdk_quartz_gc_new (GdkDrawable      *drawable,
 
 void
 _gdk_windowing_gc_set_clip_region (GdkGC           *gc,
-                                  const GdkRegion *region)
+                                  const GdkRegion *region,
+                                  gboolean         reset_origin)
 {
   GdkGCQuartz *private = GDK_GC_QUARTZ (gc);
 
@@ -224,8 +225,11 @@ _gdk_windowing_gc_set_clip_region (GdkGC           *gc,
 
   private->have_clip_region = region != NULL;
 
-  gc->clip_x_origin = 0;
-  gc->clip_y_origin = 0;
+  if (reset_origin)
+    {
+      gc->clip_x_origin = 0;
+      gc->clip_y_origin = 0;
+    }
 }
 
 void
@@ -281,7 +285,6 @@ gdk_quartz_draw_tiled_pattern (void         *info,
                               CGContextRef  context)
 {
   GdkGC       *gc = GDK_GC (info);
-  GdkGCQuartz *private = GDK_GC_QUARTZ (gc);
   CGImageRef   pattern_image;
   size_t       width, height;
 
index 921128aec56c129619e7816046a223089220547d..eceb0717f068244fe55cf73083c963f823934ba1 100644 (file)
 #include "gdkprivate-quartz.h"
 
 void
-_gdk_quartz_window_scroll (GdkWindow *window,
-                           gint       dx,
-                           gint       dy)
+_gdk_quartz_window_queue_translation (GdkWindow *window,
+                                      GdkRegion *area,
+                                      gint       dx,
+                                      gint       dy)
 {
-  NSRect visible_nsrect;
-  GdkRectangle visible_rect, scrolled_rect;
-  GdkRegion *visible_region, *scrolled_region;
-  GdkRectangle *rects;
-  gint n_rects, i;
-  GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
-  GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
-  GList *list;
-
-  /* Move the current invalid region */
-  if (private->update_area)
-    gdk_region_offset (private->update_area, dx, dy);
-
-  visible_nsrect = [impl->view visibleRect];
-
-  visible_rect.x = visible_nsrect.origin.x;
-  visible_rect.y = visible_nsrect.origin.y;
-  visible_rect.width = visible_nsrect.size.width;
-  visible_rect.height = visible_nsrect.size.height;
-  
-  scrolled_rect = visible_rect;
-  scrolled_rect.x += dx;
-  scrolled_rect.y += dy;
-  
-  gdk_rectangle_intersect (&visible_rect, &scrolled_rect, &scrolled_rect);
-  
-  visible_region = gdk_region_rectangle (&visible_rect);
-  scrolled_region = gdk_region_rectangle (&scrolled_rect);
-
-  gdk_region_subtract (visible_region, scrolled_region);
-
-  [impl->view scrollRect:[impl->view bounds] by:NSMakeSize(dx, dy)];
-
-  gdk_region_get_rectangles (visible_region, &rects, &n_rects);
-  for (i = 0; i < n_rects; i++)
-    [impl->view setNeedsDisplayInRect:NSMakeRect (rects[i].x, rects[i].y, rects[i].width, rects[i].height)];
-  
-  g_free (rects);
-
-  gdk_region_destroy (visible_region);
-  gdk_region_destroy (scrolled_region);
-
-  /* Move child windows */
-  for (list = private->children; list; list = list->next)
-    {
-      GdkWindowObject *child = GDK_WINDOW_OBJECT (list->data);
-
-      gdk_window_move (list->data,
-                      child->x + dx,
-                      child->y + dy);
-    }
 }
 
-void
-_gdk_quartz_window_move_region (GdkWindow       *window,
-                                const GdkRegion *region,
-                                gint             dx,
-                                gint             dy)
+gboolean
+_gdk_quartz_window_queue_antiexpose (GdkWindow *window,
+                                     GdkRegion *area)
 {
-  /* FIXME: Implement */
+  return FALSE;
 }
index 280af5e3039756537147b1cb71fa728352991157..657d43590b27f8ec8ab0a393f7a642fe56a7bd7c 100644 (file)
@@ -206,7 +206,7 @@ gdk_device_get_history  (GdkDevice         *device,
                         gint              *n_events)
 {
   g_return_val_if_fail (window != NULL, FALSE);
-  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+  g_return_val_if_fail (GDK_WINDOW_IS_QUARTZ (window), FALSE);
   g_return_val_if_fail (events != NULL, FALSE);
   g_return_val_if_fail (n_events != NULL, FALSE);
 
@@ -262,7 +262,7 @@ gdk_input_set_extension_events (GdkWindow *window, gint mask,
   GdkInputWindow *iw;
 
   g_return_if_fail (window != NULL);
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_WINDOW_IS_QUARTZ (window));
 
   window_private = (GdkWindowObject*) window;
 
index e55ff9d1aa5226a00f77b1df3d5884c3c9db9deb..a74348089da72680af9c9ad05a6efac05c5bd810 100644 (file)
@@ -137,10 +137,10 @@ data_provider_release (void *info, const void *data, size_t size)
 }
 
 GdkPixmap*
-gdk_pixmap_new (GdkDrawable *drawable,
-               gint         width,
-               gint         height,
-               gint         depth)
+_gdk_pixmap_new (GdkDrawable *drawable,
+                 gint         width,
+                 gint         height,
+                 gint         depth)
 {
   GdkPixmap *pixmap;
   GdkDrawableImplQuartz *draw_impl;
@@ -224,10 +224,10 @@ gdk_pixmap_new (GdkDrawable *drawable,
 }
 
 GdkPixmap *
-gdk_bitmap_create_from_data (GdkDrawable *window,
-                            const gchar *data,
-                            gint         width,
-                            gint         height)
+_gdk_bitmap_create_from_data (GdkDrawable *window,
+                              const gchar *data,
+                              gint         width,
+                              gint         height)
 {
   GdkPixmap *pixmap;
   GdkPixmapImplQuartz *impl;
@@ -264,13 +264,13 @@ gdk_bitmap_create_from_data (GdkDrawable *window,
 }
 
 GdkPixmap*
-gdk_pixmap_create_from_data (GdkDrawable    *drawable,
-                            const gchar    *data,
-                            gint            width,
-                            gint            height,
-                            gint            depth,
-                            const GdkColor *fg,
-                            const GdkColor *bg)
+_gdk_pixmap_create_from_data (GdkDrawable    *drawable,
+                              const gchar    *data,
+                              gint            width,
+                              gint            height,
+                              gint            depth,
+                              const GdkColor *fg,
+                              const GdkColor *bg)
 {      
   /* FIXME: Implement */
   return NULL;
index efffe6b62b33d274c9a9c8045772cff0be95c553..9590d9b561d115e50692ec6a19bfaa7a5abe28fe 100644 (file)
@@ -102,6 +102,8 @@ extern GdkWindow *_gdk_root;
 
 extern GdkDragContext *_gdk_quartz_drag_source_context;
 
+#define GDK_WINDOW_IS_QUARTZ(win)        (GDK_IS_WINDOW_IMPL_QUARTZ (((GdkWindowObject *)win)->impl))
+
 /* Initialization */
 void _gdk_windowing_window_init  (void);
 void _gdk_events_init            (void);
@@ -149,21 +151,13 @@ void       _gdk_quartz_window_debug_highlight       (GdkWindow *window,
 
 /* Events */
 typedef enum {
-  GDK_QUARTZ_EVENT_SUBTYPE_EVENTLOOP,
-  GDK_QUARTZ_EVENT_SUBTYPE_FAKE_CROSSING
+  GDK_QUARTZ_EVENT_SUBTYPE_EVENTLOOP
 } GdkQuartzEventSubType;
 
 void         _gdk_quartz_events_update_focus_window    (GdkWindow *new_window,
                                                         gboolean   got_focus);
-GdkWindow *  _gdk_quartz_events_get_mouse_window       (gboolean   consider_grabs);
-void         _gdk_quartz_events_update_mouse_window    (GdkWindow *window);
-void         _gdk_quartz_events_update_cursor          (GdkWindow *window);
-void         _gdk_quartz_events_send_map_events        (GdkWindow *window);
+void         _gdk_quartz_events_send_map_event         (GdkWindow *window);
 GdkEventMask _gdk_quartz_events_get_current_event_mask (void);
-void         _gdk_quartz_events_trigger_crossing_events(gboolean   defer_to_mainloop);
-
-extern GdkWindow *_gdk_quartz_keyboard_grab_window;
-extern GdkWindow *_gdk_quartz_pointer_grab_window;
 
 /* Event loop */
 gboolean   _gdk_quartz_event_loop_check_pending (void);
@@ -186,14 +180,17 @@ gboolean     _gdk_quartz_keys_is_modifier (guint      keycode);
 
 /* Drawable */
 void        _gdk_quartz_drawable_finish (GdkDrawable *drawable);
+void        _gdk_quartz_drawable_flush  (GdkDrawable *drawable);
 
 /* Geometry */
 void        _gdk_quartz_window_scroll      (GdkWindow       *window,
                                             gint             dx,
                                             gint             dy);
-void        _gdk_quartz_window_move_region (GdkWindow       *window,
-                                            const GdkRegion *region,
-                                            gint             dx,
-                                            gint             dy);
+void        _gdk_quartz_window_queue_translation (GdkWindow *window,
+                                                  GdkRegion *area,
+                                                  gint       dx,
+                                                  gint       dy);
+gboolean    _gdk_quartz_window_queue_antiexpose  (GdkWindow *window,
+                                                  GdkRegion *area);
 
 #endif /* __GDK_PRIVATE_QUARTZ_H__ */
index c6ed9cb9e62a7ee72c3815bbd599402f9e43ddc2..aa8d437a4684d0d055fbf0033e164a8ab71fcd35 100644 (file)
@@ -28,8 +28,8 @@
 
 static gpointer parent_class;
 
-static GSList *update_windows;
-static guint   update_idle;
+static GSList   *update_nswindows;
+static gboolean  in_process_all_updates = FALSE;
 
 static GSList *main_window_stack;
 
@@ -48,9 +48,10 @@ static void clear_toplevel_order  (void);
 
 static FullscreenSavedGeometry *get_fullscreen_geometry (GdkWindow *window);
 
-#define WINDOW_IS_TOPLEVEL(window)                \
-  (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
-   GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
+#define WINDOW_IS_TOPLEVEL(window)                  \
+  (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&   \
+   GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN && \
+   GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
 
 static void gdk_window_impl_iface_init (GdkWindowImplIface *iface);
 
@@ -76,19 +77,6 @@ gdk_quartz_window_get_nswindow (GdkWindow *window)
   return ((GdkWindowImplQuartz *)private->impl)->toplevel;
 }
 
-static void
-gdk_window_impl_quartz_get_size (GdkDrawable *drawable,
-                                gint        *width,
-                                gint        *height)
-{
-  g_return_if_fail (GDK_IS_WINDOW_IMPL_QUARTZ (drawable));
-
-  if (width)
-    *width = GDK_WINDOW_IMPL_QUARTZ (drawable)->width;
-  if (height)
-    *height = GDK_WINDOW_IMPL_QUARTZ (drawable)->height;
-}
-
 static CGContextRef
 gdk_window_impl_quartz_get_context (GdkDrawable *drawable,
                                    gboolean     antialias)
@@ -104,7 +92,7 @@ gdk_window_impl_quartz_get_context (GdkDrawable *drawable,
    * is needed when called from outside "real" expose events, for
    * example for synthesized expose events when realizing windows
    * and for widgets that send fake expose events like the arrow
-   * buttons in spinbuttons.
+   * buttons in spinbuttons or the position marker in rulers.
    */
   if (window_impl->in_paint_rect_count == 0)
     {
@@ -150,54 +138,44 @@ gdk_window_impl_quartz_get_context (GdkDrawable *drawable,
   return cg_context;
 }
 
-static GdkRegion*
-gdk_window_impl_quartz_get_visible_region (GdkDrawable *drawable)
+static void
+check_grab_unmap (GdkWindow *window)
 {
-  GdkWindowObject *private = GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_QUARTZ (drawable)->wrapper);
-  GdkRectangle rect;
-  GdkWindowImplQuartz *impl;
-  GList *windows = NULL, *l;
+  GdkDisplay *display = gdk_drawable_get_display (window);
 
-  /* FIXME: The clip rectangle should really be cached
-   * and recalculated when the window rectangle changes.
-   */
-  while (private)
+  _gdk_display_end_pointer_grab (display, 0, window, TRUE);
+
+  if (display->keyboard_grab.window)
     {
-      windows = g_list_prepend (windows, private);
+      GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
+      GdkWindowObject *tmp = GDK_WINDOW_OBJECT (display->keyboard_grab.window);
 
-      if (private->parent == GDK_WINDOW_OBJECT (_gdk_root))
-       break;
+      while (tmp && tmp != private)
+       tmp = tmp->parent;
 
-      private = private->parent;
+      if (tmp)
+       _gdk_display_unset_has_keyboard_grab (display, TRUE);
     }
+}
 
-  /* Get rectangle for toplevel window */
-  private = GDK_WINDOW_OBJECT (windows->data);
-  impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
-  
-  rect.x = 0;
-  rect.y = 0;
-  rect.width = impl->width;
-  rect.height = impl->height;
+static void
+check_grab_destroy (GdkWindow *window)
+{
+  GdkDisplay *display = gdk_drawable_get_display (window);
+  GdkPointerGrabInfo *grab;
 
-  /* Skip toplevel window since we have its rect */
-  for (l = windows->next; l; l = l->next)
+  /* Make sure there is no lasting grab in this native window */
+  grab = _gdk_display_get_last_pointer_grab (display);
+  if (grab && grab->native_window == window)
     {
-      private = GDK_WINDOW_OBJECT (l->data);
-      impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
-      GdkRectangle tmp_rect;
-
-      tmp_rect.x = -MIN (0, private->x - rect.x);
-      tmp_rect.y = -MIN (0, private->y - rect.y);
-      tmp_rect.width = MIN (rect.width, impl->width + private->x - rect.x) - MAX (0, private->x - rect.x);
-      tmp_rect.height = MIN (rect.height, impl->height + private->y - rect.y) - MAX (0, private->y - rect.y);
-
-      rect = tmp_rect;
+      /* Serials are always 0 in quartz, but for clarity: */
+      grab->serial_end = grab->serial_start;
+      grab->implicit_ungrab = TRUE;
     }
-  
-  g_list_free (windows);
-  
-  return gdk_region_rectangle (&rect);
+
+  if (window == display->keyboard_grab.native_window &&
+      display->keyboard_grab.window != NULL)
+    _gdk_display_unset_has_keyboard_grab (display, TRUE);
 }
 
 static void
@@ -205,8 +183,7 @@ gdk_window_impl_quartz_finalize (GObject *object)
 {
   GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (object);
 
-  if (impl->nscursor)
-    [impl->nscursor release];
+  check_grab_destroy (GDK_DRAWABLE_IMPL_QUARTZ (object)->wrapper);
 
   if (impl->paint_clip_region)
     gdk_region_destroy (impl->paint_clip_region);
@@ -220,56 +197,58 @@ gdk_window_impl_quartz_finalize (GObject *object)
 static void
 gdk_window_impl_quartz_class_init (GdkWindowImplQuartzClass *klass)
 {
-  GdkDrawableImplQuartzClass *drawable_quartz_class = GDK_DRAWABLE_IMPL_QUARTZ_CLASS (klass);
-  GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GdkDrawableImplQuartzClass *drawable_quartz_class = GDK_DRAWABLE_IMPL_QUARTZ_CLASS (klass);
 
   parent_class = g_type_class_peek_parent (klass);
 
   object_class->finalize = gdk_window_impl_quartz_finalize;
 
-  drawable_class->get_size = gdk_window_impl_quartz_get_size;
-
   drawable_quartz_class->get_context = gdk_window_impl_quartz_get_context;
-
-  /* Visible and clip regions are the same */
-  drawable_class->get_clip_region = gdk_window_impl_quartz_get_visible_region;
-  drawable_class->get_visible_region = gdk_window_impl_quartz_get_visible_region;
 }
 
 static void
 gdk_window_impl_quartz_init (GdkWindowImplQuartz *impl)
 {
-  impl->width = 1;
-  impl->height = 1;
   impl->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL;
 }
 
 static void
 gdk_window_impl_quartz_begin_paint_region (GdkPaintable    *paintable,
+                                           GdkWindow       *window,
                                           const GdkRegion *region)
 {
   GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (paintable);
-  GdkDrawableImplQuartz *drawable_impl;
+  GdkWindowObject *private = (GdkWindowObject*)window;
   int n_rects;
-  GdkRectangle *rects;
+  GdkRectangle *rects = NULL;
   GdkPixmap *bg_pixmap;
-  GdkWindow *window;
+  GdkRegion *clipped_and_offset_region;
+  gboolean free_clipped_and_offset_region = TRUE;
+
+  bg_pixmap = private->bg_pixmap;
 
-  drawable_impl = GDK_DRAWABLE_IMPL_QUARTZ (impl);
-  bg_pixmap = GDK_WINDOW_OBJECT (drawable_impl->wrapper)->bg_pixmap;
+  clipped_and_offset_region = gdk_region_copy (region);
+
+  gdk_region_intersect (clipped_and_offset_region,
+                        private->clip_region_with_children);
+  gdk_region_offset (clipped_and_offset_region,
+                     private->abs_x, private->abs_y);
 
   if (impl->begin_paint_count == 0)
-    impl->paint_clip_region = gdk_region_copy (region);
+    {
+      impl->paint_clip_region = clipped_and_offset_region;
+      free_clipped_and_offset_region = FALSE;
+    }
   else
-    gdk_region_union (impl->paint_clip_region, region);
+    gdk_region_union (impl->paint_clip_region, clipped_and_offset_region);
 
   impl->begin_paint_count++;
 
   if (bg_pixmap == GDK_NO_BG)
-    return;
+    goto done;
 
-  gdk_region_get_rectangles (region, &rects, &n_rects);
+  gdk_region_get_rectangles (clipped_and_offset_region, &rects, &n_rects);
 
   if (bg_pixmap == NULL)
     {
@@ -278,9 +257,9 @@ gdk_window_impl_quartz_begin_paint_region (GdkPaintable    *paintable,
       gint i;
 
       cg_context = gdk_quartz_drawable_get_context (GDK_DRAWABLE (impl), FALSE);
-      _gdk_quartz_colormap_get_rgba_from_pixel (gdk_drawable_get_colormap (drawable_impl->wrapper),
-                                     GDK_WINDOW_OBJECT (drawable_impl->wrapper)->bg_color.pixel,
-                                     &r, &g, &b, &a);
+      _gdk_quartz_colormap_get_rgba_from_pixel (gdk_drawable_get_colormap (window),
+                                                private->bg_color.pixel,
+                                                &r, &g, &b, &a);
       CGContextSetRGBFillColor (cg_context, r, g, b, a);
  
       for (i = 0; i < n_rects; i++)
@@ -301,7 +280,6 @@ gdk_window_impl_quartz_begin_paint_region (GdkPaintable    *paintable,
 
       x_offset = y_offset = 0;
 
-      window = GDK_WINDOW (drawable_impl->wrapper);
       while (window && bg_pixmap == GDK_PARENT_RELATIVE_BG)
         {
           /* If this window should have the same background as the parent,
@@ -319,8 +297,7 @@ gdk_window_impl_quartz_begin_paint_region (GdkPaintable    *paintable,
           /* Parent relative background but the parent doesn't have a
            * pixmap.
            */ 
-          g_free (rects);
-          return;
+          goto done;
         }
 
       /* Note: There should be a CG API to draw tiled images, we might
@@ -350,6 +327,9 @@ gdk_window_impl_quartz_begin_paint_region (GdkPaintable    *paintable,
       g_object_unref (gc);
     }
 
+ done:
+  if (free_clipped_and_offset_region)
+    gdk_region_destroy (clipped_and_offset_region);
   g_free (rects);
 }
 
@@ -367,155 +347,97 @@ gdk_window_impl_quartz_end_paint (GdkPaintable *paintable)
     }
 }
 
-static void
-gdk_window_quartz_process_updates_internal (GdkWindow *window)
-{
-  GdkWindowObject *private = (GdkWindowObject *) window;
-  GdkWindowImplQuartz *impl = (GdkWindowImplQuartz *) private->impl;
-      
-  if (private->update_area)
-    {
-      int i, n_rects;
-      GdkRectangle *rects;
-
-      gdk_region_get_rectangles (private->update_area, &rects, &n_rects);
-
-      gdk_region_destroy (private->update_area);
-      private->update_area = NULL;
-
-      for (i = 0; i < n_rects; i++) 
-       {
-         [impl->view setNeedsDisplayInRect:NSMakeRect (rects[i].x, rects[i].y,
-                                                       rects[i].width, rects[i].height)];
-       }
-
-      [impl->view displayIfNeeded];
-
-      g_free (rects);
-    }
-}
-
-static void
-gdk_window_quartz_process_all_updates (void)
+void
+_gdk_windowing_window_process_updates_recurse (GdkWindow *window,
+                                               GdkRegion *region)
 {
-  GSList *old_update_windows = update_windows;
-  GSList *tmp_list = update_windows;
-  GSList *nswindows;
-
-  update_idle = 0;
-  update_windows = NULL;
-  nswindows = NULL;
-
-  g_slist_foreach (old_update_windows, (GFunc) g_object_ref, NULL);
-  
-  GDK_QUARTZ_ALLOC_POOL;
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowImplQuartz *impl = (GdkWindowImplQuartz *)private->impl;
+  int i, n_rects;
+  GdkRectangle *rects;
 
-  while (tmp_list)
+  /* Make sure to only flush each toplevel at most once if we're called
+   * from process_all_updates.
+   */
+  if (in_process_all_updates)
     {
-      GdkWindow *window = tmp_list->data;
       GdkWindow *toplevel;
 
-      /* Only flush each toplevel at most once. */
       toplevel = gdk_window_get_toplevel (window);
       if (toplevel)
         {
-          GdkWindowObject *private;
-          GdkWindowImplQuartz *impl;
+          GdkWindowObject *toplevel_private;
+          GdkWindowImplQuartz *toplevel_impl;
           NSWindow *nswindow;
 
-          private = (GdkWindowObject *) toplevel;
-          impl = (GdkWindowImplQuartz *) private->impl;
-          nswindow = impl->toplevel;
+          toplevel_private = (GdkWindowObject *)toplevel;
+          toplevel_impl = (GdkWindowImplQuartz *)toplevel_private->impl;
+          nswindow = toplevel_impl->toplevel;
 
+          /* In theory, we could skip the flush disabling, since we only
+           * have one NSView.
+           */
           if (nswindow && ![nswindow isFlushWindowDisabled]) 
             {
+              [nswindow retain];
               [nswindow disableFlushWindow];
-              nswindows = g_slist_prepend (nswindows, nswindow);
+              update_nswindows = g_slist_prepend (update_nswindows, nswindow);
             }
         }
-
-      gdk_window_quartz_process_updates_internal (tmp_list->data);
-
-      g_object_unref (tmp_list->data);
-      tmp_list = tmp_list->next;
     }
 
-  tmp_list = nswindows;
-  while (tmp_list) 
-    {
-      NSWindow *nswindow = tmp_list->data;
-
-      [nswindow enableFlushWindow];
-      [nswindow flushWindow];
+  gdk_region_get_rectangles (region, &rects, &n_rects);
 
-      tmp_list = tmp_list->next;
+  for (i = 0; i < n_rects; i++)
+    {
+      [impl->view setNeedsDisplayInRect:NSMakeRect (rects[i].x, rects[i].y,
+                                                    rects[i].width, rects[i].height)];
     }
-                   
-  GDK_QUARTZ_RELEASE_POOL;
 
-  g_slist_free (old_update_windows);
-  g_slist_free (nswindows);
+  g_free (rects);
+
+  /* NOTE: I'm not sure if we should displayIfNeeded here. It slows down a
+   * lot (since it triggers the beam syncing) and things seem to work
+   * without it.
+   */
 }
 
-static gboolean
-gdk_window_quartz_update_idle (gpointer data)
+void
+_gdk_windowing_before_process_all_updates (void)
 {
-  gdk_window_quartz_process_all_updates ();
+  in_process_all_updates = TRUE;
 
-  return FALSE;
+  NSDisableScreenUpdates ();
 }
 
-static void
-gdk_window_impl_quartz_invalidate_maybe_recurse (GdkPaintable    *paintable,
-                                                const GdkRegion *region,
-                                                gboolean        (*child_func) (GdkWindow *, gpointer),
-                                                gpointer         user_data)
-{
-  GdkWindowImplQuartz *window_impl = GDK_WINDOW_IMPL_QUARTZ (paintable);
-  GdkDrawableImplQuartz *drawable_impl = (GdkDrawableImplQuartz *) window_impl;
-  GdkWindow *window = (GdkWindow *) drawable_impl->wrapper;
-  GdkWindowObject *private = (GdkWindowObject *) window;
-  GdkRegion *visible_region;
+void
+_gdk_windowing_after_process_all_updates (void)
+{
+  GSList *old_update_nswindows = update_nswindows;
+  GSList *tmp_list = update_nswindows;
 
-  visible_region = gdk_drawable_get_visible_region (window);
-  gdk_region_intersect (visible_region, region);
+  update_nswindows = NULL;
 
-  if (private->update_area)
-    {
-      gdk_region_union (private->update_area, visible_region);
-      gdk_region_destroy (visible_region);
-    }
-  else
+  while (tmp_list)
     {
-      /* FIXME: When the update_window/update_area handling is abstracted in
-       * some way, we can remove this check. Currently it might be cleared
-       * in the generic code without us knowing, see bug #530801.
-       */
-      if (!g_slist_find (update_windows, window))
-        update_windows = g_slist_prepend (update_windows, window);
-      private->update_area = visible_region;
+      NSWindow *nswindow = tmp_list->data;
 
-      if (update_idle == 0)
-        update_idle = gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
-                                                 gdk_window_quartz_update_idle, NULL, NULL);
-    }
-}
+      [[nswindow contentView] displayIfNeeded];
 
-static void
-gdk_window_impl_quartz_process_updates (GdkPaintable *paintable,
-                                       gboolean      update_children)
-{
-  GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (paintable);
-  GdkDrawableImplQuartz *drawable_impl = (GdkDrawableImplQuartz *) impl;
-  GdkWindowObject *private = (GdkWindowObject *) drawable_impl->wrapper;
+      _gdk_quartz_drawable_flush (NULL);
 
-  if (private->update_area)
-    {
-      GDK_QUARTZ_ALLOC_POOL;
-      gdk_window_quartz_process_updates_internal ((GdkWindow *) private);
-      update_windows = g_slist_remove (update_windows, private);
-      GDK_QUARTZ_RELEASE_POOL;
+      [nswindow enableFlushWindow];
+      [nswindow flushWindow];
+      [nswindow release];
+
+      tmp_list = tmp_list->next;
     }
+
+  g_slist_free (old_update_nswindows);
+
+  in_process_all_updates = FALSE;
+
+  NSEnableScreenUpdates ();
 }
 
 static void
@@ -523,9 +445,6 @@ gdk_window_impl_quartz_paintable_init (GdkPaintableIface *iface)
 {
   iface->begin_paint_region = gdk_window_impl_quartz_begin_paint_region;
   iface->end_paint = gdk_window_impl_quartz_end_paint;
-
-  iface->invalidate_maybe_recurse = gdk_window_impl_quartz_invalidate_maybe_recurse;
-  iface->process_updates = gdk_window_impl_quartz_process_updates;
 }
 
 GType
@@ -621,7 +540,6 @@ void
 _gdk_quartz_window_debug_highlight (GdkWindow *window, gint number)
 {
   GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
-  GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
   gint x, y;
   GdkWindow *toplevel;
   gint tx, ty;
@@ -652,8 +570,8 @@ _gdk_quartz_window_debug_highlight (GdkWindow *window, gint number)
   y += ty;
 
   rect = NSMakeRect (x,
-                     _gdk_quartz_window_get_inverted_screen_y (y + impl->height),
-                     impl->width, impl->height);
+                     _gdk_quartz_window_get_inverted_screen_y (y + private->height),
+                     private->width, private->height);
 
   if (debug_window[number] && NSEqualRects (rect, old_rect[number]))
     return;
@@ -775,7 +693,7 @@ find_child_window_helper (GdkWindow *window,
 
           if (titlebar_height > 0 &&
               x >= temp_x && y >= temp_y - titlebar_height &&
-              x < temp_x + child_impl->width && y < temp_y)
+              x < temp_x + child_private->width && y < temp_y)
             {
               /* The root means "unknown" i.e. a window not managed by
                * GDK.
@@ -785,7 +703,7 @@ find_child_window_helper (GdkWindow *window,
         }
 
       if (x >= temp_x && y >= temp_y &&
-         x < temp_x + child_impl->width && y < temp_y + child_impl->height)
+         x < temp_x + child_private->width && y < temp_y + child_private->height)
        {
          /* Look for child windows. */
          return find_child_window_helper (l->data,
@@ -807,9 +725,8 @@ _gdk_quartz_window_find_child (GdkWindow *window,
                               gint       y)
 {
   GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
-  GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
 
-  if (x >= 0 && y >= 0 && x < impl->width && y < impl->height)
+  if (x >= 0 && y >= 0 && x < private->width && y < private->height)
     return find_child_window_helper (window, x, y, 0, 0);
 
   return NULL;
@@ -857,101 +774,45 @@ _gdk_quartz_window_did_resign_main (GdkWindow *window)
   clear_toplevel_order ();
 }
 
-GdkWindow *
-_gdk_window_new (GdkWindow     *parent,
-                 GdkWindowAttr *attributes,
-                 gint           attributes_mask)
+void
+_gdk_window_impl_new (GdkWindow     *window,
+                     GdkWindow     *real_parent,
+                     GdkScreen     *screen,
+                     GdkVisual     *visual,
+                     GdkEventMask   event_mask,
+                     GdkWindowAttr *attributes,
+                     gint           attributes_mask)
 {
-  GdkWindow *window;
   GdkWindowObject *private;
   GdkWindowImplQuartz *impl;
   GdkDrawableImplQuartz *draw_impl;
-  GdkVisual *visual;
   GdkWindowImplQuartz *parent_impl;
 
-  if (parent && GDK_WINDOW_DESTROYED (parent))
-    return NULL;
-
   GDK_QUARTZ_ALLOC_POOL;
 
-  if (!parent)
-    parent = _gdk_root;
-
-  window = g_object_new (GDK_TYPE_WINDOW, NULL);
-
   private = (GdkWindowObject *)window;
-  private->impl = g_object_new (_gdk_window_impl_get_type (), NULL);
 
-  impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
-  draw_impl = GDK_DRAWABLE_IMPL_QUARTZ (private->impl);
+  impl = g_object_new (_gdk_window_impl_get_type (), NULL);
+  private->impl = (GdkDrawable *)impl;
+  draw_impl = GDK_DRAWABLE_IMPL_QUARTZ (impl);
   draw_impl->wrapper = GDK_DRAWABLE (window);
 
-  private->parent = (GdkWindowObject *)parent;
   parent_impl = GDK_WINDOW_IMPL_QUARTZ (private->parent->impl);
 
-  private->accept_focus = TRUE;
-  private->focus_on_map = TRUE;
-
-  if (attributes_mask & GDK_WA_X)
-    private->x = attributes->x;
-  else
-    private->x = 0;
-  
-  if (attributes_mask & GDK_WA_Y)
-    private->y = attributes->y;
-  else if (attributes_mask & GDK_WA_X)
-    private->y = 100;
-  else
-    private->y = 0;
-
-  private->event_mask = attributes->event_mask;
-
-  impl->width = attributes->width > 1 ? attributes->width : 1;
-  impl->height = attributes->height > 1 ? attributes->height : 1;
-
-  if (attributes_mask & GDK_WA_VISUAL)
-    visual = attributes->visual;
-  else
-    visual = gdk_screen_get_system_visual (_gdk_screen);
-
-  if (attributes->wclass == GDK_INPUT_ONLY)
-    {
-      /* Backwards compatiblity - we've always ignored
-       * attributes->window_type for input-only windows
-       * before
-       */
-      if (parent == _gdk_root)
-       private->window_type = GDK_WINDOW_TEMP;
-      else
-       private->window_type = GDK_WINDOW_CHILD;
-    }
-  else
-    private->window_type = attributes->window_type;
-
-  /* Sanity checks */
   switch (private->window_type)
     {
     case GDK_WINDOW_TOPLEVEL:
     case GDK_WINDOW_DIALOG:
     case GDK_WINDOW_TEMP:
-      if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
+      if (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
        {
-         g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
-                    "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
+         /* The common code warns for this case */
+          parent_impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (_gdk_root)->impl);
        }
-    case GDK_WINDOW_CHILD:
-      break;
-    default:
-      g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
-      GDK_QUARTZ_RELEASE_POOL;
-      return NULL;
     }
 
-  if (attributes->wclass == GDK_INPUT_OUTPUT)
+  if (!private->input_only)
     {
-      private->input_only = FALSE;
-      private->depth = visual->depth;
-
       if (attributes_mask & GDK_WA_COLORMAP)
        {
          draw_impl->colormap = attributes->colormap;
@@ -974,22 +835,15 @@ _gdk_window_new (GdkWindow     *parent,
              draw_impl->colormap = gdk_colormap_new (visual, FALSE);
            }
        }
-
-      private->bg_color.pixel = 0;
-      private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
     }
   else
     {
-      private->depth = 0;
-      private->input_only = TRUE;
       draw_impl->colormap = gdk_screen_get_system_colormap (_gdk_screen);
       g_object_ref (draw_impl->colormap);
     }
 
-  private->parent->children = g_list_prepend (private->parent->children, window);
-
   /* Maintain the z-ordered list of children. */
-  if (parent != _gdk_root)
+  if (private->parent != (GdkWindowObject *)_gdk_root)
     parent_impl->sorted_children = g_list_prepend (parent_impl->sorted_children, window);
   else
     clear_toplevel_order ();
@@ -1008,13 +862,10 @@ _gdk_window_new (GdkWindow     *parent,
         int style_mask;
         const char *title;
 
-        /* Big hack: We start out outside the screen and move the
-         * window in before showing it. This makes the initial
-         * MouseEntered event work if the window ends up right under
-         * the mouse pointer, bad quartz.
-         */
-        content_rect = NSMakeRect (-500 - impl->width, -500 - impl->height,
-                                   impl->width, impl->height);
+        content_rect = NSMakeRect (private->x,
+                                   _gdk_quartz_window_get_inverted_screen_y (private->y) - private->height,
+                                   private->width,
+                                   private->height);
 
         if (attributes->window_type == GDK_WINDOW_TEMP ||
             attributes->type_hint == GDK_WINDOW_TYPE_HINT_SPLASHSCREEN)
@@ -1047,6 +898,9 @@ _gdk_window_new (GdkWindow     *parent,
            [impl->toplevel setBackgroundColor:[NSColor clearColor]];
          }
 
+        content_rect.origin.x = 0;
+        content_rect.origin.y = 0;
+
        impl->view = [[GdkQuartzView alloc] initWithFrame:content_rect];
        [impl->view setGdkWindow:window];
        [impl->toplevel setContentView:impl->view];
@@ -1055,11 +909,14 @@ _gdk_window_new (GdkWindow     *parent,
 
     case GDK_WINDOW_CHILD:
       {
-       GdkWindowImplQuartz *parent_impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (parent)->impl);
+       GdkWindowImplQuartz *parent_impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (private->parent)->impl);
 
-       if (attributes->wclass == GDK_INPUT_OUTPUT)
+       if (!private->input_only)
          {
-           NSRect frame_rect = NSMakeRect (private->x, private->y, impl->width, impl->height);
+           NSRect frame_rect = NSMakeRect (private->x + private->parent->abs_x,
+                                            private->y + private->parent->abs_y,
+                                            private->width,
+                                            private->height);
        
            impl->view = [[GdkQuartzView alloc] initWithFrame:frame_rect];
            
@@ -1080,8 +937,6 @@ _gdk_window_new (GdkWindow     *parent,
 
   if (attributes_mask & GDK_WA_TYPE_HINT)
     gdk_window_set_type_hint (window, attributes->type_hint);
-
-  return window;
 }
 
 void
@@ -1098,12 +953,18 @@ _gdk_windowing_window_init (void)
 
   private = (GdkWindowObject *)_gdk_root;
   private->impl = g_object_new (_gdk_window_impl_get_type (), NULL);
+  private->impl_window = private;
 
   /* Note: This needs to be reworked for multi-screen support. */
   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (_gdk_root)->impl);
   rect = [[NSScreen mainScreen] frame];
-  impl->width = rect.size.width;
-  impl->height = rect.size.height;
+
+  private->x = 0;
+  private->y = 0;
+  private->abs_x = 0;
+  private->abs_y = 0;
+  private->width = rect.size.width;
+  private->height = rect.size.height;
 
   private->state = 0; /* We don't want GDK_WINDOW_STATE_WITHDRAWN here */
   private->window_type = GDK_WINDOW_ROOT;
@@ -1116,20 +977,18 @@ _gdk_windowing_window_init (void)
   g_object_ref (drawable_impl->colormap);
 }
 
-void
-_gdk_windowing_window_destroy (GdkWindow *window,
-                              gboolean   recursing,
-                              gboolean   foreign_destroy)
+static void
+_gdk_quartz_window_destroy (GdkWindow *window,
+                            gboolean   recursing,
+                            gboolean   foreign_destroy)
 {
   GdkWindowObject *private;
   GdkWindowImplQuartz *impl;
   GdkWindowObject *parent;
-  GdkWindow *mouse_window;
 
   private = GDK_WINDOW_OBJECT (window);
   impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
 
-  update_windows = g_slist_remove (update_windows, window);
   main_window_stack = g_slist_remove (main_window_stack, window);
 
   g_list_free (impl->sorted_children);
@@ -1143,22 +1002,8 @@ _gdk_windowing_window_destroy (GdkWindow *window,
       parent_impl->sorted_children = g_list_remove (parent_impl->sorted_children, window);
     }
 
-  /* If the destroyed window was targeted for a pointer or keyboard
-   * grab, release the grab.
-   */
-  if (window == _gdk_quartz_pointer_grab_window)
-    gdk_pointer_ungrab (0);
-
-  if (window == _gdk_quartz_keyboard_grab_window)
-    gdk_keyboard_ungrab (0);
-
   _gdk_quartz_drawable_finish (GDK_DRAWABLE (impl));
 
-  mouse_window = _gdk_quartz_events_get_mouse_window (FALSE);
-  if (window == mouse_window ||
-      _gdk_quartz_window_is_ancestor (window, mouse_window))
-    _gdk_quartz_events_update_mouse_window (_gdk_root);
-
   if (!recursing && !foreign_destroy)
     {
       GDK_QUARTZ_ALLOC_POOL;
@@ -1178,39 +1023,16 @@ _gdk_windowing_window_destroy_foreign (GdkWindow *window)
   /* Foreign windows aren't supported in OSX. */
 }
 
-static gboolean
-all_parents_shown (GdkWindowObject *private)
-{
-  while (GDK_WINDOW_IS_MAPPED (private))
-    {
-      if (private->parent)
-       private = (GdkWindowObject *)private->parent;
-      else
-       return TRUE;
-    }
-
-  return FALSE;
-}
-
-/* Note: the raise argument is not really used, it doesn't seem
- * possible to show a window without raising it?
- */
+/* FIXME: This might be possible to simplify with client-side windows. */
 static void
-gdk_window_quartz_show (GdkWindow *window,
-                        gboolean   raise)
+gdk_window_quartz_show (GdkWindow *window)
 {
-  GdkWindowObject *private;
-  GdkWindowImplQuartz *impl;
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
   gboolean focus_on_map;
 
-  if (GDK_WINDOW_DESTROYED (window))
-    return;
-
   GDK_QUARTZ_ALLOC_POOL;
 
-  private = (GdkWindowObject *)window;
-  impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
-
   if (!GDK_WINDOW_IS_MAPPED (window))
     focus_on_map = private->focus_on_map;
   else
@@ -1220,14 +1042,13 @@ gdk_window_quartz_show (GdkWindow *window,
     {
       gboolean make_key;
 
-      /* Move the window into place, to guarantee that we get the
-       * initial MouseEntered event.
-       */
-      make_key = (private->accept_focus && focus_on_map && raise && 
+      make_key = (private->accept_focus && focus_on_map &&
                   private->window_type != GDK_WINDOW_TEMP);
 
       [(GdkQuartzWindow*)impl->toplevel showAndMakeKey:make_key];
       clear_toplevel_order ();
+
+      _gdk_quartz_events_send_map_event (window);
     }
   else
     {
@@ -1236,9 +1057,6 @@ gdk_window_quartz_show (GdkWindow *window,
 
   [impl->view setNeedsDisplay:YES];
 
-  if (all_parents_shown (private->parent))
-    _gdk_quartz_events_send_map_events (window);
-
   gdk_synthesize_window_state (window, GDK_WINDOW_STATE_WITHDRAWN, 0);
 
   if (private->state & GDK_WINDOW_STATE_MAXIMIZED)
@@ -1250,12 +1068,6 @@ gdk_window_quartz_show (GdkWindow *window,
   if (impl->transient_for && !GDK_WINDOW_DESTROYED (impl->transient_for))
     _gdk_quartz_window_attach_to_parent (window);
 
-  /* Create a crossing event for windows that pop up under the mouse. Part
-   * of the workarounds for problems with the tracking rect API.
-   */
-  if (impl->toplevel)
-    _gdk_quartz_events_trigger_crossing_events (TRUE);
-
   GDK_QUARTZ_RELEASE_POOL;
 }
 
@@ -1310,24 +1122,12 @@ gdk_window_quartz_hide (GdkWindow *window)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
   GdkWindowImplQuartz *impl;
-  GdkWindow *mouse_window;
 
   /* Make sure we're not stuck in fullscreen mode. */
   if (get_fullscreen_geometry (window))
     SetSystemUIMode (kUIModeNormal, 0);
 
-  if (GDK_WINDOW_DESTROYED (window))
-    return;
-
-  mouse_window = _gdk_quartz_events_get_mouse_window (FALSE);
-  if (window == mouse_window || 
-      _gdk_quartz_window_is_ancestor (window, mouse_window))
-    _gdk_quartz_events_update_mouse_window (_gdk_root);
-
-  if (GDK_WINDOW_IS_MAPPED (window))
-    gdk_synthesize_window_state (window,
-                                0,
-                                GDK_WINDOW_STATE_WITHDRAWN);
+  check_grab_unmap (window);
 
   _gdk_window_clear_update_area (window);
 
@@ -1349,12 +1149,6 @@ gdk_window_quartz_hide (GdkWindow *window)
     {
       [impl->view setHidden:YES];
     }
-
-  if (window == _gdk_quartz_pointer_grab_window)
-    gdk_pointer_ungrab (0);
-
-  if (window == _gdk_quartz_keyboard_grab_window)
-    gdk_keyboard_ungrab (0);
 }
 
 void
@@ -1386,8 +1180,8 @@ move_resize_window_internal (GdkWindow *window,
 
   if ((x == -1 || (x == private->x)) &&
       (y == -1 || (y == private->y)) &&
-      (width == -1 || (width == impl->width)) &&
-      (height == -1 || (height == impl->height)))
+      (width == -1 || (width == private->width)) &&
+      (height == -1 || (height == private->height)))
     {
       return;
     }
@@ -1426,10 +1220,10 @@ move_resize_window_internal (GdkWindow *window,
     }
 
   if (width != -1)
-    impl->width = width;
+    private->width = width;
 
   if (height != -1)
-    impl->height = height;
+    private->height = height;
 
   GDK_QUARTZ_ALLOC_POOL;
 
@@ -1438,19 +1232,12 @@ move_resize_window_internal (GdkWindow *window,
       NSRect content_rect;
       NSRect frame_rect;
 
-      /* We don't update the NSWindow while unmapped, since we move windows
-       * off-screen when hiding in order for MouseEntered to be triggered
-       * reliably when showing windows and they appear under the mouse.
-       */
-      if (GDK_WINDOW_IS_MAPPED (window))
-        {
-          content_rect =  NSMakeRect (private->x,
-                                      _gdk_quartz_window_get_inverted_screen_y (private->y + impl->height),
-                                      impl->width, impl->height);
+      content_rect =  NSMakeRect (private->x,
+                                  _gdk_quartz_window_get_inverted_screen_y (private->y + private->height),
+                                  private->width, private->height);
 
-          frame_rect = [impl->toplevel frameRectForContentRect:content_rect];
-          [impl->toplevel setFrame:frame_rect display:YES];
-        }
+      frame_rect = [impl->toplevel frameRectForContentRect:content_rect];
+      [impl->toplevel setFrame:frame_rect display:YES];
     }
   else 
     {
@@ -1458,7 +1245,7 @@ move_resize_window_internal (GdkWindow *window,
         {
           NSRect nsrect;
 
-          nsrect = NSMakeRect (private->x, private->y, impl->width, impl->height);
+          nsrect = NSMakeRect (private->x, private->y, private->width, private->height);
 
           /* The newly visible area of this window in a coordinate
            * system rooted at the origin of this window.
@@ -1588,6 +1375,9 @@ gdk_window_quartz_move_resize (GdkWindow *window,
     }
 }
 
+/* FIXME: This might need fixing (reparenting didn't work before client-side
+ * windows either).
+ */
 static gboolean
 gdk_window_quartz_reparent (GdkWindow *window,
                             GdkWindow *new_parent,
@@ -1598,7 +1388,7 @@ gdk_window_quartz_reparent (GdkWindow *window,
   GdkWindowImplQuartz *impl, *old_parent_impl, *new_parent_impl;
   NSView *view, *new_parent_view;
 
-  if (!new_parent || new_parent == _gdk_root)
+  if (new_parent == _gdk_root)
     {
       /* Could be added, just needs implementing. */
       g_warning ("Reparenting to root window is not supported yet in the Mac OS X backend");
@@ -1623,31 +1413,16 @@ gdk_window_quartz_reparent (GdkWindow *window,
 
   [view release];
 
-  private->x = x;
-  private->y = y;
-  private->parent = (GdkWindowObject *)new_parent;
+  private->parent = new_parent_private;
 
   if (old_parent_private)
     {
-      old_parent_private->children = g_list_remove (old_parent_private->children, window);
       old_parent_impl->sorted_children = g_list_remove (old_parent_impl->sorted_children, window);
     }
 
-  new_parent_private->children = g_list_prepend (new_parent_private->children, window);
   new_parent_impl->sorted_children = g_list_prepend (new_parent_impl->sorted_children, window);
 
-  return TRUE;
-}
-
-static void
-gdk_window_quartz_clear_area (GdkWindow *window,
-                              gint       x,
-                              gint       y,
-                              gint       width,
-                              gint       height,
-                              gboolean   send_expose)
-{
-  /* FIXME: Implement */
+  return FALSE;
 }
 
 /* Get the toplevel ordering from NSApp and update our own list. We do
@@ -1767,87 +1542,38 @@ static void
 gdk_window_quartz_set_background (GdkWindow      *window,
                                   const GdkColor *color)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkWindowImplQuartz *impl;
-
-  if (GDK_WINDOW_DESTROYED (window))
-    return;
-
-  impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
-
-  private->bg_color = *color;
-
-  if (private->bg_pixmap &&
-      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
-      private->bg_pixmap != GDK_NO_BG)
-    g_object_unref (private->bg_pixmap);
-  
-  private->bg_pixmap = NULL;
+  /* FIXME: We could theoretically set the background color for toplevels
+   * here. (Currently we draw the background before emitting expose events)
+   */
 }
 
 static void
 gdk_window_quartz_set_back_pixmap (GdkWindow *window,
-                                   GdkPixmap *pixmap,
-                                   gboolean   parent_relative)
+                                   GdkPixmap *pixmap)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-
-  if (GDK_WINDOW_DESTROYED (window))
-    return;
-
-  if (private->bg_pixmap &&
-      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
-      private->bg_pixmap != GDK_NO_BG)
-    g_object_unref (private->bg_pixmap);
-
-  if (parent_relative)
-    {
-      private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
-      GDK_NOTE (MISC, g_print (G_STRLOC ": setting background pixmap to parent_relative\n"));
-    }
-  else
-    {
-      if (pixmap)
-       {
-         g_object_ref (pixmap);
-         private->bg_pixmap = pixmap;
-       }
-      else
-       {
-         private->bg_pixmap = GDK_NO_BG;
-       }
-    }
+  /* FIXME: Could theoretically set some background image here. (Currently
+   * the back pixmap is drawn before emitting expose events.
+   */
 }
 
 static void
 gdk_window_quartz_set_cursor (GdkWindow *window,
                               GdkCursor *cursor)
 {
-  GdkWindowImplQuartz *impl;
   GdkCursorPrivate *cursor_private;
   NSCursor *nscursor;
 
-  impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
   cursor_private = (GdkCursorPrivate *)cursor;
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
-  GDK_QUARTZ_ALLOC_POOL;
-
   if (!cursor)
-    nscursor = NULL;
+    nscursor = [NSCursor arrowCursor];
   else 
-    nscursor = [cursor_private->nscursor retain];
-
-  if (impl->nscursor)
-    [impl->nscursor release];
-
-  impl->nscursor = nscursor;
+    nscursor = cursor_private->nscursor;
 
-  GDK_QUARTZ_RELEASE_POOL;
-
-  _gdk_quartz_events_update_cursor (_gdk_quartz_events_get_mouse_window (TRUE));
+  [nscursor set];
 }
 
 static void
@@ -1859,12 +1585,14 @@ gdk_window_quartz_get_geometry (GdkWindow *window,
                                 gint      *depth)
 {
   GdkWindowImplQuartz *impl;
+  GdkWindowObject *private;
   NSRect ns_rect;
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
+  private = GDK_WINDOW_OBJECT (window);
   if (window == _gdk_root)
     {
       if (x) 
@@ -1873,9 +1601,9 @@ gdk_window_quartz_get_geometry (GdkWindow *window,
         *y = 0;
 
       if (width) 
-        *width = impl->width;
+        *width = private->width;
       if (height)
-        *height = impl->height;
+        *height = private->height;
     }
   else if (WINDOW_IS_TOPLEVEL (window))
     {
@@ -1950,8 +1678,11 @@ gdk_window_quartz_get_origin (GdkWindow *window,
 
   if (window == _gdk_root)
     {
-      *x = 0;
-      *y = 0;
+      if (x)
+        *x = 0;
+      if (y)
+        *y = 0;
+
       return 1;
     }
   
@@ -1967,8 +1698,11 @@ gdk_window_quartz_get_origin (GdkWindow *window,
 
   while (private != GDK_WINDOW_OBJECT (toplevel))
     {
-      tmp_x += private->x;
-      tmp_y += private->y;
+      if (_gdk_window_has_impl ((GdkWindow *)private))
+        {
+          tmp_x += private->x;
+          tmp_y += private->y;
+        }
 
       private = private->parent;
     }
@@ -1981,13 +1715,11 @@ gdk_window_quartz_get_origin (GdkWindow *window,
   return TRUE;
 }
 
-gboolean
-gdk_window_get_deskrelative_origin (GdkWindow *window,
-                                   gint      *x,
-                                   gint      *y)
+static gboolean
+gdk_window_quartz_get_deskrelative_origin (GdkWindow *window,
+                                           gint      *x,
+                                           gint      *y)
 {
-  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
-
   return gdk_window_get_origin (window, x, y);
 }
 
@@ -1998,8 +1730,6 @@ gdk_window_get_root_origin (GdkWindow *window,
 {
   GdkRectangle rect;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
   rect.x = 0;
   rect.y = 0;
   
@@ -2040,6 +1770,8 @@ _gdk_windowing_window_get_pointer (GdkDisplay      *display,
   gint x_tmp, y_tmp;
   GdkWindow *found_window;
 
+  g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
+
   if (GDK_WINDOW_DESTROYED (window))
     {
       *x = 0;
@@ -2065,23 +1797,15 @@ _gdk_windowing_window_get_pointer (GdkDisplay      *display,
       NSWindow *nswindow;
 
       impl = GDK_WINDOW_IMPL_QUARTZ (toplevel->impl);
+      private = GDK_WINDOW_OBJECT (toplevel);
       nswindow = impl->toplevel;
 
       point = [nswindow mouseLocationOutsideOfEventStream];
-      x_tmp = point.x;
-      y_tmp = impl->height - point.y;
-    }
 
-  /* The coords are relative to the toplevel of the passed in window
-   * at this point, make them relative to the passed in window:
-   */
-  private = GDK_WINDOW_OBJECT (window);
-  while (private != toplevel)
-    {
-      x_tmp -= private->x;
-      y_tmp -= private->y;
+      x_tmp = point.x;
+      y_tmp = private->height - point.y;
 
-      private = private->parent;
+      window = (GdkWindow *)toplevel;
     }
 
   found_window = _gdk_quartz_window_find_child (window, x_tmp, y_tmp);
@@ -2107,18 +1831,19 @@ gdk_display_warp_pointer (GdkDisplay *display,
 
 /* Returns coordinates relative to the found window. */
 GdkWindow *
-_gdk_windowing_window_at_pointer (GdkDisplay *display,
-                                 gint       *win_x,
-                                 gint       *win_y)
+_gdk_windowing_window_at_pointer (GdkDisplay      *display,
+                                 gint            *win_x,
+                                 gint            *win_y,
+                                  GdkModifierType *mask)
 {
-  GdkModifierType mask;
   GdkWindow *found_window;
   gint x, y;
+  GdkModifierType tmp_mask = 0;
 
   found_window = _gdk_windowing_window_get_pointer (display,
                                                    _gdk_root,
                                                    &x, &y,
-                                                   &mask);
+                                                   &tmp_mask);
   if (found_window)
     {
       GdkWindowObject *private;
@@ -2145,6 +1870,9 @@ _gdk_windowing_window_at_pointer (GdkDisplay *display,
       *win_y = -1;
     }
 
+  if (mask)
+    *mask = tmp_mask;
+
   return found_window;
 }
 
@@ -2161,16 +1889,17 @@ static void
 gdk_window_quartz_set_events (GdkWindow       *window,
                               GdkEventMask     event_mask)
 {
-  if (!GDK_WINDOW_DESTROYED (window))
-    {
-      GDK_WINDOW_OBJECT (window)->event_mask = event_mask;
-    }
+  /* The mask is set in the common code. */
 }
 
 void
 gdk_window_set_urgency_hint (GdkWindow *window,
                             gboolean   urgent)
 {
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
   /* FIXME: Implement */
 }
 
@@ -2181,10 +1910,10 @@ gdk_window_set_geometry_hints (GdkWindow         *window,
 {
   GdkWindowImplQuartz *impl;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (geometry != NULL);
 
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
   
   impl = GDK_WINDOW_IMPL_QUARTZ (((GdkWindowObject *) window)->impl);
@@ -2258,10 +1987,10 @@ gdk_window_set_title (GdkWindow   *window,
 {
   GdkWindowImplQuartz *impl;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (title != NULL);
 
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      WINDOW_IS_TOPLEVEL (window))
     return;
 
   impl = GDK_WINDOW_IMPL_QUARTZ (((GdkWindowObject *)window)->impl);
@@ -2278,6 +2007,10 @@ void
 gdk_window_set_role (GdkWindow   *window,
                     const gchar *role)
 {
+  if (GDK_WINDOW_DESTROYED (window) ||
+      WINDOW_IS_TOPLEVEL (window))
+    return;
+
   /* FIXME: Implement */
 }
 
@@ -2288,7 +2021,8 @@ gdk_window_set_transient_for (GdkWindow *window,
   GdkWindowImplQuartz *window_impl;
   GdkWindowImplQuartz *parent_impl;
 
-  if (GDK_WINDOW_DESTROYED (window) || GDK_WINDOW_DESTROYED (parent))
+  if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (parent) &&
+      WINDOW_IS_TOPLEVEL (window))
     return;
 
   window_impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
@@ -2343,38 +2077,14 @@ gdk_window_quartz_shape_combine_region (GdkWindow       *window,
 }
 
 static void
-gdk_window_quartz_shape_combine_mask (GdkWindow *window,
-                                      GdkBitmap *mask,
-                                      gint       x,
-                                      gint       y)
-{
-  /* FIXME: Implement */
-}
-
-void
-gdk_window_input_shape_combine_mask (GdkWindow *window,
-                                    GdkBitmap *mask,
-                                    gint       x,
-                                    gint       y)
+gdk_window_quartz_input_shape_combine_region (GdkWindow       *window,
+                                              const GdkRegion *shape_region,
+                                              gint             offset_x,
+                                              gint             offset_y)
 {
   /* FIXME: Implement */
 }
 
-void
-gdk_window_input_shape_combine_region (GdkWindow       *window,
-                                       const GdkRegion *shape_region,
-                                       gint             offset_x,
-                                       gint             offset_y)
-{
-  /* FIXME: Implement */
-}
-
-void 
-gdk_window_set_child_input_shapes (GdkWindow *window)
-{
-  /* FIXME: IMplement */
-}
-
 void
 gdk_window_set_override_redirect (GdkWindow *window,
                                  gboolean override_redirect)
@@ -2388,35 +2098,19 @@ gdk_window_set_accept_focus (GdkWindow *window,
 {
   GdkWindowObject *private;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
   private = (GdkWindowObject *)window;  
 
   private->accept_focus = accept_focus != FALSE;
 }
 
-static void
-gdk_window_quartz_set_child_shapes (GdkWindow *window)
-{
-  /* FIXME: Implement */
-}
-
-static void
-gdk_window_quartz_merge_child_shapes (GdkWindow *window)
-{
-  /* FIXME: Implement */
-}
-
-void 
-gdk_window_merge_child_input_shapes (GdkWindow *window)
-{
-  /* FIXME: Implement */
-}
-
 static gboolean 
 gdk_window_quartz_set_static_gravities (GdkWindow *window,
                                         gboolean   use_static)
 {
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return FALSE;
+
   /* FIXME: Implement */
   return FALSE;
 }
@@ -2427,8 +2121,6 @@ gdk_window_set_focus_on_map (GdkWindow *window,
 {
   GdkWindowObject *private;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
   private = (GdkWindowObject *)window;  
   
   private->focus_on_map = focus_on_map != FALSE;
@@ -2440,8 +2132,6 @@ gdk_window_set_icon (GdkWindow *window,
                     GdkPixmap *pixmap,
                     GdkBitmap *mask)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
   /* FIXME: Implement */
 }
 
@@ -2449,8 +2139,6 @@ void
 gdk_window_set_icon_name (GdkWindow   *window, 
                          const gchar *name)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
   /* FIXME: Implement */
 }
 
@@ -2461,20 +2149,19 @@ gdk_window_focus (GdkWindow *window,
   GdkWindowObject *private;
   GdkWindowImplQuartz *impl;
        
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
   private = (GdkWindowObject*) window;
   impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
 
-  if (impl->toplevel)
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
+
+  if (private->accept_focus && private->window_type != GDK_WINDOW_TEMP)
     {
-      if (private->accept_focus && private->window_type != GDK_WINDOW_TEMP) 
-        {
-          GDK_QUARTZ_ALLOC_POOL;
-          [impl->toplevel makeKeyAndOrderFront:impl->toplevel];
-          clear_toplevel_order ();
-          GDK_QUARTZ_RELEASE_POOL;
-        }
+      GDK_QUARTZ_ALLOC_POOL;
+      [impl->toplevel makeKeyAndOrderFront:impl->toplevel];
+      clear_toplevel_order ();
+      GDK_QUARTZ_RELEASE_POOL;
     }
 }
 
@@ -2564,9 +2251,8 @@ gdk_window_set_type_hint (GdkWindow        *window,
 {
   GdkWindowImplQuartz *impl;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   impl = GDK_WINDOW_IMPL_QUARTZ (((GdkWindowObject *) window)->impl);
@@ -2584,7 +2270,8 @@ gdk_window_set_type_hint (GdkWindow        *window,
 GdkWindowTypeHint
 gdk_window_get_type_hint (GdkWindow *window)
 {
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return GDK_WINDOW_TYPE_HINT_NORMAL;
   
   return GDK_WINDOW_IMPL_QUARTZ (((GdkWindowObject *) window)->impl)->type_hint;
@@ -2594,7 +2281,9 @@ void
 gdk_window_set_modal_hint (GdkWindow *window,
                           gboolean   modal)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
 
   /* FIXME: Implement */
 }
@@ -2603,7 +2292,9 @@ void
 gdk_window_set_skip_taskbar_hint (GdkWindow *window,
                                  gboolean   skips_taskbar)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
 
   /* FIXME: Implement */
 }
@@ -2612,7 +2303,9 @@ void
 gdk_window_set_skip_pager_hint (GdkWindow *window,
                                gboolean   skips_pager)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
 
   /* FIXME: Implement */
 }
@@ -2661,9 +2354,8 @@ gdk_window_begin_move_drag (GdkWindow *window,
   GdkWindowObject *private;
   GdkWindowImplQuartz *impl;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   private = GDK_WINDOW_OBJECT (window);
@@ -2694,7 +2386,6 @@ gdk_window_get_frame_extents (GdkWindow    *window,
   GdkWindowImplQuartz *impl;
   NSRect ns_rect;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (rect != NULL);
 
   private = GDK_WINDOW_OBJECT (window);
@@ -2704,9 +2395,6 @@ gdk_window_get_frame_extents (GdkWindow    *window,
   rect->width = 1;
   rect->height = 1;
   
-  if (GDK_WINDOW_DESTROYED (window))
-    return;
-
   toplevel = gdk_window_get_toplevel (window);
   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (toplevel)->impl);
 
@@ -2726,10 +2414,8 @@ gdk_window_set_decorations (GdkWindow       *window,
   int old_mask, new_mask;
   NSView *old_view;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
@@ -2804,10 +2490,8 @@ gdk_window_get_decorations (GdkWindow       *window,
 {
   GdkWindowImplQuartz *impl;
 
-  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
-  g_return_val_if_fail (WINDOW_IS_TOPLEVEL (window), FALSE);
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return FALSE;
 
   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
@@ -2838,14 +2522,6 @@ gdk_window_set_functions (GdkWindow    *window,
   /* FIXME: Implement */
 }
 
-static void
-gdk_window_quartz_get_offsets (GdkWindow  *window,
-                               gint       *x_offset,
-                               gint       *y_offset)
-{
-  *x_offset = *y_offset = 0;
-}
-
 gboolean
 _gdk_windowing_window_queue_antiexpose (GdkWindow  *window,
                                        GdkRegion  *area)
@@ -2856,13 +2532,17 @@ _gdk_windowing_window_queue_antiexpose (GdkWindow  *window,
 void
 gdk_window_stick (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
 }
 
 void
 gdk_window_unstick (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
 }
 
 void
@@ -2870,9 +2550,8 @@ gdk_window_maximize (GdkWindow *window)
 {
   GdkWindowImplQuartz *impl;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
@@ -2899,9 +2578,8 @@ gdk_window_unmaximize (GdkWindow *window)
 {
   GdkWindowImplQuartz *impl;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
@@ -2928,11 +2606,10 @@ gdk_window_iconify (GdkWindow *window)
 {
   GdkWindowImplQuartz *impl;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
-  
+
   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
 
   if (GDK_WINDOW_IS_MAPPED (window))
@@ -2957,9 +2634,8 @@ gdk_window_deiconify (GdkWindow *window)
 {
   GdkWindowImplQuartz *impl;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   impl = GDK_WINDOW_IMPL_QUARTZ (GDK_WINDOW_OBJECT (window)->impl);
@@ -2992,11 +2668,11 @@ gdk_window_fullscreen (GdkWindow *window)
 {
   FullscreenSavedGeometry *geometry;
   GdkWindowObject *private = (GdkWindowObject *) window;
-  GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (private->impl);
   NSRect frame;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
 
   geometry = get_fullscreen_geometry (window);
   if (!geometry)
@@ -3005,8 +2681,8 @@ gdk_window_fullscreen (GdkWindow *window)
 
       geometry->x = private->x;
       geometry->y = private->y;
-      geometry->width = impl->width;
-      geometry->height = impl->height;
+      geometry->width = private->width;
+      geometry->height = private->height;
 
       if (!gdk_window_get_decorations (window, &geometry->decor))
         geometry->decor = GDK_DECOR_ALL;
@@ -3033,8 +2709,9 @@ gdk_window_unfullscreen (GdkWindow *window)
 {
   FullscreenSavedGeometry *geometry;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
 
   geometry = get_fullscreen_geometry (window);
   if (geometry)
@@ -3063,9 +2740,9 @@ gdk_window_set_keep_above (GdkWindow *window, gboolean setting)
   gint level;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
-  g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
 
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   level = window_type_hint_to_level (gdk_window_get_type_hint (window));
@@ -3082,9 +2759,9 @@ gdk_window_set_keep_below (GdkWindow *window, gboolean setting)
   gint level;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
-  g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
 
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
   
   level = window_type_hint_to_level (gdk_window_get_type_hint (window));
@@ -3096,9 +2773,12 @@ gdk_window_set_keep_below (GdkWindow *window, gboolean setting)
 GdkWindow *
 gdk_window_get_group (GdkWindow *window)
 {
-  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
   g_return_val_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD, NULL);
 
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return NULL;
+
   /* FIXME: Implement */
 
   return NULL;
@@ -3146,11 +2826,17 @@ gdk_window_configure_finished (GdkWindow *window)
 void
 gdk_window_destroy_notify (GdkWindow *window)
 {
+  check_grab_destroy (window);
 }
 
 void 
 gdk_window_beep (GdkWindow *window)
 {
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
   gdk_display_beep (_gdk_display);
 }
 
@@ -3164,7 +2850,8 @@ gdk_window_set_opacity (GdkWindow *window,
   g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
 
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (opacity < 0)
@@ -3188,22 +2875,20 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface)
   iface->withdraw = gdk_window_quartz_withdraw;
   iface->set_events = gdk_window_quartz_set_events;
   iface->get_events = gdk_window_quartz_get_events;
-  iface->clear_area = gdk_window_quartz_clear_area;
   iface->raise = gdk_window_quartz_raise;
   iface->lower = gdk_window_quartz_lower;
   iface->move_resize = gdk_window_quartz_move_resize;
-  iface->scroll = _gdk_quartz_window_scroll;
-  iface->move_region = _gdk_quartz_window_move_region;
   iface->set_background = gdk_window_quartz_set_background;
   iface->set_back_pixmap = gdk_window_quartz_set_back_pixmap;
   iface->reparent = gdk_window_quartz_reparent;
   iface->set_cursor = gdk_window_quartz_set_cursor;
   iface->get_geometry = gdk_window_quartz_get_geometry;
   iface->get_origin = gdk_window_quartz_get_origin;
-  iface->shape_combine_mask = gdk_window_quartz_shape_combine_mask;
+  iface->get_deskrelative_origin = gdk_window_quartz_get_deskrelative_origin;
   iface->shape_combine_region = gdk_window_quartz_shape_combine_region;
-  iface->set_child_shapes = gdk_window_quartz_set_child_shapes;
-  iface->merge_child_shapes = gdk_window_quartz_merge_child_shapes;
+  iface->input_shape_combine_region = gdk_window_quartz_input_shape_combine_region;
   iface->set_static_gravities = gdk_window_quartz_set_static_gravities;
-  iface->get_offsets = gdk_window_quartz_get_offsets;
+  iface->queue_antiexpose = _gdk_quartz_window_queue_antiexpose;
+  iface->queue_translation = _gdk_quartz_window_queue_translation;
+  iface->destroy = _gdk_quartz_window_destroy;
 }
index b3e3fb9db2430020003ee31c43c4f82264d8580b..89f2ec06bf0abf9f556995122ffc84917defda0f 100644 (file)
@@ -45,17 +45,12 @@ struct _GdkWindowImplQuartz
 {
   GdkDrawableImplQuartz parent_instance;
 
-  gint width;
-  gint height;
-
   NSWindow *toplevel;
   NSTrackingRectTag tracking_rect;
   GdkQuartzView *view;
 
   GdkWindowTypeHint type_hint;
 
-  NSCursor *nscursor;
-
   GdkRegion *paint_clip_region;
   gint begin_paint_count;
   gint in_paint_rect_count;
index 75fde086598e22c1afffb1878bbf9ac799819189..340d243f33d1741b870ff5f57296614bc40b1433 100644 (file)
@@ -36,6 +36,12 @@ _gdk_windowing_set_default_display (GdkDisplay *display)
   g_assert (display == NULL || _gdk_display == display);
 }
 
+gulong
+_gdk_windowing_window_get_next_serial (GdkDisplay *display)
+{
+       return 0;
+}
+
 #ifdef HAVE_MONITOR_INFO
 static BOOL CALLBACK
 count_monitor (HMONITOR hmonitor,
@@ -200,7 +206,7 @@ gdk_display_open (const gchar *display_name)
   _gdk_visual_init ();
   gdk_screen_set_default_colormap (_gdk_screen,
                                    gdk_screen_get_system_colormap (_gdk_screen));
-  _gdk_windowing_window_init ();
+  _gdk_windowing_window_init (_gdk_screen);
   _gdk_windowing_image_init ();
   _gdk_events_init ();
   _gdk_input_init (_gdk_display);
index e762ae0f05272825c7aa6709fbf13bdbe28a77a9..18997ad0abdac092711146bd51a11fa139cfe0a4 100644 (file)
@@ -87,6 +87,7 @@ static void gdk_win32_draw_text_wc   (GdkDrawable    *drawable,
 static void gdk_win32_draw_drawable  (GdkDrawable    *drawable,
                                      GdkGC          *gc,
                                      GdkPixmap      *src,
+                                     GdkDrawable    *original_src,
                                      gint            xsrc,
                                      gint            ysrc,
                                      gint            xdest,
@@ -1143,6 +1144,7 @@ static void
 gdk_win32_draw_drawable (GdkDrawable *drawable,
                         GdkGC       *gc,
                         GdkPixmap   *src,
+                        GdkDrawable *original_src,
                         gint         xsrc,
                         gint         ysrc,
                         gint         xdest,
@@ -1657,16 +1659,45 @@ _gdk_win32_blit (gboolean              use_fg_bg,
   else
     g_assert_not_reached ();
 
+  if (GDK_IS_WINDOW_IMPL_WIN32 (draw_impl) &&
+      GDK_IS_PIXMAP_IMPL_WIN32 (src_impl))
+    {
+      GdkPixmapImplWin32 *src_pixmap = GDK_PIXMAP_IMPL_WIN32 (src_impl);
+
+      if (xsrc < 0)
+       {
+         width += xsrc;
+         xdest -= xsrc;
+         xsrc = 0;
+       }
+
+      if (ysrc < 0)
+       {
+         height += ysrc;
+         ydest -= ysrc;
+         ysrc = 0;
+       }
+
+      if (xsrc + width > src_pixmap->width)
+       width = src_pixmap->width - xsrc;
+      if (ysrc + height > src_pixmap->height)
+       height = src_pixmap->height - ysrc;
+    }
+
   hdc = gdk_win32_hdc_get (&draw_impl->parent_instance, gc, GDK_GC_FOREGROUND);
 
   gdk_drawable_get_size (src, &src_width, &src_height);
 
   if ((src_rgn = CreateRectRgn (0, 0, src_width + 1, src_height + 1)) == NULL)
-    WIN32_GDI_FAILED ("CreateRectRgn");
+    {
+      WIN32_GDI_FAILED ("CreateRectRgn");
+    }
   else if ((draw_rgn = CreateRectRgn (xsrc, ysrc,
                                      xsrc + width + 1,
                                      ysrc + height + 1)) == NULL)
-    WIN32_GDI_FAILED ("CreateRectRgn");
+    {
+      WIN32_GDI_FAILED ("CreateRectRgn");
+    }
   else
     {
       if (GDK_IS_WINDOW_IMPL_WIN32 (draw_impl))
@@ -1731,6 +1762,7 @@ _gdk_win32_blit (gboolean              use_fg_bg,
                      xsrc, ysrc, xdest, ydest, width, height);
   else
     blit_from_window (hdc, GDK_GC_WIN32 (gc), src_impl, xsrc, ysrc, xdest, ydest, width, height);
+
   gdk_win32_hdc_release (&draw_impl->parent_instance, gc, GDK_GC_FOREGROUND);
 }
 
@@ -1807,7 +1839,9 @@ _gdk_win32_drawable_acquire_dc (GdkDrawable *drawable)
       return impl->hdc;
     }
   else
-    return NULL;
+    {
+      return NULL;
+    }
 }
 
 /**
@@ -1844,6 +1878,27 @@ _gdk_win32_drawable_release_dc (GdkDrawable *drawable)
     }
 }
 
+cairo_surface_t *
+_gdk_windowing_create_cairo_surface (GdkDrawable *drawable,
+                                    gint width,
+                                    gint height)
+{
+  GdkDrawableImplWin32 *impl = GDK_DRAWABLE_IMPL_WIN32 (drawable);
+  RECT rect;
+
+  HDC hdc = _gdk_win32_drawable_acquire_dc (drawable);
+  if (!hdc)
+    {
+      return NULL;
+    }
+
+  GetClipBox (hdc, &rect);
+  g_print ("create_cairo_surface(): [%d %d %d %d]\n",
+          rect.left, rect.top, rect.right, rect.bottom);
+
+  return cairo_win32_surface_create (hdc);
+}
+
 static void
 gdk_win32_cairo_surface_destroy (void *data)
 {
@@ -1864,21 +1919,29 @@ gdk_win32_ref_cairo_surface (GdkDrawable *drawable)
 
   if (!impl->cairo_surface)
     {
-      HDC hdc = _gdk_win32_drawable_acquire_dc (drawable);
-      if (!hdc)
-       return NULL;
-
-      impl->cairo_surface = cairo_win32_surface_create (hdc);
+      // On Win32 cairo surface, width and height are determined from the DC
+      impl->cairo_surface = _gdk_windowing_create_cairo_surface (drawable, 0, 0);
 
       cairo_surface_set_user_data (impl->cairo_surface, &gdk_win32_cairo_key,
                                   drawable, gdk_win32_cairo_surface_destroy);
     }
   else
-    cairo_surface_reference (impl->cairo_surface);
+    {
+      cairo_surface_reference (impl->cairo_surface);
+    }
 
   return impl->cairo_surface;
 }
 
+void
+_gdk_windowing_set_cairo_surface_size (cairo_surface_t *surface,
+                                      gint width,
+                                      gint height)
+{
+  // Do nothing.  The surface size is determined by the DC
+  g_print ("*** set_cairo_surface_size()\n");
+}
+
 static gint
 gdk_win32_get_depth (GdkDrawable *drawable)
 {
@@ -1922,10 +1985,11 @@ _gdk_win32_drawable_finish (GdkDrawable *drawable)
   if (impl->cairo_surface)
     {
       cairo_surface_finish (impl->cairo_surface);
-      cairo_surface_set_user_data (impl->cairo_surface, &gdk_win32_cairo_key,
-                                  NULL, NULL);
+      cairo_surface_set_user_data (impl->cairo_surface, &gdk_win32_cairo_key, NULL, NULL);
     }
+
+  g_print ("hdc_count == %d\n", impl->hdc_count);
   
-  g_assert (impl->hdc_count == 0);
+  //g_assert (impl->hdc_count == 0);
 }
 
index d11ee6ad934dec0e341ed3d86e327b3de879ee7c..72082705af25825fcd2916609e17120dd21f204c 100644 (file)
@@ -61,7 +61,6 @@ struct _GdkDrawableImplWin32
 struct _GdkDrawableImplWin32Class 
 {
   GdkDrawableClass parent_class;
-
 };
 
 GType gdk_drawable_impl_win32_get_type (void);
index 3cdd66f0e11c0c23f893e87b240630d5cb58ff3f..67217e34e786a83fd3bab29dda009b5903236c76 100644 (file)
@@ -1,7 +1,7 @@
 /* GDK - The GIMP Drawing Kit
  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
  * Copyright (C) 1998-2002 Tor Lillqvist
- * Copyright (C) 2007-2008 Cody Russell
+ * Copyright (C) 2007-2009 Cody Russell
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -99,6 +99,7 @@ static gboolean is_modally_blocked (GdkWindow   *window);
 /* Private variable declarations
  */
 
+#if 0
 static GdkWindow *p_grab_window = NULL; /* Window that currently holds
                                         * the pointer grab
                                         */
@@ -108,6 +109,7 @@ static GdkWindow *p_grab_confine_to = NULL;
 static GdkWindow *k_grab_window = NULL; /* Window the holds the
                                         * keyboard grab
                                         */
+#endif
 
 static GList *client_filters;  /* Filters for client messages */
 
@@ -482,131 +484,43 @@ gdk_pointer_grab (GdkWindow    *window,
                  GdkCursor    *cursor,
                  guint32       time)
 {
-  HCURSOR hcursor;
-  GdkCursorPrivate *cursor_private;
-  gint return_val = GDK_GRAB_SUCCESS;
+  GdkWindow *native;
 
-  g_return_val_if_fail (window != NULL, 0);
   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
   g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
-  
-  cursor_private = (GdkCursorPrivate*) cursor;
-  
-  if (!cursor)
-    hcursor = NULL;
-  else if ((hcursor = CopyCursor (cursor_private->hcursor)) == NULL)
-    WIN32_API_FAILED ("CopyCursor");
-
-  return_val = _gdk_input_grab_pointer (window,
-                                       owner_events,
-                                       event_mask,
-                                       confine_to,
-                                       time);
-
-  if (return_val == GDK_GRAB_SUCCESS)
-    {
-      if (!GDK_WINDOW_DESTROYED (window))
-       {
-         GDK_NOTE (EVENTS, g_print ("%sgdk_pointer_grab: %p %s %p %s%s",
-                                    (debug_indent > 0 ? "\n" : ""),
-                                    GDK_WINDOW_HWND (window),
-                                    (owner_events ? "TRUE" : "FALSE"),
-                                    hcursor,
-                                    event_mask_string (event_mask),
-                                    (debug_indent == 0 ? "\n" : "")));
-
-         p_grab_mask = event_mask;
-         p_grab_owner_events = owner_events;
-         p_grab_automatic = FALSE;
-         
-         SetCapture (GDK_WINDOW_HWND (window));
-         return_val = GDK_GRAB_SUCCESS;
-       }
-      else
-       return_val = GDK_GRAB_ALREADY_GRABBED;
-    }
-  
-  if (return_val == GDK_GRAB_SUCCESS)
-    {
-      GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl);
-
-      if (p_grab_window != NULL && p_grab_window != window)
-       generate_grab_broken_event (p_grab_window, FALSE, window);
-      
-      assign_object (&p_grab_window, window);
-
-      if (p_grab_cursor != NULL)
-       {
-         if (GetCursor () == p_grab_cursor)
-           SetCursor (NULL);
-         DestroyCursor (p_grab_cursor);
-       }
 
-      p_grab_cursor = hcursor;
+  native = gdk_window_get_toplevel (window);
 
-      if (p_grab_cursor != NULL)
-       SetCursor (p_grab_cursor);
-      else if (impl->hcursor != NULL)
-       SetCursor (impl->hcursor);
-      else
-       SetCursor (LoadCursor (NULL, IDC_ARROW));
-
-      if (confine_to != NULL)
-       {
-         gint x, y, width, height;
-         RECT rect;
+  if (!GDK_IS_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (native)->impl))
+    return GDK_GRAB_SUCCESS;
 
-         gdk_window_get_origin (confine_to, &x, &y);
-         gdk_drawable_get_size (confine_to, &width, &height);
+  if (!_gdk_window_has_impl (window) &&
+      !gdk_window_is_viewable (window))
+    return GDK_GRAB_NOT_VIEWABLE;
 
-         x -= _gdk_offset_x;
-         y -= _gdk_offset_y;
-
-         rect.left = x;
-         rect.top = y;
-         rect.right = x + width;
-         rect.bottom = y + height;
-         API_CALL (ClipCursor, (&rect));
-         p_grab_confine_to = confine_to;
-       }
+  _gdk_display_add_pointer_grab (_gdk_display,
+                                window,
+                                native,
+                                owner_events,
+                                event_mask,
+                                0,
+                                time,
+                                FALSE);
 
-      /* FIXME: Generate GDK_CROSSING_GRAB events */
-    }
-  
-  return return_val;
+  return GDK_GRAB_SUCCESS;
 }
 
 void
 gdk_display_pointer_ungrab (GdkDisplay *display,
                             guint32     time)
 {
-  g_return_if_fail (display == _gdk_display);
-
-  GDK_NOTE (EVENTS, g_print ("%sgdk_display_pointer_ungrab%s",
-                            (debug_indent > 0 ? "\n" : ""),
-                            (debug_indent == 0 ? "\n" : "")));
-
-  _gdk_input_ungrab_pointer (time);
-
-  if (GetCapture () != NULL)
-    ReleaseCapture ();
+  GdkPointerGrabInfo *info;
 
-  /* FIXME: Generate GDK_CROSSING_UNGRAB events */
-
-  assign_object (&p_grab_window, NULL);
-  if (p_grab_cursor != NULL)
-    {
-      if (GetCursor () == p_grab_cursor)
-       SetCursor (NULL);
-      DestroyCursor (p_grab_cursor);
-      p_grab_cursor = NULL;
-    }
+  info = _gdk_display_get_last_pointer_grab (display);
+  if (info)
+    info->serial_end = 0;
 
-  if (p_grab_confine_to != NULL)
-    {
-      API_CALL (ClipCursor, (NULL));
-      p_grab_confine_to = NULL;
-    }
+  _gdk_display_pointer_grab_update (display, 0);
 }
 
 static GdkWindow *
@@ -632,13 +546,19 @@ find_real_window_for_grabbed_mouse_event (GdkWindow* reported_window,
       GetClientRect (hwnd, &rect);
       ScreenToClient (hwnd, &pt);
       if (!PtInRect (&rect, pt))
-       return _gdk_root;
+       {
+         g_print ("find_real_window_for_grabbed_mouse_event(), PtInRect() failed\n");
+         return _gdk_root;
+       }
 
       other_window = gdk_win32_handle_table_lookup ((GdkNativeWindow) hwnd);
     }
 
   if (other_window == NULL)
-    return _gdk_root;
+    {
+      g_print ("find_real_window_for_grabbed_mouse_event(), other_window == NULL\n");
+      return _gdk_root;
+    }
 
   return other_window;
 }
@@ -647,155 +567,47 @@ static GdkWindow*
 find_window_for_mouse_event (GdkWindow* reported_window,
                             MSG*       msg)
 {
-  if (p_grab_window == NULL || !p_grab_owner_events)
+  GdkPointerGrabInfo *info = _gdk_display_get_last_pointer_grab (_gdk_display);
+
+  if (!info || !info->window || !info->owner_events)
     return reported_window;
   else
     return find_real_window_for_grabbed_mouse_event (reported_window, msg);
 }
 
-gboolean
-gdk_display_pointer_is_grabbed (GdkDisplay *display)
-{
-  g_return_val_if_fail (display == _gdk_display, FALSE);
-  GDK_NOTE (EVENTS, g_print ("gdk_pointer_is_grabbed: %s\n",
-                            p_grab_window != NULL ? "TRUE" : "FALSE"));
-  return p_grab_window != NULL;
-}
-
-gboolean
-gdk_pointer_grab_info_libgtk_only (GdkDisplay *display,
-                                  GdkWindow **grab_window,
-                                  gboolean   *owner_events)
-{
-  g_return_val_if_fail (display == _gdk_display, FALSE);
-
-  if (p_grab_window != NULL)
-    {
-      if (grab_window)
-        *grab_window = p_grab_window;
-      if (owner_events)
-        *owner_events = p_grab_owner_events;
-
-      return TRUE;
-    }
-  else
-    return FALSE;
-}
-
 GdkGrabStatus
 gdk_keyboard_grab (GdkWindow *window,
                   gboolean   owner_events,
                   guint32    time)
 {
-  GdkWindow *real_focus_window, *grab_focus_window;
+  GdkDisplay *display;
+  GdkWindow  *toplevel;
 
-  gint return_val;
-  
   g_return_val_if_fail (window != NULL, 0);
   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
   
   GDK_NOTE (EVENTS, g_print ("gdk_keyboard_grab %p%s\n",
                             GDK_WINDOW_HWND (window), owner_events ? " OWNER_EVENTS" : ""));
 
-  if (!GDK_WINDOW_DESTROYED (window))
-    {
-      k_grab_owner_events = owner_events;
-      return_val = GDK_GRAB_SUCCESS;
-    }
-  else
-    return_val = GDK_GRAB_ALREADY_GRABBED;
-
-  if (return_val == GDK_GRAB_SUCCESS)
-    {
-      if (k_grab_window != NULL && k_grab_window != window)
-       generate_grab_broken_event (k_grab_window, TRUE, window);
+  display = gdk_drawable_get_display (window);
+  toplevel = gdk_window_get_toplevel (window);
 
-      assign_object (&k_grab_window, window);
+  _gdk_display_set_has_keyboard_grab (display,
+                                     window,
+                                     toplevel,
+                                     owner_events,
+                                     0,
+                                     time);
 
-      if (!k_grab_owner_events)
-       {
-         real_focus_window = gdk_win32_handle_table_lookup ((GdkNativeWindow) GetFocus ());
-         if (real_focus_window)
-           real_focus_window = gdk_window_get_toplevel (real_focus_window);
-         grab_focus_window = gdk_window_get_toplevel (k_grab_window);
-         if (real_focus_window != grab_focus_window)
-           {
-             /* Generate events for focus change from the window that really
-              * has focus to the grabber.
-              */
-             if (real_focus_window && !GDK_WINDOW_DESTROYED (real_focus_window)
-                 && (((GdkWindowObject *) real_focus_window)->event_mask
-                     & GDK_FOCUS_CHANGE_MASK))
-               generate_focus_event (real_focus_window, FALSE);
-
-             if (((GdkWindowObject *) grab_focus_window)->event_mask 
-                 & GDK_FOCUS_CHANGE_MASK)
-               generate_focus_event (grab_focus_window, TRUE);
-           }
-       }
-    }
-  
-  return return_val;
+  return GDK_GRAB_SUCCESS;
 }
 
 void
 gdk_display_keyboard_ungrab (GdkDisplay *display,
                              guint32 time)
 {
-  GdkWindow *real_focus_window, *grab_focus_window;
-
-  g_return_if_fail (display == _gdk_display);
-
   GDK_NOTE (EVENTS, g_print ("gdk_display_keyboard_ungrab\n"));
-
-  if (k_grab_window && !k_grab_owner_events)
-    {
-      real_focus_window = gdk_win32_handle_table_lookup ((GdkNativeWindow) GetFocus ());
-      if (real_focus_window)
-       real_focus_window = gdk_window_get_toplevel (real_focus_window);
-      if (!GDK_WINDOW_DESTROYED (k_grab_window))
-       grab_focus_window = gdk_window_get_toplevel (k_grab_window);
-      else
-       grab_focus_window = NULL;
-      if (real_focus_window != grab_focus_window)
-       {
-         /* Generate events for focus change from grabber to the window that
-          * really has focus. Important for example if a new window is created
-          * while focus is grabbed.
-          */
-         if (grab_focus_window
-             && (((GdkWindowObject *) grab_focus_window)->event_mask
-                 & GDK_FOCUS_CHANGE_MASK))
-           generate_focus_event (grab_focus_window, FALSE);
-
-         if (real_focus_window && !GDK_WINDOW_DESTROYED (real_focus_window)
-             && (((GdkWindowObject *) real_focus_window)->event_mask
-                 & GDK_FOCUS_CHANGE_MASK))
-           generate_focus_event (real_focus_window, TRUE);
-       }
-    }
-
-  assign_object (&k_grab_window, NULL);
-}
-
-gboolean
-gdk_keyboard_grab_info_libgtk_only (GdkDisplay *display,
-                                   GdkWindow **grab_window,
-                                   gboolean   *owner_events)
-{
-  g_return_val_if_fail (display == _gdk_display, FALSE);
-
-  if (k_grab_window)
-    {
-      if (grab_window)
-        *grab_window = k_grab_window;
-      if (owner_events)
-        *owner_events = k_grab_owner_events;
-
-      return TRUE;
-    }
-  else
-    return FALSE;
+  _gdk_display_unset_has_keyboard_grab (display, FALSE);
 }
 
 void 
@@ -808,7 +620,7 @@ gdk_display_add_client_message_filter (GdkDisplay   *display,
   gdk_add_client_message_filter (message_type, func, data);
 }
 
-void 
+void
 gdk_add_client_message_filter (GdkAtom       message_type,
                               GdkFilterFunc func,
                               gpointer      data)
@@ -1393,22 +1205,20 @@ synthesize_enter_or_leave_event (GdkWindow      *window,
                                 gint            y)
 {
   GdkEvent *event;
-  gint xoffset, yoffset;
   
   event = gdk_event_new (type);
   event->crossing.window = window;
   event->crossing.subwindow = NULL;
   event->crossing.time = _gdk_win32_get_next_tick (msg->time);
-  _gdk_win32_windowing_window_get_offsets (window, &xoffset, &yoffset);
-  event->crossing.x = x + xoffset;
-  event->crossing.y = y + yoffset;
+  event->crossing.x = x;
+  event->crossing.y = y;
   event->crossing.x_root = msg->pt.x + _gdk_offset_x;
   event->crossing.y_root = msg->pt.y + _gdk_offset_y;
   event->crossing.mode = mode;
   event->crossing.detail = detail;
   event->crossing.focus = TRUE; /* FIXME: Set correctly */
   event->crossing.state = 0;   /* FIXME: Set correctly */
-  
+
   append_event (event);
   
   if (type == GDK_ENTER_NOTIFY &&
@@ -1423,8 +1233,11 @@ synthesize_leave_event (GdkWindow      *window,
                        GdkNotifyType   detail)
 {
   POINT pt;
+  GdkPointerGrabInfo *grab;
+
+  grab = _gdk_display_get_last_pointer_grab (_gdk_display);
 
-  if (p_grab_window != NULL && !p_grab_owner_events && !(p_grab_mask & GDK_LEAVE_NOTIFY_MASK))
+  if (grab && grab->window != NULL && !grab->owner_events && !(grab->event_mask & GDK_LEAVE_NOTIFY_MASK))
     return;
 
   if (!(((GdkWindowObject *) window)->event_mask & GDK_LEAVE_NOTIFY_MASK))
@@ -1457,8 +1270,11 @@ synthesize_enter_event (GdkWindow      *window,
                        GdkNotifyType   detail)
 {
   POINT pt;
+  GdkPointerGrabInfo *grab;
 
-  if (p_grab_window != NULL && !p_grab_owner_events && !(p_grab_mask & GDK_ENTER_NOTIFY_MASK))
+  grab = _gdk_display_get_last_pointer_grab (_gdk_display);
+
+  if (grab && grab->window != NULL && !grab->owner_events && !(grab->event_mask & GDK_ENTER_NOTIFY_MASK))
     return;
 
   if (!(((GdkWindowObject *) window)->event_mask & GDK_ENTER_NOTIFY_MASK))
@@ -1491,6 +1307,7 @@ synthesize_enter_events (GdkWindow      *from,
   
   if (prev != from)
     synthesize_enter_events (from, prev, msg, mode, detail);
+
   synthesize_enter_event (to, msg, mode, detail);
 }
                         
@@ -1504,6 +1321,7 @@ synthesize_leave_events (GdkWindow        *from,
   GdkWindow *next = gdk_window_get_parent (from);
   
   synthesize_leave_event (from, msg, mode, detail);
+
   if (next != to)
     synthesize_leave_events (next, to, msg, mode, detail);
 }
@@ -1855,10 +1673,12 @@ handle_configure_event (MSG       *msg,
 {
   RECT client_rect;
   POINT point;
+  GdkWindowObject *window_object;
 
   GetClientRect (msg->hwnd, &client_rect);
   point.x = client_rect.left; /* always 0 */
   point.y = client_rect.top;
+
   /* top level windows need screen coords */
   if (gdk_window_get_parent (window) == _gdk_root)
     {
@@ -1867,13 +1687,17 @@ handle_configure_event (MSG       *msg,
       point.y += _gdk_offset_y;
     }
 
-  GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->width = client_rect.right - client_rect.left;
-  GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->height = client_rect.bottom - client_rect.top;
+  window_object = GDK_WINDOW_OBJECT (window);
+
+  window_object->width = client_rect.right - client_rect.left;
+  window_object->height = client_rect.bottom - client_rect.top;
   
-  ((GdkWindowObject *) window)->x = point.x;
-  ((GdkWindowObject *) window)->y = point.y;
+  window_object->x = point.x;
+  window_object->y = point.y;
+
+  _gdk_window_update_size (window);
   
-  if (((GdkWindowObject *) window)->event_mask & GDK_STRUCTURE_MASK)
+  if (window_object->event_mask & GDK_STRUCTURE_MASK)
     {
       GdkEvent *event = gdk_event_new (GDK_CONFIGURE);
 
@@ -1953,7 +1777,6 @@ handle_wm_paint (MSG        *msg,
   HDC hdc;
   PAINTSTRUCT paintstruct;
   GdkRegion *update_region;
-  gint xoffset, yoffset;
 
   if (GetUpdateRgn (msg->hwnd, hrgn, FALSE) == ERROR)
     {
@@ -2037,9 +1860,10 @@ handle_wm_paint (MSG        *msg,
 
   update_region = _gdk_win32_hrgn_to_region (hrgn);
 
-  _gdk_win32_windowing_window_get_offsets (window, &xoffset, &yoffset);
-  gdk_region_offset (update_region, xoffset, yoffset);
-  
+
+  //_gdk_win32_windowing_window_get_offsets (window, &xoffset, &yoffset);
+  //gdk_region_offset (update_region, xoffset, yoffset);
+
   _gdk_window_process_expose (window, update_region);
   gdk_region_destroy (update_region);
 
@@ -2097,7 +1921,6 @@ generate_button_event (GdkEventType type,
                       MSG         *msg)
 {
   GdkEvent *event = gdk_event_new (type);
-  gint xoffset, yoffset;
 
   event->button.window = window;
   event->button.time = _gdk_win32_get_next_tick (msg->time);
@@ -2105,9 +1928,6 @@ generate_button_event (GdkEventType type,
     translate_mouse_coords (orig_window, window, msg);
   event->button.x = current_x = (gint16) GET_X_LPARAM (msg->lParam);
   event->button.y = current_y = (gint16) GET_Y_LPARAM (msg->lParam);
-  _gdk_win32_windowing_window_get_offsets (window, &xoffset, &yoffset);
-  event->button.x += xoffset;
-  event->button.y += yoffset;
   event->button.x_root = msg->pt.x + _gdk_offset_x;
   event->button.y_root = msg->pt.y + _gdk_offset_y;
   event->button.axes = NULL;
@@ -2283,7 +2103,11 @@ gdk_event_translate (MSG  *msg,
   GdkWindowImplWin32 *impl;
 
   GdkWindow *orig_window, *new_window;
-  gint xoffset, yoffset;
+
+  GdkPointerGrabInfo *grab = NULL;
+  GdkWindow *grab_window = NULL;
+  guint grab_mask = 0;
+  gboolean grab_owner_events = FALSE;
 
   static gint update_colors_counter = 0;
   gint button;
@@ -2461,7 +2285,7 @@ gdk_event_translate (MSG  *msg,
       /* Let the system handle Alt-Tab, Alt-Space and Alt-F4 unless
        * the keyboard is grabbed.
        */
-      if (k_grab_window == NULL &&
+      if (_gdk_display->keyboard_grab.window == NULL &&
          (msg->wParam == VK_TAB ||
           msg->wParam == VK_SPACE ||
           msg->wParam == VK_F4))
@@ -2486,7 +2310,9 @@ gdk_event_translate (MSG  *msg,
        break;
 
       if (!propagate (&window, msg,
-                     k_grab_window, k_grab_owner_events, GDK_ALL_EVENTS_MASK,
+                     _gdk_display->keyboard_grab.window,
+                     _gdk_display->keyboard_grab.owner_events,
+                     GDK_ALL_EVENTS_MASK,
                      doesnt_want_key, FALSE))
        break;
 
@@ -2588,7 +2414,9 @@ gdk_event_translate (MSG  *msg,
        break;
 
       if (!propagate (&window, msg,
-                     k_grab_window, k_grab_owner_events, GDK_ALL_EVENTS_MASK,
+                     _gdk_display->keyboard_grab.window,
+                     _gdk_display->keyboard_grab.owner_events,
+                     GDK_ALL_EVENTS_MASK,
                      doesnt_want_char, FALSE))
        break;
 
@@ -2654,21 +2482,32 @@ gdk_event_translate (MSG  *msg,
 
       assign_object (&window, find_window_for_mouse_event (window, msg));
 
-      if (p_grab_window != NULL)
+      grab = _gdk_display_get_last_pointer_grab (_gdk_display);
+      if (grab)
+       {
+         grab_window = grab->window;
+         grab_mask = grab->event_mask;
+         grab_owner_events = grab->owner_events;
+       }
+
+      if (grab_window != NULL)
        {
          GdkWindow *real_window = find_real_window_for_grabbed_mouse_event (window, msg);
 
          if (real_window != current_window)
-           synthesize_crossing_events (real_window, GDK_CROSSING_NORMAL, msg);
+           {
+             synthesize_crossing_events (real_window, GDK_CROSSING_NORMAL, msg);
+           }
        }
       else
        {
          if (window != current_window)
-           synthesize_crossing_events (window, GDK_CROSSING_NORMAL, msg);
+           {
+             synthesize_crossing_events (window, GDK_CROSSING_NORMAL, msg);
+           }
        }
 
-      if (!propagate (&window, msg,
-                     p_grab_window, p_grab_owner_events, p_grab_mask,
+      if (!propagate (&window, msg, grab_window, grab_owner_events, grab_mask,
                      doesnt_want_button_press, TRUE))
        break;
 
@@ -2676,7 +2515,8 @@ gdk_event_translate (MSG  *msg,
        break;
 
       /* Emulate X11's automatic active grab */
-      if (!p_grab_window)
+      /*     XXX: Do we still want this with CSW? -- Cody */
+      if (!grab_window)
        {
          /* No explicit active grab, let's start one automatically */
          GDK_NOTE (EVENTS, g_print (" (automatic grab)"));
@@ -2687,6 +2527,8 @@ gdk_event_translate (MSG  *msg,
          p_grab_automatic = TRUE;
        }
 
+      g_print ("generate_button_event()\n");
+
       generate_button_event (GDK_BUTTON_PRESS, button,
                             window, orig_window, msg);
 
@@ -2718,7 +2560,15 @@ gdk_event_translate (MSG  *msg,
 
       assign_object (&window, find_window_for_mouse_event (window, msg));
 
-      if (p_grab_window != NULL)
+      grab = _gdk_display_get_last_pointer_grab (_gdk_display);
+      if (grab != NULL)
+       {
+         grab_window = grab->window;
+         grab_owner_events = grab->owner_events;
+         grab_mask = grab->event_mask;
+       }
+
+      if (grab_window != NULL)
        {
          GdkWindow *real_window = find_real_window_for_grabbed_mouse_event (window, msg);
 
@@ -2740,9 +2590,8 @@ gdk_event_translate (MSG  *msg,
        }
 #endif
 
-      if (!propagate (&window, msg,
-                     p_grab_window, p_grab_owner_events, p_grab_mask,
-                     doesnt_want_button_release, TRUE))
+      if (!propagate (&window, msg, grab_window, grab_owner_events,
+                     grab_mask, doesnt_want_button_release, TRUE))
        {
        }
       else if (!GDK_WINDOW_DESTROYED (window))
@@ -2751,11 +2600,9 @@ gdk_event_translate (MSG  *msg,
                                 window, orig_window, msg);
        }
 
-      if (p_grab_window != NULL &&
-         p_grab_automatic &&
-         (msg->wParam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) == 0)
+      if (grab_window != NULL && p_grab_automatic &&
+         (msg->wParam && (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) == 0)
        {
-         /* Terminate automatic grab */
          gdk_pointer_ungrab (0);
        }
 
@@ -2781,53 +2628,68 @@ gdk_event_translate (MSG  *msg,
 
       assign_object (&window, find_window_for_mouse_event (window, msg));
 
-      if (p_grab_window != NULL)
+      if (window != current_window)
+       synthesize_crossing_events (window, GDK_CROSSING_NORMAL, msg);
+
+      GdkPointerGrabInfo *grab = _gdk_display_get_last_pointer_grab (_gdk_display);
+      if (grab != NULL)
+       {
+         grab_window = grab->window;
+         grab_owner_events = grab->owner_events;
+         grab_mask = grab->event_mask;
+       }
+
+      if (grab_window != NULL)
        {
          GdkWindow *real_window = find_real_window_for_grabbed_mouse_event (window, msg);
 
          if (real_window != current_window)
            {
-             if (p_grab_owner_events)
+             if (grab_owner_events)
                {
                  synthesize_crossing_events (real_window, GDK_CROSSING_NORMAL, msg);
                }
-             else if (current_window == p_grab_window)
+             else if (current_window == grab_window)
                {
-                 synthesize_leave_event (p_grab_window, msg, GDK_CROSSING_NORMAL, GDK_NOTIFY_ANCESTOR);
+                 synthesize_leave_event (grab_window, msg, GDK_CROSSING_NORMAL, GDK_NOTIFY_ANCESTOR);
                  assign_object (&current_window, _gdk_root);
                }
-             else if (real_window == p_grab_window)
+             else if (real_window == grab_window)
                {
-                 synthesize_enter_event (p_grab_window, msg, GDK_CROSSING_NORMAL, GDK_NOTIFY_ANCESTOR);
-                 assign_object (&current_window, p_grab_window);
+                 synthesize_enter_event (grab_window, msg, GDK_CROSSING_NORMAL, GDK_NOTIFY_ANCESTOR);
+                 assign_object (&current_window, grab_window);
                }
            }
        }
       else
        {
          if (window != current_window)
-           synthesize_crossing_events (window, GDK_CROSSING_NORMAL, msg);
+           {
+             synthesize_crossing_events (window, GDK_CROSSING_NORMAL, msg);
+           }
        }
 
-      if (!propagate (&window, msg,
-                     p_grab_window, p_grab_owner_events, p_grab_mask,
+#if 0   // XXX - this seems to always block us from creating motion notify events -- Cody
+      if (!propagate (&window, msg, grab_window, grab_owner_events, grab_mask,
                      doesnt_want_button_motion, TRUE))
-       break;
+       {
+         break;
+       }
+#endif
 
       if (GDK_WINDOW_DESTROYED (window))
        break;
 
       if (window != orig_window)
-       translate_mouse_coords (orig_window, window, msg);
+       {
+         translate_mouse_coords (orig_window, window, msg);
+       }
 
       event = gdk_event_new (GDK_MOTION_NOTIFY);
       event->motion.window = window;
       event->motion.time = _gdk_win32_get_next_tick (msg->time);
       event->motion.x = current_x = (gint16) GET_X_LPARAM (msg->lParam);
       event->motion.y = current_y = (gint16) GET_Y_LPARAM (msg->lParam);
-      _gdk_win32_windowing_window_get_offsets (window, &xoffset, &yoffset);
-      event->motion.x += xoffset;
-      event->motion.y += yoffset;
       event->motion.x_root = current_root_x;
       event->motion.y_root = current_root_y;
       event->motion.axes = NULL;
@@ -2901,9 +2763,19 @@ gdk_event_translate (MSG  *msg,
          assign_object (&window, new_window);
        }
 
-      if (!propagate (&window, msg,
-                     p_grab_window, p_grab_owner_events, p_grab_mask,
-                     doesnt_want_scroll, TRUE))
+      grab = _gdk_display_get_last_pointer_grab (_gdk_display);
+      if (grab != NULL)
+       {
+         grab_window = grab->window;
+         grab_mask = grab->event_mask;
+         grab_owner_events = grab->owner_events;
+       }
+
+      if (!propagate (&window, msg, grab_window,
+                     grab_owner_events,
+                     grab_mask,
+                     doesnt_want_scroll,
+                     TRUE))
        break;
 
       if (GDK_WINDOW_DESTROYED (window))
@@ -2916,9 +2788,8 @@ gdk_event_translate (MSG  *msg,
       event->scroll.direction = (((short) HIWORD (msg->wParam)) > 0) ?
        GDK_SCROLL_UP : GDK_SCROLL_DOWN;
       event->scroll.time = _gdk_win32_get_next_tick (msg->time);
-      _gdk_win32_windowing_window_get_offsets (window, &xoffset, &yoffset);
-      event->scroll.x = (gint16) point.x + xoffset;
-      event->scroll.y = (gint16) point.y + yoffset;
+      event->scroll.x = (gint16) point.x;
+      event->scroll.y = (gint16) point.y;
       event->scroll.x_root = (gint16) GET_X_LPARAM (msg->lParam) + _gdk_offset_x;
       event->scroll.y_root = (gint16) GET_Y_LPARAM (msg->lParam) + _gdk_offset_y;
       event->scroll.state = build_pointer_event_state (msg);
@@ -3022,16 +2893,16 @@ gdk_event_translate (MSG  *msg,
        break;
 
     case WM_KILLFOCUS:
-      if (p_grab_window != NULL && !GDK_WINDOW_DESTROYED (p_grab_window))
-       generate_grab_broken_event (p_grab_window, FALSE, NULL);
-
-      if (k_grab_window != NULL && !GDK_WINDOW_DESTROYED (k_grab_window) 
-         && k_grab_window != p_grab_window)
-       generate_grab_broken_event (k_grab_window, TRUE, NULL);
+      if (_gdk_display->keyboard_grab.window != NULL &&
+         !GDK_WINDOW_DESTROYED (_gdk_display->keyboard_grab.window))
+       {
+         generate_grab_broken_event (_gdk_display->keyboard_grab.window, FALSE, NULL);
+       }
 
       /* fallthrough */
     case WM_SETFOCUS:
-      if (k_grab_window != NULL && !k_grab_owner_events)
+      if (_gdk_display->keyboard_grab.window != NULL &&
+         !_gdk_display->keyboard_grab.owner_events)
        break;
 
       if (!(((GdkWindowObject *) window)->event_mask & GDK_FOCUS_CHANGE_MASK))
@@ -3068,10 +2939,16 @@ gdk_event_translate (MSG  *msg,
       GDK_NOTE (EVENTS, g_print (" %#x %#x",
                                 LOWORD (msg->lParam), HIWORD (msg->lParam)));
 
-      if (p_grab_window == NULL && LOWORD (msg->lParam) != HTCLIENT)
+      grab = _gdk_display_get_last_pointer_grab (_gdk_display);
+      if (grab != NULL)
+       {
+         grab_window = grab->window;
+       }
+
+      if (grab_window == NULL && LOWORD (msg->lParam) != HTCLIENT)
        break;
 
-      if (p_grab_window != NULL && p_grab_cursor != NULL)
+      if (grab_window != NULL && p_grab_cursor != NULL)
        hcursor = p_grab_cursor;
       else if (!GDK_WINDOW_DESTROYED (window))
        hcursor = GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->hcursor;
@@ -3121,15 +2998,15 @@ gdk_event_translate (MSG  *msg,
              SetForegroundWindow (GDK_WINDOW_HWND (impl->transient_owner));
            }
 
-         if (p_grab_window == window)
+         grab = _gdk_display_get_last_pointer_grab (_gdk_display);
+         if (grab != NULL)
            {
-             gdk_pointer_ungrab (msg->time);
+             if (grab->window == window)
+               gdk_pointer_ungrab (msg->time);
            }
 
-         if (k_grab_window == window)
-           {
-             gdk_keyboard_ungrab (msg->time);
-           }
+         if (_gdk_display->keyboard_grab.window == window)
+           gdk_keyboard_ungrab (msg->time);
        }
 
       return_val = TRUE;
@@ -3159,11 +3036,13 @@ gdk_event_translate (MSG  *msg,
       if (msg->wParam == SIZE_MINIMIZED)
        {
          /* Don't generate any GDK event. This is *not* an UNMAP. */
-
-         if (p_grab_window == window)
-           gdk_pointer_ungrab (msg->time);
-
-         if (k_grab_window == window)
+         grab = _gdk_display_get_last_pointer_grab (_gdk_display);
+         if (grab != NULL)
+           {
+             if (grab->window == window)
+               gdk_pointer_ungrab (msg->time);
+           }
+         if (_gdk_display->keyboard_grab.window == window)
            gdk_keyboard_ungrab (msg->time);
 
          gdk_synthesize_window_state (window,
@@ -3604,10 +3483,14 @@ gdk_event_translate (MSG  *msg,
       if (window == current_window)
        assign_object (&current_window, _gdk_root);
 
-      if (p_grab_window == window)
-       gdk_pointer_ungrab (msg->time);
+      grab = _gdk_display_get_last_pointer_grab (_gdk_display);
+      if (grab != NULL)
+       {
+         if (grab->window == window)
+           gdk_pointer_ungrab (msg->time);
+       }
 
-      if (k_grab_window == window)
+      if (_gdk_display->keyboard_grab.window == window)
        gdk_keyboard_ungrab (msg->time);
 
       if ((window != NULL) && (msg->hwnd != GetDesktopWindow ()))
index c255f4b1583b7cd808c31d97cde5203bf419da9f..d1e2909b7274793689e2a8686cf53a15c98aba1a 100644 (file)
@@ -572,7 +572,8 @@ gdk_win32_gc_set_dashes (GdkGC *gc,
 
 void
 _gdk_windowing_gc_set_clip_region (GdkGC           *gc,
-                                   const GdkRegion *region)
+                                   const GdkRegion *region,
+                                  gboolean         reset_origin)
 {
   GdkGCWin32 *win32_gc = GDK_GC_WIN32 (gc);
 
@@ -596,9 +597,12 @@ _gdk_windowing_gc_set_clip_region (GdkGC           *gc,
       win32_gc->values_mask &= ~GDK_GC_CLIP_MASK;
     }
 
-  gc->clip_x_origin = 0;
-  gc->clip_y_origin = 0;
-  
+  if (reset_origin)
+  {
+         gc->clip_x_origin = 0;
+         gc->clip_y_origin = 0;
+  }
+
   win32_gc->values_mask &= ~(GDK_GC_CLIP_X_ORIGIN | GDK_GC_CLIP_Y_ORIGIN);
 }
 
index 61dbf762876a52a32580e9d43492d40cc5a91692..833fc5b625cc6d77cda77209012e26f656c2d005 100644 (file)
 #include "gdk.h"               /* For gdk_rectangle_intersect */
 #include "gdkregion.h"
 #include "gdkregion-generic.h"
+#include "gdkinternals.h"
 #include "gdkprivate-win32.h"
 
 #define SIZE_LIMIT 32767
 
 typedef struct _GdkWindowParentPos GdkWindowParentPos;
 
-struct _GdkWindowParentPos
-{
-  gint x;
-  gint y;
-  gint win32_x;
-  gint win32_y;
-  GdkRectangle clip_rect;
-};
-
-static void gdk_window_compute_position   (GdkWindowImplWin32     *window,
-                                          GdkWindowParentPos     *parent_pos,
-                                          GdkWin32PositionInfo   *info);
-static void gdk_window_compute_parent_pos (GdkWindowImplWin32     *window,
-                                          GdkWindowParentPos     *parent_pos);
-
-static void gdk_window_postmove           (GdkWindow          *window,
-                                          GdkWindowParentPos *parent_pos,
-                                          gboolean           anti_scroll);
-static void gdk_window_tmp_unset_bg       (GdkWindow          *window);
-static void gdk_window_tmp_reset_bg       (GdkWindow          *window);
-static GdkRegion *gdk_window_clip_changed (GdkWindow          *window,
-                                          GdkRectangle       *old_clip,
-                                          GdkRectangle       *new_clip);
-static void gdk_window_post_scroll        (GdkWindow          *window,
-                                          GdkRegion          *new_clip_region);
-
-void
-_gdk_win32_windowing_window_get_offsets (GdkWindow *window,
-                                        gint      *x_offset,
-                                        gint      *y_offset)
-{
-  GdkWindowImplWin32 *impl =
-    GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
-
-  *x_offset = impl->position_info.x_offset;
-  *y_offset = impl->position_info.y_offset;
-}
-
-void
-_gdk_window_init_position (GdkWindow *window)
-{
-  GdkWindowParentPos parent_pos;
-  GdkWindowImplWin32 *impl;
-
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
-  
-  gdk_window_compute_parent_pos (impl, &parent_pos);
-  gdk_window_compute_position (impl, &parent_pos, &impl->position_info);
-}
-
-void
-_gdk_win32_window_scroll (GdkWindow *window,
-                         gint       dx,
-                         gint       dy)
-{
-  GdkRegion *invalidate_region;
-  GdkWindowImplWin32 *impl;
-  GdkWindowObject *obj;
-  GList *tmp_list;
-  GdkWindowParentPos parent_pos;
-  HRGN native_invalidate_region;
-
-  GDK_NOTE (EVENTS, g_print ("gdk_window_scroll: %p %d,%d\n",
-                            GDK_WINDOW_HWND (window), dx, dy));
-
-  obj = GDK_WINDOW_OBJECT (window);
-  impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);  
-
-  /* Move the current invalid region */
-  if (obj->update_area)
-    gdk_region_offset (obj->update_area, dx, dy);
-  
-  gdk_window_compute_parent_pos (impl, &parent_pos);
-
-  parent_pos.x += obj->x;
-  parent_pos.y += obj->y;
-  parent_pos.win32_x += impl->position_info.x;
-  parent_pos.win32_y += impl->position_info.y;
-  parent_pos.clip_rect = impl->position_info.clip_rect;
-
-  gdk_window_tmp_unset_bg (window);
-
-  native_invalidate_region = CreateRectRgn (0, 0, 0, 0);
-  if (native_invalidate_region == NULL)
-    WIN32_API_FAILED ("CreateRectRgn");
-
-  API_CALL (ScrollWindowEx, (GDK_WINDOW_HWND (window),
-                            dx, dy, NULL, NULL,
-                            native_invalidate_region, NULL, SW_SCROLLCHILDREN));
-
-  if (impl->position_info.no_bg)
-    gdk_window_tmp_reset_bg (window);
-  
-  tmp_list = obj->children;
-  while (tmp_list)
-    {
-      GDK_WINDOW_OBJECT(tmp_list->data)->x += dx;
-      GDK_WINDOW_OBJECT(tmp_list->data)->y += dy;
-      gdk_window_postmove (tmp_list->data, &parent_pos, FALSE);
-      tmp_list = tmp_list->next;
-    }
-
-  if (native_invalidate_region != NULL)
-    {
-      invalidate_region = _gdk_win32_hrgn_to_region (native_invalidate_region);
-      gdk_region_offset (invalidate_region, impl->position_info.x_offset,
-                         impl->position_info.y_offset);
-      gdk_window_invalidate_region (window, invalidate_region, TRUE);
-      gdk_region_destroy (invalidate_region);
-      GDI_CALL (DeleteObject, (native_invalidate_region));
-    }
-}
-
-void
-_gdk_win32_window_move_region (GdkWindow       *window,
-                              const GdkRegion *region,
-                              gint             dx,
-                              gint             dy)
-{
-  GdkRegion *invalidate_region;
-  GdkWindowImplWin32 *impl;
-  GdkWindowObject *obj;
-  GdkRectangle src_rect, dest_rect;
-  HRGN hrgn;
-  RECT clipRect, destRect;
-
-  obj = GDK_WINDOW_OBJECT (window);
-  impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);  
-
-  /* Move the current invalid region */
-  if (obj->update_area)
-    gdk_region_offset (obj->update_area, dx, dy);
-  
-  /* impl->position_info.clip_rect isn't meaningful for toplevels */
-  if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
-    src_rect = impl->position_info.clip_rect;
-  else
-    {
-      src_rect.x = 0;
-      src_rect.y = 0;
-      src_rect.width = impl->width;
-      src_rect.height = impl->height;
-    }
-  
-  invalidate_region = gdk_region_rectangle (&src_rect);
-
-  dest_rect = src_rect;
-  dest_rect.x += dx;
-  dest_rect.y += dy;
-  gdk_rectangle_intersect (&dest_rect, &src_rect, &dest_rect);
-
-  if (dest_rect.width > 0 && dest_rect.height > 0)
-    {
-      GdkRegion *tmp_region;
-
-      tmp_region = gdk_region_rectangle (&dest_rect);
-      gdk_region_subtract (invalidate_region, tmp_region);
-      gdk_region_destroy (tmp_region);
-    }
-  
-  /* no guffaw scroll on win32 */
-  hrgn = _gdk_win32_gdkregion_to_hrgn(invalidate_region, 0, 0);
-  gdk_region_destroy (invalidate_region);
-  destRect.left = dest_rect.y;
-  destRect.top = dest_rect.x;
-  destRect.right = dest_rect.x + dest_rect.width;
-  destRect.bottom = dest_rect.y + dest_rect.height;
-  clipRect.left = src_rect.y;
-  clipRect.top = src_rect.x;
-  clipRect.right = src_rect.x + src_rect.width;
-  clipRect.bottom = src_rect.y + src_rect.height;
-
-  g_print ("ScrollWindowEx(%d, %d, ...) - if you see this work, remove trace;)\n", dx, dy);
-  API_CALL(ScrollWindowEx, (GDK_WINDOW_HWND (window),
-                       dx, dy, /* in: scroll offsets */
-                       NULL, /* in: scroll rect, NULL == entire client area */
-                       &clipRect, /* in: restrict to */
-                       hrgn, /* in: update region */
-                       NULL, /* out: update rect */
-                       SW_INVALIDATE));
-  API_CALL(DeleteObject, (hrgn));
-}
+static void tmp_unset_bg (GdkWindow *window);
+static void tmp_reset_bg (GdkWindow *window);
 
 void
 _gdk_window_move_resize_child (GdkWindow *window,
@@ -242,443 +61,189 @@ _gdk_window_move_resize_child (GdkWindow *window,
 {
   GdkWindowImplWin32 *impl;
   GdkWindowObject *obj;
-  GdkWin32PositionInfo new_info;
-  GdkWindowParentPos parent_pos;
-  GList *tmp_list;
-  gint d_xoffset, d_yoffset;
-  gint dx, dy;
   gboolean is_move;
   gboolean is_resize;
-  GdkRegion *new_clip_region;
-  
+
   g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window));
 
   obj = GDK_WINDOW_OBJECT (window);
   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
+
+  is_move = (x - obj->x != 0) && (y - obj->y != 0);
+  is_resize = obj->width != width && obj->height != height;
   
   GDK_NOTE (MISC, g_print ("_gdk_window_move_resize_child: %s@%+d%+d %dx%d@%+d%+d\n",
                           _gdk_win32_drawable_description (window),
-                          obj->x, obj->y,
-                          width, height, x, y));
+                          obj->x, obj->y, width, height, x, y));
 
-  dx = x - obj->x;
-  dy = y - obj->y;
+  if (width > 65535 || height > 65535)
+  {
+    g_warning ("Native children wider or taller than 65535 pixels are not supported.");
 
-  is_move = dx != 0 || dy != 0;
-  is_resize = impl->width != width || impl->height != height;
-
-  if (!is_move && !is_resize)
-    {
-      GDK_NOTE (MISC, g_print ("... neither move or resize\n"));
-      return;
-    }
-  
-  GDK_NOTE (MISC, g_print ("... %s%s\n",
-                          is_move ? "is_move " : "",
-                          is_resize ? "is_resize" : ""));
+    if (width > 65535)
+      width = 65535;
+    if (height > 65535)
+      height = 65535;
+  }
 
   obj->x = x;
   obj->y = y;
-  impl->width = width;
-  impl->height = height;
-
-  gdk_window_compute_parent_pos (impl, &parent_pos);
-  gdk_window_compute_position (impl, &parent_pos, &new_info);
+  obj->width = width;
+  obj->height = height;
 
-  new_clip_region =
-    gdk_window_clip_changed (window, &impl->position_info.clip_rect, &new_info.clip_rect);
-
-  parent_pos.x += obj->x;
-  parent_pos.y += obj->y;
-  parent_pos.win32_x += new_info.x;
-  parent_pos.win32_y += new_info.y;
-  parent_pos.clip_rect = new_info.clip_rect;
-
-  d_xoffset = new_info.x_offset - impl->position_info.x_offset;
-  d_yoffset = new_info.y_offset - impl->position_info.y_offset;
+  _gdk_win32_window_tmp_unset_parent_bg (window);
+  _gdk_win32_window_tmp_unset_bg (window, TRUE);
   
-  if (d_xoffset != 0 || d_yoffset != 0)
-    {
-      GDK_NOTE (MISC, g_print ("... d_offset=%+d%+d\n", d_xoffset, d_yoffset));
-
-      if (!ScrollWindowEx (GDK_WINDOW_HWND (window),
-                          -d_xoffset, -d_yoffset, /* in: scroll offsets */
-                          NULL, /* in: scroll rect, NULL == entire client area */
-                          NULL, /* in: restrict to */
-                          NULL, /* in: update region */
-                          NULL, /* out: update rect */
-                          SW_SCROLLCHILDREN))
-       WIN32_API_FAILED ("ScrollWindowEx");
-
-      if (dx != d_xoffset || dy != d_yoffset || is_resize)
-       {
-         GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,%d,%d,%d,%d,"
-                                  "NOACTIVATE|NOZORDER%s%s)\n",
-                                  GDK_WINDOW_HWND (window),
-                                  new_info.x, new_info.y, 
-                                  new_info.width, new_info.height,
-                                  (is_move ? "" : "|NOMOVE"),
-                                  (is_resize ? "" : "|NOSIZE")));
-
-         API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
-                                  new_info.x, new_info.y, 
-                                  new_info.width, new_info.height,
-                                  SWP_NOACTIVATE | SWP_NOZORDER | 
-                                  (is_move ? 0 : SWP_NOMOVE) |
-                                  (is_resize ? 0 : SWP_NOSIZE)));
-       }
-
-      if (impl->position_info.no_bg)
-       gdk_window_tmp_reset_bg (window);
-
-      if (!impl->position_info.mapped && new_info.mapped && GDK_WINDOW_IS_MAPPED (obj))
-       {
-         GDK_NOTE (MISC, g_print ("... ShowWindow(%p, SW_SHOWNA)\n",
-                                  GDK_WINDOW_HWND (window)));
-         ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNA);
-       }
-
-      impl->position_info = new_info;
-      
-      tmp_list = obj->children;
-      while (tmp_list)
-       {
-         gdk_window_postmove (tmp_list->data, &parent_pos, FALSE);
-         tmp_list = tmp_list->next;
-       }
-    }
-  else
-    {
-      if (impl->position_info.mapped && !new_info.mapped)
-       {
-         GDK_NOTE (MISC, g_print ("... ShowWindow(%p, SW_HIDE)\n",
-                                  GDK_WINDOW_HWND (window)));
-         ShowWindow (GDK_WINDOW_HWND (window), SW_HIDE);
-       }
-      
-      GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,%d,%d,%d,%d,"
-                              "NOACTIVATE|NOZORDER%s%s)\n",
-                              GDK_WINDOW_HWND (window),
-                              new_info.x, new_info.y, 
-                              new_info.width, new_info.height,
-                              (is_move ? "" : "|NOMOVE"),
-                              (is_resize ? "" : "|NOSIZE")));
-
-      API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
-                              new_info.x, new_info.y, 
-                              new_info.width, new_info.height,
-                              SWP_NOACTIVATE | SWP_NOZORDER | 
-                              (is_move ? 0 : SWP_NOMOVE) |
-                              (is_resize ? 0 : SWP_NOSIZE)));
-
-      tmp_list = obj->children;
-      while (tmp_list)
-       {
-         gdk_window_postmove (tmp_list->data, &parent_pos, FALSE);
-         tmp_list = tmp_list->next;
-       }
-
-      if (impl->position_info.no_bg)
-       gdk_window_tmp_reset_bg (window);
-
-      if (!impl->position_info.mapped && new_info.mapped && GDK_WINDOW_IS_MAPPED (obj))
-       {
-         GDK_NOTE (MISC, g_print ("... ShowWindow(%p, SW_SHOWNA)\n",
-                                  GDK_WINDOW_HWND (window)));
-         ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNA);
-       }
-
-      impl->position_info = new_info;
-    }
-  if (new_clip_region)
-    gdk_window_post_scroll (window, new_clip_region);
+  GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,%d,%d,%d,%d,"
+                          "NOACTIVATE|NOZORDER%s%s)\n",
+                          GDK_WINDOW_HWND (window),
+                          obj->x + obj->parent->abs_x, obj->y + obj->parent->abs_y, 
+                          width, height,
+                          (is_move ? "" : "|NOMOVE"),
+                          (is_resize ? "" : "|NOSIZE")));
+
+  API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
+                          obj->x + obj->parent->abs_x, obj->y + obj->parent->abs_y, 
+                          width, height,
+                          SWP_NOACTIVATE | SWP_NOZORDER | 
+                          (is_move ? 0 : SWP_NOMOVE) |
+                          (is_resize ? 0 : SWP_NOSIZE)));
+
+  //_gdk_win32_window_tmp_reset_parent_bg (window);
+  _gdk_win32_window_tmp_reset_bg (window, TRUE);
 }
 
-static void
-gdk_window_compute_position (GdkWindowImplWin32   *window,
-                            GdkWindowParentPos   *parent_pos,
-                            GdkWin32PositionInfo *info)
+void
+_gdk_window_process_expose (GdkWindow *window,
+                           GdkRegion *invalidate_region)
 {
-  GdkWindowObject *wrapper;
-  int parent_x_offset;
-  int parent_y_offset;
-
-  g_return_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (window));
-
-  wrapper = GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_WIN32 (window)->wrapper);
-  
-  info->big = FALSE;
+  GdkWindowImplWin32 *impl;
+  //GdkRegion *clip_region;
+  impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
   
-  if (window->width <= SIZE_LIMIT)
-    {
-      info->width = window->width;
-      info->x = parent_pos->x + wrapper->x - parent_pos->win32_x;
-    }
-  else
-    {
-      info->big = TRUE;
-      info->width = SIZE_LIMIT;
-      if (parent_pos->x + wrapper->x < -(SIZE_LIMIT/2))
-       {
-         if (parent_pos->x + wrapper->x + window->width < (SIZE_LIMIT/2))
-           info->x = parent_pos->x + wrapper->x + window->width - info->width - parent_pos->win32_x;
-         else
-           info->x = -(SIZE_LIMIT/2) - parent_pos->win32_x;
-       }
-      else
-       info->x = parent_pos->x + wrapper->x - parent_pos->win32_x;
-    }
+  GDK_NOTE (EVENTS, g_print ("_gdk_window_process_expose: %p %s\n",
+                            GDK_WINDOW_HWND (window),
+                            _gdk_win32_gdkregion_to_string (invalidate_region)));
 
-  if (window->height <= SIZE_LIMIT)
-    {
-      info->height = window->height;
-      info->y = parent_pos->y + wrapper->y - parent_pos->win32_y;
-    }
+  if (!gdk_region_empty (invalidate_region))
+    _gdk_window_invalidate_for_expose (window, invalidate_region);
   else
-    {
-      info->big = TRUE;
-      info->height = SIZE_LIMIT;
-      if (parent_pos->y + wrapper->y < -(SIZE_LIMIT/2))
-       {
-         if (parent_pos->y + wrapper->y + window->height < (SIZE_LIMIT/2))
-           info->y = parent_pos->y + wrapper->y + window->height - info->height - parent_pos->win32_y;
-         else
-           info->y = -(SIZE_LIMIT/2) - parent_pos->win32_y;
-       }
-      else
-       info->y = parent_pos->y + wrapper->y - parent_pos->win32_y;
-    }
-
-  parent_x_offset = parent_pos->win32_x - parent_pos->x;
-  parent_y_offset = parent_pos->win32_y - parent_pos->y;
+    g_print ("process_expose(), empty region\n");
   
-  info->x_offset = parent_x_offset + info->x - wrapper->x;
-  info->y_offset = parent_y_offset + info->y - wrapper->y;
-
-  /* We don't considering the clipping of toplevel windows and their immediate children
-   * by their parents, and simply always map those windows.
-   */
-  if (parent_pos->clip_rect.width == G_MAXINT)
-    info->mapped = TRUE;
-  /* Check if the window would wrap around into the visible space in either direction */
-  else if (info->x + parent_x_offset < parent_pos->clip_rect.x + parent_pos->clip_rect.width - 65536 ||
-      info->x + info->width + parent_x_offset > parent_pos->clip_rect.x + 65536 ||
-      info->y + parent_y_offset < parent_pos->clip_rect.y + parent_pos->clip_rect.height - 65536 ||
-      info->y + info->height + parent_y_offset  > parent_pos->clip_rect.y + 65536)
-    info->mapped = FALSE;
-  else
-    info->mapped = TRUE;
-
-  info->no_bg = FALSE;
-
-  if (GDK_WINDOW_TYPE (wrapper) == GDK_WINDOW_CHILD)
-    {
-      info->clip_rect.x = wrapper->x;
-      info->clip_rect.y = wrapper->y;
-      info->clip_rect.width = window->width;
-      info->clip_rect.height = window->height;
-      
-      gdk_rectangle_intersect (&info->clip_rect, &parent_pos->clip_rect, &info->clip_rect);
-
-      info->clip_rect.x -= wrapper->x;
-      info->clip_rect.y -= wrapper->y;
-    }
-  else
-    {
-      info->clip_rect.x = 0;
-      info->clip_rect.y = 0;
-      info->clip_rect.width = G_MAXINT;
-      info->clip_rect.height = G_MAXINT;
-    }
+  //gdk_region_destroy (invalidate_region);
 }
 
-static void
-gdk_window_compute_parent_pos (GdkWindowImplWin32 *window,
-                              GdkWindowParentPos *parent_pos)
+void
+_gdk_win32_window_tmp_unset_bg (GdkWindow *window,
+                               gboolean recurse)
 {
-  GdkWindowObject *wrapper;
-  GdkWindowObject *parent;
-  GdkRectangle tmp_clip;
-  
-  int clip_xoffset = 0;
-  int clip_yoffset = 0;
+  GdkWindowObject *private;
 
-  g_return_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (window));
+  g_return_if_fail (GDK_IS_WINDOW (window));
 
-  wrapper = GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_WIN32 (window)->wrapper);
-  
-  parent_pos->x = 0;
-  parent_pos->y = 0;
-  parent_pos->win32_x = 0;
-  parent_pos->win32_y = 0;
-
-  /* We take a simple approach here and simply consider toplevel
-   * windows not to clip their children on the right/bottom, since the
-   * size of toplevel windows is not directly under our
-   * control. Clipping only really matters when scrolling and
-   * generally we aren't going to be moving the immediate child of a
-   * toplevel beyond the bounds of that toplevel.
-   *
-   * We could go ahead and recompute the clips of toplevel windows and
-   * their descendents when we receive size notification, but it would
-   * probably not be an improvement in most cases.
-   */
-  parent_pos->clip_rect.x = 0;
-  parent_pos->clip_rect.y = 0;
-  parent_pos->clip_rect.width = G_MAXINT;
-  parent_pos->clip_rect.height = G_MAXINT;
+  private = (GdkWindowObject *)window;
 
-  parent = (GdkWindowObject *)wrapper->parent;
-  while (parent && parent->window_type == GDK_WINDOW_CHILD)
-    {
-      GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (parent->impl);
-      
-      tmp_clip.x = - clip_xoffset;
-      tmp_clip.y = - clip_yoffset;
-      tmp_clip.width = impl->width;
-      tmp_clip.height = impl->height;
+  if (private->input_only || private->destroyed ||
+      (private->window_type != GDK_WINDOW_ROOT &&
+       !GDK_WINDOW_IS_MAPPED (window)))
+    return;
 
-      gdk_rectangle_intersect (&parent_pos->clip_rect, &tmp_clip, &parent_pos->clip_rect);
+  if (_gdk_window_has_impl (window) &&
+      GDK_WINDOW_IS_WIN32 (window) &&
+      private->window_type != GDK_WINDOW_ROOT &&
+      private->window_type != GDK_WINDOW_FOREIGN)
+    tmp_unset_bg (window);
 
-      parent_pos->x += parent->x;
-      parent_pos->y += parent->y;
-      parent_pos->win32_x += impl->position_info.x;
-      parent_pos->win32_y += impl->position_info.y;
-
-      clip_xoffset += parent->x;
-      clip_yoffset += parent->y;
+  if (recurse)
+    {
+      GList *l;
 
-      parent = (GdkWindowObject *)parent->parent;
+      for (l = private->children; l != NULL; l = l->next)
+       _gdk_win32_window_tmp_unset_bg (l->data, TRUE);
     }
 }
 
 static void
-gdk_window_postmove (GdkWindow          *window,
-                    GdkWindowParentPos *parent_pos,
-                    gboolean            anti_scroll)
+tmp_unset_bg (GdkWindow *window)
 {
   GdkWindowImplWin32 *impl;
   GdkWindowObject *obj;
-  GdkWin32PositionInfo new_info;
-  GList *tmp_list;
-  gint d_xoffset, d_yoffset;
-  GdkWindowParentPos this_pos;
-  GdkRegion *new_clip_region;
 
   obj = (GdkWindowObject *) window;
   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
-  
-  gdk_window_compute_position (impl, parent_pos, &new_info);
-
-  new_clip_region =
-    gdk_window_clip_changed (window, &impl->position_info.clip_rect, &new_info.clip_rect);
 
-  this_pos.x = parent_pos->x + obj->x;
-  this_pos.y = parent_pos->y + obj->y;
-  this_pos.win32_x = parent_pos->win32_x + new_info.x;
-  this_pos.win32_y = parent_pos->win32_y + new_info.y;
-  this_pos.clip_rect = new_info.clip_rect;
+  impl->no_bg = TRUE;
 
-  if (impl->position_info.mapped && !new_info.mapped)
-    ShowWindow (GDK_WINDOW_HWND (window), SW_HIDE);
-
-  d_xoffset = new_info.x_offset - impl->position_info.x_offset;
-  d_yoffset = new_info.y_offset - impl->position_info.y_offset;
-  
-  if (anti_scroll || (anti_scroll = d_xoffset != 0 || d_yoffset != 0))
+  /*
+   * The X version sets background = None to avoid updateing for a moment.
+   * Not sure if this could really emulate it.
+   */
+  if (obj->bg_pixmap != GDK_NO_BG)
     {
-      GDK_NOTE (MISC, g_print ("gdk_window_postmove: %s@%+d%+d\n"
-                              "... SetWindowPos(%p,NULL,%d,%d,0,0,"
-                              "NOREDRAW|NOZORDER|NOACTIVATE|NOSIZE)\n",
-                              _gdk_win32_drawable_description (window),
-                              obj->x, obj->y,
-                              GDK_WINDOW_HWND (window),
-                              new_info.x, new_info.y));
-
-      API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
-                              new_info.x, new_info.y, 
-                              0, 0,
-                              SWP_NOREDRAW | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE));
-    }
-
-  if (!impl->position_info.mapped && new_info.mapped && GDK_WINDOW_IS_MAPPED (obj))
-    ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNA);
-
-  if (impl->position_info.no_bg)
-    gdk_window_tmp_reset_bg (window);
-
-  impl->position_info = new_info;
+      ///* handled in WM_ERASEBKGRND proceesing */;
 
-  if (new_clip_region)
-    gdk_window_post_scroll (window, new_clip_region);
-
-  tmp_list = obj->children;
-  while (tmp_list)
-    {
-      gdk_window_postmove (tmp_list->data, &this_pos, anti_scroll);
-      tmp_list = tmp_list->next;
+      //HDC hdc = GetDC (GDK_WINDOW_HWND (window));
+      //erase_background (window, hdc);
     }
 }
 
-gboolean
-_gdk_windowing_window_queue_antiexpose (GdkWindow *window,
-                                       GdkRegion *area)
+static void
+tmp_reset_bg (GdkWindow *window)
 {
-  HRGN hrgn = _gdk_win32_gdkregion_to_hrgn (area, 0, 0);
-
-  GDK_NOTE (EVENTS, g_print ("_gdk_windowing_window_queue_antiexpose: ValidateRgn %p %s\n",
-                            GDK_WINDOW_HWND (window),
-                            _gdk_win32_gdkregion_to_string (area)));
-
-  ValidateRgn (GDK_WINDOW_HWND (window), hrgn);
+  GdkWindowObject *obj;
+  GdkWindowImplWin32 *impl;
 
-  DeleteObject (hrgn);
+  obj = GDK_WINDOW_OBJECT (window);
+  impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
 
-  return FALSE;
+  impl->no_bg = FALSE;
 }
 
 void
-_gdk_window_process_expose (GdkWindow *window,
-                           GdkRegion *invalidate_region)
+_gdk_win32_window_tmp_unset_parent_bg (GdkWindow *window)
 {
-  GdkWindowImplWin32 *impl;
-  GdkRegion *clip_region;
-  impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
-  
-  GDK_NOTE (EVENTS, g_print ("_gdk_window_process_expose: %p %s\n",
-                            GDK_WINDOW_HWND (window),
-                            _gdk_win32_gdkregion_to_string (invalidate_region)));
-  clip_region = gdk_region_rectangle (&impl->position_info.clip_rect);
-  gdk_region_intersect (invalidate_region, clip_region);
+  GdkWindowObject *private = (GdkWindowObject*)window;
 
-  if (!gdk_region_empty (invalidate_region))
-    gdk_window_invalidate_region (window, invalidate_region, FALSE);
-  
-  gdk_region_destroy (clip_region);
+  if (GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
+    return;
+
+  window = _gdk_window_get_impl_window ((GdkWindow*)private->parent);
+  _gdk_win32_window_tmp_unset_bg (window, FALSE);
 }
 
-static void
-gdk_window_tmp_unset_bg (GdkWindow *window)
+void
+_gdk_win32_window_tmp_reset_bg (GdkWindow *window,
+                               gboolean   recurse)
 {
-  GdkWindowImplWin32 *impl;
-  GdkWindowObject *obj;
+  GdkWindowObject *private;
 
-  obj = (GdkWindowObject *) window;
-  impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
+  g_return_if_fail (GDK_IS_WINDOW (window));
 
-  impl->position_info.no_bg = TRUE;
+  if (private->input_only || private->destroyed ||
+      (private->window_type != GDK_WINDOW_ROOT && !GDK_WINDOW_IS_MAPPED (window)))
+    return;
 
-  /*
-   * The X version sets background = None to avoid updateing for a moment.
-   * Not sure if this could really emulate it.
-   */
-  if (obj->bg_pixmap != GDK_NO_BG)
-    /* handled in WM_ERASEBKGRND proceesing */;
+  if (_gdk_window_has_impl (window) &&
+      GDK_WINDOW_IS_WIN32 (window) &&
+      private->window_type != GDK_WINDOW_ROOT &&
+      private->window_type != GDK_WINDOW_FOREIGN)
+    {
+      tmp_reset_bg (window);
+    }
+
+  if (recurse)
+    {
+      GList *l;
+
+      for (l = private->children; l != NULL; l = l->next)
+       _gdk_win32_window_tmp_reset_bg (l->data, TRUE);
+    }
 }
 
-static void
-gdk_window_tmp_reset_bg (GdkWindow *window)
+/*
+void
+_gdk_win32_window_tmp_reset_bg (GdkWindow *window)
 {
   GdkWindowImplWin32 *impl;
   GdkWindowObject *obj;
@@ -686,9 +251,11 @@ gdk_window_tmp_reset_bg (GdkWindow *window)
   obj = (GdkWindowObject *) window;
   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
 
-  impl->position_info.no_bg = FALSE;
+  impl->no_bg = FALSE;
 }
+*/
 
+#if 0
 static GdkRegion *
 gdk_window_clip_changed (GdkWindow    *window,
                         GdkRectangle *old_clip,
@@ -723,11 +290,14 @@ gdk_window_clip_changed (GdkWindow    *window,
       gdk_region_destroy (new_clip_region);
       new_clip_region = NULL;
     }
+
   gdk_region_destroy (old_clip_region);
 
   return new_clip_region;
 }
+#endif
 
+#if 0
 static void
 gdk_window_post_scroll (GdkWindow    *window,
                        GdkRegion    *new_clip_region)
@@ -737,5 +307,8 @@ gdk_window_post_scroll (GdkWindow    *window,
                     _gdk_win32_gdkregion_to_string (new_clip_region)));
 
   gdk_window_invalidate_region (window, new_clip_region, FALSE);
+  g_print ("gdk_window_post_scroll\n");
   gdk_region_destroy (new_clip_region);
 }
+
+#endif
index d844a5832f0767fce5eb3b34efefca4b869464fc..1510c24b4c7f3fb9d7f117dc3a21e8c8f34167ba 100644 (file)
@@ -647,7 +647,8 @@ gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
                                 gdouble          *x_out,
                                 gdouble          *y_out)
 {
-  GdkWindowImplWin32 *impl, *root_impl;
+  GdkWindowImplWin32 *root_impl;
+  GdkWindowObject *window_object;
 
   int i;
   int x_axis = 0;
@@ -656,33 +657,31 @@ gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
   double device_width, device_height;
   double x_offset, y_offset, x_scale, y_scale;
 
-  impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (input_window->window)->impl);
+  window_object = GDK_WINDOW_OBJECT (input_window);
 
   for (i=0; i<gdkdev->info.num_axes; i++)
     {
       switch (gdkdev->info.axes[i].use)
-       {
-       case GDK_AXIS_X:
-         x_axis = i;
-         break;
-       case GDK_AXIS_Y:
-         y_axis = i;
-         break;
-       default:
-         break;
-       }
+               {
+               case GDK_AXIS_X:
+                 x_axis = i;
+                 break;
+               case GDK_AXIS_Y:
+                 y_axis = i;
+                 break;
+               default:
+                 break;
+               }
     }
   
-  device_width = gdkdev->axes[x_axis].max_value - 
-                  gdkdev->axes[x_axis].min_value;
-  device_height = gdkdev->axes[y_axis].max_value - 
-                    gdkdev->axes[y_axis].min_value;
+  device_width = gdkdev->axes[x_axis].max_value - gdkdev->axes[x_axis].min_value;
+  device_height = gdkdev->axes[y_axis].max_value - gdkdev->axes[y_axis].min_value;
 
   if (gdkdev->info.mode == GDK_MODE_SCREEN) 
     {
       root_impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (_gdk_root)->impl);
-      x_scale = root_impl->width / device_width;
-      y_scale = root_impl->height / device_height;
+      x_scale = GDK_WINDOW_OBJECT (_gdk_root)->width / device_width;
+      y_scale = GDK_WINDOW_OBJECT (_gdk_root)->height / device_height;
 
       x_offset = - input_window->root_x;
       y_offset = - input_window->root_y;
@@ -692,50 +691,48 @@ gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
       double device_aspect = (device_height*gdkdev->axes[y_axis].resolution) /
        (device_width*gdkdev->axes[x_axis].resolution);
 
-      if (device_aspect * impl->width >= impl->height)
-       {
-         /* device taller than window */
-         x_scale = impl->width / device_width;
-         y_scale = (x_scale * gdkdev->axes[x_axis].resolution)
-           / gdkdev->axes[y_axis].resolution;
-
-         x_offset = 0;
-         y_offset = -(device_height * y_scale - 
-                              impl->height)/2;
-       }
+      if (device_aspect * window_object->width >= window_object->height)
+               {
+                 /* device taller than window */
+                 x_scale = window_object->width / device_width;
+                 y_scale = (x_scale * gdkdev->axes[x_axis].resolution) / gdkdev->axes[y_axis].resolution;
+
+                 x_offset = 0;
+                 y_offset = -(device_height * y_scale - window_object->height) / 2;
+               }
       else
-       {
-         /* window taller than device */
-         y_scale = impl->height / device_height;
-         x_scale = (y_scale * gdkdev->axes[y_axis].resolution)
-           / gdkdev->axes[x_axis].resolution;
+               {
+                 /* window taller than device */
+                 y_scale = window_object->height / device_height;
+                 x_scale = (y_scale * gdkdev->axes[y_axis].resolution)
+                       / gdkdev->axes[x_axis].resolution;
 
-         y_offset = 0;
-         x_offset = - (device_width * x_scale - impl->width)/2;
-       }
+                 y_offset = 0;
+                 x_offset = - (device_width * x_scale - window_object->width) / 2;
+               }
     }
 
-  for (i=0; i<gdkdev->info.num_axes; i++)
+  for (i = 0; i < gdkdev->info.num_axes; i++)
     {
       switch (gdkdev->info.axes[i].use)
-       {
-       case GDK_AXIS_X:
-         axis_out[i] = x_offset + x_scale*axis_data[x_axis];
-         if (x_out)
-           *x_out = axis_out[i];
-         break;
-       case GDK_AXIS_Y:
-         axis_out[i] = y_offset + y_scale*axis_data[y_axis];
-         if (y_out)
-           *y_out = axis_out[i];
-         break;
-       default:
-         axis_out[i] =
-           (gdkdev->info.axes[i].max * (axis_data[i] - gdkdev->axes[i].min_value) +
-            gdkdev->info.axes[i].min * (gdkdev->axes[i].max_value - axis_data[i])) /
-           (gdkdev->axes[i].max_value - gdkdev->axes[i].min_value);
-         break;
-       }
+               {
+               case GDK_AXIS_X:
+                 axis_out[i] = x_offset + x_scale * axis_data[x_axis];
+                 if (x_out)
+                       *x_out = axis_out[i];
+                 break;
+               case GDK_AXIS_Y:
+                 axis_out[i] = y_offset + y_scale * axis_data[y_axis];
+                 if (y_out)
+                       *y_out = axis_out[i];
+                 break;
+               default:
+                 axis_out[i] =
+                       (gdkdev->info.axes[i].max * (axis_data[i] - gdkdev->axes[i].min_value) +
+                        gdkdev->info.axes[i].min * (gdkdev->axes[i].max_value - axis_data[i])) /
+                       (gdkdev->axes[i].max_value - gdkdev->axes[i].min_value);
+                 break;
+               }
     }
 }
 
index 4d6e0de6481ca3427b5e5a772226b26366c57431..d31771d0f6db5b9aa2655ee0e13287cd709fe6f3 100644 (file)
@@ -149,13 +149,15 @@ gdk_get_use_xshm (void)
 gint
 gdk_screen_get_width (GdkScreen *screen)
 {
-  return GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (_gdk_root)->impl)->width;
+  //return GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (_gdk_root)->impl)->width;
+  return GDK_WINDOW_OBJECT (_gdk_root)->width;
 }
 
 gint
 gdk_screen_get_height (GdkScreen *screen)
 {
-  return GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (_gdk_root)->impl)->height;
+  //return GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (_gdk_root)->impl)->height;
+  return GDK_WINDOW_OBJECT (_gdk_root)->height;
 }
 gint
 gdk_screen_get_width_mm (GdkScreen *screen)
@@ -1163,6 +1165,8 @@ _gdk_win32_drawable_description (GdkDrawable *d)
 {
   gint width, height, depth;
 
+  g_return_val_if_fail (GDK_IS_DRAWABLE (d), NULL);
+
   gdk_drawable_get_size (d, &width, &height);
   depth = gdk_drawable_get_depth (d);
 
index 911fa9ddbcfb783519c07ed7e5e2eb367bfa9268..860bff20cc3d55f25e335ebf8df3c2628d3515ea 100644 (file)
@@ -130,7 +130,7 @@ gdk_pixmap_impl_win32_get_size (GdkDrawable *drawable,
 }
 
 GdkPixmap*
-gdk_pixmap_new (GdkDrawable *drawable,
+_gdk_pixmap_new (GdkDrawable *drawable,
                gint         width,
                gint         height,
                gint         depth)
@@ -348,7 +348,7 @@ static const unsigned char mirror[256] = {
 };
 
 GdkPixmap *
-gdk_bitmap_create_from_data (GdkDrawable *drawable,
+_gdk_bitmap_create_from_data (GdkDrawable *drawable,
                             const gchar *data,
                             gint         width,
                             gint         height)
@@ -388,7 +388,7 @@ gdk_bitmap_create_from_data (GdkDrawable *drawable,
 }
 
 GdkPixmap*
-gdk_pixmap_create_from_data (GdkDrawable    *drawable,
+_gdk_pixmap_create_from_data (GdkDrawable    *drawable,
                             const gchar    *data,
                             gint            width,
                             gint            height,
index 810a28a7aa7fc11b11e6468e473a8b9f247ce769..84284a86a506f5de3ccbb5714459767ac82f12c7 100644 (file)
 #define GDK_IS_GC_WIN32_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_GC_WIN32))
 #define GDK_GC_WIN32_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_GC_WIN32, GdkGCWin32Class))
 
+//#define GDK_WINDOW_SCREEN(win)         (_gdk_screen)
+GdkScreen *GDK_WINDOW_SCREEN(GObject *win);
+
+#define GDK_WINDOW_IS_WIN32(win)        (GDK_IS_WINDOW_IMPL_WIN32 (((GdkWindowObject *)win)->impl))
+
 typedef struct _GdkColormapPrivateWin32 GdkColormapPrivateWin32;
 typedef struct _GdkCursorPrivate        GdkCursorPrivate;
 typedef struct _GdkWin32SingleFont      GdkWin32SingleFont;
@@ -455,7 +460,7 @@ HICON _gdk_win32_pixbuf_to_hcursor (GdkPixbuf *pixbuf,
 gboolean _gdk_win32_pixbuf_to_hicon_supports_alpha (void);
 
 /* Initialization */
-void _gdk_windowing_window_init (void);
+void _gdk_windowing_window_init (GdkScreen *screen);
 void _gdk_root_window_size_init (void);
 void _gdk_monitor_init(void);
 void _gdk_visual_init (void);
index 340cc2a06370c70eaff84daa46e3354be9ce784f..d220da1878832c63fd1ef9cd079e811e1ea56d57 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
  * Copyright (C) 1998-2004 Tor Lillqvist
  * Copyright (C) 2001-2004 Hans Breuer
- * Copyright (C) 2007 Cody Russell
+ * Copyright (C) 2007-2009 Cody Russell
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
 static GdkColormap* gdk_window_impl_win32_get_colormap (GdkDrawable *drawable);
 static void         gdk_window_impl_win32_set_colormap (GdkDrawable *drawable,
                                                        GdkColormap *cmap);
-static void         gdk_window_impl_win32_get_size     (GdkDrawable *drawable,
-                                                       gint *width,
-                                                       gint *height);
-static GdkRegion*   gdk_window_impl_win32_get_visible_region (GdkDrawable *drawable);
 static void gdk_window_impl_win32_init       (GdkWindowImplWin32      *window);
 static void gdk_window_impl_win32_class_init (GdkWindowImplWin32Class *klass);
 static void gdk_window_impl_win32_finalize   (GObject                 *object);
@@ -56,10 +52,17 @@ static gboolean _gdk_window_get_functions (GdkWindow         *window,
 
 #define WINDOW_IS_TOPLEVEL(window)                \
   (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
-   GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
+   GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN && \
+   GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
 
 static void gdk_window_impl_iface_init (GdkWindowImplIface *iface);
 
+GdkScreen *
+GDK_WINDOW_SCREEN (GObject *win)
+{
+  return _gdk_screen;
+}
+
 GType
 _gdk_window_impl_win32_get_type (void)
 {
@@ -107,8 +110,6 @@ _gdk_window_impl_get_type (void)
 static void
 gdk_window_impl_win32_init (GdkWindowImplWin32 *impl)
 {
-  impl->width = 1;
-  impl->height = 1;
   impl->toplevel_window_type = -1;
   impl->hcursor = NULL;
   impl->hicon_big = NULL;
@@ -134,11 +135,6 @@ gdk_window_impl_win32_class_init (GdkWindowImplWin32Class *klass)
 
   drawable_class->set_colormap = gdk_window_impl_win32_set_colormap;
   drawable_class->get_colormap = gdk_window_impl_win32_get_colormap;
-  drawable_class->get_size = gdk_window_impl_win32_get_size;
-
-  /* Visible and clip regions are the same */
-  drawable_class->get_clip_region = gdk_window_impl_win32_get_visible_region;
-  drawable_class->get_visible_region = gdk_window_impl_win32_get_visible_region;
 }
 
 static void
@@ -236,53 +232,28 @@ gdk_window_impl_win32_set_colormap (GdkDrawable *drawable,
     }
 }
 
-static void
-gdk_window_impl_win32_get_size (GdkDrawable *drawable,
-                               gint        *width,
-                               gint        *height)
-{
-  g_return_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (drawable));
-
-  if (width)
-    *width = GDK_WINDOW_IMPL_WIN32 (drawable)->width;
-  if (height)
-    *height = GDK_WINDOW_IMPL_WIN32 (drawable)->height;
-}
-
-static GdkRegion*
-gdk_window_impl_win32_get_visible_region (GdkDrawable *drawable)
-{
-  GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (drawable);
-  GdkRectangle result_rect;
-
-  result_rect.x = 0;
-  result_rect.y = 0;
-  result_rect.width = impl->width;
-  result_rect.height = impl->height;
-
-  gdk_rectangle_intersect (&result_rect, &impl->position_info.clip_rect, &result_rect);
-
-  return gdk_region_rectangle (&result_rect);
-}
-
 void
 _gdk_root_window_size_init (void)
 {
-  GdkWindowImplWin32 *impl;
+  GdkWindowObject *window_object;
+  //GdkWindowImplWin32 *impl;
   GdkRectangle rect;
   int i;
 
-  impl = GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) _gdk_root)->impl);
+  window_object = GDK_WINDOW_OBJECT (_gdk_root);
+  //impl = GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) _gdk_root)->impl);
   rect = _gdk_monitors[0].rect;
   for (i = 1; i < _gdk_num_monitors; i++)
     gdk_rectangle_union (&rect, &_gdk_monitors[i].rect, &rect);
 
-  impl->width = rect.width;
-  impl->height = rect.height;
+  window_object->width = rect.width;
+  window_object->height = rect.height;
+  //impl->width = rect.width;
+  //impl->height = rect.height;
 }
 
 void
-_gdk_windowing_window_init (void)
+_gdk_windowing_window_init (GdkScreen *screen)
 {
   GdkWindowObject *private;
   GdkDrawableImplWin32 *draw_impl;
@@ -292,6 +263,8 @@ _gdk_windowing_window_init (void)
   _gdk_root = g_object_new (GDK_TYPE_WINDOW, NULL);
   private = (GdkWindowObject *)_gdk_root;
   private->impl = g_object_new (_gdk_window_impl_get_type (), NULL);
+  private->impl_window = private;
+
   draw_impl = GDK_DRAWABLE_IMPL_WIN32 (private->impl);
   
   draw_impl->handle = GetDesktopWindow ();
@@ -303,8 +276,13 @@ _gdk_windowing_window_init (void)
   private->depth = gdk_visual_get_system ()->depth;
 
   _gdk_root_window_size_init ();
-  _gdk_window_init_position (GDK_WINDOW (private));
+
+  private->x = 0;
+  private->y = 0;
+  private->abs_x = 0;
+  private->abs_y = 0;
+  private->width = GetSystemMetrics (SM_CXSCREEN);
+  private->height = GetSystemMetrics (SM_CYSCREEN);
 
   gdk_win32_handle_table_insert ((HANDLE *) &draw_impl->handle, _gdk_root);
 
@@ -486,102 +464,64 @@ RegisterGdkClass (GdkWindowType wtype, GdkWindowTypeHint wtype_hint)
   return klass;
 }
 
-static GdkWindow*
-gdk_window_new_internal (GdkWindow     *parent,
-                        GdkWindowAttr *attributes,
-                        gint           attributes_mask,
-                        gboolean       from_set_skip_taskbar_hint)
+void
+_gdk_window_impl_new (GdkWindow     *window,
+                     GdkWindow     *real_parent,
+                     GdkScreen     *screen,
+                     GdkVisual     *visual,
+                     GdkEventMask   event_mask,
+                     GdkWindowAttr *attributes,
+                     gint           attributes_mask)
 {
   HWND hwndNew;
   HANDLE hparent;
   ATOM klass = 0;
   DWORD dwStyle = 0, dwExStyle;
   RECT rect;
-  GdkWindow *window;
   GdkWindow *orig_parent;
   GdkWindowObject *private;
   GdkWindowImplWin32 *impl;
   GdkDrawableImplWin32 *draw_impl;
-  GdkVisual *visual;
   const gchar *title;
   wchar_t *wtitle;
   gint window_width, window_height;
   gint offset_x = 0, offset_y = 0;
 
-  g_return_val_if_fail (attributes != NULL, NULL);
+  private = (GdkWindowObject *)window;
 
-  if (!parent)
-    parent = _gdk_root;
-
-  g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
-  
-  orig_parent = parent;
+  orig_parent = real_parent;
 
   GDK_NOTE (MISC,
            g_print ("gdk_window_new_internal: %s\n",
-                    (attributes->window_type == GDK_WINDOW_TOPLEVEL ? "TOPLEVEL" :
-                     (attributes->window_type == GDK_WINDOW_CHILD ? "CHILD" :
-                      (attributes->window_type == GDK_WINDOW_DIALOG ? "DIALOG" :
+                       (attributes->window_type == GDK_WINDOW_TOPLEVEL ? "TOPLEVEL" :
+                       (attributes->window_type == GDK_WINDOW_CHILD ? "CHILD" :
+                       (attributes->window_type == GDK_WINDOW_DIALOG ? "DIALOG" :
                        (attributes->window_type == GDK_WINDOW_TEMP ? "TEMP" :
-                        "???"))))));
+                       "???"))))));
 
-  if (GDK_WINDOW_DESTROYED (parent))
-    return NULL;
-  
-  hparent = GDK_WINDOW_HWND (parent);
+  hparent = GDK_WINDOW_HWND (real_parent);
 
-  window = g_object_new (GDK_TYPE_WINDOW, NULL);
-  private = (GdkWindowObject *)window;
-  private->impl = g_object_new (_gdk_window_impl_get_type (), NULL);
-  impl = GDK_WINDOW_IMPL_WIN32 (private->impl);
-  draw_impl = GDK_DRAWABLE_IMPL_WIN32 (private->impl);
+  impl = g_object_new (_gdk_window_impl_get_type (), NULL);
+  private->impl = (GdkDrawable *)impl;
+  draw_impl = GDK_DRAWABLE_IMPL_WIN32 (impl);
   draw_impl->wrapper = GDK_DRAWABLE (window);
 
-  /* Windows with a foreign parent are treated as if they are children
-   * of the root window, except for actual creation.
-   */
-  if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
-    parent = _gdk_root;
-  
-  private->parent = (GdkWindowObject *)parent;
+  // XXX: xattributes_mask = 0
 
-  private->accept_focus = TRUE;
-  private->focus_on_map = TRUE;
-
-  if (attributes_mask & GDK_WA_X)
-    private->x = attributes->x;
-  else
-    private->x = 0;
-  
-  if (attributes_mask & GDK_WA_Y)
-    private->y = attributes->y;
-  else if (attributes_mask & GDK_WA_X)
-    private->y = 100;          /* ??? We must put it somewhere... */
-  else
-    private->y = 0;
-  
+#if 0
   if (attributes_mask & GDK_WA_VISUAL)
     visual = attributes->visual;
   else
     visual = gdk_visual_get_system ();
+#endif
 
+#if 0
   impl->width = (attributes->width > 1) ? (attributes->width) : (1);
   impl->height = (attributes->height > 1) ? (attributes->height) : (1);
+#endif
   impl->extension_events_selected = FALSE;
-  if (attributes->wclass == GDK_INPUT_ONLY)
-    {
-      /* Backwards compatiblity - we've always ignored
-       * attributes->window_type for input-only windows
-       * before
-       */
-      if (parent == _gdk_root)
-       private->window_type = GDK_WINDOW_TEMP;
-      else
-       private->window_type = GDK_WINDOW_CHILD;
-    }
-  else
-    private->window_type = attributes->window_type;
 
+  // XXX ?
   if (attributes->wclass == GDK_INPUT_OUTPUT)
     {
       dwExStyle = 0;
@@ -592,8 +532,8 @@ gdk_window_new_internal (GdkWindow     *parent,
       if (attributes_mask & GDK_WA_COLORMAP)
        {
          draw_impl->colormap = attributes->colormap;
-          g_object_ref (attributes->colormap);
-        }
+         g_object_ref (attributes->colormap);
+       }
       else
        {
          draw_impl->colormap = gdk_screen_get_system_colormap (_gdk_screen);
@@ -618,10 +558,9 @@ gdk_window_new_internal (GdkWindow     *parent,
     {
     case GDK_WINDOW_TOPLEVEL:
     case GDK_WINDOW_DIALOG:
-      if (parent != _gdk_root)
+      if (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
        {
-         g_warning (G_STRLOC ": Toplevel windows must be created as children\n"
-                    "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
+         /* The common code warns for this case. */
          hparent = GetDesktopWindow ();
        }
       /* Children of foreign windows aren't toplevel windows */
@@ -641,34 +580,32 @@ gdk_window_new_internal (GdkWindow     *parent,
        }
       break;
 
+         /*
     case GDK_WINDOW_CHILD:
       dwStyle = WS_CHILDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
       break;
+         */
 
     case GDK_WINDOW_TEMP:
       /* A temp window is not necessarily a top level window */
-      dwStyle = (_gdk_root == parent ? WS_POPUP : WS_CHILDWINDOW);
+      dwStyle = (_gdk_root == real_parent ? WS_POPUP : WS_CHILDWINDOW);
       dwStyle |= WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
       dwExStyle |= WS_EX_TOOLWINDOW;
       offset_x = _gdk_offset_x;
       offset_y = _gdk_offset_y;
       break;
 
-    case GDK_WINDOW_ROOT:
-      g_error ("cannot make windows of type GDK_WINDOW_ROOT");
-      break;
-
     default:
       g_assert_not_reached ();
     }
 
-  _gdk_window_init_position (GDK_WINDOW (private));
+  //_gdk_window_init_position (GDK_WINDOW (private));
 
   if (private->window_type != GDK_WINDOW_CHILD)
     {
       rect.left = rect.top = 0;
-      rect.right = impl->position_info.width;
-      rect.bottom = impl->position_info.height;
+      rect.right = private->width;
+      rect.bottom = private->height;
 
       AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle);
 
@@ -677,8 +614,8 @@ gdk_window_new_internal (GdkWindow     *parent,
     }
   else
     {
-      window_width = impl->position_info.width;
-      window_height = impl->position_info.height;
+      window_width = private->width;
+      window_height = private->height;
     }
 
   if (attributes_mask & GDK_WA_TITLE)
@@ -706,17 +643,17 @@ gdk_window_new_internal (GdkWindow     *parent,
   wtitle = g_utf8_to_utf16 (title, -1, NULL, NULL, NULL);
   
   hwndNew = CreateWindowExW (dwExStyle,
-                            MAKEINTRESOURCEW (klass),
-                            wtitle,
-                            dwStyle,
-                            ((attributes_mask & GDK_WA_X) ?
-                             impl->position_info.x - offset_x : CW_USEDEFAULT),
-                            impl->position_info.y - offset_y, 
-                            window_width, window_height,
-                            hparent,
-                            NULL,
-                            _gdk_app_hmodule,
-                            window);
+                                                        MAKEINTRESOURCEW (klass),
+                                                        wtitle,
+                                                        dwStyle,
+                                                        ((attributes_mask & GDK_WA_X) ?
+                                                         private->x - offset_x : CW_USEDEFAULT),
+                                                        private->y - offset_y, 
+                                                        window_width, window_height,
+                                                        hparent,
+                                                        NULL,
+                                                        _gdk_app_hmodule,
+                                                        window);
   if (GDK_WINDOW_HWND (window) != hwndNew)
     {
       g_warning ("gdk_window_new: gdk_event_translate::WM_CREATE (%p, %p) HWND mismatch.",
@@ -746,8 +683,8 @@ gdk_window_new_internal (GdkWindow     *parent,
                           title,
                           window_width, window_height,
                           ((attributes_mask & GDK_WA_X) ?
-                           impl->position_info.x - offset_x: CW_USEDEFAULT),
-                          impl->position_info.y - offset_y, 
+                           private->x - offset_x: CW_USEDEFAULT),
+                          private->y - offset_y, 
                           hparent,
                           GDK_WINDOW_HWND (window)));
 
@@ -760,25 +697,15 @@ gdk_window_new_internal (GdkWindow     *parent,
     {
       WIN32_API_FAILED ("CreateWindowExW");
       g_object_unref (window);
-      return NULL;
+      return;
     }
 
-  if (!from_set_skip_taskbar_hint && private->window_type == GDK_WINDOW_TEMP)
-    gdk_window_set_skip_taskbar_hint (window, TRUE);
+//  if (!from_set_skip_taskbar_hint && private->window_type == GDK_WINDOW_TEMP)
+//    gdk_window_set_skip_taskbar_hint (window, TRUE);
 
   gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
                                  (attributes->cursor) :
                                  NULL));
-
-  return window;
-}
-
-GdkWindow*
-_gdk_window_new (GdkWindow     *parent,
-                GdkWindowAttr *attributes,
-                gint           attributes_mask)
-{
-  return gdk_window_new_internal (parent, attributes, attributes_mask, FALSE);
 }
 
 GdkWindow *
@@ -819,8 +746,8 @@ gdk_window_foreign_new_for_display (GdkDisplay      *display,
     ScreenToClient (parent, &point);
   private->x = point.x;
   private->y = point.y;
-  impl->width = rect.right - rect.left;
-  impl->height = rect.bottom - rect.top;
+  private->width = rect.right - rect.left;
+  private->height = rect.bottom - rect.top;
   private->window_type = GDK_WINDOW_FOREIGN;
   private->destroyed = FALSE;
   private->event_mask = GDK_ALL_EVENTS_MASK; /* XXX */
@@ -836,7 +763,7 @@ gdk_window_foreign_new_for_display (GdkDisplay      *display,
 
   private->depth = gdk_visual_get_system ()->depth;
 
-  _gdk_window_init_position (GDK_WINDOW (private));
+  //_gdk_window_init_position (GDK_WINDOW (private));
 
   g_object_ref (window);
   gdk_win32_handle_table_insert (&GDK_WINDOW_HWND (window), window);
@@ -956,11 +883,17 @@ get_outer_rect (GdkWindow *window,
 }
 
 static void
-adjust_for_gravity_hints (GdkWindowImplWin32 *impl,
-                         RECT               *outer_rect,
-                         gint               *x,
-                         gint               *y)
+adjust_for_gravity_hints (GdkWindow *window,
+                                                 RECT      *outer_rect,
+                                                 gint          *x,
+                                                 gint          *y)
 {
+       GdkWindowObject *obj;
+       GdkWindowImplWin32 *impl;
+
+       obj = GDK_WINDOW_OBJECT (window);
+       impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
+
   if (impl->hint_flags & GDK_HINT_WIN_GRAVITY)
     {
       gint orig_x = *x, orig_y = *y;
@@ -971,14 +904,14 @@ adjust_for_gravity_hints (GdkWindowImplWin32 *impl,
        case GDK_GRAVITY_CENTER:
        case GDK_GRAVITY_SOUTH:
          *x -= (outer_rect->right - outer_rect->left) / 2;
-         *x += impl->width / 2;
+         *x += obj->width / 2;
          break;
              
        case GDK_GRAVITY_SOUTH_EAST:
        case GDK_GRAVITY_EAST:
        case GDK_GRAVITY_NORTH_EAST:
          *x -= outer_rect->right - outer_rect->left;
-         *x += impl->width;
+         *x += obj->width;
          break;
 
        case GDK_GRAVITY_STATIC:
@@ -995,14 +928,14 @@ adjust_for_gravity_hints (GdkWindowImplWin32 *impl,
        case GDK_GRAVITY_CENTER:
        case GDK_GRAVITY_EAST:
          *y -= (outer_rect->bottom - outer_rect->top) / 2;
-         *y += impl->height / 2;
+         *y += obj->height / 2;
          break;
 
        case GDK_GRAVITY_SOUTH_WEST:
        case GDK_GRAVITY_SOUTH:
        case GDK_GRAVITY_SOUTH_EAST:
          *y -= outer_rect->bottom - outer_rect->top;
-         *y += impl->height;
+         *y += obj->height;
          break;
 
        case GDK_GRAVITY_STATIC:
@@ -1039,7 +972,7 @@ show_window_internal (GdkWindow *window,
   GDK_NOTE (MISC, g_print ("show_window_internal: %p: %s%s%s\n",
                           GDK_WINDOW_HWND (window),
                           _gdk_win32_window_state_to_string (private->state),
-                          (raise ? " raise" : ""),
+                          //(raise ? " raise" : ""),
                           (deiconify ? " deiconify" : "")));
   
   /* If asked to show (not deiconify) an withdrawn and iconified
@@ -1100,10 +1033,10 @@ show_window_internal (GdkWindow *window,
     {
       UINT flags = SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOMOVE | SWP_NOSIZE;
 
-      if (!raise)
-       flags |= SWP_NOZORDER;
+         if (!raise)
+               flags |= SWP_NOZORDER;
       if (!raise || GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP || !focus_on_map)
-       flags |= SWP_NOACTIVATE;
+               flags |= SWP_NOACTIVATE;
 
       SetWindowPos (GDK_WINDOW_HWND (window), top, 0, 0, 0, 0, flags);
 
@@ -1169,9 +1102,9 @@ show_window_internal (GdkWindow *window,
 }
 
 static void
-gdk_win32_window_show (GdkWindow *window, gboolean raise)
+gdk_win32_window_show (GdkWindow *window)
 {
-  show_window_internal (window, raise, FALSE);
+  show_window_internal (window, FALSE, FALSE);
 }
 
 static void
@@ -1251,15 +1184,15 @@ gdk_win32_window_move (GdkWindow *window,
    */
   if (GetAncestor (GDK_WINDOW_HWND (window), GA_PARENT) != GetDesktopWindow ())
     {
-      _gdk_window_move_resize_child (window, x, y, impl->width, impl->height);
+      _gdk_window_move_resize_child (window, x, y, private->width, private->height);
     }
   else
     {
       RECT outer_rect;
 
-      get_outer_rect (window, impl->width, impl->height, &outer_rect);
+      get_outer_rect (window, private->width, private->height, &outer_rect);
 
-      adjust_for_gravity_hints (impl, &outer_rect, &x, &y);
+      adjust_for_gravity_hints (window, &outer_rect, &x, &y);
 
       GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,%d,%d,0,0,"
                                "NOACTIVATE|NOSIZE|NOZORDER)\n",
@@ -1329,7 +1262,7 @@ gdk_win32_window_move_resize_internal (GdkWindow *window,
                                       gint       width,
                                       gint       height)
 {
-  GdkWindowObject *private = (GdkWindowObject*) window;
+  GdkWindowObject *private;
   GdkWindowImplWin32 *impl;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
@@ -1342,6 +1275,7 @@ gdk_win32_window_move_resize_internal (GdkWindow *window,
   if (height < 1)
     height = 1;
 
+  private = GDK_WINDOW_OBJECT (window);
   impl = GDK_WINDOW_IMPL_WIN32 (private->impl);
 
   if (private->state & GDK_WINDOW_STATE_FULLSCREEN)
@@ -1361,7 +1295,7 @@ gdk_win32_window_move_resize_internal (GdkWindow *window,
 
       get_outer_rect (window, width, height, &outer_rect);
 
-      adjust_for_gravity_hints (impl, &outer_rect, &x, &y);
+      adjust_for_gravity_hints (window, &outer_rect, &x, &y);
 
       GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,%d,%d,%ld,%ld,"
                                "NOACTIVATE|NOZORDER)\n",
@@ -1452,7 +1386,7 @@ gdk_win32_window_reparent (GdkWindow *window,
                        GDK_WINDOW_HWND (new_parent)));
   
   API_CALL (MoveWindow, (GDK_WINDOW_HWND (window),
-                        x, y, impl->width, impl->height, TRUE));
+                        x, y, window_private->width, window_private->height, TRUE));
 
   /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
    * the root window
@@ -1492,7 +1426,7 @@ gdk_win32_window_reparent (GdkWindow *window,
       g_list_remove (old_parent_private->children, window);
 
   parent_private->children = g_list_prepend (parent_private->children, window);
-  _gdk_window_init_position (GDK_WINDOW (window_private));
+  //_gdk_window_init_position (GDK_WINDOW (window_private));
 
   return FALSE;
 }
@@ -1501,6 +1435,7 @@ static void
 erase_background (GdkWindow *window,
                  HDC        hdc)
 {
+#if 0
   HDC bgdc = NULL;
   HBRUSH hbr = NULL;
   HPALETTE holdpal = NULL;
@@ -1513,7 +1448,7 @@ erase_background (GdkWindow *window,
   
   if (((GdkWindowObject *) window)->input_only ||
       ((GdkWindowObject *) window)->bg_pixmap == GDK_NO_BG ||
-      GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->position_info.no_bg)
+      GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->no_bg)
     {
       return;
     }
@@ -1549,7 +1484,7 @@ erase_background (GdkWindow *window,
       window = GDK_WINDOW (((GdkWindowObject *) window)->parent);
     }
   
-  if (GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->position_info.no_bg)
+  if (GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *) window)->impl)->no_bg)
     {
       /* Improves scolling effect, e.g. main buttons of testgtk */
       return;
@@ -1628,6 +1563,7 @@ erase_background (GdkWindow *window,
          DeleteDC (bgdc);
        }
     }
+#endif
 }
 
 static void
@@ -1639,8 +1575,10 @@ gdk_win32_window_clear_area (GdkWindow *window,
                             gboolean   send_expose)
 {
   GdkWindowImplWin32 *impl;
+  GdkWindowObject *obj;
 
-  impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
+  obj = GDK_WINDOW_OBJECT (window);
+  impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
 
   if (!GDK_WINDOW_DESTROYED (window))
     {
@@ -1652,9 +1590,9 @@ gdk_win32_window_clear_area (GdkWindow *window,
       if (!send_expose)
        {
          if (width == 0)
-           width = impl->width - x;
+           width = obj->width - x;
          if (height == 0)
-           height = impl->height - y;
+           height = obj->height - y;
          GDK_NOTE (MISC, g_print ("_gdk_windowing_window_clear_area: %p: "
                                   "%dx%d@%+d%+d\n",
                                   GDK_WINDOW_HWND (window),
@@ -2118,6 +2056,7 @@ static void
 gdk_win32_window_set_background (GdkWindow      *window,
                                 const GdkColor *color)
 {
+#if 0
   GdkWindowObject *private = (GdkWindowObject *)window;
   
   GDK_NOTE (MISC, g_print ("gdk_window_set_background: %p: %s\n",
@@ -2133,42 +2072,23 @@ gdk_win32_window_set_background (GdkWindow      *window,
       g_object_unref (private->bg_pixmap);
       private->bg_pixmap = NULL;
     }
+#endif
 }
 
 static void
 gdk_win32_window_set_back_pixmap (GdkWindow *window,
-                                 GdkPixmap *pixmap,
-                                 gint       parent_relative)
+                                 GdkPixmap *pixmap)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
 
-  if (pixmap && !gdk_drawable_get_colormap (pixmap))
-    {
-      g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
-      return;
-    }
-  
   if (private->bg_pixmap &&
       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
       private->bg_pixmap != GDK_NO_BG)
     g_object_unref (private->bg_pixmap);
 
-  if (parent_relative)
+  if (pixmap == GDK_PARENT_RELATIVE_BG || pixmap == GDK_NO_BG)
     {
-      private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
-      GDK_NOTE (MISC, g_print (G_STRLOC ": setting background pixmap to parent_relative\n"));
-    }
-  else
-    {
-      if (pixmap)
-       {
-         g_object_ref (pixmap);
-         private->bg_pixmap = pixmap;
-       }
-      else
-       {
-         private->bg_pixmap = GDK_NO_BG;
-       }
+      private->bg_pixmap = pixmap;
     }
 }
 
@@ -2376,14 +2296,21 @@ gdk_win32_window_get_origin (GdkWindow *window,
   return return_val;
 }
 
-gboolean
-gdk_window_get_deskrelative_origin (GdkWindow *window,
-                                   gint      *x,
-                                   gint      *y)
+static gboolean
+gdk_win32_window_get_deskrelative_origin (GdkWindow *window,
+                                         gint      *x,
+                                         gint      *y)
 {
   return gdk_window_get_origin (window, x, y);
 }
 
+static void
+gdk_win32_window_restack_under (GdkWindow *window,
+                               GList *native_siblings)
+{
+       // ### TODO
+}
+
 void
 gdk_window_get_root_origin (GdkWindow *window,
                            gint      *x,
@@ -2545,7 +2472,8 @@ gdk_display_warp_pointer (GdkDisplay *display,
 GdkWindow*
 _gdk_windowing_window_at_pointer (GdkDisplay *display,
                                  gint       *win_x,
-                                 gint       *win_y)
+                                 gint       *win_y,
+                                 GdkModifierType *mask)
 {
   GdkWindow *window;
   POINT point, pointc;
@@ -2665,27 +2593,6 @@ gdk_win32_window_shape_combine_mask (GdkWindow *window,
     }
 }
 
-void 
-gdk_window_input_shape_combine_mask (GdkWindow *window,
-                                    GdkBitmap *mask,
-                                    gint       x,
-                                    gint       y)
-{
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  /* Not yet implemented
-   *
-   * I don't think there is anything in the Win32 API to directly
-   * support this. And anyway, as we don't currently support RGBA
-   * windows, it doesn't really matter.
-   *
-   * When we do support RGBA, input shape functionality could probably
-   * be implemented by saving the input shape region in the per-window
-   * private data, and then simply checking before generating an input
-   * event whether the event's coordinates are inside the region.
-   */
-}
-
 void
 gdk_window_set_override_redirect (GdkWindow *window,
                                  gboolean   override_redirect)
@@ -3195,6 +3102,7 @@ gdk_win32_window_merge_child_shapes (GdkWindow *window)
   gdk_propagate_shapes (GDK_WINDOW_HWND (window), TRUE);
 }
 
+#if 0
 void 
 gdk_window_set_child_input_shapes (GdkWindow *window)
 {
@@ -3204,7 +3112,9 @@ gdk_window_set_child_input_shapes (GdkWindow *window)
    * gdk_window_input_shape_combine_mask().
    */
 }
+#endif
 
+#if 0
 void 
 gdk_window_merge_child_input_shapes (GdkWindow *window)
 {
@@ -3214,6 +3124,7 @@ gdk_window_merge_child_input_shapes (GdkWindow *window)
    * gdk_window_input_shape_combine_mask().
    */
 }
+#endif
 
 static gboolean 
 gdk_win32_window_set_static_gravities (GdkWindow *window,
@@ -3651,7 +3562,7 @@ gdk_window_set_skip_taskbar_hint (GdkWindow *window,
                                  gboolean   skips_taskbar)
 {
   static GdkWindow *owner = NULL;
-  GdkWindowAttr wa;
+  //GdkWindowAttr wa;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
@@ -3664,14 +3575,16 @@ gdk_window_set_skip_taskbar_hint (GdkWindow *window,
 
   if (skips_taskbar)
     {
+#if 0
       if (owner == NULL)
-       {
-         wa.window_type = GDK_WINDOW_TEMP;
-         wa.wclass = GDK_INPUT_OUTPUT;
-         wa.width = wa.height = 1;
-         wa.event_mask = 0;
-         owner = gdk_window_new_internal (NULL, &wa, 0, TRUE);
-       }
+               {
+                 wa.window_type = GDK_WINDOW_TEMP;
+                 wa.wclass = GDK_INPUT_OUTPUT;
+                 wa.width = wa.height = 1;
+                 wa.event_mask = 0;
+                 owner = gdk_window_new_internal (NULL, &wa, 0, TRUE);
+               }
+#endif
 
       SetWindowLongPtr (GDK_WINDOW_HWND (window), GWLP_HWNDPARENT, (LONG_PTR) GDK_WINDOW_HWND (owner));
 
@@ -3771,19 +3684,6 @@ gdk_win32_window_shape_combine_region (GdkWindow       *window,
     }
 }
 
-void 
-gdk_window_input_shape_combine_region (GdkWindow       *window,
-                                       const GdkRegion *shape_region,
-                                       gint             offset_x,
-                                       gint             offset_y)
-{
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  /* Not yet implemented. See comment in
-   * gdk_window_input_shape_combine_mask().
-   */
-}
-
 GdkWindow *
 gdk_window_lookup_for_display (GdkDisplay      *display,
                                GdkNativeWindow  anid)
@@ -3849,11 +3749,88 @@ gdk_window_set_opacity (GdkWindow *window,
     }
 }
 
+GdkRegion *
+_gdk_windowing_get_shape_for_mask (GdkBitmap *mask)
+{
+       // XXX: TODO
+       return NULL;
+}
+
 void
 _gdk_windowing_window_set_composited (GdkWindow *window, gboolean composited)
 {
 }
 
+GdkRegion *
+_gdk_windowing_window_get_shape (GdkWindow *window)
+{
+       return NULL;
+}
+
+GdkRegion *
+_gdk_windowing_window_get_input_shape (GdkWindow *window)
+{
+       return NULL;
+}
+
+static void
+_gdk_win32_window_destroy (GdkWindow *window,
+                          gboolean   recursing,
+                          gboolean   foreign_destroy)
+{
+}
+
+static gboolean
+_gdk_win32_window_queue_antiexpose (GdkWindow *window,
+                                   GdkRegion *area)
+{
+  HRGN hrgn = _gdk_win32_gdkregion_to_hrgn (area, 0, 0);
+
+  GDK_NOTE (EVENTS, g_print ("_gdk_windowing_window_queue_antiexpose: ValidateRgn %p %s\n",
+                            GDK_WINDOW_HWND (window),
+                            _gdk_win32_gdkregion_to_string (area)));
+
+  ValidateRgn (GDK_WINDOW_HWND (window), hrgn);
+
+  DeleteObject (hrgn);
+
+  return FALSE;
+}
+
+static void
+_gdk_win32_window_queue_translation (GdkWindow *window,
+                                    GdkRegion *area,
+                                    gint       dx,
+                                    gint       dy)
+{
+  g_print ("queue_translation\n");
+}
+
+static void
+gdk_win32_input_shape_combine_region (GdkWindow *window,
+                                     const GdkRegion *shape_region,
+                                     gint offset_x,
+                                     gint offset_y)
+{
+}
+
+void
+_gdk_windowing_window_process_updates_recurse (GdkWindow *window,
+                                              GdkRegion *region)
+{
+  _gdk_window_process_updates_recurse (window, region);
+}
+
+void
+_gdk_windowing_before_process_all_updates (void)
+{
+}
+
+void
+_gdk_windowing_after_process_all_updates (void)
+{
+}
+
 static void
 gdk_window_impl_iface_init (GdkWindowImplIface *iface)
 {
@@ -3862,22 +3839,21 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface)
   iface->withdraw = gdk_win32_window_withdraw;
   iface->set_events = gdk_win32_window_set_events;
   iface->get_events = gdk_win32_window_get_events;
-  iface->clear_area = gdk_win32_window_clear_area;
   iface->raise = gdk_win32_window_raise;
   iface->lower = gdk_win32_window_lower;
+  iface->restack_under = gdk_win32_window_restack_under;
   iface->move_resize = gdk_win32_window_move_resize;
-  iface->scroll = _gdk_win32_window_scroll;
-  iface->move_region = _gdk_win32_window_move_region;
   iface->set_background = gdk_win32_window_set_background;
   iface->set_back_pixmap = gdk_win32_window_set_back_pixmap;
   iface->reparent = gdk_win32_window_reparent;
   iface->set_cursor = gdk_win32_window_set_cursor;
   iface->get_geometry = gdk_win32_window_get_geometry;
   iface->get_origin = gdk_win32_window_get_origin;
-  iface->shape_combine_mask = gdk_win32_window_shape_combine_mask;
   iface->shape_combine_region = gdk_win32_window_shape_combine_region;
-  iface->set_child_shapes = gdk_win32_window_set_child_shapes;
-  iface->merge_child_shapes = gdk_win32_window_merge_child_shapes;
+  iface->input_shape_combine_region = gdk_win32_input_shape_combine_region;
+  iface->get_deskrelative_origin = gdk_win32_window_get_deskrelative_origin;
   iface->set_static_gravities = gdk_win32_window_set_static_gravities;
-  iface->get_offsets = _gdk_win32_windowing_window_get_offsets;
+  iface->queue_antiexpose = _gdk_win32_window_queue_antiexpose;
+  iface->queue_translation = _gdk_win32_window_queue_translation;
+  iface->destroy = _gdk_win32_window_destroy;
 }
index fbc461c94342d8a427cba6151b12c6a3d4f80362..f488e59faabde91f88c71fedbbef813f39f25efc 100644 (file)
@@ -33,6 +33,7 @@ G_BEGIN_DECLS
 
 typedef struct _GdkWin32PositionInfo    GdkWin32PositionInfo;
 
+#if 0
 struct _GdkWin32PositionInfo
 {
   gint x;
@@ -49,6 +50,7 @@ struct _GdkWin32PositionInfo
                                 */
   GdkRectangle clip_rect;      /* visible rectangle of window */
 };
+#endif
 
 
 /* Window implementation for Win32
@@ -68,11 +70,6 @@ struct _GdkWindowImplWin32
 {
   GdkDrawableImplWin32 parent_instance;
 
-  gint width;
-  gint height;
-  
-  GdkWin32PositionInfo position_info;
-
   gint8 toplevel_window_type;
 
   HCURSOR hcursor;
@@ -91,6 +88,8 @@ struct _GdkWindowImplWin32
   GSList    *transient_children;
   gint       num_transients;
   gboolean   changing_state;
+
+  guint no_bg : 1;
 };
  
 struct _GdkWindowImplWin32Class 
@@ -100,6 +99,14 @@ struct _GdkWindowImplWin32Class
 
 GType _gdk_window_impl_win32_get_type (void);
 
+void  _gdk_win32_window_tmp_unset_bg  (GdkWindow *window,
+                                      gboolean   recurse);
+void  _gdk_win32_window_tmp_reset_bg  (GdkWindow *window,
+                                      gboolean   recurse);
+
+void  _gdk_win32_window_tmp_unset_parent_bg (GdkWindow *window);
+void  _gdk_win32_window_tmp_reset_parent_bg (GdkWindow *window);
+
 G_END_DECLS
 
 #endif /* __GDK_WINDOW_WIN32_H__ */
index 3f90d594412418335a31472141078f111cc89f2e..e412ed2f7e4eccf48643e9a1ef3e06d60e856783 100644 (file)
@@ -57,6 +57,7 @@ typedef struct _ChildInfoState ChildInfoState;
 typedef struct _ListChildrenState ListChildrenState;
 typedef struct _SendEventState SendEventState;
 typedef struct _SetInputFocusState SetInputFocusState;
+typedef struct _RoundtripState RoundtripState;
 
 typedef enum {
   CHILD_INFO_GET_PROPERTY,
@@ -112,6 +113,16 @@ struct _SetInputFocusState
   gulong get_input_focus_req;
 };
 
+struct _RoundtripState
+{
+  Display *dpy;
+  _XAsyncHandler async;
+  gulong get_input_focus_req;
+  GdkDisplay *display;
+  GdkRoundTripCallback callback;
+  gpointer data;
+};
+
 static gboolean
 callback_idle (gpointer data)
 {
@@ -743,5 +754,92 @@ _gdk_x11_get_window_child_info (GdkDisplay       *display,
   return !state.have_error;
 }
 
+static gboolean
+roundtrip_callback_idle (gpointer data)
+{
+  RoundtripState *state = (RoundtripState *)data;  
+  
+  state->callback (state->display, state->data, state->get_input_focus_req);
+
+  g_free (state);
+
+  return FALSE;
+}
+
+static Bool
+roundtrip_handler (Display *dpy,
+                  xReply  *rep,
+                  char    *buf,
+                  int      len,
+                  XPointer data)
+{
+  RoundtripState *state = (RoundtripState *)data;  
+  
+  if (dpy->last_request_read == state->get_input_focus_req)
+    {
+      xGetInputFocusReply replbuf;
+      xGetInputFocusReply *repl;
+      
+      if (rep->generic.type != X_Error)
+       {
+         /* Actually does nothing, since there are no additional bytes
+          * to read, but maintain good form.
+          */
+         repl = (xGetInputFocusReply *)
+           _XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len,
+                           (sizeof(xGetInputFocusReply) - sizeof(xReply)) >> 2,
+                           True);
+       }
+
+      
+      if (state->callback)
+        gdk_threads_add_idle (roundtrip_callback_idle, state);
+
+      DeqAsyncHandler(state->dpy, &state->async);
+
+      return (rep->generic.type != X_Error);
+    }
+
+  return False;
+}
+
+void
+_gdk_x11_roundtrip_async (GdkDisplay           *display, 
+                         GdkRoundTripCallback callback,
+                         gpointer              data)
+{
+  Display *dpy;
+  RoundtripState *state;
+  
+  dpy = GDK_DISPLAY_XDISPLAY (display);
+
+  state = g_new (RoundtripState, 1);
+
+  state->display = display;
+  state->dpy = dpy;
+  state->callback = callback;
+  state->data = data;
+  
+  LockDisplay(dpy);
+
+  state->async.next = dpy->async_handlers;
+  state->async.handler = roundtrip_handler;
+  state->async.data = (XPointer) state;
+  dpy->async_handlers = &state->async;
+
+  /*
+   * XSync (dpy, 0)
+   */
+  {
+    xReq *req;
+    
+    GetEmptyReq(GetInputFocus, req);
+    state->get_input_focus_req = dpy->request;
+  }
+  
+  UnlockDisplay(dpy);
+  SyncHandle();
+}
+
 #define __GDK_ASYNC_C__
 #include "gdkaliasdef.c"
index 91897f380f41c4f284643e3404c5680df3cdaca9..44aa18c47c69403da5bf5f697e0d12d990eb0176 100644 (file)
@@ -31,6 +31,9 @@ typedef struct _GdkChildInfoX11 GdkChildInfoX11;
 typedef void (*GdkSendXEventCallback) (Window   window,
                                       gboolean success,
                                       gpointer data);
+typedef void (*GdkRoundTripCallback)  (GdkDisplay *display,
+                                      gpointer data,
+                                      gulong serial);
 
 struct _GdkChildInfoX11
 {
@@ -63,6 +66,10 @@ gboolean _gdk_x11_get_window_child_info (GdkDisplay       *display,
                                         GdkChildInfoX11 **children,
                                         guint            *nchildren);
 
+void _gdk_x11_roundtrip_async           (GdkDisplay           *display, 
+                                        GdkRoundTripCallback callback,
+                                        gpointer              data);
+
 G_END_DECLS
 
 #endif /* __GDK_ASYNC_H__ */
index 735ac5734dbdb3413a09d1ba1ceeb9ebe0327dbd..a7b584709db4ba5b306b284864bb4f9a4353a94e 100644 (file)
@@ -31,6 +31,7 @@
 
 #include <glib.h>
 #include "gdkx.h"
+#include "gdkasync.h"
 #include "gdkdisplay.h"
 #include "gdkdisplay-x11.h"
 #include "gdkscreen.h"
@@ -439,6 +440,13 @@ process_internal_connection (GIOChannel  *gioc,
   return TRUE;
 }
 
+gulong
+_gdk_windowing_window_get_next_serial (GdkDisplay *display)
+{
+  return NextRequest (GDK_DISPLAY_XDISPLAY (display));
+}
+
+
 static GdkInternalConnection *
 gdk_add_connection_handler (Display *display,
                            guint    fd)
@@ -579,6 +587,20 @@ _gdk_x11_display_is_root_window (GdkDisplay *display,
   return FALSE;
 }
 
+struct XPointerUngrabInfo {
+  GdkDisplay *display;
+  guint32 time;
+};
+
+static void
+pointer_ungrab_callback (GdkDisplay *display,
+                        gpointer data,
+                        gulong serial)
+{
+  _gdk_display_pointer_grab_update (display, serial);
+}
+
+
 #define XSERVER_TIME_IS_LATER(time1, time2)                        \
   ( (( time1 > time2 ) && ( time1 - time2 < ((guint32)-1)/2 )) ||  \
     (( time1 < time2 ) && ( time2 - time1 > ((guint32)-1)/2 ))     \
@@ -595,43 +617,35 @@ _gdk_x11_display_is_root_window (GdkDisplay *display,
  */
 void
 gdk_display_pointer_ungrab (GdkDisplay *display,
-                           guint32     time)
+                           guint32     time_)
 {
   Display *xdisplay;
   GdkDisplayX11 *display_x11;
+  GdkPointerGrabInfo *grab;
+  unsigned long serial;
 
   g_return_if_fail (GDK_IS_DISPLAY (display));
 
   display_x11 = GDK_DISPLAY_X11 (display);
   xdisplay = GDK_DISPLAY_XDISPLAY (display);
+
+  serial = NextRequest (xdisplay);
   
-  _gdk_input_ungrab_pointer (display, time);
-  XUngrabPointer (xdisplay, time);
+  _gdk_input_ungrab_pointer (display, time_);
+  XUngrabPointer (xdisplay, time_);
   XFlush (xdisplay);
 
-  if (time == GDK_CURRENT_TIME || 
-      display_x11->pointer_xgrab_time == GDK_CURRENT_TIME ||
-      !XSERVER_TIME_IS_LATER (display_x11->pointer_xgrab_time, time))
-    display_x11->pointer_xgrab_window = NULL;
-}
-
-/**
- * gdk_display_pointer_is_grabbed:
- * @display: a #GdkDisplay
- *
- * Test if the pointer is grabbed.
- *
- * Returns: %TRUE if an active X pointer grab is in effect
- *
- * Since: 2.2
- */
-gboolean
-gdk_display_pointer_is_grabbed (GdkDisplay *display)
-{
-  g_return_val_if_fail (GDK_IS_DISPLAY (display), TRUE);
-  
-  return (GDK_DISPLAY_X11 (display)->pointer_xgrab_window != NULL &&
-         !GDK_DISPLAY_X11 (display)->pointer_xgrab_implicit);
+  grab = _gdk_display_get_last_pointer_grab (display);
+  if (grab &&
+      (time_ == GDK_CURRENT_TIME ||
+       grab->time == GDK_CURRENT_TIME ||
+       !XSERVER_TIME_IS_LATER (grab->time, time_)))
+    {
+      grab->serial_end = serial;
+      _gdk_x11_roundtrip_async (display, 
+                               pointer_ungrab_callback,
+                               NULL);
+    }
 }
 
 /**
@@ -659,9 +673,9 @@ gdk_display_keyboard_ungrab (GdkDisplay *display,
   XFlush (xdisplay);
   
   if (time == GDK_CURRENT_TIME || 
-      display_x11->keyboard_xgrab_time == GDK_CURRENT_TIME ||
-      !XSERVER_TIME_IS_LATER (display_x11->keyboard_xgrab_time, time))
-    display_x11->keyboard_xgrab_window = NULL;
+      display->keyboard_grab.time == GDK_CURRENT_TIME ||
+      !XSERVER_TIME_IS_LATER (display->keyboard_grab.time, time))
+    _gdk_display_unset_has_keyboard_grab (display, FALSE);
 }
 
 /**
@@ -1330,7 +1344,9 @@ gdk_display_store_clipboard (GdkDisplay    *display,
 {
   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display);
   Atom clipboard_manager, save_targets;
-  
+
+  g_return_if_fail (GDK_WINDOW_IS_X11 (clipboard_window));
+
   clipboard_manager = gdk_x11_get_xatom_by_name_for_display (display, "CLIPBOARD_MANAGER");
   save_targets = gdk_x11_get_xatom_by_name_for_display (display, "SAVE_TARGETS");
 
index 0ade8f08355e4a66adf0635cfb189c12d7fcbf35..2873c2d67482d593552b4248cb0bcafea9e015cb 100644 (file)
@@ -30,6 +30,7 @@
 #include <gdk/gdkdisplay.h>
 #include <gdk/gdkkeys.h>
 #include <gdk/gdkwindow.h>
+#include <gdk/gdkinternals.h>
 #include <gdk/gdk.h>           /* For gdk_get_program_class() */
 
 G_BEGIN_DECLS
@@ -93,21 +94,6 @@ struct _GdkDisplayX11
    * (grabs, properties etc.) Otherwise always TRUE. */
   gboolean trusted_client;
 
-  /* Information about current pointer and keyboard grabs held by this
-   * client. If gdk_pointer_xgrab_window or gdk_keyboard_xgrab_window
-   * window is NULL, then the other associated fields are ignored
-   */
-  GdkWindowObject *pointer_xgrab_window;
-  gulong pointer_xgrab_serial;
-  gboolean pointer_xgrab_owner_events;
-  gboolean pointer_xgrab_implicit;
-  guint32 pointer_xgrab_time;
-
-  GdkWindowObject *keyboard_xgrab_window;
-  gulong keyboard_xgrab_serial;
-  gboolean keyboard_xgrab_owner_events;
-  guint32 keyboard_xgrab_time;
-
   /* drag and drop information */
   GdkDragContext *current_dest_drag;
 
@@ -147,11 +133,6 @@ struct _GdkDisplayX11
   /* input GdkWindow list */
   GList *input_windows;
 
-  gint input_ignore_core;
-  /* information about network port and host for gxid daemon */
-  gchar *input_gxid_host;
-  gint   input_gxid_port;
-
   /* Startup notification */
   gchar *startup_notification_id;
 
@@ -169,6 +150,9 @@ struct _GdkDisplayX11
 
   /* Alpha mask picture format */
   XRenderPictFormat *mask_format;
+
+  /* The offscreen window that has the pointer in it (if any) */
+  GdkWindow *active_offscreen_window;
 };
 
 struct _GdkDisplayX11Class
index 82ef4422650258cf104ed7543e9642ff5607f139..118d793c7943ceed92e7746d871dcb1097a0e5dd 100644 (file)
@@ -2992,6 +2992,7 @@ gdk_drag_begin (GdkWindow     *window,
   GdkDragContext *new_context;
   
   g_return_val_if_fail (window != NULL, NULL);
+  g_return_val_if_fail (GDK_WINDOW_IS_X11 (window), NULL);
 
   new_context = gdk_drag_context_new ();
   new_context->is_source = TRUE;
@@ -3197,7 +3198,7 @@ gdk_drag_find_window_for_screen (GdkDragContext  *context,
   window_cache = drag_context_find_window_cache (context, screen);
 
   dest = get_client_window_at_coords (window_cache,
-                                     drag_window ? 
+                                     drag_window && GDK_WINDOW_IS_X11 (drag_window) 
                                      GDK_DRAWABLE_XID (drag_window) : None,
                                      x_root, y_root);
 
@@ -3267,6 +3268,7 @@ gdk_drag_motion (GdkDragContext *context,
   GdkDragContextPrivateX11 *private = PRIVATE_DATA (context);
 
   g_return_val_if_fail (context != NULL, FALSE);
+  g_return_val_if_fail (dest_window == NULL || GDK_WINDOW_IS_X11 (dest_window), FALSE);
 
   private->old_actions = context->actions;
   context->actions = possible_actions;
index a19c7a2e2cc473b9441fe983b081cd49c28cde3e..2b9b1d2c4e7a74280d19e4c8422e0415ec8b7333 100644 (file)
@@ -88,6 +88,7 @@ static void gdk_x11_draw_text_wc   (GdkDrawable    *drawable,
 static void gdk_x11_draw_drawable  (GdkDrawable    *drawable,
                                    GdkGC          *gc,
                                    GdkPixmap      *src,
+                                   GdkDrawable    *original_src,
                                    gint            xsrc,
                                    gint            ysrc,
                                    gint            xdest,
@@ -618,6 +619,7 @@ static void
 gdk_x11_draw_drawable (GdkDrawable *drawable,
                       GdkGC       *gc,
                       GdkPixmap   *src,
+                      GdkDrawable *original_src,
                       gint         xsrc,
                       gint         ysrc,
                       gint         xdest,
@@ -634,13 +636,50 @@ gdk_x11_draw_drawable (GdkDrawable *drawable,
 
   if (GDK_IS_DRAWABLE_IMPL_X11 (src))
     src_impl = GDK_DRAWABLE_IMPL_X11 (src);
+  else if (GDK_IS_WINDOW (src))
+    src_impl = GDK_DRAWABLE_IMPL_X11(((GdkWindowObject *)src)->impl);
   else
-    src_impl = NULL;
+    src_impl = GDK_DRAWABLE_IMPL_X11(((GdkPixmapObject *)src)->impl);
+
+  if (GDK_IS_WINDOW_IMPL_X11 (impl) &&
+      GDK_IS_PIXMAP_IMPL_X11 (src_impl))
+    {
+      GdkPixmapImplX11 *src_pixmap = GDK_PIXMAP_IMPL_X11 (src_impl);
+      /* Work around an Xserver bug where non-visible areas from
+       * a pixmap to a window will clear the window background
+       * in destination areas that are supposed to be clipped out.
+       * This is a problem with client side windows as this means
+       * things may draw outside the virtual windows. This could
+       * also happen for window to window copies, but I don't
+       * think we generate any calls like that.
+       *
+       * See: 
+       * http://lists.freedesktop.org/archives/xorg/2009-February/043318.html
+       */
+      if (xsrc < 0)
+       {
+         width += xsrc;
+         xdest -= xsrc;
+         xsrc = 0;
+       }
+      
+      if (ysrc < 0)
+       {
+         height += ysrc;
+         ydest -= ysrc;
+         ysrc = 0;
+       }
+
+      if (xsrc + width > src_pixmap->width)
+       width = src_pixmap->width - xsrc;
+      if (ysrc + height > src_pixmap->height)
+       height = src_pixmap->height - ysrc;
+    }
   
   if (src_depth == 1)
     {
       XCopyArea (GDK_SCREEN_XDISPLAY (impl->screen),
-                 src_impl ? src_impl->xid : GDK_DRAWABLE_XID (src),
+                 src_impl->xid,
                 impl->xid,
                 GDK_GC_GET_XGC (gc),
                 xsrc, ysrc,
@@ -650,7 +689,7 @@ gdk_x11_draw_drawable (GdkDrawable *drawable,
   else if (dest_depth != 0 && src_depth == dest_depth)
     {
       XCopyArea (GDK_SCREEN_XDISPLAY (impl->screen),
-                 src_impl ? src_impl->xid : GDK_DRAWABLE_XID (src),
+                 src_impl->xid,
                 impl->xid,
                 GDK_GC_GET_XGC (gc),
                 xsrc, ysrc,
@@ -870,7 +909,29 @@ gdk_x11_drawable_get_xid (GdkDrawable *drawable)
   GdkDrawable *impl;
   
   if (GDK_IS_WINDOW (drawable))
-    impl = ((GdkPixmapObject *)drawable)->impl;
+    {
+      GdkWindow *window = (GdkWindow *)drawable;
+      
+      /* Try to ensure the window has a native window */
+      if (!_gdk_window_has_impl (window))
+       {
+         gdk_window_ensure_native (window);
+
+         /* We sync here to ensure the window is created in the Xserver when
+          * this function returns. This is required because the returned XID
+          * for this window must be valid immediately, even with another
+          * connection to the Xserver */
+         gdk_display_sync (gdk_drawable_get_display (window));
+       }
+      
+      if (!GDK_WINDOW_IS_X11 (window))
+        {
+          g_warning (G_STRLOC " drawable is not a native X11 window");
+          return None;
+        }
+      
+      impl = ((GdkWindowObject *)drawable)->impl;
+    }
   else if (GDK_IS_PIXMAP (drawable))
     impl = ((GdkPixmapObject *)drawable)->impl;
   else
@@ -1447,6 +1508,45 @@ gdk_x11_cairo_surface_destroy (void *data)
   impl->cairo_surface = NULL;
 }
 
+void
+_gdk_windowing_set_cairo_surface_size (cairo_surface_t *surface,
+                                      int width,
+                                      int height)
+{
+  cairo_xlib_surface_set_size (surface, width, height);
+}
+
+cairo_surface_t *
+_gdk_windowing_create_cairo_surface (GdkDrawable *drawable,
+                                    int width,
+                                    int height)
+{
+  GdkDrawableImplX11 *impl = GDK_DRAWABLE_IMPL_X11 (drawable);
+  GdkVisual *visual;
+    
+  visual = gdk_drawable_get_visual (drawable);
+  if (visual) 
+    return cairo_xlib_surface_create (GDK_SCREEN_XDISPLAY (impl->screen),
+                                     impl->xid,
+                                     GDK_VISUAL_XVISUAL (visual),
+                                     width, height);
+  else if (gdk_drawable_get_depth (drawable) == 1)
+    return cairo_xlib_surface_create_for_bitmap (GDK_SCREEN_XDISPLAY (impl->screen),
+                                                   impl->xid,
+                                                   GDK_SCREEN_XSCREEN (impl->screen),
+                                                   width, height);
+  else
+    {
+      g_warning ("Using Cairo rendering requires the drawable argument to\n"
+                "have a specified colormap. All windows have a colormap,\n"
+                "however, pixmaps only have colormap by default if they\n"
+                "were created with a non-NULL window argument. Otherwise\n"
+                "a colormap must be set on them with gdk_drawable_set_colormap");
+      return NULL;
+    }
+  
+}
+
 static cairo_surface_t *
 gdk_x11_ref_cairo_surface (GdkDrawable *drawable)
 {
@@ -1458,35 +1558,15 @@ gdk_x11_ref_cairo_surface (GdkDrawable *drawable)
 
   if (!impl->cairo_surface)
     {
-      GdkVisual *visual = NULL;
       int width, height;
   
-      visual = gdk_drawable_get_visual (drawable);
-
       gdk_drawable_get_size (drawable, &width, &height);
 
-      if (visual) 
-       impl->cairo_surface = cairo_xlib_surface_create (GDK_SCREEN_XDISPLAY (impl->screen),
-                                                        impl->xid,
-                                                        GDK_VISUAL_XVISUAL (visual),
-                                                        width, height);
-      else if (gdk_drawable_get_depth (drawable) == 1)
-       impl->cairo_surface = cairo_xlib_surface_create_for_bitmap (GDK_SCREEN_XDISPLAY (impl->screen),
-                                                                   impl->xid,
-                                                                   GDK_SCREEN_XSCREEN (impl->screen),
-                                                                   width, height);
-      else
-       {
-         g_warning ("Using Cairo rendering requires the drawable argument to\n"
-                    "have a specified colormap. All windows have a colormap,\n"
-                    "however, pixmaps only have colormap by default if they\n"
-                    "were created with a non-NULL window argument. Otherwise\n"
-                    "a colormap must be set on them with gdk_drawable_set_colormap");
-         return NULL;
-       }
-
-      cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
-                                  drawable, gdk_x11_cairo_surface_destroy);
+      impl->cairo_surface = _gdk_windowing_create_cairo_surface (drawable, width, height);
+      
+      if (impl->cairo_surface)
+       cairo_surface_set_user_data (impl->cairo_surface, &gdk_x11_cairo_key,
+                                    drawable, gdk_x11_cairo_surface_destroy);
     }
   else
     cairo_surface_reference (impl->cairo_surface);
index 359471de9e273dac6cd3ae6e8a5f5caf4ace6dc7..4565b3961b7be4fbe3d243da70af2818eb4505b6 100644 (file)
@@ -313,7 +313,7 @@ gdk_event_get_graphics_expose (GdkWindow *window)
   GdkEvent *event;
   
   g_return_val_if_fail (window != NULL, NULL);
-  
+
   XIfEvent (GDK_WINDOW_XDISPLAY (window), &xevent, 
            graphics_expose_predicate, (XPointer) window);
   
@@ -867,6 +867,24 @@ set_user_time (GdkWindow *window,
                                   gdk_event_get_time (event));
 }
 
+static gboolean
+is_parent_of (GdkWindow *parent,
+              GdkWindow *child)
+{
+  GdkWindow *w;
+
+  w = child;
+  while (w != NULL)
+    {
+      if (w == parent)
+       return TRUE;
+
+      w = gdk_window_get_parent (w);
+    }
+
+  return FALSE;
+}
+
 static gboolean
 gdk_event_translate (GdkDisplay *display,
                     GdkEvent   *event,
@@ -879,7 +897,6 @@ gdk_event_translate (GdkDisplay *display,
   GdkWindow *filter_window;
   GdkWindowImplX11 *window_impl = NULL;
   gboolean return_val;
-  gint xoffset, yoffset;
   GdkScreen *screen = NULL;
   GdkScreenX11 *screen_x11 = NULL;
   GdkToplevelX11 *toplevel = NULL;
@@ -942,6 +959,24 @@ gdk_event_translate (GdkDisplay *display,
     
   if (window != NULL)
     {
+      /* Apply keyboard grabs to non-native windows */
+      if (/* Is key event */
+         (xevent->type == KeyPress || xevent->type == KeyRelease) &&
+         /* And we have a grab */
+         display->keyboard_grab.window != NULL &&
+         (
+          /* The window is not a descendant of the grabbed window */
+          !is_parent_of ((GdkWindow *)display->keyboard_grab.window, window) ||
+          /* Or owner event is false */
+          !display->keyboard_grab.owner_events
+          )
+         )
+        {
+         /* Report key event against grab window */
+          window = display->keyboard_grab.window;;
+          window_private = (GdkWindowObject *) window;
+        }
+
       window_impl = GDK_WINDOW_IMPL_X11 (window_private->impl);
       
       /* Move key events on focus window to the real toplevel, and
@@ -1041,16 +1076,6 @@ gdk_event_translate (GdkDisplay *display,
 
   return_val = TRUE;
 
-  if (window)
-    {
-      _gdk_x11_window_get_offsets (window, &xoffset, &yoffset);
-    }
-  else
-    {
-      xoffset = 0;
-      yoffset = 0;
-    }
-
   switch (xevent->type)
     {
     case KeyPress:
@@ -1100,9 +1125,7 @@ gdk_event_translate (GdkDisplay *display,
                           xevent->xbutton.x, xevent->xbutton.y,
                           xevent->xbutton.button));
       
-      if (window_private == NULL || 
-         ((window_private->extension_events != 0) &&
-           display_x11->input_ignore_core))
+      if (window_private == NULL)
        {
          return_val = FALSE;
          break;
@@ -1129,8 +1152,8 @@ gdk_event_translate (GdkDisplay *display,
 
          event->scroll.window = window;
          event->scroll.time = xevent->xbutton.time;
-         event->scroll.x = xevent->xbutton.x + xoffset;
-         event->scroll.y = xevent->xbutton.y + yoffset;
+         event->scroll.x = xevent->xbutton.x;
+         event->scroll.y = xevent->xbutton.y;
          event->scroll.x_root = (gfloat)xevent->xbutton.x_root;
          event->scroll.y_root = (gfloat)xevent->xbutton.y_root;
          event->scroll.state = (GdkModifierType) xevent->xbutton.state;
@@ -1148,8 +1171,8 @@ gdk_event_translate (GdkDisplay *display,
          event->button.type = GDK_BUTTON_PRESS;
          event->button.window = window;
          event->button.time = xevent->xbutton.time;
-         event->button.x = xevent->xbutton.x + xoffset;
-         event->button.y = xevent->xbutton.y + yoffset;
+         event->button.x = xevent->xbutton.x;
+         event->button.y = xevent->xbutton.y;
          event->button.x_root = (gfloat)xevent->xbutton.x_root;
          event->button.y_root = (gfloat)xevent->xbutton.y_root;
          event->button.axes = NULL;
@@ -1162,14 +1185,11 @@ gdk_event_translate (GdkDisplay *display,
              return_val = FALSE;
              break;
            }
-
-         _gdk_event_button_generate (display, event);
           break;
        }
 
       set_user_time (window, event);
 
-      _gdk_xgrab_check_button_event (window, xevent);
       break;
       
     case ButtonRelease:
@@ -1179,9 +1199,7 @@ gdk_event_translate (GdkDisplay *display,
                           xevent->xbutton.x, xevent->xbutton.y,
                           xevent->xbutton.button));
       
-      if (window_private == NULL ||
-         ((window_private->extension_events != 0) &&
-           display_x11->input_ignore_core))
+      if (window_private == NULL)
        {
          return_val = FALSE;
          break;
@@ -1198,8 +1216,8 @@ gdk_event_translate (GdkDisplay *display,
       event->button.type = GDK_BUTTON_RELEASE;
       event->button.window = window;
       event->button.time = xevent->xbutton.time;
-      event->button.x = xevent->xbutton.x + xoffset;
-      event->button.y = xevent->xbutton.y + yoffset;
+      event->button.x = xevent->xbutton.x;
+      event->button.y = xevent->xbutton.y;
       event->button.x_root = (gfloat)xevent->xbutton.x_root;
       event->button.y_root = (gfloat)xevent->xbutton.y_root;
       event->button.axes = NULL;
@@ -1208,12 +1226,8 @@ gdk_event_translate (GdkDisplay *display,
       event->button.device = display->core_pointer;
 
       if (!set_screen_from_root (display, event, xevent->xbutton.root))
-       {
-         return_val = FALSE;
-         break;
-       }
-
-      _gdk_xgrab_check_button_event (window, xevent);
+       return_val = FALSE;
+      
       break;
       
     case MotionNotify:
@@ -1223,9 +1237,7 @@ gdk_event_translate (GdkDisplay *display,
                           xevent->xmotion.x, xevent->xmotion.y,
                           (xevent->xmotion.is_hint) ? "true" : "false"));
       
-      if (window_private == NULL ||
-         ((window_private->extension_events != 0) &&
-           display_x11->input_ignore_core))
+      if (window_private == NULL)
        {
          return_val = FALSE;
          break;
@@ -1234,8 +1246,8 @@ gdk_event_translate (GdkDisplay *display,
       event->motion.type = GDK_MOTION_NOTIFY;
       event->motion.window = window;
       event->motion.time = xevent->xmotion.time;
-      event->motion.x = xevent->xmotion.x + xoffset;
-      event->motion.y = xevent->xmotion.y + yoffset;
+      event->motion.x = xevent->xmotion.x;
+      event->motion.y = xevent->xmotion.y;
       event->motion.x_root = (gfloat)xevent->xmotion.x_root;
       event->motion.y_root = (gfloat)xevent->xmotion.y_root;
       event->motion.axes = NULL;
@@ -1286,12 +1298,6 @@ gdk_event_translate (GdkDisplay *display,
            }
        }
 
-      /* Tell XInput stuff about it if appropriate */
-      if (window_private &&
-         !GDK_WINDOW_DESTROYED (window) &&
-         window_private->extension_events != 0)
-       _gdk_input_enter_event (&xevent->xcrossing, window);
-      
       event->crossing.type = GDK_ENTER_NOTIFY;
       event->crossing.window = window;
       
@@ -1304,8 +1310,8 @@ gdk_event_translate (GdkDisplay *display,
        event->crossing.subwindow = NULL;
       
       event->crossing.time = xevent->xcrossing.time;
-      event->crossing.x = xevent->xcrossing.x + xoffset;
-      event->crossing.y = xevent->xcrossing.y + yoffset;
+      event->crossing.x = xevent->xcrossing.x;
+      event->crossing.y = xevent->xcrossing.y;
       event->crossing.x_root = xevent->xcrossing.x_root;
       event->crossing.y_root = xevent->xcrossing.y_root;
       
@@ -1399,8 +1405,8 @@ gdk_event_translate (GdkDisplay *display,
        event->crossing.subwindow = NULL;
       
       event->crossing.time = xevent->xcrossing.time;
-      event->crossing.x = xevent->xcrossing.x + xoffset;
-      event->crossing.y = xevent->xcrossing.y + yoffset;
+      event->crossing.x = xevent->xcrossing.x;
+      event->crossing.y = xevent->xcrossing.y;
       event->crossing.x_root = xevent->xcrossing.x_root;
       event->crossing.y_root = xevent->xcrossing.y_root;
       
@@ -1596,8 +1602,8 @@ gdk_event_translate (GdkDisplay *display,
       {
        GdkRectangle expose_rect;
 
-       expose_rect.x = xevent->xexpose.x + xoffset;
-       expose_rect.y = xevent->xexpose.y + yoffset;
+       expose_rect.x = xevent->xexpose.x;
+       expose_rect.y = xevent->xexpose.y;
        expose_rect.width = xevent->xexpose.width;
        expose_rect.height = xevent->xexpose.height;
 
@@ -1636,8 +1642,8 @@ gdk_event_translate (GdkDisplay *display,
             break;
           }
         
-       expose_rect.x = xevent->xgraphicsexpose.x + xoffset;
-       expose_rect.y = xevent->xgraphicsexpose.y + yoffset;
+       expose_rect.x = xevent->xgraphicsexpose.x;
+       expose_rect.y = xevent->xgraphicsexpose.y;
        expose_rect.width = xevent->xgraphicsexpose.width;
        expose_rect.height = xevent->xgraphicsexpose.height;
            
@@ -1826,9 +1832,9 @@ gdk_event_translate (GdkDisplay *display,
                           : ""));
       if (window && GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT)
         { 
-         window_impl->width = xevent->xconfigure.width;
-         window_impl->height = xevent->xconfigure.height;
-         
+         window_private->width = xevent->xconfigure.width;
+         window_private->height = xevent->xconfigure.height;
+
          _gdk_x11_drawable_update_size (window_private->impl);
          _gdk_x11_screen_size_changed (screen, xevent);
         }
@@ -1836,7 +1842,7 @@ gdk_event_translate (GdkDisplay *display,
       if (window &&
          xevent->xconfigure.event == xevent->xconfigure.window &&
          !GDK_WINDOW_DESTROYED (window) &&
-         (window_private->extension_events != 0))
+         window_private->input_window != NULL)
        _gdk_input_configure_event (&xevent->xconfigure, window);
       
 #ifdef HAVE_XSYNC
@@ -1847,7 +1853,7 @@ gdk_event_translate (GdkDisplay *display,
        }
 #endif
 
-    if (!window ||
+      if (!window ||
          xevent->xconfigure.event != xevent->xconfigure.window ||
           GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD ||
           GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT)
@@ -1887,9 +1893,10 @@ gdk_event_translate (GdkDisplay *display,
            }
          window_private->x = event->configure.x;
          window_private->y = event->configure.y;
-         window_impl->width = xevent->xconfigure.width;
-         window_impl->height = xevent->xconfigure.height;
+         window_private->width = xevent->xconfigure.width;
+         window_private->height = xevent->xconfigure.height;
          
+         _gdk_window_update_size (window);
          _gdk_x11_drawable_update_size (window_private->impl);
          
          if (window_private->resize_count >= 1)
@@ -2152,8 +2159,8 @@ gdk_event_translate (GdkDisplay *display,
          
          if (window_private &&
              !GDK_WINDOW_DESTROYED (window_private) &&
-             (window_private->extension_events != 0))
-           return_val = _gdk_input_other_event(event, xevent, window);
+             window_private->input_window)
+           return_val = _gdk_input_other_event (event, xevent, window);
          else
            return_val = FALSE;
          
@@ -2180,7 +2187,7 @@ gdk_event_translate (GdkDisplay *display,
   
   if (window)
     g_object_unref (window);
-  
+
   return return_val;
 }
 
@@ -2301,6 +2308,7 @@ _gdk_events_queue (GdkDisplay *display)
       if (gdk_event_translate (display, event, &xevent, FALSE))
        {
          ((GdkEventPrivate *)event)->flags &= ~GDK_EVENT_PENDING;
+          _gdk_windowing_got_event (display, node, event, xevent.xany.serial);
        }
       else
        {
index 8c3e3407194239da741f997d41222c6870c3a2a7..0a6869a2155547fa7180e07d1952f22549c54d9d 100644 (file)
@@ -608,7 +608,8 @@ gdk_x11_gc_values_to_xvalues (GdkGCValues    *values,
 
 void
 _gdk_windowing_gc_set_clip_region (GdkGC           *gc,
-                                  const GdkRegion *region)
+                                  const GdkRegion *region,
+                                  gboolean reset_origin)
 {
   GdkGCX11 *x11_gc = GDK_GC_X11 (gc);
 
@@ -623,8 +624,11 @@ _gdk_windowing_gc_set_clip_region (GdkGC           *gc,
 
   x11_gc->have_clip_region = region != NULL;
 
-  gc->clip_x_origin = 0;
-  gc->clip_y_origin = 0;
+  if (reset_origin)
+    {
+      gc->clip_x_origin = 0;
+      gc->clip_y_origin = 0;
+    }
 
   x11_gc->dirty_mask |= GDK_GC_DIRTY_CLIP;
 }
index 9271f090d581b42ab62f42ab3728facc5236bcb6..6bd71c3b4415a6521a59b7b3338951402d8ac968 100644 (file)
@@ -165,417 +165,6 @@ struct _GdkWindowQueueItem
   } u;
 };
 
-struct _GdkWindowParentPos
-{
-  gint x;
-  gint y;
-  gint x11_x;
-  gint x11_y;
-  GdkRectangle clip_rect;
-};
-
-static void gdk_window_compute_position   (GdkWindowImplX11      *window,
-                                          GdkWindowParentPos *parent_pos,
-                                          GdkXPositionInfo   *info);
-static void gdk_window_compute_parent_pos (GdkWindowImplX11      *window,
-                                          GdkWindowParentPos *parent_pos);
-static void gdk_window_premove            (GdkWindow          *window,
-                                          GdkWindowParentPos *parent_pos);
-static void gdk_window_postmove           (GdkWindow          *window,
-                                          GdkWindowParentPos *parent_pos);
-static void gdk_window_queue_translation  (GdkWindow          *window,
-                                          GdkRegion          *area,
-                                          gint                dx,
-                                          gint                dy);
-static void gdk_window_clip_changed       (GdkWindow          *window,
-                                          GdkRectangle       *old_clip,
-                                          GdkRectangle       *new_clip);
-
-void
-_gdk_x11_window_get_offsets (GdkWindow *window,
-                             gint      *x_offset,
-                             gint      *y_offset)
-{
-  GdkWindowImplX11 *impl =
-    GDK_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (window)->impl);
-
-  *x_offset = impl->position_info.x_offset;
-  *y_offset = impl->position_info.y_offset;
-}
-
-void
-_gdk_window_init_position (GdkWindow *window)
-{
-  GdkWindowParentPos parent_pos;
-  GdkWindowImplX11 *impl;
-  
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  impl =
-    GDK_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (window)->impl);
-  
-  gdk_window_compute_parent_pos (impl, &parent_pos);
-  gdk_window_compute_position (impl, &parent_pos, &impl->position_info);
-}
-
-static void
-gdk_window_copy_area_scroll (GdkWindow    *window,
-                            GdkRectangle *dest_rect,
-                            gint          dx,
-                            gint          dy)
-{
-  GdkWindowObject *obj = GDK_WINDOW_OBJECT (window);
-  GList *l;
-
-  if (dest_rect->width > 0 && dest_rect->height > 0)
-    {
-      GdkGC *gc;
-
-      gc = _gdk_drawable_get_scratch_gc (window, TRUE);
-      
-      gdk_window_queue_translation (window, NULL, dx, dy);
-   
-      XCopyArea (GDK_WINDOW_XDISPLAY (window),
-                GDK_WINDOW_XID (window),
-                GDK_WINDOW_XID (window),
-                gdk_x11_gc_get_xgc (gc),
-                dest_rect->x - dx, dest_rect->y - dy,
-                dest_rect->width, dest_rect->height,
-                dest_rect->x, dest_rect->y);
-    }
-
-  for (l = obj->children; l; l = l->next)
-    {
-      GdkWindow *child = (GdkWindow*) l->data;
-      GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
-
-      gdk_window_move (child, child_obj->x + dx, child_obj->y + dy);
-    }
-}
-
-static void
-compute_intermediate_position (GdkXPositionInfo *position_info,
-                              GdkXPositionInfo *new_info,
-                              gint              d_xoffset,
-                              gint              d_yoffset,
-                              GdkRectangle     *new_position)
-{
-  gint new_x0, new_x1, new_y0, new_y1;
-  
-  /* Wrap d_xoffset, d_yoffset into [-32768,32767] range. For the
-   * purposes of subwindow movement, it doesn't matter if we are
-   * off by a factor of 65536, and if we don't do this range
-   * reduction, we'll end up with invalid widths.
-   */
-  d_xoffset = (gint16)d_xoffset;
-  d_yoffset = (gint16)d_yoffset;
-  
-  if (d_xoffset < 0)
-    {
-      new_x0 = position_info->x + d_xoffset;
-      new_x1 = position_info->x + position_info->width;
-    }
-  else
-    {
-      new_x0 = position_info->x;
-      new_x1 = position_info->x + new_info->width + d_xoffset;
-    }
-
-  new_position->x = new_x0;
-  new_position->width = new_x1 - new_x0;
-  
-  if (d_yoffset < 0)
-    {
-      new_y0 = position_info->y + d_yoffset;
-      new_y1 = position_info->y + position_info->height;
-    }
-  else
-    {
-      new_y0 = position_info->y;
-      new_y1 = position_info->y + new_info->height + d_yoffset;
-    }
-  
-  new_position->y = new_y0;
-  new_position->height = new_y1 - new_y0;
-}
-
-static void
-translate_pos (GdkWindowParentPos *dest, GdkWindowParentPos *src,
-               GdkWindowObject *obj, GdkXPositionInfo *pos_info,
-               gboolean set_clip)
-{
-  dest->x = src->x + obj->x;
-  dest->y = src->y + obj->y;
-  dest->x11_x = src->x11_x + pos_info->x;
-  dest->x11_y = src->x11_y + pos_info->y;
-
-  if (set_clip)
-      dest->clip_rect = pos_info->clip_rect;
-}
-
-static void
-move (GdkWindow *window, GdkXPositionInfo *pos)
-{
-  XMoveWindow (GDK_WINDOW_XDISPLAY (window),
-               GDK_WINDOW_XID (window), pos->x, pos->y);
-}
-
-static void
-move_relative (GdkWindow *window, GdkRectangle *rect,
-               gint dx, gint dy)
-{
-  XMoveWindow (GDK_WINDOW_XDISPLAY (window),
-               GDK_WINDOW_XID (window),
-               rect->x + dx, rect->y + dy);
-}
-
-static void
-move_resize (GdkWindow *window, GdkRectangle *pos)
-{
-  XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
-                     GDK_WINDOW_XID (window),
-                     pos->x, pos->y, pos->width, pos->height);
-}
-
-static void
-gdk_window_guffaw_scroll (GdkWindow    *window,
-                         gint          dx,
-                         gint          dy)
-{
-  GdkWindowObject *obj = GDK_WINDOW_OBJECT (window);
-  GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-
-  gint d_xoffset = -dx;
-  gint d_yoffset = -dy;
-  GdkRectangle new_position;
-  GdkXPositionInfo new_info;
-  GdkWindowParentPos parent_pos;
-  GList *l;
-  
-  gdk_window_compute_parent_pos (impl, &parent_pos);
-  gdk_window_compute_position (impl, &parent_pos, &new_info);
-
-  translate_pos (&parent_pos, &parent_pos, obj, &new_info, TRUE);
-
-  _gdk_x11_window_tmp_unset_bg (window, FALSE);;
-
-  if (dx > 0 || dy > 0)
-    gdk_window_queue_translation (window, NULL, MAX (dx, 0), MAX (dy, 0));
-       
-  gdk_window_set_static_gravities (window, TRUE);
-
-  compute_intermediate_position (&impl->position_info, &new_info, d_xoffset, d_yoffset,
-                                &new_position);
-  
-  move_resize (window, &new_position);
-  
-  for (l = obj->children; l; l = l->next)
-    {
-      GdkWindow *child = (GdkWindow*) l->data;
-      GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
-
-      child_obj->x -= d_xoffset;
-      child_obj->y -= d_yoffset;
-
-      gdk_window_premove (child, &parent_pos);
-    }
-  
-  move_relative (window, &new_position, -d_xoffset, -d_yoffset);
-  
-  if (dx < 0 || dy < 0)
-    gdk_window_queue_translation (window, NULL, MIN (dx, 0), MIN (dy, 0));
-  
-  move_resize (window, (GdkRectangle *) &impl->position_info);
-  
-  if (impl->position_info.no_bg)
-    _gdk_x11_window_tmp_reset_bg (window, FALSE);
-  
-  impl->position_info = new_info;
-  
-  g_list_foreach (obj->children, (GFunc) gdk_window_postmove, &parent_pos);
-}
-
-void
-_gdk_x11_window_scroll (GdkWindow *window,
-                        gint       dx,
-                        gint       dy)
-{
-  gboolean can_guffaw_scroll = FALSE;
-  GdkRegion *invalidate_region;
-  GdkWindowImplX11 *impl;
-  GdkWindowObject *obj;
-  GdkRectangle src_rect, dest_rect;
-  
-  obj = GDK_WINDOW_OBJECT (window);
-  impl = GDK_WINDOW_IMPL_X11 (obj->impl);  
-
-  /* Move the current invalid region */
-  if (obj->update_area)
-    gdk_region_offset (obj->update_area, dx, dy);
-  
-  /* impl->position_info.clip_rect isn't meaningful for toplevels */
-  if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
-    src_rect = impl->position_info.clip_rect;
-  else
-    {
-      src_rect.x = 0;
-      src_rect.y = 0;
-      src_rect.width = impl->width;
-      src_rect.height = impl->height;
-    }
-  
-  invalidate_region = gdk_region_rectangle (&src_rect);
-
-  dest_rect = src_rect;
-  dest_rect.x += dx;
-  dest_rect.y += dy;
-  gdk_rectangle_intersect (&dest_rect, &src_rect, &dest_rect);
-
-  if (dest_rect.width > 0 && dest_rect.height > 0)
-    {
-      GdkRegion *tmp_region;
-
-      tmp_region = gdk_region_rectangle (&dest_rect);
-      gdk_region_subtract (invalidate_region, tmp_region);
-      gdk_region_destroy (tmp_region);
-    }
-  
-  gdk_window_invalidate_region (window, invalidate_region, TRUE);
-  gdk_region_destroy (invalidate_region);
-
-  /* We can guffaw scroll if we are a child window, and the parent
-   * does not extend beyond our edges. Otherwise, we use XCopyArea, then
-   * move any children later
-   */
-  if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
-    {
-      GdkWindowImplX11 *parent_impl = GDK_WINDOW_IMPL_X11 (obj->parent->impl);  
-      can_guffaw_scroll = ((dx == 0 || (obj->x <= 0 && obj->x + impl->width >= parent_impl->width)) &&
-                          (dy == 0 || (obj->y <= 0 && obj->y + impl->height >= parent_impl->height)));
-    }
-
-  if (!obj->children || !can_guffaw_scroll)
-    gdk_window_copy_area_scroll (window, &dest_rect, dx, dy);
-  else
-    gdk_window_guffaw_scroll (window, dx, dy);
-}
-
-void
-_gdk_x11_window_move_region (GdkWindow       *window,
-                             const GdkRegion *region,
-                             gint             dx,
-                             gint             dy)
-{
-  GdkWindowImplX11 *impl;
-  GdkWindowObject *private;
-  GdkRegion *window_clip;
-  GdkRegion *src_region;
-  GdkRegion *brought_in;
-  GdkRegion *dest_region;
-  GdkRegion *moving_invalid_region;
-  GdkRectangle dest_extents;
-  GdkGC *gc;
-  
-  private = GDK_WINDOW_OBJECT (window);
-  impl = GDK_WINDOW_IMPL_X11 (private->impl);  
-
-  window_clip = gdk_region_rectangle (&impl->position_info.clip_rect);
-
-  /* compute source regions */
-  src_region = gdk_region_copy (region);
-  brought_in = gdk_region_copy (region);
-  gdk_region_intersect (src_region, window_clip);
-
-  gdk_region_subtract (brought_in, src_region);
-  gdk_region_offset (brought_in, dx, dy);
-
-  /* compute destination regions */
-  dest_region = gdk_region_copy (src_region);
-  gdk_region_offset (dest_region, dx, dy);
-  gdk_region_intersect (dest_region, window_clip);
-  gdk_region_get_clipbox (dest_region, &dest_extents);
-
-  gdk_region_destroy (window_clip);
-
-  /* calculating moving part of current invalid area */
-  moving_invalid_region = NULL;
-  if (private->update_area)
-    {
-      moving_invalid_region = gdk_region_copy (private->update_area);
-      gdk_region_intersect (moving_invalid_region, src_region);
-      gdk_region_offset (moving_invalid_region, dx, dy);
-    }
-  
-  /* invalidate all of the src region */
-  gdk_window_invalidate_region (window, src_region, FALSE);
-
-  /* un-invalidate destination region */
-  if (private->update_area)
-    gdk_region_subtract (private->update_area, dest_region);
-  
-  /* invalidate moving parts of existing update area */
-  if (moving_invalid_region)
-    {
-      gdk_window_invalidate_region (window, moving_invalid_region, FALSE);
-      gdk_region_destroy (moving_invalid_region);
-    }
-
-  /* invalidate area brought in from off-screen */
-  gdk_window_invalidate_region (window, brought_in, FALSE);
-  gdk_region_destroy (brought_in);
-
-  /* Actually do the moving */
-  gdk_window_queue_translation (window, src_region, dx, dy);
-
-  gc = _gdk_drawable_get_scratch_gc (window, TRUE);
-  gdk_gc_set_clip_region (gc, dest_region);
-  
-  XCopyArea (GDK_WINDOW_XDISPLAY (window),
-            GDK_WINDOW_XID (window),
-            GDK_WINDOW_XID (window),
-            GDK_GC_XGC (gc),
-            dest_extents.x - dx, dest_extents.y - dy,
-            dest_extents.width, dest_extents.height,
-            dest_extents.x, dest_extents.y);
-
-  /* Unset clip region of cached GC */
-  gdk_gc_set_clip_region (gc, NULL);
-  
-  gdk_region_destroy (src_region);
-  gdk_region_destroy (dest_region);
-}
-
-static void
-reset_backgrounds (GdkWindow *window)
-{
-  GdkWindowObject *obj = (GdkWindowObject *)window;
-
-  _gdk_x11_window_tmp_reset_bg (window, FALSE);
-  
-  if (obj->parent)
-    _gdk_x11_window_tmp_reset_bg ((GdkWindow *)obj->parent, FALSE);
-}
-
-static void
-map_if_needed (GdkWindow *window, GdkXPositionInfo *pos_info)
-{
-  GdkWindowObject *obj = (GdkWindowObject *) window;
-  GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-
-  if (!impl->position_info.mapped && pos_info->mapped && GDK_WINDOW_IS_MAPPED (obj))
-    XMapWindow (GDK_DRAWABLE_XDISPLAY (window), GDK_DRAWABLE_XID (window));
-}
-
-static void
-unmap_if_needed (GdkWindow *window, GdkXPositionInfo *pos_info)
-{
-  GdkWindowObject *obj = (GdkWindowObject *) window;
-  GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-
-  if (impl->position_info.mapped && !pos_info->mapped)
-    XUnmapWindow (GDK_DRAWABLE_XDISPLAY (window), GDK_DRAWABLE_XID (window));
-}
-
 void
 _gdk_window_move_resize_child (GdkWindow *window,
                               gint       x,
@@ -585,15 +174,6 @@ _gdk_window_move_resize_child (GdkWindow *window,
 {
   GdkWindowImplX11 *impl;
   GdkWindowObject *obj;
-  GdkXPositionInfo new_info;
-  GdkWindowParentPos parent_pos;
-  
-  gint d_xoffset, d_yoffset;
-  gint dx, dy;
-  gboolean is_move;
-  gboolean is_resize;
-
-  GdkRectangle old_pos;
   
   g_return_if_fail (window != NULL);
   g_return_if_fail (GDK_IS_WINDOW (window)); 
@@ -601,325 +181,36 @@ _gdk_window_move_resize_child (GdkWindow *window,
   impl = GDK_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (window)->impl);
   obj = GDK_WINDOW_OBJECT (window);
 
-  dx = x - obj->x;
-  dy = y - obj->y;
-  
-  is_move = dx != 0 || dy != 0;
-  is_resize = impl->width != width || impl->height != height;
-
-  if (!is_move && !is_resize)
-    return;
-  
-  old_pos.x = obj->x;
-  old_pos.y = obj->y;
-  old_pos.width = impl->width;
-  old_pos.height = impl->height;
-
-  obj->x = x;
-  obj->y = y;
-  impl->width = width;
-  impl->height = height;
-
-  gdk_window_compute_parent_pos (impl, &parent_pos);
-  gdk_window_compute_position (impl, &parent_pos, &new_info);
-
-  gdk_window_clip_changed (window, &impl->position_info.clip_rect, &new_info.clip_rect);
-
-  translate_pos (&parent_pos, &parent_pos, obj, &new_info, TRUE);
-
-  d_xoffset = new_info.x_offset - impl->position_info.x_offset;
-  d_yoffset = new_info.y_offset - impl->position_info.y_offset;
-  
-  if (d_xoffset != 0 || d_yoffset != 0)
+  if (width > 65535 ||
+      height > 65535)
     {
-      GdkRectangle new_position;
-
-      gdk_window_set_static_gravities (window, TRUE);
-
-      if (d_xoffset < 0 || d_yoffset < 0)
-       gdk_window_queue_translation (window, NULL, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
-
-      compute_intermediate_position (&impl->position_info, &new_info, d_xoffset, d_yoffset,
-                                    &new_position);
+      g_warning ("Native children wider or taller than 65535 pixels are not supported");
       
-      move_resize (window, &new_position);
-      
-      g_list_foreach (obj->children, (GFunc) gdk_window_premove, &parent_pos);
-
-      move_relative (window, &new_position, dx, dy);
-      
-      if (d_xoffset > 0 || d_yoffset > 0)
-       gdk_window_queue_translation (window, NULL, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
-      
-      move_resize (window, (GdkRectangle *) &new_info);
-
-      reset_backgrounds (window);
-
-      map_if_needed (window, &new_info);
-      
-      impl->position_info = new_info;
-      
-      g_list_foreach (obj->children, (GFunc) gdk_window_postmove, &parent_pos);
+      if (width > 65535)
+       width = 65535;
+      if (height > 65535)
+       height = 65535;
     }
-  else
-    {
-      if (is_move && is_resize)
-       gdk_window_set_static_gravities (window, FALSE);
-
-      unmap_if_needed (window, &new_info);
-      
-      g_list_foreach (obj->children, (GFunc) gdk_window_premove, &parent_pos);
-
-      if (is_resize)
-          move_resize (window, (GdkRectangle *) &new_info);
-      else
-          move (window, &new_info);
-
-      g_list_foreach (obj->children, (GFunc) gdk_window_postmove, &parent_pos);
-
-      reset_backgrounds (window);
-      
-      map_if_needed (window, &new_info);
-
-      impl->position_info = new_info;
-    }
-
-  if (GDK_WINDOW_IS_MAPPED (obj) && obj->parent && !obj->input_only)
-    gdk_window_invalidate_rect ((GdkWindow *)obj->parent, &old_pos, FALSE);
-}
-
-static void
-gdk_window_compute_position (GdkWindowImplX11   *window,
-                            GdkWindowParentPos *parent_pos,
-                            GdkXPositionInfo   *info)
-{
-  GdkWindowObject *wrapper;
-  int parent_x_offset;
-  int parent_y_offset;
-
-  g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (window));
-
-  wrapper = GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_X11 (window)->wrapper);
-  
-  info->big = FALSE;
-  
-  if (window->width <= 32767)
-    {
-      info->width = window->width;
-      info->x = parent_pos->x + wrapper->x - parent_pos->x11_x;
-    }
-  else
-    {
-      info->big = TRUE;
-      info->width = 32767;
-      if (parent_pos->x + wrapper->x < -16384)
-       {
-         if (parent_pos->x + wrapper->x + window->width < 16384)
-           info->x = parent_pos->x + wrapper->x + window->width - info->width - parent_pos->x11_x;
-         else
-           info->x = -16384 - parent_pos->x11_x;
-       }
-      else
-       info->x = parent_pos->x + wrapper->x - parent_pos->x11_x;
-    }
-
-  if (window->height <= 32767)
-    {
-      info->height = window->height;
-      info->y = parent_pos->y + wrapper->y - parent_pos->x11_y;
-    }
-  else
-    {
-      info->big = TRUE;
-      info->height = 32767;
-      if (parent_pos->y + wrapper->y < -16384)
-       {
-         if (parent_pos->y + wrapper->y + window->height < 16384)
-           info->y = parent_pos->y + wrapper->y + window->height - info->height - parent_pos->x11_y;
-         else
-           info->y = -16384 - parent_pos->x11_y;
-       }
-      else
-       info->y = parent_pos->y + wrapper->y - parent_pos->x11_y;
-    }
-
-  parent_x_offset = parent_pos->x11_x - parent_pos->x;
-  parent_y_offset = parent_pos->x11_y - parent_pos->y;
   
-  info->x_offset = parent_x_offset + info->x - wrapper->x;
-  info->y_offset = parent_y_offset + info->y - wrapper->y;
-
-  /* We don't considering the clipping of toplevel windows and their immediate children
-   * by their parents, and simply always map those windows.
-   */
-  if (parent_pos->clip_rect.width == G_MAXINT)
-    info->mapped = TRUE;
-  /* Check if the window would wrap around into the visible space in either direction */
-  else if (info->x + parent_x_offset < parent_pos->clip_rect.x + parent_pos->clip_rect.width - 65536 ||
-      info->x + info->width + parent_x_offset > parent_pos->clip_rect.x + 65536 ||
-      info->y + parent_y_offset < parent_pos->clip_rect.y + parent_pos->clip_rect.height - 65536 ||
-      info->y + info->height + parent_y_offset  > parent_pos->clip_rect.y + 65536)
-    info->mapped = FALSE;
-  else
-    info->mapped = TRUE;
-
-  info->no_bg = FALSE;
-
-  if (GDK_WINDOW_TYPE (wrapper) == GDK_WINDOW_CHILD)
-    {
-      info->clip_rect.x = wrapper->x;
-      info->clip_rect.y = wrapper->y;
-      info->clip_rect.width = window->width;
-      info->clip_rect.height = window->height;
-      
-      gdk_rectangle_intersect (&info->clip_rect, &parent_pos->clip_rect, &info->clip_rect);
-
-      info->clip_rect.x -= wrapper->x;
-      info->clip_rect.y -= wrapper->y;
-    }
-  else
-    {
-      info->clip_rect.x = 0;
-      info->clip_rect.y = 0;
-      info->clip_rect.width = G_MAXINT;
-      info->clip_rect.height = G_MAXINT;
-    }
-}
-
-static void
-gdk_window_compute_parent_pos (GdkWindowImplX11      *window,
-                              GdkWindowParentPos *parent_pos)
-{
-  GdkWindowObject *wrapper;
-  GdkWindowObject *parent;
-  GdkRectangle tmp_clip;
-  
-  int clip_xoffset = 0;
-  int clip_yoffset = 0;
-
-  g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (window));
-
-  wrapper =
-    GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_X11 (window)->wrapper);
-  
-  parent_pos->x = 0;
-  parent_pos->y = 0;
-  parent_pos->x11_x = 0;
-  parent_pos->x11_y = 0;
-
-  /* We take a simple approach here and simply consider toplevel
-   * windows not to clip their children on the right/bottom, since the
-   * size of toplevel windows is not directly under our
-   * control. Clipping only really matters when scrolling and
-   * generally we aren't going to be moving the immediate child of a
-   * toplevel beyond the bounds of that toplevel.
-   *
-   * We could go ahead and recompute the clips of toplevel windows and
-   * their descendents when we receive size notification, but it would
-   * probably not be an improvement in most cases.
-   */
-  parent_pos->clip_rect.x = 0;
-  parent_pos->clip_rect.y = 0;
-  parent_pos->clip_rect.width = G_MAXINT;
-  parent_pos->clip_rect.height = G_MAXINT;
-
-  parent = (GdkWindowObject *)wrapper->parent;
-  while (parent && parent->window_type == GDK_WINDOW_CHILD)
-    {
-      GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (parent->impl);
-      
-      tmp_clip.x = - clip_xoffset;
-      tmp_clip.y = - clip_yoffset;
-      tmp_clip.width = impl->width;
-      tmp_clip.height = impl->height;
-
-      gdk_rectangle_intersect (&parent_pos->clip_rect, &tmp_clip, &parent_pos->clip_rect);
-
-      translate_pos (parent_pos, parent_pos, parent,
-                     &impl->position_info, FALSE);
-
-      clip_xoffset += parent->x;
-      clip_yoffset += parent->y;
-
-      parent = (GdkWindowObject *)parent->parent;
-    }
-}
-
-static void
-gdk_window_premove (GdkWindow          *window,
-                   GdkWindowParentPos *parent_pos)
-{
-  GdkWindowImplX11 *impl;
-  GdkWindowObject *obj;
-  GdkXPositionInfo new_info;
-  gint d_xoffset, d_yoffset;
-  GdkWindowParentPos this_pos;
-
-  obj = (GdkWindowObject *) window;
-  impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-  
-  gdk_window_compute_position (impl, parent_pos, &new_info);
-
-  gdk_window_clip_changed (window, &impl->position_info.clip_rect, &new_info.clip_rect);
-
-  translate_pos (&this_pos, parent_pos, obj, &new_info, TRUE);
-
-  unmap_if_needed (window, &new_info);
-
-  d_xoffset = new_info.x_offset - impl->position_info.x_offset;
-  d_yoffset = new_info.y_offset - impl->position_info.y_offset;
-  
-  if (d_xoffset != 0 || d_yoffset != 0)
-    {
-      GdkRectangle new_position;
-
-      if (d_xoffset < 0 || d_yoffset < 0)
-       gdk_window_queue_translation (window, NULL, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
-
-      compute_intermediate_position (&impl->position_info, &new_info, d_xoffset, d_yoffset,
-                                    &new_position);
-
-      move_resize (window, &new_position);
-    }
-
-  g_list_foreach (obj->children, (GFunc) gdk_window_premove, &this_pos);
-}
-
-static void
-gdk_window_postmove (GdkWindow          *window,
-                    GdkWindowParentPos *parent_pos)
-{
-  GdkWindowImplX11 *impl;
-  GdkWindowObject *obj;
-  GdkXPositionInfo new_info;
-  gint d_xoffset, d_yoffset;
-  GdkWindowParentPos this_pos;
-
-  obj = (GdkWindowObject *) window;
-  impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-  
-  gdk_window_compute_position (impl, parent_pos, &new_info);
+  obj->x = x;
+  obj->y = y;
+  obj->width = width;
+  obj->height = height;
 
-  translate_pos (&this_pos, parent_pos, obj, &new_info, TRUE);
+  /* We don't really care about origin overflow, because on overflow
+     the window won't be visible anyway and thus it will be shaped
+     to nothing */
 
-  d_xoffset = new_info.x_offset - impl->position_info.x_offset;
-  d_yoffset = new_info.y_offset - impl->position_info.y_offset;
   
-  if (d_xoffset != 0 || d_yoffset != 0)
-    {
-      if (d_xoffset > 0 || d_yoffset > 0)
-       gdk_window_queue_translation (window, NULL, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
-       
-      move_resize (window, (GdkRectangle *) &new_info);
-    }
-
-  map_if_needed (window, &new_info);
-
-  reset_backgrounds (window);
-
-  impl->position_info = new_info;
-
-  g_list_foreach (obj->children, (GFunc) gdk_window_postmove, &this_pos);
+  _gdk_x11_window_tmp_unset_parent_bg (window);
+  _gdk_x11_window_tmp_unset_bg (window, TRUE);
+  XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
+                    GDK_WINDOW_XID (window),
+                    obj->x + obj->parent->abs_x,
+                    obj->y + obj->parent->abs_y,
+                    width, height);
+  _gdk_x11_window_tmp_reset_parent_bg (window);
+  _gdk_x11_window_tmp_reset_bg (window, TRUE);
 }
 
 static Bool
@@ -1050,11 +341,11 @@ gdk_window_queue (GdkWindow          *window,
   g_queue_push_tail (display_x11->translate_queue, item);
 }
 
-static void
-gdk_window_queue_translation (GdkWindow *window,
-                             GdkRegion *area,
-                             gint       dx,
-                             gint       dy)
+void
+_gdk_x11_window_queue_translation (GdkWindow *window,
+                                  GdkRegion *area,
+                                  gint       dx,
+                                  gint       dy)
 {
   GdkWindowQueueItem *item = g_new (GdkWindowQueueItem, 1);
   item->type = GDK_WINDOW_QUEUE_TRANSLATE;
@@ -1066,8 +357,8 @@ gdk_window_queue_translation (GdkWindow *window,
 }
 
 gboolean
-_gdk_windowing_window_queue_antiexpose (GdkWindow *window,
-                                       GdkRegion *area)
+_gdk_x11_window_queue_antiexpose (GdkWindow *window,
+                                 GdkRegion *area)
 {
   GdkWindowQueueItem *item = g_new (GdkWindowQueueItem, 1);
   item->type = GDK_WINDOW_QUEUE_ANTIEXPOSE;
@@ -1085,7 +376,6 @@ _gdk_window_process_expose (GdkWindow    *window,
 {
   GdkWindowImplX11 *impl;
   GdkRegion *invalidate_region = gdk_region_rectangle (area);
-  GdkRegion *clip_region;
   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
   impl = GDK_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (window)->impl);
 
@@ -1134,57 +424,10 @@ _gdk_window_process_expose (GdkWindow    *window,
        }
     }
 
-  clip_region = gdk_region_rectangle (&impl->position_info.clip_rect);
-  gdk_region_intersect (invalidate_region, clip_region);
-
   if (!gdk_region_empty (invalidate_region))
-    gdk_window_invalidate_region (window, invalidate_region, FALSE);
+    _gdk_window_invalidate_for_expose (window, invalidate_region);
   
   gdk_region_destroy (invalidate_region);
-  gdk_region_destroy (clip_region);
-}
-
-static void
-gdk_window_clip_changed (GdkWindow *window, GdkRectangle *old_clip, GdkRectangle *new_clip)
-{
-  GdkWindowImplX11 *impl;
-  GdkWindowObject *obj;
-  GdkRegion *old_clip_region;
-  GdkRegion *new_clip_region;
-  
-  if (((GdkWindowObject *)window)->input_only)
-    return;
-
-  obj = (GdkWindowObject *) window;
-  impl = GDK_WINDOW_IMPL_X11 (obj->impl);
-  
-  old_clip_region = gdk_region_rectangle (old_clip);
-  new_clip_region = gdk_region_rectangle (new_clip);
-
-  /* We need to update this here because gdk_window_invalidate_region makes
-   * use if it (through gdk_drawable_get_visible_region
-   */
-  impl->position_info.clip_rect = *new_clip;
-  
-  /* Trim invalid region of window to new clip rectangle
-   */
-  if (obj->update_area)
-    gdk_region_intersect (obj->update_area, new_clip_region);
-
-  /* Invalidate newly exposed portion of window
-   */
-  gdk_region_subtract (new_clip_region, old_clip_region);
-  if (!gdk_region_empty (new_clip_region))
-    {
-      _gdk_x11_window_tmp_unset_bg (window, FALSE);;
-      gdk_window_invalidate_region (window, new_clip_region, FALSE);
-    }
-
-  if (obj->parent)
-    _gdk_x11_window_tmp_unset_bg ((GdkWindow *)obj->parent, FALSE);
-  
-  gdk_region_destroy (new_clip_region);
-  gdk_region_destroy (old_clip_region);
 }
 
 #define __GDK_GEOMETRY_X11_C__
index 38dc59c14fa77cf1a0f9a10ab22854970f53cf91..4d21beff34bdca31800ae0d3f383b700c41b5df4 100644 (file)
@@ -37,7 +37,7 @@ _gdk_input_init (GdkDisplay *display)
   _gdk_init_input_core (display);
   
   display_x11->input_devices = g_list_append (NULL, display->core_pointer);
-  display_x11->input_ignore_core = FALSE;
+  display->ignore_core_events = FALSE;
 }
 
 void 
@@ -72,16 +72,10 @@ _gdk_device_get_history (GdkDevice         *device,
   return FALSE;
 }
 
-gboolean
-_gdk_input_enable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
-{
-  return TRUE;
-}
-
-gboolean
-_gdk_input_disable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
+void
+_gdk_input_select_events (GdkWindow        *impl_window,
+                         GdkDevicePrivate *gdkdev)
 {
-  return TRUE;
 }
 
 gboolean
@@ -99,13 +93,14 @@ _gdk_input_configure_event (XConfigureEvent *xevent,
 }
 
 void 
-_gdk_input_enter_event (XCrossingEvent *xevent, 
-                       GdkWindow      *window)
+_gdk_input_crossing_event (GdkWindow *window,
+                          gboolean enter)
 {
 }
 
 gint 
 _gdk_input_grab_pointer (GdkWindow *     window,
+                        GdkWindow      *native_window,
                         gint            owner_events,
                         GdkEventMask    event_mask,
                         GdkWindow *     confine_to,
index 8faf7048459c1f20fc672bbfe82a81c8ac707e5b..22e39a05c715778bce8f5a68d397e44994e66f6f 100644 (file)
@@ -21,7 +21,7 @@
  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
  * file for a list of people on the GTK+ Team.  See the ChangeLog
  * files for a list of changes.  These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
  */
 
 #include "config.h"
@@ -39,7 +39,7 @@ static GdkDevicePrivate *gdk_input_device_new            (GdkDisplay       *disp
                                                          XDeviceInfo      *device,
                                                          gint              include_core);
 static void              gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
-                                                         GdkInputWindow   *input_window,
+                                                         GdkWindow        *window,
                                                          gint             *axis_data,
                                                          gdouble          *axis_out,
                                                          gdouble          *x_out,
@@ -64,37 +64,26 @@ _gdk_input_find_device (GdkDisplay *display,
 }
 
 void
-_gdk_input_get_root_relative_geometry(Display *display, Window w, int *x_ret, int *y_ret,
-                                     int *width_ret, int *height_ret)
+_gdk_input_get_root_relative_geometry (GdkWindow *window,
+                                      int *x_ret, int *y_ret)
 {
-  Window root, parent, child;
-  Window *children;
-  guint nchildren;
+  Window child;
   gint x,y;
-  guint width, height;
-  guint border_widthc, depthc;
-   
-  XQueryTree (display, w, &root, &parent, &children, &nchildren);
-  if (children)
-    XFree(children);
-  
-  XGetGeometry (display, w, &root, &x, &y, &width, &height, &border_widthc, &depthc);
-
-  XTranslateCoordinates (display, w, root, 0, 0, &x, &y, &child);
+
+  XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window),
+                        GDK_WINDOW_XWINDOW (window),
+                        GDK_WINDOW_XROOTWIN (window),
+                        0, 0, &x, &y, &child);
+
   if (x_ret)
     *x_ret = x;
   if (y_ret)
     *y_ret = y;
-  if (width_ret)
-    *width_ret = width;
-  if (height_ret)
-    *height_ret = height;
 }
 
 static GdkDevicePrivate *
 gdk_input_device_new (GdkDisplay  *display,
-                     XDeviceInfo *device, 
+                     XDeviceInfo *device,
                      gint         include_core)
 {
   GdkDevicePrivate *gdkdev;
@@ -121,7 +110,7 @@ gdk_input_device_new (GdkDisplay  *display,
      for comparison purposes */
 
   tmp_name = g_ascii_strdown (gdkdev->info.name, -1);
-  
+
   if (!strcmp (tmp_name, "pointer"))
     gdkdev->info.source = GDK_SOURCE_MOUSE;
   else if (!strcmp (tmp_name, "wacom") ||
@@ -151,7 +140,7 @@ gdk_input_device_new (GdkDisplay  *display,
   gdkdev->button_state = 0;
 
   class = device->inputclassinfo;
-  for (i=0;i<device->num_classes;i++) 
+  for (i=0;i<device->num_classes;i++)
     {
       switch (class->class) {
       case ButtonClass:
@@ -160,7 +149,7 @@ gdk_input_device_new (GdkDisplay  *display,
        {
          XKeyInfo *xki = (XKeyInfo *)class;
          /* Hack to catch XFree86 3.3.1 bug. Other devices better
-          * not have exactly 25 keys... 
+          * not have exactly 25 keys...
           */
          if ((xki->min_keycode == 8) && (xki->max_keycode == 32))
            {
@@ -190,7 +179,7 @@ gdk_input_device_new (GdkDisplay  *display,
          gdkdev->info.axes = g_new0 (GdkDeviceAxis, xvi->num_axes);
          for (j=0;j<xvi->num_axes;j++)
            {
-             gdkdev->axes[j].resolution = 
+             gdkdev->axes[j].resolution =
                gdkdev->axes[j].xresolution = xvi->axes[j].resolution;
              gdkdev->axes[j].min_value =
                gdkdev->axes[j].xmin_value = xvi->axes[j].min_value;
@@ -211,7 +200,7 @@ gdk_input_device_new (GdkDisplay  *display,
            gdk_device_set_axis_use (&gdkdev->info, j++, GDK_AXIS_YTILT);
          if (j<xvi->num_axes)
            gdk_device_set_axis_use (&gdkdev->info, j++, GDK_AXIS_WHEEL);
-                      
+
          break;
        }
       }
@@ -247,20 +236,19 @@ gdk_input_device_new (GdkDisplay  *display,
  error:
 
   g_object_unref (gdkdev);
-  
+
   return NULL;
 }
 
 void
-_gdk_input_common_find_events(GdkWindow *window,
-                             GdkDevicePrivate *gdkdev,
-                             gint mask,
-                             XEventClass *classes,
-                             int *num_classes)
+_gdk_input_common_find_events (GdkDevicePrivate *gdkdev,
+                              gint mask,
+                              XEventClass *classes,
+                              int *num_classes)
 {
   gint i;
   XEventClass class;
-  
+
   i = 0;
   if (mask & GDK_BUTTON_PRESS_MASK)
     {
@@ -354,25 +342,42 @@ _gdk_input_common_find_events(GdkWindow *window,
 }
 
 void
-_gdk_input_common_select_events(GdkWindow *window,
-                               GdkDevicePrivate *gdkdev)
+_gdk_input_select_events (GdkWindow *impl_window,
+                         GdkDevicePrivate *gdkdev)
 {
   XEventClass classes[GDK_MAX_DEVICE_CLASSES];
   gint num_classes;
+  guint event_mask;
+  GdkWindowObject *w;
+  GdkInputWindow *iw;
+  GList *l;
 
-  if (gdkdev->info.mode == GDK_MODE_DISABLED)
-    _gdk_input_common_find_events(window, gdkdev, 0, classes, &num_classes);
-  else
-    _gdk_input_common_find_events(window, gdkdev, 
-                                 ((GdkWindowObject *)window)->extension_events,
-                                 classes, &num_classes);
-  
-  XSelectExtensionEvent (GDK_WINDOW_XDISPLAY (window),
-                        GDK_WINDOW_XWINDOW (window),
+  event_mask = 0;
+  iw = ((GdkWindowObject *)impl_window)->input_window;
+
+  if (gdkdev->info.mode != GDK_MODE_DISABLED &&
+      iw != NULL)
+    {
+      for (l = iw->windows; l != NULL; l = l->next)
+       {
+         w = l->data;
+         if (gdkdev->info.has_cursor || (w->extension_events & GDK_ALL_DEVICES_MASK))
+           event_mask |= w->extension_events;
+       }
+    }
+  event_mask &= ~GDK_ALL_DEVICES_MASK;
+
+  if (event_mask)
+    event_mask |= GDK_PROXIMITY_OUT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK;
+
+  _gdk_input_common_find_events (gdkdev, event_mask,
+                                classes, &num_classes);
+  XSelectExtensionEvent (GDK_WINDOW_XDISPLAY (impl_window),
+                        GDK_WINDOW_XWINDOW (impl_window),
                         classes, num_classes);
 }
 
-gint 
+gint
 _gdk_input_common_init (GdkDisplay *display,
                        gint        include_core)
 {
@@ -391,7 +396,7 @@ _gdk_input_common_init (GdkDisplay *display,
                                            event_base, 15 /* Number of events */);
 
       devices = XListInputDevices(display_x11->xdisplay, &num_devices);
-  
+
       for(loop=0; loop<num_devices; loop++)
        {
          GdkDevicePrivate *gdkdev = gdk_input_device_new(display,
@@ -410,13 +415,14 @@ _gdk_input_common_init (GdkDisplay *display,
 
 static void
 gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
-                                GdkInputWindow   *input_window,
+                                GdkWindow        *window,
                                 gint             *axis_data,
                                 gdouble          *axis_out,
                                 gdouble          *x_out,
                                 gdouble          *y_out)
 {
-  GdkWindowImplX11 *impl;
+  GdkWindowObject *priv, *impl_window;
+
   int i;
   int x_axis = 0;
   int y_axis = 0;
@@ -424,7 +430,8 @@ gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
   double device_width, device_height;
   double x_offset, y_offset, x_scale, y_scale;
 
-  impl = GDK_WINDOW_IMPL_X11 (((GdkWindowObject *) input_window->window)->impl);
+  priv = (GdkWindowObject *) window;
+  impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window);
 
   for (i=0; i<gdkdev->info.num_axes; i++)
     {
@@ -440,26 +447,24 @@ gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
          break;
        }
     }
-  
-  device_width = gdkdev->axes[x_axis].max_value - 
-                  gdkdev->axes[x_axis].min_value;
-  device_height = gdkdev->axes[y_axis].max_value - 
-                    gdkdev->axes[y_axis].min_value;
 
-  if (gdkdev->info.mode == GDK_MODE_SCREEN) 
+  device_width = gdkdev->axes[x_axis].max_value - gdkdev->axes[x_axis].min_value;
+  device_height = gdkdev->axes[y_axis].max_value - gdkdev->axes[y_axis].min_value;
+
+  if (gdkdev->info.mode == GDK_MODE_SCREEN)
     {
-      x_scale = gdk_screen_get_width (gdk_drawable_get_screen (input_window->window)) / device_width;
-      y_scale = gdk_screen_get_height (gdk_drawable_get_screen (input_window->window)) / device_height;
+      x_scale = gdk_screen_get_width (gdk_drawable_get_screen (window)) / device_width;
+      y_scale = gdk_screen_get_height (gdk_drawable_get_screen (window)) / device_height;
 
-      x_offset = - input_window->root_x;
-      y_offset = - input_window->root_y;
+      x_offset = - impl_window->input_window->root_x;
+      y_offset = - impl_window->input_window->root_y;
     }
   else                         /* GDK_MODE_WINDOW */
     {
       double x_resolution = gdkdev->axes[x_axis].resolution;
       double y_resolution = gdkdev->axes[y_axis].resolution;
       double device_aspect;
-      /* 
+      /*
        * Some drivers incorrectly report the resolution of the device
        * as zero (in partiular linuxwacom < 0.5.3 with usb tablets).
        * This causes the device_aspect to become NaN and totally
@@ -475,27 +480,24 @@ gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
          y_resolution = 1;
        }
       device_aspect = (device_height*y_resolution) /
-        (device_width*x_resolution);
-      if (device_aspect * impl->width >= impl->height)
+       (device_width*x_resolution);
+      if (device_aspect * priv->width >= priv->height)
        {
          /* device taller than window */
-         x_scale = impl->width / device_width;
-         y_scale = (x_scale * x_resolution)
-           / y_resolution;
+         x_scale = priv->width / device_width;
+         y_scale = (x_scale * x_resolution) / y_resolution;
 
          x_offset = 0;
-         y_offset = -(device_height * y_scale - 
-                              impl->height)/2;
+         y_offset = -(device_height * y_scale -  priv->height)/2;
        }
       else
        {
          /* window taller than device */
-         y_scale = impl->height / device_height;
-         x_scale = (y_scale * y_resolution)
-           / x_resolution;
+         y_scale = priv->height / device_height;
+         x_scale = (y_scale * y_resolution) / x_resolution;
 
          y_offset = 0;
-         x_offset = - (device_width * x_scale - impl->width)/2;
+         x_offset = - (device_width * x_scale - priv->width)/2;
        }
     }
 
@@ -504,13 +506,13 @@ gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
       switch (gdkdev->info.axes[i].use)
        {
        case GDK_AXIS_X:
-         axis_out[i] = x_offset + x_scale * (axis_data[x_axis] - 
+         axis_out[i] = x_offset + x_scale * (axis_data[x_axis] -
            gdkdev->axes[x_axis].min_value);
          if (x_out)
            *x_out = axis_out[i];
          break;
        case GDK_AXIS_Y:
-         axis_out[i] = y_offset + y_scale * (axis_data[y_axis] - 
+         axis_out[i] = y_offset + y_scale * (axis_data[y_axis] -
            gdkdev->axes[y_axis].min_value);
          if (y_out)
            *y_out = axis_out[i];
@@ -541,11 +543,18 @@ gdk_input_translate_state(guint state, guint device_state)
 gboolean
 _gdk_input_common_other_event (GdkEvent         *event,
                               XEvent           *xevent,
-                              GdkInputWindow   *input_window,
+                              GdkWindow        *window,
                               GdkDevicePrivate *gdkdev)
 {
+  GdkWindowObject *priv, *impl_window;
+  GdkInputWindow *input_window;
+
+  priv = (GdkWindowObject *) window;
+  impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window);
+  input_window = impl_window->input_window;
+
   if ((xevent->type == gdkdev->buttonpress_type) ||
-      (xevent->type == gdkdev->buttonrelease_type)) 
+      (xevent->type == gdkdev->buttonrelease_type))
     {
       XDeviceButtonEvent *xdbe = (XDeviceButtonEvent *)(xevent);
 
@@ -560,16 +569,16 @@ _gdk_input_common_other_event (GdkEvent         *event,
          gdkdev->button_state &= ~(1 << xdbe->button);
        }
       event->button.device = &gdkdev->info;
-      event->button.window = input_window->window;
+      event->button.window = window;
       event->button.time = xdbe->time;
 
       event->button.axes = g_new (gdouble, gdkdev->info.num_axes);
-      gdk_input_translate_coordinates (gdkdev,input_window, xdbe->axis_data,
-                                      event->button.axes, 
-                                      &event->button.x,&event->button.y);
-      event->button.x_root = event->button.x + input_window->root_x;
-      event->button.y_root = event->button.y + input_window->root_y;
-      event->button.state = gdk_input_translate_state(xdbe->state,xdbe->device_state);
+      gdk_input_translate_coordinates (gdkdev, window, xdbe->axis_data,
+                                      event->button.axes,
+                                      &event->button.x, &event->button.y);
+      event->button.x_root = event->button.x + priv->abs_x + input_window->root_x;
+      event->button.y_root = event->button.y + priv->abs_y + input_window->root_y;
+      event->button.state = gdk_input_translate_state (xdbe->state,xdbe->device_state);
       event->button.button = xdbe->button;
 
       if (event->button.type == GDK_BUTTON_PRESS)
@@ -588,8 +597,8 @@ _gdk_input_common_other_event (GdkEvent         *event,
        * a valid timestamp.
        */
       if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
-        gdk_x11_window_set_user_time (gdk_window_get_toplevel (input_window->window),
-                                      gdk_event_get_time (event));
+       gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
+                                     gdk_event_get_time (event));
       return TRUE;
   }
 
@@ -611,21 +620,21 @@ _gdk_input_common_other_event (GdkEvent         *event,
          g_warning ("Invalid device key code received");
          return FALSE;
        }
-      
+
       event->key.keyval = gdkdev->info.keys[xdke->keycode - gdkdev->min_keycode].keyval;
 
-      if (event->key.keyval == 0) 
+      if (event->key.keyval == 0)
        {
          GDK_NOTE (EVENTS,
            g_print ("\t\ttranslation - NONE\n"));
-         
+
          return FALSE;
        }
 
       event->key.type = (xdke->type == gdkdev->keypress_type) ?
        GDK_KEY_PRESS : GDK_KEY_RELEASE;
 
-      event->key.window = input_window->window;
+      event->key.window = window;
       event->key.time = xdke->time;
 
       event->key.state = gdk_input_translate_state(xdke->state, xdke->device_state)
@@ -654,26 +663,26 @@ _gdk_input_common_other_event (GdkEvent         *event,
        * a valid timestamp.
        */
       if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
-        gdk_x11_window_set_user_time (gdk_window_get_toplevel (input_window->window),
-                                      gdk_event_get_time (event));
+       gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
+                                     gdk_event_get_time (event));
       return TRUE;
     }
 
-  if (xevent->type == gdkdev->motionnotify_type) 
+  if (xevent->type == gdkdev->motionnotify_type)
     {
       XDeviceMotionEvent *xdme = (XDeviceMotionEvent *)(xevent);
 
       event->motion.device = &gdkdev->info;
-      
+
       event->motion.axes = g_new (gdouble, gdkdev->info.num_axes);
-      gdk_input_translate_coordinates(gdkdev,input_window,xdme->axis_data,
+      gdk_input_translate_coordinates(gdkdev,window,xdme->axis_data,
                                      event->motion.axes,
                                      &event->motion.x,&event->motion.y);
-      event->motion.x_root = event->motion.x + input_window->root_x;
-      event->motion.y_root = event->motion.y + input_window->root_y;
+      event->motion.x_root = event->motion.x + priv->abs_x + input_window->root_x;
+      event->motion.y_root = event->motion.y + priv->abs_y + input_window->root_y;
 
       event->motion.type = GDK_MOTION_NOTIFY;
-      event->motion.window = input_window->window;
+      event->motion.window = window;
       event->motion.time = xdme->time;
       event->motion.state = gdk_input_translate_state(xdme->state,
                                                      xdme->device_state);
@@ -686,14 +695,14 @@ _gdk_input_common_other_event (GdkEvent         *event,
                 event->motion.x, event->motion.y,
                 event->motion.state,
                 (xdme->is_hint) ? "true" : "false"));
-      
-      
+
+
       /* Update the timestamp of the latest user interaction, if the event has
        * a valid timestamp.
        */
       if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
-        gdk_x11_window_set_user_time (gdk_window_get_toplevel (input_window->window),
-                                      gdk_event_get_time (event));
+       gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
+                                     gdk_event_get_time (event));
       return TRUE;
     }
 
@@ -704,16 +713,16 @@ _gdk_input_common_other_event (GdkEvent         *event,
 
       event->proximity.device = &gdkdev->info;
       event->proximity.type = (xevent->type == gdkdev->proximityin_type)?
-       GDK_PROXIMITY_IN:GDK_PROXIMITY_OUT;
-      event->proximity.window = input_window->window;
+       GDK_PROXIMITY_IN:GDK_PROXIMITY_OUT;
+      event->proximity.window = window;
       event->proximity.time = xpne->time;
-      
+
       /* Update the timestamp of the latest user interaction, if the event has
        * a valid timestamp.
        */
       if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
-        gdk_x11_window_set_user_time (gdk_window_get_toplevel (input_window->window),
-                                      gdk_event_get_time (event));
+       gdk_x11_window_set_user_time (gdk_window_get_toplevel (window),
+                                     gdk_event_get_time (event));
       return TRUE;
   }
 
@@ -730,18 +739,17 @@ _gdk_device_get_history (GdkDevice         *device,
 {
   GdkTimeCoord **coords;
   XDeviceTimeCoord *device_coords;
-  GdkInputWindow *input_window;
+  GdkWindow *impl_window;
   GdkDevicePrivate *gdkdev;
   gint mode_return;
   gint axis_count_return;
   gint i;
 
   gdkdev = (GdkDevicePrivate *)device;
-  input_window = _gdk_input_window_find (window);
 
-  g_return_val_if_fail (input_window != NULL, FALSE);
+  impl_window = _gdk_window_get_impl_window (window);
 
-  device_coords = XGetDeviceMotionEvents (GDK_WINDOW_XDISPLAY (window),
+  device_coords = XGetDeviceMotionEvents (GDK_WINDOW_XDISPLAY (impl_window),
                                          gdkdev->xdevice,
                                          start, stop,
                                          n_events, &mode_return,
@@ -752,13 +760,13 @@ _gdk_device_get_history (GdkDevice         *device,
       coords = _gdk_device_allocate_history (device, *n_events);
 
       for (i = 0; i < *n_events; i++)
-        {
-          coords[i]->time = device_coords[i].time;
+       {
+         coords[i]->time = device_coords[i].time;
 
-          gdk_input_translate_coordinates (gdkdev, input_window,
-                                           device_coords[i].data,
-                                           coords[i]->axes, NULL, NULL);
-        }
+         gdk_input_translate_coordinates (gdkdev, window,
+                                          device_coords[i].data,
+                                          coords[i]->axes, NULL, NULL);
+       }
 
       XFreeDeviceMotionEvents (device_coords);
 
@@ -770,7 +778,7 @@ _gdk_device_get_history (GdkDevice         *device,
     return FALSE;
 }
 
-void 
+void
 gdk_device_get_state (GdkDevice       *device,
                      GdkWindow       *window,
                      gdouble         *axes,
@@ -784,7 +792,7 @@ gdk_device_get_state (GdkDevice       *device,
   if (GDK_IS_CORE (device))
     {
       gint x_int, y_int;
-      
+
       gdk_window_get_pointer (window, &x_int, &y_int, mask);
 
       if (axes)
@@ -796,16 +804,13 @@ gdk_device_get_state (GdkDevice       *device,
   else
     {
       GdkDevicePrivate *gdkdev;
-      GdkInputWindow *input_window;
       XDeviceState *state;
       XInputClass *input_class;
-      
+
       if (mask)
        gdk_window_get_pointer (window, NULL, NULL, mask);
-      
+
       gdkdev = (GdkDevicePrivate *)device;
-      input_window = _gdk_input_window_find (window);
-      g_return_if_fail (input_window != NULL);
 
       state = XQueryDeviceState (GDK_WINDOW_XDISPLAY (window),
                                 gdkdev->xdevice);
@@ -816,11 +821,11 @@ gdk_device_get_state (GdkDevice       *device,
            {
            case ValuatorClass:
              if (axes)
-               gdk_input_translate_coordinates (gdkdev, input_window,
+               gdk_input_translate_coordinates (gdkdev, window,
                                                 ((XValuatorState *)input_class)->valuators,
                                                 axes, NULL, NULL);
              break;
-             
+
            case ButtonClass:
              if (mask)
                {
index b51516b3e1d5367083bd528da31adb309a6b046f..10fd33d919d8aa15e533b490c6a37cc935cac7ca 100644 (file)
  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
  * file for a list of people on the GTK+ Team.  See the ChangeLog
  * files for a list of changes.  These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
  */
 
 /* forward declarations */
 
 static void gdk_input_check_proximity (GdkDisplay *display);
 
-void 
+void
 _gdk_input_init(GdkDisplay *display)
 {
   _gdk_init_input_core (display);
-  GDK_DISPLAY_X11 (display)->input_ignore_core = FALSE;
+  display->ignore_core_events = FALSE;
   _gdk_input_common_init (display, FALSE);
 }
 
@@ -47,7 +47,6 @@ gdk_device_set_mode (GdkDevice      *device,
 {
   GList *tmp_list;
   GdkDevicePrivate *gdkdev;
-  GdkInputMode old_mode;
   GdkInputWindow *input_window;
   GdkDisplayX11 *display_impl;
 
@@ -59,58 +58,35 @@ gdk_device_set_mode (GdkDevice      *device,
   if (device->mode == mode)
     return TRUE;
 
-  old_mode = device->mode;
   device->mode = mode;
 
-  display_impl = GDK_DISPLAY_X11 (gdkdev->display);
-
   if (mode == GDK_MODE_WINDOW)
-    {
-      device->has_cursor = FALSE;
-      for (tmp_list = display_impl->input_windows; tmp_list; tmp_list = tmp_list->next)
-       {
-         input_window = (GdkInputWindow *)tmp_list->data;
-         if (input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
-           _gdk_input_enable_window (input_window->window, gdkdev);
-         else
-           if (old_mode != GDK_MODE_DISABLED)
-             _gdk_input_disable_window (input_window->window, gdkdev);
-       }
-    }
+    device->has_cursor = FALSE;
   else if (mode == GDK_MODE_SCREEN)
+    device->has_cursor = TRUE;
+
+  display_impl = GDK_DISPLAY_X11 (gdkdev->display);
+  for (tmp_list = display_impl->input_windows; tmp_list; tmp_list = tmp_list->next)
     {
-      device->has_cursor = TRUE;
-      for (tmp_list = display_impl->input_windows; tmp_list; tmp_list = tmp_list->next)
-       _gdk_input_enable_window (((GdkInputWindow *)tmp_list->data)->window,
-                                 gdkdev);
-    }
-  else  /* mode == GDK_MODE_DISABLED */
-    {
-      for (tmp_list = display_impl->input_windows; tmp_list; tmp_list = tmp_list->next)
-       {
-         input_window = (GdkInputWindow *)tmp_list->data;
-         if (old_mode != GDK_MODE_WINDOW ||
-             input_window->mode != GDK_EXTENSION_EVENTS_CURSOR)
-           _gdk_input_disable_window (input_window->window, gdkdev);
-       }
+      input_window = (GdkInputWindow *)tmp_list->data;
+      _gdk_input_select_events (input_window->impl_window, gdkdev);
     }
 
   return TRUE;
-  
 }
 
 static void
 gdk_input_check_proximity (GdkDisplay *display)
 {
-  gint new_proximity = 0;
   GdkDisplayX11 *display_impl = GDK_DISPLAY_X11 (display);
   GList *tmp_list = display_impl->input_devices;
+  gint new_proximity = 0;
 
-  while (tmp_list && !new_proximity) 
+  while (tmp_list && !new_proximity)
     {
       GdkDevicePrivate *gdkdev = (GdkDevicePrivate *)(tmp_list->data);
 
-      if (gdkdev->info.mode != GDK_MODE_DISABLED 
+      if (gdkdev->info.mode != GDK_MODE_DISABLED
          && !GDK_IS_CORE (gdkdev)
          && gdkdev->xdevice)
        {
@@ -118,7 +94,7 @@ gdk_input_check_proximity (GdkDisplay *display)
                                                  gdkdev->xdevice);
          XInputClass *xic;
          int i;
-         
+
          xic = state->data;
          for (i=0; i<state->num_classes; i++)
            {
@@ -135,117 +111,197 @@ gdk_input_check_proximity (GdkDisplay *display)
            }
 
          XFreeDeviceState (state);
-       }
+       }
       tmp_list = tmp_list->next;
     }
 
-  display_impl->input_ignore_core = new_proximity;
+  display->ignore_core_events = new_proximity;
 }
 
 void
 _gdk_input_configure_event (XConfigureEvent *xevent,
                            GdkWindow       *window)
 {
+  GdkWindowObject *priv = (GdkWindowObject *)window;
   GdkInputWindow *input_window;
   gint root_x, root_y;
 
-  input_window = _gdk_input_window_find(window);
-  g_return_if_fail (input_window != NULL);
-
-  _gdk_input_get_root_relative_geometry(GDK_WINDOW_XDISPLAY (window),
-                                       GDK_WINDOW_XWINDOW (window),
-                                       &root_x, &root_y, NULL, NULL);
-
-  input_window->root_x = root_x;
-  input_window->root_y = root_y;
+  input_window = priv->input_window;
+  if (input_window != NULL)
+    {
+      _gdk_input_get_root_relative_geometry (window, &root_x, &root_y);
+      input_window->root_x = root_x;
+      input_window->root_y = root_y;
+    }
 }
 
-void 
-_gdk_input_enter_event (XCrossingEvent *xevent, 
-                       GdkWindow      *window)
+void
+_gdk_input_crossing_event (GdkWindow *window,
+                          gboolean enter)
 {
+  GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
+  GdkDisplayX11 *display_impl = GDK_DISPLAY_X11 (display);
+  GdkWindowObject *priv = (GdkWindowObject *)window;
   GdkInputWindow *input_window;
   gint root_x, root_y;
 
-  input_window = _gdk_input_window_find (window);
-  g_return_if_fail (input_window != NULL);
+  if (enter)
+    {
+      gdk_input_check_proximity(display);
+
+      input_window = priv->input_window;
+      if (input_window != NULL)
+       {
+         _gdk_input_get_root_relative_geometry (window, &root_x, &root_y);
+         input_window->root_x = root_x;
+         input_window->root_y = root_y;
+       }
+    }
+  else
+    display->ignore_core_events = FALSE;
+}
+
+static GdkEventType
+get_input_event_type (GdkDevicePrivate *gdkdev,
+                     XEvent *xevent,
+                     int *core_x, int *core_y)
+{
+  if (xevent->type == gdkdev->buttonpress_type)
+    {
+      XDeviceButtonEvent *xie = (XDeviceButtonEvent *)(xevent);
+      *core_x = xie->x;
+      *core_y = xie->y;
+      return GDK_BUTTON_PRESS;
+    }
+
+  if (xevent->type == gdkdev->buttonrelease_type)
+    {
+      XDeviceButtonEvent *xie = (XDeviceButtonEvent *)(xevent);
+      *core_x = xie->x;
+      *core_y = xie->y;
+      return GDK_BUTTON_RELEASE;
+    }
+
+  if (xevent->type == gdkdev->keypress_type)
+    {
+      XDeviceKeyEvent *xie = (XDeviceKeyEvent *)(xevent);
+      *core_x = xie->x;
+      *core_y = xie->y;
+      return GDK_KEY_PRESS;
+    }
+
+  if (xevent->type == gdkdev->keyrelease_type)
+    {
+      XDeviceKeyEvent *xie = (XDeviceKeyEvent *)(xevent);
+      *core_x = xie->x;
+      *core_y = xie->y;
+      return GDK_KEY_RELEASE;
+    }
+
+  if (xevent->type == gdkdev->motionnotify_type)
+    {
+      XDeviceMotionEvent *xie = (XDeviceMotionEvent *)(xevent);
+      *core_x = xie->x;
+      *core_y = xie->y;
+      return GDK_MOTION_NOTIFY;
+    }
 
-  gdk_input_check_proximity(GDK_WINDOW_DISPLAY (window));
+  if (xevent->type == gdkdev->proximityin_type)
+    {
+      XProximityNotifyEvent *xie = (XProximityNotifyEvent *)(xevent);
+      *core_x = xie->x;
+      *core_y = xie->y;
+      return GDK_PROXIMITY_IN;
+    }
 
-  _gdk_input_get_root_relative_geometry(GDK_WINDOW_XDISPLAY (window),
-                                       GDK_WINDOW_XWINDOW(window),
-                                       &root_x, &root_y, NULL, NULL);
+  if (xevent->type == gdkdev->proximityout_type)
+    {
+      XProximityNotifyEvent *xie = (XProximityNotifyEvent *)(xevent);
+      *core_x = xie->x;
+      *core_y = xie->y;
+      return GDK_PROXIMITY_OUT;
+    }
 
-  input_window->root_x = root_x;
-  input_window->root_y = root_y;
+  *core_x = 0;
+  *core_y = 0;
+  return GDK_NOTHING;
 }
 
-gboolean 
-_gdk_input_other_event (GdkEvent *event, 
-                       XEvent *xevent, 
-                       GdkWindow *window)
+
+gboolean
+_gdk_input_other_event (GdkEvent *event,
+                       XEvent *xevent,
+                       GdkWindow *event_window)
 {
-  GdkInputWindow *input_window;
-  
+  GdkWindow *window;
+  GdkWindowObject *priv;
+  GdkInputWindow *iw;
   GdkDevicePrivate *gdkdev;
   gint return_val;
-  GdkDisplayX11 *display_impl = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
-
-  input_window = _gdk_input_window_find(window);
-  g_return_val_if_fail (input_window != NULL, FALSE);
+  GdkEventType event_type;
+  int x, y;
+  GdkDisplay *display = GDK_WINDOW_DISPLAY (event_window);
+  GdkDisplayX11 *display_impl = GDK_DISPLAY_X11 (display);
 
   /* This is a sort of a hack, as there isn't any XDeviceAnyEvent -
      but it's potentially faster than scanning through the types of
      every device. If we were deceived, then it won't match any of
      the types for the device anyways */
-  gdkdev = _gdk_input_find_device (GDK_WINDOW_DISPLAY (window),
+  gdkdev = _gdk_input_find_device (display,
                                   ((XDeviceButtonEvent *)xevent)->deviceid);
   if (!gdkdev)
     return FALSE;                      /* we don't handle it - not an XInput event */
 
-  /* FIXME: It would be nice if we could just get rid of the events 
-     entirely, instead of having to ignore them */
+  event_type = get_input_event_type (gdkdev, xevent, &x, &y);
+  if (event_type == GDK_NOTHING)
+    return FALSE;
+
+  window = _gdk_window_get_input_window_for_event (event_window,
+                                                  event_type,
+                                                  x, y,
+                                                  xevent->xany.serial);
+  /* If we're not getting any event window its likely because we're outside the
+     window and there is no grab. We should still report according to the
+     implicit grab though. */
+  iw = ((GdkWindowObject *)event_window)->input_window;
+  if (window == NULL)
+    window = iw->button_down_window;
+
+  priv = (GdkWindowObject *)window;
+  if (window == NULL)
+    return FALSE;
+
   if (gdkdev->info.mode == GDK_MODE_DISABLED ||
-      (gdkdev->info.mode == GDK_MODE_WINDOW 
-       && input_window->mode == GDK_EXTENSION_EVENTS_CURSOR))
+      !(gdkdev->info.has_cursor || (priv->extension_events & GDK_ALL_DEVICES_MASK)))
     return FALSE;
-  
-  if (!display_impl->input_ignore_core)
-    gdk_input_check_proximity(GDK_WINDOW_DISPLAY (window));
 
-  return_val = _gdk_input_common_other_event (event, xevent, 
-                                             input_window, gdkdev);
+  if (!display->ignore_core_events && priv->extension_events != 0)
+    gdk_input_check_proximity (GDK_WINDOW_DISPLAY (window));
 
-  if (return_val && event->type == GDK_PROXIMITY_OUT &&
-      display_impl->input_ignore_core)
-    gdk_input_check_proximity(GDK_WINDOW_DISPLAY (window));
+  return_val = _gdk_input_common_other_event (event, xevent, window, gdkdev);
 
-  return return_val;
-}
+  if (return_val && event->type == GDK_BUTTON_PRESS)
+    iw->button_down_window = window;
+  if (return_val && event->type == GDK_BUTTON_RELEASE)
+    iw->button_down_window = NULL;
 
-gboolean
-_gdk_input_enable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
-{
-  /* FIXME: watchout, gdkdev might be core pointer, never opened */
-  _gdk_input_common_select_events (window, gdkdev);
-  return TRUE;
-}
+  if (return_val && event->type == GDK_PROXIMITY_OUT &&
+      display->ignore_core_events)
+    gdk_input_check_proximity (GDK_WINDOW_DISPLAY (window));
 
-gboolean
-_gdk_input_disable_window(GdkWindow *window, GdkDevicePrivate *gdkdev)
-{
-  _gdk_input_common_select_events (window, gdkdev);
-  return TRUE;
+  return return_val;
 }
 
-gint 
-_gdk_input_grab_pointer (GdkWindow *     window,
+gint
+_gdk_input_grab_pointer (GdkWindow      *window,
+                        GdkWindow      *native_window, /* This is the toplevel */
                         gint            owner_events,
                         GdkEventMask    event_mask,
                         GdkWindow *     confine_to,
                         guint32         time)
 {
-  GdkInputWindow *input_window, *new_window;
+  GdkInputWindow *input_window;
+  GdkWindowObject *priv, *impl_window;
   gboolean need_ungrab;
   GdkDevicePrivate *gdkdev;
   GList *tmp_list;
@@ -255,36 +311,36 @@ _gdk_input_grab_pointer (GdkWindow *     window,
   GdkDisplayX11 *display_impl  = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
 
   tmp_list = display_impl->input_windows;
-  new_window = NULL;
   need_ungrab = FALSE;
 
   while (tmp_list)
     {
       input_window = (GdkInputWindow *)tmp_list->data;
 
-      if (input_window->window == window)
-       new_window = input_window;
-      else if (input_window->grabbed)
+      if (input_window->grabbed)
        {
          input_window->grabbed = FALSE;
          need_ungrab = TRUE;
+         break;
        }
-
       tmp_list = tmp_list->next;
     }
 
-  if (new_window)
+  priv = (GdkWindowObject *)window;
+  impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window);
+  input_window = impl_window->input_window;
+  if (priv->extension_events)
     {
-      new_window->grabbed = TRUE;
-      
+      g_assert (input_window != NULL);
+      input_window->grabbed = TRUE;
+
       tmp_list = display_impl->input_devices;
       while (tmp_list)
        {
          gdkdev = (GdkDevicePrivate *)tmp_list->data;
          if (!GDK_IS_CORE (gdkdev) && gdkdev->xdevice)
            {
-             _gdk_input_common_find_events (window, gdkdev,
-                                            event_mask,
+             _gdk_input_common_find_events (gdkdev, event_mask,
                                             event_classes, &num_classes);
 #ifdef G_ENABLE_DEBUG
              if (_gdk_debug_flags & GDK_DEBUG_NOGRABS)
@@ -292,10 +348,10 @@ _gdk_input_grab_pointer (GdkWindow *     window,
              else
 #endif
                result = XGrabDevice (display_impl->xdisplay, gdkdev->xdevice,
-                                     GDK_WINDOW_XWINDOW (window),
+                                     GDK_WINDOW_XWINDOW (native_window),
                                      owner_events, num_classes, event_classes,
                                      GrabModeAsync, GrabModeAsync, time);
-             
+
              /* FIXME: if failure occurs on something other than the first
                 device, things will be badly inconsistent */
              if (result != Success)
@@ -305,7 +361,7 @@ _gdk_input_grab_pointer (GdkWindow *     window,
        }
     }
   else
-    { 
+    {
       tmp_list = display_impl->input_devices;
       while (tmp_list)
        {
@@ -316,17 +372,16 @@ _gdk_input_grab_pointer (GdkWindow *     window,
              XUngrabDevice (display_impl->xdisplay, gdkdev->xdevice, time);
              gdkdev->button_state = 0;
            }
-         
+
          tmp_list = tmp_list->next;
        }
     }
 
   return Success;
-      
 }
 
-void 
-_gdk_input_ungrab_pointer (GdkDisplay *display, 
+void
+_gdk_input_ungrab_pointer (GdkDisplay *display,
                           guint32 time)
 {
   GdkInputWindow *input_window = NULL; /* Quiet GCC */
index 0d48e13f3ba3b5f3d748af7833fe97c933566a7c..c33f09c9e40e7472bd5f91892b91c3b1fa8fa2ef 100644 (file)
@@ -21,7 +21,7 @@
  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
  * file for a list of people on the GTK+ Team.  See the ChangeLog
  * files for a list of changes.  These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
  */
 
 #include "config.h"
@@ -47,10 +47,10 @@ void
 _gdk_init_input_core (GdkDisplay *display)
 {
   GdkDevicePrivate *private;
-  
+
   display->core_pointer = g_object_new (GDK_TYPE_DEVICE, NULL);
   private = (GdkDevicePrivate *)display->core_pointer;
-  
+
   display->core_pointer->name = "Core Pointer";
   display->core_pointer->source = GDK_SOURCE_MOUSE;
   display->core_pointer->mode = GDK_MODE_SCREEN;
@@ -87,12 +87,12 @@ gdk_device_get_type (void)
          0,              /* n_preallocs */
          (GInstanceInitFunc) NULL,
        };
-      
+
       object_type = g_type_register_static (G_TYPE_OBJECT,
-                                            g_intern_static_string ("GdkDevice"),
-                                            &object_info, 0);
+                                           g_intern_static_string ("GdkDevice"),
+                                           &object_info, 0);
     }
-  
+
   return object_type;
 }
 
@@ -115,10 +115,10 @@ gdk_device_dispose (GObject *object)
     {
 #ifndef XINPUT_NONE
       if (gdkdev->xdevice)
-        {
-          XCloseDevice (GDK_DISPLAY_XDISPLAY (gdkdev->display), gdkdev->xdevice);
-          gdkdev->xdevice = NULL;
-        }
+       {
+         XCloseDevice (GDK_DISPLAY_XDISPLAY (gdkdev->display), gdkdev->xdevice);
+         gdkdev->xdevice = NULL;
+       }
       g_free (gdkdev->axes);
       gdkdev->axes = NULL;
 #endif /* !XINPUT_NONE */
@@ -140,7 +140,7 @@ gdk_device_dispose (GObject *object)
  *
  * Returns the list of available input devices for the default display.
  * The list is statically allocated and should not be freed.
- * 
+ *
  * Return value: a list of #GdkDevice
  **/
 GList *
@@ -155,16 +155,16 @@ gdk_devices_list (void)
  *
  * Returns the list of available input devices attached to @display.
  * The list is statically allocated and should not be freed.
- * 
+ *
  * Return value: a list of #GdkDevice
  *
  * Since: 2.2
  **/
-GList * 
+GList *
 gdk_display_list_devices (GdkDisplay *display)
 {
   g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
-  
+
   return GDK_DISPLAY_X11 (display)->input_devices;
 }
 
@@ -219,6 +219,22 @@ gdk_device_set_axis_use (GdkDevice   *device,
     }
 }
 
+static gboolean
+impl_coord_in_window (GdkWindow *window,
+                     int impl_x,
+                     int impl_y)
+{
+  GdkWindowObject *priv = (GdkWindowObject *)window;
+
+  if (impl_x < priv->abs_x ||
+      impl_x > priv->abs_x + priv->width)
+    return FALSE;
+  if (impl_y < priv->abs_y ||
+      impl_y > priv->abs_y + priv->height)
+    return FALSE;
+  return TRUE;
+}
+
 /**
  * gdk_device_get_history:
  * @device: a #GdkDevice
@@ -227,14 +243,14 @@ gdk_device_set_axis_use (GdkDevice   *device,
  * @stop: ending timestamp for the range of events to return
  * @events: location to store a newly-allocated array of #GdkTimeCoord, or %NULL
  * @n_events: location to store the length of @events, or %NULL
- * 
+ *
  * Obtains the motion history for a device; given a starting and
  * ending timestamp, return all events in the motion history for
  * the device in the given range of time. Some windowing systems
  * do not support motion history, in which case, %FALSE will
  * be returned. (This is not distinguishable from the case where
  * motion history is supported and no events were found.)
- * 
+ *
  * Return value: %TRUE if the windowing system supports motion history and
  *  at least one event was found.
  **/
@@ -247,29 +263,38 @@ gdk_device_get_history  (GdkDevice         *device,
                         gint              *n_events)
 {
   GdkTimeCoord **coords = NULL;
+  GdkWindow *impl_window;
   gboolean result = FALSE;
   int tmp_n_events = 0;
-  int i;
+  int i, j;
 
-  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+  g_return_val_if_fail (GDK_WINDOW_IS_X11 (window), FALSE);
+
+  impl_window = _gdk_window_get_impl_window (window);
 
   if (GDK_WINDOW_DESTROYED (window))
     /* Nothing */ ;
   else if (GDK_IS_CORE (device))
     {
       XTimeCoord *xcoords;
-      
+
       xcoords = XGetMotionEvents (GDK_DRAWABLE_XDISPLAY (window),
-                                 GDK_DRAWABLE_XID (window),
+                                 GDK_DRAWABLE_XID (impl_window),
                                  start, stop, &tmp_n_events);
       if (xcoords)
        {
+         GdkWindowObject *priv = (GdkWindowObject *)window;
          coords = _gdk_device_allocate_history (device, tmp_n_events);
+         j = 0;
          for (i=0; i<tmp_n_events; i++)
            {
-             coords[i]->time = xcoords[i].time;
-             coords[i]->axes[0] = xcoords[i].x;
-             coords[i]->axes[1] = xcoords[i].y;
+             if (impl_coord_in_window (window, xcoords[i].x, xcoords[i].y))
+               {
+                 coords[j]->time = xcoords[i].time;
+                 coords[j]->axes[0] = xcoords[i].x - priv->abs_x;
+                 coords[j]->axes[1] = xcoords[i].y - priv->abs_y;
+                 j++;
+               }
            }
 
          XFree (xcoords);
@@ -292,7 +317,7 @@ gdk_device_get_history  (GdkDevice         *device,
   return result;
 }
 
-GdkTimeCoord ** 
+GdkTimeCoord **
 _gdk_device_allocate_history (GdkDevice *device,
                              gint       n_events)
 {
@@ -306,36 +331,48 @@ _gdk_device_allocate_history (GdkDevice *device,
   return result;
 }
 
-void 
+void
 gdk_device_free_history (GdkTimeCoord **events,
                         gint           n_events)
 {
   gint i;
-  
+
   for (i=0; i<n_events; i++)
     g_free (events[i]);
 
   g_free (events);
 }
 
-GdkInputWindow *
-_gdk_input_window_find(GdkWindow *window)
+static void
+unset_extension_events (GdkWindow *window)
 {
-  GList *tmp_list;
-  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
+  GdkWindowObject *window_private;
+  GdkWindowObject *impl_window;
+  GdkDisplayX11 *display_x11;
+  GdkInputWindow *iw;
 
-  for (tmp_list=display_x11->input_windows; tmp_list; tmp_list=tmp_list->next)
-    if (((GdkInputWindow *)(tmp_list->data))->window == window)
-      return (GdkInputWindow *)(tmp_list->data);
+  window_private = (GdkWindowObject*) window;
+  impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window);
+  iw = impl_window->input_window;
 
-  return NULL;      /* Not found */
-}
+  display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
+
+  if (window_private->extension_events != 0)
+    {
+      g_assert (iw != NULL);
+      g_assert (g_list_find (iw->windows, window) != NULL);
 
-/* FIXME: this routine currently needs to be called between creation
-   and the corresponding configure event (because it doesn't get the
-   root_relative_geometry).  This should work with
-   gtk_window_set_extension_events, but will likely fail in other
-   cases */
+      iw->windows = g_list_remove (iw->windows, window);
+      if (iw->windows == NULL)
+       {
+         impl_window->input_window = NULL;
+         display_x11->input_windows = g_list_remove (display_x11->input_windows, iw);
+         g_free (iw);
+       }
+    }
+
+  window_private->extension_events = 0;
+}
 
 void
 gdk_input_set_extension_events (GdkWindow *window, gint mask,
@@ -343,63 +380,56 @@ gdk_input_set_extension_events (GdkWindow *window, gint mask,
 {
   GdkWindowObject *window_private;
   GList *tmp_list;
+  GdkWindowObject *impl_window;
   GdkInputWindow *iw;
   GdkDisplayX11 *display_x11;
 
   g_return_if_fail (window != NULL);
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_WINDOW_IS_X11 (window));
 
   window_private = (GdkWindowObject*) window;
   display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
+  impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window);
+
+  if (mode == GDK_EXTENSION_EVENTS_ALL && mask != 0)
+    mask |= GDK_ALL_DEVICES_MASK;
+
   if (mode == GDK_EXTENSION_EVENTS_NONE)
     mask = 0;
 
-  iw = _gdk_input_window_find (window);
+  iw = impl_window->input_window;
 
   if (mask != 0)
     {
       if (!iw)
-        {
-          iw = g_new(GdkInputWindow,1);
-
-          iw->window = window;
-          iw->mode = mode;
+       {
+         iw = g_new0 (GdkInputWindow,1);
 
-          iw->obscuring = NULL;
-          iw->num_obscuring = 0;
-          iw->grabbed = FALSE;
+         iw->impl_window = (GdkWindow *)impl_window;
 
-          display_x11->input_windows = g_list_append(display_x11->input_windows,iw);
-        }
+         iw->windows = NULL;
+         iw->grabbed = FALSE;
 
-      window_private->extension_events = mask;
+         display_x11->input_windows = g_list_append (display_x11->input_windows, iw);
 
 #ifndef XINPUT_NONE
-      /* Add enter window events to the event mask */
-      /* this is not needed for XINPUT_NONE */
-      gdk_window_set_events (window,
-                            gdk_window_get_events (window) | 
-                            GDK_ENTER_NOTIFY_MASK);
-
-      /* we might not receive ConfigureNotify so get the root_relative_geometry
-       * now, just in case */
-      _gdk_input_get_root_relative_geometry (GDK_WINDOW_XDISPLAY (window),
-                                             GDK_WINDOW_XWINDOW (window),
-                                             &iw->root_x, &iw->root_y, NULL, NULL);
+         /* we might not receive ConfigureNotify so get the root_relative_geometry
+          * now, just in case */
+         _gdk_input_get_root_relative_geometry (window, &iw->root_x, &iw->root_y);
 #endif /* !XINPUT_NONE */
+         impl_window->input_window = iw;
+       }
+
+      if (window_private->extension_events == 0)
+       iw->windows = g_list_append (iw->windows, window);
+      window_private->extension_events = mask;
     }
   else
     {
-      if (iw)
-       {
-         display_x11->input_windows = g_list_remove(display_x11->input_windows,iw);
-         g_free(iw);
-       }
-
-      window_private->extension_events = 0;
+      unset_extension_events (window);
     }
 
   for (tmp_list = display_x11->input_devices; tmp_list; tmp_list = tmp_list->next)
@@ -407,57 +437,14 @@ gdk_input_set_extension_events (GdkWindow *window, gint mask,
       GdkDevicePrivate *gdkdev = tmp_list->data;
 
       if (!GDK_IS_CORE (gdkdev))
-       {
-         if (mask != 0 && gdkdev->info.mode != GDK_MODE_DISABLED
-             && (gdkdev->info.has_cursor || mode == GDK_EXTENSION_EVENTS_ALL))
-           _gdk_input_enable_window (window,gdkdev);
-         else
-           _gdk_input_disable_window (window,gdkdev);
-       }
+       _gdk_input_select_events ((GdkWindow *)impl_window, gdkdev);
     }
 }
 
 void
 _gdk_input_window_destroy (GdkWindow *window)
 {
-  GdkInputWindow *input_window;
-  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
-
-  input_window = _gdk_input_window_find (window);
-  g_return_if_fail (input_window != NULL);
-
-  display_x11->input_windows = g_list_remove (display_x11->input_windows, input_window);
-  g_free(input_window);
-}
-
-void
-_gdk_input_exit (void)
-{
-  GList *tmp_list;
-  GSList *display_list;
-  GdkDevicePrivate *gdkdev;
-
-  for (display_list = _gdk_displays ; display_list ; display_list = display_list->next)
-    {
-      GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (display_list->data);
-      
-      for (tmp_list = display_x11->input_devices; tmp_list; tmp_list = tmp_list->next)
-       {
-         gdkdev = (GdkDevicePrivate *)(tmp_list->data);
-         if (!GDK_IS_CORE (gdkdev))
-           {
-             gdk_device_set_mode (&gdkdev->info, GDK_MODE_DISABLED);
-             g_object_unref(gdkdev);
-           }
-       }
-      
-      g_list_free(display_x11->input_devices);
-      
-      for (tmp_list = display_x11->input_windows; tmp_list; tmp_list = tmp_list->next)
-       g_free(tmp_list->data);
-      
-      g_list_free(display_x11->input_windows);
-    }
+  unset_extension_events (window);
 }
 
 /**
@@ -466,10 +453,10 @@ _gdk_input_exit (void)
  * @axes: pointer to an array of axes
  * @use: the use to look for
  * @value: location to store the found value.
- * 
+ *
  * Interprets an array of double as axis values for a given device,
  * and locates the value in the array for a given axis use.
- * 
+ *
  * Return value: %TRUE if the given axis use was found, otherwise %FALSE
  **/
 gboolean
@@ -479,12 +466,12 @@ gdk_device_get_axis (GdkDevice  *device,
                     gdouble    *value)
 {
   gint i;
-  
+
   g_return_val_if_fail (device != NULL, FALSE);
 
   if (axes == NULL)
     return FALSE;
-  
+
   for (i=0; i<device->num_axes; i++)
     if (device->axes[i].use == use)
       {
@@ -492,7 +479,7 @@ gdk_device_get_axis (GdkDevice  *device,
          *value = axes[i];
        return TRUE;
       }
-  
+
   return FALSE;
 }
 
index 5cbd809debfad15a870f5dd61720d8d100290080..217e28c002a4855925408001607ffc4aaa79a42a 100644 (file)
@@ -41,7 +41,6 @@
 
 typedef struct _GdkAxisInfo    GdkAxisInfo;
 typedef struct _GdkDevicePrivate GdkDevicePrivate;
-typedef struct _GdkInputWindow GdkInputWindow;
 
 /* information about a device axis */
 struct _GdkAxisInfo
@@ -102,28 +101,25 @@ struct _GdkDeviceClass
   GObjectClass parent_class;
 };
 
+/* Addition used for extension_events mask */
+#define GDK_ALL_DEVICES_MASK (1<<30)
+
 struct _GdkInputWindow
 {
-  /* gdk window */
-  GdkWindow *window;
+  GList *windows; /* GdkWindow:s with extension_events set */
 
-  /* Extension mode (GDK_EXTENSION_EVENTS_ALL/CURSOR) */
-  GdkExtensionMode mode;
+  /* gdk window */
+  GdkWindow *impl_window; /* an impl window */
+  GdkWindow *button_down_window;
 
   /* position relative to root window */
   gint root_x;
   gint root_y;
 
-  /* rectangles relative to window of windows obscuring this one */
-  GdkRectangle *obscuring;
-  gint num_obscuring;
-
   /* Is there a pointer grab for this window ? */
   gint grabbed;
 };
 
-
-
 /* Global data */
 
 #define GDK_IS_CORE(d) (((GdkDevice *)(d)) == ((GdkDevicePrivate *)(d))->display->core_pointer)
@@ -139,18 +135,15 @@ void            _gdk_init_input_core         (GdkDisplay *display);
 /* The following functions are provided by each implementation
  * (xfree, gxi, and none)
  */
-gint             _gdk_input_enable_window     (GdkWindow        *window,
-                                             GdkDevicePrivate *gdkdev);
-gint             _gdk_input_disable_window    (GdkWindow        *window,
-                                             GdkDevicePrivate *gdkdev);
 void             _gdk_input_configure_event  (XConfigureEvent  *xevent,
                                              GdkWindow        *window);
-void             _gdk_input_enter_event      (XCrossingEvent   *xevent,
-                                             GdkWindow        *window);
+void             _gdk_input_crossing_event   (GdkWindow        *window,
+                                             gboolean          enter);
 gboolean         _gdk_input_other_event      (GdkEvent         *event,
                                              XEvent           *xevent,
                                              GdkWindow        *window);
 gint             _gdk_input_grab_pointer     (GdkWindow        *window,
+                                             GdkWindow        *native_window,
                                              gint              owner_events,
                                              GdkEventMask      event_mask,
                                              GdkWindow        *confine_to,
@@ -172,22 +165,18 @@ gint               _gdk_input_common_init               (GdkDisplay         *display,
                                                         gint              include_core);
 GdkDevicePrivate * _gdk_input_find_device               (GdkDisplay      *display,
                                                         guint32           id);
-void               _gdk_input_get_root_relative_geometry(Display          *display,
-                                                        Window            w,
+void               _gdk_input_get_root_relative_geometry(GdkWindow        *window,
                                                         int              *x_ret,
-                                                        int              *y_ret,
-                                                        int              *width_ret,
-                                                        int              *height_ret);
-void               _gdk_input_common_find_events        (GdkWindow        *window,
-                                                        GdkDevicePrivate *gdkdev,
+                                                        int              *y_ret);
+void               _gdk_input_common_find_events        (GdkDevicePrivate *gdkdev,
                                                         gint              mask,
                                                         XEventClass      *classes,
                                                         int              *num_classes);
-void               _gdk_input_common_select_events      (GdkWindow        *window,
+void               _gdk_input_select_events             (GdkWindow        *impl_window,
                                                         GdkDevicePrivate *gdkdev);
 gint               _gdk_input_common_other_event        (GdkEvent         *event,
                                                         XEvent           *xevent,
-                                                        GdkInputWindow   *input_window,
+                                                        GdkWindow        *window,
                                                         GdkDevicePrivate *gdkdev);
 
 #endif /* !XINPUT_NONE */
index 7bede228a18315252ba292c6f3fe084905dcdef4..f12c7094b832534fedbe1eb94a6c69884af02690 100644 (file)
@@ -44,6 +44,7 @@
 #include "gdk.h"
 
 #include "gdkx.h"
+#include "gdkasync.h"
 #include "gdkdisplay-x11.h"
 #include "gdkinternals.h"
 #include "gdkintl.h"
@@ -138,56 +139,21 @@ gdk_x11_convert_grab_status (gint status)
 }
 
 static void
-generate_grab_broken_event (GdkWindow *window,
-                           gboolean   keyboard,
-                           gboolean   implicit,
-                           GdkWindow *grab_window)
+has_pointer_grab_callback (GdkDisplay *display,
+                          gpointer data,
+                          gulong serial)
 {
-  if (!GDK_WINDOW_DESTROYED (window))
-    {
-      GdkEvent event;
-  
-      event.type = GDK_GRAB_BROKEN;
-      event.grab_broken.window = window;
-      event.grab_broken.send_event = 0;
-      event.grab_broken.keyboard = keyboard;
-      event.grab_broken.implicit = implicit;
-      event.grab_broken.grab_window = grab_window;
-      
-      gdk_event_put (&event);
-    }
+  _gdk_display_pointer_grab_update (display, serial);
 }
 
-/*
- *--------------------------------------------------------------
- * gdk_pointer_grab
- *
- *   Grabs the pointer to a specific window
- *
- * Arguments:
- *   "window" is the window which will receive the grab
- *   "owner_events" specifies whether events will be reported as is,
- *     or relative to "window"
- *   "event_mask" masks only interesting events
- *   "confine_to" limits the cursor movement to the specified window
- *   "cursor" changes the cursor for the duration of the grab
- *   "time" specifies the time
- *
- * Results:
- *
- * Side effects:
- *   requires a corresponding call to gdk_pointer_ungrab
- *
- *--------------------------------------------------------------
- */
-
 GdkGrabStatus
-gdk_pointer_grab (GdkWindow *    window,
-                 gboolean        owner_events,
-                 GdkEventMask    event_mask,
-                 GdkWindow *     confine_to,
-                 GdkCursor *     cursor,
-                 guint32         time)
+_gdk_windowing_pointer_grab (GdkWindow *window,
+                            GdkWindow *native,
+                            gboolean owner_events,
+                            GdkEventMask event_mask,
+                            GdkWindow *confine_to,
+                            GdkCursor *cursor,
+                            guint32 time)
 {
   gint return_val;
   GdkCursorPrivate *cursor_private;
@@ -196,25 +162,22 @@ gdk_pointer_grab (GdkWindow *       window,
   Window xwindow;
   Window xconfine_to;
   Cursor xcursor;
-  unsigned long serial;
   int i;
-  
-  g_return_val_if_fail (window != NULL, 0);
-  g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
-  g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
-  
-  display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
+
+  if (confine_to)
+    confine_to = _gdk_window_get_impl_window (confine_to);
+
+  display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (native));
 
   cursor_private = (GdkCursorPrivate*) cursor;
-  
-  xwindow = GDK_WINDOW_XID (window);
-  serial = NextRequest (GDK_WINDOW_XDISPLAY (window));
-  
+
+  xwindow = GDK_WINDOW_XID (native);
+
   if (!confine_to || GDK_WINDOW_DESTROYED (confine_to))
     xconfine_to = None;
   else
     xconfine_to = GDK_WINDOW_XID (confine_to);
-  
+
   if (!cursor)
     xcursor = None;
   else
@@ -222,31 +185,37 @@ gdk_pointer_grab (GdkWindow *       window,
       _gdk_x11_cursor_update_theme (cursor);
       xcursor = cursor_private->xcursor;
     }
-  
+
   xevent_mask = 0;
   for (i = 0; i < _gdk_nenvent_masks; i++)
     {
       if (event_mask & (1 << (i + 1)))
        xevent_mask |= _gdk_event_mask_table[i];
     }
-  
+
+  /* We don't want to set a native motion hint mask, as we're emulating motion
+   * hints. If we set a native one we just wouldn't get any events.
+   */
+  xevent_mask &= ~PointerMotionHintMask;
+
   return_val = _gdk_input_grab_pointer (window,
+                                       native,
                                        owner_events,
                                        event_mask,
                                        confine_to,
                                        time);
 
-  if (return_val == GrabSuccess || 
+  if (return_val == GrabSuccess ||
       G_UNLIKELY (!display_x11->trusted_client && return_val == AlreadyGrabbed))
     {
-      if (!GDK_WINDOW_DESTROYED (window))
+      if (!GDK_WINDOW_DESTROYED (native))
        {
 #ifdef G_ENABLE_DEBUG
          if (_gdk_debug_flags & GDK_DEBUG_NOGRABS)
            return_val = GrabSuccess;
          else
 #endif
-           return_val = XGrabPointer (GDK_WINDOW_XDISPLAY (window),
+           return_val = XGrabPointer (GDK_WINDOW_XDISPLAY (native),
                                       xwindow,
                                       owner_events,
                                       xevent_mask,
@@ -258,62 +227,15 @@ gdk_pointer_grab (GdkWindow *       window,
       else
        return_val = AlreadyGrabbed;
     }
-  
+
   if (return_val == GrabSuccess)
-    {
-      if (display_x11->pointer_xgrab_window != NULL &&
-         display_x11->pointer_xgrab_window != (GdkWindowObject *)window)
-       generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_xgrab_window),
-                                   FALSE, display_x11->pointer_xgrab_implicit,
-                                   window);
-
-      display_x11->pointer_xgrab_window = (GdkWindowObject *)window;
-      display_x11->pointer_xgrab_serial = serial;
-      display_x11->pointer_xgrab_owner_events = owner_events;
-      display_x11->pointer_xgrab_time = time;
-      display_x11->pointer_xgrab_implicit = FALSE;
-    }
+    _gdk_x11_roundtrip_async (GDK_DISPLAY_OBJECT (display_x11),
+                             has_pointer_grab_callback,
+                             NULL);
 
   return gdk_x11_convert_grab_status (return_val);
 }
 
-/**
- * gdk_pointer_grab_info_libgtk_only:
- * @display: the #GdkDisplay for which to get the grab information
- * @grab_window: location to store current grab window
- * @owner_events: location to store boolean indicating whether
- *   the @owner_events flag to gdk_pointer_grab() was %TRUE.
- * 
- * Determines information about the current pointer grab.
- * This is not public API and must not be used by applications.
- * 
- * Return value: %TRUE if this application currently has the
- *  pointer grabbed.
- **/
-gboolean
-gdk_pointer_grab_info_libgtk_only (GdkDisplay *display,
-                                  GdkWindow **grab_window,
-                                  gboolean   *owner_events)
-{
-  GdkDisplayX11 *display_x11;
-  
-  g_return_val_if_fail (GDK_IS_DISPLAY (display), False);
-
-  display_x11 = GDK_DISPLAY_X11 (display);
-
-  if (display_x11->pointer_xgrab_window)
-    {
-      if (grab_window)
-        *grab_window = (GdkWindow *)display_x11->pointer_xgrab_window;
-      if (owner_events)
-        *owner_events = display_x11->pointer_xgrab_owner_events;
-
-      return TRUE;
-    }
-  else
-    return FALSE;
-}
-
 /*
  *--------------------------------------------------------------
  * gdk_keyboard_grab
@@ -341,24 +263,33 @@ gdk_keyboard_grab (GdkWindow *       window,
 {
   gint return_val;
   unsigned long serial;
+  GdkDisplay *display;
   GdkDisplayX11 *display_x11;
-  
+  GdkWindow *native;
+
   g_return_val_if_fail (window != NULL, 0);
   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
-  
-  display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
 
-  serial = NextRequest (GDK_WINDOW_XDISPLAY (window));
+  native = gdk_window_get_toplevel (window);
+
+  /* TODO: What do we do for offscreens and  children? We need to proxy the grab somehow */
+  if (!GDK_IS_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (native)->impl))
+    return GDK_GRAB_SUCCESS;
+
+  display = GDK_WINDOW_DISPLAY (native);
+  display_x11 = GDK_DISPLAY_X11 (display);
+
+  serial = NextRequest (GDK_WINDOW_XDISPLAY (native));
 
-  if (!GDK_WINDOW_DESTROYED (window))
+  if (!GDK_WINDOW_DESTROYED (native))
     {
 #ifdef G_ENABLE_DEBUG
       if (_gdk_debug_flags & GDK_DEBUG_NOGRABS)
        return_val = GrabSuccess;
       else
 #endif
-       return_val = XGrabKeyboard (GDK_WINDOW_XDISPLAY (window),
-                                   GDK_WINDOW_XID (window),
+       return_val = XGrabKeyboard (GDK_WINDOW_XDISPLAY (native),
+                                   GDK_WINDOW_XID (native),
                                    owner_events,
                                    GrabModeAsync, GrabModeAsync,
                                    time);
@@ -371,58 +302,14 @@ gdk_keyboard_grab (GdkWindow *       window,
     return_val = AlreadyGrabbed;
 
   if (return_val == GrabSuccess)
-    {
-      if (display_x11->keyboard_xgrab_window != NULL &&
-         display_x11->keyboard_xgrab_window != (GdkWindowObject *)window)
-       generate_grab_broken_event (GDK_WINDOW (display_x11->keyboard_xgrab_window),
-                                   TRUE, FALSE, window);
-      
-      display_x11->keyboard_xgrab_window = (GdkWindowObject *)window;
-      display_x11->keyboard_xgrab_serial = serial;
-      display_x11->keyboard_xgrab_owner_events = owner_events;
-      display_x11->keyboard_xgrab_time = time;      
-    }
+    _gdk_display_set_has_keyboard_grab (display,
+                                       window, native,
+                                       owner_events,
+                                       serial, time);
 
   return gdk_x11_convert_grab_status (return_val);
 }
 
-/**
- * gdk_keyboard_grab_info_libgtk_only:
- * @display: the display for which to get the grab information
- * @grab_window: location to store current grab window
- * @owner_events: location to store boolean indicating whether
- *   the @owner_events flag to gdk_keyboard_grab() was %TRUE.
- * 
- * Determines information about the current keyboard grab.
- * This is not public API and must not be used by applications.
- * 
- * Return value: %TRUE if this application currently has the
- *  keyboard grabbed.
- **/
-gboolean
-gdk_keyboard_grab_info_libgtk_only (GdkDisplay *display,
-                                   GdkWindow **grab_window,
-                                   gboolean   *owner_events)
-{
-  GdkDisplayX11 *display_x11;
-  
-  g_return_val_if_fail (GDK_IS_DISPLAY (display), False);
-
-  display_x11 = GDK_DISPLAY_X11 (display);
-
-  if (display_x11->keyboard_xgrab_window)
-    {
-      if (grab_window)
-        *grab_window = (GdkWindow *)display_x11->keyboard_xgrab_window;
-      if (owner_events)
-        *owner_events = display_x11->keyboard_xgrab_owner_events;
-
-      return TRUE;
-    }
-  else
-    return FALSE;
-}
-
 /**
  * _gdk_xgrab_check_unmap:
  * @window: a #GdkWindow
@@ -437,42 +324,21 @@ void
 _gdk_xgrab_check_unmap (GdkWindow *window,
                        gulong     serial)
 {
-  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (gdk_drawable_get_display (window));
-  
-  if (display_x11->pointer_xgrab_window && 
-      serial >= display_x11->pointer_xgrab_serial)
-    {
-      GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
-      GdkWindowObject *tmp = display_x11->pointer_xgrab_window;
+  GdkDisplay *display = gdk_drawable_get_display (window);
 
-      while (tmp && tmp != private)
-       tmp = tmp->parent;
+  _gdk_display_end_pointer_grab (display, serial, window, TRUE);
 
-      if (tmp)
-       {         
-         generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_xgrab_window),
-                                     FALSE, display_x11->pointer_xgrab_implicit, 
-                                     NULL);
-         display_x11->pointer_xgrab_window = NULL;  
-       }
-    }
-
-  if (display_x11->keyboard_xgrab_window &&
-      serial >= display_x11->keyboard_xgrab_serial)
+  if (display->keyboard_grab.window &&
+      serial >= display->keyboard_grab.serial)
     {
       GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
-      GdkWindowObject *tmp = display_x11->keyboard_xgrab_window;
-      
+      GdkWindowObject *tmp = GDK_WINDOW_OBJECT (display->keyboard_grab.window);
 
       while (tmp && tmp != private)
        tmp = tmp->parent;
 
       if (tmp)
-       {
-         generate_grab_broken_event (GDK_WINDOW (display_x11->keyboard_xgrab_window),
-                                     TRUE, FALSE, NULL);
-         display_x11->keyboard_xgrab_window = NULL;  
-       }
+       _gdk_display_unset_has_keyboard_grab (display, TRUE);
     }
 }
 
@@ -486,67 +352,26 @@ _gdk_xgrab_check_unmap (GdkWindow *window,
 void
 _gdk_xgrab_check_destroy (GdkWindow *window)
 {
-  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (gdk_drawable_get_display (window));
-  
-  if ((GdkWindowObject *)window == display_x11->pointer_xgrab_window)
-    {
-      generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_xgrab_window),
-                                 FALSE, display_x11->pointer_xgrab_implicit,
-                                 NULL);
-      display_x11->pointer_xgrab_window = NULL;
-    }
+  GdkDisplay *display = gdk_drawable_get_display (window);
+  GdkPointerGrabInfo *grab;
 
-  if ((GdkWindowObject *)window ==  display_x11->keyboard_xgrab_window)
+  /* Make sure there is no lasting grab in this native
+     window */
+  grab = _gdk_display_get_last_pointer_grab (display);
+  if (grab && grab->native_window == window)
     {
-      generate_grab_broken_event (GDK_WINDOW (display_x11->keyboard_xgrab_window),
-                                 TRUE, FALSE, NULL);
-      display_x11->keyboard_xgrab_window = NULL;
+      /* We don't know the actual serial to end, but it
+        doesn't really matter as this only happens
+        after we get told of the destroy from the
+        server so we know its ended in the server,
+        just make sure its ended. */
+      grab->serial_end = grab->serial_start;
+      grab->implicit_ungrab = TRUE;
     }
-}
-
-#define GDK_ANY_BUTTON_MASK (GDK_BUTTON1_MASK | \
-                             GDK_BUTTON2_MASK | \
-                             GDK_BUTTON3_MASK | \
-                             GDK_BUTTON4_MASK | \
-                             GDK_BUTTON5_MASK)
-
-/**
- * _gdk_xgrab_check_button_event:
- * @window: a #GdkWindow
- * @event: an XEvent of type ButtonPress or ButtonRelease
- * 
- * Checks to see if a button event starts or ends an implicit grab.
- **/
-void
-_gdk_xgrab_check_button_event (GdkWindow *window, 
-                              XEvent *xevent)
-{
-  GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (gdk_drawable_get_display (window));
   
-  /* track implicit grabs for button presses */
-  switch (xevent->type)
-    {
-    case ButtonPress:
-      if (!display_x11->pointer_xgrab_window)
-       {
-         display_x11->pointer_xgrab_window = (GdkWindowObject *)window;
-         display_x11->pointer_xgrab_serial = xevent->xany.serial;
-         display_x11->pointer_xgrab_owner_events = FALSE;
-         display_x11->pointer_xgrab_time = xevent->xbutton.time;
-         display_x11->pointer_xgrab_implicit = TRUE;     
-       }
-      break;
-    case ButtonRelease:
-      if (display_x11->pointer_xgrab_window &&
-         display_x11->pointer_xgrab_implicit &&
-         (xevent->xbutton.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (xevent->xbutton.button - 1))) == 0)
-       {
-         display_x11->pointer_xgrab_window = NULL;
-       }
-      break;
-    default:
-      g_assert_not_reached ();
-    }
+  if (window == display->keyboard_grab.native_window &&
+      display->keyboard_grab.window != NULL)
+    _gdk_display_unset_has_keyboard_grab (display, TRUE);
 }
 
 void
index 7984b5a08962035280e0882ad4403878a8721d06..1fcaf5a9b42ca097eba050ea3503bb6ddb0c5154 100644 (file)
@@ -137,10 +137,10 @@ gdk_pixmap_impl_x11_get_size   (GdkDrawable *drawable,
 }
 
 GdkPixmap*
-gdk_pixmap_new (GdkDrawable *drawable,
-               gint         width,
-               gint         height,
-               gint         depth)
+_gdk_pixmap_new (GdkDrawable *drawable,
+                 gint         width,
+                 gint         height,
+                 gint         depth)
 {
   GdkPixmap *pixmap;
   GdkDrawableImplX11 *draw_impl;
@@ -194,10 +194,10 @@ gdk_pixmap_new (GdkDrawable *drawable,
 }
 
 GdkPixmap *
-gdk_bitmap_create_from_data (GdkDrawable *drawable,
-                            const gchar *data,
-                            gint         width,
-                            gint         height)
+_gdk_bitmap_create_from_data (GdkDrawable *drawable,
+                              const gchar *data,
+                              gint         width,
+                              gint         height)
 {
   GdkPixmap *pixmap;
   GdkDrawableImplX11 *draw_impl;
@@ -238,13 +238,13 @@ gdk_bitmap_create_from_data (GdkDrawable *drawable,
 }
 
 GdkPixmap*
-gdk_pixmap_create_from_data (GdkDrawable    *drawable,
-                            const gchar    *data,
-                            gint            width,
-                            gint            height,
-                            gint            depth,
-                            const GdkColor *fg,
-                            const GdkColor *bg)
+_gdk_pixmap_create_from_data (GdkDrawable    *drawable,
+                             const gchar    *data,
+                             gint            width,
+                             gint            height,
+                             gint            depth,
+                             const GdkColor *fg,
+                             const GdkColor *bg)
 {
   GdkPixmap *pixmap;
   GdkDrawableImplX11 *draw_impl;
index f24a0df4c1adec038c04f4cf88e298ac0720823d..871fa74fd3723fd988025eb8392361c4d4453883 100644 (file)
@@ -118,7 +118,6 @@ GdkImage *_gdk_x11_copy_to_image       (GdkDrawable *drawable,
 Pixmap   _gdk_x11_image_get_shm_pixmap (GdkImage    *image);
 
 /* Routines from gdkgeometry-x11.c */
-void _gdk_window_init_position     (GdkWindow     *window);
 void _gdk_window_move_resize_child (GdkWindow     *window,
                                     gint           x,
                                     gint           y,
@@ -128,13 +127,12 @@ void _gdk_window_process_expose    (GdkWindow     *window,
                                     gulong         serial,
                                     GdkRectangle  *area);
 
-void _gdk_x11_window_scroll        (GdkWindow       *window,
-                                    gint             dx,
-                                    gint             dy);
-void _gdk_x11_window_move_region   (GdkWindow       *window,
-                                    const GdkRegion *region,
-                                    gint             dx,
-                                    gint             dy);
+gboolean _gdk_x11_window_queue_antiexpose  (GdkWindow *window,
+                                           GdkRegion *area);
+void     _gdk_x11_window_queue_translation (GdkWindow *window,
+                                           GdkRegion *area,
+                                           gint       dx,
+                                           gint       dy);
 
 void     _gdk_selection_window_destroyed   (GdkWindow            *window);
 gboolean _gdk_selection_filter_clear_event (XSelectionClearEvent *event);
@@ -166,8 +164,6 @@ void _gdk_x11_initialize_locale (void);
 void _gdk_xgrab_check_unmap        (GdkWindow *window,
                                    gulong     serial);
 void _gdk_xgrab_check_destroy      (GdkWindow *window);
-void _gdk_xgrab_check_button_event (GdkWindow *window,
-                                   XEvent    *xevent);
 
 gboolean _gdk_x11_display_is_root_window (GdkDisplay *display,
                                          Window      xroot_window);
@@ -216,5 +212,6 @@ extern gboolean          _gdk_synchronize;
 #define GDK_WINDOW_DISPLAY(win)       (GDK_SCREEN_X11 (GDK_WINDOW_SCREEN (win))->display)
 #define GDK_WINDOW_XROOTWIN(win)      (GDK_SCREEN_X11 (GDK_WINDOW_SCREEN (win))->xroot_window)
 #define GDK_GC_DISPLAY(gc)            (GDK_SCREEN_DISPLAY (GDK_GC_X11(gc)->screen))
+#define GDK_WINDOW_IS_X11(win)        (GDK_IS_WINDOW_IMPL_X11 (((GdkWindowObject *)win)->impl))
 
 #endif /* __GDK_PRIVATE_X11_H__ */
index c415dee383756ba9dc054660d8039d607e8bc536..181b13e81937b1a2926d40e75c6bb77b9b7fcebf 100644 (file)
@@ -546,7 +546,7 @@ gdk_property_get (GdkWindow   *window,
   Atom xtype;
   int res;
 
-  g_return_val_if_fail (!window || GDK_IS_WINDOW (window), FALSE);
+  g_return_val_if_fail (!window || GDK_WINDOW_IS_X11 (window), FALSE);
 
   if (!window)
     {
@@ -555,6 +555,8 @@ gdk_property_get (GdkWindow   *window,
       
       GDK_NOTE (MULTIHEAD, g_message ("gdk_property_get(): window is NULL\n"));
     }
+  else if (!GDK_WINDOW_IS_X11 (window))
+    return FALSE;
 
   if (GDK_WINDOW_DESTROYED (window))
     return FALSE;
@@ -680,7 +682,7 @@ gdk_property_change (GdkWindow    *window,
   Atom xproperty;
   Atom xtype;
 
-  g_return_if_fail (!window || GDK_IS_WINDOW (window));
+  g_return_if_fail (!window || GDK_WINDOW_IS_X11 (window));
 
   if (!window)
     {
@@ -691,7 +693,8 @@ gdk_property_change (GdkWindow    *window,
       
       GDK_NOTE (MULTIHEAD, g_message ("gdk_property_change(): window is NULL\n"));
     }
-
+  else if (!GDK_WINDOW_IS_X11 (window))
+    return;
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
@@ -731,7 +734,7 @@ void
 gdk_property_delete (GdkWindow *window,
                     GdkAtom    property)
 {
-  g_return_if_fail (!window || GDK_IS_WINDOW (window));
+  g_return_if_fail (!window || GDK_WINDOW_IS_X11 (window));
 
   if (!window)
     {
@@ -741,6 +744,8 @@ gdk_property_delete (GdkWindow *window,
       GDK_NOTE (MULTIHEAD, 
                g_message ("gdk_property_delete(): window is NULL\n"));
     }
+  else if (!GDK_WINDOW_IS_X11 (window))
+    return;
 
   if (GDK_WINDOW_DESTROYED (window))
     return;
index 6045dadea34d7dd0ceb61384a2cda0b950130ae9..7d23080fdd05231c279af5620a66cc67f838c801 100644 (file)
@@ -141,7 +141,7 @@ gdk_selection_owner_set_for_display (GdkDisplay *display,
 
   if (owner) 
     {
-      if (GDK_WINDOW_DESTROYED (owner))
+      if (GDK_WINDOW_DESTROYED (owner) || !GDK_WINDOW_IS_X11 (owner))
        return FALSE;
       
       xdisplay = GDK_WINDOW_XDISPLAY (owner);
@@ -231,7 +231,7 @@ gdk_selection_convert (GdkWindow *requestor,
 
   g_return_if_fail (selection != GDK_NONE);
   
-  if (GDK_WINDOW_DESTROYED (requestor))
+  if (GDK_WINDOW_DESTROYED (requestor) || !GDK_WINDOW_IS_X11 (requestor))
     return;
 
   display = GDK_WINDOW_DISPLAY (requestor);
@@ -279,10 +279,11 @@ gdk_selection_property_get (GdkWindow  *requestor,
 
   g_return_val_if_fail (requestor != NULL, 0);
   g_return_val_if_fail (GDK_IS_WINDOW (requestor), 0);
+  g_return_val_if_fail (GDK_WINDOW_IS_X11 (requestor), 0);
   
   display = GDK_WINDOW_DISPLAY (requestor);
 
-  if (GDK_WINDOW_DESTROYED (requestor))
+  if (GDK_WINDOW_DESTROYED (requestor) || !GDK_WINDOW_IS_X11 (requestor))
     goto err;
 
   t = NULL;
index bfaa7a1178a296d4625f690ae3a03e12b61cb083..303b18aa27a89487c160558a10c44be9de1f85ea 100644 (file)
@@ -110,16 +110,13 @@ static void     move_to_current_desktop           (GdkWindow *window);
 static GdkColormap* gdk_window_impl_x11_get_colormap (GdkDrawable *drawable);
 static void         gdk_window_impl_x11_set_colormap (GdkDrawable *drawable,
                                                      GdkColormap *cmap);
-static void         gdk_window_impl_x11_get_size    (GdkDrawable *drawable,
-                                                    gint *width,
-                                                    gint *height);
-static GdkRegion*  gdk_window_impl_x11_get_visible_region (GdkDrawable *drawable);
 static void        gdk_window_impl_x11_finalize   (GObject            *object);
 static void        gdk_window_impl_iface_init     (GdkWindowImplIface *iface);
 
-#define WINDOW_IS_TOPLEVEL(window)                \
-  (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
-   GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
+#define WINDOW_IS_TOPLEVEL(window)                  \
+  (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&   \
+   GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN && \
+   GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
 
 /* Return whether time1 is considered later than time2 as far as xserver
  * time is concerned.  Accounts for wraparound.
@@ -144,8 +141,6 @@ _gdk_window_impl_get_type (void)
 static void
 gdk_window_impl_x11_init (GdkWindowImplX11 *impl)
 {  
-  impl->width = 1;
-  impl->height = 1;
   impl->toplevel_window_type = -1;
 }
 
@@ -179,11 +174,6 @@ gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
 
   drawable_class->set_colormap = gdk_window_impl_x11_set_colormap;
   drawable_class->get_colormap = gdk_window_impl_x11_get_colormap;
-  drawable_class->get_size = gdk_window_impl_x11_get_size;
-
-  /* Visible and clip regions are the same */
-  drawable_class->get_clip_region = gdk_window_impl_x11_get_visible_region;
-  drawable_class->get_visible_region = gdk_window_impl_x11_get_visible_region;
 }
 
 static void
@@ -228,14 +218,7 @@ tmp_unset_bg (GdkWindow *window)
   obj = (GdkWindowObject *) window;
   impl = GDK_WINDOW_IMPL_X11 (obj->impl);
 
-  /* For windows without EXPOSURE_MASK, we can't do this
-   * unsetting because such windows depend on the drawing
-   * that the X server is going to do
-   */
-  if (!(obj->event_mask & GDK_EXPOSURE_MASK))
-    return;
-    
-  impl->position_info.no_bg = TRUE;
+  impl->no_bg = TRUE;
 
   if (obj->bg_pixmap != GDK_NO_BG)
     XSetWindowBackgroundPixmap (GDK_DRAWABLE_XDISPLAY (window),
@@ -251,10 +234,7 @@ tmp_reset_bg (GdkWindow *window)
   obj = (GdkWindowObject *) window;
   impl = GDK_WINDOW_IMPL_X11 (obj->impl);
 
-  if (!(obj->event_mask & GDK_EXPOSURE_MASK))
-    return;
-    
-  impl->position_info.no_bg = FALSE;
+  impl->no_bg = FALSE;
 
   if (obj->bg_pixmap == GDK_NO_BG)
     return;
@@ -299,15 +279,13 @@ _gdk_x11_window_tmp_unset_bg (GdkWindow *window,
   if (private->input_only || private->destroyed ||
       (private->window_type != GDK_WINDOW_ROOT &&
        !GDK_WINDOW_IS_MAPPED (window)))
-    {
-      return;
-    }
-
-  if (private->window_type != GDK_WINDOW_ROOT &&
+    return;
+  
+  if (_gdk_window_has_impl (window) &&
+      GDK_WINDOW_IS_X11 (window) &&
+      private->window_type != GDK_WINDOW_ROOT &&
       private->window_type != GDK_WINDOW_FOREIGN)
-    {
-      tmp_unset_bg (window);
-    }
+    tmp_unset_bg (window);
 
   if (recurse)
     {
@@ -318,6 +296,19 @@ _gdk_x11_window_tmp_unset_bg (GdkWindow *window,
     }
 }
 
+void
+_gdk_x11_window_tmp_unset_parent_bg (GdkWindow *window)
+{
+  GdkWindowObject *private;
+  private = (GdkWindowObject*) window;
+
+  if (GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
+    return;
+  
+  window = _gdk_window_get_impl_window ((GdkWindow *)private->parent);
+  _gdk_x11_window_tmp_unset_bg (window,        FALSE);
+}
+
 void
 _gdk_x11_window_tmp_reset_bg (GdkWindow *window,
                              gboolean   recurse)
@@ -331,15 +322,14 @@ _gdk_x11_window_tmp_reset_bg (GdkWindow *window,
   if (private->input_only || private->destroyed ||
       (private->window_type != GDK_WINDOW_ROOT &&
        !GDK_WINDOW_IS_MAPPED (window)))
-    {
-      return;
-    }
+    return;
 
-  if (private->window_type != GDK_WINDOW_ROOT &&
+  
+  if (_gdk_window_has_impl (window) &&
+      GDK_WINDOW_IS_X11 (window) &&
+      private->window_type != GDK_WINDOW_ROOT &&
       private->window_type != GDK_WINDOW_FOREIGN)
-    {
-      tmp_reset_bg (window);
-    }
+    tmp_reset_bg (window);
 
   if (recurse)
     {
@@ -350,6 +340,20 @@ _gdk_x11_window_tmp_reset_bg (GdkWindow *window,
     }
 }
 
+void
+_gdk_x11_window_tmp_reset_parent_bg (GdkWindow *window)
+{
+  GdkWindowObject *private;
+  private = (GdkWindowObject*) window;
+
+  if (GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
+    return;
+  
+  window = _gdk_window_get_impl_window ((GdkWindow *)private->parent);
+
+  _gdk_x11_window_tmp_reset_bg (window, FALSE);
+}
+
 static GdkColormap*
 gdk_window_impl_x11_get_colormap (GdkDrawable *drawable)
 {
@@ -407,35 +411,6 @@ gdk_window_impl_x11_set_colormap (GdkDrawable *drawable,
 }
 
 
-static void
-gdk_window_impl_x11_get_size (GdkDrawable *drawable,
-                              gint        *width,
-                              gint        *height)
-{
-  g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (drawable));
-
-  if (width)
-    *width = GDK_WINDOW_IMPL_X11 (drawable)->width;
-  if (height)
-    *height = GDK_WINDOW_IMPL_X11 (drawable)->height;
-}
-
-static GdkRegion*
-gdk_window_impl_x11_get_visible_region (GdkDrawable *drawable)
-{
-  GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (drawable);
-  GdkRectangle result_rect;
-
-  result_rect.x = 0;
-  result_rect.y = 0;
-  result_rect.width = impl->width;
-  result_rect.height = impl->height;
-
-  gdk_rectangle_intersect (&result_rect, &impl->position_info.clip_rect, &result_rect);
-
-  return gdk_region_rectangle (&result_rect);
-}
-
 void
 _gdk_windowing_window_init (GdkScreen * screen)
 {
@@ -455,6 +430,7 @@ _gdk_windowing_window_init (GdkScreen * screen)
 
   private = (GdkWindowObject *) screen_x11->root_window;
   private->impl = g_object_new (_gdk_window_impl_get_type (), NULL);
+  private->impl_window = private;
 
   impl = GDK_WINDOW_IMPL_X11 (private->impl);
   draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
@@ -467,12 +443,14 @@ _gdk_windowing_window_init (GdkScreen * screen)
   
   private->window_type = GDK_WINDOW_ROOT;
   private->depth = DefaultDepthOfScreen (screen_x11->xscreen);
-  
-  impl->width = WidthOfScreen (screen_x11->xscreen);
-  impl->height = HeightOfScreen (screen_x11->xscreen);
-  
-  _gdk_window_init_position (GDK_WINDOW (private));
 
+  private->x = 0;
+  private->y = 0;
+  private->abs_x = 0;
+  private->abs_y = 0;
+  private->width = WidthOfScreen (screen_x11->xscreen);
+  private->height = HeightOfScreen (screen_x11->xscreen);
+  
   _gdk_xid_table_insert (screen_x11->display,
                         &screen_x11->xroot_window,
                         screen_x11->root_window);
@@ -587,7 +565,6 @@ setup_toplevel_window (GdkWindow *window,
 {
   GdkWindowObject *obj = (GdkWindowObject *)window;
   GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
-  GdkWindowImplX11 *impl = (GdkWindowImplX11 *)obj->impl;
   Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
   XID xid = GDK_WINDOW_XID (window);
   XID xparent = GDK_WINDOW_XID (parent);
@@ -617,8 +594,8 @@ setup_toplevel_window (GdkWindow *window,
    * correct value???
    */
   size_hints.flags = PSize;
-  size_hints.width = impl->width;
-  size_hints.height = impl->height;
+  size_hints.width = obj->width;
+  size_hints.height = obj->height;
   
   XSetWMNormalHints (xdisplay, xid, &size_hints);
   
@@ -654,19 +631,20 @@ setup_toplevel_window (GdkWindow *window,
   ensure_sync_counter (window);
 }
 
-GdkWindow *
-_gdk_window_new (GdkWindow     *parent,
-                GdkWindowAttr *attributes,
-                gint           attributes_mask)
+void
+_gdk_window_impl_new (GdkWindow     *window,
+                     GdkWindow     *real_parent,
+                     GdkScreen     *screen,
+                     GdkVisual     *visual,
+                     GdkEventMask   event_mask,
+                     GdkWindowAttr *attributes,
+                     gint           attributes_mask)
 {
-  GdkWindow *window;
   GdkWindowObject *private;
   GdkWindowImplX11 *impl;
   GdkDrawableImplX11 *draw_impl;
   GdkScreenX11 *screen_x11;
-  GdkScreen *screen;
   
-  GdkVisual *visual;
   Window xparent;
   Visual *xvisual;
   Display *xdisplay;
@@ -675,117 +653,34 @@ _gdk_window_new (GdkWindow     *parent,
   XSetWindowAttributes xattributes;
   long xattributes_mask;
   XClassHint *class_hint;
-  int x, y, depth;
   
   unsigned int class;
   const char *title;
   int i;
   
-  g_return_val_if_fail (attributes != NULL, NULL);
+  private = (GdkWindowObject *) window;
   
-  if (!parent)
-    {
-      GDK_NOTE (MULTIHEAD,
-               g_warning ("gdk_window_new(): no parent specified reverting to parent = default root window"));
-      
-      screen = gdk_screen_get_default ();
-      parent = gdk_screen_get_root_window (screen);
-    }
-  else
-    screen = gdk_drawable_get_screen (parent);
-
   screen_x11 = GDK_SCREEN_X11 (screen);
-
-  g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
-  
-  if (GDK_WINDOW_DESTROYED (parent))
-    return NULL;
+  xparent = GDK_WINDOW_XID (real_parent);
   
-  xparent = GDK_WINDOW_XID (parent);
-  
-  window = g_object_new (GDK_TYPE_WINDOW, NULL);
-
-  private = (GdkWindowObject *) window;
-  private->impl = g_object_new (_gdk_window_impl_get_type (), NULL);
-
-  impl = GDK_WINDOW_IMPL_X11 (private->impl);
-  draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
+  impl = g_object_new (_gdk_window_impl_get_type (), NULL);
+  private->impl = (GdkDrawable *)impl;
+  draw_impl = GDK_DRAWABLE_IMPL_X11 (impl);
   draw_impl->wrapper = GDK_DRAWABLE (window);
   
   draw_impl->screen = screen;
   xdisplay = screen_x11->xdisplay;
 
-  /* Windows with a foreign parent are treated as if they are children
-   * of the root window, except for actual creation.
-   */
-  if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
-    parent = gdk_screen_get_root_window (screen);
-  
-  private->parent = (GdkWindowObject *)parent;
-
-  private->accept_focus = TRUE;
-  private->focus_on_map = TRUE;
-
   xattributes_mask = 0;
-  
-  if (attributes_mask & GDK_WA_X)
-    x = attributes->x;
-  else
-    x = 0;
-  
-  if (attributes_mask & GDK_WA_Y)
-    y = attributes->y;
-  else
-    y = 0;
-  
-  private->x = x;
-  private->y = y;
-  impl->width = (attributes->width > 1) ? (attributes->width) : (1);
-  impl->height = (attributes->height > 1) ? (attributes->height) : (1);
-
-  if (attributes->wclass == GDK_INPUT_ONLY)
-    {
-      /* Backwards compatiblity - we've always ignored
-       * attributes->window_type for input-only windows
-       * before
-       */
-      if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
-       private->window_type = GDK_WINDOW_TEMP;
-      else
-       private->window_type = GDK_WINDOW_CHILD;
-    }
-  else
-    private->window_type = attributes->window_type;
-
-  /* Work around a bug where Xorg refuses to map toplevel InputOnly windows 
-   * from an untrusted client: http://bugs.freedesktop.org/show_bug.cgi?id=6988
-   */
-  if (attributes->wclass == GDK_INPUT_ONLY &&
-      GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT &&
-      !G_LIKELY (GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (parent))->trusted_client))
-    {
-      g_warning ("Coercing GDK_INPUT_ONLY toplevel window to GDK_INPUT_OUTPUT to work around bug in Xorg server");
-      attributes->wclass = GDK_INPUT_OUTPUT;
-    }
 
-  _gdk_window_init_position (GDK_WINDOW (private));
-  if (impl->position_info.big)
-    private->guffaw_gravity = TRUE;
-  
-  if (attributes_mask & GDK_WA_VISUAL)
-    visual = attributes->visual;
-  else
-    visual = gdk_screen_get_system_visual (screen);
   xvisual = ((GdkVisualPrivate*) visual)->xvisual;
   
   xattributes.event_mask = StructureNotifyMask | PropertyChangeMask;
   for (i = 0; i < _gdk_nenvent_masks; i++)
     {
-      if (attributes->event_mask & (1 << (i + 1)))
+      if (event_mask & (1 << (i + 1)))
        xattributes.event_mask |= _gdk_event_mask_table[i];
     }
-  private->event_mask = attributes->event_mask;
-  
   if (xattributes.event_mask)
     xattributes_mask |= CWEventMask;
   
@@ -812,27 +707,17 @@ _gdk_window_new (GdkWindow     *parent,
     case GDK_WINDOW_TOPLEVEL:
     case GDK_WINDOW_DIALOG:
     case GDK_WINDOW_TEMP:
-      if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
+      if (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
        {
-         g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
-                    "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
+         /* The common code warns for this case */
          xparent = GDK_SCREEN_XROOTWIN (screen);
        }
-    case GDK_WINDOW_CHILD:
-      break;
-    default:
-      g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
-      return NULL;
     }
          
-  if (attributes->wclass == GDK_INPUT_OUTPUT)
+  if (!private->input_only)
     {
       class = InputOutput;
-      depth = visual->depth;
 
-      private->input_only = FALSE;
-      private->depth = depth;
-      
       if (attributes_mask & GDK_WA_COLORMAP)
         {
           draw_impl->colormap = attributes->colormap;
@@ -851,12 +736,8 @@ _gdk_window_new (GdkWindow     *parent,
             }
        }
       
-      private->bg_color.pixel = BlackPixel (xdisplay, screen_x11->screen_num);
-      private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
       xattributes.background_pixel = private->bg_color.pixel;
 
-      private->bg_pixmap = NULL;
-      
       xattributes.border_pixel = BlackPixel (xdisplay, screen_x11->screen_num);
       xattributes_mask |= CWBorderPixel | CWBackPixel;
 
@@ -882,30 +763,32 @@ _gdk_window_new (GdkWindow     *parent,
     }
   else
     {
-      depth = 0;
-      private->depth = 0;
       class = InputOnly;
-      private->input_only = TRUE;
       draw_impl->colormap = gdk_screen_get_system_colormap (screen);
       g_object_ref (draw_impl->colormap);
     }
 
+  if (private->width > 65535 ||
+      private->height > 65535)
+    {
+      g_warning ("Native Windows wider or taller than 65535 pixels are not supported");
+      
+      if (private->width > 65535)
+       private->width = 65535;
+      if (private->height > 65535)
+       private->height = 65535;
+    }
+  
   xid = draw_impl->xid = XCreateWindow (xdisplay, xparent,
-                                       impl->position_info.x, impl->position_info.y,
-                                       impl->position_info.width, impl->position_info.height,
-                                       0, depth, class, xvisual,
+                                       private->x + private->parent->abs_x,
+                                       private->y + private->parent->abs_y,
+                                       private->width, private->height,
+                                       0, private->depth, class, xvisual,
                                        xattributes_mask, &xattributes);
 
   g_object_ref (window);
   _gdk_xid_table_insert (screen_x11->display, &draw_impl->xid, window);
-  
-  gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
-                                 (attributes->cursor) :
-                                 NULL));
-  
-  if (private->parent)
-    private->parent->children = g_list_prepend (private->parent->children, window);
-  
+
   switch (GDK_WINDOW_TYPE (private))
     {
     case GDK_WINDOW_DIALOG:
@@ -927,11 +810,11 @@ _gdk_window_new (GdkWindow     *parent,
          XFree (class_hint);
        }
   
-      setup_toplevel_window (window, parent);
+      setup_toplevel_window (window, (GdkWindow *)private->parent);
       break;
 
     case GDK_WINDOW_CHILD:
-      if ((attributes->wclass == GDK_INPUT_OUTPUT) &&
+      if (!private->input_only &&
          (draw_impl->colormap != gdk_screen_get_system_colormap (screen)) &&
          (draw_impl->colormap != gdk_drawable_get_colormap (gdk_window_get_toplevel (window))))
        {
@@ -946,8 +829,6 @@ _gdk_window_new (GdkWindow     *parent,
 
   if (attributes_mask & GDK_WA_TYPE_HINT)
     gdk_window_set_type_hint (window, attributes->type_hint);
-
-  return window;
 }
 
 static GdkEventMask
@@ -1025,6 +906,7 @@ gdk_window_foreign_new_for_display (GdkDisplay     *display,
 
   private = (GdkWindowObject *) window;
   private->impl = g_object_new (_gdk_window_impl_get_type (), NULL);
+  private->impl_window = private;
 
   impl = GDK_WINDOW_IMPL_X11 (private->impl);
   draw_impl = GDK_DRAWABLE_IMPL_X11 (private->impl);
@@ -1042,8 +924,8 @@ gdk_window_foreign_new_for_display (GdkDisplay     *display,
 
   private->x = attrs.x;
   private->y = attrs.y;
-  impl->width = attrs.width;
-  impl->height = attrs.height;
+  private->width = attrs.width;
+  private->height = attrs.height;
   private->window_type = GDK_WINDOW_FOREIGN;
   private->destroyed = FALSE;
 
@@ -1056,10 +938,12 @@ gdk_window_foreign_new_for_display (GdkDisplay     *display,
 
   private->depth = attrs.depth;
   
-  _gdk_window_init_position (GDK_WINDOW (private));
-
   g_object_ref (window);
   _gdk_xid_table_insert (display, &GDK_WINDOW_XID (window), window);
+
+  /* Update the clip region, etc */
+  _gdk_window_update_size (window);
+  
   return window;
 }
 
@@ -1138,10 +1022,10 @@ gdk_toplevel_x11_free_contents (GdkDisplay *display,
 #endif
 }
 
-void
-_gdk_windowing_window_destroy (GdkWindow *window,
-                              gboolean   recursing,
-                              gboolean   foreign_destroy)
+static void
+_gdk_x11_window_destroy (GdkWindow *window,
+                        gboolean   recursing,
+                        gboolean   foreign_destroy)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
   GdkToplevelX11 *toplevel;
@@ -1150,9 +1034,6 @@ _gdk_windowing_window_destroy (GdkWindow *window,
 
   _gdk_selection_window_destroyed (window);
   
-  if (private->extension_events != 0)
-    _gdk_input_window_destroy (window);
-
   toplevel = _gdk_x11_window_get_toplevel (window);
   if (toplevel)
     gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), toplevel);
@@ -1213,8 +1094,6 @@ gdk_window_destroy_notify (GdkWindow *window)
 {
   GdkWindowImplX11 *window_impl;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
   window_impl = GDK_WINDOW_IMPL_X11 (((GdkWindowObject *)window)->impl);
 
   if (!GDK_WINDOW_DESTROYED (window))
@@ -1417,66 +1296,44 @@ set_initial_hints (GdkWindow *window)
 }
 
 static void
-gdk_window_x11_show (GdkWindow *window,
-                     gboolean   raise)
+gdk_window_x11_show (GdkWindow *window, gboolean already_mapped)
 {
-  GdkWindowObject *private;
+  GdkWindowObject *private = (GdkWindowObject*) window;
   GdkDisplay *display;
   GdkDisplayX11 *display_x11;
   GdkToplevelX11 *toplevel;
-  
-  private = (GdkWindowObject*) window;
-  if (!private->destroyed)
-    {
-      GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
-      Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
-      Window xwindow = GDK_WINDOW_XID (window);
-      
-      if (raise)
-        XRaiseWindow (xdisplay, xwindow);
+  GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
+  Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
+  Window xwindow = GDK_WINDOW_XID (window);
+  gboolean unset_bg;
 
-      if (!GDK_WINDOW_IS_MAPPED (window))
-        {
-          set_initial_hints (window);
-          
-          gdk_synthesize_window_state (window,
-                                       GDK_WINDOW_STATE_WITHDRAWN,
-                                       0);
-        }
+  if (!already_mapped)
+    set_initial_hints (window);
       
-      g_assert (GDK_WINDOW_IS_MAPPED (window));
-
-      if (WINDOW_IS_TOPLEVEL (window))
-       {
-         display = gdk_drawable_get_display (window);
-         display_x11 = GDK_DISPLAY_X11 (display);
-         toplevel = _gdk_x11_window_get_toplevel (window);
-
-          if (toplevel->user_time != 0 &&
+  if (WINDOW_IS_TOPLEVEL (window))
+    {
+      display = gdk_drawable_get_display (window);
+      display_x11 = GDK_DISPLAY_X11 (display);
+      toplevel = _gdk_x11_window_get_toplevel (window);
+      
+      if (toplevel->user_time != 0 &&
              display_x11->user_time != 0 &&
-             XSERVER_TIME_IS_LATER (display_x11->user_time, toplevel->user_time))
-           gdk_x11_window_set_user_time (window, display_x11->user_time);
-       }
-
-      if (impl->position_info.mapped)
-       {
-         gboolean unset_bg = !private->input_only &&
-           (private->window_type == GDK_WINDOW_CHILD ||
-            impl->override_redirect) &&
-           gdk_window_is_viewable (window);
-
-         if (unset_bg)
-           _gdk_x11_window_tmp_unset_bg (window, TRUE);
-         
-         XMapWindow (xdisplay, xwindow);
-
-         if (unset_bg)
-           {
-             _gdk_x11_window_tmp_reset_bg (window, TRUE);
-             gdk_window_invalidate_rect (window, NULL, TRUE);
-           }
-       }
+         XSERVER_TIME_IS_LATER (display_x11->user_time, toplevel->user_time))
+       gdk_x11_window_set_user_time (window, display_x11->user_time);
     }
+  
+  unset_bg = !private->input_only &&
+    (private->window_type == GDK_WINDOW_CHILD ||
+     impl->override_redirect) &&
+    gdk_window_is_viewable (window);
+  
+  if (unset_bg)
+    _gdk_x11_window_tmp_unset_bg (window, TRUE);
+  
+  XMapWindow (xdisplay, xwindow);
+  
+  if (unset_bg)
+    _gdk_x11_window_tmp_reset_bg (window, TRUE);
 }
 
 static void
@@ -1489,7 +1346,7 @@ pre_unmap (GdkWindow *window)
     return;
 
   if (private->window_type == GDK_WINDOW_CHILD)
-    start_window = (GdkWindow *)private->parent;
+    start_window = _gdk_window_get_impl_window ((GdkWindow *)private->parent);
   else if (private->window_type == GDK_WINDOW_TEMP)
     start_window = get_root (window);
 
@@ -1507,7 +1364,7 @@ post_unmap (GdkWindow *window)
     return;
 
   if (private->window_type == GDK_WINDOW_CHILD)
-    start_window = (GdkWindow *)private->parent;
+    start_window = _gdk_window_get_impl_window ((GdkWindow *)private->parent);
   else if (private->window_type == GDK_WINDOW_TEMP)
     start_window = get_root (window);
 
@@ -1557,24 +1414,12 @@ gdk_window_x11_hide (GdkWindow *window)
       break;
     }
   
-  if (!private->destroyed)
-    {
-      if (GDK_WINDOW_IS_MAPPED (window))
-        gdk_synthesize_window_state (window,
-                                     0,
-                                     GDK_WINDOW_STATE_WITHDRAWN);
-
-      g_assert (!GDK_WINDOW_IS_MAPPED (window));
-      
-      _gdk_window_clear_update_area (window);
-
-      pre_unmap (window);
-      
-      XUnmapWindow (GDK_WINDOW_XDISPLAY (window),
-                    GDK_WINDOW_XID (window));
-
-      post_unmap (window);
-    }
+  _gdk_window_clear_update_area (window);
+  
+  pre_unmap (window);
+  XUnmapWindow (GDK_WINDOW_XDISPLAY (window),
+               GDK_WINDOW_XID (window));
+  post_unmap (window);
 }
 
 static void
@@ -1613,7 +1458,7 @@ window_x11_move (GdkWindow *window,
     {
       _gdk_window_move_resize_child (window,
                                      x, y,
-                                     impl->width, impl->height);
+                                     private->width, private->height);
     }
   else
     {
@@ -1647,7 +1492,6 @@ window_x11_resize (GdkWindow *window,
       _gdk_window_move_resize_child (window,
                                      private->x, private->y,
                                      width, height);
-      _gdk_x11_drawable_update_size (private->impl);
     }
   else
     {
@@ -1659,13 +1503,13 @@ window_x11_resize (GdkWindow *window,
 
       if (impl->override_redirect)
         {
-          impl->width = width;
-          impl->height = height;
+          private->width = width;
+          private->height = height;
           _gdk_x11_drawable_update_size (private->impl);
         }
       else
         {
-          if (width != impl->width || height != impl->height)
+          if (width != private->width || height != private->height)
             private->resize_count += 1;
         }
     }
@@ -1706,14 +1550,14 @@ window_x11_move_resize (GdkWindow *window,
           private->x = x;
           private->y = y;
 
-          impl->width = width;
-          impl->height = height;
+          private->width = width;
+          private->height = height;
 
           _gdk_x11_drawable_update_size (private->impl);
         }
       else
         {
-          if (width != impl->width || height != impl->height)
+          if (width != private->width || height != private->height)
             private->resize_count += 1;
         }
     }
@@ -1748,31 +1592,25 @@ gdk_window_x11_reparent (GdkWindow *window,
   GdkWindowObject *parent_private;
   GdkWindowObject *old_parent_private;
   GdkWindowImplX11 *impl;
-  gboolean was_toplevel;
-
-  if (!new_parent)
-    new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
 
   window_private = (GdkWindowObject*) window;
   old_parent_private = (GdkWindowObject*)window_private->parent;
   parent_private = (GdkWindowObject*) new_parent;
   impl = GDK_WINDOW_IMPL_X11 (window_private->impl);
 
+  _gdk_x11_window_tmp_unset_bg (window, TRUE);
+  _gdk_x11_window_tmp_unset_parent_bg (window);
   XReparentWindow (GDK_WINDOW_XDISPLAY (window),
                   GDK_WINDOW_XID (window),
                   GDK_WINDOW_XID (new_parent),
-                  x, y);
+                  parent_private->abs_x + x, parent_private->abs_y + y);
+  _gdk_x11_window_tmp_reset_parent_bg (window);
+  _gdk_x11_window_tmp_reset_bg (window, TRUE);
 
-  window_private->x = x;
-  window_private->y = y;
-
-  /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
-   * the root window
-   */
   if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
     new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
 
-  window_private->parent = (GdkWindowObject *)new_parent;
+  window_private->parent = parent_private;
 
   /* Switch the window type as appropriate */
 
@@ -1780,83 +1618,79 @@ gdk_window_x11_reparent (GdkWindow *window,
     {
     case GDK_WINDOW_ROOT:
     case GDK_WINDOW_FOREIGN:
-      was_toplevel = WINDOW_IS_TOPLEVEL (window);
-
-      if (impl->toplevel_window_type != -1)
-       GDK_WINDOW_TYPE (window) = impl->toplevel_window_type;
-      else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
-       GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
+      /* Reparenting to toplevel */
+      
+      if (!WINDOW_IS_TOPLEVEL (window) &&
+         GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
+       {
+         /* This is also done in common code at a later stage, but we
+            need it in setup_toplevel, so do it here too */
+         if (window_private->toplevel_window_type != -1)
+           GDK_WINDOW_TYPE (window) = window_private->toplevel_window_type;
+         else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
+           GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
+         
+         /* Wasn't a toplevel, set up */
+         setup_toplevel_window (window, new_parent);
+       }
 
-      if (WINDOW_IS_TOPLEVEL (window) && !was_toplevel)
-       setup_toplevel_window (window, new_parent);
       break;
+      
     case GDK_WINDOW_TOPLEVEL:
     case GDK_WINDOW_CHILD:
     case GDK_WINDOW_DIALOG:
     case GDK_WINDOW_TEMP:
-      if (WINDOW_IS_TOPLEVEL (window))
+      if (WINDOW_IS_TOPLEVEL (window) &&
+         impl->toplevel)
        {
-         /* Save the original window type so we can restore it if the
-          * window is reparented back to be a toplevel
-          */
-         impl->toplevel_window_type = GDK_WINDOW_TYPE (window);
-         GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
-         if (impl->toplevel)
+         if (impl->toplevel->focus_window)
            {
-             if (impl->toplevel->focus_window)
-               {
-                 XDestroyWindow (GDK_WINDOW_XDISPLAY (window), impl->toplevel->focus_window);
-                 _gdk_xid_table_remove (GDK_WINDOW_DISPLAY (window), impl->toplevel->focus_window);
-               }
-
-             gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), 
-                                             impl->toplevel);
-             g_free (impl->toplevel);
-             impl->toplevel = NULL;
+             XDestroyWindow (GDK_WINDOW_XDISPLAY (window), impl->toplevel->focus_window);
+             _gdk_xid_table_remove (GDK_WINDOW_DISPLAY (window), impl->toplevel->focus_window);
            }
+         
+         gdk_toplevel_x11_free_contents (GDK_WINDOW_DISPLAY (window), 
+                                         impl->toplevel);
+         g_free (impl->toplevel);
+         impl->toplevel = NULL;
        }
     }
 
-  if (old_parent_private)
-    old_parent_private->children = g_list_remove (old_parent_private->children, window);
-
-  if ((old_parent_private &&
-       (!old_parent_private->guffaw_gravity != !parent_private->guffaw_gravity)) ||
-      (!old_parent_private && parent_private->guffaw_gravity))
-    gdk_window_set_static_win_gravity (window, parent_private->guffaw_gravity);
-
-  parent_private->children = g_list_prepend (parent_private->children, window);
-  _gdk_window_init_position (GDK_WINDOW (window_private));
-
   return FALSE;
 }
 
 static void
-gdk_window_x11_clear_area (GdkWindow *window,
-                           gint       x,
-                           gint       y,
-                           gint       width,
-                           gint       height,
-                           gboolean   send_expose)
+gdk_window_x11_raise (GdkWindow *window)
 {
-  if (!GDK_WINDOW_DESTROYED (window))
-    XClearArea (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window),
-               x, y, width, height,
-                send_expose);
+  XRaiseWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
 }
 
 static void
-gdk_window_x11_raise (GdkWindow *window)
+gdk_window_x11_restack_under (GdkWindow *window,
+                             GList *native_siblings /* in requested order, first is bottom-most */)
 {
-  if (!GDK_WINDOW_DESTROYED (window))
-    XRaiseWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
+  Window *windows;
+  int n_windows, i;
+  GList *l;
+
+  n_windows = g_list_length (native_siblings) + 1;
+  windows = g_new (Window, n_windows);
+
+  windows[0] = GDK_WINDOW_XID (window);
+  /* Reverse order, as input order is bottom-most first */
+  i = n_windows - 1;
+  for (l = native_siblings; l != NULL; l = l->next)
+    windows[i--] = GDK_WINDOW_XID (l->data);
+  XRestackWindows (GDK_WINDOW_XDISPLAY (window), windows, n_windows);
+  
+  g_free (windows);
 }
 
 static void
 gdk_window_x11_lower (GdkWindow *window)
 {
-  if (!GDK_WINDOW_DESTROYED (window))
-    XLowerWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
+  XLowerWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
 }
 
 /**
@@ -1957,10 +1791,11 @@ gdk_window_focus (GdkWindow *window,
                   guint32    timestamp)
 {
   GdkDisplay *display;
-  
-  g_return_if_fail (GDK_IS_WINDOW (window));
 
-  if (GDK_WINDOW_DESTROYED (window))
+  g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
+  
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   display = GDK_WINDOW_DISPLAY (window);
@@ -2030,9 +1865,8 @@ gdk_window_set_hints (GdkWindow *window,
 {
   XSizeHints size_hints;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
   
   size_hints.flags = 0;
@@ -2085,9 +1919,8 @@ gdk_window_set_type_hint (GdkWindow        *window,
   GdkDisplay *display;
   Atom atom;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   display = gdk_drawable_get_display (window);
@@ -2170,7 +2003,8 @@ gdk_window_get_type_hint (GdkWindow *window)
 
   g_return_val_if_fail (GDK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
 
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return GDK_WINDOW_TYPE_HINT_NORMAL;
 
   type = GDK_WINDOW_TYPE_HINT_NORMAL;
@@ -2271,9 +2105,8 @@ gdk_window_set_modal_hint (GdkWindow *window,
 {
   GdkWindowObject *private;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   private = (GdkWindowObject*) window;
@@ -2306,10 +2139,10 @@ gdk_window_set_skip_taskbar_hint (GdkWindow *window,
 {
   GdkToplevelX11 *toplevel;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
   
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   toplevel = _gdk_x11_window_get_toplevel (window);
@@ -2343,10 +2176,10 @@ gdk_window_set_skip_pager_hint (GdkWindow *window,
 {
   GdkToplevelX11 *toplevel;
     
-  g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
   
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   toplevel = _gdk_x11_window_get_toplevel (window);
@@ -2374,10 +2207,10 @@ gdk_window_set_urgency_hint (GdkWindow *window,
 {
   GdkToplevelX11 *toplevel;
     
-  g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
   
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   toplevel = _gdk_x11_window_get_toplevel (window);
@@ -2422,9 +2255,8 @@ gdk_window_set_geometry_hints (GdkWindow         *window,
 {
   XSizeHints size_hints;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
   
   size_hints.flags = 0;
@@ -2531,7 +2363,8 @@ gdk_window_get_geometry_hints (GdkWindow      *window,
 
   *geom_mask = 0;
   
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   size_hints = XAllocSizeHints ();
@@ -2686,10 +2519,10 @@ gdk_window_set_title (GdkWindow   *window,
   Display *xdisplay;
   Window xwindow;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (title != NULL);
 
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
   
   display = gdk_drawable_get_display (window);
@@ -2736,11 +2569,10 @@ gdk_window_set_role (GdkWindow   *window,
 {
   GdkDisplay *display;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
   display = gdk_drawable_get_display (window);
 
-  if (!GDK_WINDOW_DESTROYED (window))
+  if (!GDK_WINDOW_DESTROYED (window) &&
+      WINDOW_IS_TOPLEVEL (window))
     {
       if (role)
        XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
@@ -2765,7 +2597,7 @@ gdk_window_set_role (GdkWindow   *window,
  **/
 void          
 gdk_window_set_startup_id (GdkWindow   *window,
-                    const gchar *startup_id)
+                          const gchar *startup_id)
 {
   GdkDisplay *display;
   
@@ -2773,13 +2605,14 @@ gdk_window_set_startup_id (GdkWindow   *window,
 
   display = gdk_drawable_get_display (window);
 
-  if (!GDK_WINDOW_DESTROYED (window))
+  if (!GDK_WINDOW_DESTROYED (window) &&
+      WINDOW_IS_TOPLEVEL (window))
     {
       if (startup_id)
        XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
                         gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"), 
                         gdk_x11_get_xatom_by_name_for_display (display, "UTF8_STRING"), 8,
-                        PropModeReplace, startup_id, strlen (startup_id));
+                        PropModeReplace, (unsigned char *)startup_id, strlen (startup_id));
       else
        XDeleteProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
                         gdk_x11_get_xatom_by_name_for_display (display, "_NET_STARTUP_ID"));
@@ -2804,9 +2637,8 @@ void
 gdk_window_set_transient_for (GdkWindow *window, 
                              GdkWindow *parent)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (parent))
+  if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (parent) &&
+      WINDOW_IS_TOPLEVEL (window))
     XSetTransientForHint (GDK_WINDOW_XDISPLAY (window), 
                          GDK_WINDOW_XID (window),
                          GDK_WINDOW_XID (parent));
@@ -2816,62 +2648,22 @@ static void
 gdk_window_x11_set_background (GdkWindow      *window,
                                const GdkColor *color)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkColormap *colormap = gdk_drawable_get_colormap (window);
-  
-  if (!GDK_WINDOW_DESTROYED (window))
-    XSetWindowBackground (GDK_WINDOW_XDISPLAY (window),
-                         GDK_WINDOW_XID (window), color->pixel);
-
-  private->bg_color = *color;
-  gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
-
-  if (private->bg_pixmap &&
-      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
-      private->bg_pixmap != GDK_NO_BG)
-    g_object_unref (private->bg_pixmap);
-  
-  private->bg_pixmap = NULL;
+  XSetWindowBackground (GDK_WINDOW_XDISPLAY (window),
+                       GDK_WINDOW_XID (window), color->pixel);
 }
 
 static void
 gdk_window_x11_set_back_pixmap (GdkWindow *window,
-                                GdkPixmap *pixmap,
-                                gboolean   parent_relative)
+                                GdkPixmap *pixmap)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
   Pixmap xpixmap;
   
-  if (pixmap && !gdk_drawable_get_colormap (pixmap))
-    {
-      g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
-      return;
-    }
-  
-  if (private->bg_pixmap &&
-      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
-      private->bg_pixmap != GDK_NO_BG)
-    g_object_unref (private->bg_pixmap);
-
-  if (parent_relative)
-    {
-      xpixmap = ParentRelative;
-      private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
-    }
+  if (pixmap == GDK_PARENT_RELATIVE_BG)
+    xpixmap = ParentRelative;
+  else if (pixmap == GDK_NO_BG)
+    xpixmap = None;
   else
-    {
-      if (pixmap)
-       {
-         g_object_ref (pixmap);
-         private->bg_pixmap = pixmap;
-         xpixmap = GDK_PIXMAP_XID (pixmap);
-       }
-      else
-       {
-         xpixmap = None;
-         private->bg_pixmap = GDK_NO_BG;
-       }
-    }
+    xpixmap = GDK_PIXMAP_XID (pixmap);
   
   if (!GDK_WINDOW_DESTROYED (window))
     XSetWindowBackgroundPixmap (GDK_WINDOW_XDISPLAY (window),
@@ -2966,9 +2758,11 @@ gdk_window_x11_get_geometry (GdkWindow *window,
 }
 
 static gint
-gdk_window_x11_get_origin (GdkWindow *window,
-                           gint      *x,
-                           gint      *y)
+gdk_window_x11_get_root_coords (GdkWindow *window,
+                               gint       x,
+                               gint       y,
+                               gint      *root_x,
+                               gint      *root_y)
 {
   gint return_val;
   Window child;
@@ -2980,95 +2774,68 @@ gdk_window_x11_get_origin (GdkWindow *window,
       return_val = XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window),
                                          GDK_WINDOW_XID (window),
                                          GDK_WINDOW_XROOTWIN (window),
-                                         0, 0, &tx, &ty,
+                                         x, y, &tx, &ty,
                                          &child);
     }
   else
     return_val = 0;
   
-  if (x)
-    *x = tx;
-  if (y)
-    *y = ty;
+  if (root_x)
+    *root_x = tx;
+  if (root_y)
+    *root_y = ty;
   
   return return_val;
 }
 
-/**
- * gdk_window_get_deskrelative_origin:
- * @window: a toplevel #GdkWindow
- * @x: return location for X coordinate
- * @y: return location for Y coordinate
- * 
- * This gets the origin of a #GdkWindow relative to
- * an Enlightenment-window-manager desktop. As long as you don't
- * assume that the user's desktop/workspace covers the entire
- * root window (i.e. you don't assume that the desktop begins
- * at root window coordinate 0,0) this function is not necessary.
- * It's deprecated for that reason.
- * 
- * Return value: not meaningful
- **/
-gboolean
-gdk_window_get_deskrelative_origin (GdkWindow *window,
-                                   gint      *x,
-                                   gint      *y)
+static gboolean
+gdk_window_x11_get_deskrelative_origin (GdkWindow *window,
+                                       gint      *x,
+                                       gint      *y)
 {
   gboolean return_val = FALSE;
   gint num_children, format_return;
   Window win, *child, parent, root;
-  gint tx = 0;
-  gint ty = 0;
   Atom type_return;
   Atom atom;
   gulong number_return, bytes_after_return;
   guchar *data_return;
   
-  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+  atom = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
+                                               "ENLIGHTENMENT_DESKTOP");
+  win = GDK_WINDOW_XID (window);
   
-  if (!GDK_WINDOW_DESTROYED (window))
+  while (XQueryTree (GDK_WINDOW_XDISPLAY (window), win, &root, &parent,
+                    &child, (unsigned int *)&num_children))
     {
-      atom = gdk_x11_get_xatom_by_name_for_display (GDK_WINDOW_DISPLAY (window),
-                                                   "ENLIGHTENMENT_DESKTOP");
-      win = GDK_WINDOW_XID (window);
+      if ((child) && (num_children > 0))
+       XFree (child);
+      
+      if (!parent)
+       break;
+      else
+       win = parent;
+      
+      if (win == root)
+       break;
       
-      while (XQueryTree (GDK_WINDOW_XDISPLAY (window), win, &root, &parent,
-                        &child, (unsigned int *)&num_children))
+      data_return = NULL;
+      XGetWindowProperty (GDK_WINDOW_XDISPLAY (window), win, atom, 0, 0,
+                         False, XA_CARDINAL, &type_return, &format_return,
+                         &number_return, &bytes_after_return, &data_return);
+      
+      if (type_return == XA_CARDINAL)
        {
-         if ((child) && (num_children > 0))
-           XFree (child);
-         
-         if (!parent)
-           break;
-         else
-           win = parent;
-         
-         if (win == root)
-           break;
-         
-         data_return = NULL;
-         XGetWindowProperty (GDK_WINDOW_XDISPLAY (window), win, atom, 0, 0,
-                             False, XA_CARDINAL, &type_return, &format_return,
-                             &number_return, &bytes_after_return, &data_return);
-
-         if (type_return == XA_CARDINAL)
-           {
-             XFree (data_return);
-              break;
-           }
+         XFree (data_return);
+         break;
        }
-      
-      return_val = XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window),
-                                         GDK_WINDOW_XID (window),
-                                         win,
-                                         0, 0, &tx, &ty,
-                                         &root);
-      if (x)
-       *x = tx;
-      if (y)
-       *y = ty;
     }
   
+  return_val = XTranslateCoordinates (GDK_WINDOW_XDISPLAY (window),
+                                     GDK_WINDOW_XID (window),
+                                     win,
+                                     0, 0, x, y,
+                                     &root);
   
   return return_val;
 }
@@ -3090,8 +2857,6 @@ gdk_window_get_root_origin (GdkWindow *window,
 {
   GdkRectangle rect;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
   gdk_window_get_frame_extents (window, &rect);
 
   if (x)
@@ -3136,7 +2901,6 @@ gdk_window_get_frame_extents (GdkWindow    *window,
   gint wx, wy;
   gboolean got_frame_extents = FALSE;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (rect != NULL);
   
   private = (GdkWindowObject*) window;
@@ -3146,9 +2910,6 @@ gdk_window_get_frame_extents (GdkWindow    *window,
   rect->width = 1;
   rect->height = 1;
   
-  if (GDK_WINDOW_DESTROYED (window))
-    return;
-  
   while (private->parent && ((GdkWindowObject*) private->parent)->parent)
     private = (GdkWindowObject*) private->parent;
 
@@ -3327,55 +3088,53 @@ _gdk_windowing_get_pointer (GdkDisplay       *display,
   *mask = xmask;
 }
 
-GdkWindow*
-_gdk_windowing_window_get_pointer (GdkDisplay      *display,
-                                  GdkWindow       *window,
-                                  gint            *x,
-                                  gint            *y,
-                                  GdkModifierType *mask)
+static gboolean
+gdk_window_x11_get_pointer (GdkWindow       *window,
+                           gint            *x,
+                           gint            *y,
+                           GdkModifierType *mask)
 {
-  GdkWindow *return_val;
+  GdkDisplay *display = GDK_WINDOW_DISPLAY (window);
+  gboolean return_val;
   Window root;
   Window child;
   int rootx, rooty;
   int winx = 0;
   int winy = 0;
   unsigned int xmask = 0;
-  gint xoffset, yoffset;
 
-  g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
-  
-  _gdk_x11_window_get_offsets (window, &xoffset, &yoffset);
+  g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), FALSE);
 
-  return_val = NULL;
-  if (!GDK_WINDOW_DESTROYED (window)) 
+  
+  return_val = TRUE;
+  if (!GDK_WINDOW_DESTROYED (window))
     {
-      if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client)) 
+      if (G_LIKELY (GDK_DISPLAY_X11 (display)->trusted_client))
        {
          if (XQueryPointer (GDK_WINDOW_XDISPLAY (window),
                             GDK_WINDOW_XID (window),
                             &root, &child, &rootx, &rooty, &winx, &winy, &xmask))
            {
              if (child)
-               return_val = gdk_window_lookup_for_display (GDK_WINDOW_DISPLAY (window), child);
+               return_val = gdk_window_lookup_for_display (GDK_WINDOW_DISPLAY (window), child) != NULL;
            }
-       } 
-      else 
+       }
+      else
        {
          GdkScreen *screen;
          int originx, originy;
-         _gdk_windowing_get_pointer (gdk_drawable_get_display (window), &screen, 
+         _gdk_windowing_get_pointer (gdk_drawable_get_display (window), &screen,
                                      &rootx, &rooty, &xmask);
          gdk_window_get_origin (window, &originx, &originy);
          winx = rootx - originx;
          winy = rooty - originy;
        }
     }
-  
-  *x = winx + xoffset;
-  *y = winy + yoffset;
+
+  *x = winx;
+  *y = winy;
   *mask = xmask;
-  
+
   return return_val;
 }
 
@@ -3418,7 +3177,8 @@ gdk_display_warp_pointer (GdkDisplay *display,
 GdkWindow*
 _gdk_windowing_window_at_pointer (GdkDisplay *display,
                                   gint       *win_x,
-                                 gint       *win_y)
+                                 gint       *win_y,
+                                 GdkModifierType *mask)
 {
   GdkWindow *window;
   GdkScreen *screen;
@@ -3527,7 +3287,9 @@ _gdk_windowing_window_at_pointer (GdkDisplay *display,
   window = gdk_window_lookup_for_display (display, xwindow_last);
   *win_x = window ? winx : -1;
   *win_y = window ? winy : -1;
-
+  if (mask)
+    *mask = xmask;
+  
   return window;
 }
 
@@ -3562,7 +3324,6 @@ gdk_window_x11_set_events (GdkWindow    *window,
   
   if (!GDK_WINDOW_DESTROYED (window))
     {
-      GDK_WINDOW_OBJECT (window)->event_mask = event_mask;
       if (GDK_WINDOW_XID (window) != GDK_WINDOW_XROOTWIN (window))
         xevent_mask = StructureNotifyMask | PropertyChangeMask;
       for (i = 0; i < _gdk_nenvent_masks; i++)
@@ -3622,110 +3383,6 @@ gdk_window_add_colormap_windows (GdkWindow *window)
     XFree (old_windows);
 }
 
-#define WARN_SHAPE_TOO_BIG() g_warning ("GdkWindow is too large to allow the use of shape masks or shape regions.")
-
-/*
- * This needs the X11 shape extension.
- * If not available, shaped windows will look
- * ugly, but programs still work.    Stefan Wille
- */
-static inline void
-do_shape_combine_mask (GdkWindow *window,
-                      GdkBitmap *mask,
-                      gint       x,
-                      gint       y,
-                      gint       shape)
-{
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  Pixmap pixmap;
-  gint xoffset, yoffset;
-
-  if (GDK_WINDOW_DESTROYED (window))
-    return;
-
-  _gdk_x11_window_get_offsets (window, &xoffset, &yoffset);
-
-  if (xoffset != 0 || yoffset != 0)
-    {
-      WARN_SHAPE_TOO_BIG ();
-      return;
-    }
-  
-  if (shape == ShapeBounding
-      ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
-      : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
-    {
-      if (mask)
-       {
-         pixmap = GDK_PIXMAP_XID (mask);
-         
-         private->shaped = (shape == ShapeBounding);
-       }
-      else
-       {
-         x = 0;
-         y = 0;
-         pixmap = None;
-
-         private->shaped = FALSE;
-       }
-      
-      XShapeCombineMask (GDK_WINDOW_XDISPLAY (window),
-                        GDK_WINDOW_XID (window),
-                        shape,
-                        x, y,
-                        pixmap,
-                        ShapeSet);
-    }
-}
-
-static void
-gdk_window_x11_shape_combine_mask (GdkWindow *window,
-                                   GdkBitmap *mask,
-                                   gint       x,
-                                   gint       y)
-{
-  do_shape_combine_mask (window, mask, x, y, ShapeBounding);
-}
-
-/**
- * gdk_window_input_shape_combine_mask:
- * @window: a #GdkWindow
- * @mask: shape mask
- * @x: X position of shape mask with respect to @window
- * @y: Y position of shape mask with respect to @window
- * 
- * Like gdk_window_shape_combine_mask(), but the shape applies
- * only to event handling. Mouse events which happen while
- * the pointer position corresponds to an unset bit in the 
- * mask will be passed on the window below @window.
- *
- * An input shape is typically used with RGBA windows.
- * The alpha channel of the window defines which pixels are 
- * invisible and allows for nicely antialiased borders,
- * and the input shape controls where the window is
- * "clickable".
- *
- * On the X11 platform, this requires version 1.1 of the
- * shape extension.
- *
- * On the Win32 platform, this functionality is not present and the
- * function does nothing.
- *
- * Since: 2.10
- */
-void 
-gdk_window_input_shape_combine_mask (GdkWindow *window,
-                                    GdkBitmap *mask,
-                                    gint       x,
-                                    gint       y)
-{
-#ifdef ShapeInput
-  do_shape_combine_mask (window, mask, x, y, ShapeInput);
-#endif
-}
-
-
 static inline void
 do_shape_combine_region (GdkWindow       *window,
                         const GdkRegion *shape_region,
@@ -3734,23 +3391,37 @@ do_shape_combine_region (GdkWindow       *window,
                         gint             shape)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
-  gint xoffset, yoffset;
-
+  
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
-  _gdk_x11_window_get_offsets (window, &xoffset, &yoffset);
-
-  if (xoffset != 0 || yoffset != 0)
-    {
-      WARN_SHAPE_TOO_BIG ();
-      return;
-    }
-  
   if (shape_region == NULL)
     {
       /* Use NULL mask to unset the shape */
-      gdk_window_shape_combine_mask (window, NULL, 0, 0);
+      if (shape == ShapeBounding
+         ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
+         : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
+       {
+         if (shape == ShapeBounding)
+           private->shaped = FALSE;
+         
+         if (shape == ShapeBounding)
+           {
+             _gdk_x11_window_tmp_unset_parent_bg (window);
+             _gdk_x11_window_tmp_unset_bg (window, TRUE);
+           }
+         XShapeCombineMask (GDK_WINDOW_XDISPLAY (window),
+                            GDK_WINDOW_XID (window),
+                            shape,
+                            0, 0,
+                            None,
+                            ShapeSet);
+         if (shape == ShapeBounding)
+           {
+             _gdk_x11_window_tmp_reset_parent_bg (window);
+             _gdk_x11_window_tmp_reset_bg (window, TRUE);
+           }
+       }
       return;
     }
   
@@ -3761,12 +3432,18 @@ do_shape_combine_region (GdkWindow       *window,
       gint n_rects = 0;
       XRectangle *xrects = NULL;
 
-      private->shaped = shape == ShapeBounding;
+      if (shape == ShapeBounding)
+       private->shaped = TRUE;
 
       _gdk_region_get_xrectangles (shape_region,
                                    0, 0,
                                    &xrects, &n_rects);
       
+      if (shape == ShapeBounding)
+       {
+         _gdk_x11_window_tmp_unset_parent_bg (window);
+         _gdk_x11_window_tmp_unset_bg (window, TRUE);
+       }
       XShapeCombineRectangles (GDK_WINDOW_XDISPLAY (window),
                                GDK_WINDOW_XID (window),
                                shape,
@@ -3775,6 +3452,12 @@ do_shape_combine_region (GdkWindow       *window,
                                ShapeSet,
                                YXBanded);
 
+      if (shape == ShapeBounding)
+       {
+         _gdk_x11_window_tmp_reset_parent_bg (window);
+         _gdk_x11_window_tmp_reset_bg (window, TRUE);
+       }
+      
       g_free (xrects);
     }
 }
@@ -3788,37 +3471,11 @@ gdk_window_x11_shape_combine_region (GdkWindow       *window,
   do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeBounding);
 }
 
-/**
- * gdk_window_input_shape_combine_region:
- * @window: a #GdkWindow
- * @shape_region: region of window to be non-transparent
- * @offset_x: X position of @shape_region in @window coordinates
- * @offset_y: Y position of @shape_region in @window coordinates
- * 
- * Like gdk_window_shape_combine_region(), but the shape applies
- * only to event handling. Mouse events which happen while
- * the pointer position corresponds to an unset bit in the 
- * mask will be passed on the window below @window.
- *
- * An input shape is typically used with RGBA windows.
- * The alpha channel of the window defines which pixels are 
- * invisible and allows for nicely antialiased borders,
- * and the input shape controls where the window is
- * "clickable".
- *
- * On the X11 platform, this requires version 1.1 of the
- * shape extension.
- *
- * On the Win32 platform, this functionality is not present and the
- * function does nothing.
- *
- * Since: 2.10
- */
-void 
-gdk_window_input_shape_combine_region (GdkWindow       *window,
-                                      const GdkRegion *shape_region,
-                                      gint             offset_x,
-                                      gint             offset_y)
+static void 
+gdk_window_x11_input_shape_combine_region (GdkWindow       *window,
+                                          const GdkRegion *shape_region,
+                                          gint             offset_x,
+                                          gint             offset_y)
 {
 #ifdef ShapeInput
   do_shape_combine_region (window, shape_region, offset_x, offset_y, ShapeInput);
@@ -3847,9 +3504,8 @@ gdk_window_set_override_redirect (GdkWindow *window,
 {
   XSetWindowAttributes attr;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (!GDK_WINDOW_DESTROYED (window))
+  if (!GDK_WINDOW_DESTROYED (window) &&
+      WINDOW_IS_TOPLEVEL (window))
     {
       GdkWindowObject *private = (GdkWindowObject *)window;
       GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
@@ -3883,8 +3539,6 @@ gdk_window_set_accept_focus (GdkWindow *window,
 {
   GdkWindowObject *private;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
   private = (GdkWindowObject *)window;  
   
   accept_focus = accept_focus != FALSE;
@@ -3893,7 +3547,8 @@ gdk_window_set_accept_focus (GdkWindow *window,
     {
       private->accept_focus = accept_focus;
 
-      if (!GDK_WINDOW_DESTROYED (window))
+      if (!GDK_WINDOW_DESTROYED (window) &&
+         WINDOW_IS_TOPLEVEL (window))
        update_wm_hints (window, FALSE);
     }
 }
@@ -3920,8 +3575,6 @@ gdk_window_set_focus_on_map (GdkWindow *window,
 {
   GdkWindowObject *private;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
   private = (GdkWindowObject *)window;  
   
   focus_on_map = focus_on_map != FALSE;
@@ -3929,8 +3582,10 @@ gdk_window_set_focus_on_map (GdkWindow *window,
   if (private->focus_on_map != focus_on_map)
     {
       private->focus_on_map = focus_on_map;
-
-      if ((!GDK_WINDOW_DESTROYED (window)) && (!private->focus_on_map))
+      
+      if ((!GDK_WINDOW_DESTROYED (window)) &&
+         (!private->focus_on_map) &&
+         WINDOW_IS_TOPLEVEL (window))
        gdk_x11_window_set_user_time (window, 0);
     }
 }
@@ -3965,9 +3620,8 @@ gdk_x11_window_set_user_time (GdkWindow *window,
   glong timestamp_long = (glong)timestamp;
   Window xid;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   display = gdk_drawable_get_display (window);
@@ -4037,9 +3691,8 @@ gdk_window_set_icon_list (GdkWindow *window,
   GdkDisplay *display;
   gint n;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   display = gdk_drawable_get_display (window);
@@ -4149,10 +3802,10 @@ gdk_window_set_icon (GdkWindow *window,
 {
   GdkToplevelX11 *toplevel;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
   
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   toplevel = _gdk_x11_window_get_toplevel (window);
@@ -4214,9 +3867,8 @@ gdk_window_set_icon_name (GdkWindow   *window,
 {
   GdkDisplay *display;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      WINDOW_IS_TOPLEVEL (window))
     return;
 
   display = gdk_drawable_get_display (window);
@@ -4261,9 +3913,8 @@ gdk_window_set_icon_name (GdkWindow   *window,
 void
 gdk_window_iconify (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (GDK_WINDOW_IS_MAPPED (window))
@@ -4295,9 +3946,8 @@ gdk_window_iconify (GdkWindow *window)
 void
 gdk_window_deiconify (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (GDK_WINDOW_IS_MAPPED (window))
@@ -4331,9 +3981,8 @@ gdk_window_deiconify (GdkWindow *window)
 void
 gdk_window_stick (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (GDK_WINDOW_IS_MAPPED (window))
@@ -4388,9 +4037,8 @@ gdk_window_stick (GdkWindow *window)
 void
 gdk_window_unstick (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (GDK_WINDOW_IS_MAPPED (window))
@@ -4432,9 +4080,8 @@ gdk_window_unstick (GdkWindow *window)
 void
 gdk_window_maximize (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (GDK_WINDOW_IS_MAPPED (window))
@@ -4467,9 +4114,8 @@ gdk_window_maximize (GdkWindow *window)
 void
 gdk_window_unmaximize (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (GDK_WINDOW_IS_MAPPED (window))
@@ -4505,9 +4151,8 @@ gdk_window_unmaximize (GdkWindow *window)
 void
 gdk_window_fullscreen (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (GDK_WINDOW_IS_MAPPED (window))
@@ -4541,9 +4186,8 @@ gdk_window_fullscreen (GdkWindow *window)
 void
 gdk_window_unfullscreen (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (GDK_WINDOW_IS_MAPPED (window))
@@ -4580,7 +4224,8 @@ gdk_window_set_keep_above (GdkWindow *window,
 {
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (GDK_WINDOW_IS_MAPPED (window))
@@ -4621,7 +4266,8 @@ gdk_window_set_keep_below (GdkWindow *window, gboolean setting)
 {
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (GDK_WINDOW_IS_MAPPED (window))
@@ -4655,10 +4301,10 @@ gdk_window_get_group (GdkWindow *window)
 {
   GdkToplevelX11 *toplevel;
   
-  g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
   g_return_val_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD, NULL);
 
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return NULL;
   
   toplevel = _gdk_x11_window_get_toplevel (window);
@@ -4692,7 +4338,9 @@ gdk_window_set_group (GdkWindow *window,
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
   g_return_if_fail (leader == NULL || GDK_IS_WINDOW (leader));
 
-  if (GDK_WINDOW_DESTROYED (window) || (leader != NULL && GDK_WINDOW_DESTROYED (leader)))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      (leader != NULL && GDK_WINDOW_DESTROYED (leader)) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   toplevel = _gdk_x11_window_get_toplevel (window);
@@ -4817,8 +4465,10 @@ gdk_window_set_decorations (GdkWindow      *window,
                            GdkWMDecoration decorations)
 {
   MotifWmHints hints;
-  
-  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
   
   /* initialize to zero to avoid writing uninitialized data to socket */
   memset(&hints, 0, sizeof(hints));
@@ -4843,8 +4493,10 @@ gdk_window_get_decorations(GdkWindow       *window,
   MotifWmHints *hints;
   gboolean result = FALSE;
 
-  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
-
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return FALSE;
+  
   hints = gdk_window_get_mwm_hints (window);
   
   if (hints)
@@ -4889,6 +4541,10 @@ gdk_window_set_functions (GdkWindow    *window,
   MotifWmHints hints;
   
   g_return_if_fail (GDK_IS_WINDOW (window));
+
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
+    return;
   
   /* initialize to zero to avoid writing uninitialized data to socket */
   memset(&hints, 0, sizeof(hints));
@@ -4898,404 +4554,105 @@ gdk_window_set_functions (GdkWindow    *window,
   gdk_window_set_mwm_hints (window, &hints);
 }
 
-/* 
- * propagate the shapes from all child windows of a GDK window to the parent 
- * window. Shamelessly ripped from Enlightenment's code
- * 
- * - Raster
- */
-struct _gdk_span
+static GdkRegion *
+xwindow_get_shape (Display *xdisplay,
+                  Window window,
+                  gint shape_type)
 {
-  gint                start;
-  gint                end;
-  struct _gdk_span    *next;
-};
+  GdkRegion *shape;
+  GdkRectangle *rl;
+  XRectangle *xrl;
+  gint rn, ord, i;
 
-static void
-gdk_add_to_span (struct _gdk_span **s,
-                gint               x,
-                gint               xx)
-{
-  struct _gdk_span *ptr1, *ptr2, *noo, *ss;
-  gchar             spanning;
-  
-  ptr2 = NULL;
-  ptr1 = *s;
-  spanning = 0;
-  ss = NULL;
-  /* scan the spans for this line */
-  while (ptr1)
-    {
-      /* -- -> new span */
-      /* == -> existing span */
-      /* ## -> spans intersect */
-      /* if we are in the middle of spanning the span into the line */
-      if (spanning)
-       {
-         /* case: ---- ==== */
-         if (xx < ptr1->start - 1)
-           {
-             /* ends before next span - extend to here */
-             ss->end = xx;
-             return;
-           }
-         /* case: ----##=== */
-         else if (xx <= ptr1->end)
-           {
-             /* crosses into next span - delete next span and append */
-             ss->end = ptr1->end;
-             ss->next = ptr1->next;
-             g_free (ptr1);
-             return;
-           }
-         /* case: ---###--- */
-         else
-           {
-             /* overlaps next span - delete and keep checking */
-             ss->next = ptr1->next;
-             g_free (ptr1);
-             ptr1 = ss;
-           }
-       }
-      /* otherwise havent started spanning it in yet */
-      else
-       {
-         /* case: ---- ==== */
-         if (xx < ptr1->start - 1)
-           {
-             /* insert span here in list */
-             noo = g_malloc (sizeof (struct _gdk_span));
-             
-             if (noo)
-               {
-                 noo->start = x;
-                 noo->end = xx;
-                 noo->next = ptr1;
-                 if (ptr2)
-                   ptr2->next = noo;
-                 else
-                   *s = noo;
-               }
-             return;
-           }
-         /* case: ----##=== */
-         else if ((x < ptr1->start) && (xx <= ptr1->end))
-           {
-             /* expand this span to the left point of the new one */
-             ptr1->start = x;
-             return;
-           }
-         /* case: ===###=== */
-         else if ((x >= ptr1->start) && (xx <= ptr1->end))
-           {
-             /* throw the span away */
-             return;
-           }
-         /* case: ---###--- */
-         else if ((x < ptr1->start) && (xx > ptr1->end))
-           {
-             ss = ptr1;
-             spanning = 1;
-             ptr1->start = x;
-             ptr1->end = xx;
-           }
-         /* case: ===##---- */
-         else if ((x >= ptr1->start) && (x <= ptr1->end + 1) && (xx > ptr1->end))
-           {
-             ss = ptr1;
-             spanning = 1;
-             ptr1->end = xx;
-           }
-         /* case: ==== ---- */
-         /* case handled by next loop iteration - first case */
-       }
-      ptr2 = ptr1;
-      ptr1 = ptr1->next;
-    }
-  /* it started in the middle but spans beyond your current list */
-  if (spanning)
-    {
-      ptr2->end = xx;
-      return;
-    }
-  /* it does not start inside a span or in the middle, so add it to the end */
-  noo = g_malloc (sizeof (struct _gdk_span));
+  shape = NULL;
+  
+  xrl = XShapeGetRectangles (xdisplay,
+                            window,
+                            shape_type, &rn, &ord);
   
-  if (noo)
+  if (rn == 0)
+    return gdk_region_new (); /* Empty */
+  
+  if (ord != YXBanded)
     {
-      noo->start = x;
-      noo->end = xx;
-      if (ptr2)
-       {
-         noo->next = ptr2->next;
-         ptr2->next = noo;
-       }
-      else
-       {
-         noo->next = NULL;
-         *s = noo;
-       }
+      /* This really shouldn't happen with any xserver, as they
+        generally convert regions to YXBanded internally */
+      g_warning ("non YXBanded shape masks not supported");
+      XFree (xrl);
+      return NULL;
     }
-  return;
-}
 
-static void
-gdk_add_rectangles (Display           *disp,
-                   Window             win,
-                   struct _gdk_span **spans,
-                   gint               basew,
-                   gint               baseh,
-                   gint               x,
-                   gint               y)
-{
-  gint a, k;
-  gint x1, y1, x2, y2;
-  gint rn, ord;
-  XRectangle *rl;
-  
-  rl = XShapeGetRectangles (disp, win, ShapeBounding, &rn, &ord);
-  if (rl)
-    {
-      /* go through all clip rects in this window's shape */
-      for (k = 0; k < rn; k++)
-       {
-         /* for each clip rect, add it to each line's spans */
-         x1 = x + rl[k].x;
-         x2 = x + rl[k].x + (rl[k].width - 1);
-         y1 = y + rl[k].y;
-         y2 = y + rl[k].y + (rl[k].height - 1);
-         if (x1 < 0)
-           x1 = 0;
-         if (y1 < 0)
-           y1 = 0;
-         if (x2 >= basew)
-           x2 = basew - 1;
-         if (y2 >= baseh)
-           y2 = baseh - 1;
-         for (a = y1; a <= y2; a++)
-           {
-             if ((x2 - x1) >= 0)
-               gdk_add_to_span (&spans[a], x1, x2);
-           }
-       }
-      XFree (rl);
+  rl = g_new (GdkRectangle, rn);
+  for (i = 0; i < rn; i++)
+    {
+      rl[i].x = xrl[i].x;
+      rl[i].y = xrl[i].y;
+      rl[i].width = xrl[i].width;
+      rl[i].height = xrl[i].height;
     }
+  XFree (xrl);
+  
+  shape = _gdk_region_new_from_yxbanded_rects (rl, rn);
+  g_free (rl);
+  
+  return shape;
 }
 
-static void
-gdk_propagate_shapes (Display *disp,
-                     Window   win,
-                     gboolean merge,
-                     int      shape)
-{
-  Window              rt, par, *list = NULL;
-  gint                i, j, num = 0, num_rects = 0;
-  gint                x, y, contig;
-  guint               w, h, d;
-  gint                baseh, basew;
-  XRectangle         *rects = NULL;
-  struct _gdk_span  **spans = NULL, *ptr1, *ptr2, *ptr3;
-  XWindowAttributes   xatt;
-  
-  XGetGeometry (disp, win, &rt, &x, &y, &w, &h, &d, &d);
-  if (h <= 0)
-    return;
-  basew = w;
-  baseh = h;
-  spans = g_malloc (sizeof (struct _gdk_span *) * h);
+
+GdkRegion *
+_gdk_windowing_get_shape_for_mask (GdkBitmap *mask)
+{
+  GdkDisplay *display;
+  Window window;
+  GdkRegion *region;
+
+  display = gdk_drawable_get_display (GDK_DRAWABLE (mask));
+
+  window = XCreateSimpleWindow (GDK_DISPLAY_XDISPLAY (display),
+                               GDK_SCREEN_XROOTWIN (gdk_display_get_default_screen (display)),
+                               -1, -1, 1, 1, 0,
+                               0, 0);
+  XShapeCombineMask (GDK_DISPLAY_XDISPLAY (display),
+                    window,
+                    ShapeBounding,
+                    0, 0,
+                    GDK_PIXMAP_XID (mask),
+                    ShapeSet);
   
-  for (i = 0; i < h; i++)
-    spans[i] = NULL;
-  XQueryTree (disp, win, &rt, &par, &list, (unsigned int *)&num);
-  if (list)
-    {
-      /* go through all child windows and create/insert spans */
-      for (i = 0; i < num; i++)
-       {
-         if (XGetWindowAttributes (disp, list[i], &xatt) && (xatt.map_state != IsUnmapped))
-           if (XGetGeometry (disp, list[i], &rt, &x, &y, &w, &h, &d, &d))
-             gdk_add_rectangles (disp, list[i], spans, basew, baseh, x, y);
-       }
-      if (merge)
-       gdk_add_rectangles (disp, win, spans, basew, baseh, x, y);
-      
-      /* go through the spans list and build a list of rects */
-      rects = g_malloc (sizeof (XRectangle) * 256);
-      num_rects = 0;
-      for (i = 0; i < baseh; i++)
-       {
-         ptr1 = spans[i];
-         /* go through the line for all spans */
-         while (ptr1)
-           {
-             rects[num_rects].x = ptr1->start;
-             rects[num_rects].y = i;
-             rects[num_rects].width = ptr1->end - ptr1->start + 1;
-             rects[num_rects].height = 1;
-             j = i + 1;
-             /* if there are more lines */
-             contig = 1;
-             /* while contigous rects (same start/end coords) exist */
-             while ((contig) && (j < baseh))
-               {
-                 /* search next line for spans matching this one */
-                 contig = 0;
-                 ptr2 = spans[j];
-                 ptr3 = NULL;
-                 while (ptr2)
-                   {
-                     /* if we have an exact span match set contig */
-                     if ((ptr2->start == ptr1->start) &&
-                         (ptr2->end == ptr1->end))
-                       {
-                         contig = 1;
-                         /* remove the span - not needed */
-                         if (ptr3)
-                           {
-                             ptr3->next = ptr2->next;
-                             g_free (ptr2);
-                             ptr2 = NULL;
-                           }
-                         else
-                           {
-                             spans[j] = ptr2->next;
-                             g_free (ptr2);
-                             ptr2 = NULL;
-                           }
-                         break;
-                       }
-                     /* gone past the span point no point looking */
-                     else if (ptr2->start < ptr1->start)
-                       break;
-                     if (ptr2)
-                       {
-                         ptr3 = ptr2;
-                         ptr2 = ptr2->next;
-                       }
-                   }
-                 /* if a contiguous span was found increase the rect h */
-                 if (contig)
-                   {
-                     rects[num_rects].height++;
-                     j++;
-                   }
-               }
-             /* up the rect count */
-             num_rects++;
-             /* every 256 new rects increase the rect array */
-             if ((num_rects % 256) == 0)
-               rects = g_realloc (rects, sizeof (XRectangle) * (num_rects + 256));
-             ptr1 = ptr1->next;
-           }
-       }
-      /* set the rects as the shape mask */
-      if (rects)
-       {
-         XShapeCombineRectangles (disp, win, shape, 0, 0, rects, num_rects,
-                                  ShapeSet, YXSorted);
-         g_free (rects);
-       }
-      XFree (list);
-    }
-  /* free up all the spans we made */
-  for (i = 0; i < baseh; i++)
-    {
-      ptr1 = spans[i];
-      while (ptr1)
-       {
-         ptr2 = ptr1;
-         ptr1 = ptr1->next;
-         g_free (ptr2);
-       }
-    }
-  g_free (spans);
+  region = xwindow_get_shape (GDK_DISPLAY_XDISPLAY (display),
+                             window, ShapeBounding);
+
+  XDestroyWindow (GDK_DISPLAY_XDISPLAY (display),
+                 window);
+
+  return region;
 }
 
-static inline void
-do_child_shapes (GdkWindow *window,
-                 gboolean   merge)
+GdkRegion *
+_gdk_windowing_window_get_shape (GdkWindow *window)
 {
   if (!GDK_WINDOW_DESTROYED (window) &&
       gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
-    {
-      gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
-                            GDK_WINDOW_XID (window),
-                            merge,
-                            ShapeBounding);
-    }
-}
+    return xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
+                             GDK_WINDOW_XID (window), ShapeBounding);
 
-static void
-gdk_window_x11_set_child_shapes (GdkWindow *window)
-{
-  do_child_shapes (window, FALSE);
+  return NULL;
 }
 
-static void
-gdk_window_x11_merge_child_shapes (GdkWindow *window)
-{
-  do_child_shapes (window, TRUE);
-}
-
-static inline void
-do_child_input_shapes (GdkWindow *window,
-                       gboolean   merge)
+GdkRegion *
+_gdk_windowing_window_get_input_shape (GdkWindow *window)
 {
 #if defined(ShapeInput)
   if (!GDK_WINDOW_DESTROYED (window) &&
       gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
-    {
-      gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
-                            GDK_WINDOW_XID (window),
-                            merge,
-                            ShapeInput);
-    }
+    return xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
+                             GDK_WINDOW_XID (window),
+                             ShapeInput);
 #endif
-}
 
-/**
- * gdk_window_set_child_input_shapes:
- * @window: a #GdkWindow
- * 
- * Sets the input shape mask of @window to the union of input shape masks
- * for all children of @window, ignoring the input shape mask of @window
- * itself. Contrast with gdk_window_merge_child_input_shapes() which includes
- * the input shape mask of @window in the masks to be merged.
- *
- * Since: 2.10
- **/
-void 
-gdk_window_set_child_input_shapes (GdkWindow *window)
-{
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  do_child_input_shapes (window, FALSE);
-}
-
-/**
- * gdk_window_merge_child_input_shapes:
- * @window: a #GdkWindow
- * 
- * Merges the input shape masks for any child windows into the
- * input shape mask for @window. i.e. the union of all input masks
- * for @window and its children will become the new input mask
- * for @window. See gdk_window_input_shape_combine_mask().
- *
- * This function is distinct from gdk_window_set_child_input_shapes()
- * because it includes @window's input shape mask in the set of 
- * shapes to be merged.
- *
- * Since: 2.10
- **/
-void 
-gdk_window_merge_child_input_shapes (GdkWindow *window)
-{
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  do_child_input_shapes (window, TRUE);
+  return NULL;
 }
 
-
 static void
 gdk_window_set_static_bit_gravity (GdkWindow *window,
                                    gboolean   on)
@@ -5927,9 +5284,8 @@ gdk_window_begin_resize_drag (GdkWindow     *window,
                               gint           root_y,
                               guint32        timestamp)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
@@ -5962,9 +5318,8 @@ gdk_window_begin_move_drag (GdkWindow *window,
                             gint       root_y,
                             guint32    timestamp)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   if (gdk_x11_screen_supports_net_wm_hint (GDK_WINDOW_SCREEN (window),
@@ -5998,12 +5353,17 @@ gdk_window_enable_synchronized_configure (GdkWindow *window)
   GdkWindowObject *private = (GdkWindowObject *)window;
   GdkWindowImplX11 *impl;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
+  if (!GDK_IS_WINDOW_IMPL_X11 (private->impl))
+    return;
+  
   impl = GDK_WINDOW_IMPL_X11 (private->impl);
          
   if (!impl->use_synchronized_configure)
     {
+      /* This basically means you want to do fancy X specific stuff, so
+        ensure we have a native window */
+      gdk_window_ensure_native (window);
+
       impl->use_synchronized_configure = TRUE;
       ensure_sync_counter (window);
     }
@@ -6029,7 +5389,8 @@ gdk_window_configure_finished (GdkWindow *window)
 {
   GdkWindowImplX11 *impl;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  if (!WINDOW_IS_TOPLEVEL (window))
+    return;
   
   impl = GDK_WINDOW_IMPL_X11 (((GdkWindowObject *)window)->impl);
   if (!impl->use_synchronized_configure)
@@ -6055,21 +5416,13 @@ gdk_window_configure_finished (GdkWindow *window)
 #endif
 }
 
-/**
- * gdk_window_beep:
- * @window: a toplevel #GdkWindow
- *
- * Emits a short beep associated to @window in the appropriate
- * display, if supported. Otherwise, emits a short beep on
- * the display just as gdk_display_beep().
- *
- * Since: 2.12
- **/
 void
-gdk_window_beep (GdkWindow *window)
+_gdk_windowing_window_beep (GdkWindow *window)
 {
   GdkDisplay *display;
 
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
   display = GDK_WINDOW_DISPLAY (window);
 
 #ifdef HAVE_XKB
@@ -6111,7 +5464,8 @@ gdk_window_set_opacity (GdkWindow *window,
   g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
 
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   display = gdk_drawable_get_display (window);
@@ -6169,6 +5523,23 @@ _gdk_windowing_window_set_composited (GdkWindow *window,
 #endif
 }
 
+void
+_gdk_windowing_window_process_updates_recurse (GdkWindow *window,
+                                               GdkRegion *region)
+{
+  _gdk_window_process_updates_recurse (window, region);
+}
+
+void
+_gdk_windowing_before_process_all_updates (void)
+{
+}
+
+void
+_gdk_windowing_after_process_all_updates (void)
+{
+}
+
 static void
 gdk_window_impl_iface_init (GdkWindowImplIface *iface)
 {
@@ -6177,24 +5548,26 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface)
   iface->withdraw = gdk_window_x11_withdraw;
   iface->set_events = gdk_window_x11_set_events;
   iface->get_events = gdk_window_x11_get_events;
-  iface->clear_area = gdk_window_x11_clear_area;
   iface->raise = gdk_window_x11_raise;
   iface->lower = gdk_window_x11_lower;
+  iface->restack_under = gdk_window_x11_restack_under;
   iface->move_resize = gdk_window_x11_move_resize;
-  iface->scroll = _gdk_x11_window_scroll;
-  iface->move_region = _gdk_x11_window_move_region;
   iface->set_background = gdk_window_x11_set_background;
   iface->set_back_pixmap = gdk_window_x11_set_back_pixmap;
   iface->reparent = gdk_window_x11_reparent;
   iface->set_cursor = gdk_window_x11_set_cursor;
   iface->get_geometry = gdk_window_x11_get_geometry;
-  iface->get_origin = gdk_window_x11_get_origin;
-  iface->shape_combine_mask = gdk_window_x11_shape_combine_mask;
+  iface->get_root_coords = gdk_window_x11_get_root_coords;
+  iface->get_pointer = gdk_window_x11_get_pointer;
+  iface->get_deskrelative_origin = gdk_window_x11_get_deskrelative_origin;
   iface->shape_combine_region = gdk_window_x11_shape_combine_region;
-  iface->set_child_shapes = gdk_window_x11_set_child_shapes;
-  iface->merge_child_shapes = gdk_window_x11_merge_child_shapes;
+  iface->input_shape_combine_region = gdk_window_x11_input_shape_combine_region;
   iface->set_static_gravities = gdk_window_x11_set_static_gravities;
-  iface->get_offsets = _gdk_x11_window_get_offsets;
+  iface->queue_antiexpose = _gdk_x11_window_queue_antiexpose;
+  iface->queue_translation = _gdk_x11_window_queue_translation;
+  iface->destroy = _gdk_x11_window_destroy;
+  iface->input_window_destroy = _gdk_input_window_destroy;
+  iface->input_window_crossing = _gdk_input_crossing_event;
 }
 
 #define __GDK_WINDOW_X11_C__
index 2a2799b0799f334edad344da72277758d5176ccf..9a7f2aed35f4666dc494eefd15bd9a6525c29e68 100644 (file)
@@ -44,22 +44,6 @@ typedef struct _GdkWindowImplX11 GdkWindowImplX11;
 typedef struct _GdkWindowImplX11Class GdkWindowImplX11Class;
 typedef struct _GdkXPositionInfo GdkXPositionInfo;
 
-struct _GdkXPositionInfo
-{
-  gint x;
-  gint y;
-  gint width;
-  gint height;
-  gint x_offset;               /* Offsets to add to X coordinates within window */
-  gint y_offset;               /*   to get GDK coodinates within window */
-  guint big : 1;
-  guint mapped : 1;
-  guint no_bg : 1;             /* Set when the window background is temporarily
-                                * unset during resizing and scaling */
-  GdkRectangle clip_rect;      /* visible rectangle of window */
-};
-
-
 /* Window implementation for X11
  */
 
@@ -74,13 +58,11 @@ struct _GdkWindowImplX11
 {
   GdkDrawableImplX11 parent_instance;
 
-  gint width;
-  gint height;
-  
-  GdkXPositionInfo position_info;
   GdkToplevelX11 *toplevel;    /* Toplevel-specific information */
   GdkCursor *cursor;
   gint8 toplevel_window_type;
+  guint no_bg : 1;             /* Set when the window background is temporarily
+                                * unset during resizing and scaling */
   guint override_redirect : 1;
   guint use_synchronized_configure : 1;
 
@@ -158,15 +140,16 @@ struct _GdkToplevelX11
 
 GType gdk_window_impl_x11_get_type (void);
 
-void             gdk_x11_window_set_user_time (GdkWindow *window,
-                                               guint32    timestamp);
-
-GdkToplevelX11 *_gdk_x11_window_get_toplevel  (GdkWindow *window);
-void           _gdk_x11_window_tmp_unset_bg  (GdkWindow *window,
-                                              gboolean   recurse);
-void            _gdk_x11_window_tmp_reset_bg  (GdkWindow *window,
-                                              gboolean   recurse);
+void            gdk_x11_window_set_user_time        (GdkWindow *window,
+                                                    guint32    timestamp);
 
+GdkToplevelX11 *_gdk_x11_window_get_toplevel        (GdkWindow *window);
+void            _gdk_x11_window_tmp_unset_bg        (GdkWindow *window,
+                                                    gboolean   recurse);
+void            _gdk_x11_window_tmp_reset_bg        (GdkWindow *window,
+                                                    gboolean   recurse);
+void            _gdk_x11_window_tmp_unset_parent_bg (GdkWindow *window);
+void            _gdk_x11_window_tmp_reset_parent_bg (GdkWindow *window);
 
 GdkCursor      *_gdk_x11_window_get_cursor    (GdkWindow *window);
 void            _gdk_x11_window_get_offsets   (GdkWindow *window,
index 2a84a48feaa05df7edb23fb0bb3192de595e3aef..3e6fbefc188a18a175a0dedfb903e2a1a8647243 100644 (file)
@@ -1470,15 +1470,17 @@ gtk_combo_box_menu_position_below (GtkMenu  *menu,
   
   /* FIXME: is using the size request here broken? */
   child = GTK_BIN (combo_box)->child;
-   
-  gdk_window_get_origin (child->window, &sx, &sy);
-   
+
+  sx = sy = 0;
+
   if (GTK_WIDGET_NO_WINDOW (child))
     {
       sx += child->allocation.x;
       sy += child->allocation.y;
     }
 
+  gdk_window_get_root_coords (child->window, sx, sy, &sx, &sy);
+
   if (GTK_SHADOW_NONE != combo_box->priv->shadow_type)
     sx -= GTK_WIDGET (combo_box)->style->xthickness;
 
@@ -1537,10 +1539,9 @@ gtk_combo_box_menu_position_over (GtkMenu  *menu,
   menu_width = requisition.width;
 
   active = gtk_menu_get_active (GTK_MENU (combo_box->priv->popup_widget));
-  gdk_window_get_origin (widget->window, &menu_xpos, &menu_ypos);
 
-  menu_xpos += widget->allocation.x;
-  menu_ypos += widget->allocation.y + widget->allocation.height / 2 - 2;
+  menu_xpos = widget->allocation.x;
+  menu_ypos = widget->allocation.y + widget->allocation.height / 2 - 2;
 
   if (active != NULL)
     {
@@ -1568,6 +1569,9 @@ gtk_combo_box_menu_position_over (GtkMenu  *menu,
   if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_RTL)
     menu_xpos = menu_xpos + widget->allocation.width - menu_width;
 
+  gdk_window_get_root_coords (widget->window, menu_xpos, menu_ypos,
+                             &menu_xpos, &menu_ypos);
+
   /* Clamp the position on screen */
   screen_width = gdk_screen_get_width (gtk_widget_get_screen (widget));
   
@@ -1630,7 +1634,7 @@ gtk_combo_box_list_position (GtkComboBox *combo_box,
      see bug #340204 */
   GtkWidget *sample = GTK_WIDGET (combo_box);
 
-  gdk_window_get_origin (sample->window, x, y);
+  *x = *y = 0;
 
   if (GTK_WIDGET_NO_WINDOW (sample))
     {
@@ -1638,6 +1642,8 @@ gtk_combo_box_list_position (GtkComboBox *combo_box,
       *y += sample->allocation.y;
     }
   
+  gdk_window_get_root_coords (sample->window, *x, *y, x, y);
+
   *width = sample->allocation.width;
 
   hpolicy = vpolicy = GTK_POLICY_NEVER;
index d5b07e74905aa72ea74a4eaf7a63d4201ab5678b..db686263afca850c544c68fb228968675eedb496 100644 (file)
@@ -26,6 +26,7 @@ endif
 
 noinst_PROGRAMS =  $(TEST_PROGS)       \
        simple                          \
+       flicker                         \
        print-editor                    \
        testaccel                       \
        testassistant                   \
@@ -55,6 +56,7 @@ noinst_PROGRAMS =  $(TEST_PROGS)      \
        testmultiscreen                 \
        testnotebookdnd                 \
        testnouiprint                   \
+       testoffscreen                   \
        testorientable                  \
        testprint                       \
        testrgb                         \
@@ -79,6 +81,7 @@ noinst_PROGRAMS =  $(TEST_PROGS)      \
        testtreesort                    \
        treestoretest                   \
        testxinerama                    \
+       testwindows                     \
        pixbuf-read                     \
        pixbuf-lowmem                   \
        pixbuf-randomly-modified        \
@@ -104,6 +107,7 @@ endif
 
 endif
 
+flicker_DEPENDENCIES = $(TEST_DEPS)
 simple_DEPENDENCIES = $(TEST_DEPS)
 print_editor_DEPENDENCIES = $(TEST_DEPS)
 testicontheme_DEPENDENCIES = $(TEST_DEPS)
@@ -134,6 +138,7 @@ testmultidisplay_DEPENDENCIES = $(TEST_DEPS)
 testmultiscreen_DEPENDENCIES = $(TEST_DEPS)
 testnotebookdnd_DEPENDENCIES = $(TEST_DEPS)
 testnouiprint_DEPENDENCIES = $(TEST_DEPS)
+testoffscreen_DEPENDENCIES = $(TEST_DEPS)
 testorientable_DEPENDENCIES = $(TEST_DEPS)
 testprint_DEPENDENCIES = $(TEST_DEPS)
 testrecentchooser_DEPENDENCIES = $(TEST_DEPS)
@@ -162,7 +167,9 @@ testactions_DEPENDENCIES = $(TEST_DEPS)
 testgrouping_DEPENDENCIES = $(TEST_DEPS)
 testtooltips_DEPENDENCIES = $(TEST_DEPS)
 testvolumebutton_DEPENDENCIES = $(TEST_DEPS)
+testwindows_DEPENDENCIES = $(TEST_DEPS)
 
+flicker_LDADD = $(LDADDS)
 simple_LDADD = $(LDADDS)
 print_editor_LDADD = $(LDADDS)
 testaccel_LDADD = $(LDADDS)
@@ -193,6 +200,7 @@ testmultidisplay_LDADD = $(LDADDS)
 testmultiscreen_LDADD = $(LDADDS)
 testnotebookdnd_LDADD = $(LDADDS)
 testnouiprint_LDADD = $(LDADDS)
+testoffscreen_LDADD = $(LDADDS)
 testorientable_LDADD = $(LDADDS)
 testprint_LDADD = $(LDADDS)
 testrecentchooser_LDADD = $(LDADDS)
@@ -228,6 +236,7 @@ testactions_LDADD = $(LDADDS)
 testgrouping_LDADD = $(LDADDS)
 testtooltips_LDADD = $(LDADDS)
 testvolumebutton_LDADD = $(LDADDS)
+testwindows_LDADD = $(LDADDS)
 
 
 testentrycompletion_SOURCES =  \
@@ -320,6 +329,14 @@ testrecentchoosermenu_SOURCES =    \
 testvolumebutton_SOURCES =     \
        testvolumebutton.c
 
+testoffscreen_SOURCES =        \
+       gtkoffscreenbox.c       \
+       gtkoffscreenbox.h       \
+       testoffscreen.c
+
+testwindow_SOURCES =   \
+       testwindows.c
+
 EXTRA_DIST +=                  \
        prop-editor.h           \
        testgtk.1               \
diff --git a/tests/flicker.c b/tests/flicker.c
new file mode 100644 (file)
index 0000000..39c9601
--- /dev/null
@@ -0,0 +1,216 @@
+#include <gtk/gtk.h>
+
+GtkWidget*
+create_flicker (void)
+{
+  GtkWidget *window1;
+  GtkWidget *hpaned1;
+  GtkWidget *vpaned2;
+  GtkWidget *hbox2;
+  GtkObject *spinbutton7_adj;
+  GtkWidget *spinbutton7;
+  GtkObject *spinbutton8_adj;
+  GtkWidget *spinbutton8;
+  GtkWidget *vbox1;
+  GtkObject *spinbutton9_adj;
+  GtkWidget *spinbutton9;
+  GtkObject *spinbutton10_adj;
+  GtkWidget *spinbutton10;
+  GtkObject *spinbutton11_adj;
+  GtkWidget *spinbutton11;
+  GtkObject *spinbutton12_adj;
+  GtkWidget *spinbutton12;
+  GtkObject *spinbutton13_adj;
+  GtkWidget *spinbutton13;
+  GtkObject *spinbutton14_adj;
+  GtkWidget *spinbutton14;
+  GtkObject *spinbutton15_adj;
+  GtkWidget *spinbutton15;
+  GtkObject *spinbutton16_adj;
+  GtkWidget *spinbutton16;
+  GtkWidget *vpaned1;
+  GtkWidget *hbox1;
+  GtkObject *spinbutton17_adj;
+  GtkWidget *spinbutton17;
+  GtkObject *spinbutton18_adj;
+  GtkWidget *spinbutton18;
+  GtkObject *spinbutton19_adj;
+  GtkWidget *spinbutton19;
+  GtkWidget *vbox2;
+  GtkObject *spinbutton20_adj;
+  GtkWidget *spinbutton20;
+  GtkObject *spinbutton21_adj;
+  GtkWidget *spinbutton21;
+  GtkObject *spinbutton22_adj;
+  GtkWidget *spinbutton22;
+  GtkObject *spinbutton23_adj;
+  GtkWidget *spinbutton23;
+  GtkObject *spinbutton24_adj;
+  GtkWidget *spinbutton24;
+  GtkObject *spinbutton25_adj;
+  GtkWidget *spinbutton25;
+  GtkObject *spinbutton26_adj;
+  GtkWidget *spinbutton26;
+  GtkObject *spinbutton27_adj;
+  GtkWidget *spinbutton27;
+
+  window1 = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_window_set_default_size (GTK_WINDOW (window1), 500, 400);
+  gtk_window_set_title (GTK_WINDOW (window1), "window1");
+
+  hpaned1 = gtk_hpaned_new ();
+  gtk_widget_show (hpaned1);
+  gtk_container_add (GTK_CONTAINER (window1), hpaned1);
+  gtk_paned_set_position (GTK_PANED (hpaned1), 100);
+
+  vpaned2 = gtk_vpaned_new ();
+  gtk_widget_show (vpaned2);
+  gtk_paned_pack1 (GTK_PANED (hpaned1), vpaned2, FALSE, TRUE);
+  gtk_paned_set_position (GTK_PANED (vpaned2), 100);
+
+  hbox2 = gtk_hbox_new (FALSE, 0);
+  gtk_widget_show (hbox2);
+  gtk_paned_pack1 (GTK_PANED (vpaned2), hbox2, FALSE, TRUE);
+
+  spinbutton7_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+  spinbutton7 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton7_adj), 1, 0);
+  gtk_widget_show (spinbutton7);
+  gtk_box_pack_start (GTK_BOX (hbox2), spinbutton7, TRUE, TRUE, 0);
+
+  spinbutton8_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+  spinbutton8 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton8_adj), 1, 0);
+  gtk_widget_show (spinbutton8);
+  gtk_box_pack_start (GTK_BOX (hbox2), spinbutton8, TRUE, TRUE, 0);
+
+  vbox1 = gtk_vbox_new (FALSE, 0);
+  gtk_widget_show (vbox1);
+  gtk_paned_pack2 (GTK_PANED (vpaned2), vbox1, TRUE, TRUE);
+
+  spinbutton9_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+  spinbutton9 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton9_adj), 1, 0);
+  gtk_widget_show (spinbutton9);
+  gtk_box_pack_start (GTK_BOX (vbox1), spinbutton9, FALSE, FALSE, 0);
+
+  spinbutton10_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+  spinbutton10 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton10_adj), 1, 0);
+  gtk_widget_show (spinbutton10);
+  gtk_box_pack_start (GTK_BOX (vbox1), spinbutton10, FALSE, FALSE, 0);
+
+  spinbutton11_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+  spinbutton11 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton11_adj), 1, 0);
+  gtk_widget_show (spinbutton11);
+  gtk_box_pack_start (GTK_BOX (vbox1), spinbutton11, FALSE, FALSE, 0);
+
+  spinbutton12_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+  spinbutton12 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton12_adj), 1, 0);
+  gtk_widget_show (spinbutton12);
+  gtk_box_pack_start (GTK_BOX (vbox1), spinbutton12, FALSE, FALSE, 0);
+
+  spinbutton13_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+  spinbutton13 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton13_adj), 1, 0);
+  gtk_widget_show (spinbutton13);
+  gtk_box_pack_start (GTK_BOX (vbox1), spinbutton13, FALSE, FALSE, 0);
+
+  spinbutton14_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+  spinbutton14 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton14_adj), 1, 0);
+  gtk_widget_show (spinbutton14);
+  gtk_box_pack_start (GTK_BOX (vbox1), spinbutton14, FALSE, FALSE, 0);
+
+  spinbutton15_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+  spinbutton15 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton15_adj), 1, 0);
+  gtk_widget_show (spinbutton15);
+  gtk_box_pack_start (GTK_BOX (vbox1), spinbutton15, FALSE, FALSE, 0);
+
+  spinbutton16_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+  spinbutton16 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton16_adj), 1, 0);
+  gtk_widget_show (spinbutton16);
+  gtk_box_pack_start (GTK_BOX (vbox1), spinbutton16, FALSE, FALSE, 0);
+
+  vpaned1 = gtk_vpaned_new ();
+  gtk_widget_show (vpaned1);
+  gtk_paned_pack2 (GTK_PANED (hpaned1), vpaned1, TRUE, TRUE);
+  gtk_paned_set_position (GTK_PANED (vpaned1), 0);
+
+  hbox1 = gtk_hbox_new (FALSE, 0);
+  gtk_widget_show (hbox1);
+  gtk_paned_pack1 (GTK_PANED (vpaned1), hbox1, FALSE, TRUE);
+
+  spinbutton17_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+  spinbutton17 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton17_adj), 1, 0);
+  gtk_widget_show (spinbutton17);
+  gtk_box_pack_start (GTK_BOX (hbox1), spinbutton17, TRUE, TRUE, 0);
+
+  spinbutton18_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+  spinbutton18 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton18_adj), 1, 0);
+  gtk_widget_show (spinbutton18);
+  gtk_box_pack_start (GTK_BOX (hbox1), spinbutton18, TRUE, TRUE, 0);
+
+  spinbutton19_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+  spinbutton19 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton19_adj), 1, 0);
+  gtk_widget_show (spinbutton19);
+  gtk_box_pack_start (GTK_BOX (hbox1), spinbutton19, TRUE, TRUE, 0);
+
+  vbox2 = gtk_vbox_new (FALSE, 0);
+  gtk_widget_show (vbox2);
+  gtk_paned_pack2 (GTK_PANED (vpaned1), vbox2, FALSE, FALSE);
+
+  spinbutton20_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+  spinbutton20 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton20_adj), 1, 0);
+  gtk_widget_show (spinbutton20);
+  gtk_box_pack_start (GTK_BOX (vbox2), spinbutton20, FALSE, FALSE, 0);
+
+  spinbutton21_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+  spinbutton21 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton21_adj), 1, 0);
+  gtk_widget_show (spinbutton21);
+  gtk_box_pack_start (GTK_BOX (vbox2), spinbutton21, FALSE, FALSE, 0);
+
+  spinbutton22_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+  spinbutton22 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton22_adj), 1, 0);
+  gtk_widget_show (spinbutton22);
+  gtk_box_pack_start (GTK_BOX (vbox2), spinbutton22, FALSE, FALSE, 0);
+
+  spinbutton23_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+  spinbutton23 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton23_adj), 1, 0);
+  gtk_widget_show (spinbutton23);
+  gtk_box_pack_start (GTK_BOX (vbox2), spinbutton23, FALSE, FALSE, 0);
+
+  spinbutton24_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+  spinbutton24 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton24_adj), 1, 0);
+  gtk_widget_show (spinbutton24);
+  gtk_box_pack_start (GTK_BOX (vbox2), spinbutton24, FALSE, FALSE, 0);
+
+  spinbutton25_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+  spinbutton25 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton25_adj), 1, 0);
+  gtk_widget_show (spinbutton25);
+  gtk_box_pack_start (GTK_BOX (vbox2), spinbutton25, FALSE, FALSE, 0);
+
+  spinbutton26_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+  spinbutton26 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton26_adj), 1, 0);
+  gtk_widget_show (spinbutton26);
+  gtk_box_pack_start (GTK_BOX (vbox2), spinbutton26, TRUE, FALSE, 0);
+
+  spinbutton27_adj = gtk_adjustment_new (1, 0, 100, 1, 10, 10);
+  spinbutton27 = gtk_spin_button_new (GTK_ADJUSTMENT (spinbutton27_adj), 1, 0);
+  gtk_widget_show (spinbutton27);
+  gtk_box_pack_end (GTK_BOX (vbox2), spinbutton27, FALSE, FALSE, 0);
+
+
+  return window1;
+}
+
+
+int
+main (int argc, char *argv[])
+{
+  GtkWidget *window1;
+
+  gtk_set_locale ();
+  gtk_init (&argc, &argv);
+
+  window1 = create_flicker ();
+  gtk_widget_show (window1);
+
+  gtk_main ();
+  return 0;
+}
+
diff --git a/tests/gtkoffscreenbox.c b/tests/gtkoffscreenbox.c
new file mode 100644 (file)
index 0000000..d781c43
--- /dev/null
@@ -0,0 +1,660 @@
+/*
+ * gtkoffscreenbox.c
+ */
+
+#include "config.h"
+
+#include <math.h>
+#include <gtk/gtk.h>
+
+#include "gtkoffscreenbox.h"
+
+static void        gtk_offscreen_box_realize       (GtkWidget       *widget);
+static void        gtk_offscreen_box_unrealize     (GtkWidget       *widget);
+static void        gtk_offscreen_box_size_request  (GtkWidget       *widget,
+                                                    GtkRequisition  *requisition);
+static void        gtk_offscreen_box_size_allocate (GtkWidget       *widget,
+                                                    GtkAllocation   *allocation);
+static gboolean    gtk_offscreen_box_damage        (GtkWidget       *widget,
+                                                    GdkEventExpose  *event);
+static gboolean    gtk_offscreen_box_expose        (GtkWidget       *widget,
+                                                    GdkEventExpose  *offscreen);
+
+static void        gtk_offscreen_box_add           (GtkContainer    *container,
+                                                    GtkWidget       *child);
+static void        gtk_offscreen_box_remove        (GtkContainer    *container,
+                                                    GtkWidget       *widget);
+static void        gtk_offscreen_box_forall        (GtkContainer    *container,
+                                                    gboolean         include_internals,
+                                                    GtkCallback      callback,
+                                                    gpointer         callback_data);
+static GType       gtk_offscreen_box_child_type    (GtkContainer    *container);
+
+#define CHILD1_SIZE_SCALE 1.0
+#define CHILD2_SIZE_SCALE 1.0
+
+G_DEFINE_TYPE (GtkOffscreenBox, gtk_offscreen_box, GTK_TYPE_CONTAINER);
+
+static void
+to_child_2 (GtkOffscreenBox *offscreen_box,
+           double widget_x, double widget_y,
+           double *x_out, double *y_out)
+{
+  GtkAllocation child_area;
+  double x, y, xr, yr;
+  double cos_angle, sin_angle;
+
+  x = widget_x;
+  y = widget_y;
+
+  if (offscreen_box->child1 && GTK_WIDGET_VISIBLE (offscreen_box->child1))
+    y -= offscreen_box->child1->allocation.height;
+
+  child_area = offscreen_box->child2->allocation;
+
+  x -= child_area.width / 2;
+  y -= child_area.height / 2;
+
+  cos_angle = cos (-offscreen_box->angle);
+  sin_angle = sin (-offscreen_box->angle);
+
+  xr = x * cos_angle - y * sin_angle;
+  yr = x * sin_angle + y * cos_angle;
+  x = xr;
+  y = yr;
+
+  x += child_area.width / 2;
+  y += child_area.height / 2;
+
+  *x_out = x;
+  *y_out = y;
+}
+
+static void
+to_parent_2 (GtkOffscreenBox *offscreen_box,
+            double offscreen_x, double offscreen_y,
+            double *x_out, double *y_out)
+{
+  GtkAllocation child_area;
+  double x, y, xr, yr;
+  double cos_angle, sin_angle;
+
+  child_area = offscreen_box->child2->allocation;
+
+  x = offscreen_x;
+  y = offscreen_y;
+
+  x -= child_area.width / 2;
+  y -= child_area.height / 2;
+
+  cos_angle = cos (offscreen_box->angle);
+  sin_angle = sin (offscreen_box->angle);
+
+  xr = x * cos_angle - y * sin_angle;
+  yr = x * sin_angle + y * cos_angle;
+  x = xr;
+  y = yr;
+
+  x += child_area.width / 2;
+  y += child_area.height / 2;
+
+  if (offscreen_box->child1 && GTK_WIDGET_VISIBLE (offscreen_box->child1))
+    y += offscreen_box->child1->allocation.height;
+
+  *x_out = x;
+  *y_out = y;
+}
+
+static void
+gtk_offscreen_box_class_init (GtkOffscreenBoxClass *klass)
+{
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+  GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
+
+  widget_class->realize = gtk_offscreen_box_realize;
+  widget_class->unrealize = gtk_offscreen_box_unrealize;
+  widget_class->size_request = gtk_offscreen_box_size_request;
+  widget_class->size_allocate = gtk_offscreen_box_size_allocate;
+  widget_class->expose_event = gtk_offscreen_box_expose;
+
+  g_signal_override_class_closure (g_signal_lookup ("damage-event", GTK_TYPE_WIDGET),
+                                   GTK_TYPE_OFFSCREEN_BOX,
+                                   g_cclosure_new (G_CALLBACK (gtk_offscreen_box_damage),
+                                                   NULL, NULL));
+
+  container_class->add = gtk_offscreen_box_add;
+  container_class->remove = gtk_offscreen_box_remove;
+  container_class->forall = gtk_offscreen_box_forall;
+  container_class->child_type = gtk_offscreen_box_child_type;
+}
+
+static void
+gtk_offscreen_box_init (GtkOffscreenBox *offscreen_box)
+{
+  GTK_WIDGET_UNSET_FLAGS (offscreen_box, GTK_NO_WINDOW);
+}
+
+GtkWidget *
+gtk_offscreen_box_new (void)
+{
+  return g_object_new (GTK_TYPE_OFFSCREEN_BOX, NULL);
+}
+
+static GdkWindow *
+get_offscreen_parent (GdkWindow *offscreen_window,
+                     GtkOffscreenBox *offscreen_box)
+{
+  return GTK_WIDGET (offscreen_box)->window;
+}
+
+static GdkWindow *
+pick_offscreen_child (GdkWindow *offscreen_window,
+                     double widget_x, double widget_y,
+                     GtkOffscreenBox *offscreen_box)
+{
+ GtkAllocation child_area;
+ double x, y;
+
+ /* First check for child 2 */
+ if (offscreen_box->child2 &&
+     GTK_WIDGET_VISIBLE (offscreen_box->child2))
+    {
+      to_child_2 (offscreen_box,
+                 widget_x, widget_y,
+                 &x, &y);
+
+      child_area = offscreen_box->child2->allocation;
+
+      if (x >= 0 && x < child_area.width &&
+         y >= 0 && y < child_area.height)
+       return offscreen_box->offscreen_window2;
+    }
+
+ if (offscreen_box->child1 && GTK_WIDGET_VISIBLE (offscreen_box->child1))
+   {
+     x = widget_x;
+     y = widget_y;
+
+     child_area = offscreen_box->child1->allocation;
+
+     if (x >= 0 && x < child_area.width &&
+        y >= 0 && y < child_area.height)
+       return offscreen_box->offscreen_window1;
+   }
+
+  return NULL;
+}
+
+static void
+offscreen_window_to_parent1 (GdkWindow       *offscreen_window,
+                            double           offscreen_x,
+                            double           offscreen_y,
+                            double          *parent_x,
+                            double          *parent_y,
+                            GtkOffscreenBox *offscreen_box)
+{
+  *parent_x = offscreen_x;
+  *parent_y = offscreen_y;
+}
+
+static void
+offscreen_window_from_parent1 (GdkWindow       *window,
+                              double           parent_x,
+                              double           parent_y,
+                              double          *offscreen_x,
+                              double          *offscreen_y,
+                              GtkOffscreenBox *offscreen_box)
+{
+  *offscreen_x = parent_x;
+  *offscreen_y = parent_y;
+}
+
+static void
+offscreen_window_to_parent2 (GdkWindow       *offscreen_window,
+                            double           offscreen_x,
+                            double           offscreen_y,
+                            double          *parent_x,
+                            double          *parent_y,
+                            GtkOffscreenBox *offscreen_box)
+{
+  to_parent_2 (offscreen_box,
+             offscreen_x, offscreen_y,
+             parent_x, parent_y);
+}
+
+static void
+offscreen_window_from_parent2 (GdkWindow       *window,
+                              double           parent_x,
+                              double           parent_y,
+                              double          *offscreen_x,
+                              double          *offscreen_y,
+                              GtkOffscreenBox *offscreen_box)
+{
+  to_child_2 (offscreen_box,
+             parent_x, parent_y,
+             offscreen_x, offscreen_y);
+}
+
+static void
+gtk_offscreen_box_realize (GtkWidget *widget)
+{
+  GtkOffscreenBox *offscreen_box = GTK_OFFSCREEN_BOX (widget);
+  GdkWindowAttr attributes;
+  gint attributes_mask;
+  gint border_width;
+  GtkRequisition child_requisition;
+  int start_y = 0;
+
+  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+
+  border_width = GTK_CONTAINER (widget)->border_width;
+
+  attributes.x = widget->allocation.x + border_width;
+  attributes.y = widget->allocation.y + border_width;
+  attributes.width = widget->allocation.width - 2 * border_width;
+  attributes.height = widget->allocation.height - 2 * border_width;
+  attributes.window_type = GDK_WINDOW_CHILD;
+  attributes.event_mask = gtk_widget_get_events (widget)
+                       | GDK_EXPOSURE_MASK
+                       | GDK_POINTER_MOTION_MASK
+                       | GDK_BUTTON_PRESS_MASK
+                       | GDK_BUTTON_RELEASE_MASK
+                       | GDK_SCROLL_MASK
+                       | GDK_ENTER_NOTIFY_MASK
+                       | GDK_LEAVE_NOTIFY_MASK;
+
+  attributes.visual = gtk_widget_get_visual (widget);
+  attributes.colormap = gtk_widget_get_colormap (widget);
+  attributes.wclass = GDK_INPUT_OUTPUT;
+
+  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+  widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
+                                  &attributes, attributes_mask);
+  gdk_window_set_user_data (widget->window, widget);
+
+  gdk_window_set_has_offscreen_children (widget->window, TRUE);
+  g_signal_connect (widget->window, "pick-offscreen-child",
+                   G_CALLBACK (pick_offscreen_child), offscreen_box);
+
+  attributes.window_type = GDK_WINDOW_OFFSCREEN;
+
+  /* Child 1 */
+  attributes.x = attributes.y = 0;
+  if (offscreen_box->child1 && GTK_WIDGET_VISIBLE (offscreen_box->child1))
+    {
+      attributes.width = offscreen_box->child1->allocation.width;
+      attributes.height = offscreen_box->child1->allocation.height;
+      start_y += offscreen_box->child1->allocation.height;
+    }
+  offscreen_box->offscreen_window1 = gdk_window_new (gtk_widget_get_root_window (widget),
+                                                    &attributes, attributes_mask);
+  gdk_window_set_user_data (offscreen_box->offscreen_window1, widget);
+  if (offscreen_box->child1)
+    gtk_widget_set_parent_window (offscreen_box->child1, offscreen_box->offscreen_window1);
+
+  g_signal_connect (offscreen_box->offscreen_window1, "get-offscreen-parent",
+                   G_CALLBACK (get_offscreen_parent), offscreen_box);
+  g_signal_connect (offscreen_box->offscreen_window1, "to_parent",
+                   G_CALLBACK (offscreen_window_to_parent1), offscreen_box);
+  g_signal_connect (offscreen_box->offscreen_window1, "from_parent",
+                   G_CALLBACK (offscreen_window_from_parent1), offscreen_box);
+
+  /* Child 2 */
+  attributes.y = start_y;
+  child_requisition.width = child_requisition.height = 0;
+  if (offscreen_box->child2 && GTK_WIDGET_VISIBLE (offscreen_box->child2))
+    {
+      attributes.width = offscreen_box->child2->allocation.width;
+      attributes.height = offscreen_box->child2->allocation.height;
+    }
+  offscreen_box->offscreen_window2 = gdk_window_new (gtk_widget_get_root_window (widget),
+                                                    &attributes, attributes_mask);
+  gdk_window_set_user_data (offscreen_box->offscreen_window2, widget);
+  if (offscreen_box->child2)
+    gtk_widget_set_parent_window (offscreen_box->child2, offscreen_box->offscreen_window2);
+  g_signal_connect (offscreen_box->offscreen_window2, "get-offscreen-parent",
+                   G_CALLBACK (get_offscreen_parent), offscreen_box);
+  g_signal_connect (offscreen_box->offscreen_window2, "to_parent",
+                   G_CALLBACK (offscreen_window_to_parent2), offscreen_box);
+  g_signal_connect (offscreen_box->offscreen_window2, "from_parent",
+                   G_CALLBACK (offscreen_window_from_parent2), offscreen_box);
+
+  widget->style = gtk_style_attach (widget->style, widget->window);
+
+  gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+  gtk_style_set_background (widget->style, offscreen_box->offscreen_window1, GTK_STATE_NORMAL);
+  gtk_style_set_background (widget->style, offscreen_box->offscreen_window2, GTK_STATE_NORMAL);
+
+  gdk_window_show (offscreen_box->offscreen_window1);
+  gdk_window_show (offscreen_box->offscreen_window2);
+}
+
+static void
+gtk_offscreen_box_unrealize (GtkWidget *widget)
+{
+  GtkOffscreenBox *offscreen_box = GTK_OFFSCREEN_BOX (widget);
+
+  gdk_window_set_user_data (offscreen_box->offscreen_window1, NULL);
+  gdk_window_destroy (offscreen_box->offscreen_window1);
+  offscreen_box->offscreen_window1 = NULL;
+
+  gdk_window_set_user_data (offscreen_box->offscreen_window2, NULL);
+  gdk_window_destroy (offscreen_box->offscreen_window2);
+  offscreen_box->offscreen_window2 = NULL;
+
+  GTK_WIDGET_CLASS (gtk_offscreen_box_parent_class)->unrealize (widget);
+}
+
+static GType
+gtk_offscreen_box_child_type (GtkContainer *container)
+{
+  GtkOffscreenBox *offscreen_box = GTK_OFFSCREEN_BOX (container);
+
+  if (offscreen_box->child1 && offscreen_box->child2)
+    return G_TYPE_NONE;
+
+  return GTK_TYPE_WIDGET;
+}
+
+static void
+gtk_offscreen_box_add (GtkContainer *container,
+                      GtkWidget    *widget)
+{
+  GtkOffscreenBox *offscreen_box = GTK_OFFSCREEN_BOX (container);
+
+  if (!offscreen_box->child1)
+    gtk_offscreen_box_add1 (offscreen_box, widget);
+  else if (!offscreen_box->child2)
+    gtk_offscreen_box_add2 (offscreen_box, widget);
+  else
+    g_warning ("GtkOffscreenBox cannot have more than 2 children\n");
+}
+
+void
+gtk_offscreen_box_add1 (GtkOffscreenBox *offscreen_box,
+                       GtkWidget       *child)
+{
+  g_return_if_fail (GTK_IS_OFFSCREEN_BOX (offscreen_box));
+  g_return_if_fail (GTK_IS_WIDGET (child));
+
+  if (offscreen_box->child1 == NULL)
+    {
+      gtk_widget_set_parent_window (child, offscreen_box->offscreen_window1);
+      gtk_widget_set_parent (child, GTK_WIDGET (offscreen_box));
+      offscreen_box->child1 = child;
+    }
+}
+
+void
+gtk_offscreen_box_add2 (GtkOffscreenBox  *offscreen_box,
+                       GtkWidget    *child)
+{
+  g_return_if_fail (GTK_IS_OFFSCREEN_BOX (offscreen_box));
+  g_return_if_fail (GTK_IS_WIDGET (child));
+
+  if (offscreen_box->child2 == NULL)
+    {
+      gtk_widget_set_parent_window (child, offscreen_box->offscreen_window2);
+      gtk_widget_set_parent (child, GTK_WIDGET (offscreen_box));
+      offscreen_box->child2 = child;
+    }
+}
+
+static void
+gtk_offscreen_box_remove (GtkContainer *container,
+                         GtkWidget    *widget)
+{
+  GtkOffscreenBox *offscreen_box = GTK_OFFSCREEN_BOX (container);
+  gboolean was_visible;
+
+  was_visible = GTK_WIDGET_VISIBLE (widget);
+
+  if (offscreen_box->child1 == widget)
+    {
+      gtk_widget_unparent (widget);
+
+      offscreen_box->child1 = NULL;
+
+      if (was_visible && GTK_WIDGET_VISIBLE (container))
+       gtk_widget_queue_resize (GTK_WIDGET (container));
+    }
+  else if (offscreen_box->child2 == widget)
+    {
+      gtk_widget_unparent (widget);
+
+      offscreen_box->child2 = NULL;
+
+      if (was_visible && GTK_WIDGET_VISIBLE (container))
+       gtk_widget_queue_resize (GTK_WIDGET (container));
+    }
+}
+
+static void
+gtk_offscreen_box_forall (GtkContainer *container,
+                         gboolean      include_internals,
+                         GtkCallback   callback,
+                         gpointer      callback_data)
+{
+  GtkOffscreenBox *offscreen_box = GTK_OFFSCREEN_BOX (container);
+
+  g_return_if_fail (callback != NULL);
+
+  if (offscreen_box->child1)
+    (*callback) (offscreen_box->child1, callback_data);
+  if (offscreen_box->child2)
+    (*callback) (offscreen_box->child2, callback_data);
+}
+
+void
+gtk_offscreen_box_set_angle (GtkOffscreenBox  *offscreen_box,
+                            gdouble           angle)
+{
+  g_return_if_fail (GTK_IS_OFFSCREEN_BOX (offscreen_box));
+
+  offscreen_box->angle = angle;
+  gtk_widget_queue_draw (GTK_WIDGET (offscreen_box));
+
+  /* TODO: Really needs to resent pointer events if over the rotated window */
+}
+
+
+static void
+gtk_offscreen_box_size_request (GtkWidget      *widget,
+                               GtkRequisition *requisition)
+{
+  GtkOffscreenBox *offscreen_box = GTK_OFFSCREEN_BOX (widget);
+  int w, h;
+
+  w = 0;
+  h = 0;
+
+  if (offscreen_box->child1 && GTK_WIDGET_VISIBLE (offscreen_box->child1))
+    {
+      GtkRequisition child_requisition;
+
+      gtk_widget_size_request (offscreen_box->child1, &child_requisition);
+
+      w = MAX (w, CHILD1_SIZE_SCALE * child_requisition.width);
+      h += CHILD1_SIZE_SCALE * child_requisition.height;
+    }
+
+  if (offscreen_box->child2 && GTK_WIDGET_VISIBLE (offscreen_box->child2))
+    {
+      GtkRequisition child_requisition;
+
+      gtk_widget_size_request (offscreen_box->child2, &child_requisition);
+
+      w = MAX (w, CHILD2_SIZE_SCALE * child_requisition.width);
+      h += CHILD2_SIZE_SCALE * child_requisition.height;
+    }
+
+  requisition->width = GTK_CONTAINER (widget)->border_width * 2 + w;
+  requisition->height = GTK_CONTAINER (widget)->border_width * 2 + h;
+}
+
+static void
+gtk_offscreen_box_size_allocate (GtkWidget     *widget,
+                                GtkAllocation *allocation)
+{
+  GtkOffscreenBox *offscreen_box;
+  gint border_width;
+  gint start_y;
+
+  widget->allocation = *allocation;
+  offscreen_box = GTK_OFFSCREEN_BOX (widget);
+
+  border_width = GTK_CONTAINER (widget)->border_width;
+
+  if (GTK_WIDGET_REALIZED (widget))
+    gdk_window_move_resize (widget->window,
+                            allocation->x + border_width,
+                            allocation->y + border_width,
+                            allocation->width - border_width * 2,
+                            allocation->height - border_width * 2);
+
+  start_y = 0;
+
+  if (offscreen_box->child1 && GTK_WIDGET_VISIBLE (offscreen_box->child1))
+    {
+      GtkRequisition child_requisition;
+      GtkAllocation child_allocation;
+
+      gtk_widget_get_child_requisition (offscreen_box->child1, &child_requisition);
+      child_allocation.x = child_requisition.width * (CHILD1_SIZE_SCALE - 1.0) / 2;
+      child_allocation.y = start_y + child_requisition.height * (CHILD1_SIZE_SCALE - 1.0) / 2;
+      child_allocation.width = MAX (1, (gint) widget->allocation.width - 2 * border_width);
+      child_allocation.height = child_requisition.height;
+
+      start_y += CHILD1_SIZE_SCALE * child_requisition.height;
+
+      if (GTK_WIDGET_REALIZED (widget))
+       gdk_window_move_resize (offscreen_box->offscreen_window1,
+                               child_allocation.x,
+                                child_allocation.y,
+                               child_allocation.width,
+                                child_allocation.height);
+
+      child_allocation.x = child_allocation.y = 0;
+      gtk_widget_size_allocate (offscreen_box->child1, &child_allocation);
+    }
+
+  if (offscreen_box->child2 && GTK_WIDGET_VISIBLE (offscreen_box->child2))
+    {
+      GtkRequisition child_requisition;
+      GtkAllocation child_allocation;
+
+      gtk_widget_get_child_requisition (offscreen_box->child2, &child_requisition);
+      child_allocation.x = child_requisition.width * (CHILD2_SIZE_SCALE - 1.0) / 2;
+      child_allocation.y = start_y + child_requisition.height * (CHILD2_SIZE_SCALE - 1.0) / 2;
+      child_allocation.width = MAX (1, (gint) widget->allocation.width - 2 * border_width);
+      child_allocation.height = child_requisition.height;
+
+      start_y += CHILD2_SIZE_SCALE * child_requisition.height;
+
+      if (GTK_WIDGET_REALIZED (widget))
+       gdk_window_move_resize (offscreen_box->offscreen_window2,
+                               child_allocation.x,
+                                child_allocation.y,
+                               child_allocation.width,
+                                child_allocation.height);
+
+      child_allocation.x = child_allocation.y = 0;
+      gtk_widget_size_allocate (offscreen_box->child2, &child_allocation);
+    }
+}
+
+static gboolean
+gtk_offscreen_box_damage (GtkWidget      *widget,
+                          GdkEventExpose *event)
+{
+  gdk_window_invalidate_rect (widget->window, NULL, FALSE);
+
+  return TRUE;
+}
+
+static gboolean
+gtk_offscreen_box_expose (GtkWidget      *widget,
+                         GdkEventExpose *event)
+{
+  GtkOffscreenBox *offscreen_box = GTK_OFFSCREEN_BOX (widget);
+
+  if (GTK_WIDGET_DRAWABLE (widget))
+    {
+      if (event->window == widget->window)
+       {
+          GdkPixmap *pixmap;
+          GtkAllocation child_area;
+          cairo_t *cr;
+         int start_y = 0;
+
+         if (offscreen_box->child1 && GTK_WIDGET_VISIBLE (offscreen_box->child1))
+           {
+             pixmap = gdk_window_get_offscreen_pixmap (offscreen_box->offscreen_window1);
+              child_area = offscreen_box->child1->allocation;
+
+             cr = gdk_cairo_create (widget->window);
+
+              gdk_cairo_set_source_pixmap (cr, pixmap, 0, 0);
+              cairo_paint (cr);
+
+              cairo_destroy (cr);
+
+              start_y += child_area.height;
+           }
+
+         if (offscreen_box->child2 && GTK_WIDGET_VISIBLE (offscreen_box->child2))
+           {
+              gint w, h;
+
+             pixmap = gdk_window_get_offscreen_pixmap (offscreen_box->offscreen_window2);
+              child_area = offscreen_box->child2->allocation;
+
+             cr = gdk_cairo_create (widget->window);
+
+              /* transform */
+             cairo_translate (cr, 0, start_y);
+             cairo_translate (cr, child_area.width / 2, child_area.height / 2);
+             cairo_rotate (cr, offscreen_box->angle);
+             cairo_translate (cr, -child_area.width / 2, -child_area.height / 2);
+
+              /* clip */
+              gdk_drawable_get_size (pixmap, &w, &h);
+              cairo_rectangle (cr, 0, 0, w, h);
+              cairo_clip (cr);
+
+              /* paint */
+             gdk_cairo_set_source_pixmap (cr, pixmap, 0, 0);
+             cairo_paint (cr);
+
+              cairo_destroy (cr);
+           }
+       }
+      else if (event->window == offscreen_box->offscreen_window1)
+       {
+         gtk_paint_flat_box (widget->style, event->window,
+                             GTK_STATE_NORMAL, GTK_SHADOW_NONE,
+                             &event->area, widget, "blah",
+                             0, 0, -1, -1);
+
+         if (offscreen_box->child1)
+           gtk_container_propagate_expose (GTK_CONTAINER (widget),
+                                           offscreen_box->child1,
+                                            event);
+       }
+      else if (event->window == offscreen_box->offscreen_window2)
+       {
+         gtk_paint_flat_box (widget->style, event->window,
+                             GTK_STATE_NORMAL, GTK_SHADOW_NONE,
+                             &event->area, widget, "blah",
+                             0, 0, -1, -1);
+
+         if (offscreen_box->child2)
+           gtk_container_propagate_expose (GTK_CONTAINER (widget),
+                                           offscreen_box->child2,
+                                            event);
+       }
+    }
+
+  return FALSE;
+}
diff --git a/tests/gtkoffscreenbox.h b/tests/gtkoffscreenbox.h
new file mode 100644 (file)
index 0000000..aa1d15d
--- /dev/null
@@ -0,0 +1,52 @@
+#ifndef __GTK_OFFSCREEN_BOX_H__
+#define __GTK_OFFSCREEN_BOX_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_OFFSCREEN_BOX              (gtk_offscreen_box_get_type ())
+#define GTK_OFFSCREEN_BOX(obj)              (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_OFFSCREEN_BOX, GtkOffscreenBox))
+#define GTK_OFFSCREEN_BOX_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_OFFSCREEN_BOX, GtkOffscreenBoxClass))
+#define GTK_IS_OFFSCREEN_BOX(obj)           (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_OFFSCREEN_BOX))
+#define GTK_IS_OFFSCREEN_BOX_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_OFFSCREEN_BOX))
+#define GTK_OFFSCREEN_BOX_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_OFFSCREEN_BOX, GtkOffscreenBoxClass))
+
+typedef struct _GtkOffscreenBox          GtkOffscreenBox;
+typedef struct _GtkOffscreenBoxClass  GtkOffscreenBoxClass;
+
+struct _GtkOffscreenBox
+{
+  GtkContainer container;
+
+  GtkWidget *child1;
+  GtkWidget *child2;
+
+  GdkWindow *offscreen_window1;
+  GdkWindow *offscreen_window2;
+
+  gdouble angle;
+};
+
+struct _GtkOffscreenBoxClass
+{
+  GtkBinClass parent_class;
+};
+
+GType     gtk_offscreen_box_get_type           (void) G_GNUC_CONST;
+GtkWidget* gtk_offscreen_box_new       (void);
+void       gtk_offscreen_box_add1      (GtkOffscreenBox *offscreen,
+                                       GtkWidget       *child);
+void       gtk_offscreen_box_add2      (GtkOffscreenBox *offscreen,
+                                       GtkWidget       *child);
+void       gtk_offscreen_box_set_angle (GtkOffscreenBox *offscreen,
+                                       double           angle);
+
+
+
+G_END_DECLS
+
+#endif /* __GTK_OFFSCREEN_BOX_H__ */
index 436e9e80d0d93268b464edcfb18afe917b5e1ab7..bd1a0971089b78b79beb461589b36ddd8e7b4915 100644 (file)
-/* testclientmessage.c\r
- * Copyright (C) 2008  Novell, Inc.\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Library General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
- * Library General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Library General Public\r
- * License along with this library; if not, write to the\r
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,\r
- * Boston, MA 02111-1307, USA.\r
- */\r
-\r
-#include <gtk/gtk.h>\r
-\r
-static GdkAtom my_type;\r
-static GdkAtom random_type;\r
-\r
-static void\r
-send_known (void)\r
-{\r
-  GdkEvent *event = gdk_event_new (GDK_CLIENT_EVENT);\r
-  static int counter = 42;\r
-  int i;\r
-  \r
-  event->client.window = NULL;\r
-  event->client.message_type = my_type;\r
-  event->client.data_format = 32;\r
-  event->client.data.l[0] = counter++;\r
-  for (i = 1; i < 5; i++)\r
-    event->client.data.l[i] = 0;\r
-\r
-  gdk_screen_broadcast_client_message (gdk_display_get_default_screen (gdk_display_get_default ()), event);\r
-  \r
-  gdk_event_free (event);\r
-}\r
-\r
-void\r
-send_random (void)\r
-{\r
-  GdkEvent *event = gdk_event_new (GDK_CLIENT_EVENT);\r
-  static int counter = 1;\r
-  int i;\r
-  \r
-  event->client.window = NULL;\r
-  event->client.message_type = random_type;\r
-  event->client.data_format = 32;\r
-  event->client.data.l[0] = counter++;\r
-  for (i = 1; i < 5; i++)\r
-    event->client.data.l[i] = 0;\r
-\r
-  gdk_screen_broadcast_client_message (gdk_display_get_default_screen (gdk_display_get_default ()), event);\r
-  \r
-  gdk_event_free (event);\r
-}\r
-\r
-static GdkFilterReturn\r
-filter_func (GdkXEvent *xevent,\r
-            GdkEvent  *event,\r
-            gpointer   data)\r
-{\r
-  g_print ("Got matching client message!\n");\r
-  return GDK_FILTER_REMOVE;\r
-}\r
-\r
-int\r
-main (int argc, char **argv)\r
-{\r
-  GtkWidget *window;\r
-  GtkWidget *vbox;\r
-  GtkWidget *button;\r
-\r
-  gtk_init (&argc, &argv);\r
-\r
-  my_type = gdk_atom_intern ("GtkTestClientMessage", FALSE);\r
-  random_type = gdk_atom_intern (g_strdup_printf ("GtkTestClientMessage-%d",\r
-                                                 g_rand_int_range (g_rand_new (), 1, 99)),\r
-                                FALSE);\r
-\r
-  g_print ("using random client message type %s\n", gdk_atom_name (random_type));\r
-\r
-  window = g_object_connect (g_object_new (gtk_window_get_type (),\r
-                                          "type", GTK_WINDOW_TOPLEVEL,\r
-                                          "title", "testclientmessage",\r
-                                          "border_width", 10,\r
-                                          NULL),\r
-                            "signal::destroy", gtk_main_quit, NULL,\r
-                            NULL);\r
-  vbox = g_object_new (gtk_vbox_get_type (),\r
-                      "GtkWidget::parent", window,\r
-                      "GtkWidget::visible", TRUE,\r
-                      NULL);\r
-  button = g_object_connect (g_object_new (gtk_button_get_type (),\r
-                                          "GtkButton::label", "send known client message",\r
-                                          "GtkWidget::parent", vbox,\r
-                                          "GtkWidget::visible", TRUE,\r
-                                          NULL),\r
-                            "signal::clicked", send_known, NULL,\r
-                            NULL);\r
-  button = g_object_connect (g_object_new (gtk_button_get_type (),\r
-                                          "GtkButton::label", "send random client message",\r
-                                          "GtkWidget::parent", vbox,\r
-                                          "GtkWidget::visible", TRUE,\r
-                                          NULL),\r
-                            "signal::clicked", send_random, NULL,\r
-                            NULL);\r
-  gdk_display_add_client_message_filter (gdk_display_get_default (),\r
-                                        my_type,\r
-                                        filter_func,\r
-                                        NULL);\r
-  gtk_widget_show (window);\r
-\r
-  gtk_main ();\r
-\r
-  return 0;\r
-}\r
+/* testclientmessage.c
+ * Copyright (C) 2008  Novell, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <gtk/gtk.h>
+
+static GdkAtom my_type;
+static GdkAtom random_type;
+
+static void
+send_known (void)
+{
+  GdkEvent *event = gdk_event_new (GDK_CLIENT_EVENT);
+  static int counter = 42;
+  int i;
+  
+  event->client.window = NULL;
+  event->client.message_type = my_type;
+  event->client.data_format = 32;
+  event->client.data.l[0] = counter++;
+  for (i = 1; i < 5; i++)
+    event->client.data.l[i] = 0;
+
+  gdk_screen_broadcast_client_message (gdk_display_get_default_screen (gdk_display_get_default ()), event);
+  
+  gdk_event_free (event);
+}
+
+void
+send_random (void)
+{
+  GdkEvent *event = gdk_event_new (GDK_CLIENT_EVENT);
+  static int counter = 1;
+  int i;
+  
+  event->client.window = NULL;
+  event->client.message_type = random_type;
+  event->client.data_format = 32;
+  event->client.data.l[0] = counter++;
+  for (i = 1; i < 5; i++)
+    event->client.data.l[i] = 0;
+
+  gdk_screen_broadcast_client_message (gdk_display_get_default_screen (gdk_display_get_default ()), event);
+  
+  gdk_event_free (event);
+}
+
+static GdkFilterReturn
+filter_func (GdkXEvent *xevent,
+            GdkEvent  *event,
+            gpointer   data)
+{
+  g_print ("Got matching client message!\n");
+  return GDK_FILTER_REMOVE;
+}
+
+int
+main (int argc, char **argv)
+{
+  GtkWidget *window;
+  GtkWidget *vbox;
+  GtkWidget *button;
+
+  gtk_init (&argc, &argv);
+
+  my_type = gdk_atom_intern ("GtkTestClientMessage", FALSE);
+  random_type = gdk_atom_intern (g_strdup_printf ("GtkTestClientMessage-%d",
+                                                 g_rand_int_range (g_rand_new (), 1, 99)),
+                                FALSE);
+
+  g_print ("using random client message type %s\n", gdk_atom_name (random_type));
+
+  window = g_object_connect (g_object_new (gtk_window_get_type (),
+                                          "type", GTK_WINDOW_TOPLEVEL,
+                                          "title", "testclientmessage",
+                                          "border_width", 10,
+                                          NULL),
+                            "signal::destroy", gtk_main_quit, NULL,
+                            NULL);
+  vbox = g_object_new (gtk_vbox_get_type (),
+                      "GtkWidget::parent", window,
+                      "GtkWidget::visible", TRUE,
+                      NULL);
+  button = g_object_connect (g_object_new (gtk_button_get_type (),
+                                          "GtkButton::label", "send known client message",
+                                          "GtkWidget::parent", vbox,
+                                          "GtkWidget::visible", TRUE,
+                                          NULL),
+                            "signal::clicked", send_known, NULL,
+                            NULL);
+  button = g_object_connect (g_object_new (gtk_button_get_type (),
+                                          "GtkButton::label", "send random client message",
+                                          "GtkWidget::parent", vbox,
+                                          "GtkWidget::visible", TRUE,
+                                          NULL),
+                            "signal::clicked", send_random, NULL,
+                            NULL);
+  gdk_display_add_client_message_filter (gdk_display_get_default (),
+                                        my_type,
+                                        filter_func,
+                                        NULL);
+  gtk_widget_show (window);
+
+  gtk_main ();
+
+  return 0;
+}
diff --git a/tests/testoffscreen.c b/tests/testoffscreen.c
new file mode 100644 (file)
index 0000000..f332d62
--- /dev/null
@@ -0,0 +1,381 @@
+/*
+ * testoffscreen.c
+ */
+
+#undef GTK_DISABLE_DEPRECATED
+
+#include <math.h>
+#include <gtk/gtk.h>
+#include "gtkoffscreenbox.h"
+
+
+static void
+combo_changed_cb (GtkWidget *combo,
+                 gpointer   data)
+{
+  GtkWidget *label = GTK_WIDGET (data);
+  gint active;
+
+  active = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
+
+  gtk_label_set_ellipsize (GTK_LABEL (label), (PangoEllipsizeMode)active);
+}
+
+static gboolean
+layout_expose_handler (GtkWidget      *widget,
+                       GdkEventExpose *event)
+{
+  GtkLayout *layout = GTK_LAYOUT (widget);
+
+  gint i,j;
+  gint imin, imax, jmin, jmax;
+
+  if (event->window != layout->bin_window)
+    return FALSE;
+
+  imin = (event->area.x) / 10;
+  imax = (event->area.x + event->area.width + 9) / 10;
+
+  jmin = (event->area.y) / 10;
+  jmax = (event->area.y + event->area.height + 9) / 10;
+
+  for (i = imin; i < imax; i++)
+    for (j = jmin; j < jmax; j++)
+      if ((i + j) % 2)
+       gdk_draw_rectangle (layout->bin_window,
+                            widget->style->black_gc,
+                            TRUE,
+                            10 * i, 10 * j,
+                            1 + i % 10, 1 + j % 10);
+
+  return FALSE;
+}
+
+static gboolean
+scroll_layout (gpointer data)
+{
+  GtkWidget *layout = data;
+  GtkAdjustment *adj;
+
+  adj = gtk_layout_get_hadjustment (GTK_LAYOUT (layout));
+  gtk_adjustment_set_value (adj,
+                           gtk_adjustment_get_value (adj) + 5.0);
+  return TRUE;
+}
+
+static guint layout_timeout;
+
+static void
+create_layout (GtkWidget *vbox)
+{
+  GtkWidget *layout;
+  GtkWidget *scrolledwindow;
+  GtkWidget *button;
+  gchar buf[16];
+  gint i, j;
+
+  scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
+  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
+                                      GTK_SHADOW_IN);
+  gtk_scrolled_window_set_placement (GTK_SCROLLED_WINDOW (scrolledwindow),
+                                    GTK_CORNER_TOP_RIGHT);
+
+  gtk_box_pack_start (GTK_BOX (vbox), scrolledwindow, TRUE, TRUE, 0);
+
+  layout = gtk_layout_new (NULL, NULL);
+  gtk_container_add (GTK_CONTAINER (scrolledwindow), layout);
+
+  /* We set step sizes here since GtkLayout does not set
+   * them itself.
+   */
+  GTK_LAYOUT (layout)->hadjustment->step_increment = 10.0;
+  GTK_LAYOUT (layout)->vadjustment->step_increment = 10.0;
+
+  gtk_widget_set_events (layout, GDK_EXPOSURE_MASK);
+  g_signal_connect (layout, "expose_event",
+                   G_CALLBACK (layout_expose_handler),
+                    NULL);
+
+  gtk_layout_set_size (GTK_LAYOUT (layout), 1600, 128000);
+
+  for (i = 0 ; i < 16 ; i++)
+    for (j = 0 ; j < 16 ; j++)
+      {
+       g_snprintf (buf, sizeof (buf), "Button %d, %d", i, j);
+
+       if ((i + j) % 2)
+         button = gtk_button_new_with_label (buf);
+       else
+         button = gtk_label_new (buf);
+
+       gtk_layout_put (GTK_LAYOUT (layout), button,
+                       j * 100, i * 100);
+      }
+
+  for (i = 16; i < 1280; i++)
+    {
+      g_snprintf (buf, sizeof (buf), "Button %d, %d", i, 0);
+
+      if (i % 2)
+       button = gtk_button_new_with_label (buf);
+      else
+       button = gtk_label_new (buf);
+
+      gtk_layout_put (GTK_LAYOUT (layout), button,
+                     0, i * 100);
+    }
+
+  layout_timeout = g_timeout_add (1000, scroll_layout, layout);
+}
+
+static void
+create_treeview (GtkWidget *vbox)
+{
+  GtkWidget *scrolledwindow;
+  GtkListStore *store;
+  GtkWidget *tree_view;
+  GSList *stock_ids;
+  GSList *list;
+
+  scrolledwindow = gtk_scrolled_window_new (NULL, NULL);
+  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow),
+                                      GTK_SHADOW_IN);
+
+  gtk_box_pack_start (GTK_BOX (vbox), scrolledwindow, TRUE, TRUE, 0);
+
+  store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING);
+  tree_view = gtk_tree_view_new_with_model (GTK_TREE_MODEL (store));
+  g_object_unref (store);
+
+  gtk_container_add (GTK_CONTAINER (scrolledwindow), tree_view);
+
+  gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view), -1,
+                                               "Icon",
+                                               gtk_cell_renderer_pixbuf_new (),
+                                               "stock-id", 0,
+                                               NULL);
+  gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tree_view), -1,
+                                               "Label",
+                                               gtk_cell_renderer_text_new (),
+                                               "text", 1,
+                                               NULL);
+
+  stock_ids = gtk_stock_list_ids ();
+
+  for (list = stock_ids; list; list = g_slist_next (list))
+    {
+      const gchar *stock_id = list->data;
+      GtkStockItem item;
+
+      if (gtk_stock_lookup (stock_id, &item))
+        {
+          gtk_list_store_insert_with_values (store, NULL, -1,
+                                             0, item.stock_id,
+                                             1, item.label,
+                                             -1);
+        }
+    }
+
+  g_slist_foreach (stock_ids, (GFunc) g_free, NULL);
+  g_slist_free (stock_ids);
+}
+
+static GtkWidget *
+create_widgets (void)
+{
+  GtkWidget *main_hbox, *main_vbox;
+  GtkWidget *vbox, *hbox, *label, *combo, *entry, *button, *cb;
+  GtkWidget *sw, *text_view;
+  GList *cbitems = NULL;
+
+  main_vbox = gtk_vbox_new (0, FALSE);
+
+  main_hbox = gtk_hbox_new (0, FALSE);
+  gtk_box_pack_start (GTK_BOX (main_vbox), main_hbox, TRUE, TRUE, 0);
+
+  vbox = gtk_vbox_new (0, FALSE);
+  gtk_box_pack_start (GTK_BOX (main_hbox), vbox, TRUE, TRUE, 0);
+
+  hbox = gtk_hbox_new (0, FALSE);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+
+  label = gtk_label_new ("This label may be ellipsized\nto make it fit.");
+  gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0);
+
+  combo = gtk_combo_box_new_text ();
+  gtk_combo_box_append_text (GTK_COMBO_BOX (combo), "NONE");
+  gtk_combo_box_append_text (GTK_COMBO_BOX (combo), "START");
+  gtk_combo_box_append_text (GTK_COMBO_BOX (combo), "MIDDLE");
+  gtk_combo_box_append_text (GTK_COMBO_BOX (combo), "END");
+  gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0);
+  gtk_box_pack_start (GTK_BOX (hbox), combo, TRUE, TRUE, 0);
+
+  g_signal_connect (combo, "changed",
+                    G_CALLBACK (combo_changed_cb),
+                    label);
+
+  entry = gtk_entry_new ();
+  gtk_entry_set_text (GTK_ENTRY (entry), "an entry - lots of text.... lots of text.... lots of text.... lots of text.... ");
+  gtk_box_pack_start (GTK_BOX (vbox), entry, FALSE, FALSE, 0);
+
+  label = gtk_label_new ("Label after entry.");
+  gtk_label_set_selectable (GTK_LABEL (label), TRUE);
+  gtk_box_pack_start (GTK_BOX (vbox), label, TRUE, TRUE, 0);
+
+  button = gtk_button_new_with_label ("Button");
+  gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
+
+  button = gtk_check_button_new_with_mnemonic ("_Check button");
+  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+
+  cb = gtk_combo_new ();
+  cbitems = g_list_append (cbitems, "item0");
+  cbitems = g_list_append (cbitems, "item1 item1");
+  cbitems = g_list_append (cbitems, "item2 item2 item2");
+  gtk_combo_set_popdown_strings (GTK_COMBO (cb), cbitems);
+  gtk_entry_set_text (GTK_ENTRY (GTK_COMBO (cb)->entry), "hello world â™¥ foo");
+  gtk_editable_select_region (GTK_EDITABLE (GTK_COMBO (cb)->entry),
+                             0, -1);
+  gtk_box_pack_start (GTK_BOX (vbox), cb, TRUE, TRUE, 0);
+
+  sw = gtk_scrolled_window_new (NULL, NULL);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
+                                 GTK_POLICY_AUTOMATIC,
+                                 GTK_POLICY_AUTOMATIC);
+  text_view = gtk_text_view_new ();
+  gtk_box_pack_start (GTK_BOX (vbox), sw, TRUE, TRUE, 0);
+  gtk_container_add (GTK_CONTAINER (sw), text_view);
+
+  create_layout (vbox);
+
+  create_treeview (main_hbox);
+
+  return main_vbox;
+}
+
+
+static void
+scale_changed (GtkRange        *range,
+              GtkOffscreenBox *offscreen_box)
+{
+  gtk_offscreen_box_set_angle (offscreen_box, gtk_range_get_value (range));
+}
+
+static GtkWidget *scale = NULL;
+
+static void
+remove_clicked (GtkButton *button,
+                GtkWidget *widget)
+{
+  gtk_widget_destroy (widget);
+  g_source_remove (layout_timeout);
+
+  gtk_widget_set_sensitive (GTK_WIDGET (button), FALSE);
+  gtk_widget_set_sensitive (scale, FALSE);
+}
+
+int
+main (int   argc,
+      char *argv[])
+{
+  GtkWidget *window, *widget, *vbox, *button;
+  GtkWidget *offscreen = NULL;
+  gboolean use_offscreen;
+
+  gtk_init (&argc, &argv);
+
+  use_offscreen = argc == 1;
+
+  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_window_set_default_size (GTK_WINDOW (window), 300,300);
+
+  g_signal_connect (window, "destroy",
+                    G_CALLBACK (gtk_main_quit),
+                    NULL);
+
+  vbox = gtk_vbox_new (0, FALSE);
+  gtk_container_add (GTK_CONTAINER (window), vbox);
+
+  scale = gtk_hscale_new_with_range (0,
+                                    M_PI * 2,
+                                    0.01);
+  gtk_box_pack_start (GTK_BOX (vbox), scale, FALSE, FALSE, 0);
+
+  button = gtk_button_new_with_label ("Remove child 2");
+  gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 0);
+
+  if (use_offscreen)
+    {
+      offscreen = gtk_offscreen_box_new ();
+
+      g_signal_connect (scale, "value_changed",
+                        G_CALLBACK (scale_changed),
+                        offscreen);
+    }
+  else
+    {
+      offscreen = gtk_vpaned_new ();
+    }
+
+  gtk_box_pack_start (GTK_BOX (vbox), offscreen, TRUE, TRUE, 0);
+
+  widget = create_widgets ();
+  if (use_offscreen)
+    gtk_offscreen_box_add1 (GTK_OFFSCREEN_BOX (offscreen),
+                           widget);
+  else
+    gtk_paned_add1 (GTK_PANED (offscreen), widget);
+
+  widget = create_widgets ();
+  if (1)
+    {
+      GtkWidget *widget2, *box2, *offscreen2;
+
+      offscreen2 = gtk_offscreen_box_new ();
+      gtk_box_pack_start (GTK_BOX (widget), offscreen2, FALSE, FALSE, 0);
+
+      g_signal_connect (scale, "value_changed",
+                        G_CALLBACK (scale_changed),
+                        offscreen2);
+
+      box2 = gtk_vbox_new (FALSE, 0);
+      gtk_offscreen_box_add2 (GTK_OFFSCREEN_BOX (offscreen2), box2);
+
+      widget2 = gtk_button_new_with_label ("Offscreen in offscreen");
+      gtk_box_pack_start (GTK_BOX (box2), widget2, FALSE, FALSE, 0);
+
+      widget2 = gtk_entry_new ();
+      gtk_entry_set_text (GTK_ENTRY (widget2), "Offscreen in offscreen");
+      gtk_box_pack_start (GTK_BOX (box2), widget2, FALSE, FALSE, 0);
+    }
+
+  if (use_offscreen)
+    gtk_offscreen_box_add2 (GTK_OFFSCREEN_BOX (offscreen), widget);
+  else
+    gtk_paned_add2 (GTK_PANED (offscreen), widget);
+
+  gtk_widget_show_all (window);
+
+  g_signal_connect (G_OBJECT (button), "clicked",
+                    G_CALLBACK (remove_clicked),
+                    widget);
+
+  /* redirect */
+  if (0)
+    {
+      GtkWidget *redirect_win;
+
+      redirect_win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+      gtk_window_set_default_size (GTK_WINDOW (redirect_win), 400,400);
+      gtk_widget_show (redirect_win);
+      gtk_widget_realize (redirect_win);
+      gtk_widget_realize (window);
+      gdk_window_redirect_to_drawable (window->window,
+                                      GDK_DRAWABLE (redirect_win->window),
+                                      0, 0, 0, 0, -1, -1);
+    }
+
+  gtk_main ();
+
+  return 0;
+}
diff --git a/tests/testwindows.c b/tests/testwindows.c
new file mode 100644 (file)
index 0000000..ca8d8e5
--- /dev/null
@@ -0,0 +1,1061 @@
+#include <gtk/gtk.h>
+#include <X11/Xlib.h>
+
+static GtkWidget *darea;
+static GtkTreeStore *window_store = NULL;
+static GtkWidget *treeview;
+
+static void update_store (void);
+
+static GtkWidget *main_window;
+
+static gboolean
+window_has_impl (GdkWindow *window)
+{
+  GdkWindowObject *w;
+  w = (GdkWindowObject *)window;
+  return w->parent == NULL || w->parent->impl != w->impl;
+}
+
+GdkWindow *
+create_window (GdkWindow *parent,
+              int x, int y, int w, int h,
+              GdkColor *color)
+{
+  GdkWindowAttr attributes;
+  gint attributes_mask;
+  GdkWindow *window;
+  GdkColor *bg;
+
+  attributes.x = x;
+  attributes.y = y;
+  attributes.width = w;
+  attributes.height = h;
+  attributes.window_type = GDK_WINDOW_CHILD;
+  attributes.event_mask = GDK_STRUCTURE_MASK
+                       | GDK_BUTTON_MOTION_MASK
+                       | GDK_BUTTON_PRESS_MASK
+                       | GDK_BUTTON_RELEASE_MASK
+                       | GDK_EXPOSURE_MASK
+                       | GDK_ENTER_NOTIFY_MASK
+                       | GDK_LEAVE_NOTIFY_MASK;
+  attributes.wclass = GDK_INPUT_OUTPUT;
+      
+  attributes_mask = GDK_WA_X | GDK_WA_Y;
+      
+  window = gdk_window_new (parent, &attributes, attributes_mask);
+  gdk_window_set_user_data (window, darea);
+
+  bg = g_new (GdkColor, 1);
+  if (color)
+    *bg = *color;
+  else
+    {
+      bg->red = g_random_int_range (0, 0xffff);
+      bg->blue = g_random_int_range (0, 0xffff);
+      bg->green = g_random_int_range (0, 0xffff);;
+    }
+  
+  gdk_rgb_find_color (gtk_widget_get_colormap (darea), bg);
+  gdk_window_set_background (window, bg);
+  g_object_set_data_full (G_OBJECT (window), "color", bg, g_free);
+  
+  gdk_window_show (window);
+  
+  return window;
+}
+
+static void
+add_window_cb (GtkTreeModel      *model,
+              GtkTreePath       *path,
+              GtkTreeIter       *iter,
+              gpointer           data)
+{
+  GList **selected = data;
+  GdkWindow *window;
+
+  gtk_tree_model_get (GTK_TREE_MODEL (window_store),
+                     iter,
+                     0, &window,
+                     -1);
+
+  *selected = g_list_prepend (*selected, window);
+}
+
+static GList *
+get_selected_windows (void)
+{
+  GtkTreeSelection *sel;
+  GList *selected;
+
+  sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+  selected = NULL;
+  gtk_tree_selection_selected_foreach (sel, add_window_cb, &selected);
+  
+  return selected;
+}
+
+static gboolean
+find_window_helper (GtkTreeModel *model,
+                   GdkWindow *window,
+                   GtkTreeIter *iter,
+                   GtkTreeIter *selected_iter)
+{
+  GtkTreeIter child_iter;
+  GdkWindow *w;
+
+  do
+    {
+      gtk_tree_model_get (model, iter,
+                         0, &w,
+                         -1);
+      if (w == window)
+       {
+         *selected_iter = *iter;
+         return TRUE;
+       }
+      
+      if (gtk_tree_model_iter_children (model,
+                                       &child_iter,
+                                       iter))
+       {
+         if (find_window_helper (model, window, &child_iter, selected_iter))
+           return TRUE;
+       }
+    } while (gtk_tree_model_iter_next (model, iter));
+
+  return FALSE;
+}
+
+static gboolean
+find_window (GdkWindow *window,
+            GtkTreeIter *window_iter)
+{
+  GtkTreeIter iter;
+
+  if (!gtk_tree_model_get_iter_first  (GTK_TREE_MODEL (window_store), &iter))
+    return FALSE;
+
+  return find_window_helper (GTK_TREE_MODEL (window_store),
+                            window,
+                            &iter,
+                            window_iter);
+}
+
+static void
+toggle_selection_window (GdkWindow *window)
+{
+  GtkTreeSelection *selection;
+  GtkTreeIter iter;
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+  if (window != NULL &&
+      find_window (window, &iter))
+    {
+      if (gtk_tree_selection_iter_is_selected (selection, &iter))
+       gtk_tree_selection_unselect_iter (selection,  &iter);
+      else
+       gtk_tree_selection_select_iter (selection,  &iter);
+    }
+}
+
+static void
+unselect_windows (void)
+{
+  GtkTreeSelection *selection;
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+  
+  gtk_tree_selection_unselect_all (selection);
+}
+
+
+static void
+select_window (GdkWindow *window)
+{
+  GtkTreeSelection *selection;
+  GtkTreeIter iter;
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+
+  if (window != NULL &&
+      find_window (window, &iter))
+    gtk_tree_selection_select_iter (selection,  &iter);
+}
+
+static void
+select_windows (GList *windows)
+{
+  GtkTreeSelection *selection;
+  GtkTreeIter iter;
+  GList *l;
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview));
+  gtk_tree_selection_unselect_all (selection);
+  
+  for (l = windows; l != NULL; l = l->next)
+    {
+      if (find_window (l->data, &iter))
+       gtk_tree_selection_select_iter (selection,  &iter);
+    }
+}
+
+static void
+add_window_clicked (GtkWidget *button, 
+                   gpointer data)
+{
+  GdkWindow *parent;
+  GList *l;
+
+  l = get_selected_windows ();
+  if (l != NULL)
+    parent = l->data;
+  else
+    parent = darea->window;
+
+  g_list_free (l);
+  
+  create_window (parent, 10, 10, 100, 100, NULL);
+  update_store ();
+}
+
+static void
+draw_drawable_clicked (GtkWidget *button, 
+                      gpointer data)
+{
+  GdkGC *gc;
+  gc = gdk_gc_new (darea->window);
+  gdk_draw_drawable (darea->window,
+                    gc,
+                    darea->window,
+                    -15, -15,
+                    40, 70,
+                    100, 100);
+  g_object_unref (gc);
+}
+
+
+static void
+remove_window_clicked (GtkWidget *button, 
+                      gpointer data)
+{
+  GList *l, *selected;
+
+  selected = get_selected_windows ();
+
+  for (l = selected; l != NULL; l = l->next)
+    gdk_window_destroy (l->data);
+
+  g_list_free (selected);
+
+  update_store ();
+}
+
+static void save_children (GString *s, GdkWindow *window);
+
+static void
+save_window (GString *s,
+            GdkWindow *window)
+{
+  gint x, y, w, h;
+  GdkColor *color;
+
+  gdk_window_get_position (window, &x, &y);
+  gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
+  color = g_object_get_data (G_OBJECT (window), "color");
+  
+  g_string_append_printf (s, "%d,%d %dx%d (%d,%d,%d) %d %d\n",
+                         x, y, w, h,
+                         color->red, color->green, color->blue,
+                         window_has_impl (window),
+                         g_list_length (gdk_window_peek_children (window)));
+
+  save_children (s, window);
+}
+
+
+static void
+save_children (GString *s,
+              GdkWindow *window)
+{
+  GList *l;
+  GdkWindow *child;
+
+  for (l = g_list_reverse (gdk_window_peek_children (window));
+       l != NULL;
+       l = l->next)
+    {
+      child = l->data;
+
+      save_window (s, child);
+    }
+}
+
+
+static void
+save_clicked (GtkWidget *button, 
+             gpointer data)
+{
+  GString *s;
+  GtkWidget *dialog;
+  GFile *file;
+
+  s = g_string_new ("");
+
+  save_children (s, darea->window);
+
+  dialog = gtk_file_chooser_dialog_new ("Filename for window data",
+                                       NULL,
+                                       GTK_FILE_CHOOSER_ACTION_SAVE,
+                                       GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                                       GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
+                                       NULL);
+  
+  gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
+  
+  if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
+    {
+      file = gtk_file_chooser_get_file (GTK_FILE_CHOOSER (dialog));
+
+      g_file_replace_contents (file,
+                              s->str, s->len,
+                              NULL, FALSE,
+                              0, NULL, NULL, NULL);
+
+      g_object_unref (file);
+    }
+
+  gtk_widget_destroy (dialog);
+  g_string_free (s, TRUE);
+}
+
+static void
+destroy_children (GdkWindow *window)
+{
+  GList *l;
+  GdkWindow *child;
+
+  for (l = gdk_window_peek_children (window);
+       l != NULL;
+       l = l->next)
+    {
+      child = l->data;
+      
+      destroy_children (child);
+      gdk_window_destroy (child);
+    }
+}
+
+static char **
+parse_window (GdkWindow *parent, char **lines)
+{
+  int x, y, w, h, r, g, b, native, n_children;
+  GdkWindow *window;
+  GdkColor color;
+  int i;
+
+  if (*lines == NULL)
+    return lines;
+  
+  if (sscanf(*lines, "%d,%d %dx%d (%d,%d,%d) %d %d",
+            &x, &y, &w, &h, &r, &g, &b, &native, &n_children) == 9)
+    {
+      lines++;
+      color.red = r;
+      color.green = g;
+      color.blue = b;
+      window = create_window (parent, x, y, w, h, &color);
+      if (native)
+       gdk_window_ensure_native (window);
+      
+      for (i = 0; i < n_children; i++)
+       lines = parse_window (window, lines);
+    }
+  else
+    lines++;
+  
+  return lines;
+}
+  
+static void
+load_file (GFile *file)
+{
+  char *data;
+  char **lines, **l;
+  
+  if (g_file_load_contents (file, NULL, &data, NULL, NULL, NULL))
+    {
+      destroy_children (darea->window);
+
+      lines = g_strsplit (data, "\n", -1);
+
+      l = lines;
+      while (*l != NULL)
+       l = parse_window (darea->window, l);
+    }
+
+  update_store ();
+}
+
+static void
+move_window_clicked (GtkWidget *button, 
+                    gpointer data)
+{
+  GdkWindow *window;
+  GtkDirectionType direction;
+  GList *selected, *l;
+  gint x, y;
+
+  direction = GPOINTER_TO_INT (data);
+    
+  selected = get_selected_windows ();
+
+  for (l = selected; l != NULL; l = l->next)
+    {
+      window = l->data;
+      
+      gdk_window_get_position (window, &x, &y);
+      
+      switch (direction) {
+      case GTK_DIR_UP:
+       y -= 10;
+       break;
+      case GTK_DIR_DOWN:
+       y += 10;
+       break;
+      case GTK_DIR_LEFT:
+       x -= 10;
+       break;
+      case GTK_DIR_RIGHT:
+       x += 10;
+       break;
+      default:
+       break;
+      }
+
+      gdk_window_move (window, x, y);
+    }
+
+  g_list_free (selected);
+}
+
+static void
+manual_clicked (GtkWidget *button, 
+               gpointer data)
+{
+  GdkWindow *window;
+  GList *selected, *l;
+  int x, y, w, h;
+  GtkWidget *dialog, *table, *label, *xspin, *yspin, *wspin, *hspin;
+  
+
+  selected = get_selected_windows ();
+
+  if (selected == NULL)
+    return;
+
+  gdk_window_get_position (selected->data, &x, &y);
+  gdk_drawable_get_size (selected->data, &w, &h);
+
+  dialog = gtk_dialog_new_with_buttons ("Select new position and size",
+                                       GTK_WINDOW (main_window),
+                                       GTK_DIALOG_MODAL,
+                                       GTK_STOCK_OK, GTK_RESPONSE_OK,
+                                       NULL);
+  
+
+  table = gtk_table_new (2, 4, TRUE);
+  gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))),
+                     table,
+                     FALSE, FALSE,
+                     2);
+
+  
+  label = gtk_label_new ("x:");
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                            label,
+                            0, 1,
+                            0, 1);
+  label = gtk_label_new ("y:");
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                            label,
+                            0, 1,
+                            1, 2);
+  label = gtk_label_new ("width:");
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                            label,
+                            0, 1,
+                            2, 3);
+  label = gtk_label_new ("height:");
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                            label,
+                            0, 1,
+                            3, 4);
+
+  xspin = gtk_spin_button_new_with_range (G_MININT, G_MAXINT, 1);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON (xspin), x);
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                            xspin,
+                            1, 2,
+                            0, 1);
+  yspin = gtk_spin_button_new_with_range (G_MININT, G_MAXINT, 1);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON (yspin), y);
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                            yspin,
+                            1, 2,
+                            1, 2);
+  wspin = gtk_spin_button_new_with_range (G_MININT, G_MAXINT, 1);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON (wspin), w);
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                            wspin,
+                            1, 2,
+                            2, 3);
+  hspin = gtk_spin_button_new_with_range (G_MININT, G_MAXINT, 1);
+  gtk_spin_button_set_value (GTK_SPIN_BUTTON (hspin), h);
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                            hspin,
+                            1, 2,
+                            3, 4);
+  
+  gtk_widget_show_all (dialog);
+  
+  gtk_dialog_run (GTK_DIALOG (dialog));
+
+  x = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (xspin));
+  y = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (yspin));
+  w = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (wspin));
+  h = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON (hspin));
+
+  gtk_widget_destroy (dialog);
+  
+  for (l = selected; l != NULL; l = l->next)
+    {
+      window = l->data;
+      
+      gdk_window_move_resize (window, x, y, w, h);
+    }
+
+  g_list_free (selected);
+}
+
+static void
+scroll_window_clicked (GtkWidget *button, 
+                      gpointer data)
+{
+  GdkWindow *window;
+  GtkDirectionType direction;
+  GList *selected, *l;
+  gint dx, dy;
+
+  direction = GPOINTER_TO_INT (data);
+    
+  selected = get_selected_windows ();
+
+  dx = 0; dy = 0;
+  switch (direction) {
+  case GTK_DIR_UP:
+    dy = 10;
+    break;
+  case GTK_DIR_DOWN:
+    dy = -10;
+    break;
+  case GTK_DIR_LEFT:
+    dx = 10;
+    break;
+  case GTK_DIR_RIGHT:
+    dx = -10;
+    break;
+  default:
+    break;
+  }
+  
+  for (l = selected; l != NULL; l = l->next)
+    {
+      window = l->data;
+
+      gdk_window_scroll (window, dx, dy);
+    }
+
+  g_list_free (selected);
+}
+
+
+static void
+raise_window_clicked (GtkWidget *button, 
+                     gpointer data)
+{
+  GList *selected, *l;
+  GdkWindow *window;
+    
+  selected = get_selected_windows ();
+
+  for (l = selected; l != NULL; l = l->next)
+    {
+      window = l->data;
+      
+      gdk_window_raise (window);
+    }
+
+  g_list_free (selected);
+  
+  update_store ();
+}
+
+static void
+lower_window_clicked (GtkWidget *button, 
+                     gpointer data)
+{
+  GList *selected, *l;
+  GdkWindow *window;
+    
+  selected = get_selected_windows ();
+
+  for (l = selected; l != NULL; l = l->next)
+    {
+      window = l->data;
+      
+      gdk_window_lower (window);
+    }
+
+  g_list_free (selected);
+  
+  update_store ();
+}
+
+
+static void
+smaller_window_clicked (GtkWidget *button, 
+                       gpointer data)
+{
+  GList *selected, *l;
+  GdkWindow *window;
+  int w, h;
+
+  selected = get_selected_windows ();
+
+  for (l = selected; l != NULL; l = l->next)
+    {
+      window = l->data;
+      
+      gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
+      
+      w -= 10;
+      h -= 10;
+      if (w < 1)
+       w = 1;
+      if (h < 1)
+       h = 1;
+      
+      gdk_window_resize (window, w, h);
+    }
+
+  g_list_free (selected);
+}
+
+static void
+larger_window_clicked (GtkWidget *button, 
+                       gpointer data)
+{
+  GList *selected, *l;
+  GdkWindow *window;
+  int w, h;
+
+  selected = get_selected_windows ();
+
+  for (l = selected; l != NULL; l = l->next)
+    {
+      window = l->data;
+      
+      gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
+      
+      w += 10;
+      h += 10;
+      
+      gdk_window_resize (window, w, h);
+    }
+
+  g_list_free (selected);
+}
+
+static void
+native_window_clicked (GtkWidget *button, 
+                       gpointer data)
+{
+  GList *selected, *l;
+  GdkWindow *window;
+
+  selected = get_selected_windows ();
+
+  for (l = selected; l != NULL; l = l->next)
+    {
+      window = l->data;
+      
+      gdk_window_ensure_native (window);
+    }
+  
+  g_list_free (selected);
+  
+  update_store ();
+}
+
+static gboolean
+darea_button_release_event (GtkWidget *widget,
+                           GdkEventButton *event)
+{
+  if ((event->state & GDK_CONTROL_MASK) != 0)
+    {
+      toggle_selection_window (event->window);
+    }
+  else
+    {
+      unselect_windows ();
+      select_window (event->window);
+    }
+    
+  return TRUE;
+}
+
+static void
+render_window_cell (GtkTreeViewColumn *tree_column,
+                   GtkCellRenderer   *cell,
+                   GtkTreeModel      *tree_model,
+                   GtkTreeIter       *iter,
+                   gpointer           data)
+{
+  GdkWindow *window;
+  char *name;
+
+  gtk_tree_model_get (GTK_TREE_MODEL (window_store),
+                     iter,
+                     0, &window,
+                     -1);
+
+  if (window_has_impl (window))
+      name = g_strdup_printf ("%p (native)", window);
+  else
+      name = g_strdup_printf ("%p", window);
+  g_object_set (cell,
+               "text", name,
+               "background-gdk", &((GdkWindowObject *)window)->bg_color,
+               NULL);  
+}
+
+static void
+add_children (GtkTreeStore *store,
+             GdkWindow *window,
+             GtkTreeIter *window_iter)
+{
+  GList *l;
+  GtkTreeIter child_iter;
+
+  for (l = gdk_window_peek_children (window);
+       l != NULL;
+       l = l->next)
+    {
+      gtk_tree_store_append (store, &child_iter, window_iter);
+      gtk_tree_store_set (store, &child_iter,
+                         0, l->data,
+                         -1);
+
+      add_children (store, l->data, &child_iter);
+    }
+}
+
+static void
+update_store (void)
+{
+  GList *selected;
+
+  selected = get_selected_windows ();
+
+  gtk_tree_store_clear (window_store);
+
+  add_children (window_store, darea->window, NULL);
+  gtk_tree_view_expand_all (GTK_TREE_VIEW (treeview));
+
+  select_windows (selected);
+  g_list_free (selected);
+}
+
+
+int
+main (int argc, char **argv)
+{
+  GtkWidget *window, *vbox, *hbox, *frame;
+  GtkWidget *button, *scrolled, *table;
+  GtkTreeViewColumn *column;
+  GtkCellRenderer *renderer;
+  GdkColor black = {0};
+  GFile *file;
+  
+  gtk_init (&argc, &argv);
+
+  main_window = window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_container_set_border_width (GTK_CONTAINER (window), 0);
+
+  g_signal_connect (G_OBJECT (window), "delete-event", gtk_main_quit, NULL);
+
+  hbox = gtk_hbox_new (FALSE, 5);
+  gtk_container_add (GTK_CONTAINER (window), hbox);
+  gtk_widget_show (hbox);
+
+  frame = gtk_frame_new ("GdkWindows");
+  gtk_box_pack_start (GTK_BOX (hbox),
+                     frame,
+                     FALSE, FALSE,
+                     5);
+  gtk_widget_show (frame);
+
+  darea =  gtk_drawing_area_new ();
+  /*gtk_widget_set_double_buffered (darea, FALSE);*/
+  gtk_widget_add_events (darea, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
+  gtk_widget_set_size_request (darea, 500, 500);
+  g_signal_connect (darea, "button_release_event", 
+                   G_CALLBACK (darea_button_release_event), 
+                   NULL);
+
+  
+  gtk_container_add (GTK_CONTAINER (frame), darea);
+  gtk_widget_realize (darea);
+  gtk_widget_show (darea);
+  gtk_widget_modify_bg (darea, GTK_STATE_NORMAL,
+                       &black);
+                       
+  
+  vbox = gtk_vbox_new (FALSE, 5);
+  gtk_box_pack_start (GTK_BOX (hbox),
+                     vbox,
+                     FALSE, FALSE,
+                     5);
+  gtk_widget_show (vbox);
+
+  window_store = gtk_tree_store_new (1, GDK_TYPE_WINDOW);
+  
+  treeview = gtk_tree_view_new_with_model (GTK_TREE_MODEL (window_store));
+  gtk_tree_selection_set_mode (gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)),
+                              GTK_SELECTION_MULTIPLE);
+  column = gtk_tree_view_column_new ();
+  gtk_tree_view_column_set_title (column, "Window");
+  renderer = gtk_cell_renderer_text_new ();
+  gtk_tree_view_column_pack_start (column, renderer, TRUE);
+  gtk_tree_view_column_set_cell_data_func (column,
+                                          renderer,
+                                          render_window_cell,
+                                          NULL, NULL);
+
+  gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
+
+
+  scrolled = gtk_scrolled_window_new (NULL, NULL);
+  gtk_widget_set_size_request (scrolled, 200, 400);
+  gtk_container_add (GTK_CONTAINER (scrolled), treeview);
+  gtk_box_pack_start (GTK_BOX (vbox),
+                     scrolled,
+                     FALSE, FALSE,
+                     5);
+  gtk_widget_show (scrolled);
+  gtk_widget_show (treeview);
+  
+  table = gtk_table_new (4, 4, TRUE);
+  gtk_box_pack_start (GTK_BOX (vbox),
+                     table,
+                     FALSE, FALSE,
+                     2);
+  gtk_widget_show (table);
+
+  button = gtk_button_new ();
+  gtk_button_set_image (GTK_BUTTON (button),
+                       gtk_image_new_from_stock (GTK_STOCK_GO_BACK,
+                                                 GTK_ICON_SIZE_BUTTON));
+  g_signal_connect (button, "clicked", 
+                   G_CALLBACK (move_window_clicked), 
+                   GINT_TO_POINTER (GTK_DIR_LEFT));
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                            button,
+                            0, 1,
+                            1, 2);
+  gtk_widget_show (button);
+
+  button = gtk_button_new ();
+  gtk_button_set_image (GTK_BUTTON (button),
+                       gtk_image_new_from_stock (GTK_STOCK_GO_UP,
+                                                 GTK_ICON_SIZE_BUTTON));
+  g_signal_connect (button, "clicked", 
+                   G_CALLBACK (move_window_clicked), 
+                   GINT_TO_POINTER (GTK_DIR_UP));
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                            button,
+                            1, 2,
+                            0, 1);
+  gtk_widget_show (button);
+
+  button = gtk_button_new ();
+  gtk_button_set_image (GTK_BUTTON (button),
+                       gtk_image_new_from_stock (GTK_STOCK_GO_FORWARD,
+                                                 GTK_ICON_SIZE_BUTTON));
+  g_signal_connect (button, "clicked", 
+                   G_CALLBACK (move_window_clicked), 
+                   GINT_TO_POINTER (GTK_DIR_RIGHT));
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                            button,
+                            2, 3,
+                            1, 2);
+  gtk_widget_show (button);
+
+  button = gtk_button_new ();
+  gtk_button_set_image (GTK_BUTTON (button),
+                       gtk_image_new_from_stock (GTK_STOCK_GO_DOWN,
+                                                 GTK_ICON_SIZE_BUTTON));
+  g_signal_connect (button, "clicked", 
+                   G_CALLBACK (move_window_clicked), 
+                   GINT_TO_POINTER (GTK_DIR_DOWN));
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                            button,
+                            1, 2,
+                            2, 3);
+  gtk_widget_show (button);
+
+
+  button = gtk_button_new_with_label ("Raise");
+  g_signal_connect (button, "clicked", 
+                   G_CALLBACK (raise_window_clicked), 
+                   NULL);
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                            button,
+                            0, 1,
+                            0, 1);
+  gtk_widget_show (button);
+
+  button = gtk_button_new_with_label ("Lower");
+  g_signal_connect (button, "clicked", 
+                   G_CALLBACK (lower_window_clicked), 
+                   NULL);
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                            button,
+                            0, 1,
+                            2, 3);
+  gtk_widget_show (button);
+
+
+  button = gtk_button_new_with_label ("Smaller");
+  g_signal_connect (button, "clicked", 
+                   G_CALLBACK (smaller_window_clicked), 
+                   NULL);
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                            button,
+                            2, 3,
+                            0, 1);
+  gtk_widget_show (button);
+
+  button = gtk_button_new_with_label ("Larger");
+  g_signal_connect (button, "clicked", 
+                   G_CALLBACK (larger_window_clicked), 
+                   NULL);
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                            button,
+                            2, 3,
+                            2, 3);
+  gtk_widget_show (button);
+
+  button = gtk_button_new_with_label ("Native");
+  g_signal_connect (button, "clicked", 
+                   G_CALLBACK (native_window_clicked), 
+                   NULL);
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                            button,
+                            1, 2,
+                            1, 2);
+  gtk_widget_show (button);
+
+
+  button = gtk_button_new_with_label ("scroll");
+  gtk_button_set_image (GTK_BUTTON (button),
+                       gtk_image_new_from_stock (GTK_STOCK_GO_UP,
+                                                 GTK_ICON_SIZE_BUTTON));
+  g_signal_connect (button, "clicked", 
+                   G_CALLBACK (scroll_window_clicked), 
+                   GINT_TO_POINTER (GTK_DIR_UP));
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                            button,
+                            3, 4,
+                            0, 1);
+  gtk_widget_show (button);
+
+  button = gtk_button_new_with_label ("scroll");
+  gtk_button_set_image (GTK_BUTTON (button),
+                       gtk_image_new_from_stock (GTK_STOCK_GO_DOWN,
+                                                 GTK_ICON_SIZE_BUTTON));
+  g_signal_connect (button, "clicked", 
+                   G_CALLBACK (scroll_window_clicked), 
+                   GINT_TO_POINTER (GTK_DIR_DOWN));
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                            button,
+                            3, 4,
+                            1, 2);
+  gtk_widget_show (button);
+
+  button = gtk_button_new_with_label ("Manual");
+  g_signal_connect (button, "clicked", 
+                   G_CALLBACK (manual_clicked),
+                   NULL);
+  gtk_table_attach_defaults (GTK_TABLE (table),
+                            button,
+                            3, 4,
+                            2, 3);
+  gtk_widget_show (button);
+
+  button = gtk_button_new_with_label ("draw drawable");
+  gtk_box_pack_start (GTK_BOX (vbox),
+                     button,
+                     FALSE, FALSE,
+                     2);
+  gtk_widget_show (button);
+  g_signal_connect (button, "clicked", 
+                   G_CALLBACK (draw_drawable_clicked), 
+                   NULL);
+
+  button = gtk_button_new_with_label ("Add window");
+  gtk_box_pack_start (GTK_BOX (vbox),
+                     button,
+                     FALSE, FALSE,
+                     2);
+  gtk_widget_show (button);
+  g_signal_connect (button, "clicked", 
+                   G_CALLBACK (add_window_clicked), 
+                   NULL);
+  
+  button = gtk_button_new_with_label ("Remove window");
+  gtk_box_pack_start (GTK_BOX (vbox),
+                     button,
+                     FALSE, FALSE,
+                     2);
+  gtk_widget_show (button);
+  g_signal_connect (button, "clicked", 
+                   G_CALLBACK (remove_window_clicked), 
+                   NULL);
+
+  button = gtk_button_new_with_label ("Save");
+  gtk_box_pack_start (GTK_BOX (vbox),
+                     button,
+                     FALSE, FALSE,
+                     2);
+  gtk_widget_show (button);
+  g_signal_connect (button, "clicked", 
+                   G_CALLBACK (save_clicked), 
+                   NULL);
+
+  gtk_widget_show (window);
+
+  if (argc == 2)
+    {
+      file = g_file_new_for_commandline_arg (argv[1]);
+      load_file (file);
+      g_object_unref (file);
+    }
+  
+  gtk_main ();
+
+  return 0;
+}