]> Pileus Git - ~andy/gtk/blobdiff - gdk/win32/gdkgeometry-win32.c
Updated Norwegian bokmål translation.
[~andy/gtk] / gdk / win32 / gdkgeometry-win32.c
index bd14f1bdb58ff938e9c64e5d01f95364d5262a21..61dbf762876a52a32580e9d43492d40cc5a91692 100644 (file)
  */
 
 /* gdkgeometry-win32.c: emulation of 32 bit coordinates within the
- * limits of Win32 GDI. Just a copy of the X11 version, more or less.
- * Probably totally bogus in functionality. Just a quick hack, to
- * get the thing to build. Need to write some test code for it.
- * Well, need to find out what it is supposed to do first ;-)
+ * limits of Win32 GDI. The idea of big window emulation is more or less
+ * a copy of the X11 version, and the equvalent of guffaw scrolling
+ * is ScrollWindowEx(). While we determine the invalidated region
+ * ourself during scrolling, we do not pass SW_INVALIDATE to
+ * ScrollWindowEx() to avoid a unnecessary WM_PAINT.
  *
+ * Bits are always scrolled correctly by ScrollWindowEx(), but
+ * some big children may hit the coordinate boundary (i.e.
+ * win32_x/win32_y < -16383) after scrolling. They needed to be moved
+ * back to the real position determined by gdk_window_compute_position().
+ * This is handled in gdk_window_postmove().
+ * 
  * The X11 version by Owen Taylor <otaylor@redhat.com>
  * Copyright Red Hat, Inc. 2000
  * Win32 hack by Tor Lillqvist <tml@iki.fi>
+ * and Hans Breuer <hans@breuer.org>
+ * Modified by Ivan, Wong Yat Cheung <email@ivanwong.info>
+ * so that big window emulation finally works.
  */
 
+#include "config.h"
 #include "gdk.h"               /* For gdk_rectangle_intersect */
 #include "gdkregion.h"
 #include "gdkregion-generic.h"
-#include "gdkinternals.h"
 #include "gdkprivate-win32.h"
-#include "gdkdrawable-win32.h"
-#include "gdkwindow-win32.h"
-
-typedef struct _GdkWindowQueueItem GdkWindowQueueItem;
-typedef struct _GdkWindowParentPos GdkWindowParentPos;
 
-typedef enum {
-  GDK_WINDOW_QUEUE_TRANSLATE,
-  GDK_WINDOW_QUEUE_ANTIEXPOSE
-} GdkWindowQueueType;
+#define SIZE_LIMIT 32767
 
-struct _GdkWindowQueueItem
-{
-  GdkWindow *window;
-  gulong serial;
-  GdkWindowQueueType type;
-  union {
-    struct {
-      gint dx;
-      gint dy;
-    } translate;
-    struct {
-      GdkRegion *area;
-    } antiexpose;
-  } u;
-};
+typedef struct _GdkWindowParentPos GdkWindowParentPos;
 
 struct _GdkWindowParentPos
 {
@@ -69,30 +57,27 @@ struct _GdkWindowParentPos
   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_premove            (GdkWindow          *window,
-                                          GdkWindowParentPos *parent_pos);
+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);
-static void gdk_window_queue_translation  (GdkWindow          *window,
-                                          gint                dx,
-                                          gint                dy);
+                                          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 void gdk_window_clip_changed       (GdkWindow          *window,
+static GdkRegion *gdk_window_clip_changed (GdkWindow          *window,
                                           GdkRectangle       *old_clip,
                                           GdkRectangle       *new_clip);
-
-static GSList *translate_queue = NULL;
+static void gdk_window_post_scroll        (GdkWindow          *window,
+                                          GdkRegion          *new_clip_region);
 
 void
-_gdk_windowing_window_get_offsets (GdkWindow *window,
-                                  gint      *x_offset,
-                                  gint      *y_offset)
+_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);
@@ -108,108 +93,144 @@ _gdk_window_init_position (GdkWindow *window)
   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);
 }
 
-/**
- * gdk_window_scroll:
- * @window: a #GdkWindow
- * @dx: Amount to scroll in the X direction
- * @dy: Amount to scroll in the Y direction
- * 
- * Scroll the contents of its window, both pixels and children, by
- * the given amount. Portions of the window that the scroll operation
- * brings in from offscreen areas are invalidated. The invalidated
- * region may be bigger than what would strictly be necessary.
- * (For X11, a minimum area will be invalidated if the window has
- * no subwindows, or if the edges of the window's parent do not extend
- * beyond the edges of the window. In other cases, a multi-step process
- * is used to scroll the window which may produce temporary visual
- * artifacts and unnecessary invalidations.)
- **/
 void
-gdk_window_scroll (GdkWindow *window,
-                  gint       dx,
-                  gint       dy)
+_gdk_win32_window_scroll (GdkWindow *window,
+                         gint       dx,
+                         gint       dy)
 {
-  gboolean can_guffaw_scroll = FALSE;
+  GdkRegion *invalidate_region;
   GdkWindowImplWin32 *impl;
   GdkWindowObject *obj;
-  
-  g_return_if_fail (GDK_IS_WINDOW (window));
+  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);  
-  
-  if (GDK_WINDOW_DESTROYED (window))
-    return;
 
-  /* We can guffaw scroll if we are a child window, and the parent
-   * does not extend beyond our edges.
-   */
+  /* Move the current invalid region */
+  if (obj->update_area)
+    gdk_region_offset (obj->update_area, dx, dy);
   
-  if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
-    {
-      GdkWindowImplWin32 *parent_impl = GDK_WINDOW_IMPL_WIN32 (obj->parent->impl);  
-      can_guffaw_scroll = (obj->x <= 0 &&
-                          obj->y <= 0 &&
-                          obj->x + impl->width >= parent_impl->width &&
-                          obj->y + impl->height >= parent_impl->height);
-    }
+  gdk_window_compute_parent_pos (impl, &parent_pos);
 
-  if (!obj->children || !can_guffaw_scroll)
-    {
-      /* Use ScrollWindowEx, then move any children later
-       */
-      GList *tmp_list;
-      GdkRegion *invalidate_region;
-      GdkRectangle dest_rect;
+  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;
 
-      invalidate_region = gdk_region_rectangle (&impl->position_info.clip_rect);
-      
-      dest_rect = impl->position_info.clip_rect;
-      dest_rect.x += dx;
-      dest_rect.y += dy;
-      gdk_rectangle_intersect (&dest_rect, &impl->position_info.clip_rect, &dest_rect);
+  gdk_window_tmp_unset_bg (window);
 
-      if (dest_rect.width > 0 && dest_rect.height > 0)
-       {
-         GdkRegion *tmp_region;
+  native_invalidate_region = CreateRectRgn (0, 0, 0, 0);
+  if (native_invalidate_region == NULL)
+    WIN32_API_FAILED ("CreateRectRgn");
 
-         tmp_region = gdk_region_rectangle (&dest_rect);
-         gdk_region_subtract (invalidate_region, tmp_region);
-         gdk_region_destroy (tmp_region);
-         
-         gdk_window_queue_translation (window, dx, dy);
+  API_CALL (ScrollWindowEx, (GDK_WINDOW_HWND (window),
+                            dx, dy, NULL, NULL,
+                            native_invalidate_region, NULL, SW_SCROLLCHILDREN));
 
-         if (ScrollWindowEx (GDK_WINDOW_HWND (window), dx, dy,
-                             NULL, NULL, NULL, NULL, 0) == ERROR)
-           WIN32_API_FAILED ("ScrollWindowEx");
-       }
+  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);
-
-      tmp_list = obj->children;
-      while (tmp_list)
-       {
-         GdkWindow * child = GDK_WINDOW (tmp_list->data);
-         
-         gdk_window_move (child, obj->x + dx, obj->y + dy);
-         
-         tmp_list = tmp_list->next;
-       }
+      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
     {
-      /* Guffaw scroll
-       */
-      g_warning ("gdk_window_scroll(): guffaw scrolling not yet implemented");
+      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));
 }
 
 void
@@ -223,28 +244,40 @@ _gdk_window_move_resize_child (GdkWindow *window,
   GdkWindowObject *obj;
   GdkWin32PositionInfo new_info;
   GdkWindowParentPos parent_pos;
-  RECT rect;
   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);
+  
+  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));
 
   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;
+    {
+      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" : ""));
+
   obj->x = x;
   obj->y = y;
   impl->width = width;
@@ -253,7 +286,8 @@ _gdk_window_move_resize_child (GdkWindow *window,
   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);
+  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;
@@ -266,131 +300,99 @@ _gdk_window_move_resize_child (GdkWindow *window,
   
   if (d_xoffset != 0 || d_yoffset != 0)
     {
-      gint new_x0, new_y0, new_x1, new_y1;
-
-      gdk_window_set_static_gravities (window, TRUE);
-
-      if (d_xoffset < 0 || d_yoffset < 0)
-       gdk_window_queue_translation (window, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
-       
-      if (d_xoffset < 0)
-       {
-         new_x0 = impl->position_info.x + d_xoffset;
-         new_x1 = impl->position_info.x + impl->position_info.width;
-       }
-      else
+      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)
        {
-         new_x0 = impl->position_info.x;
-         new_x1 = impl->position_info.x + new_info.width + d_xoffset;
+         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 (d_yoffset < 0)
-       {
-         new_y0 = impl->position_info.y + d_yoffset;
-         new_y1 = impl->position_info.y + impl->position_info.height;
-       }
-      else
-       {
-         new_y0 = impl->position_info.y;
-         new_y1 = impl->position_info.y + new_info.height + d_yoffset;
-       }
-      
-      if (!MoveWindow (GDK_WINDOW_HWND (window),
-                      new_x0, new_y0, new_x1 - new_x0, new_y1 - new_y0,
-                      FALSE))
-         WIN32_API_FAILED ("MoveWindow");
-      
-      tmp_list = obj->children;
-      while (tmp_list)
-       {
-         gdk_window_premove (tmp_list->data, &parent_pos);
-         tmp_list = tmp_list->next;
-       }
-
-      GetClientRect (GDK_WINDOW_HWND (window), &rect);
-
-      if (!MoveWindow (GDK_WINDOW_HWND (window),
-                      new_x0 + dx, new_y0 + dy,
-                      rect.right - rect.left, rect.bottom - rect.top,
-                      FALSE))
-         WIN32_API_FAILED ("MoveWindow");
-      
-      if (d_xoffset > 0 || d_yoffset > 0)
-       gdk_window_queue_translation (window, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
-      
-      if (!MoveWindow (GDK_WINDOW_HWND (window),
-                      new_info.x, new_info.y, new_info.width, new_info.height,
-                      FALSE))
-         WIN32_API_FAILED ("MoveWindow");
-      
       if (impl->position_info.no_bg)
        gdk_window_tmp_reset_bg (window);
 
-      if (!impl->position_info.mapped && new_info.mapped && obj->mapped)
-       ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNA);
-      
+      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);
+         gdk_window_postmove (tmp_list->data, &parent_pos, FALSE);
          tmp_list = tmp_list->next;
        }
     }
   else
     {
-      if (is_move && is_resize)
-       gdk_window_set_static_gravities (window, FALSE);
-
       if (impl->position_info.mapped && !new_info.mapped)
-       ShowWindow (GDK_WINDOW_HWND (window), SW_HIDE);
-      
-      tmp_list = obj->children;
-      while (tmp_list)
-       {
-         gdk_window_premove (tmp_list->data, &parent_pos);
-         tmp_list = tmp_list->next;
-       }
-
-      /*
-       * HB: Passing TRUE(=Redraw) to MoveWindow here fixes some
-       * redraw problems with (e.g. testgtk main buttons)
-       * scrolling. AFAIK the non flicker optimization would
-       * be done by the GDI anyway, if the window is SW_HIDE.
-       */
-      if (is_resize)
        {
-         if (!MoveWindow (GDK_WINDOW_HWND (window),
-                          new_info.x, new_info.y, new_info.width, new_info.height,
-                          TRUE /*FALSE*/))
-           WIN32_API_FAILED ("MoveWindow");
-       }
-      else
-       {
-         GetClientRect (GDK_WINDOW_HWND (window), &rect);
-         if (!MoveWindow (GDK_WINDOW_HWND (window),
-                          new_info.x, new_info.y,
-                          rect.right - rect.left, rect.bottom - rect.top,
-                          TRUE /*FALSE*/))
-           WIN32_API_FAILED ("MoveWindow");
+         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);
+         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 && obj->mapped)
-       ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNA);
+      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);
 }
 
 static void
@@ -401,14 +403,14 @@ gdk_window_compute_position (GdkWindowImplWin32   *window,
   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;
   
-  if (window->width <= 32768)
+  if (window->width <= SIZE_LIMIT)
     {
       info->width = window->width;
       info->x = parent_pos->x + wrapper->x - parent_pos->win32_x;
@@ -416,19 +418,19 @@ gdk_window_compute_position (GdkWindowImplWin32   *window,
   else
     {
       info->big = TRUE;
-      info->width = 32768;
-      if (parent_pos->x + wrapper->x < -16384)
+      info->width = SIZE_LIMIT;
+      if (parent_pos->x + wrapper->x < -(SIZE_LIMIT/2))
        {
-         if (parent_pos->x + wrapper->x + window->width < 16384)
-           info->x = parent_pos->x + wrapper->x + window->width - 32768 - parent_pos->win32_x;
+         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 = -16384 - parent_pos->win32_y;
+           info->x = -(SIZE_LIMIT/2) - parent_pos->win32_x;
        }
       else
        info->x = parent_pos->x + wrapper->x - parent_pos->win32_x;
     }
 
-  if (window->height <= 32768)
+  if (window->height <= SIZE_LIMIT)
     {
       info->height = window->height;
       info->y = parent_pos->y + wrapper->y - parent_pos->win32_y;
@@ -436,13 +438,13 @@ gdk_window_compute_position (GdkWindowImplWin32   *window,
   else
     {
       info->big = TRUE;
-      info->height = 32768;
-      if (parent_pos->y + wrapper->y < -16384)
+      info->height = SIZE_LIMIT;
+      if (parent_pos->y + wrapper->y < -(SIZE_LIMIT/2))
        {
-         if (parent_pos->y + wrapper->y + window->height < 16384)
-           info->y = parent_pos->y + wrapper->y + window->height - 32768 - parent_pos->win32_y;
+         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 = -16384 - parent_pos->win32_y;
+           info->y = -(SIZE_LIMIT/2) - parent_pos->win32_y;
        }
       else
        info->y = parent_pos->y + wrapper->y - parent_pos->win32_y;
@@ -552,8 +554,9 @@ gdk_window_compute_parent_pos (GdkWindowImplWin32 *window,
 }
 
 static void
-gdk_window_premove (GdkWindow          *window,
-                   GdkWindowParentPos *parent_pos)
+gdk_window_postmove (GdkWindow          *window,
+                    GdkWindowParentPos *parent_pos,
+                    gboolean            anti_scroll)
 {
   GdkWindowImplWin32 *impl;
   GdkWindowObject *obj;
@@ -561,13 +564,15 @@ gdk_window_premove (GdkWindow          *window,
   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);
 
-  gdk_window_clip_changed (window, &impl->position_info.clip_rect, &new_info.clip_rect);
+  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;
@@ -581,86 +586,23 @@ gdk_window_premove (GdkWindow          *window,
   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)
-    {
-      gint new_x0, new_y0, new_x1, new_y1;
-
-      if (d_xoffset < 0 || d_yoffset < 0)
-       gdk_window_queue_translation (window, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
-       
-      if (d_xoffset < 0)
-       {
-         new_x0 = impl->position_info.x + d_xoffset;
-         new_x1 = impl->position_info.x + impl->position_info.width;
-       }
-      else
-       {
-         new_x0 = impl->position_info.x;
-         new_x1 = impl->position_info.x + new_info.width + d_xoffset;
-       }
-
-      if (d_yoffset < 0)
-       {
-         new_y0 = impl->position_info.y + d_yoffset;
-         new_y1 = impl->position_info.y + impl->position_info.height;
-       }
-      else
-       {
-         new_y0 = impl->position_info.y;
-         new_y1 = impl->position_info.y + new_info.height + d_yoffset;
-       }
-
-      if (!MoveWindow (GDK_WINDOW_HWND (window),
-                      new_x0, new_y0, new_x1 - new_x0, new_y1 - new_y0,
-                      FALSE))
-       WIN32_API_FAILED ("MoveWindow");
-    }
-
-  tmp_list = obj->children;
-  while (tmp_list)
+  if (anti_scroll || (anti_scroll = d_xoffset != 0 || d_yoffset != 0))
     {
-      gdk_window_premove (tmp_list->data, &this_pos);
-      tmp_list = tmp_list->next;
+      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));
     }
-}
 
-static void
-gdk_window_postmove (GdkWindow          *window,
-                    GdkWindowParentPos *parent_pos)
-{
-  GdkWindowImplWin32 *impl;
-  GdkWindowObject *obj;
-  GdkWin32PositionInfo new_info;
-  GList *tmp_list;
-  gint d_xoffset, d_yoffset;
-  GdkWindowParentPos this_pos;
-  
-  obj = (GdkWindowObject *) window;
-  impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
-  
-  gdk_window_compute_position (impl, parent_pos, &new_info);
-
-  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;
-
-  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, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
-       
-      if (!MoveWindow (GDK_WINDOW_HWND (window),
-                      new_info.x, new_info.y, new_info.width, new_info.height,
-                      FALSE))
-       WIN32_API_FAILED ("MoveWindow");
-    }
-
-  if (!impl->position_info.mapped && new_info.mapped && obj->mapped)
+  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)
@@ -668,132 +610,51 @@ gdk_window_postmove (GdkWindow          *window,
 
   impl->position_info = new_info;
 
+  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);
+      gdk_window_postmove (tmp_list->data, &this_pos, anti_scroll);
       tmp_list = tmp_list->next;
     }
 }
 
-static void
-gdk_window_queue_translation (GdkWindow *window,
-                             gint       dx,
-                             gint       dy)
-{
-  GdkWindowQueueItem *item = g_new (GdkWindowQueueItem, 1);
-  item->window = window;
-  item->serial = GetMessageTime ();
-  item->type = GDK_WINDOW_QUEUE_TRANSLATE;
-  item->u.translate.dx = dx;
-  item->u.translate.dy = dy;
-
-  GDK_NOTE (EVENTS, g_print ("gdk_window_queue_translation %#x %ld %d,%d\n",
-                            (guint) GDK_WINDOW_HWND (window),
-                            item->serial,
-                            dx, dy));
-
-  gdk_drawable_ref (window);
-  translate_queue = g_slist_append (translate_queue, item);
-}
-
 gboolean
 _gdk_windowing_window_queue_antiexpose (GdkWindow *window,
                                        GdkRegion *area)
 {
-#if 0
-  GdkWindowQueueItem *item = g_new (GdkWindowQueueItem, 1);
-
-  item->window = window;
-  item->serial = GetMessageTime ();
-  item->type = GDK_WINDOW_QUEUE_ANTIEXPOSE;
-  item->u.antiexpose.area = area;
-
-  GDK_NOTE (EVENTS, g_print ("_gdk_windowing_window_queue_antiexpose %#x %ld %dx%d@+%d+%d\n",
-                            (guint) GDK_WINDOW_HWND (window),
-                            item->serial,
-                            area->extents.x2 - area->extents.x1,
-                            area->extents.y2 - area->extents.y1,
-                            area->extents.x1, area->extents.y1));
-
-  gdk_drawable_ref (window);
-  translate_queue = g_slist_append (translate_queue, item);
-
-  return TRUE;
-#else
-  GdkRectangle r;
-  HRGN hrgn;
+  HRGN hrgn = _gdk_win32_gdkregion_to_hrgn (area, 0, 0);
 
-  gdk_region_get_clipbox (area, &r);
-  hrgn = CreateRectRgn(r.x, r.y, r.width+1, r.height+1);
+  GDK_NOTE (EVENTS, g_print ("_gdk_windowing_window_queue_antiexpose: ValidateRgn %p %s\n",
+                            GDK_WINDOW_HWND (window),
+                            _gdk_win32_gdkregion_to_string (area)));
 
-  g_return_val_if_fail (area != NULL, FALSE);
+  ValidateRgn (GDK_WINDOW_HWND (window), hrgn);
 
-  GDK_NOTE (MISC, g_print ("_gdk_windowing_window_queue_antiexpose %#x\n",
-                          (guint) GDK_WINDOW_HWND (window)));
+  DeleteObject (hrgn);
 
-  /* HB: not quite sure if this is the right thing to do.
-   * (Region not to be proceesed by next WM_PAINT)
-   */
-  ValidateRgn(GDK_WINDOW_HWND (window), hrgn);
-  DeleteObject(hrgn);
-  return TRUE;
-#endif
+  return FALSE;
 }
 
 void
-_gdk_window_process_expose (GdkWindow    *window,
-                           gulong        serial,
-                           GdkRectangle *area)
+_gdk_window_process_expose (GdkWindow *window,
+                           GdkRegion *invalidate_region)
 {
   GdkWindowImplWin32 *impl;
-  GdkRegion *invalidate_region = gdk_region_rectangle (area);
   GdkRegion *clip_region;
-  GSList *tmp_list = translate_queue;
-
   impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
   
-  GDK_NOTE (EVENTS, g_print ("_gdk_window_process_expose %#x %ld %dx%d@+%d+%d\n",
-                            (guint) GDK_WINDOW_HWND (window), serial,
-                            area->width, area->height, area->x, area->y));
-
-  while (tmp_list)
-    {
-      GdkWindowQueueItem *item = tmp_list->data;
-      tmp_list = tmp_list->next;
-
-      if (serial < item->serial)
-       {
-         if (item->window == window)
-           {
-             if (item->type == GDK_WINDOW_QUEUE_TRANSLATE)
-               gdk_region_offset (invalidate_region, - item->u.translate.dx, - item->u.translate.dy);
-             else              /* anti-expose */
-               gdk_region_subtract (invalidate_region, item->u.antiexpose.area);
-           }
-       }
-      else
-       {
-         GSList *tmp_link = translate_queue;
-         
-         translate_queue = g_slist_remove_link (translate_queue, translate_queue);
-         gdk_drawable_unref (item->window);
-
-         if (item->type == GDK_WINDOW_QUEUE_ANTIEXPOSE)
-           gdk_region_destroy (item->u.antiexpose.area);
-         
-         g_free (item);
-         g_slist_free_1 (tmp_link);
-       }
-    }
-
+  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);
 
   if (!gdk_region_empty (invalidate_region))
     gdk_window_invalidate_region (window, invalidate_region, FALSE);
-
-  gdk_region_destroy (invalidate_region);
+  
   gdk_region_destroy (clip_region);
 }
 
@@ -808,8 +669,12 @@ gdk_window_tmp_unset_bg (GdkWindow *window)
 
   impl->position_info.no_bg = TRUE;
 
+  /*
+   * 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 */;
 }
 
 static void
@@ -822,21 +687,9 @@ gdk_window_tmp_reset_bg (GdkWindow *window)
   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
 
   impl->position_info.no_bg = FALSE;
-
-  if (obj->bg_pixmap == GDK_NO_BG)
-    return;
-  
-  if (obj->bg_pixmap)
-    {
-      /* ??? */
-    }
-  else
-    {
-      /* ??? */
-    }
 }
 
-static void
+static GdkRegion *
 gdk_window_clip_changed (GdkWindow    *window,
                         GdkRectangle *old_clip,
                         GdkRectangle *new_clip)
@@ -845,9 +698,9 @@ gdk_window_clip_changed (GdkWindow    *window,
   GdkWindowObject *obj;
   GdkRegion *old_clip_region;
   GdkRegion *new_clip_region;
-
+  
   if (((GdkWindowObject *)window)->input_only)
-    return;
+    return NULL;
 
   obj = (GdkWindowObject *) window;
   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
@@ -864,11 +717,25 @@ gdk_window_clip_changed (GdkWindow    *window,
    */
   gdk_region_subtract (new_clip_region, old_clip_region);
   if (!gdk_region_empty (new_clip_region))
+    gdk_window_tmp_unset_bg (window);
+  else
     {
-      gdk_window_tmp_unset_bg (window);
-      gdk_window_invalidate_region (window, new_clip_region, FALSE);
+      gdk_region_destroy (new_clip_region);
+      new_clip_region = NULL;
     }
+  gdk_region_destroy (old_clip_region);
 
+  return new_clip_region;
+}
+
+static void
+gdk_window_post_scroll (GdkWindow    *window,
+                       GdkRegion    *new_clip_region)
+{
+  GDK_NOTE (EVENTS,
+           g_print ("gdk_window_clip_changed: invalidating region: %s\n",
+                    _gdk_win32_gdkregion_to_string (new_clip_region)));
+
+  gdk_window_invalidate_region (window, new_clip_region, FALSE);
   gdk_region_destroy (new_clip_region);
-  gdk_region_destroy (old_clip_region);
 }