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