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