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