]> Pileus Git - ~andy/gtk/blob - gdk/gdkwindow.c
Implement gdkcc (visually broken, but can be fixed by someone with a clue
[~andy/gtk] / gdk / gdkwindow.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 /*
21  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25  */
26
27 #include "gdkwindow.h"
28 #include "gdkinternals.h"
29 #include "gdk.h"                /* For gdk_rectangle_union() */
30 #include "gdkpixmap.h"
31
32 #ifndef USE_BACKING_STORE
33 #ifndef GDK_WINDOWING_WIN32
34 #define USE_BACKING_STORE       /* Doesn't work yet on Win32 */
35 #endif
36 #endif
37
38 typedef struct _GdkWindowPaint GdkWindowPaint;
39
40 struct _GdkWindowPaint
41 {
42   GdkRegion *region;
43   GdkPixmap *pixmap;
44   gint x_offset;
45   gint y_offset;
46 };
47 static GdkGC *gdk_window_create_gc      (GdkDrawable     *drawable,
48                                          GdkGCValues     *values,
49                                          GdkGCValuesMask  mask);
50 static void   gdk_window_draw_rectangle (GdkDrawable     *drawable,
51                                          GdkGC           *gc,
52                                          gint             filled,
53                                          gint             x,
54                                          gint             y,
55                                          gint             width,
56                                          gint             height);
57 static void   gdk_window_draw_arc       (GdkDrawable     *drawable,
58                                          GdkGC           *gc,
59                                          gint             filled,
60                                          gint             x,
61                                          gint             y,
62                                          gint             width,
63                                          gint             height,
64                                          gint             angle1,
65                                          gint             angle2);
66 static void   gdk_window_draw_polygon   (GdkDrawable     *drawable,
67                                          GdkGC           *gc,
68                                          gint             filled,
69                                          GdkPoint        *points,
70                                          gint             npoints);
71 static void   gdk_window_draw_text      (GdkDrawable     *drawable,
72                                          GdkFont         *font,
73                                          GdkGC           *gc,
74                                          gint             x,
75                                          gint             y,
76                                          const gchar     *text,
77                                          gint             text_length);
78 static void   gdk_window_draw_text_wc   (GdkDrawable     *drawable,
79                                          GdkFont         *font,
80                                          GdkGC           *gc,
81                                          gint             x,
82                                          gint             y,
83                                          const GdkWChar  *text,
84                                          gint             text_length);
85 static void   gdk_window_draw_drawable  (GdkDrawable     *drawable,
86                                          GdkGC           *gc,
87                                          GdkPixmap       *src,
88                                          gint             xsrc,
89                                          gint             ysrc,
90                                          gint             xdest,
91                                          gint             ydest,
92                                          gint             width,
93                                          gint             height);
94 static void   gdk_window_draw_points    (GdkDrawable     *drawable,
95                                          GdkGC           *gc,
96                                          GdkPoint        *points,
97                                          gint             npoints);
98 static void   gdk_window_draw_segments  (GdkDrawable     *drawable,
99                                          GdkGC           *gc,
100                                          GdkSegment      *segs,
101                                          gint             nsegs);
102 static void   gdk_window_draw_lines     (GdkDrawable     *drawable,
103                                          GdkGC           *gc,
104                                          GdkPoint        *points,
105                                          gint             npoints);
106 static void   gdk_window_draw_glyphs    (GdkDrawable      *drawable,
107                                          GdkGC            *gc,
108                                          PangoFont        *font,
109                                          gint              x,
110                                          gint              y,
111                                          PangoGlyphString *glyphs);
112
113 static void   gdk_window_draw_image     (GdkDrawable     *drawable,
114                                          GdkGC           *gc,
115                                          GdkImage        *image,
116                                          gint             xsrc,
117                                          gint             ysrc,
118                                          gint             xdest,
119                                          gint             ydest,
120                                          gint             width,
121                                          gint             height);
122
123
124 static void   gdk_window_real_get_size  (GdkDrawable     *drawable,
125                                          gint            *width,
126                                          gint            *height);
127
128 static GdkVisual*   gdk_window_real_get_visual   (GdkDrawable *drawable);
129 static gint         gdk_window_real_get_depth    (GdkDrawable *drawable);
130 static void         gdk_window_real_set_colormap (GdkDrawable *drawable,
131                                              GdkColormap *cmap);
132 static GdkColormap* gdk_window_real_get_colormap (GdkDrawable *drawable);
133      
134 static void gdk_window_free_paint_stack (GdkWindow *window);
135
136 static void gdk_window_init       (GdkWindowObject      *window);
137 static void gdk_window_class_init (GdkWindowObjectClass *klass);
138 static void gdk_window_finalize   (GObject              *object);
139
140 static gpointer parent_class = NULL;
141
142 GType
143 gdk_window_object_get_type (void)
144 {
145   static GType object_type = 0;
146
147   if (!object_type)
148     {
149       static const GTypeInfo object_info =
150       {
151         sizeof (GdkWindowObjectClass),
152         (GBaseInitFunc) NULL,
153         (GBaseFinalizeFunc) NULL,
154         (GClassInitFunc) gdk_window_class_init,
155         NULL,           /* class_finalize */
156         NULL,           /* class_data */
157         sizeof (GdkWindowObject),
158         0,              /* n_preallocs */
159         (GInstanceInitFunc) gdk_window_init,
160       };
161       
162       object_type = g_type_register_static (GDK_TYPE_DRAWABLE,
163                                             "GdkWindow",
164                                             &object_info);
165     }
166   
167   return object_type;
168 }
169
170 static void
171 gdk_window_init (GdkWindowObject *window)
172 {
173   /* 0-initialization is good for all other fields. */
174
175   window->window_type = GDK_WINDOW_CHILD;
176
177   window->impl = g_object_new (_gdk_window_impl_get_type (), NULL);
178 }
179
180 static void
181 gdk_window_class_init (GdkWindowObjectClass *klass)
182 {
183   GObjectClass *object_class = G_OBJECT_CLASS (klass);
184   GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
185   
186   parent_class = g_type_class_peek_parent (klass);
187
188   object_class->finalize = gdk_window_finalize;
189
190   drawable_class->create_gc = gdk_window_create_gc;
191   drawable_class->draw_rectangle = gdk_window_draw_rectangle;
192   drawable_class->draw_arc = gdk_window_draw_arc;
193   drawable_class->draw_polygon = gdk_window_draw_polygon;
194   drawable_class->draw_text = gdk_window_draw_text;
195   drawable_class->draw_text_wc = gdk_window_draw_text_wc;
196   drawable_class->draw_drawable = gdk_window_draw_drawable;
197   drawable_class->draw_points = gdk_window_draw_points;
198   drawable_class->draw_segments = gdk_window_draw_segments;
199   drawable_class->draw_lines = gdk_window_draw_lines;
200   drawable_class->draw_glyphs = gdk_window_draw_glyphs;
201   drawable_class->draw_image = gdk_window_draw_image;
202   drawable_class->get_depth = gdk_window_real_get_depth;
203   drawable_class->get_size = gdk_window_real_get_size;
204   drawable_class->set_colormap = gdk_window_real_set_colormap;
205   drawable_class->get_colormap = gdk_window_real_get_colormap;
206   drawable_class->get_visual = gdk_window_real_get_visual;
207 }
208
209 static void
210 gdk_window_finalize (GObject *object)
211 {
212   GdkWindow *window = GDK_WINDOW (object);
213   GdkWindowObject *obj = (GdkWindowObject *) object;
214   
215   if (!GDK_WINDOW_DESTROYED (window))
216     {
217       if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
218         {
219           g_warning ("losing last reference to undestroyed window\n");
220           _gdk_window_destroy (window, FALSE);
221         }
222       else
223         /* We use TRUE here, to keep us from actually calling
224          * XDestroyWindow() on the window
225          */
226         _gdk_window_destroy (window, TRUE);
227     }
228
229   g_object_unref (G_OBJECT (obj->impl));
230   obj->impl = NULL;
231   
232   G_OBJECT_CLASS (parent_class)->finalize (object);
233 }
234
235 /**
236  * _gdk_window_destroy_hierarchy:
237  * @window: a #GdkWindow
238  * @recursing: If TRUE, then this is being called because a parent
239  *            was destroyed. This generally means that the call to the windowing system
240  *            to destroy the window can be omitted, since it will be destroyed as a result
241  *            of the parent being destroyed. Unless @foreign_destroy
242  *            
243  * foreign_destroy: If TRUE, the window or a parent was destroyed by some external 
244  *            agency. The window has already been destroyed and no windowing
245  *            system calls should be made. (This may never happen for some
246  *            windowing systems.)
247  *
248  * Internal function to destroy a window. Like gdk_window_destroy(), but does not
249  * drop the reference count created by gdk_window_new().
250  **/
251 static void
252 _gdk_window_destroy_hierarchy (GdkWindow *window,
253                                gboolean   recursing,
254                                gboolean   foreign_destroy)
255 {
256   GdkWindowObject *private;
257   GdkWindowObject *temp_private;
258   GdkWindow *temp_window;
259   GList *children;
260   GList *tmp;
261   
262   g_return_if_fail (window != NULL);
263   
264   private = (GdkWindowObject*) window;
265   
266   switch (GDK_WINDOW_TYPE (window))
267     {
268     case GDK_WINDOW_TOPLEVEL:
269     case GDK_WINDOW_CHILD:
270     case GDK_WINDOW_DIALOG:
271     case GDK_WINDOW_TEMP:
272     case GDK_WINDOW_FOREIGN:
273       if (!GDK_WINDOW_DESTROYED (window))
274         {
275           private->mapped = FALSE;
276           private->destroyed = TRUE;
277           
278           _gdk_windowing_window_destroy (window, recursing, foreign_destroy);
279
280           if (private->parent)
281             {
282               GdkWindowObject *parent_private = (GdkWindowObject *)private->parent;
283               if (parent_private->children)
284                 parent_private->children = g_list_remove (parent_private->children, window);
285             }
286
287           _gdk_window_clear_update_area (window);
288           gdk_window_free_paint_stack (window);
289           
290           if (private->bg_pixmap &&
291               private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
292               private->bg_pixmap != GDK_NO_BG)
293             {
294               gdk_pixmap_unref (private->bg_pixmap);
295               private->bg_pixmap = NULL;
296             }
297           
298           if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
299             {
300               children = tmp = private->children;
301               private->children = NULL;
302               
303               while (tmp)
304                 {
305                   temp_window = tmp->data;
306                   tmp = tmp->next;
307                   
308                   temp_private = (GdkWindowObject*) temp_window;
309                   if (temp_private)
310                     _gdk_window_destroy_hierarchy (temp_window, TRUE, foreign_destroy);
311                 }
312               
313               g_list_free (children);
314             }
315           
316           if (private->filters)
317             {
318               tmp = private->filters;
319               
320               while (tmp)
321                 {
322                   g_free (tmp->data);
323                   tmp = tmp->next;
324                 }
325               
326               g_list_free (private->filters);
327               private->filters = NULL;
328             }
329
330           gdk_drawable_set_colormap (GDK_DRAWABLE (window), NULL);
331         }
332       break;
333       
334     case GDK_WINDOW_ROOT:
335       g_error ("attempted to destroy root window");
336       break;
337     }
338 }
339
340 /**
341  * _gdk_window_destroy:
342  * @window: a #GdkWindow
343  * foreign_destroy: If TRUE, the window or a parent was destroyed by some external 
344  *            agency. The window has already been destroyed and no windowing
345  *            system calls should be made. (This may never happen for some
346  *            windowing systems.)
347  *
348  * Internal function to destroy a window. Like gdk_window_destroy(), but does not
349  * drop the reference count created by gdk_window_new().
350  **/
351 void
352 _gdk_window_destroy (GdkWindow *window,
353                      gboolean   foreign_destroy)
354 {
355   _gdk_window_destroy_hierarchy (window, FALSE, foreign_destroy);
356 }
357
358 void
359 gdk_window_destroy (GdkWindow *window)
360 {
361   _gdk_window_destroy_hierarchy (window, FALSE, FALSE);
362   gdk_drawable_unref (window);
363 }
364
365 void
366 gdk_window_set_user_data (GdkWindow *window,
367                           gpointer   user_data)
368 {
369   g_return_if_fail (window != NULL);
370   
371   ((GdkWindowObject*)window)->user_data = user_data;
372 }
373
374 void
375 gdk_window_get_user_data (GdkWindow *window,
376                           gpointer  *data)
377 {
378   g_return_if_fail (window != NULL);
379   
380   *data = ((GdkWindowObject*)window)->user_data;
381 }
382
383 GdkWindowType
384 gdk_window_get_window_type (GdkWindow *window)
385 {
386   g_return_val_if_fail (GDK_IS_WINDOW (window), (GdkWindowType) -1);
387   
388   return GDK_WINDOW_TYPE (window);
389 }
390
391 void
392 gdk_window_get_position (GdkWindow *window,
393                          gint      *x,
394                          gint      *y)
395 {
396   GdkWindowObject *obj;
397   
398   g_return_if_fail (GDK_IS_WINDOW (window));
399   
400   obj = (GdkWindowObject*) window;
401   
402   if (x)
403     *x = obj->x;
404   if (y)
405     *y = obj->y;
406 }
407
408 GdkWindow*
409 gdk_window_get_parent (GdkWindow *window)
410 {
411   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
412   
413   return (GdkWindow*) ((GdkWindowObject*) window)->parent;
414 }
415
416 GdkWindow*
417 gdk_window_get_toplevel (GdkWindow *window)
418 {
419   GdkWindowObject *obj;
420   
421   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
422
423   obj = (GdkWindowObject *)window;
424   while (GDK_WINDOW_TYPE (obj) == GDK_WINDOW_CHILD)
425     obj = (GdkWindowObject *)obj->parent;
426   
427   return GDK_WINDOW (obj);
428 }
429
430 GList*
431 gdk_window_get_children (GdkWindow *window)
432 {
433   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
434
435   if (GDK_WINDOW_DESTROYED (window))
436     return NULL;
437
438   return g_list_copy (GDK_WINDOW_OBJECT (window)->children);
439 }
440
441 GList *
442 gdk_window_peek_children (GdkWindow       *window)
443 {
444   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
445
446   if (GDK_WINDOW_DESTROYED (window))
447     return NULL;
448
449   return GDK_WINDOW_OBJECT (window)->children;
450 }
451
452 void          
453 gdk_window_add_filter (GdkWindow     *window,
454                        GdkFilterFunc  function,
455                        gpointer       data)
456 {
457   GdkWindowObject *private;
458   GList *tmp_list;
459   GdkEventFilter *filter;
460   
461   g_return_if_fail (window != NULL);
462   g_return_if_fail (GDK_IS_WINDOW (window));
463
464   private = (GdkWindowObject*) window;
465   if (private && GDK_WINDOW_DESTROYED (window))
466     return;
467   
468   if (private)
469     tmp_list = private->filters;
470   else
471     tmp_list = gdk_default_filters;
472   
473   while (tmp_list)
474     {
475       filter = (GdkEventFilter *)tmp_list->data;
476       if ((filter->function == function) && (filter->data == data))
477         return;
478       tmp_list = tmp_list->next;
479     }
480   
481   filter = g_new (GdkEventFilter, 1);
482   filter->function = function;
483   filter->data = data;
484   
485   if (private)
486     private->filters = g_list_append (private->filters, filter);
487   else
488     gdk_default_filters = g_list_append (gdk_default_filters, filter);
489 }
490
491 void
492 gdk_window_remove_filter (GdkWindow     *window,
493                           GdkFilterFunc  function,
494                           gpointer       data)
495 {
496   GdkWindowObject *private;
497   GList *tmp_list, *node;
498   GdkEventFilter *filter;
499   
500   g_return_if_fail (window != NULL);
501   g_return_if_fail (GDK_IS_WINDOW (window));
502
503   private = (GdkWindowObject*) window;
504   
505   if (private)
506     tmp_list = private->filters;
507   else
508     tmp_list = gdk_default_filters;
509   
510   while (tmp_list)
511     {
512       filter = (GdkEventFilter *)tmp_list->data;
513       node = tmp_list;
514       tmp_list = tmp_list->next;
515       
516       if ((filter->function == function) && (filter->data == data))
517         {
518           if (private)
519             private->filters = g_list_remove_link (private->filters, node);
520           else
521             gdk_default_filters = g_list_remove_link (gdk_default_filters, node);
522           g_list_free_1 (node);
523           g_free (filter);
524           
525           return;
526         }
527     }
528 }
529
530 GList *
531 gdk_window_get_toplevels (void)
532 {
533   GList *new_list = NULL;
534   GList *tmp_list;
535   
536   tmp_list = ((GdkWindowObject *)gdk_parent_root)->children;
537   while (tmp_list)
538     {
539       new_list = g_list_prepend (new_list, tmp_list->data);
540       tmp_list = tmp_list->next;
541     }
542   
543   return new_list;
544 }
545
546 /*************************************************************
547  * gdk_window_is_visible:
548  *     Check if the given window is mapped.
549  *   arguments:
550  *     window: 
551  *   results:
552  *     is the window mapped
553  *************************************************************/
554
555 gboolean 
556 gdk_window_is_visible (GdkWindow *window)
557 {
558   GdkWindowObject *private = (GdkWindowObject *)window;
559   
560   g_return_val_if_fail (window != NULL, FALSE);
561   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
562   
563   return private->mapped;
564 }
565
566 /*************************************************************
567  * gdk_window_is_viewable:
568  *     Check if the window and all ancestors of the window
569  *     are mapped. (This is not necessarily "viewable" in
570  *     the X sense, since we only check as far as we have
571  *     GDK window parents, not to the root window)
572  *   arguments:
573  *     window:
574  *   results:
575  *     is the window viewable
576  *************************************************************/
577
578 gboolean 
579 gdk_window_is_viewable (GdkWindow *window)
580 {
581   GdkWindowObject *private = (GdkWindowObject *)window;
582   
583   g_return_val_if_fail (window != NULL, FALSE);
584   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
585   
586   while (private && 
587          (private != (GdkWindowObject *)gdk_parent_root) &&
588          (GDK_WINDOW_TYPE (private) != GDK_WINDOW_FOREIGN))
589     {
590       if (!private->mapped)
591         return FALSE;
592       
593       private = (GdkWindowObject *)private->parent;
594     }
595   
596   return TRUE;
597 }
598
599 void
600 gdk_window_begin_paint_rect (GdkWindow    *window,
601                              GdkRectangle *rectangle)
602 {
603   GdkRegion *region;
604
605   g_return_if_fail (window != NULL);
606   g_return_if_fail (GDK_IS_WINDOW (window));
607
608   region = gdk_region_rectangle (rectangle);
609   gdk_window_begin_paint_region (window, region);
610   gdk_region_destroy (region);
611 }
612
613 static GdkGC *
614 gdk_window_get_bg_gc (GdkWindow *window, GdkWindowPaint *paint)
615 {
616   GdkWindowObject *private = (GdkWindowObject *)window;
617
618   guint gc_mask = 0;
619   GdkGCValues gc_values;
620
621   if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
622     {
623       GdkWindowPaint tmp_paint = *paint;
624       tmp_paint.x_offset += private->x;
625       tmp_paint.y_offset += private->y;
626       
627       return gdk_window_get_bg_gc (GDK_WINDOW (private->parent), &tmp_paint);
628     }
629   else if (private->bg_pixmap && private->bg_pixmap != GDK_PARENT_RELATIVE_BG && private->bg_pixmap != GDK_NO_BG)
630     {
631       gc_values.fill = GDK_TILED;
632       gc_values.tile = private->bg_pixmap;
633       gc_values.ts_x_origin = - paint->x_offset;
634       gc_values.ts_y_origin = - paint->y_offset;
635       
636       gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN;
637     }
638   else
639     {
640       gc_values.foreground = private->bg_color;
641       gc_mask = GDK_GC_FOREGROUND;
642     }
643
644   return gdk_gc_new_with_values (paint->pixmap, &gc_values, gc_mask);
645 }
646
647 static void
648 gdk_window_paint_init_bg (GdkWindow      *window,
649                           GdkWindowPaint *paint,
650                           GdkRegion      *init_region)
651 {
652   GdkGC *tmp_gc;
653
654   tmp_gc = gdk_window_get_bg_gc (window, paint);
655   gdk_draw_rectangle (paint->pixmap, tmp_gc, TRUE, 0, 0, -1, -1);
656   gdk_gc_unref (tmp_gc);
657 }
658   
659 void          
660 gdk_window_begin_paint_region (GdkWindow *window,
661                                GdkRegion *region)
662 {
663 #ifdef USE_BACKING_STORE
664   GdkWindowObject *private = (GdkWindowObject *)window;
665   GdkRectangle clip_box;
666   GdkWindowPaint *paint;
667   GdkRegion *init_region;
668   GdkGC *tmp_gc;
669   
670   g_return_if_fail (window != NULL);
671   g_return_if_fail (GDK_IS_WINDOW (window));
672
673   if (GDK_WINDOW_DESTROYED (window))
674     return;
675   
676   paint = g_new (GdkWindowPaint, 1);
677
678   paint->region = gdk_region_copy (region);
679
680   init_region = gdk_region_copy (region);
681   gdk_region_get_clipbox (paint->region, &clip_box);
682
683   if (private->paint_stack)
684     {
685       gint old_width, old_height;
686       GdkWindowPaint *tmp_paint = private->paint_stack->data;
687       GdkRectangle old_rect, new_rect;
688       GSList *tmp_list;
689
690       gdk_drawable_get_size (tmp_paint->pixmap, &old_width, &old_height);
691       old_rect.x = tmp_paint->x_offset;
692       old_rect.y = tmp_paint->y_offset;
693       old_rect.width = old_width;
694       old_rect.height = old_height;
695
696       gdk_rectangle_union (&clip_box, &old_rect, &new_rect);
697
698       if (new_rect.width > old_rect.width || new_rect.height > old_rect.height)
699         {
700           paint->pixmap = gdk_pixmap_new (window, new_rect.width, new_rect.height, -1);
701           tmp_gc = gdk_gc_new (paint->pixmap);
702           gdk_draw_drawable (paint->pixmap, tmp_gc, tmp_paint->pixmap,
703                              0, 0, old_rect.width, old_rect.height,
704                              old_rect.x - new_rect.x, old_rect.y - new_rect.y);
705           gdk_gc_unref (tmp_gc);
706           gdk_drawable_unref (tmp_paint->pixmap);
707
708           paint->x_offset = new_rect.x;
709           paint->y_offset = new_rect.y;
710           
711           tmp_list = private->paint_stack;
712           while (tmp_list)
713             {
714               tmp_paint = private->paint_stack->data;
715               gdk_region_subtract (init_region, tmp_paint->region);
716
717               tmp_paint->pixmap = paint->pixmap;
718               tmp_paint->x_offset = paint->x_offset;
719               tmp_paint->y_offset = paint->x_offset;
720
721               tmp_list = tmp_list->next;
722             }
723         }
724       else
725         {
726           paint->x_offset = tmp_paint->x_offset;
727           paint->y_offset = tmp_paint->y_offset;
728           paint->pixmap = tmp_paint->pixmap;
729
730           tmp_list = private->paint_stack;
731           while (tmp_list)
732             {
733               tmp_paint = private->paint_stack->data;
734               gdk_region_subtract (init_region, tmp_paint->region);
735
736               tmp_list = tmp_list->next;
737             }
738         }
739     }
740   else
741     {
742       paint->x_offset = clip_box.x;
743       paint->y_offset = clip_box.y;
744       paint->pixmap = gdk_pixmap_new (window, clip_box.width, clip_box.height, -1);
745     }
746
747   if (!gdk_region_empty (init_region))
748     gdk_window_paint_init_bg (window, paint, init_region);
749   gdk_region_destroy (init_region);
750   
751   private->paint_stack = g_slist_prepend (private->paint_stack, paint);
752 #endif /* USE_BACKING_STORE */
753 }
754
755 void
756 gdk_window_end_paint (GdkWindow *window)
757 {
758 #ifdef USE_BACKING_STORE
759   GdkWindowObject *private = (GdkWindowObject *)window;
760   GdkWindowPaint *paint;
761   GdkGC *tmp_gc;
762   GdkRectangle clip_box;
763   gint x_offset, y_offset;
764
765   g_return_if_fail (window != NULL);
766   g_return_if_fail (GDK_IS_WINDOW (window));
767
768   if (GDK_WINDOW_DESTROYED (window))
769     return;
770   
771   g_return_if_fail (private->paint_stack != NULL);
772
773   paint = private->paint_stack->data;
774   private->paint_stack = g_slist_delete_link (private->paint_stack, private->paint_stack);
775
776   gdk_region_get_clipbox (paint->region, &clip_box);
777
778   tmp_gc = gdk_gc_new (window);
779
780   _gdk_windowing_window_get_offsets (window, &x_offset, &y_offset);
781
782   gdk_gc_set_clip_region (tmp_gc, paint->region);
783   gdk_gc_set_clip_origin (tmp_gc, -x_offset, -y_offset);
784
785   gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
786                      clip_box.x - paint->x_offset,
787                      clip_box.y - paint->y_offset,
788                      clip_box.x - x_offset, clip_box.y - y_offset,
789                      clip_box.width, clip_box.height);
790   gdk_gc_unref (tmp_gc);
791
792   if (private->paint_stack)
793     {
794       GSList *tmp_list = private->paint_stack;
795       while (tmp_list)
796         {
797           GdkWindowPaint *tmp_paint = tmp_list->data;
798           gdk_region_subtract (tmp_paint->region, paint->region);
799           
800           tmp_list = tmp_list->next;
801         }
802     }
803   else
804     gdk_drawable_unref (paint->pixmap);
805
806   gdk_region_destroy (paint->region);
807   g_free (paint);
808 #endif /* USE_BACKING_STORE */
809 }
810
811 static void
812 gdk_window_free_paint_stack (GdkWindow *window)
813 {
814   GdkWindowObject *private = (GdkWindowObject *)window;
815   
816   if (private->paint_stack)
817     {
818       GSList *tmp_list = private->paint_stack;
819
820       while (tmp_list)
821         {
822           GdkWindowPaint *paint = tmp_list->data;
823
824           if (tmp_list == private->paint_stack)
825             gdk_drawable_unref (paint->pixmap);
826                   
827           gdk_region_destroy (paint->region);
828           g_free (paint);
829
830           tmp_list = tmp_list->next;
831         }
832
833       g_slist_free (private->paint_stack);
834       private->paint_stack = NULL;
835     }
836 }
837
838 static void
839 gdk_window_get_offsets (GdkWindow *window,
840                         gint      *x_offset,
841                         gint      *y_offset)
842 {
843   GdkWindowObject *private = (GdkWindowObject *)window;
844   
845   if (private->paint_stack)
846     {
847       GdkWindowPaint *paint = private->paint_stack->data;
848       *x_offset = paint->x_offset;
849       *y_offset = paint->y_offset;
850     }
851   else
852     _gdk_windowing_window_get_offsets (window, x_offset, y_offset);
853 }
854
855 #define OFFSET_GC(gc)                                         \
856     gint x_offset, y_offset;                                  \
857     gint old_clip_x = gc->clip_x_origin;    \
858     gint old_clip_y = gc->clip_y_origin;    \
859     gint old_ts_x = gc->ts_x_origin;        \
860     gint old_ts_y = gc->ts_y_origin;        \
861     gdk_window_get_offsets (drawable, &x_offset, &y_offset);  \
862     if (x_offset != 0 || y_offset != 0)                       \
863       {                                                       \
864         gdk_gc_set_clip_origin (gc, old_clip_x - x_offset,    \
865                                 old_clip_y - y_offset);       \
866         gdk_gc_set_ts_origin (gc, old_ts_x - x_offset,        \
867                               old_ts_y - y_offset);           \
868       }
869
870 #define RESTORE_GC(gc)                                      \
871     if (x_offset != 0 || y_offset != 0)                     \
872      {                                                      \
873        gdk_gc_set_clip_origin (gc, old_clip_x, old_clip_y); \
874        gdk_gc_set_ts_origin (gc, old_ts_x, old_ts_y);       \
875      }
876
877 static GdkGC *
878 gdk_window_create_gc (GdkDrawable     *drawable,
879                       GdkGCValues     *values,
880                       GdkGCValuesMask  mask)
881 {
882   g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
883   
884   if (GDK_WINDOW_DESTROYED (drawable))
885     return NULL;
886
887   return gdk_gc_new_with_values (((GdkWindowObject *) drawable)->impl,
888                                  values, mask);
889 }
890
891 static void
892 gdk_window_draw_rectangle (GdkDrawable *drawable,
893                            GdkGC       *gc,
894                            gint         filled,
895                            gint         x,
896                            gint         y,
897                            gint         width,
898                            gint         height)
899 {
900   GdkWindowObject *private = (GdkWindowObject *)drawable;
901   OFFSET_GC (gc);
902
903   if (GDK_WINDOW_DESTROYED (drawable))
904     return;
905   
906   if (private->paint_stack)
907     {
908       GdkWindowPaint *paint = private->paint_stack->data;
909       gdk_draw_rectangle (paint->pixmap, gc, filled,
910                           x - x_offset, y - y_offset, width, height);
911     }
912   else
913     gdk_draw_rectangle (private->impl, gc, filled,
914                         x - x_offset, y - y_offset, width, height);
915
916   RESTORE_GC (gc);
917 }
918
919 static void
920 gdk_window_draw_arc (GdkDrawable *drawable,
921                      GdkGC       *gc,
922                      gint         filled,
923                      gint         x,
924                      gint         y,
925                      gint         width,
926                      gint         height,
927                      gint         angle1,
928                      gint         angle2)
929 {
930   GdkWindowObject *private = (GdkWindowObject *)drawable;
931   OFFSET_GC (gc);
932
933   if (GDK_WINDOW_DESTROYED (drawable))
934     return;
935   
936   if (private->paint_stack)
937     {
938       GdkWindowPaint *paint = private->paint_stack->data;
939       gdk_draw_arc (paint->pixmap, gc, filled,
940                     x - x_offset, y_offset,
941                     width, height, angle1, angle2);
942     }
943   else
944     gdk_draw_arc (private->impl, gc, filled,
945                   x - x_offset, y - y_offset,
946                   width, height, angle1, angle2);
947   RESTORE_GC (gc);
948 }
949
950 static void
951 gdk_window_draw_polygon (GdkDrawable *drawable,
952                          GdkGC       *gc,
953                          gint         filled,
954                          GdkPoint    *points,
955                          gint         npoints)
956 {
957   GdkWindowObject *private = (GdkWindowObject *)drawable;
958   GdkPoint *new_points;
959   
960   OFFSET_GC (gc);
961
962   if (GDK_WINDOW_DESTROYED (drawable))
963     return;
964   
965   if (x_offset != 0 || y_offset != 0)
966     {
967       int i;
968       
969       new_points = g_new (GdkPoint, npoints);
970       for (i=0; i<npoints; i++)
971         {
972           new_points[i].x = points[i].x - x_offset;
973           new_points[i].y = points[i].y - y_offset;
974         }
975     }
976   else
977     new_points = points;
978
979   if (private->paint_stack)
980     {
981       GdkWindowPaint *paint = private->paint_stack->data;
982       gdk_draw_polygon (paint->pixmap, gc, filled, new_points, npoints);
983
984     }
985   else
986     gdk_draw_polygon (private->impl, gc, filled, new_points, npoints);
987   
988   if (new_points != points)
989     g_free (new_points);
990
991   RESTORE_GC (gc);
992 }
993
994 static void
995 gdk_window_draw_text (GdkDrawable *drawable,
996                       GdkFont     *font,
997                       GdkGC       *gc,
998                       gint         x,
999                       gint         y,
1000                       const gchar *text,
1001                       gint         text_length)
1002 {
1003   GdkWindowObject *private = (GdkWindowObject *)drawable;
1004   OFFSET_GC (gc);
1005
1006   if (GDK_WINDOW_DESTROYED (drawable))
1007     return;
1008   
1009   if (private->paint_stack)
1010     {
1011       GdkWindowPaint *paint = private->paint_stack->data;
1012       gdk_draw_text (paint->pixmap, font, gc, 
1013                      x - x_offset, y - y_offset, text, text_length);
1014
1015     }
1016   else
1017     gdk_draw_text (private->impl, font, gc,
1018                    x - x_offset, y - y_offset, text, text_length);
1019
1020   RESTORE_GC (gc);
1021 }
1022
1023 static void
1024 gdk_window_draw_text_wc (GdkDrawable    *drawable,
1025                          GdkFont        *font,
1026                          GdkGC          *gc,
1027                          gint            x,
1028                          gint            y,
1029                          const GdkWChar *text,
1030                          gint            text_length)
1031 {
1032   GdkWindowObject *private = (GdkWindowObject *)drawable;
1033   OFFSET_GC (gc);
1034
1035   if (GDK_WINDOW_DESTROYED (drawable))
1036     return;
1037   
1038   if (private->paint_stack)
1039     {
1040       GdkWindowPaint *paint = private->paint_stack->data;
1041       gdk_draw_text_wc (paint->pixmap, font, gc, 
1042                         x - x_offset, y - y_offset, text, text_length);
1043     }
1044   else
1045     gdk_draw_text_wc (private->impl, font, gc,
1046                       x - x_offset, y - y_offset, text, text_length);
1047   
1048   RESTORE_GC (gc);
1049 }
1050
1051 static void
1052 gdk_window_draw_drawable (GdkDrawable *drawable,
1053                           GdkGC       *gc,
1054                           GdkPixmap   *src,
1055                           gint         xsrc,
1056                           gint         ysrc,
1057                           gint         xdest,
1058                           gint         ydest,
1059                           gint         width,
1060                           gint         height)
1061 {
1062   GdkWindowObject *private = (GdkWindowObject *)drawable;
1063   OFFSET_GC (gc);
1064
1065   if (GDK_WINDOW_DESTROYED (drawable))
1066     return;
1067   
1068   if (private->paint_stack)
1069     {
1070       GdkWindowPaint *paint = private->paint_stack->data;
1071       gdk_draw_drawable (paint->pixmap, gc, src, xsrc, ysrc,
1072                          xdest - x_offset, ydest - y_offset, width, height);
1073
1074     }
1075   else
1076     gdk_draw_drawable (private->impl, gc, src, xsrc, ysrc,
1077                        xdest - x_offset, ydest - y_offset,
1078                        width, height);
1079   RESTORE_GC (gc);
1080 }
1081
1082 static void
1083 gdk_window_draw_points (GdkDrawable *drawable,
1084                         GdkGC       *gc,
1085                         GdkPoint    *points,
1086                         gint         npoints)
1087 {
1088   GdkWindowObject *private = (GdkWindowObject *)drawable;
1089   GdkPoint *new_points;
1090   
1091   OFFSET_GC (gc);
1092
1093   if (GDK_WINDOW_DESTROYED (drawable))
1094     return;
1095   
1096   if (x_offset != 0 || y_offset != 0)
1097     {
1098       gint i;
1099
1100       new_points = g_new (GdkPoint, npoints);
1101       for (i=0; i<npoints; i++)
1102         {
1103           new_points[i].x = points[i].x - x_offset;
1104           new_points[i].y = points[i].y - y_offset;
1105         }
1106     }
1107   else
1108     new_points = points;
1109
1110   if (private->paint_stack)
1111     {
1112       GdkWindowPaint *paint = private->paint_stack->data;
1113       gdk_draw_points (paint->pixmap, gc, new_points, npoints);
1114     }
1115   else
1116     gdk_draw_points (private->impl, gc, points, npoints);
1117
1118   if (new_points != points)
1119     g_free (new_points);
1120
1121   RESTORE_GC (gc);
1122 }
1123
1124 static void
1125 gdk_window_draw_segments (GdkDrawable *drawable,
1126                           GdkGC       *gc,
1127                           GdkSegment  *segs,
1128                           gint         nsegs)
1129 {
1130   GdkWindowObject *private = (GdkWindowObject *)drawable;
1131   GdkSegment *new_segs;
1132
1133   OFFSET_GC (gc);
1134
1135   if (GDK_WINDOW_DESTROYED (drawable))
1136     return;
1137   
1138   if (x_offset != 0 || y_offset != 0)
1139     {
1140       gint i;
1141
1142       new_segs = g_new (GdkSegment, nsegs);
1143       for (i=0; i<nsegs; i++)
1144         {
1145           new_segs[i].x1 = segs[i].x1 - x_offset;
1146           new_segs[i].y1 = segs[i].y1 - y_offset;
1147           new_segs[i].x2 = segs[i].x2 - x_offset;
1148           new_segs[i].y2 = segs[i].y2 - y_offset;
1149         }
1150     }
1151   else
1152     new_segs = segs;
1153
1154   if (private->paint_stack)
1155     {
1156       GdkWindowPaint *paint = private->paint_stack->data;
1157       gdk_draw_segments (paint->pixmap, gc, new_segs, nsegs);
1158     }
1159   else
1160     gdk_draw_segments (private->impl, gc, new_segs, nsegs);
1161   
1162   if (new_segs != segs)
1163     g_free (new_segs);
1164
1165   RESTORE_GC (gc);
1166 }
1167
1168 static void
1169 gdk_window_draw_lines (GdkDrawable *drawable,
1170                        GdkGC       *gc,
1171                        GdkPoint    *points,
1172                        gint         npoints)
1173 {
1174   GdkWindowObject *private = (GdkWindowObject *)drawable;
1175   GdkPoint *new_points;
1176
1177   OFFSET_GC (gc);
1178
1179   if (GDK_WINDOW_DESTROYED (drawable))
1180     return;
1181   
1182   if (x_offset != 0 || y_offset != 0)
1183     {
1184       gint i;
1185
1186       new_points = g_new (GdkPoint, npoints);
1187       for (i=0; i<npoints; i++)
1188         {
1189           new_points[i].x = points[i].x - x_offset;
1190           new_points[i].y = points[i].y - y_offset;
1191         }
1192     }
1193   else
1194     new_points = points;
1195
1196   if (private->paint_stack)
1197     {
1198       GdkWindowPaint *paint = private->paint_stack->data;
1199       gdk_draw_lines (paint->pixmap, gc, new_points, npoints);
1200     }
1201   else
1202     gdk_draw_lines (private->impl, gc, new_points, npoints);
1203
1204   if (new_points != points)
1205     g_free (new_points);
1206
1207   RESTORE_GC (gc);
1208 }
1209
1210 static void
1211 gdk_window_draw_glyphs (GdkDrawable      *drawable,
1212                         GdkGC            *gc,
1213                         PangoFont        *font,
1214                         gint              x,
1215                         gint              y,
1216                         PangoGlyphString *glyphs)
1217 {
1218   GdkWindowObject *private = (GdkWindowObject *)drawable;
1219
1220   OFFSET_GC (gc);
1221
1222   if (GDK_WINDOW_DESTROYED (drawable))
1223     return;
1224   
1225   if (private->paint_stack)
1226     {
1227       GdkWindowPaint *paint = private->paint_stack->data;
1228
1229       gdk_draw_glyphs (paint->pixmap, gc, font, x - x_offset, y - y_offset, glyphs);
1230     }
1231   else
1232     gdk_draw_glyphs (private->impl, gc, font,
1233                      x - x_offset, y - y_offset, glyphs);
1234
1235   RESTORE_GC (gc);
1236 }
1237
1238 /* Fixme - this is just like gdk_window_paint_init_bg */
1239 static void
1240 gdk_window_clear_backing_rect (GdkWindow *window,
1241                                gint       x,
1242                                gint       y,
1243                                gint       width,
1244                                gint       height)
1245 {
1246   GdkWindowObject *private = (GdkWindowObject *)window;
1247   GdkWindowPaint *paint = private->paint_stack->data;
1248   GdkGC *tmp_gc;
1249
1250   if (GDK_WINDOW_DESTROYED (window))
1251     return;
1252   
1253   tmp_gc = gdk_window_get_bg_gc (window, paint);
1254   gdk_draw_rectangle (paint->pixmap, tmp_gc, TRUE,
1255                       x - paint->x_offset, y - paint->y_offset, width, height);
1256   gdk_gc_unref (tmp_gc);
1257 }
1258
1259 void
1260 gdk_window_clear (GdkWindow *window)
1261 {
1262   gint width, height;
1263   
1264   g_return_if_fail (window != NULL);
1265   g_return_if_fail (GDK_IS_WINDOW (window));
1266
1267   gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height);
1268   
1269   gdk_window_clear_area (window, 0, 0,
1270                          width, height);
1271 }
1272
1273 void
1274 gdk_window_clear_area (GdkWindow *window,
1275                        gint       x,
1276                        gint       y,
1277                        gint       width,
1278                        gint       height)
1279 {
1280   GdkWindowObject *private = (GdkWindowObject *)window;
1281
1282   g_return_if_fail (window != NULL);
1283   g_return_if_fail (GDK_IS_WINDOW (window));
1284   
1285   if (private->paint_stack)
1286     gdk_window_clear_backing_rect (window, x, y, width, height);
1287   else
1288     _gdk_windowing_window_clear_area (window, x, y, width, height);
1289 }
1290
1291 void
1292 gdk_window_clear_area_e (GdkWindow *window,
1293                          gint       x,
1294                          gint       y,
1295                          gint       width,
1296                          gint       height)
1297 {
1298   GdkWindowObject *private = (GdkWindowObject *)window;
1299
1300   g_return_if_fail (window != NULL);
1301   g_return_if_fail (GDK_IS_WINDOW (window));
1302   
1303   if (private->paint_stack)
1304     gdk_window_clear_backing_rect (window, x, y, width, height);
1305
1306   _gdk_windowing_window_clear_area_e (window, x, y, width, height);
1307 }
1308
1309 static void
1310 gdk_window_draw_image (GdkDrawable *drawable,
1311                        GdkGC       *gc,
1312                        GdkImage    *image,
1313                        gint         xsrc,
1314                        gint         ysrc,
1315                        gint         xdest,
1316                        gint         ydest,
1317                        gint         width,
1318                        gint         height)
1319 {
1320   GdkWindowObject *private = (GdkWindowObject *)drawable;
1321
1322   OFFSET_GC (gc);
1323
1324   if (GDK_WINDOW_DESTROYED (drawable))
1325     return;
1326   
1327   if (private->paint_stack)
1328     {
1329       GdkWindowPaint *paint = private->paint_stack->data;
1330       gdk_draw_image (paint->pixmap, gc, image, xsrc, ysrc,
1331                       xdest - x_offset, ydest - y_offset,
1332                       width, height);
1333
1334     }
1335   else
1336     gdk_draw_image (private->impl, gc, image, xsrc, ysrc,
1337                     xdest - x_offset, ydest - y_offset,
1338                     width, height);
1339
1340   RESTORE_GC (gc);
1341 }
1342
1343
1344 static void
1345 gdk_window_real_get_size (GdkDrawable *drawable,
1346                           gint *width,
1347                           gint *height)
1348 {
1349   g_return_if_fail (GDK_IS_WINDOW (drawable));
1350
1351   gdk_drawable_get_size (GDK_WINDOW_OBJECT (drawable)->impl,
1352                          width, height);
1353 }
1354
1355 static GdkVisual*
1356 gdk_window_real_get_visual (GdkDrawable *drawable)
1357 {
1358   GdkColormap *colormap;
1359
1360   g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
1361
1362   colormap = gdk_drawable_get_colormap (drawable);
1363   return colormap ? gdk_colormap_get_visual (colormap) : NULL;
1364 }
1365
1366 static gint
1367 gdk_window_real_get_depth (GdkDrawable *drawable)
1368 {
1369   gint depth;
1370   
1371   g_return_val_if_fail (GDK_IS_WINDOW (drawable), 0);
1372
1373   depth = ((GdkWindowObject *)GDK_WINDOW (drawable))->depth;
1374
1375   if (depth == 0)
1376     {
1377       g_print ("0 depth for type %s\n", g_type_name (G_OBJECT_TYPE (drawable)));
1378       G_BREAKPOINT ();
1379     }
1380
1381   return depth;
1382 }
1383
1384 static void
1385 gdk_window_real_set_colormap (GdkDrawable *drawable,
1386                               GdkColormap *cmap)
1387 {
1388   g_return_if_fail (GDK_IS_WINDOW (drawable));  
1389
1390   if (GDK_WINDOW_DESTROYED (drawable))
1391     return;
1392   
1393   gdk_drawable_set_colormap (((GdkWindowObject*)drawable)->impl, cmap);
1394 }
1395
1396 static GdkColormap*
1397 gdk_window_real_get_colormap (GdkDrawable *drawable)
1398 {
1399   g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
1400
1401   if (GDK_WINDOW_DESTROYED (drawable))
1402     return NULL;
1403   
1404   return gdk_drawable_get_colormap (((GdkWindowObject*)drawable)->impl);
1405 }
1406
1407 /* Code for dirty-region queueing
1408  */
1409
1410 static GSList *update_windows = NULL;
1411 static guint update_idle = 0;
1412
1413 static void
1414 gdk_window_process_updates_internal (GdkWindow *window)
1415 {
1416   GdkWindowObject *private = (GdkWindowObject *)window;
1417   gboolean save_region = FALSE;
1418
1419   /* If an update got queued during update processing, we can get a
1420    * window in the update queue that has an empty update_area.
1421    * just ignore it.
1422    */
1423   if (private->update_area)
1424     {
1425       GdkRegion *update_area = private->update_area;
1426       private->update_area = NULL;
1427       
1428       if (gdk_event_func && gdk_window_is_viewable (window))
1429         {
1430           GdkEvent event;
1431           GdkRectangle window_rect;
1432           gint width, height;
1433
1434           gdk_drawable_get_size (GDK_DRAWABLE (private), &width, &height);
1435           
1436           window_rect.x = 0;
1437           window_rect.y = 0;
1438           window_rect.width = width;
1439           window_rect.height = height;
1440
1441           save_region = _gdk_windowing_window_queue_antiexpose (window, update_area);
1442       
1443           event.expose.type = GDK_EXPOSE;
1444           event.expose.window = gdk_window_ref (window);
1445           event.expose.count = 0;
1446       
1447           gdk_region_get_clipbox (update_area, &event.expose.area);
1448           if (gdk_rectangle_intersect (&event.expose.area, &window_rect, &event.expose.area))
1449             {
1450               (*gdk_event_func) (&event, gdk_event_data);
1451             }
1452
1453           gdk_window_unref (window);
1454         }
1455       
1456       if (!save_region)
1457         gdk_region_destroy (update_area);
1458     }
1459 }
1460
1461 void
1462 gdk_window_process_all_updates (void)
1463 {
1464   GSList *old_update_windows = update_windows;
1465   GSList *tmp_list = update_windows;
1466
1467   if (update_idle)
1468     g_source_remove (update_idle);
1469   
1470   update_windows = NULL;
1471   update_idle = 0;
1472
1473   while (tmp_list)
1474     {
1475       gdk_window_process_updates_internal (tmp_list->data);
1476       tmp_list = tmp_list->next;
1477     }
1478
1479   g_slist_free (old_update_windows);
1480
1481   gdk_flush();
1482 }
1483
1484 static gboolean
1485 gdk_window_update_idle (gpointer data)
1486 {
1487   gdk_window_process_all_updates ();
1488   
1489   return FALSE;
1490 }
1491
1492 void
1493 gdk_window_process_updates (GdkWindow *window,
1494                             gboolean   update_children)
1495 {
1496   GdkWindowObject *private = (GdkWindowObject *)window;
1497
1498   g_return_if_fail (window != NULL);
1499   g_return_if_fail (GDK_IS_WINDOW (window));
1500
1501   if (private->update_area)
1502     {
1503       gdk_window_process_updates_internal (window);
1504       update_windows = g_slist_remove (update_windows, window);
1505     }
1506
1507   if (update_children)
1508     {
1509       GList *tmp_list = private->children;
1510       while (tmp_list)
1511         {
1512           gdk_window_process_updates (tmp_list->data, TRUE);
1513           tmp_list = tmp_list->next;
1514         }
1515     }
1516 }
1517
1518 void
1519 gdk_window_invalidate_rect   (GdkWindow    *window,
1520                               GdkRectangle *rect,
1521                               gboolean      invalidate_children)
1522 {
1523   GdkRectangle window_rect;
1524   GdkWindowObject *private = (GdkWindowObject *)window;
1525
1526   g_return_if_fail (window != NULL);
1527   g_return_if_fail (GDK_IS_WINDOW (window));
1528
1529   if (GDK_WINDOW_DESTROYED (window))
1530     return;
1531   
1532   if (private->input_only || !private->mapped)
1533     return;
1534
1535   if (!rect)
1536     {
1537       window_rect.x = 0;
1538       window_rect.y = 0;
1539       gdk_drawable_get_size (GDK_DRAWABLE (window),
1540                              &window_rect.width,
1541                              &window_rect.height);
1542       rect = &window_rect;
1543     }
1544   
1545   if (private->update_area)
1546     {
1547       gdk_region_union_with_rect (private->update_area, rect);
1548     }
1549   else
1550     {
1551       update_windows = g_slist_prepend (update_windows, window);
1552       private->update_area = gdk_region_rectangle (rect);
1553
1554       if (!private->update_freeze_count && !update_idle)
1555         update_idle = g_idle_add_full (GDK_PRIORITY_REDRAW,
1556                                        gdk_window_update_idle, NULL, NULL);
1557     }
1558
1559
1560   if (invalidate_children)
1561     {
1562       GList *tmp_list;
1563       GdkRectangle child_rect, new_rect;
1564
1565       tmp_list = private->children;
1566       while (tmp_list)
1567         {
1568           GdkWindowObject *child = tmp_list->data;
1569           tmp_list = tmp_list->next;
1570
1571           if (!child->input_only)
1572             {
1573               gint width, height;
1574
1575               gdk_drawable_get_size (GDK_DRAWABLE (child),
1576                                      &width, &height);
1577               
1578               child_rect.x = child->x;
1579               child_rect.y = child->y;
1580               child_rect.width = width;
1581               child_rect.height = height;
1582               
1583               if (gdk_rectangle_intersect (rect, &child_rect, &new_rect))
1584                 {
1585                   new_rect.x -= child_rect.x;
1586                   new_rect.y -= child_rect.y;
1587                   
1588                   gdk_window_invalidate_rect ((GdkWindow *)child, &new_rect, TRUE);
1589                 }
1590             }
1591         }
1592     }
1593 }
1594
1595 void
1596 gdk_window_invalidate_region (GdkWindow *window,
1597                               GdkRegion *region,
1598                               gboolean   invalidate_children)
1599 {
1600   GdkWindowObject *private = (GdkWindowObject *)window;
1601
1602   g_return_if_fail (window != NULL);
1603   g_return_if_fail (GDK_IS_WINDOW (window));
1604
1605   if (GDK_WINDOW_DESTROYED (window))
1606     return;
1607   
1608   if (private->input_only || !private->mapped)
1609     return;
1610   
1611   if (private->update_area)
1612     {
1613       gdk_region_union (private->update_area, region);
1614     }
1615   else
1616     {
1617       update_windows = g_slist_prepend (update_windows, window);
1618       private->update_area = gdk_region_copy (region);
1619
1620       if (!private->update_freeze_count && !update_idle)
1621         update_idle = g_idle_add_full (GDK_PRIORITY_REDRAW,
1622                                        gdk_window_update_idle, NULL, NULL);
1623     }
1624
1625   if (invalidate_children)
1626     {
1627       GList *tmp_list;
1628       GdkRectangle child_rect;
1629       GdkRegion *child_region;
1630
1631       tmp_list = private->children;
1632       while (tmp_list)
1633         {
1634           GdkWindowObject *child = tmp_list->data;
1635           tmp_list = tmp_list->next;
1636
1637           if (!child->input_only)
1638             {
1639               gint width, height;
1640
1641               gdk_drawable_get_size (GDK_DRAWABLE (child),
1642                                      &width, &height);
1643               
1644               child_rect.x = child->x;
1645               child_rect.y = child->y;
1646               child_rect.width = width;
1647               child_rect.height = height;
1648               
1649               child_region = gdk_region_rectangle (&child_rect);
1650               gdk_region_intersect (child_region, region);
1651               
1652               if (!gdk_region_empty (child_region))
1653                 {
1654                   gdk_region_offset (child_region, - child_rect.x, - child_rect.y);
1655                   gdk_window_invalidate_region ((GdkWindow *)child, child_region, TRUE);
1656                 }
1657               
1658               gdk_region_destroy (child_region);
1659             }
1660         }
1661     }
1662 }
1663
1664 GdkRegion *
1665 gdk_window_get_update_area (GdkWindow *window)
1666 {
1667   GdkWindowObject *private = (GdkWindowObject *)window;
1668   GdkRegion *tmp_region;
1669
1670   g_return_val_if_fail (window != NULL, NULL);
1671   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1672
1673   if (private->update_area)
1674     {
1675       tmp_region = private->update_area;
1676       private->update_area = NULL;
1677
1678       update_windows = g_slist_remove (update_windows, window);
1679       
1680       return tmp_region;
1681     }
1682   else
1683     return NULL;
1684 }
1685
1686 /**
1687  * _gdk_window_clear_update_area:
1688  * @window: a #GdkWindow.
1689  * 
1690  * Internal function to clear the update area for a window. This
1691  * is called when the window is hidden or destroyed.
1692  **/
1693 void
1694 _gdk_window_clear_update_area (GdkWindow *window)
1695 {
1696   GdkWindowObject *private = (GdkWindowObject *)window;
1697
1698   g_return_if_fail (window != NULL);
1699   g_return_if_fail (GDK_IS_WINDOW (window));
1700
1701   if (private->update_area)
1702     {
1703       update_windows = g_slist_remove (update_windows, window);
1704       
1705       gdk_region_destroy (private->update_area);
1706       private->update_area = NULL;
1707     }
1708 }
1709
1710 void
1711 gdk_window_freeze_updates (GdkWindow *window)
1712 {
1713   GdkWindowObject *private = (GdkWindowObject *)window;
1714
1715   g_return_if_fail (window != NULL);
1716   g_return_if_fail (GDK_IS_WINDOW (window));
1717
1718   private->update_freeze_count++;
1719 }
1720
1721 void
1722 gdk_window_thaw_updates (GdkWindow *window)
1723 {
1724   GdkWindowObject *private = (GdkWindowObject *)window;
1725
1726   g_return_if_fail (window != NULL);
1727   g_return_if_fail (GDK_IS_WINDOW (window));
1728   g_return_if_fail (private->update_freeze_count > 0);
1729
1730   private->update_freeze_count--;
1731   if (!private->update_freeze_count && private->update_area && !update_idle)
1732     update_idle = g_idle_add_full (GDK_PRIORITY_REDRAW,
1733                                    gdk_window_update_idle, NULL, NULL);
1734 }
1735