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