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