]> Pileus Git - ~andy/gtk/blob - gdk/win32/gdkgeometry-win32.c
updated
[~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. 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 && GDK_WINDOW_IS_MAPPED (obj))
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       /*
357        * HB: Passing TRUE(=Redraw) to MoveWindow here fixes some
358        * redraw problems with (e.g. testgtk main buttons)
359        * scrolling. AFAIK the non flicker optimization would
360        * be done by the GDI anyway, if the window is SW_HIDE.
361        */
362       if (is_resize)
363         {
364           if (!MoveWindow (GDK_WINDOW_HWND (window),
365                            new_info.x, new_info.y, new_info.width, new_info.height,
366                            TRUE /*FALSE*/))
367             WIN32_API_FAILED ("MoveWindow");
368         }
369       else
370         {
371           GetClientRect (GDK_WINDOW_HWND (window), &rect);
372           if (!MoveWindow (GDK_WINDOW_HWND (window),
373                            new_info.x, new_info.y,
374                            rect.right - rect.left, rect.bottom - rect.top,
375                            TRUE /*FALSE*/))
376             WIN32_API_FAILED ("MoveWindow");
377         }
378
379       tmp_list = obj->children;
380       while (tmp_list)
381         {
382           gdk_window_postmove (tmp_list->data, &parent_pos);
383           tmp_list = tmp_list->next;
384         }
385
386       if (impl->position_info.no_bg)
387         gdk_window_tmp_reset_bg (window);
388
389       if (!impl->position_info.mapped && new_info.mapped && GDK_WINDOW_IS_MAPPED (obj))
390         ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNA);
391
392       impl->position_info = new_info;
393     }
394 }
395
396 static void
397 gdk_window_compute_position (GdkWindowImplWin32   *window,
398                              GdkWindowParentPos   *parent_pos,
399                              GdkWin32PositionInfo *info)
400 {
401   GdkWindowObject *wrapper;
402   int parent_x_offset;
403   int parent_y_offset;
404   
405   g_return_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (window));
406
407   wrapper = GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_WIN32 (window)->wrapper);
408
409   info->big = FALSE;
410   
411   if (window->width <= 32768)
412     {
413       info->width = window->width;
414       info->x = parent_pos->x + wrapper->x - parent_pos->win32_x;
415     }
416   else
417     {
418       info->big = TRUE;
419       info->width = 32768;
420       if (parent_pos->x + wrapper->x < -16384)
421         {
422           if (parent_pos->x + wrapper->x + window->width < 16384)
423             info->x = parent_pos->x + wrapper->x + window->width - 32768 - parent_pos->win32_x;
424           else
425             info->x = -16384 - parent_pos->win32_y;
426         }
427       else
428         info->x = parent_pos->x + wrapper->x - parent_pos->win32_x;
429     }
430
431   if (window->height <= 32768)
432     {
433       info->height = window->height;
434       info->y = parent_pos->y + wrapper->y - parent_pos->win32_y;
435     }
436   else
437     {
438       info->big = TRUE;
439       info->height = 32768;
440       if (parent_pos->y + wrapper->y < -16384)
441         {
442           if (parent_pos->y + wrapper->y + window->height < 16384)
443             info->y = parent_pos->y + wrapper->y + window->height - 32768 - parent_pos->win32_y;
444           else
445             info->y = -16384 - parent_pos->win32_y;
446         }
447       else
448         info->y = parent_pos->y + wrapper->y - parent_pos->win32_y;
449     }
450
451   parent_x_offset = parent_pos->win32_x - parent_pos->x;
452   parent_y_offset = parent_pos->win32_y - parent_pos->y;
453   
454   info->x_offset = parent_x_offset + info->x - wrapper->x;
455   info->y_offset = parent_y_offset + info->y - wrapper->y;
456
457   /* We don't considering the clipping of toplevel windows and their immediate children
458    * by their parents, and simply always map those windows.
459    */
460   if (parent_pos->clip_rect.width == G_MAXINT)
461     info->mapped = TRUE;
462   /* Check if the window would wrap around into the visible space in either direction */
463   else if (info->x + parent_x_offset < parent_pos->clip_rect.x + parent_pos->clip_rect.width - 65536 ||
464       info->x + info->width + parent_x_offset > parent_pos->clip_rect.x + 65536 ||
465       info->y + parent_y_offset < parent_pos->clip_rect.y + parent_pos->clip_rect.height - 65536 ||
466       info->y + info->height + parent_y_offset  > parent_pos->clip_rect.y + 65536)
467     info->mapped = FALSE;
468   else
469     info->mapped = TRUE;
470
471   info->no_bg = FALSE;
472
473   if (GDK_WINDOW_TYPE (wrapper) == GDK_WINDOW_CHILD)
474     {
475       info->clip_rect.x = wrapper->x;
476       info->clip_rect.y = wrapper->y;
477       info->clip_rect.width = window->width;
478       info->clip_rect.height = window->height;
479       
480       gdk_rectangle_intersect (&info->clip_rect, &parent_pos->clip_rect, &info->clip_rect);
481
482       info->clip_rect.x -= wrapper->x;
483       info->clip_rect.y -= wrapper->y;
484     }
485   else
486     {
487       info->clip_rect.x = 0;
488       info->clip_rect.y = 0;
489       info->clip_rect.width = G_MAXINT;
490       info->clip_rect.height = G_MAXINT;
491     }
492 }
493
494 static void
495 gdk_window_compute_parent_pos (GdkWindowImplWin32 *window,
496                                GdkWindowParentPos *parent_pos)
497 {
498   GdkWindowObject *wrapper;
499   GdkWindowObject *parent;
500   GdkRectangle tmp_clip;
501   
502   int clip_xoffset = 0;
503   int clip_yoffset = 0;
504
505   g_return_if_fail (GDK_IS_WINDOW_IMPL_WIN32 (window));
506
507   wrapper = GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_WIN32 (window)->wrapper);
508   
509   parent_pos->x = 0;
510   parent_pos->y = 0;
511   parent_pos->win32_x = 0;
512   parent_pos->win32_y = 0;
513
514   /* We take a simple approach here and simply consider toplevel
515    * windows not to clip their children on the right/bottom, since the
516    * size of toplevel windows is not directly under our
517    * control. Clipping only really matters when scrolling and
518    * generally we aren't going to be moving the immediate child of a
519    * toplevel beyond the bounds of that toplevel.
520    *
521    * We could go ahead and recompute the clips of toplevel windows and
522    * their descendents when we receive size notification, but it would
523    * probably not be an improvement in most cases.
524    */
525   parent_pos->clip_rect.x = 0;
526   parent_pos->clip_rect.y = 0;
527   parent_pos->clip_rect.width = G_MAXINT;
528   parent_pos->clip_rect.height = G_MAXINT;
529
530   parent = (GdkWindowObject *)wrapper->parent;
531   while (parent && parent->window_type == GDK_WINDOW_CHILD)
532     {
533       GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (parent->impl);
534       
535       tmp_clip.x = - clip_xoffset;
536       tmp_clip.y = - clip_yoffset;
537       tmp_clip.width = impl->width;
538       tmp_clip.height = impl->height;
539
540       gdk_rectangle_intersect (&parent_pos->clip_rect, &tmp_clip, &parent_pos->clip_rect);
541
542       parent_pos->x += parent->x;
543       parent_pos->y += parent->y;
544       parent_pos->win32_x += impl->position_info.x;
545       parent_pos->win32_y += impl->position_info.y;
546
547       clip_xoffset += parent->x;
548       clip_yoffset += parent->y;
549
550       parent = (GdkWindowObject *)parent->parent;
551     }
552 }
553
554 static void
555 gdk_window_premove (GdkWindow          *window,
556                     GdkWindowParentPos *parent_pos)
557 {
558   GdkWindowImplWin32 *impl;
559   GdkWindowObject *obj;
560   GdkWin32PositionInfo new_info;
561   GList *tmp_list;
562   gint d_xoffset, d_yoffset;
563   GdkWindowParentPos this_pos;
564   
565   obj = (GdkWindowObject *) window;
566   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
567   
568   gdk_window_compute_position (impl, parent_pos, &new_info);
569
570   gdk_window_clip_changed (window, &impl->position_info.clip_rect, &new_info.clip_rect);
571
572   this_pos.x = parent_pos->x + obj->x;
573   this_pos.y = parent_pos->y + obj->y;
574   this_pos.win32_x = parent_pos->win32_x + new_info.x;
575   this_pos.win32_y = parent_pos->win32_y + new_info.y;
576   this_pos.clip_rect = new_info.clip_rect;
577
578   if (impl->position_info.mapped && !new_info.mapped)
579     ShowWindow (GDK_WINDOW_HWND (window), SW_HIDE);
580
581   d_xoffset = new_info.x_offset - impl->position_info.x_offset;
582   d_yoffset = new_info.y_offset - impl->position_info.y_offset;
583   
584   if (d_xoffset != 0 || d_yoffset != 0)
585     {
586       gint new_x0, new_y0, new_x1, new_y1;
587
588       if (d_xoffset < 0 || d_yoffset < 0)
589         gdk_window_queue_translation (window, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
590         
591       if (d_xoffset < 0)
592         {
593           new_x0 = impl->position_info.x + d_xoffset;
594           new_x1 = impl->position_info.x + impl->position_info.width;
595         }
596       else
597         {
598           new_x0 = impl->position_info.x;
599           new_x1 = impl->position_info.x + new_info.width + d_xoffset;
600         }
601
602       if (d_yoffset < 0)
603         {
604           new_y0 = impl->position_info.y + d_yoffset;
605           new_y1 = impl->position_info.y + impl->position_info.height;
606         }
607       else
608         {
609           new_y0 = impl->position_info.y;
610           new_y1 = impl->position_info.y + new_info.height + d_yoffset;
611         }
612
613       if (!MoveWindow (GDK_WINDOW_HWND (window),
614                        new_x0, new_y0, new_x1 - new_x0, new_y1 - new_y0,
615                        FALSE))
616         WIN32_API_FAILED ("MoveWindow");
617     }
618
619   tmp_list = obj->children;
620   while (tmp_list)
621     {
622       gdk_window_premove (tmp_list->data, &this_pos);
623       tmp_list = tmp_list->next;
624     }
625 }
626
627 static void
628 gdk_window_postmove (GdkWindow          *window,
629                      GdkWindowParentPos *parent_pos)
630 {
631   GdkWindowImplWin32 *impl;
632   GdkWindowObject *obj;
633   GdkWin32PositionInfo new_info;
634   GList *tmp_list;
635   gint d_xoffset, d_yoffset;
636   GdkWindowParentPos this_pos;
637   
638   obj = (GdkWindowObject *) window;
639   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
640   
641   gdk_window_compute_position (impl, parent_pos, &new_info);
642
643   this_pos.x = parent_pos->x + obj->x;
644   this_pos.y = parent_pos->y + obj->y;
645   this_pos.win32_x = parent_pos->win32_x + new_info.x;
646   this_pos.win32_y = parent_pos->win32_y + new_info.y;
647   this_pos.clip_rect = new_info.clip_rect;
648
649   d_xoffset = new_info.x_offset - impl->position_info.x_offset;
650   d_yoffset = new_info.y_offset - impl->position_info.y_offset;
651   
652   if (d_xoffset != 0 || d_yoffset != 0)
653     {
654       if (d_xoffset > 0 || d_yoffset > 0)
655         gdk_window_queue_translation (window, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
656         
657       if (!MoveWindow (GDK_WINDOW_HWND (window),
658                        new_info.x, new_info.y, new_info.width, new_info.height,
659                        FALSE))
660         WIN32_API_FAILED ("MoveWindow");
661     }
662
663   if (!impl->position_info.mapped && new_info.mapped && GDK_WINDOW_IS_MAPPED (obj))
664     ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNA);
665
666   if (impl->position_info.no_bg)
667     gdk_window_tmp_reset_bg (window);
668
669   impl->position_info = new_info;
670
671   tmp_list = obj->children;
672   while (tmp_list)
673     {
674       gdk_window_postmove (tmp_list->data, &this_pos);
675       tmp_list = tmp_list->next;
676     }
677 }
678
679 static void
680 gdk_window_queue_translation (GdkWindow *window,
681                               gint       dx,
682                               gint       dy)
683 {
684   GdkWindowQueueItem *item = g_new (GdkWindowQueueItem, 1);
685   item->window = window;
686   item->serial = GetMessageTime ();
687   item->type = GDK_WINDOW_QUEUE_TRANSLATE;
688   item->u.translate.dx = dx;
689   item->u.translate.dy = dy;
690
691   GDK_NOTE (EVENTS, g_print ("gdk_window_queue_translation %#x %ld %d,%d\n",
692                              (guint) GDK_WINDOW_HWND (window),
693                              item->serial,
694                              dx, dy));
695
696   gdk_drawable_ref (window);
697   translate_queue = g_slist_append (translate_queue, item);
698 }
699
700 gboolean
701 _gdk_windowing_window_queue_antiexpose (GdkWindow *window,
702                                         GdkRegion *area)
703 {
704 #if 0
705   GdkWindowQueueItem *item = g_new (GdkWindowQueueItem, 1);
706
707   item->window = window;
708   item->serial = GetMessageTime ();
709   item->type = GDK_WINDOW_QUEUE_ANTIEXPOSE;
710   item->u.antiexpose.area = area;
711
712   GDK_NOTE (EVENTS, g_print ("_gdk_windowing_window_queue_antiexpose %#x %ld %dx%d@+%d+%d\n",
713                              (guint) GDK_WINDOW_HWND (window),
714                              item->serial,
715                              area->extents.x2 - area->extents.x1,
716                              area->extents.y2 - area->extents.y1,
717                              area->extents.x1, area->extents.y1));
718
719   gdk_drawable_ref (window);
720   translate_queue = g_slist_append (translate_queue, item);
721
722   return TRUE;
723 #else
724   GdkRectangle r;
725   HRGN hrgn;
726
727   gdk_region_get_clipbox (area, &r);
728   hrgn = CreateRectRgn(r.x, r.y, r.width+1, r.height+1);
729
730   g_return_val_if_fail (area != NULL, FALSE);
731
732   GDK_NOTE (MISC, g_print ("_gdk_windowing_window_queue_antiexpose %#x\n",
733                            (guint) GDK_WINDOW_HWND (window)));
734
735   /* HB: not quite sure if this is the right thing to do.
736    * (Region not to be proceesed by next WM_PAINT)
737    */
738   ValidateRgn(GDK_WINDOW_HWND (window), hrgn);
739   DeleteObject(hrgn);
740   return TRUE;
741 #endif
742 }
743
744 void
745 _gdk_window_process_expose (GdkWindow    *window,
746                             gulong        serial,
747                             GdkRectangle *area)
748 {
749   GdkWindowImplWin32 *impl;
750   GdkRegion *invalidate_region = gdk_region_rectangle (area);
751   GdkRegion *clip_region;
752   GSList *tmp_list = translate_queue;
753
754   impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl);
755   
756   GDK_NOTE (EVENTS, g_print ("_gdk_window_process_expose %#x %ld %dx%d@+%d+%d\n",
757                              (guint) GDK_WINDOW_HWND (window), serial,
758                              area->width, area->height, area->x, area->y));
759
760   while (tmp_list)
761     {
762       GdkWindowQueueItem *item = tmp_list->data;
763       tmp_list = tmp_list->next;
764
765       if (serial < item->serial)
766         {
767           if (item->window == window)
768             {
769               if (item->type == GDK_WINDOW_QUEUE_TRANSLATE)
770                 gdk_region_offset (invalidate_region, - item->u.translate.dx, - item->u.translate.dy);
771               else              /* anti-expose */
772                 gdk_region_subtract (invalidate_region, item->u.antiexpose.area);
773             }
774         }
775       else
776         {
777           GSList *tmp_link = translate_queue;
778           
779           translate_queue = g_slist_remove_link (translate_queue, translate_queue);
780           gdk_drawable_unref (item->window);
781
782           if (item->type == GDK_WINDOW_QUEUE_ANTIEXPOSE)
783             gdk_region_destroy (item->u.antiexpose.area);
784           
785           g_free (item);
786           g_slist_free_1 (tmp_link);
787         }
788     }
789
790   clip_region = gdk_region_rectangle (&impl->position_info.clip_rect);
791   gdk_region_intersect (invalidate_region, clip_region);
792
793   if (!gdk_region_empty (invalidate_region))
794     gdk_window_invalidate_region (window, invalidate_region, FALSE);
795
796   gdk_region_destroy (invalidate_region);
797   gdk_region_destroy (clip_region);
798 }
799
800 static void
801 gdk_window_tmp_unset_bg (GdkWindow *window)
802 {
803   GdkWindowImplWin32 *impl;
804   GdkWindowObject *obj;
805
806   obj = (GdkWindowObject *) window;
807   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
808
809   impl->position_info.no_bg = TRUE;
810
811   if (obj->bg_pixmap != GDK_NO_BG)
812     /* ??? */;
813 }
814
815 static void
816 gdk_window_tmp_reset_bg (GdkWindow *window)
817 {
818   GdkWindowImplWin32 *impl;
819   GdkWindowObject *obj;
820
821   obj = (GdkWindowObject *) window;
822   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
823
824   impl->position_info.no_bg = FALSE;
825
826   if (obj->bg_pixmap == GDK_NO_BG)
827     return;
828   
829   if (obj->bg_pixmap)
830     {
831       /* ??? */
832     }
833   else
834     {
835       /* ??? */
836     }
837 }
838
839 static void
840 gdk_window_clip_changed (GdkWindow    *window,
841                          GdkRectangle *old_clip,
842                          GdkRectangle *new_clip)
843 {
844   GdkWindowImplWin32 *impl;
845   GdkWindowObject *obj;
846   GdkRegion *old_clip_region;
847   GdkRegion *new_clip_region;
848
849   if (((GdkWindowObject *)window)->input_only)
850     return;
851
852   obj = (GdkWindowObject *) window;
853   impl = GDK_WINDOW_IMPL_WIN32 (obj->impl);
854   
855   old_clip_region = gdk_region_rectangle (old_clip);
856   new_clip_region = gdk_region_rectangle (new_clip);
857
858   /* Trim invalid region of window to new clip rectangle
859    */
860   if (obj->update_area)
861     gdk_region_intersect (obj->update_area, new_clip_region);
862
863   /* Invalidate newly exposed portion of window
864    */
865   gdk_region_subtract (new_clip_region, old_clip_region);
866   if (!gdk_region_empty (new_clip_region))
867     {
868       gdk_window_tmp_unset_bg (window);
869       gdk_window_invalidate_region (window, new_clip_region, FALSE);
870     }
871
872   gdk_region_destroy (new_clip_region);
873   gdk_region_destroy (old_clip_region);
874 }