]> Pileus Git - ~andy/gtk/blob - gdk/x11/gdkgeometry-x11.c
40855e8abbf89bd489de38a0628928c8ab770a00
[~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 void
114 _gdk_window_move_resize_child (GdkWindow *window,
115                                gint       x,
116                                gint       y,
117                                gint       width,
118                                gint       height)
119 {
120   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
121   GdkXPositionInfo new_info;
122   GdkWindowParentPos parent_pos;
123   GdkWindowXData *data;
124   GList *tmp_list;
125   
126   gint d_xoffset, d_yoffset;
127   gint dx, dy;
128   gboolean is_move;
129   gboolean is_resize;
130   
131   g_return_if_fail (window != NULL);
132   g_return_if_fail (GDK_IS_WINDOW (window));
133
134   data = (GdkWindowXData *)private->drawable.klass_data;
135
136   dx = x - private->x;
137   dy = y - private->y;
138   
139   is_move = dx != 0 || dy != 0;
140   is_resize = private->drawable.width != width || private->drawable.height != height;
141
142   if (!is_move && !is_resize)
143     return;
144   
145   private->x = x;
146   private->y = y;
147   private->drawable.width = width;
148   private->drawable.height = height;
149
150   gdk_window_compute_parent_pos (window, &parent_pos);
151   gdk_window_compute_position (window, &parent_pos, &new_info);
152
153   gdk_window_clip_changed (window, &data->position_info.clip_rect, &new_info.clip_rect);
154
155   parent_pos.x += private->x;
156   parent_pos.y += private->y;
157   parent_pos.x11_x += new_info.x;
158   parent_pos.x11_y += new_info.y;
159   parent_pos.clip_rect = new_info.clip_rect;
160
161   d_xoffset = new_info.x_offset - data->position_info.x_offset;
162   d_yoffset = new_info.y_offset - data->position_info.y_offset;
163   
164   if (d_xoffset != 0 || d_yoffset != 0)
165     {
166       gint new_x0, new_y0, new_x1, new_y1;
167
168       gdk_window_set_static_gravities (window, TRUE);
169
170       if (d_xoffset < 0 || d_yoffset < 0)
171         gdk_window_queue_translation (window, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
172         
173       if (d_xoffset < 0)
174         {
175           new_x0 = data->position_info.x + d_xoffset;
176           new_x1 = data->position_info.x + data->position_info.width;
177         }
178       else
179         {
180           new_x0 = data->position_info.x;
181           new_x1 = data->position_info.x + new_info.width + d_xoffset;
182         }
183
184       if (d_yoffset < 0)
185         {
186           new_y0 = data->position_info.y + d_yoffset;
187           new_y1 = data->position_info.y + data->position_info.height;
188         }
189       else
190         {
191           new_y0 = data->position_info.y;
192           new_y1 = data->position_info.y + new_info.height + d_yoffset;
193         }
194       
195       XMoveResizeWindow (GDK_DRAWABLE_XDISPLAY (window),
196                          GDK_DRAWABLE_XID (window),
197                          new_x0, new_y0, new_x1 - new_x0, new_y1 - new_y0);
198       
199       tmp_list = private->children;
200       while (tmp_list)
201         {
202           gdk_window_premove (tmp_list->data, &parent_pos);
203           tmp_list = tmp_list->next;
204         }
205
206       XMoveWindow (GDK_DRAWABLE_XDISPLAY (window),
207                    GDK_DRAWABLE_XID (window),
208                    new_x0 + dx, new_y0 + dy);
209       
210       if (d_xoffset > 0 || d_yoffset > 0)
211         gdk_window_queue_translation (window, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
212       
213       XMoveResizeWindow (GDK_DRAWABLE_XDISPLAY (window),
214                          GDK_DRAWABLE_XID (window),
215                          new_info.x, new_info.y, new_info.width, new_info.height);
216       
217       if (data->position_info.no_bg)
218         gdk_window_tmp_reset_bg (window);
219
220       if (!data->position_info.mapped && new_info.mapped && private->mapped)
221         XMapWindow (GDK_DRAWABLE_XDISPLAY (window), GDK_DRAWABLE_XID (window));
222       
223       data->position_info = new_info;
224       
225       tmp_list = private->children;
226       while (tmp_list)
227         {
228           gdk_window_postmove (tmp_list->data, &parent_pos);
229           tmp_list = tmp_list->next;
230         }
231     }
232   else
233     {
234       if (is_move && is_resize)
235         gdk_window_set_static_gravities (window, FALSE);
236
237       if (data->position_info.mapped && !new_info.mapped)
238         XUnmapWindow (GDK_DRAWABLE_XDISPLAY (window), GDK_DRAWABLE_XID (window));
239       
240       tmp_list = private->children;
241       while (tmp_list)
242         {
243           gdk_window_premove (tmp_list->data, &parent_pos);
244           tmp_list = tmp_list->next;
245         }
246
247       if (is_resize)
248         XMoveResizeWindow (GDK_DRAWABLE_XDISPLAY (window),
249                            GDK_DRAWABLE_XID (window),
250                            new_info.x, new_info.y, new_info.width, new_info.height);
251       else
252         XMoveWindow (GDK_DRAWABLE_XDISPLAY (window),
253                      GDK_DRAWABLE_XID (window),
254                      new_info.x, new_info.y);
255
256       tmp_list = private->children;
257       while (tmp_list)
258         {
259           gdk_window_postmove (tmp_list->data, &parent_pos);
260           tmp_list = tmp_list->next;
261         }
262
263       if (data->position_info.no_bg)
264         gdk_window_tmp_reset_bg (window);
265
266       if (!data->position_info.mapped && new_info.mapped && private->mapped)
267         XMapWindow (GDK_DRAWABLE_XDISPLAY (window), GDK_DRAWABLE_XID (window));
268
269       data->position_info = new_info;
270     }
271 }
272
273 static void
274 gdk_window_compute_position (GdkWindow          *window,
275                              GdkWindowParentPos *parent_pos,
276                              GdkXPositionInfo   *info)
277 {
278   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
279   int parent_x_offset;
280   int parent_y_offset;
281   
282   info->big = FALSE;
283   
284   if (private->drawable.width <= 32768)
285     {
286       info->width = private->drawable.width;
287       info->x = parent_pos->x + private->x - parent_pos->x11_x;
288     }
289   else
290     {
291       info->big = TRUE;
292       info->width = 32768;
293       if (parent_pos->x + private->x < -16384)
294         {
295           if (parent_pos->x + private->x + private->drawable.width < 16384)
296             info->x = parent_pos->x + private->x + private->drawable.width - 32768 - parent_pos->x11_x;
297           else
298             info->x = -16384 - parent_pos->x11_y;
299         }
300       else
301         info->x = parent_pos->x + private->x - parent_pos->x11_x;
302     }
303
304   if (private->drawable.height <= 32768)
305     {
306       info->height = private->drawable.height;
307       info->y = parent_pos->y + private->y - parent_pos->x11_y;
308     }
309   else
310     {
311       info->big = TRUE;
312       info->height = 32768;
313       if (parent_pos->y + private->y < -16384)
314         {
315           if (parent_pos->y + private->y + private->drawable.height < 16384)
316             info->y = parent_pos->y + private->y + private->drawable.height - 32768 - parent_pos->x11_y;
317           else
318             info->y = -16384 - parent_pos->x11_y;
319         }
320       else
321         info->y = parent_pos->y + private->y - parent_pos->x11_y;
322     }
323
324   parent_x_offset = parent_pos->x11_x - parent_pos->x;
325   parent_y_offset = parent_pos->x11_y - parent_pos->y;
326   
327   info->x_offset = parent_x_offset + info->x - private->x;
328   info->y_offset = parent_y_offset + info->y - private->y;
329
330   /* We don't considering the clipping of toplevel windows and their immediate children
331    * by their parents, and simply always map those windows.
332    */
333   if (parent_pos->clip_rect.width == G_MAXINT)
334     info->mapped = TRUE;
335   /* Check if the window would wrap around into the visible space in either direction */
336   else if (info->x + parent_x_offset < parent_pos->clip_rect.x + parent_pos->clip_rect.width - 65536 ||
337       info->x + info->width + parent_x_offset > parent_pos->clip_rect.x + 65536 ||
338       info->y + parent_y_offset < parent_pos->clip_rect.y + parent_pos->clip_rect.height - 65536 ||
339       info->y + info->width + parent_y_offset  > parent_pos->clip_rect.y + 65536)
340     info->mapped = FALSE;
341   else
342     info->mapped = TRUE;
343
344   info->no_bg = FALSE;
345
346   if (GDK_DRAWABLE_TYPE (private) == GDK_WINDOW_CHILD)
347     {
348       info->clip_rect.x = private->x;
349       info->clip_rect.y = private->y;
350       info->clip_rect.width = private->drawable.width;
351       info->clip_rect.height = private->drawable.height;
352       
353       gdk_rectangle_intersect (&info->clip_rect, &parent_pos->clip_rect, &info->clip_rect);
354
355       info->clip_rect.x -= private->x;
356       info->clip_rect.y -= private->y;
357     }
358   else
359     {
360       info->clip_rect.x = 0;
361       info->clip_rect.y = 0;
362       info->clip_rect.width = G_MAXINT;
363       info->clip_rect.height = G_MAXINT;
364     }
365 }
366
367 static void
368 gdk_window_compute_parent_pos (GdkWindow          *window,
369                                GdkWindowParentPos *parent_pos)
370 {
371   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
372   GdkWindowXData *data;
373   GdkRectangle tmp_clip;
374   
375   int clip_xoffset = 0;
376   int clip_yoffset = 0;
377
378   parent_pos->x = 0;
379   parent_pos->y = 0;
380   parent_pos->x11_x = 0;
381   parent_pos->x11_y = 0;
382
383   /* We take a simple approach here and simply consider toplevel
384    * windows not to clip their children on the right/bottom, since the
385    * size of toplevel windows is not directly under our
386    * control. Clipping only really matters when scrolling and
387    * generally we aren't going to be moving the immediate child of a
388    * toplevel beyond the bounds of that toplevel.
389    *
390    * We could go ahead and recompute the clips of toplevel windows and
391    * their descendents when we receive size notification, but it would
392    * probably not be an improvement in most cases.
393    */
394   parent_pos->clip_rect.x = 0;
395   parent_pos->clip_rect.y = 0;
396   parent_pos->clip_rect.width = G_MAXINT;
397   parent_pos->clip_rect.height = G_MAXINT;
398
399   private = (GdkWindowPrivate *)private->parent;
400   while (private && private->drawable.window_type == GDK_WINDOW_CHILD)
401     {
402       data = (GdkWindowXData *)private->drawable.klass_data;
403
404       tmp_clip.x = - clip_xoffset;
405       tmp_clip.y = - clip_yoffset;
406       tmp_clip.width = private->drawable.width;
407       tmp_clip.height = private->drawable.height;
408
409       gdk_rectangle_intersect (&parent_pos->clip_rect, &tmp_clip, &parent_pos->clip_rect);
410
411       parent_pos->x += private->x;
412       parent_pos->y += private->y;
413       parent_pos->x11_x += data->position_info.x;
414       parent_pos->x11_y += data->position_info.y;
415
416       clip_xoffset += private->x;
417       clip_yoffset += private->y;
418
419       private = (GdkWindowPrivate *)private->parent;
420     }
421 }
422
423 static void
424 gdk_window_premove (GdkWindow          *window,
425                     GdkWindowParentPos *parent_pos)
426 {
427   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
428   GdkWindowXData *data = GDK_WINDOW_XDATA (window);
429   GdkXPositionInfo new_info;
430   GList *tmp_list;
431   gint d_xoffset, d_yoffset;
432   GdkWindowParentPos this_pos;
433   
434   gdk_window_compute_position (window, parent_pos, &new_info);
435
436   gdk_window_clip_changed (window, &data->position_info.clip_rect, &new_info.clip_rect);
437
438   this_pos.x = parent_pos->x + private->x;
439   this_pos.y = parent_pos->y + private->y;
440   this_pos.x11_x = parent_pos->x11_x + new_info.x;
441   this_pos.x11_y = parent_pos->x11_y + new_info.y;
442   this_pos.clip_rect = new_info.clip_rect;
443
444   if (data->position_info.mapped && !new_info.mapped)
445     XUnmapWindow (GDK_DRAWABLE_XDISPLAY (window), GDK_DRAWABLE_XID (window));
446
447   d_xoffset = new_info.x_offset - data->position_info.x_offset;
448   d_yoffset = new_info.y_offset - data->position_info.y_offset;
449   
450   if (d_xoffset != 0 || d_yoffset != 0)
451     {
452       gint new_x0, new_y0, new_x1, new_y1;
453
454       if (d_xoffset < 0 || d_yoffset < 0)
455         gdk_window_queue_translation (window, MIN (d_xoffset, 0), MIN (d_yoffset, 0));
456         
457       if (d_xoffset < 0)
458         {
459           new_x0 = data->position_info.x + d_xoffset;
460           new_x1 = data->position_info.x + data->position_info.width;
461         }
462       else
463         {
464           new_x0 = data->position_info.x;
465           new_x1 = data->position_info.x + new_info.width + d_xoffset;
466         }
467
468       if (d_yoffset < 0)
469         {
470           new_y0 = data->position_info.y + d_yoffset;
471           new_y1 = data->position_info.y + data->position_info.height;
472         }
473       else
474         {
475           new_y0 = data->position_info.y;
476           new_y1 = data->position_info.y + new_info.height + d_yoffset;
477         }
478
479       XMoveResizeWindow (GDK_DRAWABLE_XDISPLAY (window),
480                          GDK_DRAWABLE_XID (window),
481                          new_x0, new_y0, new_x1 - new_x0, new_y1 - new_y0);
482     }
483
484   tmp_list = private->children;
485   while (tmp_list)
486     {
487       gdk_window_premove (tmp_list->data, &this_pos);
488       tmp_list = tmp_list->next;
489     }
490 }
491
492 static void
493 gdk_window_postmove (GdkWindow          *window,
494                      GdkWindowParentPos *parent_pos)
495 {
496   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
497   GdkWindowXData *data = (GdkWindowXData *)private->drawable.klass_data;
498   GdkXPositionInfo new_info;
499   GList *tmp_list;
500   gint d_xoffset, d_yoffset;
501   GdkWindowParentPos this_pos;
502   
503   gdk_window_compute_position (window, parent_pos, &new_info);
504
505   this_pos.x = parent_pos->x + private->x;
506   this_pos.y = parent_pos->y + private->y;
507   this_pos.x11_x = parent_pos->x11_x + new_info.x;
508   this_pos.x11_y = parent_pos->x11_y + new_info.y;
509   this_pos.clip_rect = new_info.clip_rect;
510
511   d_xoffset = new_info.x_offset - data->position_info.x_offset;
512   d_yoffset = new_info.y_offset - data->position_info.y_offset;
513   
514   if (d_xoffset != 0 || d_yoffset != 0)
515     {
516       if (d_xoffset > 0 || d_yoffset > 0)
517         gdk_window_queue_translation (window, MAX (d_xoffset, 0), MAX (d_yoffset, 0));
518         
519       XMoveResizeWindow (GDK_DRAWABLE_XDISPLAY (window),
520                          GDK_DRAWABLE_XID (window),
521                          new_info.x, new_info.y, new_info.width, new_info.height);
522     }
523
524   if (!data->position_info.mapped && new_info.mapped && private->mapped)
525     XMapWindow (GDK_DRAWABLE_XDISPLAY (window), GDK_DRAWABLE_XID (window));
526
527   if (data->position_info.no_bg)
528     gdk_window_tmp_reset_bg (window);
529
530   data->position_info = new_info;
531
532   tmp_list = private->children;
533   while (tmp_list)
534     {
535       gdk_window_postmove (tmp_list->data, &this_pos);
536       tmp_list = tmp_list->next;
537     }
538 }
539
540 static void
541 gdk_window_queue_translation (GdkWindow *window,
542                               gint       dx,
543                               gint       dy)
544 {
545   GdkWindowQueueItem *item = g_new (GdkWindowQueueItem, 1);
546   item->window = window;
547   item->serial = NextRequest (GDK_WINDOW_XDISPLAY (window));
548   item->type = GDK_WINDOW_QUEUE_TRANSLATE;
549   item->u.translate.dx = dx;
550   item->u.translate.dy = dy;
551
552   gdk_drawable_ref (window);
553   translate_queue = g_slist_append (translate_queue, item);
554 }
555
556 gboolean
557 _gdk_windowing_window_queue_antiexpose (GdkWindow *window,
558                                         GdkRegion *area)
559 {
560   GdkWindowQueueItem *item = g_new (GdkWindowQueueItem, 1);
561   item->window = window;
562   item->serial = NextRequest (GDK_WINDOW_XDISPLAY (window));
563   item->type = GDK_WINDOW_QUEUE_ANTIEXPOSE;
564   item->u.antiexpose.area = area;
565
566   gdk_drawable_ref (window);
567   translate_queue = g_slist_append (translate_queue, item);
568
569   return TRUE;
570 }
571
572 void
573 _gdk_window_process_expose (GdkWindow    *window,
574                             gulong        serial,
575                             GdkRectangle *area)
576 {
577   GdkWindowXData *data = GDK_WINDOW_XDATA (window);
578   GdkRegion *invalidate_region = gdk_region_rectangle (area);
579   GdkRegion *clip_region;
580
581   GSList *tmp_list = translate_queue;
582
583   while (tmp_list)
584     {
585       GdkWindowQueueItem *item = tmp_list->data;
586       tmp_list = tmp_list->next;
587
588       if (serial < item->serial)
589         {
590           if (item->window == window)
591             {
592               if (item->type == GDK_WINDOW_QUEUE_TRANSLATE)
593                 gdk_region_offset (invalidate_region, - item->u.translate.dx, - item->u.translate.dy);
594               else              /* anti-expose */
595                 gdk_region_subtract (invalidate_region, item->u.antiexpose.area);
596             }
597         }
598       else
599         {
600           GSList *tmp_link = translate_queue;
601           
602           translate_queue = g_slist_remove_link (translate_queue, translate_queue);
603           gdk_drawable_unref (item->window);
604
605           if (item->type == GDK_WINDOW_QUEUE_ANTIEXPOSE)
606             gdk_region_destroy (item->u.antiexpose.area);
607           
608           g_free (item);
609           g_slist_free_1 (tmp_link);
610         }
611     }
612
613   clip_region = gdk_region_rectangle (&data->position_info.clip_rect);
614   gdk_region_intersect (invalidate_region, clip_region);
615
616   if (!gdk_region_empty (invalidate_region))
617     gdk_window_invalidate_region (window, invalidate_region, FALSE);
618
619   gdk_region_destroy (invalidate_region);
620   gdk_region_destroy (clip_region);
621 }
622
623 static void
624 gdk_window_tmp_unset_bg (GdkWindow *window)
625 {
626   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
627   GdkWindowXData *data = GDK_WINDOW_XDATA (window);
628
629   data->position_info.no_bg = TRUE;
630
631   if (private->bg_pixmap != GDK_NO_BG)
632     XSetWindowBackgroundPixmap (GDK_DRAWABLE_XDISPLAY (window),
633                                 GDK_DRAWABLE_XID (window), None);
634 }
635
636 static void
637 gdk_window_tmp_reset_bg (GdkWindow *window)
638 {
639   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
640   GdkWindowXData *data = GDK_WINDOW_XDATA (window);
641
642   data->position_info.no_bg = FALSE;
643
644   if (private->bg_pixmap == GDK_NO_BG)
645     return;
646   
647   if (private->bg_pixmap)
648     {
649       Pixmap xpixmap;
650
651       if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG)
652         xpixmap = ParentRelative;
653       else 
654         xpixmap = GDK_DRAWABLE_XID (private->bg_pixmap);
655
656       XSetWindowBackgroundPixmap (GDK_DRAWABLE_XDISPLAY (window),
657                                   GDK_DRAWABLE_XID (window), xpixmap);
658     }
659   else
660     {
661       XSetWindowBackground (GDK_DRAWABLE_XDISPLAY (window),
662                             GDK_DRAWABLE_XID (window),
663                             private->bg_color.pixel);
664     }
665 }
666
667 static void
668 gdk_window_clip_changed (GdkWindow *window, GdkRectangle *old_clip, GdkRectangle *new_clip)
669 {
670   GdkWindowPrivate *private = (GdkWindowPrivate *)window;
671
672   GdkRegion *old_clip_region;
673   GdkRegion *new_clip_region;
674
675   if (private->input_only)
676     return;
677     
678   old_clip_region = gdk_region_rectangle (old_clip);
679   new_clip_region = gdk_region_rectangle (new_clip);
680
681   /* Trim invalid region of window to new clip rectangle
682    */
683   if (private->update_area)
684     gdk_region_intersect (private->update_area, new_clip_region);
685
686   /* Invalidate newly exposed portion of window
687    */
688   gdk_region_subtract (new_clip_region, old_clip_region);
689   if (!gdk_region_empty (new_clip_region))
690     {
691       gdk_window_tmp_unset_bg (window);
692       gdk_window_invalidate_region (window, new_clip_region, FALSE);
693     }
694
695   gdk_region_destroy (new_clip_region);
696   gdk_region_destroy (old_clip_region);
697 }
698