]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkgeometry-win32.c
Bug 541162 – [Win32] Update for the new GdkWindowImpl stuff
[~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_win32_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_win32_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   GDK_NOTE (EVENTS, g_print ("gdk_window_scroll: %p %d,%d\n",
116                              GDK_WINDOW_HWND (window), dx, dy));
117
118   obj = GDK_WINDOW_OBJECT (window);
119   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);  
120
121   if (dx == 0 && dy == 0)
122     return;
123   
124   /* Move the current invalid region */
125   if (obj->update_area)
126     gdk_region_offset (obj->update_area, dx, dy);
127   
128   gdk_window_compute_parent_pos (impl, &parent_pos);
129
130   parent_pos.x += obj->x;
131   parent_pos.y += obj->y;
132   parent_pos.win32_x += impl->position_info.x;
133   parent_pos.win32_y += impl->position_info.y;
134   parent_pos.clip_rect = impl->position_info.clip_rect;
135
136   gdk_window_tmp_unset_bg (window);
137
138   native_invalidate_region = CreateRectRgn (0, 0, 0, 0);
139   if (native_invalidate_region == NULL)
140     WIN32_API_FAILED ("CreateRectRgn");
141
142   API_CALL (ScrollWindowEx, (GDK_WINDOW_HWND (window),
143                              dx, dy, NULL, NULL,
144                              native_invalidate_region, NULL, SW_SCROLLCHILDREN));
145
146   if (impl->position_info.no_bg)
147     gdk_window_tmp_reset_bg (window);
148   
149   tmp_list = obj->children;
150   while (tmp_list)
151     {
152       GDK_WINDOW_OBJECT(tmp_list->data)->x += dx;
153       GDK_WINDOW_OBJECT(tmp_list->data)->y += dy;
154       gdk_window_postmove (tmp_list->data, &parent_pos, FALSE);
155       tmp_list = tmp_list->next;
156     }
157
158   if (native_invalidate_region != NULL)
159     {
160       invalidate_region = _gdk_win32_hrgn_to_region (native_invalidate_region);
161       gdk_region_offset (invalidate_region, impl->position_info.x_offset,
162                          impl->position_info.y_offset);
163       gdk_window_invalidate_region (window, invalidate_region, TRUE);
164       gdk_region_destroy (invalidate_region);
165       GDI_CALL (DeleteObject, (native_invalidate_region));
166     }
167 }
168
169 void
170 _gdk_win32_window_move_region (GdkWindow       *window,
171                                const GdkRegion *region,
172                                gint             dx,
173                                gint             dy)
174 {
175   GdkRegion *invalidate_region;
176   GdkWindowImplWin32 *impl;
177   GdkWindowObject *obj;
178   GdkRectangle src_rect, dest_rect;
179   HRGN hrgn;
180   RECT clipRect, destRect;
181
182   obj = GDK_WINDOW_OBJECT (window);
183   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);  
184
185   if (dx == 0 && dy == 0)
186     return;
187   
188   /* Move the current invalid region */
189   if (obj->update_area)
190     gdk_region_offset (obj->update_area, dx, dy);
191   
192   /* impl->position_info.clip_rect isn't meaningful for toplevels */
193   if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
194     src_rect = impl->position_info.clip_rect;
195   else
196     {
197       src_rect.x = 0;
198       src_rect.y = 0;
199       src_rect.width = impl->width;
200       src_rect.height = impl->height;
201     }
202   
203   invalidate_region = gdk_region_rectangle (&src_rect);
204
205   dest_rect = src_rect;
206   dest_rect.x += dx;
207   dest_rect.y += dy;
208   gdk_rectangle_intersect (&dest_rect, &src_rect, &dest_rect);
209
210   if (dest_rect.width > 0 && dest_rect.height > 0)
211     {
212       GdkRegion *tmp_region;
213
214       tmp_region = gdk_region_rectangle (&dest_rect);
215       gdk_region_subtract (invalidate_region, tmp_region);
216       gdk_region_destroy (tmp_region);
217     }
218   
219   /* no guffaw scroll on win32 */
220   hrgn = _gdk_win32_gdkregion_to_hrgn(invalidate_region, 0, 0);
221   gdk_region_destroy (invalidate_region);
222   destRect.left = dest_rect.y;
223   destRect.top = dest_rect.x;
224   destRect.right = dest_rect.x + dest_rect.width;
225   destRect.bottom = dest_rect.y + dest_rect.height;
226   clipRect.left = src_rect.y;
227   clipRect.top = src_rect.x;
228   clipRect.right = src_rect.x + src_rect.width;
229   clipRect.bottom = src_rect.y + src_rect.height;
230
231   g_print ("ScrollWindowEx(%d, %d, ...) - if you see this work, remove trace;)\n", dx, dy);
232   API_CALL(ScrollWindowEx, (GDK_WINDOW_HWND (window),
233                        dx, dy, /* in: scroll offsets */
234                        NULL, /* in: scroll rect, NULL == entire client area */
235                        &clipRect, /* in: restrict to */
236                        hrgn, /* in: update region */
237                        NULL, /* out: update rect */
238                        SW_INVALIDATE));
239   API_CALL(DeleteObject, (hrgn));
240 }
241
242 void
243 _gdk_window_move_resize_child (GdkWindow *window,
244                                gint       x,
245                                gint       y,
246                                gint       width,
247                                gint       height)
248 {
249   GdkWindowImplWin32 *impl;
250   GdkWindowObject *obj;
251   GdkWin32PositionInfo new_info;
252   GdkWindowParentPos parent_pos;
253   GList *tmp_list;
254   gint d_xoffset, d_yoffset;
255   gint dx, dy;
256   gboolean is_move;
257   gboolean is_resize;
258   GdkRegion *new_clip_region;
259   
260   g_return_if_fail (window != NULL);
261   g_return_if_fail (GDK_IS_WINDOW (window));
262
263   obj = GDK_WINDOW_OBJECT (window);
264   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
265   
266   GDK_NOTE (MISC, g_print ("_gdk_window_move_resize_child: %s@%+d%+d %dx%d@%+d%+d\n",
267                            _gdk_win32_drawable_description (window),
268                            obj->x, obj->y,
269                            width, height, x, y));
270
271   dx = x - obj->x;
272   dy = y - obj->y;
273   
274   is_move = dx != 0 || dy != 0;
275   is_resize = impl->width != width || impl->height != height;
276
277   if (!is_move && !is_resize)
278     {
279       GDK_NOTE (MISC, g_print ("... neither move or resize\n"));
280       return;
281     }
282   
283   GDK_NOTE (MISC, g_print ("... %s%s\n",
284                            is_move ? "is_move " : "",
285                            is_resize ? "is_resize" : ""));
286
287   obj->x = x;
288   obj->y = y;
289   impl->width = width;
290   impl->height = height;
291
292   gdk_window_compute_parent_pos (impl, &parent_pos);
293   gdk_window_compute_position (impl, &parent_pos, &new_info);
294
295   new_clip_region =
296     gdk_window_clip_changed (window, &impl->position_info.clip_rect, &new_info.clip_rect);
297
298   parent_pos.x += obj->x;
299   parent_pos.y += obj->y;
300   parent_pos.win32_x += new_info.x;
301   parent_pos.win32_y += new_info.y;
302   parent_pos.clip_rect = new_info.clip_rect;
303
304   d_xoffset = new_info.x_offset - impl->position_info.x_offset;
305   d_yoffset = new_info.y_offset - impl->position_info.y_offset;
306   
307   if (d_xoffset != 0 || d_yoffset != 0)
308     {
309       GDK_NOTE (MISC, g_print ("... d_offset=%+d%+d\n", d_xoffset, d_yoffset));
310
311       if (!ScrollWindowEx (GDK_WINDOW_HWND (window),
312                            -d_xoffset, -d_yoffset, /* in: scroll offsets */
313                            NULL, /* in: scroll rect, NULL == entire client area */
314                            NULL, /* in: restrict to */
315                            NULL, /* in: update region */
316                            NULL, /* out: update rect */
317                            SW_SCROLLCHILDREN))
318         WIN32_API_FAILED ("ScrollWindowEx");
319
320       if (dx != d_xoffset || dy != d_yoffset || is_resize)
321         {
322           GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,%d,%d,%d,%d,"
323                                    "NOACTIVATE|NOZORDER%s%s)\n",
324                                    GDK_WINDOW_HWND (window),
325                                    new_info.x, new_info.y, 
326                                    new_info.width, new_info.height,
327                                    (is_move ? "" : "|NOMOVE"),
328                                    (is_resize ? "" : "|NOSIZE")));
329
330           API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
331                                    new_info.x, new_info.y, 
332                                    new_info.width, new_info.height,
333                                    SWP_NOACTIVATE | SWP_NOZORDER | 
334                                    (is_move ? 0 : SWP_NOMOVE) |
335                                    (is_resize ? 0 : SWP_NOSIZE)));
336         }
337
338       if (impl->position_info.no_bg)
339         gdk_window_tmp_reset_bg (window);
340
341       if (!impl->position_info.mapped && new_info.mapped && GDK_WINDOW_IS_MAPPED (obj))
342         {
343           GDK_NOTE (MISC, g_print ("... ShowWindow(%p, SW_SHOWNA)\n",
344                                    GDK_WINDOW_HWND (window)));
345           ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNA);
346         }
347
348       impl->position_info = new_info;
349       
350       tmp_list = obj->children;
351       while (tmp_list)
352         {
353           gdk_window_postmove (tmp_list->data, &parent_pos, FALSE);
354           tmp_list = tmp_list->next;
355         }
356     }
357   else
358     {
359       if (impl->position_info.mapped && !new_info.mapped)
360         {
361           GDK_NOTE (MISC, g_print ("... ShowWindow(%p, SW_HIDE)\n",
362                                    GDK_WINDOW_HWND (window)));
363           ShowWindow (GDK_WINDOW_HWND (window), SW_HIDE);
364         }
365       
366       GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,%d,%d,%d,%d,"
367                                "NOACTIVATE|NOZORDER%s%s)\n",
368                                GDK_WINDOW_HWND (window),
369                                new_info.x, new_info.y, 
370                                new_info.width, new_info.height,
371                                (is_move ? "" : "|NOMOVE"),
372                                (is_resize ? "" : "|NOSIZE")));
373
374       API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
375                                new_info.x, new_info.y, 
376                                new_info.width, new_info.height,
377                                SWP_NOACTIVATE | SWP_NOZORDER | 
378                                (is_move ? 0 : SWP_NOMOVE) |
379                                (is_resize ? 0 : SWP_NOSIZE)));
380
381       tmp_list = obj->children;
382       while (tmp_list)
383         {
384           gdk_window_postmove (tmp_list->data, &parent_pos, FALSE);
385           tmp_list = tmp_list->next;
386         }
387
388       if (impl->position_info.no_bg)
389         gdk_window_tmp_reset_bg (window);
390
391       if (!impl->position_info.mapped && new_info.mapped && GDK_WINDOW_IS_MAPPED (obj))
392         {
393           GDK_NOTE (MISC, g_print ("... ShowWindow(%p, SW_SHOWNA)\n",
394                                    GDK_WINDOW_HWND (window)));
395           ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNA);
396         }
397
398       impl->position_info = new_info;
399     }
400   if (new_clip_region)
401     gdk_window_post_scroll (window, new_clip_region);
402 }
403
404 static void
405 gdk_window_compute_position (GdkWindowImplWin32   *window,
406                              GdkWindowParentPos   *parent_pos,
407                              GdkWin32PositionInfo *info)
408 {
409   GdkWindowObject *wrapper;
410   int parent_x_offset;
411   int parent_y_offset;
412
413   g_return_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (window));
414
415   wrapper = GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_WIN32 (window)->wrapper);
416   
417   info->big = FALSE;
418   
419   if (window->width <= SIZE_LIMIT)
420     {
421       info->width = window->width;
422       info->x = parent_pos->x + wrapper->x - parent_pos->win32_x;
423     }
424   else
425     {
426       info->big = TRUE;
427       info->width = SIZE_LIMIT;
428       if (parent_pos->x + wrapper->x < -(SIZE_LIMIT/2))
429         {
430           if (parent_pos->x + wrapper->x + window->width < (SIZE_LIMIT/2))
431             info->x = parent_pos->x + wrapper->x + window->width - info->width - parent_pos->win32_x;
432           else
433             info->x = -(SIZE_LIMIT/2) - parent_pos->win32_x;
434         }
435       else
436         info->x = parent_pos->x + wrapper->x - parent_pos->win32_x;
437     }
438
439   if (window->height <= SIZE_LIMIT)
440     {
441       info->height = window->height;
442       info->y = parent_pos->y + wrapper->y - parent_pos->win32_y;
443     }
444   else
445     {
446       info->big = TRUE;
447       info->height = SIZE_LIMIT;
448       if (parent_pos->y + wrapper->y < -(SIZE_LIMIT/2))
449         {
450           if (parent_pos->y + wrapper->y + window->height < (SIZE_LIMIT/2))
451             info->y = parent_pos->y + wrapper->y + window->height - info->height - parent_pos->win32_y;
452           else
453             info->y = -(SIZE_LIMIT/2) - parent_pos->win32_y;
454         }
455       else
456         info->y = parent_pos->y + wrapper->y - parent_pos->win32_y;
457     }
458
459   parent_x_offset = parent_pos->win32_x - parent_pos->x;
460   parent_y_offset = parent_pos->win32_y - parent_pos->y;
461   
462   info->x_offset = parent_x_offset + info->x - wrapper->x;
463   info->y_offset = parent_y_offset + info->y - wrapper->y;
464
465   /* We don't considering the clipping of toplevel windows and their immediate children
466    * by their parents, and simply always map those windows.
467    */
468   if (parent_pos->clip_rect.width == G_MAXINT)
469     info->mapped = TRUE;
470   /* Check if the window would wrap around into the visible space in either direction */
471   else if (info->x + parent_x_offset < parent_pos->clip_rect.x + parent_pos->clip_rect.width - 65536 ||
472       info->x + info->width + parent_x_offset > parent_pos->clip_rect.x + 65536 ||
473       info->y + parent_y_offset < parent_pos->clip_rect.y + parent_pos->clip_rect.height - 65536 ||
474       info->y + info->height + parent_y_offset  > parent_pos->clip_rect.y + 65536)
475     info->mapped = FALSE;
476   else
477     info->mapped = TRUE;
478
479   info->no_bg = FALSE;
480
481   if (GDK_WINDOW_TYPE (wrapper) == GDK_WINDOW_CHILD)
482     {
483       info->clip_rect.x = wrapper->x;
484       info->clip_rect.y = wrapper->y;
485       info->clip_rect.width = window->width;
486       info->clip_rect.height = window->height;
487       
488       gdk_rectangle_intersect (&info->clip_rect, &parent_pos->clip_rect, &info->clip_rect);
489
490       info->clip_rect.x -= wrapper->x;
491       info->clip_rect.y -= wrapper->y;
492     }
493   else
494     {
495       info->clip_rect.x = 0;
496       info->clip_rect.y = 0;
497       info->clip_rect.width = G_MAXINT;
498       info->clip_rect.height = G_MAXINT;
499     }
500 }
501
502 static void
503 gdk_window_compute_parent_pos (GdkWindowImplWin32 *window,
504                                GdkWindowParentPos *parent_pos)
505 {
506   GdkWindowObject *wrapper;
507   GdkWindowObject *parent;
508   GdkRectangle tmp_clip;
509   
510   int clip_xoffset = 0;
511   int clip_yoffset = 0;
512
513   g_return_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (window));
514
515   wrapper = GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_WIN32 (window)->wrapper);
516   
517   parent_pos->x = 0;
518   parent_pos->y = 0;
519   parent_pos->win32_x = 0;
520   parent_pos->win32_y = 0;
521
522   /* We take a simple approach here and simply consider toplevel
523    * windows not to clip their children on the right/bottom, since the
524    * size of toplevel windows is not directly under our
525    * control. Clipping only really matters when scrolling and
526    * generally we aren't going to be moving the immediate child of a
527    * toplevel beyond the bounds of that toplevel.
528    *
529    * We could go ahead and recompute the clips of toplevel windows and
530    * their descendents when we receive size notification, but it would
531    * probably not be an improvement in most cases.
532    */
533   parent_pos->clip_rect.x = 0;
534   parent_pos->clip_rect.y = 0;
535   parent_pos->clip_rect.width = G_MAXINT;
536   parent_pos->clip_rect.height = G_MAXINT;
537
538   parent = (GdkWindowObject *)wrapper->parent;
539   while (parent && parent->window_type == GDK_WINDOW_CHILD)
540     {
541       GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (parent->impl);
542       
543       tmp_clip.x = - clip_xoffset;
544       tmp_clip.y = - clip_yoffset;
545       tmp_clip.width = impl->width;
546       tmp_clip.height = impl->height;
547
548       gdk_rectangle_intersect (&parent_pos->clip_rect, &tmp_clip, &parent_pos->clip_rect);
549
550       parent_pos->x += parent->x;
551       parent_pos->y += parent->y;
552       parent_pos->win32_x += impl->position_info.x;
553       parent_pos->win32_y += impl->position_info.y;
554
555       clip_xoffset += parent->x;
556       clip_yoffset += parent->y;
557
558       parent = (GdkWindowObject *)parent->parent;
559     }
560 }
561
562 static void
563 gdk_window_postmove (GdkWindow          *window,
564                      GdkWindowParentPos *parent_pos,
565                      gboolean            anti_scroll)
566 {
567   GdkWindowImplWin32 *impl;
568   GdkWindowObject *obj;
569   GdkWin32PositionInfo new_info;
570   GList *tmp_list;
571   gint d_xoffset, d_yoffset;
572   GdkWindowParentPos this_pos;
573   GdkRegion *new_clip_region;
574
575   obj = (GdkWindowObject *) window;
576   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
577   
578   gdk_window_compute_position (impl, parent_pos, &new_info);
579
580   new_clip_region =
581     gdk_window_clip_changed (window, &impl->position_info.clip_rect, &new_info.clip_rect);
582
583   this_pos.x = parent_pos->x + obj->x;
584   this_pos.y = parent_pos->y + obj->y;
585   this_pos.win32_x = parent_pos->win32_x + new_info.x;
586   this_pos.win32_y = parent_pos->win32_y + new_info.y;
587   this_pos.clip_rect = new_info.clip_rect;
588
589   if (impl->position_info.mapped && !new_info.mapped)
590     ShowWindow (GDK_WINDOW_HWND (window), SW_HIDE);
591
592   d_xoffset = new_info.x_offset - impl->position_info.x_offset;
593   d_yoffset = new_info.y_offset - impl->position_info.y_offset;
594   
595   if (anti_scroll || (anti_scroll = d_xoffset != 0 || d_yoffset != 0))
596     {
597       GDK_NOTE (MISC, g_print ("gdk_window_postmove: %s@%+d%+d\n"
598                                "... SetWindowPos(%p,NULL,%d,%d,0,0,"
599                                "NOREDRAW|NOZORDER|NOACTIVATE|NOSIZE)\n",
600                                _gdk_win32_drawable_description (window),
601                                obj->x, obj->y,
602                                GDK_WINDOW_HWND (window),
603                                new_info.x, new_info.y));
604
605       API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL,
606                                new_info.x, new_info.y, 
607                                0, 0,
608                                SWP_NOREDRAW | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE));
609     }
610
611   if (!impl->position_info.mapped && new_info.mapped && GDK_WINDOW_IS_MAPPED (obj))
612     ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNA);
613
614   if (impl->position_info.no_bg)
615     gdk_window_tmp_reset_bg (window);
616
617   impl->position_info = new_info;
618
619   if (new_clip_region)
620     gdk_window_post_scroll (window, new_clip_region);
621
622   tmp_list = obj->children;
623   while (tmp_list)
624     {
625       gdk_window_postmove (tmp_list->data, &this_pos, anti_scroll);
626       tmp_list = tmp_list->next;
627     }
628 }
629
630 gboolean
631 _gdk_windowing_window_queue_antiexpose (GdkWindow *window,
632                                         GdkRegion *area)
633 {
634   HRGN hrgn = _gdk_win32_gdkregion_to_hrgn (area, 0, 0);
635
636   GDK_NOTE (EVENTS, g_print ("_gdk_windowing_window_queue_antiexpose: ValidateRgn %p %s\n",
637                              GDK_WINDOW_HWND (window),
638                              _gdk_win32_gdkregion_to_string (area)));
639
640   ValidateRgn (GDK_WINDOW_HWND (window), hrgn);
641
642   DeleteObject (hrgn);
643
644   return FALSE;
645 }
646
647 void
648 _gdk_window_process_expose (GdkWindow *window,
649                             GdkRegion *invalidate_region)
650 {
651   GdkWindowImplWin32 *impl;
652   GdkRegion *clip_region;
653   impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
654   
655   GDK_NOTE (EVENTS, g_print ("_gdk_window_process_expose: %p %s\n",
656                              GDK_WINDOW_HWND (window),
657                              _gdk_win32_gdkregion_to_string (invalidate_region)));
658   clip_region = gdk_region_rectangle (&impl->position_info.clip_rect);
659   gdk_region_intersect (invalidate_region, clip_region);
660
661   if (!gdk_region_empty (invalidate_region))
662     gdk_window_invalidate_region (window, invalidate_region, FALSE);
663   
664   gdk_region_destroy (clip_region);
665 }
666
667 static void
668 gdk_window_tmp_unset_bg (GdkWindow *window)
669 {
670   GdkWindowImplWin32 *impl;
671   GdkWindowObject *obj;
672
673   obj = (GdkWindowObject *) window;
674   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
675
676   impl->position_info.no_bg = TRUE;
677
678   /*
679    * The X version sets background = None to avoid updateing for a moment.
680    * Not sure if this could really emulate it.
681    */
682   if (obj->bg_pixmap != GDK_NO_BG)
683     /* handled in WM_ERASEBKGRND proceesing */;
684 }
685
686 static void
687 gdk_window_tmp_reset_bg (GdkWindow *window)
688 {
689   GdkWindowImplWin32 *impl;
690   GdkWindowObject *obj;
691
692   obj = (GdkWindowObject *) window;
693   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
694
695   impl->position_info.no_bg = FALSE;
696 }
697
698 static GdkRegion *
699 gdk_window_clip_changed (GdkWindow    *window,
700                          GdkRectangle *old_clip,
701                          GdkRectangle *new_clip)
702 {
703   GdkWindowImplWin32 *impl;
704   GdkWindowObject *obj;
705   GdkRegion *old_clip_region;
706   GdkRegion *new_clip_region;
707   
708   if (((GdkWindowObject *)window)->input_only)
709     return NULL;
710
711   obj = (GdkWindowObject *) window;
712   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
713   
714   old_clip_region = gdk_region_rectangle (old_clip);
715   new_clip_region = gdk_region_rectangle (new_clip);
716
717   /* Trim invalid region of window to new clip rectangle
718    */
719   if (obj->update_area)
720     gdk_region_intersect (obj->update_area, new_clip_region);
721
722   /* Invalidate newly exposed portion of window
723    */
724   gdk_region_subtract (new_clip_region, old_clip_region);
725   if (!gdk_region_empty (new_clip_region))
726     gdk_window_tmp_unset_bg (window);
727   else
728     {
729       gdk_region_destroy (new_clip_region);
730       new_clip_region = NULL;
731     }
732   gdk_region_destroy (old_clip_region);
733
734   return new_clip_region;
735 }
736
737 static void
738 gdk_window_post_scroll (GdkWindow    *window,
739                         GdkRegion    *new_clip_region)
740 {
741   GDK_NOTE (EVENTS,
742             g_print ("gdk_window_clip_changed: invalidating region: %s\n",
743                      _gdk_win32_gdkregion_to_string (new_clip_region)));
744
745   gdk_window_invalidate_region (window, new_clip_region, FALSE);
746   gdk_region_destroy (new_clip_region);
747 }