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