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