]> Pileus Git - ~andy/gtk/blob - gdk/gdkwindow.c
Don't ever invalidate the root window
[~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   /* The region area is moved and we queue translations for all expose events
2832      to the source area that were sent prior to the copy */
2833   gdk_region_offset (dest_region, -dx, -dy); /* Temporarily move to source area */
2834   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->queue_translation ((GdkWindow *)impl_window,
2835                                                                 dest_region, dx, dy);
2836   gdk_region_offset (dest_region, dx, dy); /* back to dest area */
2837
2838   gdk_region_get_clipbox (dest_region, &copy_rect);
2839
2840   gdk_gc_set_clip_region (tmp_gc, dest_region);
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 */
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       gdk_region_subtract (impl_window->update_area, update_area);
3012
3013       /* Convert back */
3014       gdk_region_offset (update_area, dx, dy);
3015       gdk_region_union (impl_window->update_area, update_area);
3016
3017       /* This area of the destination is now invalid,
3018          so no need to copy to it.  */
3019       gdk_region_subtract (region, update_area);
3020
3021       gdk_region_destroy (update_area);
3022     }
3023
3024   if (1) /* Enable flicker free handling of moves. */
3025     append_move_region (impl_window, region, dx, dy);
3026   else
3027     do_move_region_bits_on_impl (impl_window,
3028                                  region, dx, dy);
3029
3030   gdk_region_destroy (region);
3031 }
3032
3033 /* Flushes all outstanding changes to the window, call this
3034  * before drawing directly to the window (i.e. outside a begin/end_paint pair).
3035  */
3036 static void
3037 gdk_window_flush_outstanding_moves (GdkWindow *window)
3038 {
3039   GdkWindowObject *private;
3040   GdkWindowObject *impl_window;
3041   GList *l;
3042   GdkWindowRegionMove *move;
3043
3044   private = (GdkWindowObject *) window;
3045
3046   impl_window = gdk_window_get_impl_window (private);
3047
3048   for (l = impl_window->outstanding_moves; l != NULL; l = l->next)
3049     {
3050       move = l->data;
3051
3052       do_move_region_bits_on_impl (impl_window,
3053                                    move->dest_region, move->dx, move->dy);
3054
3055       gdk_window_region_move_free (move);
3056     }
3057
3058   g_list_free (impl_window->outstanding_moves);
3059   impl_window->outstanding_moves = NULL;
3060 }
3061
3062 static void
3063 gdk_window_flush (GdkWindow *window)
3064 {
3065   gdk_window_flush_outstanding_moves (window);
3066   gdk_window_flush_implicit_paint (window);
3067 }
3068
3069 static void
3070 gdk_window_flush_recursive_helper (GdkWindowObject *window,
3071                                    GdkWindow *impl)
3072 {
3073   GdkWindowObject *child;
3074   GList *l;
3075
3076   for (l = window->children; l != NULL; l = l->next)
3077     {
3078       child = l->data;
3079
3080       if (child->impl == impl)
3081         /* Same impl, ignore */
3082         gdk_window_flush_recursive_helper (child, impl);
3083       else
3084         gdk_window_flush_recursive (child);
3085     }
3086 }
3087
3088 static void
3089 gdk_window_flush_recursive (GdkWindowObject *window)
3090 {
3091   gdk_window_flush ((GdkWindow *)window);
3092   gdk_window_flush_recursive_helper (window, window->impl);
3093 }
3094
3095 static void
3096 gdk_window_get_offsets (GdkWindow *window,
3097                         gint      *x_offset,
3098                         gint      *y_offset)
3099 {
3100   GdkWindowObject *private = (GdkWindowObject *)window;
3101
3102   if (private->paint_stack)
3103     {
3104       GdkWindowPaint *paint = private->paint_stack->data;
3105       *x_offset = paint->x_offset;
3106       *y_offset = paint->y_offset;
3107     }
3108   else
3109     {
3110       *x_offset = -private->abs_x;
3111       *y_offset = -private->abs_y;
3112     }
3113 }
3114
3115 /**
3116  * gdk_window_get_internal_paint_info:
3117  * @window: a #GdkWindow
3118  * @real_drawable: location to store the drawable to which drawing should be
3119  *            done.
3120  * @x_offset: location to store the X offset between coordinates in @window,
3121  *            and the underlying window system primitive coordinates for
3122  *            *@real_drawable.
3123  * @y_offset: location to store the Y offset between coordinates in @window,
3124  *            and the underlying window system primitive coordinates for
3125  *            *@real_drawable.
3126  *
3127  * If you bypass the GDK layer and use windowing system primitives to
3128  * draw directly onto a #GdkWindow, then you need to deal with two
3129  * details: there may be an offset between GDK coordinates and windowing
3130  * system coordinates, and GDK may have redirected drawing to a offscreen
3131  * pixmap as the result of a gdk_window_begin_paint_region() calls.
3132  * This function allows retrieving the information you need to compensate
3133  * for these effects.
3134  *
3135  * This function exposes details of the GDK implementation, and is thus
3136  * likely to change in future releases of GDK.
3137  **/
3138 void
3139 gdk_window_get_internal_paint_info (GdkWindow    *window,
3140                                     GdkDrawable **real_drawable,
3141                                     gint         *x_offset,
3142                                     gint         *y_offset)
3143 {
3144   gint x_off, y_off;
3145
3146   GdkWindowObject *private;
3147
3148   g_return_if_fail (GDK_IS_WINDOW (window));
3149
3150   private = (GdkWindowObject *)window;
3151
3152   if (real_drawable)
3153     {
3154       if (private->paint_stack)
3155         {
3156           GdkWindowPaint *paint = private->paint_stack->data;
3157           *real_drawable = paint->pixmap;
3158         }
3159       else
3160         {
3161           /* This means you're probably gonna be doing some weird shit
3162              directly to the window, so we flush all outstanding stuff */
3163           gdk_window_flush (window);
3164           *real_drawable = window;
3165         }
3166     }
3167
3168   gdk_window_get_offsets (window, &x_off, &y_off);
3169
3170   if (x_offset)
3171     *x_offset = x_off;
3172   if (y_offset)
3173     *y_offset = y_off;
3174 }
3175
3176 static GdkDrawable *
3177 start_draw_helper (GdkDrawable *drawable,
3178                    GdkGC *gc,
3179                    gint *x_offset_out,
3180                    gint *y_offset_out)
3181 {
3182   GdkWindowObject *private = (GdkWindowObject *)drawable;
3183   gint x_offset, y_offset;
3184   GdkDrawable *impl;
3185   gint old_clip_x = gc->clip_x_origin;
3186   gint old_clip_y = gc->clip_y_origin;
3187   GdkRegion *clip;
3188   guint32 clip_region_tag;
3189   GdkWindowPaint *paint;
3190
3191   paint = NULL;
3192   if (private->paint_stack)
3193     paint = private->paint_stack->data;
3194
3195   if (paint)
3196     {
3197       x_offset = paint->x_offset;
3198       y_offset = paint->y_offset;
3199     }
3200   else
3201     {
3202       x_offset = -private->abs_x;
3203       y_offset = -private->abs_y;
3204     }
3205
3206   if (x_offset != 0 || y_offset != 0)
3207     {
3208       gdk_gc_set_clip_origin (gc,
3209                               old_clip_x - x_offset,
3210                               old_clip_y - y_offset);
3211       gdk_gc_set_ts_origin (gc,
3212                             gc->ts_x_origin - x_offset,
3213                             gc->ts_y_origin - y_offset);
3214     }
3215
3216   *x_offset_out = x_offset;
3217   *y_offset_out = y_offset;
3218
3219   /* Add client side window clip region to gc */
3220   clip = NULL;
3221   if (paint)
3222     {
3223       /* Only need clipping if using implicit paint, otherwise
3224          the pixmap is clipped when copying to the window in end_paint */
3225       if (paint->uses_implicit)
3226         {
3227           /* This includes the window clip */
3228           clip = paint->region;
3229         }
3230       clip_region_tag = paint->region_tag;
3231
3232       /* After having set up the drawable clip rect on a GC we need to make sure
3233        * that we draw to th the impl, otherwise the pixmap code will reset the
3234        * drawable clip. */
3235       impl = ((GdkPixmapObject *)(paint->pixmap))->impl;
3236     }
3237   else
3238     {
3239       /* Drawing directly to the window, flush anything outstanding to
3240          guarantee ordering. */
3241       gdk_window_flush ((GdkWindow *)drawable);
3242
3243       /* Don't clip when drawing to root */
3244       if (private->window_type != GDK_WINDOW_ROOT)
3245         {
3246           if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
3247             clip = private->clip_region_with_children;
3248           else
3249             clip = private->clip_region;
3250         }
3251       clip_region_tag = private->clip_tag;
3252       impl = private->impl;
3253     }
3254
3255   if (clip)
3256     _gdk_gc_add_drawable_clip (gc,
3257                                clip_region_tag, clip,
3258                                /* If there was a clip origin set appart from the
3259                                 * window offset, need to take that into
3260                                 * consideration */
3261                                -old_clip_x, -old_clip_y);
3262
3263   return impl;
3264 }
3265
3266 #define BEGIN_DRAW                                      \
3267   {                                                     \
3268     GdkDrawable *impl;                                  \
3269     gint x_offset, y_offset;                            \
3270     gint old_clip_x = gc->clip_x_origin;                \
3271     gint old_clip_y = gc->clip_y_origin;                \
3272     gint old_ts_x = gc->ts_x_origin;                    \
3273     gint old_ts_y = gc->ts_y_origin;                    \
3274     impl = start_draw_helper (drawable, gc,             \
3275                               &x_offset, &y_offset);
3276
3277 #define END_DRAW                                            \
3278     if (x_offset != 0 || y_offset != 0)                     \
3279      {                                                      \
3280        gdk_gc_set_clip_origin (gc, old_clip_x, old_clip_y); \
3281        gdk_gc_set_ts_origin (gc, old_ts_x, old_ts_y);       \
3282      }                                                      \
3283   }
3284
3285 static GdkGC *
3286 gdk_window_create_gc (GdkDrawable     *drawable,
3287                       GdkGCValues     *values,
3288                       GdkGCValuesMask  mask)
3289 {
3290   g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
3291
3292   if (GDK_WINDOW_DESTROYED (drawable))
3293     return NULL;
3294
3295   return gdk_gc_new_with_values (((GdkWindowObject *) drawable)->impl,
3296                                  values, mask);
3297 }
3298
3299 static void
3300 gdk_window_draw_rectangle (GdkDrawable *drawable,
3301                            GdkGC       *gc,
3302                            gboolean     filled,
3303                            gint         x,
3304                            gint         y,
3305                            gint         width,
3306                            gint         height)
3307 {
3308   if (GDK_WINDOW_DESTROYED (drawable))
3309     return;
3310
3311   BEGIN_DRAW;
3312   gdk_draw_rectangle (impl, gc, filled,
3313                       x - x_offset, y - y_offset, width, height);
3314   END_DRAW;
3315 }
3316
3317 static void
3318 gdk_window_draw_arc (GdkDrawable *drawable,
3319                      GdkGC       *gc,
3320                      gboolean     filled,
3321                      gint         x,
3322                      gint         y,
3323                      gint         width,
3324                      gint         height,
3325                      gint         angle1,
3326                      gint         angle2)
3327 {
3328   if (GDK_WINDOW_DESTROYED (drawable))
3329     return;
3330
3331   BEGIN_DRAW;
3332   gdk_draw_arc (impl, gc, filled,
3333                 x - x_offset, y - y_offset,
3334                 width, height, angle1, angle2);
3335   END_DRAW;
3336 }
3337
3338 static void
3339 gdk_window_draw_polygon (GdkDrawable *drawable,
3340                          GdkGC       *gc,
3341                          gboolean     filled,
3342                          GdkPoint    *points,
3343                          gint         npoints)
3344 {
3345   GdkPoint *new_points;
3346
3347   if (GDK_WINDOW_DESTROYED (drawable))
3348     return;
3349
3350   BEGIN_DRAW;
3351
3352   if (x_offset != 0 || y_offset != 0)
3353     {
3354       int i;
3355
3356       new_points = g_new (GdkPoint, npoints);
3357       for (i=0; i<npoints; i++)
3358         {
3359           new_points[i].x = points[i].x - x_offset;
3360           new_points[i].y = points[i].y - y_offset;
3361         }
3362     }
3363   else
3364     new_points = points;
3365
3366   gdk_draw_polygon (impl, gc, filled, new_points, npoints);
3367
3368   if (new_points != points)
3369     g_free (new_points);
3370
3371   END_DRAW;
3372 }
3373
3374 static void
3375 gdk_window_draw_text (GdkDrawable *drawable,
3376                       GdkFont     *font,
3377                       GdkGC       *gc,
3378                       gint         x,
3379                       gint         y,
3380                       const gchar *text,
3381                       gint         text_length)
3382 {
3383   if (GDK_WINDOW_DESTROYED (drawable))
3384     return;
3385
3386   BEGIN_DRAW;
3387   gdk_draw_text (impl, font, gc,
3388                  x - x_offset, y - y_offset, text, text_length);
3389   END_DRAW;
3390 }
3391
3392 static void
3393 gdk_window_draw_text_wc (GdkDrawable    *drawable,
3394                          GdkFont        *font,
3395                          GdkGC          *gc,
3396                          gint            x,
3397                          gint            y,
3398                          const GdkWChar *text,
3399                          gint            text_length)
3400 {
3401   if (GDK_WINDOW_DESTROYED (drawable))
3402     return;
3403
3404   BEGIN_DRAW;
3405   gdk_draw_text_wc (impl, font, gc,
3406                     x - x_offset, y - y_offset, text, text_length);
3407   END_DRAW;
3408 }
3409
3410 static GdkDrawable *
3411 gdk_window_get_source_drawable (GdkDrawable *drawable)
3412 {
3413   GdkWindow *window = GDK_WINDOW (drawable);
3414   GdkWindowObject *private;
3415
3416   private = (GdkWindowObject *) window;
3417   if (GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable)
3418     return GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable (private->impl);
3419
3420   return drawable;
3421 }
3422
3423 static GdkDrawable *
3424 gdk_window_get_composite_drawable (GdkDrawable *drawable,
3425                                    gint         x,
3426                                    gint         y,
3427                                    gint         width,
3428                                    gint         height,
3429                                    gint        *composite_x_offset,
3430                                    gint        *composite_y_offset)
3431 {
3432   GdkWindowObject *private = (GdkWindowObject *)drawable;
3433   GSList *list;
3434   GdkPixmap *tmp_pixmap;
3435   GdkRectangle rect;
3436   GdkGC *tmp_gc;
3437   gboolean overlap_buffer;
3438   GdkDrawable *source;
3439   GdkWindowObject *impl_window;
3440   GdkWindowPaint *implicit_paint;
3441
3442   *composite_x_offset = -private->abs_x;
3443   *composite_y_offset = -private->abs_y;
3444
3445   if ((GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable)))
3446     return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
3447
3448   /* See if any buffered part is overlapping the part we want
3449    * to get
3450    */
3451   rect.x = x;
3452   rect.y = y;
3453   rect.width = width;
3454   rect.height = height;
3455
3456   overlap_buffer = FALSE;
3457
3458   for (list = private->paint_stack; list != NULL; list = list->next)
3459     {
3460       GdkWindowPaint *paint = list->data;
3461       GdkOverlapType overlap;
3462
3463       overlap = gdk_region_rect_in (paint->region, &rect);
3464
3465       if (overlap == GDK_OVERLAP_RECTANGLE_IN)
3466         {
3467           *composite_x_offset = paint->x_offset;
3468           *composite_y_offset = paint->y_offset;
3469
3470           return g_object_ref (paint->pixmap);
3471         }
3472       else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
3473         {
3474           overlap_buffer = TRUE;
3475           break;
3476         }
3477     }
3478
3479   impl_window = gdk_window_get_impl_window (private);
3480   implicit_paint = impl_window->implicit_paint;
3481   if (implicit_paint)
3482     {
3483       GdkOverlapType overlap;
3484
3485       rect.x += private->abs_x;
3486       rect.y += private->abs_y;
3487
3488       overlap = gdk_region_rect_in (implicit_paint->region, &rect);
3489       if (overlap == GDK_OVERLAP_RECTANGLE_IN)
3490         {
3491           *composite_x_offset = -private->abs_x + implicit_paint->x_offset;
3492           *composite_y_offset = -private->abs_y + implicit_paint->y_offset;
3493
3494           return g_object_ref (implicit_paint->pixmap);
3495         }
3496       else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
3497         overlap_buffer = TRUE;
3498     }
3499
3500   if (!overlap_buffer)
3501     return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
3502
3503   tmp_pixmap = gdk_pixmap_new (drawable, width, height, -1);
3504   tmp_gc = _gdk_drawable_get_scratch_gc (tmp_pixmap, FALSE);
3505
3506   source = _gdk_drawable_get_source_drawable (drawable);
3507
3508   /* Copy the current window contents */
3509   gdk_draw_drawable (tmp_pixmap,
3510                      tmp_gc,
3511                      GDK_WINDOW_OBJECT (source)->impl,
3512                      x - *composite_x_offset,
3513                      y - *composite_y_offset,
3514                      0, 0,
3515                      width, height);
3516
3517   /* paint the backing stores */
3518   if (implicit_paint)
3519     {
3520       GdkWindowPaint *paint = list->data;
3521
3522       gdk_gc_set_clip_region (tmp_gc, paint->region);
3523       gdk_gc_set_clip_origin (tmp_gc, -x  - paint->x_offset, -y  - paint->y_offset);
3524
3525       gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
3526                          x - paint->x_offset,
3527                          y - paint->y_offset,
3528                          0, 0, width, height);
3529     }
3530
3531   for (list = private->paint_stack; list != NULL; list = list->next)
3532     {
3533       GdkWindowPaint *paint = list->data;
3534
3535       if (paint->uses_implicit)
3536         continue; /* We already copied this above */
3537
3538       gdk_gc_set_clip_region (tmp_gc, paint->region);
3539       gdk_gc_set_clip_origin (tmp_gc, -x, -y);
3540
3541       gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
3542                          x - paint->x_offset,
3543                          y - paint->y_offset,
3544                          0, 0, width, height);
3545     }
3546
3547   /* Reset clip region of the cached GdkGC */
3548   gdk_gc_set_clip_region (tmp_gc, NULL);
3549
3550   /* Set these to location of tmp_pixmap within the window */
3551   *composite_x_offset = x;
3552   *composite_y_offset = y;
3553
3554   return tmp_pixmap;
3555 }
3556
3557 static GdkRegion*
3558 gdk_window_get_clip_region (GdkDrawable *drawable)
3559 {
3560   GdkWindowObject *private = (GdkWindowObject *)drawable;
3561   GdkRegion *result;
3562
3563   result = gdk_region_copy (private->clip_region);
3564
3565   if (private->paint_stack)
3566     {
3567       GdkRegion *paint_region = gdk_region_new ();
3568       GSList *tmp_list = private->paint_stack;
3569
3570       while (tmp_list)
3571         {
3572           GdkWindowPaint *paint = tmp_list->data;
3573
3574           gdk_region_union (paint_region, paint->region);
3575
3576           tmp_list = tmp_list->next;
3577         }
3578
3579       gdk_region_intersect (result, paint_region);
3580       gdk_region_destroy (paint_region);
3581     }
3582
3583   return result;
3584 }
3585
3586 static GdkRegion*
3587 gdk_window_get_visible_region (GdkDrawable *drawable)
3588 {
3589   GdkWindowObject *private = (GdkWindowObject*) drawable;
3590
3591   return gdk_region_copy (private->clip_region);
3592 }
3593
3594 static void
3595 gdk_window_draw_drawable (GdkDrawable *drawable,
3596                           GdkGC       *gc,
3597                           GdkPixmap   *src,
3598                           gint         xsrc,
3599                           gint         ysrc,
3600                           gint         xdest,
3601                           gint         ydest,
3602                           gint         width,
3603                           gint         height,
3604                           GdkDrawable *original_src)
3605 {
3606   GdkWindowObject *private = (GdkWindowObject *)drawable;
3607
3608   if (GDK_WINDOW_DESTROYED (drawable))
3609     return;
3610
3611   BEGIN_DRAW;
3612
3613   gdk_draw_drawable (impl, gc, src, xsrc, ysrc,
3614                      xdest - x_offset, ydest - y_offset, width, height);
3615
3616   if (!private->paint_stack)
3617     {
3618       /* We might have drawn from an obscured part of a client
3619          side window, if so we need to send graphics exposures */
3620       if (_gdk_gc_get_exposures (gc) &&
3621           GDK_IS_WINDOW (original_src))
3622         {
3623           GdkRegion *exposure_region;
3624           GdkRegion *clip;
3625           GdkRectangle r;
3626
3627           r.x = xdest;
3628           r.y = ydest;
3629           r.width = width;
3630           r.height = height;
3631           exposure_region = gdk_region_rectangle (&r);
3632
3633           if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
3634             clip = private->clip_region_with_children;
3635           else
3636             clip = private->clip_region;
3637           gdk_region_intersect (exposure_region, clip);
3638
3639           clip = _gdk_gc_get_clip_region (gc);
3640           if (clip)
3641             {
3642               gdk_region_offset (exposure_region,
3643                                  old_clip_x,
3644                                  old_clip_y);
3645               gdk_region_intersect (exposure_region, clip);
3646               gdk_region_offset (exposure_region,
3647                                  -old_clip_x,
3648                                  -old_clip_y);
3649             }
3650
3651           /* Note: We don't clip by the clip mask if set, so this
3652              may invalidate to much */
3653
3654           /* Remove the area that is correctly copied from the src.
3655            * Note that xsrc/ysrc has been corrected for abs_x/y offsets already,
3656            * which need to be undone */
3657           clip = gdk_drawable_get_visible_region (original_src);
3658           gdk_region_offset (clip,
3659                              xdest - (xsrc - GDK_WINDOW_OBJECT (original_src)->abs_x),
3660                              ydest - (ysrc - GDK_WINDOW_OBJECT (original_src)->abs_y));
3661           gdk_region_subtract (exposure_region, clip);
3662           gdk_region_destroy (clip);
3663
3664           gdk_window_invalidate_region (GDK_WINDOW (private),
3665                                         exposure_region,
3666                                         _gdk_gc_get_subwindow (gc) == GDK_INCLUDE_INFERIORS);
3667
3668           gdk_region_destroy (exposure_region);
3669         }
3670     }
3671
3672   END_DRAW;
3673 }
3674
3675 static void
3676 gdk_window_draw_points (GdkDrawable *drawable,
3677                         GdkGC       *gc,
3678                         GdkPoint    *points,
3679                         gint         npoints)
3680 {
3681   GdkPoint *new_points;
3682
3683   if (GDK_WINDOW_DESTROYED (drawable))
3684     return;
3685
3686   BEGIN_DRAW;
3687
3688   if (x_offset != 0 || y_offset != 0)
3689     {
3690       gint i;
3691
3692       new_points = g_new (GdkPoint, npoints);
3693       for (i=0; i<npoints; i++)
3694         {
3695           new_points[i].x = points[i].x - x_offset;
3696           new_points[i].y = points[i].y - y_offset;
3697         }
3698     }
3699   else
3700     new_points = points;
3701
3702   gdk_draw_points (impl, gc, new_points, npoints);
3703
3704   if (new_points != points)
3705     g_free (new_points);
3706
3707   END_DRAW;
3708 }
3709
3710 static void
3711 gdk_window_draw_segments (GdkDrawable *drawable,
3712                           GdkGC       *gc,
3713                           GdkSegment  *segs,
3714                           gint         nsegs)
3715 {
3716   GdkSegment *new_segs;
3717
3718   if (GDK_WINDOW_DESTROYED (drawable))
3719     return;
3720
3721   BEGIN_DRAW;
3722
3723   if (x_offset != 0 || y_offset != 0)
3724     {
3725       gint i;
3726
3727       new_segs = g_new (GdkSegment, nsegs);
3728       for (i=0; i<nsegs; i++)
3729         {
3730           new_segs[i].x1 = segs[i].x1 - x_offset;
3731           new_segs[i].y1 = segs[i].y1 - y_offset;
3732           new_segs[i].x2 = segs[i].x2 - x_offset;
3733           new_segs[i].y2 = segs[i].y2 - y_offset;
3734         }
3735     }
3736   else
3737     new_segs = segs;
3738
3739   gdk_draw_segments (impl, gc, new_segs, nsegs);
3740
3741   if (new_segs != segs)
3742     g_free (new_segs);
3743
3744   END_DRAW;
3745 }
3746
3747 static void
3748 gdk_window_draw_lines (GdkDrawable *drawable,
3749                        GdkGC       *gc,
3750                        GdkPoint    *points,
3751                        gint         npoints)
3752 {
3753   GdkPoint *new_points;
3754
3755   if (GDK_WINDOW_DESTROYED (drawable))
3756     return;
3757
3758   BEGIN_DRAW;
3759
3760   if (x_offset != 0 || y_offset != 0)
3761     {
3762       gint i;
3763
3764       new_points = g_new (GdkPoint, npoints);
3765       for (i=0; i<npoints; i++)
3766         {
3767           new_points[i].x = points[i].x - x_offset;
3768           new_points[i].y = points[i].y - y_offset;
3769         }
3770     }
3771   else
3772     new_points = points;
3773
3774   gdk_draw_lines (impl, gc, new_points, npoints);
3775
3776   if (new_points != points)
3777     g_free (new_points);
3778
3779   END_DRAW;
3780 }
3781
3782 static void
3783 gdk_window_draw_glyphs (GdkDrawable      *drawable,
3784                         GdkGC            *gc,
3785                         PangoFont        *font,
3786                         gint              x,
3787                         gint              y,
3788                         PangoGlyphString *glyphs)
3789 {
3790   if (GDK_WINDOW_DESTROYED (drawable))
3791     return;
3792
3793   BEGIN_DRAW;
3794   gdk_draw_glyphs (impl, gc, font,
3795                    x - x_offset, y - y_offset, glyphs);
3796   END_DRAW;
3797 }
3798
3799 static void
3800 gdk_window_draw_glyphs_transformed (GdkDrawable      *drawable,
3801                                     GdkGC            *gc,
3802                                     PangoMatrix      *matrix,
3803                                     PangoFont        *font,
3804                                     gint              x,
3805                                     gint              y,
3806                                     PangoGlyphString *glyphs)
3807 {
3808   PangoMatrix tmp_matrix;
3809
3810   if (GDK_WINDOW_DESTROYED (drawable))
3811     return;
3812
3813   BEGIN_DRAW;
3814
3815   if (x_offset != 0 || y_offset != 0)
3816     {
3817       if (matrix)
3818         {
3819           tmp_matrix = *matrix;
3820           tmp_matrix.x0 -= x_offset;
3821           tmp_matrix.y0 -= y_offset;
3822           matrix = &tmp_matrix;
3823         }
3824       else if (GDK_PANGO_UNITS_OVERFLOWS (x_offset, y_offset))
3825         {
3826           PangoMatrix identity = PANGO_MATRIX_INIT;
3827
3828           tmp_matrix = identity;
3829           tmp_matrix.x0 -= x_offset;
3830           tmp_matrix.y0 -= y_offset;
3831           matrix = &tmp_matrix;
3832         }
3833       else
3834         {
3835           x -= x_offset * PANGO_SCALE;
3836           y -= y_offset * PANGO_SCALE;
3837         }
3838     }
3839
3840   gdk_draw_glyphs_transformed (impl, gc, matrix, font, x, y, glyphs);
3841
3842   END_DRAW;
3843 }
3844
3845 typedef struct {
3846   cairo_t *cr; /* if non-null, it means use this cairo context */
3847   GdkGC *gc;   /* if non-null, it means use this GC instead */
3848 } BackingRectMethod;
3849
3850 static void
3851 setup_backing_rect_method (BackingRectMethod *method, GdkWindow *window, GdkWindowPaint *paint, int x_offset_cairo, int y_offset_cairo)
3852 {
3853   GdkWindowObject *private = (GdkWindowObject *)window;
3854
3855   if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
3856     {
3857       GdkWindowPaint tmp_paint;
3858
3859       tmp_paint = *paint;
3860       tmp_paint.x_offset += private->x;
3861       tmp_paint.y_offset += private->y;
3862
3863       x_offset_cairo += private->x;
3864       y_offset_cairo += private->y;
3865
3866       setup_backing_rect_method (method, GDK_WINDOW (private->parent), &tmp_paint, x_offset_cairo, y_offset_cairo);
3867     }
3868   else if (private->bg_pixmap &&
3869            private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
3870            private->bg_pixmap != GDK_NO_BG)
3871     {
3872 /* This is a workaround for https://bugs.freedesktop.org/show_bug.cgi?id=4320.
3873  * In it, using a pixmap as a repeating pattern in Cairo, and painting it to a
3874  * pixmap destination surface, can be very slow (on the order of seconds for a
3875  * whole-screen copy).  The workaround is to use pretty much the same code that
3876  * we used in GTK+ 2.6 (pre-Cairo), which clears the double-buffer pixmap with
3877  * a tiled GC XFillRectangle().
3878  */
3879
3880 /* Actually computing this flag is left as an exercise for the reader */
3881 #if defined (G_OS_UNIX)
3882 #  define GDK_CAIRO_REPEAT_IS_FAST 0
3883 #else
3884 #  define GDK_CAIRO_REPEAT_IS_FAST 1
3885 #endif
3886
3887 #if GDK_CAIRO_REPEAT_IS_FAST
3888       cairo_surface_t *surface = _gdk_drawable_ref_cairo_surface (private->bg_pixmap);
3889       cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
3890       cairo_surface_destroy (surface);
3891
3892       if (x_offset_cairo != 0 || y_offset_cairo != 0)
3893         {
3894           cairo_matrix_t matrix;
3895           cairo_matrix_init_translate (&matrix, x_offset_cairo, y_offset_cairo);
3896           cairo_pattern_set_matrix (pattern, &matrix);
3897         }
3898
3899       cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
3900
3901       method->cr = cairo_create (paint->surface);
3902       method->gc = NULL;
3903
3904       cairo_set_source (method->cr, pattern);
3905       cairo_pattern_destroy (pattern);
3906 #else
3907       guint gc_mask;
3908       GdkGCValues gc_values;
3909
3910       gc_values.fill = GDK_TILED;
3911       gc_values.tile = private->bg_pixmap;
3912       gc_values.ts_x_origin = -x_offset_cairo;
3913       gc_values.ts_y_origin = -y_offset_cairo;
3914
3915       gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN;
3916
3917       method->gc = gdk_gc_new_with_values (paint->pixmap, &gc_values, gc_mask);
3918 #endif
3919     }
3920   else
3921     {
3922       method->cr = cairo_create (paint->surface);
3923
3924       gdk_cairo_set_source_color (method->cr, &private->bg_color);
3925     }
3926 }
3927
3928 static void
3929 gdk_window_clear_backing_region (GdkWindow *window,
3930                                  GdkRegion *region)
3931 {
3932   GdkWindowObject *private = (GdkWindowObject *)window;
3933   GdkWindowPaint *paint = private->paint_stack->data;
3934   BackingRectMethod method;
3935   GdkRegion *clip;
3936   GdkRectangle clipbox;
3937 #if 0
3938   GTimer *timer;
3939   double elapsed;
3940 #endif
3941
3942   if (GDK_WINDOW_DESTROYED (window))
3943     return;
3944
3945 #if 0
3946   timer = g_timer_new ();
3947 #endif
3948
3949   method.cr = NULL;
3950   method.gc = NULL;
3951   setup_backing_rect_method (&method, window, paint, 0, 0);
3952
3953   clip = gdk_region_copy (paint->region);
3954   gdk_region_intersect (clip, region);
3955   gdk_region_get_clipbox (clip, &clipbox);
3956
3957
3958   if (method.cr)
3959     {
3960       g_assert (method.gc == NULL);
3961
3962       gdk_cairo_region (method.cr, clip);
3963       cairo_fill (method.cr);
3964
3965       cairo_destroy (method.cr);
3966 #if 0
3967       elapsed = g_timer_elapsed (timer, NULL);
3968       g_print ("Draw the background with Cairo: %fs\n", elapsed);
3969 #endif
3970     }
3971   else
3972     {
3973       g_assert (method.gc != NULL);
3974
3975       gdk_gc_set_clip_region (method.gc, clip);
3976       gdk_draw_rectangle (window, method.gc, TRUE,
3977                           clipbox.x, clipbox.y,
3978                           clipbox.width, clipbox.height);
3979       g_object_unref (method.gc);
3980
3981 #if 0
3982       elapsed = g_timer_elapsed (timer, NULL);
3983       g_print ("Draw the background with GDK: %fs\n", elapsed);
3984 #endif
3985     }
3986
3987   gdk_region_destroy (clip);
3988
3989 #if 0
3990   g_timer_destroy (timer);
3991 #endif
3992 }
3993
3994 static void
3995 gdk_window_clear_backing_region_redirect (GdkWindow *window,
3996                                           GdkRegion *region)
3997 {
3998   GdkWindowObject *private = (GdkWindowObject *)window;
3999   GdkWindowRedirect *redirect = private->redirect;
4000   GdkRegion *clip_region;
4001   GdkRectangle clipbox;
4002   gint x_offset, y_offset;
4003   BackingRectMethod method;
4004   GdkWindowPaint paint;
4005
4006   if (GDK_WINDOW_DESTROYED (window))
4007     return;
4008
4009   clip_region = _gdk_window_calculate_full_clip_region (window,
4010                                                         GDK_WINDOW (redirect->redirected),
4011                                                         TRUE,
4012                                                         &x_offset, &y_offset);
4013   gdk_region_intersect (clip_region, region);
4014
4015   /* offset is from redirected window origin to window origin, convert to
4016      the offset from the redirected pixmap origin to the window origin */
4017   x_offset += redirect->dest_x - redirect->src_x;
4018   y_offset += redirect->dest_y - redirect->src_y;
4019
4020   /* Convert region to pixmap coords */
4021   gdk_region_offset (clip_region, x_offset, y_offset);
4022
4023   paint.x_offset = 0;
4024   paint.y_offset = 0;
4025   paint.pixmap = redirect->pixmap;
4026   paint.surface = _gdk_drawable_ref_cairo_surface (redirect->pixmap);
4027
4028   method.cr = NULL;
4029   method.gc = NULL;
4030   setup_backing_rect_method (&method, window, &paint, -x_offset, -y_offset);
4031
4032   if (method.cr)
4033     {
4034       g_assert (method.gc == NULL);
4035
4036       gdk_cairo_region (method.cr, clip_region);
4037       cairo_fill (method.cr);
4038
4039       cairo_destroy (method.cr);
4040     }
4041   else
4042     {
4043       g_assert (method.gc != NULL);
4044
4045       gdk_region_get_clipbox (clip_region, &clipbox);
4046       gdk_gc_set_clip_region (method.gc, clip_region);
4047       gdk_draw_rectangle (redirect->pixmap, method.gc, TRUE,
4048                           clipbox.x, clipbox.y,
4049                           clipbox.width, clipbox.height);
4050       g_object_unref (method.gc);
4051
4052     }
4053
4054   gdk_region_destroy (clip_region);
4055   cairo_surface_destroy (paint.surface);
4056 }
4057
4058 static void
4059 gdk_window_clear_backing_region_direct (GdkWindow *window,
4060                                         GdkRegion *region)
4061 {
4062   GdkWindowObject *private = (GdkWindowObject *)window;
4063   BackingRectMethod method;
4064   GdkWindowPaint paint;
4065   GdkRegion *clip;
4066   GdkRectangle clipbox;
4067
4068   if (GDK_WINDOW_DESTROYED (window))
4069     return;
4070
4071   paint.x_offset = 0;
4072   paint.y_offset = 0;
4073   paint.pixmap = window;
4074   paint.surface = _gdk_drawable_ref_cairo_surface (window);
4075
4076   method.cr = NULL;
4077   method.gc = NULL;
4078   setup_backing_rect_method (&method, window, &paint, 0, 0);
4079
4080   clip = gdk_region_copy (private->clip_region_with_children);
4081   gdk_region_intersect (clip, region);
4082   gdk_region_get_clipbox (clip, &clipbox);
4083
4084   if (method.cr)
4085     {
4086       g_assert (method.gc == NULL);
4087
4088       gdk_cairo_region (method.cr, clip);
4089       cairo_fill (method.cr);
4090
4091       cairo_destroy (method.cr);
4092     }
4093   else
4094     {
4095       g_assert (method.gc != NULL);
4096
4097       gdk_gc_set_clip_region (method.gc, clip);
4098       gdk_draw_rectangle (window, method.gc, TRUE,
4099                           clipbox.x, clipbox.y,
4100                           clipbox.width, clipbox.height);
4101       g_object_unref (method.gc);
4102
4103     }
4104
4105   gdk_region_destroy (clip);
4106   cairo_surface_destroy (paint.surface);
4107 }
4108
4109
4110 /**
4111  * gdk_window_clear:
4112  * @window: a #GdkWindow
4113  *
4114  * Clears an entire @window to the background color or background pixmap.
4115  **/
4116 void
4117 gdk_window_clear (GdkWindow *window)
4118 {
4119   gint width, height;
4120
4121   g_return_if_fail (GDK_IS_WINDOW (window));
4122
4123   gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height);
4124
4125   gdk_window_clear_area (window, 0, 0,
4126                          width, height);
4127 }
4128
4129 static void
4130 gdk_window_clear_region_internal (GdkWindow *window,
4131                                   GdkRegion *region,
4132                                   gboolean   send_expose)
4133 {
4134   GdkWindowObject *private = (GdkWindowObject *)window;
4135
4136   if (private->paint_stack)
4137     gdk_window_clear_backing_region (window, region);
4138   else
4139     {
4140       if (private->redirect)
4141         gdk_window_clear_backing_region_redirect (window, region);
4142
4143       if (GDK_WINDOW_IMPL_GET_IFACE (private->impl)->clear_region &&
4144           gdk_window_has_impl (private))
4145         {
4146           GdkRegion *copy;
4147           copy = gdk_region_copy (region);
4148           gdk_region_intersect (copy, private->clip_region_with_children);
4149
4150           GDK_WINDOW_IMPL_GET_IFACE (private->impl)->clear_region
4151             (window, copy, send_expose);
4152
4153           gdk_region_destroy (copy);
4154         }
4155       else
4156         {
4157           gdk_window_clear_backing_region_direct (window, region);
4158           if (send_expose)
4159             gdk_window_invalidate_region (window, region, FALSE);
4160         }
4161     }
4162 }
4163
4164 static void
4165 gdk_window_clear_area_internal (GdkWindow *window,
4166                                 gint       x,
4167                                 gint       y,
4168                                 gint       width,
4169                                 gint       height,
4170                                 gboolean   send_expose)
4171 {
4172   GdkWindowObject *private = (GdkWindowObject *)window;
4173   GdkRectangle rect;
4174   GdkRegion *region;
4175
4176   g_return_if_fail (GDK_IS_WINDOW (window));
4177
4178   if (GDK_WINDOW_DESTROYED (window))
4179     return;
4180
4181   /* This is what XClearArea does, and e.g. GtkCList uses it,
4182      so we need to duplicate that */
4183   if (width == 0)
4184     width = private->width - x;
4185   if (height == 0)
4186     height = private->height - y;
4187
4188   rect.x = x;
4189   rect.y = y;
4190   rect.width = width;
4191   rect.height = height;
4192
4193   region = gdk_region_rectangle (&rect);
4194   gdk_window_clear_region_internal (window,
4195                                     region,
4196                                     FALSE);
4197   gdk_region_destroy (region);
4198
4199 }
4200
4201 /**
4202  * gdk_window_clear_area:
4203  * @window: a #GdkWindow
4204  * @x: x coordinate of rectangle to clear
4205  * @y: y coordinate of rectangle to clear
4206  * @width: width of rectangle to clear
4207  * @height: height of rectangle to clear
4208  *
4209  * Clears an area of @window to the background color or background pixmap.
4210  *
4211  **/
4212 void
4213 gdk_window_clear_area (GdkWindow *window,
4214                        gint       x,
4215                        gint       y,
4216                        gint       width,
4217                        gint       height)
4218 {
4219   gdk_window_clear_area_internal (window,
4220                                   x, y,
4221                                   width, height,
4222                                   FALSE);
4223 }
4224
4225 /**
4226  * gdk_window_clear_area_e:
4227  * @window: a #GdkWindow
4228  * @x: x coordinate of rectangle to clear
4229  * @y: y coordinate of rectangle to clear
4230  * @width: width of rectangle to clear
4231  * @height: height of rectangle to clear
4232  *
4233  * Like gdk_window_clear_area(), but also generates an expose event for
4234  * the cleared area.
4235  *
4236  * This function has a stupid name because it dates back to the mists
4237  * time, pre-GDK-1.0.
4238  *
4239  **/
4240 void
4241 gdk_window_clear_area_e (GdkWindow *window,
4242                          gint       x,
4243                          gint       y,
4244                          gint       width,
4245                          gint       height)
4246 {
4247   gdk_window_clear_area_internal (window,
4248                                   x, y,
4249                                   width, height,
4250                                   TRUE);
4251 }
4252
4253 static void
4254 gdk_window_draw_image (GdkDrawable *drawable,
4255                        GdkGC       *gc,
4256                        GdkImage    *image,
4257                        gint         xsrc,
4258                        gint         ysrc,
4259                        gint         xdest,
4260                        gint         ydest,
4261                        gint         width,
4262                        gint         height)
4263 {
4264   if (GDK_WINDOW_DESTROYED (drawable))
4265     return;
4266
4267   BEGIN_DRAW;
4268   gdk_draw_image (impl, gc, image, xsrc, ysrc,
4269                   xdest - x_offset, ydest - y_offset,
4270                   width, height);
4271   END_DRAW;
4272 }
4273
4274 static void
4275 gdk_window_draw_pixbuf (GdkDrawable     *drawable,
4276                         GdkGC           *gc,
4277                         GdkPixbuf       *pixbuf,
4278                         gint             src_x,
4279                         gint             src_y,
4280                         gint             dest_x,
4281                         gint             dest_y,
4282                         gint             width,
4283                         gint             height,
4284                         GdkRgbDither     dither,
4285                         gint             x_dither,
4286                         gint             y_dither)
4287 {
4288   GdkWindowObject *private = (GdkWindowObject *)drawable;
4289   GdkDrawableClass *klass;
4290
4291   if (GDK_WINDOW_DESTROYED (drawable))
4292     return;
4293
4294   /* If no gc => no user clipping, but we need clipping
4295      for window emulation, so use a scratch gc */
4296   if (!gc)
4297     gc = _gdk_drawable_get_scratch_gc (drawable, FALSE);
4298
4299   BEGIN_DRAW;
4300
4301   klass = GDK_DRAWABLE_GET_CLASS (impl);
4302
4303   if (private->paint_stack)
4304     klass->draw_pixbuf (impl, gc, pixbuf, src_x, src_y,
4305                         dest_x - x_offset, dest_y - y_offset,
4306                         width, height,
4307                         dither, x_dither - x_offset, y_dither - y_offset);
4308   else
4309     klass->draw_pixbuf (impl, gc, pixbuf, src_x, src_y,
4310                         dest_x - x_offset, dest_y - y_offset,
4311                         width, height,
4312                         dither, x_dither, y_dither);
4313   END_DRAW;
4314 }
4315
4316 static void
4317 gdk_window_draw_trapezoids (GdkDrawable   *drawable,
4318                             GdkGC         *gc,
4319                             GdkTrapezoid  *trapezoids,
4320                             gint           n_trapezoids)
4321 {
4322   GdkTrapezoid *new_trapezoids = NULL;
4323
4324   if (GDK_WINDOW_DESTROYED (drawable))
4325     return;
4326
4327   BEGIN_DRAW;
4328
4329   if (x_offset != 0 || y_offset != 0)
4330     {
4331       gint i;
4332
4333       new_trapezoids = g_new (GdkTrapezoid, n_trapezoids);
4334       for (i=0; i < n_trapezoids; i++)
4335         {
4336           new_trapezoids[i].y1 = trapezoids[i].y1 - y_offset;
4337           new_trapezoids[i].x11 = trapezoids[i].x11 - x_offset;
4338           new_trapezoids[i].x21 = trapezoids[i].x21 - x_offset;
4339           new_trapezoids[i].y2 = trapezoids[i].y2 - y_offset;
4340           new_trapezoids[i].x12 = trapezoids[i].x12 - x_offset;
4341           new_trapezoids[i].x22 = trapezoids[i].x22 - x_offset;
4342         }
4343
4344       trapezoids = new_trapezoids;
4345     }
4346
4347   gdk_draw_trapezoids (impl, gc, trapezoids, n_trapezoids);
4348
4349   g_free (new_trapezoids);
4350
4351   END_DRAW;
4352 }
4353
4354 static void
4355 gdk_window_real_get_size (GdkDrawable *drawable,
4356                           gint *width,
4357                           gint *height)
4358 {
4359   GdkWindowObject *private = (GdkWindowObject *)drawable;
4360
4361   if (width)
4362     *width = private->width;
4363   if (height)
4364     *height = private->height;
4365 }
4366
4367 static GdkVisual*
4368 gdk_window_real_get_visual (GdkDrawable *drawable)
4369 {
4370   GdkColormap *colormap;
4371
4372   g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4373
4374   colormap = gdk_drawable_get_colormap (drawable);
4375   return colormap ? gdk_colormap_get_visual (colormap) : NULL;
4376 }
4377
4378 static gint
4379 gdk_window_real_get_depth (GdkDrawable *drawable)
4380 {
4381   g_return_val_if_fail (GDK_IS_WINDOW (drawable), 0);
4382
4383   return ((GdkWindowObject *)GDK_WINDOW (drawable))->depth;
4384 }
4385
4386 static GdkScreen*
4387 gdk_window_real_get_screen (GdkDrawable *drawable)
4388 {
4389   return gdk_drawable_get_screen (GDK_WINDOW_OBJECT (drawable)->impl);
4390 }
4391
4392 static void
4393 gdk_window_real_set_colormap (GdkDrawable *drawable,
4394                               GdkColormap *cmap)
4395 {
4396   GdkWindowObject *private;
4397
4398   g_return_if_fail (GDK_IS_WINDOW (drawable));
4399
4400   if (GDK_WINDOW_DESTROYED (drawable))
4401     return;
4402
4403   private = (GdkWindowObject *)drawable;
4404
4405   /* different colormap than parent, requires native window */
4406   if (!private->input_only &&
4407       cmap != gdk_drawable_get_colormap ((GdkDrawable *)(private->parent)))
4408     gdk_window_ensure_native ((GdkWindow *)drawable);
4409
4410   gdk_drawable_set_colormap (private->impl, cmap);
4411 }
4412
4413 static GdkColormap*
4414 gdk_window_real_get_colormap (GdkDrawable *drawable)
4415 {
4416   g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4417
4418   if (GDK_WINDOW_DESTROYED (drawable))
4419     return NULL;
4420
4421   return gdk_drawable_get_colormap (((GdkWindowObject*)drawable)->impl);
4422 }
4423
4424 static GdkImage*
4425 gdk_window_copy_to_image (GdkDrawable     *drawable,
4426                           GdkImage        *image,
4427                           gint             src_x,
4428                           gint             src_y,
4429                           gint             dest_x,
4430                           gint             dest_y,
4431                           gint             width,
4432                           gint             height)
4433 {
4434   GdkWindowObject *private = (GdkWindowObject *) drawable;
4435   gint x_offset, y_offset;
4436
4437   g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4438
4439   if (GDK_WINDOW_DESTROYED (drawable))
4440     return NULL;
4441
4442   /* If we're here, a composite image was not necessary, so
4443    * we can ignore the paint stack.
4444    */
4445
4446   /* TODO: Is this right? */
4447   x_offset = 0;
4448   y_offset = 0;
4449
4450   return gdk_drawable_copy_to_image (private->impl,
4451                                      image,
4452                                      src_x - x_offset,
4453                                      src_y - y_offset,
4454                                      dest_x, dest_y,
4455                                      width, height);
4456 }
4457
4458 static void
4459 gdk_window_cairo_surface_destroy (void *data)
4460 {
4461   GdkWindowObject *private = (GdkWindowObject*) data;
4462
4463   private->cairo_surface = NULL;
4464 }
4465
4466 static cairo_surface_t *
4467 gdk_window_create_cairo_surface (GdkDrawable *drawable,
4468                                  int width,
4469                                  int height)
4470 {
4471   return _gdk_windowing_create_cairo_surface (GDK_WINDOW_OBJECT(drawable)->impl,
4472                                               width, height);
4473 }
4474
4475
4476 static cairo_surface_t *
4477 gdk_window_ref_cairo_surface (GdkDrawable *drawable)
4478 {
4479   GdkWindowObject *private = (GdkWindowObject*) drawable;
4480   cairo_surface_t *surface;
4481
4482   if (private->paint_stack)
4483     {
4484       GdkWindowPaint *paint = private->paint_stack->data;
4485
4486       surface = paint->surface;
4487       cairo_surface_reference (surface);
4488     }
4489   else
4490     {
4491
4492       /* This will be drawing directly to the window, so flush implicit paint */
4493       gdk_window_flush ((GdkWindow *)drawable);
4494
4495       if (!private->cairo_surface)
4496         {
4497           int width, height;
4498           GdkDrawable *source;
4499
4500           /* It would be nice if we had some cairo support here so we
4501              could set the clip rect on the cairo surface */
4502           width = private->abs_x + private->width;
4503           height = private->abs_y + private->height;
4504
4505           source = _gdk_drawable_get_source_drawable (drawable);
4506
4507           /* TODO: Avoid the typecheck crap by adding virtual call */
4508           private->cairo_surface = _gdk_drawable_create_cairo_surface (source, width, height);
4509
4510           if (private->cairo_surface)
4511             {
4512               cairo_surface_set_device_offset (private->cairo_surface,
4513                                                private->abs_x,
4514                                                private->abs_y);
4515
4516               cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
4517                                            drawable, gdk_window_cairo_surface_destroy);
4518             }
4519         }
4520       else
4521         cairo_surface_reference (private->cairo_surface);
4522
4523       surface = private->cairo_surface;
4524     }
4525
4526   return surface;
4527 }
4528
4529 static void
4530 gdk_window_set_cairo_clip (GdkDrawable *drawable,
4531                            cairo_t *cr)
4532 {
4533   GdkWindowObject *private = (GdkWindowObject*) drawable;
4534
4535   if (!private->paint_stack)
4536     {
4537       cairo_save (cr);
4538       cairo_identity_matrix (cr);
4539
4540       cairo_reset_clip (cr);
4541
4542       cairo_new_path (cr);
4543       gdk_cairo_region (cr, private->clip_region_with_children);
4544
4545       cairo_restore (cr);
4546       cairo_clip (cr);
4547     }
4548   else
4549     {
4550       GdkWindowPaint *paint = private->paint_stack->data;
4551
4552       /* Only needs to clip to region if piggybacking
4553          on an implicit paint pixmap */
4554       if (paint->uses_implicit)
4555         {
4556           cairo_save (cr);
4557           cairo_identity_matrix (cr);
4558
4559           cairo_reset_clip (cr);
4560
4561           cairo_new_path (cr);
4562           gdk_cairo_region (cr, paint->region);
4563           cairo_restore (cr);
4564
4565           cairo_clip (cr);
4566         }
4567     }
4568 }
4569
4570 /* Code for dirty-region queueing
4571  */
4572 static GSList *update_windows = NULL;
4573 static guint update_idle = 0;
4574 static gboolean debug_updates = FALSE;
4575
4576 static inline gboolean
4577 gdk_window_is_ancestor (GdkWindow *window,
4578                         GdkWindow *ancestor)
4579 {
4580   while (window)
4581     {
4582       GdkWindow *parent = (GdkWindow*) ((GdkWindowObject*) window)->parent;
4583
4584       if (parent == ancestor)
4585         return TRUE;
4586
4587       window = parent;
4588     }
4589
4590   return FALSE;
4591 }
4592
4593 static void
4594 gdk_window_add_update_window (GdkWindow *window)
4595 {
4596   GSList *tmp;
4597   GSList *prev = NULL;
4598   gboolean has_ancestor_in_list = FALSE;
4599
4600   for (tmp = update_windows; tmp; tmp = tmp->next)
4601     {
4602       GdkWindowObject *parent = GDK_WINDOW_OBJECT (window)->parent;
4603
4604       /*  check if tmp is an ancestor of "window"; if it is, set a
4605        *  flag indicating that all following windows are either
4606        *  children of "window" or from a differen hierarchy
4607        */
4608       if (!has_ancestor_in_list && gdk_window_is_ancestor (window, tmp->data))
4609         has_ancestor_in_list = TRUE;
4610
4611       /* insert in reverse stacking order when adding around siblings,
4612        * so processing updates properly paints over lower stacked windows
4613        */
4614       if (parent == GDK_WINDOW_OBJECT (tmp->data)->parent)
4615         {
4616           gint index = g_list_index (parent->children, window);
4617           for (; tmp && parent == GDK_WINDOW_OBJECT (tmp->data)->parent; tmp = tmp->next)
4618             {
4619               gint sibling_index = g_list_index (parent->children, tmp->data);
4620               if (index > sibling_index)
4621                 break;
4622               prev = tmp;
4623             }
4624           /* here, tmp got advanced past all lower stacked siblings */
4625           tmp = g_slist_prepend (tmp, window);
4626           if (prev)
4627             prev->next = tmp;
4628           else
4629             update_windows = tmp;
4630           return;
4631         }
4632
4633       /*  if "window" has an ancestor in the list and tmp is one of
4634        *  "window's" children, insert "window" before tmp
4635        */
4636       if (has_ancestor_in_list && gdk_window_is_ancestor (tmp->data, window))
4637         {
4638           tmp = g_slist_prepend (tmp, window);
4639
4640           if (prev)
4641             prev->next = tmp;
4642           else
4643             update_windows = tmp;
4644           return;
4645         }
4646
4647       /*  if we're at the end of the list and had an ancestor it it,
4648        *  append to the list
4649        */
4650       if (! tmp->next && has_ancestor_in_list)
4651         {
4652           tmp = g_slist_append (tmp, window);
4653           return;
4654         }
4655
4656       prev = tmp;
4657     }
4658
4659   /*  if all above checks failed ("window" is from a different
4660    *  hierarchy than what is already in the list) or the list is
4661    *  empty, prepend
4662    */
4663   update_windows = g_slist_prepend (update_windows, window);
4664 }
4665
4666 static void
4667 gdk_window_remove_update_window (GdkWindow *window)
4668 {
4669   update_windows = g_slist_remove (update_windows, window);
4670 }
4671
4672 static gboolean
4673 gdk_window_update_idle (gpointer data)
4674 {
4675   gdk_window_process_all_updates ();
4676
4677   return FALSE;
4678 }
4679
4680 static gboolean
4681 gdk_window_is_toplevel_frozen (GdkWindow *window)
4682 {
4683   GdkWindowObject *toplevel;
4684
4685   toplevel = (GdkWindowObject *)gdk_window_get_toplevel (window);
4686
4687   return toplevel->update_and_descendants_freeze_count > 0;
4688 }
4689
4690 static void
4691 gdk_window_schedule_update (GdkWindow *window)
4692 {
4693   if (window &&
4694       (GDK_WINDOW_OBJECT (window)->update_freeze_count ||
4695        gdk_window_is_toplevel_frozen (window)))
4696     return;
4697
4698   if (!update_idle)
4699     {
4700       update_idle = gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
4701                                      gdk_window_update_idle, NULL, NULL);
4702     }
4703 }
4704
4705 void
4706 _gdk_window_process_updates_recurse (GdkWindow *window,
4707                                      GdkRegion *expose_region)
4708 {
4709   GdkWindowObject *private = (GdkWindowObject *)window;
4710   GdkWindowObject *child;
4711   GdkRegion *child_region;
4712   GdkRectangle r;
4713   GList *l;
4714
4715   if (gdk_region_empty (expose_region))
4716     return;
4717
4718   /* Iterate over children, starting at topmost */
4719   for (l = private->children; l != NULL; l = l->next)
4720     {
4721       child = l->data;
4722
4723       if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
4724         continue;
4725
4726       /* Ignore offscreen children, as they don't draw in their parent and
4727        * don't take part in the clipping */
4728       if (gdk_window_is_offscreen (child))
4729         continue;
4730
4731       r.x = child->x;
4732       r.y = child->y;
4733       r.width = child->width;
4734       r.height = child->height;
4735
4736       child_region = gdk_region_rectangle (&r);
4737       if (child->shape)
4738         {
4739           /* Adjust shape region to parent window coords */
4740           gdk_region_offset (child->shape, child->x, child->y);
4741           gdk_region_intersect (child_region, child->shape);
4742           gdk_region_offset (child->shape, -child->x, -child->y);
4743         }
4744
4745       if (child->impl == private->impl)
4746         {
4747           /* Client side child, expose */
4748           gdk_region_intersect (child_region, expose_region);
4749           gdk_region_subtract (expose_region, child_region);
4750           gdk_region_offset (child_region, -child->x, -child->y);
4751           _gdk_window_process_updates_recurse ((GdkWindow *)child, child_region);
4752         }
4753       else
4754         {
4755           /* Native child, just remove area from expose region */
4756           gdk_region_subtract (expose_region, child_region);
4757         }
4758       gdk_region_destroy (child_region);
4759     }
4760
4761   if (!gdk_region_empty (expose_region))
4762     {
4763       if (private->event_mask & GDK_EXPOSURE_MASK)
4764         {
4765           GdkEvent event;
4766
4767           event.expose.type = GDK_EXPOSE;
4768           event.expose.window = g_object_ref (window);
4769           event.expose.send_event = FALSE;
4770           event.expose.count = 0;
4771           event.expose.region = expose_region;
4772           gdk_region_get_clipbox (expose_region, &event.expose.area);
4773
4774           (*_gdk_event_func) (&event, _gdk_event_data);
4775
4776           g_object_unref (window);
4777         }
4778       else if (private->bg_pixmap != GDK_NO_BG)
4779         {
4780           /* No exposure mask set, so nothing will be drawn, the
4781            * app relies on the background being what it specified
4782            * for the window. So, we need to clear this manually.
4783            *
4784            * We use begin/end_paint around the clear so that we can
4785            * piggyback on the implicit paint */
4786
4787           gdk_window_begin_paint_region (window, expose_region);
4788           gdk_window_clear_region_internal (window, expose_region, FALSE);
4789           gdk_window_end_paint (window);
4790         }
4791     }
4792 }
4793
4794 static void
4795 gdk_window_process_updates_internal (GdkWindow *window)
4796 {
4797   GdkWindowObject *private = (GdkWindowObject *)window;
4798   gboolean save_region = FALSE;
4799   GdkRectangle clip_box;
4800
4801   /* If an update got queued during update processing, we can get a
4802    * window in the update queue that has an empty update_area.
4803    * just ignore it.
4804    */
4805   if (private->update_area)
4806     {
4807       GdkRegion *update_area = private->update_area;
4808       private->update_area = NULL;
4809
4810       if (_gdk_event_func && gdk_window_is_viewable (window)  &&
4811           private->window_type != GDK_WINDOW_FOREIGN)
4812         {
4813           GdkRectangle window_rect;
4814           GdkRegion *expose_region;
4815           GdkRegion *window_region;
4816           gboolean end_implicit;
4817
4818           /* Clip to part visible in toplevel */
4819           gdk_region_intersect (update_area, private->clip_region);
4820
4821           if (debug_updates)
4822             {
4823               /* Make sure we see the red invalid area before redrawing. */
4824               gdk_display_sync (gdk_drawable_get_display (window));
4825               g_usleep (70000);
4826             }
4827
4828           save_region = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->queue_antiexpose (window, update_area);
4829           if (save_region)
4830             expose_region = gdk_region_copy (update_area);
4831           else
4832             expose_region = update_area;
4833
4834           window_rect.x = 0;
4835           window_rect.y = 0;
4836           window_rect.width = private->width;
4837           window_rect.height = private->height;
4838
4839           window_region = gdk_region_rectangle (&window_rect);
4840           gdk_region_intersect (expose_region,
4841                                 window_region);
4842           gdk_region_destroy (window_region);
4843
4844
4845           /* No need to do any moves that will end up over the update area */
4846           if (private->outstanding_moves)
4847             {
4848               GdkWindowRegionMove *move;
4849               GdkRegion *remove;
4850               GList *l, *prev;
4851
4852               remove = gdk_region_copy (update_area);
4853               for (l = g_list_last (private->outstanding_moves); l != NULL; l = prev)
4854                 {
4855                   prev = l->prev;
4856                   move = l->data;
4857                   /* Don't need this area */
4858                   gdk_region_subtract (move->dest_region, remove);
4859
4860                   /* However if any of the destination we do need has a source
4861                      in the updated region we do need that as a destination for
4862                      the earlier moves */
4863                   gdk_region_offset (move->dest_region, -move->dx, -move->dy);
4864                   gdk_region_subtract (remove, move->dest_region);
4865
4866                   if (gdk_region_empty (move->dest_region))
4867                     {
4868                       gdk_window_region_move_free (move);
4869                       private->outstanding_moves =
4870                         g_list_delete_link (private->outstanding_moves, l);
4871                     }
4872                   else
4873                     gdk_region_offset (move->dest_region, move->dx, move->dy);
4874                 }
4875               gdk_region_destroy (remove);
4876             }
4877
4878           gdk_region_get_clipbox (expose_region, &clip_box);
4879           end_implicit = gdk_window_begin_implicit_paint (window, &clip_box);
4880           if (end_implicit) /* rendering is not double buffered, do moves now */
4881               gdk_window_flush_outstanding_moves (window);
4882           _gdk_windowing_window_process_updates_recurse (window, expose_region);
4883           if (end_implicit)
4884             {
4885               /* Do moves right before exposes are rendered */
4886               gdk_window_flush_outstanding_moves (window);
4887               gdk_window_end_implicit_paint (window);
4888             }
4889
4890           if (expose_region != update_area)
4891             gdk_region_destroy (expose_region);
4892         }
4893       if (!save_region)
4894         gdk_region_destroy (update_area);
4895     }
4896
4897   if (private->outstanding_moves)
4898     {
4899       /* Flush any outstanding moves, may happen if we moved a window but got
4900          no actual invalid area */
4901       gdk_window_flush_outstanding_moves (window);
4902     }
4903 }
4904
4905 static void
4906 flush_all_displays (void)
4907 {
4908   GSList *displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
4909   GSList *tmp_list;
4910
4911   for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
4912     gdk_display_flush (tmp_list->data);
4913
4914   g_slist_free (displays);
4915 }
4916
4917 /* Currently it is not possible to override
4918  * gdk_window_process_all_updates in the same manner as
4919  * gdk_window_process_updates and gdk_window_invalidate_maybe_recurse
4920  * by implementing the GdkPaintable interface.  If in the future a
4921  * backend would need this, the right solution would be to add a
4922  * method to GdkDisplay that can be optionally
4923  * NULL. gdk_window_process_all_updates can then walk the list of open
4924  * displays and call the mehod.
4925  */
4926
4927 /**
4928  * gdk_window_process_all_updates:
4929  *
4930  * Calls gdk_window_process_updates() for all windows (see #GdkWindow)
4931  * in the application.
4932  *
4933  **/
4934 void
4935 gdk_window_process_all_updates (void)
4936 {
4937   GSList *old_update_windows = update_windows;
4938   GSList *tmp_list = update_windows;
4939   static gboolean in_process_all_updates = FALSE;
4940
4941   if (in_process_all_updates)
4942     return;
4943
4944   in_process_all_updates = TRUE;
4945
4946   if (update_idle)
4947     g_source_remove (update_idle);
4948
4949   update_windows = NULL;
4950   update_idle = 0;
4951
4952   _gdk_windowing_before_process_all_updates ();
4953
4954   g_slist_foreach (old_update_windows, (GFunc)g_object_ref, NULL);
4955
4956   while (tmp_list)
4957     {
4958       GdkWindowObject *private = (GdkWindowObject *)tmp_list->data;
4959
4960       if (!GDK_WINDOW_DESTROYED (tmp_list->data))
4961         {
4962           if (private->update_freeze_count ||
4963               gdk_window_is_toplevel_frozen (tmp_list->data))
4964             gdk_window_add_update_window ((GdkWindow *) private);
4965           else
4966             gdk_window_process_updates_internal (tmp_list->data);
4967         }
4968
4969       g_object_unref (tmp_list->data);
4970       tmp_list = tmp_list->next;
4971     }
4972
4973   g_slist_free (old_update_windows);
4974
4975   flush_all_displays ();
4976
4977   _gdk_windowing_after_process_all_updates ();
4978
4979   in_process_all_updates = FALSE;
4980 }
4981
4982 /**
4983  * gdk_window_process_updates:
4984  * @window: a #GdkWindow
4985  * @update_children: whether to also process updates for child windows
4986  *
4987  * Sends one or more expose events to @window. The areas in each
4988  * expose event will cover the entire update area for the window (see
4989  * gdk_window_invalidate_region() for details). Normally GDK calls
4990  * gdk_window_process_all_updates() on your behalf, so there's no
4991  * need to call this function unless you want to force expose events
4992  * to be delivered immediately and synchronously (vs. the usual
4993  * case, where GDK delivers them in an idle handler). Occasionally
4994  * this is useful to produce nicer scrolling behavior, for example.
4995  *
4996  **/
4997 void
4998 gdk_window_process_updates (GdkWindow *window,
4999                             gboolean   update_children)
5000 {
5001   GdkWindowObject *private = (GdkWindowObject *)window;
5002   GdkWindowObject *impl_window;
5003
5004   g_return_if_fail (GDK_IS_WINDOW (window));
5005
5006   impl_window = gdk_window_get_impl_window (private);
5007   if ((impl_window->update_area ||
5008        impl_window->outstanding_moves) &&
5009       !impl_window->update_freeze_count &&
5010       !gdk_window_is_toplevel_frozen (window))
5011     {
5012       gdk_window_process_updates_internal ((GdkWindow *)impl_window);
5013       gdk_window_remove_update_window ((GdkWindow *)impl_window);
5014     }
5015
5016   if (update_children)
5017     {
5018       /* process updates in reverse stacking order so composition or
5019        * painting over achieves the desired effect for offscreen windows
5020        */
5021       GList *node;
5022       for (node = g_list_last (private->children); node; node = node->prev)
5023         gdk_window_process_updates (node->data, TRUE);
5024     }
5025 }
5026
5027 /**
5028  * gdk_window_invalidate_rect:
5029  * @window: a #GdkWindow
5030  * @rect: rectangle to invalidate or %NULL to invalidate the whole
5031  *      window
5032  * @invalidate_children: whether to also invalidate child windows
5033  *
5034  * A convenience wrapper around gdk_window_invalidate_region() which
5035  * invalidates a rectangular region. See
5036  * gdk_window_invalidate_region() for details.
5037  **/
5038 void
5039 gdk_window_invalidate_rect (GdkWindow          *window,
5040                             const GdkRectangle *rect,
5041                             gboolean            invalidate_children)
5042 {
5043   GdkRectangle window_rect;
5044   GdkRegion *region;
5045   GdkWindowObject *private = (GdkWindowObject *)window;
5046
5047   g_return_if_fail (GDK_IS_WINDOW (window));
5048
5049   if (GDK_WINDOW_DESTROYED (window))
5050     return;
5051
5052   if (private->input_only || !private->viewable)
5053     return;
5054
5055   if (!rect)
5056     {
5057       window_rect.x = 0;
5058       window_rect.y = 0;
5059       gdk_drawable_get_size (GDK_DRAWABLE (window),
5060                              &window_rect.width,
5061                              &window_rect.height);
5062       rect = &window_rect;
5063     }
5064
5065   region = gdk_region_rectangle (rect);
5066   gdk_window_invalidate_region (window, region, invalidate_children);
5067   gdk_region_destroy (region);
5068 }
5069
5070 static void
5071 draw_ugly_color (GdkWindow       *window,
5072                  const GdkRegion *region)
5073 {
5074   /* Draw ugly color all over the newly-invalid region */
5075   GdkColor ugly_color = { 0, 50000, 10000, 10000 };
5076   GdkGC *ugly_gc;
5077   GdkRectangle clipbox;
5078
5079   ugly_gc = gdk_gc_new (window);
5080   gdk_gc_set_rgb_fg_color (ugly_gc, &ugly_color);
5081   gdk_gc_set_clip_region (ugly_gc, region);
5082
5083   gdk_region_get_clipbox (region, &clipbox);
5084
5085   gdk_draw_rectangle (window,
5086                       ugly_gc,
5087                       TRUE,
5088                       clipbox.x, clipbox.y,
5089                       clipbox.width, clipbox.height);
5090
5091   g_object_unref (ugly_gc);
5092 }
5093
5094 /**
5095  * gdk_window_invalidate_maybe_recurse:
5096  * @window: a #GdkWindow
5097  * @region: a #GdkRegion
5098  * @child_func: function to use to decide if to recurse to a child,
5099  *              %NULL means never recurse.
5100  * @user_data: data passed to @child_func
5101  *
5102  * Adds @region to the update area for @window. The update area is the
5103  * region that needs to be redrawn, or "dirty region." The call
5104  * gdk_window_process_updates() sends one or more expose events to the
5105  * window, which together cover the entire update area. An
5106  * application would normally redraw the contents of @window in
5107  * response to those expose events.
5108  *
5109  * GDK will call gdk_window_process_all_updates() on your behalf
5110  * whenever your program returns to the main loop and becomes idle, so
5111  * normally there's no need to do that manually, you just need to
5112  * invalidate regions that you know should be redrawn.
5113  *
5114  * The @child_func parameter controls whether the region of
5115  * each child window that intersects @region will also be invalidated.
5116  * Only children for which @child_func returns TRUE will have the area
5117  * invalidated.
5118  **/
5119 void
5120 gdk_window_invalidate_maybe_recurse (GdkWindow       *window,
5121                                      const GdkRegion *region,
5122                                      gboolean       (*child_func) (GdkWindow *,
5123                                                                    gpointer),
5124                                      gpointer   user_data)
5125 {
5126   GdkWindowObject *private = (GdkWindowObject *)window;
5127   GdkWindowObject *impl_window;
5128   GdkRegion *visible_region;
5129   GList *tmp_list;
5130
5131   g_return_if_fail (GDK_IS_WINDOW (window));
5132
5133   if (GDK_WINDOW_DESTROYED (window))
5134     return;
5135
5136   if (private->input_only ||
5137       !private->viewable ||
5138       gdk_region_empty (region) ||
5139       private->window_type == GDK_WINDOW_ROOT)
5140     return;
5141
5142   visible_region = gdk_drawable_get_visible_region (window);
5143   gdk_region_intersect (visible_region, region);
5144
5145   tmp_list = private->children;
5146   while (tmp_list)
5147     {
5148       GdkWindowObject *child = tmp_list->data;
5149
5150       if (!child->input_only)
5151         {
5152           GdkRegion *child_region;
5153           GdkRectangle child_rect;
5154
5155           child_rect.x = child->x;
5156           child_rect.y = child->y;
5157           child_rect.width = child->width;
5158           child_rect.height = child->height;
5159           child_region = gdk_region_rectangle (&child_rect);
5160
5161           /* remove child area from the invalid area of the parent */
5162           if (GDK_WINDOW_IS_MAPPED (child) && !child->shaped &&
5163               !child->composited &&
5164               !gdk_window_is_offscreen (child))
5165             gdk_region_subtract (visible_region, child_region);
5166
5167           if (child_func && (*child_func) ((GdkWindow *)child, user_data))
5168             {
5169               GdkRegion *tmp = gdk_region_copy (region);
5170
5171               gdk_region_offset (tmp, - child_rect.x, - child_rect.y);
5172               gdk_region_offset (child_region, - child_rect.x, - child_rect.y);
5173               gdk_region_intersect (child_region, tmp);
5174
5175               gdk_window_invalidate_maybe_recurse ((GdkWindow *)child,
5176                                                    child_region, child_func, user_data);
5177
5178               gdk_region_destroy (tmp);
5179             }
5180
5181           gdk_region_destroy (child_region);
5182         }
5183
5184       tmp_list = tmp_list->next;
5185     }
5186
5187   impl_window = gdk_window_get_impl_window (private);
5188
5189   if (!gdk_region_empty (visible_region)  ||
5190       /* Even if we're not exposing anything, make sure we process
5191          idles for windows with outstanding moves */
5192       (impl_window->outstanding_moves != NULL &&
5193        impl_window->update_area == NULL))
5194     {
5195       if (debug_updates)
5196         draw_ugly_color (window, region);
5197
5198       /* Convert to impl coords */
5199       gdk_region_offset (visible_region, private->abs_x, private->abs_y);
5200       if (impl_window->update_area)
5201         {
5202           gdk_region_union (impl_window->update_area, visible_region);
5203         }
5204       else
5205         {
5206           gdk_window_add_update_window ((GdkWindow *)impl_window);
5207           impl_window->update_area = gdk_region_copy (visible_region);
5208
5209           gdk_window_schedule_update ((GdkWindow *)impl_window);
5210         }
5211     }
5212
5213   gdk_region_destroy (visible_region);
5214 }
5215
5216 static gboolean
5217 true_predicate (GdkWindow *window,
5218                 gpointer   user_data)
5219 {
5220   return TRUE;
5221 }
5222
5223 /**
5224  * gdk_window_invalidate_region:
5225  * @window: a #GdkWindow
5226  * @region: a #GdkRegion
5227  * @invalidate_children: %TRUE to also invalidate child windows
5228  *
5229  * Adds @region to the update area for @window. The update area is the
5230  * region that needs to be redrawn, or "dirty region." The call
5231  * gdk_window_process_updates() sends one or more expose events to the
5232  * window, which together cover the entire update area. An
5233  * application would normally redraw the contents of @window in
5234  * response to those expose events.
5235  *
5236  * GDK will call gdk_window_process_all_updates() on your behalf
5237  * whenever your program returns to the main loop and becomes idle, so
5238  * normally there's no need to do that manually, you just need to
5239  * invalidate regions that you know should be redrawn.
5240  *
5241  * The @invalidate_children parameter controls whether the region of
5242  * each child window that intersects @region will also be invalidated.
5243  * If %FALSE, then the update area for child windows will remain
5244  * unaffected. See gdk_window_invalidate_maybe_recurse if you need
5245  * fine grained control over which children are invalidated.
5246  **/
5247 void
5248 gdk_window_invalidate_region (GdkWindow       *window,
5249                               const GdkRegion *region,
5250                               gboolean         invalidate_children)
5251 {
5252   gdk_window_invalidate_maybe_recurse (window, region,
5253                                        invalidate_children ?
5254                                          true_predicate : (gboolean (*) (GdkWindow *, gpointer))NULL,
5255                                        NULL);
5256 }
5257
5258 /**
5259  * _gdk_window_invalidate_for_expose:
5260  * @window: a #GdkWindow
5261  * @region: a #GdkRegion
5262  *
5263  * Adds @region to the update area for @window. The update area is the
5264  * region that needs to be redrawn, or "dirty region." The call
5265  * gdk_window_process_updates() sends one or more expose events to the
5266  * window, which together cover the entire update area. An
5267  * application would normally redraw the contents of @window in
5268  * response to those expose events.
5269  *
5270  * GDK will call gdk_window_process_all_updates() on your behalf
5271  * whenever your program returns to the main loop and becomes idle, so
5272  * normally there's no need to do that manually, you just need to
5273  * invalidate regions that you know should be redrawn.
5274  *
5275  * This version of invalidation is used when you recieve expose events
5276  * from the native window system. It exposes the native window, plus
5277  * any non-native child windows (but not native child windows, as those would
5278  * have gotten their own expose events).
5279  **/
5280 void
5281 _gdk_window_invalidate_for_expose (GdkWindow       *window,
5282                                    const GdkRegion *region)
5283 {
5284   gdk_window_invalidate_maybe_recurse (window, region,
5285                                        (gboolean (*) (GdkWindow *, gpointer))gdk_window_has_no_impl,
5286                                        NULL);
5287 }
5288
5289
5290 /**
5291  * gdk_window_get_update_area:
5292  * @window: a #GdkWindow
5293  *
5294  * Transfers ownership of the update area from @window to the caller
5295  * of the function. That is, after calling this function, @window will
5296  * no longer have an invalid/dirty region; the update area is removed
5297  * from @window and handed to you. If a window has no update area,
5298  * gdk_window_get_update_area() returns %NULL. You are responsible for
5299  * calling gdk_region_destroy() on the returned region if it's non-%NULL.
5300  *
5301  * Return value: the update area for @window
5302  **/
5303 GdkRegion *
5304 gdk_window_get_update_area (GdkWindow *window)
5305 {
5306   GdkWindowObject *private = (GdkWindowObject *)window;
5307   GdkWindowObject *impl_window;
5308   GdkRegion *tmp_region;
5309
5310   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
5311
5312   impl_window = gdk_window_get_impl_window (private);
5313
5314   if (impl_window->update_area)
5315     {
5316       tmp_region = gdk_region_copy (private->clip_region_with_children);
5317       /* Convert to impl coords */
5318       gdk_region_offset (tmp_region, private->abs_x, private->abs_y);
5319       gdk_region_intersect (tmp_region, impl_window->update_area);
5320
5321       if (gdk_region_empty (tmp_region))
5322         {
5323           gdk_region_destroy (tmp_region);
5324           return NULL;
5325         }
5326       else
5327         {
5328           gdk_region_subtract (impl_window->update_area, tmp_region);
5329
5330           if (gdk_region_empty (impl_window->update_area) &&
5331               impl_window->outstanding_moves == NULL)
5332             {
5333               gdk_region_destroy (impl_window->update_area);
5334               impl_window->update_area = NULL;
5335
5336               gdk_window_remove_update_window ((GdkWindow *)impl_window);
5337             }
5338
5339           /* Convert from impl coords */
5340           gdk_region_offset (tmp_region, -private->abs_x, -private->abs_y);
5341           return tmp_region;
5342
5343         }
5344     }
5345   else
5346     return NULL;
5347 }
5348
5349 /**
5350  * _gdk_window_clear_update_area:
5351  * @window: a #GdkWindow.
5352  *
5353  * Internal function to clear the update area for a window. This
5354  * is called when the window is hidden or destroyed.
5355  **/
5356 void
5357 _gdk_window_clear_update_area (GdkWindow *window)
5358 {
5359   GdkWindowObject *private = (GdkWindowObject *)window;
5360
5361   g_return_if_fail (GDK_IS_WINDOW (window));
5362
5363   if (private->update_area)
5364     {
5365       gdk_window_remove_update_window (window);
5366
5367       gdk_region_destroy (private->update_area);
5368       private->update_area = NULL;
5369     }
5370 }
5371
5372 /**
5373  * gdk_window_freeze_updates:
5374  * @window: a #GdkWindow
5375  *
5376  * Temporarily freezes a window such that it won't receive expose
5377  * events.  The window will begin receiving expose events again when
5378  * gdk_window_thaw_updates() is called. If gdk_window_freeze_updates()
5379  * has been called more than once, gdk_window_thaw_updates() must be called
5380  * an equal number of times to begin processing exposes.
5381  **/
5382 void
5383 gdk_window_freeze_updates (GdkWindow *window)
5384 {
5385   GdkWindowObject *private = (GdkWindowObject *)window;
5386   GdkWindowObject *impl_window;
5387
5388   g_return_if_fail (GDK_IS_WINDOW (window));
5389
5390   impl_window = gdk_window_get_impl_window (private);
5391   impl_window->update_freeze_count++;
5392 }
5393
5394 /**
5395  * gdk_window_thaw_updates:
5396  * @window: a #GdkWindow
5397  *
5398  * Thaws a window frozen with gdk_window_freeze_updates().
5399  **/
5400 void
5401 gdk_window_thaw_updates (GdkWindow *window)
5402 {
5403   GdkWindowObject *private = (GdkWindowObject *)window;
5404   GdkWindowObject *impl_window;
5405
5406   g_return_if_fail (GDK_IS_WINDOW (window));
5407
5408   impl_window = gdk_window_get_impl_window (private);
5409
5410   g_return_if_fail (impl_window->update_freeze_count > 0);
5411
5412   if (--impl_window->update_freeze_count == 0)
5413     gdk_window_schedule_update (GDK_WINDOW (impl_window));
5414 }
5415
5416 /**
5417  * gdk_window_freeze_toplevel_updates_libgtk_only:
5418  * @window: a #GdkWindow
5419  *
5420  * Temporarily freezes a window and all its descendants such that it won't
5421  * receive expose events.  The window will begin receiving expose events
5422  * again when gdk_window_thaw_toplevel_updates_libgtk_only() is called. If
5423  * gdk_window_freeze_toplevel_updates_libgtk_only()
5424  * has been called more than once,
5425  * gdk_window_thaw_toplevel_updates_libgtk_only() must be called
5426  * an equal number of times to begin processing exposes.
5427  *
5428  * This function is not part of the GDK public API and is only
5429  * for use by GTK+.
5430  **/
5431 void
5432 gdk_window_freeze_toplevel_updates_libgtk_only (GdkWindow *window)
5433 {
5434   GdkWindowObject *private = (GdkWindowObject *)window;
5435
5436   g_return_if_fail (GDK_IS_WINDOW (window));
5437   g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
5438
5439   private->update_and_descendants_freeze_count++;
5440 }
5441
5442 /**
5443  * gdk_window_thaw_toplevel_updates_libgtk_only:
5444  * @window: a #GdkWindow
5445  *
5446  * Thaws a window frozen with
5447  * gdk_window_freeze_toplevel_updates_libgtk_only().
5448  *
5449  * This function is not part of the GDK public API and is only
5450  * for use by GTK+.
5451  **/
5452 void
5453 gdk_window_thaw_toplevel_updates_libgtk_only (GdkWindow *window)
5454 {
5455   GdkWindowObject *private = (GdkWindowObject *)window;
5456
5457   g_return_if_fail (GDK_IS_WINDOW (window));
5458   g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
5459   g_return_if_fail (private->update_and_descendants_freeze_count > 0);
5460
5461   private->update_and_descendants_freeze_count--;
5462
5463   gdk_window_schedule_update (window);
5464 }
5465
5466 /**
5467  * gdk_window_set_debug_updates:
5468  * @setting: %TRUE to turn on update debugging
5469  *
5470  * With update debugging enabled, calls to
5471  * gdk_window_invalidate_region() clear the invalidated region of the
5472  * screen to a noticeable color, and GDK pauses for a short time
5473  * before sending exposes to windows during
5474  * gdk_window_process_updates().  The net effect is that you can see
5475  * the invalid region for each window and watch redraws as they
5476  * occur. This allows you to diagnose inefficiencies in your application.
5477  *
5478  * In essence, because the GDK rendering model prevents all flicker,
5479  * if you are redrawing the same region 400 times you may never
5480  * notice, aside from noticing a speed problem. Enabling update
5481  * debugging causes GTK to flicker slowly and noticeably, so you can
5482  * see exactly what's being redrawn when, in what order.
5483  *
5484  * The --gtk-debug=updates command line option passed to GTK+ programs
5485  * enables this debug option at application startup time. That's
5486  * usually more useful than calling gdk_window_set_debug_updates()
5487  * yourself, though you might want to use this function to enable
5488  * updates sometime after application startup time.
5489  *
5490  **/
5491 void
5492 gdk_window_set_debug_updates (gboolean setting)
5493 {
5494   debug_updates = setting;
5495 }
5496
5497 /**
5498  * gdk_window_constrain_size:
5499  * @geometry: a #GdkGeometry structure
5500  * @flags: a mask indicating what portions of @geometry are set
5501  * @width: desired width of window
5502  * @height: desired height of the window
5503  * @new_width: location to store resulting width
5504  * @new_height: location to store resulting height
5505  *
5506  * Constrains a desired width and height according to a
5507  * set of geometry hints (such as minimum and maximum size).
5508  */
5509 void
5510 gdk_window_constrain_size (GdkGeometry *geometry,
5511                            guint        flags,
5512                            gint         width,
5513                            gint         height,
5514                            gint        *new_width,
5515                            gint        *new_height)
5516 {
5517   /* This routine is partially borrowed from fvwm.
5518    *
5519    * Copyright 1993, Robert Nation
5520    *     You may use this code for any purpose, as long as the original
5521    *     copyright remains in the source code and all documentation
5522    *
5523    * which in turn borrows parts of the algorithm from uwm
5524    */
5525   gint min_width = 0;
5526   gint min_height = 0;
5527   gint base_width = 0;
5528   gint base_height = 0;
5529   gint xinc = 1;
5530   gint yinc = 1;
5531   gint max_width = G_MAXINT;
5532   gint max_height = G_MAXINT;
5533
5534 #define FLOOR(value, base)      ( ((gint) ((value) / (base))) * (base) )
5535
5536   if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
5537     {
5538       base_width = geometry->base_width;
5539       base_height = geometry->base_height;
5540       min_width = geometry->min_width;
5541       min_height = geometry->min_height;
5542     }
5543   else if (flags & GDK_HINT_BASE_SIZE)
5544     {
5545       base_width = geometry->base_width;
5546       base_height = geometry->base_height;
5547       min_width = geometry->base_width;
5548       min_height = geometry->base_height;
5549     }
5550   else if (flags & GDK_HINT_MIN_SIZE)
5551     {
5552       base_width = geometry->min_width;
5553       base_height = geometry->min_height;
5554       min_width = geometry->min_width;
5555       min_height = geometry->min_height;
5556     }
5557
5558   if (flags & GDK_HINT_MAX_SIZE)
5559     {
5560       max_width = geometry->max_width ;
5561       max_height = geometry->max_height;
5562     }
5563
5564   if (flags & GDK_HINT_RESIZE_INC)
5565     {
5566       xinc = MAX (xinc, geometry->width_inc);
5567       yinc = MAX (yinc, geometry->height_inc);
5568     }
5569
5570   /* clamp width and height to min and max values
5571    */
5572   width = CLAMP (width, min_width, max_width);
5573   height = CLAMP (height, min_height, max_height);
5574
5575   /* shrink to base + N * inc
5576    */
5577   width = base_width + FLOOR (width - base_width, xinc);
5578   height = base_height + FLOOR (height - base_height, yinc);
5579
5580   /* constrain aspect ratio, according to:
5581    *
5582    *                width
5583    * min_aspect <= -------- <= max_aspect
5584    *                height
5585    */
5586
5587   if (flags & GDK_HINT_ASPECT &&
5588       geometry->min_aspect > 0 &&
5589       geometry->max_aspect > 0)
5590     {
5591       gint delta;
5592
5593       if (geometry->min_aspect * height > width)
5594         {
5595           delta = FLOOR (height - width / geometry->min_aspect, yinc);
5596           if (height - delta >= min_height)
5597             height -= delta;
5598           else
5599             {
5600               delta = FLOOR (height * geometry->min_aspect - width, xinc);
5601               if (width + delta <= max_width)
5602                 width += delta;
5603             }
5604         }
5605
5606       if (geometry->max_aspect * height < width)
5607         {
5608           delta = FLOOR (width - height * geometry->max_aspect, xinc);
5609           if (width - delta >= min_width)
5610             width -= delta;
5611           else
5612             {
5613               delta = FLOOR (width / geometry->max_aspect - height, yinc);
5614               if (height + delta <= max_height)
5615                 height += delta;
5616             }
5617         }
5618     }
5619
5620 #undef FLOOR
5621
5622   *new_width = width;
5623   *new_height = height;
5624 }
5625
5626 /**
5627  * gdk_window_get_pointer:
5628  * @window: a #GdkWindow
5629  * @x: return location for X coordinate of pointer or %NULL to not
5630  *      return the X coordinate
5631  * @y: return location for Y coordinate of pointer or %NULL to not
5632  *      return the Y coordinate
5633  * @mask: return location for modifier mask or %NULL to not return the
5634  *      modifier mask
5635  *
5636  * Obtains the current pointer position and modifier state.
5637  * The position is given in coordinates relative to the upper left
5638  * corner of @window.
5639  *
5640  * Return value: the window containing the pointer (as with
5641  * gdk_window_at_pointer()), or %NULL if the window containing the
5642  * pointer isn't known to GDK
5643  **/
5644 GdkWindow*
5645 gdk_window_get_pointer (GdkWindow         *window,
5646                         gint              *x,
5647                         gint              *y,
5648                         GdkModifierType   *mask)
5649 {
5650   GdkDisplay *display;
5651   gint tmp_x, tmp_y;
5652   GdkModifierType tmp_mask;
5653   GdkWindow *child;
5654
5655   g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
5656
5657   if (window)
5658     {
5659       display = gdk_drawable_get_display (window);
5660     }
5661   else
5662     {
5663       GdkScreen *screen = gdk_screen_get_default ();
5664
5665       display = gdk_screen_get_display (screen);
5666       window = gdk_screen_get_root_window (screen);
5667
5668       GDK_NOTE (MULTIHEAD,
5669                 g_message ("Passing NULL for window to gdk_window_get_pointer()\n"
5670                            "is not multihead safe"));
5671     }
5672
5673   child = display->pointer_hooks->window_get_pointer (display, window, &tmp_x, &tmp_y, &tmp_mask);
5674
5675   if (x)
5676     *x = tmp_x;
5677   if (y)
5678     *y = tmp_y;
5679   if (mask)
5680     *mask = tmp_mask;
5681
5682   _gdk_display_enable_motion_hints (display);
5683
5684   return child;
5685 }
5686
5687 /**
5688  * gdk_window_at_pointer:
5689  * @win_x: return location for origin of the window under the pointer
5690  * @win_y: return location for origin of the window under the pointer
5691  *
5692  * Obtains the window underneath the mouse pointer, returning the
5693  * location of that window in @win_x, @win_y. Returns %NULL if the
5694  * window under the mouse pointer is not known to GDK (if the window
5695  * belongs to another application and a #GdkWindow hasn't been created
5696  * for it with gdk_window_foreign_new())
5697  *
5698  * NOTE: For multihead-aware widgets or applications use
5699  * gdk_display_get_window_at_pointer() instead.
5700  *
5701  * Return value: window under the mouse pointer
5702  **/
5703 GdkWindow*
5704 gdk_window_at_pointer (gint *win_x,
5705                        gint *win_y)
5706 {
5707   return gdk_display_get_window_at_pointer (gdk_display_get_default (), win_x, win_y);
5708 }
5709
5710 /**
5711  * gdk_get_default_root_window:
5712  *
5713  * Obtains the root window (parent all other windows are inside)
5714  * for the default display and screen.
5715  *
5716  * Return value: the default root window
5717  **/
5718 GdkWindow *
5719 gdk_get_default_root_window (void)
5720 {
5721   return gdk_screen_get_root_window (gdk_screen_get_default ());
5722 }
5723
5724 /**
5725  * gdk_window_foreign_new:
5726  * @anid: a native window handle.
5727  *
5728  * Wraps a native window for the default display in a #GdkWindow.
5729  * This may fail if the window has been destroyed.
5730  *
5731  * For example in the X backend, a native window handle is an Xlib
5732  * <type>XID</type>.
5733  *
5734  * Return value: the newly-created #GdkWindow wrapper for the
5735  *    native window or %NULL if the window has been destroyed.
5736  **/
5737 GdkWindow *
5738 gdk_window_foreign_new (GdkNativeWindow anid)
5739 {
5740   return gdk_window_foreign_new_for_display (gdk_display_get_default (), anid);
5741 }
5742
5743 static void
5744 get_all_native_children (GdkWindowObject *private,
5745                          GList **native)
5746 {
5747   GdkWindowObject *child;
5748   GList *l;
5749
5750   for (l = private->children; l != NULL; l = l->next)
5751     {
5752       child = l->data;
5753
5754       if (gdk_window_has_impl (child))
5755         *native = g_list_prepend (*native, child);
5756       else
5757         get_all_native_children (child, native);
5758     }
5759 }
5760
5761
5762 static inline void
5763 gdk_window_raise_internal (GdkWindow *window)
5764 {
5765   GdkWindowObject *private = (GdkWindowObject *)window;
5766   GdkWindowObject *parent = private->parent;
5767   GdkWindowObject *above;
5768   GList *native_children;
5769   GList *l, listhead;
5770
5771   if (parent)
5772     {
5773       parent->children = g_list_remove (parent->children, window);
5774       parent->children = g_list_prepend (parent->children, window);
5775     }
5776
5777   /* Just do native raise for toplevels */
5778   if (private->parent == NULL ||
5779       private->parent->window_type == GDK_WINDOW_ROOT)
5780     {
5781       GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
5782     }
5783   else if (gdk_window_has_impl (private))
5784     {
5785       above = find_native_sibling_above (parent, private);
5786       if (above)
5787         {
5788           listhead.data = window;
5789           listhead.next = NULL;
5790           listhead.prev = NULL;
5791           GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
5792                                                                     &listhead);
5793         }
5794       else
5795         GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
5796     }
5797   else
5798     {
5799       native_children = NULL;
5800       get_all_native_children (private, &native_children);
5801       if (native_children != NULL)
5802         {
5803           above = find_native_sibling_above (parent, private);
5804
5805           if (above)
5806             GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
5807                                                                       native_children);
5808           else
5809             {
5810               /* Right order, since native_children is bottom-topmost first */
5811               for (l = native_children; l != NULL; l = l->next)
5812                 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (l->data);
5813             }
5814
5815           g_list_free (native_children);
5816         }
5817
5818     }
5819 }
5820
5821 /* Showing a non-native parent may cause children to become visible,
5822    we need to handle this by manually showing them then. To simplify
5823    things we hide them all when they are not visible. */
5824 static void
5825 show_all_visible_impls (GdkWindowObject *private, gboolean already_mapped)
5826 {
5827   GdkWindowObject *child;
5828   GList *l;
5829
5830   for (l = private->children; l != NULL; l = l->next)
5831     {
5832       child = l->data;
5833
5834       /* For foreign windows, only show if if was
5835          explicitly hidden, otherwise we might cause
5836          suprising things to happen to the other client. */
5837       if (GDK_WINDOW_IS_MAPPED (child) &&
5838           child->window_type != GDK_WINDOW_FOREIGN)
5839         show_all_visible_impls (child, FALSE);
5840     }
5841
5842   if (gdk_window_has_impl (private))
5843     GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show ((GdkWindow *)private, already_mapped);
5844 }
5845
5846 static void
5847 set_viewable (GdkWindowObject *w,
5848               gboolean val)
5849 {
5850   GdkWindowObject *child;
5851   GList *l;
5852
5853   w->viewable = val;
5854
5855   if (val)
5856     recompute_visible_regions (w, FALSE, FALSE);
5857
5858   for (l = w->children; l != NULL; l = l->next)
5859     {
5860       child = l->data;
5861
5862       if (GDK_WINDOW_IS_MAPPED (child) &&
5863           child->window_type != GDK_WINDOW_FOREIGN)
5864         set_viewable (child, val);
5865     }
5866 }
5867
5868 void
5869 _gdk_window_update_viewable (GdkWindow *window)
5870 {
5871   GdkWindowObject *priv = (GdkWindowObject *)window;
5872   gboolean viewable;
5873
5874   if (priv->window_type == GDK_WINDOW_FOREIGN ||
5875       priv->window_type == GDK_WINDOW_ROOT)
5876     viewable = TRUE;
5877   else if (priv->parent == NULL ||
5878            priv->parent->window_type == GDK_WINDOW_ROOT ||
5879            priv->parent->viewable)
5880     viewable = GDK_WINDOW_IS_MAPPED (priv);
5881   else
5882     viewable = FALSE;
5883
5884   if (priv->viewable != viewable)
5885     set_viewable (priv, viewable);
5886 }
5887
5888 static void
5889 gdk_window_show_internal (GdkWindow *window, gboolean raise)
5890 {
5891   GdkWindowObject *private;
5892   gboolean was_mapped;
5893
5894   g_return_if_fail (GDK_IS_WINDOW (window));
5895
5896   private = (GdkWindowObject *) window;
5897   if (private->destroyed)
5898     return;
5899
5900   was_mapped = GDK_WINDOW_IS_MAPPED (window);
5901
5902   if (raise)
5903     /* Keep children in (reverse) stacking order */
5904     gdk_window_raise_internal (window);
5905
5906   if (gdk_window_has_impl (private))
5907     {
5908       if (!was_mapped)
5909         gdk_synthesize_window_state (window,
5910                                      GDK_WINDOW_STATE_WITHDRAWN,
5911                                      0);
5912     }
5913   else
5914     {
5915       private->state = 0;
5916     }
5917
5918   _gdk_window_update_viewable (window);
5919
5920   if (gdk_window_is_viewable (window))
5921     show_all_visible_impls (private, was_mapped);
5922
5923   if (!was_mapped && !gdk_window_has_impl (private))
5924     {
5925       if (private->event_mask & GDK_STRUCTURE_MASK)
5926         _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
5927
5928       if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
5929         _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
5930     }
5931
5932   if (!was_mapped || raise)
5933     {
5934       recompute_visible_regions (private, TRUE, FALSE);
5935
5936       /* If any decendants became visible we need to send visibility notify */
5937       gdk_window_update_visibility_recursively (private, NULL);
5938
5939       if (gdk_window_is_viewable (window))
5940         {
5941           _gdk_synthesize_crossing_events_for_geometry_change (window);
5942           gdk_window_invalidate_rect (window, NULL, TRUE);
5943         }
5944     }
5945 }
5946
5947 /**
5948  * gdk_window_show_unraised:
5949  * @window: a #GdkWindow
5950  *
5951  * Shows a #GdkWindow onscreen, but does not modify its stacking
5952  * order. In contrast, gdk_window_show() will raise the window
5953  * to the top of the window stack.
5954  *
5955  * On the X11 platform, in Xlib terms, this function calls
5956  * XMapWindow() (it also updates some internal GDK state, which means
5957  * that you can't really use XMapWindow() directly on a GDK window).
5958  */
5959 void
5960 gdk_window_show_unraised (GdkWindow *window)
5961 {
5962   gdk_window_show_internal (window, FALSE);
5963 }
5964
5965 /**
5966  * gdk_window_raise:
5967  * @window: a #GdkWindow
5968  *
5969  * Raises @window to the top of the Z-order (stacking order), so that
5970  * other windows with the same parent window appear below @window.
5971  * This is true whether or not the windows are visible.
5972  *
5973  * If @window is a toplevel, the window manager may choose to deny the
5974  * request to move the window in the Z-order, gdk_window_raise() only
5975  * requests the restack, does not guarantee it.
5976  */
5977 void
5978 gdk_window_raise (GdkWindow *window)
5979 {
5980   GdkWindowObject *private;
5981
5982   g_return_if_fail (GDK_IS_WINDOW (window));
5983
5984   private = (GdkWindowObject *) window;
5985   if (private->destroyed)
5986     return;
5987
5988   /* Keep children in (reverse) stacking order */
5989   gdk_window_raise_internal (window);
5990
5991   recompute_visible_regions (private, TRUE, FALSE);
5992
5993   gdk_window_invalidate_rect (window, NULL, TRUE);
5994 }
5995
5996 static void
5997 gdk_window_lower_internal (GdkWindow *window)
5998 {
5999   GdkWindowObject *private = (GdkWindowObject *)window;
6000   GdkWindowObject *parent = private->parent;
6001   GdkWindowObject *above;
6002   GList *native_children;
6003   GList *l, listhead;
6004
6005   if (parent)
6006     {
6007       parent->children = g_list_remove (parent->children, window);
6008       parent->children = g_list_append (parent->children, window);
6009     }
6010
6011   /* Just do native lower for toplevels */
6012   if (private->parent == NULL ||
6013       private->parent->window_type == GDK_WINDOW_ROOT)
6014     {
6015       GDK_WINDOW_IMPL_GET_IFACE (private->impl)->lower (window);
6016     }
6017   else if (gdk_window_has_impl (private))
6018     {
6019       above = find_native_sibling_above (parent, private);
6020       if (above)
6021         {
6022           listhead.data = window;
6023           listhead.next = NULL;
6024           listhead.prev = NULL;
6025           GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
6026                                                                     &listhead);
6027         }
6028       else
6029         GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
6030     }
6031   else
6032     {
6033       native_children = NULL;
6034       get_all_native_children (private, &native_children);
6035       if (native_children != NULL)
6036         {
6037           above = find_native_sibling_above (parent, private);
6038
6039           if (above)
6040             GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
6041                                                                       native_children);
6042           else
6043             {
6044               /* Right order, since native_children is bottom-topmost first */
6045               for (l = native_children; l != NULL; l = l->next)
6046                 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (l->data);
6047             }
6048
6049           g_list_free (native_children);
6050         }
6051
6052     }
6053 }
6054
6055 static void
6056 gdk_window_invalidate_in_parent (GdkWindowObject *private)
6057 {
6058   GdkRectangle r, child;
6059
6060   if (private->parent == NULL ||
6061       private->parent->window_type == GDK_WINDOW_ROOT)
6062     return;
6063
6064   /* get the visible rectangle of the parent */
6065   r.x = r.y = 0;
6066   r.width = private->parent->width;
6067   r.height = private->parent->height;
6068
6069   child.x = private->x;
6070   child.y = private->y;
6071   child.width = private->width;
6072   child.height = private->height;
6073   gdk_rectangle_intersect (&r, &child, &r);
6074
6075   gdk_window_invalidate_rect (GDK_WINDOW (private->parent), &r, TRUE);
6076 }
6077
6078
6079 /**
6080  * gdk_window_lower:
6081  * @window: a #GdkWindow
6082  *
6083  * Lowers @window to the bottom of the Z-order (stacking order), so that
6084  * other windows with the same parent window appear above @window.
6085  * This is true whether or not the other windows are visible.
6086  *
6087  * If @window is a toplevel, the window manager may choose to deny the
6088  * request to move the window in the Z-order, gdk_window_lower() only
6089  * requests the restack, does not guarantee it.
6090  *
6091  * Note that gdk_window_show() raises the window again, so don't call this
6092  * function before gdk_window_show(). (Try gdk_window_show_unraised().)
6093  */
6094 void
6095 gdk_window_lower (GdkWindow *window)
6096 {
6097   GdkWindowObject *private;
6098
6099   g_return_if_fail (GDK_IS_WINDOW (window));
6100
6101   private = (GdkWindowObject *) window;
6102   if (private->destroyed)
6103     return;
6104
6105   /* Keep children in (reverse) stacking order */
6106   gdk_window_lower_internal (window);
6107
6108   recompute_visible_regions (private, TRUE, FALSE);
6109
6110   _gdk_synthesize_crossing_events_for_geometry_change (window);
6111   gdk_window_invalidate_in_parent (private);
6112 }
6113
6114 /**
6115  * gdk_window_show:
6116  * @window: a #GdkWindow
6117  *
6118  * Like gdk_window_show_unraised(), but also raises the window to the
6119  * top of the window stack (moves the window to the front of the
6120  * Z-order).
6121  *
6122  * This function maps a window so it's visible onscreen. Its opposite
6123  * is gdk_window_hide().
6124  *
6125  * When implementing a #GtkWidget, you should call this function on the widget's
6126  * #GdkWindow as part of the "map" method.
6127  */
6128 void
6129 gdk_window_show (GdkWindow *window)
6130 {
6131   gdk_window_show_internal (window, TRUE);
6132 }
6133
6134 /* Hiding a non-native parent may cause parents to become non-visible,
6135    even if their parent native window is visible. We need to handle this
6136    by manually hiding them then. To simplify things we hide them all
6137    when they are not visible. */
6138 static void
6139 hide_all_visible_impls (GdkWindowObject *private)
6140 {
6141   GdkWindowObject *child;
6142   GList *l;
6143
6144   for (l = private->children; l != NULL; l = l->next)
6145     {
6146       child = l->data;
6147
6148       /* For foreign windows, only hide if if was
6149          explicitly hidden, otherwise we might cause
6150          suprising things to happen to the other client. */
6151       if (GDK_WINDOW_IS_MAPPED (child) &&
6152           child->window_type != GDK_WINDOW_FOREIGN)
6153         hide_all_visible_impls (child);
6154     }
6155
6156   if (gdk_window_has_impl (private))
6157     GDK_WINDOW_IMPL_GET_IFACE (private->impl)->hide ((GdkWindow *)private);
6158 }
6159
6160
6161 /**
6162  * gdk_window_hide:
6163  * @window: a #GdkWindow
6164  *
6165  * For toplevel windows, withdraws them, so they will no longer be
6166  * known to the window manager; for all windows, unmaps them, so
6167  * they won't be displayed. Normally done automatically as
6168  * part of gtk_widget_hide().
6169  */
6170 void
6171 gdk_window_hide (GdkWindow *window)
6172 {
6173   GdkWindowObject *private;
6174   gboolean was_mapped, was_viewable;
6175
6176   g_return_if_fail (GDK_IS_WINDOW (window));
6177
6178   private = (GdkWindowObject *) window;
6179   if (private->destroyed)
6180     return;
6181
6182   was_mapped = GDK_WINDOW_IS_MAPPED (private);
6183   was_viewable = gdk_window_is_viewable (window);
6184
6185   if (gdk_window_has_impl (private))
6186     {
6187
6188       if (GDK_WINDOW_IS_MAPPED (window))
6189         gdk_synthesize_window_state (window,
6190                                      0,
6191                                      GDK_WINDOW_STATE_WITHDRAWN);
6192     }
6193   else if (was_mapped)
6194     {
6195       GdkDisplay *display;
6196
6197       /* May need to break grabs on children */
6198       display = gdk_drawable_get_display (window);
6199
6200       if (_gdk_display_end_pointer_grab (display,
6201                                          _gdk_windowing_window_get_next_serial (display),
6202                                          window,
6203                                          TRUE))
6204         gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
6205
6206       if (display->keyboard_grab.window != NULL)
6207         {
6208           if (is_parent_of (window, display->keyboard_grab.window))
6209             {
6210               /* Call this ourselves, even though gdk_display_keyboard_ungrab
6211                  does so too, since we want to pass implicit == TRUE so the
6212                  broken grab event is generated */
6213               _gdk_display_unset_has_keyboard_grab (display,
6214                                                     TRUE);
6215               gdk_display_keyboard_ungrab (display, GDK_CURRENT_TIME);
6216             }
6217         }
6218
6219       private->state = GDK_WINDOW_STATE_WITHDRAWN;
6220     }
6221
6222   _gdk_window_update_viewable (window);
6223
6224   if (was_viewable)
6225     hide_all_visible_impls (private);
6226
6227   recompute_visible_regions (private, TRUE, FALSE);
6228
6229   /* all decendants became non-visible, we need to send visibility notify */
6230   gdk_window_update_visibility_recursively (private, NULL);
6231
6232   if (was_mapped && !gdk_window_has_impl (private))
6233     {
6234       if (private->event_mask & GDK_STRUCTURE_MASK)
6235         _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6236
6237       if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
6238         _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6239
6240       _gdk_synthesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
6241     }
6242
6243   /* Invalidate the rect */
6244   gdk_window_invalidate_in_parent (private);
6245 }
6246
6247 /**
6248  * gdk_window_withdraw:
6249  * @window: a toplevel #GdkWindow
6250  *
6251  * Withdraws a window (unmaps it and asks the window manager to forget about it).
6252  * This function is not really useful as gdk_window_hide() automatically
6253  * withdraws toplevel windows before hiding them.
6254  **/
6255 void
6256 gdk_window_withdraw (GdkWindow *window)
6257 {
6258   GdkWindowObject *private;
6259   gboolean was_mapped;
6260
6261   g_return_if_fail (GDK_IS_WINDOW (window));
6262
6263   private = (GdkWindowObject *) window;
6264   if (private->destroyed)
6265     return;
6266
6267   was_mapped = GDK_WINDOW_IS_MAPPED (private);
6268
6269   if (gdk_window_has_impl (private))
6270     {
6271       GDK_WINDOW_IMPL_GET_IFACE (private->impl)->withdraw (window);
6272
6273       if (was_mapped)
6274         {
6275           if (private->event_mask & GDK_STRUCTURE_MASK)
6276             _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6277
6278           if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
6279             _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6280
6281           _gdk_synthesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
6282         }
6283
6284       recompute_visible_regions (private, TRUE, FALSE);
6285     }
6286 }
6287
6288 /**
6289  * gdk_window_set_events:
6290  * @window: a #GdkWindow
6291  * @event_mask: event mask for @window
6292  *
6293  * The event mask for a window determines which events will be reported
6294  * for that window. For example, an event mask including #GDK_BUTTON_PRESS_MASK
6295  * means the window should report button press events. The event mask
6296  * is the bitwise OR of values from the #GdkEventMask enumeration.
6297  **/
6298 void
6299 gdk_window_set_events (GdkWindow       *window,
6300                        GdkEventMask     event_mask)
6301 {
6302   GdkWindowObject *private;
6303   GdkDisplay *display;
6304
6305
6306   g_return_if_fail (GDK_IS_WINDOW (window));
6307
6308   private = (GdkWindowObject *) window;
6309   if (private->destroyed)
6310     return;
6311
6312   /* If motion hint is disabled, enable motion events again */
6313   display = gdk_drawable_get_display (window);
6314   if ((private->event_mask & GDK_POINTER_MOTION_HINT_MASK) &&
6315       !(event_mask & GDK_POINTER_MOTION_HINT_MASK))
6316     _gdk_display_enable_motion_hints (display);
6317
6318   private->event_mask = event_mask;
6319
6320   if (gdk_window_has_impl (private))
6321     GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_events (window,
6322                                                            get_native_event_mask (private));
6323
6324 }
6325
6326 /**
6327  * gdk_window_get_events:
6328  * @window: a #GdkWindow
6329  *
6330  * Gets the event mask for @window. See gdk_window_set_events().
6331  *
6332  * Return value: event mask for @window
6333  **/
6334 GdkEventMask
6335 gdk_window_get_events (GdkWindow *window)
6336 {
6337   GdkWindowObject *private;
6338
6339   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
6340
6341   private = (GdkWindowObject *) window;
6342   if (private->destroyed)
6343     return 0;
6344
6345   return private->event_mask;
6346 }
6347
6348 static void
6349 gdk_window_move_resize_toplevel (GdkWindow *window,
6350                                  gboolean   with_move,
6351                                  gint       x,
6352                                  gint       y,
6353                                  gint       width,
6354                                  gint       height)
6355 {
6356   GdkWindowObject *private;
6357   GdkRegion *old_region, *new_region;
6358   GdkWindowObject *impl_window;
6359   gboolean expose;
6360   int old_x, old_y, old_abs_x, old_abs_y;
6361   int dx, dy;
6362   gboolean is_resize;
6363
6364   private = (GdkWindowObject *) window;
6365
6366   expose = FALSE;
6367   old_region = NULL;
6368
6369   impl_window = gdk_window_get_impl_window (private);
6370
6371   old_x = private->x;
6372   old_y = private->y;
6373
6374   is_resize = (width != -1) || (height != -1);
6375
6376   if (gdk_window_is_viewable (window) &&
6377       !private->input_only)
6378     {
6379       expose = TRUE;
6380       old_region = gdk_region_copy (private->clip_region);
6381     }
6382
6383   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, with_move, x, y, width, height);
6384
6385   dx = private->x - old_x;
6386   dy = private->y - old_y;
6387
6388   old_abs_x = private->abs_x;
6389   old_abs_y = private->abs_y;
6390
6391   /* Avoid recomputing for pure toplevel moves, for performance reasons */
6392   if (is_resize)
6393     recompute_visible_regions (private, TRUE, FALSE);
6394
6395   if (expose)
6396     {
6397       new_region = gdk_region_copy (private->clip_region);
6398
6399       /* This is the newly exposed area (due to any resize),
6400        * X will expose it, but lets do that without the
6401        * roundtrip
6402        */
6403       gdk_region_subtract (new_region, old_region);
6404       gdk_window_invalidate_region (window, new_region, TRUE);
6405
6406       gdk_region_destroy (old_region);
6407       gdk_region_destroy (new_region);
6408     }
6409
6410   _gdk_synthesize_crossing_events_for_geometry_change (window);
6411 }
6412
6413
6414 static void
6415 move_native_children (GdkWindowObject *private)
6416 {
6417   GList *l;
6418   GdkWindowObject *child;
6419
6420   for (l = private->children; l; l = l->next)
6421     {
6422       child = l->data;
6423
6424       if (child->impl != private->impl)
6425         GDK_WINDOW_IMPL_GET_IFACE (child->impl)->move_resize ((GdkWindow *)child, TRUE, child->x, child->y, child->width, child->height);
6426       else
6427         move_native_children  (child);
6428     }
6429 }
6430
6431 static gboolean
6432 collect_native_child_region_helper (GdkWindowObject *window,
6433                                     GdkWindow *impl,
6434                                     GdkRegion **region,
6435                                     int x_offset,
6436                                     int y_offset)
6437 {
6438   GdkWindowObject *child;
6439   GdkRegion *tmp;
6440   GList *l;
6441
6442   for (l = window->children; l != NULL; l = l->next)
6443     {
6444       child = l->data;
6445
6446       if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only)
6447         continue;
6448
6449       if (child->impl != impl)
6450         {
6451           tmp = gdk_region_copy (child->clip_region);
6452           gdk_region_offset (tmp,
6453                              x_offset + child->x,
6454                              y_offset + child->y);
6455           if (*region == NULL)
6456             *region = tmp;
6457           else
6458             {
6459               gdk_region_union (*region, tmp);
6460               gdk_region_destroy (tmp);
6461             }
6462         }
6463       else
6464         collect_native_child_region_helper (child, impl, region,
6465                                             x_offset + child->x,
6466                                             y_offset + child->y);
6467     }
6468
6469   return FALSE;
6470 }
6471
6472 static GdkRegion *
6473 collect_native_child_region (GdkWindowObject *window,
6474                              gboolean include_this)
6475 {
6476   GdkRegion *region;
6477
6478   if (include_this && gdk_window_has_impl (window) && window->viewable)
6479     return gdk_region_copy (window->clip_region);
6480
6481   region = NULL;
6482
6483   collect_native_child_region_helper (window, window->impl, &region, 0, 0);
6484
6485   return region;
6486 }
6487
6488
6489 static void
6490 gdk_window_move_resize_internal (GdkWindow *window,
6491                                  gboolean   with_move,
6492                                  gint       x,
6493                                  gint       y,
6494                                  gint       width,
6495                                  gint       height)
6496 {
6497   GdkWindowObject *private;
6498   GdkRegion *old_region, *new_region, *copy_area;
6499   GdkRegion *old_native_child_region, *new_native_child_region;
6500   GdkWindowObject *impl_window;
6501   gboolean expose;
6502   int old_x, old_y, old_abs_x, old_abs_y;
6503   int dx, dy;
6504
6505   g_return_if_fail (GDK_IS_WINDOW (window));
6506
6507   private = (GdkWindowObject *) window;
6508   if (private->destroyed)
6509     return;
6510
6511   if (private->parent == NULL ||
6512       private->parent->window_type == GDK_WINDOW_ROOT)
6513     {
6514       gdk_window_move_resize_toplevel (window, with_move, x, y, width, height);
6515       return;
6516     }
6517
6518   /* Handle child windows */
6519
6520   expose = FALSE;
6521   old_region = NULL;
6522
6523   impl_window = gdk_window_get_impl_window (private);
6524
6525   old_x = private->x;
6526   old_y = private->y;
6527
6528   old_native_child_region = NULL;
6529   if (gdk_window_is_viewable (window) &&
6530       !private->input_only)
6531     {
6532       expose = TRUE;
6533
6534       old_region = gdk_region_copy (private->clip_region);
6535       /* Adjust region to parent window coords */
6536       gdk_region_offset (old_region, private->x, private->y);
6537
6538       old_native_child_region = collect_native_child_region (private, TRUE);
6539       if (old_native_child_region)
6540         {
6541           /* Adjust region to parent window coords */
6542           gdk_region_offset (old_native_child_region, private->x, private->y);
6543
6544           /* Any native window move will immediately copy stuff to the destination, which may overwrite a
6545            * source or destination for a delayed GdkWindowRegionMove. So, we need
6546            * to flush those here for the parent window and all overlapped subwindows
6547            * of it. And we need to do this before setting the new clips as those will be
6548            * affecting this.
6549            */
6550           gdk_window_flush_recursive (private->parent);
6551         }
6552     }
6553
6554   /* Set the new position and size */
6555   if (with_move)
6556     {
6557       private->x = x;
6558       private->y = y;
6559     }
6560   if (!(width < 0 && height < 0))
6561     {
6562       if (width < 1)
6563         width = 1;
6564       private->width = width;
6565       if (height < 1)
6566         height = 1;
6567       private->height = height;
6568     }
6569
6570   dx = private->x - old_x;
6571   dy = private->y - old_y;
6572
6573   old_abs_x = private->abs_x;
6574   old_abs_y = private->abs_y;
6575
6576   recompute_visible_regions (private, TRUE, FALSE);
6577
6578   new_native_child_region = NULL;
6579   if (old_native_child_region)
6580     {
6581       new_native_child_region = collect_native_child_region (private, TRUE);
6582       /* Adjust region to parent window coords */
6583       gdk_region_offset (new_native_child_region, private->x, private->y);
6584     }
6585
6586   if (gdk_window_has_impl (private))
6587     {
6588       /* Do the actual move after recomputing things, as this will have set the shape to
6589          the now correct one, thus avoiding copying regions that should not be copied. */
6590       GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, TRUE, private->x, private->y, private->width, private->height);
6591     }
6592   else if (old_abs_x != private->abs_x ||
6593            old_abs_y != private->abs_y)
6594     move_native_children (private);
6595
6596   if (expose)
6597     {
6598       new_region = gdk_region_copy (private->clip_region);
6599       /* Adjust region to parent window coords */
6600       gdk_region_offset (new_region, private->x, private->y);
6601
6602       /* copy_area:
6603        * Part of the data at the new location can be copied from the
6604        * old location, this area is the intersection of the old region
6605        * moved as the copy will move it and then intersected with
6606        * the new region.
6607        *
6608        * new_region:
6609        * Everything in the old and new regions that is not copied must be
6610        * invalidated (including children) as this is newly exposed
6611        */
6612       copy_area = gdk_region_copy (new_region);
6613
6614       gdk_region_union (new_region, old_region);
6615
6616       if (old_native_child_region)
6617         {
6618           /* Don't copy from inside native children, as this is copied by
6619            * the native window move.
6620            */
6621           gdk_region_subtract (old_region, old_native_child_region);
6622         }
6623       gdk_region_offset (old_region, dx, dy);
6624
6625       gdk_region_intersect (copy_area, old_region);
6626
6627       if (new_native_child_region)
6628         {
6629           /* Don't copy any bits that would cause a read from the moved
6630              native windows, as we can't read that data */
6631           gdk_region_offset (new_native_child_region, dx, dy);
6632           gdk_region_subtract (copy_area, new_native_child_region);
6633         }
6634
6635       gdk_region_subtract (new_region, copy_area);
6636
6637       /* Convert old region to impl coords */
6638       gdk_region_offset (old_region, -dx + private->abs_x - private->x, -dy + private->abs_y - private->y);
6639
6640       /* convert from parent coords to impl */
6641       gdk_region_offset (copy_area, private->abs_x - private->x, private->abs_y - private->y);
6642
6643       move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
6644
6645       /* Invalidate affected part in the parent window
6646        *  (no higher window should be affected)
6647        * We also invalidate any children in that area, which could include
6648        * this window if it still overlaps that area.
6649        */
6650       gdk_window_invalidate_region (GDK_WINDOW (private->parent), new_region, TRUE);
6651
6652       gdk_region_destroy (old_region);
6653       gdk_region_destroy (new_region);
6654     }
6655
6656   if (old_native_child_region)
6657     {
6658       gdk_region_destroy (old_native_child_region);
6659       gdk_region_destroy (new_native_child_region);
6660     }
6661
6662   _gdk_synthesize_crossing_events_for_geometry_change (window);
6663 }
6664
6665
6666
6667 /**
6668  * gdk_window_move:
6669  * @window: a #GdkWindow
6670  * @x: X coordinate relative to window's parent
6671  * @y: Y coordinate relative to window's parent
6672  *
6673  * Repositions a window relative to its parent window.
6674  * For toplevel windows, window managers may ignore or modify the move;
6675  * you should probably use gtk_window_move() on a #GtkWindow widget
6676  * anyway, instead of using GDK functions. For child windows,
6677  * the move will reliably succeed.
6678  *
6679  * If you're also planning to resize the window, use gdk_window_move_resize()
6680  * to both move and resize simultaneously, for a nicer visual effect.
6681  **/
6682 void
6683 gdk_window_move (GdkWindow *window,
6684                  gint       x,
6685                  gint       y)
6686 {
6687   gdk_window_move_resize_internal (window, TRUE, x, y, -1, -1);
6688 }
6689
6690 /**
6691  * gdk_window_resize:
6692  * @window: a #GdkWindow
6693  * @width: new width of the window
6694  * @height: new height of the window
6695  *
6696  * Resizes @window; for toplevel windows, asks the window manager to resize
6697  * the window. The window manager may not allow the resize. When using GTK+,
6698  * use gtk_window_resize() instead of this low-level GDK function.
6699  *
6700  * Windows may not be resized below 1x1.
6701  *
6702  * If you're also planning to move the window, use gdk_window_move_resize()
6703  * to both move and resize simultaneously, for a nicer visual effect.
6704  **/
6705 void
6706 gdk_window_resize (GdkWindow *window,
6707                    gint       width,
6708                    gint       height)
6709 {
6710   gdk_window_move_resize_internal (window, FALSE, 0, 0, width, height);
6711 }
6712
6713
6714 /**
6715  * gdk_window_move_resize:
6716  * @window: a #GdkWindow
6717  * @x: new X position relative to window's parent
6718  * @y: new Y position relative to window's parent
6719  * @width: new width
6720  * @height: new height
6721  *
6722  * Equivalent to calling gdk_window_move() and gdk_window_resize(),
6723  * except that both operations are performed at once, avoiding strange
6724  * visual effects. (i.e. the user may be able to see the window first
6725  * move, then resize, if you don't use gdk_window_move_resize().)
6726  **/
6727 void
6728 gdk_window_move_resize (GdkWindow *window,
6729                         gint       x,
6730                         gint       y,
6731                         gint       width,
6732                         gint       height)
6733 {
6734   gdk_window_move_resize_internal (window, TRUE, x, y, width, height);
6735 }
6736
6737
6738 /**
6739  * gdk_window_scroll:
6740  * @window: a #GdkWindow
6741  * @dx: Amount to scroll in the X direction
6742  * @dy: Amount to scroll in the Y direction
6743  *
6744  * Scroll the contents of @window, both pixels and children, by the
6745  * given amount. @window itself does not move. Portions of the window
6746  * that the scroll operation brings in from offscreen areas are
6747  * invalidated. The invalidated region may be bigger than what would
6748  * strictly be necessary.
6749  *
6750  * For X11, a minimum area will be invalidated if the window has no
6751  * subwindows, or if the edges of the window's parent do not extend
6752  * beyond the edges of the window. In other cases, a multi-step process
6753  * is used to scroll the window which may produce temporary visual
6754  * artifacts and unnecessary invalidations.
6755  **/
6756 void
6757 gdk_window_scroll (GdkWindow *window,
6758                    gint       dx,
6759                    gint       dy)
6760 {
6761   GdkWindowObject *private = (GdkWindowObject *) window;
6762   GdkWindowObject *impl_window;
6763   GdkRegion *copy_area, *noncopy_area;
6764   GdkRegion *old_native_child_region, *new_native_child_region;
6765   GList *tmp_list;
6766
6767   g_return_if_fail (GDK_IS_WINDOW (window));
6768
6769   if (dx == 0 && dy == 0)
6770     return;
6771
6772   if (private->destroyed)
6773     return;
6774
6775   old_native_child_region = collect_native_child_region (private, FALSE);
6776   if (old_native_child_region)
6777     {
6778       /* Any native window move will immediately copy stuff to the destination, which may overwrite a
6779        * source or destination for a delayed GdkWindowRegionMove. So, we need
6780        * to flush those here for the window and all overlapped subwindows
6781        * of it. And we need to do this before setting the new clips as those will be
6782        * affecting this.
6783        */
6784       gdk_window_flush_recursive (private);
6785     }
6786
6787
6788   /* First move all child windows, without causing invalidation */
6789
6790   tmp_list = private->children;
6791   while (tmp_list)
6792     {
6793       GdkWindow *child = GDK_WINDOW (tmp_list->data);
6794       GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
6795
6796       /* Just update the positions, the bits will move with the copy */
6797       child_obj->x += dx;
6798       child_obj->y += dy;
6799
6800       tmp_list = tmp_list->next;
6801     }
6802
6803   recompute_visible_regions (private, FALSE, TRUE);
6804
6805   new_native_child_region = NULL;
6806   if (old_native_child_region)
6807     new_native_child_region = collect_native_child_region (private, FALSE);
6808
6809   move_native_children (private);
6810
6811   /* Then copy the actual bits of the window w/ child windows */
6812
6813   impl_window = gdk_window_get_impl_window (private);
6814
6815   /* Calculate the area that can be gotten by copying the old area */
6816   copy_area = gdk_region_copy (private->clip_region);
6817   if (old_native_child_region)
6818     {
6819       /* Don't copy from inside native children, as this is copied by
6820        * the native window move.
6821        */
6822       gdk_region_subtract (copy_area, old_native_child_region);
6823
6824       /* Don't copy any bits that would cause a read from the moved
6825          native windows, as we can't read that data */
6826       gdk_region_subtract (copy_area, new_native_child_region);
6827     }
6828   gdk_region_offset (copy_area, dx, dy);
6829   gdk_region_intersect (copy_area, private->clip_region);
6830
6831   /* And the rest need to be invalidated */
6832   noncopy_area = gdk_region_copy (private->clip_region);
6833   gdk_region_subtract (noncopy_area, copy_area);
6834
6835   /* convert from window coords to impl */
6836   gdk_region_offset (copy_area, private->abs_x, private->abs_y);
6837
6838   move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
6839
6840   /* Invalidate not copied regions */
6841   gdk_window_invalidate_region (window, noncopy_area, TRUE);
6842
6843   gdk_region_destroy (noncopy_area);
6844
6845   if (old_native_child_region)
6846     {
6847       gdk_region_destroy (old_native_child_region);
6848       gdk_region_destroy (new_native_child_region);
6849     }
6850
6851   _gdk_synthesize_crossing_events_for_geometry_change (window);
6852 }
6853
6854 /**
6855  * gdk_window_move_region:
6856  * @window: a #GdkWindow
6857  * @region: The #GdkRegion to move
6858  * @dx: Amount to move in the X direction
6859  * @dy: Amount to move in the Y direction
6860  *
6861  * Move the part of @window indicated by @region by @dy pixels in the Y
6862  * direction and @dx pixels in the X direction. The portions of @region
6863  * that not covered by the new position of @region are invalidated.
6864  *
6865  * Child windows are not moved.
6866  *
6867  * Since: 2.8
6868  */
6869 void
6870 gdk_window_move_region (GdkWindow       *window,
6871                         const GdkRegion *region,
6872                         gint             dx,
6873                         gint             dy)
6874 {
6875   GdkWindowObject *private = (GdkWindowObject *) window;
6876   GdkWindowObject *impl_window;
6877   GdkRegion *nocopy_area;
6878   GdkRegion *copy_area;
6879
6880   g_return_if_fail (GDK_IS_WINDOW (window));
6881   g_return_if_fail (region != NULL);
6882
6883   if (dx == 0 && dy == 0)
6884     return;
6885
6886   if (private->destroyed)
6887     return;
6888
6889   impl_window = gdk_window_get_impl_window (private);
6890
6891   /* compute source regions */
6892   copy_area = gdk_region_copy (region);
6893   gdk_region_intersect (copy_area, private->clip_region_with_children);
6894
6895   /* compute destination regions */
6896   gdk_region_offset (copy_area, dx, dy);
6897   gdk_region_intersect (copy_area, private->clip_region_with_children);
6898
6899   /* invalidate parts of the region not covered by the copy */
6900   nocopy_area = gdk_region_copy (region);
6901   gdk_region_offset (nocopy_area, dx, dy);
6902   gdk_region_subtract (nocopy_area, copy_area);
6903   gdk_window_invalidate_region (window, nocopy_area, FALSE);
6904   gdk_region_destroy (nocopy_area);
6905
6906   /* convert from window coords to impl */
6907   gdk_region_offset (copy_area, private->abs_x, private->abs_y);
6908
6909   move_region_on_impl (impl_window, copy_area, dx, dy); /* Takes ownership of copy_area */
6910 }
6911
6912 /**
6913  * gdk_window_set_background:
6914  * @window: a #GdkWindow
6915  * @color: an allocated #GdkColor
6916  *
6917  * Sets the background color of @window. (However, when using GTK+,
6918  * set the background of a widget with gtk_widget_modify_bg() - if
6919  * you're an application - or gtk_style_set_background() - if you're
6920  * implementing a custom widget.)
6921  *
6922  * The @color must be allocated; gdk_rgb_find_color() is the best way
6923  * to allocate a color.
6924  *
6925  * See also gdk_window_set_back_pixmap().
6926  */
6927 void
6928 gdk_window_set_background (GdkWindow      *window,
6929                            const GdkColor *color)
6930 {
6931   GdkWindowObject *private;
6932   GdkColormap *colormap = gdk_drawable_get_colormap (window);
6933
6934   g_return_if_fail (GDK_IS_WINDOW (window));
6935
6936   private = (GdkWindowObject *) window;
6937
6938   private->bg_color = *color;
6939   gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
6940
6941   if (private->bg_pixmap &&
6942       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
6943       private->bg_pixmap != GDK_NO_BG)
6944     g_object_unref (private->bg_pixmap);
6945
6946   private->bg_pixmap = NULL;
6947
6948   if (!GDK_WINDOW_DESTROYED (window) &&
6949       gdk_window_has_impl (private) &&
6950       !private->input_only)
6951     GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, &private->bg_color);
6952 }
6953
6954 /**
6955  * gdk_window_set_back_pixmap:
6956  * @window: a #GdkWindow
6957  * @pixmap: a #GdkPixmap, or %NULL
6958  * @parent_relative: whether the tiling origin is at the origin of
6959  *   @window's parent
6960  *
6961  * Sets the background pixmap of @window. May also be used to set a
6962  * background of "None" on @window, by setting a background pixmap
6963  * of %NULL.
6964  *
6965  * A background pixmap will be tiled, positioning the first tile at
6966  * the origin of @window, or if @parent_relative is %TRUE, the tiling
6967  * will be done based on the origin of the parent window (useful to
6968  * align tiles in a parent with tiles in a child).
6969  *
6970  * A background pixmap of %NULL means that the window will have no
6971  * background.  A window with no background will never have its
6972  * background filled by the windowing system, instead the window will
6973  * contain whatever pixels were already in the corresponding area of
6974  * the display.
6975  *
6976  * The windowing system will normally fill a window with its background
6977  * when the window is obscured then exposed, and when you call
6978  * gdk_window_clear().
6979  */
6980 void
6981 gdk_window_set_back_pixmap (GdkWindow *window,
6982                             GdkPixmap *pixmap,
6983                             gboolean   parent_relative)
6984 {
6985   GdkWindowObject *private;
6986
6987   g_return_if_fail (GDK_IS_WINDOW (window));
6988   g_return_if_fail (pixmap == NULL || !parent_relative);
6989   g_return_if_fail (pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap));
6990
6991   private = (GdkWindowObject *) window;
6992
6993   if (pixmap && !gdk_drawable_get_colormap (pixmap))
6994     {
6995       g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
6996       return;
6997     }
6998
6999   if (private->bg_pixmap &&
7000       private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
7001       private->bg_pixmap != GDK_NO_BG)
7002     g_object_unref (private->bg_pixmap);
7003
7004   if (parent_relative)
7005     private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
7006   else if (pixmap)
7007     private->bg_pixmap = g_object_ref (pixmap);
7008   else
7009     private->bg_pixmap = GDK_NO_BG;
7010
7011   if (!GDK_WINDOW_DESTROYED (window) &&
7012       gdk_window_has_impl (private) &&
7013       !private->input_only)
7014     GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, private->bg_pixmap);
7015 }
7016
7017 /**
7018  * gdk_window_get_cursor:
7019  * @window: a #GdkWindow
7020  * @cursor: a cursor
7021  *
7022  * Retrieves a #GdkCursor pointer for the cursor currently set on the
7023  * specified #GdkWindow, or %NULL.  If the return value is %NULL then
7024  * there is no custom cursor set on the specified window, and it is
7025  * using the cursor for its parent window.
7026  *
7027  * Return value: a #GdkCursor, or %NULL. The returned object is owned
7028  *   by the #GdkWindow and should not be unreferenced directly. Use
7029  *   gdk_window_set_cursor() to unset the cursor of the window
7030  *
7031  * Since: 2.18
7032  */
7033 GdkCursor *
7034 gdk_window_get_cursor (GdkWindow *window)
7035 {
7036   GdkWindowObject *private;
7037
7038   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
7039
7040   private = (GdkWindowObject *) window;
7041
7042   return private->cursor;
7043 }
7044
7045 /**
7046  * gdk_window_set_cursor:
7047  * @window: a #GdkWindow
7048  * @cursor: a cursor
7049  *
7050  * Sets the mouse pointer for a #GdkWindow. Use gdk_cursor_new_for_display()
7051  * or gdk_cursor_new_from_pixmap() to create the cursor. To make the cursor
7052  * invisible, use %GDK_BLANK_CURSOR. Passing %NULL for the @cursor argument
7053  * to gdk_window_set_cursor() means that @window will use the cursor of its
7054  * parent window. Most windows should use this default.
7055  */
7056 void
7057 gdk_window_set_cursor (GdkWindow *window,
7058                        GdkCursor *cursor)
7059 {
7060   GdkWindowObject *private;
7061   GdkDisplay *display;
7062
7063   g_return_if_fail (GDK_IS_WINDOW (window));
7064
7065   private = (GdkWindowObject *) window;
7066   display = gdk_drawable_get_display (window);
7067
7068   if (private->cursor)
7069     {
7070       gdk_cursor_unref (private->cursor);
7071       private->cursor = NULL;
7072     }
7073
7074   if (!GDK_WINDOW_DESTROYED (window))
7075     {
7076       if (cursor)
7077         private->cursor = gdk_cursor_ref (cursor);
7078
7079       if (_gdk_window_event_parent_of (window, display->pointer_info.window_under_pointer))
7080         update_cursor (display);
7081
7082       g_object_notify (G_OBJECT (window), "cursor");
7083     }
7084 }
7085
7086 /**
7087  * gdk_window_get_geometry:
7088  * @window: a #GdkWindow
7089  * @x: return location for X coordinate of window (relative to its parent)
7090  * @y: return location for Y coordinate of window (relative to its parent)
7091  * @width: return location for width of window
7092  * @height: return location for height of window
7093  * @depth: return location for bit depth of window
7094  *
7095  * Any of the return location arguments to this function may be %NULL,
7096  * if you aren't interested in getting the value of that field.
7097  *
7098  * The X and Y coordinates returned are relative to the parent window
7099  * of @window, which for toplevels usually means relative to the
7100  * window decorations (titlebar, etc.) rather than relative to the
7101  * root window (screen-size background window).
7102  *
7103  * On the X11 platform, the geometry is obtained from the X server,
7104  * so reflects the latest position of @window; this may be out-of-sync
7105  * with the position of @window delivered in the most-recently-processed
7106  * #GdkEventConfigure. gdk_window_get_position() in contrast gets the
7107  * position from the most recent configure event.
7108  *
7109  * <note>
7110  * If @window is not a toplevel, it is <emphasis>much</emphasis> better
7111  * to call gdk_window_get_position() and gdk_drawable_get_size() instead,
7112  * because it avoids the roundtrip to the X server and because
7113  * gdk_drawable_get_size() supports the full 32-bit coordinate space,
7114  * whereas gdk_window_get_geometry() is restricted to the 16-bit
7115  * coordinates of X11.
7116  *</note>
7117  **/
7118 void
7119 gdk_window_get_geometry (GdkWindow *window,
7120                          gint      *x,
7121                          gint      *y,
7122                          gint      *width,
7123                          gint      *height,
7124                          gint      *depth)
7125 {
7126   GdkWindowObject *private;
7127
7128   if (!window)
7129     {
7130       GDK_NOTE (MULTIHEAD,
7131                 g_message ("gdk_window_get_geometry(): Window needs "
7132                            "to be non-NULL to be multi head safe"));
7133       window = gdk_screen_get_root_window ((gdk_screen_get_default ()));
7134     }
7135
7136   g_return_if_fail (GDK_IS_WINDOW (window));
7137
7138   private = (GdkWindowObject *) window;
7139
7140   if (!GDK_WINDOW_DESTROYED (window))
7141     {
7142       if (gdk_window_has_impl (private))
7143         GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_geometry (window, x, y,
7144                                                                  width, height,
7145                                                                  depth);
7146       else
7147         {
7148           if (x)
7149             *x = private->x;
7150           if (y)
7151             *y = private->y;
7152           if (width)
7153             *width = private->width;
7154           if (height)
7155             *height = private->height;
7156           if (depth)
7157             *depth = private->depth;
7158         }
7159     }
7160 }
7161
7162 /**
7163  * gdk_window_get_origin:
7164  * @window: a #GdkWindow
7165  * @x: return location for X coordinate
7166  * @y: return location for Y coordinate
7167  *
7168  * Obtains the position of a window in root window coordinates.
7169  * (Compare with gdk_window_get_position() and
7170  * gdk_window_get_geometry() which return the position of a window
7171  * relative to its parent window.)
7172  *
7173  * Return value: not meaningful, ignore
7174  */
7175 gint
7176 gdk_window_get_origin (GdkWindow *window,
7177                        gint      *x,
7178                        gint      *y)
7179 {
7180   GdkWindowObject *private;
7181
7182   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
7183
7184   if (GDK_WINDOW_DESTROYED (window))
7185     {
7186       if (x)
7187         *x = 0;
7188       if (y)
7189         *y = 0;
7190       return 0;
7191     }
7192   
7193   private = (GdkWindowObject *) window;
7194
7195   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_root_coords (window,
7196                                                               private->abs_x,
7197                                                               private->abs_y,
7198                                                               x, y);
7199
7200   return TRUE;
7201 }
7202
7203 /**
7204  * gdk_window_get_root_coords:
7205  * @window: a #GdkWindow
7206  * @x: X coordinate in window
7207  * @y: Y coordinate in window
7208  * @root_x: return location for X coordinate
7209  * @root_y: return location for Y coordinate
7210  *
7211  * Obtains the position of a window position in root
7212  * window coordinates. This is similar to
7213  * gdk_window_get_origin() but allows you go pass
7214  * in any position in the window, not just the origin.
7215  */
7216 void
7217 gdk_window_get_root_coords (GdkWindow *window,
7218                             gint       x,
7219                             gint       y,
7220                             gint      *root_x,
7221                             gint      *root_y)
7222 {
7223   GdkWindowObject *private;
7224
7225   g_return_if_fail (GDK_IS_WINDOW (window));
7226
7227   private = (GdkWindowObject *) window;
7228
7229   if (GDK_WINDOW_DESTROYED (window))
7230     {
7231       if (x)
7232         *root_x = x;
7233       if (y)
7234         *root_y = y;
7235       return;
7236     }
7237   
7238   GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_root_coords (window,
7239                                                               x + private->abs_x,
7240                                                               y + private->abs_y,
7241                                                               root_x, root_y);
7242 }
7243
7244
7245 /**
7246  * gdk_window_get_deskrelative_origin:
7247  * @window: a toplevel #GdkWindow
7248  * @x: return location for X coordinate
7249  * @y: return location for Y coordinate
7250  *
7251  * This gets the origin of a #GdkWindow relative to
7252  * an Enlightenment-window-manager desktop. As long as you don't
7253  * assume that the user's desktop/workspace covers the entire
7254  * root window (i.e. you don't assume that the desktop begins
7255  * at root window coordinate 0,0) this function is not necessary.
7256  * It's deprecated for that reason.
7257  *
7258  * Return value: not meaningful
7259  **/
7260 gboolean
7261 gdk_window_get_deskrelative_origin (GdkWindow *window,
7262                                     gint      *x,
7263                                     gint      *y)
7264 {
7265   GdkWindowObject *private;
7266   gboolean return_val = FALSE;
7267   gint tx = 0;
7268   gint ty = 0;
7269
7270   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
7271
7272   private = (GdkWindowObject *) window;
7273
7274   if (!GDK_WINDOW_DESTROYED (window))
7275     {
7276       return_val = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_deskrelative_origin (window, &tx, &ty);
7277
7278       if (x)
7279         *x = tx + private->abs_x;
7280       if (y)
7281         *y = ty + private->abs_y;
7282     }
7283
7284   return return_val;
7285 }
7286
7287 /**
7288  * gdk_window_shape_combine_mask:
7289  * @window: a #GdkWindow
7290  * @mask: shape mask
7291  * @x: X position of shape mask with respect to @window
7292  * @y: Y position of shape mask with respect to @window
7293  *
7294  * Applies a shape mask to @window. Pixels in @window corresponding to
7295  * set bits in the @mask will be visible; pixels in @window
7296  * corresponding to unset bits in the @mask will be transparent. This
7297  * gives a non-rectangular window.
7298  *
7299  * If @mask is %NULL, the shape mask will be unset, and the @x/@y
7300  * parameters are not used.
7301  *
7302  * On the X11 platform, this uses an X server extension which is
7303  * widely available on most common platforms, but not available on
7304  * very old X servers, and occasionally the implementation will be
7305  * buggy. On servers without the shape extension, this function
7306  * will do nothing.
7307  *
7308  * This function works on both toplevel and child windows.
7309  */
7310 void
7311 gdk_window_shape_combine_mask (GdkWindow *window,
7312                                GdkBitmap *mask,
7313                                gint       x,
7314                                gint       y)
7315 {
7316   GdkWindowObject *private;
7317   GdkRegion *region;
7318
7319   g_return_if_fail (GDK_IS_WINDOW (window));
7320
7321   private = (GdkWindowObject *) window;
7322
7323   if (mask)
7324     region = _gdk_windowing_get_shape_for_mask (mask);
7325   else
7326     region = NULL;
7327
7328   gdk_window_shape_combine_region (window,
7329                                    region,
7330                                    x, y);
7331
7332   if (region)
7333     gdk_region_destroy (region);
7334 }
7335
7336 /**
7337  * gdk_window_shape_combine_region:
7338  * @window: a #GdkWindow
7339  * @shape_region: region of window to be non-transparent
7340  * @offset_x: X position of @shape_region in @window coordinates
7341  * @offset_y: Y position of @shape_region in @window coordinates
7342  *
7343  * Makes pixels in @window outside @shape_region be transparent,
7344  * so that the window may be nonrectangular. See also
7345  * gdk_window_shape_combine_mask() to use a bitmap as the mask.
7346  *
7347  * If @shape_region is %NULL, the shape will be unset, so the whole
7348  * window will be opaque again. @offset_x and @offset_y are ignored
7349  * if @shape_region is %NULL.
7350  *
7351  * On the X11 platform, this uses an X server extension which is
7352  * widely available on most common platforms, but not available on
7353  * very old X servers, and occasionally the implementation will be
7354  * buggy. On servers without the shape extension, this function
7355  * will do nothing.
7356  *
7357  * This function works on both toplevel and child windows.
7358  */
7359 void
7360 gdk_window_shape_combine_region (GdkWindow       *window,
7361                                  const GdkRegion *shape_region,
7362                                  gint             offset_x,
7363                                  gint             offset_y)
7364 {
7365   GdkWindowObject *private;
7366   GdkRegion *old_region, *new_region, *diff;
7367
7368   g_return_if_fail (GDK_IS_WINDOW (window));
7369
7370   private = (GdkWindowObject *) window;
7371
7372   if (GDK_WINDOW_DESTROYED (window))
7373     return;
7374
7375   private->shaped = (shape_region != NULL);
7376
7377   if (private->shape)
7378     gdk_region_destroy (private->shape);
7379
7380   old_region = NULL;
7381   if (GDK_WINDOW_IS_MAPPED (window))
7382     old_region = gdk_region_copy (private->clip_region);
7383
7384   if (shape_region)
7385     {
7386       private->shape = gdk_region_copy (shape_region);
7387       gdk_region_offset (private->shape, offset_x, offset_y);
7388     }
7389   else
7390     private->shape = NULL;
7391
7392   recompute_visible_regions (private, TRUE, FALSE);
7393
7394   if (old_region)
7395     {
7396       new_region = gdk_region_copy (private->clip_region);
7397
7398       /* New area in the window, needs invalidation */
7399       diff = gdk_region_copy (new_region);
7400       gdk_region_subtract (diff, old_region);
7401
7402       gdk_window_invalidate_region (window, diff, TRUE);
7403
7404       gdk_region_destroy (diff);
7405
7406       if (private->parent != NULL &&
7407           private->parent->window_type != GDK_WINDOW_ROOT)
7408         {
7409           /* New area in the non-root parent window, needs invalidation */
7410           diff = gdk_region_copy (old_region);
7411           gdk_region_subtract (diff, new_region);
7412
7413           /* Adjust region to parent window coords */
7414           gdk_region_offset (diff, private->x, private->y);
7415
7416           gdk_window_invalidate_region (GDK_WINDOW (private->parent), diff, TRUE);
7417
7418           gdk_region_destroy (diff);
7419         }
7420
7421       gdk_region_destroy (new_region);
7422       gdk_region_destroy (old_region);
7423     }
7424 }
7425
7426 static void
7427 do_child_shapes (GdkWindow *window,
7428                  gboolean merge)
7429 {
7430   GdkWindowObject *private;
7431   GdkRectangle r;
7432   GdkRegion *region;
7433
7434   private = (GdkWindowObject *) window;
7435
7436   r.x = 0;
7437   r.y = 0;
7438   r.width = private->width;
7439   r.height = private->height;
7440
7441   region = gdk_region_rectangle (&r);
7442   remove_child_area (private, NULL, FALSE, region);
7443
7444   if (merge && private->shape)
7445     gdk_region_subtract (region, private->shape);
7446
7447   gdk_window_shape_combine_region (window, region, 0, 0);
7448 }
7449
7450 /**
7451  * gdk_window_set_child_shapes:
7452  * @window: a #GdkWindow
7453  *
7454  * Sets the shape mask of @window to the union of shape masks
7455  * for all children of @window, ignoring the shape mask of @window
7456  * itself. Contrast with gdk_window_merge_child_shapes() which includes
7457  * the shape mask of @window in the masks to be merged.
7458  **/
7459 void
7460 gdk_window_set_child_shapes (GdkWindow *window)
7461 {
7462   g_return_if_fail (GDK_IS_WINDOW (window));
7463
7464   do_child_shapes (window, FALSE);
7465 }
7466
7467 /**
7468  * gdk_window_merge_child_shapes:
7469  * @window: a #GdkWindow
7470  *
7471  * Merges the shape masks for any child windows into the
7472  * shape mask for @window. i.e. the union of all masks
7473  * for @window and its children will become the new mask
7474  * for @window. See gdk_window_shape_combine_mask().
7475  *
7476  * This function is distinct from gdk_window_set_child_shapes()
7477  * because it includes @window's shape mask in the set of shapes to
7478  * be merged.
7479  */
7480 void
7481 gdk_window_merge_child_shapes (GdkWindow *window)
7482 {
7483   g_return_if_fail (GDK_IS_WINDOW (window));
7484
7485   do_child_shapes (window, TRUE);
7486 }
7487
7488 /**
7489  * gdk_window_input_shape_combine_mask:
7490  * @window: a #GdkWindow
7491  * @mask: shape mask, or %NULL
7492  * @x: X position of shape mask with respect to @window
7493  * @y: Y position of shape mask with respect to @window
7494  *
7495  * Like gdk_window_shape_combine_mask(), but the shape applies
7496  * only to event handling. Mouse events which happen while
7497  * the pointer position corresponds to an unset bit in the
7498  * mask will be passed on the window below @window.
7499  *
7500  * An input shape is typically used with RGBA windows.
7501  * The alpha channel of the window defines which pixels are
7502  * invisible and allows for nicely antialiased borders,
7503  * and the input shape controls where the window is
7504  * "clickable".
7505  *
7506  * On the X11 platform, this requires version 1.1 of the
7507  * shape extension.
7508  *
7509  * On the Win32 platform, this functionality is not present and the
7510  * function does nothing.
7511  *
7512  * Since: 2.10
7513  */
7514 void
7515 gdk_window_input_shape_combine_mask (GdkWindow *window,
7516                                      GdkBitmap *mask,
7517                                      gint       x,
7518                                      gint       y)
7519 {
7520   GdkWindowObject *private;
7521   GdkRegion *region;
7522
7523   g_return_if_fail (GDK_IS_WINDOW (window));
7524
7525   private = (GdkWindowObject *) window;
7526
7527   if (mask)
7528     region = _gdk_windowing_get_shape_for_mask (mask);
7529   else
7530     region = NULL;
7531
7532   gdk_window_input_shape_combine_region (window,
7533                                          region,
7534                                          x, y);
7535
7536   if (region != NULL)
7537     gdk_region_destroy (region);
7538 }
7539
7540 /**
7541  * gdk_window_input_shape_combine_region:
7542  * @window: a #GdkWindow
7543  * @shape_region: region of window to be non-transparent
7544  * @offset_x: X position of @shape_region in @window coordinates
7545  * @offset_y: Y position of @shape_region in @window coordinates
7546  *
7547  * Like gdk_window_shape_combine_region(), but the shape applies
7548  * only to event handling. Mouse events which happen while
7549  * the pointer position corresponds to an unset bit in the
7550  * mask will be passed on the window below @window.
7551  *
7552  * An input shape is typically used with RGBA windows.
7553  * The alpha channel of the window defines which pixels are
7554  * invisible and allows for nicely antialiased borders,
7555  * and the input shape controls where the window is
7556  * "clickable".
7557  *
7558  * On the X11 platform, this requires version 1.1 of the
7559  * shape extension.
7560  *
7561  * On the Win32 platform, this functionality is not present and the
7562  * function does nothing.
7563  *
7564  * Since: 2.10
7565  */
7566 void
7567 gdk_window_input_shape_combine_region (GdkWindow       *window,
7568                                        const GdkRegion *shape_region,
7569                                        gint             offset_x,
7570                                        gint             offset_y)
7571 {
7572   GdkWindowObject *private;
7573
7574   g_return_if_fail (GDK_IS_WINDOW (window));
7575
7576   private = (GdkWindowObject *) window;
7577
7578   if (GDK_WINDOW_DESTROYED (window))
7579     return;
7580
7581   if (private->input_shape)
7582     gdk_region_destroy (private->input_shape);
7583
7584   if (shape_region)
7585     {
7586       private->input_shape = gdk_region_copy (shape_region);
7587       gdk_region_offset (private->input_shape, offset_x, offset_y);
7588     }
7589   else
7590     private->input_shape = NULL;
7591
7592   if (gdk_window_has_impl (private))
7593     GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_shape_combine_region ((GdkWindow *)private, private->input_shape, 0, 0);
7594
7595   /* Pointer may have e.g. moved outside window due to the input mask change */
7596   _gdk_synthesize_crossing_events_for_geometry_change (window);
7597 }
7598
7599 static void
7600 do_child_input_shapes (GdkWindow *window,
7601                        gboolean merge)
7602 {
7603   GdkWindowObject *private;
7604   GdkRectangle r;
7605   GdkRegion *region;
7606
7607   private = (GdkWindowObject *) window;
7608
7609   r.x = 0;
7610   r.y = 0;
7611   r.width = private->width;
7612   r.height = private->height;
7613
7614   region = gdk_region_rectangle (&r);
7615   remove_child_area (private, NULL, TRUE, region);
7616
7617   if (merge && private->shape)
7618     gdk_region_subtract (region, private->shape);
7619   if (merge && private->input_shape)
7620     gdk_region_subtract (region, private->input_shape);
7621
7622   gdk_window_input_shape_combine_region (window, region, 0, 0);
7623 }
7624
7625
7626 /**
7627  * gdk_window_set_child_input_shapes:
7628  * @window: a #GdkWindow
7629  *
7630  * Sets the input shape mask of @window to the union of input shape masks
7631  * for all children of @window, ignoring the input shape mask of @window
7632  * itself. Contrast with gdk_window_merge_child_input_shapes() which includes
7633  * the input shape mask of @window in the masks to be merged.
7634  *
7635  * Since: 2.10
7636  **/
7637 void
7638 gdk_window_set_child_input_shapes (GdkWindow *window)
7639 {
7640   g_return_if_fail (GDK_IS_WINDOW (window));
7641
7642   do_child_input_shapes (window, FALSE);
7643 }
7644
7645 /**
7646  * gdk_window_merge_child_input_shapes:
7647  * @window: a #GdkWindow
7648  *
7649  * Merges the input shape masks for any child windows into the
7650  * input shape mask for @window. i.e. the union of all input masks
7651  * for @window and its children will become the new input mask
7652  * for @window. See gdk_window_input_shape_combine_mask().
7653  *
7654  * This function is distinct from gdk_window_set_child_input_shapes()
7655  * because it includes @window's input shape mask in the set of
7656  * shapes to be merged.
7657  *
7658  * Since: 2.10
7659  **/
7660 void
7661 gdk_window_merge_child_input_shapes (GdkWindow *window)
7662 {
7663   g_return_if_fail (GDK_IS_WINDOW (window));
7664
7665   do_child_input_shapes (window, TRUE);
7666 }
7667
7668
7669 /**
7670  * gdk_window_set_static_gravities:
7671  * @window: a #GdkWindow
7672  * @use_static: %TRUE to turn on static gravity
7673  *
7674  * Set the bit gravity of the given window to static, and flag it so
7675  * all children get static subwindow gravity. This is used if you are
7676  * implementing scary features that involve deep knowledge of the
7677  * windowing system. Don't worry about it unless you have to.
7678  *
7679  * Return value: %TRUE if the server supports static gravity
7680  */
7681 gboolean
7682 gdk_window_set_static_gravities (GdkWindow *window,
7683                                  gboolean   use_static)
7684 {
7685   GdkWindowObject *private;
7686
7687   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
7688
7689   private = (GdkWindowObject *) window;
7690
7691   if (gdk_window_has_impl (private))
7692     return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_static_gravities (window, use_static);
7693
7694   return FALSE;
7695 }
7696
7697 /**
7698  * gdk_window_set_composited:
7699  * @window: a #GdkWindow
7700  * @composited: %TRUE to set the window as composited
7701  *
7702  * Sets a #GdkWindow as composited, or unsets it. Composited
7703  * windows do not automatically have their contents drawn to
7704  * the screen. Drawing is redirected to an offscreen buffer
7705  * and an expose event is emitted on the parent of the composited
7706  * window. It is the responsibility of the parent's expose handler
7707  * to manually merge the off-screen content onto the screen in
7708  * whatever way it sees fit. See <xref linkend="composited-window-example"/>
7709  * for an example.
7710  *
7711  * It only makes sense for child windows to be composited; see
7712  * gdk_window_set_opacity() if you need translucent toplevel
7713  * windows.
7714  *
7715  * An additional effect of this call is that the area of this
7716  * window is no longer clipped from regions marked for
7717  * invalidation on its parent. Draws done on the parent
7718  * window are also no longer clipped by the child.
7719  *
7720  * This call is only supported on some systems (currently,
7721  * only X11 with new enough Xcomposite and Xdamage extensions).
7722  * You must call gdk_display_supports_composite() to check if
7723  * setting a window as composited is supported before
7724  * attempting to do so.
7725  *
7726  * Since: 2.12
7727  */
7728 void
7729 gdk_window_set_composited (GdkWindow *window,
7730                            gboolean   composited)
7731 {
7732   GdkWindowObject *private = (GdkWindowObject *)window;
7733   GdkDisplay *display;
7734
7735   g_return_if_fail (GDK_IS_WINDOW (window));
7736
7737   composited = composited != FALSE;
7738
7739   if (private->composited == composited)
7740     return;
7741
7742   if (composited)
7743     gdk_window_ensure_native (window);
7744
7745   display = gdk_drawable_get_display (GDK_DRAWABLE (window));
7746
7747   if (!gdk_display_supports_composite (display) && composited)
7748     {
7749       g_warning ("gdk_window_set_composited called but "
7750                  "compositing is not supported");
7751       return;
7752     }
7753
7754   _gdk_windowing_window_set_composited (window, composited);
7755
7756   recompute_visible_regions (private, TRUE, FALSE);
7757
7758   if (GDK_WINDOW_IS_MAPPED (window))
7759     gdk_window_invalidate_in_parent (private);
7760
7761   private->composited = composited;
7762 }
7763
7764
7765 static void
7766 remove_redirect_from_children (GdkWindowObject   *private,
7767                                GdkWindowRedirect *redirect)
7768 {
7769   GList *l;
7770   GdkWindowObject *child;
7771
7772   for (l = private->children; l != NULL; l = l->next)
7773     {
7774       child = l->data;
7775
7776       /* Don't redirect this child if it already has another redirect */
7777       if (child->redirect == redirect)
7778         {
7779           child->redirect = NULL;
7780           remove_redirect_from_children (child, redirect);
7781         }
7782     }
7783 }
7784
7785 /**
7786  * gdk_window_remove_redirection:
7787  * @window: a #GdkWindow
7788  *
7789  * Removes any active redirection started by
7790  * gdk_window_redirect_to_drawable().
7791  *
7792  * Since: 2.14
7793  **/
7794 void
7795 gdk_window_remove_redirection (GdkWindow *window)
7796 {
7797   GdkWindowObject *private;
7798
7799   g_return_if_fail (GDK_IS_WINDOW (window));
7800
7801   private = (GdkWindowObject *) window;
7802
7803   if (private->redirect &&
7804       private->redirect->redirected == private)
7805     {
7806       remove_redirect_from_children (private, private->redirect);
7807       gdk_window_redirect_free (private->redirect);
7808       private->redirect = NULL;
7809     }
7810 }
7811
7812 static void
7813 apply_redirect_to_children (GdkWindowObject   *private,
7814                             GdkWindowRedirect *redirect)
7815 {
7816   GList *l;
7817   GdkWindowObject *child;
7818
7819   for (l = private->children; l != NULL; l = l->next)
7820     {
7821       child = l->data;
7822
7823       /* Don't redirect this child if it already has another redirect */
7824       if (!child->redirect)
7825         {
7826           child->redirect = redirect;
7827           apply_redirect_to_children (child, redirect);
7828         }
7829     }
7830 }
7831
7832 /**
7833  * gdk_window_redirect_to_drawable:
7834  * @window: a #GdkWindow
7835  * @drawable: a #GdkDrawable
7836  * @src_x: x position in @window
7837  * @src_y: y position in @window
7838  * @dest_x: x position in @drawable
7839  * @dest_y: y position in @drawable
7840  * @width: width of redirection
7841  * @height: height of redirection
7842  *
7843  * Redirects drawing into @window so that drawing to the
7844  * window in the rectangle specified by @src_x, @src_y,
7845  * @width and @height is also drawn into @drawable at
7846  * @dest_x, @dest_y.
7847  *
7848  * Only drawing between gdk_window_begin_paint_region() or
7849  * gdk_window_begin_paint_rect() and gdk_window_end_paint() is
7850  * redirected.
7851  *
7852  * Redirection is active until gdk_window_remove_redirection()
7853  * is called.
7854  *
7855  * Since: 2.14
7856  **/
7857 void
7858 gdk_window_redirect_to_drawable (GdkWindow   *window,
7859                                  GdkDrawable *drawable,
7860                                  gint         src_x,
7861                                  gint         src_y,
7862                                  gint         dest_x,
7863                                  gint         dest_y,
7864                                  gint         width,
7865                                  gint         height)
7866 {
7867   GdkWindowObject *private;
7868
7869   g_return_if_fail (GDK_IS_WINDOW (window));
7870   g_return_if_fail (GDK_IS_DRAWABLE (drawable));
7871   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
7872
7873   private = (GdkWindowObject *) window;
7874
7875   if (private->redirect)
7876     gdk_window_remove_redirection (window);
7877
7878   if (width == -1 || height == -1)
7879     {
7880       gint w, h;
7881       gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
7882       if (width == -1)
7883         width = w;
7884       if (height == -1)
7885         height = h;
7886     }
7887
7888   private->redirect = g_new0 (GdkWindowRedirect, 1);
7889   private->redirect->redirected = private;
7890   private->redirect->pixmap = g_object_ref (drawable);
7891   private->redirect->src_x = src_x;
7892   private->redirect->src_y = src_y;
7893   private->redirect->dest_x = dest_x;
7894   private->redirect->dest_y = dest_y;
7895   private->redirect->width = width;
7896   private->redirect->height = height;
7897
7898   apply_redirect_to_children (private, private->redirect);
7899 }
7900
7901 static void
7902 window_get_size_rectangle (GdkWindow    *window,
7903                            GdkRectangle *rect)
7904 {
7905   GdkWindowObject *private = (GdkWindowObject *) window;
7906
7907   rect->x = rect->y = 0;
7908   rect->width = private->width;
7909   rect->height = private->height;
7910 }
7911
7912 /* Calculates the real clipping region for a window, in window coordinates,
7913  * taking into account other windows, gc clip region and gc clip mask.
7914  */
7915 GdkRegion *
7916 _gdk_window_calculate_full_clip_region (GdkWindow *window,
7917                                         GdkWindow *base_window,
7918                                         gboolean   do_children,
7919                                         gint      *base_x_offset,
7920                                         gint      *base_y_offset)
7921 {
7922   GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
7923   GdkRectangle visible_rect;
7924   GdkRegion *real_clip_region, *tmpreg;
7925   gint x_offset, y_offset;
7926   GdkWindowObject *parentwin, *lastwin;
7927
7928   if (base_x_offset)
7929     *base_x_offset = 0;
7930   if (base_y_offset)
7931     *base_y_offset = 0;
7932
7933   if (!private->viewable || private->input_only)
7934     return gdk_region_new ();
7935
7936   window_get_size_rectangle (window, &visible_rect);
7937
7938   /* real_clip_region is in window coordinates */
7939   real_clip_region = gdk_region_rectangle (&visible_rect);
7940
7941   x_offset = y_offset = 0;
7942
7943   lastwin = private;
7944   if (do_children)
7945     parentwin = lastwin;
7946   else
7947     parentwin = lastwin->parent;
7948
7949   /* Remove the areas of all overlapping windows above parentwin in the hiearachy */
7950   for (; parentwin != NULL &&
7951          (parentwin == private || lastwin != (GdkWindowObject*) base_window);
7952        lastwin = parentwin, parentwin = lastwin->parent)
7953     {
7954       GList *cur;
7955       GdkRectangle real_clip_rect;
7956       gboolean is_offscreen;
7957
7958       if (parentwin != private)
7959         {
7960           x_offset += GDK_WINDOW_OBJECT (lastwin)->x;
7961           y_offset += GDK_WINDOW_OBJECT (lastwin)->y;
7962         }
7963
7964       is_offscreen = gdk_window_is_offscreen (parentwin);
7965
7966       /* children is ordered in reverse stack order */
7967       for (cur = parentwin->children;
7968            cur && cur->data != lastwin;
7969            cur = cur->next)
7970         {
7971           GdkWindow *child = cur->data;
7972           GdkWindowObject *child_private = (GdkWindowObject *)child;
7973
7974           if (!GDK_WINDOW_IS_MAPPED (child) || child_private->input_only)
7975             continue;
7976
7977           /* Ignore offscreen children, as they don't draw in their parent and
7978            * don't take part in the clipping */
7979           if (gdk_window_is_offscreen (child_private))
7980             continue;
7981
7982           window_get_size_rectangle (child, &visible_rect);
7983
7984           /* Convert rect to "window" coords */
7985           visible_rect.x += child_private->x - x_offset;
7986           visible_rect.y += child_private->y - y_offset;
7987
7988           /* This shortcut is really necessary for performance when there are a lot of windows */
7989           gdk_region_get_clipbox (real_clip_region, &real_clip_rect);
7990           if (visible_rect.x >= real_clip_rect.x + real_clip_rect.width ||
7991               visible_rect.x + visible_rect.width <= real_clip_rect.x ||
7992               visible_rect.y >= real_clip_rect.y + real_clip_rect.height ||
7993               visible_rect.y + visible_rect.height <= real_clip_rect.y)
7994             continue;
7995
7996           tmpreg = gdk_region_rectangle (&visible_rect);
7997           gdk_region_subtract (real_clip_region, tmpreg);
7998           gdk_region_destroy (tmpreg);
7999         }
8000
8001       /* Clip to the parent */
8002       window_get_size_rectangle ((GdkWindow *)parentwin, &visible_rect);
8003       /* Convert rect to "window" coords */
8004       visible_rect.x += - x_offset;
8005       visible_rect.y += - y_offset;
8006
8007       tmpreg = gdk_region_rectangle (&visible_rect);
8008       gdk_region_intersect (real_clip_region, tmpreg);
8009       gdk_region_destroy (tmpreg);
8010     }
8011
8012   if (base_x_offset)
8013     *base_x_offset = x_offset;
8014   if (base_y_offset)
8015     *base_y_offset = y_offset;
8016
8017   return real_clip_region;
8018 }
8019
8020 void
8021 _gdk_window_add_damage (GdkWindow *toplevel,
8022                         GdkRegion *damaged_region)
8023 {
8024   GdkDisplay *display;
8025   GdkEvent event = { 0, };
8026   event.expose.type = GDK_DAMAGE;
8027   event.expose.window = toplevel;
8028   event.expose.send_event = FALSE;
8029   event.expose.region = damaged_region;
8030   gdk_region_get_clipbox (event.expose.region, &event.expose.area);
8031   display = gdk_drawable_get_display (event.expose.window);
8032   _gdk_event_queue_append (display, gdk_event_copy (&event));
8033 }
8034
8035 static void
8036 gdk_window_redirect_free (GdkWindowRedirect *redirect)
8037 {
8038   g_object_unref (redirect->pixmap);
8039   g_free (redirect);
8040 }
8041
8042 /* Gets the toplevel for a window as used for events,
8043    i.e. including offscreen parents */
8044 static GdkWindowObject *
8045 get_event_parent (GdkWindowObject *window)
8046 {
8047   if (window->window_type == GDK_WINDOW_OFFSCREEN)
8048     return (GdkWindowObject *)gdk_offscreen_window_get_embedder ((GdkWindow *)window);
8049   else
8050     return window->parent;
8051 }
8052
8053 /* Gets the toplevel for a window as used for events,
8054    i.e. including offscreen parents going up to the native
8055    toplevel */
8056 static GdkWindow *
8057 get_event_toplevel (GdkWindow *w)
8058 {
8059   GdkWindowObject *private = GDK_WINDOW_OBJECT (w);
8060   GdkWindowObject *parent;
8061
8062   while ((parent = get_event_parent (private)) != NULL &&
8063          (parent->window_type != GDK_WINDOW_ROOT))
8064     private = parent;
8065
8066   return GDK_WINDOW (private);
8067 }
8068
8069 gboolean
8070 _gdk_window_event_parent_of (GdkWindow *parent,
8071                              GdkWindow *child)
8072 {
8073   GdkWindow *w;
8074
8075   w = child;
8076   while (w != NULL)
8077     {
8078       if (w == parent)
8079         return TRUE;
8080
8081       w = (GdkWindow *)get_event_parent ((GdkWindowObject *)w);
8082     }
8083
8084   return FALSE;
8085 }
8086
8087 static void
8088 update_cursor (GdkDisplay *display)
8089 {
8090   GdkWindowObject *pointer_window, *cursor_window, *parent, *toplevel;
8091   GdkPointerGrabInfo *grab;
8092
8093   pointer_window = (GdkWindowObject *)display->pointer_info.window_under_pointer;
8094
8095   cursor_window = pointer_window;
8096   while (cursor_window->cursor == NULL &&
8097          (parent = get_event_parent (cursor_window)) != NULL &&
8098          parent->window_type != GDK_WINDOW_ROOT)
8099     cursor_window = parent;
8100
8101   /* We ignore the serials here and just pick the last grab
8102      we've sent, as that would shortly be used anyway. */
8103   grab = _gdk_display_get_last_pointer_grab (display);
8104   if (grab != NULL &&
8105       !_gdk_window_event_parent_of (grab->window, (GdkWindow *)cursor_window))
8106     cursor_window = (GdkWindowObject *)grab->window;
8107
8108   /* Set all cursors on toplevel, otherwise its tricky to keep track of
8109    * which native window has what cursor set. */
8110   toplevel = (GdkWindowObject *)get_event_toplevel ((GdkWindow *)pointer_window);
8111   GDK_WINDOW_IMPL_GET_IFACE (toplevel->impl)->set_cursor
8112     ((GdkWindow *)toplevel, cursor_window->cursor);
8113 }
8114
8115 static void
8116 from_embedder (GdkWindowObject *window,
8117                double embedder_x, double embedder_y,
8118                double *offscreen_x, double *offscreen_y)
8119 {
8120   g_signal_emit (window,
8121                  signals[FROM_EMBEDDER], 0,
8122                  embedder_x, embedder_y,
8123                  offscreen_x, offscreen_y,
8124                  NULL);
8125 }
8126
8127 static void
8128 convert_coords_to_child (GdkWindowObject *child,
8129                          double x, double y,
8130                          double *child_x, double *child_y)
8131 {
8132   if (gdk_window_is_offscreen (child))
8133     {
8134       from_embedder (child, x, y,
8135                      child_x, child_y);
8136     }
8137   else
8138     {
8139       *child_x = x - child->x;
8140       *child_y = y - child->y;
8141     }
8142 }
8143
8144 static gboolean
8145 point_in_window (GdkWindowObject *window,
8146                  double x, double y)
8147 {
8148   return
8149     x >= 0 && x < window->width &&
8150     y >= 0 && y < window->height &&
8151     (window->shape == NULL ||
8152      gdk_region_point_in (window->shape,
8153                           x, y)) &&
8154     (window->input_shape == NULL ||
8155      gdk_region_point_in (window->input_shape,
8156                           x, y));
8157 }
8158
8159 static GdkWindow *
8160 convert_native_coords_to_toplevel (GdkWindow *window,
8161                                    double child_x, double child_y,
8162                                    double *toplevel_x, double *toplevel_y)
8163 {
8164   GdkWindowObject *private = (GdkWindowObject *)window;
8165   gdouble x, y;
8166
8167   x = child_x;
8168   y = child_y;
8169
8170   while (private->parent != NULL &&
8171          (private->parent->window_type != GDK_WINDOW_ROOT))
8172     {
8173       x += private->x;
8174       y += private->y;
8175       private = private->parent;
8176     }
8177
8178   *toplevel_x = x;
8179   *toplevel_y = y;
8180
8181   return (GdkWindow *)private;
8182 }
8183
8184 static void
8185 convert_toplevel_coords_to_window (GdkWindow *window,
8186                                    gdouble    toplevel_x,
8187                                    gdouble    toplevel_y,
8188                                    gdouble   *window_x,
8189                                    gdouble   *window_y)
8190 {
8191   GdkWindowObject *private;
8192   GdkWindowObject *parent;
8193   gdouble x, y;
8194   GList *children, *l;
8195
8196   private = GDK_WINDOW_OBJECT (window);
8197
8198   x = toplevel_x;
8199   y = toplevel_y;
8200
8201   children = NULL;
8202   while ((parent = get_event_parent (private)) != NULL &&
8203          (parent->window_type != GDK_WINDOW_ROOT))
8204     {
8205       children = g_list_prepend (children, private);
8206       private = parent;
8207     }
8208
8209   for (l = children; l != NULL; l = l->next)
8210     convert_coords_to_child (l->data, x, y, &x, &y);
8211
8212   g_list_free (children);
8213
8214   *window_x = x;
8215   *window_y = y;
8216 }
8217
8218 static GdkWindowObject *
8219 pick_embedded_child (GdkWindowObject *window,
8220                       double x, double y)
8221 {
8222   GdkWindowObject *res;
8223
8224   res = NULL;
8225   g_signal_emit (window,
8226                  signals[PICK_EMBEDDED_CHILD], 0,
8227                  x, y, &res);
8228
8229   return res;
8230 }
8231
8232 GdkWindow *
8233 _gdk_window_find_child_at (GdkWindow *window,
8234                            int x, int y)
8235 {
8236   GdkWindowObject *private, *sub;
8237   double child_x, child_y;
8238   GList *l;
8239
8240   private = (GdkWindowObject *)window;
8241
8242   if (point_in_window (private, x, y))
8243     {
8244       /* Children is ordered in reverse stack order, i.e. first is topmost */
8245       for (l = private->children; l != NULL; l = l->next)
8246         {
8247           sub = l->data;
8248
8249           if (!GDK_WINDOW_IS_MAPPED (sub))
8250             continue;
8251
8252           convert_coords_to_child (sub,
8253                                    x, y,
8254                                    &child_x, &child_y);
8255           if (point_in_window (sub, child_x, child_y))
8256             return (GdkWindow *)sub;
8257         }
8258
8259       if (private->num_offscreen_children > 0)
8260         {
8261           sub = pick_embedded_child (private,
8262                                      x, y);
8263           if (sub)
8264             return (GdkWindow *)sub;
8265         }
8266     }
8267
8268   return NULL;
8269 }
8270
8271 GdkWindow *
8272 _gdk_window_find_descendant_at (GdkWindow *toplevel,
8273                                 double x, double y,
8274                                 double *found_x,
8275                                 double *found_y)
8276 {
8277   GdkWindowObject *private, *sub;
8278   double child_x, child_y;
8279   GList *l;
8280   gboolean found;
8281
8282   private = (GdkWindowObject *)toplevel;
8283
8284   if (point_in_window (private, x, y))
8285     {
8286       do
8287         {
8288           found = FALSE;
8289           /* Children is ordered in reverse stack order, i.e. first is topmost */
8290           for (l = private->children; l != NULL; l = l->next)
8291             {
8292               sub = l->data;
8293
8294               if (!GDK_WINDOW_IS_MAPPED (sub))
8295                 continue;
8296
8297               convert_coords_to_child (sub,
8298                                        x, y,
8299                                        &child_x, &child_y);
8300               if (point_in_window (sub, child_x, child_y))
8301                 {
8302                   x = child_x;
8303                   y = child_y;
8304                   private = sub;
8305                   found = TRUE;
8306                   break;
8307                 }
8308             }
8309           if (!found &&
8310               private->num_offscreen_children > 0)
8311             {
8312               sub = pick_embedded_child (private,
8313                                          x, y);
8314               if (sub)
8315                 {
8316                   found = TRUE;
8317                   private = sub;
8318                   from_embedder (sub, x, y, &x, &y);
8319                 }
8320             }
8321         }
8322       while (found);
8323     }
8324   else
8325     {
8326       /* Not in window at all */
8327       private = NULL;
8328     }
8329
8330   if (found_x)
8331     *found_x = x;
8332   if (found_y)
8333     *found_y = y;
8334
8335   return (GdkWindow *)private;
8336 }
8337
8338 /**
8339  * gdk_window_beep:
8340  * @window: a toplevel #GdkWindow
8341  *
8342  * Emits a short beep associated to @window in the appropriate
8343  * display, if supported. Otherwise, emits a short beep on
8344  * the display just as gdk_display_beep().
8345  *
8346  * Since: 2.12
8347  **/
8348 void
8349 gdk_window_beep (GdkWindow *window)
8350 {
8351   GdkDisplay *display;
8352   GdkWindow *toplevel;
8353
8354   g_return_if_fail (GDK_IS_WINDOW (window));
8355
8356   if (GDK_WINDOW_DESTROYED (window))
8357     return;
8358
8359   toplevel = get_event_toplevel (window);
8360   display = gdk_drawable_get_display (GDK_DRAWABLE (window));
8361
8362   if (toplevel && gdk_window_is_offscreen ((GdkWindowObject *)toplevel))
8363     _gdk_windowing_window_beep (toplevel);
8364   else
8365     gdk_display_beep (display);
8366 }
8367
8368 static const guint type_masks[] = {
8369   GDK_SUBSTRUCTURE_MASK, /* GDK_DELETE                 = 0  */
8370   GDK_STRUCTURE_MASK, /* GDK_DESTROY                   = 1  */
8371   GDK_EXPOSURE_MASK, /* GDK_EXPOSE                     = 2  */
8372   GDK_POINTER_MOTION_MASK, /* GDK_MOTION_NOTIFY        = 3  */
8373   GDK_BUTTON_PRESS_MASK, /* GDK_BUTTON_PRESS           = 4  */
8374   GDK_BUTTON_PRESS_MASK, /* GDK_2BUTTON_PRESS          = 5  */
8375   GDK_BUTTON_PRESS_MASK, /* GDK_3BUTTON_PRESS          = 6  */
8376   GDK_BUTTON_RELEASE_MASK, /* GDK_BUTTON_RELEASE       = 7  */
8377   GDK_KEY_PRESS_MASK, /* GDK_KEY_PRESS                 = 8  */
8378   GDK_KEY_RELEASE_MASK, /* GDK_KEY_RELEASE             = 9  */
8379   GDK_ENTER_NOTIFY_MASK, /* GDK_ENTER_NOTIFY           = 10 */
8380   GDK_LEAVE_NOTIFY_MASK, /* GDK_LEAVE_NOTIFY           = 11 */
8381   GDK_FOCUS_CHANGE_MASK, /* GDK_FOCUS_CHANGE           = 12 */
8382   GDK_STRUCTURE_MASK, /* GDK_CONFIGURE                 = 13 */
8383   GDK_VISIBILITY_NOTIFY_MASK, /* GDK_MAP               = 14 */
8384   GDK_VISIBILITY_NOTIFY_MASK, /* GDK_UNMAP             = 15 */
8385   GDK_PROPERTY_CHANGE_MASK, /* GDK_PROPERTY_NOTIFY     = 16 */
8386   GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_CLEAR     = 17 */
8387   GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_REQUEST   = 18 */
8388   GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_NOTIFY    = 19 */
8389   GDK_PROXIMITY_IN_MASK, /* GDK_PROXIMITY_IN           = 20 */
8390   GDK_PROXIMITY_OUT_MASK, /* GDK_PROXIMITY_OUT         = 21 */
8391   GDK_ALL_EVENTS_MASK, /* GDK_DRAG_ENTER               = 22 */
8392   GDK_ALL_EVENTS_MASK, /* GDK_DRAG_LEAVE               = 23 */
8393   GDK_ALL_EVENTS_MASK, /* GDK_DRAG_MOTION              = 24 */
8394   GDK_ALL_EVENTS_MASK, /* GDK_DRAG_STATUS              = 25 */
8395   GDK_ALL_EVENTS_MASK, /* GDK_DROP_START               = 26 */
8396   GDK_ALL_EVENTS_MASK, /* GDK_DROP_FINISHED            = 27 */
8397   GDK_ALL_EVENTS_MASK, /* GDK_CLIENT_EVENT             = 28 */
8398   GDK_VISIBILITY_NOTIFY_MASK, /* GDK_VISIBILITY_NOTIFY = 29 */
8399   GDK_EXPOSURE_MASK, /* GDK_NO_EXPOSE                  = 30 */
8400   GDK_SCROLL_MASK | GDK_BUTTON_PRESS_MASK,/* GDK_SCROLL= 31 */
8401   0, /* GDK_WINDOW_STATE = 32 */
8402   0, /* GDK_SETTING = 33 */
8403   0, /* GDK_OWNER_CHANGE = 34 */
8404   0, /* GDK_GRAB_BROKEN = 35 */
8405   0, /* GDK_DAMAGE = 36 */
8406 };
8407 G_STATIC_ASSERT (G_N_ELEMENTS (type_masks) == GDK_EVENT_LAST);
8408
8409 /* send motion events if the right buttons are down */
8410 static guint
8411 update_evmask_for_button_motion (guint           evmask,
8412                                  GdkModifierType mask)
8413 {
8414   if (evmask & GDK_BUTTON_MOTION_MASK &&
8415       mask & (GDK_BUTTON1_MASK |
8416               GDK_BUTTON2_MASK |
8417               GDK_BUTTON3_MASK |
8418               GDK_BUTTON4_MASK |
8419               GDK_BUTTON5_MASK))
8420     evmask |= GDK_POINTER_MOTION_MASK;
8421
8422   if ((evmask & GDK_BUTTON1_MOTION_MASK && mask & GDK_BUTTON1_MASK) ||
8423       (evmask & GDK_BUTTON2_MOTION_MASK && mask & GDK_BUTTON2_MASK) ||
8424       (evmask & GDK_BUTTON3_MOTION_MASK && mask & GDK_BUTTON3_MASK))
8425     evmask |= GDK_POINTER_MOTION_MASK;
8426
8427   return evmask;
8428 }
8429
8430 static gboolean
8431 is_button_type (GdkEventType type)
8432 {
8433   return type == GDK_BUTTON_PRESS ||
8434          type == GDK_2BUTTON_PRESS ||
8435          type == GDK_3BUTTON_PRESS ||
8436          type == GDK_BUTTON_RELEASE ||
8437          type == GDK_SCROLL;
8438 }
8439
8440 static gboolean
8441 is_motion_type (GdkEventType type)
8442 {
8443   return type == GDK_MOTION_NOTIFY ||
8444          type == GDK_ENTER_NOTIFY ||
8445          type == GDK_LEAVE_NOTIFY;
8446 }
8447
8448 static GdkWindowObject *
8449 find_common_ancestor (GdkWindowObject *win1,
8450                       GdkWindowObject *win2)
8451 {
8452   GdkWindowObject *tmp;
8453   GList *path1 = NULL, *path2 = NULL;
8454   GList *list1, *list2;
8455
8456   tmp = win1;
8457   while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
8458     {
8459       path1 = g_list_prepend (path1, tmp);
8460       tmp = get_event_parent (tmp);
8461     }
8462
8463   tmp = win2;
8464   while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
8465     {
8466       path2 = g_list_prepend (path2, tmp);
8467       tmp = get_event_parent (tmp);
8468     }
8469
8470   list1 = path1;
8471   list2 = path2;
8472   tmp = NULL;
8473   while (list1 && list2 && (list1->data == list2->data))
8474     {
8475       tmp = (GdkWindowObject *)list1->data;
8476       list1 = g_list_next (list1);
8477       list2 = g_list_next (list2);
8478     }
8479   g_list_free (path1);
8480   g_list_free (path2);
8481
8482   return tmp;
8483 }
8484
8485 GdkEvent *
8486 _gdk_make_event (GdkWindow    *window,
8487                  GdkEventType  type,
8488                  GdkEvent     *event_in_queue,
8489                  gboolean      before_event)
8490 {
8491   GdkEvent *event = gdk_event_new (type);
8492   guint32 the_time;
8493   GdkModifierType the_state;
8494
8495   the_time = gdk_event_get_time (event_in_queue);
8496   gdk_event_get_state (event_in_queue, &the_state);
8497
8498   event->any.window = g_object_ref (window);
8499   event->any.send_event = FALSE;
8500
8501   switch (type)
8502     {
8503     case GDK_MOTION_NOTIFY:
8504       event->motion.time = the_time;
8505       event->motion.axes = NULL;
8506       event->motion.state = the_state;
8507       break;
8508
8509     case GDK_BUTTON_PRESS:
8510     case GDK_2BUTTON_PRESS:
8511     case GDK_3BUTTON_PRESS:
8512     case GDK_BUTTON_RELEASE:
8513       event->button.time = the_time;
8514       event->button.axes = NULL;
8515       event->button.state = the_state;
8516       break;
8517
8518     case GDK_SCROLL:
8519       event->scroll.time = the_time;
8520       event->scroll.state = the_state;
8521       break;
8522
8523     case GDK_KEY_PRESS:
8524     case GDK_KEY_RELEASE:
8525       event->key.time = the_time;
8526       event->key.state = the_state;
8527       break;
8528
8529     case GDK_ENTER_NOTIFY:
8530     case GDK_LEAVE_NOTIFY:
8531       event->crossing.time = the_time;
8532       event->crossing.state = the_state;
8533       break;
8534
8535     case GDK_PROPERTY_NOTIFY:
8536       event->property.time = the_time;
8537       event->property.state = the_state;
8538       break;
8539
8540     case GDK_SELECTION_CLEAR:
8541     case GDK_SELECTION_REQUEST:
8542     case GDK_SELECTION_NOTIFY:
8543       event->selection.time = the_time;
8544       break;
8545
8546     case GDK_PROXIMITY_IN:
8547     case GDK_PROXIMITY_OUT:
8548       event->proximity.time = the_time;
8549       break;
8550
8551     case GDK_DRAG_ENTER:
8552     case GDK_DRAG_LEAVE:
8553     case GDK_DRAG_MOTION:
8554     case GDK_DRAG_STATUS:
8555     case GDK_DROP_START:
8556     case GDK_DROP_FINISHED:
8557       event->dnd.time = the_time;
8558       break;
8559
8560     case GDK_FOCUS_CHANGE:
8561     case GDK_CONFIGURE:
8562     case GDK_MAP:
8563     case GDK_UNMAP:
8564     case GDK_CLIENT_EVENT:
8565     case GDK_VISIBILITY_NOTIFY:
8566     case GDK_NO_EXPOSE:
8567     case GDK_DELETE:
8568     case GDK_DESTROY:
8569     case GDK_EXPOSE:
8570     default:
8571       break;
8572     }
8573
8574   if (event_in_queue)
8575     {
8576     if (before_event)
8577       _gdk_event_queue_insert_before (gdk_drawable_get_display (window), event_in_queue, event);
8578     else
8579       _gdk_event_queue_insert_after (gdk_drawable_get_display (window), event_in_queue, event);
8580     }
8581   else
8582     _gdk_event_queue_append (gdk_drawable_get_display (window), event);
8583
8584   return event;
8585 }
8586
8587 static void
8588 send_crossing_event (GdkDisplay                 *display,
8589                      GdkWindowObject            *toplevel,
8590                      GdkWindowObject            *window,
8591                      GdkEventType                type,
8592                      GdkCrossingMode             mode,
8593                      GdkNotifyType               notify_type,
8594                      GdkWindow                  *subwindow,
8595                      gint                        toplevel_x,
8596                      gint                        toplevel_y,
8597                      GdkModifierType             mask,
8598                      guint32                     time_,
8599                      GdkEvent                   *event_in_queue,
8600                      gulong                      serial)
8601 {
8602   GdkEvent *event;
8603   guint32 event_mask;
8604   GdkPointerGrabInfo *grab;
8605
8606   grab = _gdk_display_has_pointer_grab (display, serial);
8607
8608   if (grab != NULL &&
8609       !grab->owner_events &&
8610       (GdkWindow *)window != grab->window)
8611     return;
8612
8613   if (type == GDK_LEAVE_NOTIFY)
8614     event_mask = GDK_LEAVE_NOTIFY_MASK;
8615   else
8616     event_mask = GDK_ENTER_NOTIFY_MASK;
8617
8618   if (window->extension_events != 0)
8619     GDK_WINDOW_IMPL_GET_IFACE (window->impl)->input_window_crossing ((GdkWindow *)window,
8620                                                                      type == GDK_ENTER_NOTIFY);
8621
8622   if (window->event_mask & event_mask)
8623     {
8624       event = _gdk_make_event ((GdkWindow *)window, type, event_in_queue, TRUE);
8625       event->crossing.time = time_;
8626       event->crossing.subwindow = subwindow;
8627       if (subwindow)
8628         g_object_ref (subwindow);
8629       convert_toplevel_coords_to_window ((GdkWindow *)window,
8630                                          toplevel_x, toplevel_y,
8631                                          &event->crossing.x, &event->crossing.y);
8632       event->crossing.x_root = toplevel_x + toplevel->x;
8633       event->crossing.y_root = toplevel_y + toplevel->y;
8634       event->crossing.mode = mode;
8635       event->crossing.detail = notify_type;
8636       event->crossing.focus = FALSE;
8637       event->crossing.state = mask;
8638     }
8639 }
8640
8641
8642 /* The coordinates are in the toplevel window that src/dest are in.
8643  * src and dest are always (if != NULL) in the same toplevel, as
8644  * we get a leave-notify and set the window_under_pointer to null
8645  * before crossing to another toplevel.
8646  */
8647 void
8648 _gdk_synthesize_crossing_events (GdkDisplay                 *display,
8649                                  GdkWindow                  *src,
8650                                  GdkWindow                  *dest,
8651                                  GdkCrossingMode             mode,
8652                                  gint                        toplevel_x,
8653                                  gint                        toplevel_y,
8654                                  GdkModifierType             mask,
8655                                  guint32                     time_,
8656                                  GdkEvent                   *event_in_queue,
8657                                  gulong                      serial,
8658                                  gboolean                    non_linear)
8659 {
8660   GdkWindowObject *c;
8661   GdkWindowObject *win, *last, *next;
8662   GList *path, *list;
8663   GdkWindowObject *a;
8664   GdkWindowObject *b;
8665   GdkWindowObject *toplevel;
8666   GdkNotifyType notify_type;
8667
8668   /* TODO: Don't send events to toplevel, as we get those from the windowing system */
8669
8670   a = (GdkWindowObject *)src;
8671   b = (GdkWindowObject *)dest;
8672   if (a == b)
8673     return; /* No crossings generated between src and dest */
8674
8675   c = find_common_ancestor (a, b);
8676
8677   non_linear |= (c != a) && (c != b);
8678
8679   if (a) /* There might not be a source (i.e. if no previous pointer_in_window) */
8680     {
8681       toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)a);
8682
8683       /* Traverse up from a to (excluding) c sending leave events */
8684       if (non_linear)
8685         notify_type = GDK_NOTIFY_NONLINEAR;
8686       else if (c == a)
8687         notify_type = GDK_NOTIFY_INFERIOR;
8688       else
8689         notify_type = GDK_NOTIFY_ANCESTOR;
8690       send_crossing_event (display, toplevel,
8691                            a, GDK_LEAVE_NOTIFY,
8692                            mode,
8693                            notify_type,
8694                            NULL,
8695                            toplevel_x, toplevel_y,
8696                            mask, time_,
8697                            event_in_queue,
8698                            serial);
8699
8700       if (c != a)
8701         {
8702           if (non_linear)
8703             notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
8704           else
8705             notify_type = GDK_NOTIFY_VIRTUAL;
8706
8707           last = a;
8708           win = get_event_parent (a);
8709           while (win != c && win->window_type != GDK_WINDOW_ROOT)
8710             {
8711               send_crossing_event (display, toplevel,
8712                                    win, GDK_LEAVE_NOTIFY,
8713                                    mode,
8714                                    notify_type,
8715                                    (GdkWindow *)last,
8716                                    toplevel_x, toplevel_y,
8717                                    mask, time_,
8718                                    event_in_queue,
8719                                    serial);
8720
8721               last = win;
8722               win = get_event_parent (win);
8723             }
8724         }
8725     }
8726
8727   if (b) /* Might not be a dest, e.g. if we're moving out of the window */
8728     {
8729       toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)b);
8730
8731       /* Traverse down from c to b */
8732       if (c != b)
8733         {
8734           path = NULL;
8735           win = get_event_parent (b);
8736           while (win != c && win->window_type != GDK_WINDOW_ROOT)
8737             {
8738               path = g_list_prepend (path, win);
8739               win = get_event_parent (win);
8740             }
8741
8742           if (non_linear)
8743             notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
8744           else
8745             notify_type = GDK_NOTIFY_VIRTUAL;
8746
8747           list = path;
8748           while (list)
8749             {
8750               win = (GdkWindowObject *)list->data;
8751               list = g_list_next (list);
8752               if (list)
8753                 next = (GdkWindowObject *)list->data;
8754               else
8755                 next = b;
8756
8757               send_crossing_event (display, toplevel,
8758                                    win, GDK_ENTER_NOTIFY,
8759                                    mode,
8760                                    notify_type,
8761                                    (GdkWindow *)next,
8762                                    toplevel_x, toplevel_y,
8763                                    mask, time_,
8764                                    event_in_queue,
8765                                    serial);
8766             }
8767           g_list_free (path);
8768         }
8769
8770
8771       if (non_linear)
8772         notify_type = GDK_NOTIFY_NONLINEAR;
8773       else if (c == a)
8774         notify_type = GDK_NOTIFY_ANCESTOR;
8775       else
8776         notify_type = GDK_NOTIFY_INFERIOR;
8777
8778       send_crossing_event (display, toplevel,
8779                            b, GDK_ENTER_NOTIFY,
8780                            mode,
8781                            notify_type,
8782                            NULL,
8783                            toplevel_x, toplevel_y,
8784                            mask, time_,
8785                            event_in_queue,
8786                            serial);
8787     }
8788 }
8789
8790 /* Returns the window inside the event window with the pointer in it
8791  * at the specified coordinates, or NULL if its not in any child of
8792  * the toplevel. It also takes into account !owner_events grabs.
8793  */
8794 static GdkWindow *
8795 get_pointer_window (GdkDisplay *display,
8796                     GdkWindow *event_window,
8797                     gdouble toplevel_x,
8798                     gdouble toplevel_y,
8799                     gulong serial)
8800 {
8801   GdkWindow *pointer_window;
8802   GdkPointerGrabInfo *grab;
8803
8804   if (event_window == display->pointer_info.toplevel_under_pointer)
8805     pointer_window =
8806       _gdk_window_find_descendant_at (event_window,
8807                                       toplevel_x, toplevel_y,
8808                                       NULL, NULL);
8809   else
8810     pointer_window = NULL;
8811
8812   grab = _gdk_display_has_pointer_grab (display, serial);
8813   if (grab != NULL &&
8814       !grab->owner_events &&
8815       pointer_window != grab->window)
8816     pointer_window = NULL;
8817
8818   return pointer_window;
8819 }
8820
8821 void
8822 _gdk_display_set_window_under_pointer (GdkDisplay *display,
8823                                        GdkWindow *window)
8824 {
8825   GdkWindowObject *private;
8826
8827   private = (GdkWindowObject *)window;
8828
8829   if (display->pointer_info.window_under_pointer)
8830     g_object_unref (display->pointer_info.window_under_pointer);
8831   display->pointer_info.window_under_pointer = window;
8832   if (window)
8833     g_object_ref (window);
8834
8835   if (window)
8836     update_cursor (display);
8837
8838   _gdk_display_enable_motion_hints (display);
8839 }
8840
8841 /*
8842  *--------------------------------------------------------------
8843  * gdk_pointer_grab
8844  *
8845  *   Grabs the pointer to a specific window
8846  *
8847  * Arguments:
8848  *   "window" is the window which will receive the grab
8849  *   "owner_events" specifies whether events will be reported as is,
8850  *     or relative to "window"
8851  *   "event_mask" masks only interesting events
8852  *   "confine_to" limits the cursor movement to the specified window
8853  *   "cursor" changes the cursor for the duration of the grab
8854  *   "time" specifies the time
8855  *
8856  * Results:
8857  *
8858  * Side effects:
8859  *   requires a corresponding call to gdk_pointer_ungrab
8860  *
8861  *--------------------------------------------------------------
8862  */
8863 GdkGrabStatus
8864 gdk_pointer_grab (GdkWindow *     window,
8865                   gboolean        owner_events,
8866                   GdkEventMask    event_mask,
8867                   GdkWindow *     confine_to,
8868                   GdkCursor *     cursor,
8869                   guint32         time)
8870 {
8871   GdkWindow *native;
8872   GdkDisplay *display;
8873   GdkGrabStatus res;
8874   gulong serial;
8875
8876   g_return_val_if_fail (window != NULL, 0);
8877   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
8878   g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
8879
8880   /* We need a native window for confine to to work, ensure we have one */
8881   if (confine_to)
8882     {
8883       if (!gdk_window_ensure_native (confine_to))
8884         {
8885           g_warning ("Can't confine to grabbed window, not native");
8886           confine_to = NULL;
8887         }
8888     }
8889
8890   /* Non-viewable client side window => fail */
8891   if (!_gdk_window_has_impl (window) &&
8892       !gdk_window_is_viewable (window))
8893     return GDK_GRAB_NOT_VIEWABLE;
8894
8895   native = gdk_window_get_toplevel (window);
8896   while (gdk_window_is_offscreen ((GdkWindowObject *)native))
8897     {
8898       native = gdk_offscreen_window_get_embedder (native);
8899
8900       if (native == NULL ||
8901           (!_gdk_window_has_impl (native) &&
8902            !gdk_window_is_viewable (native)))
8903         return GDK_GRAB_NOT_VIEWABLE;
8904
8905       native = gdk_window_get_toplevel (native);
8906     }
8907
8908   display = gdk_drawable_get_display (window);
8909
8910   serial = _gdk_windowing_window_get_next_serial (display);
8911
8912   res = _gdk_windowing_pointer_grab (window,
8913                                      native,
8914                                      owner_events,
8915                                      event_mask,
8916                                      confine_to,
8917                                      cursor,
8918                                      time);
8919
8920   if (res == GDK_GRAB_SUCCESS)
8921     _gdk_display_add_pointer_grab (display,
8922                                    window,
8923                                    native,
8924                                    owner_events,
8925                                    event_mask,
8926                                    serial,
8927                                    time,
8928                                    FALSE);
8929
8930   return res;
8931 }
8932
8933 /**
8934  * gdk_window_geometry_changed:
8935  * @window: a #GdkWindow
8936  *
8937  * Since: 2.18
8938  */
8939 void
8940 gdk_window_geometry_changed (GdkWindow *window)
8941 {
8942   _gdk_synthesize_crossing_events_for_geometry_change (window);
8943 }
8944
8945 static gboolean
8946 do_synthesize_crossing_event (gpointer data)
8947 {
8948   GdkDisplay *display;
8949   GdkWindow *changed_toplevel;
8950   GdkWindowObject *changed_toplevel_priv;
8951   GdkWindow *new_window_under_pointer;
8952   gulong serial;
8953
8954   changed_toplevel = data;
8955   changed_toplevel_priv = (GdkWindowObject *)changed_toplevel;
8956
8957   changed_toplevel_priv->synthesize_crossing_event_queued = FALSE;
8958
8959   if (GDK_WINDOW_DESTROYED (changed_toplevel))
8960     return FALSE;
8961
8962   display = gdk_drawable_get_display (changed_toplevel);
8963   serial = _gdk_windowing_window_get_next_serial (display);
8964
8965   if (changed_toplevel == display->pointer_info.toplevel_under_pointer)
8966     {
8967       new_window_under_pointer =
8968         get_pointer_window (display, changed_toplevel,
8969                             display->pointer_info.toplevel_x,
8970                             display->pointer_info.toplevel_y,
8971                             serial);
8972       if (new_window_under_pointer !=
8973           display->pointer_info.window_under_pointer)
8974         {
8975           _gdk_synthesize_crossing_events (display,
8976                                            display->pointer_info.window_under_pointer,
8977                                            new_window_under_pointer,
8978                                            GDK_CROSSING_NORMAL,
8979                                            display->pointer_info.toplevel_x,
8980                                            display->pointer_info.toplevel_y,
8981                                            display->pointer_info.state,
8982                                            GDK_CURRENT_TIME,
8983                                            NULL,
8984                                            serial,
8985                                            FALSE);
8986           _gdk_display_set_window_under_pointer (display, new_window_under_pointer);
8987         }
8988     }
8989
8990   return FALSE;
8991 }
8992
8993 void
8994 _gdk_synthesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
8995 {
8996   GdkDisplay *display;
8997   GdkWindow *toplevel;
8998   GdkWindowObject *toplevel_priv;
8999
9000   display = gdk_drawable_get_display (changed_window);
9001
9002   toplevel = get_event_toplevel (changed_window);
9003   toplevel_priv = (GdkWindowObject *)toplevel;
9004
9005   if (toplevel == display->pointer_info.toplevel_under_pointer &&
9006       !toplevel_priv->synthesize_crossing_event_queued)
9007     {
9008       toplevel_priv->synthesize_crossing_event_queued = TRUE;
9009       g_idle_add_full (GDK_PRIORITY_EVENTS - 1,
9010                        do_synthesize_crossing_event,
9011                        g_object_ref (toplevel),
9012                        g_object_unref);
9013     }
9014 }
9015
9016 /* Don't use for crossing events */
9017 static GdkWindow *
9018 get_event_window (GdkDisplay                 *display,
9019                   GdkWindow                  *pointer_window,
9020                   GdkEventType                type,
9021                   GdkModifierType             mask,
9022                   guint                      *evmask_out,
9023                   gulong                      serial)
9024 {
9025   guint evmask;
9026   GdkWindow *grab_window;
9027   GdkWindowObject *w;
9028   GdkPointerGrabInfo *grab;
9029
9030   grab = _gdk_display_has_pointer_grab (display, serial);
9031
9032   if (grab != NULL && !grab->owner_events)
9033     {
9034       evmask = grab->event_mask;
9035       evmask = update_evmask_for_button_motion (evmask, mask);
9036
9037       grab_window = grab->window;
9038
9039       if (evmask & type_masks[type])
9040         {
9041           if (evmask_out)
9042             *evmask_out = evmask;
9043           return grab_window;
9044         }
9045       else
9046         return NULL;
9047     }
9048
9049   w = (GdkWindowObject *)pointer_window;
9050   while (w != NULL)
9051     {
9052       evmask = w->event_mask;
9053       evmask = update_evmask_for_button_motion (evmask, mask);
9054
9055       if (evmask & type_masks[type])
9056         {
9057           if (evmask_out)
9058             *evmask_out = evmask;
9059           return (GdkWindow *)w;
9060         }
9061
9062       w = get_event_parent (w);
9063     }
9064
9065   if (grab != NULL &&
9066       grab->owner_events)
9067     {
9068       evmask = grab->event_mask;
9069       evmask = update_evmask_for_button_motion (evmask, mask);
9070
9071       if (evmask & type_masks[type])
9072         {
9073           if (evmask_out)
9074             *evmask_out = evmask;
9075           return grab->window;
9076         }
9077       else
9078         return NULL;
9079     }
9080
9081   return NULL;
9082 }
9083
9084 static gboolean
9085 proxy_pointer_event (GdkDisplay                 *display,
9086                      GdkEvent                   *source_event,
9087                      gulong                      serial)
9088 {
9089   GdkWindow *toplevel_window, *event_window;
9090   GdkWindow *pointer_window;
9091   GdkEvent *event;
9092   guint state;
9093   gdouble toplevel_x, toplevel_y;
9094   guint32 time_;
9095   gboolean non_linear;
9096
9097   event_window = source_event->any.window;
9098   gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
9099   gdk_event_get_state (source_event, &state);
9100   time_ = gdk_event_get_time (source_event);
9101   toplevel_window = convert_native_coords_to_toplevel (event_window,
9102                                                        toplevel_x, toplevel_y,
9103                                                        &toplevel_x, &toplevel_y);
9104
9105   non_linear = FALSE;
9106   if ((source_event->type == GDK_LEAVE_NOTIFY ||
9107        source_event->type == GDK_ENTER_NOTIFY) &&
9108       (source_event->crossing.detail == GDK_NOTIFY_NONLINEAR ||
9109        source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))
9110     non_linear = TRUE;
9111
9112   /* If we get crossing events with subwindow unexpectedly being NULL
9113      that means there is a native subwindow that gdk doesn't know about.
9114      We track these and forward them, with the correct virtual window
9115      events inbetween.
9116      This is important to get right, as metacity uses gdk for the frame
9117      windows, but gdk doesn't know about the client windows reparented
9118      into the frame. */
9119   if (((source_event->type == GDK_LEAVE_NOTIFY &&
9120         source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
9121        (source_event->type == GDK_ENTER_NOTIFY &&
9122         (source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
9123          source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
9124       source_event->crossing.subwindow == NULL)
9125     {
9126       /* Left for an unknown (to gdk) subwindow */
9127
9128       /* Send leave events from window under pointer to event window
9129          that will get the subwindow == NULL window */
9130       _gdk_synthesize_crossing_events (display,
9131                                        display->pointer_info.window_under_pointer,
9132                                        event_window,
9133                                        source_event->crossing.mode,
9134                                        toplevel_x, toplevel_y,
9135                                        state, time_,
9136                                        source_event,
9137                                        serial,
9138                                        non_linear);
9139
9140       /* Send subwindow == NULL event */
9141       send_crossing_event (display,
9142                            (GdkWindowObject *)toplevel_window,
9143                            (GdkWindowObject *)event_window,
9144                            source_event->type,
9145                            source_event->crossing.mode,
9146                            source_event->crossing.detail,
9147                            NULL,
9148                            toplevel_x,   toplevel_y,
9149                            state, time_,
9150                            source_event,
9151                            serial);
9152
9153       _gdk_display_set_window_under_pointer (display, NULL);
9154       return TRUE;
9155     }
9156
9157   pointer_window = get_pointer_window (display, toplevel_window,
9158                                        toplevel_x, toplevel_y, serial);
9159
9160   if (((source_event->type == GDK_ENTER_NOTIFY &&
9161         source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
9162        (source_event->type == GDK_LEAVE_NOTIFY &&
9163         (source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
9164          source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
9165       source_event->crossing.subwindow == NULL)
9166     {
9167       /* Entered from an unknown (to gdk) subwindow */
9168
9169       /* Send subwindow == NULL event */
9170       send_crossing_event (display,
9171                            (GdkWindowObject *)toplevel_window,
9172                            (GdkWindowObject *)event_window,
9173                            source_event->type,
9174                            source_event->crossing.mode,
9175                            source_event->crossing.detail,
9176                            NULL,
9177                            toplevel_x,   toplevel_y,
9178                            state, time_,
9179                            source_event,
9180                            serial);
9181
9182       /* Send enter events from event window to pointer_window */
9183       _gdk_synthesize_crossing_events (display,
9184                                        event_window,
9185                                        pointer_window,
9186                                        source_event->crossing.mode,
9187                                        toplevel_x, toplevel_y,
9188                                        state, time_,
9189                                        source_event,
9190                                        serial, non_linear);
9191       _gdk_display_set_window_under_pointer (display, pointer_window);
9192       return TRUE;
9193     }
9194
9195   if (display->pointer_info.window_under_pointer != pointer_window)
9196     {
9197       /* Either a toplevel crossing notify that ended up inside a child window,
9198          or a motion notify that got into another child window  */
9199
9200       /* Different than last time, send crossing events */
9201       _gdk_synthesize_crossing_events (display,
9202                                        display->pointer_info.window_under_pointer,
9203                                        pointer_window,
9204                                        GDK_CROSSING_NORMAL,
9205                                        toplevel_x, toplevel_y,
9206                                        state, time_,
9207                                        source_event,
9208                                        serial, non_linear);
9209       _gdk_display_set_window_under_pointer (display, pointer_window);
9210     }
9211   else if (source_event->type == GDK_MOTION_NOTIFY)
9212     {
9213       GdkWindow *event_win;
9214       guint evmask;
9215       gboolean is_hint;
9216
9217       event_win = get_event_window (display,
9218                                     pointer_window,
9219                                     source_event->type,
9220                                     state,
9221                                     &evmask,
9222                                     serial);
9223
9224       is_hint = FALSE;
9225
9226       if (event_win &&
9227           (evmask & GDK_POINTER_MOTION_HINT_MASK))
9228         {
9229           if (display->pointer_info.motion_hint_serial != 0 &&
9230               serial < display->pointer_info.motion_hint_serial)
9231             event_win = NULL; /* Ignore event */
9232           else
9233             {
9234               is_hint = TRUE;
9235               display->pointer_info.motion_hint_serial = G_MAXULONG;
9236             }
9237         }
9238
9239       if (event_win && !display->ignore_core_events)
9240         {
9241           event = _gdk_make_event (event_win, GDK_MOTION_NOTIFY, source_event, FALSE);
9242           event->motion.time = time_;
9243           convert_toplevel_coords_to_window (event_win,
9244                                              toplevel_x, toplevel_y,
9245                                              &event->motion.x, &event->motion.y);
9246           event->motion.x_root = source_event->motion.x_root;
9247           event->motion.y_root = source_event->motion.y_root;;
9248           event->motion.state = state;
9249           event->motion.is_hint = is_hint;
9250           event->motion.device = NULL;
9251           event->motion.device = source_event->motion.device;
9252         }
9253     }
9254
9255   /* unlink all move events from queue.
9256      We handle our own, including our emulated masks. */
9257   return TRUE;
9258 }
9259
9260 #define GDK_ANY_BUTTON_MASK (GDK_BUTTON1_MASK | \
9261                              GDK_BUTTON2_MASK | \
9262                              GDK_BUTTON3_MASK | \
9263                              GDK_BUTTON4_MASK | \
9264                              GDK_BUTTON5_MASK)
9265
9266 static gboolean
9267 proxy_button_event (GdkEvent *source_event,
9268                     gulong serial)
9269 {
9270   GdkWindow *toplevel_window, *event_window;
9271   GdkWindow *event_win;
9272   GdkWindow *pointer_window;
9273   GdkWindowObject *parent;
9274   GdkEvent *event;
9275   guint state;
9276   guint32 time_;
9277   GdkEventType type;
9278   gdouble toplevel_x, toplevel_y;
9279   GdkDisplay *display;
9280   GdkWindowObject *w;
9281
9282   type = source_event->any.type;
9283   event_window = source_event->any.window;
9284   gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
9285   gdk_event_get_state (source_event, &state);
9286   time_ = gdk_event_get_time (source_event);
9287   display = gdk_drawable_get_display (source_event->any.window);
9288   toplevel_window = convert_native_coords_to_toplevel (event_window,
9289                                                        toplevel_x, toplevel_y,
9290                                                        &toplevel_x, &toplevel_y);
9291
9292   if (type == GDK_BUTTON_PRESS &&
9293       _gdk_display_has_pointer_grab (display, serial) == NULL)
9294     {
9295       pointer_window =
9296         _gdk_window_find_descendant_at (toplevel_window,
9297                                         toplevel_x, toplevel_y,
9298                                         NULL, NULL);
9299
9300       /* Find the event window, that gets the grab */
9301       w = (GdkWindowObject *)pointer_window;
9302       while (w != NULL &&
9303              (parent = get_event_parent (w)) != NULL &&
9304              parent->window_type != GDK_WINDOW_ROOT)
9305         {
9306           if (w->event_mask & GDK_BUTTON_PRESS_MASK)
9307             break;
9308           w = parent;
9309         }
9310       pointer_window = (GdkWindow *)w;
9311
9312       _gdk_display_add_pointer_grab  (display,
9313                                       pointer_window,
9314                                       toplevel_window,
9315                                       FALSE,
9316                                       gdk_window_get_events (pointer_window),
9317                                       serial,
9318                                       time_,
9319                                       TRUE);
9320       _gdk_display_pointer_grab_update (display, serial);
9321     }
9322
9323   pointer_window = get_pointer_window (display, toplevel_window,
9324                                        toplevel_x, toplevel_y,
9325                                        serial);
9326
9327   event_win = get_event_window (display,
9328                                 pointer_window,
9329                                 type, state,
9330                                 NULL, serial);
9331
9332   if (event_win == NULL || display->ignore_core_events)
9333     return TRUE;
9334
9335   event = _gdk_make_event (event_win, type, source_event, FALSE);
9336
9337   switch (type)
9338     {
9339     case GDK_BUTTON_PRESS:
9340     case GDK_BUTTON_RELEASE:
9341       event->button.button = source_event->button.button;
9342       convert_toplevel_coords_to_window (event_win,
9343                                          toplevel_x, toplevel_y,
9344                                          &event->button.x, &event->button.y);
9345       event->button.x_root = source_event->button.x_root;
9346       event->button.y_root = source_event->button.y_root;
9347       event->button.state = state;
9348       event->button.device = source_event->button.device;
9349
9350       if (type == GDK_BUTTON_PRESS)
9351         _gdk_event_button_generate (display, event);
9352       return TRUE;
9353
9354     case GDK_SCROLL:
9355       event->scroll.direction = source_event->scroll.direction;
9356       convert_toplevel_coords_to_window (event_win,
9357                                          toplevel_x, toplevel_y,
9358                                          &event->scroll.x, &event->scroll.y);
9359       event->scroll.x_root = source_event->scroll.x_root;
9360       event->scroll.y_root = source_event->scroll.y_root;
9361       event->scroll.state = state;
9362       event->scroll.device = source_event->scroll.device;
9363       return TRUE;
9364
9365     default:
9366       return FALSE;
9367     }
9368
9369   return TRUE; /* Always unlink original, we want to obey the emulated event mask */
9370 }
9371
9372 #ifdef DEBUG_WINDOW_PRINTING
9373 static void
9374 gdk_window_print (GdkWindowObject *window,
9375                   int indent)
9376 {
9377   GdkRectangle r;
9378
9379   g_print ("%*s%p: [%s] %d,%d %dx%d", indent, "", window,
9380            window->user_data ? g_type_name_from_instance (window->user_data) : "no widget",
9381            window->x, window->y,
9382            window->width, window->height
9383            );
9384
9385   if (gdk_window_has_impl (window))
9386     {
9387 #ifdef GDK_WINDOWING_X11
9388       g_print (" impl(0x%lx)", gdk_x11_drawable_get_xid (GDK_DRAWABLE (window)));
9389 #endif
9390     }
9391
9392   if (window->input_only)
9393     g_print (" input-only");
9394
9395   if (!gdk_window_is_visible ((GdkWindow *)window))
9396     g_print (" hidden");
9397
9398   g_print (" abs[%d,%d]",
9399            window->abs_x, window->abs_y);
9400
9401   gdk_region_get_clipbox (window->clip_region, &r);
9402   if (gdk_region_empty (window->clip_region))
9403     g_print (" clipbox[empty]");
9404   else
9405     g_print (" clipbox[%d,%d %dx%d]", r.x, r.y, r.width, r.height);
9406
9407   g_print ("\n");
9408 }
9409
9410
9411 static void
9412 gdk_window_print_tree (GdkWindow *window,
9413                        int indent,
9414                        gboolean include_input_only)
9415 {
9416   GdkWindowObject *private;
9417   GList *l;
9418
9419   private = (GdkWindowObject *)window;
9420
9421   if (private->input_only && !include_input_only)
9422     return;
9423
9424   gdk_window_print (private, indent);
9425
9426   for (l = private->children; l != NULL; l = l->next)
9427     gdk_window_print_tree (l->data, indent + 4, include_input_only);
9428 }
9429
9430 #endif /* DEBUG_WINDOW_PRINTING */
9431
9432 static gboolean
9433 is_input_event (GdkDisplay *display,
9434                 GdkEvent *event)
9435 {
9436   GdkDevice *core_pointer;
9437
9438   core_pointer = gdk_display_get_core_pointer (display);
9439   if ((event->type == GDK_MOTION_NOTIFY &&
9440        event->motion.device != core_pointer) ||
9441       ((event->type == GDK_BUTTON_PRESS ||
9442         event->type == GDK_BUTTON_RELEASE) &&
9443        event->button.device != core_pointer))
9444     return TRUE;
9445   return FALSE;
9446 }
9447
9448 void
9449 _gdk_windowing_got_event (GdkDisplay *display,
9450                           GList      *event_link,
9451                           GdkEvent   *event,
9452                           gulong      serial)
9453 {
9454   GdkWindow *event_window;
9455   GdkWindowObject *event_private;
9456   gdouble x, y;
9457   gboolean unlink_event;
9458   guint old_state, old_button;
9459   GdkPointerGrabInfo *button_release_grab;
9460   gboolean is_toplevel;
9461
9462   if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
9463     display->last_event_time = gdk_event_get_time (event);
9464
9465   _gdk_display_pointer_grab_update (display,
9466                                     serial);
9467
9468   event_window = event->any.window;
9469   if (!event_window)
9470     return;
9471
9472   event_private = GDK_WINDOW_OBJECT (event_window);
9473
9474 #ifdef DEBUG_WINDOW_PRINTING
9475   if (event->type == GDK_KEY_PRESS &&
9476       (event->key.keyval == 0xa7 ||
9477        event->key.keyval == 0xbd))
9478     {
9479       gdk_window_print_tree (event_window, 0,
9480                              event->key.keyval == 0xbd);
9481     }
9482 #endif
9483
9484   if (event->type == GDK_VISIBILITY_NOTIFY)
9485     {
9486       event_private->native_visibility = event->visibility.state;
9487       gdk_window_update_visibility_recursively (event_private,
9488                                                 event_private);
9489       return;
9490     }
9491
9492   if (is_input_event (display, event))
9493     return;
9494
9495   if (!(is_button_type (event->type) ||
9496         is_motion_type (event->type)) ||
9497       event_private->window_type == GDK_WINDOW_ROOT)
9498     return;
9499
9500   is_toplevel =
9501     event_private->parent == NULL ||
9502     event_private->parent->window_type == GDK_WINDOW_ROOT;
9503
9504   if ((event->type == GDK_ENTER_NOTIFY ||
9505        event->type == GDK_LEAVE_NOTIFY) &&
9506       (event->crossing.mode == GDK_CROSSING_GRAB ||
9507        event->crossing.mode == GDK_CROSSING_UNGRAB) &&
9508       (_gdk_display_has_pointer_grab (display, serial) ||
9509        event->crossing.detail == GDK_NOTIFY_INFERIOR))
9510     {
9511       /* We synthesize all crossing events due to grabs ourselves,
9512        * so we ignore the native ones caused by our native pointer_grab
9513        * calls. Otherwise we would proxy these crossing event and cause
9514        * multiple copies of crossing events for grabs.
9515        *
9516        * We do want to handle grabs from other clients though, as for
9517        * instance alt-tab in metacity causes grabs like these and
9518        * we want to handle those. Thus the has_pointer_grab check.
9519        *
9520        * Implicit grabs on child windows create some grabbing events
9521        * that are sent before the button press. This means we can't
9522        * detect these with the has_pointer_grab check (as the implicit
9523        * grab is only noticed when we get button press event), so we
9524        * detect these events by checking for INFERIOR enter or leave
9525        * events. These should never be a problem to filter out.
9526        */
9527
9528       /* We ended up in this window after some (perhaps other clients)
9529          grab, so update the toplevel_under_window state */
9530       if (is_toplevel &&
9531           event->type == GDK_ENTER_NOTIFY &&
9532           event->crossing.mode == GDK_CROSSING_UNGRAB)
9533         {
9534           if (display->pointer_info.toplevel_under_pointer)
9535             g_object_unref (display->pointer_info.toplevel_under_pointer);
9536           display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
9537         }
9538
9539       unlink_event = TRUE;
9540       goto out;
9541     }
9542
9543   /* Track toplevel_under_pointer */
9544   if (is_toplevel)
9545     {
9546       if (event->type == GDK_ENTER_NOTIFY &&
9547           event->crossing.detail != GDK_NOTIFY_INFERIOR)
9548         {
9549           if (display->pointer_info.toplevel_under_pointer)
9550             g_object_unref (display->pointer_info.toplevel_under_pointer);
9551           display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
9552         }
9553       else if (event->type == GDK_LEAVE_NOTIFY &&
9554                event->crossing.detail != GDK_NOTIFY_INFERIOR &&
9555                display->pointer_info.toplevel_under_pointer == event_window)
9556         {
9557           if (display->pointer_info.toplevel_under_pointer)
9558             g_object_unref (display->pointer_info.toplevel_under_pointer);
9559           display->pointer_info.toplevel_under_pointer = NULL;
9560         }
9561     }
9562
9563   /* Store last pointer window and position/state */
9564   old_state = display->pointer_info.state;
9565   old_button = display->pointer_info.button;
9566
9567   gdk_event_get_coords (event, &x, &y);
9568   convert_native_coords_to_toplevel (event_window, x, y,  &x, &y);
9569   display->pointer_info.toplevel_x = x;
9570   display->pointer_info.toplevel_y = y;
9571   gdk_event_get_state (event, &display->pointer_info.state);
9572   if (event->type == GDK_BUTTON_PRESS ||
9573       event->type == GDK_BUTTON_RELEASE)
9574     display->pointer_info.button = event->button.button;
9575
9576   if (display->pointer_info.state != old_state ||
9577       display->pointer_info.button != old_button)
9578     _gdk_display_enable_motion_hints (display);
9579
9580   unlink_event = FALSE;
9581   if (is_motion_type (event->type))
9582     unlink_event = proxy_pointer_event (display,
9583                                         event,
9584                                         serial);
9585   else if (is_button_type (event->type))
9586     unlink_event = proxy_button_event (event,
9587                                        serial);
9588
9589   if (event->type == GDK_BUTTON_RELEASE)
9590     {
9591       button_release_grab =
9592         _gdk_display_has_pointer_grab (display, serial);
9593       if (button_release_grab &&
9594           button_release_grab->implicit &&
9595           (event->button.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
9596         {
9597           button_release_grab->serial_end = serial;
9598           button_release_grab->implicit_ungrab = TRUE;
9599           _gdk_display_pointer_grab_update (display, serial);
9600         }
9601     }
9602
9603  out:
9604   if (unlink_event)
9605     {
9606       _gdk_event_queue_remove_link (display, event_link);
9607       g_list_free_1 (event_link);
9608       gdk_event_free (event);
9609     }
9610 }
9611
9612
9613 static GdkWindow *
9614 get_extension_event_window (GdkDisplay                 *display,
9615                             GdkWindow                  *pointer_window,
9616                             GdkEventType                type,
9617                             gulong                      serial)
9618 {
9619   guint evmask;
9620   GdkWindow *grab_window;
9621   GdkWindowObject *w;
9622   GdkPointerGrabInfo *grab;
9623
9624   grab = _gdk_display_has_pointer_grab (display, serial);
9625
9626   if (grab != NULL && !grab->owner_events)
9627     {
9628       evmask = grab->event_mask;
9629
9630       grab_window = grab->window;
9631
9632       if (evmask & type_masks[type])
9633         return grab_window;
9634       else
9635         return NULL;
9636     }
9637
9638   w = (GdkWindowObject *)pointer_window;
9639   while (w != NULL)
9640     {
9641       evmask = w->extension_events;
9642
9643       if (evmask & type_masks[type])
9644         return (GdkWindow *)w;
9645
9646       w = get_event_parent (w);
9647     }
9648
9649   if (grab != NULL &&
9650       grab->owner_events)
9651     {
9652       evmask = grab->event_mask;
9653
9654       if (evmask & type_masks[type])
9655         return grab->window;
9656       else
9657         return NULL;
9658     }
9659
9660   return NULL;
9661 }
9662
9663
9664 GdkWindow *
9665 _gdk_window_get_input_window_for_event (GdkWindow *native_window,
9666                                         GdkEventType event_type,
9667                                         int x, int y,
9668                                         gulong serial)
9669 {
9670   GdkDisplay *display;
9671   GdkWindow *toplevel_window;
9672   GdkWindow *pointer_window;
9673   GdkWindow *event_win;
9674   gdouble toplevel_x, toplevel_y;
9675
9676   toplevel_x = x;
9677   toplevel_y = y;
9678
9679   display = gdk_drawable_get_display (native_window);
9680   toplevel_window = convert_native_coords_to_toplevel (native_window,
9681                                                        toplevel_x, toplevel_y,
9682                                                        &toplevel_x, &toplevel_y);
9683   pointer_window = get_pointer_window (display, toplevel_window,
9684                                        toplevel_x, toplevel_y, serial);
9685   event_win = get_extension_event_window (display,
9686                                           pointer_window,
9687                                           event_type,
9688                                           serial);
9689
9690   return event_win;
9691 }
9692
9693
9694 #define __GDK_WINDOW_C__
9695 #include "gdkaliasdef.c"