]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkgeometry-x11.c
Remove all references to offscreen flag which was no longer used.
[~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 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-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
32 typedef struct _GdkWindowQueueItem GdkWindowQueueItem;
33 typedef struct _GdkWindowParentPos GdkWindowParentPos;
34
35 typedef enum {
36   GDK_WINDOW_QUEUE_TRANSLATE,
37   GDK_WINDOW_QUEUE_ANTIEXPOSE
38 } GdkWindowQueueType;
39
40 struct _GdkWindowQueueItem
41 {
42   GdkWindow *window;
43   gulong serial;
44   GdkWindowQueueType type;
45   union {
46     struct {
47       gint dx;
48       gint dy;
49     } translate;
50     struct {
51       GdkRegion *area;
52     } antiexpose;
53   } u;
54 };
55
56 struct _GdkWindowParentPos
57 {
58   gint x;
59   gint y;
60   gint x11_x;
61   gint x11_y;
62   GdkRectangle clip_rect;
63 };
64
65 static void gdk_window_compute_position   (GdkWindow          *window,
66                                            GdkWindowParentPos *parent_pos,
67                                            GdkXPositionInfo   *info);
68 static void gdk_window_compute_parent_pos (GdkWindow          *window,
69                                            GdkWindowParentPos *parent_pos);
70 static void gdk_window_premove            (GdkWindow          *window,
71                                            GdkWindowParentPos *parent_pos);
72 static void gdk_window_postmove           (GdkWindow          *window,
73                                            GdkWindowParentPos *parent_pos);
74 static void gdk_window_queue_translation  (GdkWindow          *window,
75                                            gint                dx,
76                                            gint                dy);
77 static void gdk_window_tmp_unset_bg       (GdkWindow          *window);
78 static void gdk_window_tmp_reset_bg       (GdkWindow          *window);
79 static void gdk_window_clip_changed       (GdkWindow          *window,
80                                            GdkRectangle       *old_clip,
81                                            GdkRectangle       *new_clip);
82
83 static GSList *translate_queue = NULL;
84
85 void
86 _gdk_windowing_window_get_offsets (GdkWindow *window,
87                                    gint      *x_offset,
88                                    gint      *y_offset)
89 {
90   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
91   GdkWindowXData *data = (GdkWindowXData *)private->drawable.klass_data;
92
93   *x_offset = data->position_info.x_offset;
94   *y_offset = data->position_info.y_offset;
95 }
96
97 void
98 _gdk_window_init_position (GdkWindow *window)
99 {
100   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
101   GdkWindowXData *data;
102   GdkWindowParentPos parent_pos;
103
104   g_return_if_fail (window != NULL);
105   g_return_if_fail (GDK_IS_WINDOW (window));
106
107   data = (GdkWindowXData *)private->drawable.klass_data;
108
109   gdk_window_compute_parent_pos (window, &parent_pos);
110   gdk_window_compute_position (window, &parent_pos, &data->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   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
135   gboolean can_guffaw_scroll = FALSE;
136   GdkWindowXData *data;
137   
138   g_return_if_fail (window != NULL);
139   g_return_if_fail (GDK_IS_WINDOW (window));
140
141   if (GDK_DRAWABLE_DESTROYED (window))
142     return;
143
144   data = (GdkWindowXData *)private->drawable.klass_data;
145
146   /* We can guffaw scroll if we are a child window, and the parent
147    * does not extend beyond our edges.
148    */
149
150   if (GDK_DRAWABLE_TYPE (private) == GDK_WINDOW_CHILD)
151     {
152       GdkWindowPrivate *parent_private = (GdkWindowPrivate *)private->parent;
153       
154       can_guffaw_scroll = (private->x <= 0 &&
155                            private->y <= 0 &&
156                            private->x + private->drawable.width >= parent_private->drawable.width &&
157                            private->y + private->drawable.height >= parent_private->drawable.height);
158     }
159
160   if (!private->children || !can_guffaw_scroll)
161     {
162       /* Use XCopyArea, then move any children later
163        */
164       GList *tmp_list;
165       GdkRegion *invalidate_region;
166       GdkRectangle dest_rect;
167
168       invalidate_region = gdk_region_rectangle (&data->position_info.clip_rect);
169       
170       dest_rect = data->position_info.clip_rect;
171       dest_rect.x += dx;
172       dest_rect.y += dy;
173       gdk_rectangle_intersect (&dest_rect, &data->position_info.clip_rect, &dest_rect);
174
175       if (dest_rect.width > 0 && dest_rect.height > 0)
176         {
177           GC gc;
178           XGCValues values;
179           GdkRegion *tmp_region;
180
181           tmp_region = gdk_region_rectangle (&dest_rect);
182           gdk_region_subtract (invalidate_region, tmp_region);
183           gdk_region_destroy (tmp_region);
184           
185           gdk_window_queue_translation (window, dx, dy);
186
187           values.graphics_exposures = True;
188           gc = XCreateGC (GDK_DRAWABLE_XDISPLAY (window), GDK_DRAWABLE_XID (window),
189                           GCGraphicsExposures, &values);
190
191           XCopyArea (GDK_DRAWABLE_XDISPLAY (window),
192                      GDK_DRAWABLE_XID (window),
193                      GDK_DRAWABLE_XID (window),
194                      gc,
195                      dest_rect.x - dx, dest_rect.y - dy,
196                      dest_rect.width, dest_rect.height,
197                      dest_rect.x, dest_rect.y);
198
199           XFreeGC (GDK_DRAWABLE_XDISPLAY (window), gc);
200         }
201
202       gdk_window_invalidate_region (window, invalidate_region, TRUE);
203       gdk_region_destroy (invalidate_region);
204
205       tmp_list = private->children;
206       while (tmp_list)
207         {
208           private = tmp_list->data;
209           
210           gdk_window_move (tmp_list->data, private->x + dx, private->y + dy);
211           
212           tmp_list = tmp_list->next;
213         }
214     }
215   else
216     {
217       /* Guffaw scroll
218        */
219       g_warning ("gdk_window_scroll(): guffaw scrolling not yet implemented");
220     }
221 }
222
223 void
224 _gdk_window_move_resize_child (GdkWindow *window,
225                                gint       x,
226                                gint       y,
227                                gint       width,
228                                gint       height)
229 {
230   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
231   GdkXPositionInfo new_info;
232   GdkWindowParentPos parent_pos;
233   GdkWindowXData *data;
234   GList *tmp_list;
235   
236   gint d_xoffset, d_yoffset;
237   gint dx, dy;
238   gboolean is_move;
239   gboolean is_resize;
240   
241   g_return_if_fail (window != NULL);
242   g_return_if_fail (GDK_IS_WINDOW (window));
243
244   data = (GdkWindowXData *)private->drawable.klass_data;
245
246   dx = x - private->x;
247   dy = y - private->y;
248   
249   is_move = dx != 0 || dy != 0;
250   is_resize = private->drawable.width != width || private->drawable.height != height;
251
252   if (!is_move && !is_resize)
253     return;
254   
255   private->x = x;
256   private->y = y;
257   private->drawable.width = width;
258   private->drawable.height = height;
259
260   gdk_window_compute_parent_pos (window, &parent_pos);
261   gdk_window_compute_position (window, &parent_pos, &new_info);
262
263   gdk_window_clip_changed (window, &data->position_info.clip_rect, &new_info.clip_rect);
264
265   parent_pos.x += private->x;
266   parent_pos.y += private->y;
267   parent_pos.x11_x += new_info.x;
268   parent_pos.x11_y += new_info.y;
269   parent_pos.clip_rect = new_info.clip_rect;
270
271   d_xoffset = new_info.x_offset - data->position_info.x_offset;
272   d_yoffset = new_info.y_offset - data->position_info.y_offset;
273   
274   if (d_xoffset != 0 || d_yoffset != 0)
275     {
276       gint new_x0, new_y0, new_x1, new_y1;
277
278       gdk_window_set_static_gravities (window, TRUE);
279
280       if (d_xoffset < 0 || d_yoffset < 0)
281         gdk_window_queue_translation (window, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
282         
283       if (d_xoffset < 0)
284         {
285           new_x0 = data->position_info.x + d_xoffset;
286           new_x1 = data->position_info.x + data->position_info.width;
287         }
288       else
289         {
290           new_x0 = data->position_info.x;
291           new_x1 = data->position_info.x + new_info.width + d_xoffset;
292         }
293
294       if (d_yoffset < 0)
295         {
296           new_y0 = data->position_info.y + d_yoffset;
297           new_y1 = data->position_info.y + data->position_info.height;
298         }
299       else
300         {
301           new_y0 = data->position_info.y;
302           new_y1 = data->position_info.y + new_info.height + d_yoffset;
303         }
304       
305       XMoveResizeWindow (GDK_DRAWABLE_XDISPLAY (window),
306                          GDK_DRAWABLE_XID (window),
307                          new_x0, new_y0, new_x1 - new_x0, new_y1 - new_y0);
308       
309       tmp_list = private->children;
310       while (tmp_list)
311         {
312           gdk_window_premove (tmp_list->data, &parent_pos);
313           tmp_list = tmp_list->next;
314         }
315
316       XMoveWindow (GDK_DRAWABLE_XDISPLAY (window),
317                    GDK_DRAWABLE_XID (window),
318                    new_x0 + dx, new_y0 + dy);
319       
320       if (d_xoffset > 0 || d_yoffset > 0)
321         gdk_window_queue_translation (window, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
322       
323       XMoveResizeWindow (GDK_DRAWABLE_XDISPLAY (window),
324                          GDK_DRAWABLE_XID (window),
325                          new_info.x, new_info.y, new_info.width, new_info.height);
326       
327       if (data->position_info.no_bg)
328         gdk_window_tmp_reset_bg (window);
329
330       if (!data->position_info.mapped && new_info.mapped && private->mapped)
331         XMapWindow (GDK_DRAWABLE_XDISPLAY (window), GDK_DRAWABLE_XID (window));
332       
333       data->position_info = new_info;
334       
335       tmp_list = private->children;
336       while (tmp_list)
337         {
338           gdk_window_postmove (tmp_list->data, &parent_pos);
339           tmp_list = tmp_list->next;
340         }
341     }
342   else
343     {
344       if (is_move && is_resize)
345         gdk_window_set_static_gravities (window, FALSE);
346
347       if (data->position_info.mapped && !new_info.mapped)
348         XUnmapWindow (GDK_DRAWABLE_XDISPLAY (window), GDK_DRAWABLE_XID (window));
349       
350       tmp_list = private->children;
351       while (tmp_list)
352         {
353           gdk_window_premove (tmp_list->data, &parent_pos);
354           tmp_list = tmp_list->next;
355         }
356
357       if (is_resize)
358         XMoveResizeWindow (GDK_DRAWABLE_XDISPLAY (window),
359                            GDK_DRAWABLE_XID (window),
360                            new_info.x, new_info.y, new_info.width, new_info.height);
361       else
362         XMoveWindow (GDK_DRAWABLE_XDISPLAY (window),
363                      GDK_DRAWABLE_XID (window),
364                      new_info.x, new_info.y);
365
366       tmp_list = private->children;
367       while (tmp_list)
368         {
369           gdk_window_postmove (tmp_list->data, &parent_pos);
370           tmp_list = tmp_list->next;
371         }
372
373       if (data->position_info.no_bg)
374         gdk_window_tmp_reset_bg (window);
375
376       if (!data->position_info.mapped && new_info.mapped && private->mapped)
377         XMapWindow (GDK_DRAWABLE_XDISPLAY (window), GDK_DRAWABLE_XID (window));
378
379       data->position_info = new_info;
380     }
381 }
382
383 static void
384 gdk_window_compute_position (GdkWindow          *window,
385                              GdkWindowParentPos *parent_pos,
386                              GdkXPositionInfo   *info)
387 {
388   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
389   int parent_x_offset;
390   int parent_y_offset;
391   
392   info->big = FALSE;
393   
394   if (private->drawable.width <= 32768)
395     {
396       info->width = private->drawable.width;
397       info->x = parent_pos->x + private->x - parent_pos->x11_x;
398     }
399   else
400     {
401       info->big = TRUE;
402       info->width = 32768;
403       if (parent_pos->x + private->x < -16384)
404         {
405           if (parent_pos->x + private->x + private->drawable.width < 16384)
406             info->x = parent_pos->x + private->x + private->drawable.width - 32768 - parent_pos->x11_x;
407           else
408             info->x = -16384 - parent_pos->x11_y;
409         }
410       else
411         info->x = parent_pos->x + private->x - parent_pos->x11_x;
412     }
413
414   if (private->drawable.height <= 32768)
415     {
416       info->height = private->drawable.height;
417       info->y = parent_pos->y + private->y - parent_pos->x11_y;
418     }
419   else
420     {
421       info->big = TRUE;
422       info->height = 32768;
423       if (parent_pos->y + private->y < -16384)
424         {
425           if (parent_pos->y + private->y + private->drawable.height < 16384)
426             info->y = parent_pos->y + private->y + private->drawable.height - 32768 - parent_pos->x11_y;
427           else
428             info->y = -16384 - parent_pos->x11_y;
429         }
430       else
431         info->y = parent_pos->y + private->y - parent_pos->x11_y;
432     }
433
434   parent_x_offset = parent_pos->x11_x - parent_pos->x;
435   parent_y_offset = parent_pos->x11_y - parent_pos->y;
436   
437   info->x_offset = parent_x_offset + info->x - private->x;
438   info->y_offset = parent_y_offset + info->y - private->y;
439
440   /* We don't considering the clipping of toplevel windows and their immediate children
441    * by their parents, and simply always map those windows.
442    */
443   if (parent_pos->clip_rect.width == G_MAXINT)
444     info->mapped = TRUE;
445   /* Check if the window would wrap around into the visible space in either direction */
446   else if (info->x + parent_x_offset < parent_pos->clip_rect.x + parent_pos->clip_rect.width - 65536 ||
447       info->x + info->width + parent_x_offset > parent_pos->clip_rect.x + 65536 ||
448       info->y + parent_y_offset < parent_pos->clip_rect.y + parent_pos->clip_rect.height - 65536 ||
449       info->y + info->width + parent_y_offset  > parent_pos->clip_rect.y + 65536)
450     info->mapped = FALSE;
451   else
452     info->mapped = TRUE;
453
454   info->no_bg = FALSE;
455
456   if (GDK_DRAWABLE_TYPE (private) == GDK_WINDOW_CHILD)
457     {
458       info->clip_rect.x = private->x;
459       info->clip_rect.y = private->y;
460       info->clip_rect.width = private->drawable.width;
461       info->clip_rect.height = private->drawable.height;
462       
463       gdk_rectangle_intersect (&info->clip_rect, &parent_pos->clip_rect, &info->clip_rect);
464
465       info->clip_rect.x -= private->x;
466       info->clip_rect.y -= private->y;
467     }
468   else
469     {
470       info->clip_rect.x = 0;
471       info->clip_rect.y = 0;
472       info->clip_rect.width = G_MAXINT;
473       info->clip_rect.height = G_MAXINT;
474     }
475 }
476
477 static void
478 gdk_window_compute_parent_pos (GdkWindow          *window,
479                                GdkWindowParentPos *parent_pos)
480 {
481   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
482   GdkWindowXData *data;
483   GdkRectangle tmp_clip;
484   
485   int clip_xoffset = 0;
486   int clip_yoffset = 0;
487
488   parent_pos->x = 0;
489   parent_pos->y = 0;
490   parent_pos->x11_x = 0;
491   parent_pos->x11_y = 0;
492
493   /* We take a simple approach here and simply consider toplevel
494    * windows not to clip their children on the right/bottom, since the
495    * size of toplevel windows is not directly under our
496    * control. Clipping only really matters when scrolling and
497    * generally we aren't going to be moving the immediate child of a
498    * toplevel beyond the bounds of that toplevel.
499    *
500    * We could go ahead and recompute the clips of toplevel windows and
501    * their descendents when we receive size notification, but it would
502    * probably not be an improvement in most cases.
503    */
504   parent_pos->clip_rect.x = 0;
505   parent_pos->clip_rect.y = 0;
506   parent_pos->clip_rect.width = G_MAXINT;
507   parent_pos->clip_rect.height = G_MAXINT;
508
509   private = (GdkWindowPrivate *)private->parent;
510   while (private && private->drawable.window_type == GDK_WINDOW_CHILD)
511     {
512       data = (GdkWindowXData *)private->drawable.klass_data;
513
514       tmp_clip.x = - clip_xoffset;
515       tmp_clip.y = - clip_yoffset;
516       tmp_clip.width = private->drawable.width;
517       tmp_clip.height = private->drawable.height;
518
519       gdk_rectangle_intersect (&parent_pos->clip_rect, &tmp_clip, &parent_pos->clip_rect);
520
521       parent_pos->x += private->x;
522       parent_pos->y += private->y;
523       parent_pos->x11_x += data->position_info.x;
524       parent_pos->x11_y += data->position_info.y;
525
526       clip_xoffset += private->x;
527       clip_yoffset += private->y;
528
529       private = (GdkWindowPrivate *)private->parent;
530     }
531 }
532
533 static void
534 gdk_window_premove (GdkWindow          *window,
535                     GdkWindowParentPos *parent_pos)
536 {
537   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
538   GdkWindowXData *data = GDK_WINDOW_XDATA (window);
539   GdkXPositionInfo new_info;
540   GList *tmp_list;
541   gint d_xoffset, d_yoffset;
542   GdkWindowParentPos this_pos;
543   
544   gdk_window_compute_position (window, parent_pos, &new_info);
545
546   gdk_window_clip_changed (window, &data->position_info.clip_rect, &new_info.clip_rect);
547
548   this_pos.x = parent_pos->x + private->x;
549   this_pos.y = parent_pos->y + private->y;
550   this_pos.x11_x = parent_pos->x11_x + new_info.x;
551   this_pos.x11_y = parent_pos->x11_y + new_info.y;
552   this_pos.clip_rect = new_info.clip_rect;
553
554   if (data->position_info.mapped && !new_info.mapped)
555     XUnmapWindow (GDK_DRAWABLE_XDISPLAY (window), GDK_DRAWABLE_XID (window));
556
557   d_xoffset = new_info.x_offset - data->position_info.x_offset;
558   d_yoffset = new_info.y_offset - data->position_info.y_offset;
559   
560   if (d_xoffset != 0 || d_yoffset != 0)
561     {
562       gint new_x0, new_y0, new_x1, new_y1;
563
564       if (d_xoffset < 0 || d_yoffset < 0)
565         gdk_window_queue_translation (window, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
566         
567       if (d_xoffset < 0)
568         {
569           new_x0 = data->position_info.x + d_xoffset;
570           new_x1 = data->position_info.x + data->position_info.width;
571         }
572       else
573         {
574           new_x0 = data->position_info.x;
575           new_x1 = data->position_info.x + new_info.width + d_xoffset;
576         }
577
578       if (d_yoffset < 0)
579         {
580           new_y0 = data->position_info.y + d_yoffset;
581           new_y1 = data->position_info.y + data->position_info.height;
582         }
583       else
584         {
585           new_y0 = data->position_info.y;
586           new_y1 = data->position_info.y + new_info.height + d_yoffset;
587         }
588
589       XMoveResizeWindow (GDK_DRAWABLE_XDISPLAY (window),
590                          GDK_DRAWABLE_XID (window),
591                          new_x0, new_y0, new_x1 - new_x0, new_y1 - new_y0);
592     }
593
594   tmp_list = private->children;
595   while (tmp_list)
596     {
597       gdk_window_premove (tmp_list->data, &this_pos);
598       tmp_list = tmp_list->next;
599     }
600 }
601
602 static void
603 gdk_window_postmove (GdkWindow          *window,
604                      GdkWindowParentPos *parent_pos)
605 {
606   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
607   GdkWindowXData *data = (GdkWindowXData *)private->drawable.klass_data;
608   GdkXPositionInfo new_info;
609   GList *tmp_list;
610   gint d_xoffset, d_yoffset;
611   GdkWindowParentPos this_pos;
612   
613   gdk_window_compute_position (window, parent_pos, &new_info);
614
615   this_pos.x = parent_pos->x + private->x;
616   this_pos.y = parent_pos->y + private->y;
617   this_pos.x11_x = parent_pos->x11_x + new_info.x;
618   this_pos.x11_y = parent_pos->x11_y + new_info.y;
619   this_pos.clip_rect = new_info.clip_rect;
620
621   d_xoffset = new_info.x_offset - data->position_info.x_offset;
622   d_yoffset = new_info.y_offset - data->position_info.y_offset;
623   
624   if (d_xoffset != 0 || d_yoffset != 0)
625     {
626       if (d_xoffset > 0 || d_yoffset > 0)
627         gdk_window_queue_translation (window, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
628         
629       XMoveResizeWindow (GDK_DRAWABLE_XDISPLAY (window),
630                          GDK_DRAWABLE_XID (window),
631                          new_info.x, new_info.y, new_info.width, new_info.height);
632     }
633
634   if (!data->position_info.mapped && new_info.mapped && private->mapped)
635     XMapWindow (GDK_DRAWABLE_XDISPLAY (window), GDK_DRAWABLE_XID (window));
636
637   if (data->position_info.no_bg)
638     gdk_window_tmp_reset_bg (window);
639
640   data->position_info = new_info;
641
642   tmp_list = private->children;
643   while (tmp_list)
644     {
645       gdk_window_postmove (tmp_list->data, &this_pos);
646       tmp_list = tmp_list->next;
647     }
648 }
649
650 static void
651 gdk_window_queue_translation (GdkWindow *window,
652                               gint       dx,
653                               gint       dy)
654 {
655   GdkWindowQueueItem *item = g_new (GdkWindowQueueItem, 1);
656   item->window = window;
657   item->serial = NextRequest (GDK_WINDOW_XDISPLAY (window));
658   item->type = GDK_WINDOW_QUEUE_TRANSLATE;
659   item->u.translate.dx = dx;
660   item->u.translate.dy = dy;
661
662   gdk_drawable_ref (window);
663   translate_queue = g_slist_append (translate_queue, item);
664 }
665
666 gboolean
667 _gdk_windowing_window_queue_antiexpose (GdkWindow *window,
668                                         GdkRegion *area)
669 {
670   GdkWindowQueueItem *item = g_new (GdkWindowQueueItem, 1);
671   item->window = window;
672   item->serial = NextRequest (GDK_WINDOW_XDISPLAY (window));
673   item->type = GDK_WINDOW_QUEUE_ANTIEXPOSE;
674   item->u.antiexpose.area = area;
675
676   gdk_drawable_ref (window);
677   translate_queue = g_slist_append (translate_queue, item);
678
679   return TRUE;
680 }
681
682 void
683 _gdk_window_process_expose (GdkWindow    *window,
684                             gulong        serial,
685                             GdkRectangle *area)
686 {
687   GdkWindowXData *data = GDK_WINDOW_XDATA (window);
688   GdkRegion *invalidate_region = gdk_region_rectangle (area);
689   GdkRegion *clip_region;
690
691   GSList *tmp_list = translate_queue;
692
693   while (tmp_list)
694     {
695       GdkWindowQueueItem *item = tmp_list->data;
696       tmp_list = tmp_list->next;
697
698       if (serial < item->serial)
699         {
700           if (item->window == window)
701             {
702               if (item->type == GDK_WINDOW_QUEUE_TRANSLATE)
703                 gdk_region_offset (invalidate_region, - item->u.translate.dx, - item->u.translate.dy);
704               else              /* anti-expose */
705                 gdk_region_subtract (invalidate_region, item->u.antiexpose.area);
706             }
707         }
708       else
709         {
710           GSList *tmp_link = translate_queue;
711           
712           translate_queue = g_slist_remove_link (translate_queue, translate_queue);
713           gdk_drawable_unref (item->window);
714
715           if (item->type == GDK_WINDOW_QUEUE_ANTIEXPOSE)
716             gdk_region_destroy (item->u.antiexpose.area);
717           
718           g_free (item);
719           g_slist_free_1 (tmp_link);
720         }
721     }
722
723   clip_region = gdk_region_rectangle (&data->position_info.clip_rect);
724   gdk_region_intersect (invalidate_region, clip_region);
725
726   if (!gdk_region_empty (invalidate_region))
727     gdk_window_invalidate_region (window, invalidate_region, FALSE);
728
729   gdk_region_destroy (invalidate_region);
730   gdk_region_destroy (clip_region);
731 }
732
733 static void
734 gdk_window_tmp_unset_bg (GdkWindow *window)
735 {
736   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
737   GdkWindowXData *data = GDK_WINDOW_XDATA (window);
738
739   data->position_info.no_bg = TRUE;
740
741   if (private->bg_pixmap != GDK_NO_BG)
742     XSetWindowBackgroundPixmap (GDK_DRAWABLE_XDISPLAY (window),
743                                 GDK_DRAWABLE_XID (window), None);
744 }
745
746 static void
747 gdk_window_tmp_reset_bg (GdkWindow *window)
748 {
749   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
750   GdkWindowXData *data = GDK_WINDOW_XDATA (window);
751
752   data->position_info.no_bg = FALSE;
753
754   if (private->bg_pixmap == GDK_NO_BG)
755     return;
756   
757   if (private->bg_pixmap)
758     {
759       Pixmap xpixmap;
760
761       if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG)
762         xpixmap = ParentRelative;
763       else 
764         xpixmap = GDK_DRAWABLE_XID (private->bg_pixmap);
765
766       XSetWindowBackgroundPixmap (GDK_DRAWABLE_XDISPLAY (window),
767                                   GDK_DRAWABLE_XID (window), xpixmap);
768     }
769   else
770     {
771       XSetWindowBackground (GDK_DRAWABLE_XDISPLAY (window),
772                             GDK_DRAWABLE_XID (window),
773                             private->bg_color.pixel);
774     }
775 }
776
777 static void
778 gdk_window_clip_changed (GdkWindow *window, GdkRectangle *old_clip, GdkRectangle *new_clip)
779 {
780   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
781
782   GdkRegion *old_clip_region;
783   GdkRegion *new_clip_region;
784
785   if (private->input_only)
786     return;
787     
788   old_clip_region = gdk_region_rectangle (old_clip);
789   new_clip_region = gdk_region_rectangle (new_clip);
790
791   /* Trim invalid region of window to new clip rectangle
792    */
793   if (private->update_area)
794     gdk_region_intersect (private->update_area, new_clip_region);
795
796   /* Invalidate newly exposed portion of window
797    */
798   gdk_region_subtract (new_clip_region, old_clip_region);
799   if (!gdk_region_empty (new_clip_region))
800     {
801       gdk_window_tmp_unset_bg (window);
802       gdk_window_invalidate_region (window, new_clip_region, FALSE);
803     }
804
805   gdk_region_destroy (new_clip_region);
806   gdk_region_destroy (old_clip_region);
807 }
808