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