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