]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkgeometry-x11.c
test the window state stuff
[~andy/gtk] / gdk / x11 / gdkgeometry-x11.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-x11.c: emulation of 32 bit coordinates within the
21  * limits of X. 
22  *
23  * By Owen Taylor <otaylor@redhat.com>
24  * Copyright Red Hat, Inc. 2000
25  */
26
27 #include "gdk.h"                /* For gdk_rectangle_intersect */
28 #include "gdkprivate-x11.h"
29 #include "gdkx.h"
30 #include "gdkregion.h"
31 #include "gdkinternals.h"
32
33 typedef struct _GdkWindowQueueItem GdkWindowQueueItem;
34 typedef struct _GdkWindowParentPos GdkWindowParentPos;
35
36 typedef enum {
37   GDK_WINDOW_QUEUE_TRANSLATE,
38   GDK_WINDOW_QUEUE_ANTIEXPOSE
39 } GdkWindowQueueType;
40
41 struct _GdkWindowQueueItem
42 {
43   GdkWindow *window;
44   gulong serial;
45   GdkWindowQueueType type;
46   union {
47     struct {
48       gint dx;
49       gint dy;
50     } translate;
51     struct {
52       GdkRegion *area;
53     } antiexpose;
54   } u;
55 };
56
57 struct _GdkWindowParentPos
58 {
59   gint x;
60   gint y;
61   gint x11_x;
62   gint x11_y;
63   GdkRectangle clip_rect;
64 };
65
66 static void gdk_window_compute_position   (GdkWindowImplX11      *window,
67                                            GdkWindowParentPos *parent_pos,
68                                            GdkXPositionInfo   *info);
69 static void gdk_window_compute_parent_pos (GdkWindowImplX11      *window,
70                                            GdkWindowParentPos *parent_pos);
71 static void gdk_window_premove            (GdkWindow          *window,
72                                            GdkWindowParentPos *parent_pos);
73 static void gdk_window_postmove           (GdkWindow          *window,
74                                            GdkWindowParentPos *parent_pos);
75 static void gdk_window_queue_translation  (GdkWindow          *window,
76                                            gint                dx,
77                                            gint                dy);
78 static void gdk_window_tmp_unset_bg       (GdkWindow          *window);
79 static void gdk_window_tmp_reset_bg       (GdkWindow          *window);
80 static void gdk_window_clip_changed       (GdkWindow          *window,
81                                            GdkRectangle       *old_clip,
82                                            GdkRectangle       *new_clip);
83
84 static GSList *translate_queue = NULL;
85
86 void
87 _gdk_windowing_window_get_offsets (GdkWindow *window,
88                                    gint      *x_offset,
89                                    gint      *y_offset)
90 {
91   GdkWindowImplX11 *impl =
92     GDK_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (window)->impl);
93
94   *x_offset = impl->position_info.x_offset;
95   *y_offset = impl->position_info.y_offset;
96 }
97
98 void
99 _gdk_window_init_position (GdkWindow *window)
100 {
101   GdkWindowParentPos parent_pos;
102   GdkWindowImplX11 *impl;
103   
104   g_return_if_fail (GDK_IS_WINDOW (window));
105   
106   impl =
107     GDK_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (window)->impl);
108   
109   gdk_window_compute_parent_pos (impl, &parent_pos);
110   gdk_window_compute_position (impl, &parent_pos, &impl->position_info);
111 }
112
113 /**
114  * gdk_window_scroll:
115  * @window: a #GdkWindow
116  * @dx: Amount to scroll in the X direction
117  * @dy: Amount to scroll in the Y direction
118  * 
119  * Scroll the contents of its window, both pixels and children, by
120  * the given amount. Portions of the window that the scroll operation
121  * brings in from offscreen areas are invalidated. The invalidated
122  * region may be bigger than what would strictly be necessary.
123  * (For X11, a minimum area will be invalidated if the window has
124  * no subwindows, or if the edges of the window's parent do not extend
125  * beyond the edges of the window. In other cases, a multi-step process
126  * is used to scroll the window which may produce temporary visual
127  * artifacts and unnecessary invalidations.)
128  **/
129 void
130 gdk_window_scroll (GdkWindow *window,
131                    gint       dx,
132                    gint       dy)
133 {
134   gboolean can_guffaw_scroll = FALSE;
135   GdkWindowImplX11 *impl;
136   GdkWindowObject *obj;
137   
138   g_return_if_fail (GDK_IS_WINDOW (window));
139
140   obj = GDK_WINDOW_OBJECT (window);
141   
142   impl = GDK_WINDOW_IMPL_X11 (obj->impl);  
143   
144   if (GDK_WINDOW_DESTROYED (window))
145     return;
146   
147   /* Move the current invalid region */
148   if (obj->update_area)
149     gdk_region_offset (obj->update_area, dx, dy);
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       GdkWindowImplX11 *parent_impl = GDK_WINDOW_IMPL_X11 (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 XCopyArea, 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           GC gc;
182           XGCValues values;
183           GdkRegion *tmp_region;
184
185           tmp_region = gdk_region_rectangle (&dest_rect);
186           gdk_region_subtract (invalidate_region, tmp_region);
187           gdk_region_destroy (tmp_region);
188           
189           gdk_window_queue_translation (window, dx, dy);
190
191           values.graphics_exposures = True;
192           gc = XCreateGC (GDK_WINDOW_XDISPLAY (window),
193                           GDK_WINDOW_XID (window),
194                           GCGraphicsExposures, &values);
195
196           XCopyArea (GDK_WINDOW_XDISPLAY (window),
197                      GDK_WINDOW_XID (window),
198                      GDK_WINDOW_XID (window),
199                      gc,
200                      dest_rect.x - dx, dest_rect.y - dy,
201                      dest_rect.width, dest_rect.height,
202                      dest_rect.x, dest_rect.y);
203
204           XFreeGC (GDK_WINDOW_XDISPLAY (window), gc);
205         }
206
207       gdk_window_invalidate_region (window, invalidate_region, TRUE);
208       gdk_region_destroy (invalidate_region);
209
210       tmp_list = obj->children;
211       while (tmp_list)
212         {
213           GdkWindow * child = GDK_WINDOW (tmp_list->data);
214           
215           gdk_window_move (child, obj->x + dx, obj->y + dy);
216           
217           tmp_list = tmp_list->next;
218         }
219     }
220   else
221     {
222       /* Guffaw scroll
223        */
224       g_warning ("gdk_window_scroll(): guffaw scrolling not yet implemented");
225     }
226 }
227
228 void
229 _gdk_window_move_resize_child (GdkWindow *window,
230                                gint       x,
231                                gint       y,
232                                gint       width,
233                                gint       height)
234 {
235   GdkWindowImplX11 *impl;
236   GdkWindowObject *obj;
237   GdkXPositionInfo new_info;
238   GdkWindowParentPos parent_pos;
239   GList *tmp_list;
240   
241   gint d_xoffset, d_yoffset;
242   gint dx, dy;
243   gboolean is_move;
244   gboolean is_resize;
245   
246   g_return_if_fail (window != NULL);
247   g_return_if_fail (GDK_IS_WINDOW (window));
248
249   impl = GDK_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (window)->impl);
250   obj = GDK_WINDOW_OBJECT (window);
251   
252   dx = x - obj->x;
253   dy = y - obj->y;
254   
255   is_move = dx != 0 || dy != 0;
256   is_resize = impl->width != width || impl->height != height;
257
258   if (!is_move && !is_resize)
259     return;
260   
261   obj->x = x;
262   obj->y = y;
263   impl->width = width;
264   impl->height = height;
265
266   gdk_window_compute_parent_pos (impl, &parent_pos);
267   gdk_window_compute_position (impl, &parent_pos, &new_info);
268
269   gdk_window_clip_changed (window, &impl->position_info.clip_rect, &new_info.clip_rect);
270
271   parent_pos.x += obj->x;
272   parent_pos.y += obj->y;
273   parent_pos.x11_x += new_info.x;
274   parent_pos.x11_y += new_info.y;
275   parent_pos.clip_rect = new_info.clip_rect;
276
277   d_xoffset = new_info.x_offset - impl->position_info.x_offset;
278   d_yoffset = new_info.y_offset - impl->position_info.y_offset;
279   
280   if (d_xoffset != 0 || d_yoffset != 0)
281     {
282       gint new_x0, new_y0, new_x1, new_y1;
283
284       gdk_window_set_static_gravities (window, TRUE);
285
286       if (d_xoffset < 0 || d_yoffset < 0)
287         gdk_window_queue_translation (window, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
288         
289       if (d_xoffset < 0)
290         {
291           new_x0 = impl->position_info.x + d_xoffset;
292           new_x1 = impl->position_info.x + impl->position_info.width;
293         }
294       else
295         {
296           new_x0 = impl->position_info.x;
297           new_x1 = impl->position_info.x + new_info.width + d_xoffset;
298         }
299
300       if (d_yoffset < 0)
301         {
302           new_y0 = impl->position_info.y + d_yoffset;
303           new_y1 = impl->position_info.y + impl->position_info.height;
304         }
305       else
306         {
307           new_y0 = impl->position_info.y;
308           new_y1 = impl->position_info.y + new_info.height + d_yoffset;
309         }
310       
311       XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
312                          GDK_WINDOW_XID (window),
313                          new_x0, new_y0, new_x1 - new_x0, new_y1 - new_y0);
314       
315       tmp_list = obj->children;
316       while (tmp_list)
317         {
318           gdk_window_premove (tmp_list->data, &parent_pos);
319           tmp_list = tmp_list->next;
320         }
321
322       XMoveWindow (GDK_WINDOW_XDISPLAY (window),
323                    GDK_WINDOW_XID (window),
324                    new_x0 + dx, new_y0 + dy);
325       
326       if (d_xoffset > 0 || d_yoffset > 0)
327         gdk_window_queue_translation (window, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
328       
329       XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
330                          GDK_WINDOW_XID (window),
331                          new_info.x, new_info.y, new_info.width, new_info.height);
332       
333       if (impl->position_info.no_bg)
334         gdk_window_tmp_reset_bg (window);
335
336       if (!impl->position_info.mapped && new_info.mapped && GDK_WINDOW_IS_MAPPED (obj))
337         XMapWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
338       
339       impl->position_info = new_info;
340       
341       tmp_list = obj->children;
342       while (tmp_list)
343         {
344           gdk_window_postmove (tmp_list->data, &parent_pos);
345           tmp_list = tmp_list->next;
346         }
347     }
348   else
349     {
350       if (is_move && is_resize)
351         gdk_window_set_static_gravities (window, FALSE);
352
353       if (impl->position_info.mapped && !new_info.mapped)
354         XUnmapWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
355       
356       tmp_list = obj->children;
357       while (tmp_list)
358         {
359           gdk_window_premove (tmp_list->data, &parent_pos);
360           tmp_list = tmp_list->next;
361         }
362
363       if (is_resize)
364         XMoveResizeWindow (GDK_WINDOW_XDISPLAY (window),
365                            GDK_WINDOW_XID (window),
366                            new_info.x, new_info.y, new_info.width, new_info.height);
367       else
368         XMoveWindow (GDK_WINDOW_XDISPLAY (window),
369                      GDK_WINDOW_XID (window),
370                      new_info.x, new_info.y);
371
372       tmp_list = obj->children;
373       while (tmp_list)
374         {
375           gdk_window_postmove (tmp_list->data, &parent_pos);
376           tmp_list = tmp_list->next;
377         }
378
379       if (impl->position_info.no_bg)
380         gdk_window_tmp_reset_bg (window);
381
382       if (!impl->position_info.mapped && new_info.mapped && GDK_WINDOW_IS_MAPPED (obj))
383         XMapWindow (GDK_WINDOW_XDISPLAY (window), GDK_WINDOW_XID (window));
384
385       impl->position_info = new_info;
386     }
387 }
388
389 static void
390 gdk_window_compute_position (GdkWindowImplX11   *window,
391                              GdkWindowParentPos *parent_pos,
392                              GdkXPositionInfo   *info)
393 {
394   GdkWindowObject *wrapper;
395   int parent_x_offset;
396   int parent_y_offset;
397
398   g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (window));
399
400   wrapper = GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_X11 (window)->wrapper);
401   
402   info->big = FALSE;
403   
404   if (window->width <= 32768)
405     {
406       info->width = window->width;
407       info->x = parent_pos->x + wrapper->x - parent_pos->x11_x;
408     }
409   else
410     {
411       info->big = TRUE;
412       info->width = 32768;
413       if (parent_pos->x + wrapper->x < -16384)
414         {
415           if (parent_pos->x + wrapper->x + window->width < 16384)
416             info->x = parent_pos->x + wrapper->x + window->width - 32768 - parent_pos->x11_x;
417           else
418             info->x = -16384 - parent_pos->x11_y;
419         }
420       else
421         info->x = parent_pos->x + wrapper->x - parent_pos->x11_x;
422     }
423
424   if (window->height <= 32768)
425     {
426       info->height = window->height;
427       info->y = parent_pos->y + wrapper->y - parent_pos->x11_y;
428     }
429   else
430     {
431       info->big = TRUE;
432       info->height = 32768;
433       if (parent_pos->y + wrapper->y < -16384)
434         {
435           if (parent_pos->y + wrapper->y + window->height < 16384)
436             info->y = parent_pos->y + wrapper->y + window->height - 32768 - parent_pos->x11_y;
437           else
438             info->y = -16384 - parent_pos->x11_y;
439         }
440       else
441         info->y = parent_pos->y + wrapper->y - parent_pos->x11_y;
442     }
443
444   parent_x_offset = parent_pos->x11_x - parent_pos->x;
445   parent_y_offset = parent_pos->x11_y - parent_pos->y;
446   
447   info->x_offset = parent_x_offset + info->x - wrapper->x;
448   info->y_offset = parent_y_offset + info->y - wrapper->y;
449
450   /* We don't considering the clipping of toplevel windows and their immediate children
451    * by their parents, and simply always map those windows.
452    */
453   if (parent_pos->clip_rect.width == G_MAXINT)
454     info->mapped = TRUE;
455   /* Check if the window would wrap around into the visible space in either direction */
456   else if (info->x + parent_x_offset < parent_pos->clip_rect.x + parent_pos->clip_rect.width - 65536 ||
457       info->x + info->width + parent_x_offset > parent_pos->clip_rect.x + 65536 ||
458       info->y + parent_y_offset < parent_pos->clip_rect.y + parent_pos->clip_rect.height - 65536 ||
459       info->y + info->height + parent_y_offset  > parent_pos->clip_rect.y + 65536)
460     info->mapped = FALSE;
461   else
462     info->mapped = TRUE;
463
464   info->no_bg = FALSE;
465
466   if (GDK_WINDOW_TYPE (wrapper) == GDK_WINDOW_CHILD)
467     {
468       info->clip_rect.x = wrapper->x;
469       info->clip_rect.y = wrapper->y;
470       info->clip_rect.width = window->width;
471       info->clip_rect.height = window->height;
472       
473       gdk_rectangle_intersect (&info->clip_rect, &parent_pos->clip_rect, &info->clip_rect);
474
475       info->clip_rect.x -= wrapper->x;
476       info->clip_rect.y -= wrapper->y;
477     }
478   else
479     {
480       info->clip_rect.x = 0;
481       info->clip_rect.y = 0;
482       info->clip_rect.width = G_MAXINT;
483       info->clip_rect.height = G_MAXINT;
484     }
485 }
486
487 static void
488 gdk_window_compute_parent_pos (GdkWindowImplX11      *window,
489                                GdkWindowParentPos *parent_pos)
490 {
491   GdkWindowObject *wrapper;
492   GdkWindowObject *parent;
493   GdkRectangle tmp_clip;
494   
495   int clip_xoffset = 0;
496   int clip_yoffset = 0;
497
498   g_return_if_fail (GDK_IS_WINDOW_IMPL_X11 (window));
499
500   wrapper =
501     GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_X11 (window)->wrapper);
502   
503   parent_pos->x = 0;
504   parent_pos->y = 0;
505   parent_pos->x11_x = 0;
506   parent_pos->x11_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       GdkWindowImplX11 *impl = GDK_WINDOW_IMPL_X11 (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->x11_x += impl->position_info.x;
539       parent_pos->x11_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   GdkWindowImplX11 *impl;
553   GdkWindowObject *obj;
554   GdkXPositionInfo 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_X11 (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.x11_x = parent_pos->x11_x + new_info.x;
569   this_pos.x11_y = parent_pos->x11_y + new_info.y;
570   this_pos.clip_rect = new_info.clip_rect;
571
572   if (impl->position_info.mapped && !new_info.mapped)
573     XUnmapWindow (GDK_DRAWABLE_XDISPLAY (window), GDK_DRAWABLE_XID (window));
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       XMoveResizeWindow (GDK_DRAWABLE_XDISPLAY (window),
608                          GDK_DRAWABLE_XID (window),
609                          new_x0, new_y0, new_x1 - new_x0, new_y1 - new_y0);
610     }
611
612   tmp_list = obj->children;
613   while (tmp_list)
614     {
615       gdk_window_premove (tmp_list->data, &this_pos);
616       tmp_list = tmp_list->next;
617     }
618 }
619
620 static void
621 gdk_window_postmove (GdkWindow          *window,
622                      GdkWindowParentPos *parent_pos)
623 {
624   GdkWindowImplX11 *impl;
625   GdkWindowObject *obj;
626   GdkXPositionInfo new_info;
627   GList *tmp_list;
628   gint d_xoffset, d_yoffset;
629   GdkWindowParentPos this_pos;
630
631   obj = (GdkWindowObject *) window;
632   impl = GDK_WINDOW_IMPL_X11 (obj->impl);
633   
634   gdk_window_compute_position (impl, parent_pos, &new_info);
635
636   this_pos.x = parent_pos->x + obj->x;
637   this_pos.y = parent_pos->y + obj->y;
638   this_pos.x11_x = parent_pos->x11_x + new_info.x;
639   this_pos.x11_y = parent_pos->x11_y + new_info.y;
640   this_pos.clip_rect = new_info.clip_rect;
641
642   d_xoffset = new_info.x_offset - impl->position_info.x_offset;
643   d_yoffset = new_info.y_offset - impl->position_info.y_offset;
644   
645   if (d_xoffset != 0 || d_yoffset != 0)
646     {
647       if (d_xoffset > 0 || d_yoffset > 0)
648         gdk_window_queue_translation (window, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
649         
650       XMoveResizeWindow (GDK_DRAWABLE_XDISPLAY (window),
651                          GDK_DRAWABLE_XID (window),
652                          new_info.x, new_info.y, new_info.width, new_info.height);
653     }
654
655   if (!impl->position_info.mapped && new_info.mapped && GDK_WINDOW_IS_MAPPED (obj))
656     XMapWindow (GDK_DRAWABLE_XDISPLAY (window), GDK_DRAWABLE_XID (window));
657
658   if (impl->position_info.no_bg)
659     gdk_window_tmp_reset_bg (window);
660
661   impl->position_info = new_info;
662
663   tmp_list = obj->children;
664   while (tmp_list)
665     {
666       gdk_window_postmove (tmp_list->data, &this_pos);
667       tmp_list = tmp_list->next;
668     }
669 }
670
671 static void
672 gdk_window_queue_translation (GdkWindow *window,
673                               gint       dx,
674                               gint       dy)
675 {
676   GdkWindowQueueItem *item = g_new (GdkWindowQueueItem, 1);
677   item->window = window;
678   item->serial = NextRequest (GDK_WINDOW_XDISPLAY (window));
679   item->type = GDK_WINDOW_QUEUE_TRANSLATE;
680   item->u.translate.dx = dx;
681   item->u.translate.dy = dy;
682
683   gdk_drawable_ref (window);
684   translate_queue = g_slist_append (translate_queue, item);
685 }
686
687 gboolean
688 _gdk_windowing_window_queue_antiexpose (GdkWindow *window,
689                                         GdkRegion *area)
690 {
691   GdkWindowQueueItem *item = g_new (GdkWindowQueueItem, 1);
692   item->window = window;
693   item->serial = NextRequest (GDK_WINDOW_XDISPLAY (window));
694   item->type = GDK_WINDOW_QUEUE_ANTIEXPOSE;
695   item->u.antiexpose.area = area;
696
697   gdk_drawable_ref (window);
698   translate_queue = g_slist_append (translate_queue, item);
699
700   return TRUE;
701 }
702
703 void
704 _gdk_window_process_expose (GdkWindow    *window,
705                             gulong        serial,
706                             GdkRectangle *area)
707 {
708   GdkWindowImplX11 *impl;
709   GdkRegion *invalidate_region = gdk_region_rectangle (area);
710   GdkRegion *clip_region;
711   GSList *tmp_list = translate_queue;
712
713   impl = GDK_WINDOW_IMPL_X11 (GDK_WINDOW_OBJECT (window)->impl);
714   
715   while (tmp_list)
716     {
717       GdkWindowQueueItem *item = tmp_list->data;
718       tmp_list = tmp_list->next;
719
720       if (serial < item->serial)
721         {
722           if (item->window == window)
723             {
724               if (item->type == GDK_WINDOW_QUEUE_TRANSLATE)
725                 gdk_region_offset (invalidate_region, - item->u.translate.dx, - item->u.translate.dy);
726               else              /* anti-expose */
727                 gdk_region_subtract (invalidate_region, item->u.antiexpose.area);
728             }
729         }
730       else
731         {
732           GSList *tmp_link = translate_queue;
733           
734           translate_queue = g_slist_remove_link (translate_queue, translate_queue);
735           gdk_drawable_unref (item->window);
736
737           if (item->type == GDK_WINDOW_QUEUE_ANTIEXPOSE)
738             gdk_region_destroy (item->u.antiexpose.area);
739           
740           g_free (item);
741           g_slist_free_1 (tmp_link);
742         }
743     }
744
745   clip_region = gdk_region_rectangle (&impl->position_info.clip_rect);
746   gdk_region_intersect (invalidate_region, clip_region);
747
748   if (!gdk_region_empty (invalidate_region))
749     gdk_window_invalidate_region (window, invalidate_region, FALSE);
750
751   gdk_region_destroy (invalidate_region);
752   gdk_region_destroy (clip_region);
753 }
754
755 static void
756 gdk_window_tmp_unset_bg (GdkWindow *window)
757 {
758   GdkWindowImplX11 *impl;
759   GdkWindowObject *obj;
760
761   obj = (GdkWindowObject *) window;
762   impl = GDK_WINDOW_IMPL_X11 (obj->impl);
763
764   impl->position_info.no_bg = TRUE;
765
766   if (obj->bg_pixmap != GDK_NO_BG)
767     XSetWindowBackgroundPixmap (GDK_DRAWABLE_XDISPLAY (window),
768                                 GDK_DRAWABLE_XID (window), None);
769 }
770
771 static void
772 gdk_window_tmp_reset_bg (GdkWindow *window)
773 {
774   GdkWindowImplX11 *impl;
775   GdkWindowObject *obj;
776
777   obj = (GdkWindowObject *) window;
778   impl = GDK_WINDOW_IMPL_X11 (obj->impl);
779
780   impl->position_info.no_bg = FALSE;
781
782   if (obj->bg_pixmap == GDK_NO_BG)
783     return;
784   
785   if (obj->bg_pixmap)
786     {
787       Pixmap xpixmap;
788
789       if (obj->bg_pixmap == GDK_PARENT_RELATIVE_BG)
790         xpixmap = ParentRelative;
791       else 
792         xpixmap = GDK_DRAWABLE_XID (obj->bg_pixmap);
793
794       XSetWindowBackgroundPixmap (GDK_DRAWABLE_XDISPLAY (window),
795                                   GDK_DRAWABLE_XID (window), xpixmap);
796     }
797   else
798     {
799       XSetWindowBackground (GDK_DRAWABLE_XDISPLAY (window),
800                             GDK_DRAWABLE_XID (window),
801                             obj->bg_color.pixel);
802     }
803 }
804
805 static void
806 gdk_window_clip_changed (GdkWindow *window, GdkRectangle *old_clip, GdkRectangle *new_clip)
807 {
808   GdkWindowImplX11 *impl;
809   GdkWindowObject *obj;
810   GdkRegion *old_clip_region;
811   GdkRegion *new_clip_region;
812   
813   if (((GdkWindowObject *)window)->input_only)
814     return;
815
816   obj = (GdkWindowObject *) window;
817   impl = GDK_WINDOW_IMPL_X11 (obj->impl);
818   
819   old_clip_region = gdk_region_rectangle (old_clip);
820   new_clip_region = gdk_region_rectangle (new_clip);
821
822   /* Trim invalid region of window to new clip rectangle
823    */
824   if (obj->update_area)
825     gdk_region_intersect (obj->update_area, new_clip_region);
826
827   /* Invalidate newly exposed portion of window
828    */
829   gdk_region_subtract (new_clip_region, old_clip_region);
830   if (!gdk_region_empty (new_clip_region))
831     {
832       gdk_window_tmp_unset_bg (window);
833       gdk_window_invalidate_region (window, new_clip_region, FALSE);
834     }
835
836   gdk_region_destroy (new_clip_region);
837   gdk_region_destroy (old_clip_region);
838 }
839