]> Pileus Git - ~andy/gtk/blob - gdk/gdkwindow.c
Revert name change
[~andy/gtk] / gdk / gdkwindow.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-2007 Peter Mattis, Spencer Kimball,
3  * Josh MacDonald, Ryan Lortie
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20
21 /*
22  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
23  * file for a list of people on the GTK+ Team.  See the ChangeLog
24  * files for a list of changes.  These files are distributed with
25  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
26  */
27
28 #include "config.h"
29 #include "gdkwindow.h"
30 #include "gdkwindowimpl.h"
31 #include "gdkinternals.h"
32 #include "gdk.h"                /* For gdk_rectangle_union() */
33 #include "gdkpixmap.h"
34 #include "gdkdrawable.h"
35 #include "gdkscreen.h"
36 #include "gdkalias.h"
37
38 #define USE_BACKING_STORE       /* Appears to work on Win32, too, now. */
39
40 typedef struct _GdkWindowPaint GdkWindowPaint;
41
42 struct _GdkWindowPaint
43 {
44   GdkRegion *region;
45   GdkPixmap *pixmap;
46   gint x_offset;
47   gint y_offset;
48   cairo_surface_t *surface;
49 };
50
51 typedef struct {
52   GdkRegion *old_region;
53   gint old_clip_x_origin;
54   gint old_clip_y_origin;
55   gint x_offset;
56   gint y_offset;
57 } GdkWindowClipData;
58
59 struct _GdkWindowRedirect
60 {
61   GdkWindowObject *redirected;
62   GdkDrawable *pixmap;
63   gint src_x;
64   gint src_y;
65   gint dest_x;
66   gint dest_y;
67   gint width;
68   gint height;
69 };
70
71 static GdkGC *gdk_window_create_gc      (GdkDrawable     *drawable,
72                                          GdkGCValues     *values,
73                                          GdkGCValuesMask  mask);
74 static void   gdk_window_draw_rectangle (GdkDrawable     *drawable,
75                                          GdkGC           *gc,
76                                          gboolean         filled,
77                                          gint             x,
78                                          gint             y,
79                                          gint             width,
80                                          gint             height);
81 static void   gdk_window_draw_arc       (GdkDrawable     *drawable,
82                                          GdkGC           *gc,
83                                          gboolean         filled,
84                                          gint             x,
85                                          gint             y,
86                                          gint             width,
87                                          gint             height,
88                                          gint             angle1,
89                                          gint             angle2);
90 static void   gdk_window_draw_polygon   (GdkDrawable     *drawable,
91                                          GdkGC           *gc,
92                                          gboolean         filled,
93                                          GdkPoint        *points,
94                                          gint             npoints);
95 static void   gdk_window_draw_text      (GdkDrawable     *drawable,
96                                          GdkFont         *font,
97                                          GdkGC           *gc,
98                                          gint             x,
99                                          gint             y,
100                                          const gchar     *text,
101                                          gint             text_length);
102 static void   gdk_window_draw_text_wc   (GdkDrawable     *drawable,
103                                          GdkFont         *font,
104                                          GdkGC           *gc,
105                                          gint             x,
106                                          gint             y,
107                                          const GdkWChar  *text,
108                                          gint             text_length);
109 static void   gdk_window_draw_drawable  (GdkDrawable     *drawable,
110                                          GdkGC           *gc,
111                                          GdkPixmap       *src,
112                                          gint             xsrc,
113                                          gint             ysrc,
114                                          gint             xdest,
115                                          gint             ydest,
116                                          gint             width,
117                                          gint             height);
118 static void   gdk_window_draw_points    (GdkDrawable     *drawable,
119                                          GdkGC           *gc,
120                                          GdkPoint        *points,
121                                          gint             npoints);
122 static void   gdk_window_draw_segments  (GdkDrawable     *drawable,
123                                          GdkGC           *gc,
124                                          GdkSegment      *segs,
125                                          gint             nsegs);
126 static void   gdk_window_draw_lines     (GdkDrawable     *drawable,
127                                          GdkGC           *gc,
128                                          GdkPoint        *points,
129                                          gint             npoints);
130
131 static void gdk_window_draw_glyphs             (GdkDrawable      *drawable,
132                                                 GdkGC            *gc,
133                                                 PangoFont        *font,
134                                                 gint              x,
135                                                 gint              y,
136                                                 PangoGlyphString *glyphs);
137 static void gdk_window_draw_glyphs_transformed (GdkDrawable      *drawable,
138                                                 GdkGC            *gc,
139                                                 PangoMatrix      *matrix,
140                                                 PangoFont        *font,
141                                                 gint              x,
142                                                 gint              y,
143                                                 PangoGlyphString *glyphs);
144
145 static void   gdk_window_draw_image     (GdkDrawable     *drawable,
146                                          GdkGC           *gc,
147                                          GdkImage        *image,
148                                          gint             xsrc,
149                                          gint             ysrc,
150                                          gint             xdest,
151                                          gint             ydest,
152                                          gint             width,
153                                          gint             height);
154
155 static void gdk_window_draw_pixbuf (GdkDrawable     *drawable,
156                                     GdkGC           *gc,
157                                     GdkPixbuf       *pixbuf,
158                                     gint             src_x,
159                                     gint             src_y,
160                                     gint             dest_x,
161                                     gint             dest_y,
162                                     gint             width,
163                                     gint             height,
164                                     GdkRgbDither     dither,
165                                     gint             x_dither,
166                                     gint             y_dither);
167
168 static void gdk_window_draw_trapezoids (GdkDrawable   *drawable,
169                                         GdkGC         *gc,
170                                         GdkTrapezoid  *trapezoids,
171                                         gint           n_trapezoids);
172
173 static GdkImage* gdk_window_copy_to_image (GdkDrawable *drawable,
174                                            GdkImage    *image,
175                                            gint         src_x,
176                                            gint         src_y,
177                                            gint         dest_x,
178                                            gint         dest_y,
179                                            gint         width,
180                                            gint         height);
181
182 static cairo_surface_t *gdk_window_ref_cairo_surface (GdkDrawable *drawable);
183
184 static void   gdk_window_real_get_size  (GdkDrawable     *drawable,
185                                          gint            *width,
186                                          gint            *height);
187
188 static GdkVisual*   gdk_window_real_get_visual   (GdkDrawable *drawable);
189 static gint         gdk_window_real_get_depth    (GdkDrawable *drawable);
190 static GdkScreen*   gdk_window_real_get_screen   (GdkDrawable *drawable);
191 static void         gdk_window_real_set_colormap (GdkDrawable *drawable,
192                                                   GdkColormap *cmap);
193 static GdkColormap* gdk_window_real_get_colormap (GdkDrawable *drawable);
194
195 static GdkDrawable* gdk_window_get_composite_drawable (GdkDrawable *drawable,
196                                                        gint         x,
197                                                        gint         y,
198                                                        gint         width,
199                                                        gint         height,
200                                                        gint        *composite_x_offset,
201                                                        gint        *composite_y_offset);
202 static GdkRegion*   gdk_window_get_clip_region        (GdkDrawable *drawable);
203 static GdkRegion*   gdk_window_get_visible_region     (GdkDrawable *drawable);
204
205 static void gdk_window_free_paint_stack (GdkWindow *window);
206
207 static void gdk_window_init       (GdkWindowObject      *window);
208 static void gdk_window_class_init (GdkWindowObjectClass *klass);
209 static void gdk_window_finalize   (GObject              *object);
210 static void gdk_window_clear_backing_rect (GdkWindow *window,
211                                            gint       x,
212                                            gint       y,
213                                            gint       width,
214                                            gint       height);
215 static void setup_redirect_clip           (GdkWindow         *window,
216                                            GdkGC             *gc,
217                                            GdkWindowClipData *data);
218 static void reset_redirect_clip           (GdkWindow         *offscreen,
219                                            GdkGC             *gc,
220                                            GdkWindowClipData *data);
221 static void gdk_window_redirect_free      (GdkWindowRedirect *redirect);
222 static void apply_redirect_to_children    (GdkWindowObject   *private,
223                                            GdkWindowRedirect *redirect);
224 static void remove_redirect_from_children (GdkWindowObject   *private,
225                                            GdkWindowRedirect *redirect);
226 static GdkRegion *_gdk_window_calculate_full_clip_region (GdkWindow *window,
227                                                           GdkWindow *base_window,
228                                                           GdkGC *gc,
229                                                           gboolean do_children,
230                                                           gint *base_x_offset,
231                                                           gint *base_y_offset);
232
233 static gpointer parent_class = NULL;
234
235 GType
236 gdk_window_object_get_type (void)
237 {
238   static GType object_type = 0;
239
240   if (!object_type)
241     object_type = g_type_register_static_simple (GDK_TYPE_DRAWABLE,
242                                                  "GdkWindow",
243                                                  sizeof (GdkWindowObjectClass),
244                                                  (GClassInitFunc) gdk_window_class_init,
245                                                  sizeof (GdkWindowObject),
246                                                  (GInstanceInitFunc) gdk_window_init,
247                                                  0);
248   
249   return object_type;
250 }
251
252 GType
253 _gdk_paintable_get_type (void)
254 {
255   static GType paintable_type = 0;
256
257   if (!paintable_type)
258     {
259       const GTypeInfo paintable_info =
260       {
261         sizeof (GdkPaintableIface),  /* class_size */
262         NULL,                        /* base_init */
263         NULL,                        /* base_finalize */
264       };
265
266       paintable_type = g_type_register_static (G_TYPE_INTERFACE,
267                                                g_intern_static_string ("GdkPaintable"),
268                                                &paintable_info, 0);
269
270       g_type_interface_add_prerequisite (paintable_type, G_TYPE_OBJECT);
271     }
272
273   return paintable_type;
274 }
275
276 static void
277 gdk_window_init (GdkWindowObject *window)
278 {
279   /* 0-initialization is good for all other fields. */
280
281   window->window_type = GDK_WINDOW_CHILD;
282
283   window->state = GDK_WINDOW_STATE_WITHDRAWN;
284 }
285
286 static void
287 gdk_window_class_init (GdkWindowObjectClass *klass)
288 {
289   GObjectClass *object_class = G_OBJECT_CLASS (klass);
290   GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
291   
292   parent_class = g_type_class_peek_parent (klass);
293
294   object_class->finalize = gdk_window_finalize;
295
296   drawable_class->create_gc = gdk_window_create_gc;
297   drawable_class->draw_rectangle = gdk_window_draw_rectangle;
298   drawable_class->draw_arc = gdk_window_draw_arc;
299   drawable_class->draw_polygon = gdk_window_draw_polygon;
300   drawable_class->draw_text = gdk_window_draw_text;
301   drawable_class->draw_text_wc = gdk_window_draw_text_wc;
302   drawable_class->draw_drawable = gdk_window_draw_drawable;
303   drawable_class->draw_points = gdk_window_draw_points;
304   drawable_class->draw_segments = gdk_window_draw_segments;
305   drawable_class->draw_lines = gdk_window_draw_lines;
306   drawable_class->draw_glyphs = gdk_window_draw_glyphs;
307   drawable_class->draw_glyphs_transformed = gdk_window_draw_glyphs_transformed;
308   drawable_class->draw_image = gdk_window_draw_image;
309   drawable_class->draw_pixbuf = gdk_window_draw_pixbuf;
310   drawable_class->draw_trapezoids = gdk_window_draw_trapezoids;
311   drawable_class->get_depth = gdk_window_real_get_depth;
312   drawable_class->get_screen = gdk_window_real_get_screen;
313   drawable_class->get_size = gdk_window_real_get_size;
314   drawable_class->set_colormap = gdk_window_real_set_colormap;
315   drawable_class->get_colormap = gdk_window_real_get_colormap;
316   drawable_class->get_visual = gdk_window_real_get_visual;
317   drawable_class->_copy_to_image = gdk_window_copy_to_image;
318   drawable_class->ref_cairo_surface = gdk_window_ref_cairo_surface;
319   drawable_class->get_clip_region = gdk_window_get_clip_region;
320   drawable_class->get_visible_region = gdk_window_get_visible_region;
321   drawable_class->get_composite_drawable = gdk_window_get_composite_drawable;
322 }
323
324 static void
325 gdk_window_finalize (GObject *object)
326 {
327   GdkWindow *window = GDK_WINDOW (object);
328   GdkWindowObject *obj = (GdkWindowObject *) object;
329   
330   if (!GDK_WINDOW_DESTROYED (window))
331     {
332       if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
333         {
334           g_warning ("losing last reference to undestroyed window\n");
335           _gdk_window_destroy (window, FALSE);
336         }
337       else
338         /* We use TRUE here, to keep us from actually calling
339          * XDestroyWindow() on the window
340          */
341         _gdk_window_destroy (window, TRUE);
342     }
343
344   g_object_unref (obj->impl);
345   obj->impl = NULL;
346   
347   G_OBJECT_CLASS (parent_class)->finalize (object);
348 }
349
350 /**
351  * gdk_window_new:
352  * @parent: a #GdkWindow, or %NULL to create the window as a child of
353  *   the default root window for the default display.
354  * @attributes: attributes of the new window
355  * @attributes_mask: mask indicating which fields in @attributes are valid
356  * 
357  * Creates a new #GdkWindow using the attributes from
358  * @attributes. See #GdkWindowAttr and #GdkWindowAttributesType for
359  * more details.  Note: to use this on displays other than the default
360  * display, @parent must be specified.
361  * 
362  * Return value: the new #GdkWindow
363  **/
364 GdkWindow*
365 gdk_window_new (GdkWindow     *parent,
366                 GdkWindowAttr *attributes,
367                 gint           attributes_mask)
368 {
369   GdkWindow *window;
370   GdkWindowObject *private, *parent_private;
371   
372   g_return_val_if_fail (attributes != NULL, NULL);
373
374   window = _gdk_window_new (parent, attributes, attributes_mask);
375
376   /* Inherit redirection from parent */
377   if (parent != NULL)
378     {
379       parent_private = GDK_WINDOW_OBJECT (parent);
380       private = GDK_WINDOW_OBJECT (window);
381       private->redirect = parent_private->redirect;
382     }
383   
384   return window;
385 }
386
387 /**
388  * gdk_window_reparent:
389  * @window: a #GdkWindow
390  * @new_parent: new parent to move @window into
391  * @x: X location inside the new parent
392  * @y: Y location inside the new parent
393  *
394  * Reparents @window into the given @new_parent. The window being
395  * reparented will be unmapped as a side effect.
396  * 
397  **/
398 void
399 gdk_window_reparent (GdkWindow *window,
400                      GdkWindow *new_parent,
401                      gint       x,
402                      gint       y)
403 {
404   GdkWindowObject *private;
405   gboolean show;
406   
407   g_return_if_fail (GDK_IS_WINDOW (window));
408   g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
409   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
410
411   if (GDK_WINDOW_DESTROYED (window) ||
412       (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
413     {
414       return;
415     }
416
417   private = (GdkWindowObject *) window;
418
419   /* Break up redirection if inherited */
420   if (private->redirect && private->redirect->redirected != private)
421     {
422       remove_redirect_from_children (private, private->redirect);
423       private->redirect = NULL;
424     }
425   
426   show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent (window, new_parent, x, y);
427
428   /* Inherit parent redirect if we don't have our own */
429   if (private->parent && private->redirect == NULL)
430     {
431       private->redirect = private->parent->redirect;
432       apply_redirect_to_children (private, private->redirect);
433     }
434
435   if (show)
436     gdk_window_show (window);
437 }
438
439 static void
440 window_remove_filters (GdkWindow *window)
441 {
442   GdkWindowObject *obj = (GdkWindowObject*) window;
443
444   if (obj->filters)
445     {
446       GList *tmp_list;
447       
448       for (tmp_list = obj->filters; tmp_list; tmp_list = tmp_list->next)
449         g_free (tmp_list->data);
450     
451       g_list_free (obj->filters);
452       obj->filters = NULL;
453     }
454 }
455
456 /**
457  * _gdk_window_destroy_hierarchy:
458  * @window: a #GdkWindow
459  * @recursing: If TRUE, then this is being called because a parent
460  *            was destroyed. This generally means that the call to the 
461  *            windowing system to destroy the window can be omitted, since
462  *            it will be destroyed as a result of the parent being destroyed.
463  *            Unless @foreign_destroy.           
464  * @foreign_destroy: If TRUE, the window or a parent was destroyed by some 
465  *            external agency. The window has already been destroyed and no 
466  *            windowing system calls should be made. (This may never happen
467  *            for some windowing systems.)
468  *
469  * Internal function to destroy a window. Like gdk_window_destroy(),
470  * but does not drop the reference count created by gdk_window_new().
471  **/
472 static void
473 _gdk_window_destroy_hierarchy (GdkWindow *window,
474                                gboolean   recursing,
475                                gboolean   foreign_destroy)
476 {
477   GdkWindowObject *private;
478   GdkWindowObject *temp_private;
479   GdkWindow *temp_window;
480   GdkScreen *screen;
481   GList *children;
482   GList *tmp;
483   
484   g_return_if_fail (window != NULL);
485   
486   private = (GdkWindowObject*) window;
487   
488   if (GDK_WINDOW_DESTROYED (window))
489     return;
490     
491   switch (GDK_WINDOW_TYPE (window))
492     {
493     case GDK_WINDOW_ROOT:
494       screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
495       if (!screen->closed)
496         {
497           g_error ("attempted to destroy root window");
498           break;
499         }
500       /* else fall thru */
501     case GDK_WINDOW_TOPLEVEL:
502     case GDK_WINDOW_CHILD:
503     case GDK_WINDOW_DIALOG:
504     case GDK_WINDOW_TEMP:
505     case GDK_WINDOW_FOREIGN:
506       if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN && !foreign_destroy)
507         {
508           /* Logically, it probably makes more sense to send
509            * a "destroy yourself" message to the foreign window
510            * whether or not it's in our heirarchy; but for historical
511            * reasons, we only send "destroy yourself" messages to
512            * foreign windows in our heirarchy.
513            */
514           if (private->parent)
515             _gdk_windowing_window_destroy_foreign (window);
516
517           /* Also for historical reasons, we remove any filters
518            * on a foreign window when it or a parent is destroyed;
519            * this likely causes problems if two separate portions
520            * of code are maintaining filter lists on a foreign window.
521            */
522           window_remove_filters (window);
523         }
524       else
525         {
526           private->state |= GDK_WINDOW_STATE_WITHDRAWN;
527           
528           if (private->parent)
529             {
530               GdkWindowObject *parent_private = (GdkWindowObject *)private->parent;
531               if (parent_private->children)
532                 parent_private->children = g_list_remove (parent_private->children, window);
533             }
534
535           _gdk_window_clear_update_area (window);
536           gdk_window_free_paint_stack (window);
537           
538           if (private->bg_pixmap &&
539               private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
540               private->bg_pixmap != GDK_NO_BG)
541             {
542               g_object_unref (private->bg_pixmap);
543               private->bg_pixmap = NULL;
544             }
545           
546           if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN)
547             g_assert (private->children == NULL);
548           else
549             {
550               children = tmp = private->children;
551               private->children = NULL;
552               
553               while (tmp)
554                 {
555                   temp_window = tmp->data;
556                   tmp = tmp->next;
557                   
558                   temp_private = (GdkWindowObject*) temp_window;
559                   if (temp_private)
560                     _gdk_window_destroy_hierarchy (temp_window,
561                                                    TRUE, foreign_destroy);
562                 }
563               
564               g_list_free (children);
565             }
566           
567           _gdk_windowing_window_destroy (window, recursing, foreign_destroy);
568           private->parent = NULL;
569           private->destroyed = TRUE;
570
571           window_remove_filters (window);
572
573           gdk_drawable_set_colormap (GDK_DRAWABLE (window), NULL);
574
575           /* If we own the redirect, free it */
576           if (private->redirect && private->redirect->redirected == private)
577             gdk_window_redirect_free (private->redirect);
578
579           private->redirect = NULL;
580         }
581       break;
582     }
583 }
584
585 /**
586  * _gdk_window_destroy:
587  * @window: a #GdkWindow
588  * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
589  *            external agency. The window has already been destroyed and no
590  *            windowing system calls should be made. (This may never happen
591  *            for some windowing systems.)
592  *
593  * Internal function to destroy a window. Like gdk_window_destroy(),
594  * but does not drop the reference count created by gdk_window_new().
595  **/
596 void
597 _gdk_window_destroy (GdkWindow *window,
598                      gboolean   foreign_destroy)
599 {
600   _gdk_window_destroy_hierarchy (window, FALSE, foreign_destroy);
601 }
602
603 /**
604  * gdk_window_destroy:
605  * @window: a #GdkWindow
606  *
607  * Destroys the window system resources associated with @window and decrements @window's
608  * reference count. The window system resources for all children of @window are also
609  * destroyed, but the children's reference counts are not decremented.
610  *
611  * Note that a window will not be destroyed automatically when its reference count
612  * reaches zero. You must call this function yourself before that happens.
613  *
614  **/
615 void
616 gdk_window_destroy (GdkWindow *window)
617 {
618   _gdk_window_destroy_hierarchy (window, FALSE, FALSE);
619   g_object_unref (window);
620 }
621
622 /**
623  * gdk_window_set_user_data:
624  * @window: a #GdkWindow
625  * @user_data: user data
626  *
627  * For most purposes this function is deprecated in favor of
628  * g_object_set_data(). However, for historical reasons GTK+ stores
629  * the #GtkWidget that owns a #GdkWindow as user data on the
630  * #GdkWindow. So, custom widget implementations should use
631  * this function for that. If GTK+ receives an event for a #GdkWindow,
632  * and the user data for the window is non-%NULL, GTK+ will assume the
633  * user data is a #GtkWidget, and forward the event to that widget.
634  * 
635  **/
636 void
637 gdk_window_set_user_data (GdkWindow *window,
638                           gpointer   user_data)
639 {
640   g_return_if_fail (window != NULL);
641   
642   ((GdkWindowObject*)window)->user_data = user_data;
643 }
644
645 /**
646  * gdk_window_get_user_data:
647  * @window: a #GdkWindow
648  * @data: return location for user data
649  *
650  * Retrieves the user data for @window, which is normally the widget
651  * that @window belongs to. See gdk_window_set_user_data().
652  * 
653  **/
654 void
655 gdk_window_get_user_data (GdkWindow *window,
656                           gpointer  *data)
657 {
658   g_return_if_fail (window != NULL);
659   
660   *data = ((GdkWindowObject*)window)->user_data;
661 }
662
663 /**
664  * gdk_window_get_window_type:
665  * @window: a #GdkWindow
666  * 
667  * Gets the type of the window. See #GdkWindowType.
668  * 
669  * Return value: type of window
670  **/
671 GdkWindowType
672 gdk_window_get_window_type (GdkWindow *window)
673 {
674   g_return_val_if_fail (GDK_IS_WINDOW (window), (GdkWindowType) -1);
675   
676   return GDK_WINDOW_TYPE (window);
677 }
678
679 /**
680  * gdk_window_get_position:
681  * @window: a #GdkWindow
682  * @x: X coordinate of window
683  * @y: Y coordinate of window
684  *
685  * Obtains the position of the window as reported in the
686  * most-recently-processed #GdkEventConfigure. Contrast with
687  * gdk_window_get_geometry() which queries the X server for the
688  * current window position, regardless of which events have been
689  * received or processed.
690  *
691  * The position coordinates are relative to the window's parent window.
692  * 
693  **/
694 void
695 gdk_window_get_position (GdkWindow *window,
696                          gint      *x,
697                          gint      *y)
698 {
699   GdkWindowObject *obj;
700   
701   g_return_if_fail (GDK_IS_WINDOW (window));
702   
703   obj = (GdkWindowObject*) window;
704   
705   if (x)
706     *x = obj->x;
707   if (y)
708     *y = obj->y;
709 }
710
711 /**
712  * gdk_window_get_parent:
713  * @window: a #GdkWindow
714  * 
715  * Obtains the parent of @window, as known to GDK. Does not query the
716  * X server; thus this returns the parent as passed to gdk_window_new(),
717  * not the actual parent. This should never matter unless you're using
718  * Xlib calls mixed with GDK calls on the X11 platform. It may also
719  * matter for toplevel windows, because the window manager may choose
720  * to reparent them.
721  * 
722  * Return value: parent of @window
723  **/
724 GdkWindow*
725 gdk_window_get_parent (GdkWindow *window)
726 {
727   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
728   
729   return (GdkWindow*) ((GdkWindowObject*) window)->parent;
730 }
731
732 /**
733  * gdk_window_get_toplevel:
734  * @window: a #GdkWindow
735  * 
736  * Gets the toplevel window that's an ancestor of @window.
737  * 
738  * Return value: the toplevel window containing @window
739  **/
740 GdkWindow*
741 gdk_window_get_toplevel (GdkWindow *window)
742 {
743   GdkWindowObject *obj;
744   
745   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
746
747   obj = (GdkWindowObject *)window;
748   while (GDK_WINDOW_TYPE (obj) == GDK_WINDOW_CHILD)
749     obj = (GdkWindowObject *)obj->parent;
750   
751   return GDK_WINDOW (obj);
752 }
753
754 /**
755  * gdk_window_get_children:
756  * @window: a #GdkWindow
757  * 
758  * Gets the list of children of @window known to GDK.
759  * This function only returns children created via GDK,
760  * so for example it's useless when used with the root window;
761  * it only returns windows an application created itself.
762  *
763  * The returned list must be freed, but the elements in the
764  * list need not be.
765  * 
766  * Return value: list of child windows inside @window
767  **/
768 GList*
769 gdk_window_get_children (GdkWindow *window)
770 {
771   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
772
773   if (GDK_WINDOW_DESTROYED (window))
774     return NULL;
775
776   return g_list_copy (GDK_WINDOW_OBJECT (window)->children);
777 }
778
779 /**
780  * gdk_window_peek_children:
781  * @window: a #GdkWindow
782  * 
783  * Like gdk_window_get_children(), but does not copy the list of
784  * children, so the list does not need to be freed.
785  * 
786  * Return value: a reference to the list of child windows in @window
787  **/
788 GList *
789 gdk_window_peek_children (GdkWindow *window)
790 {
791   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
792
793   if (GDK_WINDOW_DESTROYED (window))
794     return NULL;
795
796   return GDK_WINDOW_OBJECT (window)->children;
797 }
798
799 /**
800  * gdk_window_add_filter:
801  * @window: a #GdkWindow
802  * @function: filter callback
803  * @data: data to pass to filter callback
804  *
805  * Adds an event filter to @window, allowing you to intercept events
806  * before they reach GDK. This is a low-level operation and makes it
807  * easy to break GDK and/or GTK+, so you have to know what you're
808  * doing. Pass %NULL for @window to get all events for all windows,
809  * instead of events for a specific window.
810  *
811  * See gdk_display_add_client_message_filter() if you are interested
812  * in X ClientMessage events.
813  **/
814 void          
815 gdk_window_add_filter (GdkWindow     *window,
816                        GdkFilterFunc  function,
817                        gpointer       data)
818 {
819   GdkWindowObject *private;
820   GList *tmp_list;
821   GdkEventFilter *filter;
822   
823   g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
824
825   private = (GdkWindowObject*) window;
826   if (private && GDK_WINDOW_DESTROYED (window))
827     return;
828   
829   if (private)
830     tmp_list = private->filters;
831   else
832     tmp_list = _gdk_default_filters;
833   
834   while (tmp_list)
835     {
836       filter = (GdkEventFilter *)tmp_list->data;
837       if ((filter->function == function) && (filter->data == data))
838         return;
839       tmp_list = tmp_list->next;
840     }
841   
842   filter = g_new (GdkEventFilter, 1);
843   filter->function = function;
844   filter->data = data;
845   
846   if (private)
847     private->filters = g_list_append (private->filters, filter);
848   else
849     _gdk_default_filters = g_list_append (_gdk_default_filters, filter);
850 }
851
852 /**
853  * gdk_window_remove_filter:
854  * @window: a #GdkWindow
855  * @function: previously-added filter function
856  * @data: user data for previously-added filter function
857  *
858  * Remove a filter previously added with gdk_window_add_filter().
859  * 
860  **/
861 void
862 gdk_window_remove_filter (GdkWindow     *window,
863                           GdkFilterFunc  function,
864                           gpointer       data)
865 {
866   GdkWindowObject *private;
867   GList *tmp_list, *node;
868   GdkEventFilter *filter;
869   
870   g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
871
872   private = (GdkWindowObject*) window;
873   
874   if (private)
875     tmp_list = private->filters;
876   else
877     tmp_list = _gdk_default_filters;
878   
879   while (tmp_list)
880     {
881       filter = (GdkEventFilter *)tmp_list->data;
882       node = tmp_list;
883       tmp_list = tmp_list->next;
884       
885       if ((filter->function == function) && (filter->data == data))
886         {
887           if (private)
888             private->filters = g_list_remove_link (private->filters, node);
889           else
890             _gdk_default_filters = g_list_remove_link (_gdk_default_filters, node);
891           g_list_free_1 (node);
892           g_free (filter);
893           
894           return;
895         }
896     }
897 }
898
899 /**
900  * gdk_screen_get_toplevel_windows:
901  * @screen: The #GdkScreen where the toplevels are located.
902  * 
903  * Obtains a list of all toplevel windows known to GDK on the screen @screen.
904  * A toplevel window is a child of the root window (see
905  * gdk_get_default_root_window()).
906  *
907  * The returned list should be freed with g_list_free(), but
908  * its elements need not be freed.
909  * 
910  * Return value: list of toplevel windows, free with g_list_free()
911  *
912  * Since: 2.2
913  **/
914 GList *
915 gdk_screen_get_toplevel_windows (GdkScreen *screen)
916 {
917   GdkWindow * root_window;
918   GList *new_list = NULL;
919   GList *tmp_list;
920   
921   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
922   
923   root_window = gdk_screen_get_root_window (screen);
924
925   tmp_list = ((GdkWindowObject *)root_window)->children;
926   while (tmp_list)
927     {
928       if (GDK_WINDOW_TYPE (tmp_list->data) != GDK_WINDOW_FOREIGN)
929         new_list = g_list_prepend (new_list, tmp_list->data);
930       tmp_list = tmp_list->next;
931     }
932   
933   return new_list;
934 }
935
936 /**
937  * gdk_window_get_toplevels:
938  * 
939  * Obtains a list of all toplevel windows known to GDK on the default
940  * screen (see gdk_screen_get_toplevel_windows()).
941  * A toplevel window is a child of the root window (see
942  * gdk_get_default_root_window()).
943  *
944  * The returned list should be freed with g_list_free(), but
945  * its elements need not be freed.
946  * 
947  * Return value: list of toplevel windows, free with g_list_free()
948  **/
949 GList *
950 gdk_window_get_toplevels (void)
951 {
952   return gdk_screen_get_toplevel_windows (gdk_screen_get_default ());
953 }
954
955 /**
956  * gdk_window_is_visible:
957  * @window: a #GdkWindow
958  * 
959  * Checks whether the window has been mapped (with gdk_window_show() or
960  * gdk_window_show_unraised()).
961  * 
962  * Return value: %TRUE if the window is mapped
963  **/
964 gboolean 
965 gdk_window_is_visible (GdkWindow *window)
966 {
967   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
968   
969   return GDK_WINDOW_IS_MAPPED (window);
970 }
971
972 /**
973  * gdk_window_is_viewable:
974  * @window: a #GdkWindow
975  * 
976  * Check if the window and all ancestors of the window are
977  * mapped. (This is not necessarily "viewable" in the X sense, since
978  * we only check as far as we have GDK window parents, not to the root
979  * window.)
980  *
981  * Return value: %TRUE if the window is viewable
982  **/
983 gboolean 
984 gdk_window_is_viewable (GdkWindow *window)
985 {
986   GdkWindowObject *private = (GdkWindowObject *)window;
987   GdkScreen *screen;
988   GdkWindow *root_window;
989   
990   g_return_val_if_fail (window != NULL, FALSE);
991   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
992
993   screen = gdk_drawable_get_screen (window);
994   root_window = gdk_screen_get_root_window (screen);
995   
996   while (private && 
997          (private != (GdkWindowObject *)root_window) &&
998          (GDK_WINDOW_TYPE (private) != GDK_WINDOW_FOREIGN))
999     {
1000       if (GDK_WINDOW_DESTROYED (private) || !GDK_WINDOW_IS_MAPPED (private))
1001         return FALSE;
1002       
1003       private = (GdkWindowObject *)private->parent;
1004     }
1005   
1006   return TRUE;
1007 }
1008
1009 /**
1010  * gdk_window_get_state:
1011  * @window: a #GdkWindow
1012  * 
1013  * Gets the bitwise OR of the currently active window state flags,
1014  * from the #GdkWindowState enumeration.
1015  * 
1016  * Return value: window state bitfield
1017  **/
1018 GdkWindowState
1019 gdk_window_get_state (GdkWindow *window)
1020 {
1021   GdkWindowObject *private = (GdkWindowObject *)window;
1022   
1023   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
1024   
1025   return private->state;
1026 }
1027
1028 /**
1029  * gdk_window_begin_paint_rect:
1030  * @window: a #GdkWindow
1031  * @rectangle: rectangle you intend to draw to
1032  *
1033  * A convenience wrapper around gdk_window_begin_paint_region() which
1034  * creates a rectangular region for you. See
1035  * gdk_window_begin_paint_region() for details.
1036  * 
1037  **/
1038 void
1039 gdk_window_begin_paint_rect (GdkWindow          *window,
1040                              const GdkRectangle *rectangle)
1041 {
1042   GdkRegion *region;
1043
1044   g_return_if_fail (window != NULL);
1045   g_return_if_fail (GDK_IS_WINDOW (window));
1046
1047   region = gdk_region_rectangle (rectangle);
1048   gdk_window_begin_paint_region (window, region);
1049   gdk_region_destroy (region);
1050 }
1051
1052 #ifdef GDK_WINDOWING_X11
1053 #include "x11/gdkx.h"
1054 #endif
1055
1056 /**
1057  * gdk_window_begin_paint_region:
1058  * @window: a #GdkWindow
1059  * @region: region you intend to draw to
1060  *
1061  * Indicates that you are beginning the process of redrawing @region.
1062  * A backing store (offscreen buffer) large enough to contain @region
1063  * will be created. The backing store will be initialized with the
1064  * background color or background pixmap for @window. Then, all
1065  * drawing operations performed on @window will be diverted to the
1066  * backing store.  When you call gdk_window_end_paint(), the backing
1067  * store will be copied to @window, making it visible onscreen. Only
1068  * the part of @window contained in @region will be modified; that is,
1069  * drawing operations are clipped to @region.
1070  *
1071  * The net result of all this is to remove flicker, because the user
1072  * sees the finished product appear all at once when you call
1073  * gdk_window_end_paint(). If you draw to @window directly without
1074  * calling gdk_window_begin_paint_region(), the user may see flicker
1075  * as individual drawing operations are performed in sequence.  The
1076  * clipping and background-initializing features of
1077  * gdk_window_begin_paint_region() are conveniences for the
1078  * programmer, so you can avoid doing that work yourself.
1079  *
1080  * When using GTK+, the widget system automatically places calls to
1081  * gdk_window_begin_paint_region() and gdk_window_end_paint() around
1082  * emissions of the expose_event signal. That is, if you're writing an
1083  * expose event handler, you can assume that the exposed area in
1084  * #GdkEventExpose has already been cleared to the window background,
1085  * is already set as the clip region, and already has a backing store.
1086  * Therefore in most cases, application code need not call
1087  * gdk_window_begin_paint_region(). (You can disable the automatic
1088  * calls around expose events on a widget-by-widget basis by calling
1089  * gtk_widget_set_double_buffered().)
1090  *
1091  * If you call this function multiple times before calling the
1092  * matching gdk_window_end_paint(), the backing stores are pushed onto
1093  * a stack. gdk_window_end_paint() copies the topmost backing store
1094  * onscreen, subtracts the topmost region from all other regions in
1095  * the stack, and pops the stack. All drawing operations affect only
1096  * the topmost backing store in the stack. One matching call to
1097  * gdk_window_end_paint() is required for each call to
1098  * gdk_window_begin_paint_region().
1099  * 
1100  **/
1101 void          
1102 gdk_window_begin_paint_region (GdkWindow       *window,
1103                                const GdkRegion *region)
1104 {
1105 #ifdef USE_BACKING_STORE
1106   GdkWindowObject *private = (GdkWindowObject *)window;
1107   GdkRectangle clip_box;
1108   GdkWindowPaint *paint;
1109   GSList *list;
1110   
1111   g_return_if_fail (window != NULL);
1112   g_return_if_fail (GDK_IS_WINDOW (window));
1113
1114   if (GDK_WINDOW_DESTROYED (window))
1115     return;
1116
1117   if (GDK_IS_PAINTABLE (private->impl)) 
1118     {
1119       GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
1120
1121       if (iface->begin_paint_region)
1122         iface->begin_paint_region ((GdkPaintable*)private->impl, region);
1123
1124       return;
1125     }
1126
1127   gdk_region_get_clipbox (region, &clip_box);
1128
1129   paint = g_new (GdkWindowPaint, 1);
1130   paint->region = gdk_region_copy (region);
1131   paint->x_offset = clip_box.x;
1132   paint->y_offset = clip_box.y;
1133   paint->pixmap =
1134     gdk_pixmap_new (window,
1135                     MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1);
1136
1137   paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap);
1138   cairo_surface_set_device_offset (paint->surface,
1139                                    - paint->x_offset, - paint->y_offset);
1140   
1141   for (list = private->paint_stack; list != NULL; list = list->next)
1142     {
1143       GdkWindowPaint *tmp_paint = list->data;
1144
1145       gdk_region_subtract (tmp_paint->region, paint->region);
1146     }
1147   
1148   private->paint_stack = g_slist_prepend (private->paint_stack, paint);
1149
1150   if (!gdk_region_empty (region))
1151     {
1152       gdk_window_clear_backing_rect (window,
1153                                      clip_box.x, clip_box.y,
1154                                      clip_box.width, clip_box.height);
1155     }
1156 #endif /* USE_BACKING_STORE */
1157 }
1158
1159 /**
1160  * gdk_window_end_paint:
1161  * @window: a #GdkWindow
1162  *
1163  * Indicates that the backing store created by the most recent call to
1164  * gdk_window_begin_paint_region() should be copied onscreen and
1165  * deleted, leaving the next-most-recent backing store or no backing
1166  * store at all as the active paint region. See
1167  * gdk_window_begin_paint_region() for full details. It is an error to
1168  * call this function without a matching
1169  * gdk_window_begin_paint_region() first.
1170  * 
1171  **/
1172 void
1173 gdk_window_end_paint (GdkWindow *window)
1174 {
1175 #ifdef USE_BACKING_STORE
1176   GdkWindowObject *private = (GdkWindowObject *)window;
1177   GdkWindowObject *composited;
1178   GdkWindowPaint *paint;
1179   GdkGC *tmp_gc;
1180   GdkRectangle clip_box;
1181   gint x_offset, y_offset;
1182
1183   g_return_if_fail (window != NULL);
1184   g_return_if_fail (GDK_IS_WINDOW (window));
1185
1186   if (GDK_WINDOW_DESTROYED (window))
1187     return;
1188
1189   if (GDK_IS_PAINTABLE (private->impl))
1190     {
1191       GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
1192
1193       if (iface->end_paint)
1194         iface->end_paint ((GdkPaintable*)private->impl);
1195       return;
1196     }
1197
1198   if (private->paint_stack == NULL)
1199     {
1200       g_warning (G_STRLOC": no preceding call to gdk_window_begin_paint_region(), see documentation");
1201       return;
1202     }
1203
1204   paint = private->paint_stack->data;
1205   private->paint_stack = g_slist_delete_link (private->paint_stack, 
1206                                               private->paint_stack);
1207
1208   gdk_region_get_clipbox (paint->region, &clip_box);
1209
1210   tmp_gc = _gdk_drawable_get_scratch_gc (window, FALSE);
1211
1212   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (window, &x_offset, &y_offset);
1213
1214   gdk_gc_set_clip_region (tmp_gc, paint->region);
1215   gdk_gc_set_clip_origin (tmp_gc, - x_offset, - y_offset);
1216
1217   gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
1218                      clip_box.x - paint->x_offset,
1219                      clip_box.y - paint->y_offset,
1220                      clip_box.x - x_offset, clip_box.y - y_offset,
1221                      clip_box.width, clip_box.height);
1222
1223   if (private->redirect)
1224     {
1225       GdkWindowClipData data;
1226       
1227       setup_redirect_clip (window, tmp_gc, &data);
1228       gdk_draw_drawable (private->redirect->pixmap, tmp_gc, paint->pixmap,
1229                          clip_box.x - paint->x_offset,
1230                          clip_box.y - paint->y_offset,
1231                          clip_box.x + data.x_offset,
1232                          clip_box.y + data.y_offset,
1233                          clip_box.width, clip_box.height);
1234       reset_redirect_clip (window, tmp_gc, &data);
1235     }
1236   
1237   /* Reset clip region of the cached GdkGC */
1238   gdk_gc_set_clip_region (tmp_gc, NULL);
1239
1240   cairo_surface_destroy (paint->surface);
1241   g_object_unref (paint->pixmap);
1242   gdk_region_destroy (paint->region);
1243   g_free (paint);
1244
1245   /* find a composited window in our hierarchy to signal its
1246    * parent to redraw, calculating the clip box as we go...
1247    *
1248    * stop if parent becomes NULL since then we'd have nowhere
1249    * to draw (ie: 'composited' will always be non-NULL here).
1250    */
1251   for (composited = private;
1252        composited->parent;
1253        composited = composited->parent)
1254     {
1255       int width, height;
1256
1257       gdk_drawable_get_size (GDK_DRAWABLE (composited->parent),
1258                              &width, &height);
1259
1260       clip_box.x += composited->x;
1261       clip_box.y += composited->y;
1262       clip_box.width = MIN (clip_box.width, width - clip_box.x);
1263       clip_box.height = MIN (clip_box.height, height - clip_box.y);
1264
1265       if (composited->composited)
1266         {
1267           gdk_window_invalidate_rect (GDK_WINDOW (composited->parent),
1268                                       &clip_box, FALSE);
1269           break;
1270         }
1271     }
1272 #endif /* USE_BACKING_STORE */
1273 }
1274
1275 static void
1276 gdk_window_free_paint_stack (GdkWindow *window)
1277 {
1278   GdkWindowObject *private = (GdkWindowObject *)window;
1279   
1280   if (private->paint_stack)
1281     {
1282       GSList *tmp_list = private->paint_stack;
1283
1284       while (tmp_list)
1285         {
1286           GdkWindowPaint *paint = tmp_list->data;
1287
1288           if (tmp_list == private->paint_stack)
1289             g_object_unref (paint->pixmap);
1290                   
1291           gdk_region_destroy (paint->region);
1292           g_free (paint);
1293
1294           tmp_list = tmp_list->next;
1295         }
1296
1297       g_slist_free (private->paint_stack);
1298       private->paint_stack = NULL;
1299     }
1300 }
1301
1302 static void
1303 gdk_window_get_offsets (GdkWindow *window,
1304                         gint      *x_offset,
1305                         gint      *y_offset)
1306 {
1307   GdkWindowObject *private = (GdkWindowObject *)window;
1308   
1309   if (private->paint_stack)
1310     {
1311       GdkWindowPaint *paint = private->paint_stack->data;
1312       *x_offset = paint->x_offset;
1313       *y_offset = paint->y_offset;
1314     }
1315   else
1316     GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (window, x_offset, y_offset);
1317 }
1318
1319 /**
1320  * gdk_window_get_internal_paint_info:
1321  * @window: a #GdkWindow
1322  * @real_drawable: location to store the drawable to which drawing should be 
1323  *            done.
1324  * @x_offset: location to store the X offset between coordinates in @window,
1325  *            and the underlying window system primitive coordinates for 
1326  *            *@real_drawable.
1327  * @y_offset: location to store the Y offset between coordinates in @window,
1328  *            and the underlying window system primitive coordinates for
1329  *            *@real_drawable.
1330  * 
1331  * If you bypass the GDK layer and use windowing system primitives to
1332  * draw directly onto a #GdkWindow, then you need to deal with two
1333  * details: there may be an offset between GDK coordinates and windowing
1334  * system coordinates, and GDK may have redirected drawing to a offscreen
1335  * pixmap as the result of a gdk_window_begin_paint_region() calls.
1336  * This function allows retrieving the information you need to compensate
1337  * for these effects.
1338  *
1339  * This function exposes details of the GDK implementation, and is thus
1340  * likely to change in future releases of GDK.
1341  **/
1342 void
1343 gdk_window_get_internal_paint_info (GdkWindow    *window,
1344                                     GdkDrawable **real_drawable,
1345                                     gint         *x_offset,
1346                                     gint         *y_offset)
1347 {
1348   gint x_off, y_off;
1349   
1350   GdkWindowObject *private;
1351
1352   g_return_if_fail (GDK_IS_WINDOW (window));
1353
1354   private = (GdkWindowObject *)window;
1355
1356   if (real_drawable)
1357     {
1358       if (private->paint_stack)
1359         {
1360           GdkWindowPaint *paint = private->paint_stack->data;
1361           *real_drawable = paint->pixmap;
1362         }
1363       else
1364         *real_drawable = window;
1365     }
1366
1367   gdk_window_get_offsets (window, &x_off, &y_off);
1368
1369   if (x_offset)
1370     *x_offset = x_off;
1371   if (y_offset)
1372     *y_offset = y_off;
1373 }
1374
1375 #define OFFSET_GC(gc)                                         \
1376     gint x_offset, y_offset;                                  \
1377     gint old_clip_x = gc->clip_x_origin;    \
1378     gint old_clip_y = gc->clip_y_origin;    \
1379     gint old_ts_x = gc->ts_x_origin;        \
1380     gint old_ts_y = gc->ts_y_origin;        \
1381     gdk_window_get_offsets (drawable, &x_offset, &y_offset);  \
1382     if (x_offset != 0 || y_offset != 0)                       \
1383       {                                                       \
1384         gdk_gc_set_clip_origin (gc, old_clip_x - x_offset,    \
1385                                 old_clip_y - y_offset);       \
1386         gdk_gc_set_ts_origin (gc, old_ts_x - x_offset,        \
1387                               old_ts_y - y_offset);           \
1388       }
1389
1390 #define RESTORE_GC(gc)                                      \
1391     if (x_offset != 0 || y_offset != 0)                     \
1392      {                                                      \
1393        gdk_gc_set_clip_origin (gc, old_clip_x, old_clip_y); \
1394        gdk_gc_set_ts_origin (gc, old_ts_x, old_ts_y);       \
1395      }
1396
1397 static GdkGC *
1398 gdk_window_create_gc (GdkDrawable     *drawable,
1399                       GdkGCValues     *values,
1400                       GdkGCValuesMask  mask)
1401 {
1402   g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
1403   
1404   if (GDK_WINDOW_DESTROYED (drawable))
1405     return NULL;
1406
1407   return gdk_gc_new_with_values (((GdkWindowObject *) drawable)->impl,
1408                                  values, mask);
1409 }
1410
1411 static void
1412 gdk_window_draw_rectangle (GdkDrawable *drawable,
1413                            GdkGC       *gc,
1414                            gboolean     filled,
1415                            gint         x,
1416                            gint         y,
1417                            gint         width,
1418                            gint         height)
1419 {
1420   GdkWindowObject *private = (GdkWindowObject *)drawable;
1421   OFFSET_GC (gc);
1422
1423   if (GDK_WINDOW_DESTROYED (drawable))
1424     return;
1425   
1426   if (private->paint_stack)
1427     {
1428       GdkWindowPaint *paint = private->paint_stack->data;
1429       gdk_draw_rectangle (paint->pixmap, gc, filled,
1430                           x - x_offset, y - y_offset, width, height);
1431     }
1432   else
1433     gdk_draw_rectangle (private->impl, gc, filled,
1434                         x - x_offset, y - y_offset, width, height);
1435
1436   RESTORE_GC (gc);
1437 }
1438
1439 static void
1440 gdk_window_draw_arc (GdkDrawable *drawable,
1441                      GdkGC       *gc,
1442                      gboolean     filled,
1443                      gint         x,
1444                      gint         y,
1445                      gint         width,
1446                      gint         height,
1447                      gint         angle1,
1448                      gint         angle2)
1449 {
1450   GdkWindowObject *private = (GdkWindowObject *)drawable;
1451   OFFSET_GC (gc);
1452
1453   if (GDK_WINDOW_DESTROYED (drawable))
1454     return;
1455   
1456   if (private->paint_stack)
1457     {
1458       GdkWindowPaint *paint = private->paint_stack->data;
1459       gdk_draw_arc (paint->pixmap, gc, filled,
1460                     x - x_offset, y - y_offset,
1461                     width, height, angle1, angle2);
1462     }
1463   else
1464     gdk_draw_arc (private->impl, gc, filled,
1465                   x - x_offset, y - y_offset,
1466                   width, height, angle1, angle2);
1467   RESTORE_GC (gc);
1468 }
1469
1470 static void
1471 gdk_window_draw_polygon (GdkDrawable *drawable,
1472                          GdkGC       *gc,
1473                          gboolean     filled,
1474                          GdkPoint    *points,
1475                          gint         npoints)
1476 {
1477   GdkWindowObject *private = (GdkWindowObject *)drawable;
1478   GdkPoint *new_points;
1479   
1480   OFFSET_GC (gc);
1481
1482   if (GDK_WINDOW_DESTROYED (drawable))
1483     return;
1484   
1485   if (x_offset != 0 || y_offset != 0)
1486     {
1487       int i;
1488       
1489       new_points = g_new (GdkPoint, npoints);
1490       for (i=0; i<npoints; i++)
1491         {
1492           new_points[i].x = points[i].x - x_offset;
1493           new_points[i].y = points[i].y - y_offset;
1494         }
1495     }
1496   else
1497     new_points = points;
1498
1499   if (private->paint_stack)
1500     {
1501       GdkWindowPaint *paint = private->paint_stack->data;
1502       gdk_draw_polygon (paint->pixmap, gc, filled, new_points, npoints);
1503
1504     }
1505   else
1506     gdk_draw_polygon (private->impl, gc, filled, new_points, npoints);
1507   
1508   if (new_points != points)
1509     g_free (new_points);
1510
1511   RESTORE_GC (gc);
1512 }
1513
1514 static void
1515 gdk_window_draw_text (GdkDrawable *drawable,
1516                       GdkFont     *font,
1517                       GdkGC       *gc,
1518                       gint         x,
1519                       gint         y,
1520                       const gchar *text,
1521                       gint         text_length)
1522 {
1523   GdkWindowObject *private = (GdkWindowObject *)drawable;
1524   OFFSET_GC (gc);
1525
1526   if (GDK_WINDOW_DESTROYED (drawable))
1527     return;
1528   
1529   if (private->paint_stack)
1530     {
1531       GdkWindowPaint *paint = private->paint_stack->data;
1532       gdk_draw_text (paint->pixmap, font, gc, 
1533                      x - x_offset, y - y_offset, text, text_length);
1534
1535     }
1536   else
1537     gdk_draw_text (private->impl, font, gc,
1538                    x - x_offset, y - y_offset, text, text_length);
1539
1540   RESTORE_GC (gc);
1541 }
1542
1543 static void
1544 gdk_window_draw_text_wc (GdkDrawable    *drawable,
1545                          GdkFont        *font,
1546                          GdkGC          *gc,
1547                          gint            x,
1548                          gint            y,
1549                          const GdkWChar *text,
1550                          gint            text_length)
1551 {
1552   GdkWindowObject *private = (GdkWindowObject *)drawable;
1553   OFFSET_GC (gc);
1554
1555   if (GDK_WINDOW_DESTROYED (drawable))
1556     return;
1557   
1558   if (private->paint_stack)
1559     {
1560       GdkWindowPaint *paint = private->paint_stack->data;
1561       gdk_draw_text_wc (paint->pixmap, font, gc, 
1562                         x - x_offset, y - y_offset, text, text_length);
1563     }
1564   else
1565     gdk_draw_text_wc (private->impl, font, gc,
1566                       x - x_offset, y - y_offset, text, text_length);
1567   
1568   RESTORE_GC (gc);
1569 }
1570
1571 static GdkDrawable*
1572 gdk_window_get_composite_drawable (GdkDrawable *drawable,
1573                                    gint         x,
1574                                    gint         y,
1575                                    gint         width,
1576                                    gint         height,
1577                                    gint        *composite_x_offset,
1578                                    gint        *composite_y_offset)
1579 {
1580   GdkWindowObject *private = (GdkWindowObject *)drawable;
1581   GSList *list;
1582   GdkPixmap *tmp_pixmap;
1583   GdkRectangle rect;
1584   GdkGC *tmp_gc;
1585   gboolean overlap_buffer;
1586
1587   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (GDK_WINDOW (drawable),
1588                                                           composite_x_offset,
1589                                                           composite_y_offset);
1590   
1591   if ((GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable))
1592       || private->paint_stack == NULL)
1593     {
1594       /* No backing store */
1595       return g_object_ref (drawable);
1596     }
1597
1598   /* See if the buffered part is overlapping the part we want
1599    * to get
1600    */
1601   rect.x = x;
1602   rect.y = y;
1603   rect.width = width;
1604   rect.height = height;
1605
1606   overlap_buffer = FALSE;
1607   
1608   for (list = private->paint_stack; list != NULL; list = list->next)
1609     {
1610       GdkWindowPaint *paint = list->data;
1611       GdkOverlapType overlap;
1612
1613       overlap = gdk_region_rect_in (paint->region, &rect);
1614
1615       if (overlap == GDK_OVERLAP_RECTANGLE_IN)
1616         {
1617           *composite_x_offset = paint->x_offset;
1618           *composite_y_offset = paint->y_offset;
1619           
1620           return g_object_ref (paint->pixmap);
1621         }
1622       else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
1623         {
1624           overlap_buffer = TRUE;
1625           break;
1626         }
1627     }
1628
1629   if (!overlap_buffer)
1630     return g_object_ref (drawable);
1631
1632   tmp_pixmap = gdk_pixmap_new (drawable, width, height, -1);
1633   tmp_gc = _gdk_drawable_get_scratch_gc (tmp_pixmap, FALSE);
1634
1635   /* Copy the current window contents */
1636   gdk_draw_drawable (tmp_pixmap,
1637                      tmp_gc,
1638                      private->impl,
1639                      x - *composite_x_offset,
1640                      y - *composite_y_offset,
1641                      0, 0,
1642                      width, height);
1643
1644   /* paint the backing stores */
1645   for (list = private->paint_stack; list != NULL; list = list->next)
1646     {
1647       GdkWindowPaint *paint = list->data;
1648
1649       gdk_gc_set_clip_region (tmp_gc, paint->region);
1650       gdk_gc_set_clip_origin (tmp_gc, -x, -y);
1651       
1652       gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
1653                          x - paint->x_offset,
1654                          y - paint->y_offset,
1655                          0, 0, width, height);
1656     }
1657
1658   /* Reset clip region of the cached GdkGC */
1659   gdk_gc_set_clip_region (tmp_gc, NULL);
1660
1661   /* Set these to location of tmp_pixmap within the window */
1662   *composite_x_offset = x;
1663   *composite_y_offset = y;
1664
1665   return tmp_pixmap;
1666 }
1667
1668 static GdkRegion*
1669 gdk_window_get_clip_region (GdkDrawable *drawable)
1670 {
1671   GdkWindowObject *private = (GdkWindowObject *)drawable;
1672   GdkRegion *result;
1673
1674   result = gdk_drawable_get_clip_region (private->impl);
1675
1676   if (private->paint_stack)
1677     {
1678       GdkRegion *paint_region = gdk_region_new ();
1679       GSList *tmp_list = private->paint_stack;
1680
1681       while (tmp_list)
1682         {
1683           GdkWindowPaint *paint = tmp_list->data;
1684           
1685           gdk_region_union (paint_region, paint->region);
1686
1687           tmp_list = tmp_list->next;
1688         }
1689
1690       gdk_region_intersect (result, paint_region);
1691       gdk_region_destroy (paint_region);
1692     }
1693
1694   return result;
1695 }
1696
1697 static GdkRegion*
1698 gdk_window_get_visible_region (GdkDrawable *drawable)
1699 {
1700   GdkWindowObject *private = (GdkWindowObject*) drawable;
1701   
1702   return gdk_drawable_get_visible_region (private->impl);
1703 }
1704
1705 static void
1706 gdk_window_draw_drawable (GdkDrawable *drawable,
1707                           GdkGC       *gc,
1708                           GdkPixmap   *src,
1709                           gint         xsrc,
1710                           gint         ysrc,
1711                           gint         xdest,
1712                           gint         ydest,
1713                           gint         width,
1714                           gint         height)
1715 {
1716   GdkWindowObject *private = (GdkWindowObject *)drawable;
1717   OFFSET_GC (gc);
1718   
1719   if (GDK_WINDOW_DESTROYED (drawable))
1720     return;
1721
1722   /* If we have a backing pixmap draw to that */
1723   if (private->paint_stack)
1724     {
1725       GdkWindowPaint *paint = private->paint_stack->data;
1726       gdk_draw_drawable (paint->pixmap, gc,
1727                          src, xsrc, ysrc,
1728                          xdest - x_offset, ydest - y_offset, width, height);
1729
1730     }
1731   else
1732     gdk_draw_drawable (private->impl, gc,
1733                        src, xsrc, ysrc,
1734                        xdest - x_offset, ydest - y_offset,
1735                        width, height);
1736
1737   RESTORE_GC (gc);
1738 }
1739
1740 static void
1741 gdk_window_draw_points (GdkDrawable *drawable,
1742                         GdkGC       *gc,
1743                         GdkPoint    *points,
1744                         gint         npoints)
1745 {
1746   GdkWindowObject *private = (GdkWindowObject *)drawable;
1747   GdkPoint *new_points;
1748   
1749   OFFSET_GC (gc);
1750
1751   if (GDK_WINDOW_DESTROYED (drawable))
1752     return;
1753   
1754   if (x_offset != 0 || y_offset != 0)
1755     {
1756       gint i;
1757
1758       new_points = g_new (GdkPoint, npoints);
1759       for (i=0; i<npoints; i++)
1760         {
1761           new_points[i].x = points[i].x - x_offset;
1762           new_points[i].y = points[i].y - y_offset;
1763         }
1764     }
1765   else
1766     new_points = points;
1767
1768   if (private->paint_stack)
1769     {
1770       GdkWindowPaint *paint = private->paint_stack->data;
1771       gdk_draw_points (paint->pixmap, gc, new_points, npoints);
1772     }
1773   else
1774     gdk_draw_points (private->impl, gc, points, npoints);
1775
1776   if (new_points != points)
1777     g_free (new_points);
1778
1779   RESTORE_GC (gc);
1780 }
1781
1782 static void
1783 gdk_window_draw_segments (GdkDrawable *drawable,
1784                           GdkGC       *gc,
1785                           GdkSegment  *segs,
1786                           gint         nsegs)
1787 {
1788   GdkWindowObject *private = (GdkWindowObject *)drawable;
1789   GdkSegment *new_segs;
1790
1791   OFFSET_GC (gc);
1792
1793   if (GDK_WINDOW_DESTROYED (drawable))
1794     return;
1795   
1796   if (x_offset != 0 || y_offset != 0)
1797     {
1798       gint i;
1799
1800       new_segs = g_new (GdkSegment, nsegs);
1801       for (i=0; i<nsegs; i++)
1802         {
1803           new_segs[i].x1 = segs[i].x1 - x_offset;
1804           new_segs[i].y1 = segs[i].y1 - y_offset;
1805           new_segs[i].x2 = segs[i].x2 - x_offset;
1806           new_segs[i].y2 = segs[i].y2 - y_offset;
1807         }
1808     }
1809   else
1810     new_segs = segs;
1811
1812   if (private->paint_stack)
1813     {
1814       GdkWindowPaint *paint = private->paint_stack->data;
1815       gdk_draw_segments (paint->pixmap, gc, new_segs, nsegs);
1816     }
1817   else
1818     gdk_draw_segments (private->impl, gc, new_segs, nsegs);
1819   
1820   if (new_segs != segs)
1821     g_free (new_segs);
1822
1823   RESTORE_GC (gc);
1824 }
1825
1826 static void
1827 gdk_window_draw_lines (GdkDrawable *drawable,
1828                        GdkGC       *gc,
1829                        GdkPoint    *points,
1830                        gint         npoints)
1831 {
1832   GdkWindowObject *private = (GdkWindowObject *)drawable;
1833   GdkPoint *new_points;
1834
1835   OFFSET_GC (gc);
1836
1837   if (GDK_WINDOW_DESTROYED (drawable))
1838     return;
1839   
1840   if (x_offset != 0 || y_offset != 0)
1841     {
1842       gint i;
1843
1844       new_points = g_new (GdkPoint, npoints);
1845       for (i=0; i<npoints; i++)
1846         {
1847           new_points[i].x = points[i].x - x_offset;
1848           new_points[i].y = points[i].y - y_offset;
1849         }
1850     }
1851   else
1852     new_points = points;
1853
1854   if (private->paint_stack)
1855     {
1856       GdkWindowPaint *paint = private->paint_stack->data;
1857       gdk_draw_lines (paint->pixmap, gc, new_points, npoints);
1858     }
1859   else
1860     gdk_draw_lines (private->impl, gc, new_points, npoints);
1861
1862   if (new_points != points)
1863     g_free (new_points);
1864
1865   RESTORE_GC (gc);
1866 }
1867
1868 static void
1869 gdk_window_draw_glyphs (GdkDrawable      *drawable,
1870                         GdkGC            *gc,
1871                         PangoFont        *font,
1872                         gint              x,
1873                         gint              y,
1874                         PangoGlyphString *glyphs)
1875 {
1876   GdkWindowObject *private = (GdkWindowObject *)drawable;
1877
1878   OFFSET_GC (gc);
1879
1880   if (GDK_WINDOW_DESTROYED (drawable))
1881     return;
1882   
1883   if (private->paint_stack)
1884     {
1885       GdkWindowPaint *paint = private->paint_stack->data;
1886
1887       gdk_draw_glyphs (paint->pixmap, gc, font, x - x_offset, y - y_offset, glyphs);
1888     }
1889   else
1890     gdk_draw_glyphs (private->impl, gc, font,
1891                      x - x_offset, y - y_offset, glyphs);
1892
1893   RESTORE_GC (gc);
1894 }
1895
1896 static void
1897 gdk_window_draw_glyphs_transformed (GdkDrawable      *drawable,
1898                                     GdkGC            *gc,
1899                                     PangoMatrix      *matrix,
1900                                     PangoFont        *font,
1901                                     gint              x,
1902                                     gint              y,
1903                                     PangoGlyphString *glyphs)
1904 {
1905   GdkWindowObject *private = (GdkWindowObject *)drawable;
1906   PangoMatrix tmp_matrix;
1907
1908   OFFSET_GC (gc);
1909
1910   if (GDK_WINDOW_DESTROYED (drawable))
1911     return;
1912
1913   if (x_offset != 0 || y_offset != 0)
1914     {
1915       if (matrix)
1916         {
1917           tmp_matrix = *matrix;
1918           tmp_matrix.x0 -= x_offset;
1919           tmp_matrix.y0 -= y_offset;
1920           matrix = &tmp_matrix;
1921         }
1922       else if (GDK_PANGO_UNITS_OVERFLOWS (x_offset, y_offset))
1923         {
1924           PangoMatrix identity = PANGO_MATRIX_INIT;
1925           
1926           tmp_matrix = identity;
1927           tmp_matrix.x0 -= x_offset;
1928           tmp_matrix.y0 -= y_offset;
1929           matrix = &tmp_matrix;
1930         }
1931       else
1932         {
1933           x -= x_offset * PANGO_SCALE;
1934           y -= y_offset * PANGO_SCALE;
1935         }
1936     }
1937   
1938   if (private->paint_stack)
1939     {
1940       GdkWindowPaint *paint = private->paint_stack->data;
1941
1942       gdk_draw_glyphs_transformed (paint->pixmap, gc, matrix, font, x, y, glyphs);
1943     }
1944   else
1945     gdk_draw_glyphs_transformed (private->impl, gc, matrix, font, x, y, glyphs);
1946
1947   RESTORE_GC (gc);
1948 }
1949
1950 typedef struct {
1951   cairo_t *cr; /* if non-null, it means use this cairo context */
1952   GdkGC *gc;   /* if non-null, it means use this GC instead */
1953 } BackingRectMethod;
1954
1955 static void
1956 setup_backing_rect_method (BackingRectMethod *method, GdkWindow *window, GdkWindowPaint *paint, int x_offset_cairo, int y_offset_cairo)
1957 {
1958   GdkWindowObject *private = (GdkWindowObject *)window;
1959
1960   if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
1961     {
1962       GdkWindowPaint tmp_paint;
1963
1964       tmp_paint = *paint;
1965       tmp_paint.x_offset += private->x;
1966       tmp_paint.y_offset += private->y;
1967
1968       x_offset_cairo += private->x;
1969       y_offset_cairo += private->y;
1970
1971       setup_backing_rect_method (method, GDK_WINDOW (private->parent), &tmp_paint, x_offset_cairo, y_offset_cairo);
1972     }
1973   else if (private->bg_pixmap &&
1974            private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
1975            private->bg_pixmap != GDK_NO_BG)
1976     {
1977 /* This is a workaround for https://bugs.freedesktop.org/show_bug.cgi?id=4320.
1978  * In it, using a pixmap as a repeating pattern in Cairo, and painting it to a
1979  * pixmap destination surface, can be very slow (on the order of seconds for a
1980  * whole-screen copy).  The workaround is to use pretty much the same code that
1981  * we used in GTK+ 2.6 (pre-Cairo), which clears the double-buffer pixmap with
1982  * a tiled GC XFillRectangle().
1983  */
1984
1985 /* Actually computing this flag is left as an exercise for the reader */
1986 #if defined (G_OS_UNIX)
1987 #  define GDK_CAIRO_REPEAT_IS_FAST 0
1988 #else
1989 #  define GDK_CAIRO_REPEAT_IS_FAST 1
1990 #endif
1991
1992 #if GDK_CAIRO_REPEAT_IS_FAST
1993       cairo_surface_t *surface = _gdk_drawable_ref_cairo_surface (private->bg_pixmap);
1994       cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
1995       cairo_surface_destroy (surface);
1996
1997       if (x_offset_cairo != 0 || y_offset_cairo != 0)
1998         {
1999           cairo_matrix_t matrix;
2000           cairo_matrix_init_translate (&matrix, x_offset_cairo, y_offset_cairo);
2001           cairo_pattern_set_matrix (pattern, &matrix);
2002         }
2003
2004       cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
2005
2006       method->cr = cairo_create (paint->surface);
2007       method->gc = NULL;
2008
2009       cairo_set_source (method->cr, pattern);
2010       cairo_pattern_destroy (pattern);
2011 #else
2012       guint gc_mask;
2013       GdkGCValues gc_values;
2014
2015       gc_values.fill = GDK_TILED;
2016       gc_values.tile = private->bg_pixmap;
2017       gc_values.ts_x_origin = -x_offset_cairo;
2018       gc_values.ts_y_origin = -y_offset_cairo;
2019
2020       gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN;
2021
2022       method->gc = gdk_gc_new_with_values (paint->pixmap, &gc_values, gc_mask);
2023 #endif
2024     }
2025   else
2026     {
2027       method->cr = cairo_create (paint->surface);
2028
2029       gdk_cairo_set_source_color (method->cr, &private->bg_color);
2030     }
2031 }
2032
2033 static void
2034 gdk_window_clear_backing_rect (GdkWindow *window,
2035                                gint       x,
2036                                gint       y,
2037                                gint       width,
2038                                gint       height)
2039 {
2040   GdkWindowObject *private = (GdkWindowObject *)window;
2041   GdkWindowPaint *paint = private->paint_stack->data;
2042   BackingRectMethod method;
2043 #if 0
2044   GTimer *timer;
2045   double elapsed;
2046 #endif
2047
2048   if (GDK_WINDOW_DESTROYED (window))
2049     return;
2050
2051 #if 0
2052   timer = g_timer_new ();
2053 #endif
2054
2055   method.cr = NULL;
2056   method.gc = NULL;
2057   setup_backing_rect_method (&method, window, paint, 0, 0);
2058
2059   if (method.cr)
2060     {
2061       g_assert (method.gc == NULL);
2062
2063       cairo_rectangle (method.cr, x, y, width, height);
2064       cairo_clip (method.cr);
2065
2066       gdk_cairo_region (method.cr, paint->region);
2067       cairo_fill (method.cr);
2068
2069       cairo_destroy (method.cr);
2070 #if 0
2071       elapsed = g_timer_elapsed (timer, NULL);
2072       g_print ("Draw the background with Cairo: %fs\n", elapsed);
2073 #endif
2074     }
2075   else
2076     {
2077       g_assert (method.gc != NULL);
2078
2079       gdk_gc_set_clip_region (method.gc, paint->region);
2080       gdk_draw_rectangle (window, method.gc, TRUE, x, y, width, height);
2081       g_object_unref (method.gc);
2082
2083 #if 0
2084       elapsed = g_timer_elapsed (timer, NULL);
2085       g_print ("Draw the background with GDK: %fs\n", elapsed);
2086 #endif
2087     }
2088
2089 #if 0
2090   g_timer_destroy (timer);
2091 #endif
2092 }
2093
2094 static void
2095 gdk_window_clear_backing_rect_redirect (GdkWindow *window,
2096                                         gint       x,
2097                                         gint       y,
2098                                         gint       width,
2099                                         gint       height)
2100 {
2101   GdkWindowObject *private = (GdkWindowObject *)window;
2102   GdkWindowRedirect *redirect = private->redirect;
2103   GdkRegion *clip_region;
2104   gint x_offset, y_offset;
2105   BackingRectMethod method;
2106   GdkWindowPaint paint;
2107   
2108   if (GDK_WINDOW_DESTROYED (window))
2109     return;
2110
2111   paint.x_offset = x_offset;
2112   paint.y_offset = y_offset;
2113   paint.pixmap = redirect->pixmap;
2114   paint.surface = _gdk_drawable_ref_cairo_surface (redirect->pixmap);
2115   
2116   clip_region = _gdk_window_calculate_full_clip_region (window,
2117                                                         GDK_WINDOW (redirect->redirected),
2118                                                         NULL, TRUE,
2119                                                         &x_offset, &y_offset);
2120   
2121
2122   method.cr = NULL;
2123   method.gc = NULL;
2124   setup_backing_rect_method (&method, window, &paint, 0, 0);
2125
2126   if (method.cr)
2127     {
2128       g_assert (method.gc == NULL);
2129
2130       cairo_rectangle (method.cr, x, y, width, height);
2131       cairo_clip (method.cr);
2132
2133       gdk_cairo_region (method.cr, clip_region);
2134       cairo_fill (method.cr);
2135
2136       cairo_destroy (method.cr);
2137     }
2138   else
2139     {
2140       g_assert (method.gc != NULL);
2141
2142       gdk_gc_set_clip_region (method.gc, clip_region);
2143       gdk_draw_rectangle (window, method.gc, TRUE, x, y, width, height);
2144       g_object_unref (method.gc);
2145
2146     }
2147
2148   gdk_region_destroy (clip_region);
2149   cairo_surface_destroy (paint.surface);
2150 }
2151
2152
2153 /**
2154  * gdk_window_clear:
2155  * @window: a #GdkWindow
2156  * 
2157  * Clears an entire @window to the background color or background pixmap.
2158  **/
2159 void
2160 gdk_window_clear (GdkWindow *window)
2161 {
2162   gint width, height;
2163   
2164   g_return_if_fail (window != NULL);
2165   g_return_if_fail (GDK_IS_WINDOW (window));
2166
2167   gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height);
2168   
2169   gdk_window_clear_area (window, 0, 0,
2170                          width, height);
2171 }
2172
2173 /**
2174  * gdk_window_clear_area:
2175  * @window: a #GdkWindow
2176  * @x: x coordinate of rectangle to clear
2177  * @y: y coordinate of rectangle to clear
2178  * @width: width of rectangle to clear
2179  * @height: height of rectangle to clear
2180  *
2181  * Clears an area of @window to the background color or background pixmap.
2182  * 
2183  **/
2184 void
2185 gdk_window_clear_area (GdkWindow *window,
2186                        gint       x,
2187                        gint       y,
2188                        gint       width,
2189                        gint       height)
2190 {
2191   GdkWindowObject *private = (GdkWindowObject *)window;
2192
2193   g_return_if_fail (window != NULL);
2194   g_return_if_fail (GDK_IS_WINDOW (window));
2195
2196   if (private->paint_stack)
2197     gdk_window_clear_backing_rect (window, x, y, width, height);
2198   else
2199     {
2200       if (private->redirect)
2201         gdk_window_clear_backing_rect_redirect (window, x, y, width, height);
2202
2203       GDK_WINDOW_IMPL_GET_IFACE (private->impl)->clear_area (window,
2204                                                              x, y,
2205                                                              width, height,
2206                                                              FALSE);
2207     }
2208 }
2209
2210 /**
2211  * gdk_window_clear_area_e:
2212  * @window: a #GdkWindow
2213  * @x: x coordinate of rectangle to clear
2214  * @y: y coordinate of rectangle to clear
2215  * @width: width of rectangle to clear
2216  * @height: height of rectangle to clear
2217  *
2218  * Like gdk_window_clear_area(), but also generates an expose event for
2219  * the cleared area.
2220  *
2221  * This function has a stupid name because it dates back to the mists
2222  * time, pre-GDK-1.0.
2223  * 
2224  **/
2225 void
2226 gdk_window_clear_area_e (GdkWindow *window,
2227                          gint       x,
2228                          gint       y,
2229                          gint       width,
2230                          gint       height)
2231 {
2232   GdkWindowObject *private = (GdkWindowObject *)window;
2233
2234   g_return_if_fail (window != NULL);
2235   g_return_if_fail (GDK_IS_WINDOW (window));
2236   
2237   if (private->paint_stack)
2238     gdk_window_clear_backing_rect (window, x, y, width, height);
2239
2240   if (private->redirect)
2241     gdk_window_clear_backing_rect_redirect (window, x, y, width, height);
2242
2243   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->clear_area (window,
2244                                                          x, y,
2245                                                          width, height,
2246                                                          TRUE);
2247 }
2248
2249 static void
2250 gdk_window_draw_image (GdkDrawable *drawable,
2251                        GdkGC       *gc,
2252                        GdkImage    *image,
2253                        gint         xsrc,
2254                        gint         ysrc,
2255                        gint         xdest,
2256                        gint         ydest,
2257                        gint         width,
2258                        gint         height)
2259 {
2260   GdkWindowObject *private = (GdkWindowObject *)drawable;
2261
2262   OFFSET_GC (gc);
2263
2264   if (GDK_WINDOW_DESTROYED (drawable))
2265     return;
2266   
2267   if (private->paint_stack)
2268     {
2269       GdkWindowPaint *paint = private->paint_stack->data;
2270       gdk_draw_image (paint->pixmap, gc, image, xsrc, ysrc,
2271                       xdest - x_offset, ydest - y_offset,
2272                       width, height);
2273
2274     }
2275   else
2276     gdk_draw_image (private->impl, gc, image, xsrc, ysrc,
2277                     xdest - x_offset, ydest - y_offset,
2278                     width, height);
2279
2280   RESTORE_GC (gc);
2281 }
2282
2283 static void
2284 gdk_window_draw_pixbuf (GdkDrawable     *drawable,
2285                         GdkGC           *gc,
2286                         GdkPixbuf       *pixbuf,
2287                         gint             src_x,
2288                         gint             src_y,
2289                         gint             dest_x,
2290                         gint             dest_y,
2291                         gint             width,
2292                         gint             height,
2293                         GdkRgbDither     dither,
2294                         gint             x_dither,
2295                         gint             y_dither)
2296 {
2297   GdkWindowObject *private = (GdkWindowObject *)drawable;
2298
2299   if (GDK_WINDOW_DESTROYED (drawable))
2300     return;
2301   
2302   if (gc)
2303     {
2304       OFFSET_GC (gc);
2305   
2306       if (private->paint_stack)
2307         {
2308           GdkWindowPaint *paint = private->paint_stack->data;
2309           gdk_draw_pixbuf (paint->pixmap, gc, pixbuf, src_x, src_y,
2310                            dest_x - x_offset, dest_y - y_offset,
2311                            width, height,
2312                            dither, x_dither - x_offset, y_dither - y_offset);
2313         }
2314       else
2315         gdk_draw_pixbuf (private->impl, gc, pixbuf, src_x, src_y,
2316                          dest_x - x_offset, dest_y - y_offset,
2317                          width, height,
2318                          dither, x_dither, y_dither);
2319       
2320       RESTORE_GC (gc);
2321     }
2322   else
2323     {
2324       gint x_offset, y_offset;
2325       gdk_window_get_offsets (drawable, &x_offset, &y_offset);
2326       
2327       if (private->paint_stack)
2328         {
2329           GdkWindowPaint *paint = private->paint_stack->data;
2330           gdk_draw_pixbuf (paint->pixmap, gc, pixbuf, src_x, src_y,
2331                            dest_x - x_offset, dest_y - y_offset,
2332                            width, height,
2333                             dither, x_dither - x_offset, y_dither - y_offset);
2334         }
2335       else
2336         gdk_draw_pixbuf (private->impl, gc, pixbuf, src_x, src_y,
2337                          dest_x - x_offset, dest_y - y_offset,
2338                          width, height,
2339                          dither, x_dither, y_dither);
2340     }
2341 }
2342
2343 static void
2344 gdk_window_draw_trapezoids (GdkDrawable   *drawable,
2345                             GdkGC         *gc,
2346                             GdkTrapezoid  *trapezoids,
2347                             gint           n_trapezoids)
2348 {
2349   GdkWindowObject *private = (GdkWindowObject *)drawable;
2350   GdkTrapezoid *new_trapezoids = NULL;
2351
2352   OFFSET_GC (gc);
2353
2354   if (GDK_WINDOW_DESTROYED (drawable))
2355     return;
2356   
2357   if (x_offset != 0 || y_offset != 0)
2358     {
2359       gint i;
2360
2361       new_trapezoids = g_new (GdkTrapezoid, n_trapezoids);
2362       for (i=0; i < n_trapezoids; i++)
2363         {
2364           new_trapezoids[i].y1 = trapezoids[i].y1 - y_offset;
2365           new_trapezoids[i].x11 = trapezoids[i].x11 - x_offset;
2366           new_trapezoids[i].x21 = trapezoids[i].x21 - x_offset;
2367           new_trapezoids[i].y2 = trapezoids[i].y2 - y_offset;
2368           new_trapezoids[i].x12 = trapezoids[i].x12 - x_offset;
2369           new_trapezoids[i].x22 = trapezoids[i].x22 - x_offset;
2370         }
2371
2372       trapezoids = new_trapezoids;
2373     }
2374
2375   if (private->paint_stack)
2376     {
2377       GdkWindowPaint *paint = private->paint_stack->data;
2378       gdk_draw_trapezoids (paint->pixmap, gc, trapezoids, n_trapezoids);
2379     }
2380   else
2381     gdk_draw_trapezoids (private->impl, gc, trapezoids, n_trapezoids);
2382   
2383   g_free (new_trapezoids);
2384
2385   RESTORE_GC (gc);
2386 }
2387
2388 static void
2389 gdk_window_real_get_size (GdkDrawable *drawable,
2390                           gint *width,
2391                           gint *height)
2392 {
2393   g_return_if_fail (GDK_IS_WINDOW (drawable));
2394
2395   gdk_drawable_get_size (GDK_WINDOW_OBJECT (drawable)->impl,
2396                          width, height);
2397 }
2398
2399 static GdkVisual*
2400 gdk_window_real_get_visual (GdkDrawable *drawable)
2401 {
2402   GdkColormap *colormap;
2403
2404   g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
2405
2406   colormap = gdk_drawable_get_colormap (drawable);
2407   return colormap ? gdk_colormap_get_visual (colormap) : NULL;
2408 }
2409
2410 static gint
2411 gdk_window_real_get_depth (GdkDrawable *drawable)
2412 {
2413   g_return_val_if_fail (GDK_IS_WINDOW (drawable), 0);
2414
2415   return ((GdkWindowObject *)GDK_WINDOW (drawable))->depth;
2416 }
2417
2418 static GdkScreen*
2419 gdk_window_real_get_screen (GdkDrawable *drawable)
2420 {
2421   return gdk_drawable_get_screen (GDK_WINDOW_OBJECT (drawable)->impl);
2422 }
2423
2424 static void
2425 gdk_window_real_set_colormap (GdkDrawable *drawable,
2426                               GdkColormap *cmap)
2427 {
2428   g_return_if_fail (GDK_IS_WINDOW (drawable));  
2429
2430   if (GDK_WINDOW_DESTROYED (drawable))
2431     return;
2432   
2433   gdk_drawable_set_colormap (((GdkWindowObject*)drawable)->impl, cmap);
2434 }
2435
2436 static GdkColormap*
2437 gdk_window_real_get_colormap (GdkDrawable *drawable)
2438 {
2439   g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
2440
2441   if (GDK_WINDOW_DESTROYED (drawable))
2442     return NULL;
2443   
2444   return gdk_drawable_get_colormap (((GdkWindowObject*)drawable)->impl);
2445 }
2446                       
2447 static GdkImage*
2448 gdk_window_copy_to_image (GdkDrawable     *drawable,
2449                           GdkImage        *image,
2450                           gint             src_x,
2451                           gint             src_y,
2452                           gint             dest_x,
2453                           gint             dest_y,
2454                           gint             width,
2455                           gint             height)
2456 {
2457   GdkWindowObject *private = (GdkWindowObject *) drawable;
2458   gint x_offset, y_offset;
2459   
2460   g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
2461   
2462   if (GDK_WINDOW_DESTROYED (drawable))
2463     return NULL;
2464
2465   /* If we're here, a composite image was not necessary, so
2466    * we can ignore the paint stack.
2467    */
2468   
2469   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_offsets (drawable,
2470                                                           &x_offset, &y_offset);
2471   
2472   return gdk_drawable_copy_to_image (private->impl,
2473                                      image,
2474                                      src_x - x_offset,
2475                                      src_y - y_offset,
2476                                      dest_x, dest_y,
2477                                      width, height);
2478 }
2479
2480 static cairo_surface_t *
2481 gdk_window_ref_cairo_surface (GdkDrawable *drawable)
2482 {
2483   GdkWindowObject *private = (GdkWindowObject*) drawable;
2484   cairo_surface_t *surface;
2485
2486   if (private->paint_stack)
2487     {
2488       GdkWindowPaint *paint = private->paint_stack->data;
2489
2490       surface = paint->surface;
2491       cairo_surface_reference (surface);
2492     }
2493   else
2494     surface = _gdk_drawable_ref_cairo_surface (private->impl);
2495
2496   return surface;
2497 }
2498
2499 /* Code for dirty-region queueing
2500  */
2501 static GSList *update_windows = NULL;
2502 static guint update_idle = 0;
2503 static gboolean debug_updates = FALSE;
2504
2505 static gboolean
2506 gdk_window_update_idle (gpointer data)
2507 {
2508   gdk_window_process_all_updates ();
2509   
2510   return FALSE;
2511 }
2512
2513 static gboolean
2514 gdk_window_is_toplevel_frozen (GdkWindow *window)
2515 {
2516   GdkWindowObject *toplevel;
2517
2518   toplevel = (GdkWindowObject *)gdk_window_get_toplevel (window);
2519
2520   return toplevel->update_and_descendants_freeze_count > 0;
2521 }
2522
2523 static void
2524 gdk_window_schedule_update (GdkWindow *window)
2525 {
2526   if (window &&
2527       (GDK_WINDOW_OBJECT (window)->update_freeze_count ||
2528        gdk_window_is_toplevel_frozen (window)))
2529     return;
2530
2531   if (!update_idle)
2532     {
2533       update_idle = gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
2534                                      gdk_window_update_idle, NULL, NULL);
2535     }
2536 }
2537
2538 static void
2539 gdk_window_process_updates_internal (GdkWindow *window)
2540 {
2541   GdkWindowObject *private = (GdkWindowObject *)window;
2542   gboolean save_region = FALSE;
2543
2544   /* If an update got queued during update processing, we can get a
2545    * window in the update queue that has an empty update_area.
2546    * just ignore it.
2547    */
2548   if (private->update_area)
2549     {
2550       GdkRegion *update_area = private->update_area;
2551       private->update_area = NULL;
2552       
2553       if (_gdk_event_func && gdk_window_is_viewable (window))
2554         {
2555           GdkRectangle window_rect;
2556           GdkRegion *expose_region;
2557           GdkRegion *window_region;
2558           gint width, height;
2559
2560           if (debug_updates)
2561             {
2562               /* Make sure we see the red invalid area before redrawing. */
2563               gdk_display_sync (gdk_drawable_get_display (window));
2564               g_usleep (70000);
2565             }
2566           
2567           save_region = _gdk_windowing_window_queue_antiexpose (window, update_area);
2568
2569           if (save_region)
2570             expose_region = gdk_region_copy (update_area);
2571           else
2572             expose_region = update_area;
2573           
2574           gdk_drawable_get_size (GDK_DRAWABLE (private), &width, &height);
2575
2576           window_rect.x = 0;
2577           window_rect.y = 0;
2578           window_rect.width = width;
2579           window_rect.height = height;
2580
2581           window_region = gdk_region_rectangle (&window_rect);
2582           gdk_region_intersect (expose_region,
2583                                 window_region);
2584           gdk_region_destroy (window_region);
2585           
2586           if (!gdk_region_empty (expose_region) &&
2587               (private->event_mask & GDK_EXPOSURE_MASK))
2588             {
2589               GdkEvent event;
2590               
2591               event.expose.type = GDK_EXPOSE;
2592               event.expose.window = g_object_ref (window);
2593               event.expose.send_event = FALSE;
2594               event.expose.count = 0;
2595               event.expose.region = expose_region;
2596               gdk_region_get_clipbox (expose_region, &event.expose.area);
2597               
2598               (*_gdk_event_func) (&event, _gdk_event_data);
2599               
2600               g_object_unref (window);
2601             }
2602
2603           if (expose_region != update_area)
2604             gdk_region_destroy (expose_region);
2605         }
2606       if (!save_region)
2607         gdk_region_destroy (update_area);
2608     }
2609 }
2610
2611 static void
2612 flush_all_displays (void)
2613 {
2614   GSList *displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
2615   GSList *tmp_list;
2616
2617   for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
2618     gdk_display_flush (tmp_list->data);
2619
2620   g_slist_free (displays);
2621 }
2622
2623 /* Currently it is not possible to override
2624  * gdk_window_process_all_updates in the same manner as
2625  * gdk_window_process_updates and gdk_window_invalidate_maybe_recurse
2626  * by implementing the GdkPaintable interface.  If in the future a
2627  * backend would need this, the right solution would be to add a
2628  * method to GdkDisplay that can be optionally
2629  * NULL. gdk_window_process_all_updates can then walk the list of open
2630  * displays and call the mehod.
2631  */
2632
2633 /**
2634  * gdk_window_process_all_updates:
2635  *
2636  * Calls gdk_window_process_updates() for all windows (see #GdkWindow)
2637  * in the application.
2638  * 
2639  **/
2640 void
2641 gdk_window_process_all_updates (void)
2642 {
2643   GSList *old_update_windows = update_windows;
2644   GSList *tmp_list = update_windows;
2645
2646   if (update_idle)
2647     g_source_remove (update_idle);
2648   
2649   update_windows = NULL;
2650   update_idle = 0;
2651
2652   g_slist_foreach (old_update_windows, (GFunc)g_object_ref, NULL);
2653   
2654   while (tmp_list)
2655     {
2656       GdkWindowObject *private = (GdkWindowObject *)tmp_list->data;
2657       
2658       if (!GDK_WINDOW_DESTROYED (tmp_list->data))
2659         {
2660           if (private->update_freeze_count ||
2661               gdk_window_is_toplevel_frozen (tmp_list->data))
2662             update_windows = g_slist_prepend (update_windows, private);
2663           else
2664             gdk_window_process_updates_internal (tmp_list->data);
2665         }
2666
2667       g_object_unref (tmp_list->data);
2668       tmp_list = tmp_list->next;
2669     }
2670
2671   g_slist_free (old_update_windows);
2672
2673   flush_all_displays ();
2674 }
2675
2676 /**
2677  * gdk_window_process_updates:
2678  * @window: a #GdkWindow
2679  * @update_children: whether to also process updates for child windows
2680  *
2681  * Sends one or more expose events to @window. The areas in each 
2682  * expose event will cover the entire update area for the window (see
2683  * gdk_window_invalidate_region() for details). Normally GDK calls
2684  * gdk_window_process_all_updates() on your behalf, so there's no
2685  * need to call this function unless you want to force expose events
2686  * to be delivered immediately and synchronously (vs. the usual
2687  * case, where GDK delivers them in an idle handler). Occasionally
2688  * this is useful to produce nicer scrolling behavior, for example.
2689  * 
2690  **/
2691 void
2692 gdk_window_process_updates (GdkWindow *window,
2693                             gboolean   update_children)
2694 {
2695   GdkWindowObject *private = (GdkWindowObject *)window;
2696
2697   g_return_if_fail (window != NULL);
2698   g_return_if_fail (GDK_IS_WINDOW (window));
2699   
2700   if (GDK_IS_PAINTABLE (private->impl))
2701     {
2702       GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
2703
2704       if (iface->process_updates)
2705         iface->process_updates ((GdkPaintable*)private->impl, update_children);
2706
2707       return;
2708     }
2709   
2710   if (private->update_area &&
2711       !private->update_freeze_count &&
2712       !gdk_window_is_toplevel_frozen (window))
2713     {      
2714       gdk_window_process_updates_internal (window);
2715       update_windows = g_slist_remove (update_windows, window);
2716     }
2717
2718   if (update_children)
2719     {
2720       GList *tmp_list = private->children;
2721       while (tmp_list)
2722         {
2723           gdk_window_process_updates (tmp_list->data, TRUE);
2724           tmp_list = tmp_list->next;
2725         }
2726     }
2727 }
2728
2729 /**
2730  * gdk_window_invalidate_rect:
2731  * @window: a #GdkWindow
2732  * @rect: rectangle to invalidate or %NULL to invalidate the whole
2733  *      window
2734  * @invalidate_children: whether to also invalidate child windows
2735  *
2736  * A convenience wrapper around gdk_window_invalidate_region() which
2737  * invalidates a rectangular region. See
2738  * gdk_window_invalidate_region() for details.
2739  **/
2740 void
2741 gdk_window_invalidate_rect (GdkWindow          *window,
2742                             const GdkRectangle *rect,
2743                             gboolean            invalidate_children)
2744 {
2745   GdkRectangle window_rect;
2746   GdkRegion *region;
2747   GdkWindowObject *private = (GdkWindowObject *)window;
2748
2749   g_return_if_fail (window != NULL);
2750   g_return_if_fail (GDK_IS_WINDOW (window));
2751
2752   if (GDK_WINDOW_DESTROYED (window))
2753     return;
2754   
2755   if (private->input_only || !GDK_WINDOW_IS_MAPPED (window))
2756     return;
2757
2758   if (!rect)
2759     {
2760       window_rect.x = 0;
2761       window_rect.y = 0;
2762       gdk_drawable_get_size (GDK_DRAWABLE (window),
2763                              &window_rect.width,
2764                              &window_rect.height);
2765       rect = &window_rect;
2766     }
2767
2768   region = gdk_region_rectangle (rect);
2769   gdk_window_invalidate_region (window, region, invalidate_children);
2770   gdk_region_destroy (region);
2771 }
2772
2773 static void
2774 draw_ugly_color (GdkWindow       *window,
2775                  const GdkRegion *region)
2776 {
2777   /* Draw ugly color all over the newly-invalid region */
2778   GdkColor ugly_color = { 0, 50000, 10000, 10000 };
2779   GdkGC *ugly_gc;
2780   GdkRectangle clipbox;
2781     
2782   ugly_gc = gdk_gc_new (window);
2783   gdk_gc_set_rgb_fg_color (ugly_gc, &ugly_color);
2784   gdk_gc_set_clip_region (ugly_gc, region);
2785
2786   gdk_region_get_clipbox (region, &clipbox);
2787   
2788   gdk_draw_rectangle (window,
2789                       ugly_gc,
2790                       TRUE,
2791                       clipbox.x, clipbox.y,
2792                       clipbox.width, clipbox.height);
2793   
2794   g_object_unref (ugly_gc);
2795 }
2796
2797 /**
2798  * gdk_window_invalidate_maybe_recurse:
2799  * @window: a #GdkWindow
2800  * @region: a #GdkRegion
2801  * @child_func: function to use to decide if to recurse to a child,
2802  *              %NULL means never recurse.
2803  * @user_data: data passed to @child_func
2804  *
2805  * Adds @region to the update area for @window. The update area is the
2806  * region that needs to be redrawn, or "dirty region." The call
2807  * gdk_window_process_updates() sends one or more expose events to the
2808  * window, which together cover the entire update area. An
2809  * application would normally redraw the contents of @window in
2810  * response to those expose events.
2811  *
2812  * GDK will call gdk_window_process_all_updates() on your behalf
2813  * whenever your program returns to the main loop and becomes idle, so
2814  * normally there's no need to do that manually, you just need to
2815  * invalidate regions that you know should be redrawn.
2816  *
2817  * The @child_func parameter controls whether the region of
2818  * each child window that intersects @region will also be invalidated.
2819  * Only children for which @child_func returns TRUE will have the area
2820  * invalidated.
2821  **/
2822 void
2823 gdk_window_invalidate_maybe_recurse (GdkWindow       *window,
2824                                      const GdkRegion *region,
2825                                      gboolean       (*child_func) (GdkWindow *,
2826                                                                    gpointer),
2827                                      gpointer   user_data)
2828 {
2829   GdkWindowObject *private = (GdkWindowObject *)window;
2830   GdkRegion *visible_region;
2831   GList *tmp_list;
2832
2833   g_return_if_fail (window != NULL);
2834   g_return_if_fail (GDK_IS_WINDOW (window));
2835
2836   if (GDK_WINDOW_DESTROYED (window))
2837     return;
2838   
2839   if (private->input_only || !GDK_WINDOW_IS_MAPPED (window))
2840     return;
2841
2842   if (GDK_IS_PAINTABLE (private->impl))
2843     {
2844       GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
2845
2846       if (iface->invalidate_maybe_recurse)
2847         iface->invalidate_maybe_recurse ((GdkPaintable*)private->impl, 
2848                                          region, child_func, user_data);
2849       return;
2850     }
2851
2852   /* windows that a redirection has ben setup for need to be considered
2853    * fully visible, in order to avoid missing redirected paint ops
2854    * anywhere in the window area.
2855    */
2856   if (private->redirect && private->redirect->redirected == private)
2857     {
2858       GdkRectangle visible_rect = { 0, 0, 0, 0 };
2859       gdk_drawable_get_size (GDK_DRAWABLE (window), &visible_rect.width, &visible_rect.height);
2860       visible_region = gdk_region_rectangle (&visible_rect);
2861     }
2862   else
2863     visible_region = gdk_drawable_get_visible_region (window);
2864   gdk_region_intersect (visible_region, region);
2865
2866   tmp_list = private->children;
2867   while (tmp_list)
2868     {
2869       GdkWindowObject *child = tmp_list->data;
2870       
2871       if (!child->input_only)
2872         {
2873           GdkRegion *child_region;
2874           GdkRectangle child_rect;
2875           
2876           gdk_window_get_position ((GdkWindow *)child,
2877                                    &child_rect.x, &child_rect.y);
2878           gdk_drawable_get_size ((GdkDrawable *)child,
2879                                  &child_rect.width, &child_rect.height);
2880
2881           child_region = gdk_region_rectangle (&child_rect);
2882           
2883           /* remove child area from the invalid area of the parent */
2884           if (GDK_WINDOW_IS_MAPPED (child) && !child->shaped &&
2885               !child->composited)
2886             gdk_region_subtract (visible_region, child_region);
2887           
2888           if (child_func && (*child_func) ((GdkWindow *)child, user_data))
2889             {
2890               GdkRegion *tmp = gdk_region_copy (region);
2891
2892               gdk_region_offset (tmp, - child_rect.x, - child_rect.y);
2893               gdk_region_offset (child_region, - child_rect.x, - child_rect.y);
2894               gdk_region_intersect (child_region, tmp);
2895               
2896               gdk_window_invalidate_maybe_recurse ((GdkWindow *)child,
2897                                                    child_region, child_func, user_data);
2898               
2899               gdk_region_destroy (tmp);
2900             }
2901
2902           gdk_region_destroy (child_region);
2903         }
2904
2905       tmp_list = tmp_list->next;
2906     }
2907   
2908   if (!gdk_region_empty (visible_region))
2909     {
2910       if (debug_updates)
2911         draw_ugly_color (window, region);
2912
2913       if (private->update_area)
2914         {
2915           gdk_region_union (private->update_area, visible_region);
2916         }
2917       else
2918         {
2919           update_windows = g_slist_prepend (update_windows, window);
2920           private->update_area = gdk_region_copy (visible_region);
2921           
2922           gdk_window_schedule_update (window);
2923         }
2924     }
2925   
2926   gdk_region_destroy (visible_region);
2927 }
2928
2929 static gboolean
2930 true_predicate (GdkWindow *window,
2931                 gpointer   user_data)
2932 {
2933   return TRUE;
2934 }
2935
2936 /**
2937  * gdk_window_invalidate_region:
2938  * @window: a #GdkWindow
2939  * @region: a #GdkRegion
2940  * @invalidate_children: %TRUE to also invalidate child windows 
2941  *
2942  * Adds @region to the update area for @window. The update area is the
2943  * region that needs to be redrawn, or "dirty region." The call
2944  * gdk_window_process_updates() sends one or more expose events to the
2945  * window, which together cover the entire update area. An
2946  * application would normally redraw the contents of @window in
2947  * response to those expose events.
2948  *
2949  * GDK will call gdk_window_process_all_updates() on your behalf
2950  * whenever your program returns to the main loop and becomes idle, so
2951  * normally there's no need to do that manually, you just need to
2952  * invalidate regions that you know should be redrawn.
2953  *
2954  * The @invalidate_children parameter controls whether the region of
2955  * each child window that intersects @region will also be invalidated.
2956  * If %FALSE, then the update area for child windows will remain
2957  * unaffected. See gdk_window_invalidate_maybe_recurse if you need
2958  * fine grained control over which children are invalidated.
2959  **/
2960 void
2961 gdk_window_invalidate_region (GdkWindow       *window,
2962                               const GdkRegion *region,
2963                               gboolean         invalidate_children)
2964 {
2965   gdk_window_invalidate_maybe_recurse (window, region,
2966                                        invalidate_children ?
2967                                          true_predicate : (gboolean (*) (GdkWindow *, gpointer))NULL,
2968                                        NULL);
2969 }
2970
2971 /**
2972  * gdk_window_get_update_area:
2973  * @window: a #GdkWindow
2974  * 
2975  * Transfers ownership of the update area from @window to the caller
2976  * of the function. That is, after calling this function, @window will
2977  * no longer have an invalid/dirty region; the update area is removed
2978  * from @window and handed to you. If a window has no update area,
2979  * gdk_window_get_update_area() returns %NULL. You are responsible for
2980  * calling gdk_region_destroy() on the returned region if it's non-%NULL.
2981  * 
2982  * Return value: the update area for @window
2983  **/
2984 GdkRegion *
2985 gdk_window_get_update_area (GdkWindow *window)
2986 {
2987   GdkWindowObject *private = (GdkWindowObject *)window;
2988   GdkRegion *tmp_region;
2989
2990   g_return_val_if_fail (window != NULL, NULL);
2991   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2992
2993   if (private->update_area)
2994     {
2995       tmp_region = private->update_area;
2996       private->update_area = NULL;
2997
2998       update_windows = g_slist_remove (update_windows, window);
2999       
3000       return tmp_region;
3001     }
3002   else
3003     return NULL;
3004 }
3005
3006 /**
3007  * _gdk_window_clear_update_area:
3008  * @window: a #GdkWindow.
3009  * 
3010  * Internal function to clear the update area for a window. This
3011  * is called when the window is hidden or destroyed.
3012  **/
3013 void
3014 _gdk_window_clear_update_area (GdkWindow *window)
3015 {
3016   GdkWindowObject *private = (GdkWindowObject *)window;
3017
3018   g_return_if_fail (window != NULL);
3019   g_return_if_fail (GDK_IS_WINDOW (window));
3020
3021   if (private->update_area)
3022     {
3023       update_windows = g_slist_remove (update_windows, window);
3024       
3025       gdk_region_destroy (private->update_area);
3026       private->update_area = NULL;
3027     }
3028 }
3029
3030 /**
3031  * gdk_window_freeze_updates:
3032  * @window: a #GdkWindow
3033  * 
3034  * Temporarily freezes a window such that it won't receive expose
3035  * events.  The window will begin receiving expose events again when
3036  * gdk_window_thaw_updates() is called. If gdk_window_freeze_updates()
3037  * has been called more than once, gdk_window_thaw_updates() must be called
3038  * an equal number of times to begin processing exposes.
3039  **/
3040 void
3041 gdk_window_freeze_updates (GdkWindow *window)
3042 {
3043   GdkWindowObject *private = (GdkWindowObject *)window;
3044
3045   g_return_if_fail (window != NULL);
3046   g_return_if_fail (GDK_IS_WINDOW (window));
3047
3048   private->update_freeze_count++;
3049 }
3050
3051 /**
3052  * gdk_window_thaw_updates:
3053  * @window: a #GdkWindow
3054  * 
3055  * Thaws a window frozen with gdk_window_freeze_updates().
3056  **/
3057 void
3058 gdk_window_thaw_updates (GdkWindow *window)
3059 {
3060   GdkWindowObject *private = (GdkWindowObject *)window;
3061
3062   g_return_if_fail (window != NULL);
3063   g_return_if_fail (GDK_IS_WINDOW (window));
3064   g_return_if_fail (private->update_freeze_count > 0);
3065
3066   if (--private->update_freeze_count == 0)
3067     gdk_window_schedule_update (window);
3068 }
3069
3070 /**
3071  * gdk_window_freeze_toplevel_updates_libgtk_only:
3072  * @window: a #GdkWindow
3073  *
3074  * Temporarily freezes a window and all its descendants such that it won't
3075  * receive expose events.  The window will begin receiving expose events
3076  * again when gdk_window_thaw_toplevel_updates_libgtk_only() is called. If
3077  * gdk_window_freeze_toplevel_updates_libgtk_only()
3078  * has been called more than once,
3079  * gdk_window_thaw_toplevel_updates_libgtk_only() must be called
3080  * an equal number of times to begin processing exposes.
3081  *
3082  * This function is not part of the GDK public API and is only
3083  * for use by GTK+.
3084  **/
3085 void
3086 gdk_window_freeze_toplevel_updates_libgtk_only (GdkWindow *window)
3087 {
3088   GdkWindowObject *private = (GdkWindowObject *)window;
3089
3090   g_return_if_fail (window != NULL);
3091   g_return_if_fail (GDK_IS_WINDOW (window));
3092   g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
3093
3094   private->update_and_descendants_freeze_count++;
3095 }
3096
3097 /**
3098  * gdk_window_thaw_toplevel_updates_libgtk_only:
3099  * @window: a #GdkWindow
3100  * 
3101  * Thaws a window frozen with
3102  * gdk_window_freeze_toplevel_updates_libgtk_only().
3103  *
3104  * This function is not part of the GDK public API and is only
3105  * for use by GTK+.
3106  **/
3107 void
3108 gdk_window_thaw_toplevel_updates_libgtk_only (GdkWindow *window)
3109 {
3110   GdkWindowObject *private = (GdkWindowObject *)window;
3111
3112   g_return_if_fail (window != NULL);
3113   g_return_if_fail (GDK_IS_WINDOW (window));
3114   g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
3115   g_return_if_fail (private->update_and_descendants_freeze_count > 0);
3116
3117   private->update_and_descendants_freeze_count--;
3118
3119   gdk_window_schedule_update (window);
3120 }
3121
3122 /**
3123  * gdk_window_set_debug_updates:
3124  * @setting: %TRUE to turn on update debugging
3125  *
3126  * With update debugging enabled, calls to
3127  * gdk_window_invalidate_region() clear the invalidated region of the
3128  * screen to a noticeable color, and GDK pauses for a short time
3129  * before sending exposes to windows during
3130  * gdk_window_process_updates().  The net effect is that you can see
3131  * the invalid region for each window and watch redraws as they
3132  * occur. This allows you to diagnose inefficiencies in your application.
3133  *
3134  * In essence, because the GDK rendering model prevents all flicker,
3135  * if you are redrawing the same region 400 times you may never
3136  * notice, aside from noticing a speed problem. Enabling update
3137  * debugging causes GTK to flicker slowly and noticeably, so you can
3138  * see exactly what's being redrawn when, in what order.
3139  *
3140  * The --gtk-debug=updates command line option passed to GTK+ programs
3141  * enables this debug option at application startup time. That's
3142  * usually more useful than calling gdk_window_set_debug_updates()
3143  * yourself, though you might want to use this function to enable
3144  * updates sometime after application startup time.
3145  * 
3146  **/
3147 void
3148 gdk_window_set_debug_updates (gboolean setting)
3149 {
3150   debug_updates = setting;
3151 }
3152
3153 /**
3154  * gdk_window_constrain_size:
3155  * @geometry: a #GdkGeometry structure
3156  * @flags: a mask indicating what portions of @geometry are set
3157  * @width: desired width of window
3158  * @height: desired height of the window
3159  * @new_width: location to store resulting width
3160  * @new_height: location to store resulting height
3161  * 
3162  * Constrains a desired width and height according to a 
3163  * set of geometry hints (such as minimum and maximum size).
3164  */
3165 void
3166 gdk_window_constrain_size (GdkGeometry *geometry,
3167                            guint        flags,
3168                            gint         width,
3169                            gint         height,
3170                            gint        *new_width,
3171                            gint        *new_height)
3172 {
3173   /* This routine is partially borrowed from fvwm.
3174    *
3175    * Copyright 1993, Robert Nation
3176    *     You may use this code for any purpose, as long as the original
3177    *     copyright remains in the source code and all documentation
3178    *
3179    * which in turn borrows parts of the algorithm from uwm
3180    */
3181   gint min_width = 0;
3182   gint min_height = 0;
3183   gint base_width = 0;
3184   gint base_height = 0;
3185   gint xinc = 1;
3186   gint yinc = 1;
3187   gint max_width = G_MAXINT;
3188   gint max_height = G_MAXINT;
3189   
3190 #define FLOOR(value, base)      ( ((gint) ((value) / (base))) * (base) )
3191
3192   if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
3193     {
3194       base_width = geometry->base_width;
3195       base_height = geometry->base_height;
3196       min_width = geometry->min_width;
3197       min_height = geometry->min_height;
3198     }
3199   else if (flags & GDK_HINT_BASE_SIZE)
3200     {
3201       base_width = geometry->base_width;
3202       base_height = geometry->base_height;
3203       min_width = geometry->base_width;
3204       min_height = geometry->base_height;
3205     }
3206   else if (flags & GDK_HINT_MIN_SIZE)
3207     {
3208       base_width = geometry->min_width;
3209       base_height = geometry->min_height;
3210       min_width = geometry->min_width;
3211       min_height = geometry->min_height;
3212     }
3213
3214   if (flags & GDK_HINT_MAX_SIZE)
3215     {
3216       max_width = geometry->max_width ;
3217       max_height = geometry->max_height;
3218     }
3219
3220   if (flags & GDK_HINT_RESIZE_INC)
3221     {
3222       xinc = MAX (xinc, geometry->width_inc);
3223       yinc = MAX (yinc, geometry->height_inc);
3224     }
3225   
3226   /* clamp width and height to min and max values
3227    */
3228   width = CLAMP (width, min_width, max_width);
3229   height = CLAMP (height, min_height, max_height);
3230   
3231   /* shrink to base + N * inc
3232    */
3233   width = base_width + FLOOR (width - base_width, xinc);
3234   height = base_height + FLOOR (height - base_height, yinc);
3235
3236   /* constrain aspect ratio, according to:
3237    *
3238    *                width     
3239    * min_aspect <= -------- <= max_aspect
3240    *                height    
3241    */
3242   
3243   if (flags & GDK_HINT_ASPECT &&
3244       geometry->min_aspect > 0 &&
3245       geometry->max_aspect > 0)
3246     {
3247       gint delta;
3248
3249       if (geometry->min_aspect * height > width)
3250         {
3251           delta = FLOOR (height - width / geometry->min_aspect, yinc);
3252           if (height - delta >= min_height)
3253             height -= delta;
3254           else
3255             { 
3256               delta = FLOOR (height * geometry->min_aspect - width, xinc);
3257               if (width + delta <= max_width) 
3258                 width += delta;
3259             }
3260         }
3261       
3262       if (geometry->max_aspect * height < width)
3263         {
3264           delta = FLOOR (width - height * geometry->max_aspect, xinc);
3265           if (width - delta >= min_width) 
3266             width -= delta;
3267           else
3268             {
3269               delta = FLOOR (width / geometry->max_aspect - height, yinc);
3270               if (height + delta <= max_height)
3271                 height += delta;
3272             }
3273         }
3274     }
3275
3276 #undef FLOOR
3277   
3278   *new_width = width;
3279   *new_height = height;
3280 }
3281
3282 /**
3283  * gdk_window_get_pointer:
3284  * @window: a #GdkWindow
3285  * @x: return location for X coordinate of pointer or %NULL to not
3286  *      return the X coordinate
3287  * @y: return location for Y coordinate of pointer or %NULL to not
3288  *      return the Y coordinate
3289  * @mask: return location for modifier mask or %NULL to not return the
3290  *      modifier mask
3291  *
3292  * Obtains the current pointer position and modifier state.
3293  * The position is given in coordinates relative to the upper left 
3294  * corner of @window.
3295  * 
3296  * Return value: the window containing the pointer (as with
3297  * gdk_window_at_pointer()), or %NULL if the window containing the
3298  * pointer isn't known to GDK
3299  **/
3300 GdkWindow*
3301 gdk_window_get_pointer (GdkWindow         *window,
3302                         gint              *x,
3303                         gint              *y,
3304                         GdkModifierType   *mask)
3305 {
3306   GdkDisplay *display;
3307   gint tmp_x, tmp_y;
3308   GdkModifierType tmp_mask;
3309   GdkWindow *child;
3310   
3311   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
3312
3313   if (window)
3314     {
3315       display = gdk_drawable_get_display (window);
3316     }
3317   else
3318     {
3319       GdkScreen *screen = gdk_screen_get_default ();
3320
3321       display = gdk_screen_get_display (screen);
3322       window = gdk_screen_get_root_window (screen);
3323       
3324       GDK_NOTE (MULTIHEAD,
3325                 g_message ("Passing NULL for window to gdk_window_get_pointer()\n"
3326                            "is not multihead safe"));
3327     }
3328
3329   child = display->pointer_hooks->window_get_pointer (display, window, &tmp_x, &tmp_y, &tmp_mask);
3330
3331   if (x)
3332     *x = tmp_x;
3333   if (y)
3334     *y = tmp_y;
3335   if (mask)
3336     *mask = tmp_mask;
3337
3338   return child;
3339 }
3340
3341 /**
3342  * gdk_window_at_pointer:
3343  * @win_x: return location for origin of the window under the pointer
3344  * @win_y: return location for origin of the window under the pointer
3345  * 
3346  * Obtains the window underneath the mouse pointer, returning the
3347  * location of that window in @win_x, @win_y. Returns %NULL if the
3348  * window under the mouse pointer is not known to GDK (if the window
3349  * belongs to another application and a #GdkWindow hasn't been created
3350  * for it with gdk_window_foreign_new())
3351  *
3352  * NOTE: For multihead-aware widgets or applications use
3353  * gdk_display_get_window_at_pointer() instead.
3354  * 
3355  * Return value: window under the mouse pointer
3356  **/
3357 GdkWindow*
3358 gdk_window_at_pointer (gint *win_x,
3359                        gint *win_y)
3360 {
3361   return gdk_display_get_window_at_pointer (gdk_display_get_default (), win_x, win_y);
3362 }
3363
3364 /**
3365  * gdk_get_default_root_window:
3366  * 
3367  * Obtains the root window (parent all other windows are inside)
3368  * for the default display and screen.
3369  * 
3370  * Return value: the default root window
3371  **/
3372 GdkWindow *
3373 gdk_get_default_root_window (void)
3374 {
3375   return gdk_screen_get_root_window (gdk_screen_get_default ());
3376 }
3377
3378 /**
3379  * gdk_window_foreign_new:
3380  * @anid: a native window handle.
3381  * 
3382  * Wraps a native window for the default display in a #GdkWindow.
3383  * This may fail if the window has been destroyed.
3384  *
3385  * For example in the X backend, a native window handle is an Xlib
3386  * <type>XID</type>.
3387  * 
3388  * Return value: the newly-created #GdkWindow wrapper for the 
3389  *    native window or %NULL if the window has been destroyed.
3390  **/
3391 GdkWindow *
3392 gdk_window_foreign_new (GdkNativeWindow anid)
3393 {
3394   return gdk_window_foreign_new_for_display (gdk_display_get_default (), anid);
3395 }
3396
3397 /**
3398  * gdk_window_show_unraised:
3399  * @window: a #GdkWindow
3400  *
3401  * Shows a #GdkWindow onscreen, but does not modify its stacking
3402  * order. In contrast, gdk_window_show() will raise the window
3403  * to the top of the window stack.
3404  *
3405  * On the X11 platform, in Xlib terms, this function calls
3406  * XMapWindow() (it also updates some internal GDK state, which means
3407  * that you can't really use XMapWindow() directly on a GDK window).
3408  */
3409 void
3410 gdk_window_show_unraised (GdkWindow *window)
3411 {
3412   GdkWindowObject *private;
3413
3414   g_return_if_fail (GDK_IS_WINDOW (window));
3415
3416   private = (GdkWindowObject *) window;
3417   if (private->destroyed)
3418     return;
3419
3420   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show (window, FALSE);
3421 }
3422
3423 static inline void
3424 gdk_window_raise_internal (GdkWindow *window)
3425 {
3426   GdkWindowObject *private = (GdkWindowObject *)window;
3427   GdkWindowObject *parent = private->parent;
3428
3429   if (parent)
3430     {
3431       parent->children = g_list_remove (parent->children, window);
3432       parent->children = g_list_prepend (parent->children, window);
3433     }
3434 }
3435
3436 /**
3437  * gdk_window_raise:
3438  * @window: a #GdkWindow
3439  *
3440  * Raises @window to the top of the Z-order (stacking order), so that
3441  * other windows with the same parent window appear below @window.
3442  * This is true whether or not the windows are visible.
3443  *
3444  * If @window is a toplevel, the window manager may choose to deny the
3445  * request to move the window in the Z-order, gdk_window_raise() only
3446  * requests the restack, does not guarantee it.
3447  */
3448 void
3449 gdk_window_raise (GdkWindow *window)
3450 {
3451   GdkWindowObject *private;
3452
3453   g_return_if_fail (GDK_IS_WINDOW (window));
3454
3455   private = (GdkWindowObject *) window;
3456   if (private->destroyed)
3457     return;
3458
3459   /* Keep children in (reverse) stacking order */
3460   gdk_window_raise_internal (window);
3461
3462   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
3463 }
3464
3465 static void
3466 gdk_window_lower_internal (GdkWindow *window)
3467 {
3468   GdkWindowObject *private = (GdkWindowObject *)window;
3469   GdkWindowObject *parent = private->parent;
3470
3471   if (parent)
3472     {
3473       parent->children = g_list_remove (parent->children, window);
3474       parent->children = g_list_append (parent->children, window);
3475     }
3476 }
3477
3478 /**
3479  * gdk_window_lower:
3480  * @window: a #GdkWindow
3481  *
3482  * Lowers @window to the bottom of the Z-order (stacking order), so that
3483  * other windows with the same parent window appear above @window.
3484  * This is true whether or not the other windows are visible.
3485  *
3486  * If @window is a toplevel, the window manager may choose to deny the
3487  * request to move the window in the Z-order, gdk_window_lower() only
3488  * requests the restack, does not guarantee it.
3489  *
3490  * Note that gdk_window_show() raises the window again, so don't call this
3491  * function before gdk_window_show(). (Try gdk_window_show_unraised().)
3492  */
3493 void
3494 gdk_window_lower (GdkWindow *window)
3495 {
3496   GdkWindowObject *private;
3497
3498   g_return_if_fail (GDK_IS_WINDOW (window));
3499
3500   private = (GdkWindowObject *) window;
3501   if (private->destroyed)
3502     return;
3503
3504   /* Keep children in (reverse) stacking order */
3505   gdk_window_lower_internal (window);
3506
3507   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->lower (window);
3508 }
3509
3510 /**
3511  * gdk_window_show:
3512  * @window: a #GdkWindow
3513  *
3514  * Like gdk_window_show_unraised(), but also raises the window to the
3515  * top of the window stack (moves the window to the front of the
3516  * Z-order).
3517  *
3518  * This function maps a window so it's visible onscreen. Its opposite
3519  * is gdk_window_hide().
3520  *
3521  * When implementing a #GtkWidget, you should call this function on the widget's
3522  * #GdkWindow as part of the "map" method.
3523  */
3524 void
3525 gdk_window_show (GdkWindow *window)
3526 {
3527   GdkWindowObject *private;
3528
3529   g_return_if_fail (GDK_IS_WINDOW (window));
3530
3531   private = (GdkWindowObject *) window;
3532   if (private->destroyed)
3533     return;
3534
3535   /* Keep children in (reverse) stacking order */
3536   gdk_window_raise_internal (window);
3537
3538   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show (window, TRUE);
3539 }
3540
3541 /**
3542  * gdk_window_hide:
3543  * @window: a #GdkWindow
3544  *
3545  * For toplevel windows, withdraws them, so they will no longer be
3546  * known to the window manager; for all windows, unmaps them, so
3547  * they won't be displayed. Normally done automatically as
3548  * part of gtk_widget_hide().
3549  */
3550 void
3551 gdk_window_hide (GdkWindow *window)
3552 {
3553   GdkWindowObject *private;
3554
3555   g_return_if_fail (GDK_IS_WINDOW (window));
3556
3557   private = (GdkWindowObject *) window;
3558   if (private->destroyed)
3559     return;
3560
3561   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->hide (window);
3562 }
3563
3564 /**
3565  * gdk_window_withdraw:
3566  * @window: a toplevel #GdkWindow
3567  *
3568  * Withdraws a window (unmaps it and asks the window manager to forget about it).
3569  * This function is not really useful as gdk_window_hide() automatically
3570  * withdraws toplevel windows before hiding them.
3571  **/
3572 void
3573 gdk_window_withdraw (GdkWindow *window)
3574 {
3575   GdkWindowObject *private;
3576
3577   g_return_if_fail (GDK_IS_WINDOW (window));
3578
3579   private = (GdkWindowObject *) window;
3580   if (private->destroyed)
3581     return;
3582
3583   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->withdraw (window);
3584 }
3585
3586 /**
3587  * gdk_window_set_events:
3588  * @window: a #GdkWindow
3589  * @event_mask: event mask for @window
3590  *
3591  * The event mask for a window determines which events will be reported
3592  * for that window. For example, an event mask including #GDK_BUTTON_PRESS_MASK
3593  * means the window should report button press events. The event mask
3594  * is the bitwise OR of values from the #GdkEventMask enumeration.
3595  **/
3596 void
3597 gdk_window_set_events (GdkWindow       *window,
3598                        GdkEventMask     event_mask)
3599 {
3600   GdkWindowObject *private;
3601
3602   g_return_if_fail (GDK_IS_WINDOW (window));
3603
3604   private = (GdkWindowObject *) window;
3605   if (private->destroyed)
3606     return;
3607
3608   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_events (window, event_mask);
3609 }
3610
3611 /**
3612  * gdk_window_get_events:
3613  * @window: a #GdkWindow
3614  *
3615  * Gets the event mask for @window. See gdk_window_set_events().
3616  *
3617  * Return value: event mask for @window
3618  **/
3619 GdkEventMask
3620 gdk_window_get_events (GdkWindow *window)
3621 {
3622   GdkWindowObject *private;
3623
3624   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
3625
3626   private = (GdkWindowObject *) window;
3627   if (private->destroyed)
3628     return 0;
3629
3630   return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_events (window);
3631 }
3632
3633 /**
3634  * gdk_window_move:
3635  * @window: a #GdkWindow
3636  * @x: X coordinate relative to window's parent
3637  * @y: Y coordinate relative to window's parent
3638  *
3639  * Repositions a window relative to its parent window.
3640  * For toplevel windows, window managers may ignore or modify the move;
3641  * you should probably use gtk_window_move() on a #GtkWindow widget
3642  * anyway, instead of using GDK functions. For child windows,
3643  * the move will reliably succeed.
3644  *
3645  * If you're also planning to resize the window, use gdk_window_move_resize()
3646  * to both move and resize simultaneously, for a nicer visual effect.
3647  **/
3648 void
3649 gdk_window_move (GdkWindow *window,
3650                  gint       x,
3651                  gint       y)
3652 {
3653   GdkWindowObject *private;
3654
3655   g_return_if_fail (GDK_IS_WINDOW (window));
3656
3657   private = (GdkWindowObject *) window;
3658   if (private->destroyed)
3659     return;
3660
3661   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, TRUE, x, y, -1, -1);
3662 }
3663
3664 /**
3665  * gdk_window_resize:
3666  * @window: a #GdkWindow
3667  * @width: new width of the window
3668  * @height: new height of the window
3669  *
3670  * Resizes @window; for toplevel windows, asks the window manager to resize
3671  * the window. The window manager may not allow the resize. When using GTK+,
3672  * use gtk_window_resize() instead of this low-level GDK function.
3673  *
3674  * Windows may not be resized below 1x1.
3675  *
3676  * If you're also planning to move the window, use gdk_window_move_resize()
3677  * to both move and resize simultaneously, for a nicer visual effect.
3678  **/
3679 void
3680 gdk_window_resize (GdkWindow *window,
3681                    gint       width,
3682                    gint       height)
3683 {
3684   GdkWindowObject *private;
3685
3686   g_return_if_fail (GDK_IS_WINDOW (window));
3687
3688   private = (GdkWindowObject *) window;
3689   if (private->destroyed)
3690     return;
3691
3692   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, FALSE, 0, 0, width, height);
3693 }
3694
3695
3696 /**
3697  * gdk_window_move_resize:
3698  * @window: a #GdkWindow
3699  * @x: new X position relative to window's parent
3700  * @y: new Y position relative to window's parent
3701  * @width: new width
3702  * @height: new height
3703  *
3704  * Equivalent to calling gdk_window_move() and gdk_window_resize(),
3705  * except that both operations are performed at once, avoiding strange
3706  * visual effects. (i.e. the user may be able to see the window first
3707  * move, then resize, if you don't use gdk_window_move_resize().)
3708  **/
3709 void
3710 gdk_window_move_resize (GdkWindow *window,
3711                         gint       x,
3712                         gint       y,
3713                         gint       width,
3714                         gint       height)
3715 {
3716   GdkWindowObject *private;
3717
3718   g_return_if_fail (GDK_IS_WINDOW (window));
3719
3720   private = (GdkWindowObject *) window;
3721   if (private->destroyed)
3722     return;
3723
3724   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, TRUE, x, y, width, height);
3725 }
3726
3727
3728 /**
3729  * gdk_window_scroll:
3730  * @window: a #GdkWindow
3731  * @dx: Amount to scroll in the X direction
3732  * @dy: Amount to scroll in the Y direction
3733  *
3734  * Scroll the contents of @window, both pixels and children, by the
3735  * given amount. @window itself does not move. Portions of the window
3736  * that the scroll operation brings in from offscreen areas are
3737  * invalidated. The invalidated region may be bigger than what would
3738  * strictly be necessary.
3739  *
3740  * For X11, a minimum area will be invalidated if the window has no
3741  * subwindows, or if the edges of the window's parent do not extend
3742  * beyond the edges of the window. In other cases, a multi-step process
3743  * is used to scroll the window which may produce temporary visual
3744  * artifacts and unnecessary invalidations.
3745  **/
3746 void
3747 gdk_window_scroll (GdkWindow *window,
3748                    gint       dx,
3749                    gint       dy)
3750 {
3751   GdkWindowObject *private = (GdkWindowObject *) window;
3752
3753   g_return_if_fail (GDK_IS_WINDOW (window));
3754
3755   if (dx == 0 && dy == 0)
3756     return;
3757
3758   if (private->destroyed)
3759     return;
3760
3761   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->scroll (window, dx, dy);
3762 }
3763
3764 /**
3765  * gdk_window_move_region:
3766  * @window: a #GdkWindow
3767  * @region: The #GdkRegion to move
3768  * @dx: Amount to move in the X direction
3769  * @dy: Amount to move in the Y direction
3770  *
3771  * Move the part of @window indicated by @region by @dy pixels in the Y
3772  * direction and @dx pixels in the X direction. The portions of @region
3773  * that not covered by the new position of @region are invalidated.
3774  *
3775  * Child windows are not moved.
3776  *
3777  * Since: 2.8
3778  */
3779 void
3780 gdk_window_move_region (GdkWindow       *window,
3781                         const GdkRegion *region,
3782                         gint             dx,
3783                         gint             dy)
3784 {
3785   GdkWindowObject *private = (GdkWindowObject *) window;
3786
3787   g_return_if_fail (GDK_IS_WINDOW (window));
3788   g_return_if_fail (region != NULL);
3789
3790   if (dx == 0 && dy == 0)
3791     return;
3792
3793   if (private->destroyed)
3794     return;
3795
3796   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_region (window, region, dx, dy);
3797 }
3798
3799 /**
3800  * gdk_window_set_background:
3801  * @window: a #GdkWindow
3802  * @color: an allocated #GdkColor
3803  *
3804  * Sets the background color of @window. (However, when using GTK+,
3805  * set the background of a widget with gtk_widget_modify_bg() - if
3806  * you're an application - or gtk_style_set_background() - if you're
3807  * implementing a custom widget.)
3808  *
3809  * The @color must be allocated; gdk_rgb_find_color() is the best way
3810  * to allocate a color.
3811  *
3812  * See also gdk_window_set_back_pixmap().
3813  */
3814 void
3815 gdk_window_set_background (GdkWindow      *window,
3816                            const GdkColor *color)
3817 {
3818   GdkWindowObject *private;
3819
3820   g_return_if_fail (GDK_IS_WINDOW (window));
3821
3822   private = (GdkWindowObject *) window;
3823
3824   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, color);
3825 }
3826
3827 /**
3828  * gdk_window_set_back_pixmap:
3829  * @window: a #GdkWindow
3830  * @pixmap: a #GdkPixmap, or %NULL
3831  * @parent_relative: whether the tiling origin is at the origin of
3832  *   @window's parent
3833  *
3834  * Sets the background pixmap of @window. May also be used to set a
3835  * background of "None" on @window, by setting a background pixmap
3836  * of %NULL.
3837  *
3838  * A background pixmap will be tiled, positioning the first tile at
3839  * the origin of @window, or if @parent_relative is %TRUE, the tiling
3840  * will be done based on the origin of the parent window (useful to
3841  * align tiles in a parent with tiles in a child).
3842  *
3843  * A background pixmap of %NULL means that the window will have no
3844  * background.  A window with no background will never have its
3845  * background filled by the windowing system, instead the window will
3846  * contain whatever pixels were already in the corresponding area of
3847  * the display.
3848  *
3849  * The windowing system will normally fill a window with its background
3850  * when the window is obscured then exposed, and when you call
3851  * gdk_window_clear().
3852  */
3853 void
3854 gdk_window_set_back_pixmap (GdkWindow *window,
3855                             GdkPixmap *pixmap,
3856                             gboolean   parent_relative)
3857 {
3858   GdkWindowObject *private;
3859
3860   g_return_if_fail (GDK_IS_WINDOW (window));
3861   g_return_if_fail (pixmap == NULL || !parent_relative);
3862   g_return_if_fail (pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap));
3863
3864   private = (GdkWindowObject *) window;
3865
3866   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, pixmap, parent_relative);
3867 }
3868
3869 /**
3870  * gdk_window_set_cursor:
3871  * @window: a #GdkWindow
3872  * @cursor: a cursor
3873  *
3874  * Sets the mouse pointer for a #GdkWindow. Use gdk_cursor_new() or
3875  * gdk_cursor_new_from_pixmap() to create the cursor.
3876  * To make the cursor invisible, use gdk_cursor_new_from_pixmap() to create
3877  * a cursor with no pixels in it. Passing %NULL for the @cursor argument
3878  * to gdk_window_set_cursor() means that @window will use the cursor of
3879  * its parent window. Most windows should use this default.
3880  */
3881 void
3882 gdk_window_set_cursor (GdkWindow *window,
3883                        GdkCursor *cursor)
3884 {
3885   GdkWindowObject *private;
3886
3887   g_return_if_fail (GDK_IS_WINDOW (window));
3888
3889   private = (GdkWindowObject *) window;
3890
3891   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_cursor (window, cursor);
3892 }
3893
3894 /**
3895  * gdk_window_get_geometry:
3896  * @window: a #GdkWindow
3897  * @x: return location for X coordinate of window (relative to its parent)
3898  * @y: return location for Y coordinate of window (relative to its parent)
3899  * @width: return location for width of window
3900  * @height: return location for height of window
3901  * @depth: return location for bit depth of window
3902  *
3903  * Any of the return location arguments to this function may be %NULL,
3904  * if you aren't interested in getting the value of that field.
3905  *
3906  * The X and Y coordinates returned are relative to the parent window
3907  * of @window, which for toplevels usually means relative to the
3908  * window decorations (titlebar, etc.) rather than relative to the
3909  * root window (screen-size background window).
3910  *
3911  * On the X11 platform, the geometry is obtained from the X server,
3912  * so reflects the latest position of @window; this may be out-of-sync
3913  * with the position of @window delivered in the most-recently-processed
3914  * #GdkEventConfigure. gdk_window_get_position() in contrast gets the
3915  * position from the most recent configure event.
3916  *
3917  * <note>
3918  * If @window is not a toplevel, it is <emphasis>much</emphasis> better
3919  * to call gdk_window_get_position() and gdk_drawable_get_size() instead,
3920  * because it avoids the roundtrip to the X server and because
3921  * gdk_drawable_get_size() supports the full 32-bit coordinate space,
3922  * whereas gdk_window_get_geometry() is restricted to the 16-bit
3923  * coordinates of X11.
3924  *</note>
3925  **/
3926 void
3927 gdk_window_get_geometry (GdkWindow *window,
3928                          gint      *x,
3929                          gint      *y,
3930                          gint      *width,
3931                          gint      *height,
3932                          gint      *depth)
3933 {
3934   GdkWindowObject *private;
3935
3936   if (!window)
3937     {
3938       GDK_NOTE (MULTIHEAD,
3939                 g_message ("gdk_window_get_geometry(): Window needs "
3940                            "to be non-NULL to be multi head safe"));
3941       window = gdk_screen_get_root_window ((gdk_screen_get_default ()));
3942     }
3943
3944   g_return_if_fail (GDK_IS_WINDOW (window));
3945
3946   private = (GdkWindowObject *) window;
3947
3948   if (!GDK_WINDOW_DESTROYED (window))
3949     {
3950       GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_geometry (window, x, y,
3951                                                                width, height,
3952                                                                depth);
3953     }
3954 }
3955
3956 /**
3957  * gdk_window_get_origin:
3958  * @window: a #GdkWindow
3959  * @x: return location for X coordinate
3960  * @y: return location for Y coordinate
3961  *
3962  * Obtains the position of a window in root window coordinates.
3963  * (Compare with gdk_window_get_position() and
3964  * gdk_window_get_geometry() which return the position of a window
3965  * relative to its parent window.)
3966  *
3967  * Return value: not meaningful, ignore
3968  */
3969 gint
3970 gdk_window_get_origin (GdkWindow *window,
3971                        gint      *x,
3972                        gint      *y)
3973 {
3974   GdkWindowObject *private;
3975
3976   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
3977
3978   private = (GdkWindowObject *) window;
3979
3980   return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_origin (window, x, y);
3981 }
3982
3983 /**
3984  * gdk_window_shape_combine_mask:
3985  * @window: a #GdkWindow
3986  * @mask: shape mask
3987  * @x: X position of shape mask with respect to @window
3988  * @y: Y position of shape mask with respect to @window
3989  *
3990  * Applies a shape mask to @window. Pixels in @window corresponding to
3991  * set bits in the @mask will be visible; pixels in @window
3992  * corresponding to unset bits in the @mask will be transparent. This
3993  * gives a non-rectangular window.
3994  *
3995  * If @mask is %NULL, the shape mask will be unset, and the @x/@y
3996  * parameters are not used.
3997  *
3998  * On the X11 platform, this uses an X server extension which is
3999  * widely available on most common platforms, but not available on
4000  * very old X servers, and occasionally the implementation will be
4001  * buggy. On servers without the shape extension, this function
4002  * will do nothing.
4003  *
4004  * This function works on both toplevel and child windows.
4005  */
4006 void
4007 gdk_window_shape_combine_mask (GdkWindow *window,
4008                                GdkBitmap *mask,
4009                                gint       x,
4010                                gint       y)
4011 {
4012   GdkWindowObject *private;
4013
4014   g_return_if_fail (GDK_IS_WINDOW (window));
4015
4016   private = (GdkWindowObject *) window;
4017
4018   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_mask (window, mask, x, y);
4019 }
4020
4021 /**
4022  * gdk_window_shape_combine_region:
4023  * @window: a #GdkWindow
4024  * @shape_region: region of window to be non-transparent
4025  * @offset_x: X position of @shape_region in @window coordinates
4026  * @offset_y: Y position of @shape_region in @window coordinates
4027  *
4028  * Makes pixels in @window outside @shape_region be transparent,
4029  * so that the window may be nonrectangular. See also
4030  * gdk_window_shape_combine_mask() to use a bitmap as the mask.
4031  *
4032  * If @shape_region is %NULL, the shape will be unset, so the whole
4033  * window will be opaque again. @offset_x and @offset_y are ignored
4034  * if @shape_region is %NULL.
4035  *
4036  * On the X11 platform, this uses an X server extension which is
4037  * widely available on most common platforms, but not available on
4038  * very old X servers, and occasionally the implementation will be
4039  * buggy. On servers without the shape extension, this function
4040  * will do nothing.
4041  *
4042  * This function works on both toplevel and child windows.
4043  */
4044 void
4045 gdk_window_shape_combine_region (GdkWindow       *window,
4046                                  const GdkRegion *shape_region,
4047                                  gint             offset_x,
4048                                  gint             offset_y)
4049 {
4050   GdkWindowObject *private;
4051
4052   g_return_if_fail (GDK_IS_WINDOW (window));
4053
4054   private = (GdkWindowObject *) window;
4055
4056   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region (window, shape_region, offset_x, offset_y);
4057 }
4058
4059 /**
4060  * gdk_window_set_child_shapes:
4061  * @window: a #GdkWindow
4062  *
4063  * Sets the shape mask of @window to the union of shape masks
4064  * for all children of @window, ignoring the shape mask of @window
4065  * itself. Contrast with gdk_window_merge_child_shapes() which includes
4066  * the shape mask of @window in the masks to be merged.
4067  **/
4068 void
4069 gdk_window_set_child_shapes (GdkWindow *window)
4070 {
4071   GdkWindowObject *private;
4072
4073   g_return_if_fail (GDK_IS_WINDOW (window));
4074
4075   private = (GdkWindowObject *) window;
4076
4077   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_child_shapes (window);
4078 }
4079
4080 /**
4081  * gdk_window_merge_child_shapes:
4082  * @window: a #GdkWindow
4083  *
4084  * Merges the shape masks for any child windows into the
4085  * shape mask for @window. i.e. the union of all masks
4086  * for @window and its children will become the new mask
4087  * for @window. See gdk_window_shape_combine_mask().
4088  *
4089  * This function is distinct from gdk_window_set_child_shapes()
4090  * because it includes @window's shape mask in the set of shapes to
4091  * be merged.
4092  */
4093 void
4094 gdk_window_merge_child_shapes (GdkWindow *window)
4095 {
4096   GdkWindowObject *private;
4097
4098   g_return_if_fail (GDK_IS_WINDOW (window));
4099
4100   private = (GdkWindowObject *) window;
4101
4102   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->merge_child_shapes (window);
4103 }
4104
4105
4106 /**
4107  * gdk_window_set_static_gravities:
4108  * @window: a #GdkWindow
4109  * @use_static: %TRUE to turn on static gravity
4110  *
4111  * Set the bit gravity of the given window to static, and flag it so
4112  * all children get static subwindow gravity. This is used if you are
4113  * implementing scary features that involve deep knowledge of the
4114  * windowing system. Don't worry about it unless you have to.
4115  *
4116  * Return value: %TRUE if the server supports static gravity
4117  */
4118 gboolean
4119 gdk_window_set_static_gravities (GdkWindow *window,
4120                                  gboolean   use_static)
4121 {
4122   GdkWindowObject *private;
4123
4124   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
4125
4126   private = (GdkWindowObject *) window;
4127
4128   return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_static_gravities (window, use_static);
4129 }
4130
4131 /**
4132  * gdk_window_set_composited:
4133  * @window: a #GdkWindow
4134  * @composited: %TRUE to set the window as composited
4135  *
4136  * Sets a #GdkWindow as composited, or unsets it. Composited 
4137  * windows do not automatically have their contents drawn to 
4138  * the screen. Drawing is redirected to an offscreen buffer 
4139  * and an expose event is emitted on the parent of the composited 
4140  * window. It is the responsibility of the parent's expose handler
4141  * to manually merge the off-screen content onto the screen in
4142  * whatever way it sees fit. See <xref linkend="composited-window-example"/>
4143  * for an example.
4144  *
4145  * It only makes sense for child windows to be composited; see
4146  * gdk_window_set_opacity() if you need translucent toplevel
4147  * windows.
4148  *
4149  * An additional effect of this call is that the area of this
4150  * window is no longer clipped from regions marked for
4151  * invalidation on its parent. Draws done on the parent
4152  * window are also no longer clipped by the child.
4153  *
4154  * This call is only supported on some systems (currently,
4155  * only X11 with new enough Xcomposite and Xdamage extensions). 
4156  * You must call gdk_display_supports_composite() to check if
4157  * setting a window as composited is supported before
4158  * attempting to do so.
4159  *
4160  * Since: 2.12
4161  */
4162 void
4163 gdk_window_set_composited (GdkWindow *window,
4164                            gboolean   composited)
4165 {
4166   GdkWindowObject *private = (GdkWindowObject *)window;
4167   GdkDisplay *display;
4168
4169   g_return_if_fail (window != NULL);
4170   g_return_if_fail (GDK_IS_WINDOW (window));
4171
4172   composited = composited != FALSE;
4173
4174   if (private->composited == composited)
4175     return;
4176
4177   display = gdk_drawable_get_display (GDK_DRAWABLE (window));
4178
4179   if (!gdk_display_supports_composite (display) && composited)
4180     {
4181       g_warning ("gdk_window_set_composited called but "
4182                  "compositing is not supported");
4183       return;
4184     }
4185
4186   _gdk_windowing_window_set_composited (window, composited);
4187
4188   private->composited = composited;
4189 }
4190
4191
4192 static void
4193 remove_redirect_from_children (GdkWindowObject   *private,
4194                                GdkWindowRedirect *redirect)
4195 {
4196   GList *l;
4197   GdkWindowObject *child;
4198
4199   for (l = private->children; l != NULL; l = l->next)
4200     {
4201       child = l->data;
4202
4203       /* Don't redirect this child if it already has another redirect */
4204       if (child->redirect == redirect)
4205         {
4206           child->redirect = NULL;
4207           remove_redirect_from_children (child, redirect);
4208         }
4209     }
4210 }
4211
4212 /**
4213  * gdk_window_remove_redirection:
4214  * @window: a #GdkWindow
4215  *
4216  * Removes and active redirection started by
4217  * gdk_window_redirect_to_drawable().
4218  *
4219  * Since: 2.14
4220  **/
4221 void
4222 gdk_window_remove_redirection (GdkWindow *window)
4223 {
4224   GdkWindowObject *private;
4225
4226   g_return_if_fail (GDK_IS_WINDOW (window));
4227
4228   private = (GdkWindowObject *) window;
4229
4230   if (private->redirect &&
4231       private->redirect->redirected == private)
4232     {
4233       remove_redirect_from_children (private, private->redirect);
4234       gdk_window_redirect_free (private->redirect);
4235       private->redirect = NULL;
4236     }
4237 }
4238
4239 static void
4240 apply_redirect_to_children (GdkWindowObject   *private,
4241                             GdkWindowRedirect *redirect)
4242 {
4243   GList *l;
4244   GdkWindowObject *child;
4245
4246   for (l = private->children; l != NULL; l = l->next)
4247     {
4248       child = l->data;
4249
4250       /* Don't redirect this child if it already has another redirect */
4251       if (!child->redirect)
4252         {
4253           child->redirect = redirect;
4254           apply_redirect_to_children (child, redirect);
4255         }
4256     }
4257 }
4258
4259 /**
4260  * gdk_window_redirect_to_drawable:
4261  * @window: a #GdkWindow
4262  * @drawable: a #GdkDrawable
4263  * @src_x: x position in @window
4264  * @src_y: y position in @window
4265  * @dest_x: x position in @drawable
4266  * @dest_y: y position in @drawable
4267  * @width: width of redirection
4268  * @height: height of redirection
4269  *
4270  * Redirects drawing into @windows so that drawing to the
4271  * window in the rectangle specified by @src_x, @src_y,
4272  * @width and @height is also drawn into @drawable at
4273  * @dest_x, @dest_y.
4274  *
4275  * Only drawing between gdk_window_begin_paint_region() or
4276  * gdk_window_begin_paint_rect() and gdk_window_end_paint() is
4277  * redirected.
4278  *
4279  * Redirection is active until gdk_window_remove_redirection()
4280  * is called.
4281  *
4282  * This function should not be used on windows created by
4283  * gdk_window_new_offscreen(), as that is implemented using
4284  * redirection.
4285  *
4286  * Since: 2.14.
4287  **/
4288 void
4289 gdk_window_redirect_to_drawable (GdkWindow   *window,
4290                                  GdkDrawable *drawable,
4291                                  gint         src_x,
4292                                  gint         src_y,
4293                                  gint         dest_x,
4294                                  gint         dest_y,
4295                                  gint         width,
4296                                  gint         height)
4297 {
4298   GdkWindowObject *private;
4299   
4300   g_return_if_fail (GDK_IS_WINDOW (window));
4301   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
4302   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
4303
4304   private = (GdkWindowObject *) window;
4305
4306   if (private->redirect)
4307     gdk_window_remove_redirection (window);
4308
4309   if (width == -1 || height == -1)
4310     {
4311       gint w, h;
4312       gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
4313       if (width == -1)
4314         width = w;
4315       if (height == -1)
4316         height = h;
4317     }
4318   
4319   private->redirect = g_new0 (GdkWindowRedirect, 1);
4320   private->redirect->redirected = private;
4321   private->redirect->pixmap = g_object_ref (drawable);
4322   private->redirect->src_x = src_x;
4323   private->redirect->src_y = src_y;
4324   private->redirect->dest_x = dest_x;
4325   private->redirect->dest_y = dest_y;
4326   private->redirect->width = width;
4327   private->redirect->height = height;
4328
4329   apply_redirect_to_children (private, private->redirect);
4330 }
4331
4332 static void
4333 window_get_size_rectangle (GdkWindow    *window,
4334                            GdkRectangle *rect)
4335 {
4336   rect->x = rect->y = 0;
4337   gdk_drawable_get_size (GDK_DRAWABLE (window), &rect->width, &rect->height);
4338 }
4339
4340 /* Calculates the real clipping region for a window, in window coordinates,
4341  * taking into account other windows, gc clip region and gc clip mask.
4342  */
4343 static GdkRegion *
4344 _gdk_window_calculate_full_clip_region (GdkWindow *window,
4345                                         GdkWindow *base_window,
4346                                         GdkGC *gc,
4347                                         gboolean do_children,
4348                                         gint *base_x_offset,
4349                                         gint *base_y_offset)
4350 {
4351   GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
4352   GdkRectangle visible_rect;
4353   GdkRegion *real_clip_region, *tmpreg;
4354   gint x_offset, y_offset;
4355   GdkWindowObject *parentwin, *lastwin;
4356
4357   if (base_x_offset)
4358     *base_x_offset = 0;
4359   if (base_y_offset)
4360     *base_y_offset = 0;
4361   
4362   if (!GDK_WINDOW_IS_MAPPED (window) || private->input_only)
4363     return gdk_region_new ();
4364
4365   window_get_size_rectangle (window, &visible_rect);
4366
4367   /* windows that a redirection has ben setup for need to be considered
4368    * fully visible, in order to avoid missing redirected paint ops
4369    * anywhere in the window area.
4370    */
4371   if (private->redirect && private->redirect->redirected == private)
4372     return gdk_region_rectangle (&visible_rect);
4373
4374   /* real_clip_region is in window coordinates */
4375   real_clip_region = gdk_region_rectangle (&visible_rect);
4376
4377   x_offset = y_offset = 0;
4378
4379   lastwin = private;
4380   if (do_children)
4381     parentwin = lastwin;
4382   else
4383     parentwin = lastwin->parent;
4384   
4385   /* Remove the areas of all overlapping windows above parentwin in the hiearachy */
4386   for (; parentwin != NULL && (parentwin == private || lastwin != (GdkWindowObject *)base_window);
4387        lastwin = parentwin, parentwin = lastwin->parent)
4388     {
4389       GList *cur;
4390       GdkRectangle real_clip_rect;
4391       
4392       if (parentwin != private)
4393         {
4394           x_offset += GDK_WINDOW_OBJECT (lastwin)->x;
4395           y_offset += GDK_WINDOW_OBJECT (lastwin)->y;
4396         }
4397       
4398       /* children is ordered in reverse stack order */
4399       for (cur = GDK_WINDOW_OBJECT (parentwin)->children; cur && cur->data != lastwin; cur = cur->next)
4400         {
4401           GdkWindow *child = cur->data;
4402           GdkWindowObject *child_private = (GdkWindowObject *)child;
4403           
4404           if (!GDK_WINDOW_IS_MAPPED (child) || child_private->input_only)
4405             continue;
4406
4407           window_get_size_rectangle (child, &visible_rect);
4408
4409           /* Convert rect to "window" coords */
4410           visible_rect.x += child_private->x - x_offset;
4411           visible_rect.y += child_private->y - y_offset;
4412           
4413           /* This shortcut is really necessary for performance when there are a lot of windows */
4414           gdk_region_get_clipbox (real_clip_region, &real_clip_rect);
4415           if (visible_rect.x >= real_clip_rect.x + real_clip_rect.width ||
4416               visible_rect.x + visible_rect.width <= real_clip_rect.x ||
4417               visible_rect.y >= real_clip_rect.y + real_clip_rect.height ||
4418               visible_rect.y + visible_rect.height <= real_clip_rect.y)
4419             continue;
4420           
4421           tmpreg = gdk_region_rectangle (&visible_rect);
4422           gdk_region_subtract (real_clip_region, tmpreg);
4423           gdk_region_destroy (tmpreg);
4424         }
4425       
4426     }
4427
4428   if (gc)
4429     {
4430       GdkRegion *clip_region = _gdk_gc_get_clip_region (gc);
4431       
4432       if (clip_region)
4433         {
4434           /* clip_region is relative to gc clip origin which is relative to the window */
4435           /* offset it to window relative: */
4436           tmpreg = gdk_region_copy (clip_region);
4437           gdk_region_offset (real_clip_region,
4438                              gc->clip_x_origin,
4439                              gc->clip_y_origin);
4440           /* Intersect it with window hierarchy cliprect: */
4441           gdk_region_intersect (real_clip_region, tmpreg);
4442           gdk_region_destroy (tmpreg);
4443         }
4444     }
4445
4446   if (base_x_offset)
4447     *base_x_offset = x_offset;
4448   if (base_y_offset)
4449     *base_y_offset = y_offset;
4450
4451   return real_clip_region;
4452 }
4453
4454 static void
4455 gdk_window_add_damage (GdkWindow *toplevel,
4456                        GdkRegion *damaged_region)
4457 {
4458   GdkDisplay *display;
4459   GdkEvent event = { 0, };
4460   event.expose.type = GDK_DAMAGE;
4461   event.expose.window = toplevel;
4462   event.expose.send_event = FALSE;
4463   event.expose.region = damaged_region;
4464   gdk_region_get_clipbox (event.expose.region, &event.expose.area);
4465   display = gdk_drawable_get_display (event.expose.window);
4466   _gdk_event_queue_append (display, gdk_event_copy (&event));
4467 }
4468
4469 static void
4470 setup_redirect_clip (GdkWindow         *window,
4471                      GdkGC             *gc,
4472                      GdkWindowClipData *data)
4473 {
4474   GdkWindowObject *private = (GdkWindowObject *)window;
4475   GdkRegion *visible_region;
4476   GdkRectangle dest_rect;
4477   GdkRegion *tmpreg;
4478   GdkWindow *toplevel;
4479
4480   data->old_region = _gdk_gc_get_clip_region (gc);
4481   if (data->old_region) 
4482     data->old_region = gdk_region_copy (data->old_region);
4483
4484   data->old_clip_x_origin = gc->clip_x_origin;
4485   data->old_clip_y_origin = gc->clip_y_origin;
4486
4487   toplevel = GDK_WINDOW (private->redirect->redirected);
4488   
4489   /* Get the clip region for gc clip rect + window hierarchy in
4490      window relative coords */
4491   visible_region =
4492     _gdk_window_calculate_full_clip_region (window, toplevel,
4493                                             gc, TRUE,
4494                                             &data->x_offset, 
4495                                             &data->y_offset);
4496
4497   /* Compensate for the source pos/size */
4498   data->x_offset -= private->redirect->src_x;
4499   data->y_offset -= private->redirect->src_y;
4500   dest_rect.x = -data->x_offset;
4501   dest_rect.y = -data->y_offset;
4502   dest_rect.width = private->redirect->width;
4503   dest_rect.height = private->redirect->height;
4504   tmpreg = gdk_region_rectangle (&dest_rect);
4505   gdk_region_intersect (visible_region, tmpreg);
4506   gdk_region_destroy (tmpreg);
4507
4508   /* Compensate for the dest pos */
4509   data->x_offset += private->redirect->dest_x;
4510   data->y_offset += private->redirect->dest_y;
4511
4512   gdk_gc_set_clip_region (gc, visible_region); /* This resets clip origin! */
4513
4514   /* offset clip and tiles from window coords to pixmaps coords */
4515   gdk_gc_offset (gc, -data->x_offset, -data->y_offset);
4516
4517   /* Offset region to abs coords and add to damage */
4518   gdk_region_offset (visible_region, data->x_offset, data->y_offset);
4519   gdk_window_add_damage (toplevel, visible_region);
4520   
4521   gdk_region_destroy (visible_region);
4522 }
4523
4524 static void
4525 reset_redirect_clip (GdkWindow         *offscreen,
4526                      GdkGC             *gc,
4527                      GdkWindowClipData *data)
4528 {
4529   /* offset back */
4530   gdk_gc_offset (gc, data->x_offset, data->y_offset);
4531
4532   /* reset old clip */
4533   gdk_gc_set_clip_region (gc, data->old_region);
4534   if (data->old_region)
4535     gdk_region_destroy (data->old_region);
4536   gdk_gc_set_clip_origin (gc, data->old_clip_x_origin, data->old_clip_y_origin);
4537 }
4538
4539 static void
4540 gdk_window_redirect_free (GdkWindowRedirect *redirect)
4541 {
4542   g_object_unref (redirect->pixmap);
4543   g_free (redirect);
4544 }
4545
4546 #define __GDK_WINDOW_C__
4547 #include "gdkaliasdef.c"