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