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