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