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