]> Pileus Git - ~andy/gtk/blob - gdk/gdkwindow.c
For implicit grabs, we grab the *event* window, not the pointer window
[~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 #ifdef GDK_WINDOWING_X11
39 #include "x11/gdkx.h"           /* For workaround */
40 #endif
41
42 #include "math.h"
43
44 /* Not all GdkWindows have a corresponding native window.
45  * Instead some draw into the nearest parent that has whatss
46  * called an "impl", i.e. the implementation window.
47  * For toplevel window system windows the impl is always native
48  * window, but child windows can also have native windows as
49  * this is sometimes necessary. Furthermore, offscreen windows
50  * (type GDK_WINDOW_OFFSCREEN) have an impl of type
51  * GdkOffscreenWindow rather than a backend implementation native
52  * window. Such windows draw into an offscreen pixmap instead
53  * of a window and collect damage that lets you paint it where
54  * you want.
55  *
56  * All GdkWindow track their position, size, clip region and
57  * absolute position in the impl window. For child window with
58  * native windows the clip region is set on the native window
59  * as a window shape to make it clip against other non-native windows.
60  */  
61
62 #define USE_BACKING_STORE       /* Appears to work on Win32, too, now. */
63
64 struct _GdkWindowPaint
65 {
66   GdkRegion *region;
67   GdkPixmap *pixmap;
68   gint x_offset;
69   gint y_offset;
70   cairo_surface_t *surface;
71   guint uses_implicit : 1;
72   guint32 region_tag;
73 };
74
75 typedef struct {
76   GdkRegion *region; /* The destination region */
77   int dx, dy;
78 } GdkWindowRegionMove;
79
80
81 /* Global info */
82
83 static GdkGC *gdk_window_create_gc      (GdkDrawable     *drawable,
84                                          GdkGCValues     *values,
85                                          GdkGCValuesMask  mask);
86 static void   gdk_window_draw_rectangle (GdkDrawable     *drawable,
87                                          GdkGC           *gc,
88                                          gboolean         filled,
89                                          gint             x,
90                                          gint             y,
91                                          gint             width,
92                                          gint             height);
93 static void   gdk_window_draw_arc       (GdkDrawable     *drawable,
94                                          GdkGC           *gc,
95                                          gboolean         filled,
96                                          gint             x,
97                                          gint             y,
98                                          gint             width,
99                                          gint             height,
100                                          gint             angle1,
101                                          gint             angle2);
102 static void   gdk_window_draw_polygon   (GdkDrawable     *drawable,
103                                          GdkGC           *gc,
104                                          gboolean         filled,
105                                          GdkPoint        *points,
106                                          gint             npoints);
107 static void   gdk_window_draw_text      (GdkDrawable     *drawable,
108                                          GdkFont         *font,
109                                          GdkGC           *gc,
110                                          gint             x,
111                                          gint             y,
112                                          const gchar     *text,
113                                          gint             text_length);
114 static void   gdk_window_draw_text_wc   (GdkDrawable     *drawable,
115                                          GdkFont         *font,
116                                          GdkGC           *gc,
117                                          gint             x,
118                                          gint             y,
119                                          const GdkWChar  *text,
120                                          gint             text_length);
121 static void   gdk_window_draw_drawable  (GdkDrawable     *drawable,
122                                          GdkGC           *gc,
123                                          GdkPixmap       *src,
124                                          gint             xsrc,
125                                          gint             ysrc,
126                                          gint             xdest,
127                                          gint             ydest,
128                                          gint             width,
129                                          gint             height);
130 static void   gdk_window_draw_points    (GdkDrawable     *drawable,
131                                          GdkGC           *gc,
132                                          GdkPoint        *points,
133                                          gint             npoints);
134 static void   gdk_window_draw_segments  (GdkDrawable     *drawable,
135                                          GdkGC           *gc,
136                                          GdkSegment      *segs,
137                                          gint             nsegs);
138 static void   gdk_window_draw_lines     (GdkDrawable     *drawable,
139                                          GdkGC           *gc,
140                                          GdkPoint        *points,
141                                          gint             npoints);
142
143 static void gdk_window_draw_glyphs             (GdkDrawable      *drawable,
144                                                 GdkGC            *gc,
145                                                 PangoFont        *font,
146                                                 gint              x,
147                                                 gint              y,
148                                                 PangoGlyphString *glyphs);
149 static void gdk_window_draw_glyphs_transformed (GdkDrawable      *drawable,
150                                                 GdkGC            *gc,
151                                                 PangoMatrix      *matrix,
152                                                 PangoFont        *font,
153                                                 gint              x,
154                                                 gint              y,
155                                                 PangoGlyphString *glyphs);
156
157 static void   gdk_window_draw_image     (GdkDrawable     *drawable,
158                                          GdkGC           *gc,
159                                          GdkImage        *image,
160                                          gint             xsrc,
161                                          gint             ysrc,
162                                          gint             xdest,
163                                          gint             ydest,
164                                          gint             width,
165                                          gint             height);
166
167 static void gdk_window_draw_pixbuf (GdkDrawable     *drawable,
168                                     GdkGC           *gc,
169                                     GdkPixbuf       *pixbuf,
170                                     gint             src_x,
171                                     gint             src_y,
172                                     gint             dest_x,
173                                     gint             dest_y,
174                                     gint             width,
175                                     gint             height,
176                                     GdkRgbDither     dither,
177                                     gint             x_dither,
178                                     gint             y_dither);
179
180 static void gdk_window_draw_trapezoids (GdkDrawable   *drawable,
181                                         GdkGC         *gc,
182                                         GdkTrapezoid  *trapezoids,
183                                         gint           n_trapezoids);
184
185 static GdkImage* gdk_window_copy_to_image (GdkDrawable *drawable,
186                                            GdkImage    *image,
187                                            gint         src_x,
188                                            gint         src_y,
189                                            gint         dest_x,
190                                            gint         dest_y,
191                                            gint         width,
192                                            gint         height);
193
194 static cairo_surface_t *gdk_window_ref_cairo_surface (GdkDrawable *drawable);
195 static void             gdk_window_set_cairo_clip    (GdkDrawable *drawable,
196                                                       cairo_t *cr);
197
198 static void   gdk_window_real_get_size  (GdkDrawable     *drawable,
199                                          gint            *width,
200                                          gint            *height);
201
202 static GdkVisual*   gdk_window_real_get_visual   (GdkDrawable *drawable);
203 static gint         gdk_window_real_get_depth    (GdkDrawable *drawable);
204 static GdkScreen*   gdk_window_real_get_screen   (GdkDrawable *drawable);
205 static void         gdk_window_real_set_colormap (GdkDrawable *drawable,
206                                                   GdkColormap *cmap);
207 static GdkColormap* gdk_window_real_get_colormap (GdkDrawable *drawable);
208
209 static GdkDrawable* gdk_window_get_source_drawable    (GdkDrawable *drawable);
210 static GdkDrawable* gdk_window_get_composite_drawable (GdkDrawable *drawable,
211                                                        gint         x,
212                                                        gint         y,
213                                                        gint         width,
214                                                        gint         height,
215                                                        gint        *composite_x_offset,
216                                                        gint        *composite_y_offset);
217 static GdkRegion*   gdk_window_get_clip_region        (GdkDrawable *drawable);
218 static GdkRegion*   gdk_window_get_visible_region     (GdkDrawable *drawable);
219
220 static void gdk_window_free_paint_stack (GdkWindow *window);
221
222 static void gdk_window_init       (GdkWindowObject      *window);
223 static void gdk_window_class_init (GdkWindowObjectClass *klass);
224 static void gdk_window_finalize   (GObject              *object);
225 static void gdk_window_clear_backing_rect (GdkWindow *window,
226                                            gint       x,
227                                            gint       y,
228                                            gint       width,
229                                            gint       height);
230 static void gdk_window_redirect_free      (GdkWindowRedirect *redirect);
231 static void apply_redirect_to_children    (GdkWindowObject   *private,
232                                            GdkWindowRedirect *redirect);
233 static void remove_redirect_from_children (GdkWindowObject   *private,
234                                            GdkWindowRedirect *redirect);
235
236 static void recompute_visible_regions (GdkWindowObject *private,
237                                        gboolean recalculate_siblings,
238                                        gboolean recalculate_children);
239 static void gdk_window_flush          (GdkWindow *window);
240 static void do_move_region_bits_on_impl (GdkWindowObject *private,
241                                          GdkDrawable *dest,
242                                          int dest_off_x, int dest_off_y,
243                                          GdkRegion *region, /* In impl window coords */
244                                          int dx, int dy);
245   
246 static gpointer parent_class = NULL;
247
248 static const cairo_user_data_key_t gdk_window_cairo_key;
249
250 static guint32
251 new_region_tag (void)
252 {
253   static guint32 tag = 0;
254
255   return ++tag;
256 }
257
258 GType
259 gdk_window_object_get_type (void)
260 {
261   static GType object_type = 0;
262
263   if (!object_type)
264     object_type = g_type_register_static_simple (GDK_TYPE_DRAWABLE,
265                                                  "GdkWindow",
266                                                  sizeof (GdkWindowObjectClass),
267                                                  (GClassInitFunc) gdk_window_class_init,
268                                                  sizeof (GdkWindowObject),
269                                                  (GInstanceInitFunc) gdk_window_init,
270                                                  0);
271   
272   return object_type;
273 }
274
275 GType
276 _gdk_paintable_get_type (void)
277 {
278   static GType paintable_type = 0;
279
280   if (!paintable_type)
281     {
282       const GTypeInfo paintable_info =
283       {
284         sizeof (GdkPaintableIface),  /* class_size */
285         NULL,                        /* base_init */
286         NULL,                        /* base_finalize */
287       };
288
289       paintable_type = g_type_register_static (G_TYPE_INTERFACE,
290                                                g_intern_static_string ("GdkPaintable"),
291                                                &paintable_info, 0);
292
293       g_type_interface_add_prerequisite (paintable_type, G_TYPE_OBJECT);
294     }
295
296   return paintable_type;
297 }
298
299 static void
300 gdk_window_init (GdkWindowObject *window)
301 {
302   /* 0-initialization is good for all other fields. */
303
304   window->window_type = GDK_WINDOW_CHILD;
305
306   window->state = GDK_WINDOW_STATE_WITHDRAWN;
307   window->width = 1;
308   window->height = 1;
309   window->toplevel_window_type = -1;
310 }
311
312 static GQuark quark_pointer_window = 0;
313
314 static void
315 gdk_window_class_init (GdkWindowObjectClass *klass)
316 {
317   GObjectClass *object_class = G_OBJECT_CLASS (klass);
318   GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
319   
320   parent_class = g_type_class_peek_parent (klass);
321
322   object_class->finalize = gdk_window_finalize;
323
324   drawable_class->create_gc = gdk_window_create_gc;
325   drawable_class->draw_rectangle = gdk_window_draw_rectangle;
326   drawable_class->draw_arc = gdk_window_draw_arc;
327   drawable_class->draw_polygon = gdk_window_draw_polygon;
328   drawable_class->draw_text = gdk_window_draw_text;
329   drawable_class->draw_text_wc = gdk_window_draw_text_wc;
330   drawable_class->draw_drawable = gdk_window_draw_drawable;
331   drawable_class->draw_points = gdk_window_draw_points;
332   drawable_class->draw_segments = gdk_window_draw_segments;
333   drawable_class->draw_lines = gdk_window_draw_lines;
334   drawable_class->draw_glyphs = gdk_window_draw_glyphs;
335   drawable_class->draw_glyphs_transformed = gdk_window_draw_glyphs_transformed;
336   drawable_class->draw_image = gdk_window_draw_image;
337   drawable_class->draw_pixbuf = gdk_window_draw_pixbuf;
338   drawable_class->draw_trapezoids = gdk_window_draw_trapezoids;
339   drawable_class->get_depth = gdk_window_real_get_depth;
340   drawable_class->get_screen = gdk_window_real_get_screen;
341   drawable_class->get_size = gdk_window_real_get_size;
342   drawable_class->set_colormap = gdk_window_real_set_colormap;
343   drawable_class->get_colormap = gdk_window_real_get_colormap;
344   drawable_class->get_visual = gdk_window_real_get_visual;
345   drawable_class->_copy_to_image = gdk_window_copy_to_image;
346   drawable_class->ref_cairo_surface = gdk_window_ref_cairo_surface;
347   drawable_class->set_cairo_clip = gdk_window_set_cairo_clip;
348   drawable_class->get_clip_region = gdk_window_get_clip_region;
349   drawable_class->get_visible_region = gdk_window_get_visible_region;
350   drawable_class->get_composite_drawable = gdk_window_get_composite_drawable;
351   drawable_class->get_source_drawable = gdk_window_get_source_drawable;
352
353   quark_pointer_window = g_quark_from_static_string ("gtk-pointer-window");
354 }
355
356 static void
357 gdk_window_finalize (GObject *object)
358 {
359   GdkWindow *window = GDK_WINDOW (object);
360   GdkWindowObject *obj = (GdkWindowObject *) object;
361   
362   if (!GDK_WINDOW_DESTROYED (window))
363     {
364       if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
365         {
366           g_warning ("losing last reference to undestroyed window\n");
367           _gdk_window_destroy (window, FALSE);
368         }
369       else
370         /* We use TRUE here, to keep us from actually calling
371          * XDestroyWindow() on the window
372          */
373         _gdk_window_destroy (window, TRUE);
374     }
375
376   if (obj->impl)
377     {
378       g_object_unref (obj->impl);
379       obj->impl = NULL;
380     }
381
382   if (obj->cursor)
383     gdk_cursor_unref (obj->cursor);
384
385   G_OBJECT_CLASS (parent_class)->finalize (object);
386 }
387
388 static gboolean
389 gdk_window_is_offscreen (GdkWindowObject *window)
390 {
391   return GDK_WINDOW_TYPE (window) == GDK_WINDOW_OFFSCREEN;
392 }
393
394 static GdkWindowObject *
395 gdk_window_get_impl_window (GdkWindowObject *window)
396 {
397   while (window->parent != NULL && window->parent->impl == window->impl)
398     window = window->parent;
399
400   return window;
401 }
402
403 GdkWindow *
404 _gdk_window_get_impl_window (GdkWindow *window)
405 {
406   return (GdkWindow *)gdk_window_get_impl_window ((GdkWindowObject *)window);
407 }
408
409 static gboolean
410 gdk_window_has_impl (GdkWindowObject *window)
411 {
412   return window->parent == NULL || window->parent->impl != window->impl;
413 }
414
415 gboolean
416 _gdk_window_has_impl (GdkWindow *window)
417 {
418   return gdk_window_has_impl ((GdkWindowObject *)window);
419 }
420
421 static gboolean
422 gdk_window_has_no_impl (GdkWindowObject *window)
423 {
424   return window->parent->impl == window->impl;
425 }
426
427 static void
428 remove_child_area (GdkWindowObject *private,
429                    GdkWindowObject *until,
430                    GdkRegion *region)
431 {
432   GdkWindowObject *child;
433   GdkRegion *child_region;
434   GdkRectangle r;
435   GList *l;
436   
437   for (l = private->children; l; l = l->next)
438     {
439       child = l->data;
440
441       if (child == until)
442         break;
443       
444       if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
445         continue;
446
447       /* Ignore offscreen children, as they don't draw in their parent and
448        * don't take part in the clipping */
449       if (gdk_window_is_offscreen (child))
450         continue;
451
452       r.x = child->x;
453       r.y = child->y;
454       r.width = child->width;
455       r.height = child->height;
456       
457       child_region = gdk_region_rectangle (&r);
458       gdk_region_subtract (region, child_region);
459       gdk_region_destroy (child_region);
460     }
461 }
462
463 static void
464 recompute_visible_regions_internal (GdkWindowObject *private,
465                                     gboolean recalculate_clip,
466                                     gboolean recalculate_siblings,
467                                     gboolean recalculate_children)
468 {
469   GdkRectangle r;
470   GList *l;
471   GdkWindowObject *child;
472   GdkRegion *new_clip, *old_clip_region_with_children;
473   gboolean clip_region_changed;
474   gboolean abs_pos_changed;
475   int old_abs_x, old_abs_y;
476
477   old_abs_x = private->abs_x;
478   old_abs_y = private->abs_y;
479   
480   /* Update absolute position */
481   if (gdk_window_has_impl (private))
482     {
483       /* Native window starts here */
484       private->abs_x = 0;
485       private->abs_y = 0;
486     }
487   else
488     {
489       private->abs_x = private->parent->abs_x + private->x;
490       private->abs_y = private->parent->abs_y + private->y;
491     }
492
493   abs_pos_changed =
494     private->abs_x != old_abs_x ||
495     private->abs_y != old_abs_y;
496
497   /* Update clip region based on:
498    * parent clip
499    * window size
500    * siblings in parents above window
501    */
502   clip_region_changed = FALSE;
503   if (recalculate_clip)
504     {
505       /* Calculate visible region (sans children) in parent window coords */
506       r.x = private->x;
507       r.y = private->y;
508       r.width = private->width;
509       r.height = private->height;
510       new_clip = gdk_region_rectangle (&r);
511       
512       if (private->parent != NULL && GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
513         {
514           gdk_region_intersect (new_clip, private->parent->clip_region);
515           
516           /* Remove all overlapping children from parent */
517           remove_child_area (private->parent, private, new_clip);
518         }
519       
520       /* Convert from parent coords to window coords */
521       gdk_region_offset (new_clip, -private->x, -private->y);
522
523       if (private->clip_region == NULL ||
524           !gdk_region_equal (private->clip_region, new_clip))
525         clip_region_changed = TRUE;
526         
527       if (private->clip_region)
528         gdk_region_destroy (private->clip_region);
529       private->clip_region = new_clip;
530
531       old_clip_region_with_children = private->clip_region_with_children;
532       private->clip_region_with_children = gdk_region_copy (private->clip_region);
533       remove_child_area (private, NULL, private->clip_region_with_children);
534
535       if (clip_region_changed ||
536           !gdk_region_equal (private->clip_region_with_children, old_clip_region_with_children))
537           private->clip_tag = new_region_tag ();
538
539       if (old_clip_region_with_children)
540         gdk_region_destroy (old_clip_region_with_children);
541     }
542
543   /* Update all children, recursively. */
544   if (abs_pos_changed || clip_region_changed || recalculate_children)
545     {
546       for (l = private->children; l; l = l->next)
547         {
548           child = l->data;
549           /* Only recalculate clip if the the clip region changed, otherwise
550            * there is no way the child clip region could change (its has not e.g. moved)
551            * Except if recalculate_children is set to force child updates
552            */
553           recompute_visible_regions_internal (child, recalculate_clip && (clip_region_changed || recalculate_children), FALSE, FALSE);
554         }
555     }
556
557   if (clip_region_changed &&
558       gdk_window_has_impl (private) &&
559       /* Not for offscreens */
560       private->window_type != GDK_WINDOW_OFFSCREEN &&
561       /* or for toplevels */
562       private->parent != NULL &&
563       GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT &&
564       /* or for foreign windows */
565       GDK_WINDOW_TYPE (private) != GDK_WINDOW_FOREIGN
566       )
567     {
568       GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region ((GdkWindow *)private, private->clip_region, 0, 0);
569     }
570       
571   
572   if (recalculate_siblings &&
573       private->parent != NULL &&
574       GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
575     {
576       /* If we moved a child window in parent or changed the stacking order, then we
577        * need to recompute the visible area of all the other children in the parent
578        */
579       for (l = private->parent->children; l; l = l->next)
580         {
581           child = l->data;
582
583           if (child != private)
584             recompute_visible_regions_internal (child, TRUE, FALSE, FALSE);
585         }
586
587       /* We also need to recompute the _with_children clip for the parent */
588       recompute_visible_regions_internal (private->parent, TRUE, FALSE, FALSE);
589     }
590
591   if (private->cairo_surface)
592     {
593       int width, height;
594
595       /* It would be nice if we had some cairo support here so we
596          could set the clip rect on the cairo surface */
597       width = private->abs_x + private->width;
598       height = private->abs_y + private->height;
599
600       _gdk_windowing_set_cairo_surface_size (private->cairo_surface,
601                                              width, height);
602       cairo_surface_set_device_offset (private->cairo_surface, 
603                                        private->abs_x,
604                                        private->abs_y);
605     }
606 }
607
608 /* Call this when private has changed in one or more of these ways:
609  *  size changed
610  *  window moved
611  *  new window added
612  *  stacking order of window changed
613  *  child deleted
614  *
615  * It will recalculate abs_x/y and the clip regions
616  *
617  * Unless the window didn't change stacking order or size/pos, pass in TRUE
618  * for recalculate_siblings. (Mostly used internally for the recursion)
619  * 
620  * If a child window was removed (and you can't use that child for
621  * recompute_visible_regions), pass in TRUE for recalculate_children on the parent
622  */
623 static void
624 recompute_visible_regions (GdkWindowObject *private,
625                            gboolean recalculate_siblings,
626                            gboolean recalculate_children)
627 {
628   recompute_visible_regions_internal (private,
629                                       TRUE,
630                                       recalculate_siblings,
631                                       recalculate_children);
632 }
633
634 void
635 _gdk_window_update_size (GdkWindow *window)
636 {
637   recompute_visible_regions ((GdkWindowObject *)window, TRUE, FALSE);
638 }
639
640 static GdkEventMask
641 get_native_event_mask (GdkWindowObject *private)
642 {
643   if (GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
644     return
645       GDK_EXPOSURE_MASK |
646       GDK_POINTER_MOTION_MASK |
647       GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
648       GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK |
649       GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
650       GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK |
651       GDK_PROXIMITY_IN_MASK | GDK_PROXIMITY_OUT_MASK | GDK_SCROLL_MASK;
652   else
653     return GDK_EXPOSURE_MASK;
654 }
655
656
657 /**
658  * gdk_window_new:
659  * @parent: a #GdkWindow, or %NULL to create the window as a child of
660  *   the default root window for the default display.
661  * @attributes: attributes of the new window
662  * @attributes_mask: mask indicating which fields in @attributes are valid
663  * 
664  * Creates a new #GdkWindow using the attributes from
665  * @attributes. See #GdkWindowAttr and #GdkWindowAttributesType for
666  * more details.  Note: to use this on displays other than the default
667  * display, @parent must be specified.
668  * 
669  * Return value: the new #GdkWindow
670  **/
671 GdkWindow*
672 gdk_window_new (GdkWindow     *parent,
673                 GdkWindowAttr *attributes,
674                 gint           attributes_mask)
675 {
676   GdkWindow *window;
677   GdkWindowObject *private;
678   GdkScreen *screen;
679   GdkVisual *visual;
680   int x, y;
681   gboolean native;
682   GdkEventMask event_mask;
683   GdkWindow *real_parent;
684   
685   g_return_val_if_fail (attributes != NULL, NULL);
686   
687   if (!parent)
688     {
689       GDK_NOTE (MULTIHEAD,
690                 g_warning ("gdk_window_new(): no parent specified reverting to parent = default root window"));
691       
692       screen = gdk_screen_get_default ();
693       parent = gdk_screen_get_root_window (screen);
694     }
695   else
696     screen = gdk_drawable_get_screen (parent);
697
698   g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
699   
700   if (GDK_WINDOW_DESTROYED (parent))
701     return NULL;
702
703   window = g_object_new (GDK_TYPE_WINDOW, NULL);
704   private = (GdkWindowObject *) window;
705
706   /* Windows with a foreign parent are treated as if they are children
707    * of the root window, except for actual creation.
708    */
709   real_parent = parent;
710   if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
711     parent = gdk_screen_get_root_window (screen);
712
713   private->parent = (GdkWindowObject *)parent;
714
715   private->accept_focus = TRUE;
716   private->focus_on_map = TRUE;
717
718   if (attributes_mask & GDK_WA_X)
719     x = attributes->x;
720   else
721     x = 0;
722   
723   if (attributes_mask & GDK_WA_Y)
724     y = attributes->y;
725   else
726     y = 0;
727   
728   private->x = x;
729   private->y = y;
730   private->width = (attributes->width > 1) ? (attributes->width) : (1);
731   private->height = (attributes->height > 1) ? (attributes->height) : (1);
732
733 #ifdef GDK_WINDOWING_X11
734   /* Work around a bug where Xorg refuses to map toplevel InputOnly windows 
735    * from an untrusted client: http://bugs.freedesktop.org/show_bug.cgi?id=6988
736    */
737   if (attributes->wclass == GDK_INPUT_ONLY &&
738       GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT &&
739       !G_LIKELY (GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (parent))->trusted_client))
740     {
741       g_warning ("Coercing GDK_INPUT_ONLY toplevel window to GDK_INPUT_OUTPUT to work around bug in Xorg server");
742       attributes->wclass = GDK_INPUT_OUTPUT;
743     }
744 #endif
745   
746   if (attributes->wclass == GDK_INPUT_ONLY)
747     {
748       /* Backwards compatiblity - we've always ignored
749        * attributes->window_type for input-only windows
750        * before
751        */
752       if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
753         private->window_type = GDK_WINDOW_TEMP;
754       else
755         private->window_type = GDK_WINDOW_CHILD;
756     }
757   else
758     private->window_type = attributes->window_type;
759
760   /* Sanity checks */
761   switch (private->window_type)
762     {
763     case GDK_WINDOW_TOPLEVEL:
764     case GDK_WINDOW_DIALOG:
765     case GDK_WINDOW_TEMP:
766       if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
767         g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
768                    "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
769     case GDK_WINDOW_CHILD:
770     case GDK_WINDOW_OFFSCREEN:
771       break;
772     default:
773       g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
774       return NULL;
775     }
776   
777   if (attributes_mask & GDK_WA_VISUAL)
778     visual = attributes->visual;
779   else
780     visual = gdk_screen_get_system_visual (screen);
781
782   private->event_mask = attributes->event_mask;
783
784   if (attributes->wclass == GDK_INPUT_OUTPUT)
785     {
786       private->input_only = FALSE;
787       private->depth = visual->depth;
788   
789       private->bg_color.pixel = 0; // TODO: BlackPixel (xdisplay, screen_x11->screen_num);
790       private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
791
792       private->bg_pixmap = NULL;
793     }
794   else
795     {
796       private->depth = 0;
797       private->input_only = TRUE;
798     }
799
800   if (private->parent)
801     private->parent->children = g_list_prepend (private->parent->children, window);
802
803   native = FALSE; /* Default */
804   if (GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
805     native = TRUE; /* Always use native windows for toplevels */
806   else if (!private->input_only &&
807            ((attributes_mask & GDK_WA_COLORMAP &&
808              attributes->colormap != gdk_drawable_get_colormap ((GdkDrawable *)private->parent)) ||
809             (attributes_mask & GDK_WA_VISUAL &&
810              attributes->visual != gdk_drawable_get_visual ((GdkDrawable *)private->parent))))
811     native = TRUE; /* InputOutput window with different colormap or visual than parent, needs native window */
812
813   if (private->window_type == GDK_WINDOW_OFFSCREEN)
814     {
815       _gdk_offscreen_window_new (window, screen, visual, attributes, attributes_mask);
816     }
817   else if (native)
818     {
819       event_mask = get_native_event_mask (private);
820       
821       /* Create the impl */
822       _gdk_window_impl_new (window, real_parent, screen, visual, event_mask, attributes, attributes_mask);
823     }
824   else
825     {
826       private->impl = private->parent->impl;
827     }
828
829   recompute_visible_regions (private, TRUE, FALSE);
830   
831   if (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
832     {
833       /* Inherit redirection from parent */
834       private->redirect = private->parent->redirect;
835     }
836     
837   return window;
838 }
839
840 static gboolean
841 is_parent_of (GdkWindow *parent,
842               GdkWindow *child)
843 {
844   GdkWindow *w;
845
846   w = child;
847   while (w != NULL)
848     {
849       if (w == parent)
850         return TRUE;
851
852       w = gdk_window_get_parent (w);
853     }
854
855   return FALSE;
856 }
857
858 static void
859 change_impl (GdkWindowObject *private,
860              GdkDrawable *new)
861 {
862   GList *l;
863   GdkWindowObject *child;
864   gboolean show;
865   GdkDrawable *old_impl;
866
867   old_impl = private->impl;
868   private->impl = new;
869   
870   for (l = private->children; l != NULL; l = l->next)
871     {
872       child = l->data;
873
874       if (child->impl == old_impl)
875         change_impl (child, new);
876       else
877         {
878           show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent ((GdkWindow *)child,
879                                                                       (GdkWindow *)private,
880                                                                       child->x, child->y);
881           if (show)
882             gdk_window_show_unraised ((GdkWindow *)child);
883         }
884     }
885
886 }
887
888 /**
889  * gdk_window_reparent:
890  * @window: a #GdkWindow
891  * @new_parent: new parent to move @window into
892  * @x: X location inside the new parent
893  * @y: Y location inside the new parent
894  *
895  * Reparents @window into the given @new_parent. The window being
896  * reparented will be unmapped as a side effect.
897  * 
898  **/
899 void
900 gdk_window_reparent (GdkWindow *window,
901                      GdkWindow *new_parent,
902                      gint       x,
903                      gint       y)
904 {
905   GdkWindowObject *private;
906   GdkWindowObject *new_parent_private;
907   GdkWindowObject *old_parent;
908   gboolean show, was_toplevel, was_mapped;
909   
910   g_return_if_fail (GDK_IS_WINDOW (window));
911   g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
912   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
913
914   if (GDK_WINDOW_DESTROYED (window) ||
915       (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
916     return;
917
918   if (!new_parent)
919     new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
920   
921   private = (GdkWindowObject *) window;
922   new_parent_private = (GdkWindowObject *)new_parent;
923
924   /* No input-output children of input-only windows */
925   if (new_parent_private->input_only && !private->input_only)
926     return;
927
928   /* Don't create loops in hierarchy */
929   if (is_parent_of (window, new_parent))
930     return;
931   
932   if (private->cairo_surface)
933     {
934       /* This might be wrong in the new parent, e.g. for non-native surfaces.
935          To make sure we're ok, just wipe it. */
936       cairo_surface_finish (private->cairo_surface);
937       cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
938                                    NULL, NULL);
939     }
940   
941   old_parent = private->parent;
942
943   /* Break up redirection if inherited */
944   if (private->redirect && private->redirect->redirected != private)
945     {
946       remove_redirect_from_children (private, private->redirect);
947       private->redirect = NULL;
948     }
949
950   was_toplevel = private->parent == NULL;
951   was_mapped = GDK_WINDOW_IS_MAPPED (window);
952   show = FALSE;
953
954   /* Reparenting to toplevel. Ensure we have a native window so this can work */
955   if (new_parent_private->window_type == GDK_WINDOW_ROOT ||
956       new_parent_private->window_type == GDK_WINDOW_FOREIGN)
957     gdk_window_set_has_native (window, TRUE);
958   
959   if (gdk_window_has_impl (private))
960     {
961       /* Native window */
962       show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent (window, new_parent, x, y);
963     }
964   else
965     {
966       /* This shouldn't happen, as we created a native in this case, check anyway to see if that ever fails */
967       g_assert (new_parent_private->window_type != GDK_WINDOW_ROOT &&
968                 new_parent_private->window_type != GDK_WINDOW_FOREIGN);
969
970       show = was_mapped;
971       gdk_window_hide (window);
972
973       change_impl (private, new_parent_private->impl);
974     }
975
976   /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
977    * the root window
978    */
979   if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
980     {
981       new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
982       new_parent_private = (GdkWindowObject *)new_parent;
983     }
984
985   if (private->parent)
986     private->parent->children = g_list_remove (private->parent->children, window);
987   
988   private->parent = new_parent_private;
989   private->x = x;
990   private->y = y;
991
992   new_parent_private->children = g_list_prepend (new_parent_private->children, window);
993   
994   /* Switch the window type as appropriate */
995
996   switch (GDK_WINDOW_TYPE (new_parent))
997     {
998     case GDK_WINDOW_ROOT:
999     case GDK_WINDOW_FOREIGN:
1000       if (private->toplevel_window_type != -1)
1001         GDK_WINDOW_TYPE (window) = private->toplevel_window_type;
1002       else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1003         GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
1004       break;
1005     case GDK_WINDOW_OFFSCREEN:
1006     case GDK_WINDOW_TOPLEVEL:
1007     case GDK_WINDOW_CHILD:
1008     case GDK_WINDOW_DIALOG:
1009     case GDK_WINDOW_TEMP:
1010       if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
1011           GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
1012         {
1013           /* Save the original window type so we can restore it if the
1014            * window is reparented back to be a toplevel
1015            */
1016           private->toplevel_window_type = GDK_WINDOW_TYPE (window);
1017           GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
1018         }
1019     }
1020
1021   /* We might have changed window type for a native windows, so we
1022      need to change the event mask too. */
1023   if (gdk_window_has_impl (private))
1024     GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_events (window, get_native_event_mask (private));
1025   
1026   /* Inherit parent redirect if we don't have our own */
1027   if (private->parent && private->redirect == NULL)
1028     {
1029       private->redirect = private->parent->redirect;
1030       apply_redirect_to_children (private, private->redirect);
1031     }
1032
1033   recompute_visible_regions (private, TRUE, FALSE);
1034   if (old_parent && GDK_WINDOW_TYPE (old_parent) != GDK_WINDOW_ROOT)
1035     recompute_visible_regions (old_parent, FALSE, TRUE);
1036   
1037   if (show)
1038     gdk_window_show_unraised (window);
1039   else
1040     _gdk_syntesize_crossing_events_for_geometry_change (window);
1041 }
1042
1043 /**
1044  * gdk_window_set_has_native:
1045  * @window: a #GdkWindow
1046  * @has_native: whethe the window should have a native window
1047  *
1048  * Tries to create or remove a window-system native window for this
1049  * GdkWindow. This may fail in some situations. For instance:
1050  *
1051  * Toplevel and foreign windows must have a native window.
1052  * Offscreen window and children of them can never have native windows.
1053  * Some backends may not support native child windows.
1054  * 
1055  **/
1056 void
1057 gdk_window_set_has_native (GdkWindow *window, gboolean has_native)
1058 {
1059   GdkWindowObject *private;
1060   GdkWindowObject *impl_window;
1061   GdkDrawable *new_impl, *old_impl;
1062   GdkScreen *screen;
1063   GdkVisual *visual;
1064   GdkWindowAttr attributes;
1065
1066   g_return_if_fail (GDK_IS_WINDOW (window));
1067
1068   if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT ||
1069       GDK_WINDOW_DESTROYED (window))
1070     return;
1071
1072   private = (GdkWindowObject *) window;
1073   
1074   if (has_native)
1075     {
1076       /* Create native window */
1077
1078       if (gdk_window_has_impl (private))
1079         /* Already has an impl, either native (ok) or
1080            offscreen (not supported). Bail. */
1081         return; 
1082
1083       impl_window = gdk_window_get_impl_window (private);
1084       if (impl_window->window_type == GDK_WINDOW_OFFSCREEN)
1085         return; /* native in offscreens not supported */
1086
1087       screen = gdk_drawable_get_screen (window);
1088       visual = gdk_drawable_get_visual (window);
1089
1090       attributes.colormap = gdk_drawable_get_colormap (window);
1091       
1092       old_impl = private->impl;
1093       _gdk_window_impl_new (window, (GdkWindow *)private->parent, screen, visual,
1094                             get_native_event_mask (private), &attributes, GDK_WA_COLORMAP);
1095       new_impl = private->impl;
1096       
1097       private->impl = old_impl;
1098       change_impl (private, new_impl);
1099     }
1100   else
1101     {
1102       /* Remove native window */
1103
1104       if (!gdk_window_has_impl (private))
1105         return;  /* Not native, can't remove */
1106
1107       if (private->window_type == GDK_WINDOW_OFFSCREEN)
1108         return; /* Not native, can't remove */
1109       
1110       if (private->parent == NULL ||
1111           GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
1112         return; /* toplevel, must be native */
1113
1114       g_warning ("Tried to turn native window to client side window, this is not supported yet.");
1115
1116       /* TODO: remove native */
1117     }
1118 }
1119
1120 static void
1121 window_remove_filters (GdkWindow *window)
1122 {
1123   GdkWindowObject *obj = (GdkWindowObject*) window;
1124
1125   if (obj->filters)
1126     {
1127       GList *tmp_list;
1128       
1129       for (tmp_list = obj->filters; tmp_list; tmp_list = tmp_list->next)
1130         g_free (tmp_list->data);
1131     
1132       g_list_free (obj->filters);
1133       obj->filters = NULL;
1134     }
1135 }
1136
1137 /**
1138  * _gdk_window_destroy_hierarchy:
1139  * @window: a #GdkWindow
1140  * @recursing: If TRUE, then this is being called because a parent
1141  *            was destroyed. This generally means that the call to the 
1142  *            windowing system to destroy the window can be omitted, since
1143  *            it will be destroyed as a result of the parent being destroyed.
1144  *            Unless @foreign_destroy.           
1145  * @foreign_destroy: If TRUE, the window or a parent was destroyed by some 
1146  *            external agency. The window has already been destroyed and no 
1147  *            windowing system calls should be made. (This may never happen
1148  *            for some windowing systems.)
1149  *
1150  * Internal function to destroy a window. Like gdk_window_destroy(),
1151  * but does not drop the reference count created by gdk_window_new().
1152  **/
1153 static void
1154 _gdk_window_destroy_hierarchy (GdkWindow *window,
1155                                gboolean   recursing,
1156                                gboolean   foreign_destroy)
1157 {
1158   GdkWindowObject *private;
1159   GdkWindowObject *temp_private;
1160   GdkWindow *temp_window;
1161   GdkScreen *screen;
1162   GdkDisplay *display;
1163   GList *children;
1164   GList *tmp;
1165
1166   g_return_if_fail (GDK_IS_WINDOW (window));
1167
1168   private = (GdkWindowObject*) window;
1169   
1170   if (GDK_WINDOW_DESTROYED (window))
1171     return;
1172     
1173   display = gdk_drawable_get_display (GDK_DRAWABLE (window));
1174   screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
1175   temp_window = g_object_get_qdata (G_OBJECT (screen), quark_pointer_window);
1176   if (temp_window == window)
1177     g_object_set_qdata (G_OBJECT (screen), quark_pointer_window, NULL);
1178
1179
1180   switch (GDK_WINDOW_TYPE (window))
1181     {
1182     case GDK_WINDOW_ROOT:
1183       if (!screen->closed)
1184         {
1185           g_error ("attempted to destroy root window");
1186           break;
1187         }
1188       /* else fall thru */
1189     case GDK_WINDOW_TOPLEVEL:
1190     case GDK_WINDOW_CHILD:
1191     case GDK_WINDOW_DIALOG:
1192     case GDK_WINDOW_TEMP:
1193     case GDK_WINDOW_FOREIGN:
1194     case GDK_WINDOW_OFFSCREEN:
1195       if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN && !foreign_destroy)
1196         {
1197           /* Logically, it probably makes more sense to send
1198            * a "destroy yourself" message to the foreign window
1199            * whether or not it's in our hierarchy; but for historical
1200            * reasons, we only send "destroy yourself" messages to
1201            * foreign windows in our hierarchy.
1202            */
1203           if (private->parent)
1204             _gdk_windowing_window_destroy_foreign (window);
1205
1206           /* Also for historical reasons, we remove any filters
1207            * on a foreign window when it or a parent is destroyed;
1208            * this likely causes problems if two separate portions
1209            * of code are maintaining filter lists on a foreign window.
1210            */
1211           window_remove_filters (window);
1212         }
1213       else
1214         {
1215           if (private->parent)
1216             {
1217               GdkWindowObject *parent_private = (GdkWindowObject *)private->parent;
1218               if (parent_private->children)
1219                 parent_private->children = g_list_remove (parent_private->children, window);
1220             }
1221
1222           gdk_window_free_paint_stack (window);
1223           
1224           if (private->bg_pixmap &&
1225               private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
1226               private->bg_pixmap != GDK_NO_BG)
1227             {
1228               g_object_unref (private->bg_pixmap);
1229               private->bg_pixmap = NULL;
1230             }
1231           
1232           if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN)
1233             g_assert (private->children == NULL);
1234           else
1235             {
1236               children = tmp = private->children;
1237               private->children = NULL;
1238               
1239               while (tmp)
1240                 {
1241                   temp_window = tmp->data;
1242                   tmp = tmp->next;
1243                   
1244                   temp_private = (GdkWindowObject*) temp_window;
1245                   if (temp_private)
1246                     _gdk_window_destroy_hierarchy (temp_window,
1247                                                    TRUE, foreign_destroy);
1248                 }
1249               
1250               g_list_free (children);
1251             }
1252
1253           _gdk_window_clear_update_area (window); 
1254           
1255           if (private->cairo_surface)
1256             {
1257               cairo_surface_finish (private->cairo_surface);
1258               cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
1259                                            NULL, NULL);
1260             }
1261
1262           if (gdk_window_has_impl (private))
1263             {
1264               if (gdk_window_is_offscreen (private))
1265                 _gdk_offscreen_window_destroy (window, recursing);
1266               else
1267                 _gdk_windowing_window_destroy (window, recursing, foreign_destroy);
1268             }
1269           else
1270             {
1271               /* hide to make sure we repaint and break grabs */
1272               gdk_window_hide (window);
1273               /* NULL out impl so we don't double free it on finalize */
1274               private->impl = NULL;
1275             }
1276
1277           private->state |= GDK_WINDOW_STATE_WITHDRAWN;
1278           private->parent = NULL;
1279           private->destroyed = TRUE;
1280
1281           window_remove_filters (window);
1282
1283           gdk_drawable_set_colormap (GDK_DRAWABLE (window), NULL);
1284
1285           /* If we own the redirect, free it */
1286           if (private->redirect && private->redirect->redirected == private)
1287             gdk_window_redirect_free (private->redirect);
1288
1289           private->redirect = NULL;
1290
1291           if (display->pointer_info.toplevel_under_pointer == window)
1292             {
1293               g_object_unref (display->pointer_info.toplevel_under_pointer);
1294               display->pointer_info.toplevel_under_pointer = NULL;
1295             }
1296         }
1297       break;
1298     }
1299 }
1300
1301 /**
1302  * _gdk_window_destroy:
1303  * @window: a #GdkWindow
1304  * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
1305  *            external agency. The window has already been destroyed and no
1306  *            windowing system calls should be made. (This may never happen
1307  *            for some windowing systems.)
1308  *
1309  * Internal function to destroy a window. Like gdk_window_destroy(),
1310  * but does not drop the reference count created by gdk_window_new().
1311  **/
1312 void
1313 _gdk_window_destroy (GdkWindow *window,
1314                      gboolean   foreign_destroy)
1315 {
1316   _gdk_window_destroy_hierarchy (window, FALSE, foreign_destroy);
1317 }
1318
1319 /**
1320  * gdk_window_destroy:
1321  * @window: a #GdkWindow
1322  *
1323  * Destroys the window system resources associated with @window and decrements @window's
1324  * reference count. The window system resources for all children of @window are also
1325  * destroyed, but the children's reference counts are not decremented.
1326  *
1327  * Note that a window will not be destroyed automatically when its reference count
1328  * reaches zero. You must call this function yourself before that happens.
1329  *
1330  **/
1331 void
1332 gdk_window_destroy (GdkWindow *window)
1333 {
1334   _gdk_window_destroy_hierarchy (window, FALSE, FALSE);
1335   g_object_unref (window);
1336 }
1337
1338 /**
1339  * gdk_window_set_user_data:
1340  * @window: a #GdkWindow
1341  * @user_data: user data
1342  *
1343  * For most purposes this function is deprecated in favor of
1344  * g_object_set_data(). However, for historical reasons GTK+ stores
1345  * the #GtkWidget that owns a #GdkWindow as user data on the
1346  * #GdkWindow. So, custom widget implementations should use
1347  * this function for that. If GTK+ receives an event for a #GdkWindow,
1348  * and the user data for the window is non-%NULL, GTK+ will assume the
1349  * user data is a #GtkWidget, and forward the event to that widget.
1350  * 
1351  **/
1352 void
1353 gdk_window_set_user_data (GdkWindow *window,
1354                           gpointer   user_data)
1355 {
1356   g_return_if_fail (GDK_IS_WINDOW (window));
1357
1358   ((GdkWindowObject*)window)->user_data = user_data;
1359 }
1360
1361 /**
1362  * gdk_window_get_user_data:
1363  * @window: a #GdkWindow
1364  * @data: return location for user data
1365  *
1366  * Retrieves the user data for @window, which is normally the widget
1367  * that @window belongs to. See gdk_window_set_user_data().
1368  * 
1369  **/
1370 void
1371 gdk_window_get_user_data (GdkWindow *window,
1372                           gpointer  *data)
1373 {
1374   g_return_if_fail (GDK_IS_WINDOW (window));
1375
1376   *data = ((GdkWindowObject*)window)->user_data;
1377 }
1378
1379 /**
1380  * gdk_window_get_window_type:
1381  * @window: a #GdkWindow
1382  * 
1383  * Gets the type of the window. See #GdkWindowType.
1384  * 
1385  * Return value: type of window
1386  **/
1387 GdkWindowType
1388 gdk_window_get_window_type (GdkWindow *window)
1389 {
1390   g_return_val_if_fail (GDK_IS_WINDOW (window), (GdkWindowType) -1);
1391   
1392   return GDK_WINDOW_TYPE (window);
1393 }
1394
1395 /**
1396  * gdk_window_get_position:
1397  * @window: a #GdkWindow
1398  * @x: X coordinate of window
1399  * @y: Y coordinate of window
1400  *
1401  * Obtains the position of the window as reported in the
1402  * most-recently-processed #GdkEventConfigure. Contrast with
1403  * gdk_window_get_geometry() which queries the X server for the
1404  * current window position, regardless of which events have been
1405  * received or processed.
1406  *
1407  * The position coordinates are relative to the window's parent window.
1408  * 
1409  **/
1410 void
1411 gdk_window_get_position (GdkWindow *window,
1412                          gint      *x,
1413                          gint      *y)
1414 {
1415   GdkWindowObject *obj;
1416   
1417   g_return_if_fail (GDK_IS_WINDOW (window));
1418   
1419   obj = (GdkWindowObject*) window;
1420   
1421   if (x)
1422     *x = obj->x;
1423   if (y)
1424     *y = obj->y;
1425 }
1426
1427 /**
1428  * gdk_window_get_parent:
1429  * @window: a #GdkWindow
1430  * 
1431  * Obtains the parent of @window, as known to GDK. Does not query the
1432  * X server; thus this returns the parent as passed to gdk_window_new(),
1433  * not the actual parent. This should never matter unless you're using
1434  * Xlib calls mixed with GDK calls on the X11 platform. It may also
1435  * matter for toplevel windows, because the window manager may choose
1436  * to reparent them.
1437  * 
1438  * Return value: parent of @window
1439  **/
1440 GdkWindow*
1441 gdk_window_get_parent (GdkWindow *window)
1442 {
1443   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1444   
1445   return (GdkWindow*) ((GdkWindowObject*) window)->parent;
1446 }
1447
1448 /**
1449  * gdk_window_get_toplevel:
1450  * @window: a #GdkWindow
1451  * 
1452  * Gets the toplevel window that's an ancestor of @window.
1453  * 
1454  * Return value: the toplevel window containing @window
1455  **/
1456 GdkWindow*
1457 gdk_window_get_toplevel (GdkWindow *window)
1458 {
1459   GdkWindowObject *obj;
1460   
1461   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1462
1463   obj = (GdkWindowObject *)window;
1464   while (GDK_WINDOW_TYPE (obj) == GDK_WINDOW_CHILD)
1465     obj = (GdkWindowObject *)obj->parent;
1466   
1467   return GDK_WINDOW (obj);
1468 }
1469
1470 /**
1471  * gdk_window_get_children:
1472  * @window: a #GdkWindow
1473  * 
1474  * Gets the list of children of @window known to GDK.
1475  * This function only returns children created via GDK,
1476  * so for example it's useless when used with the root window;
1477  * it only returns windows an application created itself.
1478  *
1479  * The returned list must be freed, but the elements in the
1480  * list need not be.
1481  * 
1482  * Return value: list of child windows inside @window
1483  **/
1484 GList*
1485 gdk_window_get_children (GdkWindow *window)
1486 {
1487   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1488
1489   if (GDK_WINDOW_DESTROYED (window))
1490     return NULL;
1491
1492   return g_list_copy (GDK_WINDOW_OBJECT (window)->children);
1493 }
1494
1495 /**
1496  * gdk_window_peek_children:
1497  * @window: a #GdkWindow
1498  * 
1499  * Like gdk_window_get_children(), but does not copy the list of
1500  * children, so the list does not need to be freed.
1501  * 
1502  * Return value: a reference to the list of child windows in @window
1503  **/
1504 GList *
1505 gdk_window_peek_children (GdkWindow *window)
1506 {
1507   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1508
1509   if (GDK_WINDOW_DESTROYED (window))
1510     return NULL;
1511
1512   return GDK_WINDOW_OBJECT (window)->children;
1513 }
1514
1515 /**
1516  * gdk_window_add_filter:
1517  * @window: a #GdkWindow
1518  * @function: filter callback
1519  * @data: data to pass to filter callback
1520  *
1521  * Adds an event filter to @window, allowing you to intercept events
1522  * before they reach GDK. This is a low-level operation and makes it
1523  * easy to break GDK and/or GTK+, so you have to know what you're
1524  * doing. Pass %NULL for @window to get all events for all windows,
1525  * instead of events for a specific window.
1526  *
1527  * See gdk_display_add_client_message_filter() if you are interested
1528  * in X ClientMessage events.
1529  **/
1530 void          
1531 gdk_window_add_filter (GdkWindow     *window,
1532                        GdkFilterFunc  function,
1533                        gpointer       data)
1534 {
1535   GdkWindowObject *private;
1536   GList *tmp_list;
1537   GdkEventFilter *filter;
1538   
1539   g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
1540
1541   private = (GdkWindowObject*) window;
1542   if (private && GDK_WINDOW_DESTROYED (window))
1543     return;
1544
1545   /* Filters are for the native events on the native window, so
1546      ensure there is a native window. */
1547   if (window)
1548     gdk_window_set_has_native (window, TRUE);
1549   
1550   if (private)
1551     tmp_list = private->filters;
1552   else
1553     tmp_list = _gdk_default_filters;
1554   
1555   while (tmp_list)
1556     {
1557       filter = (GdkEventFilter *)tmp_list->data;
1558       if ((filter->function == function) && (filter->data == data))
1559         return;
1560       tmp_list = tmp_list->next;
1561     }
1562   
1563   filter = g_new (GdkEventFilter, 1);
1564   filter->function = function;
1565   filter->data = data;
1566   
1567   if (private)
1568     private->filters = g_list_append (private->filters, filter);
1569   else
1570     _gdk_default_filters = g_list_append (_gdk_default_filters, filter);
1571 }
1572
1573 /**
1574  * gdk_window_remove_filter:
1575  * @window: a #GdkWindow
1576  * @function: previously-added filter function
1577  * @data: user data for previously-added filter function
1578  *
1579  * Remove a filter previously added with gdk_window_add_filter().
1580  * 
1581  **/
1582 void
1583 gdk_window_remove_filter (GdkWindow     *window,
1584                           GdkFilterFunc  function,
1585                           gpointer       data)
1586 {
1587   GdkWindowObject *private;
1588   GList *tmp_list, *node;
1589   GdkEventFilter *filter;
1590   
1591   g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
1592
1593   private = (GdkWindowObject*) window;
1594   
1595   if (private)
1596     tmp_list = private->filters;
1597   else
1598     tmp_list = _gdk_default_filters;
1599   
1600   while (tmp_list)
1601     {
1602       filter = (GdkEventFilter *)tmp_list->data;
1603       node = tmp_list;
1604       tmp_list = tmp_list->next;
1605       
1606       if ((filter->function == function) && (filter->data == data))
1607         {
1608           if (private)
1609             private->filters = g_list_remove_link (private->filters, node);
1610           else
1611             _gdk_default_filters = g_list_remove_link (_gdk_default_filters, node);
1612           g_list_free_1 (node);
1613           g_free (filter);
1614           
1615           return;
1616         }
1617     }
1618 }
1619
1620 /**
1621  * gdk_screen_get_toplevel_windows:
1622  * @screen: The #GdkScreen where the toplevels are located.
1623  * 
1624  * Obtains a list of all toplevel windows known to GDK on the screen @screen.
1625  * A toplevel window is a child of the root window (see
1626  * gdk_get_default_root_window()).
1627  *
1628  * The returned list should be freed with g_list_free(), but
1629  * its elements need not be freed.
1630  * 
1631  * Return value: list of toplevel windows, free with g_list_free()
1632  *
1633  * Since: 2.2
1634  **/
1635 GList *
1636 gdk_screen_get_toplevel_windows (GdkScreen *screen)
1637 {
1638   GdkWindow * root_window;
1639   GList *new_list = NULL;
1640   GList *tmp_list;
1641   
1642   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
1643   
1644   root_window = gdk_screen_get_root_window (screen);
1645
1646   tmp_list = ((GdkWindowObject *)root_window)->children;
1647   while (tmp_list)
1648     {
1649       if (GDK_WINDOW_TYPE (tmp_list->data) != GDK_WINDOW_FOREIGN)
1650         new_list = g_list_prepend (new_list, tmp_list->data);
1651       tmp_list = tmp_list->next;
1652     }
1653   
1654   return new_list;
1655 }
1656
1657 /**
1658  * gdk_window_get_toplevels:
1659  * 
1660  * Obtains a list of all toplevel windows known to GDK on the default
1661  * screen (see gdk_screen_get_toplevel_windows()).
1662  * A toplevel window is a child of the root window (see
1663  * gdk_get_default_root_window()).
1664  *
1665  * The returned list should be freed with g_list_free(), but
1666  * its elements need not be freed.
1667  * 
1668  * Return value: list of toplevel windows, free with g_list_free()
1669  *
1670  * Deprecated: 2.16: Use gdk_screen_get_toplevel_windows() instead.
1671  **/
1672 GList *
1673 gdk_window_get_toplevels (void)
1674 {
1675   return gdk_screen_get_toplevel_windows (gdk_screen_get_default ());
1676 }
1677
1678 /**
1679  * gdk_window_is_visible:
1680  * @window: a #GdkWindow
1681  * 
1682  * Checks whether the window has been mapped (with gdk_window_show() or
1683  * gdk_window_show_unraised()).
1684  * 
1685  * Return value: %TRUE if the window is mapped
1686  **/
1687 gboolean 
1688 gdk_window_is_visible (GdkWindow *window)
1689 {
1690   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
1691   
1692   return GDK_WINDOW_IS_MAPPED (window);
1693 }
1694
1695 /**
1696  * gdk_window_is_viewable:
1697  * @window: a #GdkWindow
1698  * 
1699  * Check if the window and all ancestors of the window are
1700  * mapped. (This is not necessarily "viewable" in the X sense, since
1701  * we only check as far as we have GDK window parents, not to the root
1702  * window.)
1703  *
1704  * Return value: %TRUE if the window is viewable
1705  **/
1706 gboolean 
1707 gdk_window_is_viewable (GdkWindow *window)
1708 {
1709   GdkWindowObject *private = (GdkWindowObject *)window;
1710   GdkScreen *screen;
1711   GdkWindow *root_window;
1712
1713   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
1714
1715   screen = gdk_drawable_get_screen (window);
1716   root_window = gdk_screen_get_root_window (screen);
1717   
1718   while (private && 
1719          (private != (GdkWindowObject *)root_window) &&
1720          (GDK_WINDOW_TYPE (private) != GDK_WINDOW_FOREIGN))
1721     {
1722       if (GDK_WINDOW_DESTROYED (private) || !GDK_WINDOW_IS_MAPPED (private))
1723         return FALSE;
1724       
1725       private = (GdkWindowObject *)private->parent;
1726     }
1727   
1728   return TRUE;
1729 }
1730
1731 /**
1732  * gdk_window_get_state:
1733  * @window: a #GdkWindow
1734  * 
1735  * Gets the bitwise OR of the currently active window state flags,
1736  * from the #GdkWindowState enumeration.
1737  * 
1738  * Return value: window state bitfield
1739  **/
1740 GdkWindowState
1741 gdk_window_get_state (GdkWindow *window)
1742 {
1743   GdkWindowObject *private = (GdkWindowObject *)window;
1744   
1745   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
1746   
1747   return private->state;
1748 }
1749
1750
1751 /* This creates an empty "implicit" paint region for the impl window.
1752  * By itself this does nothing, but real paints to this window
1753  * or children of it can use this pixmap as backing to avoid allocating
1754  * multiple pixmaps for subwindow rendering. When doing so they
1755  * add to the region of the implicit paint region, which will be
1756  * pushed to the window when the implicit paint region is ended.
1757  * Such paints should not copy anything to the window on paint end, but
1758  * should rely on the implicit paint end.
1759  * The implicit paint will be automatically ended if someone draws
1760  * directly to the window or a child window.
1761  */
1762 static gboolean
1763 gdk_window_begin_implicit_paint (GdkWindow *window, GdkRectangle *rect)
1764 {
1765   GdkWindowObject *private = (GdkWindowObject *)window;
1766   GdkWindowPaint *paint;
1767   GdkRectangle r, clipbox;
1768   GList *l;
1769   GdkWindowRegionMove *move;
1770
1771   g_assert (gdk_window_has_impl (private));
1772
1773   if (GDK_IS_PAINTABLE (private->impl))
1774     return FALSE; /* Implementation does double buffering */
1775   
1776   if (private->paint_stack != NULL ||
1777       private->implicit_paint != NULL)
1778     return FALSE; /* Don't stack implicit paints */
1779
1780   r = *rect;
1781   for (l = private->outstanding_moves; l != NULL; l = l->next)
1782     {
1783       move = l->data;
1784
1785       gdk_region_get_clipbox (move->region, &clipbox);
1786       gdk_rectangle_union (&r, &clipbox, &r);
1787     }
1788   
1789   paint = g_new (GdkWindowPaint, 1);
1790   paint->region = gdk_region_new (); /* Empty */
1791   paint->x_offset = r.x;
1792   paint->y_offset = r.y;
1793   paint->uses_implicit = FALSE;
1794   paint->surface = NULL;
1795   paint->pixmap =
1796     gdk_pixmap_new (window,
1797                     MAX (r.width, 1), MAX (r.height, 1), -1);
1798   
1799   _gdk_pixmap_set_as_backing (paint->pixmap,
1800                               window, r.x, r.y);
1801
1802   for (l = private->outstanding_moves; l != NULL; l = l->next)
1803     {
1804       move = l->data;
1805
1806       gdk_region_union (paint->region, move->region);
1807       g_object_ref (paint->pixmap);
1808       do_move_region_bits_on_impl (private,
1809                                    paint->pixmap,
1810                                    paint->x_offset, paint->y_offset,
1811                                    move->region, /* In impl window coords */
1812                                    move->dx, move->dy);
1813       gdk_region_destroy (move->region);
1814       g_slice_free (GdkWindowRegionMove, move);
1815     }
1816   private->outstanding_moves = NULL;
1817
1818   private->implicit_paint = paint;
1819   
1820   return TRUE;
1821 }
1822
1823 /* Ensure that all content related to this (sub)window is pushed to the
1824    native region */
1825 static void
1826 gdk_window_flush_implicit_paint (GdkWindow *window)
1827 {
1828   GdkWindowObject *private = (GdkWindowObject *)window;
1829   GdkWindowObject *impl_window;
1830   GdkWindowPaint *paint;
1831   GdkRegion *region;
1832   GdkGC *tmp_gc;
1833
1834   /* Ensure that there is no explicit paint region. */
1835   g_assert (private->paint_stack == NULL);
1836   
1837   impl_window = gdk_window_get_impl_window (private);
1838   if (impl_window->implicit_paint == NULL)
1839     return;
1840
1841   paint = impl_window->implicit_paint;
1842   region = gdk_region_copy (private->clip_region_with_children);
1843   gdk_region_offset (region, private->abs_x, private->abs_y);
1844   gdk_region_intersect (region, paint->region);
1845   
1846   if (!gdk_region_empty (region))
1847     {
1848       /* Some regions are valid, push these to window now */
1849       tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
1850       _gdk_gc_set_clip_region_internal (tmp_gc, region, TRUE);
1851       gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
1852                          0, 0, paint->x_offset, paint->y_offset, -1, -1);
1853       /* Reset clip region of the cached GdkGC */
1854       gdk_gc_set_clip_region (tmp_gc, NULL);
1855
1856       /* Remove flushed region from the implicit paint */
1857       gdk_region_subtract (paint->region, region);
1858     }
1859   else
1860     gdk_region_destroy (region);
1861 }
1862
1863 /* Ends an implicit paint, paired with gdk_window_begin_implicit_paint returning TRUE */
1864 static void
1865 gdk_window_end_implicit_paint (GdkWindow *window)
1866 {
1867   GdkWindowObject *private = (GdkWindowObject *)window;
1868   GdkWindowPaint *paint;
1869   GdkGC *tmp_gc;
1870
1871   g_assert (gdk_window_has_impl (private));
1872
1873   g_assert (private->implicit_paint != NULL);
1874
1875   paint = private->implicit_paint;
1876
1877   private->implicit_paint = NULL;
1878   
1879   if (!gdk_region_empty (paint->region))
1880     {
1881       /* Some regions are valid, push these to window now */
1882       tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
1883       _gdk_gc_set_clip_region_internal (tmp_gc, paint->region, TRUE);
1884       gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
1885                          0, 0, paint->x_offset, paint->y_offset, -1, -1);
1886       /* Reset clip region of the cached GdkGC */
1887       gdk_gc_set_clip_region (tmp_gc, NULL);
1888     }
1889   
1890   g_object_unref (paint->pixmap);
1891   g_free (paint);
1892 }
1893
1894 /**
1895  * gdk_window_begin_paint_rect:
1896  * @window: a #GdkWindow
1897  * @rectangle: rectangle you intend to draw to
1898  *
1899  * A convenience wrapper around gdk_window_begin_paint_region() which
1900  * creates a rectangular region for you. See
1901  * gdk_window_begin_paint_region() for details.
1902  * 
1903  **/
1904 void
1905 gdk_window_begin_paint_rect (GdkWindow          *window,
1906                              const GdkRectangle *rectangle)
1907 {
1908   GdkRegion *region;
1909
1910   g_return_if_fail (GDK_IS_WINDOW (window));
1911
1912   region = gdk_region_rectangle (rectangle);
1913   gdk_window_begin_paint_region (window, region);
1914   gdk_region_destroy (region);
1915 }
1916
1917 #ifdef GDK_WINDOWING_X11
1918 #include "x11/gdkx.h"
1919 #endif
1920
1921 /**
1922  * gdk_window_begin_paint_region:
1923  * @window: a #GdkWindow
1924  * @region: region you intend to draw to
1925  *
1926  * Indicates that you are beginning the process of redrawing @region.
1927  * A backing store (offscreen buffer) large enough to contain @region
1928  * will be created. The backing store will be initialized with the
1929  * background color or background pixmap for @window. Then, all
1930  * drawing operations performed on @window will be diverted to the
1931  * backing store.  When you call gdk_window_end_paint(), the backing
1932  * store will be copied to @window, making it visible onscreen. Only
1933  * the part of @window contained in @region will be modified; that is,
1934  * drawing operations are clipped to @region.
1935  *
1936  * The net result of all this is to remove flicker, because the user
1937  * sees the finished product appear all at once when you call
1938  * gdk_window_end_paint(). If you draw to @window directly without
1939  * calling gdk_window_begin_paint_region(), the user may see flicker
1940  * as individual drawing operations are performed in sequence.  The
1941  * clipping and background-initializing features of
1942  * gdk_window_begin_paint_region() are conveniences for the
1943  * programmer, so you can avoid doing that work yourself.
1944  *
1945  * When using GTK+, the widget system automatically places calls to
1946  * gdk_window_begin_paint_region() and gdk_window_end_paint() around
1947  * emissions of the expose_event signal. That is, if you're writing an
1948  * expose event handler, you can assume that the exposed area in
1949  * #GdkEventExpose has already been cleared to the window background,
1950  * is already set as the clip region, and already has a backing store.
1951  * Therefore in most cases, application code need not call
1952  * gdk_window_begin_paint_region(). (You can disable the automatic
1953  * calls around expose events on a widget-by-widget basis by calling
1954  * gtk_widget_set_double_buffered().)
1955  *
1956  * If you call this function multiple times before calling the
1957  * matching gdk_window_end_paint(), the backing stores are pushed onto
1958  * a stack. gdk_window_end_paint() copies the topmost backing store
1959  * onscreen, subtracts the topmost region from all other regions in
1960  * the stack, and pops the stack. All drawing operations affect only
1961  * the topmost backing store in the stack. One matching call to
1962  * gdk_window_end_paint() is required for each call to
1963  * gdk_window_begin_paint_region().
1964  * 
1965  **/
1966 void          
1967 gdk_window_begin_paint_region (GdkWindow       *window,
1968                                const GdkRegion *region)
1969 {
1970 #ifdef USE_BACKING_STORE
1971   GdkWindowObject *private = (GdkWindowObject *)window;
1972   GdkRectangle clip_box;
1973   GdkWindowPaint *paint, *implicit_paint;
1974   GdkWindowObject *impl_window;
1975   GSList *list;
1976
1977   g_return_if_fail (GDK_IS_WINDOW (window));
1978
1979   if (GDK_WINDOW_DESTROYED (window))
1980     return;
1981
1982   if (GDK_IS_PAINTABLE (private->impl)) 
1983     {
1984       GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
1985
1986       if (iface->begin_paint_region)
1987         iface->begin_paint_region ((GdkPaintable*)private->impl, region);
1988       
1989       return;
1990     }
1991
1992   gdk_region_get_clipbox (region, &clip_box);
1993
1994   impl_window = gdk_window_get_impl_window (private);
1995   implicit_paint = impl_window->implicit_paint;
1996
1997   paint = g_new (GdkWindowPaint, 1);
1998   paint->region = gdk_region_copy (region);
1999   paint->region_tag = new_region_tag ();
2000       
2001   if (implicit_paint)
2002     {
2003       int width, height;
2004       
2005       paint->uses_implicit = TRUE;
2006       paint->pixmap = g_object_ref (implicit_paint->pixmap);
2007       paint->x_offset = -private->abs_x + implicit_paint->x_offset;
2008       paint->y_offset = -private->abs_y + implicit_paint->y_offset;
2009       gdk_region_intersect (paint->region, private->clip_region_with_children);
2010       
2011       /* It would be nice if we had some cairo support here so we
2012          could set the clip rect on the cairo surface */
2013       width = private->abs_x + private->width;
2014       height = private->abs_y + private->height;
2015       
2016       paint->surface = _gdk_windowing_create_cairo_surface (((GdkPixmapObject *)paint->pixmap)->impl,
2017                                                             width, height);
2018
2019       /* Mark the region as valid on the implicit paint */
2020       gdk_region_offset (paint->region, private->abs_x, private->abs_y); 
2021       gdk_region_union (implicit_paint->region, paint->region);
2022       gdk_region_offset (paint->region, -private->abs_x, -private->abs_y); 
2023     }
2024   else
2025     {
2026       paint->uses_implicit = FALSE;
2027       paint->x_offset = clip_box.x;
2028       paint->y_offset = clip_box.y;
2029       paint->pixmap =
2030         gdk_pixmap_new (window,
2031                         MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1);
2032       paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap);
2033     }
2034  
2035   if (paint->surface)
2036     cairo_surface_set_device_offset (paint->surface,
2037                                      -paint->x_offset, -paint->y_offset);
2038   
2039   for (list = private->paint_stack; list != NULL; list = list->next)
2040     {
2041       GdkWindowPaint *tmp_paint = list->data;
2042
2043       gdk_region_subtract (tmp_paint->region, paint->region);
2044     }
2045   
2046   private->paint_stack = g_slist_prepend (private->paint_stack, paint);
2047
2048   if (!gdk_region_empty (paint->region))
2049     {
2050       gdk_window_clear_backing_rect (window,
2051                                      clip_box.x, clip_box.y,
2052                                      clip_box.width, clip_box.height);
2053     }
2054
2055 #endif /* USE_BACKING_STORE */
2056 }
2057
2058 static void
2059 setup_redirect_clip (GdkWindow      *window,
2060                      GdkGC          *gc,
2061                      int            *x_offset_out,
2062                      int            *y_offset_out)
2063 {
2064   GdkWindowObject *private = (GdkWindowObject *)window;
2065   GdkRegion *visible_region;
2066   GdkRectangle dest_rect;
2067   GdkRegion *tmpreg;
2068   GdkWindow *toplevel;
2069   int x_offset, y_offset;
2070
2071   toplevel = GDK_WINDOW (private->redirect->redirected);
2072   
2073   /* Get the clip region for gc clip rect + window hierarchy in
2074      window relative coords */
2075   visible_region =
2076     _gdk_window_calculate_full_clip_region (window, toplevel,
2077                                             TRUE,
2078                                             &x_offset, 
2079                                             &y_offset);
2080
2081   /* Compensate for the source pos/size */
2082   x_offset -= private->redirect->src_x;
2083   y_offset -= private->redirect->src_y;
2084   dest_rect.x = -x_offset;
2085   dest_rect.y = -y_offset;
2086   dest_rect.width = private->redirect->width;
2087   dest_rect.height = private->redirect->height;
2088   tmpreg = gdk_region_rectangle (&dest_rect);
2089   gdk_region_intersect (visible_region, tmpreg);
2090   gdk_region_destroy (tmpreg);
2091
2092   /* Compensate for the dest pos */
2093   x_offset += private->redirect->dest_x;
2094   y_offset += private->redirect->dest_y;
2095
2096   gdk_gc_set_clip_region (gc, visible_region); /* This resets clip origin! */
2097
2098   /* offset clip and tiles from window coords to pixmaps coords */
2099   gdk_gc_offset (gc, -x_offset, -y_offset);
2100
2101   gdk_region_destroy (visible_region);
2102
2103   *x_offset_out = x_offset;
2104   *y_offset_out = y_offset;
2105 }
2106
2107 /**
2108  * gdk_window_end_paint:
2109  * @window: a #GdkWindow
2110  *
2111  * Indicates that the backing store created by the most recent call to
2112  * gdk_window_begin_paint_region() should be copied onscreen and
2113  * deleted, leaving the next-most-recent backing store or no backing
2114  * store at all as the active paint region. See
2115  * gdk_window_begin_paint_region() for full details. It is an error to
2116  * call this function without a matching
2117  * gdk_window_begin_paint_region() first.
2118  * 
2119  **/
2120 void
2121 gdk_window_end_paint (GdkWindow *window)
2122 {
2123 #ifdef USE_BACKING_STORE
2124   GdkWindowObject *private = (GdkWindowObject *)window;
2125   GdkWindowObject *composited;
2126   GdkWindowPaint *paint;
2127   GdkGC *tmp_gc;
2128   GdkRectangle clip_box;
2129   gint x_offset, y_offset;
2130   GdkRegion *full_clip;
2131
2132   g_return_if_fail (GDK_IS_WINDOW (window));
2133
2134   if (GDK_WINDOW_DESTROYED (window))
2135     return;
2136
2137   if (GDK_IS_PAINTABLE (private->impl))
2138     {
2139       GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
2140
2141       if (iface->end_paint)
2142         iface->end_paint ((GdkPaintable*)private->impl);
2143       return;
2144     }
2145
2146   if (private->paint_stack == NULL)
2147     {
2148       g_warning (G_STRLOC": no preceding call to gdk_window_begin_paint_region(), see documentation");
2149       return;
2150     }
2151
2152   paint = private->paint_stack->data;
2153
2154   private->paint_stack = g_slist_delete_link (private->paint_stack, 
2155                                               private->paint_stack);
2156
2157   gdk_region_get_clipbox (paint->region, &clip_box);
2158
2159   tmp_gc = _gdk_drawable_get_scratch_gc (window, FALSE);
2160
2161   x_offset = -private->abs_x;
2162   y_offset = -private->abs_y;
2163
2164   if (!paint->uses_implicit)
2165     {
2166       full_clip = gdk_region_copy (private->clip_region_with_children);
2167       gdk_region_intersect (full_clip, paint->region);
2168       _gdk_gc_set_clip_region_internal (tmp_gc, full_clip, TRUE); /* Takes ownership of full_clip */
2169       gdk_gc_set_clip_origin (tmp_gc, - x_offset, - y_offset);
2170       gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2171                          clip_box.x - paint->x_offset,
2172                          clip_box.y - paint->y_offset,
2173                          clip_box.x - x_offset, clip_box.y - y_offset,
2174                          clip_box.width, clip_box.height);
2175     }
2176   
2177   if (private->redirect)
2178     {
2179       int x_offset, y_offset;
2180
2181       /* TODO: Should also use paint->region for clipping */
2182       setup_redirect_clip (window, tmp_gc, &x_offset, &y_offset);
2183       gdk_draw_drawable (private->redirect->pixmap, tmp_gc, paint->pixmap,
2184                          clip_box.x - paint->x_offset,
2185                          clip_box.y - paint->y_offset,
2186                          clip_box.x + x_offset,
2187                          clip_box.y + y_offset,
2188                          clip_box.width, clip_box.height);
2189     }
2190   
2191   /* Reset clip region of the cached GdkGC */
2192   gdk_gc_set_clip_region (tmp_gc, NULL);
2193
2194   cairo_surface_destroy (paint->surface);
2195   g_object_unref (paint->pixmap);
2196   gdk_region_destroy (paint->region);
2197   g_free (paint);
2198
2199   /* find a composited window in our hierarchy to signal its
2200    * parent to redraw, calculating the clip box as we go...
2201    *
2202    * stop if parent becomes NULL since then we'd have nowhere
2203    * to draw (ie: 'composited' will always be non-NULL here).
2204    */
2205   for (composited = private;
2206        composited->parent;
2207        composited = composited->parent)
2208     {
2209       int width, height;
2210
2211       gdk_drawable_get_size (GDK_DRAWABLE (composited->parent),
2212                              &width, &height);
2213
2214       clip_box.x += composited->x;
2215       clip_box.y += composited->y;
2216       clip_box.width = MIN (clip_box.width, width - clip_box.x);
2217       clip_box.height = MIN (clip_box.height, height - clip_box.y);
2218
2219       if (composited->composited)
2220         {
2221           gdk_window_invalidate_rect (GDK_WINDOW (composited->parent),
2222                                       &clip_box, FALSE);
2223           break;
2224         }
2225     }
2226 #endif /* USE_BACKING_STORE */
2227 }
2228
2229 static void
2230 gdk_window_free_paint_stack (GdkWindow *window)
2231 {
2232   GdkWindowObject *private = (GdkWindowObject *)window;
2233   
2234   if (private->paint_stack)
2235     {
2236       GSList *tmp_list = private->paint_stack;
2237
2238       while (tmp_list)
2239         {
2240           GdkWindowPaint *paint = tmp_list->data;
2241
2242           if (tmp_list == private->paint_stack)
2243             g_object_unref (paint->pixmap);
2244                   
2245           gdk_region_destroy (paint->region);
2246           g_free (paint);
2247
2248           tmp_list = tmp_list->next;
2249         }
2250
2251       g_slist_free (private->paint_stack);
2252       private->paint_stack = NULL;
2253     }
2254 }
2255
2256 static void
2257 do_move_region_bits_on_impl (GdkWindowObject *private,
2258                              GdkDrawable *dest,
2259                              int dest_off_x, int dest_off_y,
2260                              GdkRegion *region, /* In impl window coords */
2261                              int dx, int dy)
2262 {
2263   GdkGC *tmp_gc;
2264   GdkRectangle copy_rect;
2265   
2266   gdk_region_get_clipbox (region, &copy_rect);
2267   gdk_region_offset (region, -dest_off_x, -dest_off_y);
2268   tmp_gc = _gdk_drawable_get_scratch_gc ((GdkWindow *)private, TRUE);
2269   gdk_gc_set_clip_region (tmp_gc, region);
2270   gdk_draw_drawable (dest,
2271                      tmp_gc,
2272                      private->impl,
2273                      copy_rect.x-dx, copy_rect.y-dy,
2274                      copy_rect.x - dest_off_x, copy_rect.y - dest_off_y,
2275                      copy_rect.width, copy_rect.height);
2276   gdk_gc_set_clip_region (tmp_gc, NULL);
2277 }
2278
2279 static void
2280 append_move_region (GdkWindowObject *impl_window,
2281                     GdkRegion *region,
2282                     int dx, int dy)
2283 {
2284   GList *moves_to_add, *l, *s;
2285   GdkRegion *intersection;
2286   GdkWindowRegionMove *move, *new_move, *existing_move;
2287   
2288   move = g_slice_new (GdkWindowRegionMove);
2289   move->region  = region;
2290   move->dx = dx;
2291   move->dy = dy;
2292
2293   moves_to_add = g_list_prepend (NULL, move);
2294
2295   for (l = impl_window->outstanding_moves; l != NULL; l = l->next)
2296     {
2297       existing_move = l->data;
2298       
2299       for (s = moves_to_add; s != NULL; s = s->next)
2300         {
2301           move = s->data;
2302
2303           intersection = gdk_region_copy (move->region);
2304           gdk_region_offset (intersection, -move->dx, -move->dy);
2305           gdk_region_intersect (intersection, existing_move->region);
2306           gdk_region_offset (intersection, move->dx, move->dy);
2307
2308           if (!gdk_region_empty (intersection))
2309             {
2310               
2311               new_move = g_slice_new (GdkWindowRegionMove);
2312               new_move->region  = intersection;
2313               new_move->dx = move->dx + existing_move->dx;
2314               new_move->dy = move->dy + existing_move->dy;
2315               moves_to_add = g_list_prepend (moves_to_add, new_move);
2316
2317               gdk_region_subtract (move->region, intersection);
2318               gdk_region_subtract (existing_move->region, intersection);
2319             }
2320           else
2321             gdk_region_destroy (intersection);
2322         }
2323     }
2324
2325   impl_window->outstanding_moves = g_list_concat (impl_window->outstanding_moves,
2326                                                   moves_to_add);
2327   
2328 }
2329
2330 /* Moves bits and update area by dx/dy in impl window
2331  * Takes ownership of region.
2332  */
2333 static void
2334 move_region_on_impl (GdkWindowObject *private,
2335                      GdkRegion *region, /* In impl window coords */
2336                      int dx, int dy)
2337 {
2338   GdkWindowObject *impl_window;
2339   gboolean free_region;
2340
2341   free_region = TRUE;
2342   impl_window = gdk_window_get_impl_window (private);
2343
2344   if (1) /* Enable flicker free handling of moves. */
2345     {
2346       free_region = FALSE;
2347
2348       append_move_region (impl_window, region, dx, dy);
2349     }
2350   else
2351     do_move_region_bits_on_impl (private,
2352                                  private->impl, 0,0,
2353                                  region, dx, dy);
2354     
2355   /* Move any old invalid regions in the copy source area by dx/dy */
2356   if (impl_window->update_area)
2357     {
2358       GdkRegion *update_area;
2359       
2360       update_area = gdk_region_copy (region);
2361       /* Convert from target to source */
2362       gdk_region_offset (update_area, -dx, -dy);
2363       gdk_region_intersect (update_area, impl_window->update_area);
2364       gdk_region_subtract (impl_window->update_area, update_area);
2365       /* Convert back */
2366       gdk_region_offset (update_area, dx, dy);
2367       gdk_region_union (impl_window->update_area, update_area);
2368       gdk_region_destroy (update_area);
2369     }
2370
2371   if (free_region)
2372     gdk_region_destroy (region);
2373 }
2374
2375 /* Flushes all outstanding changes to the window, call this
2376  * before drawing directly to the window (i.e. outside a begin/end_paint pair).
2377  */
2378 static void
2379 gdk_window_flush (GdkWindow *window)
2380 {
2381   GdkWindowObject *private;
2382   GdkWindowObject *impl_window;
2383   GList *l;
2384   GdkWindowRegionMove *move;
2385
2386   private = (GdkWindowObject *) window;
2387   
2388   impl_window = gdk_window_get_impl_window (private);
2389   
2390   for (l = impl_window->outstanding_moves; l != NULL; l = l->next)
2391     {
2392       move = l->data;
2393
2394       do_move_region_bits_on_impl (private,
2395                                    private->impl, 0, 0,
2396                                    move->region, move->dx, move->dy);
2397
2398       gdk_region_destroy (move->region);
2399       g_slice_free (GdkWindowRegionMove, move);
2400     }
2401   
2402   g_list_free (impl_window->outstanding_moves);
2403   impl_window->outstanding_moves = NULL;
2404   
2405   gdk_window_flush_implicit_paint (window);
2406 }
2407
2408 static void
2409 gdk_window_get_offsets (GdkWindow *window,
2410                         gint      *x_offset,
2411                         gint      *y_offset)
2412 {
2413   GdkWindowObject *private = (GdkWindowObject *)window;
2414
2415   if (private->paint_stack)
2416     {
2417       GdkWindowPaint *paint = private->paint_stack->data;
2418       *x_offset = paint->x_offset;
2419       *y_offset = paint->y_offset;
2420     }
2421   else
2422     {
2423       *x_offset = -private->abs_x;
2424       *y_offset = -private->abs_y;
2425     }
2426 }
2427
2428 /**
2429  * gdk_window_get_internal_paint_info:
2430  * @window: a #GdkWindow
2431  * @real_drawable: location to store the drawable to which drawing should be 
2432  *            done.
2433  * @x_offset: location to store the X offset between coordinates in @window,
2434  *            and the underlying window system primitive coordinates for 
2435  *            *@real_drawable.
2436  * @y_offset: location to store the Y offset between coordinates in @window,
2437  *            and the underlying window system primitive coordinates for
2438  *            *@real_drawable.
2439  * 
2440  * If you bypass the GDK layer and use windowing system primitives to
2441  * draw directly onto a #GdkWindow, then you need to deal with two
2442  * details: there may be an offset between GDK coordinates and windowing
2443  * system coordinates, and GDK may have redirected drawing to a offscreen
2444  * pixmap as the result of a gdk_window_begin_paint_region() calls.
2445  * This function allows retrieving the information you need to compensate
2446  * for these effects.
2447  *
2448  * This function exposes details of the GDK implementation, and is thus
2449  * likely to change in future releases of GDK.
2450  **/
2451 void
2452 gdk_window_get_internal_paint_info (GdkWindow    *window,
2453                                     GdkDrawable **real_drawable,
2454                                     gint         *x_offset,
2455                                     gint         *y_offset)
2456 {
2457   gint x_off, y_off;
2458   
2459   GdkWindowObject *private;
2460
2461   g_return_if_fail (GDK_IS_WINDOW (window));
2462
2463   private = (GdkWindowObject *)window;
2464
2465   if (real_drawable)
2466     {
2467       if (private->paint_stack)
2468         {
2469           GdkWindowPaint *paint = private->paint_stack->data;
2470           *real_drawable = paint->pixmap;
2471         }
2472       else
2473         *real_drawable = window;
2474     }
2475
2476   gdk_window_get_offsets (window, &x_off, &y_off);
2477
2478   if (x_offset)
2479     *x_offset = x_off;
2480   if (y_offset)
2481     *y_offset = y_off;
2482 }
2483
2484 static void
2485 setup_clip_for_draw (GdkDrawable *drawable,
2486                      GdkGC *gc,
2487                      int old_clip_x, int old_clip_y)
2488 {
2489   GdkWindowObject *private = (GdkWindowObject *)drawable;
2490   GdkRegion *clip;
2491
2492   if (private->window_type == GDK_WINDOW_ROOT)
2493     return;
2494   
2495   if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
2496     clip = private->clip_region_with_children;
2497   else
2498     clip = private->clip_region;
2499     
2500   _gdk_gc_add_drawable_clip (gc,
2501                              private->clip_tag,
2502                              clip,
2503                              /* If there was a clip origin set appart from the
2504                               * window offset, need to take that into consideration */
2505                              -old_clip_x, -old_clip_y);
2506 }
2507
2508 static void
2509 setup_clip_for_paint (GdkDrawable *drawable,
2510                       GdkWindowPaint *paint,
2511                       GdkGC *gc,
2512                       int old_clip_x, int old_clip_y)
2513 {
2514   _gdk_gc_add_drawable_clip (gc,
2515                              paint->region_tag,
2516                              /* This includes the window clip */
2517                              paint->region,
2518                              /* If there was a clip origin set appart from the
2519                               * window offset, need to take that into consideration */
2520                              -old_clip_x, -old_clip_y);
2521 }
2522
2523
2524 #define OFFSET_GC(gc)                                         \
2525     gint x_offset, y_offset;                                  \
2526     gint old_clip_x = gc->clip_x_origin;    \
2527     gint old_clip_y = gc->clip_y_origin;    \
2528     gint old_ts_x = gc->ts_x_origin;        \
2529     gint old_ts_y = gc->ts_y_origin;        \
2530     gdk_window_get_offsets (drawable, &x_offset, &y_offset);  \
2531     if (x_offset != 0 || y_offset != 0)                       \
2532       {                                                       \
2533         gdk_gc_set_clip_origin (gc, old_clip_x - x_offset,    \
2534                                 old_clip_y - y_offset);       \
2535         gdk_gc_set_ts_origin (gc, old_ts_x - x_offset,        \
2536                               old_ts_y - y_offset);           \
2537       }
2538
2539 #define RESTORE_GC(gc)                                      \
2540     if (x_offset != 0 || y_offset != 0)                     \
2541      {                                                      \
2542        gdk_gc_set_clip_origin (gc, old_clip_x, old_clip_y); \
2543        gdk_gc_set_ts_origin (gc, old_ts_x, old_ts_y);       \
2544      }
2545
2546 #define SETUP_PAINT_GC_CLIP(gc)                             \
2547       if (paint->uses_implicit)                             \
2548         setup_clip_for_paint (drawable, paint, gc, old_clip_x,  \
2549                               old_clip_y);
2550
2551 #define RESTORE_PAINT_GC_CLIP(gc) 
2552
2553
2554 #define SETUP_DIRECT_GC_CLIP(gc)                            \
2555       gdk_window_flush ((GdkWindow *)drawable);\
2556       setup_clip_for_draw (drawable, gc, old_clip_x, old_clip_y);
2557
2558 #define RESTORE_DIRECT_GC_CLIP(gc)
2559
2560 static GdkGC *
2561 gdk_window_create_gc (GdkDrawable     *drawable,
2562                       GdkGCValues     *values,
2563                       GdkGCValuesMask  mask)
2564 {
2565   g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
2566   
2567   if (GDK_WINDOW_DESTROYED (drawable))
2568     return NULL;
2569
2570   return gdk_gc_new_with_values (((GdkWindowObject *) drawable)->impl,
2571                                  values, mask);
2572 }
2573
2574 /* After having set up the drawable clip rect on a GC we need
2575  * to make sure that if we draw to a pixmap we draw to the impl,
2576  * otherwise the pixmap code will reset the drawable clip.
2577  */
2578 static GdkDrawable *
2579 pixmap_impl (GdkPixmap *pixmap)
2580 {
2581   return ((GdkPixmapObject *)pixmap)->impl;
2582 }
2583
2584 static void
2585 gdk_window_draw_rectangle (GdkDrawable *drawable,
2586                            GdkGC       *gc,
2587                            gboolean     filled,
2588                            gint         x,
2589                            gint         y,
2590                            gint         width,
2591                            gint         height)
2592 {
2593   GdkWindowObject *private = (GdkWindowObject *)drawable;
2594   OFFSET_GC (gc);
2595
2596   if (GDK_WINDOW_DESTROYED (drawable))
2597     return;
2598   
2599   if (private->paint_stack)
2600     {
2601       GdkWindowPaint *paint = private->paint_stack->data;
2602       SETUP_PAINT_GC_CLIP (gc);
2603       gdk_draw_rectangle (pixmap_impl (paint->pixmap), gc, filled,
2604                           x - x_offset, y - y_offset, width, height);
2605       RESTORE_PAINT_GC_CLIP (gc);
2606     }
2607   else
2608     {
2609       SETUP_DIRECT_GC_CLIP(gc);
2610       gdk_draw_rectangle (private->impl, gc, filled,
2611                           x - x_offset, y - y_offset, width, height);
2612       RESTORE_DIRECT_GC_CLIP(gc);
2613     }
2614
2615   RESTORE_GC (gc);
2616 }
2617
2618 static void
2619 gdk_window_draw_arc (GdkDrawable *drawable,
2620                      GdkGC       *gc,
2621                      gboolean     filled,
2622                      gint         x,
2623                      gint         y,
2624                      gint         width,
2625                      gint         height,
2626                      gint         angle1,
2627                      gint         angle2)
2628 {
2629   GdkWindowObject *private = (GdkWindowObject *)drawable;
2630   OFFSET_GC (gc);
2631
2632   if (GDK_WINDOW_DESTROYED (drawable))
2633     return;
2634   
2635   if (private->paint_stack)
2636     {
2637       GdkWindowPaint *paint = private->paint_stack->data;
2638       SETUP_PAINT_GC_CLIP (gc);
2639       gdk_draw_arc (pixmap_impl (paint->pixmap), gc, filled,
2640                     x - x_offset, y - y_offset,
2641                     width, height, angle1, angle2);
2642       RESTORE_PAINT_GC_CLIP (gc);
2643     }
2644   else
2645     {
2646       SETUP_DIRECT_GC_CLIP(gc);
2647       gdk_draw_arc (private->impl, gc, filled,
2648                     x - x_offset, y - y_offset,
2649                     width, height, angle1, angle2);
2650       RESTORE_DIRECT_GC_CLIP(gc);
2651     }
2652   RESTORE_GC (gc);
2653 }
2654
2655 static void
2656 gdk_window_draw_polygon (GdkDrawable *drawable,
2657                          GdkGC       *gc,
2658                          gboolean     filled,
2659                          GdkPoint    *points,
2660                          gint         npoints)
2661 {
2662   GdkWindowObject *private = (GdkWindowObject *)drawable;
2663   GdkPoint *new_points;
2664   
2665   OFFSET_GC (gc);
2666
2667   if (GDK_WINDOW_DESTROYED (drawable))
2668     return;
2669   
2670   if (x_offset != 0 || y_offset != 0)
2671     {
2672       int i;
2673       
2674       new_points = g_new (GdkPoint, npoints);
2675       for (i=0; i<npoints; i++)
2676         {
2677           new_points[i].x = points[i].x - x_offset;
2678           new_points[i].y = points[i].y - y_offset;
2679         }
2680     }
2681   else
2682     new_points = points;
2683
2684   if (private->paint_stack)
2685     {
2686       GdkWindowPaint *paint = private->paint_stack->data;
2687       SETUP_PAINT_GC_CLIP (gc);
2688       gdk_draw_polygon (pixmap_impl (paint->pixmap), gc, filled, new_points, npoints);
2689       RESTORE_PAINT_GC_CLIP (gc);
2690     }
2691   else
2692     {
2693       SETUP_DIRECT_GC_CLIP(gc);
2694       gdk_draw_polygon (private->impl, gc, filled, new_points, npoints);
2695       RESTORE_DIRECT_GC_CLIP(gc);
2696     }
2697   
2698   if (new_points != points)
2699     g_free (new_points);
2700
2701   RESTORE_GC (gc);
2702 }
2703
2704 static void
2705 gdk_window_draw_text (GdkDrawable *drawable,
2706                       GdkFont     *font,
2707                       GdkGC       *gc,
2708                       gint         x,
2709                       gint         y,
2710                       const gchar *text,
2711                       gint         text_length)
2712 {
2713   GdkWindowObject *private = (GdkWindowObject *)drawable;
2714   OFFSET_GC (gc);
2715
2716   if (GDK_WINDOW_DESTROYED (drawable))
2717     return;
2718   
2719   if (private->paint_stack)
2720     {
2721       GdkWindowPaint *paint = private->paint_stack->data;
2722       SETUP_PAINT_GC_CLIP (gc);
2723       gdk_draw_text (pixmap_impl (paint->pixmap), font, gc, 
2724                      x - x_offset, y - y_offset, text, text_length);
2725
2726       RESTORE_PAINT_GC_CLIP (gc);
2727     }
2728   else
2729     {
2730       SETUP_DIRECT_GC_CLIP(gc);
2731       gdk_draw_text (private->impl, font, gc,
2732                      x - x_offset, y - y_offset, text, text_length);
2733       RESTORE_DIRECT_GC_CLIP(gc);
2734     }
2735
2736   RESTORE_GC (gc);
2737 }
2738
2739 static void
2740 gdk_window_draw_text_wc (GdkDrawable    *drawable,
2741                          GdkFont        *font,
2742                          GdkGC          *gc,
2743                          gint            x,
2744                          gint            y,
2745                          const GdkWChar *text,
2746                          gint            text_length)
2747 {
2748   GdkWindowObject *private = (GdkWindowObject *)drawable;
2749   OFFSET_GC (gc);
2750
2751   if (GDK_WINDOW_DESTROYED (drawable))
2752     return;
2753   
2754   if (private->paint_stack)
2755     {
2756       GdkWindowPaint *paint = private->paint_stack->data;
2757       SETUP_PAINT_GC_CLIP (gc);
2758       gdk_draw_text_wc (pixmap_impl (paint->pixmap), font, gc, 
2759                         x - x_offset, y - y_offset, text, text_length);
2760       RESTORE_PAINT_GC_CLIP (gc);
2761     }
2762   else
2763     {
2764       SETUP_DIRECT_GC_CLIP(gc);
2765       gdk_draw_text_wc (private->impl, font, gc,
2766                         x - x_offset, y - y_offset, text, text_length);
2767       RESTORE_DIRECT_GC_CLIP(gc);
2768     }
2769   
2770   RESTORE_GC (gc);
2771 }
2772
2773 static GdkDrawable *
2774 gdk_window_get_source_drawable (GdkDrawable *drawable)
2775 {
2776   GdkWindow *window = GDK_WINDOW (drawable);
2777   GdkWindowObject *private;
2778
2779   private = (GdkWindowObject *) window;
2780   if (GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable)
2781     return GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable (private->impl);
2782   
2783   return drawable;
2784 }
2785
2786 static GdkDrawable *
2787 gdk_window_get_composite_drawable (GdkDrawable *drawable,
2788                                    gint         x,
2789                                    gint         y,
2790                                    gint         width,
2791                                    gint         height,
2792                                    gint        *composite_x_offset,
2793                                    gint        *composite_y_offset)
2794 {
2795   GdkWindowObject *private = (GdkWindowObject *)drawable;
2796   GSList *list;
2797   GdkPixmap *tmp_pixmap;
2798   GdkRectangle rect;
2799   GdkGC *tmp_gc;
2800   gboolean overlap_buffer;
2801   GdkDrawable *source;
2802   GdkWindowObject *impl_window;
2803   GdkWindowPaint *implicit_paint;
2804
2805   *composite_x_offset = -private->abs_x;
2806   *composite_y_offset = -private->abs_y;
2807
2808   if ((GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable)))
2809     return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
2810
2811   /* See if any buffered part is overlapping the part we want
2812    * to get
2813    */
2814   rect.x = x;
2815   rect.y = y;
2816   rect.width = width;
2817   rect.height = height;
2818
2819   overlap_buffer = FALSE;
2820
2821   for (list = private->paint_stack; list != NULL; list = list->next)
2822     {
2823       GdkWindowPaint *paint = list->data;
2824       GdkOverlapType overlap;
2825       
2826       overlap = gdk_region_rect_in (paint->region, &rect);
2827       
2828       if (overlap == GDK_OVERLAP_RECTANGLE_IN)
2829         {
2830           *composite_x_offset = paint->x_offset;
2831           *composite_y_offset = paint->y_offset;
2832           
2833           return g_object_ref (paint->pixmap);
2834         }
2835       else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
2836         {
2837           overlap_buffer = TRUE;
2838           break;
2839         }
2840     }
2841
2842   impl_window = gdk_window_get_impl_window (private);
2843   implicit_paint = impl_window->implicit_paint;
2844   if (implicit_paint)
2845     {
2846       GdkOverlapType overlap;
2847
2848       rect.x += private->abs_x;
2849       rect.y += private->abs_y;
2850       
2851       overlap = gdk_region_rect_in (implicit_paint->region, &rect);
2852       if (overlap == GDK_OVERLAP_RECTANGLE_IN)
2853         {
2854           *composite_x_offset = -private->abs_x + implicit_paint->x_offset;
2855           *composite_y_offset = -private->abs_y + implicit_paint->y_offset;
2856           
2857           return g_object_ref (implicit_paint->pixmap);
2858         }
2859       else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
2860         overlap_buffer = TRUE;
2861     }
2862
2863   if (!overlap_buffer)
2864     return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
2865   
2866   tmp_pixmap = gdk_pixmap_new (drawable, width, height, -1);
2867   tmp_gc = _gdk_drawable_get_scratch_gc (tmp_pixmap, FALSE);
2868
2869   source = _gdk_drawable_get_source_drawable (drawable);
2870   
2871   /* Copy the current window contents */
2872   gdk_draw_drawable (tmp_pixmap,
2873                      tmp_gc,
2874                      GDK_WINDOW_OBJECT (source)->impl,
2875                      x - *composite_x_offset,
2876                      y - *composite_y_offset,
2877                      0, 0,
2878                      width, height);
2879
2880   /* paint the backing stores */
2881   if (implicit_paint)
2882     {
2883       GdkWindowPaint *paint = list->data;
2884       
2885       gdk_gc_set_clip_region (tmp_gc, paint->region);
2886       gdk_gc_set_clip_origin (tmp_gc, -x  - paint->x_offset, -y  - paint->y_offset);
2887       
2888       gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
2889                          x - paint->x_offset,
2890                          y - paint->y_offset,
2891                          0, 0, width, height);
2892     }
2893   
2894   for (list = private->paint_stack; list != NULL; list = list->next)
2895     {
2896       GdkWindowPaint *paint = list->data;
2897
2898       if (paint->uses_implicit)
2899         continue; /* We already copied this above */
2900       
2901       gdk_gc_set_clip_region (tmp_gc, paint->region);
2902       gdk_gc_set_clip_origin (tmp_gc, -x, -y);
2903       
2904       gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
2905                          x - paint->x_offset,
2906                          y - paint->y_offset,
2907                          0, 0, width, height);
2908     }
2909   
2910   /* Reset clip region of the cached GdkGC */
2911   gdk_gc_set_clip_region (tmp_gc, NULL);
2912
2913   /* Set these to location of tmp_pixmap within the window */
2914   *composite_x_offset = x;
2915   *composite_y_offset = y;
2916
2917   return tmp_pixmap;
2918 }
2919
2920 static GdkRegion*
2921 gdk_window_get_clip_region (GdkDrawable *drawable)
2922 {
2923   GdkWindowObject *private = (GdkWindowObject *)drawable;
2924   GdkRegion *result;
2925
2926   result = gdk_region_copy (private->clip_region);
2927
2928   if (private->paint_stack)
2929     {
2930       GdkRegion *paint_region = gdk_region_new ();
2931       GSList *tmp_list = private->paint_stack;
2932
2933       while (tmp_list)
2934         {
2935           GdkWindowPaint *paint = tmp_list->data;
2936           
2937           gdk_region_union (paint_region, paint->region);
2938
2939           tmp_list = tmp_list->next;
2940         }
2941
2942       gdk_region_intersect (result, paint_region);
2943       gdk_region_destroy (paint_region);
2944     }
2945
2946   return result;
2947 }
2948
2949 static GdkRegion*
2950 gdk_window_get_visible_region (GdkDrawable *drawable)
2951 {
2952   GdkWindowObject *private = (GdkWindowObject*) drawable;
2953
2954   return gdk_region_copy (private->clip_region);
2955 }
2956
2957 static void
2958 gdk_window_draw_drawable (GdkDrawable *drawable,
2959                           GdkGC       *gc,
2960                           GdkPixmap   *src,
2961                           gint         xsrc,
2962                           gint         ysrc,
2963                           gint         xdest,
2964                           gint         ydest,
2965                           gint         width,
2966                           gint         height)
2967 {
2968   GdkWindowObject *private = (GdkWindowObject *)drawable;
2969   OFFSET_GC (gc);
2970   
2971   if (GDK_WINDOW_DESTROYED (drawable))
2972     return;
2973
2974   /* If we have a backing pixmap draw to that */
2975   if (private->paint_stack)
2976     {
2977       GdkWindowPaint *paint = private->paint_stack->data;
2978       SETUP_PAINT_GC_CLIP (gc);
2979       gdk_draw_drawable (pixmap_impl (paint->pixmap), gc,
2980                          src, xsrc, ysrc,
2981                          xdest - x_offset, ydest - y_offset, width, height);
2982
2983       RESTORE_PAINT_GC_CLIP (gc);
2984     }
2985   else
2986     {
2987       SETUP_DIRECT_GC_CLIP(gc);
2988       gdk_draw_drawable (private->impl, gc,
2989                          src, xsrc, ysrc,
2990                          xdest - x_offset, ydest - y_offset,
2991                          width, height);
2992       RESTORE_DIRECT_GC_CLIP(gc);
2993     }
2994
2995   RESTORE_GC (gc);
2996 }
2997
2998 static void
2999 gdk_window_draw_points (GdkDrawable *drawable,
3000                         GdkGC       *gc,
3001                         GdkPoint    *points,
3002                         gint         npoints)
3003 {
3004   GdkWindowObject *private = (GdkWindowObject *)drawable;
3005   GdkPoint *new_points;
3006   
3007   OFFSET_GC (gc);
3008
3009   if (GDK_WINDOW_DESTROYED (drawable))
3010     return;
3011   
3012   if (x_offset != 0 || y_offset != 0)
3013     {
3014       gint i;
3015
3016       new_points = g_new (GdkPoint, npoints);
3017       for (i=0; i<npoints; i++)
3018         {
3019           new_points[i].x = points[i].x - x_offset;
3020           new_points[i].y = points[i].y - y_offset;
3021         }
3022     }
3023   else
3024     new_points = points;
3025
3026   if (private->paint_stack)
3027     {
3028       GdkWindowPaint *paint = private->paint_stack->data;
3029       SETUP_PAINT_GC_CLIP (gc);
3030       gdk_draw_points (pixmap_impl (paint->pixmap), gc, new_points, npoints);
3031       RESTORE_PAINT_GC_CLIP (gc);
3032     }
3033   else
3034     {
3035       SETUP_DIRECT_GC_CLIP(gc);
3036       gdk_draw_points (private->impl, gc, new_points, npoints);
3037       RESTORE_DIRECT_GC_CLIP(gc);
3038     }
3039
3040   if (new_points != points)
3041     g_free (new_points);
3042
3043   RESTORE_GC (gc);
3044 }
3045
3046 static void
3047 gdk_window_draw_segments (GdkDrawable *drawable,
3048                           GdkGC       *gc,
3049                           GdkSegment  *segs,
3050                           gint         nsegs)
3051 {
3052   GdkWindowObject *private = (GdkWindowObject *)drawable;
3053   GdkSegment *new_segs;
3054
3055   OFFSET_GC (gc);
3056
3057   if (GDK_WINDOW_DESTROYED (drawable))
3058     return;
3059   
3060   if (x_offset != 0 || y_offset != 0)
3061     {
3062       gint i;
3063
3064       new_segs = g_new (GdkSegment, nsegs);
3065       for (i=0; i<nsegs; i++)
3066         {
3067           new_segs[i].x1 = segs[i].x1 - x_offset;
3068           new_segs[i].y1 = segs[i].y1 - y_offset;
3069           new_segs[i].x2 = segs[i].x2 - x_offset;
3070           new_segs[i].y2 = segs[i].y2 - y_offset;
3071         }
3072     }
3073   else
3074     new_segs = segs;
3075
3076   if (private->paint_stack)
3077     {
3078       GdkWindowPaint *paint = private->paint_stack->data;
3079       SETUP_PAINT_GC_CLIP (gc);
3080       gdk_draw_segments (pixmap_impl (paint->pixmap), gc, new_segs, nsegs);
3081       RESTORE_PAINT_GC_CLIP (gc);
3082     }
3083   else
3084     {
3085       SETUP_DIRECT_GC_CLIP(gc);
3086       gdk_draw_segments (private->impl, gc, new_segs, nsegs);
3087       RESTORE_DIRECT_GC_CLIP(gc);
3088     }
3089   
3090   if (new_segs != segs)
3091     g_free (new_segs);
3092
3093   RESTORE_GC (gc);
3094 }
3095
3096 static void
3097 gdk_window_draw_lines (GdkDrawable *drawable,
3098                        GdkGC       *gc,
3099                        GdkPoint    *points,
3100                        gint         npoints)
3101 {
3102   GdkWindowObject *private = (GdkWindowObject *)drawable;
3103   GdkPoint *new_points;
3104
3105   OFFSET_GC (gc);
3106
3107   if (GDK_WINDOW_DESTROYED (drawable))
3108     return;
3109   
3110   if (x_offset != 0 || y_offset != 0)
3111     {
3112       gint i;
3113
3114       new_points = g_new (GdkPoint, npoints);
3115       for (i=0; i<npoints; i++)
3116         {
3117           new_points[i].x = points[i].x - x_offset;
3118           new_points[i].y = points[i].y - y_offset;
3119         }
3120     }
3121   else
3122     new_points = points;
3123
3124   if (private->paint_stack)
3125     {
3126       GdkWindowPaint *paint = private->paint_stack->data;
3127       SETUP_PAINT_GC_CLIP (gc);
3128       gdk_draw_lines (pixmap_impl (paint->pixmap), gc, new_points, npoints);
3129       RESTORE_PAINT_GC_CLIP (gc);
3130     }
3131   else
3132     {
3133       SETUP_DIRECT_GC_CLIP(gc);
3134       gdk_draw_lines (private->impl, gc, new_points, npoints);
3135       RESTORE_DIRECT_GC_CLIP(gc);
3136     }
3137
3138   if (new_points != points)
3139     g_free (new_points);
3140
3141   RESTORE_GC (gc);
3142 }
3143
3144 static void
3145 gdk_window_draw_glyphs (GdkDrawable      *drawable,
3146                         GdkGC            *gc,
3147                         PangoFont        *font,
3148                         gint              x,
3149                         gint              y,
3150                         PangoGlyphString *glyphs)
3151 {
3152   GdkWindowObject *private = (GdkWindowObject *)drawable;
3153
3154   OFFSET_GC (gc);
3155
3156   if (GDK_WINDOW_DESTROYED (drawable))
3157     return;
3158   
3159   if (private->paint_stack)
3160     {
3161       GdkWindowPaint *paint = private->paint_stack->data;
3162
3163       SETUP_PAINT_GC_CLIP (gc);
3164       gdk_draw_glyphs (pixmap_impl (paint->pixmap), gc, font, x - x_offset, y - y_offset, glyphs);
3165       RESTORE_PAINT_GC_CLIP (gc);
3166     }
3167   else
3168     {
3169       SETUP_DIRECT_GC_CLIP(gc);
3170       gdk_draw_glyphs (private->impl, gc, font,
3171                        x - x_offset, y - y_offset, glyphs);
3172       RESTORE_DIRECT_GC_CLIP(gc);
3173     }
3174
3175   RESTORE_GC (gc);
3176 }
3177
3178 static void
3179 gdk_window_draw_glyphs_transformed (GdkDrawable      *drawable,
3180                                     GdkGC            *gc,
3181                                     PangoMatrix      *matrix,
3182                                     PangoFont        *font,
3183                                     gint              x,
3184                                     gint              y,
3185                                     PangoGlyphString *glyphs)
3186 {
3187   GdkWindowObject *private = (GdkWindowObject *)drawable;
3188   PangoMatrix tmp_matrix;
3189
3190   OFFSET_GC (gc);
3191
3192   if (GDK_WINDOW_DESTROYED (drawable))
3193     return;
3194
3195   if (x_offset != 0 || y_offset != 0)
3196     {
3197       if (matrix)
3198         {
3199           tmp_matrix = *matrix;
3200           tmp_matrix.x0 -= x_offset;
3201           tmp_matrix.y0 -= y_offset;
3202           matrix = &tmp_matrix;
3203         }
3204       else if (GDK_PANGO_UNITS_OVERFLOWS (x_offset, y_offset))
3205         {
3206           PangoMatrix identity = PANGO_MATRIX_INIT;
3207           
3208           tmp_matrix = identity;
3209           tmp_matrix.x0 -= x_offset;
3210           tmp_matrix.y0 -= y_offset;
3211           matrix = &tmp_matrix;
3212         }
3213       else
3214         {
3215           x -= x_offset * PANGO_SCALE;
3216           y -= y_offset * PANGO_SCALE;
3217         }
3218     }
3219   
3220   if (private->paint_stack)
3221     {
3222       GdkWindowPaint *paint = private->paint_stack->data;
3223
3224       SETUP_PAINT_GC_CLIP (gc);
3225       gdk_draw_glyphs_transformed (pixmap_impl (paint->pixmap), gc, matrix, font, x, y, glyphs);
3226       RESTORE_PAINT_GC_CLIP (gc);
3227     }
3228   else
3229     {
3230       SETUP_DIRECT_GC_CLIP(gc);
3231       gdk_draw_glyphs_transformed (private->impl, gc, matrix, font, x, y, glyphs);
3232       RESTORE_DIRECT_GC_CLIP(gc);
3233     }
3234
3235   RESTORE_GC (gc);
3236 }
3237
3238 typedef struct {
3239   cairo_t *cr; /* if non-null, it means use this cairo context */
3240   GdkGC *gc;   /* if non-null, it means use this GC instead */
3241 } BackingRectMethod;
3242
3243 static void
3244 setup_backing_rect_method (BackingRectMethod *method, GdkWindow *window, GdkWindowPaint *paint, int x_offset_cairo, int y_offset_cairo)
3245 {
3246   GdkWindowObject *private = (GdkWindowObject *)window;
3247
3248   if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
3249     {
3250       GdkWindowPaint tmp_paint;
3251
3252       tmp_paint = *paint;
3253       tmp_paint.x_offset += private->x;
3254       tmp_paint.y_offset += private->y;
3255
3256       x_offset_cairo += private->x;
3257       y_offset_cairo += private->y;
3258
3259       setup_backing_rect_method (method, GDK_WINDOW (private->parent), &tmp_paint, x_offset_cairo, y_offset_cairo);
3260     }
3261   else if (private->bg_pixmap &&
3262            private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
3263            private->bg_pixmap != GDK_NO_BG)
3264     {
3265 /* This is a workaround for https://bugs.freedesktop.org/show_bug.cgi?id=4320.
3266  * In it, using a pixmap as a repeating pattern in Cairo, and painting it to a
3267  * pixmap destination surface, can be very slow (on the order of seconds for a
3268  * whole-screen copy).  The workaround is to use pretty much the same code that
3269  * we used in GTK+ 2.6 (pre-Cairo), which clears the double-buffer pixmap with
3270  * a tiled GC XFillRectangle().
3271  */
3272
3273 /* Actually computing this flag is left as an exercise for the reader */
3274 #if defined (G_OS_UNIX)
3275 #  define GDK_CAIRO_REPEAT_IS_FAST 0
3276 #else
3277 #  define GDK_CAIRO_REPEAT_IS_FAST 1
3278 #endif
3279
3280 #if GDK_CAIRO_REPEAT_IS_FAST
3281       cairo_surface_t *surface = _gdk_drawable_ref_cairo_surface (private->bg_pixmap);
3282       cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
3283       cairo_surface_destroy (surface);
3284
3285       if (x_offset_cairo != 0 || y_offset_cairo != 0)
3286         {
3287           cairo_matrix_t matrix;
3288           cairo_matrix_init_translate (&matrix, x_offset_cairo, y_offset_cairo);
3289           cairo_pattern_set_matrix (pattern, &matrix);
3290         }
3291
3292       cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
3293
3294       method->cr = cairo_create (paint->surface);
3295       method->gc = NULL;
3296
3297       cairo_set_source (method->cr, pattern);
3298       cairo_pattern_destroy (pattern);
3299 #else
3300       guint gc_mask;
3301       GdkGCValues gc_values;
3302
3303       gc_values.fill = GDK_TILED;
3304       gc_values.tile = private->bg_pixmap;
3305       gc_values.ts_x_origin = -x_offset_cairo;
3306       gc_values.ts_y_origin = -y_offset_cairo;
3307
3308       gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN;
3309
3310       method->gc = gdk_gc_new_with_values (paint->pixmap, &gc_values, gc_mask);
3311 #endif
3312     }
3313   else
3314     {
3315       method->cr = cairo_create (paint->surface);
3316
3317       gdk_cairo_set_source_color (method->cr, &private->bg_color);
3318     }
3319 }
3320
3321 static void
3322 gdk_window_clear_backing_rect (GdkWindow *window,
3323                                gint       x,
3324                                gint       y,
3325                                gint       width,
3326                                gint       height)
3327 {
3328   GdkWindowObject *private = (GdkWindowObject *)window;
3329   GdkWindowPaint *paint = private->paint_stack->data;
3330   BackingRectMethod method;
3331 #if 0
3332   GTimer *timer;
3333   double elapsed;
3334 #endif
3335
3336   if (GDK_WINDOW_DESTROYED (window))
3337     return;
3338
3339 #if 0
3340   timer = g_timer_new ();
3341 #endif
3342
3343   method.cr = NULL;
3344   method.gc = NULL;
3345   setup_backing_rect_method (&method, window, paint, 0, 0);
3346
3347   if (method.cr)
3348     {
3349       g_assert (method.gc == NULL);
3350
3351       cairo_rectangle (method.cr, x, y, width, height);
3352       cairo_clip (method.cr);
3353
3354       gdk_cairo_region (method.cr, paint->region);
3355       cairo_fill (method.cr);
3356
3357       cairo_destroy (method.cr);
3358 #if 0
3359       elapsed = g_timer_elapsed (timer, NULL);
3360       g_print ("Draw the background with Cairo: %fs\n", elapsed);
3361 #endif
3362     }
3363   else
3364     {
3365       g_assert (method.gc != NULL);
3366
3367       gdk_gc_set_clip_region (method.gc, paint->region);
3368       gdk_draw_rectangle (window, method.gc, TRUE, x, y, width, height);
3369       g_object_unref (method.gc);
3370
3371 #if 0
3372       elapsed = g_timer_elapsed (timer, NULL);
3373       g_print ("Draw the background with GDK: %fs\n", elapsed);
3374 #endif
3375     }
3376
3377 #if 0
3378   g_timer_destroy (timer);
3379 #endif
3380 }
3381
3382 static void
3383 gdk_window_clear_backing_rect_redirect (GdkWindow *window,
3384                                         gint       x,
3385                                         gint       y,
3386                                         gint       width,
3387                                         gint       height)
3388 {
3389   GdkWindowObject *private = (GdkWindowObject *)window;
3390   GdkWindowRedirect *redirect = private->redirect;
3391   GdkRegion *clip_region;
3392   gint x_offset, y_offset;
3393   BackingRectMethod method;
3394   GdkWindowPaint paint;
3395   
3396   if (GDK_WINDOW_DESTROYED (window))
3397     return;
3398
3399   clip_region = _gdk_window_calculate_full_clip_region (window,
3400                                                         GDK_WINDOW (redirect->redirected),
3401                                                         TRUE,
3402                                                         &x_offset, &y_offset);
3403   
3404   paint.x_offset = x_offset;
3405   paint.y_offset = y_offset;
3406   paint.pixmap = redirect->pixmap;
3407   paint.surface = _gdk_drawable_ref_cairo_surface (redirect->pixmap);
3408   
3409   method.cr = NULL;
3410   method.gc = NULL;
3411   setup_backing_rect_method (&method, window, &paint, 0, 0);
3412
3413   if (method.cr)
3414     {
3415       g_assert (method.gc == NULL);
3416
3417       cairo_rectangle (method.cr, x, y, width, height);
3418       cairo_clip (method.cr);
3419
3420       gdk_cairo_region (method.cr, clip_region);
3421       cairo_fill (method.cr);
3422
3423       cairo_destroy (method.cr);
3424     }
3425   else
3426     {
3427       g_assert (method.gc != NULL);
3428
3429       gdk_gc_set_clip_region (method.gc, clip_region);
3430       gdk_draw_rectangle (window, method.gc, TRUE, x, y, width, height);
3431       g_object_unref (method.gc);
3432
3433     }
3434
3435   gdk_region_destroy (clip_region);
3436   cairo_surface_destroy (paint.surface);
3437 }
3438
3439 static void
3440 gdk_window_clear_backing_rect_direct (GdkWindow *window,
3441                                       gint       x,
3442                                       gint       y,
3443                                       gint       width,
3444                                       gint       height)
3445 {
3446   GdkWindowObject *private = (GdkWindowObject *)window;
3447   BackingRectMethod method;
3448   GdkWindowPaint paint;
3449   
3450   if (GDK_WINDOW_DESTROYED (window))
3451     return;
3452
3453   paint.x_offset = 0;
3454   paint.y_offset = 0;
3455   paint.pixmap = window;
3456   paint.surface = _gdk_drawable_ref_cairo_surface (window);
3457   
3458   method.cr = NULL;
3459   method.gc = NULL;
3460   setup_backing_rect_method (&method, window, &paint, 0, 0);
3461
3462   if (method.cr)
3463     {
3464       g_assert (method.gc == NULL);
3465
3466       gdk_cairo_region (method.cr, private->clip_region_with_children);
3467       cairo_clip (method.cr);
3468       
3469       cairo_rectangle (method.cr, x, y, width, height);
3470       cairo_fill (method.cr);
3471
3472       cairo_destroy (method.cr);
3473     }
3474   else
3475     {
3476       g_assert (method.gc != NULL);
3477
3478       gdk_gc_set_clip_region (method.gc, private->clip_region_with_children);
3479       gdk_draw_rectangle (window, method.gc, TRUE, x, y, width, height);
3480       g_object_unref (method.gc);
3481
3482     }
3483
3484   cairo_surface_destroy (paint.surface);
3485 }
3486
3487
3488 /**
3489  * gdk_window_clear:
3490  * @window: a #GdkWindow
3491  * 
3492  * Clears an entire @window to the background color or background pixmap.
3493  **/
3494 void
3495 gdk_window_clear (GdkWindow *window)
3496 {
3497   gint width, height;
3498
3499   g_return_if_fail (GDK_IS_WINDOW (window));
3500
3501   gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height);
3502   
3503   gdk_window_clear_area (window, 0, 0,
3504                          width, height);
3505 }
3506
3507 static void
3508 gdk_window_clear_area_internal (GdkWindow *window,
3509                                 gint       x,
3510                                 gint       y,
3511                                 gint       width,
3512                                 gint       height,
3513                                 gboolean   send_expose)
3514 {
3515   GdkWindowObject *private = (GdkWindowObject *)window;
3516
3517   g_return_if_fail (GDK_IS_WINDOW (window));
3518
3519   /* This is what XClearArea does, and e.g. GtkCList uses it,
3520      so we need to duplicate that */
3521   if (width == 0)
3522     width = private->width - x;
3523   if (height == 0)
3524     height = private->height - y;
3525   
3526   if (private->paint_stack)
3527     gdk_window_clear_backing_rect (window, x, y, width, height);
3528   else
3529     {
3530       if (private->redirect)
3531         gdk_window_clear_backing_rect_redirect (window, x, y, width, height);
3532
3533       
3534       
3535       gdk_window_clear_backing_rect_direct (window, x, y, width, height);
3536       if (send_expose)
3537         {
3538           GdkRectangle rect;
3539
3540           rect.x = x;
3541           rect.y = x;
3542           rect.width = width;
3543           rect.height = height;
3544           
3545           gdk_window_invalidate_rect (window, &rect, FALSE);
3546         }
3547     }
3548 }
3549
3550
3551 /**
3552  * gdk_window_clear_area:
3553  * @window: a #GdkWindow
3554  * @x: x coordinate of rectangle to clear
3555  * @y: y coordinate of rectangle to clear
3556  * @width: width of rectangle to clear
3557  * @height: height of rectangle to clear
3558  *
3559  * Clears an area of @window to the background color or background pixmap.
3560  * 
3561  **/
3562 void
3563 gdk_window_clear_area (GdkWindow *window,
3564                        gint       x,
3565                        gint       y,
3566                        gint       width,
3567                        gint       height)
3568 {
3569   gdk_window_clear_area_internal (window,
3570                                   x, y,
3571                                   width, height,
3572                                   FALSE);
3573 }
3574
3575 /**
3576  * gdk_window_clear_area_e:
3577  * @window: a #GdkWindow
3578  * @x: x coordinate of rectangle to clear
3579  * @y: y coordinate of rectangle to clear
3580  * @width: width of rectangle to clear
3581  * @height: height of rectangle to clear
3582  *
3583  * Like gdk_window_clear_area(), but also generates an expose event for
3584  * the cleared area.
3585  *
3586  * This function has a stupid name because it dates back to the mists
3587  * time, pre-GDK-1.0.
3588  * 
3589  **/
3590 void
3591 gdk_window_clear_area_e (GdkWindow *window,
3592                          gint       x,
3593                          gint       y,
3594                          gint       width,
3595                          gint       height)
3596 {
3597   gdk_window_clear_area_internal (window,
3598                                   x, y,
3599                                   width, height,
3600                                   TRUE);
3601 }
3602
3603 static void
3604 gdk_window_draw_image (GdkDrawable *drawable,
3605                        GdkGC       *gc,
3606                        GdkImage    *image,
3607                        gint         xsrc,
3608                        gint         ysrc,
3609                        gint         xdest,
3610                        gint         ydest,
3611                        gint         width,
3612                        gint         height)
3613 {
3614   GdkWindowObject *private = (GdkWindowObject *)drawable;
3615
3616   OFFSET_GC (gc);
3617
3618   if (GDK_WINDOW_DESTROYED (drawable))
3619     return;
3620   
3621   if (private->paint_stack)
3622     {
3623       GdkWindowPaint *paint = private->paint_stack->data;
3624       SETUP_PAINT_GC_CLIP (gc);
3625       gdk_draw_image (pixmap_impl (paint->pixmap), gc, image, xsrc, ysrc,
3626                       xdest - x_offset, ydest - y_offset,
3627                       width, height);
3628
3629       RESTORE_PAINT_GC_CLIP (gc);
3630     }
3631   else
3632     {
3633       SETUP_DIRECT_GC_CLIP(gc);
3634       gdk_draw_image (private->impl, gc, image, xsrc, ysrc,
3635                       xdest - x_offset, ydest - y_offset,
3636                       width, height);
3637       RESTORE_DIRECT_GC_CLIP(gc);
3638     }
3639
3640   RESTORE_GC (gc);
3641 }
3642
3643 static void
3644 gdk_window_draw_pixbuf (GdkDrawable     *drawable,
3645                         GdkGC           *gc,
3646                         GdkPixbuf       *pixbuf,
3647                         gint             src_x,
3648                         gint             src_y,
3649                         gint             dest_x,
3650                         gint             dest_y,
3651                         gint             width,
3652                         gint             height,
3653                         GdkRgbDither     dither,
3654                         gint             x_dither,
3655                         gint             y_dither)
3656 {
3657   GdkWindowObject *private = (GdkWindowObject *)drawable;
3658
3659   if (GDK_WINDOW_DESTROYED (drawable))
3660     return;
3661   
3662   if (gc)
3663     {
3664       OFFSET_GC (gc);
3665   
3666       if (private->paint_stack)
3667         {
3668           GdkWindowPaint *paint = private->paint_stack->data;
3669           SETUP_PAINT_GC_CLIP (gc);
3670           gdk_draw_pixbuf (pixmap_impl (paint->pixmap), gc, pixbuf, src_x, src_y,
3671                            dest_x - x_offset, dest_y - y_offset,
3672                            width, height,
3673                            dither, x_dither - x_offset, y_dither - y_offset);
3674           RESTORE_PAINT_GC_CLIP (gc);
3675         }
3676       else
3677         {
3678           SETUP_DIRECT_GC_CLIP(gc);
3679           gdk_draw_pixbuf (private->impl, gc, pixbuf, src_x, src_y,
3680                            dest_x - x_offset, dest_y - y_offset,
3681                            width, height,
3682                            dither, x_dither, y_dither);
3683           RESTORE_DIRECT_GC_CLIP(gc);
3684         }
3685       
3686       RESTORE_GC (gc);
3687     }
3688   else
3689     {
3690       gint x_offset, y_offset;
3691       gdk_window_get_offsets (drawable, &x_offset, &y_offset);
3692       
3693       if (private->paint_stack)
3694         {
3695           GdkWindowPaint *paint = private->paint_stack->data;
3696           /* TODO: Do paint clipping here... */
3697           gdk_draw_pixbuf (paint->pixmap, gc, pixbuf, src_x, src_y,
3698                            dest_x - x_offset, dest_y - y_offset,
3699                            width, height,
3700                             dither, x_dither - x_offset, y_dither - y_offset);
3701         }
3702       else
3703         {
3704           /* TODO: No GC passed in, but still want clipping here... */
3705           gdk_draw_pixbuf (private->impl, gc, pixbuf, src_x, src_y,
3706                            dest_x - x_offset, dest_y - y_offset,
3707                            width, height,
3708                            dither, x_dither, y_dither);
3709         }
3710     }
3711 }
3712
3713 static void
3714 gdk_window_draw_trapezoids (GdkDrawable   *drawable,
3715                             GdkGC         *gc,
3716                             GdkTrapezoid  *trapezoids,
3717                             gint           n_trapezoids)
3718 {
3719   GdkWindowObject *private = (GdkWindowObject *)drawable;
3720   GdkTrapezoid *new_trapezoids = NULL;
3721
3722   OFFSET_GC (gc);
3723
3724   if (GDK_WINDOW_DESTROYED (drawable))
3725     return;
3726   
3727   if (x_offset != 0 || y_offset != 0)
3728     {
3729       gint i;
3730
3731       new_trapezoids = g_new (GdkTrapezoid, n_trapezoids);
3732       for (i=0; i < n_trapezoids; i++)
3733         {
3734           new_trapezoids[i].y1 = trapezoids[i].y1 - y_offset;
3735           new_trapezoids[i].x11 = trapezoids[i].x11 - x_offset;
3736           new_trapezoids[i].x21 = trapezoids[i].x21 - x_offset;
3737           new_trapezoids[i].y2 = trapezoids[i].y2 - y_offset;
3738           new_trapezoids[i].x12 = trapezoids[i].x12 - x_offset;
3739           new_trapezoids[i].x22 = trapezoids[i].x22 - x_offset;
3740         }
3741
3742       trapezoids = new_trapezoids;
3743     }
3744
3745   if (private->paint_stack)
3746     {
3747       GdkWindowPaint *paint = private->paint_stack->data;
3748       SETUP_PAINT_GC_CLIP (gc);
3749       gdk_draw_trapezoids (pixmap_impl (paint->pixmap), gc, trapezoids, n_trapezoids);
3750       RESTORE_PAINT_GC_CLIP (gc);
3751     }
3752   else
3753     {
3754       SETUP_DIRECT_GC_CLIP(gc);
3755       gdk_draw_trapezoids (private->impl, gc, trapezoids, n_trapezoids);
3756       RESTORE_DIRECT_GC_CLIP(gc);
3757     }
3758   
3759   g_free (new_trapezoids);
3760
3761   RESTORE_GC (gc);
3762 }
3763
3764 static void
3765 gdk_window_real_get_size (GdkDrawable *drawable,
3766                           gint *width,
3767                           gint *height)
3768 {
3769   GdkWindowObject *private = (GdkWindowObject *)drawable;
3770
3771   if (width)
3772     *width = private->width;
3773   if (height)
3774     *height = private->height;
3775 }
3776
3777 static GdkVisual*
3778 gdk_window_real_get_visual (GdkDrawable *drawable)
3779 {
3780   GdkColormap *colormap;
3781
3782   g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
3783
3784   colormap = gdk_drawable_get_colormap (drawable);
3785   return colormap ? gdk_colormap_get_visual (colormap) : NULL;
3786 }
3787
3788 static gint
3789 gdk_window_real_get_depth (GdkDrawable *drawable)
3790 {
3791   g_return_val_if_fail (GDK_IS_WINDOW (drawable), 0);
3792
3793   return ((GdkWindowObject *)GDK_WINDOW (drawable))->depth;
3794 }
3795
3796 static GdkScreen*
3797 gdk_window_real_get_screen (GdkDrawable *drawable)
3798 {
3799   return gdk_drawable_get_screen (GDK_WINDOW_OBJECT (drawable)->impl);
3800 }
3801
3802 static void
3803 gdk_window_real_set_colormap (GdkDrawable *drawable,
3804                               GdkColormap *cmap)
3805 {
3806   GdkWindowObject *private;
3807   
3808   g_return_if_fail (GDK_IS_WINDOW (drawable));  
3809
3810   if (GDK_WINDOW_DESTROYED (drawable))
3811     return;
3812
3813   private = (GdkWindowObject *)drawable;
3814
3815   /* different colormap than parent, requires native window */
3816   if (!private->input_only &&
3817       cmap != gdk_drawable_get_colormap ((GdkDrawable *)(private->parent)))
3818     gdk_window_set_has_native ((GdkWindow *)drawable, TRUE);
3819   
3820   gdk_drawable_set_colormap (private->impl, cmap);
3821 }
3822
3823 static GdkColormap*
3824 gdk_window_real_get_colormap (GdkDrawable *drawable)
3825 {
3826   g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
3827
3828   if (GDK_WINDOW_DESTROYED (drawable))
3829     return NULL;
3830   
3831   return gdk_drawable_get_colormap (((GdkWindowObject*)drawable)->impl);
3832 }
3833                       
3834 static GdkImage*
3835 gdk_window_copy_to_image (GdkDrawable     *drawable,
3836                           GdkImage        *image,
3837                           gint             src_x,
3838                           gint             src_y,
3839                           gint             dest_x,
3840                           gint             dest_y,
3841                           gint             width,
3842                           gint             height)
3843 {
3844   GdkWindowObject *private = (GdkWindowObject *) drawable;
3845   gint x_offset, y_offset;
3846   
3847   g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
3848   
3849   if (GDK_WINDOW_DESTROYED (drawable))
3850     return NULL;
3851
3852   /* If we're here, a composite image was not necessary, so
3853    * we can ignore the paint stack.
3854    */
3855
3856   /* TODO: Is this right? */
3857   x_offset = 0;
3858   y_offset = 0; 
3859   
3860   return gdk_drawable_copy_to_image (private->impl,
3861                                      image,
3862                                      src_x - x_offset,
3863                                      src_y - y_offset,
3864                                      dest_x, dest_y,
3865                                      width, height);
3866 }
3867
3868 static void
3869 gdk_window_cairo_surface_destroy (void *data)
3870 {
3871   GdkWindowObject *private = (GdkWindowObject*) data;
3872
3873   private->cairo_surface = NULL;
3874 }
3875
3876 static cairo_surface_t *
3877 gdk_window_ref_cairo_surface (GdkDrawable *drawable)
3878 {
3879   GdkWindowObject *private = (GdkWindowObject*) drawable;
3880   cairo_surface_t *surface;
3881
3882   if (private->paint_stack)
3883     {
3884       GdkWindowPaint *paint = private->paint_stack->data;
3885
3886       surface = paint->surface;
3887       cairo_surface_reference (surface);
3888     }
3889   else
3890     {
3891       
3892       /* This will be drawing directly to the window, so flush implicit paint */
3893       gdk_window_flush ((GdkWindow *)drawable);
3894       
3895       if (!private->cairo_surface)
3896         {
3897           int width, height;
3898           GdkDrawable *source;
3899
3900           /* It would be nice if we had some cairo support here so we
3901              could set the clip rect on the cairo surface */
3902           width = private->abs_x + private->width;
3903           height = private->abs_y + private->height;
3904
3905           source = _gdk_drawable_get_source_drawable (drawable);
3906
3907           /* TODO: Avoid the typecheck crap by adding virtual call */
3908           private->cairo_surface = _gdk_windowing_create_cairo_surface (GDK_IS_PIXMAP (source) ? GDK_PIXMAP_OBJECT(source)->impl : GDK_WINDOW_OBJECT(source)->impl,
3909                                                                         width, height);
3910           
3911           if (private->cairo_surface)
3912             {
3913               cairo_surface_set_device_offset (private->cairo_surface, 
3914                                                private->abs_x,
3915                                                private->abs_y);
3916               
3917               cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
3918                                            drawable, gdk_window_cairo_surface_destroy);
3919             }
3920         }
3921       else
3922         cairo_surface_reference (private->cairo_surface);
3923       
3924       surface = private->cairo_surface;
3925     }
3926
3927   return surface;
3928 }
3929
3930 static void
3931 gdk_window_set_cairo_clip (GdkDrawable *drawable,
3932                            cairo_t *cr)
3933 {
3934   GdkWindowObject *private = (GdkWindowObject*) drawable;
3935
3936   if (!private->paint_stack)
3937     {
3938       cairo_save (cr);
3939       cairo_identity_matrix (cr);
3940       
3941       cairo_new_path (cr);
3942       gdk_cairo_region (cr, private->clip_region);
3943       
3944       cairo_restore (cr);
3945       cairo_clip (cr);
3946     }
3947   else
3948     {
3949       GdkWindowPaint *paint = private->paint_stack->data;
3950
3951       /* Only needs to clip to region if piggybacking
3952          on an implicit paint pixmap */
3953       if (paint->uses_implicit)
3954         {
3955           cairo_save (cr);
3956           cairo_identity_matrix (cr);
3957           
3958           cairo_new_path (cr);
3959           gdk_cairo_region (cr, paint->region);
3960           cairo_restore (cr);
3961           
3962           cairo_clip (cr);
3963         }
3964     }
3965 }
3966
3967 /* Code for dirty-region queueing
3968  */
3969 static GSList *update_windows = NULL;
3970 static guint update_idle = 0;
3971 static gboolean debug_updates = FALSE;
3972
3973 static inline gboolean
3974 gdk_window_is_ancestor (GdkWindow *window,
3975                         GdkWindow *ancestor)
3976 {
3977   while (window)
3978     {
3979       GdkWindow *parent = (GdkWindow*) ((GdkWindowObject*) window)->parent;
3980
3981       if (parent == ancestor)
3982         return TRUE;
3983
3984       window = parent;
3985     }
3986
3987   return FALSE;
3988 }
3989
3990 static void
3991 gdk_window_add_update_window (GdkWindow *window)
3992 {
3993   GSList *tmp;
3994   GSList *prev = NULL;
3995   gboolean has_ancestor_in_list = FALSE;
3996
3997   for (tmp = update_windows; tmp; tmp = tmp->next)
3998     {
3999       GdkWindowObject *parent = GDK_WINDOW_OBJECT (window)->parent;
4000
4001       /*  check if tmp is an ancestor of "window"; if it is, set a
4002        *  flag indicating that all following windows are either
4003        *  children of "window" or from a differen hierarchy
4004        */
4005       if (!has_ancestor_in_list && gdk_window_is_ancestor (window, tmp->data))
4006         has_ancestor_in_list = TRUE;
4007
4008       /* insert in reverse stacking order when adding around siblings,
4009        * so processing updates properly paints over lower stacked windows
4010        */
4011       if (parent == GDK_WINDOW_OBJECT (tmp->data)->parent)
4012         {
4013           gint index = g_list_index (parent->children, window);
4014           for (; tmp && parent == GDK_WINDOW_OBJECT (tmp->data)->parent; tmp = tmp->next)
4015             {
4016               gint sibling_index = g_list_index (parent->children, tmp->data);
4017               if (index > sibling_index)
4018                 break;
4019               prev = tmp;
4020             }
4021           /* here, tmp got advanced past all lower stacked siblings */
4022           tmp = g_slist_prepend (tmp, window);
4023           if (prev)
4024             prev->next = tmp;
4025           else
4026             update_windows = tmp;
4027           return;
4028         }
4029
4030       /*  if "window" has an ancestor in the list and tmp is one of
4031        *  "window's" children, insert "window" before tmp
4032        */
4033       if (has_ancestor_in_list && gdk_window_is_ancestor (tmp->data, window))
4034         {
4035           tmp = g_slist_prepend (tmp, window);
4036
4037           if (prev)
4038             prev->next = tmp;
4039           else
4040             update_windows = tmp;
4041           return;
4042         }
4043
4044       /*  if we're at the end of the list and had an ancestor it it,
4045        *  append to the list
4046        */
4047       if (! tmp->next && has_ancestor_in_list)
4048         {
4049           tmp = g_slist_append (tmp, window);
4050           return;
4051         }
4052
4053       prev = tmp;
4054     }
4055
4056   /*  if all above checks failed ("window" is from a different
4057    *  hierarchy than what is already in the list) or the list is
4058    *  empty, prepend
4059    */
4060   update_windows = g_slist_prepend (update_windows, window);
4061 }
4062
4063 static void
4064 gdk_window_remove_update_window (GdkWindow *window)
4065 {
4066   update_windows = g_slist_remove (update_windows, window);
4067 }
4068
4069 static gboolean
4070 gdk_window_update_idle (gpointer data)
4071 {
4072   gdk_window_process_all_updates ();
4073   
4074   return FALSE;
4075 }
4076
4077 static gboolean
4078 gdk_window_is_toplevel_frozen (GdkWindow *window)
4079 {
4080   GdkWindowObject *toplevel;
4081
4082   toplevel = (GdkWindowObject *)gdk_window_get_toplevel (window);
4083
4084   return toplevel->update_and_descendants_freeze_count > 0;
4085 }
4086
4087 static void
4088 gdk_window_schedule_update (GdkWindow *window)
4089 {
4090   if (window &&
4091       (GDK_WINDOW_OBJECT (window)->update_freeze_count ||
4092        gdk_window_is_toplevel_frozen (window)))
4093     return;
4094
4095   if (!update_idle)
4096     {
4097       update_idle = gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
4098                                      gdk_window_update_idle, NULL, NULL);
4099     }
4100 }
4101
4102 static void
4103 gdk_window_process_updates_recurse (GdkWindow *window,
4104                                     GdkRegion *expose_region)
4105 {
4106   GdkWindowObject *private = (GdkWindowObject *)window;
4107   GdkWindowObject *child;
4108   GdkRegion *child_region;
4109   GdkRectangle r;
4110   GList *l;
4111
4112   if (gdk_region_empty (expose_region))
4113     return;
4114   
4115   /* Iterate over children, starting at topmost */
4116   for (l = private->children; l != NULL; l = l->next)
4117     {
4118       child = l->data;
4119       
4120       if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only)
4121         continue;
4122
4123       /* Ignore offscreen children, as they don't draw in their parent and
4124        * don't take part in the clipping */
4125       if (gdk_window_is_offscreen (child))
4126         continue;
4127
4128       r.x = child->x;
4129       r.y = child->y;
4130       r.width = child->width;
4131       r.height = child->height;
4132       
4133       child_region = gdk_region_rectangle (&r);
4134       
4135       if (child->impl == private->impl) 
4136         {
4137           /* Client side child, expose */
4138           gdk_region_intersect (child_region, expose_region);
4139           gdk_region_subtract (expose_region, child_region);
4140           gdk_region_offset (child_region, -child->x, -child->y);
4141           gdk_window_process_updates_recurse ((GdkWindow *)child, child_region);
4142         }
4143       else 
4144         {
4145           /* Native child, just remove area from expose region */
4146           gdk_region_subtract (expose_region, child_region);
4147         }
4148       gdk_region_destroy (child_region);
4149     }
4150
4151   if (private->event_mask & GDK_EXPOSURE_MASK)
4152     {
4153       GdkEvent event;
4154       
4155       event.expose.type = GDK_EXPOSE;
4156       event.expose.window = g_object_ref (window);
4157       event.expose.send_event = FALSE;
4158       event.expose.count = 0;
4159       event.expose.region = expose_region;
4160       gdk_region_get_clipbox (expose_region, &event.expose.area);
4161       
4162       (*_gdk_event_func) (&event, _gdk_event_data);
4163       
4164       g_object_unref (window);
4165     }
4166 }
4167
4168 static void
4169 gdk_window_process_updates_internal (GdkWindow *window)
4170 {
4171   GdkWindowObject *private = (GdkWindowObject *)window;
4172   gboolean save_region = FALSE;
4173   GdkRectangle clip_box;
4174
4175   /* If an update got queued during update processing, we can get a
4176    * window in the update queue that has an empty update_area.
4177    * just ignore it.
4178    */
4179   if (private->update_area)
4180     {
4181       GdkRegion *update_area = private->update_area;
4182       private->update_area = NULL;
4183       
4184       if (_gdk_event_func && gdk_window_is_viewable (window))
4185         {
4186           GdkRectangle window_rect;
4187           GdkRegion *expose_region;
4188           GdkRegion *window_region;
4189           gboolean end_implicit;
4190
4191           if (debug_updates)
4192             {
4193               /* Make sure we see the red invalid area before redrawing. */
4194               gdk_display_sync (gdk_drawable_get_display (window));
4195               g_usleep (70000);
4196             }
4197
4198           save_region = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->queue_antiexpose (window, update_area);
4199           if (save_region)
4200             expose_region = gdk_region_copy (update_area);
4201           else
4202             expose_region = update_area;
4203           
4204           window_rect.x = 0;
4205           window_rect.y = 0;
4206           window_rect.width = private->width;
4207           window_rect.height = private->height;
4208
4209           window_region = gdk_region_rectangle (&window_rect);
4210           gdk_region_intersect (expose_region,
4211                                 window_region);
4212           gdk_region_destroy (window_region);
4213
4214           gdk_region_get_clipbox (expose_region, &clip_box);
4215           end_implicit = gdk_window_begin_implicit_paint (window, &clip_box);
4216           gdk_window_process_updates_recurse (window, expose_region);
4217           if (end_implicit)
4218             gdk_window_end_implicit_paint (window);
4219           
4220           if (expose_region != update_area)
4221             gdk_region_destroy (expose_region);
4222         }
4223       if (!save_region)
4224         gdk_region_destroy (update_area);
4225     }
4226 }
4227
4228 static void
4229 flush_all_displays (void)
4230 {
4231   GSList *displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
4232   GSList *tmp_list;
4233
4234   for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
4235     gdk_display_flush (tmp_list->data);
4236
4237   g_slist_free (displays);
4238 }
4239
4240 /* Currently it is not possible to override
4241  * gdk_window_process_all_updates in the same manner as
4242  * gdk_window_process_updates and gdk_window_invalidate_maybe_recurse
4243  * by implementing the GdkPaintable interface.  If in the future a
4244  * backend would need this, the right solution would be to add a
4245  * method to GdkDisplay that can be optionally
4246  * NULL. gdk_window_process_all_updates can then walk the list of open
4247  * displays and call the mehod.
4248  */
4249
4250 /**
4251  * gdk_window_process_all_updates:
4252  *
4253  * Calls gdk_window_process_updates() for all windows (see #GdkWindow)
4254  * in the application.
4255  * 
4256  **/
4257 void
4258 gdk_window_process_all_updates (void)
4259 {
4260   GSList *old_update_windows = update_windows;
4261   GSList *tmp_list = update_windows;
4262
4263   if (update_idle)
4264     g_source_remove (update_idle);
4265   
4266   update_windows = NULL;
4267   update_idle = 0;
4268
4269   g_slist_foreach (old_update_windows, (GFunc)g_object_ref, NULL);
4270   
4271   while (tmp_list)
4272     {
4273       GdkWindowObject *private = (GdkWindowObject *)tmp_list->data;
4274       
4275       if (!GDK_WINDOW_DESTROYED (tmp_list->data))
4276         {
4277           if (private->update_freeze_count ||
4278               gdk_window_is_toplevel_frozen (tmp_list->data))
4279             gdk_window_add_update_window ((GdkWindow *) private);
4280           else
4281             gdk_window_process_updates_internal (tmp_list->data);
4282         }
4283
4284       g_object_unref (tmp_list->data);
4285       tmp_list = tmp_list->next;
4286     }
4287
4288   g_slist_free (old_update_windows);
4289
4290   flush_all_displays ();
4291 }
4292
4293 /**
4294  * gdk_window_process_updates:
4295  * @window: a #GdkWindow
4296  * @update_children: whether to also process updates for child windows
4297  *
4298  * Sends one or more expose events to @window. The areas in each 
4299  * expose event will cover the entire update area for the window (see
4300  * gdk_window_invalidate_region() for details). Normally GDK calls
4301  * gdk_window_process_all_updates() on your behalf, so there's no
4302  * need to call this function unless you want to force expose events
4303  * to be delivered immediately and synchronously (vs. the usual
4304  * case, where GDK delivers them in an idle handler). Occasionally
4305  * this is useful to produce nicer scrolling behavior, for example.
4306  * 
4307  **/
4308 void
4309 gdk_window_process_updates (GdkWindow *window,
4310                             gboolean   update_children)
4311 {
4312   GdkWindowObject *private = (GdkWindowObject *)window;
4313   GdkWindowObject *impl_window;
4314
4315   g_return_if_fail (GDK_IS_WINDOW (window));
4316
4317   if (GDK_IS_PAINTABLE (private->impl))
4318     {
4319       GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
4320
4321       if (iface->process_updates)
4322         iface->process_updates ((GdkPaintable*)private->impl, update_children);
4323
4324       return;
4325     }
4326
4327   impl_window = gdk_window_get_impl_window (private);
4328   if (impl_window->update_area &&
4329       !impl_window->update_freeze_count &&
4330       !gdk_window_is_toplevel_frozen (window))
4331     {      
4332       gdk_window_process_updates_internal ((GdkWindow *)impl_window);
4333       gdk_window_remove_update_window ((GdkWindow *)impl_window);
4334     }
4335
4336   if (update_children)
4337     {
4338       /* process updates in reverse stacking order so composition or
4339        * painting over achieves the desired effect for offscreen windows
4340        */
4341       GList *node;
4342       for (node = g_list_last (private->children); node; node = node->prev)
4343         gdk_window_process_updates (node->data, TRUE);
4344     }
4345 }
4346
4347 /**
4348  * gdk_window_invalidate_rect:
4349  * @window: a #GdkWindow
4350  * @rect: rectangle to invalidate or %NULL to invalidate the whole
4351  *      window
4352  * @invalidate_children: whether to also invalidate child windows
4353  *
4354  * A convenience wrapper around gdk_window_invalidate_region() which
4355  * invalidates a rectangular region. See
4356  * gdk_window_invalidate_region() for details.
4357  **/
4358 void
4359 gdk_window_invalidate_rect (GdkWindow          *window,
4360                             const GdkRectangle *rect,
4361                             gboolean            invalidate_children)
4362 {
4363   GdkRectangle window_rect;
4364   GdkRegion *region;
4365   GdkWindowObject *private = (GdkWindowObject *)window;
4366
4367   g_return_if_fail (GDK_IS_WINDOW (window));
4368
4369   if (GDK_WINDOW_DESTROYED (window))
4370     return;
4371   
4372   if (private->input_only || !GDK_WINDOW_IS_MAPPED (window))
4373     return;
4374
4375   if (!rect)
4376     {
4377       window_rect.x = 0;
4378       window_rect.y = 0;
4379       gdk_drawable_get_size (GDK_DRAWABLE (window),
4380                              &window_rect.width,
4381                              &window_rect.height);
4382       rect = &window_rect;
4383     }
4384
4385   region = gdk_region_rectangle (rect);
4386   gdk_window_invalidate_region (window, region, invalidate_children);
4387   gdk_region_destroy (region);
4388 }
4389
4390 static void
4391 draw_ugly_color (GdkWindow       *window,
4392                  const GdkRegion *region)
4393 {
4394   /* Draw ugly color all over the newly-invalid region */
4395   GdkColor ugly_color = { 0, 50000, 10000, 10000 };
4396   GdkGC *ugly_gc;
4397   GdkRectangle clipbox;
4398     
4399   ugly_gc = gdk_gc_new (window);
4400   gdk_gc_set_rgb_fg_color (ugly_gc, &ugly_color);
4401   gdk_gc_set_clip_region (ugly_gc, region);
4402
4403   gdk_region_get_clipbox (region, &clipbox);
4404   
4405   gdk_draw_rectangle (window,
4406                       ugly_gc,
4407                       TRUE,
4408                       clipbox.x, clipbox.y,
4409                       clipbox.width, clipbox.height);
4410   
4411   g_object_unref (ugly_gc);
4412 }
4413
4414 /**
4415  * gdk_window_invalidate_maybe_recurse:
4416  * @window: a #GdkWindow
4417  * @region: a #GdkRegion
4418  * @child_func: function to use to decide if to recurse to a child,
4419  *              %NULL means never recurse.
4420  * @user_data: data passed to @child_func
4421  *
4422  * Adds @region to the update area for @window. The update area is the
4423  * region that needs to be redrawn, or "dirty region." The call
4424  * gdk_window_process_updates() sends one or more expose events to the
4425  * window, which together cover the entire update area. An
4426  * application would normally redraw the contents of @window in
4427  * response to those expose events.
4428  *
4429  * GDK will call gdk_window_process_all_updates() on your behalf
4430  * whenever your program returns to the main loop and becomes idle, so
4431  * normally there's no need to do that manually, you just need to
4432  * invalidate regions that you know should be redrawn.
4433  *
4434  * The @child_func parameter controls whether the region of
4435  * each child window that intersects @region will also be invalidated.
4436  * Only children for which @child_func returns TRUE will have the area
4437  * invalidated.
4438  **/
4439 void
4440 gdk_window_invalidate_maybe_recurse (GdkWindow       *window,
4441                                      const GdkRegion *region,
4442                                      gboolean       (*child_func) (GdkWindow *,
4443                                                                    gpointer),
4444                                      gpointer   user_data)
4445 {
4446   GdkWindowObject *private = (GdkWindowObject *)window;
4447   GdkWindowObject *impl_window;
4448   GdkRegion *visible_region;
4449   GList *tmp_list;
4450
4451   g_return_if_fail (GDK_IS_WINDOW (window));
4452
4453   if (GDK_WINDOW_DESTROYED (window))
4454     return;
4455   
4456   if (private->input_only || !GDK_WINDOW_IS_MAPPED (window))
4457     return;
4458
4459   if (GDK_IS_PAINTABLE (private->impl))
4460     {
4461       GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
4462
4463       if (iface->invalidate_maybe_recurse)
4464         iface->invalidate_maybe_recurse ((GdkPaintable*)private->impl, 
4465                                          region, child_func, user_data);
4466       return;
4467     }
4468
4469   visible_region = gdk_drawable_get_visible_region (window);
4470   gdk_region_intersect (visible_region, region);
4471
4472   tmp_list = private->children;
4473   while (tmp_list)
4474     {
4475       GdkWindowObject *child = tmp_list->data;
4476       
4477       if (!child->input_only)
4478         {
4479           GdkRegion *child_region;
4480           GdkRectangle child_rect;
4481
4482           child_rect.x = child->x;
4483           child_rect.y = child->y;
4484           child_rect.width = child->width;
4485           child_rect.height = child->height;
4486           child_region = gdk_region_rectangle (&child_rect);
4487           
4488           /* remove child area from the invalid area of the parent */
4489           if (GDK_WINDOW_IS_MAPPED (child) && !child->shaped &&
4490               !child->composited &&
4491               !gdk_window_is_offscreen (child))
4492             gdk_region_subtract (visible_region, child_region);
4493           
4494           if (child_func && (*child_func) ((GdkWindow *)child, user_data))
4495             {
4496               GdkRegion *tmp = gdk_region_copy (region);
4497
4498               gdk_region_offset (tmp, - child_rect.x, - child_rect.y);
4499               gdk_region_offset (child_region, - child_rect.x, - child_rect.y);
4500               gdk_region_intersect (child_region, tmp);
4501               
4502               gdk_window_invalidate_maybe_recurse ((GdkWindow *)child,
4503                                                    child_region, child_func, user_data);
4504               
4505               gdk_region_destroy (tmp);
4506             }
4507
4508           gdk_region_destroy (child_region);
4509         }
4510
4511       tmp_list = tmp_list->next;
4512     }
4513   
4514   if (!gdk_region_empty (visible_region))
4515     {
4516       if (debug_updates)
4517         draw_ugly_color (window, region);
4518       
4519       /* Convert to impl coords */
4520       impl_window = gdk_window_get_impl_window (private);
4521       gdk_region_offset (visible_region, private->abs_x, private->abs_y);
4522       if (impl_window->update_area)
4523         {
4524           gdk_region_union (impl_window->update_area, visible_region);
4525         }
4526       else
4527         {
4528           gdk_window_add_update_window ((GdkWindow *)impl_window);
4529           impl_window->update_area = gdk_region_copy (visible_region);
4530           
4531           gdk_window_schedule_update ((GdkWindow *)impl_window);
4532         }
4533     }
4534   
4535   gdk_region_destroy (visible_region);
4536 }
4537
4538 static gboolean
4539 true_predicate (GdkWindow *window,
4540                 gpointer   user_data)
4541 {
4542   return TRUE;
4543 }
4544
4545 /**
4546  * gdk_window_invalidate_region:
4547  * @window: a #GdkWindow
4548  * @region: a #GdkRegion
4549  * @invalidate_children: %TRUE to also invalidate child windows 
4550  *
4551  * Adds @region to the update area for @window. The update area is the
4552  * region that needs to be redrawn, or "dirty region." The call
4553  * gdk_window_process_updates() sends one or more expose events to the
4554  * window, which together cover the entire update area. An
4555  * application would normally redraw the contents of @window in
4556  * response to those expose events.
4557  *
4558  * GDK will call gdk_window_process_all_updates() on your behalf
4559  * whenever your program returns to the main loop and becomes idle, so
4560  * normally there's no need to do that manually, you just need to
4561  * invalidate regions that you know should be redrawn.
4562  *
4563  * The @invalidate_children parameter controls whether the region of
4564  * each child window that intersects @region will also be invalidated.
4565  * If %FALSE, then the update area for child windows will remain
4566  * unaffected. See gdk_window_invalidate_maybe_recurse if you need
4567  * fine grained control over which children are invalidated.
4568  **/
4569 void
4570 gdk_window_invalidate_region (GdkWindow       *window,
4571                               const GdkRegion *region,
4572                               gboolean         invalidate_children)
4573 {
4574   gdk_window_invalidate_maybe_recurse (window, region,
4575                                        invalidate_children ?
4576                                          true_predicate : (gboolean (*) (GdkWindow *, gpointer))NULL,
4577                                        NULL);
4578 }
4579
4580 /**
4581  * _gdk_window_invalidate_for_expose:
4582  * @window: a #GdkWindow
4583  * @region: a #GdkRegion
4584  *
4585  * Adds @region to the update area for @window. The update area is the
4586  * region that needs to be redrawn, or "dirty region." The call
4587  * gdk_window_process_updates() sends one or more expose events to the
4588  * window, which together cover the entire update area. An
4589  * application would normally redraw the contents of @window in
4590  * response to those expose events.
4591  *
4592  * GDK will call gdk_window_process_all_updates() on your behalf
4593  * whenever your program returns to the main loop and becomes idle, so
4594  * normally there's no need to do that manually, you just need to
4595  * invalidate regions that you know should be redrawn.
4596  *
4597  * This version of invalidation is used when you recieve expose events
4598  * from the native window system. It exposes the native window, plus
4599  * any non-native child windows (but not native child windows, as those would
4600  * have gotten their own expose events). 
4601  **/
4602 void
4603 _gdk_window_invalidate_for_expose (GdkWindow       *window,
4604                                    const GdkRegion *region)
4605 {
4606   gdk_window_invalidate_maybe_recurse (window, region,
4607                                        (gboolean (*) (GdkWindow *, gpointer))gdk_window_has_no_impl,
4608                                        NULL);
4609 }
4610
4611
4612 /**
4613  * gdk_window_get_update_area:
4614  * @window: a #GdkWindow
4615  * 
4616  * Transfers ownership of the update area from @window to the caller
4617  * of the function. That is, after calling this function, @window will
4618  * no longer have an invalid/dirty region; the update area is removed
4619  * from @window and handed to you. If a window has no update area,
4620  * gdk_window_get_update_area() returns %NULL. You are responsible for
4621  * calling gdk_region_destroy() on the returned region if it's non-%NULL.
4622  * 
4623  * Return value: the update area for @window
4624  **/
4625 GdkRegion *
4626 gdk_window_get_update_area (GdkWindow *window)
4627 {
4628   GdkWindowObject *private = (GdkWindowObject *)window;
4629   GdkWindowObject *impl_window;
4630   GdkRegion *tmp_region;
4631
4632   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
4633
4634   impl_window = gdk_window_get_impl_window (private);
4635   
4636   if (impl_window->update_area)
4637     {
4638       tmp_region = gdk_region_copy (private->clip_region_with_children);
4639       /* Convert to impl coords */
4640       gdk_region_offset (tmp_region, private->abs_x, private->abs_y);
4641       gdk_region_intersect (tmp_region, impl_window->update_area);
4642
4643       if (gdk_region_empty (tmp_region))
4644         {
4645           gdk_region_destroy (tmp_region);
4646           return NULL;
4647         }
4648       else
4649         {
4650           gdk_region_subtract (impl_window->update_area, tmp_region);
4651
4652           if (gdk_region_empty (impl_window->update_area))
4653             {
4654               gdk_region_destroy (impl_window->update_area);
4655               impl_window->update_area = NULL;
4656           
4657               gdk_window_remove_update_window ((GdkWindow *)impl_window);
4658             }
4659           
4660           /* Convert from impl coords */
4661           gdk_region_offset (tmp_region, -private->abs_x, -private->abs_y);
4662           return tmp_region;
4663
4664         }
4665     }
4666   else
4667     return NULL;
4668 }
4669
4670 /**
4671  * _gdk_window_clear_update_area:
4672  * @window: a #GdkWindow.
4673  * 
4674  * Internal function to clear the update area for a window. This
4675  * is called when the window is hidden or destroyed.
4676  **/
4677 void
4678 _gdk_window_clear_update_area (GdkWindow *window)
4679 {
4680   GdkWindowObject *private = (GdkWindowObject *)window;
4681
4682   g_return_if_fail (GDK_IS_WINDOW (window));
4683
4684   if (private->update_area)
4685     {
4686       gdk_window_remove_update_window (window);
4687
4688       gdk_region_destroy (private->update_area);
4689       private->update_area = NULL;
4690     }
4691 }
4692
4693 /**
4694  * gdk_window_freeze_updates:
4695  * @window: a #GdkWindow
4696  * 
4697  * Temporarily freezes a window such that it won't receive expose
4698  * events.  The window will begin receiving expose events again when
4699  * gdk_window_thaw_updates() is called. If gdk_window_freeze_updates()
4700  * has been called more than once, gdk_window_thaw_updates() must be called
4701  * an equal number of times to begin processing exposes.
4702  **/
4703 void
4704 gdk_window_freeze_updates (GdkWindow *window)
4705 {
4706   GdkWindowObject *private = (GdkWindowObject *)window;
4707   GdkWindowObject *impl_window;
4708
4709   g_return_if_fail (GDK_IS_WINDOW (window));
4710
4711   impl_window = gdk_window_get_impl_window (private);
4712   impl_window->update_freeze_count++;
4713 }
4714
4715 /**
4716  * gdk_window_thaw_updates:
4717  * @window: a #GdkWindow
4718  * 
4719  * Thaws a window frozen with gdk_window_freeze_updates().
4720  **/
4721 void
4722 gdk_window_thaw_updates (GdkWindow *window)
4723 {
4724   GdkWindowObject *private = (GdkWindowObject *)window;
4725   GdkWindowObject *impl_window;
4726
4727   g_return_if_fail (GDK_IS_WINDOW (window));
4728   g_return_if_fail (private->update_freeze_count > 0);
4729
4730   impl_window = gdk_window_get_impl_window (private);
4731   
4732   if (--impl_window->update_freeze_count == 0)
4733     gdk_window_schedule_update (GDK_WINDOW (impl_window));
4734 }
4735
4736 /**
4737  * gdk_window_freeze_toplevel_updates_libgtk_only:
4738  * @window: a #GdkWindow
4739  *
4740  * Temporarily freezes a window and all its descendants such that it won't
4741  * receive expose events.  The window will begin receiving expose events
4742  * again when gdk_window_thaw_toplevel_updates_libgtk_only() is called. If
4743  * gdk_window_freeze_toplevel_updates_libgtk_only()
4744  * has been called more than once,
4745  * gdk_window_thaw_toplevel_updates_libgtk_only() must be called
4746  * an equal number of times to begin processing exposes.
4747  *
4748  * This function is not part of the GDK public API and is only
4749  * for use by GTK+.
4750  **/
4751 void
4752 gdk_window_freeze_toplevel_updates_libgtk_only (GdkWindow *window)
4753 {
4754   GdkWindowObject *private = (GdkWindowObject *)window;
4755
4756   g_return_if_fail (GDK_IS_WINDOW (window));
4757   g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
4758
4759   private->update_and_descendants_freeze_count++;
4760 }
4761
4762 /**
4763  * gdk_window_thaw_toplevel_updates_libgtk_only:
4764  * @window: a #GdkWindow
4765  * 
4766  * Thaws a window frozen with
4767  * gdk_window_freeze_toplevel_updates_libgtk_only().
4768  *
4769  * This function is not part of the GDK public API and is only
4770  * for use by GTK+.
4771  **/
4772 void
4773 gdk_window_thaw_toplevel_updates_libgtk_only (GdkWindow *window)
4774 {
4775   GdkWindowObject *private = (GdkWindowObject *)window;
4776
4777   g_return_if_fail (GDK_IS_WINDOW (window));
4778   g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
4779   g_return_if_fail (private->update_and_descendants_freeze_count > 0);
4780
4781   private->update_and_descendants_freeze_count--;
4782
4783   gdk_window_schedule_update (window);
4784 }
4785
4786 /**
4787  * gdk_window_set_debug_updates:
4788  * @setting: %TRUE to turn on update debugging
4789  *
4790  * With update debugging enabled, calls to
4791  * gdk_window_invalidate_region() clear the invalidated region of the
4792  * screen to a noticeable color, and GDK pauses for a short time
4793  * before sending exposes to windows during
4794  * gdk_window_process_updates().  The net effect is that you can see
4795  * the invalid region for each window and watch redraws as they
4796  * occur. This allows you to diagnose inefficiencies in your application.
4797  *
4798  * In essence, because the GDK rendering model prevents all flicker,
4799  * if you are redrawing the same region 400 times you may never
4800  * notice, aside from noticing a speed problem. Enabling update
4801  * debugging causes GTK to flicker slowly and noticeably, so you can
4802  * see exactly what's being redrawn when, in what order.
4803  *
4804  * The --gtk-debug=updates command line option passed to GTK+ programs
4805  * enables this debug option at application startup time. That's
4806  * usually more useful than calling gdk_window_set_debug_updates()
4807  * yourself, though you might want to use this function to enable
4808  * updates sometime after application startup time.
4809  * 
4810  **/
4811 void
4812 gdk_window_set_debug_updates (gboolean setting)
4813 {
4814   debug_updates = setting;
4815 }
4816
4817 /**
4818  * gdk_window_constrain_size:
4819  * @geometry: a #GdkGeometry structure
4820  * @flags: a mask indicating what portions of @geometry are set
4821  * @width: desired width of window
4822  * @height: desired height of the window
4823  * @new_width: location to store resulting width
4824  * @new_height: location to store resulting height
4825  * 
4826  * Constrains a desired width and height according to a 
4827  * set of geometry hints (such as minimum and maximum size).
4828  */
4829 void
4830 gdk_window_constrain_size (GdkGeometry *geometry,
4831                            guint        flags,
4832                            gint         width,
4833                            gint         height,
4834                            gint        *new_width,
4835                            gint        *new_height)
4836 {
4837   /* This routine is partially borrowed from fvwm.
4838    *
4839    * Copyright 1993, Robert Nation
4840    *     You may use this code for any purpose, as long as the original
4841    *     copyright remains in the source code and all documentation
4842    *
4843    * which in turn borrows parts of the algorithm from uwm
4844    */
4845   gint min_width = 0;
4846   gint min_height = 0;
4847   gint base_width = 0;
4848   gint base_height = 0;
4849   gint xinc = 1;
4850   gint yinc = 1;
4851   gint max_width = G_MAXINT;
4852   gint max_height = G_MAXINT;
4853   
4854 #define FLOOR(value, base)      ( ((gint) ((value) / (base))) * (base) )
4855
4856   if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
4857     {
4858       base_width = geometry->base_width;
4859       base_height = geometry->base_height;
4860       min_width = geometry->min_width;
4861       min_height = geometry->min_height;
4862     }
4863   else if (flags & GDK_HINT_BASE_SIZE)
4864     {
4865       base_width = geometry->base_width;
4866       base_height = geometry->base_height;
4867       min_width = geometry->base_width;
4868       min_height = geometry->base_height;
4869     }
4870   else if (flags & GDK_HINT_MIN_SIZE)
4871     {
4872       base_width = geometry->min_width;
4873       base_height = geometry->min_height;
4874       min_width = geometry->min_width;
4875       min_height = geometry->min_height;
4876     }
4877
4878   if (flags & GDK_HINT_MAX_SIZE)
4879     {
4880       max_width = geometry->max_width ;
4881       max_height = geometry->max_height;
4882     }
4883
4884   if (flags & GDK_HINT_RESIZE_INC)
4885     {
4886       xinc = MAX (xinc, geometry->width_inc);
4887       yinc = MAX (yinc, geometry->height_inc);
4888     }
4889   
4890   /* clamp width and height to min and max values
4891    */
4892   width = CLAMP (width, min_width, max_width);
4893   height = CLAMP (height, min_height, max_height);
4894   
4895   /* shrink to base + N * inc
4896    */
4897   width = base_width + FLOOR (width - base_width, xinc);
4898   height = base_height + FLOOR (height - base_height, yinc);
4899
4900   /* constrain aspect ratio, according to:
4901    *
4902    *                width     
4903    * min_aspect <= -------- <= max_aspect
4904    *                height    
4905    */
4906   
4907   if (flags & GDK_HINT_ASPECT &&
4908       geometry->min_aspect > 0 &&
4909       geometry->max_aspect > 0)
4910     {
4911       gint delta;
4912
4913       if (geometry->min_aspect * height > width)
4914         {
4915           delta = FLOOR (height - width / geometry->min_aspect, yinc);
4916           if (height - delta >= min_height)
4917             height -= delta;
4918           else
4919             { 
4920               delta = FLOOR (height * geometry->min_aspect - width, xinc);
4921               if (width + delta <= max_width) 
4922                 width += delta;
4923             }
4924         }
4925       
4926       if (geometry->max_aspect * height < width)
4927         {
4928           delta = FLOOR (width - height * geometry->max_aspect, xinc);
4929           if (width - delta >= min_width) 
4930             width -= delta;
4931           else
4932             {
4933               delta = FLOOR (width / geometry->max_aspect - height, yinc);
4934               if (height + delta <= max_height)
4935                 height += delta;
4936             }
4937         }
4938     }
4939
4940 #undef FLOOR
4941   
4942   *new_width = width;
4943   *new_height = height;
4944 }
4945
4946 /**
4947  * gdk_window_get_pointer:
4948  * @window: a #GdkWindow
4949  * @x: return location for X coordinate of pointer or %NULL to not
4950  *      return the X coordinate
4951  * @y: return location for Y coordinate of pointer or %NULL to not
4952  *      return the Y coordinate
4953  * @mask: return location for modifier mask or %NULL to not return the
4954  *      modifier mask
4955  *
4956  * Obtains the current pointer position and modifier state.
4957  * The position is given in coordinates relative to the upper left 
4958  * corner of @window.
4959  * 
4960  * Return value: the window containing the pointer (as with
4961  * gdk_window_at_pointer()), or %NULL if the window containing the
4962  * pointer isn't known to GDK
4963  **/
4964 GdkWindow*
4965 gdk_window_get_pointer (GdkWindow         *window,
4966                         gint              *x,
4967                         gint              *y,
4968                         GdkModifierType   *mask)
4969 {
4970   GdkDisplay *display;
4971   gint tmp_x, tmp_y;
4972   GdkModifierType tmp_mask;
4973   GdkWindow *child;
4974   
4975   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
4976
4977   if (window)
4978     {
4979       display = gdk_drawable_get_display (window);
4980     }
4981   else
4982     {
4983       GdkScreen *screen = gdk_screen_get_default ();
4984
4985       display = gdk_screen_get_display (screen);
4986       window = gdk_screen_get_root_window (screen);
4987       
4988       GDK_NOTE (MULTIHEAD,
4989                 g_message ("Passing NULL for window to gdk_window_get_pointer()\n"
4990                            "is not multihead safe"));
4991     }
4992
4993   child = display->pointer_hooks->window_get_pointer (display, window, &tmp_x, &tmp_y, &tmp_mask);
4994
4995   if (x)
4996     *x = tmp_x;
4997   if (y)
4998     *y = tmp_y;
4999   if (mask)
5000     *mask = tmp_mask;
5001
5002   return child;
5003 }
5004
5005 /**
5006  * gdk_window_at_pointer:
5007  * @win_x: return location for origin of the window under the pointer
5008  * @win_y: return location for origin of the window under the pointer
5009  * 
5010  * Obtains the window underneath the mouse pointer, returning the
5011  * location of that window in @win_x, @win_y. Returns %NULL if the
5012  * window under the mouse pointer is not known to GDK (if the window
5013  * belongs to another application and a #GdkWindow hasn't been created
5014  * for it with gdk_window_foreign_new())
5015  *
5016  * NOTE: For multihead-aware widgets or applications use
5017  * gdk_display_get_window_at_pointer() instead.
5018  * 
5019  * Return value: window under the mouse pointer
5020  **/
5021 GdkWindow*
5022 gdk_window_at_pointer (gint *win_x,
5023                        gint *win_y)
5024 {
5025   return gdk_display_get_window_at_pointer (gdk_display_get_default (), win_x, win_y);
5026 }
5027
5028 /**
5029  * gdk_get_default_root_window:
5030  * 
5031  * Obtains the root window (parent all other windows are inside)
5032  * for the default display and screen.
5033  * 
5034  * Return value: the default root window
5035  **/
5036 GdkWindow *
5037 gdk_get_default_root_window (void)
5038 {
5039   return gdk_screen_get_root_window (gdk_screen_get_default ());
5040 }
5041
5042 /**
5043  * gdk_window_foreign_new:
5044  * @anid: a native window handle.
5045  * 
5046  * Wraps a native window for the default display in a #GdkWindow.
5047  * This may fail if the window has been destroyed.
5048  *
5049  * For example in the X backend, a native window handle is an Xlib
5050  * <type>XID</type>.
5051  * 
5052  * Return value: the newly-created #GdkWindow wrapper for the 
5053  *    native window or %NULL if the window has been destroyed.
5054  **/
5055 GdkWindow *
5056 gdk_window_foreign_new (GdkNativeWindow anid)
5057 {
5058   return gdk_window_foreign_new_for_display (gdk_display_get_default (), anid);
5059 }
5060
5061 static inline void
5062 gdk_window_raise_internal (GdkWindow *window)
5063 {
5064   GdkWindowObject *private = (GdkWindowObject *)window;
5065   GdkWindowObject *parent = private->parent;
5066
5067   if (parent)
5068     {
5069       parent->children = g_list_remove (parent->children, window);
5070       parent->children = g_list_prepend (parent->children, window);
5071     }
5072 }
5073
5074 static void
5075 gdk_window_show_internal (GdkWindow *window, gboolean raise)
5076 {
5077   GdkWindowObject *private;
5078   gboolean was_mapped;
5079
5080   g_return_if_fail (GDK_IS_WINDOW (window));
5081
5082   private = (GdkWindowObject *) window;
5083   if (private->destroyed)
5084     return;
5085
5086   was_mapped = GDK_WINDOW_IS_MAPPED (window);
5087   
5088   if (raise)
5089     {
5090       /* Keep children in (reverse) stacking order */
5091       gdk_window_raise_internal (window);
5092     }
5093
5094   if (gdk_window_has_impl (private))
5095     GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show (window, raise);
5096   else
5097     {
5098       if (GDK_WINDOW_IS_MAPPED (window))
5099         {
5100           /* If we're raising, need to invalidate even if we're already shown */
5101           if (raise && gdk_window_is_viewable (window) && !private->input_only)
5102             gdk_window_invalidate_rect (window, NULL, TRUE);
5103         }
5104       else
5105         {
5106           /* Wasn't visible already */
5107           private->state = 0;
5108         }
5109     }
5110
5111   if (!was_mapped)
5112     {
5113       if (private->event_mask & GDK_STRUCTURE_MASK)
5114         _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
5115       
5116       if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
5117         _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
5118     }
5119   
5120   if (!was_mapped || raise)
5121     {
5122       if (gdk_window_is_viewable (window))
5123         _gdk_syntesize_crossing_events_for_geometry_change (window);
5124       
5125       recompute_visible_regions (private, TRUE, FALSE);
5126     }
5127   
5128   if (!was_mapped && gdk_window_is_viewable (window))
5129     gdk_window_invalidate_rect (window, NULL, TRUE);
5130 }
5131   
5132 /**
5133  * gdk_window_show_unraised:
5134  * @window: a #GdkWindow
5135  *
5136  * Shows a #GdkWindow onscreen, but does not modify its stacking
5137  * order. In contrast, gdk_window_show() will raise the window
5138  * to the top of the window stack.
5139  *
5140  * On the X11 platform, in Xlib terms, this function calls
5141  * XMapWindow() (it also updates some internal GDK state, which means
5142  * that you can't really use XMapWindow() directly on a GDK window).
5143  */
5144 void
5145 gdk_window_show_unraised (GdkWindow *window)
5146 {
5147   gdk_window_show_internal (window, FALSE);
5148 }
5149
5150 /**
5151  * gdk_window_raise:
5152  * @window: a #GdkWindow
5153  *
5154  * Raises @window to the top of the Z-order (stacking order), so that
5155  * other windows with the same parent window appear below @window.
5156  * This is true whether or not the windows are visible.
5157  *
5158  * If @window is a toplevel, the window manager may choose to deny the
5159  * request to move the window in the Z-order, gdk_window_raise() only
5160  * requests the restack, does not guarantee it.
5161  */
5162 void
5163 gdk_window_raise (GdkWindow *window)
5164 {
5165   GdkWindowObject *private;
5166
5167   g_return_if_fail (GDK_IS_WINDOW (window));
5168
5169   private = (GdkWindowObject *) window;
5170   if (private->destroyed)
5171     return;
5172
5173   /* Keep children in (reverse) stacking order */
5174   gdk_window_raise_internal (window);
5175
5176   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
5177
5178   recompute_visible_regions (private, TRUE, FALSE);
5179 }
5180
5181 static void
5182 gdk_window_lower_internal (GdkWindow *window)
5183 {
5184   GdkWindowObject *private = (GdkWindowObject *)window;
5185   GdkWindowObject *parent = private->parent;
5186
5187   if (parent)
5188     {
5189       parent->children = g_list_remove (parent->children, window);
5190       parent->children = g_list_append (parent->children, window);
5191     }
5192 }
5193
5194 static void
5195 gdk_window_invalidate_in_parent (GdkWindowObject *private)
5196 {
5197   GdkRectangle r, child;
5198
5199   if (private->parent == NULL ||
5200       GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
5201     return;
5202   
5203   /* get the visible rectangle of the parent */
5204   r.x = r.y = 0;
5205   r.width = private->parent->width;
5206   r.height = private->parent->height;
5207
5208   child.x = private->x;
5209   child.y = private->y;
5210   child.width = private->width;
5211   child.height = private->height;
5212   gdk_rectangle_intersect (&r, &child, &r);
5213
5214   gdk_window_invalidate_rect (GDK_WINDOW (private->parent), &r, TRUE);
5215 }
5216
5217
5218 /**
5219  * gdk_window_lower:
5220  * @window: a #GdkWindow
5221  *
5222  * Lowers @window to the bottom of the Z-order (stacking order), so that
5223  * other windows with the same parent window appear above @window.
5224  * This is true whether or not the other windows are visible.
5225  *
5226  * If @window is a toplevel, the window manager may choose to deny the
5227  * request to move the window in the Z-order, gdk_window_lower() only
5228  * requests the restack, does not guarantee it.
5229  *
5230  * Note that gdk_window_show() raises the window again, so don't call this
5231  * function before gdk_window_show(). (Try gdk_window_show_unraised().)
5232  */
5233 void
5234 gdk_window_lower (GdkWindow *window)
5235 {
5236   GdkWindowObject *private;
5237
5238   g_return_if_fail (GDK_IS_WINDOW (window));
5239
5240   private = (GdkWindowObject *) window;
5241   if (private->destroyed)
5242     return;
5243
5244   /* Keep children in (reverse) stacking order */
5245   gdk_window_lower_internal (window);
5246
5247   if (gdk_window_has_impl (private))
5248     GDK_WINDOW_IMPL_GET_IFACE (private->impl)->lower (window);
5249   else
5250     {
5251       gdk_window_invalidate_in_parent (private);
5252       _gdk_syntesize_crossing_events_for_geometry_change (window);
5253     }
5254
5255   recompute_visible_regions (private, TRUE, FALSE);
5256 }
5257
5258 /**
5259  * gdk_window_show:
5260  * @window: a #GdkWindow
5261  *
5262  * Like gdk_window_show_unraised(), but also raises the window to the
5263  * top of the window stack (moves the window to the front of the
5264  * Z-order).
5265  *
5266  * This function maps a window so it's visible onscreen. Its opposite
5267  * is gdk_window_hide().
5268  *
5269  * When implementing a #GtkWidget, you should call this function on the widget's
5270  * #GdkWindow as part of the "map" method.
5271  */
5272 void
5273 gdk_window_show (GdkWindow *window)
5274 {
5275   gdk_window_show_internal (window, TRUE);
5276 }
5277
5278 /**
5279  * gdk_window_hide:
5280  * @window: a #GdkWindow
5281  *
5282  * For toplevel windows, withdraws them, so they will no longer be
5283  * known to the window manager; for all windows, unmaps them, so
5284  * they won't be displayed. Normally done automatically as
5285  * part of gtk_widget_hide().
5286  */
5287 void
5288 gdk_window_hide (GdkWindow *window)
5289 {
5290   GdkWindowObject *private;
5291   gboolean was_mapped;
5292
5293   g_return_if_fail (GDK_IS_WINDOW (window));
5294
5295   private = (GdkWindowObject *) window;
5296   if (private->destroyed)
5297     return;
5298
5299   was_mapped = GDK_WINDOW_IS_MAPPED (private);
5300   
5301   if (gdk_window_has_impl (private))
5302     GDK_WINDOW_IMPL_GET_IFACE (private->impl)->hide (window);
5303   else if (was_mapped)
5304     {
5305       GdkDisplay *display;
5306
5307       /* May need to break grabs on children */
5308       display = gdk_drawable_get_display (window);
5309
5310       if (display->pointer_grab.window != NULL)
5311         {
5312           if (is_parent_of (window, display->pointer_grab.window))
5313             {
5314               /* Call this ourselves, even though gdk_display_pointer_ungrab
5315                  does so too, since we want to pass implicit == TRUE so the
5316                  broken grab event is generated */
5317               _gdk_display_unset_has_pointer_grab (display,
5318                                                    TRUE,
5319                                                    FALSE,
5320                                                    GDK_CURRENT_TIME);
5321               gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
5322             }
5323         }
5324
5325       private->state = GDK_WINDOW_STATE_WITHDRAWN;
5326       
5327       /* Invalidate the rect */
5328       gdk_window_invalidate_in_parent (private);
5329     }
5330
5331   if (was_mapped)
5332     {
5333       if (private->event_mask & GDK_STRUCTURE_MASK)
5334         _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
5335       
5336       if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
5337         _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
5338       
5339       _gdk_syntesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
5340     }
5341   
5342   recompute_visible_regions (private, TRUE, FALSE);
5343 }
5344
5345 /**
5346  * gdk_window_withdraw:
5347  * @window: a toplevel #GdkWindow
5348  *
5349  * Withdraws a window (unmaps it and asks the window manager to forget about it).
5350  * This function is not really useful as gdk_window_hide() automatically
5351  * withdraws toplevel windows before hiding them.
5352  **/
5353 void
5354 gdk_window_withdraw (GdkWindow *window)
5355 {
5356   GdkWindowObject *private;
5357   gboolean was_mapped;
5358
5359   g_return_if_fail (GDK_IS_WINDOW (window));
5360
5361   private = (GdkWindowObject *) window;
5362   if (private->destroyed)
5363     return;
5364
5365   was_mapped = GDK_WINDOW_IS_MAPPED (private);
5366   
5367   if (gdk_window_has_impl (private))
5368     {
5369       GDK_WINDOW_IMPL_GET_IFACE (private->impl)->withdraw (window);
5370       
5371       if (was_mapped)
5372         {
5373           if (private->event_mask & GDK_STRUCTURE_MASK)
5374             _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
5375           
5376           if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
5377             _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
5378           
5379           _gdk_syntesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
5380         }
5381       
5382       recompute_visible_regions (private, TRUE, FALSE);
5383     }
5384 }
5385
5386 /**
5387  * gdk_window_set_events:
5388  * @window: a #GdkWindow
5389  * @event_mask: event mask for @window
5390  *
5391  * The event mask for a window determines which events will be reported
5392  * for that window. For example, an event mask including #GDK_BUTTON_PRESS_MASK
5393  * means the window should report button press events. The event mask
5394  * is the bitwise OR of values from the #GdkEventMask enumeration.
5395  **/
5396 void
5397 gdk_window_set_events (GdkWindow       *window,
5398                        GdkEventMask     event_mask)
5399 {
5400   GdkWindowObject *private;
5401
5402   g_return_if_fail (GDK_IS_WINDOW (window));
5403
5404   private = (GdkWindowObject *) window;
5405   if (private->destroyed)
5406     return;
5407
5408   private->event_mask = event_mask;
5409 }
5410
5411 /**
5412  * gdk_window_get_events:
5413  * @window: a #GdkWindow
5414  *
5415  * Gets the event mask for @window. See gdk_window_set_events().
5416  *
5417  * Return value: event mask for @window
5418  **/
5419 GdkEventMask
5420 gdk_window_get_events (GdkWindow *window)
5421 {
5422   GdkWindowObject *private;
5423
5424   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
5425
5426   private = (GdkWindowObject *) window;
5427   if (private->destroyed)
5428     return 0;
5429
5430   return private->event_mask;
5431 }
5432
5433 static void
5434 move_native_children (GdkWindowObject *private)
5435 {
5436   GList *l;
5437   GdkWindowObject *child;
5438   
5439   for (l = private->children; l; l = l->next)
5440     {
5441       child = l->data;
5442       
5443       if (child->impl != private->impl)
5444         GDK_WINDOW_IMPL_GET_IFACE (child->impl)->move_resize ((GdkWindow *)child, TRUE, child->x, child->y, child->width, child->height);
5445       else
5446         move_native_children  (child);
5447     }
5448 }
5449
5450 static void
5451 gdk_window_move_resize_internal (GdkWindow *window,
5452                                  gboolean   with_move,
5453                                  gint       x,
5454                                  gint       y,
5455                                  gint       width,
5456                                  gint       height)
5457 {
5458   GdkWindowObject *private;
5459   GdkRegion *old_region, *new_region, *copy_area;
5460   GdkWindowObject *impl_window;
5461   gboolean expose;
5462   int old_x, old_y, old_abs_x, old_abs_y;
5463   int dx, dy;
5464   gboolean do_move_native_children;
5465
5466   g_return_if_fail (GDK_IS_WINDOW (window));
5467
5468   private = (GdkWindowObject *) window;
5469   if (private->destroyed)
5470     return;
5471
5472   do_move_native_children = FALSE;
5473   expose = FALSE;
5474   old_region = NULL;
5475
5476   impl_window = gdk_window_get_impl_window (private);
5477
5478   old_x = private->x;
5479   old_y = private->y;
5480   
5481   if (gdk_window_has_impl (private))
5482     {
5483       if (GDK_WINDOW_IS_MAPPED (window))
5484         {
5485           expose = !private->input_only;
5486           old_region = gdk_region_copy (private->clip_region);
5487           /* Adjust region to parent window coords */
5488           gdk_region_offset (old_region, private->x, private->y);
5489         }
5490       
5491       GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, with_move, x, y, width, height);
5492     }
5493   else
5494     {
5495       if (GDK_WINDOW_IS_MAPPED (window))
5496         {
5497           expose = !private->input_only;
5498           old_region = gdk_region_copy (private->clip_region);
5499           /* Adjust region to parent window coords */
5500           gdk_region_offset (old_region, private->x, private->y);
5501         }
5502
5503       if (with_move)
5504         {
5505           private->x = x;
5506           private->y = y;
5507         }
5508       if (!(width < 0 && height < 0))
5509         {
5510           if (width < 1)
5511             width = 1;
5512           private->width = width;
5513           if (height < 1)
5514             height = 1;
5515           private->height = height;
5516         }
5517
5518       do_move_native_children = TRUE;
5519     }
5520
5521   dx = private->x - old_x;
5522   dy = private->y - old_y;
5523
5524   old_abs_x = private->abs_x;
5525   old_abs_y = private->abs_y;
5526   
5527   recompute_visible_regions (private, TRUE, FALSE);
5528
5529   if (do_move_native_children &&
5530       (old_abs_x != private->abs_x ||
5531        old_abs_y != private->abs_y))
5532       move_native_children (private);
5533   
5534   if (expose)
5535     {
5536       new_region = gdk_region_copy (private->clip_region);
5537       /* Adjust region to parent window coords */
5538       gdk_region_offset (new_region, private->x, private->y);
5539
5540       /* copy_area:
5541        * Part of the data at the new location can be copied from the
5542        * old location, this area is the intersection of the old region
5543        * moved as the copy will move it and then intersected with
5544        * the new region.
5545        *
5546        * new_region:
5547        * Everything in the old and new regions that is not copied must be
5548        * invalidated (including children) as this is newly exposed 
5549        */
5550       copy_area = gdk_region_copy (new_region);
5551           
5552       gdk_region_union (new_region, old_region);
5553       
5554       gdk_region_offset (old_region, dx, dy);
5555       gdk_region_intersect (copy_area, old_region);
5556       
5557       gdk_region_subtract (new_region, copy_area);
5558
5559       /* Convert old region to impl coords */
5560       gdk_region_offset (old_region, -dx + private->abs_x - private->x, -dy + private->abs_y - private->y);
5561
5562       /* The old_region area is moved and we queue translations for all expose events
5563          to it that will be sent before the copy operation */
5564       /* TODO: Make queue_translation a vtable call instead of hardcoding this crap */
5565       if (!gdk_window_is_offscreen (impl_window)) 
5566         _gdk_windowing_window_queue_translation ((GdkWindow *)impl_window, old_region, dx, dy);
5567       
5568       /* convert from parent coords to impl */
5569       gdk_region_offset (copy_area, private->abs_x - private->x, private->abs_y - private->y);
5570
5571       move_region_on_impl (private, copy_area, dx, dy); /* Takes ownership of copy_area */
5572
5573       /* Invalidate affected part in the parent window
5574        *  (no higher window should be affected)
5575        * We also invalidate any children in that area, which could include
5576        * this window if it still overlaps that area.
5577        */
5578       gdk_window_invalidate_region (GDK_WINDOW (private->parent), new_region, TRUE);
5579
5580       gdk_region_destroy (old_region);
5581       gdk_region_destroy (new_region);
5582     }
5583
5584   _gdk_syntesize_crossing_events_for_geometry_change (window);
5585 }
5586
5587
5588
5589 /**
5590  * gdk_window_move:
5591  * @window: a #GdkWindow
5592  * @x: X coordinate relative to window's parent
5593  * @y: Y coordinate relative to window's parent
5594  *
5595  * Repositions a window relative to its parent window.
5596  * For toplevel windows, window managers may ignore or modify the move;
5597  * you should probably use gtk_window_move() on a #GtkWindow widget
5598  * anyway, instead of using GDK functions. For child windows,
5599  * the move will reliably succeed.
5600  *
5601  * If you're also planning to resize the window, use gdk_window_move_resize()
5602  * to both move and resize simultaneously, for a nicer visual effect.
5603  **/
5604 void
5605 gdk_window_move (GdkWindow *window,
5606                  gint       x,
5607                  gint       y)
5608 {
5609   gdk_window_move_resize_internal (window, TRUE, x, y, -1, -1);
5610 }
5611
5612 /**
5613  * gdk_window_resize:
5614  * @window: a #GdkWindow
5615  * @width: new width of the window
5616  * @height: new height of the window
5617  *
5618  * Resizes @window; for toplevel windows, asks the window manager to resize
5619  * the window. The window manager may not allow the resize. When using GTK+,
5620  * use gtk_window_resize() instead of this low-level GDK function.
5621  *
5622  * Windows may not be resized below 1x1.
5623  *
5624  * If you're also planning to move the window, use gdk_window_move_resize()
5625  * to both move and resize simultaneously, for a nicer visual effect.
5626  **/
5627 void
5628 gdk_window_resize (GdkWindow *window,
5629                    gint       width,
5630                    gint       height)
5631 {
5632   gdk_window_move_resize_internal (window, FALSE, 0, 0, width, height);
5633 }
5634
5635
5636 /**
5637  * gdk_window_move_resize:
5638  * @window: a #GdkWindow
5639  * @x: new X position relative to window's parent
5640  * @y: new Y position relative to window's parent
5641  * @width: new width
5642  * @height: new height
5643  *
5644  * Equivalent to calling gdk_window_move() and gdk_window_resize(),
5645  * except that both operations are performed at once, avoiding strange
5646  * visual effects. (i.e. the user may be able to see the window first
5647  * move, then resize, if you don't use gdk_window_move_resize().)
5648  **/
5649 void
5650 gdk_window_move_resize (GdkWindow *window,
5651                         gint       x,
5652                         gint       y,
5653                         gint       width,
5654                         gint       height)
5655 {
5656   gdk_window_move_resize_internal (window, TRUE, x, y, width, height);
5657 }
5658
5659
5660 /**
5661  * gdk_window_scroll:
5662  * @window: a #GdkWindow
5663  * @dx: Amount to scroll in the X direction
5664  * @dy: Amount to scroll in the Y direction
5665  *
5666  * Scroll the contents of @window, both pixels and children, by the
5667  * given amount. @window itself does not move. Portions of the window
5668  * that the scroll operation brings in from offscreen areas are
5669  * invalidated. The invalidated region may be bigger than what would
5670  * strictly be necessary.
5671  *
5672  * For X11, a minimum area will be invalidated if the window has no
5673  * subwindows, or if the edges of the window's parent do not extend
5674  * beyond the edges of the window. In other cases, a multi-step process
5675  * is used to scroll the window which may produce temporary visual
5676  * artifacts and unnecessary invalidations.
5677  **/
5678 void
5679 gdk_window_scroll (GdkWindow *window,
5680                    gint       dx,
5681                    gint       dy)
5682 {
5683   GdkWindowObject *private = (GdkWindowObject *) window;
5684   GdkWindowObject *impl_window;
5685   GdkRegion *source_area, *copy_area, *noncopy_area;
5686   GList *tmp_list;
5687
5688   g_return_if_fail (GDK_IS_WINDOW (window));
5689
5690   if (dx == 0 && dy == 0)
5691     return;
5692
5693   if (private->destroyed)
5694     return;
5695
5696   /* First move all child windows, without causing invalidation */
5697   
5698   tmp_list = private->children;
5699   while (tmp_list)
5700     {
5701       GdkWindow *child = GDK_WINDOW (tmp_list->data);
5702       GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
5703       
5704       if (child_obj->impl == private->impl)
5705         {
5706           /* Just update the positions, the bits will move with the copy */
5707           child_obj->x += dx;
5708           child_obj->y += dy;
5709         }
5710       else
5711         {
5712           /* Native window, need to move it */
5713           GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, TRUE, child_obj->x + dx, child_obj->y + dy, -1, -1);
5714         }
5715       
5716       tmp_list = tmp_list->next;
5717     }
5718   
5719   recompute_visible_regions (private, FALSE, TRUE);
5720
5721   /* Then copy the actual bits of the window w/ child windows */
5722   
5723   impl_window = gdk_window_get_impl_window (private);
5724
5725   /* Calculate the area that can be gotten by copying the old area */
5726   copy_area = gdk_region_copy (private->clip_region);
5727   gdk_region_offset (copy_area, dx, dy);
5728   gdk_region_intersect (copy_area, private->clip_region);
5729
5730   /* And the rest need to be invalidated */
5731   noncopy_area = gdk_region_copy (private->clip_region);
5732   gdk_region_subtract (noncopy_area, copy_area);
5733
5734   /* Get window clip and convert to real window coords, this
5735      area is moved and we queue translations for all expose events
5736      to it that will be sent before the copy operation */
5737   /* TODO: Make queue_translation a vtable call instead of hardcoding this crap */
5738   if (!gdk_window_is_offscreen (impl_window))
5739     {
5740       source_area = gdk_region_copy (private->clip_region);
5741       /* convert from window coords to real parent */
5742       gdk_region_offset (source_area, private->abs_x, private->abs_y);
5743       _gdk_windowing_window_queue_translation ((GdkWindow *)impl_window, source_area, dx, dy);
5744       gdk_region_destroy (source_area);
5745     }
5746   
5747   /* convert from window coords to impl */
5748   gdk_region_offset (copy_area, private->abs_x, private->abs_y);
5749
5750   move_region_on_impl (private, copy_area, dx, dy); /* Takes ownership of copy_area */
5751    
5752   /* Invalidate not copied regions */
5753   gdk_window_invalidate_region (window, noncopy_area, TRUE);
5754
5755   gdk_region_destroy (noncopy_area);
5756   
5757   _gdk_syntesize_crossing_events_for_geometry_change (window);
5758 }
5759
5760 /**
5761  * gdk_window_move_region:
5762  * @window: a #GdkWindow
5763  * @region: The #GdkRegion to move
5764  * @dx: Amount to move in the X direction
5765  * @dy: Amount to move in the Y direction
5766  *
5767  * Move the part of @window indicated by @region by @dy pixels in the Y
5768  * direction and @dx pixels in the X direction. The portions of @region
5769  * that not covered by the new position of @region are invalidated.
5770  *
5771  * Child windows are not moved.
5772  *
5773  * Since: 2.8
5774  */
5775 void
5776 gdk_window_move_region (GdkWindow       *window,
5777                         const GdkRegion *region,
5778                         gint             dx,
5779                         gint             dy)
5780 {
5781   GdkWindowObject *private = (GdkWindowObject *) window;
5782   GdkWindowObject *impl_window;
5783   GdkRegion *source_area;
5784   GdkRegion *nocopy_area;
5785   GdkRegion *copy_area;
5786
5787   g_return_if_fail (GDK_IS_WINDOW (window));
5788   g_return_if_fail (region != NULL);
5789
5790   if (dx == 0 && dy == 0)
5791     return;
5792
5793   if (private->destroyed)
5794     return;
5795
5796   impl_window = gdk_window_get_impl_window (private);
5797   
5798   /* compute source regions */
5799   source_area = gdk_region_copy (region);
5800   gdk_region_intersect (source_area, private->clip_region_with_children);
5801
5802   /* compute destination regions */
5803   copy_area = gdk_region_copy (source_area);
5804   gdk_region_offset (copy_area, dx, dy);
5805   gdk_region_intersect (copy_area, private->clip_region_with_children);
5806
5807   /* invalidate parts of the region not covered by the copy */
5808   nocopy_area = gdk_region_copy (region);
5809   gdk_region_offset (nocopy_area, dx, dy);
5810   gdk_region_subtract (nocopy_area, copy_area);
5811   gdk_window_invalidate_region (window, nocopy_area, FALSE);
5812   gdk_region_destroy (nocopy_area);
5813
5814   /* TODO: Make queue_translation a vtable call instead of hardcoding this crap */
5815   if (!gdk_window_is_offscreen (impl_window))
5816     {
5817       gdk_region_offset (source_area, private->abs_x, private->abs_y);
5818       _gdk_windowing_window_queue_translation ((GdkWindow *)impl_window, source_area, dx, dy);
5819     }
5820
5821   /* convert from window coords to impl */
5822   gdk_region_offset (copy_area, private->abs_x, private->abs_y);
5823   
5824   move_region_on_impl (private, copy_area, dx, dy); /* Takes ownership of copy_area */
5825
5826   gdk_region_destroy (source_area);
5827 }
5828
5829 /**
5830  * gdk_window_set_background:
5831  * @window: a #GdkWindow
5832  * @color: an allocated #GdkColor
5833  *
5834  * Sets the background color of @window. (However, when using GTK+,
5835  * set the background of a widget with gtk_widget_modify_bg() - if
5836  * you're an application - or gtk_style_set_background() - if you're
5837  * implementing a custom widget.)
5838  *
5839  * The @color must be allocated; gdk_rgb_find_color() is the best way
5840  * to allocate a color.
5841  *
5842  * See also gdk_window_set_back_pixmap().
5843  */
5844 void
5845 gdk_window_set_background (GdkWindow      *window,
5846                            const GdkColor *color)
5847 {
5848   GdkWindowObject *private;
5849   GdkColormap *colormap = gdk_drawable_get_colormap (window);
5850
5851   g_return_if_fail (GDK_IS_WINDOW (window));
5852
5853   private = (GdkWindowObject *) window;
5854   
5855   private->bg_color = *color;
5856   gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
5857
5858   if (private->bg_pixmap &&
5859       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
5860       private->bg_pixmap != GDK_NO_BG)
5861     g_object_unref (private->bg_pixmap);
5862   
5863   private->bg_pixmap = NULL;
5864
5865   if (!GDK_WINDOW_DESTROYED (window) && gdk_window_has_impl (private))
5866     GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, &private->bg_color);
5867 }
5868
5869 /**
5870  * gdk_window_set_back_pixmap:
5871  * @window: a #GdkWindow
5872  * @pixmap: a #GdkPixmap, or %NULL
5873  * @parent_relative: whether the tiling origin is at the origin of
5874  *   @window's parent
5875  *
5876  * Sets the background pixmap of @window. May also be used to set a
5877  * background of "None" on @window, by setting a background pixmap
5878  * of %NULL.
5879  *
5880  * A background pixmap will be tiled, positioning the first tile at
5881  * the origin of @window, or if @parent_relative is %TRUE, the tiling
5882  * will be done based on the origin of the parent window (useful to
5883  * align tiles in a parent with tiles in a child).
5884  *
5885  * A background pixmap of %NULL means that the window will have no
5886  * background.  A window with no background will never have its
5887  * background filled by the windowing system, instead the window will
5888  * contain whatever pixels were already in the corresponding area of
5889  * the display.
5890  *
5891  * The windowing system will normally fill a window with its background
5892  * when the window is obscured then exposed, and when you call
5893  * gdk_window_clear().
5894  */
5895 void
5896 gdk_window_set_back_pixmap (GdkWindow *window,
5897                             GdkPixmap *pixmap,
5898                             gboolean   parent_relative)
5899 {
5900   GdkWindowObject *private;
5901
5902   g_return_if_fail (GDK_IS_WINDOW (window));
5903   g_return_if_fail (pixmap == NULL || !parent_relative);
5904   g_return_if_fail (pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap));
5905
5906   private = (GdkWindowObject *) window;
5907
5908   if (pixmap && !gdk_drawable_get_colormap (pixmap))
5909     {
5910       g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
5911       return;
5912     }
5913   
5914   if (private->bg_pixmap &&
5915       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
5916       private->bg_pixmap != GDK_NO_BG)
5917     g_object_unref (private->bg_pixmap);
5918
5919   if (parent_relative)
5920     private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
5921   else if (pixmap)
5922     private->bg_pixmap = g_object_ref (pixmap);
5923   else
5924     private->bg_pixmap = GDK_NO_BG;
5925   
5926   if (!GDK_WINDOW_DESTROYED (window) && gdk_window_has_impl (private))
5927     GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, private->bg_pixmap);
5928 }
5929
5930 static void
5931 update_cursor (GdkDisplay *display)
5932 {
5933   GdkWindowObject *pointer_window, *cursor_window;
5934   
5935   pointer_window = (GdkWindowObject *)display->pointer_info.window_under_pointer;
5936   
5937   cursor_window = pointer_window;
5938   while (cursor_window->cursor == NULL &&
5939          cursor_window->parent != NULL &&
5940          cursor_window->parent->window_type != GDK_WINDOW_ROOT)
5941     cursor_window = cursor_window->parent;
5942
5943   if (display->pointer_grab.window != NULL &&
5944       !is_parent_of (display->pointer_grab.window, (GdkWindow *)cursor_window))
5945     cursor_window = (GdkWindowObject *)display->pointer_grab.window;
5946   
5947   GDK_WINDOW_IMPL_GET_IFACE (pointer_window->impl)->set_cursor (pointer_window,
5948                                                                 cursor_window->cursor);
5949 }
5950
5951 /**
5952  * gdk_window_set_cursor:
5953  * @window: a #GdkWindow
5954  * @cursor: a cursor
5955  *
5956  * Sets the mouse pointer for a #GdkWindow. Use gdk_cursor_new_for_display() 
5957  * or gdk_cursor_new_from_pixmap() to create the cursor. To make the cursor 
5958  * invisible, use %GDK_BLANK_CURSOR. Passing %NULL for the @cursor argument 
5959  * to gdk_window_set_cursor() means that @window will use the cursor of its 
5960  * parent window. Most windows should use this default.
5961  */
5962 void
5963 gdk_window_set_cursor (GdkWindow *window,
5964                        GdkCursor *cursor)
5965 {
5966   GdkWindowObject *private;
5967   GdkDisplay *display;
5968
5969   g_return_if_fail (GDK_IS_WINDOW (window));
5970
5971   private = (GdkWindowObject *) window;
5972   display = gdk_drawable_get_display (window);
5973
5974   if (private->cursor)
5975     {
5976       gdk_cursor_unref (private->cursor);
5977       private->cursor = NULL;
5978     }
5979
5980   if (!GDK_WINDOW_DESTROYED (window))
5981     {
5982       if (cursor)
5983         private->cursor = gdk_cursor_ref (cursor);
5984
5985       if (is_parent_of (window, display->pointer_info.window_under_pointer))
5986         update_cursor (display);
5987     }
5988 }
5989
5990 /**
5991  * gdk_window_get_geometry:
5992  * @window: a #GdkWindow
5993  * @x: return location for X coordinate of window (relative to its parent)
5994  * @y: return location for Y coordinate of window (relative to its parent)
5995  * @width: return location for width of window
5996  * @height: return location for height of window
5997  * @depth: return location for bit depth of window
5998  *
5999  * Any of the return location arguments to this function may be %NULL,
6000  * if you aren't interested in getting the value of that field.
6001  *
6002  * The X and Y coordinates returned are relative to the parent window
6003  * of @window, which for toplevels usually means relative to the
6004  * window decorations (titlebar, etc.) rather than relative to the
6005  * root window (screen-size background window).
6006  *
6007  * On the X11 platform, the geometry is obtained from the X server,
6008  * so reflects the latest position of @window; this may be out-of-sync
6009  * with the position of @window delivered in the most-recently-processed
6010  * #GdkEventConfigure. gdk_window_get_position() in contrast gets the
6011  * position from the most recent configure event.
6012  *
6013  * <note>
6014  * If @window is not a toplevel, it is <emphasis>much</emphasis> better
6015  * to call gdk_window_get_position() and gdk_drawable_get_size() instead,
6016  * because it avoids the roundtrip to the X server and because
6017  * gdk_drawable_get_size() supports the full 32-bit coordinate space,
6018  * whereas gdk_window_get_geometry() is restricted to the 16-bit
6019  * coordinates of X11.
6020  *</note>
6021  **/
6022 void
6023 gdk_window_get_geometry (GdkWindow *window,
6024                          gint      *x,
6025                          gint      *y,
6026                          gint      *width,
6027                          gint      *height,
6028                          gint      *depth)
6029 {
6030   GdkWindowObject *private;
6031
6032   if (!window)
6033     {
6034       GDK_NOTE (MULTIHEAD,
6035                 g_message ("gdk_window_get_geometry(): Window needs "
6036                            "to be non-NULL to be multi head safe"));
6037       window = gdk_screen_get_root_window ((gdk_screen_get_default ()));
6038     }
6039
6040   g_return_if_fail (GDK_IS_WINDOW (window));
6041
6042   private = (GdkWindowObject *) window;
6043
6044   if (!GDK_WINDOW_DESTROYED (window))
6045     {
6046       if (gdk_window_has_impl (private))
6047         GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_geometry (window, x, y,
6048                                                                  width, height,
6049                                                                  depth);
6050       else
6051         {
6052           if (x)
6053             *x = private->x;
6054           if (y)
6055             *y = private->y;
6056           if (width)
6057             *width = private->width;
6058           if (height)
6059             *height = private->height;
6060           if (depth)
6061             *depth = private->depth;
6062         }
6063     }
6064 }
6065
6066 /**
6067  * gdk_window_get_origin:
6068  * @window: a #GdkWindow
6069  * @x: return location for X coordinate
6070  * @y: return location for Y coordinate
6071  *
6072  * Obtains the position of a window in root window coordinates.
6073  * (Compare with gdk_window_get_position() and
6074  * gdk_window_get_geometry() which return the position of a window
6075  * relative to its parent window.)
6076  *
6077  * Return value: not meaningful, ignore
6078  */
6079 gint
6080 gdk_window_get_origin (GdkWindow *window,
6081                        gint      *x,
6082                        gint      *y)
6083 {
6084   GdkWindowObject *private;
6085
6086   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
6087
6088   private = (GdkWindowObject *) window;
6089   
6090   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_origin (window, x, y);
6091
6092   if (x)
6093     *x += private->abs_x;
6094   if (y)
6095     *y += private->abs_y;
6096   
6097   return TRUE;
6098 }
6099
6100
6101 /**
6102  * gdk_window_get_deskrelative_origin:
6103  * @window: a toplevel #GdkWindow
6104  * @x: return location for X coordinate
6105  * @y: return location for Y coordinate
6106  * 
6107  * This gets the origin of a #GdkWindow relative to
6108  * an Enlightenment-window-manager desktop. As long as you don't
6109  * assume that the user's desktop/workspace covers the entire
6110  * root window (i.e. you don't assume that the desktop begins
6111  * at root window coordinate 0,0) this function is not necessary.
6112  * It's deprecated for that reason.
6113  * 
6114  * Return value: not meaningful
6115  **/
6116 gboolean
6117 gdk_window_get_deskrelative_origin (GdkWindow *window,
6118                                     gint      *x,
6119                                     gint      *y)
6120 {
6121   GdkWindowObject *private;
6122   gboolean return_val = FALSE;
6123   gint tx = 0;
6124   gint ty = 0;
6125
6126   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
6127
6128   private = (GdkWindowObject *) window;
6129   
6130   if (!GDK_WINDOW_DESTROYED (window))
6131     {
6132       return_val = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_deskrelative_origin (window, &tx, &ty);
6133       
6134       if (x)
6135         *x = tx + private->abs_x;
6136       if (y)
6137         *y = ty + private->abs_y;
6138     }
6139   
6140   return return_val;
6141 }
6142
6143 /**
6144  * gdk_window_shape_combine_mask:
6145  * @window: a #GdkWindow
6146  * @mask: shape mask
6147  * @x: X position of shape mask with respect to @window
6148  * @y: Y position of shape mask with respect to @window
6149  *
6150  * Applies a shape mask to @window. Pixels in @window corresponding to
6151  * set bits in the @mask will be visible; pixels in @window
6152  * corresponding to unset bits in the @mask will be transparent. This
6153  * gives a non-rectangular window.
6154  *
6155  * If @mask is %NULL, the shape mask will be unset, and the @x/@y
6156  * parameters are not used.
6157  *
6158  * On the X11 platform, this uses an X server extension which is
6159  * widely available on most common platforms, but not available on
6160  * very old X servers, and occasionally the implementation will be
6161  * buggy. On servers without the shape extension, this function
6162  * will do nothing.
6163  *
6164  * This function works on both toplevel and child windows.
6165  */
6166 void
6167 gdk_window_shape_combine_mask (GdkWindow *window,
6168                                GdkBitmap *mask,
6169                                gint       x,
6170                                gint       y)
6171 {
6172   GdkWindowObject *private;
6173
6174   g_return_if_fail (GDK_IS_WINDOW (window));
6175
6176   private = (GdkWindowObject *) window;
6177
6178   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_mask (window, mask, x, y);
6179 }
6180
6181 /**
6182  * gdk_window_shape_combine_region:
6183  * @window: a #GdkWindow
6184  * @shape_region: region of window to be non-transparent
6185  * @offset_x: X position of @shape_region in @window coordinates
6186  * @offset_y: Y position of @shape_region in @window coordinates
6187  *
6188  * Makes pixels in @window outside @shape_region be transparent,
6189  * so that the window may be nonrectangular. See also
6190  * gdk_window_shape_combine_mask() to use a bitmap as the mask.
6191  *
6192  * If @shape_region is %NULL, the shape will be unset, so the whole
6193  * window will be opaque again. @offset_x and @offset_y are ignored
6194  * if @shape_region is %NULL.
6195  *
6196  * On the X11 platform, this uses an X server extension which is
6197  * widely available on most common platforms, but not available on
6198  * very old X servers, and occasionally the implementation will be
6199  * buggy. On servers without the shape extension, this function
6200  * will do nothing.
6201  *
6202  * This function works on both toplevel and child windows.
6203  */
6204 void
6205 gdk_window_shape_combine_region (GdkWindow       *window,
6206                                  const GdkRegion *shape_region,
6207                                  gint             offset_x,
6208                                  gint             offset_y)
6209 {
6210   GdkWindowObject *private;
6211
6212   g_return_if_fail (GDK_IS_WINDOW (window));
6213
6214   private = (GdkWindowObject *) window;
6215
6216   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region (window, shape_region, offset_x, offset_y);
6217 }
6218
6219 /**
6220  * gdk_window_set_child_shapes:
6221  * @window: a #GdkWindow
6222  *
6223  * Sets the shape mask of @window to the union of shape masks
6224  * for all children of @window, ignoring the shape mask of @window
6225  * itself. Contrast with gdk_window_merge_child_shapes() which includes
6226  * the shape mask of @window in the masks to be merged.
6227  **/
6228 void
6229 gdk_window_set_child_shapes (GdkWindow *window)
6230 {
6231   GdkWindowObject *private;
6232
6233   g_return_if_fail (GDK_IS_WINDOW (window));
6234
6235   private = (GdkWindowObject *) window;
6236
6237   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_child_shapes (window);
6238 }
6239
6240 /**
6241  * gdk_window_merge_child_shapes:
6242  * @window: a #GdkWindow
6243  *
6244  * Merges the shape masks for any child windows into the
6245  * shape mask for @window. i.e. the union of all masks
6246  * for @window and its children will become the new mask
6247  * for @window. See gdk_window_shape_combine_mask().
6248  *
6249  * This function is distinct from gdk_window_set_child_shapes()
6250  * because it includes @window's shape mask in the set of shapes to
6251  * be merged.
6252  */
6253 void
6254 gdk_window_merge_child_shapes (GdkWindow *window)
6255 {
6256   GdkWindowObject *private;
6257
6258   g_return_if_fail (GDK_IS_WINDOW (window));
6259
6260   private = (GdkWindowObject *) window;
6261
6262   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->merge_child_shapes (window);
6263 }
6264
6265
6266 /**
6267  * gdk_window_set_static_gravities:
6268  * @window: a #GdkWindow
6269  * @use_static: %TRUE to turn on static gravity
6270  *
6271  * Set the bit gravity of the given window to static, and flag it so
6272  * all children get static subwindow gravity. This is used if you are
6273  * implementing scary features that involve deep knowledge of the
6274  * windowing system. Don't worry about it unless you have to.
6275  *
6276  * Return value: %TRUE if the server supports static gravity
6277  */
6278 gboolean
6279 gdk_window_set_static_gravities (GdkWindow *window,
6280                                  gboolean   use_static)
6281 {
6282   GdkWindowObject *private;
6283
6284   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
6285
6286   private = (GdkWindowObject *) window;
6287
6288   if (gdk_window_has_impl (private))
6289     return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_static_gravities (window, use_static);
6290   
6291   return FALSE;
6292 }
6293
6294 /**
6295  * gdk_window_set_composited:
6296  * @window: a #GdkWindow
6297  * @composited: %TRUE to set the window as composited
6298  *
6299  * Sets a #GdkWindow as composited, or unsets it. Composited 
6300  * windows do not automatically have their contents drawn to 
6301  * the screen. Drawing is redirected to an offscreen buffer 
6302  * and an expose event is emitted on the parent of the composited 
6303  * window. It is the responsibility of the parent's expose handler
6304  * to manually merge the off-screen content onto the screen in
6305  * whatever way it sees fit. See <xref linkend="composited-window-example"/>
6306  * for an example.
6307  *
6308  * It only makes sense for child windows to be composited; see
6309  * gdk_window_set_opacity() if you need translucent toplevel
6310  * windows.
6311  *
6312  * An additional effect of this call is that the area of this
6313  * window is no longer clipped from regions marked for
6314  * invalidation on its parent. Draws done on the parent
6315  * window are also no longer clipped by the child.
6316  *
6317  * This call is only supported on some systems (currently,
6318  * only X11 with new enough Xcomposite and Xdamage extensions). 
6319  * You must call gdk_display_supports_composite() to check if
6320  * setting a window as composited is supported before
6321  * attempting to do so.
6322  *
6323  * Since: 2.12
6324  */
6325 void
6326 gdk_window_set_composited (GdkWindow *window,
6327                            gboolean   composited)
6328 {
6329   GdkWindowObject *private = (GdkWindowObject *)window;
6330   GdkDisplay *display;
6331
6332   g_return_if_fail (GDK_IS_WINDOW (window));
6333
6334   composited = composited != FALSE;
6335
6336   if (private->composited == composited)
6337     return;
6338
6339   if (composited)
6340     gdk_window_set_has_native (window, TRUE);
6341
6342   display = gdk_drawable_get_display (GDK_DRAWABLE (window));
6343
6344   if (!gdk_display_supports_composite (display) && composited)
6345     {
6346       g_warning ("gdk_window_set_composited called but "
6347                  "compositing is not supported");
6348       return;
6349     }
6350
6351   _gdk_windowing_window_set_composited (window, composited);
6352
6353   recompute_visible_regions (private, TRUE, FALSE);
6354                              
6355   private->composited = composited;
6356 }
6357
6358
6359 static void
6360 remove_redirect_from_children (GdkWindowObject   *private,
6361                                GdkWindowRedirect *redirect)
6362 {
6363   GList *l;
6364   GdkWindowObject *child;
6365
6366   for (l = private->children; l != NULL; l = l->next)
6367     {
6368       child = l->data;
6369
6370       /* Don't redirect this child if it already has another redirect */
6371       if (child->redirect == redirect)
6372         {
6373           child->redirect = NULL;
6374           remove_redirect_from_children (child, redirect);
6375         }
6376     }
6377 }
6378
6379 /**
6380  * gdk_window_remove_redirection:
6381  * @window: a #GdkWindow
6382  *
6383  * Removes any active redirection started by
6384  * gdk_window_redirect_to_drawable().
6385  *
6386  * Since: 2.14
6387  **/
6388 void
6389 gdk_window_remove_redirection (GdkWindow *window)
6390 {
6391   GdkWindowObject *private;
6392
6393   g_return_if_fail (GDK_IS_WINDOW (window));
6394
6395   private = (GdkWindowObject *) window;
6396
6397   if (private->redirect &&
6398       private->redirect->redirected == private)
6399     {
6400       remove_redirect_from_children (private, private->redirect);
6401       gdk_window_redirect_free (private->redirect);
6402       private->redirect = NULL;
6403     }
6404 }
6405
6406 static void
6407 apply_redirect_to_children (GdkWindowObject   *private,
6408                             GdkWindowRedirect *redirect)
6409 {
6410   GList *l;
6411   GdkWindowObject *child;
6412
6413   for (l = private->children; l != NULL; l = l->next)
6414     {
6415       child = l->data;
6416
6417       /* Don't redirect this child if it already has another redirect */
6418       if (!child->redirect)
6419         {
6420           child->redirect = redirect;
6421           apply_redirect_to_children (child, redirect);
6422         }
6423     }
6424 }
6425
6426 /**
6427  * gdk_window_redirect_to_drawable:
6428  * @window: a #GdkWindow
6429  * @drawable: a #GdkDrawable
6430  * @src_x: x position in @window
6431  * @src_y: y position in @window
6432  * @dest_x: x position in @drawable
6433  * @dest_y: y position in @drawable
6434  * @width: width of redirection
6435  * @height: height of redirection
6436  *
6437  * Redirects drawing into @window so that drawing to the
6438  * window in the rectangle specified by @src_x, @src_y,
6439  * @width and @height is also drawn into @drawable at
6440  * @dest_x, @dest_y.
6441  *
6442  * Only drawing between gdk_window_begin_paint_region() or
6443  * gdk_window_begin_paint_rect() and gdk_window_end_paint() is
6444  * redirected.
6445  *
6446  * Redirection is active until gdk_window_remove_redirection()
6447  * is called.
6448  *
6449  * Since: 2.14
6450  **/
6451 void
6452 gdk_window_redirect_to_drawable (GdkWindow   *window,
6453                                  GdkDrawable *drawable,
6454                                  gint         src_x,
6455                                  gint         src_y,
6456                                  gint         dest_x,
6457                                  gint         dest_y,
6458                                  gint         width,
6459                                  gint         height)
6460 {
6461   GdkWindowObject *private;
6462
6463   g_return_if_fail (GDK_IS_WINDOW (window));
6464   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
6465   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
6466
6467   private = (GdkWindowObject *) window;
6468
6469   if (private->redirect)
6470     gdk_window_remove_redirection (window);
6471
6472   if (width == -1 || height == -1)
6473     {
6474       gint w, h;
6475       gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
6476       if (width == -1)
6477         width = w;
6478       if (height == -1)
6479         height = h;
6480     }
6481   
6482   private->redirect = g_new0 (GdkWindowRedirect, 1);
6483   private->redirect->redirected = private;
6484   private->redirect->pixmap = g_object_ref (drawable);
6485   private->redirect->src_x = src_x;
6486   private->redirect->src_y = src_y;
6487   private->redirect->dest_x = dest_x;
6488   private->redirect->dest_y = dest_y;
6489   private->redirect->width = width;
6490   private->redirect->height = height;
6491
6492   apply_redirect_to_children (private, private->redirect);
6493 }
6494
6495 static void
6496 window_get_size_rectangle (GdkWindow    *window,
6497                            GdkRectangle *rect)
6498 {
6499   GdkWindowObject *private = (GdkWindowObject *) window;
6500   
6501   rect->x = rect->y = 0;
6502   rect->width = private->width;
6503   rect->height = private->height;
6504 }
6505
6506 /* Calculates the real clipping region for a window, in window coordinates,
6507  * taking into account other windows, gc clip region and gc clip mask.
6508  */
6509 GdkRegion *
6510 _gdk_window_calculate_full_clip_region (GdkWindow *window,
6511                                         GdkWindow *base_window,
6512                                         gboolean   do_children,
6513                                         gint      *base_x_offset,
6514                                         gint      *base_y_offset)
6515 {
6516   GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
6517   GdkRectangle visible_rect;
6518   GdkRegion *real_clip_region, *tmpreg;
6519   gint x_offset, y_offset;
6520   GdkWindowObject *parentwin, *lastwin;
6521
6522   if (base_x_offset)
6523     *base_x_offset = 0;
6524   if (base_y_offset)
6525     *base_y_offset = 0;
6526   
6527   if (!GDK_WINDOW_IS_MAPPED (window) || private->input_only)
6528     return gdk_region_new ();
6529
6530   window_get_size_rectangle (window, &visible_rect);
6531
6532   /* real_clip_region is in window coordinates */
6533   real_clip_region = gdk_region_rectangle (&visible_rect);
6534
6535   x_offset = y_offset = 0;
6536
6537   lastwin = private;
6538   if (do_children)
6539     parentwin = lastwin;
6540   else
6541     parentwin = lastwin->parent;
6542   
6543   /* Remove the areas of all overlapping windows above parentwin in the hiearachy */
6544   for (; parentwin != NULL &&
6545          (parentwin == private || lastwin != (GdkWindowObject*) base_window);
6546        lastwin = parentwin, parentwin = lastwin->parent)
6547     {
6548       GList *cur;
6549       GdkRectangle real_clip_rect;
6550       gboolean is_offscreen;
6551
6552       if (parentwin != private)
6553         {
6554           x_offset += GDK_WINDOW_OBJECT (lastwin)->x;
6555           y_offset += GDK_WINDOW_OBJECT (lastwin)->y;
6556         }
6557
6558       is_offscreen = gdk_window_is_offscreen (parentwin);
6559
6560       /* children is ordered in reverse stack order */
6561       for (cur = parentwin->children;
6562            cur && cur->data != lastwin;
6563            cur = cur->next)
6564         {
6565           GdkWindow *child = cur->data;
6566           GdkWindowObject *child_private = (GdkWindowObject *)child;
6567
6568           if (!GDK_WINDOW_IS_MAPPED (child) || child_private->input_only)
6569             continue;
6570
6571           /* Ignore offscreen children, as they don't draw in their parent and
6572            * don't take part in the clipping */
6573           if (gdk_window_is_offscreen (child_private))
6574             continue;
6575
6576           window_get_size_rectangle (child, &visible_rect);
6577
6578           /* Convert rect to "window" coords */
6579           visible_rect.x += child_private->x - x_offset;
6580           visible_rect.y += child_private->y - y_offset;
6581           
6582           /* This shortcut is really necessary for performance when there are a lot of windows */
6583           gdk_region_get_clipbox (real_clip_region, &real_clip_rect);
6584           if (visible_rect.x >= real_clip_rect.x + real_clip_rect.width ||
6585               visible_rect.x + visible_rect.width <= real_clip_rect.x ||
6586               visible_rect.y >= real_clip_rect.y + real_clip_rect.height ||
6587               visible_rect.y + visible_rect.height <= real_clip_rect.y)
6588             continue;
6589           
6590           tmpreg = gdk_region_rectangle (&visible_rect);
6591           gdk_region_subtract (real_clip_region, tmpreg);
6592           gdk_region_destroy (tmpreg);
6593         }
6594       
6595       /* Clip to the parent */
6596       window_get_size_rectangle ((GdkWindow *)parentwin, &visible_rect);
6597       /* Convert rect to "window" coords */
6598       visible_rect.x += - x_offset;
6599       visible_rect.y += - y_offset;
6600       
6601       tmpreg = gdk_region_rectangle (&visible_rect);
6602       gdk_region_intersect (real_clip_region, tmpreg);
6603       gdk_region_destroy (tmpreg);
6604     }
6605
6606   if (base_x_offset)
6607     *base_x_offset = x_offset;
6608   if (base_y_offset)
6609     *base_y_offset = y_offset;
6610
6611   return real_clip_region;
6612 }
6613
6614 void
6615 _gdk_window_add_damage (GdkWindow *toplevel,
6616                         GdkRegion *damaged_region)
6617 {
6618   GdkDisplay *display;
6619   GdkEvent event = { 0, };
6620   event.expose.type = GDK_DAMAGE;
6621   event.expose.window = toplevel;
6622   event.expose.send_event = FALSE;
6623   event.expose.region = damaged_region;
6624   gdk_region_get_clipbox (event.expose.region, &event.expose.area);
6625   display = gdk_drawable_get_display (event.expose.window);
6626   _gdk_event_queue_append (display, gdk_event_copy (&event));
6627 }
6628
6629 static void
6630 gdk_window_redirect_free (GdkWindowRedirect *redirect)
6631 {
6632   g_object_unref (redirect->pixmap);
6633   g_free (redirect);
6634 }
6635
6636 static void
6637 convert_coords_to_child (GdkWindowObject *child,
6638                          double x, double y,
6639                          double *child_x, double *child_y)
6640 {
6641   *child_x = x - child->x;
6642   *child_y = y - child->y;
6643
6644   if (child->offscreen_hooks)
6645     child->offscreen_hooks->from_parent ((GdkWindow *)child, x, y, child_x, child_y);
6646 }
6647
6648 static gboolean
6649 point_in_window (GdkWindowObject *window,
6650                  double x, double y)
6651 {
6652   return
6653     x >= 0 &&  x < window->width &&
6654     y >= 0 && y < window->height;
6655 }
6656
6657 static void
6658 convert_toplevel_coords_to_window (GdkWindow *window,
6659                                    gdouble    toplevel_x,
6660                                    gdouble    toplevel_y,
6661                                    gdouble   *window_x,
6662                                    gdouble   *window_y)
6663 {
6664   GdkWindowObject *private;
6665   gdouble x, y;
6666   GList *children, *l;
6667
6668   private = GDK_WINDOW_OBJECT (window);
6669   
6670   x = toplevel_x;
6671   y = toplevel_y;
6672
6673   children = NULL;
6674   while (private->parent != NULL &&
6675          (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT))
6676     {
6677       children = g_list_prepend (children, private);
6678       private = private->parent;
6679     }
6680
6681   for (l = children; l != NULL; l = l->next)
6682     convert_coords_to_child (l->data, x, y, &x, &y);
6683   
6684   g_list_free (children);
6685   
6686   *window_x = x;
6687   *window_y = y;
6688 }
6689
6690 GdkWindow *
6691 _gdk_window_find_descendant_at (GdkWindow *toplevel,
6692                                 double x, double y,
6693                                 double *found_x,
6694                                 double *found_y)
6695 {
6696   GdkWindowObject *private, *sub;
6697   double child_x, child_y;
6698   GList *l;
6699
6700   private = (GdkWindowObject *)toplevel;
6701   
6702   if (point_in_window (private, x, y))
6703     {
6704       do 
6705         {
6706           /* Children is ordered in reverse stack order, i.e. first is topmost */
6707           for (l = private->children; l != NULL; l = l->next)
6708             {
6709               sub = l->data;
6710
6711               if (!GDK_WINDOW_IS_MAPPED (sub))
6712                 continue;
6713               
6714               convert_coords_to_child (sub,
6715                                        x, y,
6716                                        &child_x, &child_y);
6717               if (point_in_window (sub, child_x, child_y))
6718                 {
6719                   x = child_x;
6720                   y = child_y;
6721                   private = sub;
6722                   break;
6723                 }
6724             }
6725         }
6726       while (l != NULL);
6727     }
6728   else
6729     {
6730       /* Not in window at all */
6731       private = NULL;
6732     }
6733
6734   if (found_x)
6735     *found_x = x;
6736   if (found_y)
6737     *found_y = y;
6738   
6739   return (GdkWindow *)private;
6740 }
6741
6742 static const guint type_masks[] = {
6743   GDK_SUBSTRUCTURE_MASK, /* GDK_DELETE                 = 0  */
6744   GDK_STRUCTURE_MASK, /* GDK_DESTROY                   = 1  */
6745   GDK_EXPOSURE_MASK, /* GDK_EXPOSE                     = 2  */
6746   GDK_POINTER_MOTION_MASK, /* GDK_MOTION_NOTIFY        = 3  */
6747   GDK_BUTTON_PRESS_MASK, /* GDK_BUTTON_PRESS           = 4  */
6748   GDK_BUTTON_PRESS_MASK, /* GDK_2BUTTON_PRESS          = 5  */
6749   GDK_BUTTON_PRESS_MASK, /* GDK_3BUTTON_PRESS          = 6  */
6750   GDK_BUTTON_RELEASE_MASK, /* GDK_BUTTON_RELEASE       = 7  */
6751   GDK_KEY_PRESS_MASK, /* GDK_KEY_PRESS                 = 8  */
6752   GDK_KEY_RELEASE_MASK, /* GDK_KEY_RELEASE             = 9  */
6753   GDK_ENTER_NOTIFY_MASK, /* GDK_ENTER_NOTIFY           = 10 */
6754   GDK_LEAVE_NOTIFY_MASK, /* GDK_LEAVE_NOTIFY           = 11 */
6755   GDK_FOCUS_CHANGE_MASK, /* GDK_FOCUS_CHANGE           = 12 */
6756   GDK_STRUCTURE_MASK, /* GDK_CONFIGURE                 = 13 */
6757   GDK_VISIBILITY_NOTIFY_MASK, /* GDK_MAP               = 14 */
6758   GDK_VISIBILITY_NOTIFY_MASK, /* GDK_UNMAP             = 15 */
6759   GDK_PROPERTY_CHANGE_MASK, /* GDK_PROPERTY_NOTIFY     = 16 */
6760   GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_CLEAR     = 17 */
6761   GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_REQUEST   = 18 */
6762   GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_NOTIFY    = 19 */
6763   GDK_PROXIMITY_IN_MASK, /* GDK_PROXIMITY_IN           = 20 */
6764   GDK_PROXIMITY_OUT_MASK, /* GDK_PROXIMITY_OUT         = 21 */
6765   GDK_ALL_EVENTS_MASK, /* GDK_DRAG_ENTER               = 22 */
6766   GDK_ALL_EVENTS_MASK, /* GDK_DRAG_LEAVE               = 23 */
6767   GDK_ALL_EVENTS_MASK, /* GDK_DRAG_MOTION              = 24 */
6768   GDK_ALL_EVENTS_MASK, /* GDK_DRAG_STATUS              = 25 */
6769   GDK_ALL_EVENTS_MASK, /* GDK_DROP_START               = 26 */
6770   GDK_ALL_EVENTS_MASK, /* GDK_DROP_FINISHED            = 27 */
6771   GDK_ALL_EVENTS_MASK, /* GDK_CLIENT_EVENT             = 28 */
6772   GDK_VISIBILITY_NOTIFY_MASK, /* GDK_VISIBILITY_NOTIFY = 29 */
6773   GDK_EXPOSURE_MASK, /* GDK_NO_EXPOSE                  = 30 */
6774   GDK_SCROLL_MASK | GDK_BUTTON_PRESS_MASK,/* GDK_SCROLL= 31 */
6775   0, /* GDK_WINDOW_STATE = 32 */
6776   0, /* GDK_SETTING = 33 */
6777   0, /* GDK_OWNER_CHANGE = 34 */
6778   0, /* GDK_GRAB_BROKEN = 35 */
6779   0, /* GDK_DAMAGE = 36 */
6780 };
6781 G_STATIC_ASSERT (G_N_ELEMENTS (type_masks) == GDK_EVENT_LAST);
6782
6783 /* send motion events if the right buttons are down */
6784 static guint
6785 update_evmask_for_button_motion (guint           evmask,
6786                                  GdkModifierType mask)
6787 {
6788   if (evmask & GDK_BUTTON_MOTION_MASK &&
6789       mask & (GDK_BUTTON1_MASK |
6790               GDK_BUTTON2_MASK |
6791               GDK_BUTTON3_MASK |
6792               GDK_BUTTON4_MASK |
6793               GDK_BUTTON5_MASK))
6794     evmask |= GDK_POINTER_MOTION_MASK;
6795
6796   if ((evmask & GDK_BUTTON1_MOTION_MASK && mask & GDK_BUTTON1_MASK) ||
6797       (evmask & GDK_BUTTON2_MOTION_MASK && mask & GDK_BUTTON2_MASK) ||
6798       (evmask & GDK_BUTTON3_MOTION_MASK && mask & GDK_BUTTON3_MASK))
6799     evmask |= GDK_POINTER_MOTION_MASK;
6800
6801   return evmask;
6802 }
6803
6804 static gboolean
6805 is_button_type (GdkEventType type)
6806 {
6807   return type == GDK_BUTTON_PRESS ||
6808          type == GDK_2BUTTON_PRESS ||
6809          type == GDK_3BUTTON_PRESS ||
6810          type == GDK_BUTTON_RELEASE ||
6811          type == GDK_SCROLL;
6812 }
6813
6814 static gboolean
6815 is_motion_type (GdkEventType type)
6816 {
6817   return type == GDK_MOTION_NOTIFY ||
6818          type == GDK_ENTER_NOTIFY ||
6819          type == GDK_LEAVE_NOTIFY;
6820 }
6821
6822 static GdkWindowObject *
6823 find_common_ancestor (GdkWindowObject *win1,
6824                       GdkWindowObject *win2)
6825 {
6826   GdkWindowObject *tmp;
6827   GList *path1 = NULL, *path2 = NULL;
6828   GList *list1, *list2;
6829
6830   tmp = win1;
6831   while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
6832     {
6833       path1 = g_list_prepend (path1, tmp);
6834       tmp = tmp->parent;
6835     }
6836
6837   tmp = win2;
6838   while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
6839     {
6840       path2 = g_list_prepend (path2, tmp);
6841       tmp = tmp->parent;
6842     }
6843
6844   list1 = path1;
6845   list2 = path2;
6846   tmp = NULL;
6847   while (list1 && list2 && (list1->data == list2->data))
6848     {
6849       tmp = (GdkWindowObject *)list1->data;
6850       list1 = g_list_next (list1);
6851       list2 = g_list_next (list2);
6852     }
6853   g_list_free (path1);
6854   g_list_free (path2);
6855
6856   return tmp;
6857 }
6858
6859 GdkEvent *
6860 _gdk_make_event (GdkWindow    *window,
6861                  GdkEventType  type,
6862                  GdkEvent     *event_in_queue,
6863                  gboolean      before_event)
6864 {
6865   GdkEvent *event = gdk_event_new (type);
6866   guint32 the_time;
6867   GdkModifierType the_state;
6868
6869   the_time = gdk_event_get_time (event_in_queue);
6870   gdk_event_get_state (event_in_queue, &the_state);
6871
6872   event->any.window = g_object_ref (window);
6873   event->any.send_event = FALSE;
6874
6875   switch (type)
6876     {
6877     case GDK_MOTION_NOTIFY:
6878       event->motion.time = the_time;
6879       event->motion.axes = NULL;
6880       event->motion.state = the_state;
6881       break;
6882
6883     case GDK_BUTTON_PRESS:
6884     case GDK_2BUTTON_PRESS:
6885     case GDK_3BUTTON_PRESS:
6886     case GDK_BUTTON_RELEASE:
6887       event->button.time = the_time;
6888       event->button.axes = NULL;
6889       event->button.state = the_state;
6890       break;
6891
6892     case GDK_SCROLL:
6893       event->scroll.time = the_time;
6894       event->scroll.state = the_state;
6895       break;
6896
6897     case GDK_KEY_PRESS:
6898     case GDK_KEY_RELEASE:
6899       event->key.time = the_time;
6900       event->key.state = the_state;
6901       break;
6902
6903     case GDK_ENTER_NOTIFY:
6904     case GDK_LEAVE_NOTIFY:
6905       event->crossing.time = the_time;
6906       event->crossing.state = the_state;
6907       break;
6908
6909     case GDK_PROPERTY_NOTIFY:
6910       event->property.time = the_time;
6911       event->property.state = the_state;
6912       break;
6913
6914     case GDK_SELECTION_CLEAR:
6915     case GDK_SELECTION_REQUEST:
6916     case GDK_SELECTION_NOTIFY:
6917       event->selection.time = the_time;
6918       break;
6919
6920     case GDK_PROXIMITY_IN:
6921     case GDK_PROXIMITY_OUT:
6922       event->proximity.time = the_time;
6923       break;
6924
6925     case GDK_DRAG_ENTER:
6926     case GDK_DRAG_LEAVE:
6927     case GDK_DRAG_MOTION:
6928     case GDK_DRAG_STATUS:
6929     case GDK_DROP_START:
6930     case GDK_DROP_FINISHED:
6931       event->dnd.time = the_time;
6932       break;
6933
6934     case GDK_FOCUS_CHANGE:
6935     case GDK_CONFIGURE:
6936     case GDK_MAP:
6937     case GDK_UNMAP:
6938     case GDK_CLIENT_EVENT:
6939     case GDK_VISIBILITY_NOTIFY:
6940     case GDK_NO_EXPOSE:
6941     case GDK_DELETE:
6942     case GDK_DESTROY:
6943     case GDK_EXPOSE:
6944     default:
6945       break;
6946     }
6947
6948   if (event_in_queue)
6949     {
6950     if (before_event)
6951       _gdk_event_queue_insert_before (gdk_drawable_get_display (window), event_in_queue, event);
6952     else
6953       _gdk_event_queue_insert_after (gdk_drawable_get_display (window), event_in_queue, event);
6954     }
6955   else
6956     _gdk_event_queue_append (gdk_drawable_get_display (window), event);
6957
6958   return event;
6959 }
6960
6961 static void
6962 send_crossing_event (GdkDisplay                 *display,
6963                      GdkWindowObject            *toplevel,
6964                      GdkWindowObject            *window,
6965                      GdkEventType                type,
6966                      GdkCrossingMode             mode,
6967                      GdkNotifyType               notify_type,
6968                      GdkWindow                  *subwindow,
6969                      gint                        toplevel_x,
6970                      gint                        toplevel_y,
6971                      GdkModifierType             mask,
6972                      guint32                     time_,
6973                      GdkEvent                   *event_in_queue)
6974 {
6975   GdkEvent *event;
6976   guint32 event_mask;
6977
6978   if (display->pointer_grab.window != NULL &&
6979       !display->pointer_grab.owner_events &&
6980       (GdkWindow *)window != display->pointer_grab.window)
6981     return;
6982   
6983   if (type == GDK_LEAVE_NOTIFY)
6984     event_mask = GDK_LEAVE_NOTIFY_MASK;
6985   else
6986     event_mask = GDK_ENTER_NOTIFY_MASK;
6987
6988   if (window->event_mask & event_mask)
6989     {
6990       event = _gdk_make_event ((GdkWindow *)window, type, event_in_queue, TRUE);
6991       event->crossing.time = time_;
6992       event->crossing.subwindow = subwindow;
6993       if (subwindow)
6994         g_object_ref (subwindow);
6995       convert_toplevel_coords_to_window ((GdkWindow *)window,
6996                                          toplevel_x, toplevel_y,
6997                                          &event->crossing.x, &event->crossing.y);
6998       event->crossing.x_root = toplevel_x + toplevel->x;
6999       event->crossing.y_root = toplevel_y + toplevel->y;
7000       event->crossing.mode = mode;
7001       event->crossing.detail = notify_type;
7002       event->crossing.focus = FALSE;
7003       event->crossing.state = mask;
7004     }
7005 }
7006   
7007
7008 /* The coordinates are in the toplevel window that src/dest are in.
7009  * src and dest are always (if != NULL) in the same toplevel, as
7010  * we get a leave-notify and set the window_under_pointer to null
7011  * before crossing to another toplevel.
7012  */
7013 void
7014 _gdk_syntesize_crossing_events (GdkDisplay                 *display,
7015                                 GdkWindow                  *src,
7016                                 GdkWindow                  *dest,
7017                                 GdkCrossingMode             mode,
7018                                 gint                        toplevel_x,
7019                                 gint                        toplevel_y,
7020                                 GdkModifierType             mask,
7021                                 guint32                     time_,
7022                                 GdkEvent                   *event_in_queue)
7023 {
7024   GdkWindowObject *c;
7025   GdkWindowObject *win, *last, *next;
7026   GList *path, *list;
7027   gboolean non_linear;
7028   GdkWindowObject *a;
7029   GdkWindowObject *b;
7030   GdkWindowObject *toplevel;
7031   GdkNotifyType notify_type;
7032
7033   /* TODO: Don't send events to toplevel, as we get those from the windowing system */
7034   
7035   a = (GdkWindowObject *)src;
7036   b = (GdkWindowObject *)dest;
7037   if (a == b)
7038     return; /* No crossings generated between src and dest */
7039
7040   c = find_common_ancestor (a, b);
7041
7042   non_linear = (c != a) && (c != b);
7043
7044   if (a) /* There might not be a source (i.e. if no previous pointer_in_window) */
7045     {
7046       toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)a);
7047       
7048       /* Traverse up from a to (excluding) c sending leave events */
7049       if (non_linear)
7050         notify_type = GDK_NOTIFY_NONLINEAR;
7051       else if (c == a)
7052         notify_type = GDK_NOTIFY_INFERIOR;
7053       else
7054         notify_type = GDK_NOTIFY_ANCESTOR;
7055       send_crossing_event (display, toplevel,
7056                            a, GDK_LEAVE_NOTIFY,
7057                            mode,
7058                            notify_type,
7059                            NULL,
7060                            toplevel_x, toplevel_y,
7061                            mask, time_,
7062                            event_in_queue);
7063      
7064       if (c != a)
7065         {
7066           if (non_linear)
7067             notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
7068           else
7069             notify_type = GDK_NOTIFY_VIRTUAL;
7070           
7071           last = a;
7072           win = a->parent;
7073           while (win != c && GDK_WINDOW_TYPE (win) != GDK_WINDOW_ROOT)
7074             {
7075               send_crossing_event (display, toplevel,
7076                                    win, GDK_LEAVE_NOTIFY,
7077                                    mode,
7078                                    notify_type,
7079                                    (GdkWindow *)last,
7080                                    toplevel_x, toplevel_y,
7081                                    mask, time_,
7082                                    event_in_queue);
7083               
7084               last = win;
7085               win = win->parent;
7086             }
7087         }
7088     }
7089
7090   if (b) /* Might not be a dest, e.g. if we're moving out of the window */
7091     {
7092       toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)b);
7093       
7094       /* Traverse down from c to b */
7095       if (c != b)
7096         {
7097           path = NULL;
7098           win = b->parent;
7099           while (win != c && GDK_WINDOW_TYPE (win) != GDK_WINDOW_ROOT)
7100             {
7101               path = g_list_prepend (path, win);
7102               win = win->parent;
7103             }
7104           
7105           if (non_linear)
7106             notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
7107           else
7108             notify_type = GDK_NOTIFY_VIRTUAL;
7109           
7110           list = path;
7111           while (list)
7112             {
7113               win = (GdkWindowObject *)list->data;
7114               list = g_list_next (list);
7115               if (list)
7116                 next = (GdkWindowObject *)list->data;
7117               else
7118                 next = b;
7119
7120               send_crossing_event (display, toplevel,
7121                                    win, GDK_ENTER_NOTIFY,
7122                                    mode,
7123                                    notify_type,
7124                                    (GdkWindow *)next,
7125                                    toplevel_x, toplevel_y,
7126                                    mask, time_,
7127                                    event_in_queue);
7128             }
7129           g_list_free (path);
7130         }
7131
7132
7133       if (non_linear)
7134         notify_type = GDK_NOTIFY_NONLINEAR;
7135       else if (c == a)
7136         notify_type = GDK_NOTIFY_ANCESTOR;
7137       else
7138         notify_type = GDK_NOTIFY_INFERIOR;
7139       
7140       send_crossing_event (display, toplevel,
7141                            b, GDK_ENTER_NOTIFY,
7142                            mode,
7143                            notify_type,
7144                            NULL,
7145                            toplevel_x, toplevel_y,
7146                            mask, time_,
7147                            event_in_queue);
7148     }
7149 }
7150
7151 static GdkWindow *
7152 get_toplevel (GdkWindow *w)
7153 {
7154   GdkWindowObject *private = GDK_WINDOW_OBJECT (w);
7155   
7156   while (private->parent != NULL &&
7157          (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT))
7158     private = private->parent;
7159
7160   return GDK_WINDOW (private);
7161 }
7162
7163 /* Returns the window inside the event window with the pointer in it
7164  * at the specified coordinates, or NULL if its not in any child of
7165  * the toplevel. It also takes into account !owner_events grabs.
7166  */
7167 static GdkWindow *
7168 get_pointer_window (GdkDisplay *display,
7169                     GdkWindow *event_window,
7170                     gdouble toplevel_x,
7171                     gdouble toplevel_y)
7172 {
7173   GdkWindow *pointer_window;
7174
7175   if (event_window == display->pointer_info.toplevel_under_pointer)
7176     pointer_window =
7177       _gdk_window_find_descendant_at (event_window,
7178                                       toplevel_x, toplevel_y,
7179                                       NULL, NULL);
7180   else
7181     pointer_window = NULL;
7182
7183   if (display->pointer_grab.window != NULL &&
7184       !display->pointer_grab.owner_events &&
7185       pointer_window != display->pointer_grab.window)
7186     pointer_window = NULL;
7187   
7188   return pointer_window;
7189 }
7190
7191 void
7192 _gdk_display_set_window_under_pointer (GdkDisplay *display,
7193                                        GdkWindow *window)
7194 {
7195   GdkWindowObject *private;
7196
7197   private = (GdkWindowObject *)window;
7198
7199   if (display->pointer_info.window_under_pointer)
7200     g_object_unref (display->pointer_info.window_under_pointer);
7201   display->pointer_info.window_under_pointer = window;
7202   if (window)
7203     g_object_ref (window);
7204
7205   if (window)
7206     update_cursor (display);
7207 }
7208
7209 void
7210 _gdk_syntesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
7211 {
7212   GdkDisplay *display;
7213   GdkWindow *changed_toplevel;
7214   GdkWindow *new_window_under_pointer;
7215
7216   changed_toplevel = get_toplevel (changed_window);
7217   
7218   display = gdk_drawable_get_display (changed_window);
7219   if (changed_toplevel == display->pointer_info.toplevel_under_pointer)
7220     {
7221       new_window_under_pointer =
7222         get_pointer_window (display, changed_toplevel,
7223                             display->pointer_info.toplevel_x,
7224                             display->pointer_info.toplevel_y);
7225       if (new_window_under_pointer !=
7226           display->pointer_info.window_under_pointer)
7227         {
7228           _gdk_syntesize_crossing_events (display,
7229                                           display->pointer_info.window_under_pointer,
7230                                           new_window_under_pointer,
7231                                           GDK_CROSSING_NORMAL,
7232                                           display->pointer_info.toplevel_x,
7233                                           display->pointer_info.toplevel_y,
7234                                           display->pointer_info.state,
7235                                           GDK_CURRENT_TIME,
7236                                           NULL);
7237           _gdk_display_set_window_under_pointer (display, new_window_under_pointer);
7238         }
7239     }
7240 }
7241
7242 /* Don't use for crossing events */
7243 static GdkWindow *
7244 get_event_window (GdkDisplay                 *display,
7245                   GdkWindow                  *pointer_window,
7246                   GdkEventType                type,
7247                   GdkModifierType             mask)
7248 {
7249   guint evmask;
7250   GdkWindow *grab_window;
7251   GdkWindowObject *w;
7252
7253   if ((display->pointer_grab.window != NULL && !display->pointer_grab.owner_events) ||
7254       (type == GDK_BUTTON_RELEASE && display->pointer_grab.grab_one_pointer_release_event))
7255     {
7256       evmask = display->pointer_grab.event_mask;
7257       evmask = update_evmask_for_button_motion (evmask, mask);
7258
7259       if (type == GDK_BUTTON_RELEASE &&
7260           display->pointer_grab.grab_one_pointer_release_event)
7261         {
7262           grab_window = display->pointer_grab.grab_one_pointer_release_event;
7263           display->pointer_grab.grab_one_pointer_release_event = NULL;
7264         }
7265       else
7266         grab_window = display->pointer_grab.window;
7267
7268       if (evmask & type_masks[type])
7269         return grab_window;
7270       else
7271         return NULL;
7272     }
7273
7274   w = (GdkWindowObject *)pointer_window;
7275   while (w != NULL)
7276     {
7277       evmask = w->event_mask;
7278       evmask = update_evmask_for_button_motion (evmask, mask);
7279
7280       if (evmask & type_masks[type])
7281         return (GdkWindow *)w;
7282
7283       w = w->parent;
7284     }
7285
7286   if (display->pointer_grab.window != NULL &&
7287       display->pointer_grab.owner_events)
7288     {
7289       evmask = display->pointer_grab.event_mask;
7290       evmask = update_evmask_for_button_motion (evmask, mask);
7291
7292       if (evmask & type_masks[type])
7293         return display->pointer_grab.window;
7294       else
7295         return NULL;
7296     }
7297
7298   return NULL;
7299 }
7300
7301 static gboolean
7302 proxy_pointer_event (GdkDisplay                 *display,
7303                      GdkEvent                   *source_event)
7304 {
7305   GdkWindow *toplevel_window;
7306   GdkWindow *pointer_window;
7307   GdkWindow *cursor_window;
7308   gboolean sent_motion;
7309   GdkEvent *event;
7310   guint state;
7311   gdouble toplevel_x, toplevel_y;
7312   guint32 time_;
7313
7314   toplevel_window = source_event->any.window;
7315   gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
7316   gdk_event_get_state (source_event, &state);
7317   time_ = gdk_event_get_time (source_event);
7318
7319   pointer_window = get_pointer_window (display, toplevel_window, toplevel_x, toplevel_y);
7320   if (display->pointer_info.window_under_pointer != pointer_window)
7321     {
7322       /* Either a toplevel crossing notify that ended up inside a child window,
7323          or a motion notify that got into another child window  */
7324       /* Different than last time, send crossing events */
7325
7326       _gdk_syntesize_crossing_events (display,
7327                                       display->pointer_info.window_under_pointer,
7328                                       pointer_window,
7329                                       GDK_CROSSING_NORMAL,
7330                                       toplevel_x, toplevel_y,
7331                                       state, time_,
7332                                       source_event);
7333
7334       _gdk_display_set_window_under_pointer (display, pointer_window);
7335     }
7336   else if (source_event->type == GDK_MOTION_NOTIFY)
7337     {
7338       GdkWindow *event_win;
7339
7340       event_win = get_event_window (display,
7341                                     pointer_window,
7342                                     source_event->type,
7343                                     state);
7344       
7345       if (event_win)
7346         {
7347           sent_motion = TRUE;
7348           event = _gdk_make_event (event_win, GDK_MOTION_NOTIFY, source_event, FALSE);
7349           event->motion.time = time_;
7350           convert_toplevel_coords_to_window (event_win,
7351                                              toplevel_x, toplevel_y,
7352                                              &event->motion.x, &event->motion.y);
7353           event->motion.x_root = source_event->motion.x_root;
7354           event->motion.y_root = source_event->motion.y_root;;
7355           event->motion.state = state;
7356           event->motion.is_hint = FALSE;
7357           event->motion.device = NULL;
7358           if (source_event && source_event->type == GDK_MOTION_NOTIFY)
7359             event->motion.device = source_event->motion.device;
7360         }
7361     }
7362
7363   /* TODO: set cursor from cursor_window, or grab cursor */
7364   cursor_window = pointer_window;
7365   if (display->pointer_grab.window &&
7366       (pointer_window == NULL ||
7367        !is_parent_of (display->pointer_grab.window, pointer_window)))
7368     cursor_window = display->pointer_grab.window;
7369   /* Actually, this should probably happen in synthesize crossing so it works with geometry changes */
7370
7371   
7372   /* unlink all move events from queue.
7373      We handle our own, including our emulated masks. */
7374   return TRUE;
7375 }
7376
7377 static gboolean
7378 proxy_button_event (GdkEvent *source_event)
7379 {
7380   GdkWindow *toplevel_window;
7381   GdkWindow *event_win;
7382   GdkWindow *pointer_window;
7383   GdkEvent *event;
7384   guint state;
7385   guint32 time_;
7386   GdkEventType type;
7387   gdouble toplevel_x, toplevel_y;
7388   GdkDisplay *display;
7389   GdkWindowObject *w;
7390
7391   type = source_event->any.type;
7392   toplevel_window = source_event->any.window;
7393   gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
7394   gdk_event_get_state (source_event, &state);
7395   time_ = gdk_event_get_time (source_event);
7396   display = gdk_drawable_get_display (source_event->any.window);
7397
7398   if ((type == GDK_BUTTON_PRESS || type == GDK_SCROLL) &&
7399       display->pointer_grab.window == source_event->any.window &&
7400       display->pointer_grab.implicit &&
7401       !display->pointer_grab.converted_implicit)
7402     {
7403       pointer_window =
7404         _gdk_window_find_descendant_at (toplevel_window,
7405                                         toplevel_x, toplevel_y,
7406                                         NULL, NULL);
7407
7408       /* Find the actual event window, its what gets the grab */
7409       w = (GdkWindowObject *)pointer_window;
7410       while (w != NULL && w->parent->window_type != GDK_WINDOW_ROOT)
7411         {
7412           if (w->event_mask & GDK_BUTTON_PRESS_MASK)
7413             break;
7414           w = w->parent;
7415         }
7416       pointer_window = w;
7417       
7418       
7419       if (pointer_window != NULL &&
7420           pointer_window != source_event->any.window)
7421         _gdk_display_set_has_pointer_grab (display,
7422                                            pointer_window,
7423                                            display->pointer_grab.native_window,
7424                                            display->pointer_grab.owner_events,
7425                                            gdk_window_get_events (pointer_window),
7426                                            display->pointer_grab.serial,
7427                                            display->pointer_grab.time,
7428                                            display->pointer_grab.implicit);
7429       display->pointer_grab.converted_implicit = TRUE;
7430     }
7431
7432   pointer_window = get_pointer_window (display, toplevel_window, toplevel_x, toplevel_y);
7433   
7434   event_win = get_event_window (display,
7435                                 pointer_window,
7436                                 type,
7437                                 state);
7438
7439   if (event_win == NULL)
7440     return TRUE;
7441   
7442   event = _gdk_make_event (event_win, type, source_event, FALSE);
7443   
7444   switch (type)
7445     {
7446     case GDK_BUTTON_PRESS:
7447     case GDK_BUTTON_RELEASE:
7448       event->button.button = source_event->button.button;
7449       convert_toplevel_coords_to_window (event_win,
7450                                          toplevel_x, toplevel_y,
7451                                          &event->button.x, &event->button.y);
7452       event->button.x_root = source_event->button.x_root;
7453       event->button.y_root = source_event->button.y_root;
7454       event->button.state = state;
7455       event->button.device = source_event->button.device;
7456       
7457       if (type == GDK_BUTTON_PRESS)
7458         _gdk_event_button_generate (display, event);
7459       return TRUE;
7460       
7461     case GDK_SCROLL:
7462       event->scroll.direction = source_event->scroll.direction;
7463       convert_toplevel_coords_to_window (event_win,
7464                                          toplevel_x, toplevel_y,
7465                                          &event->scroll.x, &event->scroll.y);
7466       event->scroll.x_root = source_event->scroll.x_root;
7467       event->scroll.y_root = source_event->scroll.y_root;
7468       event->scroll.state = state;
7469       event->scroll.device = source_event->scroll.device;
7470       return TRUE;
7471       
7472     default:
7473       return FALSE;
7474     }
7475
7476   return TRUE; /* Always unlink original, we want to obey the emulated event mask */
7477 }
7478
7479 void
7480 _gdk_windowing_got_event (GdkDisplay *display,
7481                           GList      *event_link,
7482                           GdkEvent   *event)
7483 {
7484   GdkWindow *event_window;
7485   GdkWindowObject *event_private;
7486   gdouble x, y;
7487   gboolean unlink_event;
7488
7489   event_window = event->any.window;
7490   if (!event_window)
7491     return;
7492   
7493   event_private = GDK_WINDOW_OBJECT (event_window);
7494
7495   if (!(is_button_type (event->type) ||
7496         is_motion_type (event->type)))
7497     return;
7498
7499   if (GDK_WINDOW_TYPE (event_private->parent) != GDK_WINDOW_ROOT)
7500     {
7501       GEnumValue *event_type_value, *window_type_value;
7502       
7503       event_type_value = g_enum_get_value ((GEnumClass *) g_type_class_ref (GDK_TYPE_EVENT_TYPE),
7504                                            event->type);
7505       window_type_value = g_enum_get_value ((GEnumClass *) g_type_class_ref (GDK_TYPE_WINDOW_TYPE),
7506                                             event_private->window_type);
7507       
7508      /* We should only get these events on toplevel windows */
7509       g_warning ("got unexpected event of type %s on non-toplevel window (gtype %s, type %d)",
7510                  event_type_value->value_name,
7511                  window_type_value->value_name,
7512                  GDK_WINDOW_TYPE (event_window));
7513       return;
7514     }
7515
7516   if ((event->type == GDK_ENTER_NOTIFY ||
7517        event->type == GDK_LEAVE_NOTIFY) &&
7518       (event->crossing.mode == GDK_CROSSING_GRAB ||
7519        event->crossing.mode == GDK_CROSSING_UNGRAB))
7520     {
7521       /* We synthesize all crossing events due to grabs are synthesized,
7522        * so we ignore the native ones. This is partly to get easier non-X
7523        * portability, and because of problems with race conditions due to
7524        * the cached state in the client and the real state in the xserver
7525        * when grabbing.
7526        */
7527
7528       /* We ended up in this window after some (perhaps other clients)
7529          grab, so update the toplevel_under_window state */
7530       if (event->type == GDK_ENTER_NOTIFY &&
7531           event->crossing.mode == GDK_CROSSING_UNGRAB)
7532         {
7533           if (display->pointer_info.toplevel_under_pointer)
7534             g_object_unref (display->pointer_info.toplevel_under_pointer);
7535           display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
7536         }
7537       
7538       unlink_event = TRUE;
7539       goto out;
7540     }
7541   
7542   /* Store last pointer window and position/state */
7543   if (event->type == GDK_ENTER_NOTIFY &&
7544       event->crossing.detail != GDK_NOTIFY_INFERIOR)
7545     {
7546       if (display->pointer_info.toplevel_under_pointer)
7547         g_object_unref (display->pointer_info.toplevel_under_pointer);
7548       display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
7549     }
7550   else if (event->type == GDK_LEAVE_NOTIFY &&
7551            event->crossing.detail != GDK_NOTIFY_INFERIOR &&
7552            display->pointer_info.toplevel_under_pointer == event_window)
7553     {
7554       if (display->pointer_info.toplevel_under_pointer)
7555         g_object_unref (display->pointer_info.toplevel_under_pointer);
7556       display->pointer_info.toplevel_under_pointer = NULL;
7557     }
7558
7559   gdk_event_get_coords (event, &x, &y);
7560   display->pointer_info.toplevel_x = x;
7561   display->pointer_info.toplevel_y = y;
7562   gdk_event_get_state (event, &display->pointer_info.state);
7563
7564   
7565   unlink_event = FALSE;
7566   if (is_motion_type (event->type))
7567     unlink_event = proxy_pointer_event (display,
7568                                         event);
7569   else if (is_button_type (event->type))
7570     unlink_event = proxy_button_event (event);
7571
7572  out:
7573   if (unlink_event)
7574     {
7575       _gdk_event_queue_remove_link (display, event_link);
7576       g_list_free_1 (event_link);
7577       gdk_event_free (event);
7578     }
7579 }
7580
7581 #define __GDK_WINDOW_C__
7582 #include "gdkaliasdef.c"