]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkgeometry-win32.c
Include the build directory.
[~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 Library 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  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library 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. Just a copy of the X11 version, more or less.
22  * Probably totally bogus in functionality. Just a quick hack, to
23  * get the thing to build. Need to write some test code for it.
24  * Well, need to find out what it is supposed to do first ;-)
25  *
26  * The X11 version by Owen Taylor <otaylor@redhat.com>
27  * Copyright Red Hat, Inc. 2000
28  * Win32 hack by Tor Lillqvist <tml@iki.fi>
29  */
30
31 #include "gdk.h"                /* For gdk_rectangle_intersect */
32 #include "gdkregion.h"
33 #include "gdkregion-generic.h"
34 #include "gdkinternals.h"
35 #include "gdkprivate-win32.h"
36 #include "gdkdrawable-win32.h"
37 #include "gdkwindow-win32.h"
38
39 typedef struct _GdkWindowQueueItem GdkWindowQueueItem;
40 typedef struct _GdkWindowParentPos GdkWindowParentPos;
41
42 typedef enum {
43   GDK_WINDOW_QUEUE_TRANSLATE,
44   GDK_WINDOW_QUEUE_ANTIEXPOSE
45 } GdkWindowQueueType;
46
47 struct _GdkWindowQueueItem
48 {
49   GdkWindow *window;
50   gulong serial;
51   GdkWindowQueueType type;
52   union {
53     struct {
54       gint dx;
55       gint dy;
56     } translate;
57     struct {
58       GdkRegion *area;
59     } antiexpose;
60   } u;
61 };
62
63 struct _GdkWindowParentPos
64 {
65   gint x;
66   gint y;
67   gint win32_x;
68   gint win32_y;
69   GdkRectangle clip_rect;
70 };
71
72 static void gdk_window_compute_position   (GdkWindowImplWin32   *window,
73                                            GdkWindowParentPos   *parent_pos,
74                                            GdkWin32PositionInfo *info);
75 static void gdk_window_compute_parent_pos (GdkWindowImplWin32 *window,
76                                            GdkWindowParentPos *parent_pos);
77 static void gdk_window_premove            (GdkWindow          *window,
78                                            GdkWindowParentPos *parent_pos);
79 static void gdk_window_postmove           (GdkWindow          *window,
80                                            GdkWindowParentPos *parent_pos);
81 static void gdk_window_queue_translation  (GdkWindow          *window,
82                                            gint                dx,
83                                            gint                dy);
84 static void gdk_window_tmp_unset_bg       (GdkWindow          *window);
85 static void gdk_window_tmp_reset_bg       (GdkWindow          *window);
86 static void gdk_window_clip_changed       (GdkWindow          *window,
87                                            GdkRectangle       *old_clip,
88                                            GdkRectangle       *new_clip);
89
90 static GSList *translate_queue = NULL;
91
92 void
93 _gdk_windowing_window_get_offsets (GdkWindow *window,
94                                    gint      *x_offset,
95                                    gint      *y_offset)
96 {
97   GdkWindowImplWin32 *impl =
98     GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
99
100   *x_offset = impl->position_info.x_offset;
101   *y_offset = impl->position_info.y_offset;
102 }
103
104 void
105 _gdk_window_init_position (GdkWindow *window)
106 {
107   GdkWindowParentPos parent_pos;
108   GdkWindowImplWin32 *impl;
109
110   g_return_if_fail (GDK_IS_WINDOW (window));
111
112   impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
113
114   gdk_window_compute_parent_pos (impl, &parent_pos);
115   gdk_window_compute_position (impl, &parent_pos, &impl->position_info);
116 }
117
118 /**
119  * gdk_window_scroll:
120  * @window: a #GdkWindow
121  * @dx: Amount to scroll in the X direction
122  * @dy: Amount to scroll in the Y direction
123  * 
124  * Scroll the contents of its window, both pixels and children, by
125  * the given amount. Portions of the window that the scroll operation
126  * brings in from offscreen areas are invalidated. The invalidated
127  * region may be bigger than what would strictly be necessary.
128  * (For X11, a minimum area will be invalidated if the window has
129  * no subwindows, or if the edges of the window's parent do not extend
130  * beyond the edges of the window. In other cases, a multi-step process
131  * is used to scroll the window which may produce temporary visual
132  * artifacts and unnecessary invalidations.)
133  **/
134 void
135 gdk_window_scroll (GdkWindow *window,
136                    gint       dx,
137                    gint       dy)
138 {
139   gboolean can_guffaw_scroll = FALSE;
140   GdkWindowImplWin32 *impl;
141   GdkWindowObject *obj;
142   
143   g_return_if_fail (GDK_IS_WINDOW (window));
144
145   obj = GDK_WINDOW_OBJECT (window);
146   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);  
147   
148   if (GDK_WINDOW_DESTROYED (window))
149     return;
150
151   /* We can guffaw scroll if we are a child window, and the parent
152    * does not extend beyond our edges.
153    */
154   
155   if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
156     {
157       GdkWindowImplWin32 *parent_impl = GDK_WINDOW_IMPL_WIN32 (obj->parent->impl);  
158       can_guffaw_scroll = (obj->x <= 0 &&
159                            obj->y <= 0 &&
160                            obj->x + impl->width >= parent_impl->width &&
161                            obj->y + impl->height >= parent_impl->height);
162     }
163
164   if (!obj->children || !can_guffaw_scroll)
165     {
166       /* Use ScrollWindowEx, then move any children later
167        */
168       GList *tmp_list;
169       GdkRegion *invalidate_region;
170       GdkRectangle dest_rect;
171
172       invalidate_region = gdk_region_rectangle (&impl->position_info.clip_rect);
173       
174       dest_rect = impl->position_info.clip_rect;
175       dest_rect.x += dx;
176       dest_rect.y += dy;
177       gdk_rectangle_intersect (&dest_rect, &impl->position_info.clip_rect, &dest_rect);
178
179       if (dest_rect.width > 0 && dest_rect.height > 0)
180         {
181           GdkRegion *tmp_region;
182
183           tmp_region = gdk_region_rectangle (&dest_rect);
184           gdk_region_subtract (invalidate_region, tmp_region);
185           gdk_region_destroy (tmp_region);
186           
187           gdk_window_queue_translation (window, dx, dy);
188
189           if (ScrollWindowEx (GDK_WINDOW_HWND (window), dx, dy,
190                               NULL, NULL, NULL, NULL, 0) == ERROR)
191             WIN32_API_FAILED ("ScrollWindowEx");
192         }
193
194       gdk_window_invalidate_region (window, invalidate_region, TRUE);
195       gdk_region_destroy (invalidate_region);
196
197       tmp_list = obj->children;
198       while (tmp_list)
199         {
200           GdkWindow * child = GDK_WINDOW (tmp_list->data);
201           
202           gdk_window_move (child, obj->x + dx, obj->y + dy);
203           
204           tmp_list = tmp_list->next;
205         }
206     }
207   else
208     {
209       /* Guffaw scroll
210        */
211       g_warning ("gdk_window_scroll(): guffaw scrolling not yet implemented");
212     }
213 }
214
215 void
216 _gdk_window_move_resize_child (GdkWindow *window,
217                                gint       x,
218                                gint       y,
219                                gint       width,
220                                gint       height)
221 {
222   GdkWindowImplWin32 *impl;
223   GdkWindowObject *obj;
224   GdkWin32PositionInfo new_info;
225   GdkWindowParentPos parent_pos;
226   RECT rect;
227   GList *tmp_list;
228   gint d_xoffset, d_yoffset;
229   gint dx, dy;
230   gboolean is_move;
231   gboolean is_resize;
232   
233   g_return_if_fail (window != NULL);
234   g_return_if_fail (GDK_IS_WINDOW (window));
235
236   obj = GDK_WINDOW_OBJECT (window);
237   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
238
239   dx = x - obj->x;
240   dy = y - obj->y;
241   
242   is_move = dx != 0 || dy != 0;
243   is_resize = impl->width != width || impl->height != height;
244
245   if (!is_move && !is_resize)
246     return;
247   
248   obj->x = x;
249   obj->y = y;
250   impl->width = width;
251   impl->height = height;
252
253   gdk_window_compute_parent_pos (impl, &parent_pos);
254   gdk_window_compute_position (impl, &parent_pos, &new_info);
255
256   gdk_window_clip_changed (window, &impl->position_info.clip_rect, &new_info.clip_rect);
257
258   parent_pos.x += obj->x;
259   parent_pos.y += obj->y;
260   parent_pos.win32_x += new_info.x;
261   parent_pos.win32_y += new_info.y;
262   parent_pos.clip_rect = new_info.clip_rect;
263
264   d_xoffset = new_info.x_offset - impl->position_info.x_offset;
265   d_yoffset = new_info.y_offset - impl->position_info.y_offset;
266   
267   if (d_xoffset != 0 || d_yoffset != 0)
268     {
269       gint new_x0, new_y0, new_x1, new_y1;
270
271       gdk_window_set_static_gravities (window, TRUE);
272
273       if (d_xoffset < 0 || d_yoffset < 0)
274         gdk_window_queue_translation (window, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
275         
276       if (d_xoffset < 0)
277         {
278           new_x0 = impl->position_info.x + d_xoffset;
279           new_x1 = impl->position_info.x + impl->position_info.width;
280         }
281       else
282         {
283           new_x0 = impl->position_info.x;
284           new_x1 = impl->position_info.x + new_info.width + d_xoffset;
285         }
286
287       if (d_yoffset < 0)
288         {
289           new_y0 = impl->position_info.y + d_yoffset;
290           new_y1 = impl->position_info.y + impl->position_info.height;
291         }
292       else
293         {
294           new_y0 = impl->position_info.y;
295           new_y1 = impl->position_info.y + new_info.height + d_yoffset;
296         }
297       
298       if (!MoveWindow (GDK_WINDOW_HWND (window),
299                        new_x0, new_y0, new_x1 - new_x0, new_y1 - new_y0,
300                        FALSE))
301           WIN32_API_FAILED ("MoveWindow");
302       
303       tmp_list = obj->children;
304       while (tmp_list)
305         {
306           gdk_window_premove (tmp_list->data, &parent_pos);
307           tmp_list = tmp_list->next;
308         }
309
310       GetClientRect (GDK_WINDOW_HWND (window), &rect);
311
312       if (!MoveWindow (GDK_WINDOW_HWND (window),
313                        new_x0 + dx, new_y0 + dy,
314                        rect.right - rect.left, rect.bottom - rect.top,
315                        FALSE))
316           WIN32_API_FAILED ("MoveWindow");
317       
318       if (d_xoffset > 0 || d_yoffset > 0)
319         gdk_window_queue_translation (window, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
320       
321       if (!MoveWindow (GDK_WINDOW_HWND (window),
322                        new_info.x, new_info.y, new_info.width, new_info.height,
323                        FALSE))
324           WIN32_API_FAILED ("MoveWindow");
325       
326       if (impl->position_info.no_bg)
327         gdk_window_tmp_reset_bg (window);
328
329       if (!impl->position_info.mapped && new_info.mapped && obj->mapped)
330         ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNA);
331       
332       impl->position_info = new_info;
333       
334       tmp_list = obj->children;
335       while (tmp_list)
336         {
337           gdk_window_postmove (tmp_list->data, &parent_pos);
338           tmp_list = tmp_list->next;
339         }
340     }
341   else
342     {
343       if (is_move && is_resize)
344         gdk_window_set_static_gravities (window, FALSE);
345
346       if (impl->position_info.mapped && !new_info.mapped)
347         ShowWindow (GDK_WINDOW_HWND (window), SW_HIDE);
348       
349       tmp_list = obj->children;
350       while (tmp_list)
351         {
352           gdk_window_premove (tmp_list->data, &parent_pos);
353           tmp_list = tmp_list->next;
354         }
355
356       if (is_resize)
357         {
358           if (!MoveWindow (GDK_WINDOW_HWND (window),
359                            new_info.x, new_info.y, new_info.width, new_info.height,
360                            FALSE))
361             WIN32_API_FAILED ("MoveWindow");
362         }
363       else
364         {
365           GetClientRect (GDK_WINDOW_HWND (window), &rect);
366           if (!MoveWindow (GDK_WINDOW_HWND (window),
367                            new_info.x, new_info.y,
368                            rect.right - rect.left, rect.bottom - rect.top,
369                            FALSE))
370             WIN32_API_FAILED ("MoveWindow");
371         }
372
373       tmp_list = obj->children;
374       while (tmp_list)
375         {
376           gdk_window_postmove (tmp_list->data, &parent_pos);
377           tmp_list = tmp_list->next;
378         }
379
380       if (impl->position_info.no_bg)
381         gdk_window_tmp_reset_bg (window);
382
383       if (!impl->position_info.mapped && new_info.mapped && obj->mapped)
384         ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNA);
385
386       impl->position_info = new_info;
387     }
388 }
389
390 static void
391 gdk_window_compute_position (GdkWindowImplWin32   *window,
392                              GdkWindowParentPos   *parent_pos,
393                              GdkWin32PositionInfo *info)
394 {
395   GdkWindowObject *wrapper;
396   int parent_x_offset;
397   int parent_y_offset;
398   
399   g_return_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (window));
400
401   wrapper = GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_WIN32 (window)->wrapper);
402
403   info->big = FALSE;
404   
405   if (window->width <= 32768)
406     {
407       info->width = window->width;
408       info->x = parent_pos->x + wrapper->x - parent_pos->win32_x;
409     }
410   else
411     {
412       info->big = TRUE;
413       info->width = 32768;
414       if (parent_pos->x + wrapper->x < -16384)
415         {
416           if (parent_pos->x + wrapper->x + window->width < 16384)
417             info->x = parent_pos->x + wrapper->x + window->width - 32768 - parent_pos->win32_x;
418           else
419             info->x = -16384 - parent_pos->win32_y;
420         }
421       else
422         info->x = parent_pos->x + wrapper->x - parent_pos->win32_x;
423     }
424
425   if (window->height <= 32768)
426     {
427       info->height = window->height;
428       info->y = parent_pos->y + wrapper->y - parent_pos->win32_y;
429     }
430   else
431     {
432       info->big = TRUE;
433       info->height = 32768;
434       if (parent_pos->y + wrapper->y < -16384)
435         {
436           if (parent_pos->y + wrapper->y + window->height < 16384)
437             info->y = parent_pos->y + wrapper->y + window->height - 32768 - parent_pos->win32_y;
438           else
439             info->y = -16384 - parent_pos->win32_y;
440         }
441       else
442         info->y = parent_pos->y + wrapper->y - parent_pos->win32_y;
443     }
444
445   parent_x_offset = parent_pos->win32_x - parent_pos->x;
446   parent_y_offset = parent_pos->win32_y - parent_pos->y;
447   
448   info->x_offset = parent_x_offset + info->x - wrapper->x;
449   info->y_offset = parent_y_offset + info->y - wrapper->y;
450
451   /* We don't considering the clipping of toplevel windows and their immediate children
452    * by their parents, and simply always map those windows.
453    */
454   if (parent_pos->clip_rect.width == G_MAXINT)
455     info->mapped = TRUE;
456   /* Check if the window would wrap around into the visible space in either direction */
457   else if (info->x + parent_x_offset < parent_pos->clip_rect.x + parent_pos->clip_rect.width - 65536 ||
458       info->x + info->width + parent_x_offset > parent_pos->clip_rect.x + 65536 ||
459       info->y + parent_y_offset < parent_pos->clip_rect.y + parent_pos->clip_rect.height - 65536 ||
460       info->y + info->height + parent_y_offset  > parent_pos->clip_rect.y + 65536)
461     info->mapped = FALSE;
462   else
463     info->mapped = TRUE;
464
465   info->no_bg = FALSE;
466
467   if (GDK_WINDOW_TYPE (wrapper) == GDK_WINDOW_CHILD)
468     {
469       info->clip_rect.x = wrapper->x;
470       info->clip_rect.y = wrapper->y;
471       info->clip_rect.width = window->width;
472       info->clip_rect.height = window->height;
473       
474       gdk_rectangle_intersect (&info->clip_rect, &parent_pos->clip_rect, &info->clip_rect);
475
476       info->clip_rect.x -= wrapper->x;
477       info->clip_rect.y -= wrapper->y;
478     }
479   else
480     {
481       info->clip_rect.x = 0;
482       info->clip_rect.y = 0;
483       info->clip_rect.width = G_MAXINT;
484       info->clip_rect.height = G_MAXINT;
485     }
486 }
487
488 static void
489 gdk_window_compute_parent_pos (GdkWindowImplWin32 *window,
490                                GdkWindowParentPos *parent_pos)
491 {
492   GdkWindowObject *wrapper;
493   GdkWindowObject *parent;
494   GdkRectangle tmp_clip;
495   
496   int clip_xoffset = 0;
497   int clip_yoffset = 0;
498
499   g_return_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (window));
500
501   wrapper = GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_WIN32 (window)->wrapper);
502   
503   parent_pos->x = 0;
504   parent_pos->y = 0;
505   parent_pos->win32_x = 0;
506   parent_pos->win32_y = 0;
507
508   /* We take a simple approach here and simply consider toplevel
509    * windows not to clip their children on the right/bottom, since the
510    * size of toplevel windows is not directly under our
511    * control. Clipping only really matters when scrolling and
512    * generally we aren't going to be moving the immediate child of a
513    * toplevel beyond the bounds of that toplevel.
514    *
515    * We could go ahead and recompute the clips of toplevel windows and
516    * their descendents when we receive size notification, but it would
517    * probably not be an improvement in most cases.
518    */
519   parent_pos->clip_rect.x = 0;
520   parent_pos->clip_rect.y = 0;
521   parent_pos->clip_rect.width = G_MAXINT;
522   parent_pos->clip_rect.height = G_MAXINT;
523
524   parent = (GdkWindowObject *)wrapper->parent;
525   while (parent && parent->window_type == GDK_WINDOW_CHILD)
526     {
527       GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (parent->impl);
528       
529       tmp_clip.x = - clip_xoffset;
530       tmp_clip.y = - clip_yoffset;
531       tmp_clip.width = impl->width;
532       tmp_clip.height = impl->height;
533
534       gdk_rectangle_intersect (&parent_pos->clip_rect, &tmp_clip, &parent_pos->clip_rect);
535
536       parent_pos->x += parent->x;
537       parent_pos->y += parent->y;
538       parent_pos->win32_x += impl->position_info.x;
539       parent_pos->win32_y += impl->position_info.y;
540
541       clip_xoffset += parent->x;
542       clip_yoffset += parent->y;
543
544       parent = (GdkWindowObject *)parent->parent;
545     }
546 }
547
548 static void
549 gdk_window_premove (GdkWindow          *window,
550                     GdkWindowParentPos *parent_pos)
551 {
552   GdkWindowImplWin32 *impl;
553   GdkWindowObject *obj;
554   GdkWin32PositionInfo new_info;
555   GList *tmp_list;
556   gint d_xoffset, d_yoffset;
557   GdkWindowParentPos this_pos;
558   
559   obj = (GdkWindowObject *) window;
560   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
561   
562   gdk_window_compute_position (impl, parent_pos, &new_info);
563
564   gdk_window_clip_changed (window, &impl->position_info.clip_rect, &new_info.clip_rect);
565
566   this_pos.x = parent_pos->x + obj->x;
567   this_pos.y = parent_pos->y + obj->y;
568   this_pos.win32_x = parent_pos->win32_x + new_info.x;
569   this_pos.win32_y = parent_pos->win32_y + new_info.y;
570   this_pos.clip_rect = new_info.clip_rect;
571
572   if (impl->position_info.mapped && !new_info.mapped)
573     ShowWindow (GDK_WINDOW_HWND (window), SW_HIDE);
574
575   d_xoffset = new_info.x_offset - impl->position_info.x_offset;
576   d_yoffset = new_info.y_offset - impl->position_info.y_offset;
577   
578   if (d_xoffset != 0 || d_yoffset != 0)
579     {
580       gint new_x0, new_y0, new_x1, new_y1;
581
582       if (d_xoffset < 0 || d_yoffset < 0)
583         gdk_window_queue_translation (window, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
584         
585       if (d_xoffset < 0)
586         {
587           new_x0 = impl->position_info.x + d_xoffset;
588           new_x1 = impl->position_info.x + impl->position_info.width;
589         }
590       else
591         {
592           new_x0 = impl->position_info.x;
593           new_x1 = impl->position_info.x + new_info.width + d_xoffset;
594         }
595
596       if (d_yoffset < 0)
597         {
598           new_y0 = impl->position_info.y + d_yoffset;
599           new_y1 = impl->position_info.y + impl->position_info.height;
600         }
601       else
602         {
603           new_y0 = impl->position_info.y;
604           new_y1 = impl->position_info.y + new_info.height + d_yoffset;
605         }
606
607       if (!MoveWindow (GDK_WINDOW_HWND (window),
608                        new_x0, new_y0, new_x1 - new_x0, new_y1 - new_y0,
609                        FALSE))
610         WIN32_API_FAILED ("MoveWindow");
611     }
612
613   tmp_list = obj->children;
614   while (tmp_list)
615     {
616       gdk_window_premove (tmp_list->data, &this_pos);
617       tmp_list = tmp_list->next;
618     }
619 }
620
621 static void
622 gdk_window_postmove (GdkWindow          *window,
623                      GdkWindowParentPos *parent_pos)
624 {
625   GdkWindowImplWin32 *impl;
626   GdkWindowObject *obj;
627   GdkWin32PositionInfo new_info;
628   GList *tmp_list;
629   gint d_xoffset, d_yoffset;
630   GdkWindowParentPos this_pos;
631   
632   obj = (GdkWindowObject *) window;
633   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
634   
635   gdk_window_compute_position (impl, parent_pos, &new_info);
636
637   this_pos.x = parent_pos->x + obj->x;
638   this_pos.y = parent_pos->y + obj->y;
639   this_pos.win32_x = parent_pos->win32_x + new_info.x;
640   this_pos.win32_y = parent_pos->win32_y + new_info.y;
641   this_pos.clip_rect = new_info.clip_rect;
642
643   d_xoffset = new_info.x_offset - impl->position_info.x_offset;
644   d_yoffset = new_info.y_offset - impl->position_info.y_offset;
645   
646   if (d_xoffset != 0 || d_yoffset != 0)
647     {
648       if (d_xoffset > 0 || d_yoffset > 0)
649         gdk_window_queue_translation (window, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
650         
651       if (!MoveWindow (GDK_WINDOW_HWND (window),
652                        new_info.x, new_info.y, new_info.width, new_info.height,
653                        FALSE))
654         WIN32_API_FAILED ("MoveWindow");
655     }
656
657   if (!impl->position_info.mapped && new_info.mapped && obj->mapped)
658     ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNA);
659
660   if (impl->position_info.no_bg)
661     gdk_window_tmp_reset_bg (window);
662
663   impl->position_info = new_info;
664
665   tmp_list = obj->children;
666   while (tmp_list)
667     {
668       gdk_window_postmove (tmp_list->data, &this_pos);
669       tmp_list = tmp_list->next;
670     }
671 }
672
673 static void
674 gdk_window_queue_translation (GdkWindow *window,
675                               gint       dx,
676                               gint       dy)
677 {
678   GdkWindowQueueItem *item = g_new (GdkWindowQueueItem, 1);
679   item->window = window;
680   item->serial = GetMessageTime ();
681   item->type = GDK_WINDOW_QUEUE_TRANSLATE;
682   item->u.translate.dx = dx;
683   item->u.translate.dy = dy;
684
685   GDK_NOTE (EVENTS, g_print ("gdk_window_queue_translation %#x %d %d,%d\n",
686                              GDK_WINDOW_HWND (window),
687                              item->serial,
688                              dx, dy));
689
690   gdk_drawable_ref (window);
691   translate_queue = g_slist_append (translate_queue, item);
692 }
693
694 gboolean
695 _gdk_windowing_window_queue_antiexpose (GdkWindow *window,
696                                         GdkRegion *area)
697 {
698   GdkWindowQueueItem *item = g_new (GdkWindowQueueItem, 1);
699
700   item->window = window;
701   item->serial = GetMessageTime ();
702   item->type = GDK_WINDOW_QUEUE_ANTIEXPOSE;
703   item->u.antiexpose.area = area;
704
705   GDK_NOTE (EVENTS, g_print ("_gdk_windowing_window_queue_antiexpose %#x %d %dx%d@+%d+%d\n",
706                              GDK_WINDOW_HWND (window),
707                              item->serial,
708                              area->extents.x2 - area->extents.x1,
709                              area->extents.y2 - area->extents.y1,
710                              area->extents.x1, area->extents.y1));
711
712   gdk_drawable_ref (window);
713   translate_queue = g_slist_append (translate_queue, item);
714
715   return TRUE;
716 }
717
718 void
719 _gdk_window_process_expose (GdkWindow    *window,
720                             gulong        serial,
721                             GdkRectangle *area)
722 {
723   GdkWindowImplWin32 *impl;
724   GdkRegion *invalidate_region = gdk_region_rectangle (area);
725   GdkRegion *clip_region;
726   GSList *tmp_list = translate_queue;
727
728   impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
729   
730   GDK_NOTE (EVENTS, g_print ("_gdk_window_process_expose %#x %d %dx%d@+%d+%d\n",
731                              GDK_WINDOW_HWND (window), serial,
732                              area->width, area->height, area->x, area->y));
733
734   while (tmp_list)
735     {
736       GdkWindowQueueItem *item = tmp_list->data;
737       tmp_list = tmp_list->next;
738
739       if (serial < item->serial)
740         {
741           if (item->window == window)
742             {
743               if (item->type == GDK_WINDOW_QUEUE_TRANSLATE)
744                 gdk_region_offset (invalidate_region, - item->u.translate.dx, - item->u.translate.dy);
745               else              /* anti-expose */
746                 gdk_region_subtract (invalidate_region, item->u.antiexpose.area);
747             }
748         }
749       else
750         {
751           GSList *tmp_link = translate_queue;
752           
753           translate_queue = g_slist_remove_link (translate_queue, translate_queue);
754           gdk_drawable_unref (item->window);
755
756           if (item->type == GDK_WINDOW_QUEUE_ANTIEXPOSE)
757             gdk_region_destroy (item->u.antiexpose.area);
758           
759           g_free (item);
760           g_slist_free_1 (tmp_link);
761         }
762     }
763
764   clip_region = gdk_region_rectangle (&impl->position_info.clip_rect);
765   gdk_region_intersect (invalidate_region, clip_region);
766
767   if (!gdk_region_empty (invalidate_region))
768     gdk_window_invalidate_region (window, invalidate_region, FALSE);
769
770   gdk_region_destroy (invalidate_region);
771   gdk_region_destroy (clip_region);
772 }
773
774 static void
775 gdk_window_tmp_unset_bg (GdkWindow *window)
776 {
777   GdkWindowImplWin32 *impl;
778   GdkWindowObject *obj;
779
780   obj = (GdkWindowObject *) window;
781   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
782
783   impl->position_info.no_bg = TRUE;
784
785   if (obj->bg_pixmap != GDK_NO_BG)
786     /* ??? */;
787 }
788
789 static void
790 gdk_window_tmp_reset_bg (GdkWindow *window)
791 {
792   GdkWindowImplWin32 *impl;
793   GdkWindowObject *obj;
794
795   obj = (GdkWindowObject *) window;
796   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
797
798   impl->position_info.no_bg = FALSE;
799
800   if (obj->bg_pixmap == GDK_NO_BG)
801     return;
802   
803   if (obj->bg_pixmap)
804     {
805       HBITMAP hbitmap;
806
807       /* ??? */
808     }
809   else
810     {
811       /* ??? */
812     }
813 }
814
815 static void
816 gdk_window_clip_changed (GdkWindow    *window,
817                          GdkRectangle *old_clip,
818                          GdkRectangle *new_clip)
819 {
820   GdkWindowImplWin32 *impl;
821   GdkWindowObject *obj;
822   GdkRegion *old_clip_region;
823   GdkRegion *new_clip_region;
824
825   if (((GdkWindowObject *)window)->input_only)
826     return;
827
828   old_clip_region = gdk_region_rectangle (old_clip);
829   new_clip_region = gdk_region_rectangle (new_clip);
830
831   /* Trim invalid region of window to new clip rectangle
832    */
833   if (obj->update_area)
834     gdk_region_intersect (obj->update_area, new_clip_region);
835
836   /* Invalidate newly exposed portion of window
837    */
838   gdk_region_subtract (new_clip_region, old_clip_region);
839   if (!gdk_region_empty (new_clip_region))
840     {
841       gdk_window_tmp_unset_bg (window);
842       gdk_window_invalidate_region (window, new_clip_region, FALSE);
843     }
844
845   gdk_region_destroy (new_clip_region);
846   gdk_region_destroy (old_clip_region);
847 }
848