1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-2007 Peter Mattis, Spencer Kimball,
3 * Josh MacDonald, Ryan Lortie
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
22 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
23 * file for a list of people on the GTK+ Team. See the ChangeLog
24 * files for a list of changes. These files are distributed with
25 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
30 #include "gdkwindow.h"
32 #ifdef GDK_WINDOWING_X11
33 #include "x11/gdkx.h" /* For workaround */
37 #include "gdk.h" /* For gdk_rectangle_union() */
38 #include "gdkinternals.h"
40 #include "gdkscreen.h"
41 #include "gdkdeviceprivate.h"
42 #include "gdkdrawable.h"
43 #include "gdkmarshalers.h"
44 #include "gdkpixmap.h"
45 #include "gdkscreen.h"
46 #include "gdkwindowimpl.h"
50 #undef DEBUG_WINDOW_PRINTING
55 * @Short_description: Onscreen display areas in the target window system
58 * A #GdkWindow is a rectangular region on the screen. It's a low-level object,
59 * used to implement high-level objects such as #GtkWidget and #GtkWindow on the
60 * GTK+ level. A #GtkWindow is a toplevel window, the thing a user might think
61 * of as a "window" with a titlebar and so on; a #GtkWindow may contain many
62 * #GdkWindow<!-- -->s. For example, each #GtkButton has a #GdkWindow associated
65 * <refsect2 id="COMPOSITED-WINDOWS">
66 * <title>Composited Windows</title>
68 * Normally, the windowing system takes care of rendering the contents of a
69 * child window onto its parent window. This mechanism can be intercepted by
70 * calling gdk_window_set_composited() on the child window. For a
71 * <firstterm>composited</firstterm> window it is the responsibility of the
72 * application to render the window contents at the right spot.
74 * <example id="composited-window-example">
75 * <title>Composited windows</title>
77 * <xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../examples/gdk/composited-window-example.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include>
78 * </programlisting></example>
80 * In the example <xref linkend="composited-window-example"/>, a button is
81 * placed inside of an event box inside of a window. The event box is set as
82 * composited and therefore is no longer automatically drawn to the screen.
84 * When the contents of the event box change, an expose event is generated on
85 * it's parent window (which, in this case, belongs to the toplevel #GtkWindow).
86 * The expose handler for this widget is responsible for merging the changes
87 * back on the screen in the way that it wishes.
89 * In our case, we merge the contents with a 50% transparency. We also set the
90 * background colour of the window to red. The effect is that the background
91 * shows through the button.
94 * <refsect2 id="OFFSCREEN-WINDOWS">
95 * <title>Offscreen Windows</title>
97 * Offscreen windows are more general than composited windows, since they allow
98 * not only to modify the rendering of the child window onto its parent, but
99 * also to apply coordinate transformations.
101 * To integrate an offscreen window into a window hierarchy, one has to call
102 * gdk_offscreen_window_set_embedder() and handle a number of signals. The
103 * #GdkWindow::pick-embedded-child signal on the embedder window is used to
104 * select an offscreen child at given coordinates, and the
105 * #GdkWindow::to-embedder and #GdkWindow::from-embedder signals on the
106 * offscreen window are used to translate coordinates between the embedder and
107 * the offscreen window.
109 * For rendering an offscreen window onto its embedder, the contents of the
110 * offscreen window are available as a pixmap, via
111 * gdk_offscreen_window_get_pixmap().
117 /* Historically a GdkWindow always matches a platform native window,
118 * be it a toplevel window or a child window. In this setup the
119 * GdkWindow (and other GdkDrawables) were platform independent classes,
120 * and the actual platform specific implementation was in a delegate
121 * object availible as "impl" in the window object.
123 * With the addition of client side windows and offscreen windows this
124 * changes a bit. The application-visible GdkWindow object behaves as
125 * it did before, but not all such windows now have a corresponding native
126 * window. Instead windows that are "client side" are emulated by the gdk
127 * code such that clipping, drawing, moving, events etc work as expected.
129 * For GdkWindows that have a native window the "impl" object is the
130 * same as before. However, for all client side windows the impl object
131 * is shared with its parent (i.e. all client windows descendants of one
132 * native window has the same impl.
134 * Additionally there is a new type of platform independent impl object,
135 * GdkOffscreenWindow. All windows of type GDK_WINDOW_OFFSCREEN get an impl
136 * of this type (while their children are generally GDK_WINDOW_CHILD virtual
137 * windows). Such windows work by allocating a GdkPixmap as the backing store
138 * for drawing operations, which is resized with the window.
140 * GdkWindows have a pointer to the "impl window" they are in, i.e.
141 * the topmost GdkWindow which have the same "impl" value. This is stored
142 * in impl_window, which is different from the window itself only for client
144 * All GdkWindows (native or not) track the position of the window in the parent
145 * (x, y), the size of the window (width, height), the position of the window
146 * with respect to the impl window (abs_x, abs_y). We also track the clip
147 * region of the window wrt parent windows and siblings, in window-relative
148 * coordinates with and without child windows included (clip_region,
149 * clip_region_with_children).
151 * All toplevel windows are native windows, but also child windows can be
152 * native (although not children of offscreens). We always listen to
153 * a basic set of events (see get_native_event_mask) for these windows
154 * so that we can emulate events for any client side children.
156 * For native windows we apply the calculated clip region as a window shape
157 * so that eg. client side siblings that overlap the native child properly
158 * draws over the native child window.
160 * In order to minimize flicker and for performance we use a couple of cacheing
161 * tricks. First of all, every time we do a window to window copy area, for instance
162 * when moving a client side window or when scrolling/moving a region in a window
163 * we store this in outstanding_moves instead of applying immediately. We then
164 * delay this move until we really need it (because something depends on being
165 * able to read it), or until we're handing a redraw from an expose/invalidation
166 * (actually we delay it past redraw, but before blitting the double buffer pixmap
167 * to the window). This gives us two advantages. First of all it minimizes the time
168 * from the window is moved to the exposes related to that move, secondly it allows
169 * us to be smart about how to do the copy. We combine multiple moves into one (when
170 * possible) and we don't actually do copies to anything that is or will be
171 * invalidated and exposed anyway.
173 * Secondly, we use something called a "implicit paint" during repaint handling.
174 * An implicit paint is similar to a regular paint for the paint stack, but it is
175 * not put on the stack. Instead, it is set on the impl window, and later when
176 * regular gdk_window_begin_paint_region() happen on a window of this impl window
177 * we reuse the pixmap from the implicit paint. During repaint we create and at the
178 * end flush an implicit paint, which means we can collect all the paints on
179 * multiple client side windows in the same backing store pixmap.
181 * All drawing to windows are wrapped with macros that set up the GC such that
182 * the offsets and clip region is right for drawing to the paint object or
183 * directly to the emulated window. It also automatically handles any flushing
184 * needed when drawing directly to a window. Adding window/paint clipping is
185 * done using _gdk_gc_add_drawable_clip which lets us efficiently add and then
186 * remove a custom clip region.
189 #define USE_BACKING_STORE /* Appears to work on Win32, too, now. */
191 /* This adds a local value to the GdkVisibilityState enum */
192 #define GDK_VISIBILITY_NOT_VIEWABLE 3
195 PICK_EMBEDDED_CHILD, /* only called if children are embedded */
208 CLEAR_BG_WINCLEARED, /* Clear backgrounds except those that the window system clears */
212 struct _GdkWindowPaint
218 cairo_surface_t *surface;
219 guint uses_implicit : 1;
225 GdkRegion *dest_region; /* The destination region */
226 int dx, dy; /* The amount that the source was moved to reach dest_region */
227 } GdkWindowRegionMove;
231 static GdkGC *gdk_window_create_gc (GdkDrawable *drawable,
233 GdkGCValuesMask mask);
234 static void gdk_window_draw_rectangle (GdkDrawable *drawable,
241 static void gdk_window_draw_arc (GdkDrawable *drawable,
250 static void gdk_window_draw_polygon (GdkDrawable *drawable,
255 static void gdk_window_draw_text (GdkDrawable *drawable,
262 static void gdk_window_draw_text_wc (GdkDrawable *drawable,
267 const GdkWChar *text,
269 static void gdk_window_draw_drawable (GdkDrawable *drawable,
278 GdkDrawable *original_src);
279 static void gdk_window_draw_points (GdkDrawable *drawable,
283 static void gdk_window_draw_segments (GdkDrawable *drawable,
287 static void gdk_window_draw_lines (GdkDrawable *drawable,
292 static void gdk_window_draw_glyphs (GdkDrawable *drawable,
297 PangoGlyphString *glyphs);
298 static void gdk_window_draw_glyphs_transformed (GdkDrawable *drawable,
304 PangoGlyphString *glyphs);
306 static void gdk_window_draw_image (GdkDrawable *drawable,
316 static void gdk_window_draw_pixbuf (GdkDrawable *drawable,
329 static void gdk_window_draw_trapezoids (GdkDrawable *drawable,
331 GdkTrapezoid *trapezoids,
334 static GdkImage* gdk_window_copy_to_image (GdkDrawable *drawable,
343 static cairo_surface_t *gdk_window_ref_cairo_surface (GdkDrawable *drawable);
344 static cairo_surface_t *gdk_window_create_cairo_surface (GdkDrawable *drawable,
347 static void gdk_window_drop_cairo_surface (GdkWindowObject *private);
348 static void gdk_window_set_cairo_clip (GdkDrawable *drawable,
351 static void gdk_window_real_get_size (GdkDrawable *drawable,
355 static GdkVisual* gdk_window_real_get_visual (GdkDrawable *drawable);
356 static gint gdk_window_real_get_depth (GdkDrawable *drawable);
357 static GdkScreen* gdk_window_real_get_screen (GdkDrawable *drawable);
358 static void gdk_window_real_set_colormap (GdkDrawable *drawable,
360 static GdkColormap* gdk_window_real_get_colormap (GdkDrawable *drawable);
362 static GdkDrawable* gdk_window_get_source_drawable (GdkDrawable *drawable);
363 static GdkDrawable* gdk_window_get_composite_drawable (GdkDrawable *drawable,
368 gint *composite_x_offset,
369 gint *composite_y_offset);
370 static GdkRegion* gdk_window_get_clip_region (GdkDrawable *drawable);
371 static GdkRegion* gdk_window_get_visible_region (GdkDrawable *drawable);
373 static void gdk_window_free_paint_stack (GdkWindow *window);
375 static void gdk_window_init (GdkWindowObject *window);
376 static void gdk_window_class_init (GdkWindowObjectClass *klass);
377 static void gdk_window_finalize (GObject *object);
379 static void gdk_window_set_property (GObject *object,
383 static void gdk_window_get_property (GObject *object,
388 static void gdk_window_clear_backing_region (GdkWindow *window,
390 static void gdk_window_redirect_free (GdkWindowRedirect *redirect);
391 static void apply_redirect_to_children (GdkWindowObject *private,
392 GdkWindowRedirect *redirect);
393 static void remove_redirect_from_children (GdkWindowObject *private,
394 GdkWindowRedirect *redirect);
396 static void recompute_visible_regions (GdkWindowObject *private,
397 gboolean recalculate_siblings,
398 gboolean recalculate_children);
399 static void gdk_window_flush_outstanding_moves (GdkWindow *window);
400 static void gdk_window_flush_recursive (GdkWindowObject *window);
401 static void do_move_region_bits_on_impl (GdkWindowObject *private,
402 GdkRegion *region, /* In impl window coords */
404 static void gdk_window_invalidate_in_parent (GdkWindowObject *private);
405 static void move_native_children (GdkWindowObject *private);
406 static void update_cursor (GdkDisplay *display,
408 static void impl_window_add_update_area (GdkWindowObject *impl_window,
410 static void gdk_window_region_move_free (GdkWindowRegionMove *move);
411 static void gdk_window_invalidate_region_full (GdkWindow *window,
412 const GdkRegion *region,
413 gboolean invalidate_children,
415 static void gdk_window_invalidate_rect_full (GdkWindow *window,
416 const GdkRectangle *rect,
417 gboolean invalidate_children,
420 static guint signals[LAST_SIGNAL] = { 0 };
422 static gpointer parent_class = NULL;
424 static const cairo_user_data_key_t gdk_window_cairo_key;
427 new_region_tag (void)
429 static guint32 tag = 0;
435 gdk_window_object_get_type (void)
437 static GType object_type = 0;
440 object_type = g_type_register_static_simple (GDK_TYPE_DRAWABLE,
442 sizeof (GdkWindowObjectClass),
443 (GClassInitFunc) gdk_window_class_init,
444 sizeof (GdkWindowObject),
445 (GInstanceInitFunc) gdk_window_init,
452 _gdk_paintable_get_type (void)
454 static GType paintable_type = 0;
458 const GTypeInfo paintable_info =
460 sizeof (GdkPaintableIface), /* class_size */
461 NULL, /* base_init */
462 NULL, /* base_finalize */
465 paintable_type = g_type_register_static (G_TYPE_INTERFACE,
466 g_intern_static_string ("GdkPaintable"),
469 g_type_interface_add_prerequisite (paintable_type, G_TYPE_OBJECT);
472 return paintable_type;
476 gdk_window_init (GdkWindowObject *window)
478 /* 0-initialization is good for all other fields. */
480 window->window_type = GDK_WINDOW_CHILD;
482 window->state = GDK_WINDOW_STATE_WITHDRAWN;
485 window->toplevel_window_type = -1;
487 window->effective_visibility = GDK_VISIBILITY_NOT_VIEWABLE;
488 window->visibility = GDK_VISIBILITY_FULLY_OBSCURED;
489 /* Default to unobscured since some backends don't send visibility events */
490 window->native_visibility = GDK_VISIBILITY_UNOBSCURED;
493 /* Stop and return on the first non-NULL parent */
495 accumulate_get_window (GSignalInvocationHint *ihint,
497 const GValue *handler_return,
500 g_value_copy (handler_return, return_accu);
501 /* Continue while returning NULL */
502 return g_value_get_object (handler_return) == NULL;
505 static GQuark quark_pointer_window = 0;
508 gdk_window_class_init (GdkWindowObjectClass *klass)
510 GObjectClass *object_class = G_OBJECT_CLASS (klass);
511 GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
513 parent_class = g_type_class_peek_parent (klass);
515 object_class->finalize = gdk_window_finalize;
516 object_class->set_property = gdk_window_set_property;
517 object_class->get_property = gdk_window_get_property;
519 drawable_class->create_gc = gdk_window_create_gc;
520 drawable_class->draw_rectangle = gdk_window_draw_rectangle;
521 drawable_class->draw_arc = gdk_window_draw_arc;
522 drawable_class->draw_polygon = gdk_window_draw_polygon;
523 drawable_class->draw_text = gdk_window_draw_text;
524 drawable_class->draw_text_wc = gdk_window_draw_text_wc;
525 drawable_class->draw_drawable_with_src = gdk_window_draw_drawable;
526 drawable_class->draw_points = gdk_window_draw_points;
527 drawable_class->draw_segments = gdk_window_draw_segments;
528 drawable_class->draw_lines = gdk_window_draw_lines;
529 drawable_class->draw_glyphs = gdk_window_draw_glyphs;
530 drawable_class->draw_glyphs_transformed = gdk_window_draw_glyphs_transformed;
531 drawable_class->draw_image = gdk_window_draw_image;
532 drawable_class->draw_pixbuf = gdk_window_draw_pixbuf;
533 drawable_class->draw_trapezoids = gdk_window_draw_trapezoids;
534 drawable_class->get_depth = gdk_window_real_get_depth;
535 drawable_class->get_screen = gdk_window_real_get_screen;
536 drawable_class->get_size = gdk_window_real_get_size;
537 drawable_class->set_colormap = gdk_window_real_set_colormap;
538 drawable_class->get_colormap = gdk_window_real_get_colormap;
539 drawable_class->get_visual = gdk_window_real_get_visual;
540 drawable_class->_copy_to_image = gdk_window_copy_to_image;
541 drawable_class->ref_cairo_surface = gdk_window_ref_cairo_surface;
542 drawable_class->create_cairo_surface = gdk_window_create_cairo_surface;
543 drawable_class->set_cairo_clip = gdk_window_set_cairo_clip;
544 drawable_class->get_clip_region = gdk_window_get_clip_region;
545 drawable_class->get_visible_region = gdk_window_get_visible_region;
546 drawable_class->get_composite_drawable = gdk_window_get_composite_drawable;
547 drawable_class->get_source_drawable = gdk_window_get_source_drawable;
549 quark_pointer_window = g_quark_from_static_string ("gtk-pointer-window");
557 * The mouse pointer for a #GdkWindow. See gdk_window_set_cursor() and
558 * gdk_window_get_cursor() for details.
562 g_object_class_install_property (object_class,
564 g_param_spec_boxed ("cursor",
571 * GdkWindow::pick-embedded-child:
572 * @window: the window on which the signal is emitted
573 * @x: x coordinate in the window
574 * @y: y coordinate in the window
576 * The ::pick-embedded-child signal is emitted to find an embedded
577 * child at the given position.
579 * Returns: the #GdkWindow of the embedded child at @x, @y, or %NULL
583 signals[PICK_EMBEDDED_CHILD] =
584 g_signal_new (g_intern_static_string ("pick-embedded-child"),
585 G_OBJECT_CLASS_TYPE (object_class),
588 accumulate_get_window, NULL,
589 _gdk_marshal_OBJECT__DOUBLE_DOUBLE,
596 * GdkWindow::to-embedder:
597 * @window: the offscreen window on which the signal is emitted
598 * @offscreen-x: x coordinate in the offscreen window
599 * @offscreen-y: y coordinate in the offscreen window
600 * @embedder-x: return location for the x coordinate in the embedder window
601 * @embedder-y: return location for the y coordinate in the embedder window
603 * The ::to-embedder signal is emitted to translate coordinates
604 * in an offscreen window to its embedder.
606 * See also #GtkWindow::from-embedder.
610 signals[TO_EMBEDDER] =
611 g_signal_new (g_intern_static_string ("to-embedder"),
612 G_OBJECT_CLASS_TYPE (object_class),
616 _gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
625 * GdkWindow::from-embedder:
626 * @window: the offscreen window on which the signal is emitted
627 * @embedder-x: x coordinate in the embedder window
628 * @embedder-y: y coordinate in the embedder window
629 * @offscreen-x: return location for the x coordinate in the offscreen window
630 * @offscreen-y: return location for the y coordinate in the offscreen window
632 * The ::from-embedder signal is emitted to translate coordinates
633 * in the embedder of an offscreen window to the offscreen window.
635 * See also #GtkWindow::to-embedder.
639 signals[FROM_EMBEDDER] =
640 g_signal_new (g_intern_static_string ("from-embedder"),
641 G_OBJECT_CLASS_TYPE (object_class),
645 _gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
655 device_removed_cb (GdkDeviceManager *device_manager,
659 GdkWindowObject *private;
661 private = (GdkWindowObject *) window;
663 private->devices_inside = g_list_remove (private->devices_inside, device);
664 g_hash_table_remove (private->device_cursor, device);
666 if (private->device_events)
667 g_hash_table_remove (private->device_events, device);
671 gdk_window_finalize (GObject *object)
673 GdkWindow *window = GDK_WINDOW (object);
674 GdkWindowObject *obj = (GdkWindowObject *) object;
675 GdkDeviceManager *device_manager;
677 device_manager = gdk_display_get_device_manager (gdk_drawable_get_display (GDK_DRAWABLE (window)));
678 g_signal_handlers_disconnect_by_func (device_manager, device_removed_cb, window);
680 if (!GDK_WINDOW_DESTROYED (window))
682 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
684 g_warning ("losing last reference to undestroyed window\n");
685 _gdk_window_destroy (window, FALSE);
688 /* We use TRUE here, to keep us from actually calling
689 * XDestroyWindow() on the window
691 _gdk_window_destroy (window, TRUE);
696 g_object_unref (obj->impl);
700 if (obj->impl_window != obj)
702 g_object_unref (obj->impl_window);
703 obj->impl_window = NULL;
707 gdk_region_destroy (obj->shape);
709 if (obj->input_shape)
710 gdk_region_destroy (obj->input_shape);
713 gdk_cursor_unref (obj->cursor);
715 if (obj->device_cursor)
716 g_hash_table_destroy (obj->device_cursor);
718 if (obj->device_events)
719 g_hash_table_destroy (obj->device_events);
721 if (obj->devices_inside)
722 g_list_free (obj->devices_inside);
724 G_OBJECT_CLASS (parent_class)->finalize (object);
728 gdk_window_set_property (GObject *object,
733 GdkWindow *window = (GdkWindow *)object;
738 gdk_window_set_cursor (window, g_value_get_boxed (value));
742 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
748 gdk_window_get_property (GObject *object,
753 GdkWindow *window = (GdkWindow *) object;
758 g_value_set_boxed (value, gdk_window_get_cursor (window));
762 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
768 gdk_window_is_offscreen (GdkWindowObject *window)
770 return window->window_type == GDK_WINDOW_OFFSCREEN;
773 static GdkWindowObject *
774 gdk_window_get_impl_window (GdkWindowObject *window)
776 return window->impl_window;
780 _gdk_window_get_impl_window (GdkWindow *window)
782 return (GdkWindow *)gdk_window_get_impl_window ((GdkWindowObject *)window);
786 gdk_window_has_impl (GdkWindowObject *window)
788 return window->impl_window == window;
792 gdk_window_is_toplevel (GdkWindowObject *window)
795 window->parent == NULL ||
796 window->parent->window_type == GDK_WINDOW_ROOT;
800 _gdk_window_has_impl (GdkWindow *window)
802 return gdk_window_has_impl ((GdkWindowObject *)window);
806 gdk_window_has_no_impl (GdkWindowObject *window)
808 return window->impl_window != window;
812 remove_child_area (GdkWindowObject *private,
813 GdkWindowObject *until,
817 GdkWindowObject *child;
818 GdkRegion *child_region;
823 for (l = private->children; l; l = l->next)
830 /* If region is empty already, no need to do
831 anything potentially costly */
832 if (gdk_region_empty (region))
835 if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
838 /* Ignore offscreen children, as they don't draw in their parent and
839 * don't take part in the clipping */
840 if (gdk_window_is_offscreen (child))
845 r.width = child->width;
846 r.height = child->height;
848 /* Bail early if child totally outside region */
849 if (gdk_region_rect_in (region, &r) == GDK_OVERLAP_RECTANGLE_OUT)
852 child_region = gdk_region_rectangle (&r);
856 /* Adjust shape region to parent window coords */
857 gdk_region_offset (child->shape, child->x, child->y);
858 gdk_region_intersect (child_region, child->shape);
859 gdk_region_offset (child->shape, -child->x, -child->y);
861 else if (private->window_type == GDK_WINDOW_FOREIGN)
863 shape = _gdk_windowing_window_get_shape ((GdkWindow *)child);
866 gdk_region_intersect (child_region, shape);
867 gdk_region_destroy (shape);
873 if (child->input_shape)
874 gdk_region_intersect (child_region, child->input_shape);
875 else if (private->window_type == GDK_WINDOW_FOREIGN)
877 shape = _gdk_windowing_window_get_input_shape ((GdkWindow *)child);
880 gdk_region_intersect (child_region, shape);
881 gdk_region_destroy (shape);
886 gdk_region_subtract (region, child_region);
887 gdk_region_destroy (child_region);
892 static GdkVisibilityState
893 effective_visibility (GdkWindowObject *private)
895 GdkVisibilityState native;
897 if (!gdk_window_is_viewable ((GdkWindow *)private))
898 return GDK_VISIBILITY_NOT_VIEWABLE;
900 native = private->impl_window->native_visibility;
902 if (native == GDK_VISIBILITY_FULLY_OBSCURED ||
903 private->visibility == GDK_VISIBILITY_FULLY_OBSCURED)
904 return GDK_VISIBILITY_FULLY_OBSCURED;
905 else if (native == GDK_VISIBILITY_UNOBSCURED)
906 return private->visibility;
907 else /* native PARTIAL, private partial or unobscured */
908 return GDK_VISIBILITY_PARTIAL;
912 gdk_window_update_visibility (GdkWindowObject *private)
914 GdkVisibilityState new_visibility;
917 new_visibility = effective_visibility (private);
919 if (new_visibility != private->effective_visibility)
921 private->effective_visibility = new_visibility;
923 if (new_visibility != GDK_VISIBILITY_NOT_VIEWABLE &&
924 private->event_mask & GDK_VISIBILITY_NOTIFY)
926 event = _gdk_make_event ((GdkWindow *)private, GDK_VISIBILITY_NOTIFY,
928 event->visibility.state = new_visibility;
934 gdk_window_update_visibility_recursively (GdkWindowObject *private,
935 GdkWindowObject *only_for_impl)
937 GdkWindowObject *child;
940 gdk_window_update_visibility (private);
941 for (l = private->children; l != NULL; l = l->next)
944 if ((only_for_impl == NULL) ||
945 (only_for_impl == child->impl_window))
946 gdk_window_update_visibility_recursively (child, only_for_impl);
951 should_apply_clip_as_shape (GdkWindowObject *private)
954 gdk_window_has_impl (private) &&
955 /* Not for offscreens */
956 !gdk_window_is_offscreen (private) &&
957 /* or for toplevels */
958 !gdk_window_is_toplevel (private) &&
959 /* or for foreign windows */
960 private->window_type != GDK_WINDOW_FOREIGN &&
961 /* or for the root window */
962 private->window_type != GDK_WINDOW_ROOT;
966 apply_shape (GdkWindowObject *private,
969 GdkWindowImplIface *impl_iface;
971 /* We trash whether we applied a shape so that
972 we can avoid unsetting it many times, which
973 could happen in e.g. apply_clip_as_shape as
974 windows get resized */
975 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
977 impl_iface->shape_combine_region ((GdkWindow *)private,
979 else if (private->applied_shape)
980 impl_iface->shape_combine_region ((GdkWindow *)private,
983 private->applied_shape = region != NULL;
987 apply_clip_as_shape (GdkWindowObject *private)
992 r.width = private->width;
993 r.height = private->height;
995 /* We only apply the clip region if would differ
996 from the actual clip region implied by the size
997 of the window. This is to avoid unneccessarily
998 adding meaningless shapes to all native subwindows */
999 if (!gdk_region_rect_equal (private->clip_region, &r))
1000 apply_shape (private, private->clip_region);
1002 apply_shape (private, NULL);
1006 recompute_visible_regions_internal (GdkWindowObject *private,
1007 gboolean recalculate_clip,
1008 gboolean recalculate_siblings,
1009 gboolean recalculate_children)
1013 GdkWindowObject *child;
1014 GdkRegion *new_clip, *old_clip_region_with_children;
1015 gboolean clip_region_changed;
1016 gboolean abs_pos_changed;
1017 int old_abs_x, old_abs_y;
1019 old_abs_x = private->abs_x;
1020 old_abs_y = private->abs_y;
1022 /* Update absolute position */
1023 if (gdk_window_has_impl (private))
1025 /* Native window starts here */
1031 private->abs_x = private->parent->abs_x + private->x;
1032 private->abs_y = private->parent->abs_y + private->y;
1036 private->abs_x != old_abs_x ||
1037 private->abs_y != old_abs_y;
1039 /* Update clip region based on:
1042 * siblings in parents above window
1044 clip_region_changed = FALSE;
1045 if (recalculate_clip)
1047 if (private->viewable)
1049 /* Calculate visible region (sans children) in parent window coords */
1052 r.width = private->width;
1053 r.height = private->height;
1054 new_clip = gdk_region_rectangle (&r);
1056 if (!gdk_window_is_toplevel (private))
1058 gdk_region_intersect (new_clip, private->parent->clip_region);
1060 /* Remove all overlapping children from parent.
1061 * Unless we're all native, because then we don't need to take
1062 * siblings into account since X does that clipping for us.
1063 * This makes things like SWT that modify the raw X stacking
1064 * order without GDKs knowledge work.
1066 if (!_gdk_native_windows)
1067 remove_child_area (private->parent, private, FALSE, new_clip);
1070 /* Convert from parent coords to window coords */
1071 gdk_region_offset (new_clip, -private->x, -private->y);
1074 gdk_region_intersect (new_clip, private->shape);
1077 new_clip = gdk_region_new ();
1079 if (private->clip_region == NULL ||
1080 !gdk_region_equal (private->clip_region, new_clip))
1081 clip_region_changed = TRUE;
1083 if (private->clip_region)
1084 gdk_region_destroy (private->clip_region);
1085 private->clip_region = new_clip;
1087 old_clip_region_with_children = private->clip_region_with_children;
1088 private->clip_region_with_children = gdk_region_copy (private->clip_region);
1089 if (private->window_type != GDK_WINDOW_ROOT)
1090 remove_child_area (private, NULL, FALSE, private->clip_region_with_children);
1092 if (clip_region_changed ||
1093 !gdk_region_equal (private->clip_region_with_children, old_clip_region_with_children))
1094 private->clip_tag = new_region_tag ();
1096 if (old_clip_region_with_children)
1097 gdk_region_destroy (old_clip_region_with_children);
1100 if (clip_region_changed)
1102 GdkVisibilityState visibility;
1103 gboolean fully_visible;
1105 if (gdk_region_empty (private->clip_region))
1106 visibility = GDK_VISIBILITY_FULLY_OBSCURED;
1111 fully_visible = gdk_region_equal (private->clip_region,
1118 r.width = private->width;
1119 r.height = private->height;
1120 fully_visible = gdk_region_rect_equal (private->clip_region, &r);
1124 visibility = GDK_VISIBILITY_UNOBSCURED;
1126 visibility = GDK_VISIBILITY_PARTIAL;
1129 if (private->visibility != visibility)
1131 private->visibility = visibility;
1132 gdk_window_update_visibility (private);
1136 /* Update all children, recursively (except for root, where children are not exact). */
1137 if ((abs_pos_changed || clip_region_changed || recalculate_children) &&
1138 private->window_type != GDK_WINDOW_ROOT)
1140 for (l = private->children; l; l = l->next)
1143 /* Only recalculate clip if the the clip region changed, otherwise
1144 * there is no way the child clip region could change (its has not e.g. moved)
1145 * Except if recalculate_children is set to force child updates
1147 recompute_visible_regions_internal (child,
1148 recalculate_clip && (clip_region_changed || recalculate_children),
1153 if (clip_region_changed &&
1154 should_apply_clip_as_shape (private))
1155 apply_clip_as_shape (private);
1157 if (recalculate_siblings &&
1158 !gdk_window_is_toplevel (private))
1160 /* If we moved a child window in parent or changed the stacking order, then we
1161 * need to recompute the visible area of all the other children in the parent
1163 for (l = private->parent->children; l; l = l->next)
1167 if (child != private)
1168 recompute_visible_regions_internal (child, TRUE, FALSE, FALSE);
1171 /* We also need to recompute the _with_children clip for the parent */
1172 recompute_visible_regions_internal (private->parent, TRUE, FALSE, FALSE);
1175 if (private->cairo_surface)
1179 /* It would be nice if we had some cairo support here so we
1180 could set the clip rect on the cairo surface */
1181 width = private->abs_x + private->width;
1182 height = private->abs_y + private->height;
1184 _gdk_windowing_set_cairo_surface_size (private->cairo_surface,
1186 cairo_surface_set_device_offset (private->cairo_surface,
1192 /* Call this when private has changed in one or more of these ways:
1196 * stacking order of window changed
1199 * It will recalculate abs_x/y and the clip regions
1201 * Unless the window didn't change stacking order or size/pos, pass in TRUE
1202 * for recalculate_siblings. (Mostly used internally for the recursion)
1204 * If a child window was removed (and you can't use that child for
1205 * recompute_visible_regions), pass in TRUE for recalculate_children on the parent
1208 recompute_visible_regions (GdkWindowObject *private,
1209 gboolean recalculate_siblings,
1210 gboolean recalculate_children)
1212 recompute_visible_regions_internal (private,
1214 recalculate_siblings,
1215 recalculate_children);
1219 _gdk_window_update_size (GdkWindow *window)
1221 recompute_visible_regions ((GdkWindowObject *)window, TRUE, FALSE);
1224 /* Find the native window that would be just above "child"
1225 * in the native stacking order if "child" was a native window
1226 * (it doesn't have to be native). If there is no such native
1227 * window inside this native parent then NULL is returned.
1228 * If child is NULL, find lowest native window in parent.
1230 static GdkWindowObject *
1231 find_native_sibling_above_helper (GdkWindowObject *parent,
1232 GdkWindowObject *child)
1239 l = g_list_find (parent->children, child);
1240 g_assert (l != NULL); /* Better be a child of its parent... */
1241 l = l->prev; /* Start looking at the one above the child */
1244 l = g_list_last (parent->children);
1246 for (; l != NULL; l = l->prev)
1250 if (gdk_window_has_impl (w))
1253 g_assert (parent != w);
1254 w = find_native_sibling_above_helper (w, NULL);
1263 static GdkWindowObject *
1264 find_native_sibling_above (GdkWindowObject *parent,
1265 GdkWindowObject *child)
1269 w = find_native_sibling_above_helper (parent, child);
1273 if (gdk_window_has_impl (parent))
1276 return find_native_sibling_above (parent->parent, parent);
1280 get_native_device_event_mask (GdkWindowObject *private,
1283 GdkEventMask event_mask;
1286 event_mask = GPOINTER_TO_INT (g_hash_table_lookup (private->device_events, device));
1288 event_mask = private->event_mask;
1290 if (_gdk_native_windows ||
1291 private->window_type == GDK_WINDOW_ROOT ||
1292 private->window_type == GDK_WINDOW_FOREIGN)
1298 /* Do whatever the app asks to, since the app
1299 * may be asking for weird things for native windows,
1300 * but don't use motion hints as that may affect non-native
1301 * child windows that don't want it. Also, we need to
1302 * set all the app-specified masks since they will be picked
1303 * up by any implicit grabs (i.e. if they were not set as
1304 * native we would not get the events we need). */
1305 mask = private->event_mask & ~GDK_POINTER_MOTION_HINT_MASK;
1307 /* We need thse for all native windows so we can
1308 emulate events on children: */
1311 GDK_VISIBILITY_NOTIFY_MASK |
1312 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK;
1314 /* Additionally we select for pointer and button events
1315 * for toplevels as we need to get these to emulate
1316 * them for non-native subwindows. Even though we don't
1317 * select on them for all native windows we will get them
1318 * as the events are propagated out to the first window
1319 * that select for them.
1320 * Not selecting for button press on all windows is an
1321 * important thing, because in X only one client can do
1322 * so, and we don't want to unexpectedly prevent another
1323 * client from doing it.
1325 * We also need to do the same if the app selects for button presses
1326 * because then we will get implicit grabs for this window, and the
1327 * event mask used for that grab is based on the rest of the mask
1328 * for the window, but we might need more events than this window
1329 * lists due to some non-native child window.
1331 if (gdk_window_is_toplevel (private) ||
1332 mask & GDK_BUTTON_PRESS_MASK)
1334 GDK_POINTER_MOTION_MASK |
1335 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
1343 get_native_grab_event_mask (GdkEventMask grab_mask)
1345 /* Similar to the above but for pointer events only */
1347 GDK_POINTER_MOTION_MASK |
1348 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
1349 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
1352 ~GDK_POINTER_MOTION_HINT_MASK);
1356 get_native_event_mask (GdkWindowObject *private)
1358 return get_native_device_event_mask (private, NULL);
1361 /* Puts the native window in the right order wrt the other native windows
1362 * in the hierarchy, given the position it has in the client side data.
1363 * This is useful if some operation changed the stacking order.
1364 * This calls assumes the native window is now topmost in its native parent.
1367 sync_native_window_stack_position (GdkWindow *window)
1369 GdkWindowObject *above;
1370 GdkWindowObject *private;
1371 GdkWindowImplIface *impl_iface;
1372 GList listhead = {0};
1374 private = (GdkWindowObject *) window;
1375 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
1377 above = find_native_sibling_above (private->parent, private);
1380 listhead.data = window;
1381 impl_iface->restack_under ((GdkWindow *)above,
1388 * @parent: (allow-none): a #GdkWindow, or %NULL to create the window as a child of
1389 * the default root window for the default display.
1390 * @attributes: attributes of the new window
1391 * @attributes_mask: mask indicating which fields in @attributes are valid
1393 * Creates a new #GdkWindow using the attributes from
1394 * @attributes. See #GdkWindowAttr and #GdkWindowAttributesType for
1395 * more details. Note: to use this on displays other than the default
1396 * display, @parent must be specified.
1398 * Return value: (transfer none): the new #GdkWindow
1401 gdk_window_new (GdkWindow *parent,
1402 GdkWindowAttr *attributes,
1403 gint attributes_mask)
1406 GdkWindowObject *private;
1411 GdkEventMask event_mask;
1412 GdkWindow *real_parent;
1413 GdkDeviceManager *device_manager;
1415 g_return_val_if_fail (attributes != NULL, NULL);
1419 GDK_NOTE (MULTIHEAD,
1420 g_warning ("gdk_window_new(): no parent specified reverting to parent = default root window"));
1422 screen = gdk_screen_get_default ();
1423 parent = gdk_screen_get_root_window (screen);
1426 screen = gdk_drawable_get_screen (parent);
1428 g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
1430 if (GDK_WINDOW_DESTROYED (parent))
1432 g_warning ("gdk_window_new(): parent is destroyed\n");
1436 if (attributes->window_type == GDK_WINDOW_OFFSCREEN &&
1437 _gdk_native_windows)
1439 g_warning ("Offscreen windows not supported with native-windows gdk");
1443 window = g_object_new (GDK_TYPE_WINDOW, NULL);
1444 private = (GdkWindowObject *) window;
1446 /* Windows with a foreign parent are treated as if they are children
1447 * of the root window, except for actual creation.
1449 real_parent = parent;
1450 if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
1451 parent = gdk_screen_get_root_window (screen);
1453 private->parent = (GdkWindowObject *)parent;
1455 private->accept_focus = TRUE;
1456 private->focus_on_map = TRUE;
1458 if (attributes_mask & GDK_WA_X)
1463 if (attributes_mask & GDK_WA_Y)
1470 private->width = (attributes->width > 1) ? (attributes->width) : (1);
1471 private->height = (attributes->height > 1) ? (attributes->height) : (1);
1473 #ifdef GDK_WINDOWING_X11
1474 /* Work around a bug where Xorg refuses to map toplevel InputOnly windows
1475 * from an untrusted client: http://bugs.freedesktop.org/show_bug.cgi?id=6988
1477 if (attributes->wclass == GDK_INPUT_ONLY &&
1478 private->parent->window_type == GDK_WINDOW_ROOT &&
1479 !G_LIKELY (GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (parent))->trusted_client))
1481 g_warning ("Coercing GDK_INPUT_ONLY toplevel window to GDK_INPUT_OUTPUT to work around bug in Xorg server");
1482 attributes->wclass = GDK_INPUT_OUTPUT;
1486 if (attributes->wclass == GDK_INPUT_ONLY)
1488 /* Backwards compatiblity - we've always ignored
1489 * attributes->window_type for input-only windows
1492 if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
1493 private->window_type = GDK_WINDOW_TEMP;
1495 private->window_type = GDK_WINDOW_CHILD;
1498 private->window_type = attributes->window_type;
1501 switch (private->window_type)
1503 case GDK_WINDOW_TOPLEVEL:
1504 case GDK_WINDOW_DIALOG:
1505 case GDK_WINDOW_TEMP:
1506 case GDK_WINDOW_OFFSCREEN:
1507 if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
1508 g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
1509 "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
1510 case GDK_WINDOW_CHILD:
1514 g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
1518 if (attributes_mask & GDK_WA_VISUAL)
1519 visual = attributes->visual;
1521 visual = gdk_screen_get_system_visual (screen);
1523 private->event_mask = attributes->event_mask;
1525 if (attributes->wclass == GDK_INPUT_OUTPUT)
1527 private->input_only = FALSE;
1528 private->depth = visual->depth;
1530 private->bg_color.pixel = 0; /* TODO: BlackPixel (xdisplay, screen_x11->screen_num); */
1531 private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
1533 private->bg_pixmap = NULL;
1538 private->input_only = TRUE;
1541 if (private->parent)
1542 private->parent->children = g_list_prepend (private->parent->children, window);
1544 native = _gdk_native_windows; /* Default */
1545 if (private->parent->window_type == GDK_WINDOW_ROOT)
1546 native = TRUE; /* Always use native windows for toplevels */
1547 else if (!private->input_only &&
1548 ((attributes_mask & GDK_WA_COLORMAP &&
1549 attributes->colormap != gdk_drawable_get_colormap ((GdkDrawable *)private->parent)) ||
1550 (attributes_mask & GDK_WA_VISUAL &&
1551 attributes->visual != gdk_drawable_get_visual ((GdkDrawable *)private->parent))))
1552 native = TRUE; /* InputOutput window with different colormap or visual than parent, needs native window */
1554 if (gdk_window_is_offscreen (private))
1556 _gdk_offscreen_window_new (window, screen, visual, attributes, attributes_mask);
1557 private->impl_window = private;
1561 event_mask = get_native_event_mask (private);
1563 /* Create the impl */
1564 _gdk_window_impl_new (window, real_parent, screen, visual, event_mask, attributes, attributes_mask);
1565 private->impl_window = private;
1567 /* This will put the native window topmost in the native parent, which may
1568 * be wrong wrt other native windows in the non-native hierarchy, so restack */
1569 if (!_gdk_window_has_impl (real_parent))
1570 sync_native_window_stack_position (window);
1574 private->impl_window = g_object_ref (private->parent->impl_window);
1575 private->impl = g_object_ref (private->impl_window->impl);
1578 recompute_visible_regions (private, TRUE, FALSE);
1580 if (private->parent->window_type != GDK_WINDOW_ROOT)
1582 /* Inherit redirection from parent */
1583 private->redirect = private->parent->redirect;
1586 gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
1587 (attributes->cursor) :
1590 private->device_cursor = g_hash_table_new_full (NULL, NULL, NULL,
1591 (GDestroyNotify) gdk_cursor_unref);
1593 device_manager = gdk_display_get_device_manager (gdk_drawable_get_display (GDK_DRAWABLE (parent)));
1594 g_signal_connect (device_manager, "device-removed",
1595 G_CALLBACK (device_removed_cb), window);
1601 is_parent_of (GdkWindow *parent,
1612 w = gdk_window_get_parent (w);
1619 change_impl (GdkWindowObject *private,
1620 GdkWindowObject *impl_window,
1624 GdkWindowObject *child;
1625 GdkDrawable *old_impl;
1626 GdkWindowObject *old_impl_window;
1628 old_impl = private->impl;
1629 old_impl_window = private->impl_window;
1630 if (private != impl_window)
1631 private->impl_window = g_object_ref (impl_window);
1633 private->impl_window = private;
1634 private->impl = g_object_ref (new);
1635 if (old_impl_window != private)
1636 g_object_unref (old_impl_window);
1637 g_object_unref (old_impl);
1639 for (l = private->children; l != NULL; l = l->next)
1643 if (child->impl == old_impl)
1644 change_impl (child, impl_window, new);
1649 reparent_to_impl (GdkWindowObject *private)
1652 GdkWindowObject *child;
1654 GdkWindowImplIface *impl_iface;
1656 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
1658 /* Enumerate in reverse order so we get the right order for the native
1659 windows (first in childrens list is topmost, and reparent places on top) */
1660 for (l = g_list_last (private->children); l != NULL; l = l->prev)
1664 if (child->impl == private->impl)
1665 reparent_to_impl (child);
1668 show = impl_iface->reparent ((GdkWindow *)child,
1669 (GdkWindow *)private,
1670 child->x, child->y);
1672 gdk_window_show_unraised ((GdkWindow *)child);
1679 * gdk_window_reparent:
1680 * @window: a #GdkWindow
1681 * @new_parent: new parent to move @window into
1682 * @x: X location inside the new parent
1683 * @y: Y location inside the new parent
1685 * Reparents @window into the given @new_parent. The window being
1686 * reparented will be unmapped as a side effect.
1690 gdk_window_reparent (GdkWindow *window,
1691 GdkWindow *new_parent,
1695 GdkWindowObject *private;
1696 GdkWindowObject *new_parent_private;
1697 GdkWindowObject *old_parent;
1699 gboolean show, was_mapped, applied_clip_as_shape;
1700 gboolean do_reparent_to_impl;
1701 GdkEventMask old_native_event_mask;
1702 GdkWindowImplIface *impl_iface;
1704 g_return_if_fail (GDK_IS_WINDOW (window));
1705 g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
1706 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
1708 if (GDK_WINDOW_DESTROYED (window) ||
1709 (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
1712 screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
1714 new_parent = gdk_screen_get_root_window (screen);
1716 private = (GdkWindowObject *) window;
1717 new_parent_private = (GdkWindowObject *)new_parent;
1719 /* No input-output children of input-only windows */
1720 if (new_parent_private->input_only && !private->input_only)
1723 /* Don't create loops in hierarchy */
1724 if (is_parent_of (window, new_parent))
1727 /* This might be wrong in the new parent, e.g. for non-native surfaces.
1728 To make sure we're ok, just wipe it. */
1729 gdk_window_drop_cairo_surface (private);
1731 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
1732 old_parent = private->parent;
1734 /* Break up redirection if inherited */
1735 if (private->redirect && private->redirect->redirected != private)
1737 remove_redirect_from_children (private, private->redirect);
1738 private->redirect = NULL;
1741 was_mapped = GDK_WINDOW_IS_MAPPED (window);
1744 /* Reparenting to toplevel. Ensure we have a native window so this can work */
1745 if (new_parent_private->window_type == GDK_WINDOW_ROOT ||
1746 new_parent_private->window_type == GDK_WINDOW_FOREIGN)
1747 gdk_window_ensure_native (window);
1749 applied_clip_as_shape = should_apply_clip_as_shape (private);
1751 old_native_event_mask = 0;
1752 do_reparent_to_impl = FALSE;
1753 if (gdk_window_has_impl (private))
1755 old_native_event_mask = get_native_event_mask (private);
1757 show = impl_iface->reparent (window, new_parent, x, y);
1761 /* This shouldn't happen, as we created a native in this case, check anyway to see if that ever fails */
1762 g_assert (new_parent_private->window_type != GDK_WINDOW_ROOT &&
1763 new_parent_private->window_type != GDK_WINDOW_FOREIGN);
1766 gdk_window_hide (window);
1768 do_reparent_to_impl = TRUE;
1769 change_impl (private,
1770 new_parent_private->impl_window,
1771 new_parent_private->impl);
1774 /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
1777 if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1779 new_parent = gdk_screen_get_root_window (screen);
1780 new_parent_private = (GdkWindowObject *)new_parent;
1784 old_parent->children = g_list_remove (old_parent->children, window);
1786 private->parent = new_parent_private;
1790 new_parent_private->children = g_list_prepend (new_parent_private->children, window);
1792 /* Switch the window type as appropriate */
1794 switch (GDK_WINDOW_TYPE (new_parent))
1796 case GDK_WINDOW_ROOT:
1797 case GDK_WINDOW_FOREIGN:
1798 if (private->toplevel_window_type != -1)
1799 GDK_WINDOW_TYPE (window) = private->toplevel_window_type;
1800 else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1801 GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
1803 case GDK_WINDOW_OFFSCREEN:
1804 case GDK_WINDOW_TOPLEVEL:
1805 case GDK_WINDOW_CHILD:
1806 case GDK_WINDOW_DIALOG:
1807 case GDK_WINDOW_TEMP:
1808 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
1809 GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
1811 /* Save the original window type so we can restore it if the
1812 * window is reparented back to be a toplevel
1814 private->toplevel_window_type = GDK_WINDOW_TYPE (window);
1815 GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
1819 /* We might have changed window type for a native windows, so we
1820 need to change the event mask too. */
1821 if (gdk_window_has_impl (private))
1823 GdkEventMask native_event_mask = get_native_event_mask (private);
1825 if (native_event_mask != old_native_event_mask)
1826 impl_iface->set_events (window, native_event_mask);
1829 /* Inherit parent redirect if we don't have our own */
1830 if (private->parent && private->redirect == NULL)
1832 private->redirect = private->parent->redirect;
1833 apply_redirect_to_children (private, private->redirect);
1836 _gdk_window_update_viewable (window);
1838 recompute_visible_regions (private, TRUE, FALSE);
1839 if (old_parent && GDK_WINDOW_TYPE (old_parent) != GDK_WINDOW_ROOT)
1840 recompute_visible_regions (old_parent, FALSE, TRUE);
1842 /* We used to apply the clip as the shape, but no more.
1843 Reset this to the real shape */
1844 if (gdk_window_has_impl (private) &&
1845 applied_clip_as_shape &&
1846 !should_apply_clip_as_shape (private))
1847 apply_shape (private, private->shape);
1849 if (do_reparent_to_impl)
1850 reparent_to_impl (private);
1853 /* The reparent will have put the native window topmost in the native parent,
1854 * which may be wrong wrt other native windows in the non-native hierarchy,
1856 if (!gdk_window_has_impl (new_parent_private))
1857 sync_native_window_stack_position (window);
1861 gdk_window_show_unraised (window);
1863 _gdk_synthesize_crossing_events_for_geometry_change (window);
1867 temporary_disable_extension_events (GdkWindowObject *window)
1869 GdkWindowObject *child;
1873 if (window->extension_events != 0)
1875 g_object_set_data (G_OBJECT (window),
1876 "gdk-window-extension-events",
1877 GINT_TO_POINTER (window->extension_events));
1878 gdk_input_set_extension_events ((GdkWindow *)window, 0,
1879 GDK_EXTENSION_EVENTS_NONE);
1884 for (l = window->children; l != NULL; l = l->next)
1888 if (window->impl_window == child->impl_window)
1889 res |= temporary_disable_extension_events (child);
1896 reenable_extension_events (GdkWindowObject *window)
1898 GdkWindowObject *child;
1902 mask = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window),
1903 "gdk-window-extension-events"));
1907 /* We don't have the mode here, so we pass in cursor.
1908 This works with the current code since mode is not
1909 stored except as part of the mask, and cursor doesn't
1911 gdk_input_set_extension_events ((GdkWindow *)window, mask,
1912 GDK_EXTENSION_EVENTS_CURSOR);
1913 g_object_set_data (G_OBJECT (window),
1914 "gdk-window-extension-events",
1918 for (l = window->children; l != NULL; l = l->next)
1922 if (window->impl_window == child->impl_window)
1923 reenable_extension_events (window);
1928 * gdk_window_ensure_native:
1929 * @window: a #GdkWindow
1931 * Tries to ensure that there is a window-system native window for this
1932 * GdkWindow. This may fail in some situations, returning %FALSE.
1934 * Offscreen window and children of them can never have native windows.
1936 * Some backends may not support native child windows.
1938 * Returns: %TRUE if the window has a native window, %FALSE otherwise
1943 gdk_window_ensure_native (GdkWindow *window)
1945 GdkWindowObject *private;
1946 GdkWindowObject *impl_window;
1947 GdkDrawable *new_impl, *old_impl;
1950 GdkWindowAttr attributes;
1951 GdkWindowObject *above;
1953 GdkWindowImplIface *impl_iface;
1954 gboolean disabled_extension_events;
1956 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
1958 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT ||
1959 GDK_WINDOW_DESTROYED (window))
1962 private = (GdkWindowObject *) window;
1964 impl_window = gdk_window_get_impl_window (private);
1966 if (gdk_window_is_offscreen (impl_window))
1967 return FALSE; /* native in offscreens not supported */
1969 if (impl_window == private)
1970 /* Already has an impl, and its not offscreen . */
1973 /* Need to create a native window */
1975 /* First we disable any extension events on the window or its
1976 descendants to handle the native input window moving */
1977 disabled_extension_events = FALSE;
1978 if (impl_window->input_window)
1979 disabled_extension_events = temporary_disable_extension_events (private);
1981 gdk_window_drop_cairo_surface (private);
1983 screen = gdk_drawable_get_screen (window);
1984 visual = gdk_drawable_get_visual (window);
1986 attributes.colormap = gdk_drawable_get_colormap (window);
1988 old_impl = private->impl;
1989 _gdk_window_impl_new (window, (GdkWindow *)private->parent,
1991 get_native_event_mask (private),
1992 &attributes, GDK_WA_COLORMAP);
1993 new_impl = private->impl;
1995 private->impl = old_impl;
1996 change_impl (private, private, new_impl);
1998 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
2000 /* Native window creation will put the native window topmost in the
2001 * native parent, which may be wrong wrt the position of the previous
2002 * non-native window wrt to the other non-native children, so correct this.
2004 above = find_native_sibling_above (private->parent, private);
2007 listhead.data = window;
2008 listhead.prev = NULL;
2009 listhead.next = NULL;
2010 impl_iface->restack_under ((GdkWindow *)above, &listhead);
2013 recompute_visible_regions (private, FALSE, FALSE);
2015 /* The shape may not have been set, as the clip region doesn't actually
2016 change, so do it here manually */
2017 if (should_apply_clip_as_shape (private))
2018 apply_clip_as_shape (private);
2020 reparent_to_impl (private);
2022 if (!private->input_only)
2024 impl_iface->set_background (window, &private->bg_color);
2025 if (private->bg_pixmap != NULL)
2026 impl_iface->set_back_pixmap (window, private->bg_pixmap);
2029 impl_iface->input_shape_combine_region (window,
2030 private->input_shape,
2033 if (gdk_window_is_viewable (window))
2034 impl_iface->show (window, FALSE);
2036 if (disabled_extension_events)
2037 reenable_extension_events (private);
2043 window_remove_filters (GdkWindow *window)
2045 GdkWindowObject *obj = (GdkWindowObject*) window;
2051 for (tmp_list = obj->filters; tmp_list; tmp_list = tmp_list->next)
2052 g_free (tmp_list->data);
2054 g_list_free (obj->filters);
2055 obj->filters = NULL;
2060 update_pointer_info_foreach (GdkDisplay *display,
2062 GdkPointerWindowInfo *pointer_info,
2065 GdkWindow *window = user_data;
2067 if (pointer_info->toplevel_under_pointer == window)
2069 g_object_unref (pointer_info->toplevel_under_pointer);
2070 pointer_info->toplevel_under_pointer = NULL;
2075 window_remove_from_pointer_info (GdkWindow *window,
2076 GdkDisplay *display)
2078 _gdk_display_pointer_info_foreach (display,
2079 update_pointer_info_foreach,
2084 * _gdk_window_destroy_hierarchy:
2085 * @window: a #GdkWindow
2086 * @recursing: If TRUE, then this is being called because a parent
2088 * @recursing_native: If TRUE, then this is being called because a native parent
2089 * was destroyed. This generally means that the call to the
2090 * windowing system to destroy the window can be omitted, since
2091 * it will be destroyed as a result of the parent being destroyed.
2092 * Unless @foreign_destroy.
2093 * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
2094 * external agency. The window has already been destroyed and no
2095 * windowing system calls should be made. (This may never happen
2096 * for some windowing systems.)
2098 * Internal function to destroy a window. Like gdk_window_destroy(),
2099 * but does not drop the reference count created by gdk_window_new().
2102 _gdk_window_destroy_hierarchy (GdkWindow *window,
2104 gboolean recursing_native,
2105 gboolean foreign_destroy)
2107 GdkWindowObject *private;
2108 GdkWindowObject *temp_private;
2109 GdkWindowImplIface *impl_iface;
2110 GdkWindow *temp_window;
2112 GdkDisplay *display;
2116 g_return_if_fail (GDK_IS_WINDOW (window));
2118 private = (GdkWindowObject*) window;
2120 if (GDK_WINDOW_DESTROYED (window))
2123 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
2124 screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
2125 temp_window = g_object_get_qdata (G_OBJECT (screen), quark_pointer_window);
2126 if (temp_window == window)
2127 g_object_set_qdata (G_OBJECT (screen), quark_pointer_window, NULL);
2130 switch (private->window_type)
2132 case GDK_WINDOW_ROOT:
2133 if (!screen->closed)
2135 g_error ("attempted to destroy root window");
2138 /* else fall thru */
2139 case GDK_WINDOW_TOPLEVEL:
2140 case GDK_WINDOW_CHILD:
2141 case GDK_WINDOW_DIALOG:
2142 case GDK_WINDOW_TEMP:
2143 case GDK_WINDOW_FOREIGN:
2144 case GDK_WINDOW_OFFSCREEN:
2145 if (private->window_type == GDK_WINDOW_FOREIGN && !foreign_destroy)
2147 /* Logically, it probably makes more sense to send
2148 * a "destroy yourself" message to the foreign window
2149 * whether or not it's in our hierarchy; but for historical
2150 * reasons, we only send "destroy yourself" messages to
2151 * foreign windows in our hierarchy.
2153 if (private->parent)
2154 _gdk_windowing_window_destroy_foreign (window);
2156 /* Also for historical reasons, we remove any filters
2157 * on a foreign window when it or a parent is destroyed;
2158 * this likely causes problems if two separate portions
2159 * of code are maintaining filter lists on a foreign window.
2161 window_remove_filters (window);
2165 if (private->parent)
2167 GdkWindowObject *parent_private = (GdkWindowObject *)private->parent;
2169 if (parent_private->children)
2170 parent_private->children = g_list_remove (parent_private->children, window);
2173 GDK_WINDOW_IS_MAPPED (window))
2175 recompute_visible_regions (private, TRUE, FALSE);
2176 gdk_window_invalidate_in_parent (private);
2180 gdk_window_free_paint_stack (window);
2182 if (private->bg_pixmap &&
2183 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
2184 private->bg_pixmap != GDK_NO_BG)
2186 g_object_unref (private->bg_pixmap);
2187 private->bg_pixmap = NULL;
2190 if (private->window_type == GDK_WINDOW_FOREIGN)
2191 g_assert (private->children == NULL);
2194 children = tmp = private->children;
2195 private->children = NULL;
2199 temp_window = tmp->data;
2202 temp_private = (GdkWindowObject*) temp_window;
2204 _gdk_window_destroy_hierarchy (temp_window,
2206 recursing_native || gdk_window_has_impl (private),
2210 g_list_free (children);
2213 _gdk_window_clear_update_area (window);
2215 gdk_window_drop_cairo_surface (private);
2217 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
2219 if (gdk_window_has_impl (private))
2220 impl_iface->destroy (window, recursing_native,
2224 /* hide to make sure we repaint and break grabs */
2225 gdk_window_hide (window);
2228 private->state |= GDK_WINDOW_STATE_WITHDRAWN;
2229 private->parent = NULL;
2230 private->destroyed = TRUE;
2232 window_remove_filters (window);
2234 gdk_drawable_set_colormap (GDK_DRAWABLE (window), NULL);
2236 /* If we own the redirect, free it */
2237 if (private->redirect && private->redirect->redirected == private)
2238 gdk_window_redirect_free (private->redirect);
2240 private->redirect = NULL;
2242 window_remove_from_pointer_info (window, display);
2244 if (private->clip_region)
2246 gdk_region_destroy (private->clip_region);
2247 private->clip_region = NULL;
2250 if (private->clip_region_with_children)
2252 gdk_region_destroy (private->clip_region_with_children);
2253 private->clip_region_with_children = NULL;
2256 if (private->outstanding_moves)
2258 g_list_foreach (private->outstanding_moves, (GFunc)gdk_window_region_move_free, NULL);
2259 g_list_free (private->outstanding_moves);
2260 private->outstanding_moves = NULL;
2268 * _gdk_window_destroy:
2269 * @window: a #GdkWindow
2270 * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
2271 * external agency. The window has already been destroyed and no
2272 * windowing system calls should be made. (This may never happen
2273 * for some windowing systems.)
2275 * Internal function to destroy a window. Like gdk_window_destroy(),
2276 * but does not drop the reference count created by gdk_window_new().
2279 _gdk_window_destroy (GdkWindow *window,
2280 gboolean foreign_destroy)
2282 _gdk_window_destroy_hierarchy (window, FALSE, FALSE, foreign_destroy);
2286 * gdk_window_destroy:
2287 * @window: a #GdkWindow
2289 * Destroys the window system resources associated with @window and decrements @window's
2290 * reference count. The window system resources for all children of @window are also
2291 * destroyed, but the children's reference counts are not decremented.
2293 * Note that a window will not be destroyed automatically when its reference count
2294 * reaches zero. You must call this function yourself before that happens.
2298 gdk_window_destroy (GdkWindow *window)
2300 _gdk_window_destroy_hierarchy (window, FALSE, FALSE, FALSE);
2301 g_object_unref (window);
2305 * gdk_window_set_user_data:
2306 * @window: a #GdkWindow
2307 * @user_data: user data
2309 * For most purposes this function is deprecated in favor of
2310 * g_object_set_data(). However, for historical reasons GTK+ stores
2311 * the #GtkWidget that owns a #GdkWindow as user data on the
2312 * #GdkWindow. So, custom widget implementations should use
2313 * this function for that. If GTK+ receives an event for a #GdkWindow,
2314 * and the user data for the window is non-%NULL, GTK+ will assume the
2315 * user data is a #GtkWidget, and forward the event to that widget.
2319 gdk_window_set_user_data (GdkWindow *window,
2322 g_return_if_fail (GDK_IS_WINDOW (window));
2324 ((GdkWindowObject*)window)->user_data = user_data;
2328 * gdk_window_get_user_data:
2329 * @window: a #GdkWindow
2330 * @data: return location for user data
2332 * Retrieves the user data for @window, which is normally the widget
2333 * that @window belongs to. See gdk_window_set_user_data().
2337 gdk_window_get_user_data (GdkWindow *window,
2340 g_return_if_fail (GDK_IS_WINDOW (window));
2342 *data = ((GdkWindowObject*)window)->user_data;
2346 * gdk_window_get_window_type:
2347 * @window: a #GdkWindow
2349 * Gets the type of the window. See #GdkWindowType.
2351 * Return value: type of window
2354 gdk_window_get_window_type (GdkWindow *window)
2356 g_return_val_if_fail (GDK_IS_WINDOW (window), (GdkWindowType) -1);
2358 return GDK_WINDOW_TYPE (window);
2362 * gdk_window_is_destroyed:
2363 * @window: a #GdkWindow
2365 * Check to see if a window is destroyed..
2367 * Return value: %TRUE if the window is destroyed
2372 gdk_window_is_destroyed (GdkWindow *window)
2374 return GDK_WINDOW_DESTROYED (window);
2378 to_embedder (GdkWindowObject *window,
2379 gdouble offscreen_x,
2380 gdouble offscreen_y,
2381 gdouble *embedder_x,
2382 gdouble *embedder_y)
2384 g_signal_emit (window, signals[TO_EMBEDDER], 0,
2385 offscreen_x, offscreen_y,
2386 embedder_x, embedder_y);
2390 from_embedder (GdkWindowObject *window,
2393 gdouble *offscreen_x,
2394 gdouble *offscreen_y)
2396 g_signal_emit (window, signals[FROM_EMBEDDER], 0,
2397 embedder_x, embedder_y,
2398 offscreen_x, offscreen_y);
2402 * gdk_window_get_position:
2403 * @window: a #GdkWindow
2404 * @x: X coordinate of window
2405 * @y: Y coordinate of window
2407 * Obtains the position of the window as reported in the
2408 * most-recently-processed #GdkEventConfigure. Contrast with
2409 * gdk_window_get_geometry() which queries the X server for the
2410 * current window position, regardless of which events have been
2411 * received or processed.
2413 * The position coordinates are relative to the window's parent window.
2417 gdk_window_get_position (GdkWindow *window,
2421 GdkWindowObject *obj;
2423 g_return_if_fail (GDK_IS_WINDOW (window));
2425 obj = (GdkWindowObject*) window;
2434 * gdk_window_get_parent:
2435 * @window: a #GdkWindow
2437 * Obtains the parent of @window, as known to GDK. Does not query the
2438 * X server; thus this returns the parent as passed to gdk_window_new(),
2439 * not the actual parent. This should never matter unless you're using
2440 * Xlib calls mixed with GDK calls on the X11 platform. It may also
2441 * matter for toplevel windows, because the window manager may choose
2444 * Note that you should use gdk_window_get_effective_parent() when
2445 * writing generic code that walks up a window hierarchy, because
2446 * gdk_window_get_parent() will most likely not do what you expect if
2447 * there are offscreen windows in the hierarchy.
2449 * Return value: parent of @window
2452 gdk_window_get_parent (GdkWindow *window)
2454 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2456 return (GdkWindow*) ((GdkWindowObject*) window)->parent;
2460 * gdk_window_get_effective_parent:
2461 * @window: a #GdkWindow
2463 * Obtains the parent of @window, as known to GDK. Works like
2464 * gdk_window_get_parent() for normal windows, but returns the
2465 * window's embedder for offscreen windows.
2467 * See also: gdk_offscreen_window_get_embedder()
2469 * Return value: effective parent of @window
2474 gdk_window_get_effective_parent (GdkWindow *window)
2476 GdkWindowObject *obj;
2478 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2480 obj = (GdkWindowObject *)window;
2482 if (gdk_window_is_offscreen (obj))
2483 return gdk_offscreen_window_get_embedder (window);
2485 return (GdkWindow *) obj->parent;
2489 * gdk_window_get_toplevel:
2490 * @window: a #GdkWindow
2492 * Gets the toplevel window that's an ancestor of @window.
2494 * Any window type but %GDK_WINDOW_CHILD is considered a
2495 * toplevel window, as is a %GDK_WINDOW_CHILD window that
2496 * has a root window as parent.
2498 * Note that you should use gdk_window_get_effective_toplevel() when
2499 * you want to get to a window's toplevel as seen on screen, because
2500 * gdk_window_get_toplevel() will most likely not do what you expect
2501 * if there are offscreen windows in the hierarchy.
2503 * Return value: the toplevel window containing @window
2506 gdk_window_get_toplevel (GdkWindow *window)
2508 GdkWindowObject *obj;
2510 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2512 obj = (GdkWindowObject *)window;
2514 while (obj->window_type == GDK_WINDOW_CHILD)
2516 if (gdk_window_is_toplevel (obj))
2521 return GDK_WINDOW (obj);
2525 * gdk_window_get_effective_toplevel:
2526 * @window: a #GdkWindow
2528 * Gets the toplevel window that's an ancestor of @window.
2530 * Works like gdk_window_get_toplevel(), but treats an offscreen window's
2531 * embedder as its parent, using gdk_window_get_effective_parent().
2533 * See also: gdk_offscreen_window_get_embedder()
2535 * Return value: the effective toplevel window containing @window
2540 gdk_window_get_effective_toplevel (GdkWindow *window)
2544 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2546 while ((parent = gdk_window_get_effective_parent (window)) != NULL &&
2547 (gdk_window_get_window_type (parent) != GDK_WINDOW_ROOT))
2554 * gdk_window_get_children:
2555 * @window: a #GdkWindow
2557 * Gets the list of children of @window known to GDK.
2558 * This function only returns children created via GDK,
2559 * so for example it's useless when used with the root window;
2560 * it only returns windows an application created itself.
2562 * The returned list must be freed, but the elements in the
2565 * Return value: list of child windows inside @window
2568 gdk_window_get_children (GdkWindow *window)
2570 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2572 if (GDK_WINDOW_DESTROYED (window))
2575 return g_list_copy (GDK_WINDOW_OBJECT (window)->children);
2579 * gdk_window_peek_children:
2580 * @window: a #GdkWindow
2582 * Like gdk_window_get_children(), but does not copy the list of
2583 * children, so the list does not need to be freed.
2585 * Return value: a reference to the list of child windows in @window
2588 gdk_window_peek_children (GdkWindow *window)
2590 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2592 if (GDK_WINDOW_DESTROYED (window))
2595 return GDK_WINDOW_OBJECT (window)->children;
2599 * gdk_window_add_filter:
2600 * @window: a #GdkWindow
2601 * @function: filter callback
2602 * @data: data to pass to filter callback
2604 * Adds an event filter to @window, allowing you to intercept events
2605 * before they reach GDK. This is a low-level operation and makes it
2606 * easy to break GDK and/or GTK+, so you have to know what you're
2607 * doing. Pass %NULL for @window to get all events for all windows,
2608 * instead of events for a specific window.
2610 * See gdk_display_add_client_message_filter() if you are interested
2611 * in X ClientMessage events.
2614 gdk_window_add_filter (GdkWindow *window,
2615 GdkFilterFunc function,
2618 GdkWindowObject *private;
2620 GdkEventFilter *filter;
2622 g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
2624 private = (GdkWindowObject*) window;
2625 if (private && GDK_WINDOW_DESTROYED (window))
2628 /* Filters are for the native events on the native window, so
2629 ensure there is a native window. */
2631 gdk_window_ensure_native (window);
2634 tmp_list = private->filters;
2636 tmp_list = _gdk_default_filters;
2640 filter = (GdkEventFilter *)tmp_list->data;
2641 if ((filter->function == function) && (filter->data == data))
2643 tmp_list = tmp_list->next;
2646 filter = g_new (GdkEventFilter, 1);
2647 filter->function = function;
2648 filter->data = data;
2651 private->filters = g_list_append (private->filters, filter);
2653 _gdk_default_filters = g_list_append (_gdk_default_filters, filter);
2657 * gdk_window_remove_filter:
2658 * @window: a #GdkWindow
2659 * @function: previously-added filter function
2660 * @data: user data for previously-added filter function
2662 * Remove a filter previously added with gdk_window_add_filter().
2666 gdk_window_remove_filter (GdkWindow *window,
2667 GdkFilterFunc function,
2670 GdkWindowObject *private;
2671 GList *tmp_list, *node;
2672 GdkEventFilter *filter;
2674 g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
2676 private = (GdkWindowObject*) window;
2679 tmp_list = private->filters;
2681 tmp_list = _gdk_default_filters;
2685 filter = (GdkEventFilter *)tmp_list->data;
2687 tmp_list = tmp_list->next;
2689 if ((filter->function == function) && (filter->data == data))
2692 private->filters = g_list_remove_link (private->filters, node);
2694 _gdk_default_filters = g_list_remove_link (_gdk_default_filters, node);
2695 g_list_free_1 (node);
2704 * gdk_screen_get_toplevel_windows:
2705 * @screen: The #GdkScreen where the toplevels are located.
2707 * Obtains a list of all toplevel windows known to GDK on the screen @screen.
2708 * A toplevel window is a child of the root window (see
2709 * gdk_get_default_root_window()).
2711 * The returned list should be freed with g_list_free(), but
2712 * its elements need not be freed.
2714 * Return value: list of toplevel windows, free with g_list_free()
2719 gdk_screen_get_toplevel_windows (GdkScreen *screen)
2721 GdkWindow * root_window;
2722 GList *new_list = NULL;
2725 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
2727 root_window = gdk_screen_get_root_window (screen);
2729 tmp_list = ((GdkWindowObject *)root_window)->children;
2732 GdkWindowObject *w = tmp_list->data;
2734 if (w->window_type != GDK_WINDOW_FOREIGN)
2735 new_list = g_list_prepend (new_list, w);
2736 tmp_list = tmp_list->next;
2743 * gdk_window_is_visible:
2744 * @window: a #GdkWindow
2746 * Checks whether the window has been mapped (with gdk_window_show() or
2747 * gdk_window_show_unraised()).
2749 * Return value: %TRUE if the window is mapped
2752 gdk_window_is_visible (GdkWindow *window)
2754 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2756 return GDK_WINDOW_IS_MAPPED (window);
2760 * gdk_window_is_viewable:
2761 * @window: a #GdkWindow
2763 * Check if the window and all ancestors of the window are
2764 * mapped. (This is not necessarily "viewable" in the X sense, since
2765 * we only check as far as we have GDK window parents, not to the root
2768 * Return value: %TRUE if the window is viewable
2771 gdk_window_is_viewable (GdkWindow *window)
2773 GdkWindowObject *private = (GdkWindowObject *)window;
2775 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2777 if (private->destroyed)
2780 return private->viewable;
2784 * gdk_window_get_state:
2785 * @window: a #GdkWindow
2787 * Gets the bitwise OR of the currently active window state flags,
2788 * from the #GdkWindowState enumeration.
2790 * Return value: window state bitfield
2793 gdk_window_get_state (GdkWindow *window)
2795 GdkWindowObject *private = (GdkWindowObject *)window;
2797 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2799 return private->state;
2803 /* This creates an empty "implicit" paint region for the impl window.
2804 * By itself this does nothing, but real paints to this window
2805 * or children of it can use this pixmap as backing to avoid allocating
2806 * multiple pixmaps for subwindow rendering. When doing so they
2807 * add to the region of the implicit paint region, which will be
2808 * pushed to the window when the implicit paint region is ended.
2809 * Such paints should not copy anything to the window on paint end, but
2810 * should rely on the implicit paint end.
2811 * The implicit paint will be automatically ended if someone draws
2812 * directly to the window or a child window.
2815 gdk_window_begin_implicit_paint (GdkWindow *window, GdkRectangle *rect)
2817 GdkWindowObject *private = (GdkWindowObject *)window;
2818 GdkWindowPaint *paint;
2820 g_assert (gdk_window_has_impl (private));
2822 if (_gdk_native_windows)
2823 return FALSE; /* No need for implicit paints since we can't merge draws anyway */
2825 if (GDK_IS_PAINTABLE (private->impl))
2826 return FALSE; /* Implementation does double buffering */
2828 if (private->paint_stack != NULL ||
2829 private->implicit_paint != NULL)
2830 return FALSE; /* Don't stack implicit paints */
2832 if (private->outstanding_surfaces != 0)
2833 return FALSE; /* May conflict with direct drawing to cairo surface */
2835 /* Never do implicit paints for foreign windows, they don't need
2836 * double buffer combination since they have no client side children,
2837 * and creating pixmaps for them is risky since they could disappear
2840 if (private->window_type == GDK_WINDOW_FOREIGN)
2843 paint = g_new (GdkWindowPaint, 1);
2844 paint->region = gdk_region_new (); /* Empty */
2845 paint->x_offset = rect->x;
2846 paint->y_offset = rect->y;
2847 paint->uses_implicit = FALSE;
2848 paint->flushed = FALSE;
2849 paint->surface = NULL;
2851 gdk_pixmap_new (window,
2852 MAX (rect->width, 1), MAX (rect->height, 1), -1);
2854 private->implicit_paint = paint;
2859 /* Ensure that all content related to this (sub)window is pushed to the
2860 native region. If there is an active paint then that area is not
2861 pushed, in order to not show partially finished double buffers. */
2863 gdk_window_flush_implicit_paint (GdkWindow *window)
2865 GdkWindowObject *private = (GdkWindowObject *)window;
2866 GdkWindowObject *impl_window;
2867 GdkWindowPaint *paint;
2872 impl_window = gdk_window_get_impl_window (private);
2873 if (impl_window->implicit_paint == NULL)
2876 paint = impl_window->implicit_paint;
2877 paint->flushed = TRUE;
2878 region = gdk_region_copy (private->clip_region_with_children);
2880 /* Don't flush active double buffers, as that may show partially done
2882 for (list = private->paint_stack; list != NULL; list = list->next)
2884 GdkWindowPaint *tmp_paint = list->data;
2886 gdk_region_subtract (region, tmp_paint->region);
2889 gdk_region_offset (region, private->abs_x, private->abs_y);
2890 gdk_region_intersect (region, paint->region);
2892 if (!GDK_WINDOW_DESTROYED (window) && !gdk_region_empty (region))
2894 /* Remove flushed region from the implicit paint */
2895 gdk_region_subtract (paint->region, region);
2897 /* Some regions are valid, push these to window now */
2898 tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
2899 _gdk_gc_set_clip_region_internal (tmp_gc, region, TRUE);
2900 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2901 0, 0, paint->x_offset, paint->y_offset, -1, -1);
2902 /* Reset clip region of the cached GdkGC */
2903 gdk_gc_set_clip_region (tmp_gc, NULL);
2906 gdk_region_destroy (region);
2909 /* Ends an implicit paint, paired with gdk_window_begin_implicit_paint returning TRUE */
2911 gdk_window_end_implicit_paint (GdkWindow *window)
2913 GdkWindowObject *private = (GdkWindowObject *)window;
2914 GdkWindowPaint *paint;
2917 g_assert (gdk_window_has_impl (private));
2919 g_assert (private->implicit_paint != NULL);
2921 paint = private->implicit_paint;
2923 private->implicit_paint = NULL;
2925 if (!GDK_WINDOW_DESTROYED (window) && !gdk_region_empty (paint->region))
2927 /* Some regions are valid, push these to window now */
2928 tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
2929 _gdk_gc_set_clip_region_internal (tmp_gc, paint->region, TRUE);
2930 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2931 0, 0, paint->x_offset, paint->y_offset, -1, -1);
2932 /* Reset clip region of the cached GdkGC */
2933 gdk_gc_set_clip_region (tmp_gc, NULL);
2936 gdk_region_destroy (paint->region);
2938 g_object_unref (paint->pixmap);
2943 * gdk_window_begin_paint_rect:
2944 * @window: a #GdkWindow
2945 * @rectangle: rectangle you intend to draw to
2947 * A convenience wrapper around gdk_window_begin_paint_region() which
2948 * creates a rectangular region for you. See
2949 * gdk_window_begin_paint_region() for details.
2953 gdk_window_begin_paint_rect (GdkWindow *window,
2954 const GdkRectangle *rectangle)
2958 g_return_if_fail (GDK_IS_WINDOW (window));
2960 region = gdk_region_rectangle (rectangle);
2961 gdk_window_begin_paint_region (window, region);
2962 gdk_region_destroy (region);
2966 * gdk_window_begin_paint_region:
2967 * @window: a #GdkWindow
2968 * @region: region you intend to draw to
2970 * Indicates that you are beginning the process of redrawing @region.
2971 * A backing store (offscreen buffer) large enough to contain @region
2972 * will be created. The backing store will be initialized with the
2973 * background color or background pixmap for @window. Then, all
2974 * drawing operations performed on @window will be diverted to the
2975 * backing store. When you call gdk_window_end_paint(), the backing
2976 * store will be copied to @window, making it visible onscreen. Only
2977 * the part of @window contained in @region will be modified; that is,
2978 * drawing operations are clipped to @region.
2980 * The net result of all this is to remove flicker, because the user
2981 * sees the finished product appear all at once when you call
2982 * gdk_window_end_paint(). If you draw to @window directly without
2983 * calling gdk_window_begin_paint_region(), the user may see flicker
2984 * as individual drawing operations are performed in sequence. The
2985 * clipping and background-initializing features of
2986 * gdk_window_begin_paint_region() are conveniences for the
2987 * programmer, so you can avoid doing that work yourself.
2989 * When using GTK+, the widget system automatically places calls to
2990 * gdk_window_begin_paint_region() and gdk_window_end_paint() around
2991 * emissions of the expose_event signal. That is, if you're writing an
2992 * expose event handler, you can assume that the exposed area in
2993 * #GdkEventExpose has already been cleared to the window background,
2994 * is already set as the clip region, and already has a backing store.
2995 * Therefore in most cases, application code need not call
2996 * gdk_window_begin_paint_region(). (You can disable the automatic
2997 * calls around expose events on a widget-by-widget basis by calling
2998 * gtk_widget_set_double_buffered().)
3000 * If you call this function multiple times before calling the
3001 * matching gdk_window_end_paint(), the backing stores are pushed onto
3002 * a stack. gdk_window_end_paint() copies the topmost backing store
3003 * onscreen, subtracts the topmost region from all other regions in
3004 * the stack, and pops the stack. All drawing operations affect only
3005 * the topmost backing store in the stack. One matching call to
3006 * gdk_window_end_paint() is required for each call to
3007 * gdk_window_begin_paint_region().
3011 gdk_window_begin_paint_region (GdkWindow *window,
3012 const GdkRegion *region)
3014 #ifdef USE_BACKING_STORE
3015 GdkWindowObject *private = (GdkWindowObject *)window;
3016 GdkRectangle clip_box;
3017 GdkWindowPaint *paint, *implicit_paint;
3018 GdkWindowObject *impl_window;
3021 g_return_if_fail (GDK_IS_WINDOW (window));
3023 if (GDK_WINDOW_DESTROYED (window))
3026 if (GDK_IS_PAINTABLE (private->impl))
3028 GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
3030 if (iface->begin_paint_region)
3031 iface->begin_paint_region ((GdkPaintable*)private->impl, window, region);
3036 impl_window = gdk_window_get_impl_window (private);
3037 implicit_paint = impl_window->implicit_paint;
3039 paint = g_new (GdkWindowPaint, 1);
3040 paint->region = gdk_region_copy (region);
3041 paint->region_tag = new_region_tag ();
3043 gdk_region_intersect (paint->region, private->clip_region_with_children);
3044 gdk_region_get_clipbox (paint->region, &clip_box);
3046 /* Convert to impl coords */
3047 gdk_region_offset (paint->region, private->abs_x, private->abs_y);
3049 /* Mark the region as valid on the implicit paint */
3052 gdk_region_union (implicit_paint->region, paint->region);
3054 /* Convert back to normal coords */
3055 gdk_region_offset (paint->region, -private->abs_x, -private->abs_y);
3061 paint->uses_implicit = TRUE;
3062 paint->pixmap = g_object_ref (implicit_paint->pixmap);
3063 paint->x_offset = -private->abs_x + implicit_paint->x_offset;
3064 paint->y_offset = -private->abs_y + implicit_paint->y_offset;
3066 gdk_drawable_get_size (paint->pixmap, &width, &height);
3067 paint->surface = _gdk_drawable_create_cairo_surface (paint->pixmap, width, height);
3071 paint->uses_implicit = FALSE;
3072 paint->x_offset = clip_box.x;
3073 paint->y_offset = clip_box.y;
3075 gdk_pixmap_new (window,
3076 MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1);
3077 paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap);
3081 cairo_surface_set_device_offset (paint->surface,
3082 -paint->x_offset, -paint->y_offset);
3084 for (list = private->paint_stack; list != NULL; list = list->next)
3086 GdkWindowPaint *tmp_paint = list->data;
3088 gdk_region_subtract (tmp_paint->region, paint->region);
3091 private->paint_stack = g_slist_prepend (private->paint_stack, paint);
3093 if (!gdk_region_empty (paint->region))
3095 gdk_window_clear_backing_region (window,
3099 #endif /* USE_BACKING_STORE */
3103 setup_redirect_clip (GdkWindow *window,
3108 GdkWindowObject *private = (GdkWindowObject *)window;
3109 GdkRegion *visible_region;
3110 GdkRectangle dest_rect;
3112 GdkWindow *toplevel;
3113 int x_offset, y_offset;
3115 toplevel = GDK_WINDOW (private->redirect->redirected);
3117 /* Get the clip region for gc clip rect + window hierarchy in
3118 window relative coords */
3120 _gdk_window_calculate_full_clip_region (window, toplevel,
3125 /* Compensate for the source pos/size */
3126 x_offset -= private->redirect->src_x;
3127 y_offset -= private->redirect->src_y;
3128 dest_rect.x = -x_offset;
3129 dest_rect.y = -y_offset;
3130 dest_rect.width = private->redirect->width;
3131 dest_rect.height = private->redirect->height;
3132 tmpreg = gdk_region_rectangle (&dest_rect);
3133 gdk_region_intersect (visible_region, tmpreg);
3134 gdk_region_destroy (tmpreg);
3136 /* Compensate for the dest pos */
3137 x_offset += private->redirect->dest_x;
3138 y_offset += private->redirect->dest_y;
3140 gdk_gc_set_clip_region (gc, visible_region); /* This resets clip origin! */
3142 /* offset clip and tiles from window coords to pixmaps coords */
3143 gdk_gc_offset (gc, -x_offset, -y_offset);
3145 gdk_region_destroy (visible_region);
3147 *x_offset_out = x_offset;
3148 *y_offset_out = y_offset;
3152 * gdk_window_end_paint:
3153 * @window: a #GdkWindow
3155 * Indicates that the backing store created by the most recent call to
3156 * gdk_window_begin_paint_region() should be copied onscreen and
3157 * deleted, leaving the next-most-recent backing store or no backing
3158 * store at all as the active paint region. See
3159 * gdk_window_begin_paint_region() for full details. It is an error to
3160 * call this function without a matching
3161 * gdk_window_begin_paint_region() first.
3165 gdk_window_end_paint (GdkWindow *window)
3167 #ifdef USE_BACKING_STORE
3168 GdkWindowObject *private = (GdkWindowObject *)window;
3169 GdkWindowObject *composited;
3170 GdkWindowPaint *paint;
3172 GdkRectangle clip_box;
3173 gint x_offset, y_offset;
3174 GdkRegion *full_clip;
3176 g_return_if_fail (GDK_IS_WINDOW (window));
3178 if (GDK_WINDOW_DESTROYED (window))
3181 if (GDK_IS_PAINTABLE (private->impl))
3183 GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
3185 if (iface->end_paint)
3186 iface->end_paint ((GdkPaintable*)private->impl);
3190 if (private->paint_stack == NULL)
3192 g_warning (G_STRLOC": no preceding call to gdk_window_begin_paint_region(), see documentation");
3196 paint = private->paint_stack->data;
3198 private->paint_stack = g_slist_delete_link (private->paint_stack,
3199 private->paint_stack);
3201 gdk_region_get_clipbox (paint->region, &clip_box);
3203 tmp_gc = _gdk_drawable_get_scratch_gc (window, FALSE);
3205 x_offset = -private->abs_x;
3206 y_offset = -private->abs_y;
3208 if (!paint->uses_implicit)
3210 gdk_window_flush_outstanding_moves (window);
3212 full_clip = gdk_region_copy (private->clip_region_with_children);
3213 gdk_region_intersect (full_clip, paint->region);
3214 _gdk_gc_set_clip_region_internal (tmp_gc, full_clip, TRUE); /* Takes ownership of full_clip */
3215 gdk_gc_set_clip_origin (tmp_gc, - x_offset, - y_offset);
3216 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
3217 clip_box.x - paint->x_offset,
3218 clip_box.y - paint->y_offset,
3219 clip_box.x - x_offset, clip_box.y - y_offset,
3220 clip_box.width, clip_box.height);
3223 if (private->redirect)
3225 int x_offset, y_offset;
3227 /* TODO: Should also use paint->region for clipping */
3228 setup_redirect_clip (window, tmp_gc, &x_offset, &y_offset);
3229 gdk_draw_drawable (private->redirect->pixmap, tmp_gc, paint->pixmap,
3230 clip_box.x - paint->x_offset,
3231 clip_box.y - paint->y_offset,
3232 clip_box.x + x_offset,
3233 clip_box.y + y_offset,
3234 clip_box.width, clip_box.height);
3237 /* Reset clip region of the cached GdkGC */
3238 gdk_gc_set_clip_region (tmp_gc, NULL);
3240 cairo_surface_destroy (paint->surface);
3241 g_object_unref (paint->pixmap);
3242 gdk_region_destroy (paint->region);
3245 /* find a composited window in our hierarchy to signal its
3246 * parent to redraw, calculating the clip box as we go...
3248 * stop if parent becomes NULL since then we'd have nowhere
3249 * to draw (ie: 'composited' will always be non-NULL here).
3251 for (composited = private;
3253 composited = composited->parent)
3257 gdk_drawable_get_size (GDK_DRAWABLE (composited->parent),
3260 clip_box.x += composited->x;
3261 clip_box.y += composited->y;
3262 clip_box.width = MIN (clip_box.width, width - clip_box.x);
3263 clip_box.height = MIN (clip_box.height, height - clip_box.y);
3265 if (composited->composited)
3267 gdk_window_invalidate_rect (GDK_WINDOW (composited->parent),
3272 #endif /* USE_BACKING_STORE */
3276 gdk_window_free_paint_stack (GdkWindow *window)
3278 GdkWindowObject *private = (GdkWindowObject *)window;
3280 if (private->paint_stack)
3282 GSList *tmp_list = private->paint_stack;
3286 GdkWindowPaint *paint = tmp_list->data;
3288 if (tmp_list == private->paint_stack)
3289 g_object_unref (paint->pixmap);
3291 gdk_region_destroy (paint->region);
3294 tmp_list = tmp_list->next;
3297 g_slist_free (private->paint_stack);
3298 private->paint_stack = NULL;
3303 do_move_region_bits_on_impl (GdkWindowObject *impl_window,
3304 GdkRegion *dest_region, /* In impl window coords */
3308 GdkRectangle copy_rect;
3309 GdkWindowObject *private;
3310 GdkWindowImplIface *impl_iface;
3312 /* We need to get data from subwindows here, because we might have
3313 * shaped a native window over the moving region (with bg none,
3314 * so the pixels are still there). In fact we might need to get data
3315 * from overlapping native window that are not children of this window,
3316 * so we copy from the toplevel with INCLUDE_INFERIORS.
3318 private = impl_window;
3319 while (!gdk_window_is_toplevel (private))
3321 dx -= private->parent->abs_x + private->x;
3322 dy -= private->parent->abs_y + private->y;
3323 private = gdk_window_get_impl_window (private->parent);
3325 tmp_gc = _gdk_drawable_get_subwindow_scratch_gc ((GdkWindow *)private);
3327 gdk_region_get_clipbox (dest_region, ©_rect);
3328 gdk_gc_set_clip_region (tmp_gc, dest_region);
3330 /* The region area is moved and we queue translations for all expose events
3331 to the source area that were sent prior to the copy */
3332 gdk_region_offset (dest_region, -dx, -dy); /* Move to source region */
3333 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
3335 impl_iface->queue_translation ((GdkWindow *)impl_window,
3337 dest_region, dx, dy);
3339 gdk_draw_drawable (impl_window->impl,
3342 copy_rect.x-dx, copy_rect.y-dy,
3343 copy_rect.x, copy_rect.y,
3344 copy_rect.width, copy_rect.height);
3345 gdk_gc_set_clip_region (tmp_gc, NULL);
3348 static GdkWindowRegionMove *
3349 gdk_window_region_move_new (GdkRegion *region,
3352 GdkWindowRegionMove *move;
3354 move = g_slice_new (GdkWindowRegionMove);
3355 move->dest_region = gdk_region_copy (region);
3363 gdk_window_region_move_free (GdkWindowRegionMove *move)
3365 gdk_region_destroy (move->dest_region);
3366 g_slice_free (GdkWindowRegionMove, move);
3370 append_move_region (GdkWindowObject *impl_window,
3371 GdkRegion *new_dest_region,
3374 GdkWindowRegionMove *move, *old_move;
3375 GdkRegion *new_total_region, *old_total_region;
3376 GdkRegion *source_overlaps_destination;
3377 GdkRegion *non_overwritten;
3378 gboolean added_move;
3381 if (gdk_region_empty (new_dest_region))
3384 /* In principle this could just append the move to the list of outstanding
3385 moves that will be replayed before drawing anything when we're handling
3386 exposes. However, we'd like to do a bit better since its commonly the case
3387 that we get multiple copies where A is copied to B and then B is copied
3388 to C, and we'd like to express this as a simple copy A to C operation. */
3390 /* We approach this by taking the new move and pushing it ahead of moves
3391 starting at the end of the list and stopping when its not safe to do so.
3392 It's not safe to push past a move if either the source of the new move
3393 is in the destination of the old move, or if the destination of the new
3394 move is in the source of the new move, or if the destination of the new
3395 move overlaps the destination of the old move. We simplify this by
3396 just comparing the total regions (src + dest) */
3397 new_total_region = gdk_region_copy (new_dest_region);
3398 gdk_region_offset (new_total_region, -dx, -dy);
3399 gdk_region_union (new_total_region, new_dest_region);
3402 for (l = g_list_last (impl_window->outstanding_moves); l != NULL; l = prev)
3407 old_total_region = gdk_region_copy (old_move->dest_region);
3408 gdk_region_offset (old_total_region, -old_move->dx, -old_move->dy);
3409 gdk_region_union (old_total_region, old_move->dest_region);
3411 gdk_region_intersect (old_total_region, new_total_region);
3412 /* If these regions intersect then its not safe to push the
3413 new region before the old one */
3414 if (!gdk_region_empty (old_total_region))
3416 /* The area where the new moves source overlaps the old ones
3418 source_overlaps_destination = gdk_region_copy (new_dest_region);
3419 gdk_region_offset (source_overlaps_destination, -dx, -dy);
3420 gdk_region_intersect (source_overlaps_destination, old_move->dest_region);
3421 gdk_region_offset (source_overlaps_destination, dx, dy);
3423 /* We can do all sort of optimizations here, but to do things safely it becomes
3424 quite complicated. However, a very common case is that you copy something first,
3425 then copy all that or a subset of it to a new location (i.e. if you scroll twice
3426 in the same direction). We'd like to detect this case and optimize it to one
3428 if (gdk_region_equal (source_overlaps_destination, new_dest_region))
3430 /* This means we might be able to replace the old move and the new one
3431 with the new one read from the old ones source, and a second copy of
3432 the non-overwritten parts of the old move. However, such a split
3433 is only valid if the source in the old move isn't overwritten
3434 by the destination of the new one */
3436 /* the new destination of old move if split is ok: */
3437 non_overwritten = gdk_region_copy (old_move->dest_region);
3438 gdk_region_subtract (non_overwritten, new_dest_region);
3439 /* move to source region */
3440 gdk_region_offset (non_overwritten, -old_move->dx, -old_move->dy);
3442 gdk_region_intersect (non_overwritten, new_dest_region);
3443 if (gdk_region_empty (non_overwritten))
3446 move = gdk_window_region_move_new (new_dest_region,
3450 impl_window->outstanding_moves =
3451 g_list_insert_before (impl_window->outstanding_moves,
3453 gdk_region_subtract (old_move->dest_region, new_dest_region);
3455 gdk_region_destroy (non_overwritten);
3458 gdk_region_destroy (source_overlaps_destination);
3459 gdk_region_destroy (old_total_region);
3462 gdk_region_destroy (old_total_region);
3465 gdk_region_destroy (new_total_region);
3469 move = gdk_window_region_move_new (new_dest_region, dx, dy);
3472 impl_window->outstanding_moves =
3473 g_list_prepend (impl_window->outstanding_moves,
3476 impl_window->outstanding_moves =
3477 g_list_insert_before (impl_window->outstanding_moves,
3482 /* Moves bits and update area by dx/dy in impl window.
3483 Takes ownership of region to avoid copy (because we may change it) */
3485 move_region_on_impl (GdkWindowObject *impl_window,
3486 GdkRegion *region, /* In impl window coords */
3489 if ((dx == 0 && dy == 0) ||
3490 gdk_region_empty (region))
3492 gdk_region_destroy (region);
3496 g_assert (impl_window == gdk_window_get_impl_window (impl_window));
3498 /* Move any old invalid regions in the copy source area by dx/dy */
3499 if (impl_window->update_area)
3501 GdkRegion *update_area;
3503 update_area = gdk_region_copy (region);
3505 /* Convert from target to source */
3506 gdk_region_offset (update_area, -dx, -dy);
3507 gdk_region_intersect (update_area, impl_window->update_area);
3508 /* We only copy the area, so keep the old update area invalid.
3509 It would be safe to remove it too, as code that uses
3510 move_region_on_impl generally also invalidate the source
3511 area. However, it would just use waste cycles. */
3514 gdk_region_offset (update_area, dx, dy);
3515 gdk_region_union (impl_window->update_area, update_area);
3517 /* This area of the destination is now invalid,
3518 so no need to copy to it. */
3519 gdk_region_subtract (region, update_area);
3521 gdk_region_destroy (update_area);
3524 /* If we're currently exposing this window, don't copy to this
3525 destination, as it will be overdrawn when the expose is done,
3526 instead invalidate it and repaint later. */
3527 if (impl_window->implicit_paint)
3529 GdkWindowPaint *implicit_paint = impl_window->implicit_paint;
3530 GdkRegion *exposing;
3532 exposing = gdk_region_copy (implicit_paint->region);
3533 gdk_region_intersect (exposing, region);
3534 gdk_region_subtract (region, exposing);
3536 impl_window_add_update_area (impl_window, exposing);
3537 gdk_region_destroy (exposing);
3540 if (impl_window->outstanding_surfaces == 0) /* Enable flicker free handling of moves. */
3541 append_move_region (impl_window, region, dx, dy);
3543 do_move_region_bits_on_impl (impl_window,
3546 gdk_region_destroy (region);
3549 /* Flushes all outstanding changes to the window, call this
3550 * before drawing directly to the window (i.e. outside a begin/end_paint pair).
3553 gdk_window_flush_outstanding_moves (GdkWindow *window)
3555 GdkWindowObject *private;
3556 GdkWindowObject *impl_window;
3558 GdkWindowRegionMove *move;
3560 private = (GdkWindowObject *) window;
3562 impl_window = gdk_window_get_impl_window (private);
3564 for (l = impl_window->outstanding_moves; l != NULL; l = l->next)
3568 do_move_region_bits_on_impl (impl_window,
3569 move->dest_region, move->dx, move->dy);
3571 gdk_window_region_move_free (move);
3574 g_list_free (impl_window->outstanding_moves);
3575 impl_window->outstanding_moves = NULL;
3580 * @window: a #GdkWindow
3582 * Flush all outstanding cached operations on a window, leaving the
3583 * window in a state which reflects all that has been drawn before.
3585 * Gdk uses multiple kinds of caching to get better performance and
3586 * nicer drawing. For instance, during exposes all paints to a window
3587 * using double buffered rendering are keep on a pixmap until the last
3588 * window has been exposed. It also delays window moves/scrolls until
3589 * as long as possible until next update to avoid tearing when moving
3592 * Normally this should be completely invisible to applications, as
3593 * we automatically flush the windows when required, but this might
3594 * be needed if you for instance mix direct native drawing with
3595 * gdk drawing. For Gtk widgets that don't use double buffering this
3596 * will be called automatically before sending the expose event.
3601 gdk_window_flush (GdkWindow *window)
3603 gdk_window_flush_outstanding_moves (window);
3604 gdk_window_flush_implicit_paint (window);
3607 /* If we're about to move/resize or otherwise change the
3608 * hierarchy of a client side window in an impl and we're
3609 * called from an expose event handler then we need to
3610 * flush any already painted parts of the implicit paint
3611 * that are not part of the current paint, as these may
3612 * be used when scrolling or may overdraw the changes
3613 * caused by the hierarchy change.
3616 gdk_window_flush_if_exposing (GdkWindow *window)
3618 GdkWindowObject *private;
3619 GdkWindowObject *impl_window;
3621 private = (GdkWindowObject *) window;
3622 impl_window = gdk_window_get_impl_window (private);
3624 /* If we're in an implicit paint (i.e. in an expose handler, flush
3625 all the already finished exposes to get things to an uptodate state. */
3626 if (impl_window->implicit_paint)
3627 gdk_window_flush (window);
3632 gdk_window_flush_recursive_helper (GdkWindowObject *window,
3635 GdkWindowObject *child;
3638 for (l = window->children; l != NULL; l = l->next)
3642 if (child->impl == impl)
3643 /* Same impl, ignore */
3644 gdk_window_flush_recursive_helper (child, impl);
3646 gdk_window_flush_recursive (child);
3651 gdk_window_flush_recursive (GdkWindowObject *window)
3653 gdk_window_flush ((GdkWindow *)window);
3654 gdk_window_flush_recursive_helper (window, window->impl);
3658 gdk_window_get_offsets (GdkWindow *window,
3662 GdkWindowObject *private = (GdkWindowObject *)window;
3664 if (private->paint_stack)
3666 GdkWindowPaint *paint = private->paint_stack->data;
3667 *x_offset = paint->x_offset;
3668 *y_offset = paint->y_offset;
3672 *x_offset = -private->abs_x;
3673 *y_offset = -private->abs_y;
3678 * gdk_window_get_internal_paint_info:
3679 * @window: a #GdkWindow
3680 * @real_drawable: (out): location to store the drawable to which drawing should be
3682 * @x_offset: (out): location to store the X offset between coordinates in @window,
3683 * and the underlying window system primitive coordinates for
3685 * @y_offset: (out): location to store the Y offset between coordinates in @window,
3686 * and the underlying window system primitive coordinates for
3689 * If you bypass the GDK layer and use windowing system primitives to
3690 * draw directly onto a #GdkWindow, then you need to deal with two
3691 * details: there may be an offset between GDK coordinates and windowing
3692 * system coordinates, and GDK may have redirected drawing to a offscreen
3693 * pixmap as the result of a gdk_window_begin_paint_region() calls.
3694 * This function allows retrieving the information you need to compensate
3695 * for these effects.
3697 * This function exposes details of the GDK implementation, and is thus
3698 * likely to change in future releases of GDK.
3701 gdk_window_get_internal_paint_info (GdkWindow *window,
3702 GdkDrawable **real_drawable,
3708 GdkWindowObject *private;
3710 g_return_if_fail (GDK_IS_WINDOW (window));
3712 private = (GdkWindowObject *)window;
3716 if (private->paint_stack)
3718 GdkWindowPaint *paint = private->paint_stack->data;
3719 *real_drawable = paint->pixmap;
3723 /* This means you're probably gonna be doing some weird shit
3724 directly to the window, so we flush all outstanding stuff */
3725 gdk_window_flush (window);
3726 *real_drawable = window;
3730 gdk_window_get_offsets (window, &x_off, &y_off);
3738 static GdkDrawable *
3739 start_draw_helper (GdkDrawable *drawable,
3744 GdkWindowObject *private = (GdkWindowObject *)drawable;
3745 gint x_offset, y_offset;
3747 gint old_clip_x = gc->clip_x_origin;
3748 gint old_clip_y = gc->clip_y_origin;
3750 guint32 clip_region_tag;
3751 GdkWindowPaint *paint;
3754 if (private->paint_stack)
3755 paint = private->paint_stack->data;
3759 x_offset = paint->x_offset;
3760 y_offset = paint->y_offset;
3764 x_offset = -private->abs_x;
3765 y_offset = -private->abs_y;
3768 if (x_offset != 0 || y_offset != 0)
3770 gdk_gc_set_clip_origin (gc,
3771 old_clip_x - x_offset,
3772 old_clip_y - y_offset);
3773 gdk_gc_set_ts_origin (gc,
3774 gc->ts_x_origin - x_offset,
3775 gc->ts_y_origin - y_offset);
3778 *x_offset_out = x_offset;
3779 *y_offset_out = y_offset;
3781 /* Add client side window clip region to gc */
3785 /* Only need clipping if using implicit paint, otherwise
3786 the pixmap is clipped when copying to the window in end_paint */
3787 if (paint->uses_implicit)
3789 /* This includes the window clip */
3790 clip = paint->region;
3792 clip_region_tag = paint->region_tag;
3794 /* After having set up the drawable clip rect on a GC we need to make sure
3795 * that we draw to th the impl, otherwise the pixmap code will reset the
3797 impl = ((GdkPixmapObject *)(paint->pixmap))->impl;
3801 /* Drawing directly to the window, flush anything outstanding to
3802 guarantee ordering. */
3803 gdk_window_flush ((GdkWindow *)drawable);
3805 /* Don't clip when drawing to root or all native */
3806 if (!_gdk_native_windows && private->window_type != GDK_WINDOW_ROOT)
3808 if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
3809 clip = private->clip_region_with_children;
3811 clip = private->clip_region;
3813 clip_region_tag = private->clip_tag;
3814 impl = private->impl;
3818 _gdk_gc_add_drawable_clip (gc,
3819 clip_region_tag, clip,
3820 /* If there was a clip origin set appart from the
3821 * window offset, need to take that into
3823 -old_clip_x, -old_clip_y);
3828 #define BEGIN_DRAW \
3830 GdkDrawable *impl; \
3831 gint x_offset, y_offset; \
3832 gint old_clip_x = gc->clip_x_origin; \
3833 gint old_clip_y = gc->clip_y_origin; \
3834 gint old_ts_x = gc->ts_x_origin; \
3835 gint old_ts_y = gc->ts_y_origin; \
3836 impl = start_draw_helper (drawable, gc, \
3837 &x_offset, &y_offset);
3840 if (x_offset != 0 || y_offset != 0) \
3842 gdk_gc_set_clip_origin (gc, old_clip_x, old_clip_y); \
3843 gdk_gc_set_ts_origin (gc, old_ts_x, old_ts_y); \
3848 gdk_window_create_gc (GdkDrawable *drawable,
3849 GdkGCValues *values,
3850 GdkGCValuesMask mask)
3852 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
3854 if (GDK_WINDOW_DESTROYED (drawable))
3857 return gdk_gc_new_with_values (((GdkWindowObject *) drawable)->impl,
3862 gdk_window_draw_rectangle (GdkDrawable *drawable,
3870 if (GDK_WINDOW_DESTROYED (drawable))
3874 gdk_draw_rectangle (impl, gc, filled,
3875 x - x_offset, y - y_offset, width, height);
3880 gdk_window_draw_arc (GdkDrawable *drawable,
3890 if (GDK_WINDOW_DESTROYED (drawable))
3894 gdk_draw_arc (impl, gc, filled,
3895 x - x_offset, y - y_offset,
3896 width, height, angle1, angle2);
3901 gdk_window_draw_polygon (GdkDrawable *drawable,
3907 GdkPoint *new_points;
3909 if (GDK_WINDOW_DESTROYED (drawable))
3914 if (x_offset != 0 || y_offset != 0)
3918 new_points = g_new (GdkPoint, npoints);
3919 for (i=0; i<npoints; i++)
3921 new_points[i].x = points[i].x - x_offset;
3922 new_points[i].y = points[i].y - y_offset;
3926 new_points = points;
3928 gdk_draw_polygon (impl, gc, filled, new_points, npoints);
3930 if (new_points != points)
3931 g_free (new_points);
3937 gdk_window_draw_text (GdkDrawable *drawable,
3945 if (GDK_WINDOW_DESTROYED (drawable))
3949 gdk_draw_text (impl, font, gc,
3950 x - x_offset, y - y_offset, text, text_length);
3955 gdk_window_draw_text_wc (GdkDrawable *drawable,
3960 const GdkWChar *text,
3963 if (GDK_WINDOW_DESTROYED (drawable))
3967 gdk_draw_text_wc (impl, font, gc,
3968 x - x_offset, y - y_offset, text, text_length);
3972 static GdkDrawable *
3973 gdk_window_get_source_drawable (GdkDrawable *drawable)
3975 GdkWindow *window = GDK_WINDOW (drawable);
3976 GdkWindowObject *private;
3978 private = (GdkWindowObject *) window;
3979 if (GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable)
3980 return GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable (private->impl);
3985 static GdkDrawable *
3986 gdk_window_get_composite_drawable (GdkDrawable *drawable,
3991 gint *composite_x_offset,
3992 gint *composite_y_offset)
3994 GdkWindowObject *private = (GdkWindowObject *)drawable;
3996 GdkPixmap *tmp_pixmap;
3999 gboolean overlap_buffer;
4000 GdkDrawable *source;
4001 GdkWindowObject *impl_window;
4002 GdkWindowPaint *implicit_paint;
4004 *composite_x_offset = -private->abs_x;
4005 *composite_y_offset = -private->abs_y;
4007 if ((GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable)))
4008 return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
4010 /* See if any buffered part is overlapping the part we want
4016 rect.height = height;
4018 overlap_buffer = FALSE;
4020 for (list = private->paint_stack; list != NULL; list = list->next)
4022 GdkWindowPaint *paint = list->data;
4023 GdkOverlapType overlap;
4025 overlap = gdk_region_rect_in (paint->region, &rect);
4027 if (overlap == GDK_OVERLAP_RECTANGLE_IN)
4029 *composite_x_offset = paint->x_offset;
4030 *composite_y_offset = paint->y_offset;
4032 return g_object_ref (paint->pixmap);
4034 else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
4036 overlap_buffer = TRUE;
4041 impl_window = gdk_window_get_impl_window (private);
4042 implicit_paint = impl_window->implicit_paint;
4045 GdkOverlapType overlap;
4047 rect.x += private->abs_x;
4048 rect.y += private->abs_y;
4050 overlap = gdk_region_rect_in (implicit_paint->region, &rect);
4051 if (overlap == GDK_OVERLAP_RECTANGLE_IN)
4053 *composite_x_offset = -private->abs_x + implicit_paint->x_offset;
4054 *composite_y_offset = -private->abs_y + implicit_paint->y_offset;
4056 return g_object_ref (implicit_paint->pixmap);
4058 else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
4059 overlap_buffer = TRUE;
4062 if (!overlap_buffer)
4063 return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
4065 tmp_pixmap = gdk_pixmap_new (drawable, width, height, -1);
4066 tmp_gc = _gdk_drawable_get_scratch_gc (tmp_pixmap, FALSE);
4068 source = _gdk_drawable_get_source_drawable (drawable);
4070 /* Copy the current window contents */
4071 gdk_draw_drawable (tmp_pixmap,
4073 GDK_WINDOW_OBJECT (source)->impl,
4074 x - *composite_x_offset,
4075 y - *composite_y_offset,
4079 /* paint the backing stores */
4082 GdkWindowPaint *paint = list->data;
4084 gdk_gc_set_clip_region (tmp_gc, paint->region);
4085 gdk_gc_set_clip_origin (tmp_gc, -x - paint->x_offset, -y - paint->y_offset);
4087 gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
4088 x - paint->x_offset,
4089 y - paint->y_offset,
4090 0, 0, width, height);
4093 for (list = private->paint_stack; list != NULL; list = list->next)
4095 GdkWindowPaint *paint = list->data;
4097 if (paint->uses_implicit)
4098 continue; /* We already copied this above */
4100 gdk_gc_set_clip_region (tmp_gc, paint->region);
4101 gdk_gc_set_clip_origin (tmp_gc, -x, -y);
4103 gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
4104 x - paint->x_offset,
4105 y - paint->y_offset,
4106 0, 0, width, height);
4109 /* Reset clip region of the cached GdkGC */
4110 gdk_gc_set_clip_region (tmp_gc, NULL);
4112 /* Set these to location of tmp_pixmap within the window */
4113 *composite_x_offset = x;
4114 *composite_y_offset = y;
4120 gdk_window_get_clip_region (GdkDrawable *drawable)
4122 GdkWindowObject *private = (GdkWindowObject *)drawable;
4125 result = gdk_region_copy (private->clip_region);
4127 if (private->paint_stack)
4129 GdkRegion *paint_region = gdk_region_new ();
4130 GSList *tmp_list = private->paint_stack;
4134 GdkWindowPaint *paint = tmp_list->data;
4136 gdk_region_union (paint_region, paint->region);
4138 tmp_list = tmp_list->next;
4141 gdk_region_intersect (result, paint_region);
4142 gdk_region_destroy (paint_region);
4149 gdk_window_get_visible_region (GdkDrawable *drawable)
4151 GdkWindowObject *private = (GdkWindowObject*) drawable;
4153 return gdk_region_copy (private->clip_region);
4157 gdk_window_draw_drawable (GdkDrawable *drawable,
4166 GdkDrawable *original_src)
4168 GdkWindowObject *private = (GdkWindowObject *)drawable;
4170 if (GDK_WINDOW_DESTROYED (drawable))
4175 /* Call the method directly to avoid getting the composite drawable again */
4176 GDK_DRAWABLE_GET_CLASS (impl)->draw_drawable_with_src (impl, gc,
4184 if (!private->paint_stack)
4186 /* We might have drawn from an obscured part of a client
4187 side window, if so we need to send graphics exposures */
4188 if (_gdk_gc_get_exposures (gc) &&
4189 GDK_IS_WINDOW (original_src))
4191 GdkRegion *exposure_region;
4199 exposure_region = gdk_region_rectangle (&r);
4201 if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
4202 clip = private->clip_region_with_children;
4204 clip = private->clip_region;
4205 gdk_region_intersect (exposure_region, clip);
4207 _gdk_gc_remove_drawable_clip (gc);
4208 clip = _gdk_gc_get_clip_region (gc);
4211 gdk_region_offset (exposure_region,
4214 gdk_region_intersect (exposure_region, clip);
4215 gdk_region_offset (exposure_region,
4220 /* Note: We don't clip by the clip mask if set, so this
4221 may invalidate to much */
4223 /* Remove the area that is correctly copied from the src.
4224 * Note that xsrc/ysrc has been corrected for abs_x/y offsets already,
4225 * which need to be undone */
4226 clip = gdk_drawable_get_visible_region (original_src);
4227 gdk_region_offset (clip,
4228 xdest - (xsrc - GDK_WINDOW_OBJECT (original_src)->abs_x),
4229 ydest - (ysrc - GDK_WINDOW_OBJECT (original_src)->abs_y));
4230 gdk_region_subtract (exposure_region, clip);
4231 gdk_region_destroy (clip);
4233 gdk_window_invalidate_region_full (GDK_WINDOW (private),
4235 _gdk_gc_get_subwindow (gc) == GDK_INCLUDE_INFERIORS,
4238 gdk_region_destroy (exposure_region);
4246 gdk_window_draw_points (GdkDrawable *drawable,
4251 GdkPoint *new_points;
4253 if (GDK_WINDOW_DESTROYED (drawable))
4258 if (x_offset != 0 || y_offset != 0)
4262 new_points = g_new (GdkPoint, npoints);
4263 for (i=0; i<npoints; i++)
4265 new_points[i].x = points[i].x - x_offset;
4266 new_points[i].y = points[i].y - y_offset;
4270 new_points = points;
4272 gdk_draw_points (impl, gc, new_points, npoints);
4274 if (new_points != points)
4275 g_free (new_points);
4281 gdk_window_draw_segments (GdkDrawable *drawable,
4286 GdkSegment *new_segs;
4288 if (GDK_WINDOW_DESTROYED (drawable))
4293 if (x_offset != 0 || y_offset != 0)
4297 new_segs = g_new (GdkSegment, nsegs);
4298 for (i=0; i<nsegs; i++)
4300 new_segs[i].x1 = segs[i].x1 - x_offset;
4301 new_segs[i].y1 = segs[i].y1 - y_offset;
4302 new_segs[i].x2 = segs[i].x2 - x_offset;
4303 new_segs[i].y2 = segs[i].y2 - y_offset;
4309 gdk_draw_segments (impl, gc, new_segs, nsegs);
4311 if (new_segs != segs)
4318 gdk_window_draw_lines (GdkDrawable *drawable,
4323 GdkPoint *new_points;
4325 if (GDK_WINDOW_DESTROYED (drawable))
4330 if (x_offset != 0 || y_offset != 0)
4334 new_points = g_new (GdkPoint, npoints);
4335 for (i=0; i<npoints; i++)
4337 new_points[i].x = points[i].x - x_offset;
4338 new_points[i].y = points[i].y - y_offset;
4342 new_points = points;
4344 gdk_draw_lines (impl, gc, new_points, npoints);
4346 if (new_points != points)
4347 g_free (new_points);
4353 gdk_window_draw_glyphs (GdkDrawable *drawable,
4358 PangoGlyphString *glyphs)
4360 if (GDK_WINDOW_DESTROYED (drawable))
4364 gdk_draw_glyphs (impl, gc, font,
4365 x - x_offset, y - y_offset, glyphs);
4370 gdk_window_draw_glyphs_transformed (GdkDrawable *drawable,
4372 PangoMatrix *matrix,
4376 PangoGlyphString *glyphs)
4378 PangoMatrix tmp_matrix;
4380 if (GDK_WINDOW_DESTROYED (drawable))
4385 if (x_offset != 0 || y_offset != 0)
4389 tmp_matrix = *matrix;
4390 tmp_matrix.x0 -= x_offset;
4391 tmp_matrix.y0 -= y_offset;
4392 matrix = &tmp_matrix;
4394 else if (GDK_PANGO_UNITS_OVERFLOWS (x_offset, y_offset))
4396 PangoMatrix identity = PANGO_MATRIX_INIT;
4398 tmp_matrix = identity;
4399 tmp_matrix.x0 -= x_offset;
4400 tmp_matrix.y0 -= y_offset;
4401 matrix = &tmp_matrix;
4405 x -= x_offset * PANGO_SCALE;
4406 y -= y_offset * PANGO_SCALE;
4410 gdk_draw_glyphs_transformed (impl, gc, matrix, font, x, y, glyphs);
4416 cairo_t *cr; /* if non-null, it means use this cairo context */
4417 GdkGC *gc; /* if non-null, it means use this GC instead */
4418 } BackingRectMethod;
4421 setup_backing_rect_method (BackingRectMethod *method, GdkWindow *window, GdkWindowPaint *paint, int x_offset_cairo, int y_offset_cairo)
4423 GdkWindowObject *private = (GdkWindowObject *)window;
4425 if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
4427 GdkWindowPaint tmp_paint;
4430 tmp_paint.x_offset += private->x;
4431 tmp_paint.y_offset += private->y;
4433 x_offset_cairo += private->x;
4434 y_offset_cairo += private->y;
4436 setup_backing_rect_method (method, GDK_WINDOW (private->parent), &tmp_paint, x_offset_cairo, y_offset_cairo);
4438 else if (private->bg_pixmap &&
4439 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
4440 private->bg_pixmap != GDK_NO_BG)
4442 /* This is a workaround for https://bugs.freedesktop.org/show_bug.cgi?id=4320.
4443 * In it, using a pixmap as a repeating pattern in Cairo, and painting it to a
4444 * pixmap destination surface, can be very slow (on the order of seconds for a
4445 * whole-screen copy). The workaround is to use pretty much the same code that
4446 * we used in GTK+ 2.6 (pre-Cairo), which clears the double-buffer pixmap with
4447 * a tiled GC XFillRectangle().
4450 /* Actually computing this flag is left as an exercise for the reader */
4451 #if defined (G_OS_UNIX)
4452 # define GDK_CAIRO_REPEAT_IS_FAST 0
4454 # define GDK_CAIRO_REPEAT_IS_FAST 1
4457 #if GDK_CAIRO_REPEAT_IS_FAST
4458 cairo_surface_t *surface = _gdk_drawable_ref_cairo_surface (private->bg_pixmap);
4459 cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
4460 cairo_surface_destroy (surface);
4462 if (x_offset_cairo != 0 || y_offset_cairo != 0)
4464 cairo_matrix_t matrix;
4465 cairo_matrix_init_translate (&matrix, x_offset_cairo, y_offset_cairo);
4466 cairo_pattern_set_matrix (pattern, &matrix);
4469 cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
4471 method->cr = cairo_create (paint->surface);
4474 cairo_set_source (method->cr, pattern);
4475 cairo_pattern_destroy (pattern);
4478 GdkGCValues gc_values;
4480 gc_values.fill = GDK_TILED;
4481 gc_values.tile = private->bg_pixmap;
4482 gc_values.ts_x_origin = -x_offset_cairo;
4483 gc_values.ts_y_origin = -y_offset_cairo;
4485 gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN;
4487 method->gc = gdk_gc_new_with_values (paint->pixmap, &gc_values, gc_mask);
4492 method->cr = cairo_create (paint->surface);
4494 gdk_cairo_set_source_color (method->cr, &private->bg_color);
4499 gdk_window_clear_backing_region (GdkWindow *window,
4502 GdkWindowObject *private = (GdkWindowObject *)window;
4503 GdkWindowPaint *paint = private->paint_stack->data;
4504 BackingRectMethod method;
4506 GdkRectangle clipbox;
4512 if (GDK_WINDOW_DESTROYED (window))
4516 timer = g_timer_new ();
4521 setup_backing_rect_method (&method, window, paint, 0, 0);
4523 clip = gdk_region_copy (paint->region);
4524 gdk_region_intersect (clip, region);
4525 gdk_region_get_clipbox (clip, &clipbox);
4530 g_assert (method.gc == NULL);
4532 gdk_cairo_region (method.cr, clip);
4533 cairo_fill (method.cr);
4535 cairo_destroy (method.cr);
4537 elapsed = g_timer_elapsed (timer, NULL);
4538 g_print ("Draw the background with Cairo: %fs\n", elapsed);
4543 g_assert (method.gc != NULL);
4545 gdk_gc_set_clip_region (method.gc, clip);
4546 gdk_draw_rectangle (window, method.gc, TRUE,
4547 clipbox.x, clipbox.y,
4548 clipbox.width, clipbox.height);
4549 g_object_unref (method.gc);
4552 elapsed = g_timer_elapsed (timer, NULL);
4553 g_print ("Draw the background with GDK: %fs\n", elapsed);
4557 gdk_region_destroy (clip);
4560 g_timer_destroy (timer);
4565 gdk_window_clear_backing_region_redirect (GdkWindow *window,
4568 GdkWindowObject *private = (GdkWindowObject *)window;
4569 GdkWindowRedirect *redirect = private->redirect;
4570 GdkRegion *clip_region;
4571 GdkRectangle clipbox;
4572 gint x_offset, y_offset;
4573 BackingRectMethod method;
4574 GdkWindowPaint paint;
4576 if (GDK_WINDOW_DESTROYED (window))
4579 clip_region = _gdk_window_calculate_full_clip_region (window,
4580 GDK_WINDOW (redirect->redirected),
4582 &x_offset, &y_offset);
4583 gdk_region_intersect (clip_region, region);
4585 /* offset is from redirected window origin to window origin, convert to
4586 the offset from the redirected pixmap origin to the window origin */
4587 x_offset += redirect->dest_x - redirect->src_x;
4588 y_offset += redirect->dest_y - redirect->src_y;
4590 /* Convert region to pixmap coords */
4591 gdk_region_offset (clip_region, x_offset, y_offset);
4595 paint.pixmap = redirect->pixmap;
4596 paint.surface = _gdk_drawable_ref_cairo_surface (redirect->pixmap);
4600 setup_backing_rect_method (&method, window, &paint, -x_offset, -y_offset);
4604 g_assert (method.gc == NULL);
4606 gdk_cairo_region (method.cr, clip_region);
4607 cairo_fill (method.cr);
4609 cairo_destroy (method.cr);
4613 g_assert (method.gc != NULL);
4615 gdk_region_get_clipbox (clip_region, &clipbox);
4616 gdk_gc_set_clip_region (method.gc, clip_region);
4617 gdk_draw_rectangle (redirect->pixmap, method.gc, TRUE,
4618 clipbox.x, clipbox.y,
4619 clipbox.width, clipbox.height);
4620 g_object_unref (method.gc);
4624 gdk_region_destroy (clip_region);
4625 cairo_surface_destroy (paint.surface);
4629 gdk_window_clear_backing_region_direct (GdkWindow *window,
4632 GdkWindowObject *private = (GdkWindowObject *)window;
4633 BackingRectMethod method;
4634 GdkWindowPaint paint;
4636 GdkRectangle clipbox;
4638 if (GDK_WINDOW_DESTROYED (window))
4643 paint.pixmap = window;
4644 paint.surface = _gdk_drawable_ref_cairo_surface (window);
4648 setup_backing_rect_method (&method, window, &paint, 0, 0);
4650 clip = gdk_region_copy (private->clip_region_with_children);
4651 gdk_region_intersect (clip, region);
4652 gdk_region_get_clipbox (clip, &clipbox);
4656 g_assert (method.gc == NULL);
4658 gdk_cairo_region (method.cr, clip);
4659 cairo_fill (method.cr);
4661 cairo_destroy (method.cr);
4665 g_assert (method.gc != NULL);
4667 gdk_gc_set_clip_region (method.gc, clip);
4668 gdk_draw_rectangle (window, method.gc, TRUE,
4669 clipbox.x, clipbox.y,
4670 clipbox.width, clipbox.height);
4671 g_object_unref (method.gc);
4675 gdk_region_destroy (clip);
4676 cairo_surface_destroy (paint.surface);
4682 * @window: a #GdkWindow
4684 * Clears an entire @window to the background color or background pixmap.
4687 gdk_window_clear (GdkWindow *window)
4691 g_return_if_fail (GDK_IS_WINDOW (window));
4693 gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height);
4695 gdk_window_clear_area (window, 0, 0,
4699 /* TRUE if the window clears to the same pixels as a native
4700 window clear. This means you can use the native window
4701 clearing operation, and additionally it means any clearing
4702 done by the native window system for you will already be right */
4704 clears_as_native (GdkWindowObject *private)
4706 GdkWindowObject *next;
4712 if (gdk_window_has_impl (private))
4714 next = private->parent;
4716 while (private->bg_pixmap == GDK_PARENT_RELATIVE_BG &&
4717 next && next->window_type != GDK_WINDOW_ROOT);
4722 gdk_window_clear_region_internal (GdkWindow *window,
4724 gboolean send_expose)
4726 GdkWindowObject *private = (GdkWindowObject *)window;
4727 GdkWindowImplIface *impl_iface;
4729 if (private->paint_stack)
4730 gdk_window_clear_backing_region (window, region);
4733 if (private->redirect)
4734 gdk_window_clear_backing_region_redirect (window, region);
4736 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
4738 if (impl_iface->clear_region && clears_as_native (private))
4741 copy = gdk_region_copy (region);
4742 gdk_region_intersect (copy,
4743 private->clip_region_with_children);
4746 /* Drawing directly to the window, flush anything outstanding to
4747 guarantee ordering. */
4748 gdk_window_flush (window);
4749 impl_iface->clear_region (window, copy, send_expose);
4751 gdk_region_destroy (copy);
4755 gdk_window_clear_backing_region_direct (window, region);
4757 gdk_window_invalidate_region (window, region, FALSE);
4763 gdk_window_clear_area_internal (GdkWindow *window,
4768 gboolean send_expose)
4773 g_return_if_fail (GDK_IS_WINDOW (window));
4775 if (GDK_WINDOW_DESTROYED (window))
4778 /* Terminate early to avoid weird interpretation of
4779 zero width/height by XClearArea */
4780 if (width == 0 || height == 0)
4786 rect.height = height;
4788 region = gdk_region_rectangle (&rect);
4789 gdk_window_clear_region_internal (window,
4792 gdk_region_destroy (region);
4797 * gdk_window_clear_area:
4798 * @window: a #GdkWindow
4799 * @x: x coordinate of rectangle to clear
4800 * @y: y coordinate of rectangle to clear
4801 * @width: width of rectangle to clear
4802 * @height: height of rectangle to clear
4804 * Clears an area of @window to the background color or background pixmap.
4808 gdk_window_clear_area (GdkWindow *window,
4814 gdk_window_clear_area_internal (window,
4821 * gdk_window_clear_area_e:
4822 * @window: a #GdkWindow
4823 * @x: x coordinate of rectangle to clear
4824 * @y: y coordinate of rectangle to clear
4825 * @width: width of rectangle to clear
4826 * @height: height of rectangle to clear
4828 * Like gdk_window_clear_area(), but also generates an expose event for
4831 * This function has a stupid name because it dates back to the mists
4832 * time, pre-GDK-1.0.
4836 gdk_window_clear_area_e (GdkWindow *window,
4842 gdk_window_clear_area_internal (window,
4849 gdk_window_draw_image (GdkDrawable *drawable,
4859 if (GDK_WINDOW_DESTROYED (drawable))
4863 gdk_draw_image (impl, gc, image, xsrc, ysrc,
4864 xdest - x_offset, ydest - y_offset,
4870 gdk_window_draw_pixbuf (GdkDrawable *drawable,
4879 GdkRgbDither dither,
4883 GdkWindowObject *private = (GdkWindowObject *)drawable;
4884 GdkDrawableClass *klass;
4886 if (GDK_WINDOW_DESTROYED (drawable))
4889 /* If no gc => no user clipping, but we need clipping
4890 for window emulation, so use a scratch gc */
4892 gc = _gdk_drawable_get_scratch_gc (drawable, FALSE);
4896 klass = GDK_DRAWABLE_GET_CLASS (impl);
4898 if (private->paint_stack)
4899 klass->draw_pixbuf (impl, gc, pixbuf, src_x, src_y,
4900 dest_x - x_offset, dest_y - y_offset,
4902 dither, x_dither - x_offset, y_dither - y_offset);
4904 klass->draw_pixbuf (impl, gc, pixbuf, src_x, src_y,
4905 dest_x - x_offset, dest_y - y_offset,
4907 dither, x_dither, y_dither);
4912 gdk_window_draw_trapezoids (GdkDrawable *drawable,
4914 GdkTrapezoid *trapezoids,
4917 GdkTrapezoid *new_trapezoids = NULL;
4919 if (GDK_WINDOW_DESTROYED (drawable))
4924 if (x_offset != 0 || y_offset != 0)
4928 new_trapezoids = g_new (GdkTrapezoid, n_trapezoids);
4929 for (i=0; i < n_trapezoids; i++)
4931 new_trapezoids[i].y1 = trapezoids[i].y1 - y_offset;
4932 new_trapezoids[i].x11 = trapezoids[i].x11 - x_offset;
4933 new_trapezoids[i].x21 = trapezoids[i].x21 - x_offset;
4934 new_trapezoids[i].y2 = trapezoids[i].y2 - y_offset;
4935 new_trapezoids[i].x12 = trapezoids[i].x12 - x_offset;
4936 new_trapezoids[i].x22 = trapezoids[i].x22 - x_offset;
4939 trapezoids = new_trapezoids;
4942 gdk_draw_trapezoids (impl, gc, trapezoids, n_trapezoids);
4944 g_free (new_trapezoids);
4950 gdk_window_real_get_size (GdkDrawable *drawable,
4954 GdkWindowObject *private = (GdkWindowObject *)drawable;
4957 *width = private->width;
4959 *height = private->height;
4963 gdk_window_real_get_visual (GdkDrawable *drawable)
4965 GdkColormap *colormap;
4967 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4969 colormap = gdk_drawable_get_colormap (drawable);
4970 return colormap ? gdk_colormap_get_visual (colormap) : NULL;
4974 gdk_window_real_get_depth (GdkDrawable *drawable)
4976 g_return_val_if_fail (GDK_IS_WINDOW (drawable), 0);
4978 return ((GdkWindowObject *)GDK_WINDOW (drawable))->depth;
4982 gdk_window_real_get_screen (GdkDrawable *drawable)
4984 return gdk_drawable_get_screen (GDK_WINDOW_OBJECT (drawable)->impl);
4988 gdk_window_real_set_colormap (GdkDrawable *drawable,
4991 GdkWindowObject *private;
4993 g_return_if_fail (GDK_IS_WINDOW (drawable));
4995 if (GDK_WINDOW_DESTROYED (drawable))
4998 private = (GdkWindowObject *)drawable;
5000 /* different colormap than parent, requires native window */
5001 if (!private->input_only &&
5002 cmap != gdk_drawable_get_colormap ((GdkDrawable *)(private->parent)))
5003 gdk_window_ensure_native ((GdkWindow *)drawable);
5005 gdk_drawable_set_colormap (private->impl, cmap);
5009 gdk_window_real_get_colormap (GdkDrawable *drawable)
5011 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
5013 if (GDK_WINDOW_DESTROYED (drawable))
5016 return gdk_drawable_get_colormap (((GdkWindowObject*)drawable)->impl);
5020 gdk_window_copy_to_image (GdkDrawable *drawable,
5029 GdkWindowObject *private = (GdkWindowObject *) drawable;
5030 gint x_offset, y_offset;
5032 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
5034 if (GDK_WINDOW_DESTROYED (drawable))
5037 /* If we're here, a composite image was not necessary, so
5038 * we can ignore the paint stack.
5041 /* TODO: Is this right? */
5045 return gdk_drawable_copy_to_image (private->impl,
5054 gdk_window_drop_cairo_surface (GdkWindowObject *private)
5056 if (private->cairo_surface)
5058 cairo_surface_finish (private->cairo_surface);
5059 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
5065 gdk_window_cairo_surface_destroy (void *data)
5067 GdkWindowObject *private = (GdkWindowObject*) data;
5069 private->cairo_surface = NULL;
5070 private->impl_window->outstanding_surfaces--;
5073 static cairo_surface_t *
5074 gdk_window_create_cairo_surface (GdkDrawable *drawable,
5078 return _gdk_windowing_create_cairo_surface (GDK_WINDOW_OBJECT(drawable)->impl,
5083 static cairo_surface_t *
5084 gdk_window_ref_cairo_surface (GdkDrawable *drawable)
5086 GdkWindowObject *private = (GdkWindowObject*) drawable;
5087 cairo_surface_t *surface;
5089 if (private->paint_stack)
5091 GdkWindowPaint *paint = private->paint_stack->data;
5093 surface = paint->surface;
5094 cairo_surface_reference (surface);
5099 /* This will be drawing directly to the window, so flush implicit paint */
5100 gdk_window_flush ((GdkWindow *)drawable);
5102 if (!private->cairo_surface)
5105 GdkDrawable *source;
5107 /* It would be nice if we had some cairo support here so we
5108 could set the clip rect on the cairo surface */
5109 width = private->abs_x + private->width;
5110 height = private->abs_y + private->height;
5112 source = _gdk_drawable_get_source_drawable (drawable);
5114 private->cairo_surface = _gdk_drawable_create_cairo_surface (source, width, height);
5116 if (private->cairo_surface)
5118 private->impl_window->outstanding_surfaces++;
5120 cairo_surface_set_device_offset (private->cairo_surface,
5124 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
5125 drawable, gdk_window_cairo_surface_destroy);
5129 cairo_surface_reference (private->cairo_surface);
5131 surface = private->cairo_surface;
5138 gdk_window_set_cairo_clip (GdkDrawable *drawable,
5141 GdkWindowObject *private = (GdkWindowObject*) drawable;
5143 if (!private->paint_stack)
5145 cairo_reset_clip (cr);
5148 cairo_identity_matrix (cr);
5150 cairo_new_path (cr);
5151 gdk_cairo_region (cr, private->clip_region_with_children);
5158 GdkWindowPaint *paint = private->paint_stack->data;
5160 /* Only needs to clip to region if piggybacking
5161 on an implicit paint pixmap */
5162 cairo_reset_clip (cr);
5163 if (paint->uses_implicit)
5166 cairo_identity_matrix (cr);
5168 cairo_new_path (cr);
5169 gdk_cairo_region (cr, paint->region);
5177 /* Code for dirty-region queueing
5179 static GSList *update_windows = NULL;
5180 static guint update_idle = 0;
5181 static gboolean debug_updates = FALSE;
5183 static inline gboolean
5184 gdk_window_is_ancestor (GdkWindow *window,
5185 GdkWindow *ancestor)
5189 GdkWindow *parent = (GdkWindow*) ((GdkWindowObject*) window)->parent;
5191 if (parent == ancestor)
5201 gdk_window_add_update_window (GdkWindow *window)
5204 GSList *prev = NULL;
5205 gboolean has_ancestor_in_list = FALSE;
5207 for (tmp = update_windows; tmp; tmp = tmp->next)
5209 GdkWindowObject *parent = GDK_WINDOW_OBJECT (window)->parent;
5211 /* check if tmp is an ancestor of "window"; if it is, set a
5212 * flag indicating that all following windows are either
5213 * children of "window" or from a differen hierarchy
5215 if (!has_ancestor_in_list && gdk_window_is_ancestor (window, tmp->data))
5216 has_ancestor_in_list = TRUE;
5218 /* insert in reverse stacking order when adding around siblings,
5219 * so processing updates properly paints over lower stacked windows
5221 if (parent == GDK_WINDOW_OBJECT (tmp->data)->parent)
5223 gint index = g_list_index (parent->children, window);
5224 for (; tmp && parent == GDK_WINDOW_OBJECT (tmp->data)->parent; tmp = tmp->next)
5226 gint sibling_index = g_list_index (parent->children, tmp->data);
5227 if (index > sibling_index)
5231 /* here, tmp got advanced past all lower stacked siblings */
5232 tmp = g_slist_prepend (tmp, window);
5236 update_windows = tmp;
5240 /* if "window" has an ancestor in the list and tmp is one of
5241 * "window's" children, insert "window" before tmp
5243 if (has_ancestor_in_list && gdk_window_is_ancestor (tmp->data, window))
5245 tmp = g_slist_prepend (tmp, window);
5250 update_windows = tmp;
5254 /* if we're at the end of the list and had an ancestor it it,
5255 * append to the list
5257 if (! tmp->next && has_ancestor_in_list)
5259 tmp = g_slist_append (tmp, window);
5266 /* if all above checks failed ("window" is from a different
5267 * hierarchy than what is already in the list) or the list is
5270 update_windows = g_slist_prepend (update_windows, window);
5274 gdk_window_remove_update_window (GdkWindow *window)
5276 update_windows = g_slist_remove (update_windows, window);
5280 gdk_window_update_idle (gpointer data)
5282 gdk_window_process_all_updates ();
5288 gdk_window_is_toplevel_frozen (GdkWindow *window)
5290 GdkWindowObject *toplevel;
5292 toplevel = (GdkWindowObject *)gdk_window_get_toplevel (window);
5294 return toplevel->update_and_descendants_freeze_count > 0;
5298 gdk_window_schedule_update (GdkWindow *window)
5301 (GDK_WINDOW_OBJECT (window)->update_freeze_count ||
5302 gdk_window_is_toplevel_frozen (window)))
5307 gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
5308 gdk_window_update_idle,
5313 _gdk_window_process_updates_recurse (GdkWindow *window,
5314 GdkRegion *expose_region)
5316 GdkWindowObject *private = (GdkWindowObject *)window;
5317 GdkWindowObject *child;
5318 GdkRegion *child_region;
5320 GList *l, *children;
5322 if (gdk_region_empty (expose_region))
5325 /* Make this reentrancy safe for expose handlers freeing windows */
5326 children = g_list_copy (private->children);
5327 g_list_foreach (children, (GFunc)g_object_ref, NULL);
5329 /* Iterate over children, starting at topmost */
5330 for (l = children; l != NULL; l = l->next)
5334 if (child->destroyed || !GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
5337 /* Ignore offscreen children, as they don't draw in their parent and
5338 * don't take part in the clipping */
5339 if (gdk_window_is_offscreen (child))
5344 r.width = child->width;
5345 r.height = child->height;
5347 child_region = gdk_region_rectangle (&r);
5350 /* Adjust shape region to parent window coords */
5351 gdk_region_offset (child->shape, child->x, child->y);
5352 gdk_region_intersect (child_region, child->shape);
5353 gdk_region_offset (child->shape, -child->x, -child->y);
5356 if (child->impl == private->impl)
5358 /* Client side child, expose */
5359 gdk_region_intersect (child_region, expose_region);
5360 gdk_region_subtract (expose_region, child_region);
5361 gdk_region_offset (child_region, -child->x, -child->y);
5362 _gdk_window_process_updates_recurse ((GdkWindow *)child, child_region);
5366 /* Native child, just remove area from expose region */
5367 gdk_region_subtract (expose_region, child_region);
5369 gdk_region_destroy (child_region);
5372 g_list_foreach (children, (GFunc)g_object_unref, NULL);
5373 g_list_free (children);
5375 if (!gdk_region_empty (expose_region) &&
5376 !private->destroyed)
5378 if (private->event_mask & GDK_EXPOSURE_MASK)
5382 event.expose.type = GDK_EXPOSE;
5383 event.expose.window = g_object_ref (window);
5384 event.expose.send_event = FALSE;
5385 event.expose.count = 0;
5386 event.expose.region = expose_region;
5387 gdk_region_get_clipbox (expose_region, &event.expose.area);
5389 (*_gdk_event_func) (&event, _gdk_event_data);
5391 g_object_unref (window);
5393 else if (private->bg_pixmap != GDK_NO_BG &&
5394 private->window_type != GDK_WINDOW_FOREIGN)
5396 /* No exposure mask set, so nothing will be drawn, the
5397 * app relies on the background being what it specified
5398 * for the window. So, we need to clear this manually.
5400 * For foreign windows if expose is not set that generally
5401 * means some other client paints them, so don't clear
5404 * We use begin/end_paint around the clear so that we can
5405 * piggyback on the implicit paint */
5407 gdk_window_begin_paint_region (window, expose_region);
5408 gdk_window_clear_region_internal (window, expose_region, FALSE);
5409 gdk_window_end_paint (window);
5414 /* Process and remove any invalid area on the native window by creating
5415 * expose events for the window and all non-native descendants.
5416 * Also processes any outstanding moves on the window before doing
5417 * any drawing. Note that its possible to have outstanding moves without
5418 * any invalid area as we use the update idle mechanism to coalesce
5419 * multiple moves as well as multiple invalidations.
5422 gdk_window_process_updates_internal (GdkWindow *window)
5424 GdkWindowObject *private = (GdkWindowObject *)window;
5425 GdkWindowImplIface *impl_iface;
5426 gboolean save_region = FALSE;
5427 GdkRectangle clip_box;
5429 /* Ensure the window lives while updating it */
5430 g_object_ref (window);
5432 /* If an update got queued during update processing, we can get a
5433 * window in the update queue that has an empty update_area.
5436 if (private->update_area)
5438 GdkRegion *update_area = private->update_area;
5439 private->update_area = NULL;
5441 if (_gdk_event_func && gdk_window_is_viewable (window))
5443 GdkRegion *expose_region;
5444 gboolean end_implicit;
5446 /* Clip to part visible in toplevel */
5447 gdk_region_intersect (update_area, private->clip_region);
5451 /* Make sure we see the red invalid area before redrawing. */
5452 gdk_display_sync (gdk_drawable_get_display (window));
5456 /* At this point we will be completely redrawing all of update_area.
5457 * If we have any outstanding moves that end up moving stuff inside
5458 * this area we don't actually need to move that as that part would
5459 * be overdrawn by the expose anyway. So, in order to copy less data
5460 * we remove these areas from the outstanding moves.
5462 if (private->outstanding_moves)
5464 GdkWindowRegionMove *move;
5468 remove = gdk_region_copy (update_area);
5469 /* We iterate backwards, starting from the state that would be
5470 if we had applied all the moves. */
5471 for (l = g_list_last (private->outstanding_moves); l != NULL; l = prev)
5476 /* Don't need this area */
5477 gdk_region_subtract (move->dest_region, remove);
5479 /* However if any of the destination we do need has a source
5480 in the updated region we do need that as a destination for
5481 the earlier moves */
5482 gdk_region_offset (move->dest_region, -move->dx, -move->dy);
5483 gdk_region_subtract (remove, move->dest_region);
5485 if (gdk_region_empty (move->dest_region))
5487 gdk_window_region_move_free (move);
5488 private->outstanding_moves =
5489 g_list_delete_link (private->outstanding_moves, l);
5491 else /* move back */
5492 gdk_region_offset (move->dest_region, move->dx, move->dy);
5494 gdk_region_destroy (remove);
5497 /* By now we a set of window moves that should be applied, and then
5498 * an update region that should be repainted. A trivial implementation
5499 * would just do that in order, however in order to get nicer drawing
5500 * we do some tricks:
5502 * First of all, each subwindow expose may be double buffered by
5503 * itself (depending on widget setting) via
5504 * gdk_window_begin/end_paint(). But we also do an "implicit" paint,
5505 * creating a single pixmap the size of the invalid area on the
5506 * native window which all the individual normal paints will draw
5507 * into. This way in the normal case there will be only one pixmap
5508 * allocated and only once pixmap draw done for all the windows
5509 * in this native window.
5510 * There are a couple of reasons this may fail, for instance, some
5511 * backends (like quartz) do its own double buffering, so we disable
5512 * gdk double buffering there. Secondly, some subwindow could be
5513 * non-double buffered and draw directly to the window outside a
5514 * begin/end_paint pair. That will be lead to a gdk_window_flush
5515 * which immediately executes all outstanding moves and paints+removes
5516 * the implicit paint (further paints will allocate their own pixmap).
5518 * Secondly, in the case of implicit double buffering we expose all
5519 * the child windows into the implicit pixmap before we execute
5520 * the outstanding moves. This way we minimize the time between
5521 * doing the moves and rendering the new update area, thus minimizing
5522 * flashing. Of course, if any subwindow is non-double buffered we
5523 * well flush earlier than that.
5525 * Thirdly, after having done the outstanding moves we queue an
5526 * "antiexpose" on the area that will be drawn by the expose, which
5527 * means that any invalid region on the native window side before
5528 * the first expose drawing operation will be discarded, as it
5529 * has by then been overdrawn with valid data. This means we can
5530 * avoid doing the unnecessary repaint any outstanding expose events.
5533 gdk_region_get_clipbox (update_area, &clip_box);
5534 end_implicit = gdk_window_begin_implicit_paint (window, &clip_box);
5535 expose_region = gdk_region_copy (update_area);
5538 /* Rendering is not double buffered by gdk, do outstanding
5539 * moves and queue antiexposure immediately. No need to do
5541 gdk_window_flush_outstanding_moves (window);
5542 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
5543 save_region = impl_iface->queue_antiexpose (window, update_area);
5546 /* Render the invalid areas to the implicit paint, by sending exposes.
5547 * May flush if non-double buffered widget draw. */
5548 _gdk_windowing_window_process_updates_recurse (window, expose_region);
5552 /* Do moves right before exposes are rendered to the window */
5553 gdk_window_flush_outstanding_moves (window);
5555 /* By this time we know that any outstanding expose for this
5556 * area is invalid and we can avoid it, so queue an antiexpose.
5557 * However, it may be that due to an non-double buffered expose
5558 * we have already started drawing to the window, so it would
5559 * be to late to anti-expose now. Since this is merely an
5560 * optimization we just avoid doing it at all in that case.
5562 if (private->implicit_paint != NULL &&
5563 !private->implicit_paint->flushed)
5565 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
5566 save_region = impl_iface->queue_antiexpose (window, update_area);
5569 gdk_window_end_implicit_paint (window);
5571 gdk_region_destroy (expose_region);
5574 gdk_region_destroy (update_area);
5577 if (private->outstanding_moves)
5579 /* Flush any outstanding moves, may happen if we moved a window but got
5580 no actual invalid area */
5581 gdk_window_flush_outstanding_moves (window);
5584 g_object_unref (window);
5588 flush_all_displays (void)
5590 GSList *displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
5593 for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
5594 gdk_display_flush (tmp_list->data);
5596 g_slist_free (displays);
5599 /* Currently it is not possible to override
5600 * gdk_window_process_all_updates in the same manner as
5601 * gdk_window_process_updates and gdk_window_invalidate_maybe_recurse
5602 * by implementing the GdkPaintable interface. If in the future a
5603 * backend would need this, the right solution would be to add a
5604 * method to GdkDisplay that can be optionally
5605 * NULL. gdk_window_process_all_updates can then walk the list of open
5606 * displays and call the mehod.
5610 * gdk_window_process_all_updates:
5612 * Calls gdk_window_process_updates() for all windows (see #GdkWindow)
5613 * in the application.
5617 gdk_window_process_all_updates (void)
5619 GSList *old_update_windows = update_windows;
5620 GSList *tmp_list = update_windows;
5621 static gboolean in_process_all_updates = FALSE;
5622 static gboolean got_recursive_update = FALSE;
5624 if (in_process_all_updates)
5626 /* We can't do this now since that would recurse, so
5627 delay it until after the recursion is done. */
5628 got_recursive_update = TRUE;
5633 in_process_all_updates = TRUE;
5634 got_recursive_update = FALSE;
5637 g_source_remove (update_idle);
5639 update_windows = NULL;
5642 _gdk_windowing_before_process_all_updates ();
5644 g_slist_foreach (old_update_windows, (GFunc)g_object_ref, NULL);
5648 GdkWindowObject *private = (GdkWindowObject *)tmp_list->data;
5650 if (!GDK_WINDOW_DESTROYED (tmp_list->data))
5652 if (private->update_freeze_count ||
5653 gdk_window_is_toplevel_frozen (tmp_list->data))
5654 gdk_window_add_update_window ((GdkWindow *) private);
5656 gdk_window_process_updates_internal (tmp_list->data);
5659 g_object_unref (tmp_list->data);
5660 tmp_list = tmp_list->next;
5663 g_slist_free (old_update_windows);
5665 flush_all_displays ();
5667 _gdk_windowing_after_process_all_updates ();
5669 in_process_all_updates = FALSE;
5671 /* If we ignored a recursive call, schedule a
5672 redraw now so that it eventually happens,
5673 otherwise we could miss an update if nothing
5674 else schedules an update. */
5675 if (got_recursive_update && !update_idle)
5677 gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
5678 gdk_window_update_idle,
5683 * gdk_window_process_updates:
5684 * @window: a #GdkWindow
5685 * @update_children: whether to also process updates for child windows
5687 * Sends one or more expose events to @window. The areas in each
5688 * expose event will cover the entire update area for the window (see
5689 * gdk_window_invalidate_region() for details). Normally GDK calls
5690 * gdk_window_process_all_updates() on your behalf, so there's no
5691 * need to call this function unless you want to force expose events
5692 * to be delivered immediately and synchronously (vs. the usual
5693 * case, where GDK delivers them in an idle handler). Occasionally
5694 * this is useful to produce nicer scrolling behavior, for example.
5698 gdk_window_process_updates (GdkWindow *window,
5699 gboolean update_children)
5701 GdkWindowObject *private = (GdkWindowObject *)window;
5702 GdkWindowObject *impl_window;
5704 g_return_if_fail (GDK_IS_WINDOW (window));
5706 if (GDK_WINDOW_DESTROYED (window))
5709 /* Make sure the window lives during the expose callouts */
5710 g_object_ref (window);
5712 impl_window = gdk_window_get_impl_window (private);
5713 if ((impl_window->update_area ||
5714 impl_window->outstanding_moves) &&
5715 !impl_window->update_freeze_count &&
5716 !gdk_window_is_toplevel_frozen (window) &&
5718 /* Don't recurse into process_updates_internal, we'll
5719 * do the update later when idle instead. */
5720 impl_window->implicit_paint == NULL)
5722 gdk_window_process_updates_internal ((GdkWindow *)impl_window);
5723 gdk_window_remove_update_window ((GdkWindow *)impl_window);
5726 if (update_children)
5728 /* process updates in reverse stacking order so composition or
5729 * painting over achieves the desired effect for offscreen windows
5731 GList *node, *children;
5733 children = g_list_copy (private->children);
5734 g_list_foreach (children, (GFunc)g_object_ref, NULL);
5736 for (node = g_list_last (children); node; node = node->prev)
5738 gdk_window_process_updates (node->data, TRUE);
5739 g_object_unref (node->data);
5742 g_list_free (children);
5745 g_object_unref (window);
5749 gdk_window_invalidate_rect_full (GdkWindow *window,
5750 const GdkRectangle *rect,
5751 gboolean invalidate_children,
5754 GdkRectangle window_rect;
5756 GdkWindowObject *private = (GdkWindowObject *)window;
5758 g_return_if_fail (GDK_IS_WINDOW (window));
5760 if (GDK_WINDOW_DESTROYED (window))
5763 if (private->input_only || !private->viewable)
5770 gdk_drawable_get_size (GDK_DRAWABLE (window),
5772 &window_rect.height);
5773 rect = &window_rect;
5776 region = gdk_region_rectangle (rect);
5777 gdk_window_invalidate_region_full (window, region, invalidate_children, clear_bg);
5778 gdk_region_destroy (region);
5782 * gdk_window_invalidate_rect:
5783 * @window: a #GdkWindow
5784 * @rect: (allow-none): rectangle to invalidate or %NULL to invalidate the whole
5786 * @invalidate_children: whether to also invalidate child windows
5788 * A convenience wrapper around gdk_window_invalidate_region() which
5789 * invalidates a rectangular region. See
5790 * gdk_window_invalidate_region() for details.
5793 gdk_window_invalidate_rect (GdkWindow *window,
5794 const GdkRectangle *rect,
5795 gboolean invalidate_children)
5797 gdk_window_invalidate_rect_full (window, rect, invalidate_children, CLEAR_BG_NONE);
5801 draw_ugly_color (GdkWindow *window,
5802 const GdkRegion *region)
5804 /* Draw ugly color all over the newly-invalid region */
5805 GdkColor ugly_color = { 0, 50000, 10000, 10000 };
5807 GdkRectangle clipbox;
5809 ugly_gc = gdk_gc_new (window);
5810 gdk_gc_set_rgb_fg_color (ugly_gc, &ugly_color);
5811 gdk_gc_set_clip_region (ugly_gc, region);
5813 gdk_region_get_clipbox (region, &clipbox);
5815 gdk_draw_rectangle (window,
5818 clipbox.x, clipbox.y,
5819 clipbox.width, clipbox.height);
5821 g_object_unref (ugly_gc);
5825 impl_window_add_update_area (GdkWindowObject *impl_window,
5828 if (impl_window->update_area)
5829 gdk_region_union (impl_window->update_area, region);
5832 gdk_window_add_update_window ((GdkWindow *)impl_window);
5833 impl_window->update_area = gdk_region_copy (region);
5834 gdk_window_schedule_update ((GdkWindow *)impl_window);
5838 /* clear_bg controls if the region will be cleared to
5839 * the background color/pixmap if the exposure mask is not
5840 * set for the window, whereas this might not otherwise be
5841 * done (unless necessary to emulate background settings).
5842 * Set this to CLEAR_BG_WINCLEARED or CLEAR_BG_ALL if you
5843 * need to clear the background, such as when exposing the area beneath a
5844 * hidden or moved window, but not when an app requests repaint or when the
5845 * windowing system exposes a newly visible area (because then the windowing
5846 * system has already cleared the area).
5849 gdk_window_invalidate_maybe_recurse_full (GdkWindow *window,
5850 const GdkRegion *region,
5852 gboolean (*child_func) (GdkWindow *,
5856 GdkWindowObject *private = (GdkWindowObject *)window;
5857 GdkWindowObject *impl_window;
5858 GdkRegion *visible_region;
5861 g_return_if_fail (GDK_IS_WINDOW (window));
5863 if (GDK_WINDOW_DESTROYED (window))
5866 if (private->input_only ||
5867 !private->viewable ||
5868 gdk_region_empty (region) ||
5869 private->window_type == GDK_WINDOW_ROOT)
5872 visible_region = gdk_drawable_get_visible_region (window);
5873 gdk_region_intersect (visible_region, region);
5875 tmp_list = private->children;
5878 GdkWindowObject *child = tmp_list->data;
5880 if (!child->input_only)
5882 GdkRegion *child_region;
5883 GdkRectangle child_rect;
5885 child_rect.x = child->x;
5886 child_rect.y = child->y;
5887 child_rect.width = child->width;
5888 child_rect.height = child->height;
5889 child_region = gdk_region_rectangle (&child_rect);
5891 /* remove child area from the invalid area of the parent */
5892 if (GDK_WINDOW_IS_MAPPED (child) && !child->shaped &&
5893 !child->composited &&
5894 !gdk_window_is_offscreen (child))
5895 gdk_region_subtract (visible_region, child_region);
5897 if (child_func && (*child_func) ((GdkWindow *)child, user_data))
5899 GdkRegion *tmp = gdk_region_copy (region);
5901 gdk_region_offset (tmp, - child_rect.x, - child_rect.y);
5902 gdk_region_offset (child_region, - child_rect.x, - child_rect.y);
5903 gdk_region_intersect (child_region, tmp);
5905 gdk_window_invalidate_maybe_recurse_full ((GdkWindow *)child,
5906 child_region, clear_bg, child_func, user_data);
5908 gdk_region_destroy (tmp);
5911 gdk_region_destroy (child_region);
5914 tmp_list = tmp_list->next;
5917 impl_window = gdk_window_get_impl_window (private);
5919 if (!gdk_region_empty (visible_region) ||
5920 /* Even if we're not exposing anything, make sure we process
5921 idles for windows with outstanding moves */
5922 (impl_window->outstanding_moves != NULL &&
5923 impl_window->update_area == NULL))
5926 draw_ugly_color (window, region);
5928 /* Convert to impl coords */
5929 gdk_region_offset (visible_region, private->abs_x, private->abs_y);
5931 /* Only invalidate area if app requested expose events or if
5932 we need to clear the area (by request or to emulate background
5933 clearing for non-native windows or native windows with no support
5934 for window backgrounds */
5935 if (private->event_mask & GDK_EXPOSURE_MASK ||
5936 clear_bg == CLEAR_BG_ALL ||
5937 (clear_bg == CLEAR_BG_WINCLEARED &&
5938 (!clears_as_native (private) ||
5939 !GDK_WINDOW_IMPL_GET_IFACE (private->impl)->supports_native_bg)))
5940 impl_window_add_update_area (impl_window, visible_region);
5943 gdk_region_destroy (visible_region);
5947 * gdk_window_invalidate_maybe_recurse:
5948 * @window: a #GdkWindow
5949 * @region: a #GdkRegion
5950 * @child_func: function to use to decide if to recurse to a child,
5951 * %NULL means never recurse.
5952 * @user_data: data passed to @child_func
5954 * Adds @region to the update area for @window. The update area is the
5955 * region that needs to be redrawn, or "dirty region." The call
5956 * gdk_window_process_updates() sends one or more expose events to the
5957 * window, which together cover the entire update area. An
5958 * application would normally redraw the contents of @window in
5959 * response to those expose events.
5961 * GDK will call gdk_window_process_all_updates() on your behalf
5962 * whenever your program returns to the main loop and becomes idle, so
5963 * normally there's no need to do that manually, you just need to
5964 * invalidate regions that you know should be redrawn.
5966 * The @child_func parameter controls whether the region of
5967 * each child window that intersects @region will also be invalidated.
5968 * Only children for which @child_func returns TRUE will have the area
5972 gdk_window_invalidate_maybe_recurse (GdkWindow *window,
5973 const GdkRegion *region,
5974 gboolean (*child_func) (GdkWindow *,
5978 gdk_window_invalidate_maybe_recurse_full (window, region, CLEAR_BG_NONE,
5979 child_func, user_data);
5983 true_predicate (GdkWindow *window,
5990 gdk_window_invalidate_region_full (GdkWindow *window,
5991 const GdkRegion *region,
5992 gboolean invalidate_children,
5995 gdk_window_invalidate_maybe_recurse_full (window, region, clear_bg,
5996 invalidate_children ?
5997 true_predicate : (gboolean (*) (GdkWindow *, gpointer))NULL,
6002 * gdk_window_invalidate_region:
6003 * @window: a #GdkWindow
6004 * @region: a #GdkRegion
6005 * @invalidate_children: %TRUE to also invalidate child windows
6007 * Adds @region to the update area for @window. The update area is the
6008 * region that needs to be redrawn, or "dirty region." The call
6009 * gdk_window_process_updates() sends one or more expose events to the
6010 * window, which together cover the entire update area. An
6011 * application would normally redraw the contents of @window in
6012 * response to those expose events.
6014 * GDK will call gdk_window_process_all_updates() on your behalf
6015 * whenever your program returns to the main loop and becomes idle, so
6016 * normally there's no need to do that manually, you just need to
6017 * invalidate regions that you know should be redrawn.
6019 * The @invalidate_children parameter controls whether the region of
6020 * each child window that intersects @region will also be invalidated.
6021 * If %FALSE, then the update area for child windows will remain
6022 * unaffected. See gdk_window_invalidate_maybe_recurse if you need
6023 * fine grained control over which children are invalidated.
6026 gdk_window_invalidate_region (GdkWindow *window,
6027 const GdkRegion *region,
6028 gboolean invalidate_children)
6030 gdk_window_invalidate_maybe_recurse (window, region,
6031 invalidate_children ?
6032 true_predicate : (gboolean (*) (GdkWindow *, gpointer))NULL,
6037 * _gdk_window_invalidate_for_expose:
6038 * @window: a #GdkWindow
6039 * @region: a #GdkRegion
6041 * Adds @region to the update area for @window. The update area is the
6042 * region that needs to be redrawn, or "dirty region." The call
6043 * gdk_window_process_updates() sends one or more expose events to the
6044 * window, which together cover the entire update area. An
6045 * application would normally redraw the contents of @window in
6046 * response to those expose events.
6048 * GDK will call gdk_window_process_all_updates() on your behalf
6049 * whenever your program returns to the main loop and becomes idle, so
6050 * normally there's no need to do that manually, you just need to
6051 * invalidate regions that you know should be redrawn.
6053 * This version of invalidation is used when you recieve expose events
6054 * from the native window system. It exposes the native window, plus
6055 * any non-native child windows (but not native child windows, as those would
6056 * have gotten their own expose events).
6059 _gdk_window_invalidate_for_expose (GdkWindow *window,
6062 GdkWindowObject *private = (GdkWindowObject *) window;
6063 GdkWindowRegionMove *move;
6064 GdkRegion *move_region;
6067 /* Any invalidations comming from the windowing system will
6068 be in areas that may be moved by outstanding moves,
6069 so we need to modify the expose region correspondingly,
6070 otherwise we would expose in the wrong place, as the
6071 outstanding moves will be copied before we draw the
6073 for (l = private->outstanding_moves; l != NULL; l = l->next)
6077 /* covert to move source region */
6078 move_region = gdk_region_copy (move->dest_region);
6079 gdk_region_offset (move_region, -move->dx, -move->dy);
6081 /* Move area of region that intersects with move source
6082 by dx, dy of the move*/
6083 gdk_region_intersect (move_region, region);
6084 gdk_region_subtract (region, move_region);
6085 gdk_region_offset (move_region, move->dx, move->dy);
6086 gdk_region_union (region, move_region);
6088 gdk_region_destroy (move_region);
6091 gdk_window_invalidate_maybe_recurse_full (window, region, CLEAR_BG_WINCLEARED,
6092 (gboolean (*) (GdkWindow *, gpointer))gdk_window_has_no_impl,
6098 * gdk_window_get_update_area:
6099 * @window: a #GdkWindow
6101 * Transfers ownership of the update area from @window to the caller
6102 * of the function. That is, after calling this function, @window will
6103 * no longer have an invalid/dirty region; the update area is removed
6104 * from @window and handed to you. If a window has no update area,
6105 * gdk_window_get_update_area() returns %NULL. You are responsible for
6106 * calling gdk_region_destroy() on the returned region if it's non-%NULL.
6108 * Return value: the update area for @window
6111 gdk_window_get_update_area (GdkWindow *window)
6113 GdkWindowObject *private = (GdkWindowObject *)window;
6114 GdkWindowObject *impl_window;
6115 GdkRegion *tmp_region;
6117 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
6119 impl_window = gdk_window_get_impl_window (private);
6121 if (impl_window->update_area)
6123 tmp_region = gdk_region_copy (private->clip_region_with_children);
6124 /* Convert to impl coords */
6125 gdk_region_offset (tmp_region, private->abs_x, private->abs_y);
6126 gdk_region_intersect (tmp_region, impl_window->update_area);
6128 if (gdk_region_empty (tmp_region))
6130 gdk_region_destroy (tmp_region);
6135 gdk_region_subtract (impl_window->update_area, tmp_region);
6137 if (gdk_region_empty (impl_window->update_area) &&
6138 impl_window->outstanding_moves == NULL)
6140 gdk_region_destroy (impl_window->update_area);
6141 impl_window->update_area = NULL;
6143 gdk_window_remove_update_window ((GdkWindow *)impl_window);
6146 /* Convert from impl coords */
6147 gdk_region_offset (tmp_region, -private->abs_x, -private->abs_y);
6157 * _gdk_window_clear_update_area:
6158 * @window: a #GdkWindow.
6160 * Internal function to clear the update area for a window. This
6161 * is called when the window is hidden or destroyed.
6164 _gdk_window_clear_update_area (GdkWindow *window)
6166 GdkWindowObject *private = (GdkWindowObject *)window;
6168 g_return_if_fail (GDK_IS_WINDOW (window));
6170 if (private->update_area)
6172 gdk_window_remove_update_window (window);
6174 gdk_region_destroy (private->update_area);
6175 private->update_area = NULL;
6180 * gdk_window_freeze_updates:
6181 * @window: a #GdkWindow
6183 * Temporarily freezes a window such that it won't receive expose
6184 * events. The window will begin receiving expose events again when
6185 * gdk_window_thaw_updates() is called. If gdk_window_freeze_updates()
6186 * has been called more than once, gdk_window_thaw_updates() must be called
6187 * an equal number of times to begin processing exposes.
6190 gdk_window_freeze_updates (GdkWindow *window)
6192 GdkWindowObject *private = (GdkWindowObject *)window;
6193 GdkWindowObject *impl_window;
6195 g_return_if_fail (GDK_IS_WINDOW (window));
6197 impl_window = gdk_window_get_impl_window (private);
6198 impl_window->update_freeze_count++;
6202 * gdk_window_thaw_updates:
6203 * @window: a #GdkWindow
6205 * Thaws a window frozen with gdk_window_freeze_updates().
6208 gdk_window_thaw_updates (GdkWindow *window)
6210 GdkWindowObject *private = (GdkWindowObject *)window;
6211 GdkWindowObject *impl_window;
6213 g_return_if_fail (GDK_IS_WINDOW (window));
6215 impl_window = gdk_window_get_impl_window (private);
6217 g_return_if_fail (impl_window->update_freeze_count > 0);
6219 if (--impl_window->update_freeze_count == 0)
6220 gdk_window_schedule_update (GDK_WINDOW (impl_window));
6224 * gdk_window_freeze_toplevel_updates_libgtk_only:
6225 * @window: a #GdkWindow
6227 * Temporarily freezes a window and all its descendants such that it won't
6228 * receive expose events. The window will begin receiving expose events
6229 * again when gdk_window_thaw_toplevel_updates_libgtk_only() is called. If
6230 * gdk_window_freeze_toplevel_updates_libgtk_only()
6231 * has been called more than once,
6232 * gdk_window_thaw_toplevel_updates_libgtk_only() must be called
6233 * an equal number of times to begin processing exposes.
6235 * This function is not part of the GDK public API and is only
6239 gdk_window_freeze_toplevel_updates_libgtk_only (GdkWindow *window)
6241 GdkWindowObject *private = (GdkWindowObject *)window;
6243 g_return_if_fail (GDK_IS_WINDOW (window));
6244 g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
6246 private->update_and_descendants_freeze_count++;
6250 * gdk_window_thaw_toplevel_updates_libgtk_only:
6251 * @window: a #GdkWindow
6253 * Thaws a window frozen with
6254 * gdk_window_freeze_toplevel_updates_libgtk_only().
6256 * This function is not part of the GDK public API and is only
6260 gdk_window_thaw_toplevel_updates_libgtk_only (GdkWindow *window)
6262 GdkWindowObject *private = (GdkWindowObject *)window;
6264 g_return_if_fail (GDK_IS_WINDOW (window));
6265 g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
6266 g_return_if_fail (private->update_and_descendants_freeze_count > 0);
6268 private->update_and_descendants_freeze_count--;
6270 gdk_window_schedule_update (window);
6274 * gdk_window_set_debug_updates:
6275 * @setting: %TRUE to turn on update debugging
6277 * With update debugging enabled, calls to
6278 * gdk_window_invalidate_region() clear the invalidated region of the
6279 * screen to a noticeable color, and GDK pauses for a short time
6280 * before sending exposes to windows during
6281 * gdk_window_process_updates(). The net effect is that you can see
6282 * the invalid region for each window and watch redraws as they
6283 * occur. This allows you to diagnose inefficiencies in your application.
6285 * In essence, because the GDK rendering model prevents all flicker,
6286 * if you are redrawing the same region 400 times you may never
6287 * notice, aside from noticing a speed problem. Enabling update
6288 * debugging causes GTK to flicker slowly and noticeably, so you can
6289 * see exactly what's being redrawn when, in what order.
6291 * The --gtk-debug=updates command line option passed to GTK+ programs
6292 * enables this debug option at application startup time. That's
6293 * usually more useful than calling gdk_window_set_debug_updates()
6294 * yourself, though you might want to use this function to enable
6295 * updates sometime after application startup time.
6299 gdk_window_set_debug_updates (gboolean setting)
6301 debug_updates = setting;
6305 * gdk_window_constrain_size:
6306 * @geometry: a #GdkGeometry structure
6307 * @flags: a mask indicating what portions of @geometry are set
6308 * @width: desired width of window
6309 * @height: desired height of the window
6310 * @new_width: location to store resulting width
6311 * @new_height: location to store resulting height
6313 * Constrains a desired width and height according to a
6314 * set of geometry hints (such as minimum and maximum size).
6317 gdk_window_constrain_size (GdkGeometry *geometry,
6324 /* This routine is partially borrowed from fvwm.
6326 * Copyright 1993, Robert Nation
6327 * You may use this code for any purpose, as long as the original
6328 * copyright remains in the source code and all documentation
6330 * which in turn borrows parts of the algorithm from uwm
6333 gint min_height = 0;
6334 gint base_width = 0;
6335 gint base_height = 0;
6338 gint max_width = G_MAXINT;
6339 gint max_height = G_MAXINT;
6341 #define FLOOR(value, base) ( ((gint) ((value) / (base))) * (base) )
6343 if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
6345 base_width = geometry->base_width;
6346 base_height = geometry->base_height;
6347 min_width = geometry->min_width;
6348 min_height = geometry->min_height;
6350 else if (flags & GDK_HINT_BASE_SIZE)
6352 base_width = geometry->base_width;
6353 base_height = geometry->base_height;
6354 min_width = geometry->base_width;
6355 min_height = geometry->base_height;
6357 else if (flags & GDK_HINT_MIN_SIZE)
6359 base_width = geometry->min_width;
6360 base_height = geometry->min_height;
6361 min_width = geometry->min_width;
6362 min_height = geometry->min_height;
6365 if (flags & GDK_HINT_MAX_SIZE)
6367 max_width = geometry->max_width ;
6368 max_height = geometry->max_height;
6371 if (flags & GDK_HINT_RESIZE_INC)
6373 xinc = MAX (xinc, geometry->width_inc);
6374 yinc = MAX (yinc, geometry->height_inc);
6377 /* clamp width and height to min and max values
6379 width = CLAMP (width, min_width, max_width);
6380 height = CLAMP (height, min_height, max_height);
6382 /* shrink to base + N * inc
6384 width = base_width + FLOOR (width - base_width, xinc);
6385 height = base_height + FLOOR (height - base_height, yinc);
6387 /* constrain aspect ratio, according to:
6390 * min_aspect <= -------- <= max_aspect
6394 if (flags & GDK_HINT_ASPECT &&
6395 geometry->min_aspect > 0 &&
6396 geometry->max_aspect > 0)
6400 if (geometry->min_aspect * height > width)
6402 delta = FLOOR (height - width / geometry->min_aspect, yinc);
6403 if (height - delta >= min_height)
6407 delta = FLOOR (height * geometry->min_aspect - width, xinc);
6408 if (width + delta <= max_width)
6413 if (geometry->max_aspect * height < width)
6415 delta = FLOOR (width - height * geometry->max_aspect, xinc);
6416 if (width - delta >= min_width)
6420 delta = FLOOR (width / geometry->max_aspect - height, yinc);
6421 if (height + delta <= max_height)
6430 *new_height = height;
6434 * gdk_window_get_pointer:
6435 * @window: a #GdkWindow
6436 * @x: (out) (allow-none): return location for X coordinate of pointer or %NULL to not
6437 * return the X coordinate
6438 * @y: (out) (allow-none): return location for Y coordinate of pointer or %NULL to not
6439 * return the Y coordinate
6440 * @mask: (out) (allow-none): return location for modifier mask or %NULL to not return the
6443 * Obtains the current pointer position and modifier state.
6444 * The position is given in coordinates relative to the upper left
6445 * corner of @window.
6447 * Return value: (transfer none): the window containing the pointer (as with
6448 * gdk_window_at_pointer()), or %NULL if the window containing the
6449 * pointer isn't known to GDK
6451 * Deprecated: 3.0: Use gdk_window_get_device_position() instead.
6454 gdk_window_get_pointer (GdkWindow *window,
6457 GdkModifierType *mask)
6459 GdkDisplay *display;
6461 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
6463 display = gdk_drawable_get_display (window);
6465 return gdk_window_get_device_position (window, display->core_pointer, x, y, mask);
6469 * gdk_window_get_device_position:
6470 * @window: a #GdkWindow.
6471 * @device: #GdkDevice to query to.
6472 * @x: return location for the X coordinate of @device, or %NULL.
6473 * @y: return location for the Y coordinate of @device, or %NULL.
6474 * @mask: return location for the modifier mask, or %NULL.
6476 * Obtains the current device position and modifier state.
6477 * The position is given in coordinates relative to the upper left
6478 * corner of @window.
6480 * Returns: The window underneath @device (as with
6481 * gdk_display_get_window_at_device_position()), or %NULL if the
6482 * window is not known to GDK.
6487 gdk_window_get_device_position (GdkWindow *window,
6491 GdkModifierType *mask)
6493 GdkDisplay *display;
6495 GdkModifierType tmp_mask;
6498 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
6499 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
6501 display = gdk_drawable_get_display (window);
6502 child = display->device_hooks->window_get_device_position (display, device, window,
6503 &tmp_x, &tmp_y, &tmp_mask);
6512 _gdk_display_enable_motion_hints (display, device);
6518 * gdk_window_at_pointer:
6519 * @win_x: (out) (allow-none): return location for origin of the window under the pointer
6520 * @win_y: (out) (allow-none): return location for origin of the window under the pointer
6522 * Obtains the window underneath the mouse pointer, returning the
6523 * location of that window in @win_x, @win_y. Returns %NULL if the
6524 * window under the mouse pointer is not known to GDK (if the window
6525 * belongs to another application and a #GdkWindow hasn't been created
6526 * for it with gdk_window_foreign_new())
6528 * NOTE: For multihead-aware widgets or applications use
6529 * gdk_display_get_window_at_pointer() instead.
6531 * Return value: (transfer none): window under the mouse pointer
6533 * Deprecated: 3.0: Use gdk_display_get_window_at_device_position() instead.
6536 gdk_window_at_pointer (gint *win_x,
6539 return gdk_display_get_window_at_pointer (gdk_display_get_default (), win_x, win_y);
6543 * gdk_get_default_root_window:
6545 * Obtains the root window (parent all other windows are inside)
6546 * for the default display and screen.
6548 * Return value: the default root window
6551 gdk_get_default_root_window (void)
6553 return gdk_screen_get_root_window (gdk_screen_get_default ());
6557 * gdk_window_foreign_new:
6558 * @anid: a native window handle.
6560 * Wraps a native window for the default display in a #GdkWindow.
6561 * This may fail if the window has been destroyed.
6563 * For example in the X backend, a native window handle is an Xlib
6566 * Return value: the newly-created #GdkWindow wrapper for the
6567 * native window or %NULL if the window has been destroyed.
6570 gdk_window_foreign_new (GdkNativeWindow anid)
6572 return gdk_window_foreign_new_for_display (gdk_display_get_default (), anid);
6576 get_all_native_children (GdkWindowObject *private,
6579 GdkWindowObject *child;
6582 for (l = private->children; l != NULL; l = l->next)
6586 if (gdk_window_has_impl (child))
6587 *native = g_list_prepend (*native, child);
6589 get_all_native_children (child, native);
6595 gdk_window_raise_internal (GdkWindow *window)
6597 GdkWindowObject *private = (GdkWindowObject *)window;
6598 GdkWindowObject *parent = private->parent;
6599 GdkWindowObject *above;
6600 GList *native_children;
6602 GdkWindowImplIface *impl_iface;
6606 parent->children = g_list_remove (parent->children, window);
6607 parent->children = g_list_prepend (parent->children, window);
6610 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
6611 /* Just do native raise for toplevels */
6612 if (gdk_window_is_toplevel (private) ||
6613 /* The restack_under codepath should work correctly even if the parent
6614 is native, but it relies on the order of ->children to be correct,
6615 and some apps like SWT reorder the x windows without gdks knowledge,
6616 so we use raise directly in order to make these behave as before
6617 when using native windows */
6618 (gdk_window_has_impl (private) && gdk_window_has_impl (parent)))
6620 impl_iface->raise (window);
6622 else if (gdk_window_has_impl (private))
6624 above = find_native_sibling_above (parent, private);
6627 listhead.data = window;
6628 listhead.next = NULL;
6629 listhead.prev = NULL;
6630 impl_iface->restack_under ((GdkWindow *)above,
6634 impl_iface->raise (window);
6638 native_children = NULL;
6639 get_all_native_children (private, &native_children);
6640 if (native_children != NULL)
6642 above = find_native_sibling_above (parent, private);
6645 impl_iface->restack_under ((GdkWindow *)above,
6649 /* Right order, since native_children is bottom-topmost first */
6650 for (l = native_children; l != NULL; l = l->next)
6651 impl_iface->raise (l->data);
6654 g_list_free (native_children);
6660 /* Returns TRUE If the native window was mapped or unmapped */
6662 set_viewable (GdkWindowObject *w,
6665 GdkWindowObject *child;
6666 GdkWindowImplIface *impl_iface;
6669 if (w->viewable == val)
6675 recompute_visible_regions (w, FALSE, FALSE);
6677 for (l = w->children; l != NULL; l = l->next)
6681 if (GDK_WINDOW_IS_MAPPED (child) &&
6682 child->window_type != GDK_WINDOW_FOREIGN)
6683 set_viewable (child, val);
6686 if (!_gdk_native_windows &&
6687 gdk_window_has_impl (w) &&
6688 w->window_type != GDK_WINDOW_FOREIGN &&
6689 !gdk_window_is_toplevel (w))
6691 /* For most native windows we show/hide them not when they are
6692 * mapped/unmapped, because that may not produce the correct results.
6693 * For instance, if a native window have a non-native parent which is
6694 * hidden, but its native parent is viewable then showing the window
6695 * would make it viewable to X but its not viewable wrt the non-native
6696 * hierarchy. In order to handle this we track the gdk side viewability
6697 * and only map really viewable windows.
6699 * There are two exceptions though:
6701 * For foreign windows we don't want ever change the mapped state
6702 * except when explicitly done via gdk_window_show/hide, as this may
6703 * cause problems for client owning the foreign window when its window
6704 * is suddenly mapped or unmapped.
6706 * For toplevel windows embedded in a foreign window (e.g. a plug)
6707 * we sometimes synthesize a map of a window, but the native
6708 * window is really shown by the embedder, so we don't want to
6709 * do the show ourselves. We can't really tell this case from the normal
6710 * toplevel show as such toplevels are seen by gdk as parents of the
6711 * root window, so we make an exception for all toplevels.
6713 * Also, when in GDK_NATIVE_WINDOW mode we never need to play games
6714 * like this, so we just always show/hide directly.
6717 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (w->impl);
6719 impl_iface->show ((GdkWindow *)w, FALSE);
6721 impl_iface->hide ((GdkWindow *)w);
6729 /* Returns TRUE If the native window was mapped or unmapped */
6731 _gdk_window_update_viewable (GdkWindow *window)
6733 GdkWindowObject *priv = (GdkWindowObject *)window;
6736 if (priv->window_type == GDK_WINDOW_FOREIGN ||
6737 priv->window_type == GDK_WINDOW_ROOT)
6739 else if (gdk_window_is_toplevel (priv) ||
6740 priv->parent->viewable)
6741 viewable = GDK_WINDOW_IS_MAPPED (priv);
6745 return set_viewable (priv, viewable);
6749 gdk_window_show_internal (GdkWindow *window, gboolean raise)
6751 GdkWindowObject *private;
6752 GdkWindowImplIface *impl_iface;
6753 gboolean was_mapped, was_viewable;
6756 g_return_if_fail (GDK_IS_WINDOW (window));
6758 private = (GdkWindowObject *) window;
6759 if (private->destroyed)
6762 was_mapped = GDK_WINDOW_IS_MAPPED (window);
6763 was_viewable = private->viewable;
6766 /* Keep children in (reverse) stacking order */
6767 gdk_window_raise_internal (window);
6769 if (gdk_window_has_impl (private))
6772 gdk_synthesize_window_state (window,
6773 GDK_WINDOW_STATE_WITHDRAWN,
6781 did_show = _gdk_window_update_viewable (window);
6783 /* If it was already viewable the backend show op won't be called, call it
6784 again to ensure things happen right if the mapped tracking was not right
6785 for e.g. a foreign window.
6786 Dunno if this is strictly needed but its what happened pre-csw.
6787 Also show if not done by gdk_window_update_viewable. */
6788 if (gdk_window_has_impl (private) && (was_viewable || !did_show))
6790 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
6791 impl_iface->show ((GdkWindow *)private,
6792 !did_show ? was_mapped : TRUE);
6795 if (!was_mapped && !gdk_window_has_impl (private))
6797 if (private->event_mask & GDK_STRUCTURE_MASK)
6798 _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
6800 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
6801 _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
6804 if (!was_mapped || raise)
6806 recompute_visible_regions (private, TRUE, FALSE);
6808 /* If any decendants became visible we need to send visibility notify */
6809 gdk_window_update_visibility_recursively (private, NULL);
6811 if (gdk_window_is_viewable (window))
6813 _gdk_synthesize_crossing_events_for_geometry_change (window);
6814 gdk_window_invalidate_rect_full (window, NULL, TRUE, CLEAR_BG_ALL);
6820 * gdk_window_show_unraised:
6821 * @window: a #GdkWindow
6823 * Shows a #GdkWindow onscreen, but does not modify its stacking
6824 * order. In contrast, gdk_window_show() will raise the window
6825 * to the top of the window stack.
6827 * On the X11 platform, in Xlib terms, this function calls
6828 * XMapWindow() (it also updates some internal GDK state, which means
6829 * that you can't really use XMapWindow() directly on a GDK window).
6832 gdk_window_show_unraised (GdkWindow *window)
6834 gdk_window_show_internal (window, FALSE);
6839 * @window: a #GdkWindow
6841 * Raises @window to the top of the Z-order (stacking order), so that
6842 * other windows with the same parent window appear below @window.
6843 * This is true whether or not the windows are visible.
6845 * If @window is a toplevel, the window manager may choose to deny the
6846 * request to move the window in the Z-order, gdk_window_raise() only
6847 * requests the restack, does not guarantee it.
6850 gdk_window_raise (GdkWindow *window)
6852 GdkWindowObject *private;
6853 GdkRegion *old_region, *new_region;
6855 g_return_if_fail (GDK_IS_WINDOW (window));
6857 private = (GdkWindowObject *) window;
6858 if (private->destroyed)
6861 gdk_window_flush_if_exposing (window);
6864 if (gdk_window_is_viewable (window) &&
6865 !private->input_only)
6866 old_region = gdk_region_copy (private->clip_region);
6868 /* Keep children in (reverse) stacking order */
6869 gdk_window_raise_internal (window);
6871 recompute_visible_regions (private, TRUE, FALSE);
6875 new_region = gdk_region_copy (private->clip_region);
6877 gdk_region_subtract (new_region, old_region);
6878 gdk_window_invalidate_region_full (window, new_region, TRUE, CLEAR_BG_ALL);
6880 gdk_region_destroy (old_region);
6881 gdk_region_destroy (new_region);
6886 gdk_window_lower_internal (GdkWindow *window)
6888 GdkWindowObject *private = (GdkWindowObject *)window;
6889 GdkWindowObject *parent = private->parent;
6890 GdkWindowImplIface *impl_iface;
6891 GdkWindowObject *above;
6892 GList *native_children;
6897 parent->children = g_list_remove (parent->children, window);
6898 parent->children = g_list_append (parent->children, window);
6901 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
6902 /* Just do native lower for toplevels */
6903 if (gdk_window_is_toplevel (private) ||
6904 /* The restack_under codepath should work correctly even if the parent
6905 is native, but it relies on the order of ->children to be correct,
6906 and some apps like SWT reorder the x windows without gdks knowledge,
6907 so we use lower directly in order to make these behave as before
6908 when using native windows */
6909 (gdk_window_has_impl (private) && gdk_window_has_impl (parent)))
6911 impl_iface->lower (window);
6913 else if (gdk_window_has_impl (private))
6915 above = find_native_sibling_above (parent, private);
6918 listhead.data = window;
6919 listhead.next = NULL;
6920 listhead.prev = NULL;
6921 impl_iface->restack_under ((GdkWindow *)above, &listhead);
6924 impl_iface->raise (window);
6928 native_children = NULL;
6929 get_all_native_children (private, &native_children);
6930 if (native_children != NULL)
6932 above = find_native_sibling_above (parent, private);
6935 impl_iface->restack_under ((GdkWindow *)above,
6939 /* Right order, since native_children is bottom-topmost first */
6940 for (l = native_children; l != NULL; l = l->next)
6941 impl_iface->raise (l->data);
6944 g_list_free (native_children);
6951 gdk_window_invalidate_in_parent (GdkWindowObject *private)
6953 GdkRectangle r, child;
6955 if (gdk_window_is_toplevel (private))
6958 /* get the visible rectangle of the parent */
6960 r.width = private->parent->width;
6961 r.height = private->parent->height;
6963 child.x = private->x;
6964 child.y = private->y;
6965 child.width = private->width;
6966 child.height = private->height;
6967 gdk_rectangle_intersect (&r, &child, &r);
6969 gdk_window_invalidate_rect_full (GDK_WINDOW (private->parent), &r, TRUE, CLEAR_BG_ALL);
6975 * @window: a #GdkWindow
6977 * Lowers @window to the bottom of the Z-order (stacking order), so that
6978 * other windows with the same parent window appear above @window.
6979 * This is true whether or not the other windows are visible.
6981 * If @window is a toplevel, the window manager may choose to deny the
6982 * request to move the window in the Z-order, gdk_window_lower() only
6983 * requests the restack, does not guarantee it.
6985 * Note that gdk_window_show() raises the window again, so don't call this
6986 * function before gdk_window_show(). (Try gdk_window_show_unraised().)
6989 gdk_window_lower (GdkWindow *window)
6991 GdkWindowObject *private;
6993 g_return_if_fail (GDK_IS_WINDOW (window));
6995 private = (GdkWindowObject *) window;
6996 if (private->destroyed)
6999 gdk_window_flush_if_exposing (window);
7001 /* Keep children in (reverse) stacking order */
7002 gdk_window_lower_internal (window);
7004 recompute_visible_regions (private, TRUE, FALSE);
7006 _gdk_synthesize_crossing_events_for_geometry_change (window);
7007 gdk_window_invalidate_in_parent (private);
7011 * gdk_window_restack:
7012 * @window: a #GdkWindow
7013 * @sibling: (allow-none): a #GdkWindow that is a sibling of @window, or %NULL
7016 * Changes the position of @window in the Z-order (stacking order), so that
7017 * it is above @sibling (if @above is %TRUE) or below @sibling (if @above is
7020 * If @sibling is %NULL, then this either raises (if @above is %TRUE) or
7021 * lowers the window.
7023 * If @window is a toplevel, the window manager may choose to deny the
7024 * request to move the window in the Z-order, gdk_window_restack() only
7025 * requests the restack, does not guarantee it.
7030 gdk_window_restack (GdkWindow *window,
7034 GdkWindowObject *private;
7035 GdkWindowImplIface *impl_iface;
7036 GdkWindowObject *parent;
7037 GdkWindowObject *above_native;
7038 GList *sibling_link;
7039 GList *native_children;
7042 g_return_if_fail (GDK_IS_WINDOW (window));
7043 g_return_if_fail (sibling == NULL || GDK_IS_WINDOW (sibling));
7045 private = (GdkWindowObject *) window;
7046 if (private->destroyed)
7049 if (sibling == NULL)
7052 gdk_window_raise (window);
7054 gdk_window_lower (window);
7058 gdk_window_flush_if_exposing (window);
7060 if (gdk_window_is_toplevel (private))
7062 g_return_if_fail (gdk_window_is_toplevel (GDK_WINDOW_OBJECT (sibling)));
7063 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
7064 impl_iface->restack_toplevel (window, sibling, above);
7068 parent = private->parent;
7071 sibling_link = g_list_find (parent->children, sibling);
7072 g_return_if_fail (sibling_link != NULL);
7073 if (sibling_link == NULL)
7076 parent->children = g_list_remove (parent->children, window);
7078 parent->children = g_list_insert_before (parent->children,
7082 parent->children = g_list_insert_before (parent->children,
7086 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
7087 if (gdk_window_has_impl (private))
7089 above_native = find_native_sibling_above (parent, private);
7092 listhead.data = window;
7093 listhead.next = NULL;
7094 listhead.prev = NULL;
7095 impl_iface->restack_under ((GdkWindow *)above_native, &listhead);
7098 impl_iface->raise (window);
7102 native_children = NULL;
7103 get_all_native_children (private, &native_children);
7104 if (native_children != NULL)
7106 above_native = find_native_sibling_above (parent, private);
7108 impl_iface->restack_under ((GdkWindow *)above_native,
7112 /* Right order, since native_children is bottom-topmost first */
7113 for (l = native_children; l != NULL; l = l->next)
7114 impl_iface->raise (l->data);
7117 g_list_free (native_children);
7122 recompute_visible_regions (private, TRUE, FALSE);
7124 _gdk_synthesize_crossing_events_for_geometry_change (window);
7125 gdk_window_invalidate_in_parent (private);
7131 * @window: a #GdkWindow
7133 * Like gdk_window_show_unraised(), but also raises the window to the
7134 * top of the window stack (moves the window to the front of the
7137 * This function maps a window so it's visible onscreen. Its opposite
7138 * is gdk_window_hide().
7140 * When implementing a #GtkWidget, you should call this function on the widget's
7141 * #GdkWindow as part of the "map" method.
7144 gdk_window_show (GdkWindow *window)
7146 gdk_window_show_internal (window, TRUE);
7151 * @window: a #GdkWindow
7153 * For toplevel windows, withdraws them, so they will no longer be
7154 * known to the window manager; for all windows, unmaps them, so
7155 * they won't be displayed. Normally done automatically as
7156 * part of gtk_widget_hide().
7159 gdk_window_hide (GdkWindow *window)
7161 GdkWindowObject *private;
7162 GdkWindowImplIface *impl_iface;
7163 gboolean was_mapped, did_hide;
7165 g_return_if_fail (GDK_IS_WINDOW (window));
7167 private = (GdkWindowObject *) window;
7168 if (private->destroyed)
7171 was_mapped = GDK_WINDOW_IS_MAPPED (private);
7173 if (gdk_window_has_impl (private))
7176 if (GDK_WINDOW_IS_MAPPED (window))
7177 gdk_synthesize_window_state (window,
7179 GDK_WINDOW_STATE_WITHDRAWN);
7181 else if (was_mapped)
7183 GdkDisplay *display;
7184 GdkDeviceManager *device_manager;
7187 /* May need to break grabs on children */
7188 display = gdk_drawable_get_display (window);
7189 device_manager = gdk_display_get_device_manager (display);
7191 /* Get all devices */
7192 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
7193 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_SLAVE));
7194 devices = g_list_concat (devices, gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_FLOATING));
7196 for (d = devices; d; d = d->next)
7198 GdkDevice *device = d->data;
7200 if (_gdk_display_end_device_grab (display, device,
7201 _gdk_windowing_window_get_next_serial (display),
7204 gdk_device_ungrab (device, GDK_CURRENT_TIME);
7207 private->state = GDK_WINDOW_STATE_WITHDRAWN;
7208 g_list_free (devices);
7211 did_hide = _gdk_window_update_viewable (window);
7213 /* Hide foreign window as those are not handled by update_viewable. */
7214 if (gdk_window_has_impl (private) && (!did_hide))
7216 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
7217 impl_iface->hide (window);
7220 recompute_visible_regions (private, TRUE, FALSE);
7222 /* all decendants became non-visible, we need to send visibility notify */
7223 gdk_window_update_visibility_recursively (private, NULL);
7225 if (was_mapped && !gdk_window_has_impl (private))
7227 if (private->event_mask & GDK_STRUCTURE_MASK)
7228 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
7230 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
7231 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
7233 _gdk_synthesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
7236 /* Invalidate the rect */
7238 gdk_window_invalidate_in_parent (private);
7242 * gdk_window_withdraw:
7243 * @window: a toplevel #GdkWindow
7245 * Withdraws a window (unmaps it and asks the window manager to forget about it).
7246 * This function is not really useful as gdk_window_hide() automatically
7247 * withdraws toplevel windows before hiding them.
7250 gdk_window_withdraw (GdkWindow *window)
7252 GdkWindowObject *private;
7253 GdkWindowImplIface *impl_iface;
7254 gboolean was_mapped;
7256 g_return_if_fail (GDK_IS_WINDOW (window));
7258 private = (GdkWindowObject *) window;
7259 if (private->destroyed)
7262 was_mapped = GDK_WINDOW_IS_MAPPED (private);
7264 if (gdk_window_has_impl (private))
7266 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
7267 impl_iface->withdraw (window);
7271 if (private->event_mask & GDK_STRUCTURE_MASK)
7272 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
7274 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
7275 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
7277 _gdk_synthesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
7280 recompute_visible_regions (private, TRUE, FALSE);
7285 * gdk_window_set_events:
7286 * @window: a #GdkWindow
7287 * @event_mask: event mask for @window
7289 * The event mask for a window determines which events will be reported
7290 * for that window from all master input devices. For example, an event mask
7291 * including #GDK_BUTTON_PRESS_MASK means the window should report button
7292 * press events. The event mask is the bitwise OR of values from the
7293 * #GdkEventMask enumeration.
7296 gdk_window_set_events (GdkWindow *window,
7297 GdkEventMask event_mask)
7299 GdkWindowObject *private;
7300 GdkWindowImplIface *impl_iface;
7301 GdkDisplay *display;
7303 g_return_if_fail (GDK_IS_WINDOW (window));
7305 private = (GdkWindowObject *) window;
7306 if (private->destroyed)
7309 /* If motion hint is disabled, enable motion events again */
7310 display = gdk_drawable_get_display (window);
7311 if ((private->event_mask & GDK_POINTER_MOTION_HINT_MASK) &&
7312 !(event_mask & GDK_POINTER_MOTION_HINT_MASK))
7314 GList *devices = private->devices_inside;
7318 _gdk_display_enable_motion_hints (display, (GdkDevice *) devices->data);
7319 devices = devices->next;
7323 private->event_mask = event_mask;
7325 if (gdk_window_has_impl (private))
7327 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
7328 impl_iface->set_events (window,
7329 get_native_event_mask (private));
7335 * gdk_window_get_events:
7336 * @window: a #GdkWindow
7338 * Gets the event mask for @window for all master input devices. See
7339 * gdk_window_set_events().
7341 * Return value: event mask for @window
7344 gdk_window_get_events (GdkWindow *window)
7346 GdkWindowObject *private;
7348 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
7350 private = (GdkWindowObject *) window;
7351 if (private->destroyed)
7354 return private->event_mask;
7358 * gdk_window_set_device_events:
7359 * @window: a #GdkWindow
7360 * @device: #GdkDevice to enable events for.
7361 * @event_mask: event mask for @window
7363 * Sets the event mask for a given device (Normally a floating device, not
7364 * attached to any visible pointer) to @window. For example, an event mask
7365 * including #GDK_BUTTON_PRESS_MASK means the window should report button
7366 * press events. The event mask is the bitwise OR of values from the
7367 * #GdkEventMask enumeration.
7372 gdk_window_set_device_events (GdkWindow *window,
7374 GdkEventMask event_mask)
7376 GdkEventMask device_mask;
7377 GdkWindowObject *private;
7378 GdkDisplay *display;
7381 g_return_if_fail (GDK_IS_WINDOW (window));
7382 g_return_if_fail (GDK_IS_DEVICE (device));
7384 if (GDK_WINDOW_DESTROYED (window))
7387 private = (GdkWindowObject *) window;
7389 /* If motion hint is disabled, enable motion events again */
7390 display = gdk_drawable_get_display (window);
7391 if ((private->event_mask & GDK_POINTER_MOTION_HINT_MASK) &&
7392 !(event_mask & GDK_POINTER_MOTION_HINT_MASK))
7393 _gdk_display_enable_motion_hints (display, device);
7395 if (G_UNLIKELY (!private->device_events))
7396 private->device_events = g_hash_table_new (NULL, NULL);
7398 if (event_mask == 0)
7400 /* FIXME: unsetting events on a master device
7401 * would restore private->event_mask
7403 g_hash_table_remove (private->device_events, device);
7406 g_hash_table_insert (private->device_events, device,
7407 GINT_TO_POINTER (event_mask));
7409 if (_gdk_native_windows)
7412 native = gdk_window_get_toplevel (window);
7414 while (gdk_window_is_offscreen ((GdkWindowObject *)native))
7416 native = gdk_offscreen_window_get_embedder (native);
7418 if (native == NULL ||
7419 (!_gdk_window_has_impl (native) &&
7420 !gdk_window_is_viewable (native)))
7423 native = gdk_window_get_toplevel (native);
7426 device_mask = get_native_device_event_mask (private, device);
7427 GDK_DEVICE_GET_CLASS (device)->select_window_events (device, native, device_mask);
7431 * gdk_window_get_device_events:
7432 * @window: a #GdkWindow.
7433 * @device: a #GdkDevice.
7435 * Returns the event mask for @window corresponding to an specific device.
7437 * Returns: device event mask for @window
7442 gdk_window_get_device_events (GdkWindow *window,
7445 GdkWindowObject *private;
7448 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
7449 g_return_val_if_fail (GDK_IS_DEVICE (device), 0);
7451 if (GDK_WINDOW_DESTROYED (window))
7454 private = (GdkWindowObject *) window;
7456 if (!private->device_events)
7459 mask = GPOINTER_TO_INT (g_hash_table_lookup (private->device_events, device));
7461 /* FIXME: device could be controlled by private->event_mask */
7467 gdk_window_move_resize_toplevel (GdkWindow *window,
7474 GdkWindowObject *private;
7475 GdkRegion *old_region, *new_region;
7476 GdkWindowImplIface *impl_iface;
7478 int old_x, old_y, old_abs_x, old_abs_y;
7482 private = (GdkWindowObject *) window;
7490 is_resize = (width != -1) || (height != -1);
7492 if (gdk_window_is_viewable (window) &&
7493 !private->input_only)
7496 old_region = gdk_region_copy (private->clip_region);
7499 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
7500 impl_iface->move_resize (window, with_move, x, y, width, height);
7502 dx = private->x - old_x;
7503 dy = private->y - old_y;
7505 old_abs_x = private->abs_x;
7506 old_abs_y = private->abs_y;
7508 /* Avoid recomputing for pure toplevel moves, for performance reasons */
7510 recompute_visible_regions (private, TRUE, FALSE);
7514 new_region = gdk_region_copy (private->clip_region);
7516 /* This is the newly exposed area (due to any resize),
7517 * X will expose it, but lets do that without the
7520 gdk_region_subtract (new_region, old_region);
7521 gdk_window_invalidate_region_full (window, new_region, TRUE, CLEAR_BG_WINCLEARED);
7523 gdk_region_destroy (old_region);
7524 gdk_region_destroy (new_region);
7527 _gdk_synthesize_crossing_events_for_geometry_change (window);
7532 move_native_children (GdkWindowObject *private)
7535 GdkWindowObject *child;
7536 GdkWindowImplIface *impl_iface;
7538 for (l = private->children; l; l = l->next)
7542 if (child->impl != private->impl)
7544 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (child->impl);
7545 impl_iface->move_resize ((GdkWindow *)child, TRUE,
7547 child->width, child->height);
7550 move_native_children (child);
7555 collect_native_child_region_helper (GdkWindowObject *window,
7561 GdkWindowObject *child;
7565 for (l = window->children; l != NULL; l = l->next)
7569 if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only)
7572 if (child->impl != impl)
7574 tmp = gdk_region_copy (child->clip_region);
7575 gdk_region_offset (tmp,
7576 x_offset + child->x,
7577 y_offset + child->y);
7578 if (*region == NULL)
7582 gdk_region_union (*region, tmp);
7583 gdk_region_destroy (tmp);
7587 collect_native_child_region_helper (child, impl, region,
7588 x_offset + child->x,
7589 y_offset + child->y);
7596 collect_native_child_region (GdkWindowObject *window,
7597 gboolean include_this)
7601 if (include_this && gdk_window_has_impl (window) && window->viewable)
7602 return gdk_region_copy (window->clip_region);
7606 collect_native_child_region_helper (window, window->impl, ®ion, 0, 0);
7613 gdk_window_move_resize_internal (GdkWindow *window,
7620 GdkWindowObject *private;
7621 GdkRegion *old_region, *new_region, *copy_area;
7622 GdkRegion *old_native_child_region, *new_native_child_region;
7623 GdkWindowObject *impl_window;
7624 GdkWindowImplIface *impl_iface;
7626 int old_x, old_y, old_abs_x, old_abs_y;
7629 g_return_if_fail (GDK_IS_WINDOW (window));
7631 private = (GdkWindowObject *) window;
7632 if (private->destroyed)
7635 if (gdk_window_is_toplevel (private))
7637 gdk_window_move_resize_toplevel (window, with_move, x, y, width, height);
7641 /* Bail early if no change */
7642 if (private->width == width &&
7643 private->height == height &&
7649 gdk_window_flush_if_exposing (window);
7651 /* Handle child windows */
7656 impl_window = gdk_window_get_impl_window (private);
7661 old_native_child_region = NULL;
7662 if (gdk_window_is_viewable (window) &&
7663 !private->input_only)
7667 old_region = gdk_region_copy (private->clip_region);
7668 /* Adjust region to parent window coords */
7669 gdk_region_offset (old_region, private->x, private->y);
7671 old_native_child_region = collect_native_child_region (private, TRUE);
7672 if (old_native_child_region)
7674 /* Adjust region to parent window coords */
7675 gdk_region_offset (old_native_child_region, private->x, private->y);
7677 /* Any native window move will immediately copy stuff to the destination, which may overwrite a
7678 * source or destination for a delayed GdkWindowRegionMove. So, we need
7679 * to flush those here for the parent window and all overlapped subwindows
7680 * of it. And we need to do this before setting the new clips as those will be
7683 gdk_window_flush_recursive (private->parent);
7687 /* Set the new position and size */
7693 if (!(width < 0 && height < 0))
7697 private->width = width;
7700 private->height = height;
7703 dx = private->x - old_x;
7704 dy = private->y - old_y;
7706 old_abs_x = private->abs_x;
7707 old_abs_y = private->abs_y;
7709 recompute_visible_regions (private, TRUE, FALSE);
7711 new_native_child_region = NULL;
7712 if (old_native_child_region)
7714 new_native_child_region = collect_native_child_region (private, TRUE);
7715 /* Adjust region to parent window coords */
7716 gdk_region_offset (new_native_child_region, private->x, private->y);
7719 if (gdk_window_has_impl (private))
7721 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
7723 /* Do the actual move after recomputing things, as this will have set the shape to
7724 the now correct one, thus avoiding copying regions that should not be copied. */
7725 impl_iface->move_resize (window, TRUE,
7726 private->x, private->y,
7727 private->width, private->height);
7729 else if (old_abs_x != private->abs_x ||
7730 old_abs_y != private->abs_y)
7731 move_native_children (private);
7735 new_region = gdk_region_copy (private->clip_region);
7736 /* Adjust region to parent window coords */
7737 gdk_region_offset (new_region, private->x, private->y);
7740 * Part of the data at the new location can be copied from the
7741 * old location, this area is the intersection of the old region
7742 * moved as the copy will move it and then intersected with
7746 * Everything in the old and new regions that is not copied must be
7747 * invalidated (including children) as this is newly exposed
7749 copy_area = gdk_region_copy (new_region);
7751 gdk_region_union (new_region, old_region);
7753 if (old_native_child_region)
7755 /* Don't copy from inside native children, as this is copied by
7756 * the native window move.
7758 gdk_region_subtract (old_region, old_native_child_region);
7760 gdk_region_offset (old_region, dx, dy);
7762 gdk_region_intersect (copy_area, old_region);
7764 if (new_native_child_region)
7766 /* Don't copy any bits that would cause a read from the moved
7767 native windows, as we can't read that data */
7768 gdk_region_offset (new_native_child_region, dx, dy);
7769 gdk_region_subtract (copy_area, new_native_child_region);
7770 gdk_region_offset (new_native_child_region, -dx, -dy);
7773 gdk_region_subtract (new_region, copy_area);
7775 /* Convert old region to impl coords */
7776 gdk_region_offset (old_region, -dx + private->abs_x - private->x, -dy + private->abs_y - private->y);
7778 /* convert from parent coords to impl */
7779 gdk_region_offset (copy_area, private->abs_x - private->x, private->abs_y - private->y);
7781 move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
7783 /* Invalidate affected part in the parent window
7784 * (no higher window should be affected)
7785 * We also invalidate any children in that area, which could include
7786 * this window if it still overlaps that area.
7788 if (old_native_child_region)
7790 /* No need to expose the region that the native window move copies */
7791 gdk_region_offset (old_native_child_region, dx, dy);
7792 gdk_region_intersect (old_native_child_region, new_native_child_region);
7793 gdk_region_subtract (new_region, old_native_child_region);
7795 gdk_window_invalidate_region_full (GDK_WINDOW (private->parent), new_region, TRUE, CLEAR_BG_ALL);
7797 gdk_region_destroy (old_region);
7798 gdk_region_destroy (new_region);
7801 if (old_native_child_region)
7803 gdk_region_destroy (old_native_child_region);
7804 gdk_region_destroy (new_native_child_region);
7807 _gdk_synthesize_crossing_events_for_geometry_change (window);
7814 * @window: a #GdkWindow
7815 * @x: X coordinate relative to window's parent
7816 * @y: Y coordinate relative to window's parent
7818 * Repositions a window relative to its parent window.
7819 * For toplevel windows, window managers may ignore or modify the move;
7820 * you should probably use gtk_window_move() on a #GtkWindow widget
7821 * anyway, instead of using GDK functions. For child windows,
7822 * the move will reliably succeed.
7824 * If you're also planning to resize the window, use gdk_window_move_resize()
7825 * to both move and resize simultaneously, for a nicer visual effect.
7828 gdk_window_move (GdkWindow *window,
7832 gdk_window_move_resize_internal (window, TRUE, x, y, -1, -1);
7836 * gdk_window_resize:
7837 * @window: a #GdkWindow
7838 * @width: new width of the window
7839 * @height: new height of the window
7841 * Resizes @window; for toplevel windows, asks the window manager to resize
7842 * the window. The window manager may not allow the resize. When using GTK+,
7843 * use gtk_window_resize() instead of this low-level GDK function.
7845 * Windows may not be resized below 1x1.
7847 * If you're also planning to move the window, use gdk_window_move_resize()
7848 * to both move and resize simultaneously, for a nicer visual effect.
7851 gdk_window_resize (GdkWindow *window,
7855 gdk_window_move_resize_internal (window, FALSE, 0, 0, width, height);
7860 * gdk_window_move_resize:
7861 * @window: a #GdkWindow
7862 * @x: new X position relative to window's parent
7863 * @y: new Y position relative to window's parent
7865 * @height: new height
7867 * Equivalent to calling gdk_window_move() and gdk_window_resize(),
7868 * except that both operations are performed at once, avoiding strange
7869 * visual effects. (i.e. the user may be able to see the window first
7870 * move, then resize, if you don't use gdk_window_move_resize().)
7873 gdk_window_move_resize (GdkWindow *window,
7879 gdk_window_move_resize_internal (window, TRUE, x, y, width, height);
7884 * gdk_window_scroll:
7885 * @window: a #GdkWindow
7886 * @dx: Amount to scroll in the X direction
7887 * @dy: Amount to scroll in the Y direction
7889 * Scroll the contents of @window, both pixels and children, by the
7890 * given amount. @window itself does not move. Portions of the window
7891 * that the scroll operation brings in from offscreen areas are
7892 * invalidated. The invalidated region may be bigger than what would
7893 * strictly be necessary.
7895 * For X11, a minimum area will be invalidated if the window has no
7896 * subwindows, or if the edges of the window's parent do not extend
7897 * beyond the edges of the window. In other cases, a multi-step process
7898 * is used to scroll the window which may produce temporary visual
7899 * artifacts and unnecessary invalidations.
7902 gdk_window_scroll (GdkWindow *window,
7906 GdkWindowObject *private = (GdkWindowObject *) window;
7907 GdkWindowObject *impl_window;
7908 GdkRegion *copy_area, *noncopy_area;
7909 GdkRegion *old_native_child_region, *new_native_child_region;
7912 g_return_if_fail (GDK_IS_WINDOW (window));
7914 if (dx == 0 && dy == 0)
7917 if (private->destroyed)
7920 gdk_window_flush_if_exposing (window);
7922 old_native_child_region = collect_native_child_region (private, FALSE);
7923 if (old_native_child_region)
7925 /* Any native window move will immediately copy stuff to the destination, which may overwrite a
7926 * source or destination for a delayed GdkWindowRegionMove. So, we need
7927 * to flush those here for the window and all overlapped subwindows
7928 * of it. And we need to do this before setting the new clips as those will be
7931 gdk_window_flush_recursive (private);
7935 /* First move all child windows, without causing invalidation */
7937 tmp_list = private->children;
7940 GdkWindow *child = GDK_WINDOW (tmp_list->data);
7941 GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
7943 /* Just update the positions, the bits will move with the copy */
7947 tmp_list = tmp_list->next;
7950 recompute_visible_regions (private, FALSE, TRUE);
7952 new_native_child_region = NULL;
7953 if (old_native_child_region)
7954 new_native_child_region = collect_native_child_region (private, FALSE);
7956 move_native_children (private);
7958 /* Then copy the actual bits of the window w/ child windows */
7960 impl_window = gdk_window_get_impl_window (private);
7962 /* Calculate the area that can be gotten by copying the old area */
7963 copy_area = gdk_region_copy (private->clip_region);
7964 if (old_native_child_region)
7966 /* Don't copy from inside native children, as this is copied by
7967 * the native window move.
7969 gdk_region_subtract (copy_area, old_native_child_region);
7971 /* Don't copy any bits that would cause a read from the moved
7972 native windows, as we can't read that data */
7973 gdk_region_subtract (copy_area, new_native_child_region);
7975 gdk_region_offset (copy_area, dx, dy);
7976 gdk_region_intersect (copy_area, private->clip_region);
7978 /* And the rest need to be invalidated */
7979 noncopy_area = gdk_region_copy (private->clip_region);
7980 gdk_region_subtract (noncopy_area, copy_area);
7982 /* convert from window coords to impl */
7983 gdk_region_offset (copy_area, private->abs_x, private->abs_y);
7985 move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
7987 /* Invalidate not copied regions */
7988 if (old_native_child_region)
7990 /* No need to expose the region that the native window move copies */
7991 gdk_region_offset (old_native_child_region, dx, dy);
7992 gdk_region_intersect (old_native_child_region, new_native_child_region);
7993 gdk_region_subtract (noncopy_area, old_native_child_region);
7995 gdk_window_invalidate_region_full (window, noncopy_area, TRUE, CLEAR_BG_ALL);
7997 gdk_region_destroy (noncopy_area);
7999 if (old_native_child_region)
8001 gdk_region_destroy (old_native_child_region);
8002 gdk_region_destroy (new_native_child_region);
8005 _gdk_synthesize_crossing_events_for_geometry_change (window);
8009 * gdk_window_move_region:
8010 * @window: a #GdkWindow
8011 * @region: The #GdkRegion to move
8012 * @dx: Amount to move in the X direction
8013 * @dy: Amount to move in the Y direction
8015 * Move the part of @window indicated by @region by @dy pixels in the Y
8016 * direction and @dx pixels in the X direction. The portions of @region
8017 * that not covered by the new position of @region are invalidated.
8019 * Child windows are not moved.
8024 gdk_window_move_region (GdkWindow *window,
8025 const GdkRegion *region,
8029 GdkWindowObject *private = (GdkWindowObject *) window;
8030 GdkWindowObject *impl_window;
8031 GdkRegion *nocopy_area;
8032 GdkRegion *copy_area;
8034 g_return_if_fail (GDK_IS_WINDOW (window));
8035 g_return_if_fail (region != NULL);
8037 if (dx == 0 && dy == 0)
8040 if (private->destroyed)
8043 impl_window = gdk_window_get_impl_window (private);
8045 /* compute source regions */
8046 copy_area = gdk_region_copy (region);
8047 gdk_region_intersect (copy_area, private->clip_region_with_children);
8049 /* compute destination regions */
8050 gdk_region_offset (copy_area, dx, dy);
8051 gdk_region_intersect (copy_area, private->clip_region_with_children);
8053 /* Invalidate parts of the region (source and dest) not covered
8055 nocopy_area = gdk_region_copy (region);
8056 gdk_region_offset (nocopy_area, dx, dy);
8057 gdk_region_union (nocopy_area, region);
8058 gdk_region_subtract (nocopy_area, copy_area);
8060 /* convert from window coords to impl */
8061 gdk_region_offset (copy_area, private->abs_x, private->abs_y);
8062 move_region_on_impl (impl_window, copy_area, dx, dy); /* Takes ownership of copy_area */
8064 gdk_window_invalidate_region_full (window, nocopy_area, FALSE, CLEAR_BG_ALL);
8065 gdk_region_destroy (nocopy_area);
8069 * gdk_window_get_background:
8070 * @window: a #GdkWindow.
8071 * @color: (out): a #GdkColor to be filled in
8073 * Sets @color to equal the current background color of @window.
8078 gdk_window_get_background (GdkWindow *window,
8081 GdkWindowObject *private;
8083 g_return_if_fail (GDK_IS_WINDOW (window));
8084 g_return_if_fail (color != NULL);
8086 private = (GdkWindowObject *) window;
8088 *color = private->bg_color;
8092 * gdk_window_set_background:
8093 * @window: a #GdkWindow
8094 * @color: an allocated #GdkColor
8096 * Sets the background color of @window. (However, when using GTK+,
8097 * set the background of a widget with gtk_widget_modify_bg() - if
8098 * you're an application - or gtk_style_set_background() - if you're
8099 * implementing a custom widget.)
8101 * The @color must be allocated; gdk_rgb_find_color() is the best way
8102 * to allocate a color.
8104 * See also gdk_window_set_background_pixmap().
8107 gdk_window_set_background (GdkWindow *window,
8108 const GdkColor *color)
8110 GdkWindowObject *private;
8111 GdkColormap *colormap = gdk_drawable_get_colormap (window);
8112 GdkWindowImplIface *impl_iface;
8114 g_return_if_fail (GDK_IS_WINDOW (window));
8116 private = (GdkWindowObject *) window;
8118 private->bg_color = *color;
8119 gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
8121 if (private->bg_pixmap &&
8122 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
8123 private->bg_pixmap != GDK_NO_BG)
8124 g_object_unref (private->bg_pixmap);
8126 private->bg_pixmap = NULL;
8128 if (!GDK_WINDOW_DESTROYED (window) &&
8129 gdk_window_has_impl (private) &&
8130 !private->input_only)
8132 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
8133 impl_iface->set_background (window, &private->bg_color);
8138 * gdk_window_get_back_pixmap:
8139 * @window: a #GdkWindow.
8140 * @pixmap: (out) (allow-none): a #GdkPixmap to be filled in, or %NULL.
8141 * @parent_relative: (out) (allow-none): a pointer to a #gboolean to be filled in, or %NULL.
8143 * Sets @pixmap to the current background pixmap of @window. You do not
8144 * own the pointer that is returned and this pointer should not be freeed
8145 * or unreferenced. Sets @parent_relative to %TRUE if the tiling is done
8146 * based on the origin of the parent window.
8151 gdk_window_get_back_pixmap (GdkWindow *window,
8153 gboolean *parent_relative)
8155 GdkWindowObject *private;
8157 g_return_if_fail (GDK_IS_WINDOW (window));
8159 private = (GdkWindowObject *) window;
8163 if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG ||
8164 private->bg_pixmap == GDK_NO_BG)
8167 *pixmap = private->bg_pixmap;
8170 if (parent_relative)
8171 *parent_relative = (private->bg_pixmap == GDK_PARENT_RELATIVE_BG);
8175 * gdk_window_set_back_pixmap:
8176 * @window: a #GdkWindow
8177 * @pixmap: (allow-none): a #GdkPixmap, or %NULL
8178 * @parent_relative: whether the tiling origin is at the origin of
8181 * Sets the background pixmap of @window. May also be used to set a
8182 * background of "None" on @window, by setting a background pixmap
8185 * A background pixmap will be tiled, positioning the first tile at
8186 * the origin of @window, or if @parent_relative is %TRUE, the tiling
8187 * will be done based on the origin of the parent window (useful to
8188 * align tiles in a parent with tiles in a child).
8190 * A background pixmap of %NULL means that the window will have no
8191 * background. A window with no background will never have its
8192 * background filled by the windowing system, instead the window will
8193 * contain whatever pixels were already in the corresponding area of
8196 * The windowing system will normally fill a window with its background
8197 * when the window is obscured then exposed, and when you call
8198 * gdk_window_clear().
8201 gdk_window_set_back_pixmap (GdkWindow *window,
8203 gboolean parent_relative)
8205 GdkWindowObject *private;
8206 GdkWindowImplIface *impl_iface;
8208 g_return_if_fail (GDK_IS_WINDOW (window));
8209 g_return_if_fail (pixmap == NULL || !parent_relative);
8210 g_return_if_fail (pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap));
8212 private = (GdkWindowObject *) window;
8214 if (pixmap && !gdk_drawable_get_colormap (pixmap))
8216 g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
8220 if (private->bg_pixmap &&
8221 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
8222 private->bg_pixmap != GDK_NO_BG)
8223 g_object_unref (private->bg_pixmap);
8225 if (parent_relative)
8226 private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
8228 private->bg_pixmap = g_object_ref (pixmap);
8230 private->bg_pixmap = GDK_NO_BG;
8232 if (!GDK_WINDOW_DESTROYED (window) &&
8233 gdk_window_has_impl (private) &&
8234 !private->input_only)
8236 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
8237 impl_iface->set_back_pixmap (window, private->bg_pixmap);
8242 update_cursor_foreach (GdkDisplay *display,
8244 GdkPointerWindowInfo *pointer_info,
8247 GdkWindow *window = user_data;
8248 GdkWindowObject *private = (GdkWindowObject *) window;
8250 if (_gdk_native_windows ||
8251 private->window_type == GDK_WINDOW_ROOT ||
8252 private->window_type == GDK_WINDOW_FOREIGN)
8253 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_device_cursor (window, device, private->cursor);
8254 else if (_gdk_window_event_parent_of (window, pointer_info->window_under_pointer))
8255 update_cursor (display, device);
8259 * gdk_window_get_cursor:
8260 * @window: a #GdkWindow
8262 * Retrieves a #GdkCursor pointer for the cursor currently set on the
8263 * specified #GdkWindow, or %NULL. If the return value is %NULL then
8264 * there is no custom cursor set on the specified window, and it is
8265 * using the cursor for its parent window.
8267 * Return value: a #GdkCursor, or %NULL. The returned object is owned
8268 * by the #GdkWindow and should not be unreferenced directly. Use
8269 * gdk_window_set_cursor() to unset the cursor of the window
8274 gdk_window_get_cursor (GdkWindow *window)
8276 GdkWindowObject *private;
8278 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
8280 private = (GdkWindowObject *) window;
8282 return private->cursor;
8286 * gdk_window_set_cursor:
8287 * @window: a #GdkWindow
8290 * Sets the default mouse pointer for a #GdkWindow. Use gdk_cursor_new_for_display()
8291 * or gdk_cursor_new_from_pixmap() to create the cursor. To make the cursor
8292 * invisible, use %GDK_BLANK_CURSOR. Passing %NULL for the @cursor argument
8293 * to gdk_window_set_cursor() means that @window will use the cursor of its
8294 * parent window. Most windows should use this default.
8297 gdk_window_set_cursor (GdkWindow *window,
8300 GdkWindowObject *private;
8301 GdkDisplay *display;
8303 g_return_if_fail (GDK_IS_WINDOW (window));
8305 private = (GdkWindowObject *) window;
8306 display = gdk_drawable_get_display (window);
8308 if (private->cursor)
8310 gdk_cursor_unref (private->cursor);
8311 private->cursor = NULL;
8314 if (!GDK_WINDOW_DESTROYED (window))
8317 private->cursor = gdk_cursor_ref (cursor);
8319 _gdk_display_pointer_info_foreach (display,
8320 update_cursor_foreach,
8323 g_object_notify (G_OBJECT (window), "cursor");
8328 * gdk_window_get_device_cursor:
8329 * @window: a #GdkWindow.
8330 * @device: a #GdkDevice.
8332 * Retrieves a #GdkCursor pointer for the @device currently set on the
8333 * specified #GdkWindow, or %NULL. If the return value is %NULL then
8334 * there is no custom cursor set on the specified window, and it is
8335 * using the cursor for its parent window.
8337 * Returns: a #GdkCursor, or %NULL. The returned object is owned
8338 * by the #GdkWindow and should not be unreferenced directly. Use
8339 * gdk_window_set_cursor() to unset the cursor of the window
8344 gdk_window_get_device_cursor (GdkWindow *window,
8347 GdkWindowObject *private;
8349 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
8350 g_return_val_if_fail (GDK_IS_DEVICE (device), NULL);
8352 private = (GdkWindowObject *) window;
8354 return g_hash_table_lookup (private->device_cursor, device);
8358 * gdk_window_set_device_cursor:
8359 * @window: a #Gdkwindow
8360 * @device: a #GdkDevice
8361 * @cursor: a #GdkCursor
8363 * Sets a specific #GdkCursor for a given device when it gets inside @window.
8364 * Use gdk_cursor_new_for_display() or gdk_cursor_new_from_pixmap() to create
8365 * the cursor. To make the cursor invisible, use %GDK_BLANK_CURSOR. Passing
8366 * %NULL for the @cursor argument to gdk_window_set_cursor() means that
8367 * @window will use the cursor of its parent window. Most windows should
8373 gdk_window_set_device_cursor (GdkWindow *window,
8377 GdkWindowObject *private;
8378 GdkDisplay *display;
8380 g_return_if_fail (GDK_IS_WINDOW (window));
8381 g_return_if_fail (GDK_IS_DEVICE (device));
8383 private = (GdkWindowObject *) window;
8384 display = gdk_drawable_get_display (window);
8387 g_hash_table_remove (private->device_cursor, device);
8389 g_hash_table_replace (private->device_cursor, device, cursor);
8391 if (!GDK_WINDOW_DESTROYED (window))
8393 GdkPointerWindowInfo *pointer_info;
8395 pointer_info = _gdk_display_get_pointer_info (display, device);
8397 if (_gdk_window_event_parent_of (window, pointer_info->window_under_pointer))
8398 update_cursor (display, device);
8403 * gdk_window_get_geometry:
8404 * @window: a #GdkWindow
8405 * @x: return location for X coordinate of window (relative to its parent)
8406 * @y: return location for Y coordinate of window (relative to its parent)
8407 * @width: return location for width of window
8408 * @height: return location for height of window
8409 * @depth: return location for bit depth of window
8411 * Any of the return location arguments to this function may be %NULL,
8412 * if you aren't interested in getting the value of that field.
8414 * The X and Y coordinates returned are relative to the parent window
8415 * of @window, which for toplevels usually means relative to the
8416 * window decorations (titlebar, etc.) rather than relative to the
8417 * root window (screen-size background window).
8419 * On the X11 platform, the geometry is obtained from the X server,
8420 * so reflects the latest position of @window; this may be out-of-sync
8421 * with the position of @window delivered in the most-recently-processed
8422 * #GdkEventConfigure. gdk_window_get_position() in contrast gets the
8423 * position from the most recent configure event.
8426 * If @window is not a toplevel, it is <emphasis>much</emphasis> better
8427 * to call gdk_window_get_position() and gdk_drawable_get_size() instead,
8428 * because it avoids the roundtrip to the X server and because
8429 * gdk_drawable_get_size() supports the full 32-bit coordinate space,
8430 * whereas gdk_window_get_geometry() is restricted to the 16-bit
8431 * coordinates of X11.
8435 gdk_window_get_geometry (GdkWindow *window,
8442 GdkWindowObject *private, *parent;
8443 GdkWindowImplIface *impl_iface;
8447 GDK_NOTE (MULTIHEAD,
8448 g_message ("gdk_window_get_geometry(): Window needs "
8449 "to be non-NULL to be multi head safe"));
8450 window = gdk_screen_get_root_window ((gdk_screen_get_default ()));
8453 g_return_if_fail (GDK_IS_WINDOW (window));
8455 private = (GdkWindowObject *) window;
8457 if (!GDK_WINDOW_DESTROYED (window))
8459 if (gdk_window_has_impl (private))
8461 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
8462 impl_iface->get_geometry (window, x, y,
8465 /* This reports the position wrt to the native parent, we need to convert
8466 it to be relative to the client side parent */
8467 parent = private->parent;
8468 if (parent && !gdk_window_has_impl (parent))
8471 *x -= parent->abs_x;
8473 *y -= parent->abs_y;
8483 *width = private->width;
8485 *height = private->height;
8487 *depth = private->depth;
8493 * gdk_window_get_origin:
8494 * @window: a #GdkWindow
8495 * @x: return location for X coordinate
8496 * @y: return location for Y coordinate
8498 * Obtains the position of a window in root window coordinates.
8499 * (Compare with gdk_window_get_position() and
8500 * gdk_window_get_geometry() which return the position of a window
8501 * relative to its parent window.)
8503 * Return value: not meaningful, ignore
8506 gdk_window_get_origin (GdkWindow *window,
8510 GdkWindowObject *private;
8511 GdkWindowImplIface *impl_iface;
8513 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
8515 if (GDK_WINDOW_DESTROYED (window))
8524 private = (GdkWindowObject *) window;
8526 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
8527 impl_iface->get_root_coords (window,
8536 * gdk_window_get_root_coords:
8537 * @window: a #GdkWindow
8538 * @x: X coordinate in window
8539 * @y: Y coordinate in window
8540 * @root_x: return location for X coordinate
8541 * @root_y: return location for Y coordinate
8543 * Obtains the position of a window position in root
8544 * window coordinates. This is similar to
8545 * gdk_window_get_origin() but allows you go pass
8546 * in any position in the window, not just the origin.
8551 gdk_window_get_root_coords (GdkWindow *window,
8557 GdkWindowObject *private;
8558 GdkWindowImplIface *impl_iface;
8560 g_return_if_fail (GDK_IS_WINDOW (window));
8562 private = (GdkWindowObject *) window;
8564 if (GDK_WINDOW_DESTROYED (window))
8573 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
8574 impl_iface->get_root_coords (window,
8581 * gdk_window_coords_to_parent:
8582 * @window: a child window
8583 * @x: X coordinate in child's coordinate system
8584 * @y: Y coordinate in child's coordinate system
8585 * @parent_x: (out) (allow-none): return location for X coordinate
8586 * in parent's coordinate system, or %NULL
8587 * @parent_y: (out) (allow-none): return location for Y coordinate
8588 * in parent's coordinate system, or %NULL
8590 * Transforms window coordinates from a child window to its parent
8591 * window, where the parent window is the normal parent as returned by
8592 * gdk_window_get_parent() for normal windows, and the window's
8593 * embedder as returned by gdk_offscreen_window_get_embedder() for
8594 * offscreen windows.
8596 * For normal windows, calling this function is equivalent to adding
8597 * the return values of gdk_window_get_position() to the child coordinates.
8598 * For offscreen windows however (which can be arbitrarily transformed),
8599 * this function calls the GdkWindow::to-embedder: signal to translate
8602 * You should always use this function when writing generic code that
8603 * walks up a window hierarchy.
8605 * See also: gdk_window_coords_from_parent()
8610 gdk_window_coords_to_parent (GdkWindow *window,
8616 GdkWindowObject *obj;
8618 g_return_if_fail (GDK_IS_WINDOW (window));
8620 obj = (GdkWindowObject *) window;
8622 if (gdk_window_is_offscreen (obj))
8626 to_embedder (obj, x, y, &px, &py);
8637 *parent_x = x + obj->x;
8640 *parent_y = y + obj->y;
8645 * gdk_window_coords_from_parent:
8646 * @window: a child window
8647 * @parent_x: X coordinate in parent's coordinate system
8648 * @parent_y: Y coordinate in parent's coordinate system
8649 * @x: (out) (allow-none): return location for X coordinate in child's coordinate system
8650 * @y: (out) (allow-none): return location for Y coordinate in child's coordinate system
8652 * Transforms window coordinates from a parent window to a child
8653 * window, where the parent window is the normal parent as returned by
8654 * gdk_window_get_parent() for normal windows, and the window's
8655 * embedder as returned by gdk_offscreen_window_get_embedder() for
8656 * offscreen windows.
8658 * For normal windows, calling this function is equivalent to subtracting
8659 * the return values of gdk_window_get_position() from the parent coordinates.
8660 * For offscreen windows however (which can be arbitrarily transformed),
8661 * this function calls the GdkWindow::from-embedder: signal to translate
8664 * You should always use this function when writing generic code that
8665 * walks down a window hierarchy.
8667 * See also: gdk_window_coords_to_parent()
8672 gdk_window_coords_from_parent (GdkWindow *window,
8678 GdkWindowObject *obj;
8680 g_return_if_fail (GDK_IS_WINDOW (window));
8682 obj = (GdkWindowObject *) window;
8684 if (gdk_window_is_offscreen (obj))
8688 from_embedder (obj, parent_x, parent_y, &cx, &cy);
8699 *x = parent_x - obj->x;
8702 *y = parent_y - obj->y;
8707 * gdk_window_get_deskrelative_origin:
8708 * @window: a toplevel #GdkWindow
8709 * @x: return location for X coordinate
8710 * @y: return location for Y coordinate
8712 * This gets the origin of a #GdkWindow relative to
8713 * an Enlightenment-window-manager desktop. As long as you don't
8714 * assume that the user's desktop/workspace covers the entire
8715 * root window (i.e. you don't assume that the desktop begins
8716 * at root window coordinate 0,0) this function is not necessary.
8717 * It's deprecated for that reason.
8719 * Return value: not meaningful
8722 gdk_window_get_deskrelative_origin (GdkWindow *window,
8726 GdkWindowObject *private;
8727 GdkWindowImplIface *impl_iface;
8728 gboolean return_val = FALSE;
8732 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
8734 private = (GdkWindowObject *) window;
8736 if (!GDK_WINDOW_DESTROYED (window))
8738 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
8739 return_val = impl_iface->get_deskrelative_origin (window, &tx, &ty);
8742 *x = tx + private->abs_x;
8744 *y = ty + private->abs_y;
8751 * gdk_window_shape_combine_mask:
8752 * @window: a #GdkWindow
8754 * @x: X position of shape mask with respect to @window
8755 * @y: Y position of shape mask with respect to @window
8757 * Applies a shape mask to @window. Pixels in @window corresponding to
8758 * set bits in the @mask will be visible; pixels in @window
8759 * corresponding to unset bits in the @mask will be transparent. This
8760 * gives a non-rectangular window.
8762 * If @mask is %NULL, the shape mask will be unset, and the @x/@y
8763 * parameters are not used.
8765 * On the X11 platform, this uses an X server extension which is
8766 * widely available on most common platforms, but not available on
8767 * very old X servers, and occasionally the implementation will be
8768 * buggy. On servers without the shape extension, this function
8771 * This function works on both toplevel and child windows.
8774 gdk_window_shape_combine_mask (GdkWindow *window,
8779 GdkWindowObject *private;
8782 g_return_if_fail (GDK_IS_WINDOW (window));
8784 private = (GdkWindowObject *) window;
8787 region = _gdk_windowing_get_shape_for_mask (mask);
8791 gdk_window_shape_combine_region (window,
8796 gdk_region_destroy (region);
8800 * gdk_window_shape_combine_region:
8801 * @window: a #GdkWindow
8802 * @shape_region: region of window to be non-transparent
8803 * @offset_x: X position of @shape_region in @window coordinates
8804 * @offset_y: Y position of @shape_region in @window coordinates
8806 * Makes pixels in @window outside @shape_region be transparent,
8807 * so that the window may be nonrectangular. See also
8808 * gdk_window_shape_combine_mask() to use a bitmap as the mask.
8810 * If @shape_region is %NULL, the shape will be unset, so the whole
8811 * window will be opaque again. @offset_x and @offset_y are ignored
8812 * if @shape_region is %NULL.
8814 * On the X11 platform, this uses an X server extension which is
8815 * widely available on most common platforms, but not available on
8816 * very old X servers, and occasionally the implementation will be
8817 * buggy. On servers without the shape extension, this function
8820 * This function works on both toplevel and child windows.
8823 gdk_window_shape_combine_region (GdkWindow *window,
8824 const GdkRegion *shape_region,
8828 GdkWindowObject *private;
8829 GdkRegion *old_region, *new_region, *diff;
8831 g_return_if_fail (GDK_IS_WINDOW (window));
8833 private = (GdkWindowObject *) window;
8835 if (GDK_WINDOW_DESTROYED (window))
8838 private->shaped = (shape_region != NULL);
8841 gdk_region_destroy (private->shape);
8844 if (GDK_WINDOW_IS_MAPPED (window))
8845 old_region = gdk_region_copy (private->clip_region);
8849 private->shape = gdk_region_copy (shape_region);
8850 gdk_region_offset (private->shape, offset_x, offset_y);
8853 private->shape = NULL;
8855 recompute_visible_regions (private, TRUE, FALSE);
8857 if (gdk_window_has_impl (private) &&
8858 !should_apply_clip_as_shape (private))
8859 apply_shape (private, private->shape);
8863 new_region = gdk_region_copy (private->clip_region);
8865 /* New area in the window, needs invalidation */
8866 diff = gdk_region_copy (new_region);
8867 gdk_region_subtract (diff, old_region);
8869 gdk_window_invalidate_region_full (window, diff, TRUE, CLEAR_BG_ALL);
8871 gdk_region_destroy (diff);
8873 if (!gdk_window_is_toplevel (private))
8875 /* New area in the non-root parent window, needs invalidation */
8876 diff = gdk_region_copy (old_region);
8877 gdk_region_subtract (diff, new_region);
8879 /* Adjust region to parent window coords */
8880 gdk_region_offset (diff, private->x, private->y);
8882 gdk_window_invalidate_region_full (GDK_WINDOW (private->parent), diff, TRUE, CLEAR_BG_ALL);
8884 gdk_region_destroy (diff);
8887 gdk_region_destroy (new_region);
8888 gdk_region_destroy (old_region);
8893 do_child_shapes (GdkWindow *window,
8896 GdkWindowObject *private;
8900 private = (GdkWindowObject *) window;
8904 r.width = private->width;
8905 r.height = private->height;
8907 region = gdk_region_rectangle (&r);
8908 remove_child_area (private, NULL, FALSE, region);
8910 if (merge && private->shape)
8911 gdk_region_subtract (region, private->shape);
8913 gdk_window_shape_combine_region (window, region, 0, 0);
8917 * gdk_window_set_child_shapes:
8918 * @window: a #GdkWindow
8920 * Sets the shape mask of @window to the union of shape masks
8921 * for all children of @window, ignoring the shape mask of @window
8922 * itself. Contrast with gdk_window_merge_child_shapes() which includes
8923 * the shape mask of @window in the masks to be merged.
8926 gdk_window_set_child_shapes (GdkWindow *window)
8928 g_return_if_fail (GDK_IS_WINDOW (window));
8930 do_child_shapes (window, FALSE);
8934 * gdk_window_merge_child_shapes:
8935 * @window: a #GdkWindow
8937 * Merges the shape masks for any child windows into the
8938 * shape mask for @window. i.e. the union of all masks
8939 * for @window and its children will become the new mask
8940 * for @window. See gdk_window_shape_combine_mask().
8942 * This function is distinct from gdk_window_set_child_shapes()
8943 * because it includes @window's shape mask in the set of shapes to
8947 gdk_window_merge_child_shapes (GdkWindow *window)
8949 g_return_if_fail (GDK_IS_WINDOW (window));
8951 do_child_shapes (window, TRUE);
8955 * gdk_window_input_shape_combine_mask:
8956 * @window: a #GdkWindow
8957 * @mask: (allow-none): shape mask, or %NULL
8958 * @x: X position of shape mask with respect to @window
8959 * @y: Y position of shape mask with respect to @window
8961 * Like gdk_window_shape_combine_mask(), but the shape applies
8962 * only to event handling. Mouse events which happen while
8963 * the pointer position corresponds to an unset bit in the
8964 * mask will be passed on the window below @window.
8966 * An input shape is typically used with RGBA windows.
8967 * The alpha channel of the window defines which pixels are
8968 * invisible and allows for nicely antialiased borders,
8969 * and the input shape controls where the window is
8972 * On the X11 platform, this requires version 1.1 of the
8975 * On the Win32 platform, this functionality is not present and the
8976 * function does nothing.
8981 gdk_window_input_shape_combine_mask (GdkWindow *window,
8986 GdkWindowObject *private;
8989 g_return_if_fail (GDK_IS_WINDOW (window));
8991 private = (GdkWindowObject *) window;
8994 region = _gdk_windowing_get_shape_for_mask (mask);
8998 gdk_window_input_shape_combine_region (window,
9003 gdk_region_destroy (region);
9007 * gdk_window_input_shape_combine_region:
9008 * @window: a #GdkWindow
9009 * @shape_region: region of window to be non-transparent
9010 * @offset_x: X position of @shape_region in @window coordinates
9011 * @offset_y: Y position of @shape_region in @window coordinates
9013 * Like gdk_window_shape_combine_region(), but the shape applies
9014 * only to event handling. Mouse events which happen while
9015 * the pointer position corresponds to an unset bit in the
9016 * mask will be passed on the window below @window.
9018 * An input shape is typically used with RGBA windows.
9019 * The alpha channel of the window defines which pixels are
9020 * invisible and allows for nicely antialiased borders,
9021 * and the input shape controls where the window is
9024 * On the X11 platform, this requires version 1.1 of the
9027 * On the Win32 platform, this functionality is not present and the
9028 * function does nothing.
9033 gdk_window_input_shape_combine_region (GdkWindow *window,
9034 const GdkRegion *shape_region,
9038 GdkWindowObject *private;
9039 GdkWindowImplIface *impl_iface;
9041 g_return_if_fail (GDK_IS_WINDOW (window));
9043 private = (GdkWindowObject *) window;
9045 if (GDK_WINDOW_DESTROYED (window))
9048 if (private->input_shape)
9049 gdk_region_destroy (private->input_shape);
9053 private->input_shape = gdk_region_copy (shape_region);
9054 gdk_region_offset (private->input_shape, offset_x, offset_y);
9057 private->input_shape = NULL;
9059 if (gdk_window_has_impl (private))
9061 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
9062 impl_iface->input_shape_combine_region (window, private->input_shape, 0, 0);
9065 /* Pointer may have e.g. moved outside window due to the input mask change */
9066 _gdk_synthesize_crossing_events_for_geometry_change (window);
9070 do_child_input_shapes (GdkWindow *window,
9073 GdkWindowObject *private;
9077 private = (GdkWindowObject *) window;
9081 r.width = private->width;
9082 r.height = private->height;
9084 region = gdk_region_rectangle (&r);
9085 remove_child_area (private, NULL, TRUE, region);
9087 if (merge && private->shape)
9088 gdk_region_subtract (region, private->shape);
9089 if (merge && private->input_shape)
9090 gdk_region_subtract (region, private->input_shape);
9092 gdk_window_input_shape_combine_region (window, region, 0, 0);
9097 * gdk_window_set_child_input_shapes:
9098 * @window: a #GdkWindow
9100 * Sets the input shape mask of @window to the union of input shape masks
9101 * for all children of @window, ignoring the input shape mask of @window
9102 * itself. Contrast with gdk_window_merge_child_input_shapes() which includes
9103 * the input shape mask of @window in the masks to be merged.
9108 gdk_window_set_child_input_shapes (GdkWindow *window)
9110 g_return_if_fail (GDK_IS_WINDOW (window));
9112 do_child_input_shapes (window, FALSE);
9116 * gdk_window_merge_child_input_shapes:
9117 * @window: a #GdkWindow
9119 * Merges the input shape masks for any child windows into the
9120 * input shape mask for @window. i.e. the union of all input masks
9121 * for @window and its children will become the new input mask
9122 * for @window. See gdk_window_input_shape_combine_mask().
9124 * This function is distinct from gdk_window_set_child_input_shapes()
9125 * because it includes @window's input shape mask in the set of
9126 * shapes to be merged.
9131 gdk_window_merge_child_input_shapes (GdkWindow *window)
9133 g_return_if_fail (GDK_IS_WINDOW (window));
9135 do_child_input_shapes (window, TRUE);
9140 * gdk_window_set_static_gravities:
9141 * @window: a #GdkWindow
9142 * @use_static: %TRUE to turn on static gravity
9144 * Set the bit gravity of the given window to static, and flag it so
9145 * all children get static subwindow gravity. This is used if you are
9146 * implementing scary features that involve deep knowledge of the
9147 * windowing system. Don't worry about it unless you have to.
9149 * Return value: %TRUE if the server supports static gravity
9152 gdk_window_set_static_gravities (GdkWindow *window,
9153 gboolean use_static)
9155 GdkWindowObject *private;
9156 GdkWindowImplIface *impl_iface;
9158 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
9160 private = (GdkWindowObject *) window;
9162 if (gdk_window_has_impl (private))
9164 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
9165 return impl_iface->set_static_gravities (window, use_static);
9172 * gdk_window_get_composited:
9173 * @window: a #GdkWindow
9175 * Determines whether @window is composited.
9177 * See gdk_window_set_composited().
9179 * Returns: %TRUE if the window is composited.
9184 gdk_window_get_composited (GdkWindow *window)
9186 GdkWindowObject *private;
9188 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
9190 private = (GdkWindowObject *)window;
9192 return private->composited;
9196 * gdk_window_set_composited:
9197 * @window: a #GdkWindow
9198 * @composited: %TRUE to set the window as composited
9200 * Sets a #GdkWindow as composited, or unsets it. Composited
9201 * windows do not automatically have their contents drawn to
9202 * the screen. Drawing is redirected to an offscreen buffer
9203 * and an expose event is emitted on the parent of the composited
9204 * window. It is the responsibility of the parent's expose handler
9205 * to manually merge the off-screen content onto the screen in
9206 * whatever way it sees fit. See <xref linkend="composited-window-example"/>
9209 * It only makes sense for child windows to be composited; see
9210 * gdk_window_set_opacity() if you need translucent toplevel
9213 * An additional effect of this call is that the area of this
9214 * window is no longer clipped from regions marked for
9215 * invalidation on its parent. Draws done on the parent
9216 * window are also no longer clipped by the child.
9218 * This call is only supported on some systems (currently,
9219 * only X11 with new enough Xcomposite and Xdamage extensions).
9220 * You must call gdk_display_supports_composite() to check if
9221 * setting a window as composited is supported before
9222 * attempting to do so.
9227 gdk_window_set_composited (GdkWindow *window,
9228 gboolean composited)
9230 GdkWindowObject *private = (GdkWindowObject *)window;
9231 GdkDisplay *display;
9233 g_return_if_fail (GDK_IS_WINDOW (window));
9235 composited = composited != FALSE;
9237 if (private->composited == composited)
9241 gdk_window_ensure_native (window);
9243 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
9245 if (!gdk_display_supports_composite (display) && composited)
9247 g_warning ("gdk_window_set_composited called but "
9248 "compositing is not supported");
9252 _gdk_windowing_window_set_composited (window, composited);
9254 recompute_visible_regions (private, TRUE, FALSE);
9256 if (GDK_WINDOW_IS_MAPPED (window))
9257 gdk_window_invalidate_in_parent (private);
9259 private->composited = composited;
9264 remove_redirect_from_children (GdkWindowObject *private,
9265 GdkWindowRedirect *redirect)
9268 GdkWindowObject *child;
9270 for (l = private->children; l != NULL; l = l->next)
9274 /* Don't redirect this child if it already has another redirect */
9275 if (child->redirect == redirect)
9277 child->redirect = NULL;
9278 remove_redirect_from_children (child, redirect);
9284 * gdk_window_remove_redirection:
9285 * @window: a #GdkWindow
9287 * Removes any active redirection started by
9288 * gdk_window_redirect_to_drawable().
9293 gdk_window_remove_redirection (GdkWindow *window)
9295 GdkWindowObject *private;
9297 g_return_if_fail (GDK_IS_WINDOW (window));
9299 private = (GdkWindowObject *) window;
9301 if (private->redirect &&
9302 private->redirect->redirected == private)
9304 remove_redirect_from_children (private, private->redirect);
9305 gdk_window_redirect_free (private->redirect);
9306 private->redirect = NULL;
9311 * gdk_window_get_modal_hint:
9312 * @window: A toplevel #GdkWindow.
9314 * Determines whether or not the window manager is hinted that @window
9315 * has modal behaviour.
9317 * Return value: whether or not the window has the modal hint set.
9322 gdk_window_get_modal_hint (GdkWindow *window)
9324 GdkWindowObject *private;
9326 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
9328 private = (GdkWindowObject*) window;
9330 return private->modal_hint;
9334 * gdk_window_get_accept_focus:
9335 * @window: a toplevel #GdkWindow.
9337 * Determines whether or not the desktop environment shuld be hinted that
9338 * the window does not want to receive input focus.
9340 * Return value: whether or not the window should receive input focus.
9345 gdk_window_get_accept_focus (GdkWindow *window)
9347 GdkWindowObject *private;
9349 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
9351 private = (GdkWindowObject *)window;
9353 return private->accept_focus;
9357 * gdk_window_get_focus_on_map:
9358 * @window: a toplevel #GdkWindow.
9360 * Determines whether or not the desktop environment should be hinted that the
9361 * window does not want to receive input focus when it is mapped.
9363 * Return value: whether or not the window wants to receive input focus when
9369 gdk_window_get_focus_on_map (GdkWindow *window)
9371 GdkWindowObject *private;
9373 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
9375 private = (GdkWindowObject *)window;
9377 return private->focus_on_map;
9381 * gdk_window_is_input_only:
9382 * @window: a toplevel #GdkWindow
9384 * Determines whether or not the window is an input only window.
9386 * Return value: %TRUE if @window is input only
9391 gdk_window_is_input_only (GdkWindow *window)
9393 GdkWindowObject *private;
9395 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
9397 private = (GdkWindowObject *)window;
9399 return private->input_only;
9403 * gdk_window_is_shaped:
9404 * @window: a toplevel #GdkWindow
9406 * Determines whether or not the window is shaped.
9408 * Return value: %TRUE if @window is shaped
9413 gdk_window_is_shaped (GdkWindow *window)
9415 GdkWindowObject *private;
9417 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
9419 private = (GdkWindowObject *)window;
9421 return private->shaped;
9425 apply_redirect_to_children (GdkWindowObject *private,
9426 GdkWindowRedirect *redirect)
9429 GdkWindowObject *child;
9431 for (l = private->children; l != NULL; l = l->next)
9435 /* Don't redirect this child if it already has another redirect */
9436 if (!child->redirect)
9438 child->redirect = redirect;
9439 apply_redirect_to_children (child, redirect);
9445 * gdk_window_redirect_to_drawable:
9446 * @window: a #GdkWindow
9447 * @drawable: a #GdkDrawable
9448 * @src_x: x position in @window
9449 * @src_y: y position in @window
9450 * @dest_x: x position in @drawable
9451 * @dest_y: y position in @drawable
9452 * @width: width of redirection, or -1 to use the width of @window
9453 * @height: height of redirection or -1 to use the height of @window
9455 * Redirects drawing into @window so that drawing to the
9456 * window in the rectangle specified by @src_x, @src_y,
9457 * @width and @height is also drawn into @drawable at
9460 * Only drawing between gdk_window_begin_paint_region() or
9461 * gdk_window_begin_paint_rect() and gdk_window_end_paint() is
9464 * Redirection is active until gdk_window_remove_redirection()
9470 gdk_window_redirect_to_drawable (GdkWindow *window,
9471 GdkDrawable *drawable,
9479 GdkWindowObject *private;
9481 g_return_if_fail (GDK_IS_WINDOW (window));
9482 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
9483 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
9485 private = (GdkWindowObject *) window;
9487 if (private->redirect)
9488 gdk_window_remove_redirection (window);
9490 if (width == -1 || height == -1)
9493 gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
9500 private->redirect = g_new0 (GdkWindowRedirect, 1);
9501 private->redirect->redirected = private;
9502 private->redirect->pixmap = g_object_ref (drawable);
9503 private->redirect->src_x = src_x;
9504 private->redirect->src_y = src_y;
9505 private->redirect->dest_x = dest_x;
9506 private->redirect->dest_y = dest_y;
9507 private->redirect->width = width;
9508 private->redirect->height = height;
9510 apply_redirect_to_children (private, private->redirect);
9514 window_get_size_rectangle (GdkWindow *window,
9517 GdkWindowObject *private = (GdkWindowObject *) window;
9519 rect->x = rect->y = 0;
9520 rect->width = private->width;
9521 rect->height = private->height;
9524 /* Calculates the real clipping region for a window, in window coordinates,
9525 * taking into account other windows, gc clip region and gc clip mask.
9528 _gdk_window_calculate_full_clip_region (GdkWindow *window,
9529 GdkWindow *base_window,
9530 gboolean do_children,
9531 gint *base_x_offset,
9532 gint *base_y_offset)
9534 GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
9535 GdkRectangle visible_rect;
9536 GdkRegion *real_clip_region, *tmpreg;
9537 gint x_offset, y_offset;
9538 GdkWindowObject *parentwin, *lastwin;
9545 if (!private->viewable || private->input_only)
9546 return gdk_region_new ();
9548 window_get_size_rectangle (window, &visible_rect);
9550 /* real_clip_region is in window coordinates */
9551 real_clip_region = gdk_region_rectangle (&visible_rect);
9553 x_offset = y_offset = 0;
9557 parentwin = lastwin;
9559 parentwin = lastwin->parent;
9561 /* Remove the areas of all overlapping windows above parentwin in the hiearachy */
9562 for (; parentwin != NULL &&
9563 (parentwin == private || lastwin != (GdkWindowObject*) base_window);
9564 lastwin = parentwin, parentwin = lastwin->parent)
9567 GdkRectangle real_clip_rect;
9569 if (parentwin != private)
9571 x_offset += GDK_WINDOW_OBJECT (lastwin)->x;
9572 y_offset += GDK_WINDOW_OBJECT (lastwin)->y;
9575 /* children is ordered in reverse stack order */
9576 for (cur = parentwin->children;
9577 cur && cur->data != lastwin;
9580 GdkWindow *child = cur->data;
9581 GdkWindowObject *child_private = (GdkWindowObject *)child;
9583 if (!GDK_WINDOW_IS_MAPPED (child) || child_private->input_only)
9586 /* Ignore offscreen children, as they don't draw in their parent and
9587 * don't take part in the clipping */
9588 if (gdk_window_is_offscreen (child_private))
9591 window_get_size_rectangle (child, &visible_rect);
9593 /* Convert rect to "window" coords */
9594 visible_rect.x += child_private->x - x_offset;
9595 visible_rect.y += child_private->y - y_offset;
9597 /* This shortcut is really necessary for performance when there are a lot of windows */
9598 gdk_region_get_clipbox (real_clip_region, &real_clip_rect);
9599 if (visible_rect.x >= real_clip_rect.x + real_clip_rect.width ||
9600 visible_rect.x + visible_rect.width <= real_clip_rect.x ||
9601 visible_rect.y >= real_clip_rect.y + real_clip_rect.height ||
9602 visible_rect.y + visible_rect.height <= real_clip_rect.y)
9605 tmpreg = gdk_region_rectangle (&visible_rect);
9606 gdk_region_subtract (real_clip_region, tmpreg);
9607 gdk_region_destroy (tmpreg);
9610 /* Clip to the parent */
9611 window_get_size_rectangle ((GdkWindow *)parentwin, &visible_rect);
9612 /* Convert rect to "window" coords */
9613 visible_rect.x += - x_offset;
9614 visible_rect.y += - y_offset;
9616 tmpreg = gdk_region_rectangle (&visible_rect);
9617 gdk_region_intersect (real_clip_region, tmpreg);
9618 gdk_region_destroy (tmpreg);
9622 *base_x_offset = x_offset;
9624 *base_y_offset = y_offset;
9626 return real_clip_region;
9630 _gdk_window_add_damage (GdkWindow *toplevel,
9631 GdkRegion *damaged_region)
9633 GdkDisplay *display;
9634 GdkEvent event = { 0, };
9635 event.expose.type = GDK_DAMAGE;
9636 event.expose.window = toplevel;
9637 event.expose.send_event = FALSE;
9638 event.expose.region = damaged_region;
9639 gdk_region_get_clipbox (event.expose.region, &event.expose.area);
9640 display = gdk_drawable_get_display (event.expose.window);
9641 _gdk_event_queue_append (display, gdk_event_copy (&event));
9645 gdk_window_redirect_free (GdkWindowRedirect *redirect)
9647 g_object_unref (redirect->pixmap);
9651 /* Gets the toplevel for a window as used for events,
9652 i.e. including offscreen parents */
9653 static GdkWindowObject *
9654 get_event_parent (GdkWindowObject *window)
9656 if (gdk_window_is_offscreen (window))
9657 return (GdkWindowObject *)gdk_offscreen_window_get_embedder ((GdkWindow *)window);
9659 return window->parent;
9662 /* Gets the toplevel for a window as used for events,
9663 i.e. including offscreen parents going up to the native
9666 get_event_toplevel (GdkWindow *w)
9668 GdkWindowObject *private = GDK_WINDOW_OBJECT (w);
9669 GdkWindowObject *parent;
9671 while ((parent = get_event_parent (private)) != NULL &&
9672 (parent->window_type != GDK_WINDOW_ROOT))
9675 return GDK_WINDOW (private);
9679 _gdk_window_event_parent_of (GdkWindow *parent,
9690 w = (GdkWindow *)get_event_parent ((GdkWindowObject *)w);
9697 update_cursor (GdkDisplay *display,
9700 GdkWindowObject *cursor_window, *parent, *toplevel;
9701 GdkWindow *pointer_window;
9702 GdkWindowImplIface *impl_iface;
9703 GdkPointerWindowInfo *pointer_info;
9704 GdkDeviceGrabInfo *grab;
9706 pointer_info = _gdk_display_get_pointer_info (display, device);
9707 pointer_window = pointer_info->window_under_pointer;
9709 /* We ignore the serials here and just pick the last grab
9710 we've sent, as that would shortly be used anyway. */
9711 grab = _gdk_display_get_last_device_grab (display, device);
9714 /* the pointer is not in a descendant of the grab window */
9715 !_gdk_window_event_parent_of (grab->window, pointer_window))
9717 /* use the cursor from the grab window */
9718 cursor_window = (GdkWindowObject *) grab->window;
9722 /* otherwise use the cursor from the pointer window */
9723 cursor_window = (GdkWindowObject *) pointer_window;
9726 /* Find the first window with the cursor actually set, as
9727 the cursor is inherited from the parent */
9728 while (cursor_window->cursor == NULL &&
9729 (parent = get_event_parent (cursor_window)) != NULL &&
9730 parent->window_type != GDK_WINDOW_ROOT)
9731 cursor_window = parent;
9733 /* Set all cursors on toplevel, otherwise its tricky to keep track of
9734 * which native window has what cursor set. */
9735 toplevel = (GdkWindowObject *) get_event_toplevel (pointer_window);
9736 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (toplevel->impl);
9737 impl_iface->set_device_cursor ((GdkWindow *) toplevel, device,
9738 cursor_window->cursor);
9742 point_in_window (GdkWindowObject *window,
9747 x >= 0 && x < window->width &&
9748 y >= 0 && y < window->height &&
9749 (window->shape == NULL ||
9750 gdk_region_point_in (window->shape,
9752 (window->input_shape == NULL ||
9753 gdk_region_point_in (window->input_shape,
9758 convert_native_coords_to_toplevel (GdkWindow *window,
9761 gdouble *toplevel_x,
9762 gdouble *toplevel_y)
9764 GdkWindowObject *private = (GdkWindowObject *)window;
9770 while (!gdk_window_is_toplevel (private))
9774 private = private->parent;
9780 return (GdkWindow *)private;
9784 convert_toplevel_coords_to_window (GdkWindow *window,
9790 GdkWindowObject *private;
9791 GdkWindowObject *parent;
9793 GList *children, *l;
9795 private = GDK_WINDOW_OBJECT (window);
9801 while ((parent = get_event_parent (private)) != NULL &&
9802 (parent->window_type != GDK_WINDOW_ROOT))
9804 children = g_list_prepend (children, private);
9808 for (l = children; l != NULL; l = l->next)
9809 gdk_window_coords_from_parent (l->data, x, y, &x, &y);
9811 g_list_free (children);
9817 static GdkWindowObject *
9818 pick_embedded_child (GdkWindowObject *window,
9822 GdkWindowObject *res;
9825 g_signal_emit (window,
9826 signals[PICK_EMBEDDED_CHILD], 0,
9833 _gdk_window_find_child_at (GdkWindow *window,
9837 GdkWindowObject *private, *sub;
9838 double child_x, child_y;
9841 private = (GdkWindowObject *)window;
9843 if (point_in_window (private, x, y))
9845 /* Children is ordered in reverse stack order, i.e. first is topmost */
9846 for (l = private->children; l != NULL; l = l->next)
9850 if (!GDK_WINDOW_IS_MAPPED (sub))
9853 gdk_window_coords_from_parent ((GdkWindow *)sub,
9855 &child_x, &child_y);
9856 if (point_in_window (sub, child_x, child_y))
9857 return (GdkWindow *)sub;
9860 if (private->num_offscreen_children > 0)
9862 sub = pick_embedded_child (private,
9865 return (GdkWindow *)sub;
9873 _gdk_window_find_descendant_at (GdkWindow *toplevel,
9879 GdkWindowObject *private, *sub;
9880 gdouble child_x, child_y;
9884 private = (GdkWindowObject *)toplevel;
9886 if (point_in_window (private, x, y))
9891 /* Children is ordered in reverse stack order, i.e. first is topmost */
9892 for (l = private->children; l != NULL; l = l->next)
9896 if (!GDK_WINDOW_IS_MAPPED (sub))
9899 gdk_window_coords_from_parent ((GdkWindow *)sub,
9901 &child_x, &child_y);
9902 if (point_in_window (sub, child_x, child_y))
9912 private->num_offscreen_children > 0)
9914 sub = pick_embedded_child (private,
9920 from_embedder (sub, x, y, &x, &y);
9928 /* Not in window at all */
9937 return (GdkWindow *)private;
9942 * @window: a toplevel #GdkWindow
9944 * Emits a short beep associated to @window in the appropriate
9945 * display, if supported. Otherwise, emits a short beep on
9946 * the display just as gdk_display_beep().
9951 gdk_window_beep (GdkWindow *window)
9953 GdkDisplay *display;
9954 GdkWindow *toplevel;
9956 g_return_if_fail (GDK_IS_WINDOW (window));
9958 if (GDK_WINDOW_DESTROYED (window))
9961 toplevel = get_event_toplevel (window);
9962 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
9964 if (toplevel && !gdk_window_is_offscreen ((GdkWindowObject *)toplevel))
9965 _gdk_windowing_window_beep (toplevel);
9967 gdk_display_beep (display);
9971 * gdk_window_set_support_multidevice:
9972 * @window: a #GdkWindow.
9973 * @support_multidevice: %TRUE to enable multidevice support in @window.
9975 * This function will enable multidevice features in @window.
9977 * Multidevice aware windows will need to handle properly multiple,
9978 * per device enter/leave events, device grabs and grab ownerships.
9983 gdk_window_set_support_multidevice (GdkWindow *window,
9984 gboolean support_multidevice)
9986 GdkWindowObject *private = (GdkWindowObject *) window;
9988 g_return_if_fail (GDK_IS_WINDOW (window));
9990 if (GDK_WINDOW_DESTROYED (window))
9993 if (private->support_multidevice == support_multidevice)
9996 private->support_multidevice = support_multidevice;
9998 /* FIXME: What to do if called when some pointers are inside the window ? */
10002 * gdk_window_get_support_multidevice:
10003 * @window: a #GdkWindow.
10005 * Returns %TRUE if the window is aware of the existence of multiple
10008 * Returns: %TRUE if the window handles multidevice features.
10013 gdk_window_get_support_multidevice (GdkWindow *window)
10015 GdkWindowObject *private = (GdkWindowObject *) window;
10017 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
10019 if (GDK_WINDOW_DESTROYED (window))
10022 return private->support_multidevice;
10025 static const guint type_masks[] = {
10026 GDK_SUBSTRUCTURE_MASK, /* GDK_DELETE = 0 */
10027 GDK_STRUCTURE_MASK, /* GDK_DESTROY = 1 */
10028 GDK_EXPOSURE_MASK, /* GDK_EXPOSE = 2 */
10029 GDK_POINTER_MOTION_MASK, /* GDK_MOTION_NOTIFY = 3 */
10030 GDK_BUTTON_PRESS_MASK, /* GDK_BUTTON_PRESS = 4 */
10031 GDK_BUTTON_PRESS_MASK, /* GDK_2BUTTON_PRESS = 5 */
10032 GDK_BUTTON_PRESS_MASK, /* GDK_3BUTTON_PRESS = 6 */
10033 GDK_BUTTON_RELEASE_MASK, /* GDK_BUTTON_RELEASE = 7 */
10034 GDK_KEY_PRESS_MASK, /* GDK_KEY_PRESS = 8 */
10035 GDK_KEY_RELEASE_MASK, /* GDK_KEY_RELEASE = 9 */
10036 GDK_ENTER_NOTIFY_MASK, /* GDK_ENTER_NOTIFY = 10 */
10037 GDK_LEAVE_NOTIFY_MASK, /* GDK_LEAVE_NOTIFY = 11 */
10038 GDK_FOCUS_CHANGE_MASK, /* GDK_FOCUS_CHANGE = 12 */
10039 GDK_STRUCTURE_MASK, /* GDK_CONFIGURE = 13 */
10040 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_MAP = 14 */
10041 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_UNMAP = 15 */
10042 GDK_PROPERTY_CHANGE_MASK, /* GDK_PROPERTY_NOTIFY = 16 */
10043 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_CLEAR = 17 */
10044 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_REQUEST = 18 */
10045 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_NOTIFY = 19 */
10046 GDK_PROXIMITY_IN_MASK, /* GDK_PROXIMITY_IN = 20 */
10047 GDK_PROXIMITY_OUT_MASK, /* GDK_PROXIMITY_OUT = 21 */
10048 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_ENTER = 22 */
10049 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_LEAVE = 23 */
10050 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_MOTION = 24 */
10051 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_STATUS = 25 */
10052 GDK_ALL_EVENTS_MASK, /* GDK_DROP_START = 26 */
10053 GDK_ALL_EVENTS_MASK, /* GDK_DROP_FINISHED = 27 */
10054 GDK_ALL_EVENTS_MASK, /* GDK_CLIENT_EVENT = 28 */
10055 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_VISIBILITY_NOTIFY = 29 */
10056 GDK_EXPOSURE_MASK, /* GDK_NO_EXPOSE = 30 */
10057 GDK_SCROLL_MASK | GDK_BUTTON_PRESS_MASK,/* GDK_SCROLL= 31 */
10058 0, /* GDK_WINDOW_STATE = 32 */
10059 0, /* GDK_SETTING = 33 */
10060 0, /* GDK_OWNER_CHANGE = 34 */
10061 0, /* GDK_GRAB_BROKEN = 35 */
10062 0, /* GDK_DAMAGE = 36 */
10064 G_STATIC_ASSERT (G_N_ELEMENTS (type_masks) == GDK_EVENT_LAST);
10066 /* send motion events if the right buttons are down */
10068 update_evmask_for_button_motion (guint evmask,
10069 GdkModifierType mask)
10071 if (evmask & GDK_BUTTON_MOTION_MASK &&
10072 mask & (GDK_BUTTON1_MASK |
10077 evmask |= GDK_POINTER_MOTION_MASK;
10079 if ((evmask & GDK_BUTTON1_MOTION_MASK && mask & GDK_BUTTON1_MASK) ||
10080 (evmask & GDK_BUTTON2_MOTION_MASK && mask & GDK_BUTTON2_MASK) ||
10081 (evmask & GDK_BUTTON3_MOTION_MASK && mask & GDK_BUTTON3_MASK))
10082 evmask |= GDK_POINTER_MOTION_MASK;
10088 is_button_type (GdkEventType type)
10090 return type == GDK_BUTTON_PRESS ||
10091 type == GDK_2BUTTON_PRESS ||
10092 type == GDK_3BUTTON_PRESS ||
10093 type == GDK_BUTTON_RELEASE ||
10094 type == GDK_SCROLL;
10098 is_motion_type (GdkEventType type)
10100 return type == GDK_MOTION_NOTIFY ||
10101 type == GDK_ENTER_NOTIFY ||
10102 type == GDK_LEAVE_NOTIFY;
10105 static GdkWindowObject *
10106 find_common_ancestor (GdkWindowObject *win1,
10107 GdkWindowObject *win2)
10109 GdkWindowObject *tmp;
10110 GList *path1 = NULL, *path2 = NULL;
10111 GList *list1, *list2;
10114 while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
10116 path1 = g_list_prepend (path1, tmp);
10117 tmp = get_event_parent (tmp);
10121 while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
10123 path2 = g_list_prepend (path2, tmp);
10124 tmp = get_event_parent (tmp);
10130 while (list1 && list2 && (list1->data == list2->data))
10132 tmp = (GdkWindowObject *)list1->data;
10133 list1 = g_list_next (list1);
10134 list2 = g_list_next (list2);
10136 g_list_free (path1);
10137 g_list_free (path2);
10143 _gdk_make_event (GdkWindow *window,
10145 GdkEvent *event_in_queue,
10146 gboolean before_event)
10148 GdkEvent *event = gdk_event_new (type);
10150 GdkModifierType the_state;
10152 the_time = gdk_event_get_time (event_in_queue);
10153 gdk_event_get_state (event_in_queue, &the_state);
10155 event->any.window = g_object_ref (window);
10156 event->any.send_event = FALSE;
10157 if (event_in_queue && event_in_queue->any.send_event)
10158 event->any.send_event = TRUE;
10162 case GDK_MOTION_NOTIFY:
10163 event->motion.time = the_time;
10164 event->motion.axes = NULL;
10165 event->motion.state = the_state;
10168 case GDK_BUTTON_PRESS:
10169 case GDK_2BUTTON_PRESS:
10170 case GDK_3BUTTON_PRESS:
10171 case GDK_BUTTON_RELEASE:
10172 event->button.time = the_time;
10173 event->button.axes = NULL;
10174 event->button.state = the_state;
10178 event->scroll.time = the_time;
10179 event->scroll.state = the_state;
10182 case GDK_KEY_PRESS:
10183 case GDK_KEY_RELEASE:
10184 event->key.time = the_time;
10185 event->key.state = the_state;
10188 case GDK_ENTER_NOTIFY:
10189 case GDK_LEAVE_NOTIFY:
10190 event->crossing.time = the_time;
10191 event->crossing.state = the_state;
10194 case GDK_PROPERTY_NOTIFY:
10195 event->property.time = the_time;
10196 event->property.state = the_state;
10199 case GDK_SELECTION_CLEAR:
10200 case GDK_SELECTION_REQUEST:
10201 case GDK_SELECTION_NOTIFY:
10202 event->selection.time = the_time;
10205 case GDK_PROXIMITY_IN:
10206 case GDK_PROXIMITY_OUT:
10207 event->proximity.time = the_time;
10210 case GDK_DRAG_ENTER:
10211 case GDK_DRAG_LEAVE:
10212 case GDK_DRAG_MOTION:
10213 case GDK_DRAG_STATUS:
10214 case GDK_DROP_START:
10215 case GDK_DROP_FINISHED:
10216 event->dnd.time = the_time;
10219 case GDK_FOCUS_CHANGE:
10220 case GDK_CONFIGURE:
10223 case GDK_CLIENT_EVENT:
10224 case GDK_VISIBILITY_NOTIFY:
10225 case GDK_NO_EXPOSE:
10233 if (event_in_queue)
10236 _gdk_event_queue_insert_before (gdk_drawable_get_display (window), event_in_queue, event);
10238 _gdk_event_queue_insert_after (gdk_drawable_get_display (window), event_in_queue, event);
10241 _gdk_event_queue_append (gdk_drawable_get_display (window), event);
10247 send_crossing_event (GdkDisplay *display,
10248 GdkWindowObject *toplevel,
10249 GdkWindowObject *window,
10251 GdkCrossingMode mode,
10252 GdkNotifyType notify_type,
10253 GdkWindow *subwindow,
10257 GdkModifierType mask,
10259 GdkEvent *event_in_queue,
10263 guint32 window_event_mask, type_event_mask;
10264 GdkDeviceGrabInfo *grab;
10265 gboolean block_event = FALSE;
10267 grab = _gdk_display_has_device_grab (display, device, serial);
10269 if (grab != NULL &&
10270 !grab->owner_events)
10272 /* !owner_event => only report events wrt grab window, ignore rest */
10273 if ((GdkWindow *)window != grab->window)
10275 window_event_mask = grab->event_mask;
10278 window_event_mask = window->event_mask;
10280 if (type == GDK_LEAVE_NOTIFY)
10282 type_event_mask = GDK_LEAVE_NOTIFY_MASK;
10283 window->devices_inside = g_list_remove (window->devices_inside, device);
10285 if (!window->support_multidevice && window->devices_inside)
10287 /* Block leave events unless it's the last pointer */
10288 block_event = TRUE;
10293 type_event_mask = GDK_ENTER_NOTIFY_MASK;
10295 if (!window->support_multidevice && window->devices_inside)
10297 /* Only emit enter events for the first device */
10298 block_event = TRUE;
10301 if (gdk_device_get_device_type (device) == GDK_DEVICE_TYPE_MASTER &&
10302 device->mode != GDK_MODE_DISABLED &&
10303 !g_list_find (window->devices_inside, device))
10304 window->devices_inside = g_list_prepend (window->devices_inside, device);
10310 if (window_event_mask & type_event_mask)
10312 event = _gdk_make_event ((GdkWindow *)window, type, event_in_queue, TRUE);
10313 gdk_event_set_device (event, device);
10314 event->crossing.time = time_;
10315 event->crossing.subwindow = subwindow;
10317 g_object_ref (subwindow);
10318 convert_toplevel_coords_to_window ((GdkWindow *)window,
10319 toplevel_x, toplevel_y,
10320 &event->crossing.x, &event->crossing.y);
10321 event->crossing.x_root = toplevel_x + toplevel->x;
10322 event->crossing.y_root = toplevel_y + toplevel->y;
10323 event->crossing.mode = mode;
10324 event->crossing.detail = notify_type;
10325 event->crossing.focus = FALSE;
10326 event->crossing.state = mask;
10331 /* The coordinates are in the toplevel window that src/dest are in.
10332 * src and dest are always (if != NULL) in the same toplevel, as
10333 * we get a leave-notify and set the window_under_pointer to null
10334 * before crossing to another toplevel.
10337 _gdk_synthesize_crossing_events (GdkDisplay *display,
10341 GdkCrossingMode mode,
10344 GdkModifierType mask,
10346 GdkEvent *event_in_queue,
10348 gboolean non_linear)
10350 GdkWindowObject *c;
10351 GdkWindowObject *win, *last, *next;
10352 GList *path, *list;
10353 GdkWindowObject *a;
10354 GdkWindowObject *b;
10355 GdkWindowObject *toplevel;
10356 GdkNotifyType notify_type;
10358 /* TODO: Don't send events to toplevel, as we get those from the windowing system */
10360 a = (GdkWindowObject *)src;
10361 b = (GdkWindowObject *)dest;
10363 return; /* No crossings generated between src and dest */
10365 if (gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_MASTER)
10367 if (a && gdk_window_get_device_events (src, device) == 0)
10370 if (b && gdk_window_get_device_events (dest, device) == 0)
10377 c = find_common_ancestor (a, b);
10379 non_linear |= (c != a) && (c != b);
10381 if (a) /* There might not be a source (i.e. if no previous pointer_in_window) */
10383 toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)a);
10385 /* Traverse up from a to (excluding) c sending leave events */
10387 notify_type = GDK_NOTIFY_NONLINEAR;
10389 notify_type = GDK_NOTIFY_INFERIOR;
10391 notify_type = GDK_NOTIFY_ANCESTOR;
10392 send_crossing_event (display, toplevel,
10393 a, GDK_LEAVE_NOTIFY,
10397 toplevel_x, toplevel_y,
10405 notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
10407 notify_type = GDK_NOTIFY_VIRTUAL;
10410 win = get_event_parent (a);
10411 while (win != c && win->window_type != GDK_WINDOW_ROOT)
10413 send_crossing_event (display, toplevel,
10414 win, GDK_LEAVE_NOTIFY,
10419 toplevel_x, toplevel_y,
10425 win = get_event_parent (win);
10430 if (b) /* Might not be a dest, e.g. if we're moving out of the window */
10432 toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)b);
10434 /* Traverse down from c to b */
10438 win = get_event_parent (b);
10439 while (win != c && win->window_type != GDK_WINDOW_ROOT)
10441 path = g_list_prepend (path, win);
10442 win = get_event_parent (win);
10446 notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
10448 notify_type = GDK_NOTIFY_VIRTUAL;
10453 win = (GdkWindowObject *)list->data;
10454 list = g_list_next (list);
10456 next = (GdkWindowObject *)list->data;
10460 send_crossing_event (display, toplevel,
10461 win, GDK_ENTER_NOTIFY,
10466 toplevel_x, toplevel_y,
10471 g_list_free (path);
10476 notify_type = GDK_NOTIFY_NONLINEAR;
10478 notify_type = GDK_NOTIFY_ANCESTOR;
10480 notify_type = GDK_NOTIFY_INFERIOR;
10482 send_crossing_event (display, toplevel,
10483 b, GDK_ENTER_NOTIFY,
10488 toplevel_x, toplevel_y,
10495 /* Returns the window inside the event window with the pointer in it
10496 * at the specified coordinates, or NULL if its not in any child of
10497 * the toplevel. It also takes into account !owner_events grabs.
10500 get_pointer_window (GdkDisplay *display,
10501 GdkWindow *event_window,
10503 gdouble toplevel_x,
10504 gdouble toplevel_y,
10507 GdkWindow *pointer_window;
10508 GdkDeviceGrabInfo *grab;
10509 GdkPointerWindowInfo *pointer_info;
10511 pointer_info = _gdk_display_get_pointer_info (display, device);
10513 if (event_window == pointer_info->toplevel_under_pointer)
10515 _gdk_window_find_descendant_at (event_window,
10516 toplevel_x, toplevel_y,
10519 pointer_window = NULL;
10521 grab = _gdk_display_has_device_grab (display, device, serial);
10522 if (grab != NULL &&
10523 !grab->owner_events &&
10524 pointer_window != grab->window)
10525 pointer_window = NULL;
10527 return pointer_window;
10531 _gdk_display_set_window_under_pointer (GdkDisplay *display,
10535 GdkPointerWindowInfo *device_info;
10537 /* We don't track this if all native, and it can cause issues
10538 with the update_cursor call below */
10539 if (_gdk_native_windows)
10542 device_info = _gdk_display_get_pointer_info (display, device);
10544 if (device_info->window_under_pointer)
10545 g_object_unref (device_info->window_under_pointer);
10546 device_info->window_under_pointer = window;
10550 g_object_ref (window);
10551 update_cursor (display, device);
10554 _gdk_display_enable_motion_hints (display, device);
10558 * gdk_pointer_grab:
10559 * @window: the #GdkWindow which will own the grab (the grab window).
10560 * @owner_events: if %FALSE then all pointer events are reported with respect to
10561 * @window and are only reported if selected by @event_mask. If %TRUE then pointer
10562 * events for this application are reported as normal, but pointer events outside
10563 * this application are reported with respect to @window and only if selected by
10564 * @event_mask. In either mode, unreported events are discarded.
10565 * @event_mask: specifies the event mask, which is used in accordance with
10566 * @owner_events. Note that only pointer events (i.e. button and motion events)
10568 * @confine_to: If non-%NULL, the pointer will be confined to this
10569 * window during the grab. If the pointer is outside @confine_to, it will
10570 * automatically be moved to the closest edge of @confine_to and enter
10571 * and leave events will be generated as necessary.
10572 * @cursor: the cursor to display while the grab is active. If this is %NULL then
10573 * the normal cursors are used for @window and its descendants, and the cursor
10574 * for @window is used for all other windows.
10575 * @time_: the timestamp of the event which led to this pointer grab. This usually
10576 * comes from a #GdkEventButton struct, though %GDK_CURRENT_TIME can be used if
10577 * the time isn't known.
10579 * Grabs the pointer (usually a mouse) so that all events are passed to this
10580 * application until the pointer is ungrabbed with gdk_pointer_ungrab(), or
10581 * the grab window becomes unviewable.
10582 * This overrides any previous pointer grab by this client.
10584 * Pointer grabs are used for operations which need complete control over mouse
10585 * events, even if the mouse leaves the application.
10586 * For example in GTK+ it is used for Drag and Drop, for dragging the handle in
10587 * the #GtkHPaned and #GtkVPaned widgets, and for resizing columns in #GtkCList
10590 * Note that if the event mask of an X window has selected both button press and
10591 * button release events, then a button press event will cause an automatic
10592 * pointer grab until the button is released.
10593 * X does this automatically since most applications expect to receive button
10594 * press and release events in pairs.
10595 * It is equivalent to a pointer grab on the window with @owner_events set to
10598 * If you set up anything at the time you take the grab that needs to be cleaned
10599 * up when the grab ends, you should handle the #GdkEventGrabBroken events that
10600 * are emitted when the grab ends unvoluntarily.
10602 * Returns: %GDK_GRAB_SUCCESS if the grab was successful.
10604 * Deprecated: 3.0: Use gdk_device_grab() instead.
10607 gdk_pointer_grab (GdkWindow * window,
10608 gboolean owner_events,
10609 GdkEventMask event_mask,
10610 GdkWindow * confine_to,
10611 GdkCursor * cursor,
10615 GdkDisplay *display;
10616 GdkDeviceManager *device_manager;
10618 GdkGrabStatus res = 0;
10620 GList *devices, *dev;
10622 g_return_val_if_fail (window != NULL, 0);
10623 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
10624 g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
10626 /* We need a native window for confine to to work, ensure we have one */
10629 if (!gdk_window_ensure_native (confine_to))
10631 g_warning ("Can't confine to grabbed window, not native");
10636 /* Non-viewable client side window => fail */
10637 if (!_gdk_window_has_impl (window) &&
10638 !gdk_window_is_viewable (window))
10639 return GDK_GRAB_NOT_VIEWABLE;
10641 if (_gdk_native_windows)
10644 native = gdk_window_get_toplevel (window);
10645 while (gdk_window_is_offscreen ((GdkWindowObject *)native))
10647 native = gdk_offscreen_window_get_embedder (native);
10649 if (native == NULL ||
10650 (!_gdk_window_has_impl (native) &&
10651 !gdk_window_is_viewable (native)))
10652 return GDK_GRAB_NOT_VIEWABLE;
10654 native = gdk_window_get_toplevel (native);
10657 display = gdk_drawable_get_display (window);
10659 serial = _gdk_windowing_window_get_next_serial (display);
10660 device_manager = gdk_display_get_device_manager (display);
10661 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
10663 /* FIXME: Should this be generic to all backends? */
10664 /* FIXME: What happens with extended devices? */
10665 for (dev = devices; dev; dev = dev->next)
10667 device = dev->data;
10669 if (device->source != GDK_SOURCE_MOUSE)
10672 res = _gdk_windowing_device_grab (device,
10676 get_native_grab_event_mask (event_mask),
10681 if (res == GDK_GRAB_SUCCESS)
10682 _gdk_display_add_device_grab (display,
10686 GDK_OWNERSHIP_NONE,
10694 /* FIXME: handle errors when grabbing */
10696 g_list_free (devices);
10702 * gdk_keyboard_grab:
10703 * @window: the #GdkWindow which will own the grab (the grab window).
10704 * @owner_events: if %FALSE then all keyboard events are reported with respect to
10705 * @window. If %TRUE then keyboard events for this application are
10706 * reported as normal, but keyboard events outside this application
10707 * are reported with respect to @window. Both key press and key
10708 * release events are always reported, independant of the event mask
10709 * set by the application.
10710 * @time: a timestamp from a #GdkEvent, or %GDK_CURRENT_TIME if no timestamp is
10713 * Grabs the keyboard so that all events are passed to this
10714 * application until the keyboard is ungrabbed with gdk_keyboard_ungrab().
10715 * This overrides any previous keyboard grab by this client.
10717 * If you set up anything at the time you take the grab that needs to be cleaned
10718 * up when the grab ends, you should handle the #GdkEventGrabBroken events that
10719 * are emitted when the grab ends unvoluntarily.
10721 * Returns: %GDK_GRAB_SUCCESS if the grab was successful.
10723 * Deprecated: 3.0: Use gdk_device_grab() instead.
10726 gdk_keyboard_grab (GdkWindow *window,
10727 gboolean owner_events,
10731 GdkDisplay *display;
10732 GdkDeviceManager *device_manager;
10734 GdkGrabStatus res = 0;
10736 GList *devices, *dev;
10738 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
10740 /* Non-viewable client side window => fail */
10741 if (!_gdk_window_has_impl (window) &&
10742 !gdk_window_is_viewable (window))
10743 return GDK_GRAB_NOT_VIEWABLE;
10745 if (_gdk_native_windows)
10748 native = gdk_window_get_toplevel (window);
10750 while (gdk_window_is_offscreen ((GdkWindowObject *)native))
10752 native = gdk_offscreen_window_get_embedder (native);
10754 if (native == NULL ||
10755 (!_gdk_window_has_impl (native) &&
10756 !gdk_window_is_viewable (native)))
10757 return GDK_GRAB_NOT_VIEWABLE;
10759 native = gdk_window_get_toplevel (native);
10762 display = gdk_drawable_get_display (window);
10764 serial = _gdk_windowing_window_get_next_serial (display);
10765 device_manager = gdk_display_get_device_manager (display);
10766 devices = gdk_device_manager_list_devices (device_manager, GDK_DEVICE_TYPE_MASTER);
10768 /* FIXME: Should this be generic to all backends? */
10769 /* FIXME: What happens with extended devices? */
10770 for (dev = devices; dev; dev = dev->next)
10772 device = dev->data;
10774 if (device->source != GDK_SOURCE_KEYBOARD)
10777 res = _gdk_windowing_device_grab (device,
10781 GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK,
10786 if (res == GDK_GRAB_SUCCESS)
10787 _gdk_display_add_device_grab (display,
10791 GDK_OWNERSHIP_NONE,
10798 /* FIXME: handle errors when grabbing */
10800 g_list_free (devices);
10806 * gdk_window_geometry_changed:
10807 * @window: an embedded offscreen #GdkWindow
10809 * This function informs GDK that the geometry of an embedded
10810 * offscreen window has changed. This is necessary for GDK to keep
10811 * track of which offscreen window the pointer is in.
10816 gdk_window_geometry_changed (GdkWindow *window)
10818 _gdk_synthesize_crossing_events_for_geometry_change (window);
10822 do_synthesize_crossing_event (gpointer data)
10824 GdkDisplay *display;
10825 GdkWindow *changed_toplevel;
10826 GdkWindowObject *changed_toplevel_priv;
10827 GHashTableIter iter;
10828 gpointer key, value;
10831 changed_toplevel = data;
10832 changed_toplevel_priv = (GdkWindowObject *)changed_toplevel;
10834 changed_toplevel_priv->synthesize_crossing_event_queued = FALSE;
10836 if (GDK_WINDOW_DESTROYED (changed_toplevel))
10839 display = gdk_drawable_get_display (changed_toplevel);
10840 serial = _gdk_windowing_window_get_next_serial (display);
10841 g_hash_table_iter_init (&iter, display->pointers_info);
10843 while (g_hash_table_iter_next (&iter, &key, &value))
10845 GdkWindow *new_window_under_pointer;
10846 GdkPointerWindowInfo *pointer_info = value;
10847 GdkDevice *device = key;
10849 if (changed_toplevel == pointer_info->toplevel_under_pointer)
10851 new_window_under_pointer =
10852 get_pointer_window (display, changed_toplevel,
10854 pointer_info->toplevel_x,
10855 pointer_info->toplevel_y,
10857 if (new_window_under_pointer != pointer_info->window_under_pointer)
10859 _gdk_synthesize_crossing_events (display,
10860 pointer_info->window_under_pointer,
10861 new_window_under_pointer,
10863 GDK_CROSSING_NORMAL,
10864 pointer_info->toplevel_x,
10865 pointer_info->toplevel_y,
10866 pointer_info->state,
10871 _gdk_display_set_window_under_pointer (display, device, new_window_under_pointer);
10880 _gdk_synthesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
10882 GdkDisplay *display;
10883 GdkWindow *toplevel;
10884 GdkWindowObject *toplevel_priv;
10886 if (_gdk_native_windows)
10887 return; /* We use the native crossing events if all native */
10889 display = gdk_drawable_get_display (changed_window);
10891 toplevel = get_event_toplevel (changed_window);
10892 toplevel_priv = (GdkWindowObject *) toplevel;
10894 if (!toplevel_priv->synthesize_crossing_event_queued)
10896 toplevel_priv->synthesize_crossing_event_queued = TRUE;
10898 g_idle_add_full (GDK_PRIORITY_EVENTS - 1,
10899 do_synthesize_crossing_event,
10900 g_object_ref (toplevel),
10905 /* Don't use for crossing events */
10907 get_event_window (GdkDisplay *display,
10909 GdkWindow *pointer_window,
10911 GdkModifierType mask,
10916 GdkWindow *grab_window;
10917 GdkWindowObject *w;
10918 GdkDeviceGrabInfo *grab;
10920 grab = _gdk_display_has_device_grab (display, device, serial);
10922 if (grab != NULL && !grab->owner_events)
10924 evmask = grab->event_mask;
10925 evmask = update_evmask_for_button_motion (evmask, mask);
10927 grab_window = grab->window;
10929 if (evmask & type_masks[type])
10932 *evmask_out = evmask;
10933 return grab_window;
10939 w = (GdkWindowObject *)pointer_window;
10942 evmask = w->event_mask;
10943 evmask = update_evmask_for_button_motion (evmask, mask);
10945 if (evmask & type_masks[type])
10948 *evmask_out = evmask;
10949 return (GdkWindow *)w;
10952 w = get_event_parent (w);
10955 if (grab != NULL &&
10956 grab->owner_events)
10958 evmask = grab->event_mask;
10959 evmask = update_evmask_for_button_motion (evmask, mask);
10961 if (evmask & type_masks[type])
10964 *evmask_out = evmask;
10965 return grab->window;
10975 proxy_pointer_event (GdkDisplay *display,
10976 GdkEvent *source_event,
10979 GdkWindow *toplevel_window, *event_window;
10980 GdkWindow *pointer_window;
10981 GdkPointerWindowInfo *pointer_info;
10985 gdouble toplevel_x, toplevel_y;
10987 gboolean non_linear;
10989 event_window = source_event->any.window;
10990 gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
10991 gdk_event_get_state (source_event, &state);
10992 time_ = gdk_event_get_time (source_event);
10993 device = gdk_event_get_device (source_event);
10994 pointer_info = _gdk_display_get_pointer_info (display, device);
10995 toplevel_window = convert_native_coords_to_toplevel (event_window,
10996 toplevel_x, toplevel_y,
10997 &toplevel_x, &toplevel_y);
10999 non_linear = FALSE;
11000 if ((source_event->type == GDK_LEAVE_NOTIFY ||
11001 source_event->type == GDK_ENTER_NOTIFY) &&
11002 (source_event->crossing.detail == GDK_NOTIFY_NONLINEAR ||
11003 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))
11006 /* If we get crossing events with subwindow unexpectedly being NULL
11007 that means there is a native subwindow that gdk doesn't know about.
11008 We track these and forward them, with the correct virtual window
11010 This is important to get right, as metacity uses gdk for the frame
11011 windows, but gdk doesn't know about the client windows reparented
11013 if (((source_event->type == GDK_LEAVE_NOTIFY &&
11014 source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
11015 (source_event->type == GDK_ENTER_NOTIFY &&
11016 (source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
11017 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
11018 source_event->crossing.subwindow == NULL)
11020 /* Left for an unknown (to gdk) subwindow */
11022 /* Send leave events from window under pointer to event window
11023 that will get the subwindow == NULL window */
11024 _gdk_synthesize_crossing_events (display,
11025 pointer_info->window_under_pointer,
11028 source_event->crossing.mode,
11029 toplevel_x, toplevel_y,
11035 /* Send subwindow == NULL event */
11036 send_crossing_event (display,
11037 (GdkWindowObject *)toplevel_window,
11038 (GdkWindowObject *)event_window,
11039 source_event->type,
11040 source_event->crossing.mode,
11041 source_event->crossing.detail,
11044 toplevel_x, toplevel_y,
11049 _gdk_display_set_window_under_pointer (display, device, NULL);
11053 pointer_window = get_pointer_window (display, toplevel_window, device,
11054 toplevel_x, toplevel_y, serial);
11056 if (((source_event->type == GDK_ENTER_NOTIFY &&
11057 source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
11058 (source_event->type == GDK_LEAVE_NOTIFY &&
11059 (source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
11060 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
11061 source_event->crossing.subwindow == NULL)
11063 /* Entered from an unknown (to gdk) subwindow */
11065 /* Send subwindow == NULL event */
11066 send_crossing_event (display,
11067 (GdkWindowObject *)toplevel_window,
11068 (GdkWindowObject *)event_window,
11069 source_event->type,
11070 source_event->crossing.mode,
11071 source_event->crossing.detail,
11074 toplevel_x, toplevel_y,
11079 /* Send enter events from event window to pointer_window */
11080 _gdk_synthesize_crossing_events (display,
11084 source_event->crossing.mode,
11085 toplevel_x, toplevel_y,
11088 serial, non_linear);
11089 _gdk_display_set_window_under_pointer (display, device, pointer_window);
11093 if (pointer_info->window_under_pointer != pointer_window)
11095 /* Either a toplevel crossing notify that ended up inside a child window,
11096 or a motion notify that got into another child window */
11098 /* Different than last time, send crossing events */
11099 _gdk_synthesize_crossing_events (display,
11100 pointer_info->window_under_pointer,
11103 GDK_CROSSING_NORMAL,
11104 toplevel_x, toplevel_y,
11107 serial, non_linear);
11108 _gdk_display_set_window_under_pointer (display, device, pointer_window);
11110 else if (source_event->type == GDK_MOTION_NOTIFY)
11112 GdkWindow *event_win;
11116 event_win = get_event_window (display,
11119 source_event->type,
11125 gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_MASTER &&
11126 gdk_window_get_device_events (event_win, device) == 0)
11132 (evmask & GDK_POINTER_MOTION_HINT_MASK))
11134 gulong *device_serial;
11136 device_serial = g_hash_table_lookup (display->motion_hint_info, device);
11138 if (!device_serial ||
11139 (*device_serial != 0 &&
11140 serial < *device_serial))
11141 event_win = NULL; /* Ignore event */
11145 *device_serial = G_MAXULONG;
11149 if (event_win && !display->ignore_core_events)
11151 event = _gdk_make_event (event_win, GDK_MOTION_NOTIFY, source_event, FALSE);
11152 event->motion.time = time_;
11153 convert_toplevel_coords_to_window (event_win,
11154 toplevel_x, toplevel_y,
11155 &event->motion.x, &event->motion.y);
11156 event->motion.x_root = source_event->motion.x_root;
11157 event->motion.y_root = source_event->motion.y_root;
11158 event->motion.state = state;
11159 event->motion.is_hint = is_hint;
11160 event->motion.device = source_event->motion.device;
11161 event->motion.axes = g_memdup (source_event->motion.axes,
11162 sizeof (gdouble) * source_event->motion.device->num_axes);
11166 /* unlink all move events from queue.
11167 We handle our own, including our emulated masks. */
11171 #define GDK_ANY_BUTTON_MASK (GDK_BUTTON1_MASK | \
11172 GDK_BUTTON2_MASK | \
11173 GDK_BUTTON3_MASK | \
11174 GDK_BUTTON4_MASK | \
11178 proxy_button_event (GdkEvent *source_event,
11181 GdkWindow *toplevel_window, *event_window;
11182 GdkWindow *event_win;
11183 GdkWindow *pointer_window;
11184 GdkWindowObject *parent;
11189 gdouble toplevel_x, toplevel_y;
11190 GdkDisplay *display;
11191 GdkWindowObject *w;
11194 type = source_event->any.type;
11195 event_window = source_event->any.window;
11196 gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
11197 gdk_event_get_state (source_event, &state);
11198 time_ = gdk_event_get_time (source_event);
11199 device = gdk_event_get_device (source_event);
11200 display = gdk_drawable_get_display (source_event->any.window);
11201 toplevel_window = convert_native_coords_to_toplevel (event_window,
11202 toplevel_x, toplevel_y,
11203 &toplevel_x, &toplevel_y);
11205 if (type == GDK_BUTTON_PRESS &&
11206 !source_event->any.send_event &&
11207 _gdk_display_has_device_grab (display, device, serial) == NULL)
11210 _gdk_window_find_descendant_at (toplevel_window,
11211 toplevel_x, toplevel_y,
11214 /* Find the event window, that gets the grab */
11215 w = (GdkWindowObject *)pointer_window;
11216 while (w != NULL &&
11217 (parent = get_event_parent (w)) != NULL &&
11218 parent->window_type != GDK_WINDOW_ROOT)
11220 if (w->event_mask & GDK_BUTTON_PRESS_MASK)
11224 pointer_window = (GdkWindow *)w;
11226 _gdk_display_add_device_grab (display,
11230 GDK_OWNERSHIP_NONE,
11232 gdk_window_get_events (pointer_window),
11236 _gdk_display_device_grab_update (display, device, serial);
11239 pointer_window = get_pointer_window (display, toplevel_window, device,
11240 toplevel_x, toplevel_y,
11243 event_win = get_event_window (display,
11249 if (event_win == NULL || display->ignore_core_events)
11252 if (gdk_device_get_device_type (device) != GDK_DEVICE_TYPE_MASTER &&
11253 gdk_window_get_device_events (event_win, device) == 0)
11256 event = _gdk_make_event (event_win, type, source_event, FALSE);
11260 case GDK_BUTTON_PRESS:
11261 case GDK_BUTTON_RELEASE:
11262 event->button.button = source_event->button.button;
11263 convert_toplevel_coords_to_window (event_win,
11264 toplevel_x, toplevel_y,
11265 &event->button.x, &event->button.y);
11266 event->button.x_root = source_event->button.x_root;
11267 event->button.y_root = source_event->button.y_root;
11268 event->button.state = state;
11269 event->button.device = source_event->button.device;
11270 event->button.axes = g_memdup (source_event->button.axes,
11271 sizeof (gdouble) * source_event->button.device->num_axes);
11273 if (type == GDK_BUTTON_PRESS)
11274 _gdk_event_button_generate (display, event);
11278 event->scroll.direction = source_event->scroll.direction;
11279 convert_toplevel_coords_to_window (event_win,
11280 toplevel_x, toplevel_y,
11281 &event->scroll.x, &event->scroll.y);
11282 event->scroll.x_root = source_event->scroll.x_root;
11283 event->scroll.y_root = source_event->scroll.y_root;
11284 event->scroll.state = state;
11285 event->scroll.device = source_event->scroll.device;
11292 return TRUE; /* Always unlink original, we want to obey the emulated event mask */
11295 #ifdef DEBUG_WINDOW_PRINTING
11297 gdk_window_print (GdkWindowObject *window,
11301 const char *window_types[] = {
11311 g_print ("%*s%p: [%s] %d,%d %dx%d", indent, "", window,
11312 window->user_data ? g_type_name_from_instance (window->user_data) : "no widget",
11313 window->x, window->y,
11314 window->width, window->height
11317 if (gdk_window_has_impl (window))
11319 #ifdef GDK_WINDOWING_X11
11320 g_print (" impl(0x%lx)", gdk_x11_drawable_get_xid (GDK_DRAWABLE (window)));
11324 if (window->window_type != GDK_WINDOW_CHILD)
11325 g_print (" %s", window_types[window->window_type]);
11327 if (window->input_only)
11328 g_print (" input-only");
11330 if (window->shaped)
11331 g_print (" shaped");
11333 if (!gdk_window_is_visible ((GdkWindow *)window))
11334 g_print (" hidden");
11336 g_print (" abs[%d,%d]",
11337 window->abs_x, window->abs_y);
11339 gdk_region_get_clipbox (window->clip_region, &r);
11340 if (gdk_region_empty (window->clip_region))
11341 g_print (" clipbox[empty]");
11343 g_print (" clipbox[%d,%d %dx%d]", r.x, r.y, r.width, r.height);
11350 gdk_window_print_tree (GdkWindow *window,
11352 gboolean include_input_only)
11354 GdkWindowObject *private;
11357 private = (GdkWindowObject *)window;
11359 if (private->input_only && !include_input_only)
11362 gdk_window_print (private, indent);
11364 for (l = private->children; l != NULL; l = l->next)
11365 gdk_window_print_tree (l->data, indent + 4, include_input_only);
11368 #endif /* DEBUG_WINDOW_PRINTING */
11371 _gdk_windowing_got_event (GdkDisplay *display,
11376 GdkWindow *event_window;
11377 GdkWindowObject *event_private;
11379 gboolean unlink_event;
11380 guint old_state, old_button;
11381 GdkDeviceGrabInfo *button_release_grab;
11382 GdkPointerWindowInfo *pointer_info;
11384 gboolean is_toplevel;
11386 if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
11387 display->last_event_time = gdk_event_get_time (event);
11389 device = gdk_event_get_device (event);
11395 g_object_get (device, "input-mode", &mode, NULL);
11396 _gdk_display_device_grab_update (display, device, serial);
11398 if (mode == GDK_MODE_DISABLED ||
11399 !_gdk_display_check_grab_ownership (display, device, serial))
11401 /* Device events are blocked by another
11402 * device grab, or the device is disabled
11404 unlink_event = TRUE;
11409 event_window = event->any.window;
11413 pointer_info = _gdk_display_get_pointer_info (display, device);
11414 event_private = GDK_WINDOW_OBJECT (event_window);
11416 #ifdef DEBUG_WINDOW_PRINTING
11417 if (event->type == GDK_KEY_PRESS &&
11418 (event->key.keyval == 0xa7 ||
11419 event->key.keyval == 0xbd))
11421 gdk_window_print_tree (event_window, 0,
11422 event->key.keyval == 0xbd);
11426 if (_gdk_native_windows)
11428 if (event->type == GDK_BUTTON_PRESS &&
11429 !event->any.send_event &&
11430 _gdk_display_has_device_grab (display, device, serial) == NULL)
11432 _gdk_display_add_device_grab (display,
11436 GDK_OWNERSHIP_NONE,
11438 gdk_window_get_events (event_window),
11440 gdk_event_get_time (event),
11442 _gdk_display_device_grab_update (display, device, serial);
11444 if (event->type == GDK_BUTTON_RELEASE &&
11445 !event->any.send_event)
11447 button_release_grab =
11448 _gdk_display_has_device_grab (display, device, serial);
11449 if (button_release_grab &&
11450 button_release_grab->implicit &&
11451 (event->button.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
11453 button_release_grab->serial_end = serial;
11454 button_release_grab->implicit_ungrab = FALSE;
11455 _gdk_display_device_grab_update (display, device, serial);
11459 if (event->type == GDK_BUTTON_PRESS)
11460 _gdk_event_button_generate (display, event);
11465 if (event->type == GDK_VISIBILITY_NOTIFY)
11467 event_private->native_visibility = event->visibility.state;
11468 gdk_window_update_visibility_recursively (event_private,
11473 if (!(is_button_type (event->type) ||
11474 is_motion_type (event->type)) ||
11475 event_private->window_type == GDK_WINDOW_ROOT)
11478 is_toplevel = gdk_window_is_toplevel (event_private);
11480 if ((event->type == GDK_ENTER_NOTIFY ||
11481 event->type == GDK_LEAVE_NOTIFY) &&
11482 (event->crossing.mode == GDK_CROSSING_GRAB ||
11483 event->crossing.mode == GDK_CROSSING_UNGRAB) &&
11484 (_gdk_display_has_device_grab (display, device, serial) ||
11485 event->crossing.detail == GDK_NOTIFY_INFERIOR))
11487 /* We synthesize all crossing events due to grabs ourselves,
11488 * so we ignore the native ones caused by our native pointer_grab
11489 * calls. Otherwise we would proxy these crossing event and cause
11490 * multiple copies of crossing events for grabs.
11492 * We do want to handle grabs from other clients though, as for
11493 * instance alt-tab in metacity causes grabs like these and
11494 * we want to handle those. Thus the has_pointer_grab check.
11496 * Implicit grabs on child windows create some grabbing events
11497 * that are sent before the button press. This means we can't
11498 * detect these with the has_pointer_grab check (as the implicit
11499 * grab is only noticed when we get button press event), so we
11500 * detect these events by checking for INFERIOR enter or leave
11501 * events. These should never be a problem to filter out.
11504 /* We ended up in this window after some (perhaps other clients)
11505 grab, so update the toplevel_under_window state */
11507 event->type == GDK_ENTER_NOTIFY &&
11508 event->crossing.mode == GDK_CROSSING_UNGRAB)
11510 if (pointer_info->toplevel_under_pointer)
11511 g_object_unref (pointer_info->toplevel_under_pointer);
11512 pointer_info->toplevel_under_pointer = g_object_ref (event_window);
11515 unlink_event = TRUE;
11519 /* Track toplevel_under_pointer */
11522 if (event->type == GDK_ENTER_NOTIFY &&
11523 event->crossing.detail != GDK_NOTIFY_INFERIOR)
11525 if (pointer_info->toplevel_under_pointer)
11526 g_object_unref (pointer_info->toplevel_under_pointer);
11527 pointer_info->toplevel_under_pointer = g_object_ref (event_window);
11529 else if (event->type == GDK_LEAVE_NOTIFY &&
11530 event->crossing.detail != GDK_NOTIFY_INFERIOR &&
11531 pointer_info->toplevel_under_pointer == event_window)
11533 if (pointer_info->toplevel_under_pointer)
11534 g_object_unref (pointer_info->toplevel_under_pointer);
11535 pointer_info->toplevel_under_pointer = NULL;
11539 /* Store last pointer window and position/state */
11540 old_state = pointer_info->state;
11541 old_button = pointer_info->button;
11543 gdk_event_get_coords (event, &x, &y);
11544 convert_native_coords_to_toplevel (event_window, x, y, &x, &y);
11545 pointer_info->toplevel_x = x;
11546 pointer_info->toplevel_y = y;
11547 gdk_event_get_state (event, &pointer_info->state);
11548 if (event->type == GDK_BUTTON_PRESS ||
11549 event->type == GDK_BUTTON_RELEASE)
11550 pointer_info->button = event->button.button;
11553 (pointer_info->state != old_state ||
11554 pointer_info->button != old_button))
11555 _gdk_display_enable_motion_hints (display, device);
11557 unlink_event = FALSE;
11558 if (is_motion_type (event->type))
11559 unlink_event = proxy_pointer_event (display,
11562 else if (is_button_type (event->type))
11563 unlink_event = proxy_button_event (event,
11566 if (event->type == GDK_BUTTON_RELEASE &&
11567 !event->any.send_event)
11569 button_release_grab =
11570 _gdk_display_has_device_grab (display, device, serial);
11571 if (button_release_grab &&
11572 button_release_grab->implicit &&
11573 (event->button.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
11575 button_release_grab->serial_end = serial;
11576 button_release_grab->implicit_ungrab = FALSE;
11577 _gdk_display_device_grab_update (display, device, serial);
11584 _gdk_event_queue_remove_link (display, event_link);
11585 g_list_free_1 (event_link);
11586 gdk_event_free (event);
11592 get_extension_event_window (GdkDisplay *display,
11593 GdkWindow *pointer_window,
11598 GdkWindow *grab_window;
11599 GdkWindowObject *w;
11600 GdkDeviceGrabInfo *grab;
11602 /* FIXME: which device? */
11603 grab = _gdk_display_has_device_grab (display, display->core_pointer, serial);
11605 if (grab != NULL && !grab->owner_events)
11607 evmask = grab->event_mask;
11609 grab_window = grab->window;
11611 if (evmask & type_masks[type])
11612 return grab_window;
11617 w = (GdkWindowObject *)pointer_window;
11620 evmask = w->extension_events;
11622 if (evmask & type_masks[type])
11623 return (GdkWindow *)w;
11625 w = get_event_parent (w);
11628 if (grab != NULL &&
11629 grab->owner_events)
11631 evmask = grab->event_mask;
11633 if (evmask & type_masks[type])
11634 return grab->window;
11644 _gdk_window_get_input_window_for_event (GdkWindow *native_window,
11645 GdkEventType event_type,
11649 GdkDisplay *display;
11650 GdkWindow *toplevel_window;
11651 GdkWindow *pointer_window;
11652 GdkWindow *event_win;
11653 gdouble toplevel_x, toplevel_y;
11658 display = gdk_drawable_get_display (native_window);
11659 toplevel_window = convert_native_coords_to_toplevel (native_window,
11660 toplevel_x, toplevel_y,
11661 &toplevel_x, &toplevel_y);
11662 /* FIXME: which device? */
11663 pointer_window = get_pointer_window (display, toplevel_window, NULL,
11664 toplevel_x, toplevel_y, serial);
11665 event_win = get_extension_event_window (display,
11674 #define __GDK_WINDOW_C__
11675 #include "gdkaliasdef.c"