]> Pileus Git - ~andy/gtk/commitdiff
Merge branch 'master' into client-side-windows
authorAlexander Larsson <alexl@redhat.com>
Mon, 25 May 2009 12:30:01 +0000 (14:30 +0200)
committerAlexander Larsson <alexl@redhat.com>
Mon, 25 May 2009 12:30:01 +0000 (14:30 +0200)
Conflicts:
gdk/x11/gdkwindow-x11.c

69 files changed:
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/gdkoffscreenwindow.c [new file with mode: 0644]
gdk/gdkpango.c
gdk/gdkpixmap.c
gdk/gdkregion-generic.c
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-x11.c
gdk/x11/gdkinput.c
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
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 52a5bf04608f9e6b0d4ee3f270a292f4877ab456..1e962428be3fb02a171278baed509ff6ea5f7a73 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      \
index cfb54c202368b824f32cc21ee9f88efd5f8077ca..44cee62b4a93eca2c607433370fd22dfa9456923 100644 (file)
@@ -69,9 +69,7 @@ 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 +83,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 +255,6 @@ gdk_visual_type_get_type G_GNUC_CONST
 #endif
 #endif
 
-#if IN_HEADER(__GDK_PIXMAP_H__)
-#if IN_FILE(__GDK_PIXMAP_X11_C__)
-gdk_bitmap_create_from_data
-#endif
-#endif
-
 #if IN_HEADER(__GDK_FONT_H__)
 #if IN_FILE(__GDK_FONT_C__)
 #ifndef GDK_DISABLE_DEPRECATED
@@ -466,7 +461,6 @@ gdk_display_get_default_screen
 gdk_display_get_name
 gdk_display_get_n_screens
 gdk_display_get_screen
-gdk_display_pointer_is_grabbed
 gdk_display_pointer_ungrab
 gdk_display_keyboard_ungrab
 gdk_display_open
@@ -667,10 +661,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
@@ -719,6 +718,12 @@ gdk_window_set_composited
 #endif
 #endif
 
+#if IN_HEADER(__GDK_WINDOW_H__)
+#if IN_FILE(__GDK_OFFSCREEN_WINDOW_C__)
+gdk_window_get_offscreen_pixmap
+#endif
+#endif
+
 #if IN_HEADER(__GDK_WINDOW_H__)
 #if IN_FILE(__GDK_DND_X11_C__)
 gdk_window_register_dnd
@@ -733,7 +738,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,8 +752,6 @@ 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
@@ -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..ae9c8f92dca1d04f5d982ed3239a3111efed4954 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,80 @@ 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;
+  GdkWindow *pointer_window;
+  gint tmpx, tmpy;
+  GdkModifierType tmp_mask;
+
+  private = (GdkWindowObject *) window;
+
+  pointer_window = _gdk_windowing_window_get_pointer (display,
+                                                      window,
+                                                      &tmpx, &tmpy,
+                                                      mask);
+  /* We got the coords on the impl, conver to the window */
+  tmpx -= private->abs_x;
+  tmpy -= private->abs_y;
+  
+  if (x)
+    *x = tmpx;
+  if (y)
+    *y = tmpy;
+
+  /* We need to recalculate the true child window with the pointer in it
+     due to possible client side child windows */
+  if (pointer_window != NULL)
+    {
+      /* First get the pointer coords relative to pointer_window */
+      _gdk_windowing_window_get_pointer (display,
+                                        pointer_window,
+                                        &tmpx, &tmpy,
+                                        &tmp_mask);
+      /* Then convert that to a client side window */
+      pointer_window = _gdk_window_find_descendant_at (pointer_window,
+                                                      tmpx, tmpy, 
+                                                      NULL, NULL);
+    }
+
+  return pointer_window;
+}
+
 /**
  * gdk_display_get_window_at_pointer:
  * @display: a #GdkDisplay
@@ -586,8 +689,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 +698,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 +735,568 @@ 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_windowing_window_get_pointer (display,
+                                        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_windowing_window_get_pointer (display,
+                                        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_windowing_window_get_pointer (display,
+                                        src_toplevel,
+                                        &x, &y, &state);
+      _gdk_syntesize_crossing_events (display,
+                                     src_window,
+                                     NULL,
+                                     crossing_mode,
+                                     x, y, state,
+                                     time,
+                                     NULL,
+                                     serial);
+      _gdk_windowing_window_get_pointer (display,
+                                        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 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 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_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..3c7bde322fdaa739da9e7d59951099da1a95f0e6 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;
@@ -68,6 +95,13 @@ struct _GdkDisplay
   guint double_click_distance; /* Maximum distance between clicks in pixels */
   gint button_x[2];             /* The last 2 button click positions. */
   gint button_y[2];
+
+  GList *pointer_grabs;
+  GdkKeyboardGrabInfo keyboard_grab;
+  GdkPointerWindowInfo pointer_info;
+
+  /* Last reported event time from server */
+  guint32 last_event_time;
 };
 
 struct _GdkDisplayClass
index 81e6e08390a500a25b160d74f730669e1d2b4f69..8c5d4227ac260ed7b4e7ee3f2998dc5c16e165e3 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,8 +653,21 @@ gdk_draw_drawable (GdkDrawable *drawable,
                                                           &composite_x_offset,
                                                           &composite_y_offset);
 
+  /* 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 clear that area in the destination instead. */
   
-  GDK_DRAWABLE_GET_CLASS (drawable)->draw_drawable (drawable, gc, composite,
+  GDK_DRAWABLE_GET_CLASS (drawable)->draw_drawable (drawable, gc, composite_impl,
                                                     xsrc - composite_x_offset,
                                                     ysrc - composite_y_offset,
                                                     xdest, ydest,
@@ -871,7 +885,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 +1009,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 +1199,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 +1785,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..50904fc2e74bc70f900d6bb41233ad14fadc48df 100644 (file)
@@ -200,10 +200,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..f3ac9682026c6b65146be4216ae596f9b876874a 100644 (file)
@@ -43,9 +43,20 @@ struct _GdkGCPrivate
 {
   GdkRegion *clip_region;
 
+  guint32 region_tag_applied;
+  int region_tag_offset_x;
+  int region_tag_offset_y;
+  
+  GdkRegion *old_clip_region;
+  GdkPixmap *old_clip_mask;
+  
+  GdkSubwindowMode subwindow_mode;
+  
   GdkFill fill;
   GdkBitmap *stipple;
   GdkPixmap *tile;
+
+  GdkPixmap *clip_mask;
   
   guint32 fg_pixel;
   guint32 bg_pixel;
@@ -150,6 +161,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 +185,8 @@ _gdk_gc_init (GdkGC           *gc,
     priv->fg_pixel = values->foreground.pixel;
   if (values_mask & GDK_GC_BACKGROUND)
     priv->bg_pixel = values->background.pixel;
+  if (values_mask & GDK_GC_SUBWINDOW)
+    priv->subwindow_mode = values->subwindow_mode;
 
   gc->colormap = gdk_drawable_get_colormap (drawable);
   if (gc->colormap)
@@ -183,9 +198,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 +290,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 +306,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 +348,8 @@ gdk_gc_set_values (GdkGC           *gc,
     priv->fg_pixel = values->foreground.pixel;
   if (values_mask & GDK_GC_BACKGROUND)
     priv->bg_pixel = values->background.pixel;
+  if (values_mask & GDK_GC_SUBWINDOW)
+    priv->subwindow_mode = values->subwindow_mode;
   
   GDK_GC_GET_CLASS (gc)->set_values (gc, values, values_mask);
 }
@@ -542,18 +579,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 +713,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 +740,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);
 }
 
 /**
@@ -723,13 +867,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 +1048,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 +1085,7 @@ gdk_gc_copy (GdkGC *dst_gc,
 
   dst_priv->fg_pixel = src_priv->fg_pixel;
   dst_priv->bg_pixel = src_priv->bg_pixel;
+  dst_priv->subwindow_mode = src_priv->subwindow_mode;
 }
 
 /**
@@ -1117,6 +1296,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 +1308,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 +1428,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..a37f9e8937f41869c7e5f9cb073052f436a3622b 100644 (file)
@@ -170,6 +170,103 @@ 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;
+
+
+/* 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;
+
+  GdkWindowPaint *implicit_paint;
+
+  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 +279,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 +330,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);
 
@@ -263,6 +397,16 @@ 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,9 +428,14 @@ 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);
+                                                                                                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_get_pointer        (GdkDisplay       *display,
                                              GdkScreen       **screen,
@@ -300,44 +449,25 @@ GdkWindow* _gdk_windowing_window_get_pointer (GdkDisplay       *display,
                                              GdkModifierType  *mask);
 GdkWindow* _gdk_windowing_window_at_pointer  (GdkDisplay       *display,
                                              gint             *win_x,
-                                             gint             *win_y);
+                                             gint             *win_y,
+                                             GdkModifierType  *mask);
+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 +495,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 +511,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 +523,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 +561,93 @@ 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_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);
+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 *
diff --git a/gdk/gdkoffscreenwindow.c b/gdk/gdkoffscreenwindow.c
new file mode 100644 (file)
index 0000000..5791eac
--- /dev/null
@@ -0,0 +1,1085 @@
+/* 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,
+                                   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 gint
+gdk_offscreen_window_get_origin (GdkWindow *window,
+                                gint      *x,
+                                gint      *y)
+{
+  if (x)
+    *x = 0;
+  if (y)
+    *y = 0;
+
+  return TRUE;
+}
+
+/**
+ * gdk_window_get_offscreen_pixmap:
+ * @window: a #GdkWindow
+ *
+ * Gets the offscreen pixmap that an offscreen window renders into. If
+ * you need to keep this around over window resizes, you need to add a
+ * reference to it.
+ *
+ * Returns: The offscreen pixmap, or NULL if not offscreen
+ **/
+GdkPixmap *
+gdk_window_get_offscreen_pixmap (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkOffscreenWindow *offscreen;
+  
+  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+
+  if (!GDK_IS_OFFSCREEN_WINDOW (private->impl))
+    return NULL;
+  
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+  return offscreen->pixmap;
+}
+
+static void
+gdk_offscreen_window_raise (GdkWindow *window)
+{
+  /* gdk_window_raise already changed the stacking order */
+  _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
+
+static void
+gdk_offscreen_window_lower (GdkWindow *window)
+{
+  /* gdk_window_lower already changed the stacking order */
+  _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
+
+static void
+gdk_offscreen_window_move_resize_internal (GdkWindow *window,
+                                          gint       x,
+                                          gint       y,
+                                          gint       width,
+                                          gint       height,
+                                          gboolean   send_expose_events)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkOffscreenWindow *offscreen;
+  gint dx, dy, dw, dh;
+  GdkGC *gc;
+  GdkPixmap *old_pixmap;
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+  if (width < 1)
+    width = 1;
+  if (height < 1)
+    height = 1;
+
+  if (private->destroyed)
+    return;
+
+  dx = x - private->x;
+  dy = y - private->y;
+  dw = width - private->width;
+  dh = height - private->height;
+
+  private->x = x;
+  private->y = y;
+
+  if (private->width != width ||
+      private->height != height)
+    {
+      private->width = width;
+      private->height = height;
+      
+      old_pixmap = offscreen->pixmap;
+      offscreen->pixmap = gdk_pixmap_new (GDK_DRAWABLE (old_pixmap),
+                                         width,
+                                         height,
+                                         private->depth);
+
+      gc = _gdk_drawable_get_scratch_gc (offscreen->pixmap, FALSE);
+      gdk_draw_drawable (offscreen->pixmap,
+                        gc,
+                        old_pixmap,
+                        0,0, 0, 0,
+                        -1, -1);
+      g_object_unref (old_pixmap);
+    }
+  
+  if (GDK_WINDOW_IS_MAPPED (private))
+    {
+      // TODO: Only invalidate new area, i.e. for larger windows
+      gdk_window_invalidate_rect (window, NULL, TRUE);
+      _gdk_syntesize_crossing_events_for_geometry_change (window);
+    }
+}
+
+static void
+gdk_offscreen_window_move_resize (GdkWindow *window,
+                                  gboolean   with_move,
+                                 gint       x,
+                                  gint       y,
+                                 gint       width,
+                                  gint       height)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkOffscreenWindow *offscreen;
+
+  offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
+
+  if (!with_move)
+    {
+      x = private->x;
+      y = private->y;
+    }
+
+  if (width < 0)
+    width = private->width;
+
+  if (height < 0)
+    height = private->height;
+
+  gdk_offscreen_window_move_resize_internal (window, x, y,
+                                            width, height,
+                                            TRUE);
+}
+
+static void
+gdk_offscreen_window_show (GdkWindow *window)
+{
+  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_origin = gdk_offscreen_window_get_origin;
+  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..de735b91f0a3fc6ac765796fbb4efd56148c9e14 100644 (file)
@@ -145,6 +145,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 +219,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 +233,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 +301,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 +319,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 +334,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 +349,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 +365,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);
 }
@@ -326,6 +383,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 +397,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 +409,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 +421,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 +435,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 +450,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 +467,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 +488,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 +503,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 +582,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..19e03e45c45380d92406c7fb2e5c26d753cf275f 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
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..d2798ba01e4b05ede16ee126497089c4e49ed045 100644 (file)
 #include "gdkscreen.h"
 #include "gdkalias.h"
 
-#define USE_BACKING_STORE      /* Appears to work on Win32, too, now. */
+#undef DEBUG_WINDOW_PRINTING
+
+#ifdef GDK_WINDOWING_X11
+#include "x11/gdkx.h"           /* For workaround */
+#endif
 
-typedef struct _GdkWindowPaint GdkWindowPaint;
+#include "math.h"
+
+/* Not all GdkWindows have a corresponding native window.
+ * Instead some draw into the nearest parent that has whatss
+ * called an "impl", i.e. the implementation window.
+ * For toplevel window system windows the impl is always native
+ * window, but child windows can also have native windows as
+ * this is sometimes necessary. Furthermore, offscreen windows
+ * (type GDK_WINDOW_OFFSCREEN) have an impl of type
+ * GdkOffscreenWindow rather than a backend implementation native
+ * window. Such windows draw into an offscreen pixmap instead
+ * of a window and collect damage that lets you paint it where
+ * you want.
+ *
+ * All GdkWindow track their position, size, clip region and
+ * absolute position in the impl window. For child window with
+ * native windows the clip region is set on the native window
+ * as a window shape to make it clip against other non-native windows.
+ */  
+
+#define USE_BACKING_STORE      /* Appears to work on Win32, too, now. */
 
 struct _GdkWindowPaint
 {
@@ -46,27 +70,17 @@ 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,
@@ -180,6 +194,11 @@ 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,
@@ -192,6 +211,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 +227,38 @@ 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 void move_native_children (GdkWindowObject *private);
+  
 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)
 {
@@ -281,6 +308,9 @@ gdk_window_init (GdkWindowObject *window)
   window->window_type = GDK_WINDOW_CHILD;
 
   window->state = GDK_WINDOW_STATE_WITHDRAWN;
+  window->width = 1;
+  window->height = 1;
+  window->toplevel_window_type = -1;
 }
 
 static GQuark quark_pointer_window = 0;
@@ -318,9 +348,12 @@ 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");
 }
@@ -345,12 +378,397 @@ 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);
 }
 
+static gboolean
+gdk_window_is_offscreen (GdkWindowObject *window)
+{
+  return GDK_WINDOW_TYPE (window) == GDK_WINDOW_OFFSCREEN;
+}
+
+static GdkWindowObject *
+gdk_window_get_impl_window (GdkWindowObject *window)
+{
+  return window->impl_window;
+}
+
+GdkWindow *
+_gdk_window_get_impl_window (GdkWindow *window)
+{
+  return (GdkWindow *)gdk_window_get_impl_window ((GdkWindowObject *)window);
+}
+
+static gboolean
+gdk_window_has_impl (GdkWindowObject *window)
+{
+  return window->impl_window == window;
+}
+
+gboolean
+_gdk_window_has_impl (GdkWindow *window)
+{
+  return gdk_window_has_impl ((GdkWindowObject *)window);
+}
+
+static gboolean
+gdk_window_has_no_impl (GdkWindowObject *window)
+{
+  return window->impl_window != window;
+}
+
+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)
+    {
+      child = l->data;
+
+      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);
+
+    }
+}
+
+static void
+recompute_visible_regions_internal (GdkWindowObject *private,
+                                   gboolean recalculate_clip,
+                                   gboolean recalculate_siblings,
+                                   gboolean recalculate_children)
+{
+  GdkRectangle r;
+  GList *l;
+  GdkWindowObject *child;
+  GdkRegion *new_clip, *old_clip_region_with_children;
+  gboolean clip_region_changed;
+  gboolean abs_pos_changed;
+  int old_abs_x, old_abs_y;
+
+  old_abs_x = private->abs_x;
+  old_abs_y = private->abs_y;
+  
+  /* Update absolute position */
+  if (gdk_window_has_impl (private))
+    {
+      /* Native window starts here */
+      private->abs_x = 0;
+      private->abs_y = 0;
+    }
+  else
+    {
+      private->abs_x = private->parent->abs_x + private->x;
+      private->abs_y = private->parent->abs_y + private->y;
+    }
+
+  abs_pos_changed =
+    private->abs_x != old_abs_x ||
+    private->abs_y != old_abs_y;
+
+  /* Update clip region based on:
+   * parent clip
+   * window size
+   * siblings in parents above window
+   */
+  clip_region_changed = FALSE;
+  if (recalculate_clip)
+    {
+      /* Calculate visible region (sans children) in parent window coords */
+      r.x = private->x;
+      r.y = private->y;
+      r.width = private->width;
+      r.height = private->height;
+      new_clip = gdk_region_rectangle (&r);
+
+      if (private->parent != NULL && GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
+       {
+         gdk_region_intersect (new_clip, private->parent->clip_region);
+         
+         /* Remove all overlapping children from parent */
+         remove_child_area (private->parent, private, FALSE, new_clip);
+       }
+      
+      /* Convert from parent coords to window coords */
+      gdk_region_offset (new_clip, -private->x, -private->y);
+
+      if (private->shape)
+       gdk_region_intersect (new_clip, private->shape);
+
+      if (private->clip_region == NULL ||
+         !gdk_region_equal (private->clip_region, new_clip))
+       clip_region_changed = TRUE;
+       
+      if (private->clip_region)
+       gdk_region_destroy (private->clip_region);
+      private->clip_region = new_clip;
+
+      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);
+    }
+
+  /* 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);
+    }
+}
+
+/* Call this when private has changed in one or more of these ways:
+ *  size changed
+ *  window moved
+ *  new window added
+ *  stacking order of window changed
+ *  child deleted
+ *
+ * It will recalculate abs_x/y and the clip regions
+ *
+ * Unless the window didn't change stacking order or size/pos, pass in TRUE
+ * for recalculate_siblings. (Mostly used internally for the recursion)
+ * 
+ * If a child window was removed (and you can't use that child for
+ * recompute_visible_regions), pass in TRUE for recalculate_children on the parent
+ */
+static void
+recompute_visible_regions (GdkWindowObject *private,
+                          gboolean recalculate_siblings,
+                          gboolean recalculate_children)
+{
+  recompute_visible_regions_internal (private,
+                                     TRUE,
+                                     recalculate_siblings,
+                                     recalculate_children);
+}
+
+void
+_gdk_window_update_size (GdkWindow *window)
+{
+  recompute_visible_regions ((GdkWindowObject *)window, TRUE, FALSE);
+}
+
+/* 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)
+{
+  GdkWindowObject *w;
+  GList *l;
+
+  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);
+
+  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;
+}
+
+
+static GdkWindowObject *
+find_native_sibling_above (GdkWindowObject *parent,
+                          GdkWindowObject *child)
+{
+  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);
+}
+
+static GdkEventMask
+get_native_event_mask (GdkWindowObject *private)
+{
+  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_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_new:
  * @parent: a #GdkWindow, or %NULL to create the window as a child of
@@ -371,98 +789,580 @@ gdk_window_new (GdkWindow     *parent,
                gint           attributes_mask)
 {
   GdkWindow *window;
-  GdkWindowObject *private, *parent_private;
-
-  g_return_val_if_fail (parent == NULL || GDK_IS_WINDOW (parent), NULL);
+  GdkWindowObject *private;
+  GdkScreen *screen;
+  GdkVisual *visual;
+  int x, y;
+  gboolean native;
+  GdkEventMask event_mask;
+  GdkWindow *real_parent;
+  
   g_return_val_if_fail (attributes != NULL, NULL);
-
-  window = _gdk_window_new (parent, attributes, attributes_mask);
-  g_return_val_if_fail (window != NULL, window);
-
-  /* Inherit redirection from parent */
-  if (parent != NULL)
+  
+  if (!parent)
     {
-      parent_private = GDK_WINDOW_OBJECT (parent);
-      private = GDK_WINDOW_OBJECT (window);
-      private->redirect = parent_private->redirect;
+      GDK_NOTE (MULTIHEAD,
+               g_warning ("gdk_window_new(): no parent specified reverting to parent = default root window"));
+      
+      screen = gdk_screen_get_default ();
+      parent = gdk_screen_get_root_window (screen);
     }
+  else
+    screen = gdk_drawable_get_screen (parent);
+
+  g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
   
-  return window;
-}
+  if (GDK_WINDOW_DESTROYED (parent))
+    return NULL;
 
-/**
- * gdk_window_reparent:
- * @window: a #GdkWindow
- * @new_parent: new parent to move @window into
- * @x: X location inside the new parent
- * @y: Y location inside the new parent
- *
- * Reparents @window into the given @new_parent. The window being
- * reparented will be unmapped as a side effect.
- * 
- **/
-void
-gdk_window_reparent (GdkWindow *window,
-                    GdkWindow *new_parent,
-                    gint       x,
-                    gint       y)
-{
-  GdkWindowObject *private;
-  gboolean show;
+  window = g_object_new (GDK_TYPE_WINDOW, NULL);
+  private = (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);
+  /* 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);
 
-  if (GDK_WINDOW_DESTROYED (window) ||
-      (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
-    {
-      return;
-    }
+  private->parent = (GdkWindowObject *)parent;
 
-  private = (GdkWindowObject *) window;
+  private->accept_focus = TRUE;
+  private->focus_on_map = TRUE;
 
-  /* Break up redirection if inherited */
-  if (private->redirect && private->redirect->redirected != private)
+  if (attributes_mask & GDK_WA_X)
+    x = attributes->x;
+  else
+    x = 0;
+  
+  if (attributes_mask & GDK_WA_Y)
+    y = attributes->y;
+  else
+    y = 0;
+  
+  private->x = x;
+  private->y = y;
+  private->width = (attributes->width > 1) ? (attributes->width) : (1);
+  private->height = (attributes->height > 1) ? (attributes->height) : (1);
+
+#ifdef GDK_WINDOWING_X11
+  /* Work around a bug where Xorg refuses to map toplevel InputOnly windows 
+   * from an untrusted client: http://bugs.freedesktop.org/show_bug.cgi?id=6988
+   */
+  if (attributes->wclass == GDK_INPUT_ONLY &&
+      GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT &&
+      !G_LIKELY (GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (parent))->trusted_client))
     {
-      remove_redirect_from_children (private, private->redirect);
-      private->redirect = NULL;
+      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
   
-  show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent (window, new_parent, x, y);
+  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;
 
-  /* Inherit parent redirect if we don't have our own */
-  if (private->parent && private->redirect == NULL)
+  /* Sanity checks */
+  switch (private->window_type)
     {
-      private->redirect = private->parent->redirect;
-      apply_redirect_to_children (private, private->redirect);
+    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;
     }
+  
+  if (attributes_mask & GDK_WA_VISUAL)
+    visual = attributes->visual;
+  else
+    visual = gdk_screen_get_system_visual (screen);
 
-  if (show)
-    gdk_window_show (window);
-}
+  private->event_mask = attributes->event_mask;
 
-static void
-window_remove_filters (GdkWindow *window)
-{
-  GdkWindowObject *obj = (GdkWindowObject*) window;
+  if (attributes->wclass == GDK_INPUT_OUTPUT)
+    {
+      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;
 
-  if (obj->filters)
+      private->bg_pixmap = NULL;
+    }
+  else
     {
-      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;
+      private->depth = 0;
+      private->input_only = TRUE;
     }
-}
 
-/**
- * _gdk_window_destroy_hierarchy:
- * @window: a #GdkWindow
- * @recursing: If TRUE, then this is being called because a parent
+  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)
+       {
+         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);
+    }
+
+  recompute_visible_regions (private, TRUE, FALSE);
+  
+  if (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
+    {
+      /* Inherit redirection from parent */
+      private->redirect = private->parent->redirect;
+    }
+    
+  gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
+                                 (attributes->cursor) :
+                                 NULL));
+
+  return window;
+}
+
+static gboolean
+is_parent_of (GdkWindow *parent,
+              GdkWindow *child)
+{
+  GdkWindow *w;
+
+  w = child;
+  while (w != NULL)
+    {
+      if (w == parent)
+       return TRUE;
+
+      w = gdk_window_get_parent (w);
+    }
+
+  return FALSE;
+}
+
+static void
+change_impl (GdkWindowObject *private,
+            GdkWindowObject *impl_window,
+            GdkDrawable *new)
+{
+  GList *l;
+  GdkWindowObject *child;
+  GdkDrawable *old_impl;
+  GdkWindowObject *old_impl_window;
+
+  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);
+  
+  for (l = private->children; l != NULL; l = l->next)
+    {
+      child = l->data;
+
+      if (child->impl == old_impl)
+       change_impl (child, impl_window, new);
+    }
+}
+
+static void
+reparent_to_impl (GdkWindowObject *private)
+{
+  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_reparent:
+ * @window: a #GdkWindow
+ * @new_parent: new parent to move @window into
+ * @x: X location inside the new parent
+ * @y: Y location inside the new parent
+ *
+ * Reparents @window into the given @new_parent. The window being
+ * reparented will be unmapped as a side effect.
+ * 
+ **/
+void
+gdk_window_reparent (GdkWindow *window,
+                    GdkWindow *new_parent,
+                    gint       x,
+                    gint       y)
+{
+  GdkWindowObject *private;
+  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);
+
+  if (GDK_WINDOW_DESTROYED (window) ||
+      (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
+    return;
+
+  if (!new_parent)
+    new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
+  
+  private = (GdkWindowObject *) window;
+  new_parent_private = (GdkWindowObject *)new_parent;
+
+  /* No input-output children of input-only windows */
+  if (new_parent_private->input_only && !private->input_only)
+    return;
+
+  /* Don't create loops in hierarchy */
+  if (is_parent_of (window, new_parent))
+    return;
+  
+  if (private->cairo_surface)
+    {
+      /* This might be wrong in the new parent, e.g. for non-native surfaces.
+        To make sure we're ok, just wipe it. */
+      cairo_surface_finish (private->cairo_surface);
+      cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
+                                  NULL, NULL);
+    }
+  
+  old_parent = private->parent;
+
+  /* Break up redirection if inherited */
+  if (private->redirect && private->redirect->redirected != private)
+    {
+      remove_redirect_from_children (private, private->redirect);
+      private->redirect = NULL;
+    }
+
+  was_toplevel = private->parent == NULL;
+  was_mapped = GDK_WINDOW_IS_MAPPED (window);
+  show = FALSE;
+
+  /* Reparenting to toplevel. Ensure we have a native window so this can work */
+  if (new_parent_private->window_type == GDK_WINDOW_ROOT ||
+      new_parent_private->window_type == GDK_WINDOW_FOREIGN)
+    gdk_window_set_has_native (window, TRUE);
+
+  do_reparent_to_impl = FALSE;
+  if (gdk_window_has_impl (private))
+    {
+      /* 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);
+
+      show = was_mapped;
+      gdk_window_hide (window);
+
+      do_reparent_to_impl = TRUE;
+      change_impl (private,
+                  new_parent_private->impl_window,
+                  new_parent_private->impl);
+    }
+
+  /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
+   * the root window
+   */
+  if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
+    {
+      new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
+      new_parent_private = (GdkWindowObject *)new_parent;
+    }
+
+  if (old_parent)
+    old_parent->children = g_list_remove (old_parent->children, window);
+  
+  private->parent = new_parent_private;
+  private->x = x;
+  private->y = y;
+
+  new_parent_private->children = g_list_prepend (new_parent_private->children, window);
+  
+  /* Switch the window type as appropriate */
+
+  switch (GDK_WINDOW_TYPE (new_parent))
+    {
+    case GDK_WINDOW_ROOT:
+    case GDK_WINDOW_FOREIGN:
+      if (private->toplevel_window_type != -1)
+       GDK_WINDOW_TYPE (window) = private->toplevel_window_type;
+      else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
+       GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
+      break;
+    case GDK_WINDOW_OFFSCREEN:
+    case GDK_WINDOW_TOPLEVEL:
+    case GDK_WINDOW_CHILD:
+    case GDK_WINDOW_DIALOG:
+    case GDK_WINDOW_TEMP:
+      if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
+         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;
+       }
+    }
+
+  /* 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);
+    }
+
+  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
+    {
+      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);
+       }
+    }
+
+  if (show)
+    gdk_window_show_unraised (window);
+  else
+    _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
+
+/**
+ * gdk_window_set_has_native:
+ * @window: a #GdkWindow
+ * @has_native: whethe the window should have a native window
+ *
+ * Tries to create or remove a window-system native window for this
+ * GdkWindow. This may fail in some situations. For instance:
+ *
+ * Toplevel and foreign windows must have a native window.
+ * Offscreen window and children of them can never have native windows.
+ * Some backends may not support native child windows.
+ * 
+ **/
+void
+gdk_window_set_has_native (GdkWindow *window, gboolean has_native)
+{
+  GdkWindowObject *private;
+  GdkWindowObject *impl_window;
+  GdkDrawable *new_impl, *old_impl;
+  GdkScreen *screen;
+  GdkVisual *visual;
+  GdkWindowAttr attributes;
+  GdkWindowObject *above;
+  GList listhead;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT ||
+      GDK_WINDOW_DESTROYED (window))
+    return;
+
+  private = (GdkWindowObject *) window;
+  
+  if (has_native)
+    {
+      /* Create native window */
+
+      if (gdk_window_has_impl (private))
+       /* Already has an impl, either native (ok) or
+          offscreen (not supported). Bail. */
+       return; 
+
+      impl_window = gdk_window_get_impl_window (private);
+      if (impl_window->window_type == GDK_WINDOW_OFFSCREEN)
+       return; /* native in offscreens not supported */
+
+      screen = gdk_drawable_get_screen (window);
+      visual = gdk_drawable_get_visual (window);
+
+      attributes.colormap = gdk_drawable_get_colormap (window);
+      
+      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;
+
+      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)
+       {
+         listhead.data = window;
+         listhead.prev = NULL;
+         listhead.next = NULL;
+         GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
+                                                                   &listhead);
+       }
+
+      recompute_visible_regions (private, FALSE, FALSE);
+
+      /* 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);
+
+      reparent_to_impl (private);
+
+      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);
+    }
+  else
+    {
+      /* Remove native window */
+
+      if (!gdk_window_has_impl (private))
+       return;  /* Not native, can't remove */
+
+      if (private->window_type == GDK_WINDOW_OFFSCREEN)
+       return; /* Not native, can't remove */
+      
+      if (private->parent == NULL ||
+         GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
+       return; /* toplevel, must be native */
+
+      g_warning ("Tried to turn native window to client side window, this is not supported yet.");
+
+      /* TODO: remove native */
+    }
+}
+
+static void
+window_remove_filters (GdkWindow *window)
+{
+  GdkWindowObject *obj = (GdkWindowObject*) window;
+
+  if (obj->filters)
+    {
+      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;
+    }
+}
+
+/**
+ * _gdk_window_destroy_hierarchy:
+ * @window: a #GdkWindow
+ * @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.
@@ -478,12 +1378,14 @@ window_remove_filters (GdkWindow *window)
 static void
 _gdk_window_destroy_hierarchy (GdkWindow *window,
                               gboolean   recursing,
+                              gboolean   recursing_native,
                               gboolean   foreign_destroy)
 {
   GdkWindowObject *private;
   GdkWindowObject *temp_private;
   GdkWindow *temp_window;
   GdkScreen *screen;
+  GdkDisplay *display;
   GList *children;
   GList *tmp;
 
@@ -494,11 +1396,13 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
   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))
     {
     case GDK_WINDOW_ROOT:
@@ -513,6 +1417,7 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
     case GDK_WINDOW_DIALOG:
     case GDK_WINDOW_TEMP:
     case GDK_WINDOW_FOREIGN:
+    case GDK_WINDOW_OFFSCREEN:
       if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN && !foreign_destroy)
        {
          /* Logically, it probably makes more sense to send
@@ -533,16 +1438,21 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
        }
       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);
+
+             if (!recursing &&
+                 GDK_WINDOW_IS_MAPPED (window))
+               {
+                 recompute_visible_regions (private, TRUE, FALSE);
+                 gdk_window_invalidate_in_parent (private);
+               }
            }
 
-         _gdk_window_clear_update_area (window);
          gdk_window_free_paint_stack (window);
          
          if (private->bg_pixmap &&
@@ -568,13 +1478,34 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
                  temp_private = (GdkWindowObject*) temp_window;
                  if (temp_private)
                    _gdk_window_destroy_hierarchy (temp_window,
-                                                   TRUE, foreign_destroy);
+                                                   TRUE,
+                                                  recursing_native || gdk_window_has_impl (private),
+                                                  foreign_destroy);
                }
              
              g_list_free (children);
            }
+
+         _gdk_window_clear_update_area (window); 
          
-         _gdk_windowing_window_destroy (window, recursing, foreign_destroy);
+         if (private->cairo_surface)
+           {
+             cairo_surface_finish (private->cairo_surface);
+             cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
+                                          NULL, NULL);
+           }
+
+         if (gdk_window_has_impl (private))
+           {
+             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);
+           }
+
+         private->state |= GDK_WINDOW_STATE_WITHDRAWN;
          private->parent = NULL;
          private->destroyed = TRUE;
 
@@ -587,6 +1518,12 @@ _gdk_window_destroy_hierarchy (GdkWindow *window,
            gdk_window_redirect_free (private->redirect);
 
          private->redirect = NULL;
+
+         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;
     }
@@ -607,7 +1544,7 @@ void
 _gdk_window_destroy (GdkWindow *window,
                     gboolean   foreign_destroy)
 {
-  _gdk_window_destroy_hierarchy (window, FALSE, foreign_destroy);
+  _gdk_window_destroy_hierarchy (window, FALSE, FALSE, foreign_destroy);
 }
 
 /**
@@ -625,7 +1562,7 @@ _gdk_window_destroy (GdkWindow *window,
 void
 gdk_window_destroy (GdkWindow *window)
 {
-  _gdk_window_destroy_hierarchy (window, FALSE, FALSE);
+  _gdk_window_destroy_hierarchy (window, FALSE, FALSE, FALSE);
   g_object_unref (window);
 }
 
@@ -744,6 +1681,10 @@ gdk_window_get_parent (GdkWindow *window)
  * @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
  **/
@@ -755,8 +1696,14 @@ gdk_window_get_toplevel (GdkWindow *window)
   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 
   obj = (GdkWindowObject *)window;
+  
   while (GDK_WINDOW_TYPE (obj) == GDK_WINDOW_CHILD)
-    obj = (GdkWindowObject *)obj->parent;
+    {
+      if (obj->parent == NULL ||
+         GDK_WINDOW_TYPE (obj->parent) == GDK_WINDOW_ROOT)
+       break;
+      obj = obj->parent;
+    }
   
   return GDK_WINDOW (obj);
 }
@@ -835,6 +1782,11 @@ gdk_window_add_filter (GdkWindow     *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_set_has_native (window, TRUE);
   
   if (private)
     tmp_list = private->filters;
@@ -1036,6 +1988,119 @@ gdk_window_get_state (GdkWindow *window)
   return private->state;
 }
 
+
+/* This creates an empty "implicit" paint region for the impl window.
+ * By itself this does nothing, but real paints to this window
+ * or children of it can use this pixmap as backing to avoid allocating
+ * multiple pixmaps for subwindow rendering. When doing so they
+ * add to the region of the implicit paint region, which will be
+ * pushed to the window when the implicit paint region is ended.
+ * Such paints should not copy anything to the window on paint end, but
+ * should rely on the implicit paint end.
+ * The implicit paint will be automatically ended if someone draws
+ * directly to the window or a child window.
+ */
+static gboolean
+gdk_window_begin_implicit_paint (GdkWindow *window, GdkRectangle *rect)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowPaint *paint;
+
+  g_assert (gdk_window_has_impl (private));
+
+  if (GDK_IS_PAINTABLE (private->impl))
+    return FALSE; /* Implementation does double buffering */
+  
+  if (private->paint_stack != NULL ||
+      private->implicit_paint != NULL)
+    return FALSE; /* Don't stack implicit paints */
+
+  paint = g_new (GdkWindowPaint, 1);
+  paint->region = gdk_region_new (); /* Empty */
+  paint->x_offset = rect->x;
+  paint->y_offset = rect->y;
+  paint->uses_implicit = FALSE;
+  paint->surface = NULL;
+  paint->pixmap =
+    gdk_pixmap_new (window,
+                   MAX (rect->width, 1), MAX (rect->height, 1), -1);
+
+  private->implicit_paint = paint;
+  
+  return TRUE;
+}
+
+/* Ensure that all content related to this (sub)window is pushed to the
+   native region */
+static void
+gdk_window_flush_implicit_paint (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *impl_window;
+  GdkWindowPaint *paint;
+  GdkRegion *region;
+  GdkGC *tmp_gc;
+
+  /* Ensure that there is no explicit paint region. */
+  g_assert (private->paint_stack == NULL);
+  
+  impl_window = gdk_window_get_impl_window (private);
+  if (impl_window->implicit_paint == NULL)
+    return;
+
+  paint = impl_window->implicit_paint;
+  region = gdk_region_copy (private->clip_region_with_children);
+  gdk_region_offset (region, private->abs_x, private->abs_y);
+  gdk_region_intersect (region, paint->region);
+  
+  if (!gdk_region_empty (region))
+    {
+      /* Some regions are valid, push these to window now */
+      tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
+      _gdk_gc_set_clip_region_internal (tmp_gc, region, TRUE);
+      gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
+                        0, 0, paint->x_offset, paint->y_offset, -1, -1);
+      /* Reset clip region of the cached GdkGC */
+      gdk_gc_set_clip_region (tmp_gc, NULL);
+
+      /* Remove flushed region from the implicit paint */
+      gdk_region_subtract (paint->region, region);
+    }
+  else
+    gdk_region_destroy (region);
+}
+
+/* Ends an implicit paint, paired with gdk_window_begin_implicit_paint returning TRUE */
+static void
+gdk_window_end_implicit_paint (GdkWindow *window)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowPaint *paint;
+  GdkGC *tmp_gc;
+
+  g_assert (gdk_window_has_impl (private));
+
+  g_assert (private->implicit_paint != NULL);
+
+  paint = private->implicit_paint;
+
+  private->implicit_paint = NULL;
+
+  if (!gdk_region_empty (paint->region))
+    {
+      /* Some regions are valid, push these to window now */
+      tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
+      _gdk_gc_set_clip_region_internal (tmp_gc, paint->region, TRUE);
+      gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
+                        0, 0, paint->x_offset, paint->y_offset, -1, -1);
+      /* Reset clip region of the cached GdkGC */
+      gdk_gc_set_clip_region (tmp_gc, NULL);
+    }
+  
+  g_object_unref (paint->pixmap);
+  g_free (paint);
+}
+
 /**
  * gdk_window_begin_paint_rect:
  * @window: a #GdkWindow
@@ -1115,7 +2180,8 @@ gdk_window_begin_paint_region (GdkWindow       *window,
 #ifdef USE_BACKING_STORE
   GdkWindowObject *private = (GdkWindowObject *)window;
   GdkRectangle clip_box;
-  GdkWindowPaint *paint;
+  GdkWindowPaint *paint, *implicit_paint;
+  GdkWindowObject *impl_window;
   GSList *list;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
@@ -1128,24 +2194,63 @@ gdk_window_begin_paint_region (GdkWindow       *window,
       GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
 
       if (iface->begin_paint_region)
-        iface->begin_paint_region ((GdkPaintable*)private->impl, region);
-
+        iface->begin_paint_region ((GdkPaintable*)private->impl, window, region);
+      
       return;
     }
 
-  gdk_region_get_clipbox (region, &clip_box);
+  impl_window = gdk_window_get_impl_window (private);
+  implicit_paint = impl_window->implicit_paint;
 
   paint = g_new (GdkWindowPaint, 1);
   paint->region = gdk_region_copy (region);
-  paint->x_offset = clip_box.x;
-  paint->y_offset = clip_box.y;
-  paint->pixmap =
-    gdk_pixmap_new (window,
-                   MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1);
+  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);
 
-  paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap);
-  cairo_surface_set_device_offset (paint->surface,
-                                  - paint->x_offset, - paint->y_offset);
+    }
+  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)
     {
@@ -1156,15 +2261,64 @@ gdk_window_begin_paint_region (GdkWindow       *window,
   
   private->paint_stack = g_slist_prepend (private->paint_stack, paint);
 
-  if (!gdk_region_empty (region))
+  if (!gdk_region_empty (paint->region))
     {
-      gdk_window_clear_backing_rect (window,
-                                    clip_box.x, clip_box.y,
-                                    clip_box.width, clip_box.height);
+      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
@@ -1188,6 +2342,7 @@ gdk_window_end_paint (GdkWindow *window)
   GdkGC *tmp_gc;
   GdkRectangle clip_box;
   gint x_offset, y_offset;
+  GdkRegion *full_clip;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
@@ -1210,36 +2365,44 @@ gdk_window_end_paint (GdkWindow *window)
     }
 
   paint = private->paint_stack->data;
+
   private->paint_stack = g_slist_delete_link (private->paint_stack, 
-                                              private->paint_stack);
+                                             private->paint_stack);
 
   gdk_region_get_clipbox (paint->region, &clip_box);
 
   tmp_gc = _gdk_drawable_get_scratch_gc (window, FALSE);
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (window, &x_offset, &y_offset);
-
-  gdk_gc_set_clip_region (tmp_gc, paint->region);
-  gdk_gc_set_clip_origin (tmp_gc, - x_offset, - y_offset);
+  x_offset = -private->abs_x;
+  y_offset = -private->abs_y;
 
-  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)
+  if (!paint->uses_implicit)
     {
-      GdkWindowClipData data;
+      gdk_window_flush_outstanding_moves (window);
       
-      setup_redirect_clip (window, tmp_gc, &data);
+      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 + data.x_offset,
-                        clip_box.y + data.y_offset,
+                        clip_box.x + x_offset,
+                        clip_box.y + y_offset,
                         clip_box.width, clip_box.height);
-      reset_redirect_clip (window, tmp_gc, &data);
     }
   
   /* Reset clip region of the cached GdkGC */
@@ -1307,6 +2470,295 @@ gdk_window_free_paint_stack (GdkWindow *window)
     }
 }
 
+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,
@@ -1321,7 +2773,10 @@ gdk_window_get_offsets (GdkWindow *window,
       *y_offset = paint->y_offset;
     }
   else
-    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (window, x_offset, y_offset);
+    {
+      *x_offset = -private->abs_x;
+      *y_offset = -private->abs_y;
+    }
 }
 
 /**
@@ -1369,7 +2824,12 @@ gdk_window_get_internal_paint_info (GdkWindow    *window,
          *real_drawable = paint->pixmap;
        }
       else
-       *real_drawable = window;
+       {
+         /* 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);
@@ -1380,6 +2840,46 @@ gdk_window_get_internal_paint_info (GdkWindow    *window,
     *y_offset = y_off;
 }
 
+static void
+setup_clip_for_draw (GdkDrawable *drawable,
+                    GdkGC *gc,
+                    int old_clip_x, int old_clip_y)
+{
+  GdkWindowObject *private = (GdkWindowObject *)drawable;
+  GdkRegion *clip;
+
+  if (private->window_type == GDK_WINDOW_ROOT)
+    return;
+  
+  if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
+    clip = private->clip_region_with_children;
+  else
+    clip = private->clip_region;
+    
+  _gdk_gc_add_drawable_clip (gc,
+                            private->clip_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);
+}
+
+static void
+setup_clip_for_paint (GdkDrawable *drawable,
+                     GdkWindowPaint *paint,
+                     GdkGC *gc,
+                     int old_clip_x, int old_clip_y)
+{
+  _gdk_gc_add_drawable_clip (gc,
+                            paint->region_tag,
+                            /* This includes the window clip */
+                            paint->region,
+                            /* If there was a clip origin set appart from the
+                             * window offset, need to take that into consideration */
+                            -old_clip_x, -old_clip_y);
+}
+
+
 #define OFFSET_GC(gc)                                         \
     gint x_offset, y_offset;                                 \
     gint old_clip_x = gc->clip_x_origin;    \
@@ -1402,6 +2902,20 @@ gdk_window_get_internal_paint_info (GdkWindow    *window,
        gdk_gc_set_ts_origin (gc, old_ts_x, old_ts_y);       \
      }
 
+#define SETUP_PAINT_GC_CLIP(gc)                             \
+      if (paint->uses_implicit)                                    \
+       setup_clip_for_paint (drawable, paint, gc, old_clip_x,  \
+                              old_clip_y);
+
+#define RESTORE_PAINT_GC_CLIP(gc) 
+
+
+#define SETUP_DIRECT_GC_CLIP(gc)                            \
+      gdk_window_flush ((GdkWindow *)drawable);\
+      setup_clip_for_draw (drawable, gc, old_clip_x, old_clip_y);
+
+#define RESTORE_DIRECT_GC_CLIP(gc)
+
 static GdkGC *
 gdk_window_create_gc (GdkDrawable     *drawable,
                       GdkGCValues     *values,
@@ -1416,6 +2930,16 @@ gdk_window_create_gc (GdkDrawable     *drawable,
                                  values, mask);
 }
 
+/* After having set up the drawable clip rect on a GC we need
+ * to make sure that if we draw to a pixmap we draw to the impl,
+ * otherwise the pixmap code will reset the drawable clip.
+ */
+static GdkDrawable *
+pixmap_impl (GdkPixmap *pixmap)
+{
+  return ((GdkPixmapObject *)pixmap)->impl;
+}
+
 static void
 gdk_window_draw_rectangle (GdkDrawable *drawable,
                           GdkGC       *gc,
@@ -1434,12 +2958,18 @@ gdk_window_draw_rectangle (GdkDrawable *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
-      gdk_draw_rectangle (paint->pixmap, gc, filled,
+      SETUP_PAINT_GC_CLIP (gc);
+      gdk_draw_rectangle (pixmap_impl (paint->pixmap), gc, filled,
                           x - x_offset, y - y_offset, width, height);
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_rectangle (private->impl, gc, filled,
-                        x - x_offset, y - y_offset, width, height);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_rectangle (private->impl, gc, filled,
+                         x - x_offset, y - y_offset, width, height);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
 
   RESTORE_GC (gc);
 }
@@ -1464,14 +2994,20 @@ gdk_window_draw_arc (GdkDrawable *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
-      gdk_draw_arc (paint->pixmap, gc, filled,
+      SETUP_PAINT_GC_CLIP (gc);
+      gdk_draw_arc (pixmap_impl (paint->pixmap), gc, filled,
                    x - x_offset, y - y_offset,
                    width, height, angle1, angle2);
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_arc (private->impl, gc, filled,
-                  x - x_offset, y - y_offset,
-                  width, height, angle1, angle2);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_arc (private->impl, gc, filled,
+                   x - x_offset, y - y_offset,
+                   width, height, angle1, angle2);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
   RESTORE_GC (gc);
 }
 
@@ -1507,11 +3043,16 @@ gdk_window_draw_polygon (GdkDrawable *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
-      gdk_draw_polygon (paint->pixmap, gc, filled, new_points, npoints);
-
+      SETUP_PAINT_GC_CLIP (gc);
+      gdk_draw_polygon (pixmap_impl (paint->pixmap), gc, filled, new_points, npoints);
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_polygon (private->impl, gc, filled, new_points, npoints);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_polygon (private->impl, gc, filled, new_points, npoints);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
   
   if (new_points != points)
     g_free (new_points);
@@ -1537,13 +3078,19 @@ gdk_window_draw_text (GdkDrawable *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
-      gdk_draw_text (paint->pixmap, font, gc, 
+      SETUP_PAINT_GC_CLIP (gc);
+      gdk_draw_text (pixmap_impl (paint->pixmap), font, gc, 
                     x - x_offset, y - y_offset, text, text_length);
 
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_text (private->impl, font, gc,
-                   x - x_offset, y - y_offset, text, text_length);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_text (private->impl, font, gc,
+                    x - x_offset, y - y_offset, text, text_length);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
 
   RESTORE_GC (gc);
 }
@@ -1566,17 +3113,36 @@ gdk_window_draw_text_wc (GdkDrawable    *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
-      gdk_draw_text_wc (paint->pixmap, font, gc, 
+      SETUP_PAINT_GC_CLIP (gc);
+      gdk_draw_text_wc (pixmap_impl (paint->pixmap), font, gc, 
                        x - x_offset, y - y_offset, text, text_length);
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_text_wc (private->impl, font, gc,
-                      x - x_offset, y - y_offset, text, text_length);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_text_wc (private->impl, font, gc,
+                       x - x_offset, y - y_offset, text, text_length);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
   
   RESTORE_GC (gc);
 }
 
-static GdkDrawable*
+static GdkDrawable *
+gdk_window_get_source_drawable (GdkDrawable *drawable)
+{
+  GdkWindow *window = GDK_WINDOW (drawable);
+  GdkWindowObject *private;
+
+  private = (GdkWindowObject *) window;
+  if (GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable)
+    return GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable (private->impl);
+  
+  return drawable;
+}
+
+static GdkDrawable *
 gdk_window_get_composite_drawable (GdkDrawable *drawable,
                                    gint         x,
                                    gint         y,
@@ -1591,19 +3157,17 @@ gdk_window_get_composite_drawable (GdkDrawable *drawable,
   GdkRectangle rect;
   GdkGC *tmp_gc;
   gboolean overlap_buffer;
+  GdkDrawable *source;
+  GdkWindowObject *impl_window;
+  GdkWindowPaint *implicit_paint;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (GDK_WINDOW (drawable),
-                                                          composite_x_offset,
-                                                          composite_y_offset);
-  
-  if ((GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable))
-      || private->paint_stack == NULL)
-    {
-      /* No backing store */
-      return g_object_ref (drawable);
-    }
+  *composite_x_offset = -private->abs_x;
+  *composite_y_offset = -private->abs_y;
 
-  /* See if the buffered part is overlapping the part we want
+  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;
@@ -1612,14 +3176,14 @@ gdk_window_get_composite_drawable (GdkDrawable *drawable,
   rect.height = height;
 
   overlap_buffer = FALSE;
-  
+
   for (list = private->paint_stack; list != NULL; list = list->next)
     {
       GdkWindowPaint *paint = list->data;
       GdkOverlapType overlap;
-
+      
       overlap = gdk_region_rect_in (paint->region, &rect);
-
+      
       if (overlap == GDK_OVERLAP_RECTANGLE_IN)
        {
          *composite_x_offset = paint->x_offset;
@@ -1634,26 +3198,65 @@ gdk_window_get_composite_drawable (GdkDrawable *drawable,
        }
     }
 
-  if (!overlap_buffer)
-    return g_object_ref (drawable);
+  impl_window = gdk_window_get_impl_window (private);
+  implicit_paint = impl_window->implicit_paint;
+  if (implicit_paint)
+    {
+      GdkOverlapType overlap;
+
+      rect.x += private->abs_x;
+      rect.y += private->abs_y;
+      
+      overlap = gdk_region_rect_in (implicit_paint->region, &rect);
+      if (overlap == GDK_OVERLAP_RECTANGLE_IN)
+       {
+         *composite_x_offset = -private->abs_x + implicit_paint->x_offset;
+         *composite_y_offset = -private->abs_y + implicit_paint->y_offset;
+         
+         return g_object_ref (implicit_paint->pixmap);
+       }
+      else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
+       overlap_buffer = TRUE;
+    }
 
+  if (!overlap_buffer)
+    return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
+  
   tmp_pixmap = gdk_pixmap_new (drawable, width, height, -1);
   tmp_gc = _gdk_drawable_get_scratch_gc (tmp_pixmap, FALSE);
 
+  source = _gdk_drawable_get_source_drawable (drawable);
+  
   /* Copy the current window contents */
   gdk_draw_drawable (tmp_pixmap,
                      tmp_gc,
-                     private->impl,
+                     GDK_WINDOW_OBJECT (source)->impl,
                      x - *composite_x_offset,
                      y - *composite_y_offset,
                      0, 0,
                      width, height);
 
   /* paint the backing stores */
+  if (implicit_paint)
+    {
+      GdkWindowPaint *paint = list->data;
+      
+      gdk_gc_set_clip_region (tmp_gc, paint->region);
+      gdk_gc_set_clip_origin (tmp_gc, -x  - paint->x_offset, -y  - paint->y_offset);
+      
+      gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
+                        x - paint->x_offset,
+                        y - paint->y_offset,
+                        0, 0, width, height);
+    }
+  
   for (list = private->paint_stack; list != NULL; list = list->next)
     {
       GdkWindowPaint *paint = list->data;
 
+      if (paint->uses_implicit)
+       continue; /* We already copied this above */
+      
       gdk_gc_set_clip_region (tmp_gc, paint->region);
       gdk_gc_set_clip_origin (tmp_gc, -x, -y);
       
@@ -1662,7 +3265,7 @@ gdk_window_get_composite_drawable (GdkDrawable *drawable,
                         y - paint->y_offset,
                         0, 0, width, height);
     }
-
+  
   /* Reset clip region of the cached GdkGC */
   gdk_gc_set_clip_region (tmp_gc, NULL);
 
@@ -1679,7 +3282,7 @@ gdk_window_get_clip_region (GdkDrawable *drawable)
   GdkWindowObject *private = (GdkWindowObject *)drawable;
   GdkRegion *result;
 
-  result = gdk_drawable_get_clip_region (private->impl);
+  result = gdk_region_copy (private->clip_region);
 
   if (private->paint_stack)
     {
@@ -1706,8 +3309,8 @@ static GdkRegion*
 gdk_window_get_visible_region (GdkDrawable *drawable)
 {
   GdkWindowObject *private = (GdkWindowObject*) drawable;
-  
-  return gdk_drawable_get_visible_region (private->impl);
+
+  return gdk_region_copy (private->clip_region);
 }
 
 static void
@@ -1731,16 +3334,22 @@ gdk_window_draw_drawable (GdkDrawable *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
-      gdk_draw_drawable (paint->pixmap, gc,
+      SETUP_PAINT_GC_CLIP (gc);
+      gdk_draw_drawable (pixmap_impl (paint->pixmap), gc,
                          src, xsrc, ysrc,
                         xdest - x_offset, ydest - y_offset, width, height);
 
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_drawable (private->impl, gc,
-                       src, xsrc, ysrc,
-                       xdest - x_offset, ydest - y_offset,
-                       width, height);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_drawable (private->impl, gc,
+                        src, xsrc, ysrc,
+                        xdest - x_offset, ydest - y_offset,
+                        width, height);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
 
   RESTORE_GC (gc);
 }
@@ -1776,10 +3385,16 @@ gdk_window_draw_points (GdkDrawable *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
-      gdk_draw_points (paint->pixmap, gc, new_points, npoints);
+      SETUP_PAINT_GC_CLIP (gc);
+      gdk_draw_points (pixmap_impl (paint->pixmap), gc, new_points, npoints);
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_points (private->impl, gc, points, npoints);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_points (private->impl, gc, new_points, npoints);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
 
   if (new_points != points)
     g_free (new_points);
@@ -1820,10 +3435,16 @@ gdk_window_draw_segments (GdkDrawable *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
-      gdk_draw_segments (paint->pixmap, gc, new_segs, nsegs);
+      SETUP_PAINT_GC_CLIP (gc);
+      gdk_draw_segments (pixmap_impl (paint->pixmap), gc, new_segs, nsegs);
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_segments (private->impl, gc, new_segs, nsegs);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_segments (private->impl, gc, new_segs, nsegs);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
   
   if (new_segs != segs)
     g_free (new_segs);
@@ -1862,10 +3483,16 @@ gdk_window_draw_lines (GdkDrawable *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
-      gdk_draw_lines (paint->pixmap, gc, new_points, npoints);
+      SETUP_PAINT_GC_CLIP (gc);
+      gdk_draw_lines (pixmap_impl (paint->pixmap), gc, new_points, npoints);
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_lines (private->impl, gc, new_points, npoints);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_lines (private->impl, gc, new_points, npoints);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
 
   if (new_points != points)
     g_free (new_points);
@@ -1892,11 +3519,17 @@ gdk_window_draw_glyphs (GdkDrawable      *drawable,
     {
       GdkWindowPaint *paint = private->paint_stack->data;
 
-      gdk_draw_glyphs (paint->pixmap, gc, font, x - x_offset, y - y_offset, glyphs);
+      SETUP_PAINT_GC_CLIP (gc);
+      gdk_draw_glyphs (pixmap_impl (paint->pixmap), gc, font, x - x_offset, y - y_offset, glyphs);
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_glyphs (private->impl, gc, font,
-                     x - x_offset, y - y_offset, glyphs);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_glyphs (private->impl, gc, font,
+                      x - x_offset, y - y_offset, glyphs);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
 
   RESTORE_GC (gc);
 }
@@ -1947,10 +3580,16 @@ gdk_window_draw_glyphs_transformed (GdkDrawable      *drawable,
     {
       GdkWindowPaint *paint = private->paint_stack->data;
 
-      gdk_draw_glyphs_transformed (paint->pixmap, gc, matrix, font, x, y, glyphs);
+      SETUP_PAINT_GC_CLIP (gc);
+      gdk_draw_glyphs_transformed (pixmap_impl (paint->pixmap), gc, matrix, font, x, y, glyphs);
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_glyphs_transformed (private->impl, gc, matrix, font, x, y, glyphs);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_glyphs_transformed (private->impl, gc, matrix, font, x, y, glyphs);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
 
   RESTORE_GC (gc);
 }
@@ -2039,15 +3678,14 @@ setup_backing_rect_method (BackingRectMethod *method, GdkWindow *window, GdkWind
 }
 
 static void
-gdk_window_clear_backing_rect (GdkWindow *window,
-                              gint       x,
-                              gint       y,
-                              gint       width,
-                              gint       height)
+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;
@@ -2064,14 +3702,16 @@ gdk_window_clear_backing_rect (GdkWindow *window,
   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);
 
-      cairo_rectangle (method.cr, x, y, width, height);
-      cairo_clip (method.cr);
-
-      gdk_cairo_region (method.cr, paint->region);
+      gdk_cairo_region (method.cr, clip);
       cairo_fill (method.cr);
 
       cairo_destroy (method.cr);
@@ -2084,8 +3724,10 @@ gdk_window_clear_backing_rect (GdkWindow *window,
     {
       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);
+      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
@@ -2094,21 +3736,21 @@ gdk_window_clear_backing_rect (GdkWindow *window,
 #endif
     }
 
+  gdk_region_destroy (clip);
+  
 #if 0
   g_timer_destroy (timer);
 #endif
 }
 
 static void
-gdk_window_clear_backing_rect_redirect (GdkWindow *window,
-                                       gint       x,
-                                       gint       y,
-                                       gint       width,
-                                       gint       height)
+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;
@@ -2116,25 +3758,25 @@ gdk_window_clear_backing_rect_redirect (GdkWindow *window,
   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,
+                                                       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 and rect to pixmap coords */
+  /* Convert region to pixmap coords */
   gdk_region_offset (clip_region, x_offset, y_offset);
-  x += x_offset;
-  y += 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);
@@ -2143,9 +3785,6 @@ gdk_window_clear_backing_rect_redirect (GdkWindow *window,
     {
       g_assert (method.gc == NULL);
 
-      cairo_rectangle (method.cr, x, y, width, height);
-      cairo_clip (method.cr);
-
       gdk_cairo_region (method.cr, clip_region);
       cairo_fill (method.cr);
 
@@ -2155,8 +3794,11 @@ gdk_window_clear_backing_rect_redirect (GdkWindow *window,
     {
       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, x, y, width, height);
+      gdk_draw_rectangle (redirect->pixmap, method.gc, TRUE,
+                         clipbox.x, clipbox.y,
+                         clipbox.width, clipbox.height);
       g_object_unref (method.gc);
 
     }
@@ -2165,6 +3807,57 @@ gdk_window_clear_backing_rect_redirect (GdkWindow *window,
   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:
@@ -2185,6 +3878,60 @@ gdk_window_clear (GdkWindow *window)
                          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
@@ -2203,22 +3950,10 @@ gdk_window_clear_area (GdkWindow *window,
                       gint       width,
                       gint       height)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (private->paint_stack)
-    gdk_window_clear_backing_rect (window, x, y, width, height);
-  else
-    {
-      if (private->redirect)
-       gdk_window_clear_backing_rect_redirect (window, x, y, width, height);
-
-      GDK_WINDOW_IMPL_GET_IFACE (private->impl)->clear_area (window,
-                                                             x, y,
-                                                             width, height,
-                                                             FALSE);
-    }
+  gdk_window_clear_area_internal (window,
+                                 x, y,
+                                 width, height,
+                                 FALSE);
 }
 
 /**
@@ -2243,20 +3978,10 @@ gdk_window_clear_area_e (GdkWindow *window,
                         gint       width,
                         gint       height)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  if (private->paint_stack)
-    gdk_window_clear_backing_rect (window, x, y, width, height);
-
-  if (private->redirect)
-    gdk_window_clear_backing_rect_redirect (window, x, y, width, height);
-
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->clear_area (window,
-                                                         x, y,
-                                                         width, height,
-                                                         TRUE);
+  gdk_window_clear_area_internal (window,
+                                 x, y,
+                                 width, height,
+                                 TRUE);
 }
 
 static void
@@ -2280,15 +4005,21 @@ gdk_window_draw_image (GdkDrawable *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
-      gdk_draw_image (paint->pixmap, gc, image, xsrc, ysrc,
+      SETUP_PAINT_GC_CLIP (gc);
+      gdk_draw_image (pixmap_impl (paint->pixmap), gc, image, xsrc, ysrc,
                       xdest - x_offset, ydest - y_offset,
                       width, height);
 
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_image (private->impl, gc, image, xsrc, ysrc,
-                    xdest - x_offset, ydest - y_offset,
-                    width, height);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_image (private->impl, gc, image, xsrc, ysrc,
+                     xdest - x_offset, ydest - y_offset,
+                     width, height);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
 
   RESTORE_GC (gc);
 }
@@ -2311,45 +4042,37 @@ gdk_window_draw_pixbuf (GdkDrawable     *drawable,
 
   if (GDK_WINDOW_DESTROYED (drawable))
     return;
-  
-  if (gc)
+
+  /* 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);
+
+  /* Need block to make OFFSET_GC macro to work */
     {
       OFFSET_GC (gc);
   
       if (private->paint_stack)
        {
          GdkWindowPaint *paint = private->paint_stack->data;
-         gdk_draw_pixbuf (paint->pixmap, gc, pixbuf, src_x, src_y,
+         SETUP_PAINT_GC_CLIP (gc);
+         gdk_draw_pixbuf (pixmap_impl (paint->pixmap), gc, pixbuf, src_x, src_y,
                           dest_x - x_offset, dest_y - y_offset,
                           width, height,
                           dither, x_dither - x_offset, y_dither - y_offset);
+         RESTORE_PAINT_GC_CLIP (gc);
        }
       else
-       gdk_draw_pixbuf (private->impl, gc, pixbuf, src_x, src_y,
-                        dest_x - x_offset, dest_y - y_offset,
-                        width, height,
-                        dither, x_dither, y_dither);
-      
-      RESTORE_GC (gc);
-    }
-  else
-    {
-      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,
+         SETUP_DIRECT_GC_CLIP(gc);
+         gdk_draw_pixbuf (private->impl, gc, pixbuf, src_x, src_y,
                           dest_x - x_offset, dest_y - y_offset,
                           width, height,
-                           dither, x_dither - x_offset, y_dither - y_offset);
+                          dither, x_dither, y_dither);
+         RESTORE_DIRECT_GC_CLIP(gc);
        }
-      else
-       gdk_draw_pixbuf (private->impl, gc, pixbuf, src_x, src_y,
-                        dest_x - x_offset, dest_y - y_offset,
-                        width, height,
-                        dither, x_dither, y_dither);
+      
+      RESTORE_GC (gc);
     }
 }
 
@@ -2388,10 +4111,16 @@ gdk_window_draw_trapezoids (GdkDrawable   *drawable,
   if (private->paint_stack)
     {
       GdkWindowPaint *paint = private->paint_stack->data;
-      gdk_draw_trapezoids (paint->pixmap, gc, trapezoids, n_trapezoids);
+      SETUP_PAINT_GC_CLIP (gc);
+      gdk_draw_trapezoids (pixmap_impl (paint->pixmap), gc, trapezoids, n_trapezoids);
+      RESTORE_PAINT_GC_CLIP (gc);
     }
   else
-    gdk_draw_trapezoids (private->impl, gc, trapezoids, n_trapezoids);
+    {
+      SETUP_DIRECT_GC_CLIP(gc);
+      gdk_draw_trapezoids (private->impl, gc, trapezoids, n_trapezoids);
+      RESTORE_DIRECT_GC_CLIP(gc);
+    }
   
   g_free (new_trapezoids);
 
@@ -2403,10 +4132,12 @@ gdk_window_real_get_size (GdkDrawable *drawable,
                           gint *width,
                           gint *height)
 {
-  g_return_if_fail (GDK_IS_WINDOW (drawable));
+  GdkWindowObject *private = (GdkWindowObject *)drawable;
 
-  gdk_drawable_get_size (GDK_WINDOW_OBJECT (drawable)->impl,
-                         width, height);
+  if (width)
+    *width = private->width;
+  if (height)
+    *height = private->height;
 }
 
 static GdkVisual*
@@ -2438,12 +4169,21 @@ 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_set_has_native ((GdkWindow *)drawable, TRUE);
   
-  gdk_drawable_set_colormap (((GdkWindowObject*)drawable)->impl, cmap);
+  gdk_drawable_set_colormap (private->impl, cmap);
 }
 
 static GdkColormap*
@@ -2478,9 +4218,10 @@ gdk_window_copy_to_image (GdkDrawable     *drawable,
   /* If we're here, a composite image was not necessary, so
    * we can ignore the paint stack.
    */
-  
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (drawable,
-                                                          &x_offset, &y_offset);
+
+  /* TODO: Is this right? */
+  x_offset = 0;
+  y_offset = 0; 
   
   return gdk_drawable_copy_to_image (private->impl,
                                     image,
@@ -2490,6 +4231,24 @@ gdk_window_copy_to_image (GdkDrawable     *drawable,
                                     width, height);
 }
 
+static void
+gdk_window_cairo_surface_destroy (void *data)
+{
+  GdkWindowObject *private = (GdkWindowObject*) data;
+
+  private->cairo_surface = NULL;
+}
+
+static cairo_surface_t *
+gdk_window_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)
 {
@@ -2504,27 +4263,198 @@ gdk_window_ref_cairo_surface (GdkDrawable *drawable)
       cairo_surface_reference (surface);
     }
   else
-    surface = _gdk_drawable_ref_cairo_surface (private->impl);
+    {
+      
+      /* This will be drawing directly to the window, so flush implicit paint */
+      gdk_window_flush ((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 gboolean
-gdk_window_update_idle (gpointer data)
+static inline gboolean
+gdk_window_is_ancestor (GdkWindow *window,
+                        GdkWindow *ancestor)
 {
-  gdk_window_process_all_updates ();
-  
+  while (window)
+    {
+      GdkWindow *parent = (GdkWindow*) ((GdkWindowObject*) window)->parent;
+
+      if (parent == ancestor)
+        return TRUE;
+
+      window = parent;
+    }
+
   return FALSE;
 }
 
-static gboolean
-gdk_window_is_toplevel_frozen (GdkWindow *window)
+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;
 
@@ -2548,11 +4478,96 @@ gdk_window_schedule_update (GdkWindow *window)
     }
 }
 
+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.
@@ -2563,62 +4578,99 @@ gdk_window_process_updates_internal (GdkWindow *window)
       GdkRegion *update_area = private->update_area;
       private->update_area = NULL;
       
-      if (_gdk_event_func && gdk_window_is_viewable (window))
+      if (_gdk_event_func && gdk_window_is_viewable (window)  &&
+         private->window_type != GDK_WINDOW_FOREIGN)
        {
          GdkRectangle window_rect;
          GdkRegion *expose_region;
          GdkRegion *window_region;
-          gint width, height;
+         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_windowing_window_queue_antiexpose (window, update_area);
 
+         save_region = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->queue_antiexpose (window, update_area);
          if (save_region)
            expose_region = gdk_region_copy (update_area);
          else
            expose_region = update_area;
          
-          gdk_drawable_get_size (GDK_DRAWABLE (private), &width, &height);
-
          window_rect.x = 0;
          window_rect.y = 0;
-         window_rect.width = width;
-         window_rect.height = height;
+         window_rect.width = private->width;
+         window_rect.height = private->height;
 
          window_region = gdk_region_rectangle (&window_rect);
          gdk_region_intersect (expose_region,
                                window_region);
          gdk_region_destroy (window_region);
-         
-         if (!gdk_region_empty (expose_region) &&
-             (private->event_mask & GDK_EXPOSURE_MASK))
+
+
+         /* No need to do any moves that will end up over the update area */
+         if (private->outstanding_moves)
            {
-             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);
+             GdkWindowRegionMove *move;
+             GdkRegion *remove;
+             GList *l, *prev;
              
-             (*_gdk_event_func) (&event, _gdk_event_data);
-             
-             g_object_unref (window);
+             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
@@ -2655,6 +4707,12 @@ 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);
@@ -2662,6 +4720,8 @@ gdk_window_process_all_updates (void)
   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)
@@ -2672,7 +4732,7 @@ gdk_window_process_all_updates (void)
         {
          if (private->update_freeze_count ||
              gdk_window_is_toplevel_frozen (tmp_list->data))
-           update_windows = g_slist_prepend (update_windows, private);
+           gdk_window_add_update_window ((GdkWindow *) private);
          else
            gdk_window_process_updates_internal (tmp_list->data);
        }
@@ -2684,6 +4744,10 @@ gdk_window_process_all_updates (void)
   g_slist_free (old_update_windows);
 
   flush_all_displays ();
+
+  _gdk_windowing_after_process_all_updates ();
+
+  in_process_all_updates = FALSE;
 }
 
 /**
@@ -2706,35 +4770,28 @@ gdk_window_process_updates (GdkWindow *window,
                            gboolean   update_children)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *impl_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 &&
+  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 (window);
-      update_windows = g_slist_remove (update_windows, window);
+      gdk_window_process_updates_internal ((GdkWindow *)impl_window);
+      gdk_window_remove_update_window ((GdkWindow *)impl_window);
     }
 
   if (update_children)
     {
-      GList *tmp_list = private->children;
-      while (tmp_list)
-       {
-         gdk_window_process_updates (tmp_list->data, TRUE);
-         tmp_list = tmp_list->next;
-       }
+      /* process updates in reverse stacking order so composition or
+       * painting over achieves the desired effect for offscreen windows
+       */
+      GList *node;
+      for (node = g_list_last (private->children); node; node = node->prev)
+        gdk_window_process_updates (node->data, TRUE);
     }
 }
 
@@ -2838,6 +4895,7 @@ gdk_window_invalidate_maybe_recurse (GdkWindow       *window,
                                     gpointer   user_data)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *impl_window;
   GdkRegion *visible_region;
   GList *tmp_list;
 
@@ -2849,28 +4907,7 @@ gdk_window_invalidate_maybe_recurse (GdkWindow       *window,
   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;
-    }
-
-  /* windows that a redirection has ben setup for need to be considered
-   * fully visible, in order to avoid missing redirected paint ops
-   * anywhere in the window area.
-   */
-  if (private->redirect && private->redirect->redirected == private)
-    {
-      GdkRectangle visible_rect = { 0, 0, 0, 0 };
-      gdk_drawable_get_size (GDK_DRAWABLE (window), &visible_rect.width, &visible_rect.height);
-      visible_region = gdk_region_rectangle (&visible_rect);
-    }
-  else
-    visible_region = gdk_drawable_get_visible_region (window);
+  visible_region = gdk_drawable_get_visible_region (window);
   gdk_region_intersect (visible_region, region);
 
   tmp_list = private->children;
@@ -2882,17 +4919,17 @@ gdk_window_invalidate_maybe_recurse (GdkWindow       *window,
        {
          GdkRegion *child_region;
          GdkRectangle child_rect;
-         
-         gdk_window_get_position ((GdkWindow *)child,
-                                  &child_rect.x, &child_rect.y);
-         gdk_drawable_get_size ((GdkDrawable *)child,
-                                &child_rect.width, &child_rect.height);
 
+         child_rect.x = child->x;
+         child_rect.y = child->y;
+         child_rect.width = child->width;
+         child_rect.height = child->height;
          child_region = gdk_region_rectangle (&child_rect);
          
          /* remove child area from the invalid area of the parent */
          if (GDK_WINDOW_IS_MAPPED (child) && !child->shaped &&
-             !child->composited)
+             !child->composited &&
+              !gdk_window_is_offscreen (child))
            gdk_region_subtract (visible_region, child_region);
          
          if (child_func && (*child_func) ((GdkWindow *)child, user_data))
@@ -2914,22 +4951,30 @@ gdk_window_invalidate_maybe_recurse (GdkWindow       *window,
 
       tmp_list = tmp_list->next;
     }
+
+  impl_window = gdk_window_get_impl_window (private);
   
-  if (!gdk_region_empty (visible_region))
+  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);
-
-      if (private->update_area)
+      
+      /* Convert to impl coords */
+      gdk_region_offset (visible_region, private->abs_x, private->abs_y);
+      if (impl_window->update_area)
        {
-         gdk_region_union (private->update_area, visible_region);
+         gdk_region_union (impl_window->update_area, visible_region);
        }
       else
        {
-         update_windows = g_slist_prepend (update_windows, window);
-         private->update_area = gdk_region_copy (visible_region);
+         gdk_window_add_update_window ((GdkWindow *)impl_window);
+         impl_window->update_area = gdk_region_copy (visible_region);
          
-         gdk_window_schedule_update (window);
+         gdk_window_schedule_update ((GdkWindow *)impl_window);
        }
     }
   
@@ -2978,6 +5023,38 @@ gdk_window_invalidate_region (GdkWindow       *window,
                                       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
@@ -2995,18 +5072,43 @@ GdkRegion *
 gdk_window_get_update_area (GdkWindow *window)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *impl_window;
   GdkRegion *tmp_region;
 
   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 
-  if (private->update_area)
+  impl_window = gdk_window_get_impl_window (private);
+  
+  if (impl_window->update_area)
     {
-      tmp_region = private->update_area;
-      private->update_area = NULL;
+      tmp_region = gdk_region_copy (private->clip_region_with_children);
+      /* Convert to impl coords */
+      gdk_region_offset (tmp_region, private->abs_x, private->abs_y);
+      gdk_region_intersect (tmp_region, impl_window->update_area);
 
-      update_windows = g_slist_remove (update_windows, window);
-      
-      return tmp_region;
+      if (gdk_region_empty (tmp_region))
+       {
+         gdk_region_destroy (tmp_region);
+         return NULL;
+       }
+      else
+       {
+         gdk_region_subtract (impl_window->update_area, tmp_region);
+
+         if (gdk_region_empty (impl_window->update_area) &&
+             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;
@@ -3028,8 +5130,8 @@ _gdk_window_clear_update_area (GdkWindow *window)
 
   if (private->update_area)
     {
-      update_windows = g_slist_remove (update_windows, window);
-      
+      gdk_window_remove_update_window (window);
+
       gdk_region_destroy (private->update_area);
       private->update_area = NULL;
     }
@@ -3049,10 +5151,12 @@ void
 gdk_window_freeze_updates (GdkWindow *window)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *impl_window;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  private->update_freeze_count++;
+  impl_window = gdk_window_get_impl_window (private);
+  impl_window->update_freeze_count++;
 }
 
 /**
@@ -3065,12 +5169,16 @@ void
 gdk_window_thaw_updates (GdkWindow *window)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
+  GdkWindowObject *impl_window;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
-  g_return_if_fail (private->update_freeze_count > 0);
 
-  if (--private->update_freeze_count == 0)
-    gdk_window_schedule_update (window);
+  impl_window = gdk_window_get_impl_window (private);
+
+  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));
 }
 
 /**
@@ -3339,6 +5447,8 @@ gdk_window_get_pointer (GdkWindow   *window,
   if (mask)
     *mask = tmp_mask;
 
+  _gdk_display_enable_motion_hints (display);
+  
   return child;
 }
 
@@ -3398,61 +5508,106 @@ gdk_window_foreign_new (GdkNativeWindow anid)
   return gdk_window_foreign_new_for_display (gdk_display_get_default (), anid);
 }
 
-/**
- * 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)
+static void
+get_all_native_children (GdkWindowObject *private,
+                        GList **native)
 {
-  GdkWindowObject *private;
-
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
-    return;
+  GdkWindowObject *child;
+  GList *l;
+  
+  for (l = private->children; l != NULL; l = l->next)
+    {
+      child = l->data;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show (window, FALSE);
+      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);
+       }
+      
+    }
 }
 
-/**
- * gdk_window_raise:
- * @window: a #GdkWindow
- *
- * Raises @window to the top of the Z-order (stacking order), so that
- * other windows with the same parent window appear below @window.
- * This is true whether or not the windows are visible.
- *
- * If @window is a toplevel, the window manager may choose to deny the
- * request to move the window in the Z-order, gdk_window_raise() only
- * requests the restack, does not guarantee it.
- */
-void
-gdk_window_raise (GdkWindow *window)
+static void
+show_all_visible_impls (GdkWindowObject *private)
+{
+  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);
+    }
+  
+  if (gdk_window_has_impl (private))
+    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show ((GdkWindow *)private);
+}
+
+static void
+gdk_window_show_internal (GdkWindow *window, gboolean raise)
 {
   GdkWindowObject *private;
+  gboolean was_mapped;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
@@ -3460,31 +5615,186 @@ gdk_window_raise (GdkWindow *window)
   if (private->destroyed)
     return;
 
-  /* Keep children in (reverse) stacking order */
-  gdk_window_raise_internal (window);
-
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
-}
-
-static void
-gdk_window_lower_internal (GdkWindow *window)
-{
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkWindowObject *parent = private->parent;
+  was_mapped = GDK_WINDOW_IS_MAPPED (window);
+  
+  if (raise)
+    /* Keep children in (reverse) stacking order */
+    gdk_window_raise_internal (window);
 
-  if (parent)
+  if (gdk_window_has_impl (private))
     {
-      parent->children = g_list_remove (parent->children, window);
-      parent->children = g_list_append (parent->children, window);
+      if (!was_mapped)
+       gdk_synthesize_window_state (window,
+                                    GDK_WINDOW_STATE_WITHDRAWN,
+                                    0);
+    }
+  else
+    {
+      private->state = 0;
     }
-}
 
-/**
- * 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.
+  if (gdk_window_is_viewable (window))
+    show_all_visible_impls (private);
+  
+  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 (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
+    {
+      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
@@ -3508,7 +5818,10 @@ gdk_window_lower (GdkWindow *window)
   /* Keep children in (reverse) stacking order */
   gdk_window_lower_internal (window);
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->lower (window);
+  recompute_visible_regions (private, TRUE, FALSE);
+  
+  _gdk_syntesize_crossing_events_for_geometry_change (window);
+  gdk_window_invalidate_in_parent (private);
 }
 
 /**
@@ -3528,20 +5841,28 @@ gdk_window_lower (GdkWindow *window)
 void
 gdk_window_show (GdkWindow *window)
 {
-  GdkWindowObject *private;
-
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
-    return;
-
-  /* Keep children in (reverse) stacking order */
-  gdk_window_raise_internal (window);
+  gdk_window_show_internal (window, TRUE);
+}
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show (window, TRUE);
+static void
+hide_all_visible_impls (GdkWindowObject *private)
+{
+  GdkWindowObject *child;
+  GList *l;
+  
+  for (l = private->children; l != NULL; l = l->next)
+    {
+      child = l->data;
+      
+      if (GDK_WINDOW_IS_MAPPED (child))
+       hide_all_visible_impls (child);
+    }
+  
+  if (gdk_window_has_impl (private))
+    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->hide ((GdkWindow *)private);
 }
 
+
 /**
  * gdk_window_hide:
  * @window: a #GdkWindow
@@ -3555,6 +5876,7 @@ void
 gdk_window_hide (GdkWindow *window)
 {
   GdkWindowObject *private;
+  gboolean was_mapped, was_viewable;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
@@ -3562,7 +5884,64 @@ gdk_window_hide (GdkWindow *window)
   if (private->destroyed)
     return;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->hide (window);
+  was_mapped = GDK_WINDOW_IS_MAPPED (private);
+  was_viewable = gdk_window_is_viewable (window);
+  
+  if (gdk_window_has_impl (private))
+    {
+
+      if (GDK_WINDOW_IS_MAPPED (window))
+        gdk_synthesize_window_state (window,
+                                     0,
+                                     GDK_WINDOW_STATE_WITHDRAWN);
+    }
+  else if (was_mapped)
+    {
+      GdkDisplay *display;
+
+      /* 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)
+       {
+         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 (was_viewable)
+    hide_all_visible_impls (private);
+  
+  recompute_visible_regions (private, TRUE, FALSE);
+  
+  if (was_mapped)
+    {
+      if (private->event_mask & GDK_STRUCTURE_MASK)
+       _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
+      
+      if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+       _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
+      
+      _gdk_syntesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
+    }
+  
+  /* Invalidate the rect */
+  gdk_window_invalidate_in_parent (private);
 }
 
 /**
@@ -3577,6 +5956,7 @@ void
 gdk_window_withdraw (GdkWindow *window)
 {
   GdkWindowObject *private;
+  gboolean was_mapped;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
@@ -3584,7 +5964,25 @@ gdk_window_withdraw (GdkWindow *window)
   if (private->destroyed)
     return;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->withdraw (window);
+  was_mapped = GDK_WINDOW_IS_MAPPED (private);
+  
+  if (gdk_window_has_impl (private))
+    {
+      GDK_WINDOW_IMPL_GET_IFACE (private->impl)->withdraw (window);
+      
+      if (was_mapped)
+       {
+         if (private->event_mask & GDK_STRUCTURE_MASK)
+           _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
+         
+         if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
+           _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
+         
+         _gdk_syntesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
+       }
+      
+      recompute_visible_regions (private, TRUE, FALSE);
+    }
 }
 
 /**
@@ -3602,6 +6000,8 @@ gdk_window_set_events (GdkWindow       *window,
                       GdkEventMask     event_mask)
 {
   GdkWindowObject *private;
+  GdkDisplay *display;
+  
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
@@ -3609,7 +6009,18 @@ gdk_window_set_events (GdkWindow       *window,
   if (private->destroyed)
     return;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_events (window, event_mask);
+  /* 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));
+  
 }
 
 /**
@@ -3631,106 +6042,397 @@ gdk_window_get_events (GdkWindow *window)
   if (private->destroyed)
     return 0;
 
-  return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_events (window);
+  return private->event_mask;
 }
 
-/**
- * gdk_window_move:
- * @window: a #GdkWindow
- * @x: X coordinate relative to window's parent
- * @y: Y coordinate relative to window's parent
- *
- * Repositions a window relative to its parent window.
- * For toplevel windows, window managers may ignore or modify the move;
- * you should probably use gtk_window_move() on a #GtkWindow widget
- * anyway, instead of using GDK functions. For child windows,
- * the move will reliably succeed.
- *
- * If you're also planning to resize the window, use gdk_window_move_resize()
- * to both move and resize simultaneously, for a nicer visual effect.
- **/
-void
-gdk_window_move (GdkWindow *window,
-                gint       x,
-                gint       y)
+static void
+gdk_window_move_resize_toplevel (GdkWindow *window,
+                                gboolean   with_move,
+                                gint       x,
+                                gint       y,
+                                gint       width,
+                                gint       height)
 {
   GdkWindowObject *private;
-
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  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;
 
   private = (GdkWindowObject *) window;
-  if (private->destroyed)
-    return;
-
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (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)
-{
-  GdkWindowObject *private;
-
-  g_return_if_fail (GDK_IS_WINDOW (window));
 
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
-    return;
+  expose = FALSE;
+  old_region = NULL;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, FALSE, 0, 0, width, height);
-}
+  impl_window = gdk_window_get_impl_window (private);
 
+  old_x = private->x;
+  old_y = private->y;
 
-/**
- * gdk_window_move_resize:
- * @window: a #GdkWindow
- * @x: new X position relative to window's parent
- * @y: new Y position relative to window's parent
- * @width: new width
- * @height: new height
- *
- * Equivalent to calling gdk_window_move() and gdk_window_resize(),
- * except that both operations are performed at once, avoiding strange
- * visual effects. (i.e. the user may be able to see the window first
- * move, then resize, if you don't use gdk_window_move_resize().)
- **/
-void
-gdk_window_move_resize (GdkWindow *window,
-                       gint       x,
-                       gint       y,
-                       gint       width,
-                       gint       height)
-{
-  GdkWindowObject *private;
+  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);
+    }
+  
+  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, with_move, x, y, width, height);
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  dx = private->x - old_x;
+  dy = private->y - old_y;
+  
+  old_abs_x = private->abs_x;
+  old_abs_y = private->abs_y;
 
-  private = (GdkWindowObject *) window;
-  if (private->destroyed)
-    return;
+  /* Avoid recomputing for pure toplevel moves, for performance reasons */
+  if (is_resize)
+    recompute_visible_regions (private, TRUE, FALSE);
+  
+  if (expose)
+    {
+      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);
+    }
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, TRUE, x, y, width, height);
+  _gdk_syntesize_crossing_events_for_geometry_change (window);
 }
 
 
-/**
- * gdk_window_scroll:
+static void
+move_native_children (GdkWindowObject *private)
+{
+  GList *l;
+  GdkWindowObject *child;
+  
+  for (l = private->children; l; l = l->next)
+    {
+      child = l->data;
+      
+      if (child->impl != private->impl)
+       GDK_WINDOW_IMPL_GET_IFACE (child->impl)->move_resize ((GdkWindow *)child, TRUE, child->x, child->y, child->width, child->height);
+      else
+       move_native_children  (child);
+    }
+}
+
+static gboolean
+collect_native_child_region_helper (GdkWindowObject *window,
+                                   GdkWindow *impl,
+                                   GdkRegion **region,
+                                   int x_offset,
+                                   int y_offset)
+{
+  GdkWindowObject *child;
+  GdkRegion *tmp;
+  GList *l;
+  
+  for (l = window->children; l != NULL; l = l->next)
+    {
+      child = l->data;
+
+      if (child->impl != impl)
+       {
+         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);
+    }
+  
+  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);
+  
+  return region;
+}
+
+
+static void
+gdk_window_move_resize_internal (GdkWindow *window,
+                                gboolean   with_move,
+                                gint       x,
+                                gint       y,
+                                gint       width,
+                                gint       height)
+{
+  GdkWindowObject *private;
+  GdkRegion *old_region, *new_region, *copy_area;
+  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;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *) window;
+  if (private->destroyed)
+    return;
+
+  if (private->parent == NULL ||
+      GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
+    {
+      gdk_window_move_resize_toplevel (window, with_move, x, y, width, height);
+      return;
+    }
+
+  /* Handle child windows */
+  
+  expose = FALSE;
+  old_region = NULL;
+
+  impl_window = gdk_window_get_impl_window (private);
+
+  old_x = private->x;
+  old_y = private->y;
+
+  if (GDK_WINDOW_IS_MAPPED (window) &&
+      !private->input_only)
+    {
+      expose = TRUE;
+      
+      old_region = gdk_region_copy (private->clip_region);
+      /* Adjust region to parent window coords */
+      gdk_region_offset (old_region, private->x, private->y);
+    }
+
+  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);
+    }
+  /* 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;
+    }
+  
+  dx = private->x - old_x;
+  dy = private->y - old_y;
+  
+  old_abs_x = private->abs_x;
+  old_abs_y = private->abs_y;
+
+  recompute_visible_regions (private, TRUE, FALSE);
+
+  new_native_child_region = NULL;
+  if (old_native_child_region)
+    {
+      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)
+       {
+         /* 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);
+       }
+      gdk_region_offset (old_region, dx, dy);
+
+      gdk_region_intersect (copy_area, old_region);
+
+      if (new_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_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 (old_native_child_region)
+    {
+      gdk_region_destroy (old_native_child_region);
+      gdk_region_destroy (new_native_child_region);
+    }
+  
+  _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
+
+
+
+/**
+ * gdk_window_move:
+ * @window: a #GdkWindow
+ * @x: X coordinate relative to window's parent
+ * @y: Y coordinate relative to window's parent
+ *
+ * Repositions a window relative to its parent window.
+ * For toplevel windows, window managers may ignore or modify the move;
+ * you should probably use gtk_window_move() on a #GtkWindow widget
+ * anyway, instead of using GDK functions. For child windows,
+ * the move will reliably succeed.
+ *
+ * If you're also planning to resize the window, use gdk_window_move_resize()
+ * to both move and resize simultaneously, for a nicer visual effect.
+ **/
+void
+gdk_window_move (GdkWindow *window,
+                gint       x,
+                gint       y)
+{
+  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
@@ -3753,6 +6455,10 @@ gdk_window_scroll (GdkWindow *window,
                   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));
 
@@ -3762,7 +6468,83 @@ gdk_window_scroll (GdkWindow *window,
   if (private->destroyed)
     return;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->scroll (window, dx, dy);
+  old_native_child_region = collect_native_child_region (private, FALSE);
+  if (old_native_child_region)
+    {
+      /* 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);
+    }
+
+  
+  /* First move all child windows, without causing invalidation */
+  
+  tmp_list = private->children;
+  while (tmp_list)
+    {
+      GdkWindow *child = GDK_WINDOW (tmp_list->data);
+      GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
+      
+      /* Just update the positions, the bits will move with the copy */
+      child_obj->x += dx;
+      child_obj->y += dy;
+      
+      tmp_list = tmp_list->next;
+    }
+
+  recompute_visible_regions (private, FALSE, TRUE);
+
+  new_native_child_region = NULL;
+  if (old_native_child_region)
+    new_native_child_region = collect_native_child_region (private, FALSE);
+  
+  move_native_children (private);
+  
+  /* Then copy the actual bits of the window w/ child windows */
+  
+  impl_window = gdk_window_get_impl_window (private);
+
+  /* Calculate the area that can be gotten by copying the old area */
+  copy_area = gdk_region_copy (private->clip_region);
+  if (old_native_child_region)
+    {
+      /* 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);
+    }
+  gdk_region_offset (copy_area, dx, dy);
+  gdk_region_intersect (copy_area, private->clip_region);
+
+  /* And the rest need to be invalidated */
+  noncopy_area = gdk_region_copy (private->clip_region);
+  gdk_region_subtract (noncopy_area, copy_area);
+
+  /* convert from window coords to impl */
+  gdk_region_offset (copy_area, private->abs_x, private->abs_y);
+
+  move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
+   
+  /* Invalidate not copied regions */
+  gdk_window_invalidate_region (window, noncopy_area, TRUE);
+
+  gdk_region_destroy (noncopy_area);
+
+  if (old_native_child_region)
+    {
+      gdk_region_destroy (old_native_child_region);
+      gdk_region_destroy (new_native_child_region);
+    }
+  
+  _gdk_syntesize_crossing_events_for_geometry_change (window);
 }
 
 /**
@@ -3787,6 +6569,9 @@ gdk_window_move_region (GdkWindow       *window,
                        gint             dy)
 {
   GdkWindowObject *private = (GdkWindowObject *) window;
+  GdkWindowObject *impl_window;
+  GdkRegion *nocopy_area;
+  GdkRegion *copy_area;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (region != NULL);
@@ -3797,7 +6582,27 @@ gdk_window_move_region (GdkWindow       *window,
   if (private->destroyed)
     return;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_region (window, region, dx, dy);
+  impl_window = gdk_window_get_impl_window (private);
+  
+  /* compute source regions */
+  copy_area = gdk_region_copy (region);
+  gdk_region_intersect (copy_area, private->clip_region_with_children);
+
+  /* compute destination regions */
+  gdk_region_offset (copy_area, dx, dy);
+  gdk_region_intersect (copy_area, private->clip_region_with_children);
+
+  /* invalidate parts of the region not covered by the copy */
+  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);
+  
+  move_region_on_impl (impl_window, copy_area, dx, dy); /* Takes ownership of copy_area */
 }
 
 /**
@@ -3820,12 +6625,26 @@ gdk_window_set_background (GdkWindow      *window,
                           const GdkColor *color)
 {
   GdkWindowObject *private;
+  GdkColormap *colormap = gdk_drawable_get_colormap (window);
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
   private = (GdkWindowObject *) window;
+  
+  private->bg_color = *color;
+  gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
+
+  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;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, color);
+  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);
 }
 
 /**
@@ -3867,7 +6686,56 @@ gdk_window_set_back_pixmap (GdkWindow *window,
 
   private = (GdkWindowObject *) window;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, pixmap, parent_relative);
+  if (pixmap && !gdk_drawable_get_colormap (pixmap))
+    {
+      g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
+      return;
+    }
+  
+  if (private->bg_pixmap &&
+      private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+      private->bg_pixmap != GDK_NO_BG)
+    g_object_unref (private->bg_pixmap);
+
+  if (parent_relative)
+    private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
+  else if (pixmap)
+    private->bg_pixmap = g_object_ref (pixmap);
+  else
+    private->bg_pixmap = GDK_NO_BG;
+  
+  if (!GDK_WINDOW_DESTROYED (window) &&
+      gdk_window_has_impl (private) &&
+      !private->input_only)
+    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, private->bg_pixmap);
+}
+
+static void
+update_cursor (GdkDisplay *display)
+{
+  GdkWindowObject *pointer_window, *cursor_window;
+  GdkPointerGrabInfo *grab;
+  
+  pointer_window = (GdkWindowObject *)display->pointer_info.window_under_pointer;
+  
+  cursor_window = pointer_window;
+  while (cursor_window->cursor == NULL &&
+        cursor_window->parent != NULL &&
+        cursor_window->parent->window_type != GDK_WINDOW_ROOT)
+    cursor_window = 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_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. */
+  GDK_WINDOW_IMPL_GET_IFACE (pointer_window->impl)->set_cursor
+      (gdk_window_get_toplevel ((GdkWindow *)pointer_window),
+       cursor_window->cursor);
 }
 
 /**
@@ -3886,12 +6754,27 @@ gdk_window_set_cursor (GdkWindow *window,
                       GdkCursor *cursor)
 {
   GdkWindowObject *private;
+  GdkDisplay *display;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
   private = (GdkWindowObject *) window;
+  display = gdk_drawable_get_display (window);
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_cursor (window, cursor);
+  if (private->cursor)
+    {
+      gdk_cursor_unref (private->cursor);
+      private->cursor = NULL;
+    }
+
+  if (!GDK_WINDOW_DESTROYED (window))
+    {
+      if (cursor)
+       private->cursor = gdk_cursor_ref (cursor);
+
+      if (is_parent_of (window, display->pointer_info.window_under_pointer))
+       update_cursor (display);
+    }
 }
 
 /**
@@ -3950,9 +6833,23 @@ gdk_window_get_geometry (GdkWindow *window,
 
   if (!GDK_WINDOW_DESTROYED (window))
     {
-      GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_geometry (window, x, y,
-                                                              width, height,
-                                                               depth);
+      if (gdk_window_has_impl (private))
+       GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_geometry (window, x, y,
+                                                                width, height,
+                                                                depth);
+      else
+       {
+         if (x)
+           *x = private->x;
+         if (y)
+           *y = private->y;
+         if (width)
+           *width = private->width;
+         if (height)
+           *height = private->height;
+         if (depth)
+           *depth = private->depth;
+       }
     }
 }
 
@@ -3979,27 +6876,77 @@ gdk_window_get_origin (GdkWindow *window,
   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
 
   private = (GdkWindowObject *) window;
+  
+  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_origin (window, x, y);
 
-  return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_origin (window, x, y);
+  if (x)
+    *x += private->abs_x;
+  if (y)
+    *y += private->abs_y;
+  
+  return TRUE;
 }
 
+
 /**
- * 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
+ * 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;
+  gboolean return_val = FALSE;
+  gint tx = 0;
+  gint ty = 0;
+
+  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+
+  private = (GdkWindowObject *) window;
+  
+  if (!GDK_WINDOW_DESTROYED (window))
+    {
+      return_val = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_deskrelative_origin (window, &tx, &ty);
+      
+      if (x)
+       *x = tx + private->abs_x;
+      if (y)
+       *y = ty + private->abs_y;
+    }
+  
+  return return_val;
+}
+
+/**
+ * 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.
@@ -4013,12 +6960,23 @@ gdk_window_shape_combine_mask (GdkWindow *window,
                                gint       y)
 {
   GdkWindowObject *private;
+  GdkRegion *region;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
   private = (GdkWindowObject *) window;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_mask (window, mask, x, y);
+  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);
 }
 
 /**
@@ -4051,12 +7009,88 @@ gdk_window_shape_combine_region (GdkWindow       *window,
                                  gint             offset_y)
 {
   GdkWindowObject *private;
+  GdkRegion *old_region, *new_region, *diff;
 
   g_return_if_fail (GDK_IS_WINDOW (window));
 
   private = (GdkWindowObject *) window;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region (window, shape_region, offset_x, offset_y);
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
+  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)
+    {
+      private->shape = gdk_region_copy (shape_region);
+      gdk_region_offset (private->shape, offset_x, offset_y);      
+    }
+  else
+    private->shape = NULL;
+  
+  recompute_visible_regions (private, TRUE, FALSE);
+
+  if (old_region)
+    {
+      new_region = gdk_region_copy (private->clip_region);
+
+      /* New area in the window, needs invalidation */
+      diff = gdk_region_copy (new_region);
+      gdk_region_subtract (diff, old_region);
+
+      gdk_window_invalidate_region (window, diff, TRUE);
+
+      gdk_region_destroy (diff);
+
+      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);
+         
+         /* 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);
+       }
+
+      gdk_region_destroy (new_region);
+      gdk_region_destroy (old_region);
+    }
+}
+
+static void
+do_child_shapes (GdkWindow *window,
+                gboolean merge)
+{
+  GdkWindowObject *private;
+  GdkRectangle r;
+  GdkRegion *region;
+
+  private = (GdkWindowObject *) window;
+  
+  r.x = 0;
+  r.y = 0;
+  r.width = private->width;
+  r.height = private->height;
+  
+  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);
 }
 
 /**
@@ -4071,13 +7105,9 @@ gdk_window_shape_combine_region (GdkWindow       *window,
 void
 gdk_window_set_child_shapes (GdkWindow *window)
 {
-  GdkWindowObject *private;
-
   g_return_if_fail (GDK_IS_WINDOW (window));
 
-  private = (GdkWindowObject *) window;
-
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_child_shapes (window);
+  do_child_shapes (window, FALSE);
 }
 
 /**
@@ -4095,6 +7125,94 @@ gdk_window_set_child_shapes (GdkWindow *window)
  */
 void
 gdk_window_merge_child_shapes (GdkWindow *window)
+{
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  do_child_shapes (window, TRUE);
+}
+
+/**
+ * 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)
+{
+  GdkWindowObject *private;
+  GdkRegion *region;
+
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  private = (GdkWindowObject *) window;
+
+  if (mask)
+    region = _gdk_windowing_get_shape_for_mask (mask);
+  else
+    region = NULL;
+
+  gdk_window_input_shape_combine_region (window,
+                                        region,
+                                        x, y);
+  
+  gdk_region_destroy (region);
+}
+
+/**
+ * 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)
 {
   GdkWindowObject *private;
 
@@ -4102,7 +7220,94 @@ gdk_window_merge_child_shapes (GdkWindow *window)
 
   private = (GdkWindowObject *) window;
 
-  GDK_WINDOW_IMPL_GET_IFACE (private->impl)->merge_child_shapes (window);
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+
+  if (private->input_shape)
+    gdk_region_destroy (private->input_shape);
+
+  if (shape_region)
+    {
+      private->input_shape = gdk_region_copy (shape_region);
+      gdk_region_offset (private->input_shape, offset_x, offset_y);      
+    }
+  else
+    private->input_shape = NULL;
+
+  if (gdk_window_has_impl (private))
+    GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_shape_combine_region ((GdkWindow *)private, private->input_shape, 0, 0);
+
+  /* Pointer may have e.g. moved outside window due to the input mask change */
+  _gdk_syntesize_crossing_events_for_geometry_change (window);
+}
+
+static void
+do_child_input_shapes (GdkWindow *window,
+                      gboolean merge)
+{
+  GdkWindowObject *private;
+  GdkRectangle r;
+  GdkRegion *region;
+
+  private = (GdkWindowObject *) window;
+  
+  r.x = 0;
+  r.y = 0;
+  r.width = private->width;
+  r.height = private->height;
+  
+  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);
+}
+
+
+/**
+ * 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);
 }
 
 
@@ -4128,7 +7333,10 @@ gdk_window_set_static_gravities (GdkWindow *window,
 
   private = (GdkWindowObject *) window;
 
-  return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_static_gravities (window, use_static);
+  if (gdk_window_has_impl (private))
+    return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_static_gravities (window, use_static);
+  
+  return FALSE;
 }
 
 /**
@@ -4176,6 +7384,9 @@ gdk_window_set_composited (GdkWindow *window,
   if (private->composited == composited)
     return;
 
+  if (composited)
+    gdk_window_set_has_native (window, TRUE);
+
   display = gdk_drawable_get_display (GDK_DRAWABLE (window));
 
   if (!gdk_display_supports_composite (display) && composited)
@@ -4187,6 +7398,11 @@ gdk_window_set_composited (GdkWindow *window,
 
   _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);
+  
   private->composited = composited;
 }
 
@@ -4294,7 +7510,7 @@ gdk_window_redirect_to_drawable (GdkWindow   *window,
                                  gint         height)
 {
   GdkWindowObject *private;
-  
+
   g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
@@ -4331,20 +7547,22 @@ static void
 window_get_size_rectangle (GdkWindow    *window,
                            GdkRectangle *rect)
 {
+  GdkWindowObject *private = (GdkWindowObject *) window;
+  
   rect->x = rect->y = 0;
-  gdk_drawable_get_size (GDK_DRAWABLE (window), &rect->width, &rect->height);
+  rect->width = private->width;
+  rect->height = private->height;
 }
 
 /* Calculates the real clipping region for a window, in window coordinates,
  * taking into account other windows, gc clip region and gc clip mask.
  */
-static GdkRegion *
+GdkRegion *
 _gdk_window_calculate_full_clip_region (GdkWindow *window,
                                        GdkWindow *base_window,
-                                       GdkGC *gc,
-                                       gboolean do_children,
-                                       gint *base_x_offset,
-                                       gint *base_y_offset)
+                                       gboolean   do_children,
+                                       gint      *base_x_offset,
+                                       gint      *base_y_offset)
 {
   GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
   GdkRectangle visible_rect;
@@ -4362,13 +7580,6 @@ _gdk_window_calculate_full_clip_region (GdkWindow *window,
 
   window_get_size_rectangle (window, &visible_rect);
 
-  /* windows that a redirection has ben setup for need to be considered
-   * fully visible, in order to avoid missing redirected paint ops
-   * anywhere in the window area.
-   */
-  if (private->redirect && private->redirect->redirected == private)
-    return gdk_region_rectangle (&visible_rect);
-
   /* real_clip_region is in window coordinates */
   real_clip_region = gdk_region_rectangle (&visible_rect);
 
@@ -4381,27 +7592,38 @@ _gdk_window_calculate_full_clip_region (GdkWindow *window,
     parentwin = lastwin->parent;
   
   /* Remove the areas of all overlapping windows above parentwin in the hiearachy */
-  for (; parentwin != NULL && (parentwin == private || lastwin != (GdkWindowObject *)base_window);
+  for (; parentwin != NULL &&
+         (parentwin == private || lastwin != (GdkWindowObject*) base_window);
        lastwin = parentwin, parentwin = lastwin->parent)
     {
       GList *cur;
       GdkRectangle real_clip_rect;
-      
+      gboolean is_offscreen;
+
       if (parentwin != private)
        {
          x_offset += GDK_WINDOW_OBJECT (lastwin)->x;
          y_offset += GDK_WINDOW_OBJECT (lastwin)->y;
        }
-      
+
+      is_offscreen = gdk_window_is_offscreen (parentwin);
+
       /* children is ordered in reverse stack order */
-      for (cur = GDK_WINDOW_OBJECT (parentwin)->children; cur && cur->data != lastwin; cur = cur->next)
+      for (cur = parentwin->children;
+           cur && cur->data != lastwin;
+           cur = cur->next)
        {
          GdkWindow *child = cur->data;
          GdkWindowObject *child_private = (GdkWindowObject *)child;
-         
+
          if (!GDK_WINDOW_IS_MAPPED (child) || child_private->input_only)
            continue;
 
+          /* Ignore offscreen children, as they don't draw in their parent and
+          * don't take part in the clipping */
+         if (gdk_window_is_offscreen (child_private))
+           continue;
+
           window_get_size_rectangle (child, &visible_rect);
 
          /* Convert rect to "window" coords */
@@ -4432,24 +7654,6 @@ _gdk_window_calculate_full_clip_region (GdkWindow *window,
       gdk_region_destroy (tmpreg);
     }
 
-  if (gc)
-    {
-      GdkRegion *clip_region = _gdk_gc_get_clip_region (gc);
-      
-      if (clip_region)
-       {
-         /* clip_region is relative to gc clip origin which is relative to the window */
-         /* offset it to window relative: */
-         tmpreg = gdk_region_copy (clip_region);
-         gdk_region_offset (real_clip_region,
-                            gc->clip_x_origin,
-                            gc->clip_y_origin);
-         /* Intersect it with window hierarchy cliprect: */
-         gdk_region_intersect (real_clip_region, tmpreg);
-         gdk_region_destroy (tmpreg);
-       }
-    }
-
   if (base_x_offset)
     *base_x_offset = x_offset;
   if (base_y_offset)
@@ -4458,9 +7662,9 @@ _gdk_window_calculate_full_clip_region (GdkWindow *window,
   return real_clip_region;
 }
 
-static void
-gdk_window_add_damage (GdkWindow *toplevel,
-                      GdkRegion *damaged_region)
+void
+_gdk_window_add_damage (GdkWindow *toplevel,
+                       GdkRegion *damaged_region)
 {
   GdkDisplay *display;
   GdkEvent event = { 0, };
@@ -4474,80 +7678,1222 @@ gdk_window_add_damage (GdkWindow *toplevel,
 }
 
 static void
-setup_redirect_clip (GdkWindow         *window,
-                    GdkGC             *gc,
-                    GdkWindowClipData *data)
+gdk_window_redirect_free (GdkWindowRedirect *redirect)
 {
-  GdkWindowObject *private = (GdkWindowObject *)window;
-  GdkRegion *visible_region;
-  GdkRectangle dest_rect;
-  GdkRegion *tmpreg;
-  GdkWindow *toplevel;
+  g_object_unref (redirect->pixmap);
+  g_free (redirect);
+}
+
+static void
+convert_coords_to_child (GdkWindowObject *child,
+                        double x, double y,
+                        double *child_x, double *child_y)
+{
+  *child_x = x - child->x;
+  *child_y = y - child->y;
+}
+
+static gboolean
+point_in_window (GdkWindowObject *window,
+                double x, double y)
+{
+  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));
+}
 
-  data->old_region = _gdk_gc_get_clip_region (gc);
-  if (data->old_region) 
-    data->old_region = gdk_region_copy (data->old_region);
+static GdkWindow *
+convert_coords_to_toplevel (GdkWindow *window,
+                           double child_x, double child_y,
+                           double *toplevel_x, double *toplevel_y)
+{
+  GdkWindowObject *private = (GdkWindowObject *)window;
+  gdouble x, y;
 
-  data->old_clip_x_origin = gc->clip_x_origin;
-  data->old_clip_y_origin = gc->clip_y_origin;
+  x = child_x;
+  y = child_y;
 
-  toplevel = GDK_WINDOW (private->redirect->redirected);
+  while (private->parent != NULL &&
+        (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT))
+    {
+      x += private->x;
+      y += private->y;
+      private = private->parent;
+    }
   
-  /* 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);
+  *toplevel_x = x;
+  *toplevel_y = y;
+  
+  return (GdkWindow *)private;
+}
 
-  /* Compensate for the source pos/size */
-  data->x_offset -= private->redirect->src_x;
-  data->y_offset -= private->redirect->src_y;
-  dest_rect.x = -data->x_offset;
-  dest_rect.y = -data->y_offset;
-  dest_rect.width = private->redirect->width;
-  dest_rect.height = private->redirect->height;
-  tmpreg = gdk_region_rectangle (&dest_rect);
-  gdk_region_intersect (visible_region, tmpreg);
-  gdk_region_destroy (tmpreg);
 
-  /* Compensate for the dest pos */
-  data->x_offset += private->redirect->dest_x;
-  data->y_offset += private->redirect->dest_y;
+static void
+convert_toplevel_coords_to_window (GdkWindow *window,
+                                  gdouble    toplevel_x,
+                                  gdouble    toplevel_y,
+                                  gdouble   *window_x,
+                                  gdouble   *window_y)
+{
+  GdkWindowObject *private;
+  gdouble x, y;
+  GList *children, *l;
 
-  gdk_gc_set_clip_region (gc, visible_region); /* This resets clip origin! */
+  private = GDK_WINDOW_OBJECT (window);
+  
+  x = toplevel_x;
+  y = toplevel_y;
 
-  /* offset clip and tiles from window coords to pixmaps coords */
-  gdk_gc_offset (gc, -data->x_offset, -data->y_offset);
+  children = NULL;
+  while (private->parent != NULL &&
+        (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT))
+    {
+      children = g_list_prepend (children, private);
+      private = private->parent;
+    }
 
-  /* 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);
+  for (l = children; l != NULL; l = l->next)
+    convert_coords_to_child (l->data, x, y, &x, &y);
   
-  gdk_region_destroy (visible_region);
+  g_list_free (children);
+  
+  *window_x = x;
+  *window_y = y;
 }
 
-static void
-reset_redirect_clip (GdkWindow         *offscreen,
-                     GdkGC             *gc,
-                     GdkWindowClipData *data)
+GdkWindow *
+_gdk_window_find_descendant_at (GdkWindow *toplevel,
+                               double x, double y,
+                               double *found_x,
+                               double *found_y)
 {
-  /* offset back */
-  gdk_gc_offset (gc, data->x_offset, data->y_offset);
+  GdkWindowObject *private, *sub;
+  double child_x, child_y;
+  GList *l;
 
-  /* 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);
-}
+  private = (GdkWindowObject *)toplevel;
+  
+  if (point_in_window (private, x, y))
+    {
+      do 
+       {
+         /* Children is ordered in reverse stack order, i.e. first is topmost */
+         for (l = private->children; l != NULL; l = l->next)
+           {
+             sub = l->data;
 
-static void
-gdk_window_redirect_free (GdkWindowRedirect *redirect)
-{
-  g_object_unref (redirect->pixmap);
-  g_free (redirect);
+              if (!GDK_WINDOW_IS_MAPPED (sub))
+                continue;
+             
+             convert_coords_to_child (sub,
+                                      x, y,
+                                      &child_x, &child_y);
+             if (point_in_window (sub, child_x, child_y))
+               {
+                 x = child_x;
+                 y = child_y;
+                 private = sub;
+                 break;
+               }
+           }
+       }
+      while (l != NULL);
+    }
+  else
+    {
+      /* Not in window at all */
+      private = NULL;
+    }
+
+  if (found_x)
+    *found_x = x;
+  if (found_y)
+    *found_y = y;
+  
+  return (GdkWindow *)private;
+}
+
+static const guint type_masks[] = {
+  GDK_SUBSTRUCTURE_MASK, /* GDK_DELETE                 = 0  */
+  GDK_STRUCTURE_MASK, /* GDK_DESTROY                   = 1  */
+  GDK_EXPOSURE_MASK, /* GDK_EXPOSE                     = 2  */
+  GDK_POINTER_MOTION_MASK, /* GDK_MOTION_NOTIFY        = 3  */
+  GDK_BUTTON_PRESS_MASK, /* GDK_BUTTON_PRESS           = 4  */
+  GDK_BUTTON_PRESS_MASK, /* GDK_2BUTTON_PRESS          = 5  */
+  GDK_BUTTON_PRESS_MASK, /* GDK_3BUTTON_PRESS          = 6  */
+  GDK_BUTTON_RELEASE_MASK, /* GDK_BUTTON_RELEASE       = 7  */
+  GDK_KEY_PRESS_MASK, /* GDK_KEY_PRESS                 = 8  */
+  GDK_KEY_RELEASE_MASK, /* GDK_KEY_RELEASE             = 9  */
+  GDK_ENTER_NOTIFY_MASK, /* GDK_ENTER_NOTIFY           = 10 */
+  GDK_LEAVE_NOTIFY_MASK, /* GDK_LEAVE_NOTIFY           = 11 */
+  GDK_FOCUS_CHANGE_MASK, /* GDK_FOCUS_CHANGE           = 12 */
+  GDK_STRUCTURE_MASK, /* GDK_CONFIGURE                 = 13 */
+  GDK_VISIBILITY_NOTIFY_MASK, /* GDK_MAP               = 14 */
+  GDK_VISIBILITY_NOTIFY_MASK, /* GDK_UNMAP             = 15 */
+  GDK_PROPERTY_CHANGE_MASK, /* GDK_PROPERTY_NOTIFY     = 16 */
+  GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_CLEAR     = 17 */
+  GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_REQUEST   = 18 */
+  GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_NOTIFY    = 19 */
+  GDK_PROXIMITY_IN_MASK, /* GDK_PROXIMITY_IN           = 20 */
+  GDK_PROXIMITY_OUT_MASK, /* GDK_PROXIMITY_OUT         = 21 */
+  GDK_ALL_EVENTS_MASK, /* GDK_DRAG_ENTER               = 22 */
+  GDK_ALL_EVENTS_MASK, /* GDK_DRAG_LEAVE               = 23 */
+  GDK_ALL_EVENTS_MASK, /* GDK_DRAG_MOTION              = 24 */
+  GDK_ALL_EVENTS_MASK, /* GDK_DRAG_STATUS              = 25 */
+  GDK_ALL_EVENTS_MASK, /* GDK_DROP_START               = 26 */
+  GDK_ALL_EVENTS_MASK, /* GDK_DROP_FINISHED            = 27 */
+  GDK_ALL_EVENTS_MASK, /* GDK_CLIENT_EVENT            = 28 */
+  GDK_VISIBILITY_NOTIFY_MASK, /* GDK_VISIBILITY_NOTIFY = 29 */
+  GDK_EXPOSURE_MASK, /* GDK_NO_EXPOSE                  = 30 */
+  GDK_SCROLL_MASK | GDK_BUTTON_PRESS_MASK,/* GDK_SCROLL= 31 */
+  0, /* GDK_WINDOW_STATE = 32 */
+  0, /* GDK_SETTING = 33 */
+  0, /* GDK_OWNER_CHANGE = 34 */
+  0, /* GDK_GRAB_BROKEN = 35 */
+  0, /* GDK_DAMAGE = 36 */
+};
+G_STATIC_ASSERT (G_N_ELEMENTS (type_masks) == GDK_EVENT_LAST);
+
+/* send motion events if the right buttons are down */
+static guint
+update_evmask_for_button_motion (guint           evmask,
+                                 GdkModifierType mask)
+{
+  if (evmask & GDK_BUTTON_MOTION_MASK &&
+      mask & (GDK_BUTTON1_MASK |
+             GDK_BUTTON2_MASK |
+             GDK_BUTTON3_MASK |
+             GDK_BUTTON4_MASK |
+             GDK_BUTTON5_MASK))
+    evmask |= GDK_POINTER_MOTION_MASK;
+
+  if ((evmask & GDK_BUTTON1_MOTION_MASK && mask & GDK_BUTTON1_MASK) ||
+      (evmask & GDK_BUTTON2_MOTION_MASK && mask & GDK_BUTTON2_MASK) ||
+      (evmask & GDK_BUTTON3_MOTION_MASK && mask & GDK_BUTTON3_MASK))
+    evmask |= GDK_POINTER_MOTION_MASK;
+
+  return evmask;
+}
+
+static 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 = tmp->parent;
+    }
+
+  tmp = win2;
+  while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
+    {
+      path2 = g_list_prepend (path2, tmp);
+      tmp = tmp->parent;
+    }
+
+  list1 = path1;
+  list2 = path2;
+  tmp = NULL;
+  while (list1 && list2 && (list1->data == list2->data))
+    {
+      tmp = (GdkWindowObject *)list1->data;
+      list1 = g_list_next (list1);
+      list2 = g_list_next (list2);
+    }
+  g_list_free (path1);
+  g_list_free (path2);
+
+  return tmp;
+}
+
+GdkEvent *
+_gdk_make_event (GdkWindow    *window,
+                GdkEventType  type,
+                GdkEvent     *event_in_queue,
+                gboolean      before_event)
+{
+  GdkEvent *event = gdk_event_new (type);
+  guint32 the_time;
+  GdkModifierType the_state;
+
+  the_time = gdk_event_get_time (event_in_queue);
+  gdk_event_get_state (event_in_queue, &the_state);
+
+  event->any.window = g_object_ref (window);
+  event->any.send_event = FALSE;
+
+  switch (type)
+    {
+    case GDK_MOTION_NOTIFY:
+      event->motion.time = the_time;
+      event->motion.axes = NULL;
+      event->motion.state = the_state;
+      break;
+
+    case GDK_BUTTON_PRESS:
+    case GDK_2BUTTON_PRESS:
+    case GDK_3BUTTON_PRESS:
+    case GDK_BUTTON_RELEASE:
+      event->button.time = the_time;
+      event->button.axes = NULL;
+      event->button.state = the_state;
+      break;
+
+    case GDK_SCROLL:
+      event->scroll.time = the_time;
+      event->scroll.state = the_state;
+      break;
+
+    case GDK_KEY_PRESS:
+    case GDK_KEY_RELEASE:
+      event->key.time = the_time;
+      event->key.state = the_state;
+      break;
+
+    case GDK_ENTER_NOTIFY:
+    case GDK_LEAVE_NOTIFY:
+      event->crossing.time = the_time;
+      event->crossing.state = the_state;
+      break;
+
+    case GDK_PROPERTY_NOTIFY:
+      event->property.time = the_time;
+      event->property.state = the_state;
+      break;
+
+    case GDK_SELECTION_CLEAR:
+    case GDK_SELECTION_REQUEST:
+    case GDK_SELECTION_NOTIFY:
+      event->selection.time = the_time;
+      break;
+
+    case GDK_PROXIMITY_IN:
+    case GDK_PROXIMITY_OUT:
+      event->proximity.time = the_time;
+      break;
+
+    case GDK_DRAG_ENTER:
+    case GDK_DRAG_LEAVE:
+    case GDK_DRAG_MOTION:
+    case GDK_DRAG_STATUS:
+    case GDK_DROP_START:
+    case GDK_DROP_FINISHED:
+      event->dnd.time = the_time;
+      break;
+
+    case GDK_FOCUS_CHANGE:
+    case GDK_CONFIGURE:
+    case GDK_MAP:
+    case GDK_UNMAP:
+    case GDK_CLIENT_EVENT:
+    case GDK_VISIBILITY_NOTIFY:
+    case GDK_NO_EXPOSE:
+    case GDK_DELETE:
+    case GDK_DESTROY:
+    case GDK_EXPOSE:
+    default:
+      break;
+    }
+
+  if (event_in_queue)
+    {
+    if (before_event)
+      _gdk_event_queue_insert_before (gdk_drawable_get_display (window), event_in_queue, event);
+    else
+      _gdk_event_queue_insert_after (gdk_drawable_get_display (window), event_in_queue, event);
+    }
+  else
+    _gdk_event_queue_append (gdk_drawable_get_display (window), event);
+
+  return event;
+}
+
+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)
+{
+  GdkEvent *event;
+  guint32 event_mask;
+  GdkPointerGrabInfo *grab;
+  
+  grab = _gdk_display_has_pointer_grab (display, serial);
+  
+  if (grab != NULL &&
+      !grab->owner_events &&
+      (GdkWindow *)window != grab->window)
+    return;
+  
+  if (type == GDK_LEAVE_NOTIFY)
+    event_mask = GDK_LEAVE_NOTIFY_MASK;
+  else
+    event_mask = GDK_ENTER_NOTIFY_MASK;
+
+  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;
+    }
+}
+  
+
+/* The coordinates are in the toplevel window that src/dest are in.
+ * src and dest are always (if != NULL) in the same toplevel, as
+ * we get a leave-notify and set the window_under_pointer to null
+ * before crossing to another toplevel.
+ */
+void
+_gdk_syntesize_crossing_events (GdkDisplay                 *display,
+                               GdkWindow                  *src,
+                               GdkWindow                  *dest,
+                               GdkCrossingMode             mode,
+                               gint                        toplevel_x,
+                               gint                        toplevel_y,
+                               GdkModifierType             mask,
+                               guint32                     time_,
+                               GdkEvent                   *event_in_queue,
+                               gulong                      serial)
+{
+  GdkWindowObject *c;
+  GdkWindowObject *win, *last, *next;
+  GList *path, *list;
+  gboolean non_linear;
+  GdkWindowObject *a;
+  GdkWindowObject *b;
+  GdkWindowObject *toplevel;
+  GdkNotifyType notify_type;
+
+  /* TODO: Don't send events to toplevel, as we get those from the windowing system */
+  
+  a = (GdkWindowObject *)src;
+  b = (GdkWindowObject *)dest;
+  if (a == b)
+    return; /* No crossings generated between src and dest */
+
+  c = find_common_ancestor (a, b);
+
+  non_linear = (c != a) && (c != b);
+
+  if (a) /* There might not be a source (i.e. if no previous pointer_in_window) */
+    {
+      toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)a);
+      
+      /* 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 = a->parent;
+         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 = win->parent;
+           }
+       }
+    }
+
+  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 = b->parent;
+         while (win != c && GDK_WINDOW_TYPE (win) != GDK_WINDOW_ROOT)
+           {
+             path = g_list_prepend (path, win);
+             win = win->parent;
+           }
+         
+         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);
+       }
+
+
+      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);
+    }
+}
+
+static GdkWindow *
+get_toplevel (GdkWindow *w)
+{
+  GdkWindowObject *private = GDK_WINDOW_OBJECT (w);
+  
+  while (private->parent != NULL &&
+        (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT))
+    private = private->parent;
+
+  return GDK_WINDOW (private);
+}
+
+/* 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.
+ */
+static GdkWindow *
+get_pointer_window (GdkDisplay *display,
+                   GdkWindow *event_window,
+                   gdouble toplevel_x,
+                   gdouble toplevel_y,
+                   gulong serial)
+{
+  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;
+
+  grab = _gdk_display_has_pointer_grab (display, serial);
+  if (grab != NULL &&
+      !grab->owner_events &&
+      pointer_window != grab->window)
+    pointer_window = NULL;
+  
+  return pointer_window;
+}
+
+void
+_gdk_display_set_window_under_pointer (GdkDisplay *display,
+                                      GdkWindow *window)
+{
+  GdkWindowObject *private;
+
+  private = (GdkWindowObject *)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);
+
+  if (window)
+    update_cursor (display);
+
+  _gdk_display_enable_motion_hints (display);
+}
+
+void
+_gdk_syntesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
+{
+  GdkDisplay *display;
+  GdkWindow *changed_toplevel;
+  GdkWindow *new_window_under_pointer;
+  gulong serial;
+
+  display = gdk_drawable_get_display (changed_window);
+  
+  serial = _gdk_windowing_window_get_next_serial (display);
+  changed_toplevel = get_toplevel (changed_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);
+       }
+    }
+}
+
+/* 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)
+{
+  guint evmask;
+  GdkWindow *grab_window;
+  GdkWindowObject *w;
+  GdkPointerGrabInfo *grab;
+
+  grab = _gdk_display_has_pointer_grab (display, serial);
+
+  if (grab != NULL && !grab->owner_events)
+    {
+      evmask = grab->event_mask;
+      evmask = update_evmask_for_button_motion (evmask, mask);
+
+      grab_window = grab->window;
+      
+      if (evmask & type_masks[type])
+       {
+         if (evmask_out)
+           *evmask_out = evmask;
+         return grab_window;
+       }
+      else
+       return NULL;
+    }
+
+  w = (GdkWindowObject *)pointer_window;
+  while (w != NULL)
+    {
+      evmask = w->event_mask;
+      evmask = update_evmask_for_button_motion (evmask, mask);
+
+      if (evmask & type_masks[type])
+       {
+         if (evmask_out)
+           *evmask_out = evmask;
+         return (GdkWindow *)w;
+       }
+
+      w = w->parent;
+    }
+
+  if (grab != NULL &&
+      grab->owner_events)
+    {
+      evmask = grab->event_mask;
+      evmask = update_evmask_for_button_motion (evmask, mask);
+
+      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_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)
+    {
+      /* 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;
+    }
+      
+  pointer_window = get_pointer_window (display, toplevel_window,
+                                      toplevel_x, toplevel_y, serial);
+  
+  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)
+       {
+         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 gboolean
+proxy_button_event (GdkEvent *source_event,
+                   gulong serial)
+{
+  GdkWindow *toplevel_window, *event_window;
+  GdkWindow *event_win;
+  GdkWindow *pointer_window;
+  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_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)
+    {
+      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 && w->parent->window_type != GDK_WINDOW_ROOT)
+       {
+         if (w->event_mask & GDK_BUTTON_PRESS_MASK)
+           break;
+         w = 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);
+    }
+
+  pointer_window = get_pointer_window (display, toplevel_window,
+                                      toplevel_x, toplevel_y,
+                                      serial);
+  
+  event_win = get_event_window (display,
+                               pointer_window,
+                               type, state,
+                               NULL, serial);
+
+  if (event_win == NULL)
+    return TRUE;
+  
+  event = _gdk_make_event (event_win, type, source_event, FALSE);
+  
+  switch (type)
+    {
+    case GDK_BUTTON_PRESS:
+    case GDK_BUTTON_RELEASE:
+      event->button.button = source_event->button.button;
+      convert_toplevel_coords_to_window (event_win,
+                                        toplevel_x, toplevel_y,
+                                        &event->button.x, &event->button.y);
+      event->button.x_root = 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
+gdk_window_print (GdkWindowObject *window,
+                 int indent)
+{
+  GdkRectangle r;
+  
+  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
+          );
+
+  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");
+}
+
+
+static void
+gdk_window_print_tree (GdkWindow *window,
+                      int indent,
+                      gboolean include_input_only)
+{
+  GdkWindowObject *private;
+  GList *l;
+
+  private = (GdkWindowObject *)window;
+
+  if (private->input_only && !include_input_only)
+    return;
+  
+  gdk_window_print (private, indent);
+
+  for (l = private->children; l != NULL; l = l->next)
+    gdk_window_print_tree (l->data, indent + 4, include_input_only);
+}
+
+#endif /* DEBUG_WINDOW_PRINTING */
+
+void
+_gdk_windowing_got_event (GdkDisplay *display,
+                         GList      *event_link,
+                         GdkEvent   *event,
+                         gulong      serial)
+{
+  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;
+  
+  event_private = GDK_WINDOW_OBJECT (event_window);
+
+#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
+  
+  if (!(is_button_type (event->type) ||
+       is_motion_type (event->type)) ||
+      GDK_WINDOW_TYPE (event_private) == GDK_WINDOW_ROOT)
+    return;
+
+  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))
+    {
+      /* 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)
+       {
+         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);
+       }
+      
+      unlink_event = TRUE;
+      goto out;
+    }
+  
+  /* 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;
+       }
+    }
+
+  /* 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_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)
+    {
+      button_release_grab =
+       _gdk_display_has_pointer_grab (display, serial);
+      if (button_release_grab &&
+         button_release_grab->implicit &&
+         (event->button.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
+       {
+         button_release_grab->serial_end = serial;
+         button_release_grab->implicit_ungrab = TRUE;
+         _gdk_display_pointer_grab_update (display, serial);
+       }
+    }
+
+ out:
+  if (unlink_event)
+    {
+      _gdk_event_queue_remove_link (display, event_link);
+      g_list_free_1 (event_link);
+      gdk_event_free (event);
+    }
 }
 
 #define __GDK_WINDOW_C__
index 866bb694675b3115f7090c04dd89eecb88839ebd..6a9985a4fa4976b29cf8ea3aeed6c44d8e4630e3 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,8 @@ void              gdk_window_move_region           (GdkWindow       *window,
                                                const GdkRegion *region,
                                                gint             dx,
                                                gint             dy);
+void          gdk_window_set_has_native        (GdkWindow       *window,
+                                               gboolean         has_native);
 
 /* 
  * This allows for making shaped (partially transparent) windows
@@ -645,12 +655,18 @@ GdkPointerHooks *gdk_set_pointer_hooks (const GdkPointerHooks *new_hooks);
 
 GdkWindow *gdk_get_default_root_window (void);
 
-void gdk_window_redirect_to_drawable (GdkWindow *window,
-                                     GdkDrawable *drawable,
-                                     gint src_x, gint src_y,
-                                     gint dest_x, gint dest_y,
-                                     gint width, gint height);
-void gdk_window_remove_redirection   (GdkWindow *window);
+/* Offscreen redirection */
+GdkPixmap *gdk_window_get_offscreen_pixmap   (GdkWindow     *window);
+
+void       gdk_window_redirect_to_drawable   (GdkWindow     *window,
+                                              GdkDrawable   *drawable,
+                                              gint           src_x,
+                                              gint           src_y,
+                                              gint           dest_x,
+                                              gint           dest_y,
+                                              gint           width,
+                                              gint           height);
+void       gdk_window_remove_redirection     (GdkWindow     *window);
 
 #ifndef GDK_DISABLE_DEPRECATED
 #define GDK_ROOT_PARENT()             (gdk_get_default_root_window ())
index f9f97b6fa0d84ca5a6f8ce12fc20c1bcc46c7291..d63e5a1ff3352caad433001c45e63c11602ed27b 100644 (file)
@@ -43,12 +43,13 @@ struct _GdkWindowImplIface
 {
   GTypeInterface g_iface;
 
-  void         (* show)                 (GdkWindow       *window,
-                                         gboolean         raise);
+  void         (* show)                 (GdkWindow       *window);
   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 +57,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,
@@ -97,28 +83,74 @@ struct _GdkWindowImplIface
   gint         (* get_origin)           (GdkWindow       *window,
                                          gint            *x,
                                          gint            *y);
-  void         (* get_offsets)          (GdkWindow       *window,
-                                         gint            *x_offset,
-                                         gint            *y_offset);
+  gint         (* get_deskrelative_origin) (GdkWindow       *window,
+                                         gint            *x,
+                                         gint            *y);
 
-  void         (* shape_combine_mask)   (GdkWindow       *window,
-                                         GdkBitmap       *mask,
-                                         gint             x,
-                                         gint             y);
   void         (* shape_combine_region) (GdkWindow       *window,
                                          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);
 };
 
 /* 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..72b678c0c5636d41bce5215905c3a73e53b6f296 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);
 }
 
@@ -317,49 +337,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 +721,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 +779,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..4ccf0b3b605505bfc64fa6dfeb07eca7011485bf 100644 (file)
@@ -1657,16 +1657,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 +1760,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 +1837,9 @@ _gdk_win32_drawable_acquire_dc (GdkDrawable *drawable)
       return impl->hdc;
     }
   else
-    return NULL;
+    {
+      return NULL;
+    }
 }
 
 /**
@@ -1844,6 +1876,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 +1917,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 +1983,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 c51a4956f2e92582ef7dc003422ecafc82e5276e..a517404e1ed17100572daf6e3a185bbd7c345db6 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"
@@ -444,6 +445,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)
@@ -584,6 +592,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 ))     \
@@ -600,43 +622,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);
+    }
 }
 
 /**
@@ -664,9 +678,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);
 }
 
 /**
@@ -1335,7 +1349,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..e92418d379c19dfdf39d44b0b8b36562a2dd67f2 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;
 
@@ -169,6 +155,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..e6ea4f1853e206bf5bb0a61f6ef7e47dd7a7d579 100644 (file)
@@ -634,13 +634,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 +687,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 +907,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_set_has_native (window, TRUE);
+
+         /* 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 +1506,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 +1556,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..8d3141a8ee2b79b0b0c96942d24e7b9be8cb80fb 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:
@@ -1129,8 +1154,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 +1173,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 +1187,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:
@@ -1198,8 +1220,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 +1230,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:
@@ -1234,8 +1252,8 @@ gdk_event_translate (GdkDisplay *display,
       event->motion.type = GDK_MOTION_NOTIFY;
       event->motion.window = window;
       event->motion.time = xevent->xmotion.time;
-      event->motion.x = xevent->xmotion.x + xoffset;
-      event->motion.y = xevent->xmotion.y + yoffset;
+      event->motion.x = xevent->xmotion.x;
+      event->motion.y = xevent->xmotion.y;
       event->motion.x_root = (gfloat)xevent->xmotion.x_root;
       event->motion.y_root = (gfloat)xevent->xmotion.y_root;
       event->motion.axes = NULL;
@@ -1304,8 +1322,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 +1417,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 +1614,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 +1654,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 +1844,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);
         }
@@ -1847,7 +1865,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 +1905,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)
@@ -2180,7 +2199,7 @@ gdk_event_translate (GdkDisplay *display,
   
   if (window)
     g_object_unref (window);
-  
+
   return return_val;
 }
 
@@ -2301,6 +2320,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 8faf7048459c1f20fc672bbfe82a81c8ac707e5b..9e2d81889fad911e868bc5c9e5a061bc4735b6b3 100644 (file)
@@ -416,15 +416,15 @@ gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
                                 gdouble          *x_out,
                                 gdouble          *y_out)
 {
-  GdkWindowImplX11 *impl;
+  GdkWindowObject *window_private;
   int i;
   int x_axis = 0;
   int y_axis = 0;
 
   double device_width, device_height;
   double x_offset, y_offset, x_scale, y_scale;
-
-  impl = GDK_WINDOW_IMPL_X11 (((GdkWindowObject *) input_window->window)->impl);
+  
+  window_private = (GdkWindowObject *) input_window->window;
 
   for (i=0; i<gdkdev->info.num_axes; i++)
     {
@@ -476,26 +476,26 @@ gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev,
        }
       device_aspect = (device_height*y_resolution) /
         (device_width*x_resolution);
-      if (device_aspect * impl->width >= impl->height)
+      if (device_aspect * window_private->width >= window_private->height)
        {
          /* device taller than window */
-         x_scale = impl->width / device_width;
+         x_scale = window_private->width / device_width;
          y_scale = (x_scale * x_resolution)
            / y_resolution;
 
          x_offset = 0;
          y_offset = -(device_height * y_scale - 
-                              impl->height)/2;
+                      window_private->height)/2;
        }
       else
        {
          /* window taller than device */
-         y_scale = impl->height / device_height;
+         y_scale = window_private->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 - window_private->width)/2;
        }
     }
 
index 0d48e13f3ba3b5f3d748af7833fe97c933566a7c..95a301d24d2e37794dd139bc6efe00179b486656 100644 (file)
@@ -251,7 +251,7 @@ gdk_device_get_history  (GdkDevice         *device,
   int tmp_n_events = 0;
   int i;
 
-  g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
+  g_return_val_if_fail (GDK_WINDOW_IS_X11 (window), FALSE);
 
   if (GDK_WINDOW_DESTROYED (window))
     /* Nothing */ ;
@@ -324,6 +324,11 @@ _gdk_input_window_find(GdkWindow *window)
   GList *tmp_list;
   GdkDisplayX11 *display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
 
+  /* Ensure we have a native window, or the input stuff won't work.
+     Its possible we could emulate this also, but at least this should make
+     it work. */
+  gdk_window_set_has_native (window, TRUE);
+
   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);
@@ -347,7 +352,7 @@ gdk_input_set_extension_events (GdkWindow *window, gint mask,
   GdkDisplayX11 *display_x11;
 
   g_return_if_fail (window != NULL);
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  g_return_if_fail (GDK_WINDOW_IS_X11 (window));
 
   window_private = (GdkWindowObject*) window;
   display_x11 = GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (window));
index 7bede228a18315252ba292c6f3fe084905dcdef4..41639c478239c9427776f228970d76093e5728ba 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"
@@ -137,25 +138,22 @@ gdk_x11_convert_grab_status (gint status)
   return 0;
 }
 
+struct XPointerGrabInfo {
+  GdkDisplay *display;
+  GdkWindow *window;
+  GdkWindow *native_window;
+  gboolean owner_events;
+  gulong serial;
+  guint event_mask;
+  guint32 time;
+};
+
 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);
 }
 
 /*
@@ -191,6 +189,7 @@ gdk_pointer_grab (GdkWindow *         window,
 {
   gint return_val;
   GdkCursorPrivate *cursor_private;
+  GdkWindow *native;
   GdkDisplayX11 *display_x11;
   guint xevent_mask;
   Window xwindow;
@@ -202,13 +201,30 @@ gdk_pointer_grab (GdkWindow *       window,
   g_return_val_if_fail (window != NULL, 0);
   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
   g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
+
+  native = gdk_window_get_toplevel (window);
+
+  /* We need a native window for confine to to work, ensure we have one */
+  if (confine_to)
+    gdk_window_set_has_native (confine_to, TRUE);
+  
+  /* TODO: What do we do for offscreens and  their children? We need to proxy the grab somehow */
+  if (!GDK_IS_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (native)->impl))
+    return GDK_GRAB_SUCCESS;
+
+  if (!_gdk_window_has_impl (window) &&
+      !gdk_window_is_viewable (window))
+    return GDK_GRAB_NOT_VIEWABLE;
   
-  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);
+  serial = NextRequest (GDK_WINDOW_XDISPLAY (native));
   
   if (!confine_to || GDK_WINDOW_DESTROYED (confine_to))
     xconfine_to = None;
@@ -229,8 +245,13 @@ gdk_pointer_grab (GdkWindow *        window,
       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,
+  return_val = _gdk_input_grab_pointer (native,
                                        owner_events,
                                        event_mask,
                                        confine_to,
@@ -239,14 +260,14 @@ gdk_pointer_grab (GdkWindow *       window,
   if (return_val == GrabSuccess || 
       G_UNLIKELY (!display_x11->trusted_client && return_val == AlreadyGrabbed))
     {
-      if (!GDK_WINDOW_DESTROYED (window))
+      if (!GDK_WINDOW_DESTROYED (native))
        {
 #ifdef G_ENABLE_DEBUG
          if (_gdk_debug_flags & GDK_DEBUG_NOGRABS)
            return_val = GrabSuccess;
          else
 #endif
-           return_val = XGrabPointer (GDK_WINDOW_XDISPLAY (window),
+           return_val = XGrabPointer (GDK_WINDOW_XDISPLAY (native),
                                       xwindow,
                                       owner_events,
                                       xevent_mask,
@@ -261,59 +282,23 @@ gdk_pointer_grab (GdkWindow *       window,
   
   if (return_val == GrabSuccess)
     {
-      if (display_x11->pointer_xgrab_window != NULL &&
-         display_x11->pointer_xgrab_window != (GdkWindowObject *)window)
-       generate_grab_broken_event (GDK_WINDOW (display_x11->pointer_xgrab_window),
-                                   FALSE, display_x11->pointer_xgrab_implicit,
-                                   window);
-
-      display_x11->pointer_xgrab_window = (GdkWindowObject *)window;
-      display_x11->pointer_xgrab_serial = serial;
-      display_x11->pointer_xgrab_owner_events = owner_events;
-      display_x11->pointer_xgrab_time = time;
-      display_x11->pointer_xgrab_implicit = FALSE;
+      _gdk_display_add_pointer_grab (GDK_DISPLAY_OBJECT (display_x11),
+                                    window,
+                                    native,
+                                    owner_events,
+                                    event_mask,
+                                    serial,
+                                    time,
+                                    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 +326,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);
 
-  if (!GDK_WINDOW_DESTROYED (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 (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 +365,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 +387,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 +415,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 116f47d9ff70814ad090a5cd0e5a2e206d30034e..9123990b6008b6ed950c42ae7802cbf88fd3d226 100644 (file)
@@ -543,7 +543,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)
     {
@@ -552,6 +552,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;
@@ -677,7 +679,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)
     {
@@ -688,7 +690,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;
@@ -728,7 +731,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)
     {
@@ -738,6 +741,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 77033fea76def58b7df3c226ec17349dd9dcbb7d..e29dc7b14b9473a16770c14b83aaa38e4cb04ce7 100644 (file)
@@ -112,16 +112,13 @@ static void     move_to_current_desktop           (GdkWindow *window);
 static GdkColormap* gdk_window_impl_x11_get_colormap (GdkDrawable *drawable);
 static void         gdk_window_impl_x11_set_colormap (GdkDrawable *drawable,
                                                      GdkColormap *cmap);
-static void         gdk_window_impl_x11_get_size    (GdkDrawable *drawable,
-                                                    gint *width,
-                                                    gint *height);
-static GdkRegion*  gdk_window_impl_x11_get_visible_region (GdkDrawable *drawable);
 static void        gdk_window_impl_x11_finalize   (GObject            *object);
 static void        gdk_window_impl_iface_init     (GdkWindowImplIface *iface);
 
-#define WINDOW_IS_TOPLEVEL(window)                \
-  (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
-   GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
+#define WINDOW_IS_TOPLEVEL(window)                  \
+  (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD &&   \
+   GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN && \
+   GDK_WINDOW_TYPE (window) != GDK_WINDOW_OFFSCREEN)
 
 /* Return whether time1 is considered later than time2 as far as xserver
  * time is concerned.  Accounts for wraparound.
@@ -146,8 +143,6 @@ _gdk_window_impl_get_type (void)
 static void
 gdk_window_impl_x11_init (GdkWindowImplX11 *impl)
 {  
-  impl->width = 1;
-  impl->height = 1;
   impl->toplevel_window_type = -1;
 }
 
@@ -181,11 +176,6 @@ gdk_window_impl_x11_class_init (GdkWindowImplX11Class *klass)
 
   drawable_class->set_colormap = gdk_window_impl_x11_set_colormap;
   drawable_class->get_colormap = gdk_window_impl_x11_get_colormap;
-  drawable_class->get_size = gdk_window_impl_x11_get_size;
-
-  /* Visible and clip regions are the same */
-  drawable_class->get_clip_region = gdk_window_impl_x11_get_visible_region;
-  drawable_class->get_visible_region = gdk_window_impl_x11_get_visible_region;
 }
 
 static void
@@ -230,14 +220,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),
@@ -253,10 +236,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;
@@ -301,15 +281,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)
     {
@@ -320,6 +298,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)
@@ -333,15 +324,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)
     {
@@ -352,6 +342,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)
 {
@@ -409,35 +413,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)
 {
@@ -457,6 +432,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);
@@ -469,12 +445,14 @@ _gdk_windowing_window_init (GdkScreen * screen)
   
   private->window_type = GDK_WINDOW_ROOT;
   private->depth = DefaultDepthOfScreen (screen_x11->xscreen);
-  
-  impl->width = WidthOfScreen (screen_x11->xscreen);
-  impl->height = HeightOfScreen (screen_x11->xscreen);
-  
-  _gdk_window_init_position (GDK_WINDOW (private));
 
+  private->x = 0;
+  private->y = 0;
+  private->abs_x = 0;
+  private->abs_y = 0;
+  private->width = WidthOfScreen (screen_x11->xscreen);
+  private->height = HeightOfScreen (screen_x11->xscreen);
+  
   _gdk_xid_table_insert (screen_x11->display,
                         &screen_x11->xroot_window,
                         screen_x11->root_window);
@@ -589,7 +567,6 @@ setup_toplevel_window (GdkWindow *window,
 {
   GdkWindowObject *obj = (GdkWindowObject *)window;
   GdkToplevelX11 *toplevel = _gdk_x11_window_get_toplevel (window);
-  GdkWindowImplX11 *impl = (GdkWindowImplX11 *)obj->impl;
   Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
   XID xid = GDK_WINDOW_XID (window);
   XID xparent = GDK_WINDOW_XID (parent);
@@ -619,8 +596,8 @@ setup_toplevel_window (GdkWindow *window,
    * correct value???
    */
   size_hints.flags = PSize;
-  size_hints.width = impl->width;
-  size_hints.height = impl->height;
+  size_hints.width = obj->width;
+  size_hints.height = obj->height;
   
   XSetWMNormalHints (xdisplay, xid, &size_hints);
   
@@ -656,19 +633,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;
@@ -677,117 +655,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;
   
@@ -814,27 +709,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;
@@ -853,12 +738,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;
 
@@ -884,30 +765,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:
@@ -929,11 +812,11 @@ _gdk_window_new (GdkWindow     *parent,
          XFree (class_hint);
        }
   
-      setup_toplevel_window (window, parent);
+      setup_toplevel_window (window, (GdkWindow *)private->parent);
       break;
 
     case GDK_WINDOW_CHILD:
-      if ((attributes->wclass == GDK_INPUT_OUTPUT) &&
+      if (!private->input_only &&
          (draw_impl->colormap != gdk_screen_get_system_colormap (screen)) &&
          (draw_impl->colormap != gdk_drawable_get_colormap (gdk_window_get_toplevel (window))))
        {
@@ -948,8 +831,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
@@ -1027,6 +908,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);
@@ -1044,8 +926,8 @@ gdk_window_foreign_new_for_display (GdkDisplay     *display,
 
   private->x = attrs.x;
   private->y = attrs.y;
-  impl->width = attrs.width;
-  impl->height = attrs.height;
+  private->width = attrs.width;
+  private->height = attrs.height;
   private->window_type = GDK_WINDOW_FOREIGN;
   private->destroyed = FALSE;
 
@@ -1058,10 +940,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;
 }
 
@@ -1140,10 +1024,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;
@@ -1215,8 +1099,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))
@@ -1419,66 +1301,43 @@ set_initial_hints (GdkWindow *window)
 }
 
 static void
-gdk_window_x11_show (GdkWindow *window,
-                     gboolean   raise)
+gdk_window_x11_show (GdkWindow *window)
 {
-  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);
+  GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (private->impl);
+  Display *xdisplay = GDK_WINDOW_XDISPLAY (window);
+  Window xwindow = GDK_WINDOW_XID (window);
+  gboolean unset_bg;
       
-      if (raise)
-        XRaiseWindow (xdisplay, xwindow);
-
-      if (!GDK_WINDOW_IS_MAPPED (window))
-        {
-          set_initial_hints (window);
-          
-          gdk_synthesize_window_state (window,
-                                       GDK_WINDOW_STATE_WITHDRAWN,
-                                       0);
-        }
+  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
@@ -1491,7 +1350,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);
 
@@ -1509,7 +1368,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);
 
@@ -1559,24 +1418,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
@@ -1615,7 +1462,7 @@ window_x11_move (GdkWindow *window,
     {
       _gdk_window_move_resize_child (window,
                                      x, y,
-                                     impl->width, impl->height);
+                                     private->width, private->height);
     }
   else
     {
@@ -1649,7 +1496,6 @@ window_x11_resize (GdkWindow *window,
       _gdk_window_move_resize_child (window,
                                      private->x, private->y,
                                      width, height);
-      _gdk_x11_drawable_update_size (private->impl);
     }
   else
     {
@@ -1661,13 +1507,13 @@ window_x11_resize (GdkWindow *window,
 
       if (impl->override_redirect)
         {
-          impl->width = width;
-          impl->height = height;
+          private->width = width;
+          private->height = height;
           _gdk_x11_drawable_update_size (private->impl);
         }
       else
         {
-          if (width != impl->width || height != impl->height)
+          if (width != private->width || height != private->height)
             private->resize_count += 1;
         }
     }
@@ -1708,14 +1554,14 @@ window_x11_move_resize (GdkWindow *window,
           private->x = x;
           private->y = y;
 
-          impl->width = width;
-          impl->height = height;
+          private->width = width;
+          private->height = height;
 
           _gdk_x11_drawable_update_size (private->impl);
         }
       else
         {
-          if (width != impl->width || height != impl->height)
+          if (width != private->width || height != private->height)
             private->resize_count += 1;
         }
     }
@@ -1750,31 +1596,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);
-
-  window_private->x = x;
-  window_private->y = 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);
 
-  /* 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 */
 
@@ -1782,83 +1622,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));
 }
 
 /**
@@ -1959,10 +1795,11 @@ gdk_window_focus (GdkWindow *window,
                   guint32    timestamp)
 {
   GdkDisplay *display;
-  
-  g_return_if_fail (GDK_IS_WINDOW (window));
 
-  if (GDK_WINDOW_DESTROYED (window))
+  g_return_if_fail (WINDOW_IS_TOPLEVEL (window));
+  
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   display = GDK_WINDOW_DISPLAY (window);
@@ -2032,9 +1869,8 @@ gdk_window_set_hints (GdkWindow *window,
 {
   XSizeHints size_hints;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
   
   size_hints.flags = 0;
@@ -2087,9 +1923,8 @@ gdk_window_set_type_hint (GdkWindow        *window,
   GdkDisplay *display;
   Atom atom;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   display = gdk_drawable_get_display (window);
@@ -2172,7 +2007,8 @@ gdk_window_get_type_hint (GdkWindow *window)
 
   g_return_val_if_fail (GDK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL);
 
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return GDK_WINDOW_TYPE_HINT_NORMAL;
 
   type = GDK_WINDOW_TYPE_HINT_NORMAL;
@@ -2273,9 +2109,8 @@ gdk_window_set_modal_hint (GdkWindow *window,
 {
   GdkWindowObject *private;
 
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   private = (GdkWindowObject*) window;
@@ -2308,10 +2143,10 @@ gdk_window_set_skip_taskbar_hint (GdkWindow *window,
 {
   GdkToplevelX11 *toplevel;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
   
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   toplevel = _gdk_x11_window_get_toplevel (window);
@@ -2345,10 +2180,10 @@ gdk_window_set_skip_pager_hint (GdkWindow *window,
 {
   GdkToplevelX11 *toplevel;
     
-  g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
   
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   toplevel = _gdk_x11_window_get_toplevel (window);
@@ -2376,10 +2211,10 @@ gdk_window_set_urgency_hint (GdkWindow *window,
 {
   GdkToplevelX11 *toplevel;
     
-  g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD);
   
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   toplevel = _gdk_x11_window_get_toplevel (window);
@@ -2424,9 +2259,8 @@ gdk_window_set_geometry_hints (GdkWindow         *window,
 {
   XSizeHints size_hints;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
   
   size_hints.flags = 0;
@@ -2533,7 +2367,8 @@ gdk_window_get_geometry_hints (GdkWindow      *window,
 
   *geom_mask = 0;
   
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
 
   size_hints = XAllocSizeHints ();
@@ -2688,10 +2523,10 @@ gdk_window_set_title (GdkWindow   *window,
   Display *xdisplay;
   Window xwindow;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (title != NULL);
 
-  if (GDK_WINDOW_DESTROYED (window))
+  if (GDK_WINDOW_DESTROYED (window) ||
+      !WINDOW_IS_TOPLEVEL (window))
     return;
   
   display = gdk_drawable_get_display (window);
@@ -2738,11 +2573,10 @@ gdk_window_set_role (GdkWindow   *window,
 {
   GdkDisplay *display;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
-
   display = gdk_drawable_get_display (window);
 
-  if (!GDK_WINDOW_DESTROYED (window))
+  if (!GDK_WINDOW_DESTROYED (window) &&
+      WINDOW_IS_TOPLEVEL (window))
     {
       if (role)
        XChangeProperty (GDK_DISPLAY_XDISPLAY (display), GDK_WINDOW_XID (window),
@@ -2767,7 +2601,7 @@ gdk_window_set_role (GdkWindow   *window,
  **/
 void          
 gdk_window_set_startup_id (GdkWindow   *window,
-                    const gchar *startup_id)
+                          const gchar *startup_id)
 {
   GdkDisplay *display;
   
@@ -2775,13 +2609,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"));
@@ -2806,9 +2641,8 @@ void
 gdk_window_set_transient_for (GdkWindow *window, 
                              GdkWindow *parent)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (parent))
+  if (!GDK_WINDOW_DESTROYED (window) && !GDK_WINDOW_DESTROYED (parent) &&
+      WINDOW_IS_TOPLEVEL (window))
     XSetTransientForHint (GDK_WINDOW_XDISPLAY (window), 
                          GDK_WINDOW_XID (window),
                          GDK_WINDOW_XID (parent));
@@ -2818,62 +2652,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),
@@ -2996,81 +2790,54 @@ gdk_window_x11_get_origin (GdkWindow *window,
   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;
 }
@@ -3092,8 +2859,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)
@@ -3138,7 +2903,6 @@ gdk_window_get_frame_extents (GdkWindow    *window,
   gint wx, wy;
   gboolean got_frame_extents = FALSE;
   
-  g_return_if_fail (GDK_IS_WINDOW (window));
   g_return_if_fail (rect != NULL);
   
   private = (GdkWindowObject*) window;
@@ -3148,9 +2912,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;
 
@@ -3343,12 +3104,9 @@ _gdk_windowing_window_get_pointer (GdkDisplay      *display,
   int winx = 0;
   int winy = 0;
   unsigned int xmask = 0;
-  gint xoffset, yoffset;
 
   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
   
-  _gdk_x11_window_get_offsets (window, &xoffset, &yoffset);
-
   return_val = NULL;
   if (!GDK_WINDOW_DESTROYED (window)) 
     {
@@ -3374,8 +3132,8 @@ _gdk_windowing_window_get_pointer (GdkDisplay      *display,
        }
     }
   
-  *x = winx + xoffset;
-  *y = winy + yoffset;
+  *x = winx;
+  *y = winy;
   *mask = xmask;
   
   return return_val;
@@ -3420,7 +3178,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;
@@ -3529,7 +3288,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;
 }
 
@@ -3564,7 +3325,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++)
@@ -3624,112 +3384,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;
-  
-#ifdef HAVE_SHAPE_EXT
-  if (GDK_WINDOW_DESTROYED (window))
-    return;
-
-  _gdk_x11_window_get_offsets (window, &xoffset, &yoffset);
-
-  if (xoffset != 0 || yoffset != 0)
-    {
-      WARN_SHAPE_TOO_BIG ();
-      return;
-    }
-  
-  if (shape == ShapeBounding
-      ? gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window))
-      : gdk_display_supports_input_shapes (GDK_WINDOW_DISPLAY (window)))
-    {
-      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);
-    }
-#endif /* HAVE_SHAPE_EXT */
-}
-
-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,
@@ -3738,24 +3392,38 @@ do_shape_combine_region (GdkWindow       *window,
                         gint             shape)
 {
   GdkWindowObject *private = (GdkWindowObject *)window;
-  gint xoffset, yoffset;
   
 #ifdef HAVE_SHAPE_EXT
   if (GDK_WINDOW_DESTROYED (window))
     return;
 
-  _gdk_x11_window_get_offsets (window, &xoffset, &yoffset);
-
-  if (xoffset != 0 || yoffset != 0)
-    {
-      WARN_SHAPE_TOO_BIG ();
-      return;
-    }
-  
   if (shape_region == NULL)
     {
       /* Use NULL mask to unset the shape */
-      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;
     }
   
@@ -3766,12 +3434,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,
@@ -3780,6 +3454,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);
     }
 #endif /* HAVE_SHAPE_EXT */
@@ -3794,37 +3474,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);
@@ -3853,9 +3507,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);
@@ -3889,8 +3542,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;
@@ -3899,7 +3550,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);
     }
 }
@@ -3926,8 +3578,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;
@@ -3935,8 +3585,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);
     }
 }
@@ -3971,9 +3623,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);
@@ -4043,9 +3694,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);
@@ -4155,10 +3805,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);
@@ -4220,9 +3870,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);
@@ -4267,9 +3916,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))
@@ -4301,9 +3949,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))
@@ -4337,9 +3984,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))
@@ -4394,9 +4040,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))
@@ -4438,9 +4083,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))
@@ -4473,9 +4117,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))
@@ -4511,9 +4154,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))
@@ -4547,9 +4189,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))
@@ -4586,7 +4227,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))
@@ -4627,7 +4269,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))
@@ -4661,10 +4304,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);
@@ -4698,7 +4341,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);
@@ -4823,8 +4468,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));
@@ -4849,8 +4496,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)
@@ -4895,6 +4544,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));
@@ -4904,409 +4557,108 @@ gdk_window_set_functions (GdkWindow    *window,
   gdk_window_set_mwm_hints (window, &hints);
 }
 
-#ifdef HAVE_SHAPE_EXT
-
-/* 
- * 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;
   
-  if (noo)
-    {
-      noo->start = x;
-      noo->end = xx;
-      if (ptr2)
-       {
-         noo->next = ptr2->next;
-         ptr2->next = noo;
-       }
-      else
-       {
-         noo->next = NULL;
-         *s = noo;
-       }
-    }
-  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);
-    }
-}
-
-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);
+#if defined(HAVE_SHAPE_EXT)
+  xrl = XShapeGetRectangles (xdisplay,
+                            window,
+                            shape_type, &rn, &ord);
   
-  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++)
+  if (rn == 0)
+    return gdk_region_new (); /* Empty */
+  
+  if (ord != YXBanded)
     {
-      ptr1 = spans[i];
-      while (ptr1)
-       {
-         ptr2 = ptr1;
-         ptr1 = ptr1->next;
-         g_free (ptr2);
-       }
+      /* 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;
     }
-  g_free (spans);
-}
 
-#endif /* HAVE_SHAPE_EXT */
-
-static inline void
-do_child_shapes (GdkWindow *window,
-                 gboolean   merge)
-{
-#ifdef HAVE_SHAPE_EXT
-  if (!GDK_WINDOW_DESTROYED (window) &&
-      gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
+  rl = g_new (GdkRectangle, rn);
+  for (i = 0; i < rn; i++)
     {
-      gdk_propagate_shapes (GDK_WINDOW_XDISPLAY (window),
-                            GDK_WINDOW_XID (window),
-                            merge,
-                            ShapeBounding);
+      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);
 #endif
+  
+  return shape;
 }
 
-static void
-gdk_window_x11_set_child_shapes (GdkWindow *window)
-{
-  do_child_shapes (window, FALSE);
-}
 
-static void
-gdk_window_x11_merge_child_shapes (GdkWindow *window)
+GdkRegion *
+_gdk_windowing_get_shape_for_mask (GdkBitmap *mask)
 {
-  do_child_shapes (window, TRUE);
+  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);
+  
+  region = xwindow_get_shape (GDK_DISPLAY_XDISPLAY (display),
+                             window, ShapeBounding);
+
+  XDestroyWindow (GDK_DISPLAY_XDISPLAY (display),
+                 window);
+
+  return region;
 }
 
-static inline void
-do_child_input_shapes (GdkWindow *window,
-                       gboolean   merge)
+GdkRegion *
+_gdk_windowing_window_get_shape (GdkWindow *window)
 {
-#if defined(HAVE_SHAPE_EXT) && defined(ShapeInput)
+#if defined(HAVE_SHAPE_EXT)
   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), ShapeBounding);
 #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);
+  return NULL;
 }
 
-/**
- * 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)
+GdkRegion *
+_gdk_windowing_window_get_input_shape (GdkWindow *window)
 {
-  g_return_if_fail (GDK_IS_WINDOW (window));
-  
-  do_child_input_shapes (window, TRUE);
-}
+#if defined(HAVE_SHAPE_EXT)
+  if (!GDK_WINDOW_DESTROYED (window) &&
+      gdk_display_supports_shapes (GDK_WINDOW_DISPLAY (window)))
+    return xwindow_get_shape (GDK_WINDOW_XDISPLAY (window),
+                             GDK_WINDOW_XID (window),
+                             ShapeInput);
+#endif
 
+  return NULL;
+}
 
 static void
 gdk_window_set_static_bit_gravity (GdkWindow *window,
@@ -5939,9 +5291,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),
@@ -5974,9 +5325,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),
@@ -6010,12 +5360,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_set_has_native (window, TRUE);
+  
       impl->use_synchronized_configure = TRUE;
       ensure_sync_counter (window);
     }
@@ -6041,7 +5396,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)
@@ -6082,6 +5438,11 @@ gdk_window_beep (GdkWindow *window)
 {
   GdkDisplay *display;
 
+  g_return_if_fail (GDK_IS_WINDOW (window));
+
+  if (GDK_WINDOW_DESTROYED (window))
+    return;
+  
   display = GDK_WINDOW_DISPLAY (window);
 
 #ifdef HAVE_XKB
@@ -6123,7 +5484,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);
@@ -6181,6 +5543,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)
 {
@@ -6189,24 +5568,23 @@ 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_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;
 }
 
 #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 924ac99842dc5e68ef27c5098dac5f0a2ce7a2af..48e440550c54069e2ae44afc910eb8e4bffef96a 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                   \
        testprint                       \
        testrgb                         \
        testrecentchooser               \
@@ -78,6 +80,7 @@ noinst_PROGRAMS =  $(TEST_PROGS)      \
        testtreesort                    \
        treestoretest                   \
        testxinerama                    \
+       testwindows                     \
        pixbuf-read                     \
        pixbuf-lowmem                   \
        pixbuf-randomly-modified        \
@@ -103,6 +106,7 @@ endif
 
 endif
 
+flicker_DEPENDENCIES = $(TEST_DEPS)
 simple_DEPENDENCIES = $(TEST_DEPS)
 print_editor_DEPENDENCIES = $(TEST_DEPS)
 testicontheme_DEPENDENCIES = $(TEST_DEPS)
@@ -133,6 +137,7 @@ testmultidisplay_DEPENDENCIES = $(TEST_DEPS)
 testmultiscreen_DEPENDENCIES = $(TEST_DEPS)
 testnotebookdnd_DEPENDENCIES = $(TEST_DEPS)
 testnouiprint_DEPENDENCIES = $(TEST_DEPS)
+testoffscreen_DEPENDENCIES = $(TEST_DEPS)
 testprint_DEPENDENCIES = $(TEST_DEPS)
 testrecentchooser_DEPENDENCIES = $(TEST_DEPS)
 testrecentchoosermenu_DEPENDENCIES = $(TEST_DEPS)
@@ -160,7 +165,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)
@@ -191,6 +198,7 @@ testmultidisplay_LDADD = $(LDADDS)
 testmultiscreen_LDADD = $(LDADDS)
 testnotebookdnd_LDADD = $(LDADDS)
 testnouiprint_LDADD = $(LDADDS)
+testoffscreen_LDADD = $(LDADDS)
 testprint_LDADD = $(LDADDS)
 testrecentchooser_LDADD = $(LDADDS)
 testrecentchoosermenu_LDADD = $(LDADDS)
@@ -225,6 +233,7 @@ testactions_LDADD = $(LDADDS)
 testgrouping_LDADD = $(LDADDS)
 testtooltips_LDADD = $(LDADDS)
 testvolumebutton_LDADD = $(LDADDS)
+testwindows_LDADD = $(LDADDS)
 
 
 testentrycompletion_SOURCES =  \
@@ -317,6 +326,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..5a0749b
--- /dev/null
@@ -0,0 +1,478 @@
+/*
+ * 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
+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 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);
+
+  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 (NULL,
+                                                    &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);
+
+  /* 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 (NULL,
+                                                    &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);
+
+  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..842f856
--- /dev/null
@@ -0,0 +1,1035 @@
+#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
+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_set_has_native (window, TRUE);
+      
+      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_set_has_native (window, TRUE);
+    }
+  
+  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 ("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;
+}