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