 0c72ce94ea
			
		
	
	0c72ce94ea
	
	
	
		
			
			Checking for offscreen windows with gdk_window_is_offscreen () is not enough in this case. What we want here is that the impl classes match, as backends are meant to know only about their windows. Instead gdk_window_is_offscreen () checks whether the GdkWindow.window_type field is GDK_WINDOW_OFFSCREEN. In the case of child windows in offscreen windows, the window type is GDK_WINDOW_CHILD, even though their impl is still GdkOffscreenWindow. So actually check whether GDK_WINDOW_IMPL_GET_CLASS (window) matches GDK_WINDOW_IMPL_GET_CLASS (parent). We may also consider getting the toplevels from child windows, as transient-for relationships are really about toplevels, but child windows doesn't seem to cause problems in practice.
		
			
				
	
	
		
			12024 lines
		
	
	
		
			355 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			12024 lines
		
	
	
		
			355 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* GDK - The GIMP Drawing Kit
 | ||
|  * Copyright (C) 1995-2007 Peter Mattis, Spencer Kimball,
 | ||
|  * Josh MacDonald, Ryan Lortie
 | ||
|  *
 | ||
|  * This library is free software; you can redistribute it and/or
 | ||
|  * modify it under the terms of the GNU Lesser General Public
 | ||
|  * License as published by the Free Software Foundation; either
 | ||
|  * version 2 of the License, or (at your option) any later version.
 | ||
|  *
 | ||
|  * This library is distributed in the hope that it will be useful,
 | ||
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | ||
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | ||
|  * Lesser General Public License for more details.
 | ||
|  *
 | ||
|  * You should have received a copy of the GNU Lesser General Public
 | ||
|  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 | ||
|  */
 | ||
| 
 | ||
| /*
 | ||
|  * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
 | ||
|  * file for a list of people on the GTK+ Team.  See the ChangeLog
 | ||
|  * files for a list of changes.  These files are distributed with
 | ||
|  * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
 | ||
|  */
 | ||
| 
 | ||
| #include "config.h"
 | ||
| 
 | ||
| #include <cairo-gobject.h>
 | ||
| 
 | ||
| #include "gdkwindow.h"
 | ||
| 
 | ||
| #include "gdkrectangle.h"
 | ||
| #include "gdkinternals.h"
 | ||
| #include "gdkintl.h"
 | ||
| #include "gdkscreenprivate.h"
 | ||
| #include "gdkdisplayprivate.h"
 | ||
| #include "gdkdeviceprivate.h"
 | ||
| #include "gdkvisualprivate.h"
 | ||
| #include "gdkmarshalers.h"
 | ||
| #include "gdkframeclockidle.h"
 | ||
| #include "gdkwindowimpl.h"
 | ||
| #include "gdkglcontextprivate.h"
 | ||
| #include "gdkdrawingcontextprivate.h"
 | ||
| #include "gdk-private.h"
 | ||
| 
 | ||
| #include <math.h>
 | ||
| 
 | ||
| #include <epoxy/gl.h>
 | ||
| 
 | ||
| /* for the use of round() */
 | ||
| #include "fallback-c89.c"
 | ||
| 
 | ||
| #ifdef GDK_WINDOWING_WAYLAND
 | ||
| #include "wayland/gdkwayland.h"
 | ||
| #endif
 | ||
| 
 | ||
| #undef DEBUG_WINDOW_PRINTING
 | ||
| 
 | ||
| 
 | ||
| /**
 | ||
|  * SECTION:windows
 | ||
|  * @Short_description: Onscreen display areas in the target window system
 | ||
|  * @Title: Windows
 | ||
|  *
 | ||
|  * A #GdkWindow is a (usually) rectangular region on the screen.
 | ||
|  * It’s a low-level object, used to implement high-level objects such as
 | ||
|  * #GtkWidget and #GtkWindow on the GTK+ level. A #GtkWindow is a toplevel
 | ||
|  * window, the thing a user might think of as a “window” with a titlebar
 | ||
|  * and so on; a #GtkWindow may contain many #GdkWindows. For example,
 | ||
|  * each #GtkButton has a #GdkWindow associated with it.
 | ||
|  *
 | ||
|  * # Composited Windows # {#COMPOSITED-WINDOWS}
 | ||
|  *
 | ||
|  * Normally, the windowing system takes care of rendering the contents
 | ||
|  * of a child window onto its parent window. This mechanism can be
 | ||
|  * intercepted by calling gdk_window_set_composited() on the child
 | ||
|  * window. For a “composited” window it is the
 | ||
|  * responsibility of the application to render the window contents at
 | ||
|  * the right spot.
 | ||
|  *
 | ||
|  * # Offscreen Windows # {#OFFSCREEN-WINDOWS}
 | ||
|  *
 | ||
|  * Offscreen windows are more general than composited windows, since
 | ||
|  * they allow not only to modify the rendering of the child window onto
 | ||
|  * its parent, but also to apply coordinate transformations.
 | ||
|  *
 | ||
|  * To integrate an offscreen window into a window hierarchy, one has
 | ||
|  * to call gdk_offscreen_window_set_embedder() and handle a number of
 | ||
|  * signals. The #GdkWindow::pick-embedded-child signal on the embedder
 | ||
|  * window is used to select an offscreen child at given coordinates,
 | ||
|  * and the #GdkWindow::to-embedder and #GdkWindow::from-embedder signals
 | ||
|  * on the offscreen window are used to translate coordinates between
 | ||
|  * the embedder and the offscreen window.
 | ||
|  *
 | ||
|  * For rendering an offscreen window onto its embedder, the contents
 | ||
|  * of the offscreen window are available as a surface, via
 | ||
|  * gdk_offscreen_window_get_surface().
 | ||
|  */
 | ||
| 
 | ||
| 
 | ||
| /* Historically a GdkWindow always matches a platform native window,
 | ||
|  * be it a toplevel window or a child window. In this setup the
 | ||
|  * GdkWindow (and other GdkDrawables) were platform independent classes,
 | ||
|  * and the actual platform specific implementation was in a delegate
 | ||
|  * object available as “impl” in the window object.
 | ||
|  *
 | ||
|  * With the addition of client side windows and offscreen windows this
 | ||
|  * changes a bit. The application-visible GdkWindow object behaves as
 | ||
|  * it did before, but not all such windows now have a corresponding native
 | ||
|  * window. Instead windows that are “client side” are emulated by the gdk
 | ||
|  * code such that clipping, drawing, moving, events etc work as expected.
 | ||
|  *
 | ||
|  * For GdkWindows that have a native window the “impl” object is the
 | ||
|  * same as before. However, for all client side windows the impl object
 | ||
|  * is shared with its parent (i.e. all client windows descendants of one
 | ||
|  * native window has the same impl.
 | ||
|  *
 | ||
|  * Additionally there is a new type of platform independent impl object,
 | ||
|  * GdkOffscreenWindow. All windows of type GDK_WINDOW_OFFSCREEN get an impl
 | ||
|  * of this type (while their children are generally GDK_WINDOW_CHILD virtual
 | ||
|  * windows). Such windows work by allocating a #cairo_surface_t as the backing
 | ||
|  * store for drawing operations, which is resized with the window.
 | ||
|  *
 | ||
|  * GdkWindows have a pointer to the “impl window” they are in, i.e.
 | ||
|  * the topmost GdkWindow which have the same “impl” value. This is stored
 | ||
|  * in impl_window, which is different from the window itself only for client
 | ||
|  * side windows.
 | ||
|  * All GdkWindows (native or not) track the position of the window in the parent
 | ||
|  * (x, y), the size of the window (width, height), the position of the window
 | ||
|  * with respect to the impl window (abs_x, abs_y). We also track the clip
 | ||
|  * region of the window wrt parent windows, in window-relative coordinates (clip_region).
 | ||
|  *
 | ||
|  * All toplevel windows are native windows, but also child windows can be
 | ||
|  * native (although not children of offscreens). We always listen to
 | ||
|  * a basic set of events (see get_native_event_mask) for these windows
 | ||
|  * so that we can emulate events for any client side children.
 | ||
|  *
 | ||
|  * For native windows we apply the calculated clip region as a window shape
 | ||
|  * so that eg. client side siblings that overlap the native child properly
 | ||
|  * draws over the native child window.
 | ||
|  */
 | ||
| 
 | ||
| /* This adds a local value to the GdkVisibilityState enum */
 | ||
| #define GDK_VISIBILITY_NOT_VIEWABLE 3
 | ||
| 
 | ||
| enum {
 | ||
|   PICK_EMBEDDED_CHILD, /* only called if children are embedded */
 | ||
|   TO_EMBEDDER,
 | ||
|   FROM_EMBEDDER,
 | ||
|   CREATE_SURFACE,
 | ||
|   MOVED_TO_RECT,
 | ||
|   LAST_SIGNAL
 | ||
| };
 | ||
| 
 | ||
| enum {
 | ||
|   PROP_0,
 | ||
|   PROP_CURSOR,
 | ||
|   LAST_PROP
 | ||
| };
 | ||
| 
 | ||
| /* Global info */
 | ||
| 
 | ||
| static void gdk_window_finalize   (GObject              *object);
 | ||
| 
 | ||
| static void gdk_window_set_property (GObject      *object,
 | ||
|                                      guint         prop_id,
 | ||
|                                      const GValue *value,
 | ||
|                                      GParamSpec   *pspec);
 | ||
| static void gdk_window_get_property (GObject      *object,
 | ||
|                                      guint         prop_id,
 | ||
|                                      GValue       *value,
 | ||
|                                      GParamSpec   *pspec);
 | ||
| 
 | ||
| static void gdk_window_clear_backing_region (GdkWindow *window);
 | ||
| 
 | ||
| static void recompute_visible_regions   (GdkWindow *private,
 | ||
| 					 gboolean recalculate_children);
 | ||
| static void gdk_window_invalidate_in_parent (GdkWindow *private);
 | ||
| static void move_native_children        (GdkWindow *private);
 | ||
| static void update_cursor               (GdkDisplay *display,
 | ||
|                                          GdkDevice  *device);
 | ||
| static void impl_window_add_update_area (GdkWindow *impl_window,
 | ||
| 					 cairo_region_t *region);
 | ||
| static void gdk_window_invalidate_region_full (GdkWindow       *window,
 | ||
| 					       const cairo_region_t *region,
 | ||
| 					       gboolean         invalidate_children);
 | ||
| static void gdk_window_invalidate_rect_full (GdkWindow          *window,
 | ||
| 					     const GdkRectangle *rect,
 | ||
| 					     gboolean            invalidate_children);
 | ||
| static cairo_surface_t *gdk_window_ref_impl_surface (GdkWindow *window);
 | ||
| 
 | ||
| static void gdk_window_set_frame_clock (GdkWindow      *window,
 | ||
|                                         GdkFrameClock  *clock);
 | ||
| 
 | ||
| static void draw_ugly_color (GdkWindow       *window,
 | ||
|                              const cairo_region_t *region,
 | ||
|                              int color);
 | ||
| 
 | ||
| 
 | ||
| static guint signals[LAST_SIGNAL] = { 0 };
 | ||
| static GParamSpec *properties[LAST_PROP] = { NULL, };
 | ||
| 
 | ||
| G_DEFINE_ABSTRACT_TYPE (GdkWindow, gdk_window, G_TYPE_OBJECT)
 | ||
| 
 | ||
| #ifdef DEBUG_WINDOW_PRINTING
 | ||
| char *
 | ||
| print_region (cairo_region_t *region)
 | ||
| {
 | ||
|   GString *s = g_string_new ("{");
 | ||
|   if (cairo_region_is_empty (region))
 | ||
|     {
 | ||
|       g_string_append (s, "empty");
 | ||
|     }
 | ||
|   else
 | ||
|     {
 | ||
|       int num = cairo_region_num_rectangles (region);
 | ||
|       cairo_rectangle_int_t r;
 | ||
| 
 | ||
|       if (num == 1)
 | ||
| 	{
 | ||
| 	  cairo_region_get_rectangle (region, 0, &r);
 | ||
| 	  g_string_append_printf (s, "%dx%d @%d,%d", r.width, r.height, r.x, r.y);
 | ||
| 	}
 | ||
|       else
 | ||
| 	{
 | ||
| 	  int i;
 | ||
| 	  cairo_region_get_extents (region, &r);
 | ||
| 	  g_string_append_printf (s, "extent: %dx%d @%d,%d, details: ", r.width, r.height, r.x, r.y);
 | ||
| 	  for (i = 0; i < num; i++)
 | ||
| 	    {
 | ||
|               cairo_region_get_rectangle (region, i, &r);
 | ||
| 	      g_string_append_printf (s, "[%dx%d @%d,%d]", r.width, r.height, r.x, r.y);
 | ||
| 	      if (i != num -1)
 | ||
| 		g_string_append (s, ", ");
 | ||
| 	    }
 | ||
| 	}
 | ||
|     }
 | ||
|   g_string_append (s, "}");
 | ||
|   return g_string_free (s, FALSE);
 | ||
| }
 | ||
| #endif
 | ||
| 
 | ||
| static GList *
 | ||
| list_insert_link_before (GList *list,
 | ||
|                          GList *sibling,
 | ||
|                          GList *link)
 | ||
| {
 | ||
|   if (list == NULL || sibling == list)
 | ||
|     {
 | ||
|       link->prev = NULL;
 | ||
|       link->next = list;
 | ||
|       if (list)
 | ||
|         list->prev = link;
 | ||
|       return link;
 | ||
|     }
 | ||
|   else if (sibling == NULL)
 | ||
|     {
 | ||
|       GList *last = g_list_last (list);
 | ||
| 
 | ||
|       last->next = link;
 | ||
|       link->prev = last;
 | ||
|       link->next = NULL;
 | ||
| 
 | ||
|       return list;
 | ||
|     }
 | ||
|   else
 | ||
|     {
 | ||
|       link->next = sibling;
 | ||
|       link->prev = sibling->prev;
 | ||
|       sibling->prev = link;
 | ||
| 
 | ||
|       if (link->prev)
 | ||
|         link->prev->next = link;
 | ||
| 
 | ||
|       return list;
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_init (GdkWindow *window)
 | ||
| {
 | ||
|   /* 0-initialization is good for all other fields. */
 | ||
| 
 | ||
|   window->window_type = GDK_WINDOW_CHILD;
 | ||
| 
 | ||
|   window->state = GDK_WINDOW_STATE_WITHDRAWN;
 | ||
|   window->fullscreen_mode = GDK_FULLSCREEN_ON_CURRENT_MONITOR;
 | ||
|   window->width = 1;
 | ||
|   window->height = 1;
 | ||
|   window->toplevel_window_type = -1;
 | ||
|   /* starts hidden */
 | ||
|   window->effective_visibility = GDK_VISIBILITY_NOT_VIEWABLE;
 | ||
|   window->visibility = GDK_VISIBILITY_FULLY_OBSCURED;
 | ||
|   /* Default to unobscured since some backends don't send visibility events */
 | ||
|   window->native_visibility = GDK_VISIBILITY_UNOBSCURED;
 | ||
|   window->children_list_node.data = window;
 | ||
| 
 | ||
|   window->device_cursor = g_hash_table_new_full (NULL, NULL,
 | ||
|                                                  NULL, g_object_unref);
 | ||
| }
 | ||
| 
 | ||
| /* Stop and return on the first non-NULL parent */
 | ||
| static gboolean
 | ||
| accumulate_get_window (GSignalInvocationHint *ihint,
 | ||
| 		       GValue		       *return_accu,
 | ||
| 		       const GValue	       *handler_return,
 | ||
| 		       gpointer               data)
 | ||
| {
 | ||
|   g_value_copy (handler_return, return_accu);
 | ||
|   /* Continue while returning NULL */
 | ||
|   return g_value_get_object (handler_return) == NULL;
 | ||
| }
 | ||
| 
 | ||
| static gboolean
 | ||
| create_surface_accumulator (GSignalInvocationHint *ihint,
 | ||
|                             GValue                *return_accu,
 | ||
|                             const GValue          *handler_return,
 | ||
|                             gpointer               data)
 | ||
| {
 | ||
|   g_value_copy (handler_return, return_accu);
 | ||
| 
 | ||
|   /* Stop on the first non-NULL return value */
 | ||
|   return g_value_get_boxed (handler_return) == NULL;
 | ||
| }
 | ||
| 
 | ||
| static GQuark quark_pointer_window = 0;
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_class_init (GdkWindowClass *klass)
 | ||
| {
 | ||
|   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 | ||
| 
 | ||
|   object_class->finalize = gdk_window_finalize;
 | ||
|   object_class->set_property = gdk_window_set_property;
 | ||
|   object_class->get_property = gdk_window_get_property;
 | ||
| 
 | ||
|   klass->create_surface = _gdk_offscreen_window_create_surface;
 | ||
| 
 | ||
|   quark_pointer_window = g_quark_from_static_string ("gtk-pointer-window");
 | ||
| 
 | ||
| 
 | ||
|   /* Properties */
 | ||
| 
 | ||
|   /**
 | ||
|    * GdkWindow:cursor:
 | ||
|    *
 | ||
|    * The mouse pointer for a #GdkWindow. See gdk_window_set_cursor() and
 | ||
|    * gdk_window_get_cursor() for details.
 | ||
|    *
 | ||
|    * Since: 2.18
 | ||
|    */
 | ||
|   properties[PROP_CURSOR] =
 | ||
|       g_param_spec_object ("cursor",
 | ||
|                            P_("Cursor"),
 | ||
|                            P_("Cursor"),
 | ||
|                            GDK_TYPE_CURSOR,
 | ||
|                            G_PARAM_READWRITE);
 | ||
|   g_object_class_install_properties (object_class, LAST_PROP, properties);
 | ||
| 
 | ||
|   /**
 | ||
|    * GdkWindow::pick-embedded-child:
 | ||
|    * @window: the window on which the signal is emitted
 | ||
|    * @x: x coordinate in the window
 | ||
|    * @y: y coordinate in the window
 | ||
|    *
 | ||
|    * The ::pick-embedded-child signal is emitted to find an embedded
 | ||
|    * child at the given position.
 | ||
|    *
 | ||
|    * Returns: (nullable) (transfer none): the #GdkWindow of the
 | ||
|    *     embedded child at @x, @y, or %NULL
 | ||
|    *
 | ||
|    * Since: 2.18
 | ||
|    */
 | ||
|   signals[PICK_EMBEDDED_CHILD] =
 | ||
|     g_signal_new (g_intern_static_string ("pick-embedded-child"),
 | ||
| 		  G_OBJECT_CLASS_TYPE (object_class),
 | ||
| 		  G_SIGNAL_RUN_LAST,
 | ||
|                   G_STRUCT_OFFSET (GdkWindowClass, pick_embedded_child),
 | ||
| 		  accumulate_get_window, NULL,
 | ||
| 		  _gdk_marshal_OBJECT__DOUBLE_DOUBLE,
 | ||
| 		  GDK_TYPE_WINDOW,
 | ||
| 		  2,
 | ||
| 		  G_TYPE_DOUBLE,
 | ||
| 		  G_TYPE_DOUBLE);
 | ||
|   g_signal_set_va_marshaller (signals[PICK_EMBEDDED_CHILD],
 | ||
|                               G_OBJECT_CLASS_TYPE (object_class),
 | ||
|                               _gdk_marshal_OBJECT__DOUBLE_DOUBLEv);
 | ||
| 
 | ||
|   /**
 | ||
|    * GdkWindow::to-embedder:
 | ||
|    * @window: the offscreen window on which the signal is emitted
 | ||
|    * @offscreen_x: x coordinate in the offscreen window
 | ||
|    * @offscreen_y: y coordinate in the offscreen window
 | ||
|    * @embedder_x: (out) (type double): return location for the x
 | ||
|    *     coordinate in the embedder window
 | ||
|    * @embedder_y: (out) (type double): return location for the y
 | ||
|    *     coordinate in the embedder window
 | ||
|    *
 | ||
|    * The ::to-embedder signal is emitted to translate coordinates
 | ||
|    * in an offscreen window to its embedder.
 | ||
|    *
 | ||
|    * See also #GdkWindow::from-embedder.
 | ||
|    *
 | ||
|    * Since: 2.18
 | ||
|    */
 | ||
|   signals[TO_EMBEDDER] =
 | ||
|     g_signal_new (g_intern_static_string ("to-embedder"),
 | ||
| 		  G_OBJECT_CLASS_TYPE (object_class),
 | ||
| 		  G_SIGNAL_RUN_LAST,
 | ||
|                   G_STRUCT_OFFSET (GdkWindowClass, to_embedder),
 | ||
| 		  NULL, NULL,
 | ||
| 		  _gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
 | ||
| 		  G_TYPE_NONE,
 | ||
| 		  4,
 | ||
| 		  G_TYPE_DOUBLE,
 | ||
| 		  G_TYPE_DOUBLE,
 | ||
| 		  G_TYPE_POINTER,
 | ||
| 		  G_TYPE_POINTER);
 | ||
|   g_signal_set_va_marshaller (signals[TO_EMBEDDER],
 | ||
|                               G_OBJECT_CLASS_TYPE (object_class),
 | ||
|                               _gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTERv);
 | ||
| 
 | ||
|   /**
 | ||
|    * GdkWindow::from-embedder:
 | ||
|    * @window: the offscreen window on which the signal is emitted
 | ||
|    * @embedder_x: x coordinate in the embedder window
 | ||
|    * @embedder_y: y coordinate in the embedder window
 | ||
|    * @offscreen_x: (out) (type double): return location for the x
 | ||
|    *     coordinate in the offscreen window
 | ||
|    * @offscreen_y: (out) (type double): return location for the y
 | ||
|    *     coordinate in the offscreen window
 | ||
|    *
 | ||
|    * The ::from-embedder signal is emitted to translate coordinates
 | ||
|    * in the embedder of an offscreen window to the offscreen window.
 | ||
|    *
 | ||
|    * See also #GdkWindow::to-embedder.
 | ||
|    *
 | ||
|    * Since: 2.18
 | ||
|    */
 | ||
|   signals[FROM_EMBEDDER] =
 | ||
|     g_signal_new (g_intern_static_string ("from-embedder"),
 | ||
| 		  G_OBJECT_CLASS_TYPE (object_class),
 | ||
| 		  G_SIGNAL_RUN_LAST,
 | ||
|                   G_STRUCT_OFFSET (GdkWindowClass, from_embedder),
 | ||
| 		  NULL, NULL,
 | ||
| 		  _gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
 | ||
| 		  G_TYPE_NONE,
 | ||
| 		  4,
 | ||
| 		  G_TYPE_DOUBLE,
 | ||
| 		  G_TYPE_DOUBLE,
 | ||
| 		  G_TYPE_POINTER,
 | ||
| 		  G_TYPE_POINTER);
 | ||
|   g_signal_set_va_marshaller (signals[FROM_EMBEDDER],
 | ||
|                               G_OBJECT_CLASS_TYPE (object_class),
 | ||
|                               _gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTERv);
 | ||
| 
 | ||
|   /**
 | ||
|    * GdkWindow::create-surface:
 | ||
|    * @window: the offscreen window on which the signal is emitted
 | ||
|    * @width: the width of the offscreen surface to create
 | ||
|    * @height: the height of the offscreen surface to create
 | ||
|    *
 | ||
|    * The ::create-surface signal is emitted when an offscreen window
 | ||
|    * needs its surface (re)created, which happens either when the
 | ||
|    * window is first drawn to, or when the window is being
 | ||
|    * resized. The first signal handler that returns a non-%NULL
 | ||
|    * surface will stop any further signal emission, and its surface
 | ||
|    * will be used.
 | ||
|    *
 | ||
|    * Note that it is not possible to access the window's previous
 | ||
|    * surface from within any callback of this signal. Calling
 | ||
|    * gdk_offscreen_window_get_surface() will lead to a crash.
 | ||
|    *
 | ||
|    * Returns: the newly created #cairo_surface_t for the offscreen window
 | ||
|    *
 | ||
|    * Since: 3.0
 | ||
|    */
 | ||
|   signals[CREATE_SURFACE] =
 | ||
|     g_signal_new (g_intern_static_string ("create-surface"),
 | ||
|                   G_OBJECT_CLASS_TYPE (object_class),
 | ||
|                   G_SIGNAL_RUN_LAST,
 | ||
|                   G_STRUCT_OFFSET (GdkWindowClass, create_surface),
 | ||
|                   create_surface_accumulator, NULL,
 | ||
|                   _gdk_marshal_BOXED__INT_INT,
 | ||
|                   CAIRO_GOBJECT_TYPE_SURFACE,
 | ||
|                   2,
 | ||
|                   G_TYPE_INT,
 | ||
|                   G_TYPE_INT);
 | ||
|   g_signal_set_va_marshaller (signals[CREATE_SURFACE],
 | ||
|                               G_OBJECT_CLASS_TYPE (object_class),
 | ||
|                               _gdk_marshal_BOXED__INT_INTv);
 | ||
| 
 | ||
|   /**
 | ||
|    * GdkWindow::moved-to-rect:
 | ||
|    * @window: the #GdkWindow that moved
 | ||
|    * @flipped_rect: (nullable): the position of @window after any possible
 | ||
|    *                flipping or %NULL if the backend can't obtain it
 | ||
|    * @final_rect: (nullable): the final position of @window or %NULL if the
 | ||
|    *              backend can't obtain it
 | ||
|    * @flipped_x: %TRUE if the anchors were flipped horizontally
 | ||
|    * @flipped_y: %TRUE if the anchors were flipped vertically
 | ||
|    *
 | ||
|    * Emitted when the position of @window is finalized after being moved to a
 | ||
|    * destination rectangle.
 | ||
|    *
 | ||
|    * @window might be flipped over the destination rectangle in order to keep
 | ||
|    * it on-screen, in which case @flipped_x and @flipped_y will be set to %TRUE
 | ||
|    * accordingly.
 | ||
|    *
 | ||
|    * @flipped_rect is the ideal position of @window after any possible
 | ||
|    * flipping, but before any possible sliding. @final_rect is @flipped_rect,
 | ||
|    * but possibly translated in the case that flipping is still ineffective in
 | ||
|    * keeping @window on-screen.
 | ||
|    *
 | ||
|    * Since: 3.22
 | ||
|    * Stability: Private
 | ||
|    */
 | ||
|   signals[MOVED_TO_RECT] =
 | ||
|     g_signal_new (g_intern_static_string ("moved-to-rect"),
 | ||
|                   G_OBJECT_CLASS_TYPE (object_class),
 | ||
|                   G_SIGNAL_RUN_FIRST,
 | ||
|                   0,
 | ||
|                   NULL,
 | ||
|                   NULL,
 | ||
|                   _gdk_marshal_VOID__POINTER_POINTER_BOOLEAN_BOOLEAN,
 | ||
|                   G_TYPE_NONE,
 | ||
|                   4,
 | ||
|                   G_TYPE_POINTER,
 | ||
|                   G_TYPE_POINTER,
 | ||
|                   G_TYPE_BOOLEAN,
 | ||
|                   G_TYPE_BOOLEAN);
 | ||
|   g_signal_set_va_marshaller (signals[MOVED_TO_RECT],
 | ||
|                               G_OBJECT_CLASS_TYPE (object_class),
 | ||
|                               _gdk_marshal_VOID__POINTER_POINTER_BOOLEAN_BOOLEANv);
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| seat_removed_cb (GdkDisplay *display,
 | ||
|                  GdkSeat    *seat,
 | ||
|                  GdkWindow  *window)
 | ||
| {
 | ||
|   GdkDevice *device = gdk_seat_get_pointer (seat);
 | ||
| 
 | ||
|   window->devices_inside = g_list_remove (window->devices_inside, device);
 | ||
|   g_hash_table_remove (window->device_cursor, device);
 | ||
| 
 | ||
|   if (window->device_events)
 | ||
|     g_hash_table_remove (window->device_events, device);
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_finalize (GObject *object)
 | ||
| {
 | ||
|   GdkWindow *window = GDK_WINDOW (object);
 | ||
| 
 | ||
|   g_signal_handlers_disconnect_by_func (gdk_window_get_display (window),
 | ||
|                                         seat_removed_cb, window);
 | ||
| 
 | ||
|   if (!GDK_WINDOW_DESTROYED (window))
 | ||
|     {
 | ||
|       if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
 | ||
| 	{
 | ||
| 	  g_warning ("losing last reference to undestroyed window");
 | ||
| 	  _gdk_window_destroy (window, FALSE);
 | ||
| 	}
 | ||
|       else
 | ||
| 	/* We use TRUE here, to keep us from actually calling
 | ||
| 	 * XDestroyWindow() on the window
 | ||
| 	 */
 | ||
| 	_gdk_window_destroy (window, TRUE);
 | ||
|     }
 | ||
| 
 | ||
|   if (window->synthesized_crossing_event_id)
 | ||
|     {
 | ||
|       g_source_remove (window->synthesized_crossing_event_id);
 | ||
|       window->synthesized_crossing_event_id = 0;
 | ||
|     }
 | ||
| 
 | ||
|   if (window->impl)
 | ||
|     {
 | ||
|       g_object_unref (window->impl);
 | ||
|       window->impl = NULL;
 | ||
|     }
 | ||
| 
 | ||
|   if (window->impl_window != window)
 | ||
|     {
 | ||
|       g_object_unref (window->impl_window);
 | ||
|       window->impl_window = NULL;
 | ||
|     }
 | ||
| 
 | ||
|   if (window->shape)
 | ||
|     cairo_region_destroy (window->shape);
 | ||
| 
 | ||
|   if (window->input_shape)
 | ||
|     cairo_region_destroy (window->input_shape);
 | ||
| 
 | ||
|   if (window->cursor)
 | ||
|     g_object_unref (window->cursor);
 | ||
| 
 | ||
|   if (window->device_cursor)
 | ||
|     g_hash_table_destroy (window->device_cursor);
 | ||
| 
 | ||
|   if (window->device_events)
 | ||
|     g_hash_table_destroy (window->device_events);
 | ||
| 
 | ||
|   if (window->source_event_masks)
 | ||
|     g_hash_table_destroy (window->source_event_masks);
 | ||
| 
 | ||
|   if (window->devices_inside)
 | ||
|     g_list_free (window->devices_inside);
 | ||
| 
 | ||
|   if (window->opaque_region)
 | ||
|     cairo_region_destroy (window->opaque_region);
 | ||
| 
 | ||
|   G_OBJECT_CLASS (gdk_window_parent_class)->finalize (object);
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_set_property (GObject      *object,
 | ||
|                          guint         prop_id,
 | ||
|                          const GValue *value,
 | ||
|                          GParamSpec   *pspec)
 | ||
| {
 | ||
|   GdkWindow *window = (GdkWindow *)object;
 | ||
| 
 | ||
|   switch (prop_id)
 | ||
|     {
 | ||
|     case PROP_CURSOR:
 | ||
|       gdk_window_set_cursor (window, g_value_get_object (value));
 | ||
|       break;
 | ||
| 
 | ||
|     default:
 | ||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | ||
|       break;
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_get_property (GObject    *object,
 | ||
|                          guint       prop_id,
 | ||
|                          GValue     *value,
 | ||
|                          GParamSpec *pspec)
 | ||
| {
 | ||
|   GdkWindow *window = (GdkWindow *) object;
 | ||
| 
 | ||
|   switch (prop_id)
 | ||
|     {
 | ||
|     case PROP_CURSOR:
 | ||
|       g_value_set_object (value, gdk_window_get_cursor (window));
 | ||
|       break;
 | ||
| 
 | ||
|     default:
 | ||
|       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 | ||
|       break;
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| static gboolean
 | ||
| gdk_window_is_offscreen (GdkWindow *window)
 | ||
| {
 | ||
|   return window->window_type == GDK_WINDOW_OFFSCREEN;
 | ||
| }
 | ||
| 
 | ||
| static gboolean
 | ||
| gdk_window_is_subsurface (GdkWindow *window)
 | ||
| {
 | ||
|    return window->window_type == GDK_WINDOW_SUBSURFACE;
 | ||
| }
 | ||
| 
 | ||
| static GdkWindow *
 | ||
| gdk_window_get_impl_window (GdkWindow *window)
 | ||
| {
 | ||
|   return window->impl_window;
 | ||
| }
 | ||
| 
 | ||
| GdkWindow *
 | ||
| _gdk_window_get_impl_window (GdkWindow *window)
 | ||
| {
 | ||
|   return gdk_window_get_impl_window (window);
 | ||
| }
 | ||
| 
 | ||
| static gboolean
 | ||
| gdk_window_has_impl (GdkWindow *window)
 | ||
| {
 | ||
|   return window->impl_window == window;
 | ||
| }
 | ||
| 
 | ||
| static gboolean
 | ||
| gdk_window_is_toplevel (GdkWindow *window)
 | ||
| {
 | ||
|   return
 | ||
|     window->parent == NULL ||
 | ||
|     window->parent->window_type == GDK_WINDOW_ROOT;
 | ||
| }
 | ||
| 
 | ||
| gboolean
 | ||
| _gdk_window_has_impl (GdkWindow *window)
 | ||
| {
 | ||
|   return gdk_window_has_impl (window);
 | ||
| }
 | ||
| 
 | ||
| static gboolean
 | ||
| gdk_window_has_no_impl (GdkWindow *window)
 | ||
| {
 | ||
|   return window->impl_window != window;
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| remove_sibling_overlapped_area (GdkWindow *window,
 | ||
| 				cairo_region_t *region)
 | ||
| {
 | ||
|   GdkWindow *parent;
 | ||
|   GdkWindow *sibling;
 | ||
|   cairo_region_t *child_region;
 | ||
|   GdkRectangle r;
 | ||
|   GList *l;
 | ||
|   cairo_region_t *shape;
 | ||
| 
 | ||
|   parent = window->parent;
 | ||
| 
 | ||
|   if (gdk_window_is_toplevel (window))
 | ||
|     return;
 | ||
| 
 | ||
|   /* Convert from from window coords to parent coords */
 | ||
|   cairo_region_translate (region, window->x, window->y);
 | ||
| 
 | ||
|   for (l = parent->children; l; l = l->next)
 | ||
|     {
 | ||
|       sibling = l->data;
 | ||
| 
 | ||
|       if (sibling == window)
 | ||
| 	break;
 | ||
| 
 | ||
|       if (!GDK_WINDOW_IS_MAPPED (sibling) || sibling->input_only || sibling->composited)
 | ||
| 	continue;
 | ||
| 
 | ||
|       /* Ignore offscreen children, as they don't draw in their parent and
 | ||
|        * don't take part in the clipping */
 | ||
|       if (gdk_window_is_offscreen (sibling))
 | ||
| 	continue;
 | ||
| 
 | ||
|       r.x = sibling->x;
 | ||
|       r.y = sibling->y;
 | ||
|       r.width = sibling->width;
 | ||
|       r.height = sibling->height;
 | ||
| 
 | ||
|       child_region = cairo_region_create_rectangle (&r);
 | ||
| 
 | ||
|       if (sibling->shape)
 | ||
| 	{
 | ||
| 	  /* Adjust shape region to parent window coords */
 | ||
| 	  cairo_region_translate (sibling->shape, sibling->x, sibling->y);
 | ||
| 	  cairo_region_intersect (child_region, sibling->shape);
 | ||
| 	  cairo_region_translate (sibling->shape, -sibling->x, -sibling->y);
 | ||
| 	}
 | ||
|       else if (window->window_type == GDK_WINDOW_FOREIGN)
 | ||
| 	{
 | ||
| 	  shape = GDK_WINDOW_IMPL_GET_CLASS (sibling)->get_shape (sibling);
 | ||
| 	  if (shape)
 | ||
| 	    {
 | ||
| 	      cairo_region_intersect (child_region, shape);
 | ||
| 	      cairo_region_destroy (shape);
 | ||
| 	    }
 | ||
| 	}
 | ||
| 
 | ||
|       cairo_region_subtract (region, child_region);
 | ||
|       cairo_region_destroy (child_region);
 | ||
|     }
 | ||
| 
 | ||
|   remove_sibling_overlapped_area (parent, region);
 | ||
| 
 | ||
|   /* Convert back to window coords */
 | ||
|   cairo_region_translate (region, -window->x, -window->y);
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| remove_child_area (GdkWindow *window,
 | ||
| 		   gboolean for_input,
 | ||
| 		   cairo_region_t *region)
 | ||
| {
 | ||
|   GdkWindow *child;
 | ||
|   cairo_region_t *child_region;
 | ||
|   GdkRectangle r;
 | ||
|   GList *l;
 | ||
|   cairo_region_t *shape;
 | ||
| 
 | ||
|   for (l = window->children; l; l = l->next)
 | ||
|     {
 | ||
|       child = l->data;
 | ||
| 
 | ||
|       /* If region is empty already, no need to do
 | ||
| 	 anything potentially costly */
 | ||
|       if (cairo_region_is_empty (region))
 | ||
| 	break;
 | ||
| 
 | ||
|       if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
 | ||
| 	continue;
 | ||
| 
 | ||
|       /* Ignore offscreen children, as they don't draw in their parent and
 | ||
|        * don't take part in the clipping */
 | ||
|       if (gdk_window_is_offscreen (child))
 | ||
| 	continue;
 | ||
| 
 | ||
|       r.x = child->x;
 | ||
|       r.y = child->y;
 | ||
|       r.width = child->width;
 | ||
|       r.height = child->height;
 | ||
| 
 | ||
|       /* Bail early if child totally outside region */
 | ||
|       if (cairo_region_contains_rectangle (region, &r) == CAIRO_REGION_OVERLAP_OUT)
 | ||
| 	continue;
 | ||
| 
 | ||
|       child_region = cairo_region_create_rectangle (&r);
 | ||
| 
 | ||
|       if (child->shape)
 | ||
| 	{
 | ||
| 	  /* Adjust shape region to parent window coords */
 | ||
| 	  cairo_region_translate (child->shape, child->x, child->y);
 | ||
| 	  cairo_region_intersect (child_region, child->shape);
 | ||
| 	  cairo_region_translate (child->shape, -child->x, -child->y);
 | ||
| 	}
 | ||
|       else if (window->window_type == GDK_WINDOW_FOREIGN)
 | ||
| 	{
 | ||
| 	  shape = GDK_WINDOW_IMPL_GET_CLASS (child)->get_shape (child);
 | ||
| 	  if (shape)
 | ||
| 	    {
 | ||
| 	      cairo_region_intersect (child_region, shape);
 | ||
| 	      cairo_region_destroy (shape);
 | ||
| 	    }
 | ||
| 	}
 | ||
| 
 | ||
|       if (for_input)
 | ||
| 	{
 | ||
| 	  if (child->input_shape)
 | ||
| 	    cairo_region_intersect (child_region, child->input_shape);
 | ||
| 	  else if (window->window_type == GDK_WINDOW_FOREIGN)
 | ||
| 	    {
 | ||
| 	      shape = GDK_WINDOW_IMPL_GET_CLASS (child)->get_input_shape (child);
 | ||
| 	      if (shape)
 | ||
| 		{
 | ||
| 		  cairo_region_intersect (child_region, shape);
 | ||
| 		  cairo_region_destroy (shape);
 | ||
| 		}
 | ||
| 	    }
 | ||
| 	}
 | ||
| 
 | ||
|       cairo_region_subtract (region, child_region);
 | ||
|       cairo_region_destroy (child_region);
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| static GdkVisibilityState
 | ||
| effective_visibility (GdkWindow *window)
 | ||
| {
 | ||
|   GdkVisibilityState native;
 | ||
| 
 | ||
|   if (!gdk_window_is_viewable (window))
 | ||
|     return GDK_VISIBILITY_NOT_VIEWABLE;
 | ||
| 
 | ||
|   native = window->impl_window->native_visibility;
 | ||
| 
 | ||
|   if (native == GDK_VISIBILITY_FULLY_OBSCURED ||
 | ||
|       window->visibility == GDK_VISIBILITY_FULLY_OBSCURED)
 | ||
|     return GDK_VISIBILITY_FULLY_OBSCURED;
 | ||
|   else if (native == GDK_VISIBILITY_UNOBSCURED)
 | ||
|     return window->visibility;
 | ||
|   else /* native PARTIAL, private partial or unobscured  */
 | ||
|     return GDK_VISIBILITY_PARTIAL;
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_update_visibility (GdkWindow *window)
 | ||
| {
 | ||
|   GdkVisibilityState new_visibility;
 | ||
|   GdkEvent *event;
 | ||
| 
 | ||
|   new_visibility = effective_visibility (window);
 | ||
| 
 | ||
|   if (new_visibility != window->effective_visibility)
 | ||
|     {
 | ||
|       window->effective_visibility = new_visibility;
 | ||
| 
 | ||
|       if (new_visibility != GDK_VISIBILITY_NOT_VIEWABLE &&
 | ||
| 	  window->event_mask & GDK_VISIBILITY_NOTIFY_MASK)
 | ||
| 	{
 | ||
| 	  event = _gdk_make_event (window, GDK_VISIBILITY_NOTIFY,
 | ||
| 				   NULL, FALSE);
 | ||
| 	  event->visibility.state = new_visibility;
 | ||
| 	}
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_update_visibility_recursively (GdkWindow *window,
 | ||
| 					  GdkWindow *only_for_impl)
 | ||
| {
 | ||
|   GdkWindow *child;
 | ||
|   GList *l;
 | ||
| 
 | ||
|   gdk_window_update_visibility (window);
 | ||
|   for (l = window->children; l != NULL; l = l->next)
 | ||
|     {
 | ||
|       child = l->data;
 | ||
|       if ((only_for_impl == NULL) ||
 | ||
| 	  (only_for_impl == child->impl_window))
 | ||
| 	gdk_window_update_visibility_recursively (child, only_for_impl);
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| static gboolean
 | ||
| should_apply_clip_as_shape (GdkWindow *window)
 | ||
| {
 | ||
|   return
 | ||
|     gdk_window_has_impl (window) &&
 | ||
|     /* Not for offscreens */
 | ||
|     !gdk_window_is_offscreen (window) &&
 | ||
|     /* or for non-shaped toplevels */
 | ||
|     (!gdk_window_is_toplevel (window) ||
 | ||
|      window->shape != NULL || window->applied_shape) &&
 | ||
|     /* or for foreign windows */
 | ||
|     window->window_type != GDK_WINDOW_FOREIGN &&
 | ||
|     /* or for the root window */
 | ||
|     window->window_type != GDK_WINDOW_ROOT;
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| apply_shape (GdkWindow *window,
 | ||
| 	     cairo_region_t *region)
 | ||
| {
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
| 
 | ||
|   /* We trash whether we applied a shape so that
 | ||
|      we can avoid unsetting it many times, which
 | ||
|      could happen in e.g. apply_clip_as_shape as
 | ||
|      windows get resized */
 | ||
|   impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
|   if (region)
 | ||
|     impl_class->shape_combine_region (window,
 | ||
| 				      region, 0, 0);
 | ||
|   else if (window->applied_shape)
 | ||
|     impl_class->shape_combine_region (window,
 | ||
| 				      NULL, 0, 0);
 | ||
| 
 | ||
|   window->applied_shape = region != NULL;
 | ||
| }
 | ||
| 
 | ||
| static gboolean
 | ||
| region_rect_equal (const cairo_region_t *region,
 | ||
|                    const GdkRectangle *rect)
 | ||
| {
 | ||
|     GdkRectangle extents;
 | ||
| 
 | ||
|     if (cairo_region_num_rectangles (region) != 1)
 | ||
|         return FALSE;
 | ||
| 
 | ||
|     cairo_region_get_extents (region, &extents);
 | ||
| 
 | ||
|     return extents.x == rect->x &&
 | ||
|         extents.y == rect->y &&
 | ||
|         extents.width == rect->width &&
 | ||
|         extents.height == rect->height;
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| apply_clip_as_shape (GdkWindow *window)
 | ||
| {
 | ||
|   GdkRectangle r;
 | ||
|   cairo_region_t *region;
 | ||
| 
 | ||
|   r.x = r.y = 0;
 | ||
|   r.width = window->width;
 | ||
|   r.height = window->height;
 | ||
| 
 | ||
|   region = cairo_region_copy (window->clip_region);
 | ||
|   remove_sibling_overlapped_area (window, region);
 | ||
| 
 | ||
|   /* We only apply the clip region if would differ
 | ||
|      from the actual clip region implied by the size
 | ||
|      of the window. This is to avoid unneccessarily
 | ||
|      adding meaningless shapes to all native subwindows */
 | ||
|   if (!region_rect_equal (region, &r))
 | ||
|     apply_shape (window, region);
 | ||
|   else
 | ||
|     apply_shape (window, NULL);
 | ||
| 
 | ||
|   cairo_region_destroy (region);
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| recompute_visible_regions_internal (GdkWindow *private,
 | ||
| 				    gboolean   recalculate_clip,
 | ||
| 				    gboolean   recalculate_children)
 | ||
| {
 | ||
|   GdkRectangle r;
 | ||
|   GList *l;
 | ||
|   GdkWindow *child;
 | ||
|   cairo_region_t *new_clip;
 | ||
|   gboolean clip_region_changed;
 | ||
|   gboolean abs_pos_changed;
 | ||
|   int old_abs_x, old_abs_y;
 | ||
| 
 | ||
|   old_abs_x = private->abs_x;
 | ||
|   old_abs_y = private->abs_y;
 | ||
| 
 | ||
|   /* Update absolute position */
 | ||
|   if ((gdk_window_has_impl (private) &&
 | ||
|        private->window_type != GDK_WINDOW_SUBSURFACE) ||
 | ||
|       (gdk_window_is_toplevel (private) &&
 | ||
|        private->window_type == GDK_WINDOW_SUBSURFACE))
 | ||
|     {
 | ||
|       /* Native windows and toplevel subsurfaces start here */
 | ||
|       private->abs_x = 0;
 | ||
|       private->abs_y = 0;
 | ||
|     }
 | ||
|   else
 | ||
|     {
 | ||
|       private->abs_x = private->parent->abs_x + private->x;
 | ||
|       private->abs_y = private->parent->abs_y + private->y;
 | ||
|     }
 | ||
| 
 | ||
|   abs_pos_changed =
 | ||
|     private->abs_x != old_abs_x ||
 | ||
|     private->abs_y != old_abs_y;
 | ||
| 
 | ||
|   /* Update clip region based on:
 | ||
|    * parent clip
 | ||
|    * window size/position
 | ||
|    */
 | ||
|   clip_region_changed = FALSE;
 | ||
|   if (recalculate_clip)
 | ||
|     {
 | ||
|       if (private->viewable)
 | ||
| 	{
 | ||
| 	  /* Calculate visible region (sans children) in parent window coords */
 | ||
| 	  r.x = private->x;
 | ||
| 	  r.y = private->y;
 | ||
| 	  r.width = private->width;
 | ||
| 	  r.height = private->height;
 | ||
| 	  new_clip = cairo_region_create_rectangle (&r);
 | ||
| 
 | ||
| 	  if (!gdk_window_is_toplevel (private))
 | ||
| 	    cairo_region_intersect (new_clip, private->parent->clip_region);
 | ||
| 
 | ||
| 	  /* Convert from parent coords to window coords */
 | ||
| 	  cairo_region_translate (new_clip, -private->x, -private->y);
 | ||
| 
 | ||
| 	  if (should_apply_clip_as_shape (private) && private->shape)
 | ||
| 	    cairo_region_intersect (new_clip, private->shape);
 | ||
| 	}
 | ||
|       else
 | ||
| 	  new_clip = cairo_region_create ();
 | ||
| 
 | ||
|       if (private->clip_region == NULL ||
 | ||
| 	  !cairo_region_equal (private->clip_region, new_clip))
 | ||
| 	clip_region_changed = TRUE;
 | ||
| 
 | ||
|       if (private->clip_region)
 | ||
| 	cairo_region_destroy (private->clip_region);
 | ||
|       private->clip_region = new_clip;
 | ||
|     }
 | ||
| 
 | ||
|   if (clip_region_changed)
 | ||
|     {
 | ||
|       GdkVisibilityState visibility;
 | ||
|       gboolean fully_visible;
 | ||
| 
 | ||
|       if (cairo_region_is_empty (private->clip_region))
 | ||
| 	visibility = GDK_VISIBILITY_FULLY_OBSCURED;
 | ||
|       else
 | ||
|         {
 | ||
|           if (private->shape)
 | ||
|             {
 | ||
| 	      fully_visible = cairo_region_equal (private->clip_region,
 | ||
| 	                                        private->shape);
 | ||
|             }
 | ||
|           else
 | ||
|             {
 | ||
| 	      r.x = 0;
 | ||
| 	      r.y = 0;
 | ||
| 	      r.width = private->width;
 | ||
| 	      r.height = private->height;
 | ||
| 	      fully_visible = region_rect_equal (private->clip_region, &r);
 | ||
| 	    }
 | ||
| 
 | ||
| 	  if (fully_visible)
 | ||
| 	    visibility = GDK_VISIBILITY_UNOBSCURED;
 | ||
| 	  else
 | ||
| 	    visibility = GDK_VISIBILITY_PARTIAL;
 | ||
| 	}
 | ||
| 
 | ||
|       if (private->visibility != visibility)
 | ||
| 	{
 | ||
| 	  private->visibility = visibility;
 | ||
| 	  gdk_window_update_visibility (private);
 | ||
| 	}
 | ||
|     }
 | ||
| 
 | ||
|   /* Update all children, recursively (except for root, where children are not exact). */
 | ||
|   if ((abs_pos_changed || clip_region_changed || recalculate_children) &&
 | ||
|       private->window_type != GDK_WINDOW_ROOT)
 | ||
|     {
 | ||
|       for (l = private->children; l; l = l->next)
 | ||
| 	{
 | ||
| 	  child = l->data;
 | ||
| 	  /* Only recalculate clip if the the clip region changed, otherwise
 | ||
| 	   * there is no way the child clip region could change (its has not e.g. moved)
 | ||
| 	   * Except if recalculate_children is set to force child updates
 | ||
| 	   */
 | ||
| 	  recompute_visible_regions_internal (child,
 | ||
| 					      recalculate_clip && (clip_region_changed || recalculate_children),
 | ||
| 					      FALSE);
 | ||
| 	}
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| /* Call this when private has changed in one or more of these ways:
 | ||
|  *  size changed
 | ||
|  *  window moved
 | ||
|  *  new window added
 | ||
|  *  stacking order of window changed
 | ||
|  *  child deleted
 | ||
|  *
 | ||
|  * It will recalculate abs_x/y and the clip regions
 | ||
|  *
 | ||
|  * Unless the window didn’t change stacking order or size/pos, pass in TRUE
 | ||
|  * for recalculate_siblings. (Mostly used internally for the recursion)
 | ||
|  *
 | ||
|  * If a child window was removed (and you can’t use that child for
 | ||
|  * recompute_visible_regions), pass in TRUE for recalculate_children on the parent
 | ||
|  */
 | ||
| static void
 | ||
| recompute_visible_regions (GdkWindow *private,
 | ||
| 			   gboolean recalculate_children)
 | ||
| {
 | ||
|   GdkWindow *toplevel;
 | ||
| 
 | ||
|   toplevel = gdk_window_get_toplevel (private);
 | ||
|   toplevel->geometry_dirty = TRUE;
 | ||
| 
 | ||
|   recompute_visible_regions_internal (private,
 | ||
| 				      TRUE,
 | ||
| 				      recalculate_children);
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_clear_old_updated_area (GdkWindow *window)
 | ||
| {
 | ||
|   int i;
 | ||
| 
 | ||
|   for (i = 0; i < 2; i++)
 | ||
|     {
 | ||
|       if (window->old_updated_area[i])
 | ||
|         {
 | ||
|           cairo_region_destroy (window->old_updated_area[i]);
 | ||
|           window->old_updated_area[i] = NULL;
 | ||
|         }
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_append_old_updated_area (GdkWindow *window,
 | ||
|                                     cairo_region_t *region)
 | ||
| {
 | ||
|   if (window->old_updated_area[1])
 | ||
|     cairo_region_destroy (window->old_updated_area[1]);
 | ||
|   window->old_updated_area[1] = window->old_updated_area[0];
 | ||
|   window->old_updated_area[0] = cairo_region_reference (region);
 | ||
| }
 | ||
| 
 | ||
| void
 | ||
| _gdk_window_update_size (GdkWindow *window)
 | ||
| {
 | ||
|   gdk_window_clear_old_updated_area (window);
 | ||
|   recompute_visible_regions (window, FALSE);
 | ||
| }
 | ||
| 
 | ||
| /* Find the native window that would be just above "child"
 | ||
|  * in the native stacking order if “child” was a native window
 | ||
|  * (it doesn’t have to be native). If there is no such native
 | ||
|  * window inside this native parent then NULL is returned.
 | ||
|  * If child is NULL, find lowest native window in parent.
 | ||
|  */
 | ||
| static GdkWindow *
 | ||
| find_native_sibling_above_helper (GdkWindow *parent,
 | ||
| 				  GdkWindow *child)
 | ||
| {
 | ||
|   GdkWindow *w;
 | ||
|   GList *l;
 | ||
| 
 | ||
|   if (child)
 | ||
|     {
 | ||
|       l = g_list_find (parent->children, child);
 | ||
|       g_assert (l != NULL); /* Better be a child of its parent... */
 | ||
|       l = l->prev; /* Start looking at the one above the child */
 | ||
|     }
 | ||
|   else
 | ||
|     l = g_list_last (parent->children);
 | ||
| 
 | ||
|   for (; l != NULL; l = l->prev)
 | ||
|     {
 | ||
|       w = l->data;
 | ||
| 
 | ||
|       if (gdk_window_has_impl (w))
 | ||
| 	return w;
 | ||
| 
 | ||
|       g_assert (parent != w);
 | ||
|       w = find_native_sibling_above_helper (w, NULL);
 | ||
|       if (w)
 | ||
| 	return w;
 | ||
|     }
 | ||
| 
 | ||
|   return NULL;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| static GdkWindow *
 | ||
| find_native_sibling_above (GdkWindow *parent,
 | ||
| 			   GdkWindow *child)
 | ||
| {
 | ||
|   GdkWindow *w;
 | ||
| 
 | ||
|   if (!parent)
 | ||
|     return NULL;
 | ||
| 
 | ||
|   w = find_native_sibling_above_helper (parent, child);
 | ||
|   if (w)
 | ||
|     return w;
 | ||
| 
 | ||
|   if (gdk_window_has_impl (parent))
 | ||
|     return NULL;
 | ||
|   else
 | ||
|     return find_native_sibling_above (parent->parent, parent);
 | ||
| }
 | ||
| 
 | ||
| static GdkEventMask
 | ||
| get_native_device_event_mask (GdkWindow *private,
 | ||
|                               GdkDevice *device)
 | ||
| {
 | ||
|   GdkEventMask event_mask;
 | ||
| 
 | ||
|   if (device)
 | ||
|     event_mask = GPOINTER_TO_INT (g_hash_table_lookup (private->device_events, device));
 | ||
|   else
 | ||
|     event_mask = private->event_mask;
 | ||
| 
 | ||
|   if (private->window_type == GDK_WINDOW_ROOT ||
 | ||
|       private->window_type == GDK_WINDOW_FOREIGN)
 | ||
|     return event_mask;
 | ||
|   else
 | ||
|     {
 | ||
|       GdkEventMask mask;
 | ||
| 
 | ||
|       /* Do whatever the app asks to, since the app
 | ||
|        * may be asking for weird things for native windows,
 | ||
|        * but don't use motion hints as that may affect non-native
 | ||
|        * child windows that don't want it. Also, we need to
 | ||
|        * set all the app-specified masks since they will be picked
 | ||
|        * up by any implicit grabs (i.e. if they were not set as
 | ||
|        * native we would not get the events we need). */
 | ||
|       mask = private->event_mask & ~GDK_POINTER_MOTION_HINT_MASK;
 | ||
| 
 | ||
|       /* We need thse for all native windows so we can
 | ||
| 	 emulate events on children: */
 | ||
|       mask |=
 | ||
| 	GDK_EXPOSURE_MASK |
 | ||
| 	GDK_VISIBILITY_NOTIFY_MASK |
 | ||
| 	GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK;
 | ||
| 
 | ||
|       /* Additionally we select for pointer and button events
 | ||
|        * for toplevels as we need to get these to emulate
 | ||
|        * them for non-native subwindows. Even though we don't
 | ||
|        * select on them for all native windows we will get them
 | ||
|        * as the events are propagated out to the first window
 | ||
|        * that select for them.
 | ||
|        * Not selecting for button press on all windows is an
 | ||
|        * important thing, because in X only one client can do
 | ||
|        * so, and we don't want to unexpectedly prevent another
 | ||
|        * client from doing it.
 | ||
|        *
 | ||
|        * We also need to do the same if the app selects for button presses
 | ||
|        * because then we will get implicit grabs for this window, and the
 | ||
|        * event mask used for that grab is based on the rest of the mask
 | ||
|        * for the window, but we might need more events than this window
 | ||
|        * lists due to some non-native child window.
 | ||
|        */
 | ||
|       if (gdk_window_is_toplevel (private) ||
 | ||
|           mask & GDK_BUTTON_PRESS_MASK)
 | ||
|         mask |=
 | ||
|           GDK_TOUCH_MASK | GDK_TOUCHPAD_GESTURE_MASK |
 | ||
|           GDK_POINTER_MOTION_MASK |
 | ||
|           GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
 | ||
|           GDK_SCROLL_MASK;
 | ||
| 
 | ||
|       return mask;
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| static GdkEventMask
 | ||
| get_native_grab_event_mask (GdkEventMask grab_mask)
 | ||
| {
 | ||
|   /* Similar to the above but for pointer events only */
 | ||
|   return
 | ||
|     GDK_POINTER_MOTION_MASK |
 | ||
|     GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
 | ||
|     GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
 | ||
|     GDK_SCROLL_MASK |
 | ||
|     (grab_mask &
 | ||
|      ~GDK_POINTER_MOTION_HINT_MASK);
 | ||
| }
 | ||
| 
 | ||
| static GdkEventMask
 | ||
| get_native_event_mask (GdkWindow *private)
 | ||
| {
 | ||
|   return get_native_device_event_mask (private, NULL);
 | ||
| }
 | ||
| 
 | ||
| /* Puts the native window in the right order wrt the other native windows
 | ||
|  * in the hierarchy, given the position it has in the client side data.
 | ||
|  * This is useful if some operation changed the stacking order.
 | ||
|  * This calls assumes the native window is now topmost in its native parent.
 | ||
|  */
 | ||
| static void
 | ||
| sync_native_window_stack_position (GdkWindow *window)
 | ||
| {
 | ||
|   GdkWindow *above;
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
|   GList listhead = {0};
 | ||
| 
 | ||
|   impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
| 
 | ||
|   above = find_native_sibling_above (window->parent, window);
 | ||
|   if (above)
 | ||
|     {
 | ||
|       listhead.data = window;
 | ||
|       impl_class->restack_under (above, &listhead);
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_new: (constructor)
 | ||
|  * @parent: (allow-none): a #GdkWindow, or %NULL to create the window as a child of
 | ||
|  *   the default root window for the default display.
 | ||
|  * @attributes: attributes of the new window
 | ||
|  * @attributes_mask: (type GdkWindowAttributesType): mask indicating which
 | ||
|  *   fields in @attributes are valid
 | ||
|  *
 | ||
|  * Creates a new #GdkWindow using the attributes from
 | ||
|  * @attributes. See #GdkWindowAttr and #GdkWindowAttributesType for
 | ||
|  * more details.  Note: to use this on displays other than the default
 | ||
|  * display, @parent must be specified.
 | ||
|  *
 | ||
|  * Returns: (transfer full): the new #GdkWindow
 | ||
|  **/
 | ||
| GdkWindow*
 | ||
| gdk_window_new (GdkWindow     *parent,
 | ||
| 		GdkWindowAttr *attributes,
 | ||
| 		gint           attributes_mask)
 | ||
| {
 | ||
|   GdkWindow *window;
 | ||
|   GdkScreen *screen;
 | ||
|   GdkDisplay *display;
 | ||
|   int x, y;
 | ||
|   gboolean native;
 | ||
|   GdkEventMask event_mask;
 | ||
|   GdkWindow *real_parent;
 | ||
| 
 | ||
|   g_return_val_if_fail (attributes != NULL, NULL);
 | ||
| 
 | ||
|   if (!parent)
 | ||
|     {
 | ||
|       screen = gdk_screen_get_default ();
 | ||
|       parent = gdk_screen_get_root_window (screen);
 | ||
|     }
 | ||
|   else
 | ||
|     screen = gdk_window_get_screen (parent);
 | ||
| 
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
 | ||
| 
 | ||
|   if (GDK_WINDOW_DESTROYED (parent))
 | ||
|     {
 | ||
|       g_warning ("gdk_window_new(): parent is destroyed");
 | ||
|       return NULL;
 | ||
|     }
 | ||
| 
 | ||
|   if (attributes_mask & GDK_WA_VISUAL)
 | ||
|     {
 | ||
|       g_return_val_if_fail (gdk_visual_get_screen (attributes->visual) == screen, NULL);
 | ||
|     }
 | ||
| 
 | ||
|   display = gdk_screen_get_display (screen);
 | ||
| 
 | ||
|   window = _gdk_display_create_window (display);
 | ||
| 
 | ||
|   /* Windows with a foreign parent are treated as if they are children
 | ||
|    * of the root window, except for actual creation.
 | ||
|    */
 | ||
|   real_parent = parent;
 | ||
|   if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
 | ||
|     parent = gdk_screen_get_root_window (screen);
 | ||
| 
 | ||
|   window->parent = parent;
 | ||
| 
 | ||
|   window->accept_focus = TRUE;
 | ||
|   window->focus_on_map = TRUE;
 | ||
|   window->event_compression = TRUE;
 | ||
| 
 | ||
|   if (attributes_mask & GDK_WA_X)
 | ||
|     x = attributes->x;
 | ||
|   else
 | ||
|     x = 0;
 | ||
| 
 | ||
|   if (attributes_mask & GDK_WA_Y)
 | ||
|     y = attributes->y;
 | ||
|   else
 | ||
|     y = 0;
 | ||
| 
 | ||
|   window->x = x;
 | ||
|   window->y = y;
 | ||
|   window->width = (attributes->width > 1) ? (attributes->width) : (1);
 | ||
|   window->height = (attributes->height > 1) ? (attributes->height) : (1);
 | ||
|   window->alpha = 255;
 | ||
| 
 | ||
|   if (attributes->wclass == GDK_INPUT_ONLY)
 | ||
|     {
 | ||
|       /* Backwards compatiblity - we've always ignored
 | ||
|        * attributes->window_type for input-only windows
 | ||
|        * before
 | ||
|        */
 | ||
|       if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
 | ||
| 	window->window_type = GDK_WINDOW_TEMP;
 | ||
|       else
 | ||
| 	window->window_type = GDK_WINDOW_CHILD;
 | ||
|     }
 | ||
|   else
 | ||
|     window->window_type = attributes->window_type;
 | ||
| 
 | ||
|   /* Sanity checks */
 | ||
|   switch (window->window_type)
 | ||
|     {
 | ||
|     case GDK_WINDOW_TOPLEVEL:
 | ||
|     case GDK_WINDOW_TEMP:
 | ||
|     case GDK_WINDOW_OFFSCREEN:
 | ||
|       if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
 | ||
| 	g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
 | ||
| 		   "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
 | ||
|       break;
 | ||
|     case GDK_WINDOW_SUBSURFACE:
 | ||
| #ifdef GDK_WINDOWING_WAYLAND
 | ||
|       if (!GDK_IS_WAYLAND_DISPLAY (display))
 | ||
|         {
 | ||
|           g_warning (G_STRLOC "Subsurface windows can only be used on Wayland");
 | ||
|           return NULL;
 | ||
|         }
 | ||
| #endif
 | ||
|       break;
 | ||
|     case GDK_WINDOW_CHILD:
 | ||
|       break;
 | ||
|     default:
 | ||
|       g_warning (G_STRLOC "cannot make windows of type %d", window->window_type);
 | ||
|       return NULL;
 | ||
|     }
 | ||
| 
 | ||
|   if (attributes_mask & GDK_WA_VISUAL)
 | ||
|     window->visual = attributes->visual;
 | ||
|   else
 | ||
|     window->visual = gdk_screen_get_system_visual (screen);
 | ||
| 
 | ||
|   window->event_mask = attributes->event_mask;
 | ||
| 
 | ||
|   if (attributes->wclass == GDK_INPUT_OUTPUT)
 | ||
|     {
 | ||
|       window->input_only = FALSE;
 | ||
|       window->depth = window->visual->depth;
 | ||
| 
 | ||
|       /* XXX: Cache this somehow? */
 | ||
|       window->background = cairo_pattern_create_rgba (0, 0, 0, 0);
 | ||
|     }
 | ||
|   else
 | ||
|     {
 | ||
|       window->depth = 0;
 | ||
|       window->input_only = TRUE;
 | ||
|     }
 | ||
| 
 | ||
|   window->parent->children = g_list_concat (&window->children_list_node, window->parent->children);
 | ||
| 
 | ||
|   if (window->parent->window_type == GDK_WINDOW_ROOT)
 | ||
|     {
 | ||
|       GdkFrameClock *frame_clock = g_object_new (GDK_TYPE_FRAME_CLOCK_IDLE, NULL);
 | ||
|       gdk_window_set_frame_clock (window, frame_clock);
 | ||
|       g_object_unref (frame_clock);
 | ||
|     }
 | ||
| 
 | ||
|   native = FALSE;
 | ||
|   if (window->parent->window_type == GDK_WINDOW_ROOT)
 | ||
|     native = TRUE; /* Always use native windows for toplevels */
 | ||
| 
 | ||
| #ifdef GDK_WINDOWING_WAYLAND
 | ||
|   if (window->window_type == GDK_WINDOW_SUBSURFACE)
 | ||
|     native = TRUE; /* Always use native windows for subsurfaces as well */
 | ||
| #endif
 | ||
| 
 | ||
|   if (gdk_window_is_offscreen (window))
 | ||
|     {
 | ||
|       _gdk_offscreen_window_new (window, attributes, attributes_mask);
 | ||
|       window->impl_window = window;
 | ||
|     }
 | ||
|   else if (native)
 | ||
|     {
 | ||
|       event_mask = get_native_event_mask (window);
 | ||
| 
 | ||
|       /* Create the impl */
 | ||
|       _gdk_display_create_window_impl (display, window, real_parent, screen, event_mask, attributes, attributes_mask);
 | ||
|       window->impl_window = window;
 | ||
| 
 | ||
|       parent->impl_window->native_children = g_list_prepend (parent->impl_window->native_children, window);
 | ||
| 
 | ||
|       /* This will put the native window topmost in the native parent, which may
 | ||
|        * be wrong wrt other native windows in the non-native hierarchy, so restack */
 | ||
|       if (!_gdk_window_has_impl (real_parent))
 | ||
| 	sync_native_window_stack_position (window);
 | ||
|     }
 | ||
|   else
 | ||
|     {
 | ||
|       window->impl_window = g_object_ref (window->parent->impl_window);
 | ||
|       window->impl = g_object_ref (window->impl_window->impl);
 | ||
|     }
 | ||
| 
 | ||
|   recompute_visible_regions (window, FALSE);
 | ||
| 
 | ||
|   gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
 | ||
| 				  (attributes->cursor) :
 | ||
| 				  NULL));
 | ||
| 
 | ||
|   g_signal_connect (gdk_window_get_display (parent), "seat-removed",
 | ||
|                     G_CALLBACK (seat_removed_cb), window);
 | ||
| 
 | ||
|   if ((_gdk_gl_flags & (GDK_GL_ALWAYS | GDK_GL_DISABLE)) == GDK_GL_ALWAYS)
 | ||
|     {
 | ||
|       GError *error = NULL;
 | ||
| 
 | ||
|       if (gdk_window_get_paint_gl_context (window, &error) == NULL)
 | ||
|         {
 | ||
|           g_warning ("Unable to force GL enabled: %s", error->message);
 | ||
|           g_error_free (error);
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|   return window;
 | ||
| }
 | ||
| 
 | ||
| static gboolean
 | ||
| is_parent_of (GdkWindow *parent,
 | ||
| 	      GdkWindow *child)
 | ||
| {
 | ||
|   GdkWindow *w;
 | ||
| 
 | ||
|   w = child;
 | ||
|   while (w != NULL)
 | ||
|     {
 | ||
|       if (w == parent)
 | ||
| 	return TRUE;
 | ||
| 
 | ||
|       w = gdk_window_get_parent (w);
 | ||
|     }
 | ||
| 
 | ||
|   return FALSE;
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| change_impl (GdkWindow *private,
 | ||
| 	     GdkWindow *impl_window,
 | ||
| 	     GdkWindowImpl *new)
 | ||
| {
 | ||
|   GList *l;
 | ||
|   GdkWindow *child;
 | ||
|   GdkWindowImpl *old_impl;
 | ||
|   GdkWindow *old_impl_window;
 | ||
| 
 | ||
|   old_impl = private->impl;
 | ||
|   old_impl_window = private->impl_window;
 | ||
|   if (private != impl_window)
 | ||
|     private->impl_window = g_object_ref (impl_window);
 | ||
|   else
 | ||
|     private->impl_window = private;
 | ||
|   private->impl = g_object_ref (new);
 | ||
|   if (old_impl_window != private)
 | ||
|     g_object_unref (old_impl_window);
 | ||
|   g_object_unref (old_impl);
 | ||
| 
 | ||
|   for (l = private->children; l != NULL; l = l->next)
 | ||
|     {
 | ||
|       child = l->data;
 | ||
| 
 | ||
|       if (child->impl == old_impl)
 | ||
| 	change_impl (child, impl_window, new);
 | ||
|       else
 | ||
|         {
 | ||
|           /* The child is a native, update native_children */
 | ||
|           old_impl_window->native_children =
 | ||
|             g_list_remove (old_impl_window->native_children, child);
 | ||
|           impl_window->native_children =
 | ||
|             g_list_prepend (impl_window->native_children, child);
 | ||
|         }
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| reparent_to_impl (GdkWindow *private)
 | ||
| {
 | ||
|   GList *l;
 | ||
|   GdkWindow *child;
 | ||
|   gboolean show;
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
| 
 | ||
|   impl_class = GDK_WINDOW_IMPL_GET_CLASS (private->impl);
 | ||
| 
 | ||
|   /* Enumerate in reverse order so we get the right order for the native
 | ||
|      windows (first in childrens list is topmost, and reparent places on top) */
 | ||
|   for (l = g_list_last (private->children); l != NULL; l = l->prev)
 | ||
|     {
 | ||
|       child = l->data;
 | ||
| 
 | ||
|       if (child->impl == private->impl)
 | ||
| 	reparent_to_impl (child);
 | ||
|       else
 | ||
| 	{
 | ||
| 	  show = impl_class->reparent ((GdkWindow *)child,
 | ||
| 				       (GdkWindow *)private,
 | ||
| 				       child->x, child->y);
 | ||
| 	  if (show)
 | ||
| 	    gdk_window_show_unraised ((GdkWindow *)child);
 | ||
| 	}
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_reparent:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @new_parent: new parent to move @window into
 | ||
|  * @x: X location inside the new parent
 | ||
|  * @y: Y location inside the new parent
 | ||
|  *
 | ||
|  * Reparents @window into the given @new_parent. The window being
 | ||
|  * reparented will be unmapped as a side effect.
 | ||
|  *
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_reparent (GdkWindow *window,
 | ||
| 		     GdkWindow *new_parent,
 | ||
| 		     gint       x,
 | ||
| 		     gint       y)
 | ||
| {
 | ||
|   GdkWindow *old_parent;
 | ||
|   GdkScreen *screen;
 | ||
|   gboolean show, was_mapped;
 | ||
|   gboolean do_reparent_to_impl;
 | ||
|   GdkEventMask old_native_event_mask;
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
|   g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
 | ||
|   g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
 | ||
| 
 | ||
|   if (GDK_WINDOW_DESTROYED (window) ||
 | ||
|       (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
 | ||
|     return;
 | ||
| 
 | ||
|   screen = gdk_window_get_screen (window);
 | ||
|   if (!new_parent)
 | ||
|     new_parent = gdk_screen_get_root_window (screen);
 | ||
| 
 | ||
|   /* No input-output children of input-only windows */
 | ||
|   if (new_parent->input_only && !window->input_only)
 | ||
|     return;
 | ||
| 
 | ||
|   /* Don't create loops in hierarchy */
 | ||
|   if (is_parent_of (window, new_parent))
 | ||
|     return;
 | ||
| 
 | ||
|   impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
|   old_parent = window->parent;
 | ||
| 
 | ||
|   was_mapped = GDK_WINDOW_IS_MAPPED (window);
 | ||
| 
 | ||
|   /* Reparenting to toplevel. Ensure we have a native window so this can work */
 | ||
|   if (new_parent->window_type == GDK_WINDOW_ROOT ||
 | ||
|       new_parent->window_type == GDK_WINDOW_FOREIGN)
 | ||
|     gdk_window_ensure_native (window);
 | ||
| 
 | ||
|   old_native_event_mask = 0;
 | ||
|   do_reparent_to_impl = FALSE;
 | ||
|   if (gdk_window_has_impl (window))
 | ||
|     {
 | ||
|       old_native_event_mask = get_native_event_mask (window);
 | ||
|       /* Native window */
 | ||
|       show = impl_class->reparent (window, new_parent, x, y);
 | ||
|     }
 | ||
|   else
 | ||
|     {
 | ||
|       /* This shouldn't happen, as we created a native in this case, check anyway to see if that ever fails */
 | ||
|       g_assert (new_parent->window_type != GDK_WINDOW_ROOT &&
 | ||
| 		new_parent->window_type != GDK_WINDOW_FOREIGN);
 | ||
| 
 | ||
|       show = was_mapped;
 | ||
|       gdk_window_hide (window);
 | ||
| 
 | ||
|       do_reparent_to_impl = TRUE;
 | ||
|       change_impl (window,
 | ||
| 		   new_parent->impl_window,
 | ||
| 		   new_parent->impl);
 | ||
|     }
 | ||
| 
 | ||
|   /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
 | ||
|    * the root window
 | ||
|    */
 | ||
|   if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
 | ||
|     {
 | ||
|       new_parent = gdk_screen_get_root_window (screen);
 | ||
|     }
 | ||
| 
 | ||
|   if (old_parent)
 | ||
|     {
 | ||
|       old_parent->children = g_list_remove_link (old_parent->children, &window->children_list_node);
 | ||
| 
 | ||
|       if (gdk_window_has_impl (window))
 | ||
|         old_parent->impl_window->native_children =
 | ||
|           g_list_remove (old_parent->impl_window->native_children, window);
 | ||
|     }
 | ||
| 
 | ||
|   window->parent = new_parent;
 | ||
|   window->x = x;
 | ||
|   window->y = y;
 | ||
| 
 | ||
|   new_parent->children = g_list_concat (&window->children_list_node, new_parent->children);
 | ||
| 
 | ||
|   if (gdk_window_has_impl (window))
 | ||
|     new_parent->impl_window->native_children = g_list_prepend (new_parent->impl_window->native_children, window);
 | ||
| 
 | ||
|   /* Switch the window type as appropriate */
 | ||
| 
 | ||
|   switch (GDK_WINDOW_TYPE (new_parent))
 | ||
|     {
 | ||
|     case GDK_WINDOW_ROOT:
 | ||
|     case GDK_WINDOW_FOREIGN:
 | ||
|       if (window->toplevel_window_type != -1)
 | ||
| 	GDK_WINDOW_TYPE (window) = window->toplevel_window_type;
 | ||
|       else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
 | ||
| 	GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
 | ||
|       break;
 | ||
|     case GDK_WINDOW_OFFSCREEN:
 | ||
|     case GDK_WINDOW_TOPLEVEL:
 | ||
|     case GDK_WINDOW_CHILD:
 | ||
|     case GDK_WINDOW_TEMP:
 | ||
|       if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
 | ||
| 	  GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
 | ||
| 	{
 | ||
| 	  /* Save the original window type so we can restore it if the
 | ||
| 	   * window is reparented back to be a toplevel
 | ||
| 	   */
 | ||
| 	  window->toplevel_window_type = GDK_WINDOW_TYPE (window);
 | ||
| 	  GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
 | ||
| 	}
 | ||
|     }
 | ||
| 
 | ||
|   /* If we changed the window type, we might have to set or
 | ||
|    * unset the frame clock on the window
 | ||
|    */
 | ||
|   if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_ROOT &&
 | ||
|       GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
 | ||
|     {
 | ||
|       if (window->frame_clock == NULL)
 | ||
|         {
 | ||
|           GdkFrameClock *frame_clock = g_object_new (GDK_TYPE_FRAME_CLOCK_IDLE, NULL);
 | ||
|           gdk_window_set_frame_clock (window, frame_clock);
 | ||
|           g_object_unref (frame_clock);
 | ||
|         }
 | ||
|     }
 | ||
|   else
 | ||
|     {
 | ||
|       if (window->frame_clock != NULL)
 | ||
|         {
 | ||
|           g_object_run_dispose (G_OBJECT (window->frame_clock));
 | ||
|           gdk_window_set_frame_clock (window, NULL);
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|   /* We might have changed window type for a native windows, so we
 | ||
|      need to change the event mask too. */
 | ||
|   if (gdk_window_has_impl (window))
 | ||
|     {
 | ||
|       GdkEventMask native_event_mask = get_native_event_mask (window);
 | ||
| 
 | ||
|       if (native_event_mask != old_native_event_mask)
 | ||
| 	impl_class->set_events (window,	native_event_mask);
 | ||
|     }
 | ||
| 
 | ||
|   _gdk_window_update_viewable (window);
 | ||
| 
 | ||
|   recompute_visible_regions (window, FALSE);
 | ||
| 
 | ||
|   if (do_reparent_to_impl)
 | ||
|     reparent_to_impl (window);
 | ||
|   else
 | ||
|     {
 | ||
|       /* The reparent will have put the native window topmost in the native parent,
 | ||
|        * which may be wrong wrt other native windows in the non-native hierarchy,
 | ||
|        * so restack */
 | ||
|       if (!gdk_window_has_impl (new_parent))
 | ||
| 	sync_native_window_stack_position (window);
 | ||
|     }
 | ||
| 
 | ||
|   if (show)
 | ||
|     gdk_window_show_unraised (window);
 | ||
|   else
 | ||
|     _gdk_synthesize_crossing_events_for_geometry_change (window);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_ensure_native:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Tries to ensure that there is a window-system native window for this
 | ||
|  * GdkWindow. This may fail in some situations, returning %FALSE.
 | ||
|  *
 | ||
|  * Offscreen window and children of them can never have native windows.
 | ||
|  *
 | ||
|  * Some backends may not support native child windows.
 | ||
|  *
 | ||
|  * Returns: %TRUE if the window has a native window, %FALSE otherwise
 | ||
|  *
 | ||
|  * Since: 2.18
 | ||
|  */
 | ||
| gboolean
 | ||
| gdk_window_ensure_native (GdkWindow *window)
 | ||
| {
 | ||
|   GdkWindow *impl_window;
 | ||
|   GdkWindowImpl *new_impl, *old_impl;
 | ||
|   GdkDisplay *display;
 | ||
|   GdkScreen *screen;
 | ||
|   GdkWindow *above, *parent;
 | ||
|   GList listhead;
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
| 
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 | ||
| 
 | ||
|   if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT ||
 | ||
|       GDK_WINDOW_DESTROYED (window))
 | ||
|     return FALSE;
 | ||
| 
 | ||
|   impl_window = gdk_window_get_impl_window (window);
 | ||
| 
 | ||
|   if (gdk_window_is_offscreen (impl_window))
 | ||
|     return FALSE; /* native in offscreens not supported */
 | ||
| 
 | ||
|   if (impl_window == window)
 | ||
|     /* Already has an impl, and its not offscreen . */
 | ||
|     return TRUE;
 | ||
| 
 | ||
|   /* Need to create a native window */
 | ||
| 
 | ||
|   screen = gdk_window_get_screen (window);
 | ||
|   display = gdk_screen_get_display (screen);
 | ||
|   parent = window->parent;
 | ||
| 
 | ||
|   old_impl = window->impl;
 | ||
|   _gdk_display_create_window_impl (display,
 | ||
|                                    window, parent,
 | ||
|                                    screen,
 | ||
|                                    get_native_event_mask (window),
 | ||
|                                    NULL, 0);
 | ||
|   new_impl = window->impl;
 | ||
| 
 | ||
|   parent->impl_window->native_children =
 | ||
|     g_list_prepend (parent->impl_window->native_children, window);
 | ||
| 
 | ||
|   window->impl = old_impl;
 | ||
|   change_impl (window, window, new_impl);
 | ||
| 
 | ||
|   impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
| 
 | ||
|   /* Native window creation will put the native window topmost in the
 | ||
|    * native parent, which may be wrong wrt the position of the previous
 | ||
|    * non-native window wrt to the other non-native children, so correct this.
 | ||
|    */
 | ||
|   above = find_native_sibling_above (parent, window);
 | ||
|   if (above)
 | ||
|     {
 | ||
|       listhead.data = window;
 | ||
|       listhead.prev = NULL;
 | ||
|       listhead.next = NULL;
 | ||
|       impl_class->restack_under ((GdkWindow *)above, &listhead);
 | ||
|     }
 | ||
| 
 | ||
|   recompute_visible_regions (window, FALSE);
 | ||
| 
 | ||
|   reparent_to_impl (window);
 | ||
| 
 | ||
|   if (!window->input_only)
 | ||
|     impl_class->set_background (window, window->background);
 | ||
| 
 | ||
|   impl_class->input_shape_combine_region (window,
 | ||
|                                           window->input_shape,
 | ||
|                                           0, 0);
 | ||
| 
 | ||
|   if (gdk_window_is_viewable (window))
 | ||
|     impl_class->show (window, FALSE);
 | ||
| 
 | ||
|   gdk_window_invalidate_in_parent (window);
 | ||
| 
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * _gdk_event_filter_unref:
 | ||
|  * @window: (allow-none): A #GdkWindow, or %NULL to be the global window
 | ||
|  * @filter: A window filter
 | ||
|  *
 | ||
|  * Release a reference to @filter.  Note this function may
 | ||
|  * mutate the list storage, so you need to handle this
 | ||
|  * if iterating over a list of filters.
 | ||
|  */
 | ||
| void
 | ||
| _gdk_event_filter_unref (GdkWindow       *window,
 | ||
| 			 GdkEventFilter  *filter)
 | ||
| {
 | ||
|   GList **filters;
 | ||
|   GList *tmp_list;
 | ||
| 
 | ||
|   if (window == NULL)
 | ||
|     filters = &_gdk_default_filters;
 | ||
|   else
 | ||
|     filters = &window->filters;
 | ||
| 
 | ||
|   tmp_list = *filters;
 | ||
|   while (tmp_list)
 | ||
|     {
 | ||
|       GdkEventFilter *iter_filter = tmp_list->data;
 | ||
|       GList *node;
 | ||
| 
 | ||
|       node = tmp_list;
 | ||
|       tmp_list = tmp_list->next;
 | ||
| 
 | ||
|       if (iter_filter != filter)
 | ||
| 	continue;
 | ||
| 
 | ||
|       g_assert (iter_filter->ref_count > 0);
 | ||
| 
 | ||
|       filter->ref_count--;
 | ||
|       if (filter->ref_count != 0)
 | ||
| 	continue;
 | ||
| 
 | ||
|       *filters = g_list_remove_link (*filters, node);
 | ||
|       g_free (filter);
 | ||
|       g_list_free_1 (node);
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| window_remove_filters (GdkWindow *window)
 | ||
| {
 | ||
|   while (window->filters)
 | ||
|     _gdk_event_filter_unref (window, window->filters->data);
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| update_pointer_info_foreach (GdkDisplay           *display,
 | ||
|                              GdkDevice            *device,
 | ||
|                              GdkPointerWindowInfo *pointer_info,
 | ||
|                              gpointer              user_data)
 | ||
| {
 | ||
|   GdkWindow *window = user_data;
 | ||
| 
 | ||
|   if (pointer_info->toplevel_under_pointer == window)
 | ||
|     {
 | ||
|       g_object_unref (pointer_info->toplevel_under_pointer);
 | ||
|       pointer_info->toplevel_under_pointer = NULL;
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| window_remove_from_pointer_info (GdkWindow  *window,
 | ||
|                                  GdkDisplay *display)
 | ||
| {
 | ||
|   _gdk_display_pointer_info_foreach (display,
 | ||
|                                      update_pointer_info_foreach,
 | ||
|                                      window);
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_free_current_paint (GdkWindow *window)
 | ||
| {
 | ||
|   cairo_surface_destroy (window->current_paint.surface);
 | ||
|   window->current_paint.surface = NULL;
 | ||
| 
 | ||
|   cairo_region_destroy (window->current_paint.region);
 | ||
|   window->current_paint.region = NULL;
 | ||
| 
 | ||
|   cairo_region_destroy (window->current_paint.flushed_region);
 | ||
|   window->current_paint.flushed_region = NULL;
 | ||
| 
 | ||
|   cairo_region_destroy (window->current_paint.need_blend_region);
 | ||
|   window->current_paint.need_blend_region = NULL;
 | ||
| 
 | ||
|   window->current_paint.surface_needs_composite = FALSE;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * _gdk_window_destroy_hierarchy:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @recursing: If %TRUE, then this is being called because a parent
 | ||
|  *            was destroyed.
 | ||
|  * @recursing_native: If %TRUE, then this is being called because a native parent
 | ||
|  *            was destroyed. This generally means that the call to the
 | ||
|  *            windowing system to destroy the window can be omitted, since
 | ||
|  *            it will be destroyed as a result of the parent being destroyed.
 | ||
|  *            Unless @foreign_destroy.
 | ||
|  * @foreign_destroy: If %TRUE, the window or a parent was destroyed by some
 | ||
|  *            external agency. The window has already been destroyed and no
 | ||
|  *            windowing system calls should be made. (This may never happen
 | ||
|  *            for some windowing systems.)
 | ||
|  *
 | ||
|  * Internal function to destroy a window. Like gdk_window_destroy(),
 | ||
|  * but does not drop the reference count created by gdk_window_new().
 | ||
|  **/
 | ||
| static void
 | ||
| _gdk_window_destroy_hierarchy (GdkWindow *window,
 | ||
| 			       gboolean   recursing,
 | ||
| 			       gboolean   recursing_native,
 | ||
| 			       gboolean   foreign_destroy)
 | ||
| {
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
|   GdkWindow *temp_window;
 | ||
|   GdkScreen *screen;
 | ||
|   GdkDisplay *display;
 | ||
|   GList *tmp;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   if (GDK_WINDOW_DESTROYED (window))
 | ||
|     return;
 | ||
| 
 | ||
|   display = gdk_window_get_display (window);
 | ||
|   screen = gdk_window_get_screen (window);
 | ||
|   temp_window = g_object_get_qdata (G_OBJECT (screen), quark_pointer_window);
 | ||
|   if (temp_window == window)
 | ||
|     g_object_set_qdata (G_OBJECT (screen), quark_pointer_window, NULL);
 | ||
| 
 | ||
|   switch (window->window_type)
 | ||
|     {
 | ||
|     case GDK_WINDOW_ROOT:
 | ||
|       if (!screen->closed)
 | ||
| 	{
 | ||
| 	  g_error ("attempted to destroy root window");
 | ||
| 	  break;
 | ||
| 	}
 | ||
|       /* else fall thru */
 | ||
|     case GDK_WINDOW_TOPLEVEL:
 | ||
|     case GDK_WINDOW_CHILD:
 | ||
|     case GDK_WINDOW_TEMP:
 | ||
|     case GDK_WINDOW_FOREIGN:
 | ||
|     case GDK_WINDOW_OFFSCREEN:
 | ||
|     case GDK_WINDOW_SUBSURFACE:
 | ||
|       if (window->window_type == GDK_WINDOW_FOREIGN && !foreign_destroy)
 | ||
| 	{
 | ||
| 	  /* Logically, it probably makes more sense to send
 | ||
| 	   * a "destroy yourself" message to the foreign window
 | ||
| 	   * whether or not it's in our hierarchy; but for historical
 | ||
| 	   * reasons, we only send "destroy yourself" messages to
 | ||
| 	   * foreign windows in our hierarchy.
 | ||
| 	   */
 | ||
| 	  if (window->parent)
 | ||
|             {
 | ||
|               impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
| 
 | ||
|               if (gdk_window_has_impl (window))
 | ||
|                 impl_class->destroy_foreign (window);
 | ||
|             }
 | ||
| 
 | ||
| 	  /* Also for historical reasons, we remove any filters
 | ||
| 	   * on a foreign window when it or a parent is destroyed;
 | ||
| 	   * this likely causes problems if two separate portions
 | ||
| 	   * of code are maintaining filter lists on a foreign window.
 | ||
| 	   */
 | ||
| 	  window_remove_filters (window);
 | ||
| 	}
 | ||
|       else
 | ||
| 	{
 | ||
| 	  if (window->parent)
 | ||
| 	    {
 | ||
| 	      if (window->parent->children)
 | ||
|                 window->parent->children = g_list_remove_link (window->parent->children, &window->children_list_node);
 | ||
| 
 | ||
|               if (gdk_window_has_impl (window))
 | ||
|                 window->parent->impl_window->native_children =
 | ||
|                   g_list_remove (window->parent->impl_window->native_children, window);
 | ||
| 
 | ||
| 	      if (!recursing &&
 | ||
| 		  GDK_WINDOW_IS_MAPPED (window))
 | ||
| 		{
 | ||
| 		  recompute_visible_regions (window, FALSE);
 | ||
| 		  gdk_window_invalidate_in_parent (window);
 | ||
| 		}
 | ||
| 	    }
 | ||
| 
 | ||
|           if (window->gl_paint_context)
 | ||
|             {
 | ||
|               /* Make sure to destroy if current */
 | ||
|               g_object_run_dispose (G_OBJECT (window->gl_paint_context));
 | ||
|               g_object_unref (window->gl_paint_context);
 | ||
|               window->gl_paint_context = NULL;
 | ||
|             }
 | ||
| 
 | ||
|           if (window->frame_clock)
 | ||
|             {
 | ||
|               g_object_run_dispose (G_OBJECT (window->frame_clock));
 | ||
|               gdk_window_set_frame_clock (window, NULL);
 | ||
|             }
 | ||
| 
 | ||
|           gdk_window_free_current_paint (window);
 | ||
| 
 | ||
|           if (window->background)
 | ||
|             {
 | ||
|               cairo_pattern_destroy (window->background);
 | ||
|               window->background = NULL;
 | ||
|             }
 | ||
| 
 | ||
| 	  if (window->window_type == GDK_WINDOW_FOREIGN)
 | ||
| 	    g_assert (window->children == NULL);
 | ||
| 	  else
 | ||
| 	    {
 | ||
| 	      tmp = window->children;
 | ||
| 	      window->children = NULL;
 | ||
| 	      /* No need to free children list, its all made up of in-struct nodes */
 | ||
| 
 | ||
| 	      while (tmp)
 | ||
| 		{
 | ||
| 		  temp_window = tmp->data;
 | ||
| 		  tmp = tmp->next;
 | ||
| 
 | ||
| 		  if (temp_window)
 | ||
| 		    _gdk_window_destroy_hierarchy (temp_window,
 | ||
| 						   TRUE,
 | ||
| 						   recursing_native || gdk_window_has_impl (window),
 | ||
| 						   foreign_destroy);
 | ||
| 		}
 | ||
| 
 | ||
| 
 | ||
|               if (gdk_window_has_impl (window))
 | ||
|                 g_assert (window->native_children == NULL);
 | ||
| 	    }
 | ||
| 
 | ||
| 	  _gdk_window_clear_update_area (window);
 | ||
| 
 | ||
| 	  impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
| 
 | ||
| 	  if (gdk_window_has_impl (window))
 | ||
| 	    impl_class->destroy (window, recursing_native, foreign_destroy);
 | ||
| 	  else
 | ||
| 	    {
 | ||
| 	      /* hide to make sure we repaint and break grabs */
 | ||
| 	      gdk_window_hide (window);
 | ||
| 	    }
 | ||
| 
 | ||
| 	  window->state |= GDK_WINDOW_STATE_WITHDRAWN;
 | ||
| 	  window->parent = NULL;
 | ||
| 	  window->destroyed = TRUE;
 | ||
| 
 | ||
| 	  window_remove_filters (window);
 | ||
| 
 | ||
| 	  window_remove_from_pointer_info (window, display);
 | ||
| 
 | ||
| 	  if (window->clip_region)
 | ||
| 	    {
 | ||
| 	      cairo_region_destroy (window->clip_region);
 | ||
| 	      window->clip_region = NULL;
 | ||
| 	    }
 | ||
| 	}
 | ||
|       break;
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * _gdk_window_destroy:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @foreign_destroy: If %TRUE, the window or a parent was destroyed by some
 | ||
|  *            external agency. The window has already been destroyed and no
 | ||
|  *            windowing system calls should be made. (This may never happen
 | ||
|  *            for some windowing systems.)
 | ||
|  *
 | ||
|  * Internal function to destroy a window. Like gdk_window_destroy(),
 | ||
|  * but does not drop the reference count created by gdk_window_new().
 | ||
|  **/
 | ||
| void
 | ||
| _gdk_window_destroy (GdkWindow *window,
 | ||
| 		     gboolean   foreign_destroy)
 | ||
| {
 | ||
|   _gdk_window_destroy_hierarchy (window, FALSE, FALSE, foreign_destroy);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_destroy:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Destroys the window system resources associated with @window and decrements @window's
 | ||
|  * reference count. The window system resources for all children of @window are also
 | ||
|  * destroyed, but the children’s reference counts are not decremented.
 | ||
|  *
 | ||
|  * Note that a window will not be destroyed automatically when its reference count
 | ||
|  * reaches zero. You must call this function yourself before that happens.
 | ||
|  *
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_destroy (GdkWindow *window)
 | ||
| {
 | ||
|   _gdk_window_destroy_hierarchy (window, FALSE, FALSE, FALSE);
 | ||
|   g_object_unref (window);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_user_data:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @user_data: (allow-none) (type GObject.Object): user data
 | ||
|  *
 | ||
|  * For most purposes this function is deprecated in favor of
 | ||
|  * g_object_set_data(). However, for historical reasons GTK+ stores
 | ||
|  * the #GtkWidget that owns a #GdkWindow as user data on the
 | ||
|  * #GdkWindow. So, custom widget implementations should use
 | ||
|  * this function for that. If GTK+ receives an event for a #GdkWindow,
 | ||
|  * and the user data for the window is non-%NULL, GTK+ will assume the
 | ||
|  * user data is a #GtkWidget, and forward the event to that widget.
 | ||
|  *
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_set_user_data (GdkWindow *window,
 | ||
| 			  gpointer   user_data)
 | ||
| {
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   window->user_data = user_data;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_user_data:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @data: (out): return location for user data
 | ||
|  *
 | ||
|  * Retrieves the user data for @window, which is normally the widget
 | ||
|  * that @window belongs to. See gdk_window_set_user_data().
 | ||
|  *
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_get_user_data (GdkWindow *window,
 | ||
| 			  gpointer  *data)
 | ||
| {
 | ||
|   *data = window->user_data;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_window_type:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Gets the type of the window. See #GdkWindowType.
 | ||
|  *
 | ||
|  * Returns: type of window
 | ||
|  **/
 | ||
| GdkWindowType
 | ||
| gdk_window_get_window_type (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), (GdkWindowType) -1);
 | ||
| 
 | ||
|   return GDK_WINDOW_TYPE (window);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_visual:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * 
 | ||
|  * Gets the #GdkVisual describing the pixel format of @window.
 | ||
|  * 
 | ||
|  * Returns: (transfer none): a #GdkVisual
 | ||
|  *
 | ||
|  * Since: 2.24
 | ||
|  **/
 | ||
| GdkVisual*
 | ||
| gdk_window_get_visual (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 | ||
|   
 | ||
|   return window->visual;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_screen:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * 
 | ||
|  * Gets the #GdkScreen associated with a #GdkWindow.
 | ||
|  * 
 | ||
|  * Returns: (transfer none): the #GdkScreen associated with @window
 | ||
|  *
 | ||
|  * Since: 2.24
 | ||
|  **/
 | ||
| GdkScreen*
 | ||
| gdk_window_get_screen (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 | ||
| 
 | ||
|   return gdk_visual_get_screen (window->visual);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_display:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * 
 | ||
|  * Gets the #GdkDisplay associated with a #GdkWindow.
 | ||
|  * 
 | ||
|  * Returns: (transfer none): the #GdkDisplay associated with @window
 | ||
|  *
 | ||
|  * Since: 2.24
 | ||
|  **/
 | ||
| GdkDisplay *
 | ||
| gdk_window_get_display (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 | ||
| 
 | ||
|   return gdk_screen_get_display (gdk_visual_get_screen (window->visual));
 | ||
| }
 | ||
| /**
 | ||
|  * gdk_window_is_destroyed:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Check to see if a window is destroyed..
 | ||
|  *
 | ||
|  * Returns: %TRUE if the window is destroyed
 | ||
|  *
 | ||
|  * Since: 2.18
 | ||
|  **/
 | ||
| gboolean
 | ||
| gdk_window_is_destroyed (GdkWindow *window)
 | ||
| {
 | ||
|   return GDK_WINDOW_DESTROYED (window);
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| to_embedder (GdkWindow *window,
 | ||
|              gdouble    offscreen_x,
 | ||
|              gdouble    offscreen_y,
 | ||
|              gdouble   *embedder_x,
 | ||
|              gdouble   *embedder_y)
 | ||
| {
 | ||
|   g_signal_emit (window, signals[TO_EMBEDDER], 0,
 | ||
|                  offscreen_x, offscreen_y,
 | ||
|                  embedder_x, embedder_y);
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| from_embedder (GdkWindow *window,
 | ||
|                gdouble    embedder_x,
 | ||
|                gdouble    embedder_y,
 | ||
|                gdouble   *offscreen_x,
 | ||
|                gdouble   *offscreen_y)
 | ||
| {
 | ||
|   g_signal_emit (window, signals[FROM_EMBEDDER], 0,
 | ||
|                  embedder_x, embedder_y,
 | ||
|                  offscreen_x, offscreen_y);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_has_native:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Checks whether the window has a native window or not. Note that
 | ||
|  * you can use gdk_window_ensure_native() if a native window is needed.
 | ||
|  *
 | ||
|  * Returns: %TRUE if the @window has a native window, %FALSE otherwise.
 | ||
|  *
 | ||
|  * Since: 2.22
 | ||
|  */
 | ||
| gboolean
 | ||
| gdk_window_has_native (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 | ||
| 
 | ||
|   return window->parent == NULL || window->parent->impl != window->impl;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_position:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @x: (out) (allow-none): X coordinate of window
 | ||
|  * @y: (out) (allow-none): Y coordinate of window
 | ||
|  *
 | ||
|  * Obtains the position of the window as reported in the
 | ||
|  * most-recently-processed #GdkEventConfigure. Contrast with
 | ||
|  * gdk_window_get_geometry() which queries the X server for the
 | ||
|  * current window position, regardless of which events have been
 | ||
|  * received or processed.
 | ||
|  *
 | ||
|  * The position coordinates are relative to the window’s parent window.
 | ||
|  *
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_get_position (GdkWindow *window,
 | ||
| 			 gint      *x,
 | ||
| 			 gint      *y)
 | ||
| {
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   if (x)
 | ||
|     *x = window->x;
 | ||
|   if (y)
 | ||
|     *y = window->y;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_parent:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Obtains the parent of @window, as known to GDK. Does not query the
 | ||
|  * X server; thus this returns the parent as passed to gdk_window_new(),
 | ||
|  * not the actual parent. This should never matter unless you’re using
 | ||
|  * Xlib calls mixed with GDK calls on the X11 platform. It may also
 | ||
|  * matter for toplevel windows, because the window manager may choose
 | ||
|  * to reparent them.
 | ||
|  *
 | ||
|  * Note that you should use gdk_window_get_effective_parent() when
 | ||
|  * writing generic code that walks up a window hierarchy, because
 | ||
|  * gdk_window_get_parent() will most likely not do what you expect if
 | ||
|  * there are offscreen windows in the hierarchy.
 | ||
|  *
 | ||
|  * Returns: (transfer none): parent of @window
 | ||
|  **/
 | ||
| GdkWindow*
 | ||
| gdk_window_get_parent (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 | ||
| 
 | ||
|   return window->parent;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_effective_parent:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Obtains the parent of @window, as known to GDK. Works like
 | ||
|  * gdk_window_get_parent() for normal windows, but returns the
 | ||
|  * window’s embedder for offscreen windows.
 | ||
|  *
 | ||
|  * See also: gdk_offscreen_window_get_embedder()
 | ||
|  *
 | ||
|  * Returns: (transfer none): effective parent of @window
 | ||
|  *
 | ||
|  * Since: 2.22
 | ||
|  **/
 | ||
| GdkWindow *
 | ||
| gdk_window_get_effective_parent (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 | ||
| 
 | ||
|   if (gdk_window_is_offscreen (window))
 | ||
|     return gdk_offscreen_window_get_embedder (window);
 | ||
|   else if (gdk_window_is_subsurface (window))
 | ||
|     return window->transient_for;
 | ||
|   else
 | ||
|     return window->parent;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_toplevel:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Gets the toplevel window that’s an ancestor of @window.
 | ||
|  *
 | ||
|  * Any window type but %GDK_WINDOW_CHILD is considered a
 | ||
|  * toplevel window, as is a %GDK_WINDOW_CHILD window that
 | ||
|  * has a root window as parent.
 | ||
|  *
 | ||
|  * Note that you should use gdk_window_get_effective_toplevel() when
 | ||
|  * you want to get to a window’s toplevel as seen on screen, because
 | ||
|  * gdk_window_get_toplevel() will most likely not do what you expect
 | ||
|  * if there are offscreen windows in the hierarchy.
 | ||
|  *
 | ||
|  * Returns: (transfer none): the toplevel window containing @window
 | ||
|  **/
 | ||
| GdkWindow *
 | ||
| gdk_window_get_toplevel (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 | ||
| 
 | ||
|   while (window->window_type == GDK_WINDOW_CHILD ||
 | ||
|          window->window_type == GDK_WINDOW_SUBSURFACE)
 | ||
|     {
 | ||
|       if (gdk_window_is_toplevel (window))
 | ||
| 	break;
 | ||
|       window = window->parent;
 | ||
|     }
 | ||
| 
 | ||
|   return window;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_effective_toplevel:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Gets the toplevel window that’s an ancestor of @window.
 | ||
|  *
 | ||
|  * Works like gdk_window_get_toplevel(), but treats an offscreen window's
 | ||
|  * embedder as its parent, using gdk_window_get_effective_parent().
 | ||
|  *
 | ||
|  * See also: gdk_offscreen_window_get_embedder()
 | ||
|  *
 | ||
|  * Returns: (transfer none): the effective toplevel window containing @window
 | ||
|  *
 | ||
|  * Since: 2.22
 | ||
|  **/
 | ||
| GdkWindow *
 | ||
| gdk_window_get_effective_toplevel (GdkWindow *window)
 | ||
| {
 | ||
|   GdkWindow *parent;
 | ||
| 
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 | ||
| 
 | ||
|   while ((parent = gdk_window_get_effective_parent (window)) != NULL &&
 | ||
| 	 (gdk_window_get_window_type (parent) != GDK_WINDOW_ROOT))
 | ||
|     window = parent;
 | ||
| 
 | ||
|   return window;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_children:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Gets the list of children of @window known to GDK.
 | ||
|  * This function only returns children created via GDK,
 | ||
|  * so for example it’s useless when used with the root window;
 | ||
|  * it only returns windows an application created itself.
 | ||
|  *
 | ||
|  * The returned list must be freed, but the elements in the
 | ||
|  * list need not be.
 | ||
|  *
 | ||
|  * Returns: (transfer container) (element-type GdkWindow):
 | ||
|  *     list of child windows inside @window
 | ||
|  **/
 | ||
| GList*
 | ||
| gdk_window_get_children (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 | ||
| 
 | ||
|   if (GDK_WINDOW_DESTROYED (window))
 | ||
|     return NULL;
 | ||
| 
 | ||
|   return g_list_copy (window->children);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_peek_children:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Like gdk_window_get_children(), but does not copy the list of
 | ||
|  * children, so the list does not need to be freed.
 | ||
|  *
 | ||
|  * Returns: (transfer none) (element-type GdkWindow):
 | ||
|  *     a reference to the list of child windows in @window
 | ||
|  **/
 | ||
| GList *
 | ||
| gdk_window_peek_children (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 | ||
| 
 | ||
|   if (GDK_WINDOW_DESTROYED (window))
 | ||
|     return NULL;
 | ||
| 
 | ||
|   return window->children;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_children_with_user_data:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @user_data: user data to look for
 | ||
|  *
 | ||
|  * Gets the list of children of @window known to GDK with a
 | ||
|  * particular @user_data set on it.
 | ||
|  *
 | ||
|  * The returned list must be freed, but the elements in the
 | ||
|  * list need not be.
 | ||
|  *
 | ||
|  * The list is returned in (relative) stacking order, i.e. the
 | ||
|  * lowest window is first.
 | ||
|  *
 | ||
|  * Returns: (transfer container) (element-type GdkWindow):
 | ||
|  *     list of child windows inside @window
 | ||
|  *
 | ||
|  * Since: 3.10
 | ||
|  **/
 | ||
| GList *
 | ||
| gdk_window_get_children_with_user_data (GdkWindow *window,
 | ||
|                                         gpointer   user_data)
 | ||
| {
 | ||
|   GdkWindow *child;
 | ||
|   GList *res, *l;
 | ||
| 
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 | ||
| 
 | ||
|   if (GDK_WINDOW_DESTROYED (window))
 | ||
|     return NULL;
 | ||
| 
 | ||
|   res = NULL;
 | ||
|   for (l = window->children; l != NULL; l = l->next)
 | ||
|     {
 | ||
|       child = l->data;
 | ||
| 
 | ||
|       if (child->user_data == user_data)
 | ||
| 	res = g_list_prepend (res, child);
 | ||
|     }
 | ||
| 
 | ||
|   return res;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_add_filter: (skip)
 | ||
|  * @window: (allow-none): a #GdkWindow
 | ||
|  * @function: filter callback
 | ||
|  * @data: data to pass to filter callback
 | ||
|  *
 | ||
|  * Adds an event filter to @window, allowing you to intercept events
 | ||
|  * before they reach GDK. This is a low-level operation and makes it
 | ||
|  * easy to break GDK and/or GTK+, so you have to know what you're
 | ||
|  * doing. Pass %NULL for @window to get all events for all windows,
 | ||
|  * instead of events for a specific window.
 | ||
|  *
 | ||
|  * If you are interested in X GenericEvents, bear in mind that
 | ||
|  * XGetEventData() has been already called on the event, and
 | ||
|  * XFreeEventData() must not be called within @function.
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_add_filter (GdkWindow     *window,
 | ||
| 		       GdkFilterFunc  function,
 | ||
| 		       gpointer       data)
 | ||
| {
 | ||
|   GList *tmp_list;
 | ||
|   GdkEventFilter *filter;
 | ||
| 
 | ||
|   g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   if (window && GDK_WINDOW_DESTROYED (window))
 | ||
|     return;
 | ||
| 
 | ||
|   /* Filters are for the native events on the native window, so
 | ||
|      ensure there is a native window. */
 | ||
|   if (window)
 | ||
|     gdk_window_ensure_native (window);
 | ||
| 
 | ||
|   if (window)
 | ||
|     tmp_list = window->filters;
 | ||
|   else
 | ||
|     tmp_list = _gdk_default_filters;
 | ||
| 
 | ||
|   while (tmp_list)
 | ||
|     {
 | ||
|       filter = (GdkEventFilter *)tmp_list->data;
 | ||
|       if ((filter->function == function) && (filter->data == data))
 | ||
|         {
 | ||
|           filter->ref_count++;
 | ||
|           filter->flags = 0;
 | ||
|           return;
 | ||
|         }
 | ||
|       tmp_list = tmp_list->next;
 | ||
|     }
 | ||
| 
 | ||
|   filter = g_new (GdkEventFilter, 1);
 | ||
|   filter->function = function;
 | ||
|   filter->data = data;
 | ||
|   filter->ref_count = 1;
 | ||
|   filter->flags = 0;
 | ||
| 
 | ||
|   if (window)
 | ||
|     window->filters = g_list_append (window->filters, filter);
 | ||
|   else
 | ||
|     _gdk_default_filters = g_list_append (_gdk_default_filters, filter);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_remove_filter: (skip)
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @function: previously-added filter function
 | ||
|  * @data: user data for previously-added filter function
 | ||
|  *
 | ||
|  * Remove a filter previously added with gdk_window_add_filter().
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_remove_filter (GdkWindow     *window,
 | ||
|                           GdkFilterFunc  function,
 | ||
|                           gpointer       data)
 | ||
| {
 | ||
|   GList *tmp_list;
 | ||
|   GdkEventFilter *filter;
 | ||
| 
 | ||
|   g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   if (window)
 | ||
|     tmp_list = window->filters;
 | ||
|   else
 | ||
|     tmp_list = _gdk_default_filters;
 | ||
| 
 | ||
|   while (tmp_list)
 | ||
|     {
 | ||
|       filter = (GdkEventFilter *)tmp_list->data;
 | ||
|       tmp_list = tmp_list->next;
 | ||
| 
 | ||
|       if ((filter->function == function) && (filter->data == data))
 | ||
|         {
 | ||
|           filter->flags |= GDK_EVENT_FILTER_REMOVED;
 | ||
| 
 | ||
|           _gdk_event_filter_unref (window, filter);
 | ||
| 
 | ||
|           return;
 | ||
|         }
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_screen_get_toplevel_windows:
 | ||
|  * @screen: The #GdkScreen where the toplevels are located.
 | ||
|  *
 | ||
|  * Obtains a list of all toplevel windows known to GDK on the screen @screen.
 | ||
|  * A toplevel window is a child of the root window (see
 | ||
|  * gdk_get_default_root_window()).
 | ||
|  *
 | ||
|  * The returned list should be freed with g_list_free(), but
 | ||
|  * its elements need not be freed.
 | ||
|  *
 | ||
|  * Returns: (transfer container) (element-type GdkWindow):
 | ||
|  *     list of toplevel windows, free with g_list_free()
 | ||
|  *
 | ||
|  * Since: 2.2
 | ||
|  **/
 | ||
| GList *
 | ||
| gdk_screen_get_toplevel_windows (GdkScreen *screen)
 | ||
| {
 | ||
|   GdkWindow * root_window;
 | ||
|   GList *new_list = NULL;
 | ||
|   GList *tmp_list;
 | ||
| 
 | ||
|   g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
 | ||
| 
 | ||
|   root_window = gdk_screen_get_root_window (screen);
 | ||
| 
 | ||
|   tmp_list = root_window->children;
 | ||
|   while (tmp_list)
 | ||
|     {
 | ||
|       GdkWindow *w = tmp_list->data;
 | ||
| 
 | ||
|       if (w->window_type != GDK_WINDOW_FOREIGN)
 | ||
| 	new_list = g_list_prepend (new_list, w);
 | ||
|       tmp_list = tmp_list->next;
 | ||
|     }
 | ||
| 
 | ||
|   return new_list;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_is_visible:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Checks whether the window has been mapped (with gdk_window_show() or
 | ||
|  * gdk_window_show_unraised()).
 | ||
|  *
 | ||
|  * Returns: %TRUE if the window is mapped
 | ||
|  **/
 | ||
| gboolean
 | ||
| gdk_window_is_visible (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 | ||
| 
 | ||
|   return GDK_WINDOW_IS_MAPPED (window);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_is_viewable:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Check if the window and all ancestors of the window are
 | ||
|  * mapped. (This is not necessarily "viewable" in the X sense, since
 | ||
|  * we only check as far as we have GDK window parents, not to the root
 | ||
|  * window.)
 | ||
|  *
 | ||
|  * Returns: %TRUE if the window is viewable
 | ||
|  **/
 | ||
| gboolean
 | ||
| gdk_window_is_viewable (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 | ||
| 
 | ||
|   if (window->destroyed)
 | ||
|     return FALSE;
 | ||
| 
 | ||
|   return window->viewable;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_state:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Gets the bitwise OR of the currently active window state flags,
 | ||
|  * from the #GdkWindowState enumeration.
 | ||
|  *
 | ||
|  * Returns: window state bitfield
 | ||
|  **/
 | ||
| GdkWindowState
 | ||
| gdk_window_get_state (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 | ||
| 
 | ||
|   return window->state;
 | ||
| }
 | ||
| 
 | ||
| static cairo_content_t
 | ||
| gdk_window_get_content (GdkWindow *window)
 | ||
| {
 | ||
|   cairo_surface_t *surface;
 | ||
|   cairo_content_t content;
 | ||
| 
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
 | ||
| 
 | ||
|   surface = gdk_window_ref_impl_surface (window);
 | ||
|   content = cairo_surface_get_content (surface);
 | ||
|   cairo_surface_destroy (surface);
 | ||
| 
 | ||
|   return content;
 | ||
| }
 | ||
| 
 | ||
| static cairo_surface_t *
 | ||
| gdk_window_ref_impl_surface (GdkWindow *window)
 | ||
| {
 | ||
|   return GDK_WINDOW_IMPL_GET_CLASS (window->impl)->ref_cairo_surface (gdk_window_get_impl_window (window));
 | ||
| }
 | ||
| 
 | ||
| GdkGLContext *
 | ||
| gdk_window_get_paint_gl_context (GdkWindow  *window,
 | ||
|                                  GError    **error)
 | ||
| {
 | ||
|   GError *internal_error = NULL;
 | ||
| 
 | ||
|   if (_gdk_gl_flags & GDK_GL_DISABLE)
 | ||
|     {
 | ||
|       g_set_error_literal (error, GDK_GL_ERROR,
 | ||
|                            GDK_GL_ERROR_NOT_AVAILABLE,
 | ||
|                            _("GL support disabled via GDK_DEBUG"));
 | ||
|       return NULL;
 | ||
|     }
 | ||
| 
 | ||
|   if (window->impl_window->gl_paint_context == NULL)
 | ||
|     {
 | ||
|       GdkWindowImplClass *impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
| 
 | ||
|       if (impl_class->create_gl_context == NULL)
 | ||
|         {
 | ||
|           g_set_error_literal (error, GDK_GL_ERROR, GDK_GL_ERROR_NOT_AVAILABLE,
 | ||
|                                _("The current backend does not support OpenGL"));
 | ||
|           return NULL;
 | ||
|         }
 | ||
| 
 | ||
|       window->impl_window->gl_paint_context =
 | ||
|         impl_class->create_gl_context (window->impl_window,
 | ||
|                                        TRUE,
 | ||
|                                        NULL,
 | ||
|                                        &internal_error);
 | ||
|     }
 | ||
| 
 | ||
|   if (internal_error != NULL)
 | ||
|     {
 | ||
|       g_propagate_error (error, internal_error);
 | ||
|       g_clear_object (&(window->impl_window->gl_paint_context));
 | ||
|       return NULL;
 | ||
|     }
 | ||
| 
 | ||
|   gdk_gl_context_realize (window->impl_window->gl_paint_context, &internal_error);
 | ||
|   if (internal_error != NULL)
 | ||
|     {
 | ||
|       g_propagate_error (error, internal_error);
 | ||
|       g_clear_object (&(window->impl_window->gl_paint_context));
 | ||
|       return NULL;
 | ||
|     }
 | ||
| 
 | ||
|   return window->impl_window->gl_paint_context;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_create_gl_context:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @error: return location for an error
 | ||
|  *
 | ||
|  * Creates a new #GdkGLContext matching the
 | ||
|  * framebuffer format to the visual of the #GdkWindow. The context
 | ||
|  * is disconnected from any particular window or surface.
 | ||
|  *
 | ||
|  * If the creation of the #GdkGLContext failed, @error will be set.
 | ||
|  *
 | ||
|  * Before using the returned #GdkGLContext, you will need to
 | ||
|  * call gdk_gl_context_make_current() or gdk_gl_context_realize().
 | ||
|  *
 | ||
|  * Returns: (transfer full): the newly created #GdkGLContext, or
 | ||
|  * %NULL on error
 | ||
|  *
 | ||
|  * Since: 3.16
 | ||
|  **/
 | ||
| GdkGLContext *
 | ||
| gdk_window_create_gl_context (GdkWindow    *window,
 | ||
|                               GError      **error)
 | ||
| {
 | ||
|   GdkGLContext *paint_context;
 | ||
| 
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 | ||
|   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 | ||
| 
 | ||
|   paint_context = gdk_window_get_paint_gl_context (window, error);
 | ||
|   if (paint_context == NULL)
 | ||
|     return NULL;
 | ||
| 
 | ||
|   return GDK_WINDOW_IMPL_GET_CLASS (window->impl)->create_gl_context (window->impl_window,
 | ||
| 								      FALSE,
 | ||
|                                                                       paint_context,
 | ||
|                                                                       error);
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_begin_paint_internal (GdkWindow            *window,
 | ||
| 			         const cairo_region_t *region)
 | ||
| {
 | ||
|   GdkRectangle clip_box;
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
|   double sx, sy;
 | ||
|   gboolean needs_surface;
 | ||
|   cairo_content_t surface_content;
 | ||
| 
 | ||
|   if (GDK_WINDOW_DESTROYED (window) ||
 | ||
|       !gdk_window_has_impl (window))
 | ||
|     return;
 | ||
| 
 | ||
|   if (window->current_paint.surface != NULL)
 | ||
|     {
 | ||
|       g_warning ("A paint operation on the window is alredy in progress. "
 | ||
|                  "This is not allowed.");
 | ||
|       return;
 | ||
|     }
 | ||
| 
 | ||
|   impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
| 
 | ||
|   needs_surface = TRUE;
 | ||
|   if (impl_class->begin_paint)
 | ||
|     needs_surface = impl_class->begin_paint (window);
 | ||
| 
 | ||
|   window->current_paint.region = cairo_region_copy (region);
 | ||
|   cairo_region_intersect (window->current_paint.region, window->clip_region);
 | ||
|   cairo_region_get_extents (window->current_paint.region, &clip_box);
 | ||
| 
 | ||
|   window->current_paint.flushed_region = cairo_region_create ();
 | ||
|   window->current_paint.need_blend_region = cairo_region_create ();
 | ||
| 
 | ||
|   surface_content = gdk_window_get_content (window);
 | ||
| 
 | ||
|   window->current_paint.use_gl = window->impl_window->gl_paint_context != NULL;
 | ||
| 
 | ||
|   if (window->current_paint.use_gl)
 | ||
|     {
 | ||
|       GdkGLContext *context;
 | ||
| 
 | ||
|       int ww = gdk_window_get_width (window) * gdk_window_get_scale_factor (window);
 | ||
|       int wh = gdk_window_get_height (window) * gdk_window_get_scale_factor (window);
 | ||
| 
 | ||
|       context = gdk_window_get_paint_gl_context (window, NULL);
 | ||
|       if (context == NULL)
 | ||
|         {
 | ||
|           g_warning ("gl rendering failed, context: %p", context);
 | ||
|           window->current_paint.use_gl = FALSE;
 | ||
|         }
 | ||
|       else
 | ||
|         {
 | ||
| 	  gdk_gl_context_make_current (context);
 | ||
|           /* With gl we always need a surface to combine the gl
 | ||
|              drawing with the native drawing. */
 | ||
|           needs_surface = TRUE;
 | ||
|           /* Also, we need the surface to include alpha */
 | ||
|           surface_content = CAIRO_CONTENT_COLOR_ALPHA;
 | ||
| 
 | ||
|           /* Initial setup */
 | ||
|           glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
 | ||
|           glDisable (GL_DEPTH_TEST);
 | ||
|           glDisable(GL_BLEND);
 | ||
|           glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
 | ||
| 
 | ||
|           glViewport (0, 0, ww, wh);
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|   if (needs_surface)
 | ||
|     {
 | ||
|       window->current_paint.surface = gdk_window_create_similar_surface (window,
 | ||
|                                                                          surface_content,
 | ||
|                                                                          MAX (clip_box.width, 1),
 | ||
|                                                                          MAX (clip_box.height, 1));
 | ||
|       sx = sy = 1;
 | ||
|       cairo_surface_get_device_scale (window->current_paint.surface, &sx, &sy);
 | ||
|       cairo_surface_set_device_offset (window->current_paint.surface, -clip_box.x*sx, -clip_box.y*sy);
 | ||
|       gdk_cairo_surface_mark_as_direct (window->current_paint.surface, window);
 | ||
| 
 | ||
|       window->current_paint.surface_needs_composite = TRUE;
 | ||
|     }
 | ||
|   else
 | ||
|     {
 | ||
|       window->current_paint.surface = gdk_window_ref_impl_surface (window);
 | ||
|       window->current_paint.surface_needs_composite = FALSE;
 | ||
|     }
 | ||
| 
 | ||
|   if (!cairo_region_is_empty (window->current_paint.region))
 | ||
|     gdk_window_clear_backing_region (window);
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_end_paint_internal (GdkWindow *window)
 | ||
| {
 | ||
|   GdkWindow *composited;
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
|   GdkRectangle clip_box = { 0, };
 | ||
|   cairo_t *cr;
 | ||
| 
 | ||
|   if (GDK_WINDOW_DESTROYED (window) ||
 | ||
|       !gdk_window_has_impl (window))
 | ||
|     return;
 | ||
| 
 | ||
|   if (window->current_paint.surface == NULL)
 | ||
|     {
 | ||
|       g_warning (G_STRLOC": no preceding call to gdk_window_begin_draw_frame(), see documentation");
 | ||
|       return;
 | ||
|     }
 | ||
| 
 | ||
|   impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
| 
 | ||
|   if (impl_class->end_paint)
 | ||
|     impl_class->end_paint (window);
 | ||
| 
 | ||
|   if (window->current_paint.surface_needs_composite)
 | ||
|     {
 | ||
|       cairo_surface_t *surface;
 | ||
| 
 | ||
|       cairo_region_get_extents (window->current_paint.region, &clip_box);
 | ||
| 
 | ||
|       if (window->current_paint.use_gl)
 | ||
|         {
 | ||
|           cairo_region_t *opaque_region = cairo_region_copy (window->current_paint.region);
 | ||
|           cairo_region_subtract (opaque_region, window->current_paint.flushed_region);
 | ||
|           cairo_region_subtract (opaque_region, window->current_paint.need_blend_region);
 | ||
| 
 | ||
|           gdk_gl_context_make_current (window->gl_paint_context);
 | ||
| 
 | ||
|           if (!cairo_region_is_empty (opaque_region))
 | ||
|             gdk_gl_texture_from_surface (window->current_paint.surface,
 | ||
|                                          opaque_region);
 | ||
|           if (!cairo_region_is_empty (window->current_paint.need_blend_region))
 | ||
|             {
 | ||
|               glEnable(GL_BLEND);
 | ||
|               gdk_gl_texture_from_surface (window->current_paint.surface,
 | ||
|                                            window->current_paint.need_blend_region);
 | ||
|               glDisable(GL_BLEND);
 | ||
|             }
 | ||
| 
 | ||
|           cairo_region_destroy (opaque_region);
 | ||
| 
 | ||
|           gdk_gl_context_end_frame (window->gl_paint_context,
 | ||
|                                     window->current_paint.region,
 | ||
|                                     window->active_update_area);
 | ||
|         }
 | ||
|       else
 | ||
|         {
 | ||
|           surface = gdk_window_ref_impl_surface (window);
 | ||
|           cr = cairo_create (surface);
 | ||
| 
 | ||
|           cairo_set_source_surface (cr, window->current_paint.surface, 0, 0);
 | ||
|           gdk_cairo_region (cr, window->current_paint.region);
 | ||
|           cairo_clip (cr);
 | ||
| 
 | ||
|           cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
 | ||
|           cairo_paint (cr);
 | ||
| 
 | ||
|           cairo_destroy (cr);
 | ||
| 
 | ||
|           cairo_surface_flush (surface);
 | ||
|           cairo_surface_destroy (surface);
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|   gdk_window_free_current_paint (window);
 | ||
| 
 | ||
|   /* find a composited window in our hierarchy to signal its
 | ||
|    * parent to redraw, calculating the clip box as we go...
 | ||
|    *
 | ||
|    * stop if parent becomes NULL since then we'd have nowhere
 | ||
|    * to draw (ie: 'composited' will always be non-NULL here).
 | ||
|    */
 | ||
|   for (composited = window;
 | ||
|        composited->parent;
 | ||
|        composited = composited->parent)
 | ||
|     {
 | ||
|       clip_box.x += composited->x;
 | ||
|       clip_box.y += composited->y;
 | ||
|       clip_box.width = MIN (clip_box.width, composited->parent->width - clip_box.x);
 | ||
|       clip_box.height = MIN (clip_box.height, composited->parent->height - clip_box.y);
 | ||
| 
 | ||
|       if (composited->composited)
 | ||
| 	{
 | ||
| 	  gdk_window_invalidate_rect (GDK_WINDOW (composited->parent),
 | ||
| 				      &clip_box, FALSE);
 | ||
| 	  break;
 | ||
| 	}
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_begin_paint_rect:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @rectangle: rectangle you intend to draw to
 | ||
|  *
 | ||
|  * A convenience wrapper around gdk_window_begin_paint_region() which
 | ||
|  * creates a rectangular region for you. See
 | ||
|  * gdk_window_begin_paint_region() for details.
 | ||
|  *
 | ||
|  * Deprecated: 3.22: Use gdk_window_begin_draw_frame() instead
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_begin_paint_rect (GdkWindow          *window,
 | ||
| 			     const GdkRectangle *rectangle)
 | ||
| {
 | ||
|   cairo_region_t *region;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   region = cairo_region_create_rectangle (rectangle);
 | ||
|   gdk_window_begin_paint_internal (window, region);
 | ||
|   cairo_region_destroy (region);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_begin_paint_region:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @region: region you intend to draw to
 | ||
|  *
 | ||
|  * Indicates that you are beginning the process of redrawing @region.
 | ||
|  * A backing store (offscreen buffer) large enough to contain @region
 | ||
|  * will be created. The backing store will be initialized with the
 | ||
|  * background color or background surface for @window. Then, all
 | ||
|  * drawing operations performed on @window will be diverted to the
 | ||
|  * backing store.  When you call gdk_window_end_paint(), the backing
 | ||
|  * store will be copied to @window, making it visible onscreen. Only
 | ||
|  * the part of @window contained in @region will be modified; that is,
 | ||
|  * drawing operations are clipped to @region.
 | ||
|  *
 | ||
|  * The net result of all this is to remove flicker, because the user
 | ||
|  * sees the finished product appear all at once when you call
 | ||
|  * gdk_window_end_paint(). If you draw to @window directly without
 | ||
|  * calling gdk_window_begin_paint_region(), the user may see flicker
 | ||
|  * as individual drawing operations are performed in sequence.  The
 | ||
|  * clipping and background-initializing features of
 | ||
|  * gdk_window_begin_paint_region() are conveniences for the
 | ||
|  * programmer, so you can avoid doing that work yourself.
 | ||
|  *
 | ||
|  * When using GTK+, the widget system automatically places calls to
 | ||
|  * gdk_window_begin_paint_region() and gdk_window_end_paint() around
 | ||
|  * emissions of the expose_event signal. That is, if you’re writing an
 | ||
|  * expose event handler, you can assume that the exposed area in
 | ||
|  * #GdkEventExpose has already been cleared to the window background,
 | ||
|  * is already set as the clip region, and already has a backing store.
 | ||
|  * Therefore in most cases, application code need not call
 | ||
|  * gdk_window_begin_paint_region(). (You can disable the automatic
 | ||
|  * calls around expose events on a widget-by-widget basis by calling
 | ||
|  * gtk_widget_set_double_buffered().)
 | ||
|  *
 | ||
|  * If you call this function multiple times before calling the
 | ||
|  * matching gdk_window_end_paint(), the backing stores are pushed onto
 | ||
|  * a stack. gdk_window_end_paint() copies the topmost backing store
 | ||
|  * onscreen, subtracts the topmost region from all other regions in
 | ||
|  * the stack, and pops the stack. All drawing operations affect only
 | ||
|  * the topmost backing store in the stack. One matching call to
 | ||
|  * gdk_window_end_paint() is required for each call to
 | ||
|  * gdk_window_begin_paint_region().
 | ||
|  *
 | ||
|  * Deprecated: 3.22: Use gdk_window_begin_draw_frame() instead
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_begin_paint_region (GdkWindow            *window,
 | ||
| 			       const cairo_region_t *region)
 | ||
| {
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   gdk_window_begin_paint_internal (window, region);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_begin_draw_frame:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @region: a Cairo region
 | ||
|  *
 | ||
|  * Indicates that you are beginning the process of redrawing @region
 | ||
|  * on @window, and provides you with a #GdkDrawingContext.
 | ||
|  *
 | ||
|  * If @window is a top level #GdkWindow, backed by a native window
 | ||
|  * implementation, a backing store (offscreen buffer) large enough to
 | ||
|  * contain @region will be created. The backing store will be initialized
 | ||
|  * with the background color or background surface for @window. Then, all
 | ||
|  * drawing operations performed on @window will be diverted to the
 | ||
|  * backing store. When you call gdk_window_end_frame(), the contents of
 | ||
|  * the backing store will be copied to @window, making it visible
 | ||
|  * on screen. Only the part of @window contained in @region will be
 | ||
|  * modified; that is, drawing operations are clipped to @region.
 | ||
|  *
 | ||
|  * The net result of all this is to remove flicker, because the user
 | ||
|  * sees the finished product appear all at once when you call
 | ||
|  * gdk_window_end_draw_frame(). If you draw to @window directly without
 | ||
|  * calling gdk_window_begin_draw_frame(), the user may see flicker
 | ||
|  * as individual drawing operations are performed in sequence.
 | ||
|  *
 | ||
|  * When using GTK+, the widget system automatically places calls to
 | ||
|  * gdk_window_begin_draw_frame() and gdk_window_end_draw_frame() around
 | ||
|  * emissions of the `GtkWidget::draw` signal. That is, if you’re
 | ||
|  * drawing the contents of the widget yourself, you can assume that the
 | ||
|  * widget has a cleared background, is already set as the clip region,
 | ||
|  * and already has a backing store. Therefore in most cases, application
 | ||
|  * code in GTK does not need to call gdk_window_begin_draw_frame()
 | ||
|  * explicitly.
 | ||
|  *
 | ||
|  * Returns: (transfer none): a #GdkDrawingContext context that should be
 | ||
|  *   used to draw the contents of the window; the returned context is owned
 | ||
|  *   by GDK.
 | ||
|  *
 | ||
|  * Since: 3.22
 | ||
|  */
 | ||
| GdkDrawingContext *
 | ||
| gdk_window_begin_draw_frame (GdkWindow            *window,
 | ||
|                              const cairo_region_t *region)
 | ||
| {
 | ||
|   GdkDrawingContext *context;
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
| 
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 | ||
| 
 | ||
|   if (window->drawing_context != NULL)
 | ||
|     {
 | ||
|       g_critical ("The window %p already has a drawing context. You cannot "
 | ||
|                   "call gdk_window_begin_draw_frame() without calling "
 | ||
|                   "gdk_window_end_draw_frame() first.", window);
 | ||
|       return NULL;
 | ||
|     }
 | ||
| 
 | ||
|   if (gdk_window_has_native (window) && gdk_window_is_toplevel (window))
 | ||
|     gdk_window_begin_paint_internal (window, region);
 | ||
| 
 | ||
|   impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
|   if (impl_class->create_draw_context != NULL)
 | ||
|     {
 | ||
|       context = impl_class->create_draw_context (window, region);
 | ||
|     }
 | ||
|   else
 | ||
|     {
 | ||
|       context = g_object_new (GDK_TYPE_DRAWING_CONTEXT,
 | ||
|                               "window", window,
 | ||
|                               "clip", region,
 | ||
|                               NULL);
 | ||
|     }
 | ||
| 
 | ||
|   /* Do not take a reference, to avoid creating cycles */
 | ||
|   window->drawing_context = context;
 | ||
| 
 | ||
|   return context;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_end_draw_frame:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @context: the #GdkDrawingContext created by gdk_window_begin_draw_frame()
 | ||
|  *
 | ||
|  * Indicates that the drawing of the contents of @window started with
 | ||
|  * gdk_window_begin_frame() has been completed.
 | ||
|  *
 | ||
|  * This function will take care of destroying the #GdkDrawingContext.
 | ||
|  *
 | ||
|  * It is an error to call this function without a matching
 | ||
|  * gdk_window_begin_frame() first.
 | ||
|  *
 | ||
|  * Since: 3.22
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_end_draw_frame (GdkWindow         *window,
 | ||
|                            GdkDrawingContext *context)
 | ||
| {
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
|   g_return_if_fail (GDK_IS_DRAWING_CONTEXT (context));
 | ||
| 
 | ||
|   if (window->drawing_context == NULL)
 | ||
|     {
 | ||
|       g_critical ("The window %p has no drawing context. You must call "
 | ||
|                   "gdk_window_begin_draw_frame() before calling "
 | ||
|                   "gdk_window_end_draw_frame().", window);
 | ||
|       return;
 | ||
|     }
 | ||
| 
 | ||
|   if (gdk_window_has_native (window) && gdk_window_is_toplevel (window))
 | ||
|     gdk_window_end_paint_internal (window);
 | ||
| 
 | ||
|   impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
|   if (impl_class->destroy_draw_context != NULL)
 | ||
|     impl_class->destroy_draw_context (window, context);
 | ||
|   else
 | ||
|     g_object_unref (context);
 | ||
| 
 | ||
|   window->drawing_context = NULL;
 | ||
| }
 | ||
| 
 | ||
| /*< private >
 | ||
|  * gdk_window_get_current_paint_region:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Retrieves a copy of the current paint region.
 | ||
|  *
 | ||
|  * Returns: (transfer full): a Cairo region
 | ||
|  */
 | ||
| cairo_region_t *
 | ||
| gdk_window_get_current_paint_region (GdkWindow *window)
 | ||
| {
 | ||
|   cairo_region_t *region;
 | ||
| 
 | ||
|   if (window->impl_window->current_paint.region != NULL)
 | ||
|     {
 | ||
|       region = cairo_region_copy (window->impl_window->current_paint.region);
 | ||
|       cairo_region_translate (region, -window->abs_x, -window->abs_y);
 | ||
|     }
 | ||
|   else
 | ||
|     {
 | ||
|       region = cairo_region_copy (window->clip_region);
 | ||
|     }
 | ||
| 
 | ||
|   return region;
 | ||
| }
 | ||
| 
 | ||
| /*< private >
 | ||
|  * gdk_window_get_drawing_context:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Retrieves the #GdkDrawingContext associated to @window by
 | ||
|  * gdk_window_begin_draw_frame().
 | ||
|  *
 | ||
|  * Returns: (transfer none) (nullable): a #GdkDrawingContext, if any is set
 | ||
|  */
 | ||
| GdkDrawingContext *
 | ||
| gdk_window_get_drawing_context (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 | ||
| 
 | ||
|   if (GDK_WINDOW_DESTROYED (window))
 | ||
|     return NULL;
 | ||
| 
 | ||
|   return window->drawing_context;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_mark_paint_from_clip:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @cr: a #cairo_t
 | ||
|  *
 | ||
|  * If you call this during a paint (e.g. between gdk_window_begin_paint_region()
 | ||
|  * and gdk_window_end_paint() then GDK will mark the current clip region of the
 | ||
|  * window as being drawn. This is required when mixing GL rendering via
 | ||
|  * gdk_cairo_draw_from_gl() and cairo rendering, as otherwise GDK has no way
 | ||
|  * of knowing when something paints over the GL-drawn regions.
 | ||
|  *
 | ||
|  * This is typically called automatically by GTK+ and you don't need
 | ||
|  * to care about this.
 | ||
|  *
 | ||
|  * Since: 3.16
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_mark_paint_from_clip (GdkWindow *window,
 | ||
|                                  cairo_t   *cr)
 | ||
| {
 | ||
|   cairo_region_t *clip_region;
 | ||
|   GdkWindow *impl_window = window->impl_window;
 | ||
| 
 | ||
|   if (impl_window->current_paint.surface == NULL ||
 | ||
|       cairo_get_target (cr) != impl_window->current_paint.surface)
 | ||
|     return;
 | ||
| 
 | ||
|   if (cairo_region_is_empty (impl_window->current_paint.flushed_region))
 | ||
|     return;
 | ||
| 
 | ||
|   /* This here seems a bit weird, but basically, we're taking the current
 | ||
|      clip and applying also the flushed region, and the result is that the
 | ||
|      new clip is the intersection of these. This is the area where the newly
 | ||
|      drawn region overlaps a previosly flushed area, which is an area of the
 | ||
|      double buffer surface that need to be blended OVER the back buffer rather
 | ||
|      than SRCed. */
 | ||
|   cairo_save (cr);
 | ||
|   /* We set the identity matrix here so we get and apply regions in native
 | ||
|      window coordinates. */
 | ||
|   cairo_identity_matrix (cr);
 | ||
|   gdk_cairo_region (cr, impl_window->current_paint.flushed_region);
 | ||
|   cairo_clip (cr);
 | ||
| 
 | ||
|   clip_region = gdk_cairo_region_from_clip (cr);
 | ||
|   if (clip_region == NULL)
 | ||
|     {
 | ||
|       /* Failed to represent clip as region, mark all as requiring
 | ||
|          blend */
 | ||
|       cairo_region_union (impl_window->current_paint.need_blend_region,
 | ||
|                           impl_window->current_paint.flushed_region);
 | ||
|       cairo_region_destroy (impl_window->current_paint.flushed_region);
 | ||
|       impl_window->current_paint.flushed_region = cairo_region_create ();
 | ||
|     }
 | ||
|   else
 | ||
|     {
 | ||
|       cairo_region_subtract (impl_window->current_paint.flushed_region, clip_region);
 | ||
|       cairo_region_union (impl_window->current_paint.need_blend_region, clip_region);
 | ||
|     }
 | ||
|   cairo_region_destroy (clip_region);
 | ||
| 
 | ||
|   /* Clear the area on the double buffer surface to transparent so we
 | ||
|      can start drawing from scratch the area "above" the flushed
 | ||
|      region */
 | ||
|   cairo_set_source_rgba (cr, 0, 0, 0, 0);
 | ||
|   cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
 | ||
|   cairo_paint (cr);
 | ||
| 
 | ||
|   cairo_restore (cr);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_end_paint:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Indicates that the backing store created by the most recent call
 | ||
|  * to gdk_window_begin_paint_region() should be copied onscreen and
 | ||
|  * deleted, leaving the next-most-recent backing store or no backing
 | ||
|  * store at all as the active paint region. See
 | ||
|  * gdk_window_begin_paint_region() for full details.
 | ||
|  *
 | ||
|  * It is an error to call this function without a matching
 | ||
|  * gdk_window_begin_paint_region() first.
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_end_paint (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   gdk_window_end_paint_internal (window);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_flush:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * This function does nothing.
 | ||
|  *
 | ||
|  * Since: 2.18
 | ||
|  *
 | ||
|  * Deprecated: 3.14
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_flush (GdkWindow *window)
 | ||
| {
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_clip_region:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * 
 | ||
|  * Computes the region of a window that potentially can be written
 | ||
|  * to by drawing primitives. This region may not take into account
 | ||
|  * other factors such as if the window is obscured by other windows,
 | ||
|  * but no area outside of this region will be affected by drawing
 | ||
|  * primitives.
 | ||
|  * 
 | ||
|  * Returns: a #cairo_region_t. This must be freed with cairo_region_destroy()
 | ||
|  *          when you are done.
 | ||
|  **/
 | ||
| cairo_region_t*
 | ||
| gdk_window_get_clip_region (GdkWindow *window)
 | ||
| {
 | ||
|   cairo_region_t *result;
 | ||
| 
 | ||
|   g_return_val_if_fail (GDK_WINDOW (window), NULL);
 | ||
| 
 | ||
|   result = cairo_region_copy (window->clip_region);
 | ||
| 
 | ||
|   if (window->current_paint.region != NULL)
 | ||
|     cairo_region_intersect (result, window->current_paint.region);
 | ||
| 
 | ||
|   return result;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_visible_region:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * 
 | ||
|  * Computes the region of the @window that is potentially visible.
 | ||
|  * This does not necessarily take into account if the window is
 | ||
|  * obscured by other windows, but no area outside of this region
 | ||
|  * is visible.
 | ||
|  * 
 | ||
|  * Returns: a #cairo_region_t. This must be freed with cairo_region_destroy()
 | ||
|  *          when you are done.
 | ||
|  **/
 | ||
| cairo_region_t *
 | ||
| gdk_window_get_visible_region (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 | ||
| 
 | ||
|   return cairo_region_copy (window->clip_region);
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_clear_backing_region (GdkWindow *window)
 | ||
| {
 | ||
|   GdkWindow *bg_window;
 | ||
|   cairo_pattern_t *pattern = NULL;
 | ||
|   int x_offset = 0, y_offset = 0;
 | ||
|   cairo_t *cr;
 | ||
| 
 | ||
|   if (GDK_WINDOW_DESTROYED (window))
 | ||
|     return;
 | ||
| 
 | ||
|   cr = cairo_create (window->current_paint.surface);
 | ||
| 
 | ||
|   for (bg_window = window; bg_window; bg_window = bg_window->parent)
 | ||
|     {
 | ||
| G_GNUC_BEGIN_IGNORE_DEPRECATIONS
 | ||
|       pattern = gdk_window_get_background_pattern (bg_window);
 | ||
| G_GNUC_END_IGNORE_DEPRECATIONS
 | ||
|       if (pattern)
 | ||
|         break;
 | ||
| 
 | ||
|       x_offset += bg_window->x;
 | ||
|       y_offset += bg_window->y;
 | ||
|     }
 | ||
| 
 | ||
|   if (pattern)
 | ||
|     {
 | ||
|       cairo_translate (cr, -x_offset, -y_offset);
 | ||
|       cairo_set_source (cr, pattern);
 | ||
|       cairo_translate (cr, x_offset, y_offset);
 | ||
|     }
 | ||
|   else
 | ||
|     cairo_set_source_rgb (cr, 0, 0, 0);
 | ||
| 
 | ||
|   cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
 | ||
|   gdk_cairo_region (cr, window->current_paint.region);
 | ||
|   cairo_fill (cr);
 | ||
| 
 | ||
|   cairo_destroy (cr);
 | ||
| }
 | ||
| 
 | ||
| /* This returns either the current working surface on the paint stack
 | ||
|  * or the actual impl surface of the window. This should not be used
 | ||
|  * from very many places: be careful! */
 | ||
| static cairo_surface_t *
 | ||
| ref_window_surface (GdkWindow *window)
 | ||
| {
 | ||
|   if (window->impl_window->current_paint.surface)
 | ||
|     return cairo_surface_reference (window->impl_window->current_paint.surface);
 | ||
|   else
 | ||
|     return gdk_window_ref_impl_surface (window);
 | ||
| }
 | ||
| 
 | ||
| /* This is used in places like gdk_cairo_set_source_window and
 | ||
|  * other places to take "screenshots" of windows. Thus, we allow
 | ||
|  * it to be used outside of a begin_paint / end_paint. */
 | ||
| cairo_surface_t *
 | ||
| _gdk_window_ref_cairo_surface (GdkWindow *window)
 | ||
| {
 | ||
|   cairo_surface_t *surface;
 | ||
| 
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 | ||
| 
 | ||
|   surface = ref_window_surface (window);
 | ||
| 
 | ||
|   if (gdk_window_has_impl (window))
 | ||
|     {
 | ||
|       return surface;
 | ||
|     }
 | ||
|   else
 | ||
|     {
 | ||
|       cairo_surface_t *subsurface;
 | ||
|       subsurface = cairo_surface_create_for_rectangle (surface,
 | ||
|                                                        window->abs_x,
 | ||
|                                                        window->abs_y,
 | ||
|                                                        window->width,
 | ||
|                                                        window->height);
 | ||
|       cairo_surface_destroy (surface);
 | ||
|       return subsurface;
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_cairo_create:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * 
 | ||
|  * Creates a Cairo context for drawing to @window.
 | ||
|  *
 | ||
|  * Note that calling cairo_reset_clip() on the resulting #cairo_t will
 | ||
|  * produce undefined results, so avoid it at all costs.
 | ||
|  *
 | ||
|  * Typically, this function is used to draw on a #GdkWindow out of the paint
 | ||
|  * cycle of the toolkit; this should be avoided, as it breaks various assumptions
 | ||
|  * and optimizations.
 | ||
|  *
 | ||
|  * If you are drawing on a native #GdkWindow in response to a %GDK_EXPOSE event
 | ||
|  * you should use gdk_window_begin_draw_frame() and gdk_drawing_context_get_cairo_context()
 | ||
|  * instead. GTK will automatically do this for you when drawing a widget.
 | ||
|  *
 | ||
|  * Returns: A newly created Cairo context. Free with
 | ||
|  *  cairo_destroy() when you are done drawing.
 | ||
|  * 
 | ||
|  * Since: 2.8
 | ||
|  *
 | ||
|  * Deprecated: 3.22: Use gdk_window_begin_draw_frame() and
 | ||
|  *   gdk_drawing_context_get_cairo_context() instead
 | ||
|  **/
 | ||
| cairo_t *
 | ||
| gdk_cairo_create (GdkWindow *window)
 | ||
| {
 | ||
|   cairo_region_t *region;
 | ||
|   cairo_surface_t *surface;
 | ||
|   cairo_t *cr;
 | ||
| 
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 | ||
| 
 | ||
|   surface = _gdk_window_ref_cairo_surface (window);
 | ||
| 
 | ||
|   cr = cairo_create (surface);
 | ||
| 
 | ||
|   region = gdk_window_get_current_paint_region (window);
 | ||
|   gdk_cairo_region (cr, region);
 | ||
|   cairo_region_destroy (region);
 | ||
|   cairo_clip (cr);
 | ||
| 
 | ||
|   /* Assign a drawing context, if one is set; if gdk_cairo_create()
 | ||
|    * is called outside of a frame drawing then this is going to be
 | ||
|    * NULL.
 | ||
|    */
 | ||
|   gdk_cairo_set_drawing_context (cr, window->drawing_context);
 | ||
| 
 | ||
|   cairo_surface_destroy (surface);
 | ||
| 
 | ||
|   return cr;
 | ||
| }
 | ||
| 
 | ||
| /* Code for dirty-region queueing
 | ||
|  */
 | ||
| static GSList *update_windows = NULL;
 | ||
| gboolean _gdk_debug_updates = FALSE;
 | ||
| 
 | ||
| static inline gboolean
 | ||
| gdk_window_is_ancestor (GdkWindow *window,
 | ||
| 			GdkWindow *ancestor)
 | ||
| {
 | ||
|   while (window)
 | ||
|     {
 | ||
|       GdkWindow *parent = window->parent;
 | ||
| 
 | ||
|       if (parent == ancestor)
 | ||
| 	return TRUE;
 | ||
| 
 | ||
|       window = parent;
 | ||
|     }
 | ||
| 
 | ||
|   return FALSE;
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_add_update_window (GdkWindow *window)
 | ||
| {
 | ||
|   GSList *tmp;
 | ||
|   GSList *prev = NULL;
 | ||
|   gboolean has_ancestor_in_list = FALSE;
 | ||
| 
 | ||
|   /*  Check whether "window" is already in "update_windows" list.
 | ||
|    *  It could be added during execution of gtk_widget_destroy() when
 | ||
|    *  setting focus widget to NULL and redrawing old focus widget.
 | ||
|    *  See bug 711552.
 | ||
|    */
 | ||
|   tmp = g_slist_find (update_windows, window);
 | ||
|   if (tmp != NULL)
 | ||
|     return;
 | ||
| 
 | ||
|   for (tmp = update_windows; tmp; tmp = tmp->next)
 | ||
|     {
 | ||
|       GdkWindow *parent = window->parent;
 | ||
| 
 | ||
|       /*  check if tmp is an ancestor of "window"; if it is, set a
 | ||
|        *  flag indicating that all following windows are either
 | ||
|        *  children of "window" or from a differen hierarchy
 | ||
|        */
 | ||
|       if (!has_ancestor_in_list && gdk_window_is_ancestor (window, tmp->data))
 | ||
| 	has_ancestor_in_list = TRUE;
 | ||
| 
 | ||
|       /* insert in reverse stacking order when adding around siblings,
 | ||
|        * so processing updates properly paints over lower stacked windows
 | ||
|        */
 | ||
|       if (parent == GDK_WINDOW (tmp->data)->parent)
 | ||
| 	{
 | ||
| 	  gint index = g_list_index (parent->children, window);
 | ||
| 	  for (; tmp && parent == GDK_WINDOW (tmp->data)->parent; tmp = tmp->next)
 | ||
| 	    {
 | ||
| 	      gint sibling_index = g_list_index (parent->children, tmp->data);
 | ||
| 	      if (index > sibling_index)
 | ||
| 		break;
 | ||
| 	      prev = tmp;
 | ||
| 	    }
 | ||
| 	  /* here, tmp got advanced past all lower stacked siblings */
 | ||
| 	  tmp = g_slist_prepend (tmp, g_object_ref (window));
 | ||
| 	  if (prev)
 | ||
| 	    prev->next = tmp;
 | ||
| 	  else
 | ||
| 	    update_windows = tmp;
 | ||
| 	  return;
 | ||
| 	}
 | ||
| 
 | ||
|       /*  if "window" has an ancestor in the list and tmp is one of
 | ||
|        *  "window's" children, insert "window" before tmp
 | ||
|        */
 | ||
|       if (has_ancestor_in_list && gdk_window_is_ancestor (tmp->data, window))
 | ||
| 	{
 | ||
| 	  tmp = g_slist_prepend (tmp, g_object_ref (window));
 | ||
| 
 | ||
| 	  if (prev)
 | ||
| 	    prev->next = tmp;
 | ||
| 	  else
 | ||
| 	    update_windows = tmp;
 | ||
| 	  return;
 | ||
| 	}
 | ||
| 
 | ||
|       /*  if we're at the end of the list and had an ancestor it it,
 | ||
|        *  append to the list
 | ||
|        */
 | ||
|       if (! tmp->next && has_ancestor_in_list)
 | ||
| 	{
 | ||
| 	  tmp = g_slist_append (tmp, g_object_ref (window));
 | ||
| 	  return;
 | ||
| 	}
 | ||
| 
 | ||
|       prev = tmp;
 | ||
|     }
 | ||
| 
 | ||
|   /*  if all above checks failed ("window" is from a different
 | ||
|    *  hierarchy than what is already in the list) or the list is
 | ||
|    *  empty, prepend
 | ||
|    */
 | ||
|   update_windows = g_slist_prepend (update_windows, g_object_ref (window));
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_remove_update_window (GdkWindow *window)
 | ||
| {
 | ||
|   GSList *link;
 | ||
| 
 | ||
|   link = g_slist_find (update_windows, window);
 | ||
|   if (link != NULL)
 | ||
|     {
 | ||
|       update_windows = g_slist_delete_link (update_windows, link);
 | ||
|       g_object_unref (window);
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| static gboolean
 | ||
| gdk_window_is_toplevel_frozen (GdkWindow *window)
 | ||
| {
 | ||
|   GdkWindow *toplevel;
 | ||
| 
 | ||
|   toplevel = gdk_window_get_toplevel (window);
 | ||
| 
 | ||
|   return toplevel->update_and_descendants_freeze_count > 0;
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_schedule_update (GdkWindow *window)
 | ||
| {
 | ||
|   GdkFrameClock *frame_clock;
 | ||
| 
 | ||
|   if (window &&
 | ||
|       (window->update_freeze_count ||
 | ||
|        gdk_window_is_toplevel_frozen (window)))
 | ||
|     return;
 | ||
| 
 | ||
|   /* If there's no frame clock (a foreign window), then the invalid
 | ||
|    * region will just stick around unless gdk_window_process_updates()
 | ||
|    * is called. */
 | ||
|   frame_clock = gdk_window_get_frame_clock (window);
 | ||
|   if (frame_clock)
 | ||
|     gdk_frame_clock_request_phase (gdk_window_get_frame_clock (window),
 | ||
|                                    GDK_FRAME_CLOCK_PHASE_PAINT);
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_add_damage (GdkWindow *toplevel,
 | ||
|                        cairo_region_t *damaged_region)
 | ||
| {
 | ||
|   GdkDisplay *display;
 | ||
|   GdkEvent event = { 0, };
 | ||
| 
 | ||
|   /* This function only makes sense for offscreen windows. */
 | ||
|   g_assert (gdk_window_is_offscreen (toplevel));
 | ||
| 
 | ||
|   event.expose.type = GDK_DAMAGE;
 | ||
|   event.expose.window = toplevel;
 | ||
|   event.expose.send_event = FALSE;
 | ||
|   event.expose.region = damaged_region;
 | ||
|   cairo_region_get_extents (event.expose.region, &event.expose.area);
 | ||
| 
 | ||
|   display = gdk_window_get_display (event.expose.window);
 | ||
|   _gdk_event_queue_append (display, gdk_event_copy (&event));
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| _gdk_window_process_updates_recurse_helper (GdkWindow *window,
 | ||
|                                             cairo_region_t *expose_region)
 | ||
| {
 | ||
|   GdkWindow *child;
 | ||
|   cairo_region_t *clipped_expose_region;
 | ||
|   GdkWindow **children;
 | ||
|   GdkWindow **free_children = NULL;
 | ||
|   int i, n_children;
 | ||
|   GList *l;
 | ||
|   GList *last_link;
 | ||
| 
 | ||
|   if (window->destroyed)
 | ||
|     return;
 | ||
| 
 | ||
|   if (window->alpha == 0 && !gdk_window_has_impl (window))
 | ||
|     return;
 | ||
| 
 | ||
|   clipped_expose_region = cairo_region_copy (expose_region);
 | ||
| 
 | ||
|   if (!gdk_window_has_impl (window))
 | ||
|     cairo_region_translate (clipped_expose_region, -window->x, -window->y);
 | ||
| 
 | ||
|   cairo_region_intersect (clipped_expose_region, window->clip_region);
 | ||
| 
 | ||
|   if (cairo_region_is_empty (clipped_expose_region))
 | ||
|     goto out;
 | ||
| 
 | ||
|   if (gdk_window_is_offscreen (window))
 | ||
|     gdk_window_add_damage (window, clipped_expose_region);
 | ||
| 
 | ||
|   /* Paint the window before the children, clipped to the window region */
 | ||
| 
 | ||
|   /* While gtk+ no longer handles exposes on anything but native
 | ||
|      window we still have to send them to all windows that have the
 | ||
|      event mask set for backwards compat. We also need to send
 | ||
|      it to all native windows, even if they don't specify the
 | ||
|      expose mask, because they may have non-native children that do. */
 | ||
|   if (gdk_window_has_impl (window) ||
 | ||
|       window->event_mask & GDK_EXPOSURE_MASK)
 | ||
|     {
 | ||
|       GdkEvent event;
 | ||
| 
 | ||
|       event.expose.type = GDK_EXPOSE;
 | ||
|       event.expose.window = window; /* we already hold a ref */
 | ||
|       event.expose.send_event = FALSE;
 | ||
|       event.expose.count = 0;
 | ||
|       event.expose.region = clipped_expose_region;
 | ||
|       cairo_region_get_extents (clipped_expose_region, &event.expose.area);
 | ||
| 
 | ||
|       _gdk_event_emit (&event);
 | ||
|     }
 | ||
| 
 | ||
|   n_children = 0;
 | ||
|   last_link = NULL;
 | ||
|   /* Count n_children and fetch bottommost at same time */
 | ||
|   for (l = window->children; l != NULL; l = l->next)
 | ||
|     {
 | ||
|       last_link = l;
 | ||
|       n_children++;
 | ||
|     }
 | ||
| 
 | ||
|   children = g_newa (GdkWindow *, n_children);
 | ||
|   if (children == NULL)
 | ||
|     children = free_children = g_new (GdkWindow *, n_children);
 | ||
| 
 | ||
|   n_children = 0;
 | ||
|   /* Iterate over children, starting at bottommost */
 | ||
|   for (l = last_link; l != NULL; l = l->prev)
 | ||
|     {
 | ||
|       child = l->data;
 | ||
| 
 | ||
|       if (child->destroyed || !GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
 | ||
|         continue;
 | ||
| 
 | ||
|       /* Ignore offscreen children, as they don't draw in their parent and
 | ||
|        * don't take part in the clipping */
 | ||
|       if (gdk_window_is_offscreen (child))
 | ||
|         continue;
 | ||
| 
 | ||
|       /* Client side child, expose */
 | ||
|       if (child->impl == window->impl)
 | ||
|         {
 | ||
|           /* ref the child to make this reentrancy safe for expose
 | ||
|              handlers freeing other windows */
 | ||
|           children[n_children++] = g_object_ref (child);
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|   for (i = 0; i < n_children; i++)
 | ||
|     {
 | ||
|       _gdk_window_process_updates_recurse_helper ((GdkWindow *)children[i],
 | ||
|                                                   clipped_expose_region);
 | ||
|       g_object_unref (children[i]);
 | ||
|     }
 | ||
| 
 | ||
| 
 | ||
|   g_free (free_children);
 | ||
| 
 | ||
|  out:
 | ||
|   cairo_region_destroy (clipped_expose_region);
 | ||
| }
 | ||
| 
 | ||
| void
 | ||
| _gdk_window_process_updates_recurse (GdkWindow *window,
 | ||
|                                      cairo_region_t *expose_region)
 | ||
| {
 | ||
|   _gdk_window_process_updates_recurse_helper (window, expose_region);
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_update_native_shapes (GdkWindow *window)
 | ||
| {
 | ||
|   GdkWindow *child;
 | ||
|   GList *l;
 | ||
| 
 | ||
|   if (should_apply_clip_as_shape (window))
 | ||
|     apply_clip_as_shape (window);
 | ||
| 
 | ||
|   for (l = window->native_children; l != NULL; l = l->next)
 | ||
|     {
 | ||
|       child = l->data;
 | ||
| 
 | ||
|       gdk_window_update_native_shapes (child);
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| /* Process and remove any invalid area on the native window by creating
 | ||
|  * expose events for the window and all non-native descendants.
 | ||
|  */
 | ||
| static void
 | ||
| gdk_window_process_updates_internal (GdkWindow *window)
 | ||
| {
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
|   GdkWindow *toplevel;
 | ||
|   GdkDisplay *display;
 | ||
| 
 | ||
|   display = gdk_window_get_display (window);
 | ||
|   toplevel = gdk_window_get_toplevel (window);
 | ||
|   if (toplevel->geometry_dirty)
 | ||
|     {
 | ||
|       gdk_window_update_native_shapes (toplevel);
 | ||
|       toplevel->geometry_dirty = FALSE;
 | ||
|     }
 | ||
| 
 | ||
|   /* Ensure the window lives while updating it */
 | ||
|   g_object_ref (window);
 | ||
| 
 | ||
|   window->in_update = TRUE;
 | ||
| 
 | ||
|   /* If an update got queued during update processing, we can get a
 | ||
|    * window in the update queue that has an empty update_area.
 | ||
|    * just ignore it.
 | ||
|    */
 | ||
|   if (window->update_area)
 | ||
|     {
 | ||
|       g_assert (window->active_update_area == NULL); /* No reentrancy */
 | ||
| 
 | ||
|       window->active_update_area = window->update_area;
 | ||
|       window->update_area = NULL;
 | ||
| 
 | ||
|       if (gdk_window_is_viewable (window))
 | ||
| 	{
 | ||
| 	  cairo_region_t *expose_region;
 | ||
| 
 | ||
| 	  expose_region = cairo_region_copy (window->active_update_area);
 | ||
| 
 | ||
| 	  impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
| 
 | ||
|           /* Sometimes we can't just paint only the new area, as the windowing system
 | ||
|            * requires more to be repainted. For instance, with OpenGL you typically
 | ||
|            * repaint all of each frame each time and then swap the buffer, although
 | ||
|            * there are extensions that allow us to reuse part of an old frame.
 | ||
|            */
 | ||
|           if (impl_class->invalidate_for_new_frame)
 | ||
|             impl_class->invalidate_for_new_frame (window, expose_region);
 | ||
| 
 | ||
| 	  /* Clip to part visible in impl window */
 | ||
| 	  cairo_region_intersect (expose_region, window->clip_region);
 | ||
| 
 | ||
| 	  if (gdk_display_get_debug_updates (display))
 | ||
| 	    {
 | ||
|               cairo_region_t *swap_region = cairo_region_copy (expose_region);
 | ||
|               cairo_region_subtract (swap_region, window->active_update_area);
 | ||
|               draw_ugly_color (window, swap_region, 1);
 | ||
|               cairo_region_destroy (swap_region);
 | ||
| 
 | ||
| 	      /* Make sure we see the red invalid area before redrawing. */
 | ||
| 	      gdk_display_sync (gdk_window_get_display (window));
 | ||
| 	      g_usleep (70000);
 | ||
| 	    }
 | ||
| 
 | ||
|           if (impl_class->queue_antiexpose)
 | ||
|             impl_class->queue_antiexpose (window, expose_region);
 | ||
| 
 | ||
|           impl_class->process_updates_recurse (window, expose_region);
 | ||
| 
 | ||
|           gdk_window_append_old_updated_area (window, window->active_update_area);
 | ||
| 
 | ||
|           cairo_region_destroy (expose_region);
 | ||
|         }
 | ||
| 
 | ||
|       cairo_region_destroy (window->active_update_area);
 | ||
|       window->active_update_area = NULL;
 | ||
|     }
 | ||
| 
 | ||
|   window->in_update = FALSE;
 | ||
| 
 | ||
|   g_object_unref (window);
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| flush_all_displays (void)
 | ||
| {
 | ||
|   GSList *displays, *l;
 | ||
| 
 | ||
|   displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
 | ||
|   for (l = displays; l; l = l->next)
 | ||
|     gdk_display_flush (l->data);
 | ||
| 
 | ||
|   g_slist_free (displays);
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| before_process_all_updates (void)
 | ||
| {
 | ||
|   GSList *displays, *l;
 | ||
| 
 | ||
|   displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
 | ||
|   for (l = displays; l; l = l->next)
 | ||
|     GDK_DISPLAY_GET_CLASS (l->data)->before_process_all_updates (l->data);
 | ||
| 
 | ||
|   g_slist_free (displays);
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| after_process_all_updates (void)
 | ||
| {
 | ||
|   GSList *displays, *l;
 | ||
| 
 | ||
|   displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
 | ||
|   for (l = displays; l; l = l->next)
 | ||
|     GDK_DISPLAY_GET_CLASS (l->data)->after_process_all_updates (l->data);
 | ||
| 
 | ||
|   g_slist_free (displays);
 | ||
| }
 | ||
| 
 | ||
| /* Currently it is not possible to override
 | ||
|  * gdk_window_process_all_updates in the same manner as
 | ||
|  * gdk_window_process_updates and gdk_window_invalidate_maybe_recurse
 | ||
|  * by implementing the GdkPaintable interface.  If in the future a
 | ||
|  * backend would need this, the right solution would be to add a
 | ||
|  * method to GdkDisplay that can be optionally
 | ||
|  * NULL. gdk_window_process_all_updates can then walk the list of open
 | ||
|  * displays and call the mehod.
 | ||
|  */
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_process_all_updates:
 | ||
|  *
 | ||
|  * Calls gdk_window_process_updates() for all windows (see #GdkWindow)
 | ||
|  * in the application.
 | ||
|  *
 | ||
|  * Deprecated: 3.22
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_process_all_updates (void)
 | ||
| {
 | ||
|   GSList *old_update_windows = update_windows;
 | ||
|   GSList *tmp_list = update_windows;
 | ||
|   static gboolean in_process_all_updates = FALSE;
 | ||
|   static gboolean got_recursive_update = FALSE;
 | ||
| 
 | ||
|   if (in_process_all_updates)
 | ||
|     {
 | ||
|       /* We can't do this now since that would recurse, so
 | ||
| 	 delay it until after the recursion is done. */
 | ||
|       got_recursive_update = TRUE;
 | ||
|       return;
 | ||
|     }
 | ||
| 
 | ||
|   in_process_all_updates = TRUE;
 | ||
|   got_recursive_update = FALSE;
 | ||
| 
 | ||
|   update_windows = NULL;
 | ||
| 
 | ||
|   before_process_all_updates ();
 | ||
| 
 | ||
|   while (tmp_list)
 | ||
|     {
 | ||
|       GdkWindow *window = tmp_list->data;
 | ||
| 
 | ||
|       if (!GDK_WINDOW_DESTROYED (window))
 | ||
| 	{
 | ||
| 	  if (window->update_freeze_count ||
 | ||
| 	      gdk_window_is_toplevel_frozen (window))
 | ||
| 	    gdk_window_add_update_window (window);
 | ||
| 	  else
 | ||
| 	    gdk_window_process_updates_internal (window);
 | ||
| 	}
 | ||
| 
 | ||
|       g_object_unref (window);
 | ||
|       tmp_list = tmp_list->next;
 | ||
|     }
 | ||
| 
 | ||
|   g_slist_free (old_update_windows);
 | ||
| 
 | ||
|   flush_all_displays ();
 | ||
| 
 | ||
|   after_process_all_updates ();
 | ||
| 
 | ||
|   in_process_all_updates = FALSE;
 | ||
| 
 | ||
|   /* If we ignored a recursive call, schedule a
 | ||
|      redraw now so that it eventually happens,
 | ||
|      otherwise we could miss an update if nothing
 | ||
|      else schedules an update. */
 | ||
|   if (got_recursive_update)
 | ||
|     gdk_window_schedule_update (NULL);
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| enum {
 | ||
|   PROCESS_UPDATES_NO_RECURSE,
 | ||
|   PROCESS_UPDATES_WITH_ALL_CHILDREN,
 | ||
|   PROCESS_UPDATES_WITH_SAME_CLOCK_CHILDREN
 | ||
| };
 | ||
| 
 | ||
| static void
 | ||
| find_impl_windows_to_update (GPtrArray  *list,
 | ||
|                              GdkWindow  *window,
 | ||
|                              gint        recurse_mode)
 | ||
| {
 | ||
|   GList *node;
 | ||
| 
 | ||
|   /* Recurse first, so that we process updates in reverse stacking
 | ||
|    * order so composition or painting over achieves the desired effect
 | ||
|    * for offscreen windows
 | ||
|    */
 | ||
|   if (recurse_mode != PROCESS_UPDATES_NO_RECURSE)
 | ||
|     {
 | ||
|       for (node = window->children; node; node = node->next)
 | ||
|         {
 | ||
|           GdkWindow *child = node->data;
 | ||
| 
 | ||
|           if (!GDK_WINDOW_DESTROYED (child) &&
 | ||
|               (recurse_mode == PROCESS_UPDATES_WITH_ALL_CHILDREN ||
 | ||
|               (recurse_mode == PROCESS_UPDATES_WITH_SAME_CLOCK_CHILDREN &&
 | ||
|                child->frame_clock == NULL)))
 | ||
|             {
 | ||
|               find_impl_windows_to_update (list, child, recurse_mode);
 | ||
|             }
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|   /* add reference count so the window cannot be deleted in a callback */
 | ||
|   if (window->impl_window == window)
 | ||
|     g_ptr_array_add (list, g_object_ref (window));
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_process_updates_with_mode (GdkWindow     *window,
 | ||
|                                       int            recurse_mode)
 | ||
| {
 | ||
|   GPtrArray *list;
 | ||
|   int i;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   if (GDK_WINDOW_DESTROYED (window))
 | ||
|     return;
 | ||
| 
 | ||
|   list = g_ptr_array_new_with_free_func (g_object_unref);
 | ||
|   find_impl_windows_to_update (list, window, recurse_mode);
 | ||
| 
 | ||
|   if (window->impl_window != window)
 | ||
|     g_ptr_array_add (list, g_object_ref (window->impl_window));
 | ||
| 
 | ||
|   for (i = (int)list->len - 1; i >= 0; i --)
 | ||
|     {
 | ||
|       GdkWindow *impl_window = g_ptr_array_index (list, i);
 | ||
| 
 | ||
|       if (impl_window->update_area &&
 | ||
|           !impl_window->update_freeze_count &&
 | ||
|           !gdk_window_is_toplevel_frozen (impl_window) &&
 | ||
| 
 | ||
|           /* Don't recurse into process_updates_internal, we'll
 | ||
|            * do the update later when idle instead. */
 | ||
|           !impl_window->in_update)
 | ||
|         {
 | ||
|           gdk_window_process_updates_internal (impl_window);
 | ||
|           gdk_window_remove_update_window (impl_window);
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|   g_ptr_array_free (list, TRUE);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_process_updates:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @update_children: whether to also process updates for child windows
 | ||
|  *
 | ||
|  * Sends one or more expose events to @window. The areas in each
 | ||
|  * expose event will cover the entire update area for the window (see
 | ||
|  * gdk_window_invalidate_region() for details). Normally GDK calls
 | ||
|  * gdk_window_process_all_updates() on your behalf, so there’s no
 | ||
|  * need to call this function unless you want to force expose events
 | ||
|  * to be delivered immediately and synchronously (vs. the usual
 | ||
|  * case, where GDK delivers them in an idle handler). Occasionally
 | ||
|  * this is useful to produce nicer scrolling behavior, for example.
 | ||
|  *
 | ||
|  * Deprecated: 3.22
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_process_updates (GdkWindow *window,
 | ||
| 			    gboolean   update_children)
 | ||
| {
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   gdk_window_process_updates_with_mode (window,
 | ||
|                                         update_children ?
 | ||
|                                         PROCESS_UPDATES_WITH_ALL_CHILDREN :
 | ||
|                                         PROCESS_UPDATES_NO_RECURSE);
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_invalidate_rect_full (GdkWindow          *window,
 | ||
| 				  const GdkRectangle *rect,
 | ||
| 				  gboolean            invalidate_children)
 | ||
| {
 | ||
|   GdkRectangle window_rect;
 | ||
|   cairo_region_t *region;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   if (GDK_WINDOW_DESTROYED (window))
 | ||
|     return;
 | ||
| 
 | ||
|   if (window->input_only || !window->viewable)
 | ||
|     return;
 | ||
| 
 | ||
|   if (!rect)
 | ||
|     {
 | ||
|       window_rect.x = 0;
 | ||
|       window_rect.y = 0;
 | ||
|       window_rect.width = window->width;
 | ||
|       window_rect.height = window->height;
 | ||
|       rect = &window_rect;
 | ||
|     }
 | ||
| 
 | ||
|   region = cairo_region_create_rectangle (rect);
 | ||
|   gdk_window_invalidate_region_full (window, region, invalidate_children);
 | ||
|   cairo_region_destroy (region);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_invalidate_rect:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @rect: (allow-none): rectangle to invalidate or %NULL to invalidate the whole
 | ||
|  *      window
 | ||
|  * @invalidate_children: whether to also invalidate child windows
 | ||
|  *
 | ||
|  * A convenience wrapper around gdk_window_invalidate_region() which
 | ||
|  * invalidates a rectangular region. See
 | ||
|  * gdk_window_invalidate_region() for details.
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_invalidate_rect (GdkWindow          *window,
 | ||
| 			    const GdkRectangle *rect,
 | ||
| 			    gboolean            invalidate_children)
 | ||
| {
 | ||
|   gdk_window_invalidate_rect_full (window, rect, invalidate_children);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_invalidate_handler: (skip)
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @handler: a #GdkWindowInvalidateHandlerFunc callback function
 | ||
|  *
 | ||
|  * Registers an invalidate handler for a specific window. This
 | ||
|  * will get called whenever a region in the window or its children
 | ||
|  * is invalidated.
 | ||
|  *
 | ||
|  * This can be used to record the invalidated region, which is
 | ||
|  * useful if you are keeping an offscreen copy of some region
 | ||
|  * and want to keep it up to date. You can also modify the
 | ||
|  * invalidated region in case you’re doing some effect where
 | ||
|  * e.g. a child widget appears in multiple places.
 | ||
|  *
 | ||
|  * Since: 3.10
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_set_invalidate_handler (GdkWindow                      *window,
 | ||
| 				   GdkWindowInvalidateHandlerFunc  handler)
 | ||
| {
 | ||
|   window->invalidate_handler = handler;
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| draw_ugly_color (GdkWindow       *window,
 | ||
| 		 const cairo_region_t *region,
 | ||
|                  int color)
 | ||
| {
 | ||
|   cairo_t *cr;
 | ||
| 
 | ||
| G_GNUC_BEGIN_IGNORE_DEPRECATIONS
 | ||
|   cr = gdk_cairo_create (window);
 | ||
| G_GNUC_END_IGNORE_DEPRECATIONS
 | ||
| 
 | ||
|   /* Draw ugly color all over the newly-invalid region */
 | ||
|   if (color == 0)
 | ||
|     cairo_set_source_rgb (cr, 50000/65535., 10000/65535., 10000/65535.);
 | ||
|   else
 | ||
|     cairo_set_source_rgb (cr, 10000/65535., 50000/65535., 10000/65535.);
 | ||
| 
 | ||
|   gdk_cairo_region (cr, region);
 | ||
|   cairo_fill (cr);
 | ||
| 
 | ||
|   cairo_destroy (cr);
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| impl_window_add_update_area (GdkWindow *impl_window,
 | ||
| 			     cairo_region_t *region)
 | ||
| {
 | ||
|   if (impl_window->update_area)
 | ||
|     cairo_region_union (impl_window->update_area, region);
 | ||
|   else
 | ||
|     {
 | ||
|       gdk_window_add_update_window (impl_window);
 | ||
|       impl_window->update_area = cairo_region_copy (region);
 | ||
|       gdk_window_schedule_update (impl_window);
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_invalidate_maybe_recurse_full (GdkWindow            *window,
 | ||
| 					  const cairo_region_t *region,
 | ||
|                                           GdkWindowChildFunc    child_func,
 | ||
| 					  gpointer              user_data);
 | ||
| 
 | ||
| /* Returns true if window is a decendant of parent, but stops looking
 | ||
|  * at the first native window. Also ensures that all parents match
 | ||
|  * child_func if non-null..
 | ||
|  *
 | ||
|  * This is useful in combination with
 | ||
|  * window->impl_window->native_children as it lets you find all native
 | ||
|  * decendants in an efficient way (assuming few children are native).
 | ||
|  */
 | ||
| static gboolean
 | ||
| has_visible_ancestor_in_impl (GdkWindow *window,
 | ||
|                               GdkWindow *ancestor,
 | ||
|                               GdkWindowChildFunc child_func,
 | ||
|                               gpointer user_data)
 | ||
| {
 | ||
|   GdkWindow *p;
 | ||
|   GdkWindow *stop_at;
 | ||
| 
 | ||
|   p = window->parent;
 | ||
|   stop_at = p->impl_window;
 | ||
|   while (p != NULL)
 | ||
|     {
 | ||
|       if (!p->viewable)
 | ||
|         return FALSE;
 | ||
|       if (child_func &&
 | ||
|           !(*child_func) ((GdkWindow *)p, user_data))
 | ||
|         return FALSE;
 | ||
|       if (p == ancestor)
 | ||
|         return TRUE;
 | ||
|       if (p == stop_at)
 | ||
|         return FALSE;
 | ||
|       p = p->parent;
 | ||
|     }
 | ||
|   return FALSE;
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| invalidate_impl_subwindows (GdkWindow            *window,
 | ||
| 			    const cairo_region_t *region,
 | ||
| 			    GdkWindowChildFunc    child_func,
 | ||
| 			    gpointer              user_data)
 | ||
| {
 | ||
|   GList *l;
 | ||
| 
 | ||
|   /* Iterate over all native children of the native window
 | ||
|      that window is in. */
 | ||
|   for (l = window->impl_window->native_children;
 | ||
|        l != NULL;
 | ||
|        l = l->next)
 | ||
|     {
 | ||
|       GdkWindow *native_child = l->data;
 | ||
|       cairo_region_t *tmp;
 | ||
|       int dx, dy;
 | ||
| 
 | ||
|       if (native_child->input_only)
 | ||
| 	continue;
 | ||
| 
 | ||
|       /* Then skip any that does not have window as an ancestor,
 | ||
|        * also checking that the ancestors are visible and pass child_func
 | ||
|        * This is fast if we assume native children are rare */
 | ||
|       if (!has_visible_ancestor_in_impl (native_child, window,
 | ||
|                                          child_func, user_data))
 | ||
|         continue;
 | ||
| 
 | ||
|       dx = native_child->parent->abs_x + native_child->x - window->abs_x;
 | ||
|       dy = native_child->parent->abs_y + native_child->y - window->abs_y;
 | ||
| 
 | ||
|       tmp = cairo_region_copy (region);
 | ||
|       cairo_region_translate (tmp, -dx, -dy);
 | ||
|       gdk_window_invalidate_maybe_recurse_full (native_child,
 | ||
|                                                 tmp, child_func, user_data);
 | ||
|       cairo_region_destroy (tmp);
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_invalidate_maybe_recurse_full (GdkWindow            *window,
 | ||
| 					  const cairo_region_t *region,
 | ||
|                                           GdkWindowChildFunc    child_func,
 | ||
| 					  gpointer              user_data)
 | ||
| {
 | ||
|   cairo_region_t *visible_region;
 | ||
|   cairo_rectangle_int_t r;
 | ||
|   GdkDisplay *display;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   if (GDK_WINDOW_DESTROYED (window))
 | ||
|     return;
 | ||
| 
 | ||
|   if (window->input_only ||
 | ||
|       !window->viewable ||
 | ||
|       cairo_region_is_empty (region) ||
 | ||
|       window->window_type == GDK_WINDOW_ROOT)
 | ||
|     return;
 | ||
| 
 | ||
|   r.x = 0;
 | ||
|   r.y = 0;
 | ||
| 
 | ||
|   visible_region = cairo_region_copy (region);
 | ||
| 
 | ||
|   if (child_func)
 | ||
|     invalidate_impl_subwindows (window, region, child_func, user_data);
 | ||
| 
 | ||
|   display = gdk_window_get_display (window);
 | ||
|   if (gdk_display_get_debug_updates (display))
 | ||
|     draw_ugly_color (window, visible_region, 0);
 | ||
| 
 | ||
|   while (window != NULL && 
 | ||
| 	 !cairo_region_is_empty (visible_region))
 | ||
|     {
 | ||
|       if (window->invalidate_handler)
 | ||
| 	window->invalidate_handler (window, visible_region);
 | ||
| 
 | ||
|       r.width = window->width;
 | ||
|       r.height = window->height;
 | ||
|       cairo_region_intersect_rectangle (visible_region, &r);
 | ||
| 
 | ||
|       if (gdk_window_has_impl (window))
 | ||
| 	{
 | ||
| 	  impl_window_add_update_area (window, visible_region);
 | ||
| 	  break;
 | ||
| 	}
 | ||
|       else
 | ||
| 	{
 | ||
| 	  cairo_region_translate (visible_region,
 | ||
| 				  window->x, window->y);
 | ||
| 	  window = window->parent;
 | ||
| 	}
 | ||
|     }
 | ||
| 
 | ||
|   cairo_region_destroy (visible_region);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_invalidate_maybe_recurse:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @region: a #cairo_region_t
 | ||
|  * @child_func: (scope call) (allow-none): function to use to decide if to
 | ||
|  *     recurse to a child, %NULL means never recurse.
 | ||
|  * @user_data: data passed to @child_func
 | ||
|  *
 | ||
|  * Adds @region to the update area for @window. The update area is the
 | ||
|  * region that needs to be redrawn, or “dirty region.” The call
 | ||
|  * gdk_window_process_updates() sends one or more expose events to the
 | ||
|  * window, which together cover the entire update area. An
 | ||
|  * application would normally redraw the contents of @window in
 | ||
|  * response to those expose events.
 | ||
|  *
 | ||
|  * GDK will call gdk_window_process_all_updates() on your behalf
 | ||
|  * whenever your program returns to the main loop and becomes idle, so
 | ||
|  * normally there’s no need to do that manually, you just need to
 | ||
|  * invalidate regions that you know should be redrawn.
 | ||
|  *
 | ||
|  * The @child_func parameter controls whether the region of
 | ||
|  * each child window that intersects @region will also be invalidated.
 | ||
|  * Only children for which @child_func returns #TRUE will have the area
 | ||
|  * invalidated.
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_invalidate_maybe_recurse (GdkWindow            *window,
 | ||
| 				     const cairo_region_t *region,
 | ||
|                                      GdkWindowChildFunc    child_func,
 | ||
| 				     gpointer              user_data)
 | ||
| {
 | ||
|   gdk_window_invalidate_maybe_recurse_full (window, region,
 | ||
| 					    child_func, user_data);
 | ||
| }
 | ||
| 
 | ||
| static gboolean
 | ||
| true_predicate (GdkWindow *window,
 | ||
| 		gpointer   user_data)
 | ||
| {
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_invalidate_region_full (GdkWindow       *window,
 | ||
| 				    const cairo_region_t *region,
 | ||
| 				    gboolean         invalidate_children)
 | ||
| {
 | ||
|   gdk_window_invalidate_maybe_recurse_full (window, region,
 | ||
| 					    invalidate_children ?
 | ||
| 					    true_predicate : (gboolean (*) (GdkWindow *, gpointer))NULL,
 | ||
| 				       NULL);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_invalidate_region:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @region: a #cairo_region_t
 | ||
|  * @invalidate_children: %TRUE to also invalidate child windows
 | ||
|  *
 | ||
|  * Adds @region to the update area for @window. The update area is the
 | ||
|  * region that needs to be redrawn, or “dirty region.” The call
 | ||
|  * gdk_window_process_updates() sends one or more expose events to the
 | ||
|  * window, which together cover the entire update area. An
 | ||
|  * application would normally redraw the contents of @window in
 | ||
|  * response to those expose events.
 | ||
|  *
 | ||
|  * GDK will call gdk_window_process_all_updates() on your behalf
 | ||
|  * whenever your program returns to the main loop and becomes idle, so
 | ||
|  * normally there’s no need to do that manually, you just need to
 | ||
|  * invalidate regions that you know should be redrawn.
 | ||
|  *
 | ||
|  * The @invalidate_children parameter controls whether the region of
 | ||
|  * each child window that intersects @region will also be invalidated.
 | ||
|  * If %FALSE, then the update area for child windows will remain
 | ||
|  * unaffected. See gdk_window_invalidate_maybe_recurse if you need
 | ||
|  * fine grained control over which children are invalidated.
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_invalidate_region (GdkWindow       *window,
 | ||
| 			      const cairo_region_t *region,
 | ||
| 			      gboolean         invalidate_children)
 | ||
| {
 | ||
|   gdk_window_invalidate_maybe_recurse (window, region,
 | ||
| 				       invalidate_children ?
 | ||
| 					 true_predicate : (gboolean (*) (GdkWindow *, gpointer))NULL,
 | ||
| 				       NULL);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * _gdk_window_invalidate_for_expose:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @region: a #cairo_region_t
 | ||
|  *
 | ||
|  * Adds @region to the update area for @window. The update area is the
 | ||
|  * region that needs to be redrawn, or “dirty region.” The call
 | ||
|  * gdk_window_process_updates() sends one or more expose events to the
 | ||
|  * window, which together cover the entire update area. An
 | ||
|  * application would normally redraw the contents of @window in
 | ||
|  * response to those expose events.
 | ||
|  *
 | ||
|  * GDK will call gdk_window_process_all_updates() on your behalf
 | ||
|  * whenever your program returns to the main loop and becomes idle, so
 | ||
|  * normally there’s no need to do that manually, you just need to
 | ||
|  * invalidate regions that you know should be redrawn.
 | ||
|  *
 | ||
|  * This version of invalidation is used when you recieve expose events
 | ||
|  * from the native window system. It exposes the native window, plus
 | ||
|  * any non-native child windows (but not native child windows, as those would
 | ||
|  * have gotten their own expose events).
 | ||
|  **/
 | ||
| void
 | ||
| _gdk_window_invalidate_for_expose (GdkWindow       *window,
 | ||
| 				   cairo_region_t       *region)
 | ||
| {
 | ||
|   gdk_window_invalidate_maybe_recurse_full (window, region,
 | ||
| 					    (gboolean (*) (GdkWindow *, gpointer))gdk_window_has_no_impl,
 | ||
| 					    NULL);
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_update_area:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Transfers ownership of the update area from @window to the caller
 | ||
|  * of the function. That is, after calling this function, @window will
 | ||
|  * no longer have an invalid/dirty region; the update area is removed
 | ||
|  * from @window and handed to you. If a window has no update area,
 | ||
|  * gdk_window_get_update_area() returns %NULL. You are responsible for
 | ||
|  * calling cairo_region_destroy() on the returned region if it’s non-%NULL.
 | ||
|  *
 | ||
|  * Returns: the update area for @window
 | ||
|  **/
 | ||
| cairo_region_t *
 | ||
| gdk_window_get_update_area (GdkWindow *window)
 | ||
| {
 | ||
|   GdkWindow *impl_window;
 | ||
|   cairo_region_t *tmp_region, *to_remove;
 | ||
| 
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 | ||
| 
 | ||
|   impl_window = gdk_window_get_impl_window (window);
 | ||
| 
 | ||
|   if (impl_window->update_area)
 | ||
|     {
 | ||
|       tmp_region = cairo_region_copy (window->clip_region);
 | ||
|       /* Convert to impl coords */
 | ||
|       cairo_region_translate (tmp_region, window->abs_x, window->abs_y);
 | ||
|       cairo_region_intersect (tmp_region, impl_window->update_area);
 | ||
| 
 | ||
|       if (cairo_region_is_empty (tmp_region))
 | ||
| 	{
 | ||
| 	  cairo_region_destroy (tmp_region);
 | ||
| 	  return NULL;
 | ||
| 	}
 | ||
|       else
 | ||
| 	{
 | ||
| 	  /* Convert from impl coords */
 | ||
| 	  cairo_region_translate (tmp_region, -window->abs_x, -window->abs_y);
 | ||
| 
 | ||
| 	  /* Don't remove any update area that is overlapped by sibling windows
 | ||
| 	     or child windows as these really need to be repainted independently of this window. */
 | ||
| 	  to_remove = cairo_region_copy (tmp_region);
 | ||
| 
 | ||
| 	  remove_child_area (window, FALSE, to_remove);
 | ||
| 	  remove_sibling_overlapped_area (window, to_remove);
 | ||
| 
 | ||
| 	  /* Remove from update_area */
 | ||
| 	  cairo_region_translate (to_remove, window->abs_x, window->abs_y);
 | ||
| 	  cairo_region_subtract (impl_window->update_area, to_remove);
 | ||
| 
 | ||
| 	  cairo_region_destroy (to_remove);
 | ||
| 
 | ||
| 	  if (cairo_region_is_empty (impl_window->update_area))
 | ||
| 	    {
 | ||
| 	      cairo_region_destroy (impl_window->update_area);
 | ||
| 	      impl_window->update_area = NULL;
 | ||
| 
 | ||
| 	      gdk_window_remove_update_window ((GdkWindow *)impl_window);
 | ||
| 	    }
 | ||
| 
 | ||
| 	  return tmp_region;
 | ||
| 	}
 | ||
|     }
 | ||
|   else
 | ||
|     return NULL;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * _gdk_window_clear_update_area:
 | ||
|  * @window: a #GdkWindow.
 | ||
|  *
 | ||
|  * Internal function to clear the update area for a window. This
 | ||
|  * is called when the window is hidden or destroyed.
 | ||
|  **/
 | ||
| void
 | ||
| _gdk_window_clear_update_area (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   if (window->update_area)
 | ||
|     {
 | ||
|       gdk_window_remove_update_window (window);
 | ||
| 
 | ||
|       cairo_region_destroy (window->update_area);
 | ||
|       window->update_area = NULL;
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_freeze_updates:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Temporarily freezes a window such that it won’t receive expose
 | ||
|  * events.  The window will begin receiving expose events again when
 | ||
|  * gdk_window_thaw_updates() is called. If gdk_window_freeze_updates()
 | ||
|  * has been called more than once, gdk_window_thaw_updates() must be called
 | ||
|  * an equal number of times to begin processing exposes.
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_freeze_updates (GdkWindow *window)
 | ||
| {
 | ||
|   GdkWindow *impl_window;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   impl_window = gdk_window_get_impl_window (window);
 | ||
|   impl_window->update_freeze_count++;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_thaw_updates:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Thaws a window frozen with gdk_window_freeze_updates().
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_thaw_updates (GdkWindow *window)
 | ||
| {
 | ||
|   GdkWindow *impl_window;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   impl_window = gdk_window_get_impl_window (window);
 | ||
| 
 | ||
|   g_return_if_fail (impl_window->update_freeze_count > 0);
 | ||
| 
 | ||
|   if (--impl_window->update_freeze_count == 0)
 | ||
|     gdk_window_schedule_update (GDK_WINDOW (impl_window));
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_freeze_toplevel_updates_libgtk_only:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Temporarily freezes a window and all its descendants such that it won't
 | ||
|  * receive expose events.  The window will begin receiving expose events
 | ||
|  * again when gdk_window_thaw_toplevel_updates_libgtk_only() is called. If
 | ||
|  * gdk_window_freeze_toplevel_updates_libgtk_only()
 | ||
|  * has been called more than once,
 | ||
|  * gdk_window_thaw_toplevel_updates_libgtk_only() must be called
 | ||
|  * an equal number of times to begin processing exposes.
 | ||
|  *
 | ||
|  * This function is not part of the GDK public API and is only
 | ||
|  * for use by GTK+.
 | ||
|  *
 | ||
|  * Deprecated: 3.16: This symbol was never meant to be used outside of GTK+
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_freeze_toplevel_updates_libgtk_only (GdkWindow *window)
 | ||
| {
 | ||
|   gdk_window_freeze_toplevel_updates (window);
 | ||
| }
 | ||
| 
 | ||
| void
 | ||
| gdk_window_freeze_toplevel_updates (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
|   g_return_if_fail (window->window_type != GDK_WINDOW_CHILD);
 | ||
| 
 | ||
|   window->update_and_descendants_freeze_count++;
 | ||
|   _gdk_frame_clock_freeze (gdk_window_get_frame_clock (window));
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_thaw_toplevel_updates_libgtk_only:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Thaws a window frozen with
 | ||
|  * gdk_window_freeze_toplevel_updates_libgtk_only().
 | ||
|  *
 | ||
|  * This function is not part of the GDK public API and is only
 | ||
|  * for use by GTK+.
 | ||
|  *
 | ||
|  * Deprecated: 3.16: This symbol was never meant to be used outside of GTK+
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_thaw_toplevel_updates_libgtk_only (GdkWindow *window)
 | ||
| {
 | ||
|   gdk_window_thaw_toplevel_updates (window);
 | ||
| }
 | ||
| 
 | ||
| void
 | ||
| gdk_window_thaw_toplevel_updates (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
|   g_return_if_fail (window->window_type != GDK_WINDOW_CHILD);
 | ||
|   g_return_if_fail (window->update_and_descendants_freeze_count > 0);
 | ||
| 
 | ||
|   window->update_and_descendants_freeze_count--;
 | ||
|   _gdk_frame_clock_thaw (gdk_window_get_frame_clock (window));
 | ||
| 
 | ||
|   gdk_window_schedule_update (window);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_debug_updates:
 | ||
|  * @setting: %TRUE to turn on update debugging
 | ||
|  *
 | ||
|  * With update debugging enabled, calls to
 | ||
|  * gdk_window_invalidate_region() clear the invalidated region of the
 | ||
|  * screen to a noticeable color, and GDK pauses for a short time
 | ||
|  * before sending exposes to windows during
 | ||
|  * gdk_window_process_updates().  The net effect is that you can see
 | ||
|  * the invalid region for each window and watch redraws as they
 | ||
|  * occur. This allows you to diagnose inefficiencies in your application.
 | ||
|  *
 | ||
|  * In essence, because the GDK rendering model prevents all flicker,
 | ||
|  * if you are redrawing the same region 400 times you may never
 | ||
|  * notice, aside from noticing a speed problem. Enabling update
 | ||
|  * debugging causes GTK to flicker slowly and noticeably, so you can
 | ||
|  * see exactly what’s being redrawn when, in what order.
 | ||
|  *
 | ||
|  * The --gtk-debug=updates command line option passed to GTK+ programs
 | ||
|  * enables this debug option at application startup time. That's
 | ||
|  * usually more useful than calling gdk_window_set_debug_updates()
 | ||
|  * yourself, though you might want to use this function to enable
 | ||
|  * updates sometime after application startup time.
 | ||
|  *
 | ||
|  * Deprecated: 3.22
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_set_debug_updates (gboolean setting)
 | ||
| {
 | ||
|   _gdk_debug_updates = setting;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_constrain_size:
 | ||
|  * @geometry: a #GdkGeometry structure
 | ||
|  * @flags: a mask indicating what portions of @geometry are set
 | ||
|  * @width: desired width of window
 | ||
|  * @height: desired height of the window
 | ||
|  * @new_width: (out): location to store resulting width
 | ||
|  * @new_height: (out): location to store resulting height
 | ||
|  *
 | ||
|  * Constrains a desired width and height according to a
 | ||
|  * set of geometry hints (such as minimum and maximum size).
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_constrain_size (GdkGeometry    *geometry,
 | ||
| 			   GdkWindowHints  flags,
 | ||
| 			   gint            width,
 | ||
| 			   gint            height,
 | ||
| 			   gint           *new_width,
 | ||
| 			   gint           *new_height)
 | ||
| {
 | ||
|   /* This routine is partially borrowed from fvwm.
 | ||
|    *
 | ||
|    * Copyright 1993, Robert Nation
 | ||
|    *     You may use this code for any purpose, as long as the original
 | ||
|    *     copyright remains in the source code and all documentation
 | ||
|    *
 | ||
|    * which in turn borrows parts of the algorithm from uwm
 | ||
|    */
 | ||
|   gint min_width = 0;
 | ||
|   gint min_height = 0;
 | ||
|   gint base_width = 0;
 | ||
|   gint base_height = 0;
 | ||
|   gint xinc = 1;
 | ||
|   gint yinc = 1;
 | ||
|   gint max_width = G_MAXINT;
 | ||
|   gint max_height = G_MAXINT;
 | ||
| 
 | ||
| #define FLOOR(value, base)	( ((gint) ((value) / (base))) * (base) )
 | ||
| 
 | ||
|   if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
 | ||
|     {
 | ||
|       base_width = geometry->base_width;
 | ||
|       base_height = geometry->base_height;
 | ||
|       min_width = geometry->min_width;
 | ||
|       min_height = geometry->min_height;
 | ||
|     }
 | ||
|   else if (flags & GDK_HINT_BASE_SIZE)
 | ||
|     {
 | ||
|       base_width = geometry->base_width;
 | ||
|       base_height = geometry->base_height;
 | ||
|       min_width = geometry->base_width;
 | ||
|       min_height = geometry->base_height;
 | ||
|     }
 | ||
|   else if (flags & GDK_HINT_MIN_SIZE)
 | ||
|     {
 | ||
|       base_width = geometry->min_width;
 | ||
|       base_height = geometry->min_height;
 | ||
|       min_width = geometry->min_width;
 | ||
|       min_height = geometry->min_height;
 | ||
|     }
 | ||
| 
 | ||
|   if (flags & GDK_HINT_MAX_SIZE)
 | ||
|     {
 | ||
|       max_width = geometry->max_width ;
 | ||
|       max_height = geometry->max_height;
 | ||
|     }
 | ||
| 
 | ||
|   if (flags & GDK_HINT_RESIZE_INC)
 | ||
|     {
 | ||
|       xinc = MAX (xinc, geometry->width_inc);
 | ||
|       yinc = MAX (yinc, geometry->height_inc);
 | ||
|     }
 | ||
| 
 | ||
|   /* clamp width and height to min and max values
 | ||
|    */
 | ||
|   width = CLAMP (width, min_width, max_width);
 | ||
|   height = CLAMP (height, min_height, max_height);
 | ||
| 
 | ||
|   /* shrink to base + N * inc
 | ||
|    */
 | ||
|   width = base_width + FLOOR (width - base_width, xinc);
 | ||
|   height = base_height + FLOOR (height - base_height, yinc);
 | ||
| 
 | ||
|   /* constrain aspect ratio, according to:
 | ||
|    *
 | ||
|    *                width
 | ||
|    * min_aspect <= -------- <= max_aspect
 | ||
|    *                height
 | ||
|    */
 | ||
| 
 | ||
|   if (flags & GDK_HINT_ASPECT &&
 | ||
|       geometry->min_aspect > 0 &&
 | ||
|       geometry->max_aspect > 0)
 | ||
|     {
 | ||
|       gint delta;
 | ||
| 
 | ||
|       if (geometry->min_aspect * height > width)
 | ||
| 	{
 | ||
| 	  delta = FLOOR (height - width / geometry->min_aspect, yinc);
 | ||
| 	  if (height - delta >= min_height)
 | ||
| 	    height -= delta;
 | ||
| 	  else
 | ||
| 	    {
 | ||
| 	      delta = FLOOR (height * geometry->min_aspect - width, xinc);
 | ||
| 	      if (width + delta <= max_width)
 | ||
| 		width += delta;
 | ||
| 	    }
 | ||
| 	}
 | ||
| 
 | ||
|       if (geometry->max_aspect * height < width)
 | ||
| 	{
 | ||
| 	  delta = FLOOR (width - height * geometry->max_aspect, xinc);
 | ||
| 	  if (width - delta >= min_width)
 | ||
| 	    width -= delta;
 | ||
| 	  else
 | ||
| 	    {
 | ||
| 	      delta = FLOOR (width / geometry->max_aspect - height, yinc);
 | ||
| 	      if (height + delta <= max_height)
 | ||
| 		height += delta;
 | ||
| 	    }
 | ||
| 	}
 | ||
|     }
 | ||
| 
 | ||
| #undef FLOOR
 | ||
| 
 | ||
|   *new_width = width;
 | ||
|   *new_height = height;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_pointer:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @x: (out) (allow-none): return location for X coordinate of pointer or %NULL to not
 | ||
|  *      return the X coordinate
 | ||
|  * @y: (out) (allow-none):  return location for Y coordinate of pointer or %NULL to not
 | ||
|  *      return the Y coordinate
 | ||
|  * @mask: (out) (allow-none): return location for modifier mask or %NULL to not return the
 | ||
|  *      modifier mask
 | ||
|  *
 | ||
|  * Obtains the current pointer position and modifier state.
 | ||
|  * The position is given in coordinates relative to the upper left
 | ||
|  * corner of @window.
 | ||
|  *
 | ||
|  * Returns: (nullable) (transfer none): the window containing the
 | ||
|  * pointer (as with gdk_window_at_pointer()), or %NULL if the window
 | ||
|  * containing the pointer isn’t known to GDK
 | ||
|  *
 | ||
|  * Deprecated: 3.0: Use gdk_window_get_device_position() instead.
 | ||
|  **/
 | ||
| GdkWindow*
 | ||
| gdk_window_get_pointer (GdkWindow	  *window,
 | ||
| 			gint		  *x,
 | ||
| 			gint		  *y,
 | ||
| 			GdkModifierType   *mask)
 | ||
| {
 | ||
|   GdkDisplay *display;
 | ||
|   GdkDevice *pointer;
 | ||
| 
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 | ||
| 
 | ||
|   display = gdk_window_get_display (window);
 | ||
|   pointer = gdk_seat_get_pointer (gdk_display_get_default_seat (display));
 | ||
| 
 | ||
|   return gdk_window_get_device_position (window, pointer, x, y, mask);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_device_position_double:
 | ||
|  * @window: a #GdkWindow.
 | ||
|  * @device: pointer #GdkDevice to query to.
 | ||
|  * @x: (out) (allow-none): return location for the X coordinate of @device, or %NULL.
 | ||
|  * @y: (out) (allow-none): return location for the Y coordinate of @device, or %NULL.
 | ||
|  * @mask: (out) (allow-none): return location for the modifier mask, or %NULL.
 | ||
|  *
 | ||
|  * Obtains the current device position in doubles and modifier state.
 | ||
|  * The position is given in coordinates relative to the upper left
 | ||
|  * corner of @window.
 | ||
|  *
 | ||
|  * Returns: (nullable) (transfer none): The window underneath @device
 | ||
|  * (as with gdk_device_get_window_at_position()), or %NULL if the
 | ||
|  * window is not known to GDK.
 | ||
|  *
 | ||
|  * Since: 3.10
 | ||
|  **/
 | ||
| GdkWindow *
 | ||
| gdk_window_get_device_position_double (GdkWindow       *window,
 | ||
|                                        GdkDevice       *device,
 | ||
|                                        double          *x,
 | ||
|                                        double          *y,
 | ||
|                                        GdkModifierType *mask)
 | ||
| {
 | ||
|   gdouble tmp_x, tmp_y;
 | ||
|   GdkModifierType tmp_mask;
 | ||
|   gboolean normal_child;
 | ||
| 
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 | ||
|   g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
 | ||
|   g_return_val_if_fail (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD, NULL);
 | ||
| 
 | ||
|   tmp_x = tmp_y = 0;
 | ||
|   tmp_mask = 0;
 | ||
|   normal_child = GDK_WINDOW_IMPL_GET_CLASS (window->impl)->get_device_state (window,
 | ||
|                                                                              device,
 | ||
|                                                                              &tmp_x, &tmp_y,
 | ||
|                                                                              &tmp_mask);
 | ||
|   /* We got the coords on the impl, convert to the window */
 | ||
|   tmp_x -= window->abs_x;
 | ||
|   tmp_y -= window->abs_y;
 | ||
| 
 | ||
|   if (x)
 | ||
|     *x = tmp_x;
 | ||
|   if (y)
 | ||
|     *y = tmp_y;
 | ||
|   if (mask)
 | ||
|     *mask = tmp_mask;
 | ||
| 
 | ||
|   _gdk_display_enable_motion_hints (gdk_window_get_display (window), device);
 | ||
| 
 | ||
|   if (normal_child)
 | ||
|     return _gdk_window_find_child_at (window, tmp_x, tmp_y);
 | ||
|   return NULL;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_device_position:
 | ||
|  * @window: a #GdkWindow.
 | ||
|  * @device: pointer #GdkDevice to query to.
 | ||
|  * @x: (out) (allow-none): return location for the X coordinate of @device, or %NULL.
 | ||
|  * @y: (out) (allow-none): return location for the Y coordinate of @device, or %NULL.
 | ||
|  * @mask: (out) (allow-none): return location for the modifier mask, or %NULL.
 | ||
|  *
 | ||
|  * Obtains the current device position and modifier state.
 | ||
|  * The position is given in coordinates relative to the upper left
 | ||
|  * corner of @window.
 | ||
|  *
 | ||
|  * Use gdk_window_get_device_position_double() if you need subpixel precision.
 | ||
|  *
 | ||
|  * Returns: (nullable) (transfer none): The window underneath @device
 | ||
|  * (as with gdk_device_get_window_at_position()), or %NULL if the
 | ||
|  * window is not known to GDK.
 | ||
|  *
 | ||
|  * Since: 3.0
 | ||
|  **/
 | ||
| GdkWindow *
 | ||
| gdk_window_get_device_position (GdkWindow       *window,
 | ||
|                                 GdkDevice       *device,
 | ||
|                                 gint            *x,
 | ||
|                                 gint            *y,
 | ||
|                                 GdkModifierType *mask)
 | ||
| {
 | ||
|   gdouble tmp_x, tmp_y;
 | ||
| 
 | ||
|   window = gdk_window_get_device_position_double (window, device,
 | ||
|                                                   &tmp_x, &tmp_y, mask);
 | ||
|   if (x)
 | ||
|     *x = round (tmp_x);
 | ||
|   if (y)
 | ||
|     *y = round (tmp_y);
 | ||
| 
 | ||
|   return window;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_get_default_root_window:
 | ||
|  *
 | ||
|  * Obtains the root window (parent all other windows are inside)
 | ||
|  * for the default display and screen.
 | ||
|  *
 | ||
|  * Returns: (transfer none): the default root window
 | ||
|  **/
 | ||
| GdkWindow *
 | ||
| gdk_get_default_root_window (void)
 | ||
| {
 | ||
|   return gdk_screen_get_root_window (gdk_screen_get_default ());
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| get_all_native_children (GdkWindow *window,
 | ||
| 			 GList **native)
 | ||
| {
 | ||
|   GdkWindow *child;
 | ||
|   GList *l;
 | ||
| 
 | ||
|   for (l = window->children; l != NULL; l = l->next)
 | ||
|     {
 | ||
|       child = l->data;
 | ||
| 
 | ||
|       if (gdk_window_has_impl (child))
 | ||
| 	*native = g_list_prepend (*native, child);
 | ||
|       else
 | ||
| 	get_all_native_children (child, native);
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| static gboolean
 | ||
| gdk_window_raise_internal (GdkWindow *window)
 | ||
| {
 | ||
|   GdkWindow *parent = window->parent;
 | ||
|   GdkWindow *above;
 | ||
|   GList *native_children;
 | ||
|   GList *l, listhead;
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
|   gboolean did_raise = FALSE;
 | ||
| 
 | ||
|   if (parent && parent->children->data != window)
 | ||
|     {
 | ||
|       parent->children = g_list_remove_link (parent->children, &window->children_list_node);
 | ||
|       parent->children = g_list_concat (&window->children_list_node, parent->children);
 | ||
|       did_raise = TRUE;
 | ||
|     }
 | ||
| 
 | ||
|   impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
|   /* Just do native raise for toplevels */
 | ||
|   if (gdk_window_is_toplevel (window) ||
 | ||
|       /* The restack_under codepath should work correctly even if the parent
 | ||
| 	 is native, but it relies on the order of ->children to be correct,
 | ||
| 	 and some apps like SWT reorder the x windows without gdks knowledge,
 | ||
| 	 so we use raise directly in order to make these behave as before
 | ||
| 	 when using native windows */
 | ||
|       (gdk_window_has_impl (window) && gdk_window_has_impl (parent)))
 | ||
|     {
 | ||
|       impl_class->raise (window);
 | ||
|     }
 | ||
|   else if (gdk_window_has_impl (window))
 | ||
|     {
 | ||
|       above = find_native_sibling_above (parent, window);
 | ||
|       if (above)
 | ||
| 	{
 | ||
| 	  listhead.data = window;
 | ||
| 	  listhead.next = NULL;
 | ||
| 	  listhead.prev = NULL;
 | ||
| 	  impl_class->restack_under ((GdkWindow *)above,
 | ||
| 				     &listhead);
 | ||
| 	}
 | ||
|       else
 | ||
| 	impl_class->raise (window);
 | ||
|     }
 | ||
|   else
 | ||
|     {
 | ||
|       native_children = NULL;
 | ||
|       get_all_native_children (window, &native_children);
 | ||
|       if (native_children != NULL)
 | ||
| 	{
 | ||
| 	  above = find_native_sibling_above (parent, window);
 | ||
| 
 | ||
| 	  if (above)
 | ||
| 	    impl_class->restack_under (above, native_children);
 | ||
| 	  else
 | ||
| 	    {
 | ||
| 	      /* Right order, since native_children is bottom-topmost first */
 | ||
| 	      for (l = native_children; l != NULL; l = l->next)
 | ||
| 		impl_class->raise (l->data);
 | ||
| 	    }
 | ||
| 
 | ||
| 	  g_list_free (native_children);
 | ||
| 	}
 | ||
|     }
 | ||
| 
 | ||
|   return did_raise;
 | ||
| }
 | ||
| 
 | ||
| /* Returns TRUE If the native window was mapped or unmapped */
 | ||
| static gboolean
 | ||
| set_viewable (GdkWindow *w,
 | ||
| 	      gboolean val)
 | ||
| {
 | ||
|   GdkWindow *child;
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
|   GList *l;
 | ||
| 
 | ||
|   if (w->viewable == val)
 | ||
|     return FALSE;
 | ||
| 
 | ||
|   w->viewable = val;
 | ||
| 
 | ||
|   if (val)
 | ||
|     recompute_visible_regions (w, FALSE);
 | ||
| 
 | ||
|   for (l = w->children; l != NULL; l = l->next)
 | ||
|     {
 | ||
|       child = l->data;
 | ||
| 
 | ||
|       if (GDK_WINDOW_IS_MAPPED (child) &&
 | ||
| 	  child->window_type != GDK_WINDOW_FOREIGN)
 | ||
| 	set_viewable (child, val);
 | ||
|     }
 | ||
| 
 | ||
|   if (gdk_window_has_impl (w)  &&
 | ||
|       w->window_type != GDK_WINDOW_FOREIGN &&
 | ||
|       !gdk_window_is_toplevel (w))
 | ||
|     {
 | ||
|       /* For most native windows we show/hide them not when they are
 | ||
|        * mapped/unmapped, because that may not produce the correct results.
 | ||
|        * For instance, if a native window have a non-native parent which is
 | ||
|        * hidden, but its native parent is viewable then showing the window
 | ||
|        * would make it viewable to X but its not viewable wrt the non-native
 | ||
|        * hierarchy. In order to handle this we track the gdk side viewability
 | ||
|        * and only map really viewable windows.
 | ||
|        *
 | ||
|        * There are two exceptions though:
 | ||
|        *
 | ||
|        * For foreign windows we don't want ever change the mapped state
 | ||
|        * except when explicitly done via gdk_window_show/hide, as this may
 | ||
|        * cause problems for client owning the foreign window when its window
 | ||
|        * is suddenly mapped or unmapped.
 | ||
|        *
 | ||
|        * For toplevel windows embedded in a foreign window (e.g. a plug)
 | ||
|        * we sometimes synthesize a map of a window, but the native
 | ||
|        * window is really shown by the embedder, so we don't want to
 | ||
|        * do the show ourselves. We can't really tell this case from the normal
 | ||
|        * toplevel show as such toplevels are seen by gdk as parents of the
 | ||
|        * root window, so we make an exception for all toplevels.
 | ||
|        */
 | ||
| 
 | ||
|       impl_class = GDK_WINDOW_IMPL_GET_CLASS (w->impl);
 | ||
|       if (val)
 | ||
| 	impl_class->show ((GdkWindow *)w, FALSE);
 | ||
|       else
 | ||
| 	impl_class->hide ((GdkWindow *)w);
 | ||
| 
 | ||
|       return TRUE;
 | ||
|     }
 | ||
| 
 | ||
|   return FALSE;
 | ||
| }
 | ||
| 
 | ||
| /* Returns TRUE If the native window was mapped or unmapped */
 | ||
| gboolean
 | ||
| _gdk_window_update_viewable (GdkWindow *window)
 | ||
| {
 | ||
|   gboolean viewable;
 | ||
| 
 | ||
|   if (window->window_type == GDK_WINDOW_FOREIGN ||
 | ||
|       window->window_type == GDK_WINDOW_ROOT)
 | ||
|     viewable = TRUE;
 | ||
|   else if (gdk_window_is_toplevel (window) ||
 | ||
| 	   window->parent->viewable)
 | ||
|     viewable = GDK_WINDOW_IS_MAPPED (window);
 | ||
|   else
 | ||
|     viewable = FALSE;
 | ||
| 
 | ||
|   return set_viewable (window, viewable);
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_show_internal (GdkWindow *window, gboolean raise)
 | ||
| {
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
|   gboolean was_mapped, was_viewable;
 | ||
|   gboolean did_show, did_raise = FALSE;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   if (window->destroyed)
 | ||
|     return;
 | ||
| 
 | ||
|   was_mapped = GDK_WINDOW_IS_MAPPED (window);
 | ||
|   was_viewable = window->viewable;
 | ||
| 
 | ||
|   if (raise)
 | ||
|     {
 | ||
|       /* Keep children in (reverse) stacking order */
 | ||
|       did_raise = gdk_window_raise_internal (window);
 | ||
|     }
 | ||
| 
 | ||
|   if (gdk_window_has_impl (window))
 | ||
|     {
 | ||
|       if (!was_mapped)
 | ||
| 	gdk_synthesize_window_state (window,
 | ||
| 				     GDK_WINDOW_STATE_WITHDRAWN,
 | ||
| 				     GDK_WINDOW_STATE_FOCUSED);
 | ||
|     }
 | ||
|   else
 | ||
|     {
 | ||
|       window->state = 0;
 | ||
|     }
 | ||
| 
 | ||
|   did_show = _gdk_window_update_viewable (window);
 | ||
| 
 | ||
|   /* If it was already viewable the backend show op won't be called, call it
 | ||
|      again to ensure things happen right if the mapped tracking was not right
 | ||
|      for e.g. a foreign window.
 | ||
|      Dunno if this is strictly needed but its what happened pre-csw.
 | ||
|      Also show if not done by gdk_window_update_viewable. */
 | ||
|   if (gdk_window_has_impl (window) && (was_viewable || !did_show))
 | ||
|     {
 | ||
|       impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
|       impl_class->show (window, !did_show ? was_mapped : TRUE);
 | ||
|     }
 | ||
| 
 | ||
|   if (!was_mapped && !gdk_window_has_impl (window))
 | ||
|     {
 | ||
|       if (window->event_mask & GDK_STRUCTURE_MASK)
 | ||
| 	_gdk_make_event (window, GDK_MAP, NULL, FALSE);
 | ||
| 
 | ||
|       if (window->parent && window->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
 | ||
| 	_gdk_make_event (window, GDK_MAP, NULL, FALSE);
 | ||
|     }
 | ||
| 
 | ||
|   if (!was_mapped || did_raise)
 | ||
|     {
 | ||
|       recompute_visible_regions (window, FALSE);
 | ||
| 
 | ||
|       /* If any decendants became visible we need to send visibility notify */
 | ||
|       gdk_window_update_visibility_recursively (window, NULL);
 | ||
| 
 | ||
|       if (gdk_window_is_viewable (window))
 | ||
| 	{
 | ||
| 	  _gdk_synthesize_crossing_events_for_geometry_change (window);
 | ||
| 	  gdk_window_invalidate_rect_full (window, NULL, TRUE);
 | ||
| 	}
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_show_unraised:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Shows a #GdkWindow onscreen, but does not modify its stacking
 | ||
|  * order. In contrast, gdk_window_show() will raise the window
 | ||
|  * to the top of the window stack.
 | ||
|  *
 | ||
|  * On the X11 platform, in Xlib terms, this function calls
 | ||
|  * XMapWindow() (it also updates some internal GDK state, which means
 | ||
|  * that you can’t really use XMapWindow() directly on a GDK window).
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_show_unraised (GdkWindow *window)
 | ||
| {
 | ||
|   gdk_window_show_internal (window, FALSE);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_raise:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Raises @window to the top of the Z-order (stacking order), so that
 | ||
|  * other windows with the same parent window appear below @window.
 | ||
|  * This is true whether or not the windows are visible.
 | ||
|  *
 | ||
|  * If @window is a toplevel, the window manager may choose to deny the
 | ||
|  * request to move the window in the Z-order, gdk_window_raise() only
 | ||
|  * requests the restack, does not guarantee it.
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_raise (GdkWindow *window)
 | ||
| {
 | ||
|   gboolean did_raise;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   if (window->destroyed)
 | ||
|     return;
 | ||
| 
 | ||
|   /* Keep children in (reverse) stacking order */
 | ||
|   did_raise = gdk_window_raise_internal (window);
 | ||
| 
 | ||
|   if (did_raise &&
 | ||
|       !gdk_window_is_toplevel (window) &&
 | ||
|       gdk_window_is_viewable (window) &&
 | ||
|       !window->input_only)
 | ||
|     gdk_window_invalidate_region_full (window, window->clip_region, TRUE);
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_lower_internal (GdkWindow *window)
 | ||
| {
 | ||
|   GdkWindow *parent = window->parent;
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
|   GdkWindow *above;
 | ||
|   GList *native_children;
 | ||
|   GList *l, listhead;
 | ||
| 
 | ||
|   if (parent)
 | ||
|     {
 | ||
|       parent->children = g_list_remove_link (parent->children, &window->children_list_node);
 | ||
|       parent->children = g_list_concat (parent->children, &window->children_list_node);
 | ||
|     }
 | ||
| 
 | ||
|   impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
|   /* Just do native lower for toplevels */
 | ||
|   if (gdk_window_is_toplevel (window) ||
 | ||
|       /* The restack_under codepath should work correctly even if the parent
 | ||
| 	 is native, but it relies on the order of ->children to be correct,
 | ||
| 	 and some apps like SWT reorder the x windows without gdks knowledge,
 | ||
| 	 so we use lower directly in order to make these behave as before
 | ||
| 	 when using native windows */
 | ||
|       (gdk_window_has_impl (window) && gdk_window_has_impl (parent)))
 | ||
|     {
 | ||
|       impl_class->lower (window);
 | ||
|     }
 | ||
|   else if (gdk_window_has_impl (window))
 | ||
|     {
 | ||
|       above = find_native_sibling_above (parent, window);
 | ||
|       if (above)
 | ||
| 	{
 | ||
| 	  listhead.data = window;
 | ||
| 	  listhead.next = NULL;
 | ||
| 	  listhead.prev = NULL;
 | ||
| 	  impl_class->restack_under ((GdkWindow *)above, &listhead);
 | ||
| 	}
 | ||
|       else
 | ||
| 	impl_class->raise (window);
 | ||
|     }
 | ||
|   else
 | ||
|     {
 | ||
|       native_children = NULL;
 | ||
|       get_all_native_children (window, &native_children);
 | ||
|       if (native_children != NULL)
 | ||
| 	{
 | ||
| 	  above = find_native_sibling_above (parent, window);
 | ||
| 
 | ||
| 	  if (above)
 | ||
| 	    impl_class->restack_under ((GdkWindow *)above,
 | ||
| 				       native_children);
 | ||
| 	  else
 | ||
| 	    {
 | ||
| 	      /* Right order, since native_children is bottom-topmost first */
 | ||
| 	      for (l = native_children; l != NULL; l = l->next)
 | ||
| 		impl_class->raise (l->data);
 | ||
| 	    }
 | ||
| 
 | ||
| 	  g_list_free (native_children);
 | ||
| 	}
 | ||
| 
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_invalidate_in_parent (GdkWindow *private)
 | ||
| {
 | ||
|   GdkRectangle r, child;
 | ||
| 
 | ||
|   if (gdk_window_is_toplevel (private))
 | ||
|     return;
 | ||
| 
 | ||
|   /* get the visible rectangle of the parent */
 | ||
|   r.x = r.y = 0;
 | ||
|   r.width = private->parent->width;
 | ||
|   r.height = private->parent->height;
 | ||
| 
 | ||
|   child.x = private->x;
 | ||
|   child.y = private->y;
 | ||
|   child.width = private->width;
 | ||
|   child.height = private->height;
 | ||
|   gdk_rectangle_intersect (&r, &child, &r);
 | ||
| 
 | ||
|   gdk_window_invalidate_rect_full (private->parent, &r, TRUE);
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_lower:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Lowers @window to the bottom of the Z-order (stacking order), so that
 | ||
|  * other windows with the same parent window appear above @window.
 | ||
|  * This is true whether or not the other windows are visible.
 | ||
|  *
 | ||
|  * If @window is a toplevel, the window manager may choose to deny the
 | ||
|  * request to move the window in the Z-order, gdk_window_lower() only
 | ||
|  * requests the restack, does not guarantee it.
 | ||
|  *
 | ||
|  * Note that gdk_window_show() raises the window again, so don’t call this
 | ||
|  * function before gdk_window_show(). (Try gdk_window_show_unraised().)
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_lower (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   if (window->destroyed)
 | ||
|     return;
 | ||
| 
 | ||
|   /* Keep children in (reverse) stacking order */
 | ||
|   gdk_window_lower_internal (window);
 | ||
| 
 | ||
|   _gdk_synthesize_crossing_events_for_geometry_change (window);
 | ||
|   gdk_window_invalidate_in_parent (window);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_restack:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @sibling: (allow-none): a #GdkWindow that is a sibling of @window, or %NULL
 | ||
|  * @above: a boolean
 | ||
|  *
 | ||
|  * Changes the position of  @window in the Z-order (stacking order), so that
 | ||
|  * it is above @sibling (if @above is %TRUE) or below @sibling (if @above is
 | ||
|  * %FALSE).
 | ||
|  *
 | ||
|  * If @sibling is %NULL, then this either raises (if @above is %TRUE) or
 | ||
|  * lowers the window.
 | ||
|  *
 | ||
|  * If @window is a toplevel, the window manager may choose to deny the
 | ||
|  * request to move the window in the Z-order, gdk_window_restack() only
 | ||
|  * requests the restack, does not guarantee it.
 | ||
|  *
 | ||
|  * Since: 2.18
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_restack (GdkWindow     *window,
 | ||
| 		    GdkWindow     *sibling,
 | ||
| 		    gboolean       above)
 | ||
| {
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
|   GdkWindow *parent;
 | ||
|   GdkWindow *above_native;
 | ||
|   GList *sibling_link;
 | ||
|   GList *native_children;
 | ||
|   GList *l, listhead;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
|   g_return_if_fail (sibling == NULL || GDK_IS_WINDOW (sibling));
 | ||
| 
 | ||
|   if (window->destroyed)
 | ||
|     return;
 | ||
| 
 | ||
|   if (sibling == NULL)
 | ||
|     {
 | ||
|       if (above)
 | ||
| 	gdk_window_raise (window);
 | ||
|       else
 | ||
| 	gdk_window_lower (window);
 | ||
|       return;
 | ||
|     }
 | ||
| 
 | ||
|   if (gdk_window_is_toplevel (window))
 | ||
|     {
 | ||
|       g_return_if_fail (gdk_window_is_toplevel (sibling));
 | ||
|       impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
|       impl_class->restack_toplevel (window, sibling, above);
 | ||
|       return;
 | ||
|     }
 | ||
| 
 | ||
|   parent = window->parent;
 | ||
|   if (parent)
 | ||
|     {
 | ||
|       sibling_link = g_list_find (parent->children, sibling);
 | ||
|       g_return_if_fail (sibling_link != NULL);
 | ||
|       if (sibling_link == NULL)
 | ||
| 	return;
 | ||
| 
 | ||
|       parent->children = g_list_remove_link (parent->children, &window->children_list_node);
 | ||
|       if (above)
 | ||
| 	parent->children = list_insert_link_before (parent->children,
 | ||
|                                                     sibling_link,
 | ||
|                                                     &window->children_list_node);
 | ||
|       else
 | ||
| 	parent->children = list_insert_link_before (parent->children,
 | ||
|                                                     sibling_link->next,
 | ||
|                                                     &window->children_list_node);
 | ||
| 
 | ||
|       impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
|       if (gdk_window_has_impl (window))
 | ||
| 	{
 | ||
| 	  above_native = find_native_sibling_above (parent, window);
 | ||
| 	  if (above_native)
 | ||
| 	    {
 | ||
| 	      listhead.data = window;
 | ||
| 	      listhead.next = NULL;
 | ||
| 	      listhead.prev = NULL;
 | ||
| 	      impl_class->restack_under (above_native, &listhead);
 | ||
| 	    }
 | ||
| 	  else
 | ||
| 	    impl_class->raise (window);
 | ||
| 	}
 | ||
|       else
 | ||
| 	{
 | ||
| 	  native_children = NULL;
 | ||
| 	  get_all_native_children (window, &native_children);
 | ||
| 	  if (native_children != NULL)
 | ||
| 	    {
 | ||
| 	      above_native = find_native_sibling_above (parent, window);
 | ||
| 	      if (above_native)
 | ||
| 		impl_class->restack_under (above_native,
 | ||
| 					   native_children);
 | ||
| 	      else
 | ||
| 		{
 | ||
| 		  /* Right order, since native_children is bottom-topmost first */
 | ||
| 		  for (l = native_children; l != NULL; l = l->next)
 | ||
| 		    impl_class->raise (l->data);
 | ||
| 		}
 | ||
| 
 | ||
| 	      g_list_free (native_children);
 | ||
| 	    }
 | ||
| 	}
 | ||
|     }
 | ||
| 
 | ||
|   _gdk_synthesize_crossing_events_for_geometry_change (window);
 | ||
|   gdk_window_invalidate_in_parent (window);
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_show:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Like gdk_window_show_unraised(), but also raises the window to the
 | ||
|  * top of the window stack (moves the window to the front of the
 | ||
|  * Z-order).
 | ||
|  *
 | ||
|  * This function maps a window so it’s visible onscreen. Its opposite
 | ||
|  * is gdk_window_hide().
 | ||
|  *
 | ||
|  * When implementing a #GtkWidget, you should call this function on the widget's
 | ||
|  * #GdkWindow as part of the “map” method.
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_show (GdkWindow *window)
 | ||
| {
 | ||
|   gdk_window_show_internal (window, TRUE);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_hide:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * For toplevel windows, withdraws them, so they will no longer be
 | ||
|  * known to the window manager; for all windows, unmaps them, so
 | ||
|  * they won’t be displayed. Normally done automatically as
 | ||
|  * part of gtk_widget_hide().
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_hide (GdkWindow *window)
 | ||
| {
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
|   gboolean was_mapped, did_hide;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   if (window->destroyed)
 | ||
|     return;
 | ||
| 
 | ||
|   was_mapped = GDK_WINDOW_IS_MAPPED (window);
 | ||
| 
 | ||
|   if (gdk_window_has_impl (window))
 | ||
|     {
 | ||
| 
 | ||
|       if (GDK_WINDOW_IS_MAPPED (window))
 | ||
| 	gdk_synthesize_window_state (window,
 | ||
| 				     0,
 | ||
| 				     GDK_WINDOW_STATE_WITHDRAWN);
 | ||
|     }
 | ||
|   else if (was_mapped)
 | ||
|     {
 | ||
|       GdkDisplay *display;
 | ||
|       GdkDeviceManager *device_manager;
 | ||
|       GList *devices, *d;
 | ||
| 
 | ||
|       G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
 | ||
| 
 | ||
|       /* May need to break grabs on children */
 | ||
|       display = gdk_window_get_display (window);
 | ||
|       device_manager = gdk_display_get_device_manager (display);
 | ||
| 
 | ||
|       /* Get all devices */
 | ||
|       devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
 | ||
|       devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
 | ||
|       devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
 | ||
| 
 | ||
|       for (d = devices; d; d = d->next)
 | ||
|         {
 | ||
|           GdkDevice *device = d->data;
 | ||
| 
 | ||
|           if (_gdk_display_end_device_grab (display,
 | ||
|                                             device,
 | ||
|                                             _gdk_display_get_next_serial (display),
 | ||
|                                             window,
 | ||
|                                             TRUE))
 | ||
|             gdk_device_ungrab (device, GDK_CURRENT_TIME);
 | ||
|         }
 | ||
| 
 | ||
|       window->state = GDK_WINDOW_STATE_WITHDRAWN;
 | ||
|       g_list_free (devices);
 | ||
|       G_GNUC_END_IGNORE_DEPRECATIONS;
 | ||
|     }
 | ||
| 
 | ||
|   did_hide = _gdk_window_update_viewable (window);
 | ||
| 
 | ||
|   /* Hide foreign window as those are not handled by update_viewable. */
 | ||
|   if (gdk_window_has_impl (window) && (!did_hide))
 | ||
|     {
 | ||
|       impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
|       impl_class->hide (window);
 | ||
|     }
 | ||
| 
 | ||
|   gdk_window_clear_old_updated_area (window);
 | ||
|   recompute_visible_regions (window, FALSE);
 | ||
| 
 | ||
|   /* all decendants became non-visible, we need to send visibility notify */
 | ||
|   gdk_window_update_visibility_recursively (window, NULL);
 | ||
| 
 | ||
|   if (was_mapped && !gdk_window_has_impl (window))
 | ||
|     {
 | ||
|       if (window->event_mask & GDK_STRUCTURE_MASK)
 | ||
| 	_gdk_make_event (window, GDK_UNMAP, NULL, FALSE);
 | ||
| 
 | ||
|       if (window->parent && window->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
 | ||
| 	_gdk_make_event (window, GDK_UNMAP, NULL, FALSE);
 | ||
| 
 | ||
|       _gdk_synthesize_crossing_events_for_geometry_change (window->parent);
 | ||
|     }
 | ||
| 
 | ||
|   /* Invalidate the rect */
 | ||
|   if (was_mapped)
 | ||
|     gdk_window_invalidate_in_parent (window);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_withdraw:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  *
 | ||
|  * Withdraws a window (unmaps it and asks the window manager to forget about it).
 | ||
|  * This function is not really useful as gdk_window_hide() automatically
 | ||
|  * withdraws toplevel windows before hiding them.
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_withdraw (GdkWindow *window)
 | ||
| {
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
|   gboolean was_mapped;
 | ||
|   GdkGLContext *current_context;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   if (window->destroyed)
 | ||
|     return;
 | ||
| 
 | ||
|   was_mapped = GDK_WINDOW_IS_MAPPED (window);
 | ||
| 
 | ||
|   if (gdk_window_has_impl (window))
 | ||
|     {
 | ||
|       impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
|       impl_class->withdraw (window);
 | ||
| 
 | ||
|       if (was_mapped)
 | ||
| 	{
 | ||
| 	  if (window->event_mask & GDK_STRUCTURE_MASK)
 | ||
| 	    _gdk_make_event (window, GDK_UNMAP, NULL, FALSE);
 | ||
| 
 | ||
| 	  if (window->parent && window->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
 | ||
| 	    _gdk_make_event (window, GDK_UNMAP, NULL, FALSE);
 | ||
| 
 | ||
| 	  _gdk_synthesize_crossing_events_for_geometry_change (window->parent);
 | ||
| 	}
 | ||
| 
 | ||
|       current_context = gdk_gl_context_get_current ();
 | ||
|       if (current_context != NULL && gdk_gl_context_get_window (current_context) == window)
 | ||
|         gdk_gl_context_clear_current ();
 | ||
| 
 | ||
|       recompute_visible_regions (window, FALSE);
 | ||
|       gdk_window_clear_old_updated_area (window);
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_events:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @event_mask: event mask for @window
 | ||
|  *
 | ||
|  * The event mask for a window determines which events will be reported
 | ||
|  * for that window from all master input devices. For example, an event mask
 | ||
|  * including #GDK_BUTTON_PRESS_MASK means the window should report button
 | ||
|  * press events. The event mask is the bitwise OR of values from the
 | ||
|  * #GdkEventMask enumeration.
 | ||
|  *
 | ||
|  * See the [input handling overview][event-masks] for details.
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_set_events (GdkWindow       *window,
 | ||
| 		       GdkEventMask     event_mask)
 | ||
| {
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
|   GdkDisplay *display;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   if (window->destroyed)
 | ||
|     return;
 | ||
| 
 | ||
|   /* If motion hint is disabled, enable motion events again */
 | ||
|   display = gdk_window_get_display (window);
 | ||
|   if ((window->event_mask & GDK_POINTER_MOTION_HINT_MASK) &&
 | ||
|       !(event_mask & GDK_POINTER_MOTION_HINT_MASK))
 | ||
|     {
 | ||
|       GList *devices = window->devices_inside;
 | ||
| 
 | ||
|       while (devices)
 | ||
|         {
 | ||
|           _gdk_display_enable_motion_hints (display, (GdkDevice *) devices->data);
 | ||
|           devices = devices->next;
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|   window->event_mask = event_mask;
 | ||
| 
 | ||
|   if (gdk_window_has_impl (window))
 | ||
|     {
 | ||
|       impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
|       impl_class->set_events (window,
 | ||
| 			      get_native_event_mask (window));
 | ||
|     }
 | ||
| 
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_events:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Gets the event mask for @window for all master input devices. See
 | ||
|  * gdk_window_set_events().
 | ||
|  *
 | ||
|  * Returns: event mask for @window
 | ||
|  **/
 | ||
| GdkEventMask
 | ||
| gdk_window_get_events (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
 | ||
| 
 | ||
|   if (window->destroyed)
 | ||
|     return 0;
 | ||
| 
 | ||
|   return window->event_mask;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_device_events:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @device: #GdkDevice to enable events for.
 | ||
|  * @event_mask: event mask for @window
 | ||
|  *
 | ||
|  * Sets the event mask for a given device (Normally a floating device, not
 | ||
|  * attached to any visible pointer) to @window. For example, an event mask
 | ||
|  * including #GDK_BUTTON_PRESS_MASK means the window should report button
 | ||
|  * press events. The event mask is the bitwise OR of values from the
 | ||
|  * #GdkEventMask enumeration.
 | ||
|  *
 | ||
|  * See the [input handling overview][event-masks] for details.
 | ||
|  *
 | ||
|  * Since: 3.0
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_set_device_events (GdkWindow    *window,
 | ||
|                               GdkDevice    *device,
 | ||
|                               GdkEventMask  event_mask)
 | ||
| {
 | ||
|   GdkEventMask device_mask;
 | ||
|   GdkDisplay *display;
 | ||
|   GdkWindow *native;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
|   g_return_if_fail (GDK_IS_DEVICE (device));
 | ||
| 
 | ||
|   if (GDK_WINDOW_DESTROYED (window))
 | ||
|     return;
 | ||
| 
 | ||
|   /* If motion hint is disabled, enable motion events again */
 | ||
|   display = gdk_window_get_display (window);
 | ||
|   if ((window->event_mask & GDK_POINTER_MOTION_HINT_MASK) &&
 | ||
|       !(event_mask & GDK_POINTER_MOTION_HINT_MASK))
 | ||
|     _gdk_display_enable_motion_hints (display, device);
 | ||
| 
 | ||
|   if (G_UNLIKELY (!window->device_events))
 | ||
|     window->device_events = g_hash_table_new (NULL, NULL);
 | ||
| 
 | ||
|   if (event_mask == 0)
 | ||
|     {
 | ||
|       /* FIXME: unsetting events on a master device
 | ||
|        * would restore window->event_mask
 | ||
|        */
 | ||
|       g_hash_table_remove (window->device_events, device);
 | ||
|     }
 | ||
|   else
 | ||
|     g_hash_table_insert (window->device_events, device,
 | ||
|                          GINT_TO_POINTER (event_mask));
 | ||
| 
 | ||
|   native = gdk_window_get_toplevel (window);
 | ||
| 
 | ||
|   while (gdk_window_is_offscreen (native))
 | ||
|     {
 | ||
|       native = gdk_offscreen_window_get_embedder (native);
 | ||
| 
 | ||
|       if (native == NULL ||
 | ||
| 	  (!_gdk_window_has_impl (native) &&
 | ||
| 	   !gdk_window_is_viewable (native)))
 | ||
| 	return;
 | ||
| 
 | ||
|       native = gdk_window_get_toplevel (native);
 | ||
|     }
 | ||
| 
 | ||
|   device_mask = get_native_device_event_mask (window, device);
 | ||
|   GDK_DEVICE_GET_CLASS (device)->select_window_events (device, native, device_mask);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_device_events:
 | ||
|  * @window: a #GdkWindow.
 | ||
|  * @device: a #GdkDevice.
 | ||
|  *
 | ||
|  * Returns the event mask for @window corresponding to an specific device.
 | ||
|  *
 | ||
|  * Returns: device event mask for @window
 | ||
|  *
 | ||
|  * Since: 3.0
 | ||
|  **/
 | ||
| GdkEventMask
 | ||
| gdk_window_get_device_events (GdkWindow *window,
 | ||
|                               GdkDevice *device)
 | ||
| {
 | ||
|   GdkEventMask mask;
 | ||
| 
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
 | ||
|   g_return_val_if_fail (GDK_IS_DEVICE (device), 0);
 | ||
| 
 | ||
|   if (GDK_WINDOW_DESTROYED (window))
 | ||
|     return 0;
 | ||
| 
 | ||
|   if (!window->device_events)
 | ||
|     return 0;
 | ||
| 
 | ||
|   mask = GPOINTER_TO_INT (g_hash_table_lookup (window->device_events, device));
 | ||
| 
 | ||
|   /* FIXME: device could be controlled by window->event_mask */
 | ||
| 
 | ||
|   return mask;
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_move_resize_toplevel (GdkWindow *window,
 | ||
|                                  gboolean   with_move,
 | ||
|                                  gint       x,
 | ||
|                                  gint       y,
 | ||
|                                  gint       width,
 | ||
|                                  gint       height)
 | ||
| {
 | ||
|   cairo_region_t *old_region, *new_region;
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
|   gboolean expose;
 | ||
|   gboolean is_resize;
 | ||
| 
 | ||
|   expose = FALSE;
 | ||
|   old_region = NULL;
 | ||
| 
 | ||
|   is_resize = (width != -1) || (height != -1);
 | ||
| 
 | ||
|   if (gdk_window_is_viewable (window) &&
 | ||
|       !window->input_only)
 | ||
|     {
 | ||
|       expose = TRUE;
 | ||
|       old_region = cairo_region_copy (window->clip_region);
 | ||
|     }
 | ||
| 
 | ||
|   impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
|   impl_class->move_resize (window, with_move, x, y, width, height);
 | ||
| 
 | ||
|   /* Avoid recomputing for pure toplevel moves, for performance reasons */
 | ||
|   if (is_resize)
 | ||
|     recompute_visible_regions (window, FALSE);
 | ||
| 
 | ||
|   if (expose)
 | ||
|     {
 | ||
|       new_region = cairo_region_copy (window->clip_region);
 | ||
| 
 | ||
|       /* This is the newly exposed area (due to any resize),
 | ||
|        * X will expose it, but lets do that without the roundtrip
 | ||
|        */
 | ||
|       cairo_region_subtract (new_region, old_region);
 | ||
|       gdk_window_invalidate_region_full (window, new_region, TRUE);
 | ||
| 
 | ||
|       cairo_region_destroy (old_region);
 | ||
|       cairo_region_destroy (new_region);
 | ||
|     }
 | ||
| 
 | ||
|   _gdk_synthesize_crossing_events_for_geometry_change (window);
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| static void
 | ||
| move_native_children (GdkWindow *private)
 | ||
| {
 | ||
|   GList *l;
 | ||
|   GdkWindow *child;
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
| 
 | ||
|   for (l = private->children; l; l = l->next)
 | ||
|     {
 | ||
|       child = l->data;
 | ||
| 
 | ||
|       if (child->impl != private->impl)
 | ||
| 	{
 | ||
| 	  impl_class = GDK_WINDOW_IMPL_GET_CLASS (child->impl);
 | ||
| 	  impl_class->move_resize (child, TRUE,
 | ||
| 				   child->x, child->y,
 | ||
| 				   child->width, child->height);
 | ||
| 	}
 | ||
|       else
 | ||
| 	move_native_children  (child);
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_move_resize_internal (GdkWindow *window,
 | ||
| 				 gboolean   with_move,
 | ||
| 				 gint       x,
 | ||
| 				 gint       y,
 | ||
| 				 gint       width,
 | ||
| 				 gint       height)
 | ||
| {
 | ||
|   cairo_region_t *old_region, *new_region;
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
|   gboolean expose;
 | ||
|   int old_abs_x, old_abs_y;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   if (window->destroyed)
 | ||
|     return;
 | ||
| 
 | ||
|   if (gdk_window_is_toplevel (window))
 | ||
|     {
 | ||
|       gdk_window_move_resize_toplevel (window, with_move, x, y, width, height);
 | ||
|       return;
 | ||
|     }
 | ||
| 
 | ||
|   if (width == 0)
 | ||
|     width = 1;
 | ||
|   if (height == 0)
 | ||
|     height = 1;
 | ||
| 
 | ||
|   /* Bail early if no change */
 | ||
|   if (window->width == width &&
 | ||
|       window->height == height &&
 | ||
|       (!with_move ||
 | ||
|        (window->x == x &&
 | ||
| 	window->y == y)))
 | ||
|     return;
 | ||
| 
 | ||
|   /* Handle child windows */
 | ||
| 
 | ||
|   expose = FALSE;
 | ||
|   old_region = NULL;
 | ||
| 
 | ||
|   if (gdk_window_is_viewable (window) &&
 | ||
|       !window->input_only)
 | ||
|     {
 | ||
|       GdkRectangle r;
 | ||
| 
 | ||
|       expose = TRUE;
 | ||
| 
 | ||
|       r.x = window->x;
 | ||
|       r.y = window->y;
 | ||
|       r.width = window->width;
 | ||
|       r.height = window->height;
 | ||
| 
 | ||
|       old_region = cairo_region_create_rectangle (&r);
 | ||
|     }
 | ||
| 
 | ||
|   /* Set the new position and size */
 | ||
|   if (with_move)
 | ||
|     {
 | ||
|       window->x = x;
 | ||
|       window->y = y;
 | ||
|     }
 | ||
|   if (!(width < 0 && height < 0))
 | ||
|     {
 | ||
|       window->width = width;
 | ||
|       window->height = height;
 | ||
|     }
 | ||
| 
 | ||
|   old_abs_x = window->abs_x;
 | ||
|   old_abs_y = window->abs_y;
 | ||
| 
 | ||
|   recompute_visible_regions (window, FALSE);
 | ||
| 
 | ||
|   if (gdk_window_has_impl (window))
 | ||
|     {
 | ||
|       impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
| 
 | ||
|       /* Do the actual move after recomputing things, as this will have set the shape to
 | ||
| 	 the now correct one, thus avoiding copying regions that should not be copied. */
 | ||
|       impl_class->move_resize (window, TRUE,
 | ||
| 			       window->x, window->y,
 | ||
| 			       window->width, window->height);
 | ||
|     }
 | ||
|   else if (old_abs_x != window->abs_x ||
 | ||
| 	   old_abs_y != window->abs_y)
 | ||
|     move_native_children (window);
 | ||
| 
 | ||
|   if (expose)
 | ||
|     {
 | ||
|       GdkRectangle r;
 | ||
| 
 | ||
|       r.x = window->x;
 | ||
|       r.y = window->y;
 | ||
|       r.width = window->width;
 | ||
|       r.height = window->height;
 | ||
| 
 | ||
|       new_region = cairo_region_create_rectangle (&r);
 | ||
| 
 | ||
|       cairo_region_union (new_region, old_region);
 | ||
| 
 | ||
|       gdk_window_invalidate_region_full (window->parent, new_region, TRUE);
 | ||
| 
 | ||
|       cairo_region_destroy (old_region);
 | ||
|       cairo_region_destroy (new_region);
 | ||
|     }
 | ||
| 
 | ||
|   _gdk_synthesize_crossing_events_for_geometry_change (window);
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_move:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @x: X coordinate relative to window’s parent
 | ||
|  * @y: Y coordinate relative to window’s parent
 | ||
|  *
 | ||
|  * Repositions a window relative to its parent window.
 | ||
|  * For toplevel windows, window managers may ignore or modify the move;
 | ||
|  * you should probably use gtk_window_move() on a #GtkWindow widget
 | ||
|  * anyway, instead of using GDK functions. For child windows,
 | ||
|  * the move will reliably succeed.
 | ||
|  *
 | ||
|  * If you’re also planning to resize the window, use gdk_window_move_resize()
 | ||
|  * to both move and resize simultaneously, for a nicer visual effect.
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_move (GdkWindow *window,
 | ||
| 		 gint       x,
 | ||
| 		 gint       y)
 | ||
| {
 | ||
|   gdk_window_move_resize_internal (window, TRUE, x, y, -1, -1);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_resize:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @width: new width of the window
 | ||
|  * @height: new height of the window
 | ||
|  *
 | ||
|  * Resizes @window; for toplevel windows, asks the window manager to resize
 | ||
|  * the window. The window manager may not allow the resize. When using GTK+,
 | ||
|  * use gtk_window_resize() instead of this low-level GDK function.
 | ||
|  *
 | ||
|  * Windows may not be resized below 1x1.
 | ||
|  *
 | ||
|  * If you’re also planning to move the window, use gdk_window_move_resize()
 | ||
|  * to both move and resize simultaneously, for a nicer visual effect.
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_resize (GdkWindow *window,
 | ||
| 		   gint       width,
 | ||
| 		   gint       height)
 | ||
| {
 | ||
|   gdk_window_move_resize_internal (window, FALSE, 0, 0, width, height);
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_move_resize:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @x: new X position relative to window’s parent
 | ||
|  * @y: new Y position relative to window’s parent
 | ||
|  * @width: new width
 | ||
|  * @height: new height
 | ||
|  *
 | ||
|  * Equivalent to calling gdk_window_move() and gdk_window_resize(),
 | ||
|  * except that both operations are performed at once, avoiding strange
 | ||
|  * visual effects. (i.e. the user may be able to see the window first
 | ||
|  * move, then resize, if you don’t use gdk_window_move_resize().)
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_move_resize (GdkWindow *window,
 | ||
| 			gint       x,
 | ||
| 			gint       y,
 | ||
| 			gint       width,
 | ||
| 			gint       height)
 | ||
| {
 | ||
|   gdk_window_move_resize_internal (window, TRUE, x, y, width, height);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_move_to_rect:
 | ||
|  * @window: the #GdkWindow to move
 | ||
|  * @rect: (not nullable): the destination #GdkRectangle to align @window with
 | ||
|  * @rect_anchor: the point on @rect to align with @window's anchor point
 | ||
|  * @window_anchor: the point on @window to align with @rect's anchor point
 | ||
|  * @anchor_hints: positioning hints to use when limited on space
 | ||
|  * @rect_anchor_dx: horizontal offset to shift @window, i.e. @rect's anchor
 | ||
|  *                  point
 | ||
|  * @rect_anchor_dy: vertical offset to shift @window, i.e. @rect's anchor point
 | ||
|  *
 | ||
|  * Moves @window to @rect, aligning their anchor points.
 | ||
|  *
 | ||
|  * @rect is relative to the top-left corner of the window that @window is
 | ||
|  * transient for. @rect_anchor and @window_anchor determine anchor points on
 | ||
|  * @rect and @window to pin together. @rect's anchor point can optionally be
 | ||
|  * offset by @rect_anchor_dx and @rect_anchor_dy, which is equivalent to
 | ||
|  * offsetting the position of @window.
 | ||
|  *
 | ||
|  * @anchor_hints determines how @window will be moved if the anchor points cause
 | ||
|  * it to move off-screen. For example, %GDK_ANCHOR_FLIP_X will replace
 | ||
|  * %GDK_GRAVITY_NORTH_WEST with %GDK_GRAVITY_NORTH_EAST and vice versa if
 | ||
|  * @window extends beyond the left or right edges of the monitor.
 | ||
|  *
 | ||
|  * Connect to the #GdkWindow::moved-to-rect signal to find out how it was
 | ||
|  * actually positioned.
 | ||
|  *
 | ||
|  * Since: 3.24
 | ||
|  */
 | ||
| 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)
 | ||
| {
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
|   g_return_if_fail (window->transient_for);
 | ||
|   g_return_if_fail (rect);
 | ||
| 
 | ||
|   impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
|   impl_class->move_to_rect (window,
 | ||
|                             rect,
 | ||
|                             rect_anchor,
 | ||
|                             window_anchor,
 | ||
|                             anchor_hints,
 | ||
|                             rect_anchor_dx,
 | ||
|                             rect_anchor_dy);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_scroll:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @dx: Amount to scroll in the X direction
 | ||
|  * @dy: Amount to scroll in the Y direction
 | ||
|  *
 | ||
|  * Scroll the contents of @window, both pixels and children, by the
 | ||
|  * given amount. @window itself does not move. Portions of the window
 | ||
|  * that the scroll operation brings in from offscreen areas are
 | ||
|  * invalidated. The invalidated region may be bigger than what would
 | ||
|  * strictly be necessary.
 | ||
|  *
 | ||
|  * For X11, a minimum area will be invalidated if the window has no
 | ||
|  * subwindows, or if the edges of the window’s parent do not extend
 | ||
|  * beyond the edges of the window. In other cases, a multi-step process
 | ||
|  * is used to scroll the window which may produce temporary visual
 | ||
|  * artifacts and unnecessary invalidations.
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_scroll (GdkWindow *window,
 | ||
| 		   gint       dx,
 | ||
| 		   gint       dy)
 | ||
| {
 | ||
|   GList *tmp_list;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   if (dx == 0 && dy == 0)
 | ||
|     return;
 | ||
| 
 | ||
|   if (window->destroyed)
 | ||
|     return;
 | ||
| 
 | ||
|   /* First move all child windows, without causing invalidation */
 | ||
| 
 | ||
|   tmp_list = window->children;
 | ||
|   while (tmp_list)
 | ||
|     {
 | ||
|       GdkWindow *child = GDK_WINDOW (tmp_list->data);
 | ||
| 
 | ||
|       /* Just update the positions, the bits will move with the copy */
 | ||
|       child->x += dx;
 | ||
|       child->y += dy;
 | ||
| 
 | ||
|       tmp_list = tmp_list->next;
 | ||
|     }
 | ||
| 
 | ||
|   recompute_visible_regions (window, TRUE);
 | ||
| 
 | ||
|   move_native_children (window);
 | ||
| 
 | ||
|   gdk_window_invalidate_rect_full (window, NULL, TRUE);
 | ||
| 
 | ||
|   _gdk_synthesize_crossing_events_for_geometry_change (window);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_move_region:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @region: The #cairo_region_t to move
 | ||
|  * @dx: Amount to move in the X direction
 | ||
|  * @dy: Amount to move in the Y direction
 | ||
|  *
 | ||
|  * Move the part of @window indicated by @region by @dy pixels in the Y
 | ||
|  * direction and @dx pixels in the X direction. The portions of @region
 | ||
|  * that not covered by the new position of @region are invalidated.
 | ||
|  *
 | ||
|  * Child windows are not moved.
 | ||
|  *
 | ||
|  * Since: 2.8
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_move_region (GdkWindow            *window,
 | ||
|                         const cairo_region_t *region,
 | ||
|                         gint                  dx,
 | ||
|                         gint                  dy)
 | ||
| {
 | ||
|   cairo_region_t *expose_area;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
|   g_return_if_fail (region != NULL);
 | ||
| 
 | ||
|   if (dx == 0 && dy == 0)
 | ||
|     return;
 | ||
| 
 | ||
|   if (window->destroyed)
 | ||
|     return;
 | ||
| 
 | ||
|   expose_area = cairo_region_copy (region);
 | ||
|   cairo_region_translate (expose_area, dx, dy);
 | ||
|   cairo_region_union (expose_area, region);
 | ||
| 
 | ||
|   gdk_window_invalidate_region_full (window, expose_area, FALSE);
 | ||
|   cairo_region_destroy (expose_area);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_background:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @color: a #GdkColor
 | ||
|  *
 | ||
|  * Sets the background color of @window.
 | ||
|  *
 | ||
|  * However, when using GTK+, influence the background of a widget
 | ||
|  * using a style class or CSS — if you’re an application — or with
 | ||
|  * gtk_style_context_set_background() — if you're implementing a
 | ||
|  * custom widget.
 | ||
|  *
 | ||
|  * Deprecated: 3.4: Don't use this function
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_set_background (GdkWindow      *window,
 | ||
| 			   const GdkColor *color)
 | ||
| {
 | ||
|   cairo_pattern_t *pattern;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   pattern = cairo_pattern_create_rgb (color->red   / 65535.,
 | ||
|                                       color->green / 65535.,
 | ||
|                                       color->blue  / 65535.);
 | ||
| 
 | ||
| G_GNUC_BEGIN_IGNORE_DEPRECATIONS
 | ||
|   gdk_window_set_background_pattern (window, pattern);
 | ||
| G_GNUC_END_IGNORE_DEPRECATIONS
 | ||
| 
 | ||
|   cairo_pattern_destroy (pattern);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_background_rgba:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @rgba: a #GdkRGBA color
 | ||
|  *
 | ||
|  * Sets the background color of @window.
 | ||
|  *
 | ||
|  * See also gdk_window_set_background_pattern().
 | ||
|  *
 | ||
|  * Deprecated: 3.22: Don't use this function
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_set_background_rgba (GdkWindow     *window,
 | ||
|                                 const GdkRGBA *rgba)
 | ||
| {
 | ||
|   cairo_pattern_t *pattern;
 | ||
|   GdkRGBA prev_rgba;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
|   g_return_if_fail (rgba != NULL);
 | ||
| 
 | ||
|   /*
 | ||
|    * If the new RGBA matches the previous pattern, ignore the change so that
 | ||
|    * we do not invalidate the window contents.
 | ||
|    */
 | ||
|   if ((window->background != NULL) &&
 | ||
|       (cairo_pattern_get_type (window->background) == CAIRO_PATTERN_TYPE_SOLID) &&
 | ||
|       (cairo_pattern_get_rgba (window->background,
 | ||
|                                &prev_rgba.red,
 | ||
|                                &prev_rgba.green,
 | ||
|                                &prev_rgba.blue,
 | ||
|                                &prev_rgba.alpha) == CAIRO_STATUS_SUCCESS) &&
 | ||
|       gdk_rgba_equal (&prev_rgba, rgba))
 | ||
|     return;
 | ||
| 
 | ||
|   pattern = cairo_pattern_create_rgba (rgba->red, rgba->green,
 | ||
|                                        rgba->blue, rgba->alpha);
 | ||
| 
 | ||
| G_GNUC_BEGIN_IGNORE_DEPRECATIONS
 | ||
|   gdk_window_set_background_pattern (window, pattern);
 | ||
| G_GNUC_END_IGNORE_DEPRECATIONS
 | ||
| 
 | ||
|   cairo_pattern_destroy (pattern);
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_background_pattern:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @pattern: (allow-none): a pattern to use, or %NULL
 | ||
|  *
 | ||
|  * Sets the background of @window.
 | ||
|  *
 | ||
|  * A background of %NULL means that the window won't have any background. On the
 | ||
|  * X11 backend it's also possible to inherit the background from the parent
 | ||
|  * window using gdk_x11_get_parent_relative_pattern().
 | ||
|  *
 | ||
|  * The windowing system will normally fill a window with its background
 | ||
|  * when the window is obscured then exposed.
 | ||
|  *
 | ||
|  * Deprecated: 3.22: Don't use this function
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_set_background_pattern (GdkWindow       *window,
 | ||
|                                    cairo_pattern_t *pattern)
 | ||
| {
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   if (window->input_only)
 | ||
|     return;
 | ||
| 
 | ||
|   if (pattern)
 | ||
|     cairo_pattern_reference (pattern);
 | ||
|   if (window->background)
 | ||
|     cairo_pattern_destroy (window->background);
 | ||
|   window->background = pattern;
 | ||
| 
 | ||
|   if (gdk_window_has_impl (window))
 | ||
|     {
 | ||
|       GdkWindowImplClass *impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
|       impl_class->set_background (window, pattern);
 | ||
|     }
 | ||
|   else
 | ||
|     gdk_window_invalidate_rect_full (window, NULL, TRUE);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_background_pattern:
 | ||
|  * @window: a window
 | ||
|  *
 | ||
|  * Gets the pattern used to clear the background on @window.
 | ||
|  *
 | ||
|  * Returns: (nullable) (transfer none): The pattern to use for the
 | ||
|  * background or %NULL if there is no background.
 | ||
|  *
 | ||
|  * Since: 2.22
 | ||
|  *
 | ||
|  * Deprecated: 3.22: Don't use this function
 | ||
|  **/
 | ||
| cairo_pattern_t *
 | ||
| gdk_window_get_background_pattern (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 | ||
| 
 | ||
|   return window->background;
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_set_cursor_internal (GdkWindow *window,
 | ||
|                                 GdkDevice *device,
 | ||
|                                 GdkCursor *cursor)
 | ||
| {
 | ||
|   if (GDK_WINDOW_DESTROYED (window))
 | ||
|     return;
 | ||
| 
 | ||
|   g_assert (gdk_window_get_display (window) == gdk_device_get_display (device));
 | ||
|   g_assert (!cursor || gdk_window_get_display (window) == gdk_cursor_get_display (cursor));
 | ||
| 
 | ||
|   if (window->window_type == GDK_WINDOW_ROOT ||
 | ||
|       window->window_type == GDK_WINDOW_FOREIGN)
 | ||
|     GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_device_cursor (window, device, cursor);
 | ||
|   else
 | ||
|     {
 | ||
|       GdkPointerWindowInfo *pointer_info;
 | ||
|       GdkDisplay *display;
 | ||
| 
 | ||
|       display = gdk_window_get_display (window);
 | ||
|       pointer_info = _gdk_display_get_pointer_info (display, device);
 | ||
| 
 | ||
|       if (_gdk_window_event_parent_of (window, pointer_info->window_under_pointer))
 | ||
|         update_cursor (display, device);
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_cursor:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Retrieves a #GdkCursor pointer for the cursor currently set on the
 | ||
|  * specified #GdkWindow, or %NULL.  If the return value is %NULL then
 | ||
|  * there is no custom cursor set on the specified window, and it is
 | ||
|  * using the cursor for its parent window.
 | ||
|  *
 | ||
|  * Returns: (nullable) (transfer none): a #GdkCursor, or %NULL. The
 | ||
|  *   returned object is owned by the #GdkWindow and should not be
 | ||
|  *   unreferenced directly. Use gdk_window_set_cursor() to unset the
 | ||
|  *   cursor of the window
 | ||
|  *
 | ||
|  * Since: 2.18
 | ||
|  */
 | ||
| GdkCursor *
 | ||
| gdk_window_get_cursor (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 | ||
| 
 | ||
|   return window->cursor;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_cursor:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @cursor: (allow-none): a cursor
 | ||
|  *
 | ||
|  * Sets the default mouse pointer for a #GdkWindow.
 | ||
|  *
 | ||
|  * Note that @cursor must be for the same display as @window.
 | ||
|  *
 | ||
|  * Use gdk_cursor_new_for_display() or gdk_cursor_new_from_pixbuf() to
 | ||
|  * create the cursor. To make the cursor invisible, use %GDK_BLANK_CURSOR.
 | ||
|  * Passing %NULL for the @cursor argument to gdk_window_set_cursor() means
 | ||
|  * that @window will use the cursor of its parent window. Most windows
 | ||
|  * should use this default.
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_set_cursor (GdkWindow *window,
 | ||
| 		       GdkCursor *cursor)
 | ||
| {
 | ||
|   GdkDisplay *display;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   display = gdk_window_get_display (window);
 | ||
| 
 | ||
|   if (window->cursor)
 | ||
|     {
 | ||
|       g_object_unref (window->cursor);
 | ||
|       window->cursor = NULL;
 | ||
|     }
 | ||
| 
 | ||
|   if (!GDK_WINDOW_DESTROYED (window))
 | ||
|     {
 | ||
|       GdkDevice *device;
 | ||
|       GList *seats, *s;
 | ||
| 
 | ||
|       if (cursor)
 | ||
| 	window->cursor = g_object_ref (cursor);
 | ||
| 
 | ||
|       seats = gdk_display_list_seats (display);
 | ||
| 
 | ||
|       for (s = seats; s; s = s->next)
 | ||
|         {
 | ||
|           GList *devices, *d;
 | ||
| 
 | ||
|           device = gdk_seat_get_pointer (s->data);
 | ||
|           gdk_window_set_cursor_internal (window, device, window->cursor);
 | ||
| 
 | ||
|           devices = gdk_seat_get_slaves (s->data, GDK_SEAT_CAPABILITY_TABLET_STYLUS);
 | ||
|           for (d = devices; d; d = d->next)
 | ||
|             {
 | ||
|               device = gdk_device_get_associated_device (d->data);
 | ||
|               gdk_window_set_cursor_internal (window, device, window->cursor);
 | ||
|             }
 | ||
|           g_list_free (devices);
 | ||
|         }
 | ||
| 
 | ||
|       g_list_free (seats);
 | ||
|       g_object_notify_by_pspec (G_OBJECT (window), properties[PROP_CURSOR]);
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_device_cursor:
 | ||
|  * @window: a #GdkWindow.
 | ||
|  * @device: a master, pointer #GdkDevice.
 | ||
|  *
 | ||
|  * Retrieves a #GdkCursor pointer for the @device currently set on the
 | ||
|  * specified #GdkWindow, or %NULL.  If the return value is %NULL then
 | ||
|  * there is no custom cursor set on the specified window, and it is
 | ||
|  * using the cursor for its parent window.
 | ||
|  *
 | ||
|  * Returns: (nullable) (transfer none): a #GdkCursor, or %NULL. The
 | ||
|  *   returned object is owned by the #GdkWindow and should not be
 | ||
|  *   unreferenced directly. Use gdk_window_set_cursor() to unset the
 | ||
|  *   cursor of the window
 | ||
|  *
 | ||
|  * Since: 3.0
 | ||
|  **/
 | ||
| GdkCursor *
 | ||
| gdk_window_get_device_cursor (GdkWindow *window,
 | ||
|                               GdkDevice *device)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 | ||
|   g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
 | ||
|   g_return_val_if_fail (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD, NULL);
 | ||
|   g_return_val_if_fail (gdk_device_get_device_type (device) == GDK_DEVICE_TYPE_MASTER, NULL);
 | ||
| 
 | ||
|   return g_hash_table_lookup (window->device_cursor, device);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_device_cursor:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @device: a master, pointer #GdkDevice
 | ||
|  * @cursor: a #GdkCursor
 | ||
|  *
 | ||
|  * Sets a specific #GdkCursor for a given device when it gets inside @window.
 | ||
|  * Use gdk_cursor_new_for_display() or gdk_cursor_new_from_pixbuf() to create
 | ||
|  * the cursor. To make the cursor invisible, use %GDK_BLANK_CURSOR. Passing
 | ||
|  * %NULL for the @cursor argument to gdk_window_set_cursor() means that
 | ||
|  * @window will use the cursor of its parent window. Most windows should
 | ||
|  * use this default.
 | ||
|  *
 | ||
|  * Since: 3.0
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_set_device_cursor (GdkWindow *window,
 | ||
|                               GdkDevice *device,
 | ||
|                               GdkCursor *cursor)
 | ||
| {
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
|   g_return_if_fail (GDK_IS_DEVICE (device));
 | ||
|   g_return_if_fail (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD);
 | ||
|   g_return_if_fail (gdk_device_get_device_type (device) == GDK_DEVICE_TYPE_MASTER);
 | ||
| 
 | ||
|   if (!cursor)
 | ||
|     g_hash_table_remove (window->device_cursor, device);
 | ||
|   else
 | ||
|     g_hash_table_replace (window->device_cursor, device, g_object_ref (cursor));
 | ||
| 
 | ||
|   gdk_window_set_cursor_internal (window, device, cursor);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_geometry:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @x: (out) (allow-none): return location for X coordinate of window (relative to its parent)
 | ||
|  * @y: (out) (allow-none): return location for Y coordinate of window (relative to its parent)
 | ||
|  * @width: (out) (allow-none): return location for width of window
 | ||
|  * @height: (out) (allow-none): return location for height of window
 | ||
|  *
 | ||
|  * Any of the return location arguments to this function may be %NULL,
 | ||
|  * if you aren’t interested in getting the value of that field.
 | ||
|  *
 | ||
|  * The X and Y coordinates returned are relative to the parent window
 | ||
|  * of @window, which for toplevels usually means relative to the
 | ||
|  * window decorations (titlebar, etc.) rather than relative to the
 | ||
|  * root window (screen-size background window).
 | ||
|  *
 | ||
|  * On the X11 platform, the geometry is obtained from the X server,
 | ||
|  * so reflects the latest position of @window; this may be out-of-sync
 | ||
|  * with the position of @window delivered in the most-recently-processed
 | ||
|  * #GdkEventConfigure. gdk_window_get_position() in contrast gets the
 | ||
|  * position from the most recent configure event.
 | ||
|  *
 | ||
|  * Note: If @window is not a toplevel, it is much better
 | ||
|  * to call gdk_window_get_position(), gdk_window_get_width() and
 | ||
|  * gdk_window_get_height() instead, because it avoids the roundtrip to
 | ||
|  * the X server and because these functions support the full 32-bit
 | ||
|  * coordinate space, whereas gdk_window_get_geometry() is restricted to
 | ||
|  * the 16-bit coordinates of X11.
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_get_geometry (GdkWindow *window,
 | ||
| 			 gint      *x,
 | ||
| 			 gint      *y,
 | ||
| 			 gint      *width,
 | ||
| 			 gint      *height)
 | ||
| {
 | ||
|   GdkWindow *parent;
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
| 
 | ||
|   if (!window)
 | ||
|     window = gdk_screen_get_root_window ((gdk_screen_get_default ()));
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   if (!GDK_WINDOW_DESTROYED (window))
 | ||
|     {
 | ||
|       if (gdk_window_has_impl (window))
 | ||
| 	{
 | ||
| 	  impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
| 	  impl_class->get_geometry (window, x, y,
 | ||
| 				    width, height);
 | ||
| 	  /* This reports the position wrt to the native parent, we need to convert
 | ||
| 	     it to be relative to the client side parent */
 | ||
| 	  parent = window->parent;
 | ||
| 	  if (parent && !gdk_window_has_impl (parent))
 | ||
| 	    {
 | ||
| 	      if (x)
 | ||
| 		*x -= parent->abs_x;
 | ||
| 	      if (y)
 | ||
| 		*y -= parent->abs_y;
 | ||
| 	    }
 | ||
| 	}
 | ||
|       else
 | ||
| 	{
 | ||
|           if (x)
 | ||
|             *x = window->x;
 | ||
|           if (y)
 | ||
|             *y = window->y;
 | ||
| 	  if (width)
 | ||
| 	    *width = window->width;
 | ||
| 	  if (height)
 | ||
| 	    *height = window->height;
 | ||
| 	}
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_width:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Returns the width of the given @window.
 | ||
|  *
 | ||
|  * On the X11 platform the returned size is the size reported in the
 | ||
|  * most-recently-processed configure event, rather than the current
 | ||
|  * size on the X server.
 | ||
|  *
 | ||
|  * Returns: The width of @window
 | ||
|  *
 | ||
|  * Since: 2.24
 | ||
|  */
 | ||
| int
 | ||
| gdk_window_get_width (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
 | ||
| 
 | ||
|   return window->width;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_height:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Returns the height of the given @window.
 | ||
|  *
 | ||
|  * On the X11 platform the returned size is the size reported in the
 | ||
|  * most-recently-processed configure event, rather than the current
 | ||
|  * size on the X server.
 | ||
|  *
 | ||
|  * Returns: The height of @window
 | ||
|  *
 | ||
|  * Since: 2.24
 | ||
|  */
 | ||
| int
 | ||
| gdk_window_get_height (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
 | ||
| 
 | ||
|   return window->height;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_origin:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @x: (out) (allow-none): return location for X coordinate
 | ||
|  * @y: (out) (allow-none): return location for Y coordinate
 | ||
|  *
 | ||
|  * Obtains the position of a window in root window coordinates.
 | ||
|  * (Compare with gdk_window_get_position() and
 | ||
|  * gdk_window_get_geometry() which return the position of a window
 | ||
|  * relative to its parent window.)
 | ||
|  *
 | ||
|  * Returns: not meaningful, ignore
 | ||
|  */
 | ||
| gint
 | ||
| gdk_window_get_origin (GdkWindow *window,
 | ||
| 		       gint      *x,
 | ||
| 		       gint      *y)
 | ||
| {
 | ||
|   gint dummy_x, dummy_y;
 | ||
| 
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
 | ||
| 
 | ||
|   gdk_window_get_root_coords (window,
 | ||
|                               0, 0,
 | ||
|                               x ? x : &dummy_x,
 | ||
|                               y ? y : &dummy_y);
 | ||
| 
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_root_coords:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @x: X coordinate in window
 | ||
|  * @y: Y coordinate in window
 | ||
|  * @root_x: (out): return location for X coordinate
 | ||
|  * @root_y: (out): return location for Y coordinate
 | ||
|  *
 | ||
|  * Obtains the position of a window position in root
 | ||
|  * window coordinates. This is similar to
 | ||
|  * gdk_window_get_origin() but allows you to pass
 | ||
|  * in any position in the window, not just the origin.
 | ||
|  *
 | ||
|  * Since: 2.18
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_get_root_coords (GdkWindow *window,
 | ||
| 			    gint       x,
 | ||
| 			    gint       y,
 | ||
| 			    gint      *root_x,
 | ||
| 			    gint      *root_y)
 | ||
| {
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   if (GDK_WINDOW_DESTROYED (window))
 | ||
|     {
 | ||
|       *root_x = 0;
 | ||
|       *root_y = 0;
 | ||
|       return;
 | ||
|     }
 | ||
|   
 | ||
|   impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
|   impl_class->get_root_coords (window->impl_window,
 | ||
| 			       x + window->abs_x,
 | ||
| 			       y + window->abs_y,
 | ||
| 			       root_x, root_y);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_coords_to_parent:
 | ||
|  * @window: a child window
 | ||
|  * @x: X coordinate in child’s coordinate system
 | ||
|  * @y: Y coordinate in child’s coordinate system
 | ||
|  * @parent_x: (out) (allow-none): return location for X coordinate
 | ||
|  * in parent’s coordinate system, or %NULL
 | ||
|  * @parent_y: (out) (allow-none): return location for Y coordinate
 | ||
|  * in parent’s coordinate system, or %NULL
 | ||
|  *
 | ||
|  * Transforms window coordinates from a child window to its parent
 | ||
|  * window, where the parent window is the normal parent as returned by
 | ||
|  * gdk_window_get_parent() for normal windows, and the window's
 | ||
|  * embedder as returned by gdk_offscreen_window_get_embedder() for
 | ||
|  * offscreen windows.
 | ||
|  *
 | ||
|  * For normal windows, calling this function is equivalent to adding
 | ||
|  * the return values of gdk_window_get_position() to the child coordinates.
 | ||
|  * For offscreen windows however (which can be arbitrarily transformed),
 | ||
|  * this function calls the GdkWindow::to-embedder: signal to translate
 | ||
|  * the coordinates.
 | ||
|  *
 | ||
|  * You should always use this function when writing generic code that
 | ||
|  * walks up a window hierarchy.
 | ||
|  *
 | ||
|  * See also: gdk_window_coords_from_parent()
 | ||
|  *
 | ||
|  * Since: 2.22
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_coords_to_parent (GdkWindow *window,
 | ||
|                              gdouble    x,
 | ||
|                              gdouble    y,
 | ||
|                              gdouble   *parent_x,
 | ||
|                              gdouble   *parent_y)
 | ||
| {
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   if (gdk_window_is_offscreen (window))
 | ||
|     {
 | ||
|       gdouble px, py;
 | ||
| 
 | ||
|       to_embedder (window, x, y, &px, &py);
 | ||
| 
 | ||
|       if (parent_x)
 | ||
|         *parent_x = px;
 | ||
| 
 | ||
|       if (parent_y)
 | ||
|         *parent_y = py;
 | ||
|     }
 | ||
|   else
 | ||
|     {
 | ||
|       if (parent_x)
 | ||
|         *parent_x = x + window->x;
 | ||
| 
 | ||
|       if (parent_y)
 | ||
|         *parent_y = y + window->y;
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_coords_from_parent:
 | ||
|  * @window: a child window
 | ||
|  * @parent_x: X coordinate in parent’s coordinate system
 | ||
|  * @parent_y: Y coordinate in parent’s coordinate system
 | ||
|  * @x: (out) (allow-none): return location for X coordinate in child’s coordinate system
 | ||
|  * @y: (out) (allow-none): return location for Y coordinate in child’s coordinate system
 | ||
|  *
 | ||
|  * Transforms window coordinates from a parent window to a child
 | ||
|  * window, where the parent window is the normal parent as returned by
 | ||
|  * gdk_window_get_parent() for normal windows, and the window's
 | ||
|  * embedder as returned by gdk_offscreen_window_get_embedder() for
 | ||
|  * offscreen windows.
 | ||
|  *
 | ||
|  * For normal windows, calling this function is equivalent to subtracting
 | ||
|  * the return values of gdk_window_get_position() from the parent coordinates.
 | ||
|  * For offscreen windows however (which can be arbitrarily transformed),
 | ||
|  * this function calls the GdkWindow::from-embedder: signal to translate
 | ||
|  * the coordinates.
 | ||
|  *
 | ||
|  * You should always use this function when writing generic code that
 | ||
|  * walks down a window hierarchy.
 | ||
|  *
 | ||
|  * See also: gdk_window_coords_to_parent()
 | ||
|  *
 | ||
|  * Since: 2.22
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_coords_from_parent (GdkWindow *window,
 | ||
|                                gdouble    parent_x,
 | ||
|                                gdouble    parent_y,
 | ||
|                                gdouble   *x,
 | ||
|                                gdouble   *y)
 | ||
| {
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   if (gdk_window_is_offscreen (window))
 | ||
|     {
 | ||
|       gdouble cx, cy;
 | ||
| 
 | ||
|       from_embedder (window, parent_x, parent_y, &cx, &cy);
 | ||
| 
 | ||
|       if (x)
 | ||
|         *x = cx;
 | ||
| 
 | ||
|       if (y)
 | ||
|         *y = cy;
 | ||
|     }
 | ||
|   else
 | ||
|     {
 | ||
|       if (x)
 | ||
|         *x = parent_x - window->x;
 | ||
| 
 | ||
|       if (y)
 | ||
|         *y = parent_y - window->y;
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_shape_combine_region:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @shape_region: (allow-none): region of window to be non-transparent
 | ||
|  * @offset_x: X position of @shape_region in @window coordinates
 | ||
|  * @offset_y: Y position of @shape_region in @window coordinates
 | ||
|  *
 | ||
|  * Makes pixels in @window outside @shape_region be transparent,
 | ||
|  * so that the window may be nonrectangular.
 | ||
|  *
 | ||
|  * If @shape_region is %NULL, the shape will be unset, so the whole
 | ||
|  * window will be opaque again. @offset_x and @offset_y are ignored
 | ||
|  * if @shape_region is %NULL.
 | ||
|  *
 | ||
|  * On the X11 platform, this uses an X server extension which is
 | ||
|  * widely available on most common platforms, but not available on
 | ||
|  * very old X servers, and occasionally the implementation will be
 | ||
|  * buggy. On servers without the shape extension, this function
 | ||
|  * will do nothing.
 | ||
|  *
 | ||
|  * This function works on both toplevel and child windows.
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_shape_combine_region (GdkWindow       *window,
 | ||
| 				 const cairo_region_t *shape_region,
 | ||
| 				 gint             offset_x,
 | ||
| 				 gint             offset_y)
 | ||
| {
 | ||
|   cairo_region_t *old_region, *new_region, *diff;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   if (GDK_WINDOW_DESTROYED (window))
 | ||
|     return;
 | ||
| 
 | ||
|   if (!window->shape && shape_region == NULL)
 | ||
|     return;
 | ||
| 
 | ||
|   window->shaped = (shape_region != NULL);
 | ||
| 
 | ||
|   if (window->shape)
 | ||
|     cairo_region_destroy (window->shape);
 | ||
| 
 | ||
|   old_region = NULL;
 | ||
|   if (GDK_WINDOW_IS_MAPPED (window))
 | ||
|     old_region = cairo_region_copy (window->clip_region);
 | ||
| 
 | ||
|   if (shape_region)
 | ||
|     {
 | ||
|       window->shape = cairo_region_copy (shape_region);
 | ||
|       cairo_region_translate (window->shape, offset_x, offset_y);
 | ||
|     }
 | ||
|   else
 | ||
|     window->shape = NULL;
 | ||
| 
 | ||
|   recompute_visible_regions (window, FALSE);
 | ||
| 
 | ||
|   if (old_region)
 | ||
|     {
 | ||
|       new_region = cairo_region_copy (window->clip_region);
 | ||
| 
 | ||
|       /* New area in the window, needs invalidation */
 | ||
|       diff = cairo_region_copy (new_region);
 | ||
|       cairo_region_subtract (diff, old_region);
 | ||
| 
 | ||
|       gdk_window_invalidate_region_full (window, diff, TRUE);
 | ||
| 
 | ||
|       cairo_region_destroy (diff);
 | ||
| 
 | ||
|       if (!gdk_window_is_toplevel (window))
 | ||
| 	{
 | ||
| 	  /* New area in the non-root parent window, needs invalidation */
 | ||
| 	  diff = cairo_region_copy (old_region);
 | ||
| 	  cairo_region_subtract (diff, new_region);
 | ||
| 
 | ||
| 	  /* Adjust region to parent window coords */
 | ||
| 	  cairo_region_translate (diff, window->x, window->y);
 | ||
| 
 | ||
| 	  gdk_window_invalidate_region_full (window->parent, diff, TRUE);
 | ||
| 
 | ||
| 	  cairo_region_destroy (diff);
 | ||
| 	}
 | ||
| 
 | ||
|       cairo_region_destroy (new_region);
 | ||
|       cairo_region_destroy (old_region);
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| do_child_shapes (GdkWindow *window,
 | ||
| 		 gboolean merge)
 | ||
| {
 | ||
|   GdkRectangle r;
 | ||
|   cairo_region_t *region;
 | ||
| 
 | ||
|   r.x = 0;
 | ||
|   r.y = 0;
 | ||
|   r.width = window->width;
 | ||
|   r.height = window->height;
 | ||
| 
 | ||
|   region = cairo_region_create_rectangle (&r);
 | ||
|   remove_child_area (window, FALSE, region);
 | ||
| 
 | ||
|   if (merge && window->shape)
 | ||
|     cairo_region_subtract (region, window->shape);
 | ||
| 
 | ||
|   cairo_region_xor_rectangle (region, &r);
 | ||
| 
 | ||
|   gdk_window_shape_combine_region (window, region, 0, 0);
 | ||
| 
 | ||
|   cairo_region_destroy (region);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_child_shapes:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Sets the shape mask of @window to the union of shape masks
 | ||
|  * for all children of @window, ignoring the shape mask of @window
 | ||
|  * itself. Contrast with gdk_window_merge_child_shapes() which includes
 | ||
|  * the shape mask of @window in the masks to be merged.
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_set_child_shapes (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   do_child_shapes (window, FALSE);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_merge_child_shapes:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Merges the shape masks for any child windows into the
 | ||
|  * shape mask for @window. i.e. the union of all masks
 | ||
|  * for @window and its children will become the new mask
 | ||
|  * for @window. See gdk_window_shape_combine_region().
 | ||
|  *
 | ||
|  * This function is distinct from gdk_window_set_child_shapes()
 | ||
|  * because it includes @window’s shape mask in the set of shapes to
 | ||
|  * be merged.
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_merge_child_shapes (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   do_child_shapes (window, TRUE);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_input_shape_combine_region:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @shape_region: region of window to be non-transparent
 | ||
|  * @offset_x: X position of @shape_region in @window coordinates
 | ||
|  * @offset_y: Y position of @shape_region in @window coordinates
 | ||
|  *
 | ||
|  * Like gdk_window_shape_combine_region(), but the shape applies
 | ||
|  * only to event handling. Mouse events which happen while
 | ||
|  * the pointer position corresponds to an unset bit in the
 | ||
|  * mask will be passed on the window below @window.
 | ||
|  *
 | ||
|  * An input shape is typically used with RGBA windows.
 | ||
|  * The alpha channel of the window defines which pixels are
 | ||
|  * invisible and allows for nicely antialiased borders,
 | ||
|  * and the input shape controls where the window is
 | ||
|  * “clickable”.
 | ||
|  *
 | ||
|  * On the X11 platform, this requires version 1.1 of the
 | ||
|  * shape extension.
 | ||
|  *
 | ||
|  * On the Win32 platform, this functionality is not present and the
 | ||
|  * function does nothing.
 | ||
|  *
 | ||
|  * Since: 2.10
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_input_shape_combine_region (GdkWindow       *window,
 | ||
| 				       const cairo_region_t *shape_region,
 | ||
| 				       gint             offset_x,
 | ||
| 				       gint             offset_y)
 | ||
| {
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   if (GDK_WINDOW_DESTROYED (window))
 | ||
|     return;
 | ||
| 
 | ||
|   if (window->input_shape)
 | ||
|     cairo_region_destroy (window->input_shape);
 | ||
| 
 | ||
|   if (shape_region)
 | ||
|     {
 | ||
|       window->input_shape = cairo_region_copy (shape_region);
 | ||
|       cairo_region_translate (window->input_shape, offset_x, offset_y);
 | ||
|     }
 | ||
|   else
 | ||
|     window->input_shape = NULL;
 | ||
| 
 | ||
|   if (gdk_window_has_impl (window))
 | ||
|     {
 | ||
|       impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
|       impl_class->input_shape_combine_region (window, window->input_shape, 0, 0);
 | ||
|     }
 | ||
| 
 | ||
|   /* Pointer may have e.g. moved outside window due to the input mask change */
 | ||
|   _gdk_synthesize_crossing_events_for_geometry_change (window);
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| do_child_input_shapes (GdkWindow *window,
 | ||
| 		       gboolean merge)
 | ||
| {
 | ||
|   GdkRectangle r;
 | ||
|   cairo_region_t *region;
 | ||
| 
 | ||
|   r.x = 0;
 | ||
|   r.y = 0;
 | ||
|   r.width = window->width;
 | ||
|   r.height = window->height;
 | ||
| 
 | ||
|   region = cairo_region_create_rectangle (&r);
 | ||
|   remove_child_area (window, TRUE, region);
 | ||
| 
 | ||
|   if (merge && window->shape)
 | ||
|     cairo_region_subtract (region, window->shape);
 | ||
|   if (merge && window->input_shape)
 | ||
|     cairo_region_subtract (region, window->input_shape);
 | ||
| 
 | ||
|   cairo_region_xor_rectangle (region, &r);
 | ||
| 
 | ||
|   gdk_window_input_shape_combine_region (window, region, 0, 0);
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_child_input_shapes:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Sets the input shape mask of @window to the union of input shape masks
 | ||
|  * for all children of @window, ignoring the input shape mask of @window
 | ||
|  * itself. Contrast with gdk_window_merge_child_input_shapes() which includes
 | ||
|  * the input shape mask of @window in the masks to be merged.
 | ||
|  *
 | ||
|  * Since: 2.10
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_set_child_input_shapes (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   do_child_input_shapes (window, FALSE);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_pass_through:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @pass_through: a boolean
 | ||
|  *
 | ||
|  * Sets whether input to the window is passed through to the window
 | ||
|  * below.
 | ||
|  *
 | ||
|  * The default value of this is %FALSE, which means that pointer
 | ||
|  * events that happen inside the window are send first to the window,
 | ||
|  * but if the event is not selected by the event mask then the event
 | ||
|  * is sent to the parent window, and so on up the hierarchy.
 | ||
|  *
 | ||
|  * If @pass_through is %TRUE then such pointer events happen as if the
 | ||
|  * window wasn't there at all, and thus will be sent first to any
 | ||
|  * windows below @window. This is useful if the window is used in a
 | ||
|  * transparent fashion. In the terminology of the web this would be called
 | ||
|  * "pointer-events: none".
 | ||
|  *
 | ||
|  * Note that a window with @pass_through %TRUE can still have a subwindow
 | ||
|  * without pass through, so you can get events on a subset of a window. And in
 | ||
|  * that cases you would get the in-between related events such as the pointer
 | ||
|  * enter/leave events on its way to the destination window.
 | ||
|  *
 | ||
|  * Since: 3.18
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_set_pass_through (GdkWindow *window,
 | ||
|                              gboolean   pass_through)
 | ||
| {
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   window->pass_through = !!pass_through;
 | ||
| 
 | ||
|   /* Pointer may have e.g. moved outside window due to the input region change */
 | ||
|   _gdk_synthesize_crossing_events_for_geometry_change (window);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_pass_through:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Returns whether input to the window is passed through to the window
 | ||
|  * below.
 | ||
|  *
 | ||
|  * See gdk_window_set_pass_through() for details
 | ||
|  *
 | ||
|  * Since: 3.18
 | ||
|  **/
 | ||
| gboolean
 | ||
| gdk_window_get_pass_through (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 | ||
| 
 | ||
|   return window->pass_through;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_merge_child_input_shapes:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Merges the input shape masks for any child windows into the
 | ||
|  * input shape mask for @window. i.e. the union of all input masks
 | ||
|  * for @window and its children will become the new input mask
 | ||
|  * for @window. See gdk_window_input_shape_combine_region().
 | ||
|  *
 | ||
|  * This function is distinct from gdk_window_set_child_input_shapes()
 | ||
|  * because it includes @window’s input shape mask in the set of
 | ||
|  * shapes to be merged.
 | ||
|  *
 | ||
|  * Since: 2.10
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_merge_child_input_shapes (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   do_child_input_shapes (window, TRUE);
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_static_gravities:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @use_static: %TRUE to turn on static gravity
 | ||
|  *
 | ||
|  * Used to set the bit gravity of the given window to static, and flag
 | ||
|  * it so all children get static subwindow gravity. This is used if you
 | ||
|  * are implementing scary features that involve deep knowledge of the
 | ||
|  * windowing system. Don’t worry about it.
 | ||
|  *
 | ||
|  * Returns: %FALSE
 | ||
|  *
 | ||
|  * Deprecated: 3.16: static gravities haven't worked on anything but X11
 | ||
|  *   for a long time.
 | ||
|  */
 | ||
| gboolean
 | ||
| gdk_window_set_static_gravities (GdkWindow *window,
 | ||
| 				 gboolean   use_static)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 | ||
| 
 | ||
|   return FALSE;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_composited:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Determines whether @window is composited.
 | ||
|  *
 | ||
|  * See gdk_window_set_composited().
 | ||
|  *
 | ||
|  * Returns: %TRUE if the window is composited.
 | ||
|  *
 | ||
|  * Since: 2.22
 | ||
|  *
 | ||
|  * Deprecated: 3.16: Compositing is an outdated technology that
 | ||
|  *   only ever worked on X11.
 | ||
|  **/
 | ||
| gboolean
 | ||
| gdk_window_get_composited (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 | ||
| 
 | ||
|   return window->composited;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_composited:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @composited: %TRUE to set the window as composited
 | ||
|  *
 | ||
|  * Sets a #GdkWindow as composited, or unsets it. Composited
 | ||
|  * windows do not automatically have their contents drawn to
 | ||
|  * the screen. Drawing is redirected to an offscreen buffer
 | ||
|  * and an expose event is emitted on the parent of the composited
 | ||
|  * window. It is the responsibility of the parent’s expose handler
 | ||
|  * to manually merge the off-screen content onto the screen in
 | ||
|  * whatever way it sees fit.
 | ||
|  *
 | ||
|  * It only makes sense for child windows to be composited; see
 | ||
|  * gdk_window_set_opacity() if you need translucent toplevel
 | ||
|  * windows.
 | ||
|  *
 | ||
|  * An additional effect of this call is that the area of this
 | ||
|  * window is no longer clipped from regions marked for
 | ||
|  * invalidation on its parent. Draws done on the parent
 | ||
|  * window are also no longer clipped by the child.
 | ||
|  *
 | ||
|  * This call is only supported on some systems (currently,
 | ||
|  * only X11 with new enough Xcomposite and Xdamage extensions).
 | ||
|  * You must call gdk_display_supports_composite() to check if
 | ||
|  * setting a window as composited is supported before
 | ||
|  * attempting to do so.
 | ||
|  *
 | ||
|  * Since: 2.12
 | ||
|  *
 | ||
|  * Deprecated: 3.16: Compositing is an outdated technology that
 | ||
|  *   only ever worked on X11.
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_set_composited (GdkWindow *window,
 | ||
| 			   gboolean   composited)
 | ||
| {
 | ||
|   GdkDisplay *display;
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   composited = composited != FALSE;
 | ||
| 
 | ||
|   if (window->composited == composited)
 | ||
|     return;
 | ||
| 
 | ||
|   if (composited)
 | ||
|     gdk_window_ensure_native (window);
 | ||
| 
 | ||
|   display = gdk_window_get_display (window);
 | ||
| 
 | ||
|   impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
| 
 | ||
| G_GNUC_BEGIN_IGNORE_DEPRECATIONS
 | ||
|   if (composited && (!gdk_display_supports_composite (display) || !impl_class->set_composited))
 | ||
|     {
 | ||
|       g_warning ("gdk_window_set_composited called but "
 | ||
|                  "compositing is not supported");
 | ||
|       return;
 | ||
|     }
 | ||
| G_GNUC_END_IGNORE_DEPRECATIONS
 | ||
| 
 | ||
|   impl_class->set_composited (window, composited);
 | ||
| 
 | ||
|   recompute_visible_regions (window, FALSE);
 | ||
| 
 | ||
|   if (GDK_WINDOW_IS_MAPPED (window))
 | ||
|     gdk_window_invalidate_in_parent (window);
 | ||
| 
 | ||
|   window->composited = composited;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_modal_hint:
 | ||
|  * @window: A toplevel #GdkWindow.
 | ||
|  *
 | ||
|  * Determines whether or not the window manager is hinted that @window
 | ||
|  * has modal behaviour.
 | ||
|  *
 | ||
|  * Returns: whether or not the window has the modal hint set.
 | ||
|  *
 | ||
|  * Since: 2.22
 | ||
|  */
 | ||
| gboolean
 | ||
| gdk_window_get_modal_hint (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 | ||
| 
 | ||
|   return window->modal_hint;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_accept_focus:
 | ||
|  * @window: a toplevel #GdkWindow.
 | ||
|  *
 | ||
|  * Determines whether or not the desktop environment shuld be hinted that
 | ||
|  * the window does not want to receive input focus.
 | ||
|  *
 | ||
|  * Returns: whether or not the window should receive input focus.
 | ||
|  *
 | ||
|  * Since: 2.22
 | ||
|  */
 | ||
| gboolean
 | ||
| gdk_window_get_accept_focus (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 | ||
| 
 | ||
|   return window->accept_focus;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_focus_on_map:
 | ||
|  * @window: a toplevel #GdkWindow.
 | ||
|  *
 | ||
|  * Determines whether or not the desktop environment should be hinted that the
 | ||
|  * window does not want to receive input focus when it is mapped.
 | ||
|  *
 | ||
|  * Returns: whether or not the window wants to receive input focus when
 | ||
|  * it is mapped.
 | ||
|  *
 | ||
|  * Since: 2.22
 | ||
|  */
 | ||
| gboolean
 | ||
| gdk_window_get_focus_on_map (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 | ||
| 
 | ||
|   return window->focus_on_map;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_is_input_only:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  *
 | ||
|  * Determines whether or not the window is an input only window.
 | ||
|  *
 | ||
|  * Returns: %TRUE if @window is input only
 | ||
|  *
 | ||
|  * Since: 2.22
 | ||
|  */
 | ||
| gboolean
 | ||
| gdk_window_is_input_only (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 | ||
| 
 | ||
|   return window->input_only;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_is_shaped:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  *
 | ||
|  * Determines whether or not the window is shaped.
 | ||
|  *
 | ||
|  * Returns: %TRUE if @window is shaped
 | ||
|  *
 | ||
|  * Since: 2.22
 | ||
|  */
 | ||
| gboolean
 | ||
| gdk_window_is_shaped (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 | ||
| 
 | ||
|   return window->shaped;
 | ||
| }
 | ||
| 
 | ||
| /* Gets the toplevel for a window as used for events,
 | ||
|    i.e. including offscreen parents */
 | ||
| static GdkWindow *
 | ||
| get_event_parent (GdkWindow *window)
 | ||
| {
 | ||
|   if (gdk_window_is_offscreen (window))
 | ||
|     return gdk_offscreen_window_get_embedder ((GdkWindow *)window);
 | ||
|   else
 | ||
|     return window->parent;
 | ||
| }
 | ||
| 
 | ||
| /* Gets the toplevel for a window as used for events,
 | ||
|    i.e. including offscreen parents going up to the native
 | ||
|    toplevel */
 | ||
| static GdkWindow *
 | ||
| get_event_toplevel (GdkWindow *window)
 | ||
| {
 | ||
|   GdkWindow *parent;
 | ||
| 
 | ||
|   while ((parent = get_event_parent (window)) != NULL &&
 | ||
| 	 (parent->window_type != GDK_WINDOW_ROOT))
 | ||
|     window = parent;
 | ||
| 
 | ||
|   return window;
 | ||
| }
 | ||
| 
 | ||
| gboolean
 | ||
| _gdk_window_event_parent_of (GdkWindow *parent,
 | ||
|  	  	             GdkWindow *child)
 | ||
| {
 | ||
|   GdkWindow *w;
 | ||
| 
 | ||
|   w = child;
 | ||
|   while (w != NULL)
 | ||
|     {
 | ||
|       if (w == parent)
 | ||
| 	return TRUE;
 | ||
| 
 | ||
|       w = get_event_parent (w);
 | ||
|     }
 | ||
| 
 | ||
|   return FALSE;
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| update_cursor (GdkDisplay *display,
 | ||
|                GdkDevice  *device)
 | ||
| {
 | ||
|   GdkWindow *cursor_window, *parent, *toplevel;
 | ||
|   GdkWindow *pointer_window;
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
|   GdkPointerWindowInfo *pointer_info;
 | ||
|   GdkDeviceGrabInfo *grab;
 | ||
|   GdkCursor *cursor;
 | ||
| 
 | ||
|   pointer_info = _gdk_display_get_pointer_info (display, device);
 | ||
|   pointer_window = pointer_info->window_under_pointer;
 | ||
| 
 | ||
|   /* We ignore the serials here and just pick the last grab
 | ||
|      we've sent, as that would shortly be used anyway. */
 | ||
|   grab = _gdk_display_get_last_device_grab (display, device);
 | ||
|   if (/* have grab */
 | ||
|       grab != NULL &&
 | ||
|       /* the pointer is not in a descendant of the grab window */
 | ||
|       !_gdk_window_event_parent_of (grab->window, pointer_window))
 | ||
|     {
 | ||
|       /* use the cursor from the grab window */
 | ||
|       cursor_window = grab->window;
 | ||
|     }
 | ||
|   else
 | ||
|     {
 | ||
|       /* otherwise use the cursor from the pointer window */
 | ||
|       cursor_window = pointer_window;
 | ||
|     }
 | ||
| 
 | ||
|   /* Find the first window with the cursor actually set, as
 | ||
|      the cursor is inherited from the parent */
 | ||
|   while (cursor_window->cursor == NULL &&
 | ||
|          !g_hash_table_contains (cursor_window->device_cursor, device) &&
 | ||
| 	 (parent = get_event_parent (cursor_window)) != NULL &&
 | ||
| 	 parent->window_type != GDK_WINDOW_ROOT)
 | ||
|     cursor_window = parent;
 | ||
| 
 | ||
|   cursor = g_hash_table_lookup (cursor_window->device_cursor, device);
 | ||
| 
 | ||
|   if (!cursor)
 | ||
|     cursor = cursor_window->cursor;
 | ||
| 
 | ||
|   /* Set all cursors on toplevel, otherwise its tricky to keep track of
 | ||
|    * which native window has what cursor set. */
 | ||
|   toplevel = get_event_toplevel (pointer_window);
 | ||
|   impl_class = GDK_WINDOW_IMPL_GET_CLASS (toplevel->impl);
 | ||
|   impl_class->set_device_cursor (toplevel, device, cursor);
 | ||
| }
 | ||
| 
 | ||
| static gboolean
 | ||
| point_in_window (GdkWindow *window,
 | ||
| 		 gdouble    x,
 | ||
|                  gdouble    y)
 | ||
| {
 | ||
|   return
 | ||
|     x >= 0 && x < window->width &&
 | ||
|     y >= 0 && y < window->height &&
 | ||
|     (window->shape == NULL ||
 | ||
|      cairo_region_contains_point (window->shape,
 | ||
| 			  x, y)) &&
 | ||
|     (window->input_shape == NULL ||
 | ||
|      cairo_region_contains_point (window->input_shape,
 | ||
| 			  x, y));
 | ||
| }
 | ||
| 
 | ||
| /* Same as point_in_window, except it also takes pass_through and its
 | ||
|    interaction with child windows into account */
 | ||
| static gboolean
 | ||
| point_in_input_window (GdkWindow *window,
 | ||
| 		       gdouble    x,
 | ||
| 		       gdouble    y,
 | ||
| 		       GdkWindow **input_window,
 | ||
| 		       gdouble   *input_window_x,
 | ||
| 		       gdouble   *input_window_y)
 | ||
| {
 | ||
|   GdkWindow *sub;
 | ||
|   double child_x, child_y;
 | ||
|   GList *l;
 | ||
| 
 | ||
|   if (!point_in_window (window, x, y))
 | ||
|     return FALSE;
 | ||
| 
 | ||
|   if (!window->pass_through)
 | ||
|     {
 | ||
|       if (input_window)
 | ||
| 	{
 | ||
| 	  *input_window = window;
 | ||
| 	  *input_window_x = x;
 | ||
| 	  *input_window_y = y;
 | ||
| 	}
 | ||
|       return TRUE;
 | ||
|     }
 | ||
| 
 | ||
|   /* For pass-through, must be over a child input window */
 | ||
| 
 | ||
|   /* Children is ordered in reverse stack order, i.e. first is topmost */
 | ||
|   for (l = window->children; l != NULL; l = l->next)
 | ||
|     {
 | ||
|       sub = l->data;
 | ||
| 
 | ||
|       if (!GDK_WINDOW_IS_MAPPED (sub))
 | ||
| 	continue;
 | ||
| 
 | ||
|       gdk_window_coords_from_parent ((GdkWindow *)sub,
 | ||
| 				     x, y,
 | ||
| 				     &child_x, &child_y);
 | ||
|       if (point_in_input_window (sub, child_x, child_y,
 | ||
| 				 input_window, input_window_x, input_window_y))
 | ||
| 	{
 | ||
| 	  if (input_window)
 | ||
| 	    gdk_window_coords_to_parent (sub,
 | ||
| 					 *input_window_x,
 | ||
| 					 *input_window_y,
 | ||
| 					 input_window_x,
 | ||
| 					 input_window_y);
 | ||
| 	  return TRUE;
 | ||
| 	}
 | ||
|     }
 | ||
| 
 | ||
|   return FALSE;
 | ||
| }
 | ||
| 
 | ||
| static GdkWindow *
 | ||
| convert_native_coords_to_toplevel (GdkWindow *window,
 | ||
| 				   gdouble    child_x,
 | ||
|                                    gdouble    child_y,
 | ||
| 				   gdouble   *toplevel_x,
 | ||
|                                    gdouble   *toplevel_y)
 | ||
| {
 | ||
|   gdouble x, y;
 | ||
| 
 | ||
|   x = child_x;
 | ||
|   y = child_y;
 | ||
| 
 | ||
|   while (!gdk_window_is_toplevel (window))
 | ||
|     {
 | ||
|       x += window->x;
 | ||
|       y += window->y;
 | ||
|       window = window->parent;
 | ||
|     }
 | ||
| 
 | ||
|   *toplevel_x = x;
 | ||
|   *toplevel_y = y;
 | ||
| 
 | ||
|   return window;
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| convert_toplevel_coords_to_window (GdkWindow *window,
 | ||
| 				   gdouble    toplevel_x,
 | ||
| 				   gdouble    toplevel_y,
 | ||
| 				   gdouble   *window_x,
 | ||
| 				   gdouble   *window_y)
 | ||
| {
 | ||
|   GdkWindow *parent;
 | ||
|   gdouble x, y;
 | ||
|   GList *children, *l;
 | ||
| 
 | ||
|   x = toplevel_x;
 | ||
|   y = toplevel_y;
 | ||
| 
 | ||
|   children = NULL;
 | ||
|   while ((parent = get_event_parent (window)) != NULL &&
 | ||
| 	 (parent->window_type != GDK_WINDOW_ROOT))
 | ||
|     {
 | ||
|       children = g_list_prepend (children, window);
 | ||
|       window = parent;
 | ||
|     }
 | ||
| 
 | ||
|   for (l = children; l != NULL; l = l->next)
 | ||
|     gdk_window_coords_from_parent (l->data, x, y, &x, &y);
 | ||
| 
 | ||
|   g_list_free (children);
 | ||
| 
 | ||
|   *window_x = x;
 | ||
|   *window_y = y;
 | ||
| }
 | ||
| 
 | ||
| static GdkWindow *
 | ||
| pick_embedded_child (GdkWindow *window,
 | ||
| 		     gdouble    x,
 | ||
|                      gdouble    y)
 | ||
| {
 | ||
|   GdkWindow *res;
 | ||
| 
 | ||
|   res = NULL;
 | ||
|   g_signal_emit (window,
 | ||
| 		 signals[PICK_EMBEDDED_CHILD], 0,
 | ||
| 		 x, y, &res);
 | ||
| 
 | ||
|   return res;
 | ||
| }
 | ||
| 
 | ||
| GdkWindow *
 | ||
| _gdk_window_find_child_at (GdkWindow *window,
 | ||
| 			   double     x,
 | ||
|                            double     y)
 | ||
| {
 | ||
|   GdkWindow *sub;
 | ||
|   double child_x, child_y;
 | ||
|   GList *l;
 | ||
| 
 | ||
|   if (point_in_window (window, x, y))
 | ||
|     {
 | ||
|       /* Children is ordered in reverse stack order, i.e. first is topmost */
 | ||
|       for (l = window->children; l != NULL; l = l->next)
 | ||
| 	{
 | ||
| 	  sub = l->data;
 | ||
| 
 | ||
| 	  if (!GDK_WINDOW_IS_MAPPED (sub))
 | ||
| 	    continue;
 | ||
| 
 | ||
| 	  gdk_window_coords_from_parent ((GdkWindow *)sub,
 | ||
|                                          x, y,
 | ||
|                                          &child_x, &child_y);
 | ||
| 	  if (point_in_input_window (sub, child_x, child_y,
 | ||
| 				     NULL, NULL, NULL))
 | ||
| 	    return (GdkWindow *)sub;
 | ||
| 	}
 | ||
| 
 | ||
|       if (window->num_offscreen_children > 0)
 | ||
| 	{
 | ||
| 	  sub = pick_embedded_child (window,
 | ||
| 				     x, y);
 | ||
| 	  if (sub)
 | ||
| 	    return (GdkWindow *)sub;
 | ||
| 	}
 | ||
|     }
 | ||
| 
 | ||
|   return NULL;
 | ||
| }
 | ||
| 
 | ||
| GdkWindow *
 | ||
| _gdk_window_find_descendant_at (GdkWindow *window,
 | ||
| 				gdouble    x,
 | ||
|                                 gdouble    y,
 | ||
| 				gdouble   *found_x,
 | ||
| 				gdouble   *found_y)
 | ||
| {
 | ||
|   GdkWindow *sub, *input_window;
 | ||
|   gdouble child_x, child_y;
 | ||
|   GList *l;
 | ||
|   gboolean found;
 | ||
| 
 | ||
|   if (point_in_window (window, x, y))
 | ||
|     {
 | ||
|       do
 | ||
| 	{
 | ||
| 	  found = FALSE;
 | ||
| 	  /* Children is ordered in reverse stack order, i.e. first is topmost */
 | ||
| 	  for (l = window->children; l != NULL; l = l->next)
 | ||
| 	    {
 | ||
| 	      sub = l->data;
 | ||
| 
 | ||
| 	      if (!GDK_WINDOW_IS_MAPPED (sub))
 | ||
| 		continue;
 | ||
| 
 | ||
| 	      gdk_window_coords_from_parent ((GdkWindow *)sub,
 | ||
|                                              x, y,
 | ||
|                                              &child_x, &child_y);
 | ||
| 	      if (point_in_input_window (sub, child_x, child_y,
 | ||
| 					 &input_window, &child_x, &child_y))
 | ||
| 		{
 | ||
| 		  x = child_x;
 | ||
| 		  y = child_y;
 | ||
| 		  window = input_window;
 | ||
| 		  found = TRUE;
 | ||
| 		  break;
 | ||
| 		}
 | ||
| 	    }
 | ||
| 	  if (!found &&
 | ||
| 	      window->num_offscreen_children > 0)
 | ||
| 	    {
 | ||
| 	      sub = pick_embedded_child (window,
 | ||
| 					 x, y);
 | ||
| 	      if (sub)
 | ||
| 		{
 | ||
| 		  found = TRUE;
 | ||
| 		  window = sub;
 | ||
| 		  from_embedder (sub, x, y, &x, &y);
 | ||
| 		}
 | ||
| 	    }
 | ||
| 	}
 | ||
|       while (found);
 | ||
|     }
 | ||
|   else
 | ||
|     {
 | ||
|       /* Not in window at all */
 | ||
|       window = NULL;
 | ||
|     }
 | ||
| 
 | ||
|   if (found_x)
 | ||
|     *found_x = x;
 | ||
|   if (found_y)
 | ||
|     *found_y = y;
 | ||
| 
 | ||
|   return window;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_beep:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  *
 | ||
|  * Emits a short beep associated to @window in the appropriate
 | ||
|  * display, if supported. Otherwise, emits a short beep on
 | ||
|  * the display just as gdk_display_beep().
 | ||
|  *
 | ||
|  * Since: 2.12
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_beep (GdkWindow *window)
 | ||
| {
 | ||
|   GdkDisplay *display;
 | ||
|   GdkWindow *toplevel;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   if (GDK_WINDOW_DESTROYED (window))
 | ||
|     return;
 | ||
| 
 | ||
|   toplevel = get_event_toplevel (window);
 | ||
|   display = gdk_window_get_display (window);
 | ||
| 
 | ||
|   if (toplevel)
 | ||
|     {
 | ||
|       if (GDK_WINDOW_IMPL_GET_CLASS (toplevel->impl)->beep (toplevel))
 | ||
|         return;
 | ||
|     }
 | ||
|   
 | ||
|   /* If windows fail to beep, we beep the display. */
 | ||
|   gdk_display_beep (display);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_support_multidevice:
 | ||
|  * @window: a #GdkWindow.
 | ||
|  * @support_multidevice: %TRUE to enable multidevice support in @window.
 | ||
|  *
 | ||
|  * This function will enable multidevice features in @window.
 | ||
|  *
 | ||
|  * Multidevice aware windows will need to handle properly multiple,
 | ||
|  * per device enter/leave events, device grabs and grab ownerships.
 | ||
|  *
 | ||
|  * Since: 3.0
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_set_support_multidevice (GdkWindow *window,
 | ||
|                                     gboolean   support_multidevice)
 | ||
| {
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   if (GDK_WINDOW_DESTROYED (window))
 | ||
|     return;
 | ||
| 
 | ||
|   if (window->support_multidevice == support_multidevice)
 | ||
|     return;
 | ||
| 
 | ||
|   window->support_multidevice = support_multidevice;
 | ||
| 
 | ||
|   /* FIXME: What to do if called when some pointers are inside the window ? */
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_support_multidevice:
 | ||
|  * @window: a #GdkWindow.
 | ||
|  *
 | ||
|  * Returns %TRUE if the window is aware of the existence of multiple
 | ||
|  * devices.
 | ||
|  *
 | ||
|  * Returns: %TRUE if the window handles multidevice features.
 | ||
|  *
 | ||
|  * Since: 3.0
 | ||
|  **/
 | ||
| gboolean
 | ||
| gdk_window_get_support_multidevice (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 | ||
| 
 | ||
|   if (GDK_WINDOW_DESTROYED (window))
 | ||
|     return FALSE;
 | ||
| 
 | ||
|   return window->support_multidevice;
 | ||
| }
 | ||
| 
 | ||
| static const guint type_masks[] = {
 | ||
|   GDK_SUBSTRUCTURE_MASK, /* GDK_DELETE                 = 0  */
 | ||
|   GDK_STRUCTURE_MASK, /* GDK_DESTROY                   = 1  */
 | ||
|   GDK_EXPOSURE_MASK, /* GDK_EXPOSE                     = 2  */
 | ||
|   GDK_POINTER_MOTION_MASK, /* GDK_MOTION_NOTIFY        = 3  */
 | ||
|   GDK_BUTTON_PRESS_MASK, /* GDK_BUTTON_PRESS           = 4  */
 | ||
|   GDK_BUTTON_PRESS_MASK, /* GDK_2BUTTON_PRESS          = 5  */
 | ||
|   GDK_BUTTON_PRESS_MASK, /* GDK_3BUTTON_PRESS          = 6  */
 | ||
|   GDK_BUTTON_RELEASE_MASK, /* GDK_BUTTON_RELEASE       = 7  */
 | ||
|   GDK_KEY_PRESS_MASK, /* GDK_KEY_PRESS                 = 8  */
 | ||
|   GDK_KEY_RELEASE_MASK, /* GDK_KEY_RELEASE             = 9  */
 | ||
|   GDK_ENTER_NOTIFY_MASK, /* GDK_ENTER_NOTIFY           = 10 */
 | ||
|   GDK_LEAVE_NOTIFY_MASK, /* GDK_LEAVE_NOTIFY           = 11 */
 | ||
|   GDK_FOCUS_CHANGE_MASK, /* GDK_FOCUS_CHANGE           = 12 */
 | ||
|   GDK_STRUCTURE_MASK, /* GDK_CONFIGURE                 = 13 */
 | ||
|   GDK_VISIBILITY_NOTIFY_MASK, /* GDK_MAP               = 14 */
 | ||
|   GDK_VISIBILITY_NOTIFY_MASK, /* GDK_UNMAP             = 15 */
 | ||
|   GDK_PROPERTY_CHANGE_MASK, /* GDK_PROPERTY_NOTIFY     = 16 */
 | ||
|   GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_CLEAR     = 17 */
 | ||
|   GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_REQUEST   = 18 */
 | ||
|   GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_NOTIFY    = 19 */
 | ||
|   GDK_PROXIMITY_IN_MASK, /* GDK_PROXIMITY_IN           = 20 */
 | ||
|   GDK_PROXIMITY_OUT_MASK, /* GDK_PROXIMITY_OUT         = 21 */
 | ||
|   GDK_ALL_EVENTS_MASK, /* GDK_DRAG_ENTER               = 22 */
 | ||
|   GDK_ALL_EVENTS_MASK, /* GDK_DRAG_LEAVE               = 23 */
 | ||
|   GDK_ALL_EVENTS_MASK, /* GDK_DRAG_MOTION              = 24 */
 | ||
|   GDK_ALL_EVENTS_MASK, /* GDK_DRAG_STATUS              = 25 */
 | ||
|   GDK_ALL_EVENTS_MASK, /* GDK_DROP_START               = 26 */
 | ||
|   GDK_ALL_EVENTS_MASK, /* GDK_DROP_FINISHED            = 27 */
 | ||
|   GDK_ALL_EVENTS_MASK, /* GDK_CLIENT_EVENT	       = 28 */
 | ||
|   GDK_VISIBILITY_NOTIFY_MASK, /* GDK_VISIBILITY_NOTIFY = 29 */
 | ||
|   GDK_EXPOSURE_MASK, /* GDK_NO_EXPOSE                  = 30 */
 | ||
|   GDK_SCROLL_MASK | GDK_SMOOTH_SCROLL_MASK,/* GDK_SCROLL= 31 */
 | ||
|   0, /* GDK_WINDOW_STATE = 32 */
 | ||
|   0, /* GDK_SETTING = 33 */
 | ||
|   0, /* GDK_OWNER_CHANGE = 34 */
 | ||
|   0, /* GDK_GRAB_BROKEN = 35 */
 | ||
|   0, /* GDK_DAMAGE = 36 */
 | ||
|   GDK_TOUCH_MASK, /* GDK_TOUCH_BEGIN = 37 */
 | ||
|   GDK_TOUCH_MASK, /* GDK_TOUCH_UPDATE = 38 */
 | ||
|   GDK_TOUCH_MASK, /* GDK_TOUCH_END = 39 */
 | ||
|   GDK_TOUCH_MASK, /* GDK_TOUCH_CANCEL = 40 */
 | ||
|   GDK_TOUCHPAD_GESTURE_MASK, /* GDK_TOUCHPAD_SWIPE = 41 */
 | ||
|   GDK_TOUCHPAD_GESTURE_MASK, /* GDK_TOUCHPAD_PINCH = 42 */
 | ||
|   GDK_TABLET_PAD_MASK, /* GDK_PAD_BUTTON_PRESS  = 43 */
 | ||
|   GDK_TABLET_PAD_MASK, /* GDK_PAD_BUTTON_RELEASE = 44 */
 | ||
|   GDK_TABLET_PAD_MASK, /* GDK_PAD_RING = 45 */
 | ||
|   GDK_TABLET_PAD_MASK, /* GDK_PAD_STRIP = 46 */
 | ||
|   GDK_TABLET_PAD_MASK, /* GDK_PAD_GROUP_MODE = 47 */
 | ||
| };
 | ||
| G_STATIC_ASSERT (G_N_ELEMENTS (type_masks) == GDK_EVENT_LAST);
 | ||
| 
 | ||
| /* send motion events if the right buttons are down */
 | ||
| static guint
 | ||
| update_evmask_for_button_motion (guint           evmask,
 | ||
| 				 GdkModifierType mask)
 | ||
| {
 | ||
|   if (evmask & GDK_BUTTON_MOTION_MASK &&
 | ||
|       mask & (GDK_BUTTON1_MASK |
 | ||
| 	      GDK_BUTTON2_MASK |
 | ||
| 	      GDK_BUTTON3_MASK |
 | ||
| 	      GDK_BUTTON4_MASK |
 | ||
| 	      GDK_BUTTON5_MASK))
 | ||
|     evmask |= GDK_POINTER_MOTION_MASK;
 | ||
| 
 | ||
|   if ((evmask & GDK_BUTTON1_MOTION_MASK && mask & GDK_BUTTON1_MASK) ||
 | ||
|       (evmask & GDK_BUTTON2_MOTION_MASK && mask & GDK_BUTTON2_MASK) ||
 | ||
|       (evmask & GDK_BUTTON3_MOTION_MASK && mask & GDK_BUTTON3_MASK))
 | ||
|     evmask |= GDK_POINTER_MOTION_MASK;
 | ||
| 
 | ||
|   return evmask;
 | ||
| }
 | ||
| 
 | ||
| static gboolean
 | ||
| is_button_type (GdkEventType type)
 | ||
| {
 | ||
|   return type == GDK_BUTTON_PRESS ||
 | ||
| 	 type == GDK_2BUTTON_PRESS ||
 | ||
| 	 type == GDK_3BUTTON_PRESS ||
 | ||
| 	 type == GDK_BUTTON_RELEASE ||
 | ||
|          type == GDK_TOUCH_BEGIN ||
 | ||
|          type == GDK_TOUCH_END ||
 | ||
|          type == GDK_TOUCH_CANCEL ||
 | ||
| 	 type == GDK_SCROLL;
 | ||
| }
 | ||
| 
 | ||
| static gboolean
 | ||
| is_gesture_type (GdkEventType type)
 | ||
| {
 | ||
|   return (type == GDK_TOUCHPAD_SWIPE ||
 | ||
|           type == GDK_TOUCHPAD_PINCH);
 | ||
| }
 | ||
| 
 | ||
| static gboolean
 | ||
| is_motion_type (GdkEventType type)
 | ||
| {
 | ||
|   return type == GDK_MOTION_NOTIFY ||
 | ||
|          type == GDK_TOUCH_UPDATE ||
 | ||
| 	 type == GDK_ENTER_NOTIFY ||
 | ||
| 	 type == GDK_LEAVE_NOTIFY;
 | ||
| }
 | ||
| 
 | ||
| static gboolean
 | ||
| is_touch_type (GdkEventType type)
 | ||
| {
 | ||
|   return type == GDK_TOUCH_BEGIN ||
 | ||
|          type == GDK_TOUCH_UPDATE ||
 | ||
|          type == GDK_TOUCH_END ||
 | ||
|          type == GDK_TOUCH_CANCEL;
 | ||
| }
 | ||
| 
 | ||
| static GdkWindow *
 | ||
| find_common_ancestor (GdkWindow *win1,
 | ||
| 		      GdkWindow *win2)
 | ||
| {
 | ||
|   GdkWindow *tmp;
 | ||
|   GList *path1 = NULL, *path2 = NULL;
 | ||
|   GList *list1, *list2;
 | ||
| 
 | ||
|   tmp = win1;
 | ||
|   while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
 | ||
|     {
 | ||
|       path1 = g_list_prepend (path1, tmp);
 | ||
|       tmp = get_event_parent (tmp);
 | ||
|     }
 | ||
| 
 | ||
|   tmp = win2;
 | ||
|   while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
 | ||
|     {
 | ||
|       path2 = g_list_prepend (path2, tmp);
 | ||
|       tmp = get_event_parent (tmp);
 | ||
|     }
 | ||
| 
 | ||
|   list1 = path1;
 | ||
|   list2 = path2;
 | ||
|   tmp = NULL;
 | ||
|   while (list1 && list2 && (list1->data == list2->data))
 | ||
|     {
 | ||
|       tmp = list1->data;
 | ||
|       list1 = list1->next;
 | ||
|       list2 = list2->next;
 | ||
|     }
 | ||
|   g_list_free (path1);
 | ||
|   g_list_free (path2);
 | ||
| 
 | ||
|   return tmp;
 | ||
| }
 | ||
| 
 | ||
| GdkEvent *
 | ||
| _gdk_make_event (GdkWindow    *window,
 | ||
| 		 GdkEventType  type,
 | ||
| 		 GdkEvent     *event_in_queue,
 | ||
| 		 gboolean      before_event)
 | ||
| {
 | ||
|   GdkEvent *event = gdk_event_new (type);
 | ||
|   guint32 the_time;
 | ||
|   GdkModifierType the_state;
 | ||
| 
 | ||
|   the_time = gdk_event_get_time (event_in_queue);
 | ||
|   gdk_event_get_state (event_in_queue, &the_state);
 | ||
| 
 | ||
|   event->any.window = g_object_ref (window);
 | ||
|   event->any.send_event = FALSE;
 | ||
|   if (event_in_queue && event_in_queue->any.send_event)
 | ||
|     event->any.send_event = TRUE;
 | ||
| 
 | ||
|   switch (type)
 | ||
|     {
 | ||
|     case GDK_MOTION_NOTIFY:
 | ||
|       event->motion.time = the_time;
 | ||
|       event->motion.axes = NULL;
 | ||
|       event->motion.state = the_state;
 | ||
|       break;
 | ||
| 
 | ||
|     case GDK_BUTTON_PRESS:
 | ||
|     case GDK_2BUTTON_PRESS:
 | ||
|     case GDK_3BUTTON_PRESS:
 | ||
|     case GDK_BUTTON_RELEASE:
 | ||
|       event->button.time = the_time;
 | ||
|       event->button.axes = NULL;
 | ||
|       event->button.state = the_state;
 | ||
|       break;
 | ||
| 
 | ||
|     case GDK_TOUCH_BEGIN:
 | ||
|     case GDK_TOUCH_UPDATE:
 | ||
|     case GDK_TOUCH_END:
 | ||
|     case GDK_TOUCH_CANCEL:
 | ||
|       event->touch.time = the_time;
 | ||
|       event->touch.axes = NULL;
 | ||
|       event->touch.state = the_state;
 | ||
|       break;
 | ||
| 
 | ||
|     case GDK_SCROLL:
 | ||
|       event->scroll.time = the_time;
 | ||
|       event->scroll.state = the_state;
 | ||
|       break;
 | ||
| 
 | ||
|     case GDK_KEY_PRESS:
 | ||
|     case GDK_KEY_RELEASE:
 | ||
|       event->key.time = the_time;
 | ||
|       event->key.state = the_state;
 | ||
|       break;
 | ||
| 
 | ||
|     case GDK_ENTER_NOTIFY:
 | ||
|     case GDK_LEAVE_NOTIFY:
 | ||
|       event->crossing.time = the_time;
 | ||
|       event->crossing.state = the_state;
 | ||
|       break;
 | ||
| 
 | ||
|     case GDK_PROPERTY_NOTIFY:
 | ||
|       event->property.time = the_time;
 | ||
|       event->property.state = the_state;
 | ||
|       break;
 | ||
| 
 | ||
|     case GDK_SELECTION_CLEAR:
 | ||
|     case GDK_SELECTION_REQUEST:
 | ||
|     case GDK_SELECTION_NOTIFY:
 | ||
|       event->selection.time = the_time;
 | ||
|       break;
 | ||
| 
 | ||
|     case GDK_PROXIMITY_IN:
 | ||
|     case GDK_PROXIMITY_OUT:
 | ||
|       event->proximity.time = the_time;
 | ||
|       break;
 | ||
| 
 | ||
|     case GDK_DRAG_ENTER:
 | ||
|     case GDK_DRAG_LEAVE:
 | ||
|     case GDK_DRAG_MOTION:
 | ||
|     case GDK_DRAG_STATUS:
 | ||
|     case GDK_DROP_START:
 | ||
|     case GDK_DROP_FINISHED:
 | ||
|       event->dnd.time = the_time;
 | ||
|       break;
 | ||
| 
 | ||
|     case GDK_TOUCHPAD_SWIPE:
 | ||
|       event->touchpad_swipe.time = the_time;
 | ||
|       event->touchpad_swipe.state = the_state;
 | ||
|       break;
 | ||
| 
 | ||
|     case GDK_TOUCHPAD_PINCH:
 | ||
|       event->touchpad_pinch.time = the_time;
 | ||
|       event->touchpad_pinch.state = the_state;
 | ||
|       break;
 | ||
| 
 | ||
|     case GDK_FOCUS_CHANGE:
 | ||
|     case GDK_CONFIGURE:
 | ||
|     case GDK_MAP:
 | ||
|     case GDK_UNMAP:
 | ||
|     case GDK_CLIENT_EVENT:
 | ||
|     case GDK_VISIBILITY_NOTIFY:
 | ||
|     case GDK_DELETE:
 | ||
|     case GDK_DESTROY:
 | ||
|     case GDK_EXPOSE:
 | ||
|     default:
 | ||
|       break;
 | ||
|     }
 | ||
| 
 | ||
|   if (event_in_queue)
 | ||
|     {
 | ||
|     if (before_event)
 | ||
|       _gdk_event_queue_insert_before (gdk_window_get_display (window), event_in_queue, event);
 | ||
|     else
 | ||
|       _gdk_event_queue_insert_after (gdk_window_get_display (window), event_in_queue, event);
 | ||
|     }
 | ||
|   else
 | ||
|     _gdk_event_queue_append (gdk_window_get_display (window), event);
 | ||
| 
 | ||
|   return event;
 | ||
| }
 | ||
| 
 | ||
| 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)
 | ||
| {
 | ||
|   GdkEvent *event;
 | ||
|   guint32 window_event_mask, type_event_mask;
 | ||
|   GdkDeviceGrabInfo *grab;
 | ||
|   GdkTouchGrabInfo *touch_grab = NULL;
 | ||
|   GdkPointerWindowInfo *pointer_info;
 | ||
|   gboolean block_event = FALSE;
 | ||
|   GdkEventSequence *sequence;
 | ||
| 
 | ||
|   grab = _gdk_display_has_device_grab (display, device, serial);
 | ||
|   pointer_info = _gdk_display_get_pointer_info (display, device);
 | ||
| 
 | ||
|   sequence = gdk_event_get_event_sequence (event_in_queue);
 | ||
|   if (sequence)
 | ||
|     touch_grab = _gdk_display_has_touch_grab (display, device, sequence, serial);
 | ||
| 
 | ||
|   if (touch_grab)
 | ||
|     {
 | ||
|       if (window != touch_grab->window)
 | ||
|         return;
 | ||
| 
 | ||
|       window_event_mask = touch_grab->event_mask;
 | ||
|     }
 | ||
|   else if (grab != NULL &&
 | ||
|            !grab->owner_events)
 | ||
|     {
 | ||
|       /* !owner_event => only report events wrt grab window, ignore rest */
 | ||
|       if ((GdkWindow *)window != grab->window)
 | ||
| 	return;
 | ||
|       window_event_mask = grab->event_mask;
 | ||
|     }
 | ||
|   else
 | ||
|     window_event_mask = window->event_mask;
 | ||
| 
 | ||
|   if (type == GDK_ENTER_NOTIFY &&
 | ||
|       (pointer_info->need_touch_press_enter ||
 | ||
|        (source_device &&
 | ||
|         gdk_device_get_source (source_device) == GDK_SOURCE_TOUCHSCREEN)) &&
 | ||
|       mode != GDK_CROSSING_TOUCH_BEGIN &&
 | ||
|       mode != GDK_CROSSING_TOUCH_END)
 | ||
|     {
 | ||
|       pointer_info->need_touch_press_enter = TRUE;
 | ||
|       block_event = TRUE;
 | ||
|     }
 | ||
|   else if (type == GDK_LEAVE_NOTIFY)
 | ||
|     {
 | ||
|       type_event_mask = GDK_LEAVE_NOTIFY_MASK;
 | ||
|       window->devices_inside = g_list_remove (window->devices_inside, device);
 | ||
| 
 | ||
|       if (!window->support_multidevice && window->devices_inside)
 | ||
|         {
 | ||
|           /* Block leave events unless it's the last pointer */
 | ||
|           block_event = TRUE;
 | ||
|         }
 | ||
|     }
 | ||
|   else
 | ||
|     {
 | ||
|       type_event_mask = GDK_ENTER_NOTIFY_MASK;
 | ||
| 
 | ||
|       if (!window->support_multidevice && window->devices_inside)
 | ||
|         {
 | ||
|           /* Only emit enter events for the first device */
 | ||
|           block_event = TRUE;
 | ||
|         }
 | ||
| 
 | ||
|       if (gdk_device_get_device_type (device) == GDK_DEVICE_TYPE_MASTER &&
 | ||
|           gdk_device_get_mode (device) != GDK_MODE_DISABLED &&
 | ||
|           !g_list_find (window->devices_inside, device))
 | ||
|         window->devices_inside = g_list_prepend (window->devices_inside, device);
 | ||
|     }
 | ||
| 
 | ||
|   if (block_event)
 | ||
|     return;
 | ||
| 
 | ||
|   if (window_event_mask & type_event_mask)
 | ||
|     {
 | ||
|       event = _gdk_make_event ((GdkWindow *)window, type, event_in_queue, TRUE);
 | ||
|       gdk_event_set_device (event, device);
 | ||
|       gdk_event_set_seat (event, gdk_device_get_seat (device));
 | ||
| 
 | ||
|       if (source_device)
 | ||
|         gdk_event_set_source_device (event, source_device);
 | ||
| 
 | ||
|       event->crossing.time = time_;
 | ||
|       event->crossing.subwindow = subwindow;
 | ||
|       if (subwindow)
 | ||
| 	g_object_ref (subwindow);
 | ||
|       convert_toplevel_coords_to_window ((GdkWindow *)window,
 | ||
| 					 toplevel_x, toplevel_y,
 | ||
| 					 &event->crossing.x, &event->crossing.y);
 | ||
|       event->crossing.x_root = toplevel_x + toplevel->x;
 | ||
|       event->crossing.y_root = toplevel_y + toplevel->y;
 | ||
|       event->crossing.mode = mode;
 | ||
|       event->crossing.detail = notify_type;
 | ||
|       event->crossing.focus = FALSE;
 | ||
|       event->crossing.state = mask;
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| /* The coordinates are in the toplevel window that src/dest are in.
 | ||
|  * src and dest are always (if != NULL) in the same toplevel, as
 | ||
|  * we get a leave-notify and set the window_under_pointer to null
 | ||
|  * before crossing to another toplevel.
 | ||
|  */
 | ||
| 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)
 | ||
| {
 | ||
|   GdkWindow *c;
 | ||
|   GdkWindow *win, *last, *next;
 | ||
|   GList *path, *list;
 | ||
|   GdkWindow *a;
 | ||
|   GdkWindow *b;
 | ||
|   GdkWindow *toplevel;
 | ||
|   GdkNotifyType notify_type;
 | ||
| 
 | ||
|   /* TODO: Don't send events to toplevel, as we get those from the windowing system */
 | ||
| 
 | ||
|   a = (src && GDK_IS_WINDOW (src)) ? src : NULL;
 | ||
|   b = (dest && GDK_IS_WINDOW (dest)) ? dest : NULL;
 | ||
| 
 | ||
|   if (src == dest)
 | ||
|     return; /* No crossings generated between src and dest */
 | ||
| 
 | ||
|   if (gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_MASTER)
 | ||
|     {
 | ||
|       if (a && gdk_window_get_device_events (src, device) == 0)
 | ||
|         a = NULL;
 | ||
| 
 | ||
|       if (b && gdk_window_get_device_events (dest, device) == 0)
 | ||
|         b = NULL;
 | ||
|     }
 | ||
| 
 | ||
|   if (!a && !b)
 | ||
|     return;
 | ||
| 
 | ||
|   c = find_common_ancestor (a, b);
 | ||
| 
 | ||
|   non_linear |= (c != a) && (c != b);
 | ||
| 
 | ||
|   if (a) /* There might not be a source (i.e. if no previous pointer_in_window) */
 | ||
|     {
 | ||
|       toplevel = gdk_window_get_toplevel (a);
 | ||
| 
 | ||
|       /* Traverse up from a to (excluding) c sending leave events */
 | ||
|       if (non_linear)
 | ||
| 	notify_type = GDK_NOTIFY_NONLINEAR;
 | ||
|       else if (c == a)
 | ||
| 	notify_type = GDK_NOTIFY_INFERIOR;
 | ||
|       else
 | ||
| 	notify_type = GDK_NOTIFY_ANCESTOR;
 | ||
|       send_crossing_event (display, toplevel,
 | ||
| 			   a, GDK_LEAVE_NOTIFY,
 | ||
| 			   mode,
 | ||
| 			   notify_type,
 | ||
| 			   NULL, device, source_device,
 | ||
| 			   toplevel_x, toplevel_y,
 | ||
| 			   mask, time_,
 | ||
| 			   event_in_queue,
 | ||
| 			   serial);
 | ||
| 
 | ||
|       if (c != a)
 | ||
| 	{
 | ||
| 	  if (non_linear)
 | ||
| 	    notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
 | ||
| 	  else
 | ||
| 	    notify_type = GDK_NOTIFY_VIRTUAL;
 | ||
| 
 | ||
| 	  last = a;
 | ||
| 	  win = get_event_parent (a);
 | ||
| 	  while (win != c && win->window_type != GDK_WINDOW_ROOT)
 | ||
| 	    {
 | ||
| 	      send_crossing_event (display, toplevel,
 | ||
| 				   win, GDK_LEAVE_NOTIFY,
 | ||
| 				   mode,
 | ||
| 				   notify_type,
 | ||
| 				   (GdkWindow *)last,
 | ||
| 				   device, source_device,
 | ||
| 				   toplevel_x, toplevel_y,
 | ||
| 				   mask, time_,
 | ||
| 				   event_in_queue,
 | ||
| 				   serial);
 | ||
| 
 | ||
| 	      last = win;
 | ||
| 	      win = get_event_parent (win);
 | ||
| 	    }
 | ||
| 	}
 | ||
|     }
 | ||
| 
 | ||
|   if (b) /* Might not be a dest, e.g. if we're moving out of the window */
 | ||
|     {
 | ||
|       toplevel = gdk_window_get_toplevel ((GdkWindow *)b);
 | ||
| 
 | ||
|       /* Traverse down from c to b */
 | ||
|       if (c != b)
 | ||
| 	{
 | ||
| 	  path = NULL;
 | ||
| 	  win = get_event_parent (b);
 | ||
| 	  while (win != c && win->window_type != GDK_WINDOW_ROOT)
 | ||
| 	    {
 | ||
| 	      path = g_list_prepend (path, win);
 | ||
| 	      win = get_event_parent (win);
 | ||
| 	    }
 | ||
| 
 | ||
| 	  if (non_linear)
 | ||
| 	    notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
 | ||
| 	  else
 | ||
| 	    notify_type = GDK_NOTIFY_VIRTUAL;
 | ||
| 
 | ||
| 	  list = path;
 | ||
| 	  while (list)
 | ||
| 	    {
 | ||
| 	      win = list->data;
 | ||
| 	      list = list->next;
 | ||
| 	      if (list)
 | ||
| 		next = list->data;
 | ||
| 	      else
 | ||
| 		next = b;
 | ||
| 
 | ||
| 	      send_crossing_event (display, toplevel,
 | ||
| 				   win, GDK_ENTER_NOTIFY,
 | ||
| 				   mode,
 | ||
| 				   notify_type,
 | ||
| 				   (GdkWindow *)next,
 | ||
| 				   device, source_device,
 | ||
| 				   toplevel_x, toplevel_y,
 | ||
| 				   mask, time_,
 | ||
| 				   event_in_queue,
 | ||
| 				   serial);
 | ||
| 	    }
 | ||
| 	  g_list_free (path);
 | ||
| 	}
 | ||
| 
 | ||
| 
 | ||
|       if (non_linear)
 | ||
| 	notify_type = GDK_NOTIFY_NONLINEAR;
 | ||
|       else if (c == a)
 | ||
| 	notify_type = GDK_NOTIFY_ANCESTOR;
 | ||
|       else
 | ||
| 	notify_type = GDK_NOTIFY_INFERIOR;
 | ||
| 
 | ||
|       send_crossing_event (display, toplevel,
 | ||
| 			   b, GDK_ENTER_NOTIFY,
 | ||
| 			   mode,
 | ||
| 			   notify_type,
 | ||
| 			   NULL,
 | ||
|                            device, source_device,
 | ||
| 			   toplevel_x, toplevel_y,
 | ||
| 			   mask, time_,
 | ||
| 			   event_in_queue,
 | ||
| 			   serial);
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| /* Returns the window inside the event window with the pointer in it
 | ||
|  * at the specified coordinates, or NULL if its not in any child of
 | ||
|  * the toplevel. It also takes into account !owner_events grabs.
 | ||
|  */
 | ||
| static GdkWindow *
 | ||
| get_pointer_window (GdkDisplay *display,
 | ||
| 		    GdkWindow *event_window,
 | ||
|                     GdkDevice *device,
 | ||
| 		    gdouble toplevel_x,
 | ||
| 		    gdouble toplevel_y,
 | ||
| 		    gulong serial)
 | ||
| {
 | ||
|   GdkWindow *pointer_window;
 | ||
|   GdkDeviceGrabInfo *grab;
 | ||
|   GdkPointerWindowInfo *pointer_info;
 | ||
| 
 | ||
|   pointer_info = _gdk_display_get_pointer_info (display, device);
 | ||
| 
 | ||
|   if (event_window == pointer_info->toplevel_under_pointer)
 | ||
|     pointer_window =
 | ||
|       _gdk_window_find_descendant_at (event_window,
 | ||
| 				      toplevel_x, toplevel_y,
 | ||
| 				      NULL, NULL);
 | ||
|   else
 | ||
|     pointer_window = NULL;
 | ||
| 
 | ||
|   grab = _gdk_display_has_device_grab (display, device, serial);
 | ||
|   if (grab != NULL &&
 | ||
|       !grab->owner_events &&
 | ||
|       pointer_window != grab->window &&
 | ||
|       !gdk_window_is_ancestor (pointer_window, grab->window))
 | ||
|     pointer_window = NULL;
 | ||
| 
 | ||
|   return pointer_window;
 | ||
| }
 | ||
| 
 | ||
| void
 | ||
| _gdk_display_set_window_under_pointer (GdkDisplay *display,
 | ||
|                                        GdkDevice  *device,
 | ||
| 				       GdkWindow  *window)
 | ||
| {
 | ||
|   GdkPointerWindowInfo *device_info;
 | ||
| 
 | ||
|   device_info = _gdk_display_get_pointer_info (display, device);
 | ||
| 
 | ||
|   if (device_info->window_under_pointer)
 | ||
|     g_object_unref (device_info->window_under_pointer);
 | ||
|   device_info->window_under_pointer = window;
 | ||
| 
 | ||
|   if (window)
 | ||
|     {
 | ||
|       g_object_ref (window);
 | ||
|       update_cursor (display, device);
 | ||
|     }
 | ||
| 
 | ||
|   _gdk_display_enable_motion_hints (display, device);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_pointer_grab:
 | ||
|  * @window: the #GdkWindow which will own the grab (the grab window).
 | ||
|  * @owner_events: if %FALSE then all pointer events are reported with respect to
 | ||
|  *                @window and are only reported if selected by @event_mask. If %TRUE then pointer
 | ||
|  *                events for this application are reported as normal, but pointer events outside
 | ||
|  *                this application are reported with respect to @window and only if selected by
 | ||
|  *                @event_mask. In either mode, unreported events are discarded.
 | ||
|  * @event_mask: specifies the event mask, which is used in accordance with
 | ||
|  *              @owner_events. Note that only pointer events (i.e. button and motion events)
 | ||
|  *              may be selected.
 | ||
|  * @confine_to: (allow-none): If non-%NULL, the pointer will be confined to this
 | ||
|  *              window during the grab. If the pointer is outside @confine_to, it will
 | ||
|  *              automatically be moved to the closest edge of @confine_to and enter
 | ||
|  *              and leave events will be generated as necessary.
 | ||
|  * @cursor: (allow-none): the cursor to display while the grab is active. If this is %NULL then
 | ||
|  *          the normal cursors are used for @window and its descendants, and the cursor
 | ||
|  *          for @window is used for all other windows.
 | ||
|  * @time_: the timestamp of the event which led to this pointer grab. This usually
 | ||
|  *         comes from a #GdkEventButton struct, though %GDK_CURRENT_TIME can be used if
 | ||
|  *         the time isn’t known.
 | ||
|  *
 | ||
|  * Grabs the pointer (usually a mouse) so that all events are passed to this
 | ||
|  * application until the pointer is ungrabbed with gdk_pointer_ungrab(), or
 | ||
|  * the grab window becomes unviewable.
 | ||
|  * This overrides any previous pointer grab by this client.
 | ||
|  *
 | ||
|  * Pointer grabs are used for operations which need complete control over mouse
 | ||
|  * events, even if the mouse leaves the application.
 | ||
|  * For example in GTK+ it is used for Drag and Drop, for dragging the handle in
 | ||
|  * the #GtkHPaned and #GtkVPaned widgets.
 | ||
|  *
 | ||
|  * Note that if the event mask of an X window has selected both button press and
 | ||
|  * button release events, then a button press event will cause an automatic
 | ||
|  * pointer grab until the button is released.
 | ||
|  * X does this automatically since most applications expect to receive button
 | ||
|  * press and release events in pairs.
 | ||
|  * It is equivalent to a pointer grab on the window with @owner_events set to
 | ||
|  * %TRUE.
 | ||
|  *
 | ||
|  * If you set up anything at the time you take the grab that needs to be cleaned
 | ||
|  * up when the grab ends, you should handle the #GdkEventGrabBroken events that
 | ||
|  * are emitted when the grab ends unvoluntarily.
 | ||
|  *
 | ||
|  * Returns: %GDK_GRAB_SUCCESS if the grab was successful.
 | ||
|  *
 | ||
|  * Deprecated: 3.0: Use gdk_device_grab() instead.
 | ||
|  **/
 | ||
| GdkGrabStatus
 | ||
| gdk_pointer_grab (GdkWindow *	  window,
 | ||
| 		  gboolean	  owner_events,
 | ||
| 		  GdkEventMask	  event_mask,
 | ||
| 		  GdkWindow *	  confine_to,
 | ||
| 		  GdkCursor *	  cursor,
 | ||
| 		  guint32	  time)
 | ||
| {
 | ||
|   GdkWindow *native;
 | ||
|   GdkDisplay *display;
 | ||
|   GdkDevice *device;
 | ||
|   GdkGrabStatus res = 0;
 | ||
|   gulong serial;
 | ||
|   GList *seats, *s;
 | ||
| 
 | ||
|   g_return_val_if_fail (window != NULL, GDK_GRAB_FAILED);
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), GDK_GRAB_FAILED);
 | ||
|   g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), GDK_GRAB_FAILED);
 | ||
| 
 | ||
|   /* We need a native window for confine to to work, ensure we have one */
 | ||
|   if (confine_to)
 | ||
|     {
 | ||
|       if (!gdk_window_ensure_native (confine_to))
 | ||
| 	{
 | ||
| 	  g_warning ("Can't confine to grabbed window, not native");
 | ||
| 	  confine_to = NULL;
 | ||
| 	}
 | ||
|     }
 | ||
| 
 | ||
|   /* Non-viewable client side window => fail */
 | ||
|   if (!_gdk_window_has_impl (window) &&
 | ||
|       !gdk_window_is_viewable (window))
 | ||
|     return GDK_GRAB_NOT_VIEWABLE;
 | ||
| 
 | ||
|   native = gdk_window_get_toplevel (window);
 | ||
|   while (gdk_window_is_offscreen (native))
 | ||
|     {
 | ||
|       native = gdk_offscreen_window_get_embedder (native);
 | ||
| 
 | ||
|       if (native == NULL ||
 | ||
| 	  (!_gdk_window_has_impl (native) &&
 | ||
| 	   !gdk_window_is_viewable (native)))
 | ||
| 	return GDK_GRAB_NOT_VIEWABLE;
 | ||
| 
 | ||
|       native = gdk_window_get_toplevel (native);
 | ||
|     }
 | ||
| 
 | ||
|   display = gdk_window_get_display (window);
 | ||
| 
 | ||
|   serial = _gdk_display_get_next_serial (display);
 | ||
|   seats = gdk_display_list_seats (display);
 | ||
| 
 | ||
|   for (s = seats; s; s = s->next)
 | ||
|     {
 | ||
|       device = gdk_seat_get_pointer (s->data);
 | ||
| 
 | ||
|       res = GDK_DEVICE_GET_CLASS (device)->grab (device,
 | ||
|                                                  native,
 | ||
|                                                  owner_events,
 | ||
|                                                  get_native_grab_event_mask (event_mask),
 | ||
|                                                  confine_to,
 | ||
|                                                  cursor,
 | ||
|                                                  time);
 | ||
| 
 | ||
|       if (res == GDK_GRAB_SUCCESS)
 | ||
|         _gdk_display_add_device_grab (display,
 | ||
|                                       device,
 | ||
|                                       window,
 | ||
|                                       native,
 | ||
|                                       GDK_OWNERSHIP_NONE,
 | ||
|                                       owner_events,
 | ||
|                                       event_mask,
 | ||
|                                       serial,
 | ||
|                                       time,
 | ||
|                                       FALSE);
 | ||
|     }
 | ||
| 
 | ||
|   /* FIXME: handle errors when grabbing */
 | ||
| 
 | ||
|   g_list_free (seats);
 | ||
| 
 | ||
|   return res;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_keyboard_grab:
 | ||
|  * @window: the #GdkWindow which will own the grab (the grab window).
 | ||
|  * @owner_events: if %FALSE then all keyboard events are reported with respect to
 | ||
|  *   @window. If %TRUE then keyboard events for this application are
 | ||
|  *   reported as normal, but keyboard events outside this application
 | ||
|  *   are reported with respect to @window. Both key press and key
 | ||
|  *   release events are always reported, independant of the event mask
 | ||
|  *   set by the application.
 | ||
|  * @time_: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no timestamp is
 | ||
|  *   available.
 | ||
|  *
 | ||
|  * Grabs the keyboard so that all events are passed to this
 | ||
|  * application until the keyboard is ungrabbed with gdk_keyboard_ungrab().
 | ||
|  * This overrides any previous keyboard grab by this client.
 | ||
|  *
 | ||
|  * If you set up anything at the time you take the grab that needs to be cleaned
 | ||
|  * up when the grab ends, you should handle the #GdkEventGrabBroken events that
 | ||
|  * are emitted when the grab ends unvoluntarily.
 | ||
|  *
 | ||
|  * Returns: %GDK_GRAB_SUCCESS if the grab was successful.
 | ||
|  *
 | ||
|  * Deprecated: 3.0: Use gdk_device_grab() instead.
 | ||
|  **/
 | ||
| GdkGrabStatus
 | ||
| gdk_keyboard_grab (GdkWindow *window,
 | ||
| 		   gboolean   owner_events,
 | ||
| 		   guint32    time)
 | ||
| {
 | ||
|   GdkWindow *native;
 | ||
|   GdkDisplay *display;
 | ||
|   GdkDevice *device;
 | ||
|   GdkGrabStatus res = 0;
 | ||
|   gulong serial;
 | ||
|   GList *seats, *s;
 | ||
| 
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), GDK_GRAB_FAILED);
 | ||
| 
 | ||
|   /* Non-viewable client side window => fail */
 | ||
|   if (!_gdk_window_has_impl (window) &&
 | ||
|       !gdk_window_is_viewable (window))
 | ||
|     return GDK_GRAB_NOT_VIEWABLE;
 | ||
| 
 | ||
|   native = gdk_window_get_toplevel (window);
 | ||
| 
 | ||
|   while (gdk_window_is_offscreen (native))
 | ||
|     {
 | ||
|       native = gdk_offscreen_window_get_embedder (native);
 | ||
| 
 | ||
|       if (native == NULL ||
 | ||
| 	  (!_gdk_window_has_impl (native) &&
 | ||
| 	   !gdk_window_is_viewable (native)))
 | ||
| 	return GDK_GRAB_NOT_VIEWABLE;
 | ||
| 
 | ||
|       native = gdk_window_get_toplevel (native);
 | ||
|     }
 | ||
| 
 | ||
|   display = gdk_window_get_display (window);
 | ||
|   serial = _gdk_display_get_next_serial (display);
 | ||
|   seats = gdk_display_list_seats (display);
 | ||
| 
 | ||
|   for (s = seats; s; s = s->next)
 | ||
|     {
 | ||
|       device = gdk_seat_get_keyboard (s->data);
 | ||
| 
 | ||
|       res = GDK_DEVICE_GET_CLASS (device)->grab (device,
 | ||
|                                                  native,
 | ||
|                                                  owner_events,
 | ||
|                                                  GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK,
 | ||
|                                                  NULL,
 | ||
|                                                  NULL,
 | ||
|                                                  time);
 | ||
| 
 | ||
|       if (res == GDK_GRAB_SUCCESS)
 | ||
|         _gdk_display_add_device_grab (display,
 | ||
|                                       device,
 | ||
|                                       window,
 | ||
|                                       native,
 | ||
|                                       GDK_OWNERSHIP_NONE,
 | ||
|                                       owner_events, 0,
 | ||
|                                       serial,
 | ||
|                                       time,
 | ||
|                                       FALSE);
 | ||
|     }
 | ||
| 
 | ||
|   /* FIXME: handle errors when grabbing */
 | ||
| 
 | ||
|   g_list_free (seats);
 | ||
| 
 | ||
|   return res;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_geometry_changed:
 | ||
|  * @window: an embedded offscreen #GdkWindow
 | ||
|  *
 | ||
|  * This function informs GDK that the geometry of an embedded
 | ||
|  * offscreen window has changed. This is necessary for GDK to keep
 | ||
|  * track of which offscreen window the pointer is in.
 | ||
|  *
 | ||
|  * Since: 2.18
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_geometry_changed (GdkWindow *window)
 | ||
| {
 | ||
|   _gdk_synthesize_crossing_events_for_geometry_change (window);
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| source_events_device_added (GdkDeviceManager *device_manager,
 | ||
|                             GdkDevice        *device,
 | ||
|                             gpointer          user_data)
 | ||
| {
 | ||
|   GdkWindow *window;
 | ||
|   GdkEventMask event_mask;
 | ||
|   GdkInputSource source;
 | ||
| 
 | ||
|   if (gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_FLOATING)
 | ||
|     return;
 | ||
| 
 | ||
|   window = user_data;
 | ||
|   source = gdk_device_get_source (device);
 | ||
| 
 | ||
|   event_mask = GPOINTER_TO_INT (g_hash_table_lookup (window->source_event_masks,
 | ||
|                                                      GINT_TO_POINTER (source)));
 | ||
|   if (event_mask)
 | ||
|     gdk_window_set_device_events (window, device, event_mask);
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| source_events_device_changed (GdkDeviceManager *device_manager,
 | ||
|                               GdkDevice        *device,
 | ||
|                               gpointer          user_data)
 | ||
| {
 | ||
|   GdkDeviceType type;
 | ||
|   GdkInputSource source;
 | ||
|   GdkEventMask event_mask;
 | ||
|   GdkWindow *window;
 | ||
| 
 | ||
|   window = user_data;
 | ||
|   type = gdk_device_get_device_type (device);
 | ||
|   source = gdk_device_get_source (device);
 | ||
| 
 | ||
|   event_mask = GPOINTER_TO_INT (g_hash_table_lookup (window->source_event_masks,
 | ||
|                                                      GINT_TO_POINTER (source)));
 | ||
| 
 | ||
|   if (!event_mask)
 | ||
|     return;
 | ||
| 
 | ||
|   if (type == GDK_DEVICE_TYPE_FLOATING)
 | ||
|     {
 | ||
|       /* The device was just floated, enable its event mask */
 | ||
|       gdk_window_set_device_events (window, device, event_mask);
 | ||
|     }
 | ||
|   else if (type == GDK_DEVICE_TYPE_SLAVE)
 | ||
|     gdk_window_set_device_events (window, device, 0);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_source_events:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @source: a #GdkInputSource to define the source class.
 | ||
|  * @event_mask: event mask for @window
 | ||
|  *
 | ||
|  * Sets the event mask for any floating device (i.e. not attached to any
 | ||
|  * visible pointer) that has the source defined as @source. This event
 | ||
|  * mask will be applied both to currently existing, newly added devices
 | ||
|  * after this call, and devices being attached/detached.
 | ||
|  *
 | ||
|  * Since: 3.0
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_set_source_events (GdkWindow      *window,
 | ||
|                               GdkInputSource  source,
 | ||
|                               GdkEventMask    event_mask)
 | ||
| {
 | ||
|   GdkDeviceManager *device_manager;
 | ||
|   GdkDisplay *display;
 | ||
|   GList *devices, *d;
 | ||
|   guint size;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
 | ||
|   display = gdk_window_get_display (window);
 | ||
|   device_manager = gdk_display_get_device_manager (display);
 | ||
| 
 | ||
|   devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING);
 | ||
| 
 | ||
|   /* Set event mask for existing devices */
 | ||
|   for (d = devices; d; d = d->next)
 | ||
|     {
 | ||
|       GdkDevice *device = d->data;
 | ||
| 
 | ||
|       if (source == gdk_device_get_source (device))
 | ||
|         gdk_window_set_device_events (window, device, event_mask);
 | ||
|     }
 | ||
| 
 | ||
|   g_list_free (devices);
 | ||
|   G_GNUC_END_IGNORE_DEPRECATIONS;
 | ||
| 
 | ||
|   /* Update accounting */
 | ||
|   if (G_UNLIKELY (!window->source_event_masks))
 | ||
|     window->source_event_masks = g_hash_table_new (NULL, NULL);
 | ||
| 
 | ||
|   if (event_mask)
 | ||
|     g_hash_table_insert (window->source_event_masks,
 | ||
|                          GUINT_TO_POINTER (source),
 | ||
|                          GUINT_TO_POINTER (event_mask));
 | ||
|   else
 | ||
|     g_hash_table_remove (window->source_event_masks,
 | ||
|                          GUINT_TO_POINTER (source));
 | ||
| 
 | ||
|   size = g_hash_table_size (window->source_event_masks);
 | ||
| 
 | ||
|   /* Update handler if needed */
 | ||
|   if (!window->device_added_handler_id && size > 0)
 | ||
|     {
 | ||
|       window->device_added_handler_id =
 | ||
|         g_signal_connect (device_manager, "device-added",
 | ||
|                           G_CALLBACK (source_events_device_added), window);
 | ||
|       window->device_changed_handler_id =
 | ||
|         g_signal_connect (device_manager, "device-changed",
 | ||
|                           G_CALLBACK (source_events_device_changed), window);
 | ||
|     }
 | ||
|   else if (window->device_added_handler_id && size == 0)
 | ||
|     g_signal_handler_disconnect (device_manager, window->device_added_handler_id);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_source_events:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @source: a #GdkInputSource to define the source class.
 | ||
|  *
 | ||
|  * Returns the event mask for @window corresponding to the device class specified
 | ||
|  * by @source.
 | ||
|  *
 | ||
|  * Returns: source event mask for @window
 | ||
|  **/
 | ||
| GdkEventMask
 | ||
| gdk_window_get_source_events (GdkWindow      *window,
 | ||
|                               GdkInputSource  source)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
 | ||
| 
 | ||
|   return GPOINTER_TO_UINT (g_hash_table_lookup (window->source_event_masks,
 | ||
|                                                 GUINT_TO_POINTER (source)));
 | ||
| }
 | ||
| 
 | ||
| static gboolean
 | ||
| do_synthesize_crossing_event (gpointer data)
 | ||
| {
 | ||
|   GdkDisplay *display;
 | ||
|   GdkWindow *changed_toplevel;
 | ||
|   GHashTableIter iter;
 | ||
|   gpointer key, value;
 | ||
|   gulong serial;
 | ||
| 
 | ||
|   changed_toplevel = data;
 | ||
| 
 | ||
|   changed_toplevel->synthesized_crossing_event_id = 0;
 | ||
| 
 | ||
|   if (GDK_WINDOW_DESTROYED (changed_toplevel))
 | ||
|     return FALSE;
 | ||
| 
 | ||
|   display = gdk_window_get_display (changed_toplevel);
 | ||
|   serial = _gdk_display_get_next_serial (display);
 | ||
|   g_hash_table_iter_init (&iter, display->pointers_info);
 | ||
| 
 | ||
|   while (g_hash_table_iter_next (&iter, &key, &value))
 | ||
|     {
 | ||
|       GdkWindow *new_window_under_pointer;
 | ||
|       GdkPointerWindowInfo *pointer_info = value;
 | ||
|       GdkDevice *device = key;
 | ||
| 
 | ||
|       if (changed_toplevel == pointer_info->toplevel_under_pointer)
 | ||
|         {
 | ||
|           new_window_under_pointer =
 | ||
|             get_pointer_window (display, changed_toplevel,
 | ||
|                                 device,
 | ||
|                                 pointer_info->toplevel_x,
 | ||
|                                 pointer_info->toplevel_y,
 | ||
|                                 serial);
 | ||
|           if (new_window_under_pointer != pointer_info->window_under_pointer)
 | ||
|             {
 | ||
|               GdkDevice *source_device;
 | ||
| 
 | ||
|               if (pointer_info->last_slave)
 | ||
|                 source_device = pointer_info->last_slave;
 | ||
|               else
 | ||
|                 source_device = device;
 | ||
| 
 | ||
|               _gdk_synthesize_crossing_events (display,
 | ||
|                                                pointer_info->window_under_pointer,
 | ||
|                                                new_window_under_pointer,
 | ||
|                                                device, source_device,
 | ||
|                                                GDK_CROSSING_NORMAL,
 | ||
|                                                pointer_info->toplevel_x,
 | ||
|                                                pointer_info->toplevel_y,
 | ||
|                                                pointer_info->state,
 | ||
|                                                GDK_CURRENT_TIME,
 | ||
|                                                NULL,
 | ||
|                                                serial,
 | ||
|                                                FALSE);
 | ||
|               _gdk_display_set_window_under_pointer (display, device, new_window_under_pointer);
 | ||
|             }
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|   return FALSE;
 | ||
| }
 | ||
| 
 | ||
| void
 | ||
| _gdk_synthesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
 | ||
| {
 | ||
|   GdkWindow *toplevel;
 | ||
| 
 | ||
|   toplevel = get_event_toplevel (changed_window);
 | ||
| 
 | ||
|   if (toplevel->synthesized_crossing_event_id == 0)
 | ||
|     {
 | ||
|       toplevel->synthesized_crossing_event_id =
 | ||
|         gdk_threads_add_idle_full (GDK_PRIORITY_EVENTS - 1,
 | ||
|                                    do_synthesize_crossing_event,
 | ||
|                                    toplevel, NULL);
 | ||
|       g_source_set_name_by_id (toplevel->synthesized_crossing_event_id,
 | ||
|                                "[gtk+] do_synthesize_crossing_event");
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| /* Don't use for crossing events */
 | ||
| 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)
 | ||
| {
 | ||
|   guint evmask, emulated_mask = 0;
 | ||
|   GdkWindow *grab_window;
 | ||
|   GdkDeviceGrabInfo *grab;
 | ||
|   GdkTouchGrabInfo *touch_grab;
 | ||
| 
 | ||
|   touch_grab = _gdk_display_has_touch_grab (display, device, sequence, serial);
 | ||
|   grab = _gdk_display_get_last_device_grab (display, device);
 | ||
| 
 | ||
|   /* Default value. */
 | ||
|   if (evmask_out)
 | ||
|     *evmask_out = 0;
 | ||
| 
 | ||
|   if (is_touch_type (type) && pointer_emulated)
 | ||
|     {
 | ||
|       switch (type)
 | ||
|         {
 | ||
|         case GDK_TOUCH_BEGIN:
 | ||
|           emulated_mask |= GDK_BUTTON_PRESS_MASK;
 | ||
|           break;
 | ||
|         case GDK_TOUCH_UPDATE:
 | ||
|           emulated_mask |= GDK_POINTER_MOTION_MASK;
 | ||
|           break;
 | ||
|         case GDK_TOUCH_END:
 | ||
|           emulated_mask |= GDK_BUTTON_RELEASE_MASK;
 | ||
|         default:
 | ||
|           break;
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|   if (touch_grab != NULL &&
 | ||
|       (!grab || grab->implicit || touch_grab->serial >= grab->serial_start))
 | ||
|     {
 | ||
|       evmask = touch_grab->event_mask;
 | ||
|       evmask = update_evmask_for_button_motion (evmask, mask);
 | ||
| 
 | ||
|       if (evmask & (type_masks[type] | emulated_mask))
 | ||
|         {
 | ||
|           if (evmask_out)
 | ||
|             *evmask_out = evmask;
 | ||
|           return touch_grab->window;
 | ||
|         }
 | ||
|       else
 | ||
|         return NULL;
 | ||
|     }
 | ||
| 
 | ||
|   if (grab != NULL && !grab->owner_events)
 | ||
|     {
 | ||
|       evmask = grab->event_mask;
 | ||
|       evmask = update_evmask_for_button_motion (evmask, mask);
 | ||
| 
 | ||
|       grab_window = grab->window;
 | ||
| 
 | ||
|       if (evmask & (type_masks[type] | emulated_mask))
 | ||
| 	{
 | ||
| 	  if (evmask_out)
 | ||
| 	    *evmask_out = evmask;
 | ||
| 	  return grab_window;
 | ||
| 	}
 | ||
|       else
 | ||
| 	return NULL;
 | ||
|     }
 | ||
| 
 | ||
|   while (pointer_window != NULL)
 | ||
|     {
 | ||
|       evmask = pointer_window->event_mask;
 | ||
|       evmask = update_evmask_for_button_motion (evmask, mask);
 | ||
| 
 | ||
|       if (evmask & (type_masks[type] | emulated_mask))
 | ||
| 	{
 | ||
| 	  if (evmask_out)
 | ||
| 	    *evmask_out = evmask;
 | ||
| 	  return pointer_window;
 | ||
| 	}
 | ||
| 
 | ||
|       pointer_window = get_event_parent (pointer_window);
 | ||
|     }
 | ||
| 
 | ||
|   if (grab != NULL &&
 | ||
|       grab->owner_events)
 | ||
|     {
 | ||
|       evmask = grab->event_mask;
 | ||
|       evmask = update_evmask_for_button_motion (evmask, mask);
 | ||
| 
 | ||
|       if (evmask & (type_masks[type] | emulated_mask))
 | ||
| 	{
 | ||
| 	  if (evmask_out)
 | ||
| 	    *evmask_out = evmask;
 | ||
| 	  return grab->window;
 | ||
| 	}
 | ||
|       else
 | ||
| 	return NULL;
 | ||
|     }
 | ||
| 
 | ||
|   return NULL;
 | ||
| }
 | ||
| 
 | ||
| static gboolean
 | ||
| proxy_pointer_event (GdkDisplay                 *display,
 | ||
| 		     GdkEvent                   *source_event,
 | ||
| 		     gulong                      serial)
 | ||
| {
 | ||
|   GdkWindow *toplevel_window, *event_window;
 | ||
|   GdkWindow *pointer_window;
 | ||
|   GdkPointerWindowInfo *pointer_info;
 | ||
|   GdkDevice *device, *source_device;
 | ||
|   GdkEvent *event;
 | ||
|   guint state;
 | ||
|   gdouble toplevel_x, toplevel_y;
 | ||
|   guint32 time_;
 | ||
|   gboolean non_linear, need_synthetic_enter = FALSE;
 | ||
|   gint event_type;
 | ||
| 
 | ||
|   event_type = source_event->type;
 | ||
|   event_window = source_event->any.window;
 | ||
|   gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
 | ||
|   gdk_event_get_state (source_event, &state);
 | ||
|   time_ = gdk_event_get_time (source_event);
 | ||
|   device = gdk_event_get_device (source_event);
 | ||
|   source_device = gdk_event_get_source_device (source_event);
 | ||
|   pointer_info = _gdk_display_get_pointer_info (display, device);
 | ||
|   toplevel_window = convert_native_coords_to_toplevel (event_window,
 | ||
| 						       toplevel_x, toplevel_y,
 | ||
| 						       &toplevel_x, &toplevel_y);
 | ||
| 
 | ||
|   non_linear = FALSE;
 | ||
|   if ((source_event->type == GDK_LEAVE_NOTIFY ||
 | ||
|        source_event->type == GDK_ENTER_NOTIFY) &&
 | ||
|       (source_event->crossing.detail == GDK_NOTIFY_NONLINEAR ||
 | ||
|        source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))
 | ||
|     non_linear = TRUE;
 | ||
| 
 | ||
|   if (pointer_info->need_touch_press_enter &&
 | ||
|       gdk_device_get_source (pointer_info->last_slave) != GDK_SOURCE_TOUCHSCREEN &&
 | ||
|       (source_event->type != GDK_TOUCH_UPDATE ||
 | ||
|        gdk_event_get_pointer_emulated (source_event)))
 | ||
|     {
 | ||
|       pointer_info->need_touch_press_enter = FALSE;
 | ||
|       need_synthetic_enter = TRUE;
 | ||
|     }
 | ||
| 
 | ||
|   /* If we get crossing events with subwindow unexpectedly being NULL
 | ||
|      that means there is a native subwindow that gdk doesn't know about.
 | ||
|      We track these and forward them, with the correct virtual window
 | ||
|      events inbetween.
 | ||
|      This is important to get right, as metacity uses gdk for the frame
 | ||
|      windows, but gdk doesn't know about the client windows reparented
 | ||
|      into the frame. */
 | ||
|   if (((source_event->type == GDK_LEAVE_NOTIFY &&
 | ||
| 	source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
 | ||
|        (source_event->type == GDK_ENTER_NOTIFY &&
 | ||
| 	(source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
 | ||
| 	 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
 | ||
|       source_event->crossing.subwindow == NULL)
 | ||
|     {
 | ||
|       /* Left for an unknown (to gdk) subwindow */
 | ||
| 
 | ||
|       /* Send leave events from window under pointer to event window
 | ||
| 	 that will get the subwindow == NULL window */
 | ||
|       _gdk_synthesize_crossing_events (display,
 | ||
| 				       pointer_info->window_under_pointer,
 | ||
| 				       event_window,
 | ||
|                                        device, source_device,
 | ||
| 				       source_event->crossing.mode,
 | ||
| 				       toplevel_x, toplevel_y,
 | ||
| 				       state, time_,
 | ||
| 				       source_event,
 | ||
| 				       serial,
 | ||
| 				       non_linear);
 | ||
| 
 | ||
|       /* Send subwindow == NULL event */
 | ||
|       send_crossing_event (display,
 | ||
| 			   toplevel_window,
 | ||
| 			   event_window,
 | ||
| 			   source_event->type,
 | ||
| 			   source_event->crossing.mode,
 | ||
| 			   source_event->crossing.detail,
 | ||
| 			   NULL,
 | ||
|                            device, source_device,
 | ||
| 			   toplevel_x, toplevel_y,
 | ||
| 			   state, time_,
 | ||
| 			   source_event,
 | ||
| 			   serial);
 | ||
| 
 | ||
|       _gdk_display_set_window_under_pointer (display, device, NULL);
 | ||
|       return TRUE;
 | ||
|     }
 | ||
| 
 | ||
|   pointer_window = get_pointer_window (display, toplevel_window, device,
 | ||
| 				       toplevel_x, toplevel_y, serial);
 | ||
| 
 | ||
|   if (((source_event->type == GDK_ENTER_NOTIFY &&
 | ||
| 	source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
 | ||
|        (source_event->type == GDK_LEAVE_NOTIFY &&
 | ||
| 	(source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
 | ||
| 	 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
 | ||
|       source_event->crossing.subwindow == NULL)
 | ||
|     {
 | ||
|       /* Entered from an unknown (to gdk) subwindow */
 | ||
| 
 | ||
|       /* Send subwindow == NULL event */
 | ||
|       send_crossing_event (display,
 | ||
| 			   toplevel_window,
 | ||
| 			   event_window,
 | ||
| 			   source_event->type,
 | ||
| 			   source_event->crossing.mode,
 | ||
| 			   source_event->crossing.detail,
 | ||
| 			   NULL,
 | ||
|                            device, source_device,
 | ||
| 			   toplevel_x, toplevel_y,
 | ||
| 			   state, time_,
 | ||
| 			   source_event,
 | ||
| 			   serial);
 | ||
| 
 | ||
|       /* Send enter events from event window to pointer_window */
 | ||
|       _gdk_synthesize_crossing_events (display,
 | ||
| 				       event_window,
 | ||
| 				       pointer_window,
 | ||
|                                        device, source_device,
 | ||
| 				       source_event->crossing.mode,
 | ||
| 				       toplevel_x, toplevel_y,
 | ||
| 				       state, time_,
 | ||
| 				       source_event,
 | ||
| 				       serial, non_linear);
 | ||
|       _gdk_display_set_window_under_pointer (display, device, pointer_window);
 | ||
|       return TRUE;
 | ||
|     }
 | ||
| 
 | ||
|   if ((source_event->type != GDK_TOUCH_UPDATE ||
 | ||
|        gdk_event_get_pointer_emulated (source_event)) &&
 | ||
|       pointer_info->window_under_pointer != pointer_window)
 | ||
|     {
 | ||
|       /* Either a toplevel crossing notify that ended up inside a child window,
 | ||
| 	 or a motion notify that got into another child window  */
 | ||
| 
 | ||
|       /* Different than last time, send crossing events */
 | ||
|       _gdk_synthesize_crossing_events (display,
 | ||
| 				       pointer_info->window_under_pointer,
 | ||
| 				       pointer_window,
 | ||
|                                        device, source_device,
 | ||
| 				       GDK_CROSSING_NORMAL,
 | ||
| 				       toplevel_x, toplevel_y,
 | ||
| 				       state, time_,
 | ||
| 				       source_event,
 | ||
| 				       serial, non_linear);
 | ||
|       _gdk_display_set_window_under_pointer (display, device, pointer_window);
 | ||
|     }
 | ||
| 
 | ||
|   if (source_event->type == GDK_MOTION_NOTIFY ||
 | ||
|       source_event->type == GDK_TOUCH_UPDATE)
 | ||
|     {
 | ||
|       GdkWindow *event_win;
 | ||
|       guint evmask;
 | ||
|       gboolean is_hint;
 | ||
|       GdkEventSequence *sequence;
 | ||
| 
 | ||
|       sequence = gdk_event_get_event_sequence (source_event);
 | ||
| 
 | ||
|       event_win = get_event_window (display,
 | ||
|                                     device,
 | ||
|                                     sequence,
 | ||
|                                     pointer_window,
 | ||
|                                     source_event->type,
 | ||
|                                     state,
 | ||
|                                     &evmask,
 | ||
|                                     gdk_event_get_pointer_emulated (source_event),
 | ||
|                                     serial);
 | ||
| 
 | ||
|       if (event_type == GDK_TOUCH_UPDATE)
 | ||
|         {
 | ||
|           if (gdk_event_get_pointer_emulated (source_event))
 | ||
|             {
 | ||
|               /* Touch events emulating pointer events are transformed back
 | ||
|                * to pointer events if:
 | ||
|                * 1 - The event window doesn't select for touch events
 | ||
|                * 2 - There's no touch grab for this sequence, which means
 | ||
|                *     it was started as a pointer sequence, but a device
 | ||
|                *     grab added touch events afterwards, the sequence must
 | ||
|                *     not mutate in this case.
 | ||
|                */
 | ||
|               if ((evmask & GDK_TOUCH_MASK) == 0 ||
 | ||
|                   !_gdk_display_has_touch_grab (display, device, sequence, serial))
 | ||
|                 event_type = GDK_MOTION_NOTIFY;
 | ||
|             }
 | ||
|           else if ((evmask & GDK_TOUCH_MASK) == 0)
 | ||
|             return TRUE;
 | ||
|         }
 | ||
| 
 | ||
|       if (is_touch_type (source_event->type) && !is_touch_type (event_type))
 | ||
|         state |= GDK_BUTTON1_MASK;
 | ||
| 
 | ||
|       if (event_win &&
 | ||
|           gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_MASTER &&
 | ||
|           gdk_window_get_device_events (event_win, device) == 0)
 | ||
|         return TRUE;
 | ||
| 
 | ||
|       /* The last device to interact with the window was a touch device,
 | ||
|        * which synthesized a leave notify event, so synthesize another enter
 | ||
|        * notify to tell the pointer is on the window.
 | ||
|        */
 | ||
|       if (need_synthetic_enter)
 | ||
|         _gdk_synthesize_crossing_events (display,
 | ||
|                                          NULL, pointer_window,
 | ||
|                                          device, source_device,
 | ||
|                                          GDK_CROSSING_DEVICE_SWITCH,
 | ||
|                                          toplevel_x, toplevel_y,
 | ||
|                                          state, time_, NULL,
 | ||
|                                          serial, FALSE);
 | ||
| 
 | ||
|       is_hint = FALSE;
 | ||
| 
 | ||
|       if (event_win &&
 | ||
|           event_type == GDK_MOTION_NOTIFY &&
 | ||
| 	  (evmask & GDK_POINTER_MOTION_HINT_MASK))
 | ||
| 	{
 | ||
|           gulong *device_serial;
 | ||
| 
 | ||
|           device_serial = g_hash_table_lookup (display->motion_hint_info, device);
 | ||
| 
 | ||
|           if (!device_serial ||
 | ||
|               (*device_serial != 0 &&
 | ||
|                serial < *device_serial))
 | ||
| 	    event_win = NULL; /* Ignore event */
 | ||
| 	  else
 | ||
| 	    {
 | ||
| 	      is_hint = TRUE;
 | ||
|               *device_serial = G_MAXULONG;
 | ||
| 	    }
 | ||
| 	}
 | ||
| 
 | ||
|       if (!event_win)
 | ||
|         return TRUE;
 | ||
| 
 | ||
|       event = gdk_event_new (event_type);
 | ||
|       event->any.window = g_object_ref (event_win);
 | ||
|       event->any.send_event = source_event->any.send_event;
 | ||
| 
 | ||
|       gdk_event_set_device (event, gdk_event_get_device (source_event));
 | ||
|       gdk_event_set_source_device (event, source_device);
 | ||
|       gdk_event_set_seat (event, gdk_device_get_seat (device));
 | ||
|       gdk_event_set_device_tool (event, gdk_event_get_device_tool (source_event));
 | ||
| 
 | ||
|       if (event_type == GDK_TOUCH_UPDATE)
 | ||
| 	{
 | ||
| 	  event->touch.time = time_;
 | ||
| 	  event->touch.state = state | GDK_BUTTON1_MASK;
 | ||
| 	  event->touch.sequence = source_event->touch.sequence;
 | ||
| 	  event->touch.emulating_pointer = source_event->touch.emulating_pointer;
 | ||
| 	  convert_toplevel_coords_to_window (event_win,
 | ||
| 					     toplevel_x, toplevel_y,
 | ||
| 					     &event->touch.x, &event->touch.y);
 | ||
| 	  gdk_event_get_root_coords (source_event,
 | ||
| 				     &event->touch.x_root,
 | ||
| 				     &event->touch.y_root);
 | ||
| 
 | ||
| 	  event->touch.axes = g_memdup (source_event->touch.axes,
 | ||
| 					sizeof (gdouble) * gdk_device_get_n_axes (source_event->touch.device));
 | ||
| 	}
 | ||
|       else
 | ||
| 	{
 | ||
| 	  event->motion.time = time_;
 | ||
| 	  event->motion.state = state;
 | ||
| 	  event->motion.is_hint = is_hint;
 | ||
| 
 | ||
| 	  convert_toplevel_coords_to_window (event_win,
 | ||
| 					     toplevel_x, toplevel_y,
 | ||
| 					     &event->motion.x, &event->motion.y);
 | ||
| 	  gdk_event_get_root_coords (source_event,
 | ||
| 				     &event->motion.x_root,
 | ||
| 				     &event->motion.y_root);
 | ||
| 
 | ||
| 	  if (is_touch_type (source_event->type))
 | ||
| 	    event->motion.axes = g_memdup (source_event->touch.axes,
 | ||
| 					   sizeof (gdouble) * gdk_device_get_n_axes (source_event->touch.device));
 | ||
| 	  else
 | ||
| 	    event->motion.axes = g_memdup (source_event->motion.axes,
 | ||
| 					   sizeof (gdouble) * gdk_device_get_n_axes (source_event->motion.device));
 | ||
| 	}
 | ||
| 
 | ||
|       /* Just insert the event */
 | ||
|       _gdk_event_queue_insert_after (gdk_window_get_display (event_win),
 | ||
| 				     source_event, event);
 | ||
|     }
 | ||
| 
 | ||
|   /* unlink all move events from queue.
 | ||
|      We handle our own, including our emulated masks. */
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| #define GDK_ANY_BUTTON_MASK (GDK_BUTTON1_MASK | \
 | ||
| 			     GDK_BUTTON2_MASK | \
 | ||
| 			     GDK_BUTTON3_MASK | \
 | ||
| 			     GDK_BUTTON4_MASK | \
 | ||
| 			     GDK_BUTTON5_MASK)
 | ||
| 
 | ||
| static gboolean
 | ||
| proxy_button_event (GdkEvent *source_event,
 | ||
| 		    gulong serial)
 | ||
| {
 | ||
|   GdkWindow *toplevel_window, *event_window;
 | ||
|   GdkWindow *event_win;
 | ||
|   GdkWindow *pointer_window;
 | ||
|   GdkWindow *parent;
 | ||
|   GdkEvent *event;
 | ||
|   GdkPointerWindowInfo *pointer_info;
 | ||
|   GdkDeviceGrabInfo *pointer_grab;
 | ||
|   guint state;
 | ||
|   guint32 time_;
 | ||
|   GdkEventType type;
 | ||
|   gdouble toplevel_x, toplevel_y;
 | ||
|   GdkDisplay *display;
 | ||
|   GdkWindow *w;
 | ||
|   GdkDevice *device, *source_device;
 | ||
|   GdkEventMask evmask;
 | ||
|   GdkEventSequence *sequence;
 | ||
| 
 | ||
|   type = source_event->any.type;
 | ||
|   event_window = source_event->any.window;
 | ||
|   gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
 | ||
|   gdk_event_get_state (source_event, &state);
 | ||
|   time_ = gdk_event_get_time (source_event);
 | ||
|   device = gdk_event_get_device (source_event);
 | ||
|   source_device = gdk_event_get_source_device (source_event);
 | ||
|   display = gdk_window_get_display (source_event->any.window);
 | ||
|   toplevel_window = convert_native_coords_to_toplevel (event_window,
 | ||
| 						       toplevel_x, toplevel_y,
 | ||
| 						       &toplevel_x, &toplevel_y);
 | ||
| 
 | ||
|   sequence = gdk_event_get_event_sequence (source_event);
 | ||
| 
 | ||
|   pointer_info = _gdk_display_get_pointer_info (display, device);
 | ||
|   pointer_grab = _gdk_display_has_device_grab (display, device, serial);
 | ||
| 
 | ||
|   if ((type == GDK_BUTTON_PRESS ||
 | ||
|        type == GDK_TOUCH_BEGIN) &&
 | ||
|       !source_event->any.send_event &&
 | ||
|       (!pointer_grab ||
 | ||
|        (type == GDK_TOUCH_BEGIN && pointer_grab->implicit &&
 | ||
|         !gdk_event_get_pointer_emulated (source_event))))
 | ||
|     {
 | ||
|       pointer_window =
 | ||
| 	_gdk_window_find_descendant_at (toplevel_window,
 | ||
| 					toplevel_x, toplevel_y,
 | ||
| 					NULL, NULL);
 | ||
| 
 | ||
|       /* Find the event window, that gets the grab */
 | ||
|       w = pointer_window;
 | ||
|       while (w != NULL &&
 | ||
| 	     (parent = get_event_parent (w)) != NULL &&
 | ||
| 	     parent->window_type != GDK_WINDOW_ROOT)
 | ||
| 	{
 | ||
| 	  if (w->event_mask & GDK_BUTTON_PRESS_MASK &&
 | ||
|               (type == GDK_BUTTON_PRESS ||
 | ||
|                gdk_event_get_pointer_emulated (source_event)))
 | ||
| 	    break;
 | ||
| 
 | ||
|           if (type == GDK_TOUCH_BEGIN &&
 | ||
|               w->event_mask & GDK_TOUCH_MASK)
 | ||
|             break;
 | ||
| 
 | ||
| 	  w = parent;
 | ||
| 	}
 | ||
|       pointer_window = w;
 | ||
| 
 | ||
|       if (pointer_window)
 | ||
|         {
 | ||
|           if (type == GDK_TOUCH_BEGIN &&
 | ||
|               pointer_window->event_mask & GDK_TOUCH_MASK)
 | ||
|             {
 | ||
|               _gdk_display_add_touch_grab (display, device, sequence,
 | ||
|                                            pointer_window, event_window,
 | ||
|                                            gdk_window_get_events (pointer_window),
 | ||
|                                            serial, time_);
 | ||
|             }
 | ||
|           else if (type == GDK_BUTTON_PRESS ||
 | ||
|                    gdk_event_get_pointer_emulated (source_event))
 | ||
|             {
 | ||
|               _gdk_display_add_device_grab  (display,
 | ||
|                                              device,
 | ||
|                                              pointer_window,
 | ||
|                                              event_window,
 | ||
|                                              GDK_OWNERSHIP_NONE,
 | ||
|                                              FALSE,
 | ||
|                                              gdk_window_get_events (pointer_window),
 | ||
|                                              serial,
 | ||
|                                              time_,
 | ||
|                                              TRUE);
 | ||
|               _gdk_display_device_grab_update (display, device,
 | ||
|                                                source_device, serial);
 | ||
|             }
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|   pointer_window = get_pointer_window (display, toplevel_window, device,
 | ||
| 				       toplevel_x, toplevel_y,
 | ||
| 				       serial);
 | ||
| 
 | ||
|   event_win = get_event_window (display,
 | ||
|                                 device,
 | ||
|                                 sequence,
 | ||
|                                 pointer_window,
 | ||
|                                 type, state,
 | ||
|                                 &evmask,
 | ||
|                                 gdk_event_get_pointer_emulated (source_event),
 | ||
|                                 serial);
 | ||
| 
 | ||
|   if (type == GDK_TOUCH_BEGIN || type == GDK_TOUCH_END)
 | ||
|     {
 | ||
|       if (gdk_event_get_pointer_emulated (source_event))
 | ||
|         {
 | ||
|           if ((evmask & GDK_TOUCH_MASK) == 0 ||
 | ||
|               !_gdk_display_has_touch_grab (display, device, sequence, serial))
 | ||
|             {
 | ||
|               if (type == GDK_TOUCH_BEGIN)
 | ||
|                 type = GDK_BUTTON_PRESS;
 | ||
|               else if (type == GDK_TOUCH_END)
 | ||
|                 type = GDK_BUTTON_RELEASE;
 | ||
|             }
 | ||
|         }
 | ||
|       else if ((evmask & GDK_TOUCH_MASK) == 0)
 | ||
|         return TRUE;
 | ||
|     }
 | ||
| 
 | ||
|   if (source_event->type == GDK_TOUCH_END && !is_touch_type (type))
 | ||
|     state |= GDK_BUTTON1_MASK;
 | ||
| 
 | ||
|   if (event_win == NULL)
 | ||
|     return TRUE;
 | ||
| 
 | ||
|   if (gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_MASTER &&
 | ||
|       gdk_window_get_device_events (event_win, device) == 0)
 | ||
|     return TRUE;
 | ||
| 
 | ||
|   if ((type == GDK_BUTTON_PRESS ||
 | ||
|        (type == GDK_TOUCH_BEGIN &&
 | ||
|         gdk_event_get_pointer_emulated (source_event))) &&
 | ||
|       pointer_info->need_touch_press_enter)
 | ||
|     {
 | ||
|       GdkCrossingMode mode;
 | ||
| 
 | ||
|       /* The last device to interact with the window was a touch device,
 | ||
|        * which synthesized a leave notify event, so synthesize another enter
 | ||
|        * notify to tell the pointer is on the window.
 | ||
|        */
 | ||
|       if (gdk_device_get_source (source_device) == GDK_SOURCE_TOUCHSCREEN)
 | ||
|         mode = GDK_CROSSING_TOUCH_BEGIN;
 | ||
|       else
 | ||
|         mode = GDK_CROSSING_DEVICE_SWITCH;
 | ||
| 
 | ||
|       pointer_info->need_touch_press_enter = FALSE;
 | ||
|       _gdk_synthesize_crossing_events (display,
 | ||
|                                        NULL,
 | ||
|                                        pointer_info->window_under_pointer,
 | ||
|                                        device, source_device, mode,
 | ||
|                                        toplevel_x, toplevel_y,
 | ||
|                                        state, time_, source_event,
 | ||
|                                        serial, FALSE);
 | ||
|     }
 | ||
|   else if (type == GDK_SCROLL &&
 | ||
|            (((evmask & GDK_SMOOTH_SCROLL_MASK) == 0 &&
 | ||
|              source_event->scroll.direction == GDK_SCROLL_SMOOTH) ||
 | ||
|             ((evmask & GDK_SMOOTH_SCROLL_MASK) != 0 &&
 | ||
|              source_event->scroll.direction != GDK_SCROLL_SMOOTH &&
 | ||
|              gdk_event_get_pointer_emulated (source_event))))
 | ||
|     return FALSE;
 | ||
| 
 | ||
|   event = _gdk_make_event (event_win, type, source_event, FALSE);
 | ||
| 
 | ||
|   switch (type)
 | ||
|     {
 | ||
|     case GDK_BUTTON_PRESS:
 | ||
|     case GDK_BUTTON_RELEASE:
 | ||
|       event->button.button = source_event->button.button;
 | ||
|       convert_toplevel_coords_to_window (event_win,
 | ||
| 					 toplevel_x, toplevel_y,
 | ||
| 					 &event->button.x, &event->button.y);
 | ||
|       gdk_event_get_root_coords (source_event,
 | ||
| 				 &event->button.x_root,
 | ||
| 				 &event->button.y_root);
 | ||
|       gdk_event_set_device (event, gdk_event_get_device (source_event));
 | ||
|       gdk_event_set_source_device (event, source_device);
 | ||
|       gdk_event_set_seat (event, gdk_device_get_seat (device));
 | ||
|       gdk_event_set_device_tool (event, gdk_event_get_device_tool (source_event));
 | ||
| 
 | ||
|       if (is_touch_type (source_event->type))
 | ||
|         {
 | ||
|           if (type == GDK_BUTTON_RELEASE)
 | ||
|             event->button.state |= GDK_BUTTON1_MASK;
 | ||
| 	  event->button.button = 1;
 | ||
| 	  event->button.axes = g_memdup (source_event->touch.axes,
 | ||
| 					 sizeof (gdouble) * gdk_device_get_n_axes (source_event->touch.device));
 | ||
| 	}
 | ||
|       else
 | ||
| 	{
 | ||
| 	  event->button.button = source_event->button.button;
 | ||
| 	  event->button.axes = g_memdup (source_event->button.axes,
 | ||
| 					 sizeof (gdouble) * gdk_device_get_n_axes (source_event->button.device));
 | ||
| 	}
 | ||
| 
 | ||
|       if (type == GDK_BUTTON_PRESS)
 | ||
|         _gdk_event_button_generate (display, event);
 | ||
|       else if ((type == GDK_BUTTON_RELEASE ||
 | ||
|                 (type == GDK_TOUCH_END &&
 | ||
|                  gdk_event_get_pointer_emulated (source_event))) &&
 | ||
|                pointer_window == pointer_info->window_under_pointer &&
 | ||
|                gdk_device_get_source (source_device) == GDK_SOURCE_TOUCHSCREEN)
 | ||
|         {
 | ||
|           /* Synthesize a leave notify event
 | ||
|            * whenever a touch device is released
 | ||
|            */
 | ||
|           pointer_info->need_touch_press_enter = TRUE;
 | ||
|           _gdk_synthesize_crossing_events (display,
 | ||
|                                            pointer_window, NULL,
 | ||
|                                            device, source_device,
 | ||
|                                            GDK_CROSSING_TOUCH_END,
 | ||
|                                            toplevel_x, toplevel_y,
 | ||
|                                            state, time_, NULL,
 | ||
|                                            serial, FALSE);
 | ||
|         }
 | ||
|       return TRUE;
 | ||
| 
 | ||
|     case GDK_TOUCH_BEGIN:
 | ||
|     case GDK_TOUCH_END:
 | ||
|     case GDK_TOUCH_CANCEL:
 | ||
|       convert_toplevel_coords_to_window (event_win,
 | ||
|                                          toplevel_x, toplevel_y,
 | ||
|                                          &event->button.x, &event->button.y);
 | ||
|       gdk_event_get_root_coords (source_event,
 | ||
| 				 &event->touch.x_root,
 | ||
| 				 &event->touch.y_root);
 | ||
|       event->touch.state = state;
 | ||
|       event->touch.device = source_event->touch.device;
 | ||
|       event->touch.axes = g_memdup (source_event->touch.axes,
 | ||
|                                      sizeof (gdouble) * gdk_device_get_n_axes (source_event->touch.device));
 | ||
|       event->touch.sequence = source_event->touch.sequence;
 | ||
|       event->touch.emulating_pointer = source_event->touch.emulating_pointer;
 | ||
| 
 | ||
|       gdk_event_set_source_device (event, source_device);
 | ||
| 
 | ||
|       if (((type == GDK_TOUCH_END || type == GDK_TOUCH_CANCEL) &&
 | ||
|            gdk_event_get_pointer_emulated (source_event)) &&
 | ||
|            pointer_window == pointer_info->window_under_pointer &&
 | ||
|            gdk_device_get_source (source_device) == GDK_SOURCE_TOUCHSCREEN)
 | ||
|         {
 | ||
|           /* Synthesize a leave notify event
 | ||
|            * whenever a touch device is released
 | ||
|            */
 | ||
|           pointer_info->need_touch_press_enter = TRUE;
 | ||
|           _gdk_synthesize_crossing_events (display,
 | ||
|                                            pointer_window, NULL,
 | ||
|                                            device, source_device,
 | ||
|                                            GDK_CROSSING_TOUCH_END,
 | ||
|                                            toplevel_x, toplevel_y,
 | ||
|                                            state, time_, NULL,
 | ||
|                                            serial, FALSE);
 | ||
|         }
 | ||
|       return TRUE;
 | ||
| 
 | ||
|     case GDK_SCROLL:
 | ||
|       event->scroll.direction = source_event->scroll.direction;
 | ||
|       convert_toplevel_coords_to_window (event_win,
 | ||
| 					 toplevel_x, toplevel_y,
 | ||
| 					 &event->scroll.x, &event->scroll.y);
 | ||
|       event->scroll.x_root = source_event->scroll.x_root;
 | ||
|       event->scroll.y_root = source_event->scroll.y_root;
 | ||
|       event->scroll.state = state;
 | ||
|       event->scroll.device = source_event->scroll.device;
 | ||
|       event->scroll.delta_x = source_event->scroll.delta_x;
 | ||
|       event->scroll.delta_y = source_event->scroll.delta_y;
 | ||
|       event->scroll.is_stop = source_event->scroll.is_stop;
 | ||
|       gdk_event_set_source_device (event, source_device);
 | ||
|       return TRUE;
 | ||
| 
 | ||
|     default:
 | ||
|       return FALSE;
 | ||
|     }
 | ||
| 
 | ||
|   return TRUE; /* Always unlink original, we want to obey the emulated event mask */
 | ||
| }
 | ||
| 
 | ||
| static gboolean
 | ||
| proxy_gesture_event (GdkEvent *source_event,
 | ||
|                      gulong    serial)
 | ||
| {
 | ||
|   GdkWindow *toplevel_window, *pointer_window, *event_win;
 | ||
|   GdkDevice *device, *source_device;
 | ||
|   gdouble toplevel_x, toplevel_y;
 | ||
|   GdkDisplay *display;
 | ||
|   GdkEventMask evmask;
 | ||
|   GdkEventType evtype;
 | ||
|   GdkEvent *event;
 | ||
|   guint state;
 | ||
| 
 | ||
|   evtype = source_event->any.type;
 | ||
|   gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
 | ||
|   gdk_event_get_state (source_event, &state);
 | ||
|   device = gdk_event_get_device (source_event);
 | ||
|   source_device = gdk_event_get_source_device (source_event);
 | ||
|   display = gdk_window_get_display (source_event->any.window);
 | ||
|   toplevel_window = convert_native_coords_to_toplevel (source_event->any.window,
 | ||
| 						       toplevel_x, toplevel_y,
 | ||
| 						       &toplevel_x, &toplevel_y);
 | ||
| 
 | ||
|   pointer_window = get_pointer_window (display, toplevel_window, device,
 | ||
| 				       toplevel_x, toplevel_y,
 | ||
| 				       serial);
 | ||
| 
 | ||
|   event_win = get_event_window (display, device, NULL,
 | ||
|                                 pointer_window, evtype, state,
 | ||
|                                 &evmask, FALSE, serial);
 | ||
|   if (!event_win)
 | ||
|     return TRUE;
 | ||
| 
 | ||
|   if ((evmask & GDK_TOUCHPAD_GESTURE_MASK) == 0)
 | ||
|     return TRUE;
 | ||
| 
 | ||
|   event = _gdk_make_event (event_win, evtype, source_event, FALSE);
 | ||
|   gdk_event_set_device (event, device);
 | ||
|   gdk_event_set_source_device (event, source_device);
 | ||
|   gdk_event_set_seat (event, gdk_device_get_seat (device));
 | ||
| 
 | ||
|   switch (evtype)
 | ||
|     {
 | ||
|     case GDK_TOUCHPAD_SWIPE:
 | ||
|       convert_toplevel_coords_to_window (event_win,
 | ||
|                                          toplevel_x, toplevel_y,
 | ||
|                                          &event->touchpad_swipe.x,
 | ||
|                                          &event->touchpad_swipe.y);
 | ||
|       gdk_event_get_root_coords (source_event,
 | ||
| 				 &event->touchpad_swipe.x_root,
 | ||
| 				 &event->touchpad_swipe.y_root);
 | ||
|       event->touchpad_swipe.dx = source_event->touchpad_swipe.dx;
 | ||
|       event->touchpad_swipe.dy = source_event->touchpad_swipe.dy;
 | ||
|       event->touchpad_swipe.n_fingers = source_event->touchpad_swipe.n_fingers;
 | ||
|       event->touchpad_swipe.phase = source_event->touchpad_swipe.phase;
 | ||
|       break;
 | ||
| 
 | ||
|     case GDK_TOUCHPAD_PINCH:
 | ||
|       convert_toplevel_coords_to_window (event_win,
 | ||
|                                          toplevel_x, toplevel_y,
 | ||
|                                          &event->touchpad_pinch.x,
 | ||
|                                          &event->touchpad_pinch.y);
 | ||
|       gdk_event_get_root_coords (source_event,
 | ||
| 				 &event->touchpad_pinch.x_root,
 | ||
| 				 &event->touchpad_pinch.y_root);
 | ||
|       event->touchpad_pinch.dx = source_event->touchpad_pinch.dx;
 | ||
|       event->touchpad_pinch.dy = source_event->touchpad_pinch.dy;
 | ||
|       event->touchpad_pinch.scale = source_event->touchpad_pinch.scale;
 | ||
|       event->touchpad_pinch.angle_delta = source_event->touchpad_pinch.angle_delta;
 | ||
|       event->touchpad_pinch.n_fingers = source_event->touchpad_pinch.n_fingers;
 | ||
|       event->touchpad_pinch.phase = source_event->touchpad_pinch.phase;
 | ||
|       break;
 | ||
| 
 | ||
|     default:
 | ||
|       break;
 | ||
|     }
 | ||
| 
 | ||
|   return TRUE;
 | ||
| }
 | ||
| 
 | ||
| #ifdef DEBUG_WINDOW_PRINTING
 | ||
| 
 | ||
| #ifdef GDK_WINDOWING_X11
 | ||
| #include "x11/gdkx.h"
 | ||
| #endif
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_print (GdkWindow *window,
 | ||
| 		  int indent)
 | ||
| {
 | ||
|   char *s;
 | ||
|   const char *window_types[] = {
 | ||
|     "root",
 | ||
|     "toplevel",
 | ||
|     "child",
 | ||
|     "dialog",
 | ||
|     "temp",
 | ||
|     "foreign",
 | ||
|     "offscreen"
 | ||
|   };
 | ||
| 
 | ||
|   g_print ("%*s%p: [%s] %d,%d %dx%d", indent, "", window,
 | ||
| 	   window->user_data ? g_type_name_from_instance (window->user_data) : "no widget",
 | ||
| 	   window->x, window->y,
 | ||
| 	   window->width, window->height
 | ||
| 	   );
 | ||
| 
 | ||
|   if (gdk_window_has_impl (window))
 | ||
|     {
 | ||
| #ifdef GDK_WINDOWING_X11
 | ||
|       g_print (" impl(0x%lx)", gdk_x11_window_get_xid (window));
 | ||
| #endif
 | ||
|     }
 | ||
| 
 | ||
|   if (window->window_type != GDK_WINDOW_CHILD)
 | ||
|     g_print (" %s", window_types[window->window_type]);
 | ||
| 
 | ||
|   if (window->input_only)
 | ||
|     g_print (" input-only");
 | ||
| 
 | ||
|   if (window->shaped)
 | ||
|     g_print (" shaped");
 | ||
| 
 | ||
|   if (!gdk_window_is_visible ((GdkWindow *)window))
 | ||
|     g_print (" hidden");
 | ||
| 
 | ||
|   g_print (" abs[%d,%d]",
 | ||
| 	   window->abs_x, window->abs_y);
 | ||
| 
 | ||
|   if (window->alpha != 255)
 | ||
|     g_print (" alpha[%d]",
 | ||
| 	   window->alpha);
 | ||
| 
 | ||
|   s = print_region (window->clip_region);
 | ||
|   g_print (" clipbox[%s]", s);
 | ||
| 
 | ||
|   g_print ("\n");
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_print_tree (GdkWindow *window,
 | ||
| 		       int indent,
 | ||
| 		       gboolean include_input_only)
 | ||
| {
 | ||
|   GList *l;
 | ||
| 
 | ||
|   if (window->input_only && !include_input_only)
 | ||
|     return;
 | ||
| 
 | ||
|   gdk_window_print (window, indent);
 | ||
| 
 | ||
|   for (l = window->children; l != NULL; l = l->next)
 | ||
|     gdk_window_print_tree (l->data, indent + 4, include_input_only);
 | ||
| }
 | ||
| 
 | ||
| #endif /* DEBUG_WINDOW_PRINTING */
 | ||
| 
 | ||
| void
 | ||
| _gdk_windowing_got_event (GdkDisplay *display,
 | ||
|                           GList      *event_link,
 | ||
|                           GdkEvent   *event,
 | ||
|                           gulong      serial)
 | ||
| {
 | ||
|   GdkWindow *event_window;
 | ||
|   gdouble x, y;
 | ||
|   gboolean unlink_event = FALSE;
 | ||
|   GdkDeviceGrabInfo *button_release_grab;
 | ||
|   GdkPointerWindowInfo *pointer_info = NULL;
 | ||
|   GdkDevice *device, *source_device;
 | ||
|   gboolean is_toplevel;
 | ||
| 
 | ||
|   _gdk_display_update_last_event (display, event);
 | ||
| 
 | ||
|   device = gdk_event_get_device (event);
 | ||
|   source_device = gdk_event_get_source_device (event);
 | ||
| 
 | ||
|   if (device)
 | ||
|     {
 | ||
|       if (gdk_device_get_source (device) != GDK_SOURCE_KEYBOARD &&
 | ||
|           gdk_device_get_source (device) != GDK_SOURCE_TABLET_PAD)
 | ||
|         {
 | ||
|           pointer_info = _gdk_display_get_pointer_info (display, device);
 | ||
| 
 | ||
|           if (source_device != pointer_info->last_slave &&
 | ||
|               gdk_device_get_device_type (source_device) == GDK_DEVICE_TYPE_SLAVE)
 | ||
|             g_set_object (&pointer_info->last_slave, source_device);
 | ||
|           else if (pointer_info->last_slave)
 | ||
|             source_device = pointer_info->last_slave;
 | ||
|         }
 | ||
| 
 | ||
|       _gdk_display_device_grab_update (display, device, source_device, serial);
 | ||
| 
 | ||
|       if (gdk_device_get_input_mode (device) == GDK_MODE_DISABLED ||
 | ||
|           !_gdk_display_check_grab_ownership (display, device, serial))
 | ||
|         {
 | ||
|           /* Device events are blocked by another
 | ||
|            * device grab, or the device is disabled
 | ||
|            */
 | ||
|           unlink_event = TRUE;
 | ||
|           goto out;
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|   event_window = event->any.window;
 | ||
|   if (!event_window)
 | ||
|     goto out;
 | ||
| 
 | ||
| #ifdef DEBUG_WINDOW_PRINTING
 | ||
|   if (event->type == GDK_KEY_PRESS &&
 | ||
|       (event->key.keyval == 0xa7 ||
 | ||
|        event->key.keyval == 0xbd))
 | ||
|     {
 | ||
|       gdk_window_print_tree (event_window, 0, event->key.keyval == 0xbd);
 | ||
|     }
 | ||
| #endif
 | ||
| 
 | ||
|   if (event->type == GDK_VISIBILITY_NOTIFY)
 | ||
|     {
 | ||
|       event_window->native_visibility = event->visibility.state;
 | ||
|       gdk_window_update_visibility_recursively (event_window, event_window);
 | ||
|       goto out;
 | ||
|     }
 | ||
| 
 | ||
|   if (!(event->type == GDK_TOUCH_CANCEL ||
 | ||
|         is_button_type (event->type) ||
 | ||
|         is_motion_type (event->type) ||
 | ||
|         is_gesture_type (event->type)) ||
 | ||
|       event_window->window_type == GDK_WINDOW_ROOT)
 | ||
|     goto out;
 | ||
| 
 | ||
|   is_toplevel = gdk_window_is_toplevel (event_window);
 | ||
| 
 | ||
|   if ((event->type == GDK_ENTER_NOTIFY ||
 | ||
|        event->type == GDK_LEAVE_NOTIFY) &&
 | ||
|       (event->crossing.mode == GDK_CROSSING_GRAB ||
 | ||
|        event->crossing.mode == GDK_CROSSING_UNGRAB) &&
 | ||
|       (_gdk_display_has_device_grab (display, device, serial) ||
 | ||
|        event->crossing.detail == GDK_NOTIFY_INFERIOR))
 | ||
|     {
 | ||
|       /* We synthesize all crossing events due to grabs ourselves,
 | ||
|        * so we ignore the native ones caused by our native pointer_grab
 | ||
|        * calls. Otherwise we would proxy these crossing event and cause
 | ||
|        * multiple copies of crossing events for grabs.
 | ||
|        *
 | ||
|        * We do want to handle grabs from other clients though, as for
 | ||
|        * instance alt-tab in metacity causes grabs like these and
 | ||
|        * we want to handle those. Thus the has_pointer_grab check.
 | ||
|        *
 | ||
|        * Implicit grabs on child windows create some grabbing events
 | ||
|        * that are sent before the button press. This means we can't
 | ||
|        * detect these with the has_pointer_grab check (as the implicit
 | ||
|        * grab is only noticed when we get button press event), so we
 | ||
|        * detect these events by checking for INFERIOR enter or leave
 | ||
|        * events. These should never be a problem to filter out.
 | ||
|        */
 | ||
| 
 | ||
|       /* We ended up in this window after some (perhaps other clients)
 | ||
|        * grab, so update the toplevel_under_window state
 | ||
|        */
 | ||
|       if (pointer_info && is_toplevel &&
 | ||
|           event->type == GDK_ENTER_NOTIFY &&
 | ||
|           event->crossing.mode == GDK_CROSSING_UNGRAB)
 | ||
|         {
 | ||
|           if (pointer_info->toplevel_under_pointer)
 | ||
|             g_object_unref (pointer_info->toplevel_under_pointer);
 | ||
|           pointer_info->toplevel_under_pointer = g_object_ref (event_window);
 | ||
|         }
 | ||
| 
 | ||
|       unlink_event = TRUE;
 | ||
|       goto out;
 | ||
|     }
 | ||
| 
 | ||
|   /* Track toplevel_under_pointer */
 | ||
|   if (pointer_info && is_toplevel)
 | ||
|     {
 | ||
|       if (event->type == GDK_ENTER_NOTIFY &&
 | ||
|           event->crossing.detail != GDK_NOTIFY_INFERIOR)
 | ||
|         {
 | ||
|           if (pointer_info->toplevel_under_pointer)
 | ||
|             g_object_unref (pointer_info->toplevel_under_pointer);
 | ||
|           pointer_info->toplevel_under_pointer = g_object_ref (event_window);
 | ||
|         }
 | ||
|       else if (event->type == GDK_LEAVE_NOTIFY &&
 | ||
|                event->crossing.detail != GDK_NOTIFY_INFERIOR &&
 | ||
|                pointer_info->toplevel_under_pointer == event_window)
 | ||
|         {
 | ||
|           if (pointer_info->toplevel_under_pointer)
 | ||
|             g_object_unref (pointer_info->toplevel_under_pointer);
 | ||
|           pointer_info->toplevel_under_pointer = NULL;
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|   if (pointer_info &&
 | ||
|       (!is_touch_type (event->type) ||
 | ||
|        gdk_event_get_pointer_emulated (event)))
 | ||
|     {
 | ||
|       guint old_state, old_button;
 | ||
| 
 | ||
|       /* Store last pointer window and position/state */
 | ||
|       old_state = pointer_info->state;
 | ||
|       old_button = pointer_info->button;
 | ||
| 
 | ||
|       gdk_event_get_coords (event, &x, &y);
 | ||
|       convert_native_coords_to_toplevel (event_window, x, y,  &x, &y);
 | ||
|       pointer_info->toplevel_x = x;
 | ||
|       pointer_info->toplevel_y = y;
 | ||
|       gdk_event_get_state (event, &pointer_info->state);
 | ||
| 
 | ||
|       if (event->type == GDK_BUTTON_PRESS ||
 | ||
|           event->type == GDK_BUTTON_RELEASE)
 | ||
|         pointer_info->button = event->button.button;
 | ||
|       else if (event->type == GDK_TOUCH_BEGIN ||
 | ||
|                event->type == GDK_TOUCH_END)
 | ||
|         pointer_info->button = 1;
 | ||
| 
 | ||
|       if (device &&
 | ||
|           (pointer_info->state != old_state ||
 | ||
|            pointer_info->button != old_button))
 | ||
|         _gdk_display_enable_motion_hints (display, device);
 | ||
|     }
 | ||
| 
 | ||
|   if (is_motion_type (event->type))
 | ||
|     unlink_event = proxy_pointer_event (display, event, serial);
 | ||
|   else if (is_button_type (event->type))
 | ||
|     unlink_event = proxy_button_event (event, serial);
 | ||
|   else if (is_gesture_type (event->type))
 | ||
|     unlink_event = proxy_gesture_event (event, serial);
 | ||
| 
 | ||
|   if ((event->type == GDK_BUTTON_RELEASE ||
 | ||
|        event->type == GDK_TOUCH_CANCEL ||
 | ||
|        event->type == GDK_TOUCH_END) &&
 | ||
|       !event->any.send_event)
 | ||
|     {
 | ||
|       GdkEventSequence *sequence;
 | ||
| 
 | ||
|       sequence = gdk_event_get_event_sequence (event);
 | ||
|       if (sequence)
 | ||
|         {
 | ||
|           _gdk_display_end_touch_grab (display, device, sequence);
 | ||
|         }
 | ||
| 
 | ||
|       if (event->type == GDK_BUTTON_RELEASE ||
 | ||
|           gdk_event_get_pointer_emulated (event))
 | ||
|         {
 | ||
|           button_release_grab =
 | ||
|             _gdk_display_has_device_grab (display, device, serial);
 | ||
| 
 | ||
|           if (button_release_grab &&
 | ||
|               button_release_grab->implicit &&
 | ||
|               (event->button.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
 | ||
|             {
 | ||
|               button_release_grab->serial_end = serial;
 | ||
|               button_release_grab->implicit_ungrab = FALSE;
 | ||
|               _gdk_display_device_grab_update (display, device, source_device, serial);
 | ||
|             }
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|  out:
 | ||
|   if (unlink_event)
 | ||
|     {
 | ||
|       _gdk_event_queue_remove_link (display, event_link);
 | ||
|       g_list_free_1 (event_link);
 | ||
|       gdk_event_free (event);
 | ||
|     }
 | ||
| 
 | ||
|   /* This does two things - first it sees if there are motions at the
 | ||
|    * end of the queue that can be compressed. Second, if there is just
 | ||
|    * a single motion that won't be dispatched because it is a compression
 | ||
|    * candidate it queues up flushing the event queue.
 | ||
|    */
 | ||
|   _gdk_event_queue_handle_motion_compression (display);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_create_similar_surface:
 | ||
|  * @window: window to make new surface similar to
 | ||
|  * @content: the content for the new surface
 | ||
|  * @width: width of the new surface
 | ||
|  * @height: height of the new surface
 | ||
|  *
 | ||
|  * Create a new surface that is as compatible as possible with the
 | ||
|  * given @window. For example the new surface will have the same
 | ||
|  * fallback resolution and font options as @window. Generally, the new
 | ||
|  * surface will also use the same backend as @window, unless that is
 | ||
|  * not possible for some reason. The type of the returned surface may
 | ||
|  * be examined with cairo_surface_get_type().
 | ||
|  *
 | ||
|  * Initially the surface contents are all 0 (transparent if contents
 | ||
|  * have transparency, black otherwise.)
 | ||
|  *
 | ||
|  * Returns: a pointer to the newly allocated surface. The caller
 | ||
|  * owns the surface and should call cairo_surface_destroy() when done
 | ||
|  * with it.
 | ||
|  *
 | ||
|  * This function always returns a valid pointer, but it will return a
 | ||
|  * pointer to a “nil” surface if @other is already in an error state
 | ||
|  * or any other error occurs.
 | ||
|  *
 | ||
|  * Since: 2.22
 | ||
|  **/
 | ||
| cairo_surface_t *
 | ||
| gdk_window_create_similar_surface (GdkWindow *     window,
 | ||
|                                    cairo_content_t content,
 | ||
|                                    int             width,
 | ||
|                                    int             height)
 | ||
| {
 | ||
|   GdkDisplay *display;
 | ||
|   GdkRenderingMode rendering_mode;
 | ||
|   cairo_surface_t *window_surface, *surface;
 | ||
|   double sx, sy;
 | ||
| 
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 | ||
| 
 | ||
|   window_surface = gdk_window_ref_impl_surface (window);
 | ||
|   sx = sy = 1;
 | ||
|   cairo_surface_get_device_scale (window_surface, &sx, &sy);
 | ||
| 
 | ||
|   display = gdk_window_get_display (window);
 | ||
|   rendering_mode = gdk_display_get_rendering_mode (display);
 | ||
| 
 | ||
|   switch (rendering_mode)
 | ||
|   {
 | ||
|     case GDK_RENDERING_MODE_RECORDING:
 | ||
|       {
 | ||
|         cairo_rectangle_t rect = { 0, 0, width * sx, height *sy };
 | ||
|         surface = cairo_recording_surface_create (content, &rect);
 | ||
|         cairo_surface_set_device_scale (surface, sx, sy);
 | ||
|       }
 | ||
|       break;
 | ||
|     case GDK_RENDERING_MODE_IMAGE:
 | ||
|       surface = cairo_image_surface_create (content == CAIRO_CONTENT_COLOR ? CAIRO_FORMAT_RGB24 :
 | ||
|                                             content == CAIRO_CONTENT_ALPHA ? CAIRO_FORMAT_A8 : CAIRO_FORMAT_ARGB32,
 | ||
|                                             width * sx, height * sy);
 | ||
|       cairo_surface_set_device_scale (surface, sx, sy);
 | ||
|       break;
 | ||
|     case GDK_RENDERING_MODE_SIMILAR:
 | ||
|     default:
 | ||
|       surface = cairo_surface_create_similar (window_surface,
 | ||
|                                               content,
 | ||
|                                               width, height);
 | ||
|       break;
 | ||
|   }
 | ||
| 
 | ||
|   cairo_surface_destroy (window_surface);
 | ||
| 
 | ||
|   return surface;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_create_similar_image_surface:
 | ||
|  * @window: (nullable): window to make new surface similar to, or
 | ||
|  *   %NULL if none
 | ||
|  * @format: the format for the new surface
 | ||
|  * @width: width of the new surface
 | ||
|  * @height: height of the new surface
 | ||
|  * @scale: the scale of the new surface, or 0 to use same as @window
 | ||
|  *
 | ||
|  * Create a new image surface that is efficient to draw on the
 | ||
|  * given @window.
 | ||
|  *
 | ||
|  * Initially the surface contents are all 0 (transparent if contents
 | ||
|  * have transparency, black otherwise.)
 | ||
|  *
 | ||
|  * The @width and @height of the new surface are not affected by
 | ||
|  * the scaling factor of the @window, or by the @scale argument; they
 | ||
|  * are the size of the surface in device pixels. If you wish to create
 | ||
|  * an image surface capable of holding the contents of @window you can
 | ||
|  * use:
 | ||
|  *
 | ||
|  * |[<!-- language="C" -->
 | ||
|  *   int scale = gdk_window_get_scale_factor (window);
 | ||
|  *   int width = gdk_window_get_width (window) * scale;
 | ||
|  *   int height = gdk_window_get_height (window) * scale;
 | ||
|  *
 | ||
|  *   // format is set elsewhere
 | ||
|  *   cairo_surface_t *surface =
 | ||
|  *     gdk_window_create_similar_image_surface (window,
 | ||
|  *                                              format,
 | ||
|  *                                              width, height,
 | ||
|  *                                              scale);
 | ||
|  * ]|
 | ||
|  *
 | ||
|  * Note that unlike cairo_surface_create_similar_image(), the new
 | ||
|  * surface's device scale is set to @scale, or to the scale factor of
 | ||
|  * @window if @scale is 0.
 | ||
|  *
 | ||
|  * Returns: a pointer to the newly allocated surface. The caller
 | ||
|  * owns the surface and should call cairo_surface_destroy() when done
 | ||
|  * with it.
 | ||
|  *
 | ||
|  * This function always returns a valid pointer, but it will return a
 | ||
|  * pointer to a “nil” surface if @other is already in an error state
 | ||
|  * or any other error occurs.
 | ||
|  *
 | ||
|  * Since: 3.10
 | ||
|  **/
 | ||
| cairo_surface_t *
 | ||
| gdk_window_create_similar_image_surface (GdkWindow *     window,
 | ||
| 					 cairo_format_t  format,
 | ||
| 					 int             width,
 | ||
| 					 int             height,
 | ||
| 					 int             scale)
 | ||
| {
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
|   cairo_surface_t *window_surface, *surface;
 | ||
|   GdkDisplay *display;
 | ||
|   GdkScreen *screen;
 | ||
| 
 | ||
|   g_return_val_if_fail (window ==NULL || GDK_IS_WINDOW (window), NULL);
 | ||
| 
 | ||
|   if (window == NULL)
 | ||
|     {
 | ||
|       display = gdk_display_get_default ();
 | ||
|       screen = gdk_display_get_default_screen (display);
 | ||
|       window = gdk_screen_get_root_window (screen);
 | ||
|     }
 | ||
| 
 | ||
|   impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
| 
 | ||
|   if (impl_class->create_similar_image_surface)
 | ||
|     surface = impl_class->create_similar_image_surface (window, format, width, height);
 | ||
|   else
 | ||
|     {
 | ||
|       window_surface = gdk_window_ref_impl_surface (window);
 | ||
|       surface =
 | ||
|         cairo_surface_create_similar_image (window_surface,
 | ||
|                                             format,
 | ||
|                                             width,
 | ||
|                                             height);
 | ||
|       cairo_surface_destroy (window_surface);
 | ||
|     }
 | ||
| 
 | ||
|   if (scale == 0)
 | ||
|     scale = gdk_window_get_scale_factor (window);
 | ||
| 
 | ||
|   cairo_surface_set_device_scale (surface, scale, scale);
 | ||
| 
 | ||
|   return surface;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_focus:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @timestamp: timestamp of the event triggering the window focus
 | ||
|  *
 | ||
|  * Sets keyboard focus to @window. In most cases, gtk_window_present_with_time()
 | ||
|  * should be used on a #GtkWindow, rather than calling this function.
 | ||
|  *
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_focus (GdkWindow *window,
 | ||
|                   guint32    timestamp)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->focus (window, timestamp);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_type_hint:
 | ||
|  * @window: A toplevel #GdkWindow
 | ||
|  * @hint: A hint of the function this window will have
 | ||
|  *
 | ||
|  * The application can use this call to provide a hint to the window
 | ||
|  * manager about the functionality of a window. The window manager
 | ||
|  * can use this information when determining the decoration and behaviour
 | ||
|  * of the window.
 | ||
|  *
 | ||
|  * The hint must be set before the window is mapped.
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_set_type_hint (GdkWindow        *window,
 | ||
| 			  GdkWindowTypeHint hint)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_type_hint (window, hint);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_type_hint:
 | ||
|  * @window: A toplevel #GdkWindow
 | ||
|  *
 | ||
|  * This function returns the type hint set for a window.
 | ||
|  *
 | ||
|  * Returns: The type hint set for @window
 | ||
|  *
 | ||
|  * Since: 2.10
 | ||
|  **/
 | ||
| GdkWindowTypeHint
 | ||
| gdk_window_get_type_hint (GdkWindow *window)
 | ||
| {
 | ||
|   return GDK_WINDOW_IMPL_GET_CLASS (window->impl)->get_type_hint (window);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_modal_hint:
 | ||
|  * @window: A toplevel #GdkWindow
 | ||
|  * @modal: %TRUE if the window is modal, %FALSE otherwise.
 | ||
|  *
 | ||
|  * The application can use this hint to tell the window manager
 | ||
|  * that a certain window has modal behaviour. The window manager
 | ||
|  * can use this information to handle modal windows in a special
 | ||
|  * way.
 | ||
|  *
 | ||
|  * You should only use this on windows for which you have
 | ||
|  * previously called gdk_window_set_transient_for()
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_set_modal_hint (GdkWindow *window,
 | ||
| 			   gboolean   modal)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_modal_hint (window, modal);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_skip_taskbar_hint:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  * @skips_taskbar: %TRUE to skip the taskbar
 | ||
|  *
 | ||
|  * Toggles whether a window should appear in a task list or window
 | ||
|  * list. If a window’s semantic type as specified with
 | ||
|  * gdk_window_set_type_hint() already fully describes the window, this
 | ||
|  * function should not be called in addition,
 | ||
|  * instead you should allow the window to be treated according to
 | ||
|  * standard policy for its semantic type.
 | ||
|  *
 | ||
|  * Since: 2.2
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_set_skip_taskbar_hint (GdkWindow *window,
 | ||
|                                   gboolean   skips_taskbar)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_skip_taskbar_hint (window, skips_taskbar);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_skip_pager_hint:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  * @skips_pager: %TRUE to skip the pager
 | ||
|  *
 | ||
|  * Toggles whether a window should appear in a pager (workspace
 | ||
|  * switcher, or other desktop utility program that displays a small
 | ||
|  * thumbnail representation of the windows on the desktop). If a
 | ||
|  * window’s semantic type as specified with gdk_window_set_type_hint()
 | ||
|  * already fully describes the window, this function should
 | ||
|  * not be called in addition, instead you should
 | ||
|  * allow the window to be treated according to standard policy for
 | ||
|  * its semantic type.
 | ||
|  *
 | ||
|  * Since: 2.2
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_set_skip_pager_hint (GdkWindow *window,
 | ||
|                                 gboolean   skips_pager)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_skip_pager_hint (window, skips_pager);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_urgency_hint:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  * @urgent: %TRUE if the window is urgent
 | ||
|  *
 | ||
|  * Toggles whether a window needs the user's
 | ||
|  * urgent attention.
 | ||
|  *
 | ||
|  * Since: 2.8
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_set_urgency_hint (GdkWindow *window,
 | ||
| 			     gboolean   urgent)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_urgency_hint (window, urgent);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_geometry_hints:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  * @geometry: geometry hints
 | ||
|  * @geom_mask: bitmask indicating fields of @geometry to pay attention to
 | ||
|  *
 | ||
|  * Sets the geometry hints for @window. Hints flagged in @geom_mask
 | ||
|  * are set, hints not flagged in @geom_mask are unset.
 | ||
|  * To unset all hints, use a @geom_mask of 0 and a @geometry of %NULL.
 | ||
|  *
 | ||
|  * This function provides hints to the windowing system about
 | ||
|  * acceptable sizes for a toplevel window. The purpose of
 | ||
|  * this is to constrain user resizing, but the windowing system
 | ||
|  * will typically  (but is not required to) also constrain the
 | ||
|  * current size of the window to the provided values and
 | ||
|  * constrain programatic resizing via gdk_window_resize() or
 | ||
|  * gdk_window_move_resize().
 | ||
|  *
 | ||
|  * Note that on X11, this effect has no effect on windows
 | ||
|  * of type %GDK_WINDOW_TEMP or windows where override redirect
 | ||
|  * has been turned on via gdk_window_set_override_redirect()
 | ||
|  * since these windows are not resizable by the user.
 | ||
|  *
 | ||
|  * Since you can’t count on the windowing system doing the
 | ||
|  * constraints for programmatic resizes, you should generally
 | ||
|  * call gdk_window_constrain_size() yourself to determine
 | ||
|  * appropriate sizes.
 | ||
|  *
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_set_geometry_hints (GdkWindow         *window,
 | ||
| 			       const GdkGeometry *geometry,
 | ||
| 			       GdkWindowHints     geom_mask)
 | ||
| {
 | ||
|   g_return_if_fail (geometry != NULL || geom_mask == 0);
 | ||
| 
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_geometry_hints (window, geometry, geom_mask);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_title:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  * @title: title of @window
 | ||
|  *
 | ||
|  * Sets the title of a toplevel window, to be displayed in the titlebar.
 | ||
|  * If you haven’t explicitly set the icon name for the window
 | ||
|  * (using gdk_window_set_icon_name()), the icon name will be set to
 | ||
|  * @title as well. @title must be in UTF-8 encoding (as with all
 | ||
|  * user-readable strings in GDK/GTK+). @title may not be %NULL.
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_set_title (GdkWindow   *window,
 | ||
| 		      const gchar *title)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_title (window, title);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_role:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  * @role: a string indicating its role
 | ||
|  *
 | ||
|  * When using GTK+, typically you should use gtk_window_set_role() instead
 | ||
|  * of this low-level function.
 | ||
|  *
 | ||
|  * The window manager and session manager use a window’s role to
 | ||
|  * distinguish it from other kinds of window in the same application.
 | ||
|  * When an application is restarted after being saved in a previous
 | ||
|  * session, all windows with the same title and role are treated as
 | ||
|  * interchangeable.  So if you have two windows with the same title
 | ||
|  * that should be distinguished for session management purposes, you
 | ||
|  * should set the role on those windows. It doesn’t matter what string
 | ||
|  * you use for the role, as long as you have a different role for each
 | ||
|  * non-interchangeable kind of window.
 | ||
|  *
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_set_role (GdkWindow   *window,
 | ||
| 		     const gchar *role)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_role (window, role);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_startup_id:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  * @startup_id: a string with startup-notification identifier
 | ||
|  *
 | ||
|  * When using GTK+, typically you should use gtk_window_set_startup_id()
 | ||
|  * instead of this low-level function.
 | ||
|  *
 | ||
|  * Since: 2.12
 | ||
|  *
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_set_startup_id (GdkWindow   *window,
 | ||
| 			   const gchar *startup_id)
 | ||
| {
 | ||
|   GdkWindowImplClass *klass = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
| 
 | ||
|   if (klass->set_startup_id)
 | ||
|     klass->set_startup_id (window, startup_id);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_transient_for:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  * @parent: another toplevel #GdkWindow
 | ||
|  *
 | ||
|  * Indicates to the window manager that @window is a transient dialog
 | ||
|  * associated with the application window @parent. This allows the
 | ||
|  * window manager to do things like center @window on @parent and
 | ||
|  * keep @window above @parent.
 | ||
|  *
 | ||
|  * See gtk_window_set_transient_for() if you’re using #GtkWindow or
 | ||
|  * #GtkDialog.
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_set_transient_for (GdkWindow *window,
 | ||
| 			      GdkWindow *parent)
 | ||
| {
 | ||
|   if (parent != NULL &&
 | ||
|       GDK_WINDOW_IMPL_GET_CLASS (window->impl) != GDK_WINDOW_IMPL_GET_CLASS (parent->impl))
 | ||
|     {
 | ||
|       return;
 | ||
|     }
 | ||
| 
 | ||
|   window->transient_for = parent;
 | ||
| 
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_transient_for (window, parent);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_root_origin:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  * @x: (out): return location for X position of window frame
 | ||
|  * @y: (out): return location for Y position of window frame
 | ||
|  *
 | ||
|  * Obtains the top-left corner of the window manager frame in root
 | ||
|  * window coordinates.
 | ||
|  *
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_get_root_origin (GdkWindow *window,
 | ||
| 			    gint      *x,
 | ||
| 			    gint      *y)
 | ||
| {
 | ||
|   GdkRectangle rect;
 | ||
| 
 | ||
|   gdk_window_get_frame_extents (window, &rect);
 | ||
| 
 | ||
|   if (x)
 | ||
|     *x = rect.x;
 | ||
| 
 | ||
|   if (y)
 | ||
|     *y = rect.y;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_frame_extents:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  * @rect: (out): rectangle to fill with bounding box of the window frame
 | ||
|  *
 | ||
|  * Obtains the bounding box of the window, including window manager
 | ||
|  * titlebar/borders if any. The frame position is given in root window
 | ||
|  * coordinates. To get the position of the window itself (rather than
 | ||
|  * the frame) in root window coordinates, use gdk_window_get_origin().
 | ||
|  *
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_get_frame_extents (GdkWindow    *window,
 | ||
|                               GdkRectangle *rect)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->get_frame_extents (window, rect);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_override_redirect:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  * @override_redirect: %TRUE if window should be override redirect
 | ||
|  *
 | ||
|  * An override redirect window is not under the control of the window manager.
 | ||
|  * This means it won’t have a titlebar, won’t be minimizable, etc. - it will
 | ||
|  * be entirely under the control of the application. The window manager
 | ||
|  * can’t see the override redirect window at all.
 | ||
|  *
 | ||
|  * Override redirect should only be used for short-lived temporary
 | ||
|  * windows, such as popup menus. #GtkMenu uses an override redirect
 | ||
|  * window in its implementation, for example.
 | ||
|  *
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_set_override_redirect (GdkWindow *window,
 | ||
| 				  gboolean override_redirect)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_override_redirect (window, override_redirect);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_accept_focus:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  * @accept_focus: %TRUE if the window should receive input focus
 | ||
|  *
 | ||
|  * Setting @accept_focus to %FALSE hints the desktop environment that the
 | ||
|  * window doesn’t want to receive input focus.
 | ||
|  *
 | ||
|  * On X, it is the responsibility of the window manager to interpret this
 | ||
|  * hint. ICCCM-compliant window manager usually respect it.
 | ||
|  *
 | ||
|  * Since: 2.4
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_set_accept_focus (GdkWindow *window,
 | ||
| 			     gboolean accept_focus)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_accept_focus (window, accept_focus);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_focus_on_map:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  * @focus_on_map: %TRUE if the window should receive input focus when mapped
 | ||
|  *
 | ||
|  * Setting @focus_on_map to %FALSE hints the desktop environment that the
 | ||
|  * window doesn’t want to receive input focus when it is mapped.
 | ||
|  * focus_on_map should be turned off for windows that aren’t triggered
 | ||
|  * interactively (such as popups from network activity).
 | ||
|  *
 | ||
|  * On X, it is the responsibility of the window manager to interpret
 | ||
|  * this hint. Window managers following the freedesktop.org window
 | ||
|  * manager extension specification should respect it.
 | ||
|  *
 | ||
|  * Since: 2.6
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_set_focus_on_map (GdkWindow *window,
 | ||
| 			     gboolean focus_on_map)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_focus_on_map (window, focus_on_map);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_event_compression:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @event_compression: %TRUE if motion events should be compressed
 | ||
|  *
 | ||
|  * Determines whether or not extra unprocessed motion events in
 | ||
|  * the event queue can be discarded. If %TRUE only the most recent
 | ||
|  * event will be delivered.
 | ||
|  *
 | ||
|  * Some types of applications, e.g. paint programs, need to see all
 | ||
|  * motion events and will benefit from turning off event compression.
 | ||
|  *
 | ||
|  * By default, event compression is enabled.
 | ||
|  *
 | ||
|  * Since: 3.12
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_set_event_compression (GdkWindow *window,
 | ||
|                                   gboolean   event_compression)
 | ||
| {
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   window->event_compression = !!event_compression;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_event_compression:
 | ||
|  * @window: a #GdkWindow
 | ||
|  *
 | ||
|  * Get the current event compression setting for this window.
 | ||
|  *
 | ||
|  * Returns: %TRUE if motion events will be compressed
 | ||
|  *
 | ||
|  * Since: 3.12
 | ||
|  **/
 | ||
| gboolean
 | ||
| gdk_window_get_event_compression (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), TRUE);
 | ||
| 
 | ||
|   return window->event_compression;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_icon_list:
 | ||
|  * @window: The #GdkWindow toplevel window to set the icon of.
 | ||
|  * @pixbufs: (transfer none) (element-type GdkPixbuf):
 | ||
|  *     A list of pixbufs, of different sizes.
 | ||
|  *
 | ||
|  * Sets a list of icons for the window. One of these will be used
 | ||
|  * to represent the window when it has been iconified. The icon is
 | ||
|  * usually shown in an icon box or some sort of task bar. Which icon
 | ||
|  * size is shown depends on the window manager. The window manager
 | ||
|  * can scale the icon  but setting several size icons can give better
 | ||
|  * image quality since the window manager may only need to scale the
 | ||
|  * icon by a small amount or not at all.
 | ||
|  *
 | ||
|  * Note that some platforms don't support window icons.
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_set_icon_list (GdkWindow *window,
 | ||
| 			  GList     *pixbufs)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_icon_list (window, pixbufs);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_icon_name:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  * @name: (allow-none): name of window while iconified (minimized)
 | ||
|  *
 | ||
|  * Windows may have a name used while minimized, distinct from the
 | ||
|  * name they display in their titlebar. Most of the time this is a bad
 | ||
|  * idea from a user interface standpoint. But you can set such a name
 | ||
|  * with this function, if you like.
 | ||
|  *
 | ||
|  * After calling this with a non-%NULL @name, calls to gdk_window_set_title()
 | ||
|  * will not update the icon title.
 | ||
|  *
 | ||
|  * Using %NULL for @name unsets the icon title; further calls to
 | ||
|  * gdk_window_set_title() will again update the icon title as well.
 | ||
|  *
 | ||
|  * Note that some platforms don't support window icons.
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_set_icon_name (GdkWindow   *window,
 | ||
| 			  const gchar *name)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_icon_name (window, name);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_iconify:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  *
 | ||
|  * Asks to iconify (minimize) @window. The window manager may choose
 | ||
|  * to ignore the request, but normally will honor it. Using
 | ||
|  * gtk_window_iconify() is preferred, if you have a #GtkWindow widget.
 | ||
|  *
 | ||
|  * This function only makes sense when @window is a toplevel window.
 | ||
|  *
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_iconify (GdkWindow *window)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->iconify (window);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_deiconify:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  *
 | ||
|  * Attempt to deiconify (unminimize) @window. On X11 the window manager may
 | ||
|  * choose to ignore the request to deiconify. When using GTK+,
 | ||
|  * use gtk_window_deiconify() instead of the #GdkWindow variant. Or better yet,
 | ||
|  * you probably want to use gtk_window_present_with_time(), which raises the window, focuses it,
 | ||
|  * unminimizes it, and puts it on the current desktop.
 | ||
|  *
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_deiconify (GdkWindow *window)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->deiconify (window);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_stick:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  *
 | ||
|  * “Pins” a window such that it’s on all workspaces and does not scroll
 | ||
|  * with viewports, for window managers that have scrollable viewports.
 | ||
|  * (When using #GtkWindow, gtk_window_stick() may be more useful.)
 | ||
|  *
 | ||
|  * On the X11 platform, this function depends on window manager
 | ||
|  * support, so may have no effect with many window managers. However,
 | ||
|  * GDK will do the best it can to convince the window manager to stick
 | ||
|  * the window. For window managers that don’t support this operation,
 | ||
|  * there’s nothing you can do to force it to happen.
 | ||
|  *
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_stick (GdkWindow *window)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->stick (window);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_unstick:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  *
 | ||
|  * Reverse operation for gdk_window_stick(); see gdk_window_stick(),
 | ||
|  * and gtk_window_unstick().
 | ||
|  *
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_unstick (GdkWindow *window)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->unstick (window);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_maximize:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  *
 | ||
|  * Maximizes the window. If the window was already maximized, then
 | ||
|  * this function does nothing.
 | ||
|  *
 | ||
|  * On X11, asks the window manager to maximize @window, if the window
 | ||
|  * manager supports this operation. Not all window managers support
 | ||
|  * this, and some deliberately ignore it or don’t have a concept of
 | ||
|  * “maximized”; so you can’t rely on the maximization actually
 | ||
|  * happening. But it will happen with most standard window managers,
 | ||
|  * and GDK makes a best effort to get it to happen.
 | ||
|  *
 | ||
|  * On Windows, reliably maximizes the window.
 | ||
|  *
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_maximize (GdkWindow *window)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->maximize (window);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_unmaximize:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  *
 | ||
|  * Unmaximizes the window. If the window wasn’t maximized, then this
 | ||
|  * function does nothing.
 | ||
|  *
 | ||
|  * On X11, asks the window manager to unmaximize @window, if the
 | ||
|  * window manager supports this operation. Not all window managers
 | ||
|  * support this, and some deliberately ignore it or don’t have a
 | ||
|  * concept of “maximized”; so you can’t rely on the unmaximization
 | ||
|  * actually happening. But it will happen with most standard window
 | ||
|  * managers, and GDK makes a best effort to get it to happen.
 | ||
|  *
 | ||
|  * On Windows, reliably unmaximizes the window.
 | ||
|  *
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_unmaximize (GdkWindow *window)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->unmaximize (window);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_fullscreen:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  *
 | ||
|  * Moves the window into fullscreen mode. This means the
 | ||
|  * window covers the entire screen and is above any panels
 | ||
|  * or task bars.
 | ||
|  *
 | ||
|  * If the window was already fullscreen, then this function does nothing.
 | ||
|  *
 | ||
|  * On X11, asks the window manager to put @window in a fullscreen
 | ||
|  * state, if the window manager supports this operation. Not all
 | ||
|  * window managers support this, and some deliberately ignore it or
 | ||
|  * don’t have a concept of “fullscreen”; so you can’t rely on the
 | ||
|  * fullscreenification actually happening. But it will happen with
 | ||
|  * most standard window managers, and GDK makes a best effort to get
 | ||
|  * it to happen.
 | ||
|  *
 | ||
|  * Since: 2.2
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_fullscreen (GdkWindow *window)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->fullscreen (window);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_fullscreen_on_monitor:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  * @monitor: Which monitor to display fullscreen on.
 | ||
|  *
 | ||
|  * Moves the window into fullscreen mode on the given monitor. This means
 | ||
|  * the window covers the entire screen and is above any panels or task bars.
 | ||
|  *
 | ||
|  * If the window was already fullscreen, then this function does nothing.
 | ||
|  * Since: UNRELEASED
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_fullscreen_on_monitor (GdkWindow      *window,
 | ||
|                                   gint            monitor)
 | ||
| {
 | ||
|   GdkDisplay *display = gdk_window_get_display (window);
 | ||
| 
 | ||
|   g_return_if_fail (monitor >= 0);
 | ||
|   g_return_if_fail (monitor < gdk_display_get_n_monitors (display));
 | ||
| 
 | ||
|   if (GDK_WINDOW_IMPL_GET_CLASS (window->impl)->fullscreen_on_monitor != NULL)
 | ||
|     GDK_WINDOW_IMPL_GET_CLASS (window->impl)->fullscreen_on_monitor (window, monitor);
 | ||
|   else
 | ||
|     GDK_WINDOW_IMPL_GET_CLASS (window->impl)->fullscreen (window);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_fullscreen_mode:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  * @mode: fullscreen mode
 | ||
|  *
 | ||
|  * Specifies whether the @window should span over all monitors (in a multi-head
 | ||
|  * setup) or only the current monitor when in fullscreen mode.
 | ||
|  *
 | ||
|  * The @mode argument is from the #GdkFullscreenMode enumeration.
 | ||
|  * If #GDK_FULLSCREEN_ON_ALL_MONITORS is specified, the fullscreen @window will
 | ||
|  * span over all monitors from the #GdkScreen.
 | ||
|  *
 | ||
|  * On X11, searches through the list of monitors from the #GdkScreen the ones
 | ||
|  * which delimit the 4 edges of the entire #GdkScreen and will ask the window
 | ||
|  * manager to span the @window over these monitors.
 | ||
|  *
 | ||
|  * If the XINERAMA extension is not available or not usable, this function
 | ||
|  * has no effect.
 | ||
|  *
 | ||
|  * Not all window managers support this, so you can’t rely on the fullscreen
 | ||
|  * window to span over the multiple monitors when #GDK_FULLSCREEN_ON_ALL_MONITORS
 | ||
|  * is specified.
 | ||
|  *
 | ||
|  * Since: 3.8
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_set_fullscreen_mode (GdkWindow        *window,
 | ||
|                                 GdkFullscreenMode mode)
 | ||
| {
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   if (window->fullscreen_mode != mode)
 | ||
|     {
 | ||
|       window->fullscreen_mode = mode;
 | ||
| 
 | ||
|       impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
|       if (impl_class->apply_fullscreen_mode != NULL)
 | ||
|         impl_class->apply_fullscreen_mode (window);
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_fullscreen_mode:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  *
 | ||
|  * Obtains the #GdkFullscreenMode of the @window.
 | ||
|  *
 | ||
|  * Returns: The #GdkFullscreenMode applied to the window when fullscreen.
 | ||
|  *
 | ||
|  * Since: 3.8
 | ||
|  **/
 | ||
| GdkFullscreenMode
 | ||
| gdk_window_get_fullscreen_mode (GdkWindow *window)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), GDK_FULLSCREEN_ON_CURRENT_MONITOR);
 | ||
| 
 | ||
|   return window->fullscreen_mode;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_unfullscreen:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  *
 | ||
|  * Moves the window out of fullscreen mode. If the window was not
 | ||
|  * fullscreen, does nothing.
 | ||
|  *
 | ||
|  * On X11, asks the window manager to move @window out of the fullscreen
 | ||
|  * state, if the window manager supports this operation. Not all
 | ||
|  * window managers support this, and some deliberately ignore it or
 | ||
|  * don’t have a concept of “fullscreen”; so you can’t rely on the
 | ||
|  * unfullscreenification actually happening. But it will happen with
 | ||
|  * most standard window managers, and GDK makes a best effort to get
 | ||
|  * it to happen.
 | ||
|  *
 | ||
|  * Since: 2.2
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_unfullscreen (GdkWindow *window)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->unfullscreen (window);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_keep_above:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  * @setting: whether to keep @window above other windows
 | ||
|  *
 | ||
|  * Set if @window must be kept above other windows. If the
 | ||
|  * window was already above, then this function does nothing.
 | ||
|  *
 | ||
|  * On X11, asks the window manager to keep @window above, if the window
 | ||
|  * manager supports this operation. Not all window managers support
 | ||
|  * this, and some deliberately ignore it or don’t have a concept of
 | ||
|  * “keep above”; so you can’t rely on the window being kept above.
 | ||
|  * But it will happen with most standard window managers,
 | ||
|  * and GDK makes a best effort to get it to happen.
 | ||
|  *
 | ||
|  * Since: 2.4
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_set_keep_above (GdkWindow *window,
 | ||
|                            gboolean   setting)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_keep_above (window, setting);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_keep_below:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  * @setting: whether to keep @window below other windows
 | ||
|  *
 | ||
|  * Set if @window must be kept below other windows. If the
 | ||
|  * window was already below, then this function does nothing.
 | ||
|  *
 | ||
|  * On X11, asks the window manager to keep @window below, if the window
 | ||
|  * manager supports this operation. Not all window managers support
 | ||
|  * this, and some deliberately ignore it or don’t have a concept of
 | ||
|  * “keep below”; so you can’t rely on the window being kept below.
 | ||
|  * But it will happen with most standard window managers,
 | ||
|  * and GDK makes a best effort to get it to happen.
 | ||
|  *
 | ||
|  * Since: 2.4
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_set_keep_below (GdkWindow *window, gboolean setting)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_keep_below (window, setting);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_group:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  *
 | ||
|  * Returns the group leader window for @window. See gdk_window_set_group().
 | ||
|  *
 | ||
|  * Returns: (transfer none): the group leader window for @window
 | ||
|  *
 | ||
|  * Since: 2.4
 | ||
|  **/
 | ||
| GdkWindow *
 | ||
| gdk_window_get_group (GdkWindow *window)
 | ||
| {
 | ||
|   return GDK_WINDOW_IMPL_GET_CLASS (window->impl)->get_group (window);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_group:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  * @leader: (allow-none): group leader window, or %NULL to restore the default group leader window
 | ||
|  *
 | ||
|  * Sets the group leader window for @window. By default,
 | ||
|  * GDK sets the group leader for all toplevel windows
 | ||
|  * to a global window implicitly created by GDK. With this function
 | ||
|  * you can override this default.
 | ||
|  *
 | ||
|  * The group leader window allows the window manager to distinguish
 | ||
|  * all windows that belong to a single application. It may for example
 | ||
|  * allow users to minimize/unminimize all windows belonging to an
 | ||
|  * application at once. You should only set a non-default group window
 | ||
|  * if your application pretends to be multiple applications.
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_set_group (GdkWindow *window,
 | ||
| 		      GdkWindow *leader)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_group (window, leader);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_decorations:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  * @decorations: decoration hint mask
 | ||
|  *
 | ||
|  * “Decorations” are the features the window manager adds to a toplevel #GdkWindow.
 | ||
|  * This function sets the traditional Motif window manager hints that tell the
 | ||
|  * window manager which decorations you would like your window to have.
 | ||
|  * Usually you should use gtk_window_set_decorated() on a #GtkWindow instead of
 | ||
|  * using the GDK function directly.
 | ||
|  *
 | ||
|  * The @decorations argument is the logical OR of the fields in
 | ||
|  * the #GdkWMDecoration enumeration. If #GDK_DECOR_ALL is included in the
 | ||
|  * mask, the other bits indicate which decorations should be turned off.
 | ||
|  * If #GDK_DECOR_ALL is not included, then the other bits indicate
 | ||
|  * which decorations should be turned on.
 | ||
|  *
 | ||
|  * Most window managers honor a decorations hint of 0 to disable all decorations,
 | ||
|  * but very few honor all possible combinations of bits.
 | ||
|  *
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_set_decorations (GdkWindow      *window,
 | ||
| 			    GdkWMDecoration decorations)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_decorations (window, decorations);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_decorations:
 | ||
|  * @window: The toplevel #GdkWindow to get the decorations from
 | ||
|  * @decorations: (out): The window decorations will be written here
 | ||
|  *
 | ||
|  * Returns the decorations set on the GdkWindow with
 | ||
|  * gdk_window_set_decorations().
 | ||
|  *
 | ||
|  * Returns: %TRUE if the window has decorations set, %FALSE otherwise.
 | ||
|  **/
 | ||
| gboolean
 | ||
| gdk_window_get_decorations(GdkWindow       *window,
 | ||
| 			   GdkWMDecoration *decorations)
 | ||
| {
 | ||
|   return GDK_WINDOW_IMPL_GET_CLASS (window->impl)->get_decorations (window, decorations);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_functions:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  * @functions: bitmask of operations to allow on @window
 | ||
|  *
 | ||
|  * Sets hints about the window management functions to make available
 | ||
|  * via buttons on the window frame.
 | ||
|  *
 | ||
|  * On the X backend, this function sets the traditional Motif window
 | ||
|  * manager hint for this purpose. However, few window managers do
 | ||
|  * anything reliable or interesting with this hint. Many ignore it
 | ||
|  * entirely.
 | ||
|  *
 | ||
|  * The @functions argument is the logical OR of values from the
 | ||
|  * #GdkWMFunction enumeration. If the bitmask includes #GDK_FUNC_ALL,
 | ||
|  * then the other bits indicate which functions to disable; if
 | ||
|  * it doesn’t include #GDK_FUNC_ALL, it indicates which functions to
 | ||
|  * enable.
 | ||
|  *
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_set_functions (GdkWindow    *window,
 | ||
| 			  GdkWMFunction functions)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_functions (window, functions);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_begin_resize_drag_for_device:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  * @edge: the edge or corner from which the drag is started
 | ||
|  * @device: the device used for the operation
 | ||
|  * @button: the button being used to drag, or 0 for a keyboard-initiated drag
 | ||
|  * @root_x: root window X coordinate of mouse click that began the drag
 | ||
|  * @root_y: root window Y coordinate of mouse click that began the drag
 | ||
|  * @timestamp: timestamp of mouse click that began the drag (use gdk_event_get_time())
 | ||
|  *
 | ||
|  * Begins a window resize operation (for a toplevel window).
 | ||
|  * You might use this function to implement a “window resize grip,” for
 | ||
|  * example; in fact #GtkStatusbar uses it. The function works best
 | ||
|  * with window managers that support the
 | ||
|  * [Extended Window Manager Hints](http://www.freedesktop.org/Standards/wm-spec)
 | ||
|  * but has a fallback implementation for other window managers.
 | ||
|  *
 | ||
|  * Since: 3.4
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_begin_resize_drag_for_device (GdkWindow     *window,
 | ||
|                                          GdkWindowEdge  edge,
 | ||
|                                          GdkDevice     *device,
 | ||
|                                          gint           button,
 | ||
|                                          gint           root_x,
 | ||
|                                          gint           root_y,
 | ||
|                                          guint32        timestamp)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->begin_resize_drag (window, edge, device, button, root_x, root_y, timestamp);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_begin_resize_drag:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  * @edge: the edge or corner from which the drag is started
 | ||
|  * @button: the button being used to drag, or 0 for a keyboard-initiated drag
 | ||
|  * @root_x: root window X coordinate of mouse click that began the drag
 | ||
|  * @root_y: root window Y coordinate of mouse click that began the drag
 | ||
|  * @timestamp: timestamp of mouse click that began the drag (use gdk_event_get_time())
 | ||
|  *
 | ||
|  * Begins a window resize operation (for a toplevel window).
 | ||
|  *
 | ||
|  * This function assumes that the drag is controlled by the
 | ||
|  * client pointer device, use gdk_window_begin_resize_drag_for_device()
 | ||
|  * to begin a drag with a different device.
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_begin_resize_drag (GdkWindow     *window,
 | ||
|                               GdkWindowEdge  edge,
 | ||
|                               gint           button,
 | ||
|                               gint           root_x,
 | ||
|                               gint           root_y,
 | ||
|                               guint32        timestamp)
 | ||
| {
 | ||
|   GdkDisplay *display;
 | ||
|   GdkDevice *device;
 | ||
| 
 | ||
|   display = gdk_window_get_display (window);
 | ||
|   device = gdk_seat_get_pointer (gdk_display_get_default_seat (display));
 | ||
|   gdk_window_begin_resize_drag_for_device (window, edge,
 | ||
|                                            device, button, root_x, root_y, timestamp);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_begin_move_drag_for_device:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  * @device: the device used for the operation
 | ||
|  * @button: the button being used to drag, or 0 for a keyboard-initiated drag
 | ||
|  * @root_x: root window X coordinate of mouse click that began the drag
 | ||
|  * @root_y: root window Y coordinate of mouse click that began the drag
 | ||
|  * @timestamp: timestamp of mouse click that began the drag
 | ||
|  *
 | ||
|  * Begins a window move operation (for a toplevel window).
 | ||
|  * You might use this function to implement a “window move grip,” for
 | ||
|  * example. The function works best with window managers that support the
 | ||
|  * [Extended Window Manager Hints](http://www.freedesktop.org/Standards/wm-spec)
 | ||
|  * but has a fallback implementation for other window managers.
 | ||
|  *
 | ||
|  * Since: 3.4
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_begin_move_drag_for_device (GdkWindow *window,
 | ||
|                                        GdkDevice *device,
 | ||
|                                        gint       button,
 | ||
|                                        gint       root_x,
 | ||
|                                        gint       root_y,
 | ||
|                                        guint32    timestamp)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->begin_move_drag (window,
 | ||
|                                                              device, button, root_x, root_y, timestamp);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_begin_move_drag:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  * @button: the button being used to drag, or 0 for a keyboard-initiated drag
 | ||
|  * @root_x: root window X coordinate of mouse click that began the drag
 | ||
|  * @root_y: root window Y coordinate of mouse click that began the drag
 | ||
|  * @timestamp: timestamp of mouse click that began the drag
 | ||
|  *
 | ||
|  * Begins a window move operation (for a toplevel window).
 | ||
|  *
 | ||
|  * This function assumes that the drag is controlled by the
 | ||
|  * client pointer device, use gdk_window_begin_move_drag_for_device()
 | ||
|  * to begin a drag with a different device.
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_begin_move_drag (GdkWindow *window,
 | ||
|                             gint       button,
 | ||
|                             gint       root_x,
 | ||
|                             gint       root_y,
 | ||
|                             guint32    timestamp)
 | ||
| {
 | ||
|   GdkDisplay *display;
 | ||
|   GdkDevice *device;
 | ||
| 
 | ||
|   display = gdk_window_get_display (window);
 | ||
|   device = gdk_seat_get_pointer (gdk_display_get_default_seat (display));
 | ||
|   gdk_window_begin_move_drag_for_device (window, device, button, root_x, root_y, timestamp);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_enable_synchronized_configure:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  *
 | ||
|  * Does nothing, present only for compatiblity.
 | ||
|  *
 | ||
|  * Since: 2.6
 | ||
|  * Deprecated: 3.8: this function is no longer needed
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_enable_synchronized_configure (GdkWindow *window)
 | ||
| {
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_configure_finished:
 | ||
|  * @window: a toplevel #GdkWindow
 | ||
|  *
 | ||
|  * Does nothing, present only for compatiblity.
 | ||
|  *
 | ||
|  * Since: 2.6
 | ||
|  * Deprecated: 3.8: this function is no longer needed
 | ||
|  **/
 | ||
| void
 | ||
| gdk_window_configure_finished (GdkWindow *window)
 | ||
| {
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_opacity:
 | ||
|  * @window: a top-level or non-native #GdkWindow
 | ||
|  * @opacity: opacity
 | ||
|  *
 | ||
|  * Set @window to render as partially transparent,
 | ||
|  * with opacity 0 being fully transparent and 1 fully opaque. (Values
 | ||
|  * of the opacity parameter are clamped to the [0,1] range.) 
 | ||
|  *
 | ||
|  * For toplevel windows this depends on support from the windowing system
 | ||
|  * that may not always be there. For instance, On X11, this works only on
 | ||
|  * X screens with a compositing manager running. On Wayland, there is no
 | ||
|  * per-window opacity value that the compositor would apply. Instead, use
 | ||
|  * `gdk_window_set_opaque_region (window, NULL)` to tell the compositor
 | ||
|  * that the entire window is (potentially) non-opaque, and draw your content
 | ||
|  * with alpha, or use gtk_widget_set_opacity() to set an overall opacity
 | ||
|  * for your widgets.
 | ||
|  *
 | ||
|  * For child windows this function only works for non-native windows.
 | ||
|  *
 | ||
|  * For setting up per-pixel alpha topelevels, see gdk_screen_get_rgba_visual(),
 | ||
|  * and for non-toplevels, see gdk_window_set_composited().
 | ||
|  *
 | ||
|  * Support for non-toplevel windows was added in 3.8.
 | ||
|  *
 | ||
|  * Since: 2.12
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_set_opacity (GdkWindow *window,
 | ||
| 			gdouble    opacity)
 | ||
| {
 | ||
|   if (opacity < 0)
 | ||
|     opacity = 0;
 | ||
|   else if (opacity > 1)
 | ||
|     opacity = 1;
 | ||
| 
 | ||
|   window->alpha = round (opacity * 255);
 | ||
| 
 | ||
|   if (window->destroyed)
 | ||
|     return;
 | ||
| 
 | ||
|   if (gdk_window_has_impl (window))
 | ||
|     GDK_WINDOW_IMPL_GET_CLASS (window->impl)->set_opacity (window, opacity);
 | ||
|   else
 | ||
|     {
 | ||
|       recompute_visible_regions (window, FALSE);
 | ||
|       gdk_window_invalidate_rect_full (window, NULL, TRUE);
 | ||
|     }
 | ||
| }
 | ||
| 
 | ||
| /* This function is called when the XWindow is really gone.
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_destroy_notify (GdkWindow *window)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->destroy_notify (window);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_register_dnd:
 | ||
|  * @window: a #GdkWindow.
 | ||
|  *
 | ||
|  * Registers a window as a potential drop destination.
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_register_dnd (GdkWindow *window)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->register_dnd (window);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_drag_protocol:
 | ||
|  * @window: the destination window
 | ||
|  * @target: (out) (allow-none) (transfer full): location of the window
 | ||
|  *    where the drop should happen. This may be @window or a proxy window,
 | ||
|  *    or %NULL if @window does not support Drag and Drop.
 | ||
|  *
 | ||
|  * Finds out the DND protocol supported by a window.
 | ||
|  *
 | ||
|  * Returns: the supported DND protocol.
 | ||
|  *
 | ||
|  * Since: 3.0
 | ||
|  */
 | ||
| GdkDragProtocol
 | ||
| gdk_window_get_drag_protocol (GdkWindow  *window,
 | ||
|                               GdkWindow **target)
 | ||
| {
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), GDK_DRAG_PROTO_NONE);
 | ||
| 
 | ||
|   return GDK_WINDOW_IMPL_GET_CLASS (window->impl)->get_drag_protocol (window, target);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_drag_begin:
 | ||
|  * @window: the source window for this drag.
 | ||
|  * @targets: (transfer none) (element-type GdkAtom): the offered targets,
 | ||
|  *     as list of #GdkAtoms
 | ||
|  *
 | ||
|  * Starts a drag and creates a new drag context for it.
 | ||
|  * This function assumes that the drag is controlled by the
 | ||
|  * client pointer device, use gdk_drag_begin_for_device() to
 | ||
|  * begin a drag with a different device.
 | ||
|  *
 | ||
|  * This function is called by the drag source.
 | ||
|  *
 | ||
|  * Returns: (transfer full): a newly created #GdkDragContext
 | ||
|  */
 | ||
| GdkDragContext *
 | ||
| gdk_drag_begin (GdkWindow     *window,
 | ||
|                 GList         *targets)
 | ||
| {
 | ||
|   GdkDisplay *display;
 | ||
|   GdkDevice *device;
 | ||
| 
 | ||
|   display = gdk_window_get_display (window);
 | ||
|   device = gdk_seat_get_pointer (gdk_display_get_default_seat (display));
 | ||
| 
 | ||
|   return gdk_drag_begin_for_device (window, device, targets);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_drag_begin_for_device:
 | ||
|  * @window: the source window for this drag
 | ||
|  * @device: the device that controls this drag
 | ||
|  * @targets: (transfer none) (element-type GdkAtom): the offered targets,
 | ||
|  *     as list of #GdkAtoms
 | ||
|  *
 | ||
|  * Starts a drag and creates a new drag context for it.
 | ||
|  *
 | ||
|  * This function is called by the drag source.
 | ||
|  *
 | ||
|  * Returns: (transfer full): a newly created #GdkDragContext
 | ||
|  */
 | ||
| GdkDragContext *
 | ||
| gdk_drag_begin_for_device (GdkWindow *window,
 | ||
|                            GdkDevice *device,
 | ||
|                            GList     *targets)
 | ||
| {
 | ||
|   gint x, y;
 | ||
| 
 | ||
|   gdk_device_get_position (device, NULL, &x, &y);
 | ||
| 
 | ||
|   return gdk_drag_begin_from_point (window, device, targets, x, y);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_drag_begin_from_point:
 | ||
|  * @window: the source window for this drag
 | ||
|  * @device: the device that controls this drag
 | ||
|  * @targets: (transfer none) (element-type GdkAtom): the offered targets,
 | ||
|  *     as list of #GdkAtoms
 | ||
|  * @x_root: the x coordinate where the drag nominally started
 | ||
|  * @y_root: the y coordinate where the drag nominally started
 | ||
|  *
 | ||
|  * Starts a drag and creates a new drag context for it.
 | ||
|  *
 | ||
|  * This function is called by the drag source.
 | ||
|  *
 | ||
|  * Returns: (transfer full): a newly created #GdkDragContext
 | ||
|  *
 | ||
|  * Since: 3.20
 | ||
|  */
 | ||
| GdkDragContext *
 | ||
| gdk_drag_begin_from_point (GdkWindow *window,
 | ||
|                            GdkDevice *device,
 | ||
|                            GList     *targets,
 | ||
|                            gint       x_root,
 | ||
|                            gint       y_root)
 | ||
| {
 | ||
|   return GDK_WINDOW_IMPL_GET_CLASS (window->impl)->drag_begin (window, device, targets, x_root, y_root);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_test_render_sync:
 | ||
|  * @window: a mapped #GdkWindow
 | ||
|  *
 | ||
|  * Retrieves a pixel from @window to force the windowing
 | ||
|  * system to carry out any pending rendering commands.
 | ||
|  *
 | ||
|  * This function is intended to be used to synchronize with rendering
 | ||
|  * pipelines, to benchmark windowing system rendering operations.
 | ||
|  *
 | ||
|  * Since: 2.14
 | ||
|  **/
 | ||
| void
 | ||
| gdk_test_render_sync (GdkWindow *window)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->sync_rendering (window);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_test_simulate_key:
 | ||
|  * @window: a #GdkWindow to simulate a key event for
 | ||
|  * @x:      x coordinate within @window for the key event
 | ||
|  * @y:      y coordinate within @window for the key event
 | ||
|  * @keyval: A GDK keyboard value
 | ||
|  * @modifiers: Keyboard modifiers the event is setup with
 | ||
|  * @key_pressrelease: either %GDK_KEY_PRESS or %GDK_KEY_RELEASE
 | ||
|  *
 | ||
|  * This function is intended to be used in GTK+ test programs.
 | ||
|  * If (@x,@y) are > (-1,-1), it will warp the mouse pointer to
 | ||
|  * the given (@x,@y) coordinates within @window and simulate a
 | ||
|  * key press or release event.
 | ||
|  *
 | ||
|  * When the mouse pointer is warped to the target location, use
 | ||
|  * of this function outside of test programs that run in their
 | ||
|  * own virtual windowing system (e.g. Xvfb) is not recommended.
 | ||
|  * If (@x,@y) are passed as (-1,-1), the mouse pointer will not
 | ||
|  * be warped and @window origin will be used as mouse pointer
 | ||
|  * location for the event.
 | ||
|  *
 | ||
|  * Also, gdk_test_simulate_key() is a fairly low level function,
 | ||
|  * for most testing purposes, gtk_test_widget_send_key() is the
 | ||
|  * right function to call which will generate a key press event
 | ||
|  * followed by its accompanying key release event.
 | ||
|  *
 | ||
|  * Returns: whether all actions necessary for a key event simulation
 | ||
|  *     were carried out successfully
 | ||
|  *
 | ||
|  * Since: 2.14
 | ||
|  */
 | ||
| gboolean
 | ||
| gdk_test_simulate_key (GdkWindow      *window,
 | ||
|                        gint            x,
 | ||
|                        gint            y,
 | ||
|                        guint           keyval,
 | ||
|                        GdkModifierType modifiers,
 | ||
|                        GdkEventType    key_pressrelease)
 | ||
| {
 | ||
|   return GDK_WINDOW_IMPL_GET_CLASS (window->impl)
 | ||
|     ->simulate_key (window, x, y, keyval, modifiers, key_pressrelease);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_test_simulate_button:
 | ||
|  * @window: a #GdkWindow to simulate a button event for
 | ||
|  * @x:      x coordinate within @window for the button event
 | ||
|  * @y:      y coordinate within @window for the button event
 | ||
|  * @button: Number of the pointer button for the event, usually 1, 2 or 3
 | ||
|  * @modifiers: Keyboard modifiers the event is setup with
 | ||
|  * @button_pressrelease: either %GDK_BUTTON_PRESS or %GDK_BUTTON_RELEASE
 | ||
|  *
 | ||
|  * This function is intended to be used in GTK+ test programs.
 | ||
|  * It will warp the mouse pointer to the given (@x,@y) coordinates
 | ||
|  * within @window and simulate a button press or release event.
 | ||
|  * Because the mouse pointer needs to be warped to the target
 | ||
|  * location, use of this function outside of test programs that
 | ||
|  * run in their own virtual windowing system (e.g. Xvfb) is not
 | ||
|  * recommended.
 | ||
|  *
 | ||
| * Also, gdk_test_simulate_button() is a fairly low level function,
 | ||
|  * for most testing purposes, gtk_test_widget_click() is the right
 | ||
|  * function to call which will generate a button press event followed
 | ||
|  * by its accompanying button release event.
 | ||
|  *
 | ||
|  * Returns: whether all actions necessary for a button event simulation
 | ||
|  *     were carried out successfully
 | ||
|  *
 | ||
|  * Since: 2.14
 | ||
|  */
 | ||
| gboolean
 | ||
| gdk_test_simulate_button (GdkWindow      *window,
 | ||
|                           gint            x,
 | ||
|                           gint            y,
 | ||
|                           guint           button, /*1..3*/
 | ||
|                           GdkModifierType modifiers,
 | ||
|                           GdkEventType    button_pressrelease)
 | ||
| {
 | ||
|   return GDK_WINDOW_IMPL_GET_CLASS (window->impl)
 | ||
|     ->simulate_button (window, x, y, button, modifiers, button_pressrelease);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_property_get:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @property: the property to retrieve
 | ||
|  * @type: the desired property type, or %GDK_NONE, if any type of data
 | ||
|  *   is acceptable. If this does not match the actual
 | ||
|  *   type, then @actual_format and @actual_length will
 | ||
|  *   be filled in, a warning will be printed to stderr
 | ||
|  *   and no data will be returned.
 | ||
|  * @offset: the offset into the property at which to begin
 | ||
|  *   retrieving data, in 4 byte units.
 | ||
|  * @length: the length of the data to retrieve in bytes.  Data is
 | ||
|  *   considered to be retrieved in 4 byte chunks, so @length
 | ||
|  *   will be rounded up to the next highest 4 byte boundary
 | ||
|  *   (so be careful not to pass a value that might overflow
 | ||
|  *   when rounded up).
 | ||
|  * @pdelete: if %TRUE, delete the property after retrieving the
 | ||
|  *   data.
 | ||
|  * @actual_property_type: (out) (transfer none): location to store the
 | ||
|  *   actual type of the property.
 | ||
|  * @actual_format: (out): location to store the actual return format of the
 | ||
|  *   data; either 8, 16 or 32 bits.
 | ||
|  * @actual_length: location to store the length of the retrieved data, in
 | ||
|  *   bytes.  Data returned in the 32 bit format is stored
 | ||
|  *   in a long variable, so the actual number of 32 bit
 | ||
|  *   elements should be be calculated via
 | ||
|  *   @actual_length / sizeof(glong) to ensure portability to
 | ||
|  *   64 bit systems.
 | ||
|  * @data: (out) (array length=actual_length) (transfer full): location
 | ||
|  *   to store a pointer to the data. The retrieved data should be
 | ||
|  *   freed with g_free() when you are finished using it.
 | ||
|  *
 | ||
|  * Retrieves a portion of the contents of a property. If the
 | ||
|  * property does not exist, then the function returns %FALSE,
 | ||
|  * and %GDK_NONE will be stored in @actual_property_type.
 | ||
|  *
 | ||
|  * The XGetWindowProperty() function that gdk_property_get()
 | ||
|  * uses has a very confusing and complicated set of semantics.
 | ||
|  * Unfortunately, gdk_property_get() makes the situation
 | ||
|  * worse instead of better (the semantics should be considered
 | ||
|  * undefined), and also prints warnings to stderr in cases where it
 | ||
|  * should return a useful error to the program. You are advised to use
 | ||
|  * XGetWindowProperty() directly until a replacement function for
 | ||
|  * gdk_property_get() is provided.
 | ||
|  *
 | ||
|  * Returns: %TRUE if data was successfully received and stored
 | ||
|  *   in @data, otherwise %FALSE.
 | ||
|  */
 | ||
| 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)
 | ||
| {
 | ||
|   return GDK_WINDOW_IMPL_GET_CLASS (window->impl)
 | ||
|     ->get_property (window, property, type, offset, length, pdelete,
 | ||
|                     actual_property_type, actual_format_type,
 | ||
|                     actual_length, data);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_property_change: (skip)
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @property: the property to change
 | ||
|  * @type: the new type for the property. If @mode is
 | ||
|  *   %GDK_PROP_MODE_PREPEND or %GDK_PROP_MODE_APPEND, then this
 | ||
|  *   must match the existing type or an error will occur.
 | ||
|  * @format: the new format for the property. If @mode is
 | ||
|  *   %GDK_PROP_MODE_PREPEND or %GDK_PROP_MODE_APPEND, then this
 | ||
|  *   must match the existing format or an error will occur.
 | ||
|  * @mode: a value describing how the new data is to be combined
 | ||
|  *   with the current data.
 | ||
|  * @data: the data (a `guchar *`
 | ||
|  *   `gushort *`, or `gulong *`,
 | ||
|  *   depending on @format), cast to a `guchar *`.
 | ||
|  * @nelements: the number of elements of size determined by the format,
 | ||
|  *   contained in @data.
 | ||
|  *
 | ||
|  * Changes the contents of a property on a window.
 | ||
|  */
 | ||
| void
 | ||
| gdk_property_change (GdkWindow    *window,
 | ||
|                      GdkAtom       property,
 | ||
|                      GdkAtom       type,
 | ||
|                      gint          format,
 | ||
|                      GdkPropMode   mode,
 | ||
|                      const guchar *data,
 | ||
|                      gint          nelements)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)
 | ||
|     ->change_property (window, property, type, format, mode, data, nelements);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_property_delete:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @property: the property to delete
 | ||
|  *
 | ||
|  * Deletes a property from a window.
 | ||
|  */
 | ||
| void
 | ||
| gdk_property_delete (GdkWindow *window,
 | ||
|                      GdkAtom    property)
 | ||
| {
 | ||
|   GDK_WINDOW_IMPL_GET_CLASS (window->impl)->delete_property (window, property);
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_flush_events (GdkFrameClock *clock,
 | ||
|                          void          *data)
 | ||
| {
 | ||
|   GdkWindow *window;
 | ||
|   GdkDisplay *display;
 | ||
| 
 | ||
|   window = GDK_WINDOW (data);
 | ||
| 
 | ||
|   display = gdk_window_get_display (window);
 | ||
|   _gdk_event_queue_flush (display);
 | ||
|   _gdk_display_pause_events (display);
 | ||
| 
 | ||
|   gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_RESUME_EVENTS);
 | ||
| 
 | ||
|   window->frame_clock_events_paused = TRUE;
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_paint_on_clock (GdkFrameClock *clock,
 | ||
| 			   void          *data)
 | ||
| {
 | ||
|   GdkWindow *window;
 | ||
| 
 | ||
|   window = GDK_WINDOW (data);
 | ||
| 
 | ||
|   /* Update window and any children on the same clock.
 | ||
|    */
 | ||
|   gdk_window_process_updates_with_mode (window, PROCESS_UPDATES_WITH_SAME_CLOCK_CHILDREN);
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_resume_events (GdkFrameClock *clock,
 | ||
|                           void          *data)
 | ||
| {
 | ||
|   GdkWindow *window;
 | ||
|   GdkDisplay *display;
 | ||
| 
 | ||
|   window = GDK_WINDOW (data);
 | ||
| 
 | ||
|   display = gdk_window_get_display (window);
 | ||
|   _gdk_display_unpause_events (display);
 | ||
| 
 | ||
|   window->frame_clock_events_paused = FALSE;
 | ||
| }
 | ||
| 
 | ||
| static void
 | ||
| gdk_window_set_frame_clock (GdkWindow     *window,
 | ||
|                             GdkFrameClock *clock)
 | ||
| {
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
|   g_return_if_fail (clock == NULL || GDK_IS_FRAME_CLOCK (clock));
 | ||
|   g_return_if_fail (clock == NULL || gdk_window_is_toplevel (window));
 | ||
| 
 | ||
|   if (clock == window->frame_clock)
 | ||
|     return;
 | ||
| 
 | ||
|   if (clock)
 | ||
|     {
 | ||
|       g_object_ref (clock);
 | ||
|       g_signal_connect (G_OBJECT (clock),
 | ||
|                         "flush-events",
 | ||
|                         G_CALLBACK (gdk_window_flush_events),
 | ||
|                         window);
 | ||
|       g_signal_connect (G_OBJECT (clock),
 | ||
|                         "paint",
 | ||
|                         G_CALLBACK (gdk_window_paint_on_clock),
 | ||
|                         window);
 | ||
|       g_signal_connect (G_OBJECT (clock),
 | ||
|                         "resume-events",
 | ||
|                         G_CALLBACK (gdk_window_resume_events),
 | ||
|                         window);
 | ||
|     }
 | ||
| 
 | ||
|   if (window->frame_clock)
 | ||
|     {
 | ||
|       if (window->frame_clock_events_paused)
 | ||
|         gdk_window_resume_events (window->frame_clock, G_OBJECT (window));
 | ||
| 
 | ||
|       g_signal_handlers_disconnect_by_func (G_OBJECT (window->frame_clock),
 | ||
|                                             G_CALLBACK (gdk_window_flush_events),
 | ||
|                                             window);
 | ||
|       g_signal_handlers_disconnect_by_func (G_OBJECT (window->frame_clock),
 | ||
|                                             G_CALLBACK (gdk_window_paint_on_clock),
 | ||
|                                             window);
 | ||
|       g_signal_handlers_disconnect_by_func (G_OBJECT (window->frame_clock),
 | ||
|                                             G_CALLBACK (gdk_window_resume_events),
 | ||
|                                             window);
 | ||
|       g_object_unref (window->frame_clock);
 | ||
|     }
 | ||
| 
 | ||
|   window->frame_clock = clock;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_frame_clock:
 | ||
|  * @window: window to get frame clock for
 | ||
|  *
 | ||
|  * Gets the frame clock for the window. The frame clock for a window
 | ||
|  * never changes unless the window is reparented to a new toplevel
 | ||
|  * window.
 | ||
|  *
 | ||
|  * Since: 3.8
 | ||
|  * Returns: (transfer none): the frame clock
 | ||
|  */
 | ||
| GdkFrameClock*
 | ||
| gdk_window_get_frame_clock (GdkWindow *window)
 | ||
| {
 | ||
|   GdkWindow *toplevel;
 | ||
| 
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
 | ||
| 
 | ||
|   toplevel = gdk_window_get_toplevel (window);
 | ||
| 
 | ||
|   return toplevel->frame_clock;
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_get_scale_factor:
 | ||
|  * @window: window to get scale factor for
 | ||
|  *
 | ||
|  * Returns the internal scale factor that maps from window coordiantes
 | ||
|  * to the actual device pixels. On traditional systems this is 1, but
 | ||
|  * on very high density outputs this can be a higher value (often 2).
 | ||
|  *
 | ||
|  * A higher value means that drawing is automatically scaled up to
 | ||
|  * a higher resolution, so any code doing drawing will automatically look
 | ||
|  * nicer. However, if you are supplying pixel-based data the scale
 | ||
|  * value can be used to determine whether to use a pixel resource
 | ||
|  * with higher resolution data.
 | ||
|  *
 | ||
|  * The scale of a window may change during runtime, if this happens
 | ||
|  * a configure event will be sent to the toplevel window.
 | ||
|  *
 | ||
|  * Since: 3.10
 | ||
|  * Returns: the scale factor
 | ||
|  */
 | ||
| gint
 | ||
| gdk_window_get_scale_factor (GdkWindow *window)
 | ||
| {
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
| 
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), 1);
 | ||
| 
 | ||
|   if (GDK_WINDOW_DESTROYED (window))
 | ||
|     return 1;
 | ||
| 
 | ||
|   impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
| 
 | ||
|   if (impl_class->get_scale_factor)
 | ||
|     return impl_class->get_scale_factor (window);
 | ||
| 
 | ||
|   return 1;
 | ||
| }
 | ||
| 
 | ||
| /* Returns the *real* unscaled size, which may be a fractional size
 | ||
|    in window scale coordinates. We need this to properly handle GL
 | ||
|    coordinates which are y-flipped in the real coordinates. */
 | ||
| void
 | ||
| gdk_window_get_unscaled_size (GdkWindow *window,
 | ||
|                               int *unscaled_width,
 | ||
|                               int *unscaled_height)
 | ||
| {
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
|   gint scale;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
| 
 | ||
|   if (window->impl_window == window)
 | ||
|     {
 | ||
|       impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
| 
 | ||
|       if (impl_class->get_unscaled_size)
 | ||
|         {
 | ||
|           impl_class->get_unscaled_size (window, unscaled_width, unscaled_height);
 | ||
|           return;
 | ||
|         }
 | ||
|     }
 | ||
| 
 | ||
|   scale = gdk_window_get_scale_factor (window);
 | ||
| 
 | ||
|   if (unscaled_width)
 | ||
|     *unscaled_width = window->width * scale;
 | ||
| 
 | ||
|   if (unscaled_height)
 | ||
|     *unscaled_height = window->height * scale;
 | ||
| }
 | ||
| 
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_opaque_region:
 | ||
|  * @window: a top-level or non-native #GdkWindow
 | ||
|  * @region: (allow-none):  a region, or %NULL
 | ||
|  *
 | ||
|  * For optimisation purposes, compositing window managers may
 | ||
|  * like to not draw obscured regions of windows, or turn off blending
 | ||
|  * during for these regions. With RGB windows with no transparency,
 | ||
|  * this is just the shape of the window, but with ARGB32 windows, the
 | ||
|  * compositor does not know what regions of the window are transparent
 | ||
|  * or not.
 | ||
|  *
 | ||
|  * This function only works for toplevel windows.
 | ||
|  *
 | ||
|  * GTK+ will update this property automatically if
 | ||
|  * the @window background is opaque, as we know where the opaque regions
 | ||
|  * are. If your window background is not opaque, please update this
 | ||
|  * property in your #GtkWidget::style-updated handler.
 | ||
|  *
 | ||
|  * Since: 3.10
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_set_opaque_region (GdkWindow      *window,
 | ||
|                               cairo_region_t *region)
 | ||
| {
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
|   g_return_if_fail (!GDK_WINDOW_DESTROYED (window));
 | ||
| 
 | ||
|   if (cairo_region_equal (window->opaque_region, region))
 | ||
|     return;
 | ||
| 
 | ||
|   g_clear_pointer (&window->opaque_region, cairo_region_destroy);
 | ||
| 
 | ||
|   if (region != NULL)
 | ||
|     window->opaque_region = cairo_region_reference (region);
 | ||
| 
 | ||
|   impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
| 
 | ||
|   if (impl_class->set_opaque_region)
 | ||
|     impl_class->set_opaque_region (window, region);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_set_shadow_width:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @left: The left extent
 | ||
|  * @right: The right extent
 | ||
|  * @top: The top extent
 | ||
|  * @bottom: The bottom extent
 | ||
|  *
 | ||
|  * Newer GTK+ windows using client-side decorations use extra geometry
 | ||
|  * around their frames for effects like shadows and invisible borders.
 | ||
|  * Window managers that want to maximize windows or snap to edges need
 | ||
|  * to know where the extents of the actual frame lie, so that users
 | ||
|  * don’t feel like windows are snapping against random invisible edges.
 | ||
|  *
 | ||
|  * Note that this property is automatically updated by GTK+, so this
 | ||
|  * function should only be used by applications which do not use GTK+
 | ||
|  * to create toplevel windows.
 | ||
|  *
 | ||
|  * Since: 3.12
 | ||
|  */
 | ||
| void
 | ||
| gdk_window_set_shadow_width (GdkWindow *window,
 | ||
|                              gint       left,
 | ||
|                              gint       right,
 | ||
|                              gint       top,
 | ||
|                              gint       bottom)
 | ||
| {
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
| 
 | ||
|   g_return_if_fail (GDK_IS_WINDOW (window));
 | ||
|   g_return_if_fail (!GDK_WINDOW_DESTROYED (window));
 | ||
|   g_return_if_fail (left >= 0 && right >= 0 && top >= 0 && bottom >= 0);
 | ||
| 
 | ||
|   window->shadow_top = top;
 | ||
|   window->shadow_left = left;
 | ||
|   window->shadow_right = right;
 | ||
|   window->shadow_bottom = bottom;
 | ||
| 
 | ||
|   impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
| 
 | ||
|   if (impl_class->set_shadow_width)
 | ||
|     impl_class->set_shadow_width (window, left, right, top, bottom);
 | ||
| }
 | ||
| 
 | ||
| /**
 | ||
|  * gdk_window_show_window_menu:
 | ||
|  * @window: a #GdkWindow
 | ||
|  * @event: a #GdkEvent to show the menu for
 | ||
|  *
 | ||
|  * Asks the windowing system to show the window menu. The window menu
 | ||
|  * is the menu shown when right-clicking the titlebar on traditional
 | ||
|  * windows managed by the window manager. This is useful for windows
 | ||
|  * using client-side decorations, activating it with a right-click
 | ||
|  * on the window decorations.
 | ||
|  *
 | ||
|  * Returns: %TRUE if the window menu was shown and %FALSE otherwise.
 | ||
|  *
 | ||
|  * Since: 3.14
 | ||
|  */
 | ||
| gboolean
 | ||
| gdk_window_show_window_menu (GdkWindow *window,
 | ||
|                              GdkEvent  *event)
 | ||
| {
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
| 
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 | ||
|   g_return_val_if_fail (!GDK_WINDOW_DESTROYED (window), FALSE);
 | ||
| 
 | ||
|   impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
| 
 | ||
|   if (impl_class->show_window_menu)
 | ||
|     return impl_class->show_window_menu (window, event);
 | ||
|   else
 | ||
|     return FALSE;
 | ||
| }
 | ||
| 
 | ||
| gboolean
 | ||
| gdk_window_titlebar_gesture (GdkWindow          *window,
 | ||
|                              GdkTitlebarGesture  gesture)
 | ||
| {
 | ||
|   GdkWindowImplClass *impl_class;
 | ||
| 
 | ||
|   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
 | ||
|   g_return_val_if_fail (!GDK_WINDOW_DESTROYED (window), FALSE);
 | ||
| 
 | ||
|   impl_class = GDK_WINDOW_IMPL_GET_CLASS (window->impl);
 | ||
| 
 | ||
|   if (impl_class->titlebar_gesture)
 | ||
|     return impl_class->titlebar_gesture (window, gesture);
 | ||
|   else
 | ||
|     return FALSE;
 | ||
| }
 |