]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkgeometry-win32.c
Include "config.h" instead of <config.h> Command used: find -name
[~andy/gtk] / gdk / win32 / gdkgeometry-win32.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /* gdkgeometry-win32.c: emulation of 32 bit coordinates within the
21  * limits of Win32 GDI. The idea of big window emulation is more or less
22  * a copy of the X11 version, and the equvalent of guffaw scrolling
23  * is ScrollWindowEx(). While we determine the invalidated region
24  * ourself during scrolling, we do not pass SW_INVALIDATE to
25  * ScrollWindowEx() to avoid a unnecessary WM_PAINT.
26  *
27  * Bits are always scrolled correctly by ScrollWindowEx(), but
28  * some big children may hit the coordinate boundary (i.e.
29  * win32_x/win32_y < -16383) after scrolling. They needed to be moved
30  * back to the real position determined by gdk_window_compute_position().
31  * This is handled in gdk_window_postmove().
32  * 
33  * The X11 version by Owen Taylor <otaylor@redhat.com>
34  * Copyright Red Hat, Inc. 2000
35  * Win32 hack by Tor Lillqvist <tml@iki.fi>
36  * and Hans Breuer <hans@breuer.org>
37  * Modified by Ivan, Wong Yat Cheung <email@ivanwong.info>
38  * so that big window emulation finally works.
39  */
40
41 #include "config.h"
42 #include "gdk.h"                /* For gdk_rectangle_intersect */
43 #include "gdkregion.h"
44 #include "gdkregion-generic.h"
45 #include "gdkprivate-win32.h"
46
47 #define SIZE_LIMIT 32767
48
49 typedef struct _GdkWindowParentPos GdkWindowParentPos;
50
51 struct _GdkWindowParentPos
52 {
53   gint x;
54   gint y;
55   gint win32_x;
56   gint win32_y;
57   GdkRectangle clip_rect;
58 };
59
60 static void gdk_window_compute_position   (GdkWindowImplWin32     *window,
61                                            GdkWindowParentPos     *parent_pos,
62                                            GdkWin32PositionInfo   *info);
63 static void gdk_window_compute_parent_pos (GdkWindowImplWin32     *window,
64                                            GdkWindowParentPos     *parent_pos);
65
66 static void gdk_window_postmove           (GdkWindow          *window,
67                                            GdkWindowParentPos *parent_pos,
68                                            gboolean           anti_scroll);
69 static void gdk_window_tmp_unset_bg       (GdkWindow          *window);
70 static void gdk_window_tmp_reset_bg       (GdkWindow          *window);
71 static GdkRegion *gdk_window_clip_changed (GdkWindow          *window,
72                                            GdkRectangle       *old_clip,
73                                            GdkRectangle       *new_clip);
74 static void gdk_window_post_scroll        (GdkWindow          *window,
75                                            GdkRegion          *new_clip_region);
76
77 void
78 _gdk_windowing_window_get_offsets (GdkWindow *window,
79                                    gint      *x_offset,
80                                    gint      *y_offset)
81 {
82   GdkWindowImplWin32 *impl =
83     GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
84
85   *x_offset = impl->position_info.x_offset;
86   *y_offset = impl->position_info.y_offset;
87 }
88
89 void
90 _gdk_window_init_position (GdkWindow *window)
91 {
92   GdkWindowParentPos parent_pos;
93   GdkWindowImplWin32 *impl;
94   
95   g_return_if_fail (GDK_IS_WINDOW (window));
96   
97   impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
98   
99   gdk_window_compute_parent_pos (impl, &parent_pos);
100   gdk_window_compute_position (impl, &parent_pos, &impl->position_info);
101 }
102
103 void
104 gdk_window_scroll (GdkWindow *window,
105                    gint       dx,
106                    gint       dy)
107 {
108   GdkRegion *invalidate_region;
109   GdkWindowImplWin32 *impl;
110   GdkWindowObject *obj;
111   GList *tmp_list;
112   GdkWindowParentPos parent_pos;
113   HRGN native_invalidate_region;
114   
115   g_return_if_fail (GDK_IS_WINDOW (window));
116
117   if (GDK_WINDOW_DESTROYED (window))
118     return;
119   
120   GDK_NOTE (EVENTS, g_print ("gdk_window_scroll: %p %d,%d\n",
121                              GDK_WINDOW_HWND (window), dx, dy));
122
123   obj = GDK_WINDOW_OBJECT (window);
124   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);  
125
126   if (dx == 0 && dy == 0)
127     return;
128   
129   /* Move the current invalid region */
130   if (obj->update_area)
131     gdk_region_offset (obj->update_area, dx, dy);
132   
133   gdk_window_compute_parent_pos (impl, &parent_pos);
134
135   parent_pos.x += obj->x;
136   parent_pos.y += obj->y;
137   parent_pos.win32_x += impl->position_info.x;
138   parent_pos.win32_y += impl->position_info.y;
139   parent_pos.clip_rect = impl->position_info.clip_rect;
140
141   gdk_window_tmp_unset_bg (window);
142
143   native_invalidate_region = CreateRectRgn (0, 0, 0, 0);
144   if (native_invalidate_region == NULL)
145     WIN32_API_FAILED ("CreateRectRgn");
146
147   API_CALL (ScrollWindowEx, (GDK_WINDOW_HWND (window),
148                              dx, dy, NULL, NULL,
149                              native_invalidate_region, NULL, SW_SCROLLCHILDREN));
150
151   if (impl->position_info.no_bg)
152     gdk_window_tmp_reset_bg (window);
153   
154   tmp_list = obj->children;
155   while (tmp_list)
156     {
157       GDK_WINDOW_OBJECT(tmp_list->data)->x += dx;
158       GDK_WINDOW_OBJECT(tmp_list->data)->y += dy;
159       gdk_window_postmove (tmp_list->data, &parent_pos, FALSE);
160       tmp_list = tmp_list->next;
161     }
162
163   if (native_invalidate_region != NULL)
164     {
165       invalidate_region = _gdk_win32_hrgn_to_region (native_invalidate_region);
166       gdk_region_offset (invalidate_region, impl->position_info.x_offset,
167                          impl->position_info.y_offset);
168       gdk_window_invalidate_region (window, invalidate_region, TRUE);
169       gdk_region_destroy (invalidate_region);
170       GDI_CALL (DeleteObject, (native_invalidate_region));
171     }
172 }
173
174 void
175 gdk_window_move_region (GdkWindow       *window,
176                         const GdkRegion *region,
177                         gint             dx,
178                         gint             dy)
179 {
180   GdkRegion *invalidate_region;
181   GdkWindowImplWin32 *impl;
182   GdkWindowObject *obj;
183   GdkRectangle src_rect, dest_rect;
184   HRGN hrgn;
185   RECT clipRect, destRect;
186
187   g_return_if_fail (GDK_IS_WINDOW (window));
188
189   if (GDK_WINDOW_DESTROYED (window))
190     return;
191   
192   obj = GDK_WINDOW_OBJECT (window);
193   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);  
194
195   if (dx == 0 && dy == 0)
196     return;
197   
198   /* Move the current invalid region */
199   if (obj->update_area)
200     gdk_region_offset (obj->update_area, dx, dy);
201   
202   /* impl->position_info.clip_rect isn't meaningful for toplevels */
203   if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
204     src_rect = impl->position_info.clip_rect;
205   else
206     {
207       src_rect.x = 0;
208       src_rect.y = 0;
209       src_rect.width = impl->width;
210       src_rect.height = impl->height;
211     }
212   
213   invalidate_region = gdk_region_rectangle (&src_rect);
214
215   dest_rect = src_rect;
216   dest_rect.x += dx;
217   dest_rect.y += dy;
218   gdk_rectangle_intersect (&dest_rect, &src_rect, &dest_rect);
219
220   if (dest_rect.width > 0 && dest_rect.height > 0)
221     {
222       GdkRegion *tmp_region;
223
224       tmp_region = gdk_region_rectangle (&dest_rect);
225       gdk_region_subtract (invalidate_region, tmp_region);
226       gdk_region_destroy (tmp_region);
227     }
228   
229   /* no guffaw scroll on win32 */
230   hrgn = _gdk_win32_gdkregion_to_hrgn(invalidate_region, 0, 0);
231   gdk_region_destroy (invalidate_region);
232   destRect.left = dest_rect.y;
233   destRect.top = dest_rect.x;
234   destRect.right = dest_rect.x + dest_rect.width;
235   destRect.bottom = dest_rect.y + dest_rect.height;
236   clipRect.left = src_rect.y;
237   clipRect.top = src_rect.x;
238   clipRect.right = src_rect.x + src_rect.width;
239   clipRect.bottom = src_rect.y + src_rect.height;
240
241   g_print ("ScrollWindowEx(%d, %d, ...) - if you see this work, remove trace;)\n", dx, dy);
242   API_CALL(ScrollWindowEx, (GDK_WINDOW_HWND (window),
243                        dx, dy, /* in: scroll offsets */
244                        NULL, /* in: scroll rect, NULL == entire client area */
245                        &clipRect, /* in: restrict to */
246                        hrgn, /* in: update region */
247                        NULL, /* out: update rect */
248                        SW_INVALIDATE));
249   API_CALL(DeleteObject, (hrgn));
250 }
251
252 void
253 _gdk_window_move_resize_child (GdkWindow *window,
254                                gint       x,
255                                gint       y,
256                                gint       width,
257                                gint       height)
258 {
259   GdkWindowImplWin32 *impl;
260   GdkWindowObject *obj;
261   GdkWin32PositionInfo new_info;
262   GdkWindowParentPos parent_pos;
263   GList *tmp_list;
264   gint d_xoffset, d_yoffset;
265   gint dx, dy;
266   gboolean is_move;
267   gboolean is_resize;
268   GdkRegion *new_clip_region;
269   
270   g_return_if_fail (window != NULL);
271   g_return_if_fail (GDK_IS_WINDOW (window));
272
273   obj = GDK_WINDOW_OBJECT (window);
274   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
275   
276   GDK_NOTE (MISC, g_print ("_gdk_window_move_resize_child: %s@%+d%+d %dx%d@%+d%+d\n",
277                            _gdk_win32_drawable_description (window),
278                            obj->x, obj->y,
279                            width, height, x, y));
280
281   dx = x - obj->x;
282   dy = y - obj->y;
283   
284   is_move = dx != 0 || dy != 0;
285   is_resize = impl->width != width || impl->height != height;
286
287   if (!is_move && !is_resize)
288     {
289       GDK_NOTE (MISC, g_print ("... neither move or resize\n"));
290       return;
291     }
292   
293   GDK_NOTE (MISC, g_print ("... %s%s\n",
294                            is_move ? "is_move " : "",
295                            is_resize ? "is_resize" : ""));
296
297   obj->x = x;
298   obj->y = y;
299   impl->width = width;
300   impl->height = height;
301
302   gdk_window_compute_parent_pos (impl, &parent_pos);
303   gdk_window_compute_position (impl, &parent_pos, &new_info);
304
305   new_clip_region =
306     gdk_window_clip_changed (window, &impl->position_info.clip_rect, &new_info.clip_rect);
307
308   parent_pos.x += obj->x;
309   parent_pos.y += obj->y;
310   parent_pos.win32_x += new_info.x;
311   parent_pos.win32_y += new_info.y;
312   parent_pos.clip_rect = new_info.clip_rect;
313
314   d_xoffset = new_info.x_offset - impl->position_info.x_offset;
315   d_yoffset = new_info.y_offset - impl->position_info.y_offset;
316   
317   if (d_xoffset != 0 || d_yoffset != 0)
318     {
319       GDK_NOTE (MISC, g_print ("... d_offset=%+d%+d\n", d_xoffset, d_yoffset));
320
321       if (!ScrollWindowEx (GDK_WINDOW_HWND (window),
322                            -d_xoffset, -d_yoffset, /* in: scroll offsets */
323                            NULL, /* in: scroll rect, NULL == entire client area */
324                            NULL, /* in: restrict to */
325                            NULL, /* in: update region */
326                            NULL, /* out: update rect */
327                            SW_SCROLLCHILDREN))
328         WIN32_API_FAILED ("ScrollWindowEx");
329
330       if (dx != d_xoffset || dy != d_yoffset || is_resize)
331         {
332           GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,%d,%d,%d,%d,"
333                                    "NOACTIVATE|NOZORDER%s%s)\n",
334                                    GDK_WINDOW_HWND (window),
335                                    new_info.x, new_info.y, 
336                                    new_info.width, new_info.height,
337                                    (is_move ? "" : "|NOMOVE"),
338                                    (is_resize ? "" : "|NOSIZE")));
339
340           API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
341                                    new_info.x, new_info.y, 
342                                    new_info.width, new_info.height,
343                                    SWP_NOACTIVATE | SWP_NOZORDER | 
344                                    (is_move ? 0 : SWP_NOMOVE) |
345                                    (is_resize ? 0 : SWP_NOSIZE)));
346         }
347
348       if (impl->position_info.no_bg)
349         gdk_window_tmp_reset_bg (window);
350
351       if (!impl->position_info.mapped && new_info.mapped && GDK_WINDOW_IS_MAPPED (obj))
352         {
353           GDK_NOTE (MISC, g_print ("... ShowWindow(%p, SW_SHOWNA)\n",
354                                    GDK_WINDOW_HWND (window)));
355           ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNA);
356         }
357
358       impl->position_info = new_info;
359       
360       tmp_list = obj->children;
361       while (tmp_list)
362         {
363           gdk_window_postmove (tmp_list->data, &parent_pos, FALSE);
364           tmp_list = tmp_list->next;
365         }
366     }
367   else
368     {
369       if (impl->position_info.mapped && !new_info.mapped)
370         {
371           GDK_NOTE (MISC, g_print ("... ShowWindow(%p, SW_HIDE)\n",
372                                    GDK_WINDOW_HWND (window)));
373           ShowWindow (GDK_WINDOW_HWND (window), SW_HIDE);
374         }
375       
376       GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,%d,%d,%d,%d,"
377                                "NOACTIVATE|NOZORDER%s%s)\n",
378                                GDK_WINDOW_HWND (window),
379                                new_info.x, new_info.y, 
380                                new_info.width, new_info.height,
381                                (is_move ? "" : "|NOMOVE"),
382                                (is_resize ? "" : "|NOSIZE")));
383
384       API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
385                                new_info.x, new_info.y, 
386                                new_info.width, new_info.height,
387                                SWP_NOACTIVATE | SWP_NOZORDER | 
388                                (is_move ? 0 : SWP_NOMOVE) |
389                                (is_resize ? 0 : SWP_NOSIZE)));
390
391       tmp_list = obj->children;
392       while (tmp_list)
393         {
394           gdk_window_postmove (tmp_list->data, &parent_pos, FALSE);
395           tmp_list = tmp_list->next;
396         }
397
398       if (impl->position_info.no_bg)
399         gdk_window_tmp_reset_bg (window);
400
401       if (!impl->position_info.mapped && new_info.mapped && GDK_WINDOW_IS_MAPPED (obj))
402         {
403           GDK_NOTE (MISC, g_print ("... ShowWindow(%p, SW_SHOWNA)\n",
404                                    GDK_WINDOW_HWND (window)));
405           ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNA);
406         }
407
408       impl->position_info = new_info;
409     }
410   if (new_clip_region)
411     gdk_window_post_scroll (window, new_clip_region);
412 }
413
414 static void
415 gdk_window_compute_position (GdkWindowImplWin32   *window,
416                              GdkWindowParentPos   *parent_pos,
417                              GdkWin32PositionInfo *info)
418 {
419   GdkWindowObject *wrapper;
420   int parent_x_offset;
421   int parent_y_offset;
422
423   g_return_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (window));
424
425   wrapper = GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_WIN32 (window)->wrapper);
426   
427   info->big = FALSE;
428   
429   if (window->width <= SIZE_LIMIT)
430     {
431       info->width = window->width;
432       info->x = parent_pos->x + wrapper->x - parent_pos->win32_x;
433     }
434   else
435     {
436       info->big = TRUE;
437       info->width = SIZE_LIMIT;
438       if (parent_pos->x + wrapper->x < -(SIZE_LIMIT/2))
439         {
440           if (parent_pos->x + wrapper->x + window->width < (SIZE_LIMIT/2))
441             info->x = parent_pos->x + wrapper->x + window->width - info->width - parent_pos->win32_x;
442           else
443             info->x = -(SIZE_LIMIT/2) - parent_pos->win32_x;
444         }
445       else
446         info->x = parent_pos->x + wrapper->x - parent_pos->win32_x;
447     }
448
449   if (window->height <= SIZE_LIMIT)
450     {
451       info->height = window->height;
452       info->y = parent_pos->y + wrapper->y - parent_pos->win32_y;
453     }
454   else
455     {
456       info->big = TRUE;
457       info->height = SIZE_LIMIT;
458       if (parent_pos->y + wrapper->y < -(SIZE_LIMIT/2))
459         {
460           if (parent_pos->y + wrapper->y + window->height < (SIZE_LIMIT/2))
461             info->y = parent_pos->y + wrapper->y + window->height - info->height - parent_pos->win32_y;
462           else
463             info->y = -(SIZE_LIMIT/2) - parent_pos->win32_y;
464         }
465       else
466         info->y = parent_pos->y + wrapper->y - parent_pos->win32_y;
467     }
468
469   parent_x_offset = parent_pos->win32_x - parent_pos->x;
470   parent_y_offset = parent_pos->win32_y - parent_pos->y;
471   
472   info->x_offset = parent_x_offset + info->x - wrapper->x;
473   info->y_offset = parent_y_offset + info->y - wrapper->y;
474
475   /* We don't considering the clipping of toplevel windows and their immediate children
476    * by their parents, and simply always map those windows.
477    */
478   if (parent_pos->clip_rect.width == G_MAXINT)
479     info->mapped = TRUE;
480   /* Check if the window would wrap around into the visible space in either direction */
481   else if (info->x + parent_x_offset < parent_pos->clip_rect.x + parent_pos->clip_rect.width - 65536 ||
482       info->x + info->width + parent_x_offset > parent_pos->clip_rect.x + 65536 ||
483       info->y + parent_y_offset < parent_pos->clip_rect.y + parent_pos->clip_rect.height - 65536 ||
484       info->y + info->height + parent_y_offset  > parent_pos->clip_rect.y + 65536)
485     info->mapped = FALSE;
486   else
487     info->mapped = TRUE;
488
489   info->no_bg = FALSE;
490
491   if (GDK_WINDOW_TYPE (wrapper) == GDK_WINDOW_CHILD)
492     {
493       info->clip_rect.x = wrapper->x;
494       info->clip_rect.y = wrapper->y;
495       info->clip_rect.width = window->width;
496       info->clip_rect.height = window->height;
497       
498       gdk_rectangle_intersect (&info->clip_rect, &parent_pos->clip_rect, &info->clip_rect);
499
500       info->clip_rect.x -= wrapper->x;
501       info->clip_rect.y -= wrapper->y;
502     }
503   else
504     {
505       info->clip_rect.x = 0;
506       info->clip_rect.y = 0;
507       info->clip_rect.width = G_MAXINT;
508       info->clip_rect.height = G_MAXINT;
509     }
510 }
511
512 static void
513 gdk_window_compute_parent_pos (GdkWindowImplWin32 *window,
514                                GdkWindowParentPos *parent_pos)
515 {
516   GdkWindowObject *wrapper;
517   GdkWindowObject *parent;
518   GdkRectangle tmp_clip;
519   
520   int clip_xoffset = 0;
521   int clip_yoffset = 0;
522
523   g_return_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (window));
524
525   wrapper = GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_WIN32 (window)->wrapper);
526   
527   parent_pos->x = 0;
528   parent_pos->y = 0;
529   parent_pos->win32_x = 0;
530   parent_pos->win32_y = 0;
531
532   /* We take a simple approach here and simply consider toplevel
533    * windows not to clip their children on the right/bottom, since the
534    * size of toplevel windows is not directly under our
535    * control. Clipping only really matters when scrolling and
536    * generally we aren't going to be moving the immediate child of a
537    * toplevel beyond the bounds of that toplevel.
538    *
539    * We could go ahead and recompute the clips of toplevel windows and
540    * their descendents when we receive size notification, but it would
541    * probably not be an improvement in most cases.
542    */
543   parent_pos->clip_rect.x = 0;
544   parent_pos->clip_rect.y = 0;
545   parent_pos->clip_rect.width = G_MAXINT;
546   parent_pos->clip_rect.height = G_MAXINT;
547
548   parent = (GdkWindowObject *)wrapper->parent;
549   while (parent && parent->window_type == GDK_WINDOW_CHILD)
550     {
551       GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (parent->impl);
552       
553       tmp_clip.x = - clip_xoffset;
554       tmp_clip.y = - clip_yoffset;
555       tmp_clip.width = impl->width;
556       tmp_clip.height = impl->height;
557
558       gdk_rectangle_intersect (&parent_pos->clip_rect, &tmp_clip, &parent_pos->clip_rect);
559
560       parent_pos->x += parent->x;
561       parent_pos->y += parent->y;
562       parent_pos->win32_x += impl->position_info.x;
563       parent_pos->win32_y += impl->position_info.y;
564
565       clip_xoffset += parent->x;
566       clip_yoffset += parent->y;
567
568       parent = (GdkWindowObject *)parent->parent;
569     }
570 }
571
572 static void
573 gdk_window_postmove (GdkWindow          *window,
574                      GdkWindowParentPos *parent_pos,
575                      gboolean            anti_scroll)
576 {
577   GdkWindowImplWin32 *impl;
578   GdkWindowObject *obj;
579   GdkWin32PositionInfo new_info;
580   GList *tmp_list;
581   gint d_xoffset, d_yoffset;
582   GdkWindowParentPos this_pos;
583   GdkRegion *new_clip_region;
584
585   obj = (GdkWindowObject *) window;
586   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
587   
588   gdk_window_compute_position (impl, parent_pos, &new_info);
589
590   new_clip_region =
591     gdk_window_clip_changed (window, &impl->position_info.clip_rect, &new_info.clip_rect);
592
593   this_pos.x = parent_pos->x + obj->x;
594   this_pos.y = parent_pos->y + obj->y;
595   this_pos.win32_x = parent_pos->win32_x + new_info.x;
596   this_pos.win32_y = parent_pos->win32_y + new_info.y;
597   this_pos.clip_rect = new_info.clip_rect;
598
599   if (impl->position_info.mapped && !new_info.mapped)
600     ShowWindow (GDK_WINDOW_HWND (window), SW_HIDE);
601
602   d_xoffset = new_info.x_offset - impl->position_info.x_offset;
603   d_yoffset = new_info.y_offset - impl->position_info.y_offset;
604   
605   if (anti_scroll || (anti_scroll = d_xoffset != 0 || d_yoffset != 0))
606     {
607       GDK_NOTE (MISC, g_print ("gdk_window_postmove: %s@%+d%+d\n"
608                                "... SetWindowPos(%p,NULL,%d,%d,0,0,"
609                                "NOREDRAW|NOZORDER|NOACTIVATE|NOSIZE)\n",
610                                _gdk_win32_drawable_description (window),
611                                obj->x, obj->y,
612                                GDK_WINDOW_HWND (window),
613                                new_info.x, new_info.y));
614
615       API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
616                                new_info.x, new_info.y, 
617                                0, 0,
618                                SWP_NOREDRAW | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE));
619     }
620
621   if (!impl->position_info.mapped && new_info.mapped && GDK_WINDOW_IS_MAPPED (obj))
622     ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNA);
623
624   if (impl->position_info.no_bg)
625     gdk_window_tmp_reset_bg (window);
626
627   impl->position_info = new_info;
628
629   if (new_clip_region)
630     gdk_window_post_scroll (window, new_clip_region);
631
632   tmp_list = obj->children;
633   while (tmp_list)
634     {
635       gdk_window_postmove (tmp_list->data, &this_pos, anti_scroll);
636       tmp_list = tmp_list->next;
637     }
638 }
639
640 gboolean
641 _gdk_windowing_window_queue_antiexpose (GdkWindow *window,
642                                         GdkRegion *area)
643 {
644   HRGN hrgn = _gdk_win32_gdkregion_to_hrgn (area, 0, 0);
645
646   GDK_NOTE (EVENTS, g_print ("_gdk_windowing_window_queue_antiexpose: ValidateRgn %p %s\n",
647                              GDK_WINDOW_HWND (window),
648                              _gdk_win32_gdkregion_to_string (area)));
649
650   ValidateRgn (GDK_WINDOW_HWND (window), hrgn);
651
652   DeleteObject (hrgn);
653
654   return FALSE;
655 }
656
657 void
658 _gdk_window_process_expose (GdkWindow *window,
659                             GdkRegion *invalidate_region)
660 {
661   GdkWindowImplWin32 *impl;
662   GdkRegion *clip_region;
663   impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
664   
665   GDK_NOTE (EVENTS, g_print ("_gdk_window_process_expose: %p %s\n",
666                              GDK_WINDOW_HWND (window),
667                              _gdk_win32_gdkregion_to_string (invalidate_region)));
668   clip_region = gdk_region_rectangle (&impl->position_info.clip_rect);
669   gdk_region_intersect (invalidate_region, clip_region);
670
671   if (!gdk_region_empty (invalidate_region))
672     gdk_window_invalidate_region (window, invalidate_region, FALSE);
673   
674   gdk_region_destroy (clip_region);
675 }
676
677 static void
678 gdk_window_tmp_unset_bg (GdkWindow *window)
679 {
680   GdkWindowImplWin32 *impl;
681   GdkWindowObject *obj;
682
683   obj = (GdkWindowObject *) window;
684   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
685
686   impl->position_info.no_bg = TRUE;
687
688   /*
689    * The X version sets background = None to avoid updateing for a moment.
690    * Not sure if this could really emulate it.
691    */
692   if (obj->bg_pixmap != GDK_NO_BG)
693     /* handled in WM_ERASEBKGRND proceesing */;
694 }
695
696 static void
697 gdk_window_tmp_reset_bg (GdkWindow *window)
698 {
699   GdkWindowImplWin32 *impl;
700   GdkWindowObject *obj;
701
702   obj = (GdkWindowObject *) window;
703   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
704
705   impl->position_info.no_bg = FALSE;
706 }
707
708 static GdkRegion *
709 gdk_window_clip_changed (GdkWindow    *window,
710                          GdkRectangle *old_clip,
711                          GdkRectangle *new_clip)
712 {
713   GdkWindowImplWin32 *impl;
714   GdkWindowObject *obj;
715   GdkRegion *old_clip_region;
716   GdkRegion *new_clip_region;
717   
718   if (((GdkWindowObject *)window)->input_only)
719     return NULL;
720
721   obj = (GdkWindowObject *) window;
722   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
723   
724   old_clip_region = gdk_region_rectangle (old_clip);
725   new_clip_region = gdk_region_rectangle (new_clip);
726
727   /* Trim invalid region of window to new clip rectangle
728    */
729   if (obj->update_area)
730     gdk_region_intersect (obj->update_area, new_clip_region);
731
732   /* Invalidate newly exposed portion of window
733    */
734   gdk_region_subtract (new_clip_region, old_clip_region);
735   if (!gdk_region_empty (new_clip_region))
736     gdk_window_tmp_unset_bg (window);
737   else
738     {
739       gdk_region_destroy (new_clip_region);
740       new_clip_region = NULL;
741     }
742   gdk_region_destroy (old_clip_region);
743
744   return new_clip_region;
745 }
746
747 static void
748 gdk_window_post_scroll (GdkWindow    *window,
749                         GdkRegion    *new_clip_region)
750 {
751   GDK_NOTE (EVENTS,
752             g_print ("gdk_window_clip_changed: invalidating region: %s\n",
753                      _gdk_win32_gdkregion_to_string (new_clip_region)));
754
755   gdk_window_invalidate_region (window, new_clip_region, FALSE);
756   gdk_region_destroy (new_clip_region);
757 }