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