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/.
29 #include "gdkwindow.h"
30 #include "gdkwindowimpl.h"
31 #include "gdkinternals.h"
32 #include "gdk.h" /* For gdk_rectangle_union() */
33 #include "gdkpixmap.h"
34 #include "gdkdrawable.h"
36 #include "gdkscreen.h"
37 #include "gdkmarshalers.h"
40 #undef DEBUG_WINDOW_PRINTING
42 #ifdef GDK_WINDOWING_X11
43 #include "x11/gdkx.h" /* For workaround */
48 /* Historically a GdkWindow always matches a platform native window,
49 * be it a toplevel window or a child window. In this setup the
50 * GdkWindow (and other GdkDrawables) were platform independent classes,
51 * and the actual platform specific implementation was in a delegate
52 * object availible as "impl" in the window object.
54 * With the addition of client side windows and offscreen windows this
55 * changes a bit. The application-visible GdkWindow object behaves as
56 * it did before, but not all such windows now have a corresponding native
57 * window. Instead windows that are "client side" are emulated by the gdk
58 * code such that clipping, drawing, moving, events etc work as expected.
60 * For GdkWindows that have a native window the "impl" object is the
61 * same as before. However, for all client side windows the impl object
62 * is shared with its parent (i.e. all client windows descendants of one
63 * native window has the same impl.
65 * Additionally there is a new type of platform independent impl object,
66 * GdkOffscreenWindow. All windows of type GDK_WINDOW_OFFSCREEN get an impl
67 * of this type (while their children are generally GDK_WINDOW_CHILD virtual
68 * windows). Such windows work by allocating a GdkPixmap as the backing store
69 * for drawing operations, which is resized with the window.
71 * GdkWindows have a pointer to the "impl window" they are in, i.e.
72 * the topmost GdkWindow which have the same "impl" value. This is stored
73 * in impl_window, which is different from the window itself only for client
75 * All GdkWindows (native or not) track the position of the window in the parent
76 * (x, y), the size of the window (width, height), the position of the window
77 * with respect to the impl window (abs_x, abs_y). We also track the clip
78 * region of the window wrt parent windows and siblings, in window-relative
79 * coordinates with and without child windows included (clip_region,
80 * clip_region_with_children).
82 * All toplevel windows are native windows, but also child windows can be
83 * native (although not children of offscreens). We always listen to
84 * a basic set of events (see get_native_event_mask) for these windows
85 * so that we can emulate events for any client side children.
87 * For native windows we apply the calculated clip region as a window shape
88 * so that eg. client side siblings that overlap the native child properly
89 * draws over the native child window.
91 * In order to minimize flicker and for performance we use a couple of cacheing
92 * tricks. First of all, every time we do a window to window copy area, for instance
93 * when moving a client side window or when scrolling/moving a region in a window
94 * we store this in outstanding_moves instead of applying immediately. We then
95 * delay this move until we really need it (because something depends on being
96 * able to read it), or until we're handing a redraw from an expose/invalidation
97 * (actually we delay it past redraw, but before blitting the double buffer pixmap
98 * to the window). This gives us two advantages. First of all it minimizes the time
99 * from the window is moved to the exposes related to that move, secondly it allows
100 * us to be smart about how to do the copy. We combine multiple moves into one (when
101 * possible) and we don't actually do copies to anything that is or will be
102 * invalidated and exposed anyway.
104 * Secondly, we use something called a "implicit paint" during repaint handling.
105 * An implicit paint is similar to a regular paint for the paint stack, but it is
106 * not put on the stack. Instead, it is set on the impl window, and later when
107 * regular gdk_window_begin_paint_region() happen on a window of this impl window
108 * we reuse the pixmap from the implicit paint. During repaint we create and at the
109 * end flush an implicit paint, which means we can collect all the paints on
110 * multiple client side windows in the same backing store pixmap.
112 * All drawing to windows are wrapped with macros that set up the GC such that
113 * the offsets and clip region is right for drawing to the paint object or
114 * directly to the emulated window. It also automatically handles any flushing
115 * needed when drawing directly to a window. Adding window/paint clipping is
116 * done using _gdk_gc_add_drawable_clip which lets us efficiently add and then
117 * remove a custom clip region.
120 #define USE_BACKING_STORE /* Appears to work on Win32, too, now. */
122 /* This adds a local value to the GdkVisibilityState enum */
123 #define GDK_VISIBILITY_NOT_VIEWABLE 3
126 PICK_EMBEDDED_CHILD, /* only called if children are embedded */
139 CLEAR_BG_WINCLEARED, /* Clear backgrounds except those that the window system clears */
143 struct _GdkWindowPaint
149 cairo_surface_t *surface;
150 guint uses_implicit : 1;
156 GdkRegion *dest_region; /* The destination region */
157 int dx, dy; /* The amount that the source was moved to reach dest_region */
158 } GdkWindowRegionMove;
163 static GdkGC *gdk_window_create_gc (GdkDrawable *drawable,
165 GdkGCValuesMask mask);
166 static void gdk_window_draw_rectangle (GdkDrawable *drawable,
173 static void gdk_window_draw_arc (GdkDrawable *drawable,
182 static void gdk_window_draw_polygon (GdkDrawable *drawable,
187 static void gdk_window_draw_text (GdkDrawable *drawable,
194 static void gdk_window_draw_text_wc (GdkDrawable *drawable,
199 const GdkWChar *text,
201 static void gdk_window_draw_drawable (GdkDrawable *drawable,
210 GdkDrawable *original_src);
211 static void gdk_window_draw_points (GdkDrawable *drawable,
215 static void gdk_window_draw_segments (GdkDrawable *drawable,
219 static void gdk_window_draw_lines (GdkDrawable *drawable,
224 static void gdk_window_draw_glyphs (GdkDrawable *drawable,
229 PangoGlyphString *glyphs);
230 static void gdk_window_draw_glyphs_transformed (GdkDrawable *drawable,
236 PangoGlyphString *glyphs);
238 static void gdk_window_draw_image (GdkDrawable *drawable,
248 static void gdk_window_draw_pixbuf (GdkDrawable *drawable,
261 static void gdk_window_draw_trapezoids (GdkDrawable *drawable,
263 GdkTrapezoid *trapezoids,
266 static GdkImage* gdk_window_copy_to_image (GdkDrawable *drawable,
275 static cairo_surface_t *gdk_window_ref_cairo_surface (GdkDrawable *drawable);
276 static cairo_surface_t *gdk_window_create_cairo_surface (GdkDrawable *drawable,
279 static void gdk_window_set_cairo_clip (GdkDrawable *drawable,
282 static void gdk_window_real_get_size (GdkDrawable *drawable,
286 static GdkVisual* gdk_window_real_get_visual (GdkDrawable *drawable);
287 static gint gdk_window_real_get_depth (GdkDrawable *drawable);
288 static GdkScreen* gdk_window_real_get_screen (GdkDrawable *drawable);
289 static void gdk_window_real_set_colormap (GdkDrawable *drawable,
291 static GdkColormap* gdk_window_real_get_colormap (GdkDrawable *drawable);
293 static GdkDrawable* gdk_window_get_source_drawable (GdkDrawable *drawable);
294 static GdkDrawable* gdk_window_get_composite_drawable (GdkDrawable *drawable,
299 gint *composite_x_offset,
300 gint *composite_y_offset);
301 static GdkRegion* gdk_window_get_clip_region (GdkDrawable *drawable);
302 static GdkRegion* gdk_window_get_visible_region (GdkDrawable *drawable);
304 static void gdk_window_free_paint_stack (GdkWindow *window);
306 static void gdk_window_init (GdkWindowObject *window);
307 static void gdk_window_class_init (GdkWindowObjectClass *klass);
308 static void gdk_window_finalize (GObject *object);
310 static void gdk_window_set_property (GObject *object,
314 static void gdk_window_get_property (GObject *object,
319 static void gdk_window_clear_backing_region (GdkWindow *window,
321 static void gdk_window_redirect_free (GdkWindowRedirect *redirect);
322 static void apply_redirect_to_children (GdkWindowObject *private,
323 GdkWindowRedirect *redirect);
324 static void remove_redirect_from_children (GdkWindowObject *private,
325 GdkWindowRedirect *redirect);
327 static void recompute_visible_regions (GdkWindowObject *private,
328 gboolean recalculate_siblings,
329 gboolean recalculate_children);
330 static void gdk_window_flush_outstanding_moves (GdkWindow *window);
331 static void gdk_window_flush_recursive (GdkWindowObject *window);
332 static void do_move_region_bits_on_impl (GdkWindowObject *private,
333 GdkRegion *region, /* In impl window coords */
335 static void gdk_window_invalidate_in_parent (GdkWindowObject *private);
336 static void move_native_children (GdkWindowObject *private);
337 static void update_cursor (GdkDisplay *display);
338 static void impl_window_add_update_area (GdkWindowObject *impl_window,
340 static void gdk_window_region_move_free (GdkWindowRegionMove *move);
341 static void gdk_window_invalidate_region_full (GdkWindow *window,
342 const GdkRegion *region,
343 gboolean invalidate_children,
345 static void gdk_window_invalidate_rect_full (GdkWindow *window,
346 const GdkRectangle *rect,
347 gboolean invalidate_children,
350 static guint signals[LAST_SIGNAL] = { 0 };
352 static gpointer parent_class = NULL;
354 static const cairo_user_data_key_t gdk_window_cairo_key;
357 new_region_tag (void)
359 static guint32 tag = 0;
365 gdk_window_object_get_type (void)
367 static GType object_type = 0;
370 object_type = g_type_register_static_simple (GDK_TYPE_DRAWABLE,
372 sizeof (GdkWindowObjectClass),
373 (GClassInitFunc) gdk_window_class_init,
374 sizeof (GdkWindowObject),
375 (GInstanceInitFunc) gdk_window_init,
382 _gdk_paintable_get_type (void)
384 static GType paintable_type = 0;
388 const GTypeInfo paintable_info =
390 sizeof (GdkPaintableIface), /* class_size */
391 NULL, /* base_init */
392 NULL, /* base_finalize */
395 paintable_type = g_type_register_static (G_TYPE_INTERFACE,
396 g_intern_static_string ("GdkPaintable"),
399 g_type_interface_add_prerequisite (paintable_type, G_TYPE_OBJECT);
402 return paintable_type;
406 gdk_window_init (GdkWindowObject *window)
408 /* 0-initialization is good for all other fields. */
410 window->window_type = GDK_WINDOW_CHILD;
412 window->state = GDK_WINDOW_STATE_WITHDRAWN;
415 window->toplevel_window_type = -1;
417 window->effective_visibility = GDK_VISIBILITY_NOT_VIEWABLE;
418 window->visibility = GDK_VISIBILITY_FULLY_OBSCURED;
419 /* Default to unobscured since some backends don't send visibility events */
420 window->native_visibility = GDK_VISIBILITY_UNOBSCURED;
423 /* Stop and return on the first non-NULL parent */
425 accumulate_get_window (GSignalInvocationHint *ihint,
427 const GValue *handler_return,
430 g_value_copy (handler_return, return_accu);
431 /* Continue while returning NULL */
432 return g_value_get_object (handler_return) == NULL;
435 static GQuark quark_pointer_window = 0;
438 gdk_window_class_init (GdkWindowObjectClass *klass)
440 GObjectClass *object_class = G_OBJECT_CLASS (klass);
441 GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
443 parent_class = g_type_class_peek_parent (klass);
445 object_class->finalize = gdk_window_finalize;
446 object_class->set_property = gdk_window_set_property;
447 object_class->get_property = gdk_window_get_property;
449 drawable_class->create_gc = gdk_window_create_gc;
450 drawable_class->draw_rectangle = gdk_window_draw_rectangle;
451 drawable_class->draw_arc = gdk_window_draw_arc;
452 drawable_class->draw_polygon = gdk_window_draw_polygon;
453 drawable_class->draw_text = gdk_window_draw_text;
454 drawable_class->draw_text_wc = gdk_window_draw_text_wc;
455 drawable_class->draw_drawable_with_src = gdk_window_draw_drawable;
456 drawable_class->draw_points = gdk_window_draw_points;
457 drawable_class->draw_segments = gdk_window_draw_segments;
458 drawable_class->draw_lines = gdk_window_draw_lines;
459 drawable_class->draw_glyphs = gdk_window_draw_glyphs;
460 drawable_class->draw_glyphs_transformed = gdk_window_draw_glyphs_transformed;
461 drawable_class->draw_image = gdk_window_draw_image;
462 drawable_class->draw_pixbuf = gdk_window_draw_pixbuf;
463 drawable_class->draw_trapezoids = gdk_window_draw_trapezoids;
464 drawable_class->get_depth = gdk_window_real_get_depth;
465 drawable_class->get_screen = gdk_window_real_get_screen;
466 drawable_class->get_size = gdk_window_real_get_size;
467 drawable_class->set_colormap = gdk_window_real_set_colormap;
468 drawable_class->get_colormap = gdk_window_real_get_colormap;
469 drawable_class->get_visual = gdk_window_real_get_visual;
470 drawable_class->_copy_to_image = gdk_window_copy_to_image;
471 drawable_class->ref_cairo_surface = gdk_window_ref_cairo_surface;
472 drawable_class->create_cairo_surface = gdk_window_create_cairo_surface;
473 drawable_class->set_cairo_clip = gdk_window_set_cairo_clip;
474 drawable_class->get_clip_region = gdk_window_get_clip_region;
475 drawable_class->get_visible_region = gdk_window_get_visible_region;
476 drawable_class->get_composite_drawable = gdk_window_get_composite_drawable;
477 drawable_class->get_source_drawable = gdk_window_get_source_drawable;
479 quark_pointer_window = g_quark_from_static_string ("gtk-pointer-window");
483 g_object_class_install_property (object_class,
485 g_param_spec_boxed ("cursor",
492 * GdkWindow::pick-embedded-child:
493 * @window: the window on which the signal is emitted
494 * @x: x coordinate in the window
495 * @y: y coordinate in the window
497 * The ::pick-embedded-child signal is emitted to find an embedded
498 * child at the given position.
500 * Returns: the #GdkWindow of the embedded child at @x, @y, or %NULL
504 signals[PICK_EMBEDDED_CHILD] =
505 g_signal_new (g_intern_static_string ("pick-embedded-child"),
506 G_OBJECT_CLASS_TYPE (object_class),
509 accumulate_get_window, NULL,
510 _gdk_marshal_OBJECT__DOUBLE_DOUBLE,
517 * GdkWindow::to-embedder:
518 * @window: the offscreen window on which the signal is emitted
519 * @offscreen-x: x coordinate in the offscreen window
520 * @offscreen-y: y coordinate in the offscreen window
521 * @embedder-x: return location for the x coordinate in the embedder window
522 * @embedder-y: return location for the y coordinate in the embedder window
524 * The ::to-embedder signal is emitted to translate coordinates
525 * in an offscreen window to its embedder.
527 * See also #GtkWindow::from-embedder.
531 signals[TO_EMBEDDER] =
532 g_signal_new (g_intern_static_string ("to-embedder"),
533 G_OBJECT_CLASS_TYPE (object_class),
537 _gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
546 * GdkWindow::from-embedder:
547 * @window: the offscreen window on which the signal is emitted
548 * @embedder-x: x coordinate in the embedder window
549 * @embedder-y: y coordinate in the embedder window
550 * @offscreen-x: return location for the x coordinate in the offscreen window
551 * @offscreen-y: return location for the y coordinate in the offscreen window
553 * The ::from-embedder signal is emitted to translate coordinates
554 * in the embedder of an offscreen window to the offscreen window.
556 * See also #GtkWindow::to-embedder.
560 signals[FROM_EMBEDDER] =
561 g_signal_new (g_intern_static_string ("from-embedder"),
562 G_OBJECT_CLASS_TYPE (object_class),
566 _gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
576 gdk_window_finalize (GObject *object)
578 GdkWindow *window = GDK_WINDOW (object);
579 GdkWindowObject *obj = (GdkWindowObject *) object;
581 if (!GDK_WINDOW_DESTROYED (window))
583 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
585 g_warning ("losing last reference to undestroyed window\n");
586 _gdk_window_destroy (window, FALSE);
589 /* We use TRUE here, to keep us from actually calling
590 * XDestroyWindow() on the window
592 _gdk_window_destroy (window, TRUE);
597 g_object_unref (obj->impl);
601 if (obj->impl_window != obj)
603 g_object_unref (obj->impl_window);
604 obj->impl_window = NULL;
608 gdk_region_destroy (obj->shape);
610 if (obj->input_shape)
611 gdk_region_destroy (obj->input_shape);
614 gdk_cursor_unref (obj->cursor);
616 G_OBJECT_CLASS (parent_class)->finalize (object);
620 gdk_window_set_property (GObject *object,
625 GdkWindow *window = (GdkWindow *)object;
630 gdk_window_set_cursor (window, g_value_get_boxed (value));
634 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
640 gdk_window_get_property (GObject *object,
645 GdkWindow *window = (GdkWindow *) object;
650 g_value_set_boxed (value, gdk_window_get_cursor (window));
654 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
660 gdk_window_is_offscreen (GdkWindowObject *window)
662 return window->window_type == GDK_WINDOW_OFFSCREEN;
665 static GdkWindowObject *
666 gdk_window_get_impl_window (GdkWindowObject *window)
668 return window->impl_window;
672 _gdk_window_get_impl_window (GdkWindow *window)
674 return (GdkWindow *)gdk_window_get_impl_window ((GdkWindowObject *)window);
678 gdk_window_has_impl (GdkWindowObject *window)
680 return window->impl_window == window;
684 gdk_window_is_toplevel (GdkWindowObject *window)
687 window->parent == NULL ||
688 window->parent->window_type == GDK_WINDOW_ROOT;
692 _gdk_window_has_impl (GdkWindow *window)
694 return gdk_window_has_impl ((GdkWindowObject *)window);
698 gdk_window_has_no_impl (GdkWindowObject *window)
700 return window->impl_window != window;
704 remove_child_area (GdkWindowObject *private,
705 GdkWindowObject *until,
709 GdkWindowObject *child;
710 GdkRegion *child_region;
715 for (l = private->children; l; l = l->next)
722 /* If region is empty already, no need to do
723 anything potentially costly */
724 if (gdk_region_empty (region))
727 if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
730 /* Ignore offscreen children, as they don't draw in their parent and
731 * don't take part in the clipping */
732 if (gdk_window_is_offscreen (child))
737 r.width = child->width;
738 r.height = child->height;
740 /* Bail early if child totally outside region */
741 if (gdk_region_rect_in (region, &r) == GDK_OVERLAP_RECTANGLE_OUT)
744 child_region = gdk_region_rectangle (&r);
748 /* Adjust shape region to parent window coords */
749 gdk_region_offset (child->shape, child->x, child->y);
750 gdk_region_intersect (child_region, child->shape);
751 gdk_region_offset (child->shape, -child->x, -child->y);
753 else if (private->window_type == GDK_WINDOW_FOREIGN)
755 shape = _gdk_windowing_window_get_shape ((GdkWindow *)child);
758 gdk_region_intersect (child_region, shape);
759 gdk_region_destroy (shape);
765 if (child->input_shape)
766 gdk_region_intersect (child_region, child->input_shape);
767 else if (private->window_type == GDK_WINDOW_FOREIGN)
769 shape = _gdk_windowing_window_get_input_shape ((GdkWindow *)child);
772 gdk_region_intersect (child_region, shape);
773 gdk_region_destroy (shape);
778 gdk_region_subtract (region, child_region);
779 gdk_region_destroy (child_region);
784 static GdkVisibilityState
785 effective_visibility (GdkWindowObject *private)
787 GdkVisibilityState native;
789 if (!gdk_window_is_viewable ((GdkWindow *)private))
790 return GDK_VISIBILITY_NOT_VIEWABLE;
792 native = private->impl_window->native_visibility;
794 if (native == GDK_VISIBILITY_FULLY_OBSCURED ||
795 private->visibility == GDK_VISIBILITY_FULLY_OBSCURED)
796 return GDK_VISIBILITY_FULLY_OBSCURED;
797 else if (native == GDK_VISIBILITY_UNOBSCURED)
798 return private->visibility;
799 else /* native PARTIAL, private partial or unobscured */
800 return GDK_VISIBILITY_PARTIAL;
804 gdk_window_update_visibility (GdkWindowObject *private)
806 GdkVisibilityState new_visibility;
809 new_visibility = effective_visibility (private);
811 if (new_visibility != private->effective_visibility)
813 private->effective_visibility = new_visibility;
815 if (new_visibility != GDK_VISIBILITY_NOT_VIEWABLE &&
816 private->event_mask & GDK_VISIBILITY_NOTIFY)
818 event = _gdk_make_event ((GdkWindow *)private, GDK_VISIBILITY_NOTIFY,
820 event->visibility.state = new_visibility;
826 gdk_window_update_visibility_recursively (GdkWindowObject *private,
827 GdkWindowObject *only_for_impl)
829 GdkWindowObject *child;
832 gdk_window_update_visibility (private);
833 for (l = private->children; l != NULL; l = l->next)
836 if ((only_for_impl == NULL) ||
837 (only_for_impl == child->impl_window))
838 gdk_window_update_visibility_recursively (child, only_for_impl);
843 should_apply_clip_as_shape (GdkWindowObject *private)
846 gdk_window_has_impl (private) &&
847 /* Not for offscreens */
848 private->window_type != GDK_WINDOW_OFFSCREEN &&
849 /* or for toplevels */
850 !gdk_window_is_toplevel (private) &&
851 /* or for foreign windows */
852 private->window_type != GDK_WINDOW_FOREIGN &&
853 /* or for the root window */
854 private->window_type != GDK_WINDOW_ROOT;
858 apply_shape (GdkWindowObject *private,
861 GdkWindowImplIface *impl_iface;
863 /* We trash whether we applied a shape so that
864 we can avoid unsetting it many times, which
865 could happen in e.g. apply_clip_as_shape as
866 windows get resized */
867 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
869 impl_iface->shape_combine_region ((GdkWindow *)private,
871 else if (private->applied_shape)
872 impl_iface->shape_combine_region ((GdkWindow *)private,
875 private->applied_shape = region != NULL;
879 apply_clip_as_shape (GdkWindowObject *private)
884 r.width = private->width;
885 r.height = private->height;
887 /* We only apply the clip region if would differ
888 from the actual clip region implied by the size
889 of the window. This is to avoid unneccessarily
890 adding meaningless shapes to all native subwindows */
891 if (!gdk_region_rect_equal (private->clip_region, &r))
892 apply_shape (private, private->clip_region);
894 apply_shape (private, NULL);
898 recompute_visible_regions_internal (GdkWindowObject *private,
899 gboolean recalculate_clip,
900 gboolean recalculate_siblings,
901 gboolean recalculate_children)
905 GdkWindowObject *child;
906 GdkRegion *new_clip, *old_clip_region_with_children;
907 gboolean clip_region_changed;
908 gboolean abs_pos_changed;
909 int old_abs_x, old_abs_y;
911 old_abs_x = private->abs_x;
912 old_abs_y = private->abs_y;
914 /* Update absolute position */
915 if (gdk_window_has_impl (private))
917 /* Native window starts here */
923 private->abs_x = private->parent->abs_x + private->x;
924 private->abs_y = private->parent->abs_y + private->y;
928 private->abs_x != old_abs_x ||
929 private->abs_y != old_abs_y;
931 /* Update clip region based on:
934 * siblings in parents above window
936 clip_region_changed = FALSE;
937 if (recalculate_clip)
939 if (private->viewable)
941 /* Calculate visible region (sans children) in parent window coords */
944 r.width = private->width;
945 r.height = private->height;
946 new_clip = gdk_region_rectangle (&r);
948 if (!gdk_window_is_toplevel (private))
950 gdk_region_intersect (new_clip, private->parent->clip_region);
952 /* Remove all overlapping children from parent.
953 * Unless we're all native, because then we don't need to take
954 * siblings into account since X does that clipping for us.
955 * This makes things like SWT that modify the raw X stacking
956 * order without GDKs knowledge work.
958 if (!_gdk_native_windows)
959 remove_child_area (private->parent, private, FALSE, new_clip);
962 /* Convert from parent coords to window coords */
963 gdk_region_offset (new_clip, -private->x, -private->y);
966 gdk_region_intersect (new_clip, private->shape);
969 new_clip = gdk_region_new ();
971 if (private->clip_region == NULL ||
972 !gdk_region_equal (private->clip_region, new_clip))
973 clip_region_changed = TRUE;
975 if (private->clip_region)
976 gdk_region_destroy (private->clip_region);
977 private->clip_region = new_clip;
979 old_clip_region_with_children = private->clip_region_with_children;
980 private->clip_region_with_children = gdk_region_copy (private->clip_region);
981 if (private->window_type != GDK_WINDOW_ROOT)
982 remove_child_area (private, NULL, FALSE, private->clip_region_with_children);
984 if (clip_region_changed ||
985 !gdk_region_equal (private->clip_region_with_children, old_clip_region_with_children))
986 private->clip_tag = new_region_tag ();
988 if (old_clip_region_with_children)
989 gdk_region_destroy (old_clip_region_with_children);
992 if (clip_region_changed)
994 GdkVisibilityState visibility;
995 gboolean fully_visible;
997 if (gdk_region_empty (private->clip_region))
998 visibility = GDK_VISIBILITY_FULLY_OBSCURED;
1003 fully_visible = gdk_region_equal (private->clip_region,
1010 r.width = private->width;
1011 r.height = private->height;
1012 fully_visible = gdk_region_rect_equal (private->clip_region, &r);
1016 visibility = GDK_VISIBILITY_UNOBSCURED;
1018 visibility = GDK_VISIBILITY_PARTIAL;
1021 if (private->visibility != visibility)
1023 private->visibility = visibility;
1024 gdk_window_update_visibility (private);
1028 /* Update all children, recursively (except for root, where children are not exact). */
1029 if ((abs_pos_changed || clip_region_changed || recalculate_children) &&
1030 private->window_type != GDK_WINDOW_ROOT)
1032 for (l = private->children; l; l = l->next)
1035 /* Only recalculate clip if the the clip region changed, otherwise
1036 * there is no way the child clip region could change (its has not e.g. moved)
1037 * Except if recalculate_children is set to force child updates
1039 recompute_visible_regions_internal (child,
1040 recalculate_clip && (clip_region_changed || recalculate_children),
1045 if (clip_region_changed &&
1046 should_apply_clip_as_shape (private))
1047 apply_clip_as_shape (private);
1049 if (recalculate_siblings &&
1050 !gdk_window_is_toplevel (private))
1052 /* If we moved a child window in parent or changed the stacking order, then we
1053 * need to recompute the visible area of all the other children in the parent
1055 for (l = private->parent->children; l; l = l->next)
1059 if (child != private)
1060 recompute_visible_regions_internal (child, TRUE, FALSE, FALSE);
1063 /* We also need to recompute the _with_children clip for the parent */
1064 recompute_visible_regions_internal (private->parent, TRUE, FALSE, FALSE);
1067 if (private->cairo_surface)
1071 /* It would be nice if we had some cairo support here so we
1072 could set the clip rect on the cairo surface */
1073 width = private->abs_x + private->width;
1074 height = private->abs_y + private->height;
1076 _gdk_windowing_set_cairo_surface_size (private->cairo_surface,
1078 cairo_surface_set_device_offset (private->cairo_surface,
1084 /* Call this when private has changed in one or more of these ways:
1088 * stacking order of window changed
1091 * It will recalculate abs_x/y and the clip regions
1093 * Unless the window didn't change stacking order or size/pos, pass in TRUE
1094 * for recalculate_siblings. (Mostly used internally for the recursion)
1096 * If a child window was removed (and you can't use that child for
1097 * recompute_visible_regions), pass in TRUE for recalculate_children on the parent
1100 recompute_visible_regions (GdkWindowObject *private,
1101 gboolean recalculate_siblings,
1102 gboolean recalculate_children)
1104 recompute_visible_regions_internal (private,
1106 recalculate_siblings,
1107 recalculate_children);
1111 _gdk_window_update_size (GdkWindow *window)
1113 recompute_visible_regions ((GdkWindowObject *)window, TRUE, FALSE);
1116 /* Find the native window that would be just above "child"
1117 * in the native stacking order if "child" was a native window
1118 * (it doesn't have to be native). If there is no such native
1119 * window inside this native parent then NULL is returned.
1120 * If child is NULL, find lowest native window in parent.
1122 static GdkWindowObject *
1123 find_native_sibling_above_helper (GdkWindowObject *parent,
1124 GdkWindowObject *child)
1131 l = g_list_find (parent->children, child);
1132 g_assert (l != NULL); /* Better be a child of its parent... */
1133 l = l->prev; /* Start looking at the one above the child */
1136 l = g_list_last (parent->children);
1138 for (; l != NULL; l = l->prev)
1142 if (gdk_window_has_impl (w))
1145 g_assert (parent != w);
1146 w = find_native_sibling_above_helper (w, NULL);
1155 static GdkWindowObject *
1156 find_native_sibling_above (GdkWindowObject *parent,
1157 GdkWindowObject *child)
1161 w = find_native_sibling_above_helper (parent, child);
1165 if (gdk_window_has_impl (parent))
1168 return find_native_sibling_above (parent->parent, parent);
1172 get_native_event_mask (GdkWindowObject *private)
1174 if (_gdk_native_windows ||
1175 private->window_type == GDK_WINDOW_ROOT ||
1176 private->window_type == GDK_WINDOW_FOREIGN)
1177 return private->event_mask;
1182 /* Do whatever the app asks to, since the app
1183 * may be asking for weird things for native windows,
1184 * but don't use motion hints as that may affect non-native
1185 * child windows that don't want it. Also, we need to
1186 * set all the app-specified masks since they will be picked
1187 * up by any implicit grabs (i.e. if they were not set as
1188 * native we would not get the events we need). */
1189 mask = private->event_mask & ~GDK_POINTER_MOTION_HINT_MASK;
1191 /* We need thse for all native windows so we can
1192 emulate events on children: */
1195 GDK_VISIBILITY_NOTIFY_MASK |
1196 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK;
1198 /* Additionally we select for pointer and button events
1199 * for toplevels as we need to get these to emulate
1200 * them for non-native subwindows. Even though we don't
1201 * select on them for all native windows we will get them
1202 * as the events are propagated out to the first window
1203 * that select for them.
1204 * Not selecting for button press on all windows is an
1205 * important thing, because in X only one client can do
1206 * so, and we don't want to unexpectedly prevent another
1207 * client from doing it.
1209 if (gdk_window_is_toplevel (private))
1211 GDK_POINTER_MOTION_MASK |
1212 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
1220 get_native_grab_event_mask (GdkEventMask grab_mask)
1222 /* Similar to the above but for pointer events only */
1224 GDK_POINTER_MOTION_MASK |
1225 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
1226 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
1229 ~GDK_POINTER_MOTION_HINT_MASK);
1232 /* Puts the native window in the right order wrt the other native windows
1233 * in the hierarchy, given the position it has in the client side data.
1234 * This is useful if some operation changed the stacking order.
1235 * This calls assumes the native window is now topmost in its native parent.
1238 sync_native_window_stack_position (GdkWindow *window)
1240 GdkWindowObject *above;
1241 GdkWindowObject *private;
1242 GdkWindowImplIface *impl_iface;
1243 GList listhead = {0};
1245 private = (GdkWindowObject *) window;
1246 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
1248 above = find_native_sibling_above (private->parent, private);
1251 listhead.data = window;
1252 impl_iface->restack_under ((GdkWindow *)above,
1259 * @parent: a #GdkWindow, or %NULL to create the window as a child of
1260 * the default root window for the default display.
1261 * @attributes: attributes of the new window
1262 * @attributes_mask: mask indicating which fields in @attributes are valid
1264 * Creates a new #GdkWindow using the attributes from
1265 * @attributes. See #GdkWindowAttr and #GdkWindowAttributesType for
1266 * more details. Note: to use this on displays other than the default
1267 * display, @parent must be specified.
1269 * Return value: the new #GdkWindow
1272 gdk_window_new (GdkWindow *parent,
1273 GdkWindowAttr *attributes,
1274 gint attributes_mask)
1277 GdkWindowObject *private;
1282 GdkEventMask event_mask;
1283 GdkWindow *real_parent;
1285 g_return_val_if_fail (attributes != NULL, NULL);
1289 GDK_NOTE (MULTIHEAD,
1290 g_warning ("gdk_window_new(): no parent specified reverting to parent = default root window"));
1292 screen = gdk_screen_get_default ();
1293 parent = gdk_screen_get_root_window (screen);
1296 screen = gdk_drawable_get_screen (parent);
1298 g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
1300 if (GDK_WINDOW_DESTROYED (parent))
1302 g_warning ("gdk_window_new(): parent is destroyed\n");
1306 if (attributes->window_type == GDK_WINDOW_OFFSCREEN &&
1307 _gdk_native_windows)
1309 g_warning ("Offscreen windows not supported with native-windows gdk");
1313 window = g_object_new (GDK_TYPE_WINDOW, NULL);
1314 private = (GdkWindowObject *) window;
1316 /* Windows with a foreign parent are treated as if they are children
1317 * of the root window, except for actual creation.
1319 real_parent = parent;
1320 if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
1321 parent = gdk_screen_get_root_window (screen);
1323 private->parent = (GdkWindowObject *)parent;
1325 private->accept_focus = TRUE;
1326 private->focus_on_map = TRUE;
1328 if (attributes_mask & GDK_WA_X)
1333 if (attributes_mask & GDK_WA_Y)
1340 private->width = (attributes->width > 1) ? (attributes->width) : (1);
1341 private->height = (attributes->height > 1) ? (attributes->height) : (1);
1343 #ifdef GDK_WINDOWING_X11
1344 /* Work around a bug where Xorg refuses to map toplevel InputOnly windows
1345 * from an untrusted client: http://bugs.freedesktop.org/show_bug.cgi?id=6988
1347 if (attributes->wclass == GDK_INPUT_ONLY &&
1348 private->parent->window_type == GDK_WINDOW_ROOT &&
1349 !G_LIKELY (GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (parent))->trusted_client))
1351 g_warning ("Coercing GDK_INPUT_ONLY toplevel window to GDK_INPUT_OUTPUT to work around bug in Xorg server");
1352 attributes->wclass = GDK_INPUT_OUTPUT;
1356 if (attributes->wclass == GDK_INPUT_ONLY)
1358 /* Backwards compatiblity - we've always ignored
1359 * attributes->window_type for input-only windows
1362 if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
1363 private->window_type = GDK_WINDOW_TEMP;
1365 private->window_type = GDK_WINDOW_CHILD;
1368 private->window_type = attributes->window_type;
1371 switch (private->window_type)
1373 case GDK_WINDOW_TOPLEVEL:
1374 case GDK_WINDOW_DIALOG:
1375 case GDK_WINDOW_TEMP:
1376 case GDK_WINDOW_OFFSCREEN:
1377 if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
1378 g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
1379 "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
1380 case GDK_WINDOW_CHILD:
1384 g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
1388 if (attributes_mask & GDK_WA_VISUAL)
1389 visual = attributes->visual;
1391 visual = gdk_screen_get_system_visual (screen);
1393 private->event_mask = attributes->event_mask;
1395 if (attributes->wclass == GDK_INPUT_OUTPUT)
1397 private->input_only = FALSE;
1398 private->depth = visual->depth;
1400 private->bg_color.pixel = 0; /* TODO: BlackPixel (xdisplay, screen_x11->screen_num); */
1401 private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
1403 private->bg_pixmap = NULL;
1408 private->input_only = TRUE;
1411 if (private->parent)
1412 private->parent->children = g_list_prepend (private->parent->children, window);
1414 native = _gdk_native_windows; /* Default */
1415 if (private->parent->window_type == GDK_WINDOW_ROOT)
1416 native = TRUE; /* Always use native windows for toplevels */
1417 else if (!private->input_only &&
1418 ((attributes_mask & GDK_WA_COLORMAP &&
1419 attributes->colormap != gdk_drawable_get_colormap ((GdkDrawable *)private->parent)) ||
1420 (attributes_mask & GDK_WA_VISUAL &&
1421 attributes->visual != gdk_drawable_get_visual ((GdkDrawable *)private->parent))))
1422 native = TRUE; /* InputOutput window with different colormap or visual than parent, needs native window */
1424 if (private->window_type == GDK_WINDOW_OFFSCREEN)
1426 _gdk_offscreen_window_new (window, screen, visual, attributes, attributes_mask);
1427 private->impl_window = private;
1431 event_mask = get_native_event_mask (private);
1433 /* Create the impl */
1434 _gdk_window_impl_new (window, real_parent, screen, visual, event_mask, attributes, attributes_mask);
1435 private->impl_window = private;
1437 /* This will put the native window topmost in the native parent, which may
1438 * be wrong wrt other native windows in the non-native hierarchy, so restack */
1439 if (!_gdk_window_has_impl (real_parent))
1440 sync_native_window_stack_position (window);
1444 private->impl_window = g_object_ref (private->parent->impl_window);
1445 private->impl = g_object_ref (private->impl_window->impl);
1448 recompute_visible_regions (private, TRUE, FALSE);
1450 if (private->parent->window_type != GDK_WINDOW_ROOT)
1452 /* Inherit redirection from parent */
1453 private->redirect = private->parent->redirect;
1456 gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
1457 (attributes->cursor) :
1464 is_parent_of (GdkWindow *parent,
1475 w = gdk_window_get_parent (w);
1482 change_impl (GdkWindowObject *private,
1483 GdkWindowObject *impl_window,
1487 GdkWindowObject *child;
1488 GdkDrawable *old_impl;
1489 GdkWindowObject *old_impl_window;
1491 old_impl = private->impl;
1492 old_impl_window = private->impl_window;
1493 if (private != impl_window)
1494 private->impl_window = g_object_ref (impl_window);
1496 private->impl_window = private;
1497 private->impl = g_object_ref (new);
1498 if (old_impl_window != private)
1499 g_object_unref (old_impl_window);
1500 g_object_unref (old_impl);
1502 for (l = private->children; l != NULL; l = l->next)
1506 if (child->impl == old_impl)
1507 change_impl (child, impl_window, new);
1512 reparent_to_impl (GdkWindowObject *private)
1515 GdkWindowObject *child;
1517 GdkWindowImplIface *impl_iface;
1519 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
1521 /* Enumerate in reverse order so we get the right order for the native
1522 windows (first in childrens list is topmost, and reparent places on top) */
1523 for (l = g_list_last (private->children); l != NULL; l = l->prev)
1527 if (child->impl == private->impl)
1528 reparent_to_impl (child);
1531 show = impl_iface->reparent ((GdkWindow *)child,
1532 (GdkWindow *)private,
1533 child->x, child->y);
1535 gdk_window_show_unraised ((GdkWindow *)child);
1542 * gdk_window_reparent:
1543 * @window: a #GdkWindow
1544 * @new_parent: new parent to move @window into
1545 * @x: X location inside the new parent
1546 * @y: Y location inside the new parent
1548 * Reparents @window into the given @new_parent. The window being
1549 * reparented will be unmapped as a side effect.
1553 gdk_window_reparent (GdkWindow *window,
1554 GdkWindow *new_parent,
1558 GdkWindowObject *private;
1559 GdkWindowObject *new_parent_private;
1560 GdkWindowObject *old_parent;
1562 gboolean show, was_mapped, applied_clip_as_shape;
1563 gboolean do_reparent_to_impl;
1564 GdkEventMask old_native_event_mask;
1565 GdkWindowImplIface *impl_iface;
1567 g_return_if_fail (GDK_IS_WINDOW (window));
1568 g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
1569 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
1571 if (GDK_WINDOW_DESTROYED (window) ||
1572 (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
1575 screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
1577 new_parent = gdk_screen_get_root_window (screen);
1579 private = (GdkWindowObject *) window;
1580 new_parent_private = (GdkWindowObject *)new_parent;
1582 /* No input-output children of input-only windows */
1583 if (new_parent_private->input_only && !private->input_only)
1586 /* Don't create loops in hierarchy */
1587 if (is_parent_of (window, new_parent))
1590 if (private->cairo_surface)
1592 /* This might be wrong in the new parent, e.g. for non-native surfaces.
1593 To make sure we're ok, just wipe it. */
1594 cairo_surface_finish (private->cairo_surface);
1595 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
1599 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
1600 old_parent = private->parent;
1602 /* Break up redirection if inherited */
1603 if (private->redirect && private->redirect->redirected != private)
1605 remove_redirect_from_children (private, private->redirect);
1606 private->redirect = NULL;
1609 was_mapped = GDK_WINDOW_IS_MAPPED (window);
1612 /* Reparenting to toplevel. Ensure we have a native window so this can work */
1613 if (new_parent_private->window_type == GDK_WINDOW_ROOT ||
1614 new_parent_private->window_type == GDK_WINDOW_FOREIGN)
1615 gdk_window_ensure_native (window);
1617 applied_clip_as_shape = should_apply_clip_as_shape (private);
1619 old_native_event_mask = 0;
1620 do_reparent_to_impl = FALSE;
1621 if (gdk_window_has_impl (private))
1623 old_native_event_mask = get_native_event_mask (private);
1625 show = impl_iface->reparent (window, new_parent, x, y);
1629 /* This shouldn't happen, as we created a native in this case, check anyway to see if that ever fails */
1630 g_assert (new_parent_private->window_type != GDK_WINDOW_ROOT &&
1631 new_parent_private->window_type != GDK_WINDOW_FOREIGN);
1634 gdk_window_hide (window);
1636 do_reparent_to_impl = TRUE;
1637 change_impl (private,
1638 new_parent_private->impl_window,
1639 new_parent_private->impl);
1642 /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
1645 if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1647 new_parent = gdk_screen_get_root_window (screen);
1648 new_parent_private = (GdkWindowObject *)new_parent;
1652 old_parent->children = g_list_remove (old_parent->children, window);
1654 private->parent = new_parent_private;
1658 new_parent_private->children = g_list_prepend (new_parent_private->children, window);
1660 /* Switch the window type as appropriate */
1662 switch (GDK_WINDOW_TYPE (new_parent))
1664 case GDK_WINDOW_ROOT:
1665 case GDK_WINDOW_FOREIGN:
1666 if (private->toplevel_window_type != -1)
1667 GDK_WINDOW_TYPE (window) = private->toplevel_window_type;
1668 else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1669 GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
1671 case GDK_WINDOW_OFFSCREEN:
1672 case GDK_WINDOW_TOPLEVEL:
1673 case GDK_WINDOW_CHILD:
1674 case GDK_WINDOW_DIALOG:
1675 case GDK_WINDOW_TEMP:
1676 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
1677 GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
1679 /* Save the original window type so we can restore it if the
1680 * window is reparented back to be a toplevel
1682 private->toplevel_window_type = GDK_WINDOW_TYPE (window);
1683 GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
1687 /* We might have changed window type for a native windows, so we
1688 need to change the event mask too. */
1689 if (gdk_window_has_impl (private))
1691 GdkEventMask native_event_mask = get_native_event_mask (private);
1693 if (native_event_mask != old_native_event_mask)
1694 impl_iface->set_events (window, native_event_mask);
1697 /* Inherit parent redirect if we don't have our own */
1698 if (private->parent && private->redirect == NULL)
1700 private->redirect = private->parent->redirect;
1701 apply_redirect_to_children (private, private->redirect);
1704 _gdk_window_update_viewable (window);
1706 recompute_visible_regions (private, TRUE, FALSE);
1707 if (old_parent && GDK_WINDOW_TYPE (old_parent) != GDK_WINDOW_ROOT)
1708 recompute_visible_regions (old_parent, FALSE, TRUE);
1710 /* We used to apply the clip as the shape, but no more.
1711 Reset this to the real shape */
1712 if (gdk_window_has_impl (private) &&
1713 applied_clip_as_shape &&
1714 !should_apply_clip_as_shape (private))
1715 apply_shape (private, private->shape);
1717 if (do_reparent_to_impl)
1718 reparent_to_impl (private);
1721 /* The reparent will have put the native window topmost in the native parent,
1722 * which may be wrong wrt other native windows in the non-native hierarchy,
1724 if (!gdk_window_has_impl (new_parent_private))
1725 sync_native_window_stack_position (window);
1729 gdk_window_show_unraised (window);
1731 _gdk_synthesize_crossing_events_for_geometry_change (window);
1735 temporary_disable_extension_events (GdkWindowObject *window)
1737 GdkWindowObject *child;
1741 if (window->extension_events != 0)
1743 g_object_set_data (G_OBJECT (window),
1744 "gdk-window-extension-events",
1745 GINT_TO_POINTER (window->extension_events));
1746 gdk_input_set_extension_events ((GdkWindow *)window, 0,
1747 GDK_EXTENSION_EVENTS_NONE);
1752 for (l = window->children; l != NULL; l = l->next)
1756 if (window->impl_window == child->impl_window)
1757 res |= temporary_disable_extension_events (window);
1764 reenable_extension_events (GdkWindowObject *window)
1766 GdkWindowObject *child;
1770 mask = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window),
1771 "gdk-window-extension-events"));
1775 /* We don't have the mode here, so we pass in cursor.
1776 This works with the current code since mode is not
1777 stored except as part of the mask, and cursor doesn't
1779 gdk_input_set_extension_events ((GdkWindow *)window, mask,
1780 GDK_EXTENSION_EVENTS_CURSOR);
1781 g_object_set_data (G_OBJECT (window),
1782 "gdk-window-extension-events",
1786 for (l = window->children; l != NULL; l = l->next)
1790 if (window->impl_window == child->impl_window)
1791 reenable_extension_events (window);
1796 * gdk_window_ensure_native:
1797 * @window: a #GdkWindow
1799 * Tries to ensure that there is a window-system native window for this
1800 * GdkWindow. This may fail in some situations, returning %FALSE.
1802 * Offscreen window and children of them can never have native windows.
1804 * Some backends may not support native child windows.
1806 * Returns: %TRUE if the window has a native window, %FALSE otherwise
1811 gdk_window_ensure_native (GdkWindow *window)
1813 GdkWindowObject *private;
1814 GdkWindowObject *impl_window;
1815 GdkDrawable *new_impl, *old_impl;
1818 GdkWindowAttr attributes;
1819 GdkWindowObject *above;
1821 GdkWindowImplIface *impl_iface;
1822 gboolean disabled_extension_events;
1824 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
1826 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT ||
1827 GDK_WINDOW_DESTROYED (window))
1830 private = (GdkWindowObject *) window;
1832 impl_window = gdk_window_get_impl_window (private);
1834 if (impl_window->window_type == GDK_WINDOW_OFFSCREEN)
1835 return FALSE; /* native in offscreens not supported */
1837 if (impl_window == private)
1838 /* Already has an impl, and its not offscreen . */
1841 /* Need to create a native window */
1843 /* First we disable any extension events on the window or its
1844 descendants to handle the native input window moving */
1845 disabled_extension_events = FALSE;
1846 if (impl_window->input_window)
1847 disabled_extension_events = temporary_disable_extension_events (private);
1849 screen = gdk_drawable_get_screen (window);
1850 visual = gdk_drawable_get_visual (window);
1852 attributes.colormap = gdk_drawable_get_colormap (window);
1854 old_impl = private->impl;
1855 _gdk_window_impl_new (window, (GdkWindow *)private->parent,
1857 get_native_event_mask (private),
1858 &attributes, GDK_WA_COLORMAP);
1859 new_impl = private->impl;
1861 private->impl = old_impl;
1862 change_impl (private, private, new_impl);
1864 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
1866 /* Native window creation will put the native window topmost in the
1867 * native parent, which may be wrong wrt the position of the previous
1868 * non-native window wrt to the other non-native children, so correct this.
1870 above = find_native_sibling_above (private->parent, private);
1873 listhead.data = window;
1874 listhead.prev = NULL;
1875 listhead.next = NULL;
1876 impl_iface->restack_under ((GdkWindow *)above, &listhead);
1879 recompute_visible_regions (private, FALSE, FALSE);
1881 /* The shape may not have been set, as the clip region doesn't actually
1882 change, so do it here manually */
1883 if (should_apply_clip_as_shape (private))
1884 apply_clip_as_shape (private);
1886 reparent_to_impl (private);
1888 if (!private->input_only)
1890 impl_iface->set_background (window, &private->bg_color);
1891 if (private->bg_pixmap != NULL)
1892 impl_iface->set_back_pixmap (window, private->bg_pixmap);
1895 impl_iface->input_shape_combine_region (window,
1896 private->input_shape,
1899 if (gdk_window_is_viewable (window))
1900 impl_iface->show (window, FALSE);
1902 if (disabled_extension_events)
1903 reenable_extension_events (private);
1909 window_remove_filters (GdkWindow *window)
1911 GdkWindowObject *obj = (GdkWindowObject*) window;
1917 for (tmp_list = obj->filters; tmp_list; tmp_list = tmp_list->next)
1918 g_free (tmp_list->data);
1920 g_list_free (obj->filters);
1921 obj->filters = NULL;
1926 * _gdk_window_destroy_hierarchy:
1927 * @window: a #GdkWindow
1928 * @recursing: If TRUE, then this is being called because a parent
1930 * @recursing_native: If TRUE, then this is being called because a native parent
1931 * was destroyed. This generally means that the call to the
1932 * windowing system to destroy the window can be omitted, since
1933 * it will be destroyed as a result of the parent being destroyed.
1934 * Unless @foreign_destroy.
1935 * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
1936 * external agency. The window has already been destroyed and no
1937 * windowing system calls should be made. (This may never happen
1938 * for some windowing systems.)
1940 * Internal function to destroy a window. Like gdk_window_destroy(),
1941 * but does not drop the reference count created by gdk_window_new().
1944 _gdk_window_destroy_hierarchy (GdkWindow *window,
1946 gboolean recursing_native,
1947 gboolean foreign_destroy)
1949 GdkWindowObject *private;
1950 GdkWindowObject *temp_private;
1951 GdkWindowImplIface *impl_iface;
1952 GdkWindow *temp_window;
1954 GdkDisplay *display;
1958 g_return_if_fail (GDK_IS_WINDOW (window));
1960 private = (GdkWindowObject*) window;
1962 if (GDK_WINDOW_DESTROYED (window))
1965 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
1966 screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
1967 temp_window = g_object_get_qdata (G_OBJECT (screen), quark_pointer_window);
1968 if (temp_window == window)
1969 g_object_set_qdata (G_OBJECT (screen), quark_pointer_window, NULL);
1972 switch (private->window_type)
1974 case GDK_WINDOW_ROOT:
1975 if (!screen->closed)
1977 g_error ("attempted to destroy root window");
1980 /* else fall thru */
1981 case GDK_WINDOW_TOPLEVEL:
1982 case GDK_WINDOW_CHILD:
1983 case GDK_WINDOW_DIALOG:
1984 case GDK_WINDOW_TEMP:
1985 case GDK_WINDOW_FOREIGN:
1986 case GDK_WINDOW_OFFSCREEN:
1987 if (private->window_type == GDK_WINDOW_FOREIGN && !foreign_destroy)
1989 /* Logically, it probably makes more sense to send
1990 * a "destroy yourself" message to the foreign window
1991 * whether or not it's in our hierarchy; but for historical
1992 * reasons, we only send "destroy yourself" messages to
1993 * foreign windows in our hierarchy.
1995 if (private->parent)
1996 _gdk_windowing_window_destroy_foreign (window);
1998 /* Also for historical reasons, we remove any filters
1999 * on a foreign window when it or a parent is destroyed;
2000 * this likely causes problems if two separate portions
2001 * of code are maintaining filter lists on a foreign window.
2003 window_remove_filters (window);
2007 if (private->parent)
2009 GdkWindowObject *parent_private = (GdkWindowObject *)private->parent;
2011 if (parent_private->children)
2012 parent_private->children = g_list_remove (parent_private->children, window);
2015 GDK_WINDOW_IS_MAPPED (window))
2017 recompute_visible_regions (private, TRUE, FALSE);
2018 gdk_window_invalidate_in_parent (private);
2022 gdk_window_free_paint_stack (window);
2024 if (private->bg_pixmap &&
2025 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
2026 private->bg_pixmap != GDK_NO_BG)
2028 g_object_unref (private->bg_pixmap);
2029 private->bg_pixmap = NULL;
2032 if (private->window_type == GDK_WINDOW_FOREIGN)
2033 g_assert (private->children == NULL);
2036 children = tmp = private->children;
2037 private->children = NULL;
2041 temp_window = tmp->data;
2044 temp_private = (GdkWindowObject*) temp_window;
2046 _gdk_window_destroy_hierarchy (temp_window,
2048 recursing_native || gdk_window_has_impl (private),
2052 g_list_free (children);
2055 _gdk_window_clear_update_area (window);
2057 if (private->cairo_surface)
2059 cairo_surface_finish (private->cairo_surface);
2060 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
2065 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
2067 if (private->extension_events)
2068 impl_iface->input_window_destroy (window);
2070 if (gdk_window_has_impl (private))
2071 impl_iface->destroy (window, recursing_native,
2075 /* hide to make sure we repaint and break grabs */
2076 gdk_window_hide (window);
2079 private->state |= GDK_WINDOW_STATE_WITHDRAWN;
2080 private->parent = NULL;
2081 private->destroyed = TRUE;
2083 window_remove_filters (window);
2085 gdk_drawable_set_colormap (GDK_DRAWABLE (window), NULL);
2087 /* If we own the redirect, free it */
2088 if (private->redirect && private->redirect->redirected == private)
2089 gdk_window_redirect_free (private->redirect);
2091 private->redirect = NULL;
2093 if (display->pointer_info.toplevel_under_pointer == window)
2095 g_object_unref (display->pointer_info.toplevel_under_pointer);
2096 display->pointer_info.toplevel_under_pointer = NULL;
2099 if (private->clip_region)
2101 gdk_region_destroy (private->clip_region);
2102 private->clip_region = NULL;
2105 if (private->clip_region_with_children)
2107 gdk_region_destroy (private->clip_region_with_children);
2108 private->clip_region_with_children = NULL;
2111 if (private->outstanding_moves)
2113 g_list_foreach (private->outstanding_moves, (GFunc)gdk_window_region_move_free, NULL);
2114 g_list_free (private->outstanding_moves);
2115 private->outstanding_moves = NULL;
2123 * _gdk_window_destroy:
2124 * @window: a #GdkWindow
2125 * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
2126 * external agency. The window has already been destroyed and no
2127 * windowing system calls should be made. (This may never happen
2128 * for some windowing systems.)
2130 * Internal function to destroy a window. Like gdk_window_destroy(),
2131 * but does not drop the reference count created by gdk_window_new().
2134 _gdk_window_destroy (GdkWindow *window,
2135 gboolean foreign_destroy)
2137 _gdk_window_destroy_hierarchy (window, FALSE, FALSE, foreign_destroy);
2141 * gdk_window_destroy:
2142 * @window: a #GdkWindow
2144 * Destroys the window system resources associated with @window and decrements @window's
2145 * reference count. The window system resources for all children of @window are also
2146 * destroyed, but the children's reference counts are not decremented.
2148 * Note that a window will not be destroyed automatically when its reference count
2149 * reaches zero. You must call this function yourself before that happens.
2153 gdk_window_destroy (GdkWindow *window)
2155 _gdk_window_destroy_hierarchy (window, FALSE, FALSE, FALSE);
2156 g_object_unref (window);
2160 * gdk_window_set_user_data:
2161 * @window: a #GdkWindow
2162 * @user_data: user data
2164 * For most purposes this function is deprecated in favor of
2165 * g_object_set_data(). However, for historical reasons GTK+ stores
2166 * the #GtkWidget that owns a #GdkWindow as user data on the
2167 * #GdkWindow. So, custom widget implementations should use
2168 * this function for that. If GTK+ receives an event for a #GdkWindow,
2169 * and the user data for the window is non-%NULL, GTK+ will assume the
2170 * user data is a #GtkWidget, and forward the event to that widget.
2174 gdk_window_set_user_data (GdkWindow *window,
2177 g_return_if_fail (GDK_IS_WINDOW (window));
2179 ((GdkWindowObject*)window)->user_data = user_data;
2183 * gdk_window_get_user_data:
2184 * @window: a #GdkWindow
2185 * @data: return location for user data
2187 * Retrieves the user data for @window, which is normally the widget
2188 * that @window belongs to. See gdk_window_set_user_data().
2192 gdk_window_get_user_data (GdkWindow *window,
2195 g_return_if_fail (GDK_IS_WINDOW (window));
2197 *data = ((GdkWindowObject*)window)->user_data;
2201 * gdk_window_get_window_type:
2202 * @window: a #GdkWindow
2204 * Gets the type of the window. See #GdkWindowType.
2206 * Return value: type of window
2209 gdk_window_get_window_type (GdkWindow *window)
2211 g_return_val_if_fail (GDK_IS_WINDOW (window), (GdkWindowType) -1);
2213 return GDK_WINDOW_TYPE (window);
2217 * gdk_window_is_destroyed:
2218 * @window: a #GdkWindow
2220 * Check to see if a window is destroyed..
2222 * Return value: %TRUE if the window is destroyed
2225 gdk_window_is_destroyed (GdkWindow *window)
2227 return GDK_WINDOW_DESTROYED (window);
2231 * gdk_window_get_position:
2232 * @window: a #GdkWindow
2233 * @x: X coordinate of window
2234 * @y: Y coordinate of window
2236 * Obtains the position of the window as reported in the
2237 * most-recently-processed #GdkEventConfigure. Contrast with
2238 * gdk_window_get_geometry() which queries the X server for the
2239 * current window position, regardless of which events have been
2240 * received or processed.
2242 * The position coordinates are relative to the window's parent window.
2246 gdk_window_get_position (GdkWindow *window,
2250 GdkWindowObject *obj;
2252 g_return_if_fail (GDK_IS_WINDOW (window));
2254 obj = (GdkWindowObject*) window;
2263 * gdk_window_get_parent:
2264 * @window: a #GdkWindow
2266 * Obtains the parent of @window, as known to GDK. Does not query the
2267 * X server; thus this returns the parent as passed to gdk_window_new(),
2268 * not the actual parent. This should never matter unless you're using
2269 * Xlib calls mixed with GDK calls on the X11 platform. It may also
2270 * matter for toplevel windows, because the window manager may choose
2273 * Return value: parent of @window
2276 gdk_window_get_parent (GdkWindow *window)
2278 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2280 return (GdkWindow*) ((GdkWindowObject*) window)->parent;
2284 * gdk_window_get_toplevel:
2285 * @window: a #GdkWindow
2287 * Gets the toplevel window that's an ancestor of @window.
2289 * Any window type but %GDK_WINDOW_CHILD is considered a
2290 * toplevel window, as is a %GDK_WINDOW_CHILD window that
2291 * has a root window as parent.
2293 * Return value: the toplevel window containing @window
2296 gdk_window_get_toplevel (GdkWindow *window)
2298 GdkWindowObject *obj;
2300 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2302 obj = (GdkWindowObject *)window;
2304 while (obj->window_type == GDK_WINDOW_CHILD)
2306 if (gdk_window_is_toplevel (obj))
2311 return GDK_WINDOW (obj);
2315 * gdk_window_get_children:
2316 * @window: a #GdkWindow
2318 * Gets the list of children of @window known to GDK.
2319 * This function only returns children created via GDK,
2320 * so for example it's useless when used with the root window;
2321 * it only returns windows an application created itself.
2323 * The returned list must be freed, but the elements in the
2326 * Return value: list of child windows inside @window
2329 gdk_window_get_children (GdkWindow *window)
2331 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2333 if (GDK_WINDOW_DESTROYED (window))
2336 return g_list_copy (GDK_WINDOW_OBJECT (window)->children);
2340 * gdk_window_peek_children:
2341 * @window: a #GdkWindow
2343 * Like gdk_window_get_children(), but does not copy the list of
2344 * children, so the list does not need to be freed.
2346 * Return value: a reference to the list of child windows in @window
2349 gdk_window_peek_children (GdkWindow *window)
2351 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2353 if (GDK_WINDOW_DESTROYED (window))
2356 return GDK_WINDOW_OBJECT (window)->children;
2360 * gdk_window_add_filter:
2361 * @window: a #GdkWindow
2362 * @function: filter callback
2363 * @data: data to pass to filter callback
2365 * Adds an event filter to @window, allowing you to intercept events
2366 * before they reach GDK. This is a low-level operation and makes it
2367 * easy to break GDK and/or GTK+, so you have to know what you're
2368 * doing. Pass %NULL for @window to get all events for all windows,
2369 * instead of events for a specific window.
2371 * See gdk_display_add_client_message_filter() if you are interested
2372 * in X ClientMessage events.
2375 gdk_window_add_filter (GdkWindow *window,
2376 GdkFilterFunc function,
2379 GdkWindowObject *private;
2381 GdkEventFilter *filter;
2383 g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
2385 private = (GdkWindowObject*) window;
2386 if (private && GDK_WINDOW_DESTROYED (window))
2389 /* Filters are for the native events on the native window, so
2390 ensure there is a native window. */
2392 gdk_window_ensure_native (window);
2395 tmp_list = private->filters;
2397 tmp_list = _gdk_default_filters;
2401 filter = (GdkEventFilter *)tmp_list->data;
2402 if ((filter->function == function) && (filter->data == data))
2404 tmp_list = tmp_list->next;
2407 filter = g_new (GdkEventFilter, 1);
2408 filter->function = function;
2409 filter->data = data;
2412 private->filters = g_list_append (private->filters, filter);
2414 _gdk_default_filters = g_list_append (_gdk_default_filters, filter);
2418 * gdk_window_remove_filter:
2419 * @window: a #GdkWindow
2420 * @function: previously-added filter function
2421 * @data: user data for previously-added filter function
2423 * Remove a filter previously added with gdk_window_add_filter().
2427 gdk_window_remove_filter (GdkWindow *window,
2428 GdkFilterFunc function,
2431 GdkWindowObject *private;
2432 GList *tmp_list, *node;
2433 GdkEventFilter *filter;
2435 g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
2437 private = (GdkWindowObject*) window;
2440 tmp_list = private->filters;
2442 tmp_list = _gdk_default_filters;
2446 filter = (GdkEventFilter *)tmp_list->data;
2448 tmp_list = tmp_list->next;
2450 if ((filter->function == function) && (filter->data == data))
2453 private->filters = g_list_remove_link (private->filters, node);
2455 _gdk_default_filters = g_list_remove_link (_gdk_default_filters, node);
2456 g_list_free_1 (node);
2465 * gdk_screen_get_toplevel_windows:
2466 * @screen: The #GdkScreen where the toplevels are located.
2468 * Obtains a list of all toplevel windows known to GDK on the screen @screen.
2469 * A toplevel window is a child of the root window (see
2470 * gdk_get_default_root_window()).
2472 * The returned list should be freed with g_list_free(), but
2473 * its elements need not be freed.
2475 * Return value: list of toplevel windows, free with g_list_free()
2480 gdk_screen_get_toplevel_windows (GdkScreen *screen)
2482 GdkWindow * root_window;
2483 GList *new_list = NULL;
2486 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
2488 root_window = gdk_screen_get_root_window (screen);
2490 tmp_list = ((GdkWindowObject *)root_window)->children;
2493 GdkWindowObject *w = tmp_list->data;
2495 if (w->window_type != GDK_WINDOW_FOREIGN)
2496 new_list = g_list_prepend (new_list, w);
2497 tmp_list = tmp_list->next;
2504 * gdk_window_get_toplevels:
2506 * Obtains a list of all toplevel windows known to GDK on the default
2507 * screen (see gdk_screen_get_toplevel_windows()).
2508 * A toplevel window is a child of the root window (see
2509 * gdk_get_default_root_window()).
2511 * The returned list should be freed with g_list_free(), but
2512 * its elements need not be freed.
2514 * Return value: list of toplevel windows, free with g_list_free()
2516 * Deprecated: 2.16: Use gdk_screen_get_toplevel_windows() instead.
2519 gdk_window_get_toplevels (void)
2521 return gdk_screen_get_toplevel_windows (gdk_screen_get_default ());
2525 * gdk_window_is_visible:
2526 * @window: a #GdkWindow
2528 * Checks whether the window has been mapped (with gdk_window_show() or
2529 * gdk_window_show_unraised()).
2531 * Return value: %TRUE if the window is mapped
2534 gdk_window_is_visible (GdkWindow *window)
2536 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2538 return GDK_WINDOW_IS_MAPPED (window);
2542 * gdk_window_is_viewable:
2543 * @window: a #GdkWindow
2545 * Check if the window and all ancestors of the window are
2546 * mapped. (This is not necessarily "viewable" in the X sense, since
2547 * we only check as far as we have GDK window parents, not to the root
2550 * Return value: %TRUE if the window is viewable
2553 gdk_window_is_viewable (GdkWindow *window)
2555 GdkWindowObject *private = (GdkWindowObject *)window;
2557 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2559 if (private->destroyed)
2562 return private->viewable;
2566 * gdk_window_get_state:
2567 * @window: a #GdkWindow
2569 * Gets the bitwise OR of the currently active window state flags,
2570 * from the #GdkWindowState enumeration.
2572 * Return value: window state bitfield
2575 gdk_window_get_state (GdkWindow *window)
2577 GdkWindowObject *private = (GdkWindowObject *)window;
2579 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2581 return private->state;
2585 /* This creates an empty "implicit" paint region for the impl window.
2586 * By itself this does nothing, but real paints to this window
2587 * or children of it can use this pixmap as backing to avoid allocating
2588 * multiple pixmaps for subwindow rendering. When doing so they
2589 * add to the region of the implicit paint region, which will be
2590 * pushed to the window when the implicit paint region is ended.
2591 * Such paints should not copy anything to the window on paint end, but
2592 * should rely on the implicit paint end.
2593 * The implicit paint will be automatically ended if someone draws
2594 * directly to the window or a child window.
2597 gdk_window_begin_implicit_paint (GdkWindow *window, GdkRectangle *rect)
2599 GdkWindowObject *private = (GdkWindowObject *)window;
2600 GdkWindowPaint *paint;
2602 g_assert (gdk_window_has_impl (private));
2604 if (_gdk_native_windows)
2605 return FALSE; /* No need for implicit paints since we can't merge draws anyway */
2607 if (GDK_IS_PAINTABLE (private->impl))
2608 return FALSE; /* Implementation does double buffering */
2610 if (private->paint_stack != NULL ||
2611 private->implicit_paint != NULL)
2612 return FALSE; /* Don't stack implicit paints */
2614 /* Never do implicit paints for foreign windows, they don't need
2615 * double buffer combination since they have no client side children,
2616 * and creating pixmaps for them is risky since they could disappear
2619 if (private->window_type == GDK_WINDOW_FOREIGN)
2622 paint = g_new (GdkWindowPaint, 1);
2623 paint->region = gdk_region_new (); /* Empty */
2624 paint->x_offset = rect->x;
2625 paint->y_offset = rect->y;
2626 paint->uses_implicit = FALSE;
2627 paint->flushed = FALSE;
2628 paint->surface = NULL;
2630 gdk_pixmap_new (window,
2631 MAX (rect->width, 1), MAX (rect->height, 1), -1);
2633 private->implicit_paint = paint;
2638 /* Ensure that all content related to this (sub)window is pushed to the
2639 native region. If there is an active paint then that area is not
2640 pushed, in order to not show partially finished double buffers. */
2642 gdk_window_flush_implicit_paint (GdkWindow *window)
2644 GdkWindowObject *private = (GdkWindowObject *)window;
2645 GdkWindowObject *impl_window;
2646 GdkWindowPaint *paint;
2651 impl_window = gdk_window_get_impl_window (private);
2652 if (impl_window->implicit_paint == NULL)
2655 paint = impl_window->implicit_paint;
2656 paint->flushed = TRUE;
2657 region = gdk_region_copy (private->clip_region_with_children);
2659 /* Don't flush active double buffers, as that may show partially done
2661 for (list = private->paint_stack; list != NULL; list = list->next)
2663 GdkWindowPaint *tmp_paint = list->data;
2665 gdk_region_subtract (region, tmp_paint->region);
2668 gdk_region_offset (region, private->abs_x, private->abs_y);
2669 gdk_region_intersect (region, paint->region);
2671 if (!gdk_region_empty (region))
2673 /* Remove flushed region from the implicit paint */
2674 gdk_region_subtract (paint->region, region);
2676 /* Some regions are valid, push these to window now */
2677 tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
2678 _gdk_gc_set_clip_region_internal (tmp_gc, region, TRUE);
2679 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2680 0, 0, paint->x_offset, paint->y_offset, -1, -1);
2681 /* Reset clip region of the cached GdkGC */
2682 gdk_gc_set_clip_region (tmp_gc, NULL);
2685 gdk_region_destroy (region);
2688 /* Ends an implicit paint, paired with gdk_window_begin_implicit_paint returning TRUE */
2690 gdk_window_end_implicit_paint (GdkWindow *window)
2692 GdkWindowObject *private = (GdkWindowObject *)window;
2693 GdkWindowPaint *paint;
2696 g_assert (gdk_window_has_impl (private));
2698 g_assert (private->implicit_paint != NULL);
2700 paint = private->implicit_paint;
2702 private->implicit_paint = NULL;
2704 if (!gdk_region_empty (paint->region))
2706 /* Some regions are valid, push these to window now */
2707 tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
2708 _gdk_gc_set_clip_region_internal (tmp_gc, paint->region, TRUE);
2709 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2710 0, 0, paint->x_offset, paint->y_offset, -1, -1);
2711 /* Reset clip region of the cached GdkGC */
2712 gdk_gc_set_clip_region (tmp_gc, NULL);
2715 gdk_region_destroy (paint->region);
2717 g_object_unref (paint->pixmap);
2722 * gdk_window_begin_paint_rect:
2723 * @window: a #GdkWindow
2724 * @rectangle: rectangle you intend to draw to
2726 * A convenience wrapper around gdk_window_begin_paint_region() which
2727 * creates a rectangular region for you. See
2728 * gdk_window_begin_paint_region() for details.
2732 gdk_window_begin_paint_rect (GdkWindow *window,
2733 const GdkRectangle *rectangle)
2737 g_return_if_fail (GDK_IS_WINDOW (window));
2739 region = gdk_region_rectangle (rectangle);
2740 gdk_window_begin_paint_region (window, region);
2741 gdk_region_destroy (region);
2745 * gdk_window_begin_paint_region:
2746 * @window: a #GdkWindow
2747 * @region: region you intend to draw to
2749 * Indicates that you are beginning the process of redrawing @region.
2750 * A backing store (offscreen buffer) large enough to contain @region
2751 * will be created. The backing store will be initialized with the
2752 * background color or background pixmap for @window. Then, all
2753 * drawing operations performed on @window will be diverted to the
2754 * backing store. When you call gdk_window_end_paint(), the backing
2755 * store will be copied to @window, making it visible onscreen. Only
2756 * the part of @window contained in @region will be modified; that is,
2757 * drawing operations are clipped to @region.
2759 * The net result of all this is to remove flicker, because the user
2760 * sees the finished product appear all at once when you call
2761 * gdk_window_end_paint(). If you draw to @window directly without
2762 * calling gdk_window_begin_paint_region(), the user may see flicker
2763 * as individual drawing operations are performed in sequence. The
2764 * clipping and background-initializing features of
2765 * gdk_window_begin_paint_region() are conveniences for the
2766 * programmer, so you can avoid doing that work yourself.
2768 * When using GTK+, the widget system automatically places calls to
2769 * gdk_window_begin_paint_region() and gdk_window_end_paint() around
2770 * emissions of the expose_event signal. That is, if you're writing an
2771 * expose event handler, you can assume that the exposed area in
2772 * #GdkEventExpose has already been cleared to the window background,
2773 * is already set as the clip region, and already has a backing store.
2774 * Therefore in most cases, application code need not call
2775 * gdk_window_begin_paint_region(). (You can disable the automatic
2776 * calls around expose events on a widget-by-widget basis by calling
2777 * gtk_widget_set_double_buffered().)
2779 * If you call this function multiple times before calling the
2780 * matching gdk_window_end_paint(), the backing stores are pushed onto
2781 * a stack. gdk_window_end_paint() copies the topmost backing store
2782 * onscreen, subtracts the topmost region from all other regions in
2783 * the stack, and pops the stack. All drawing operations affect only
2784 * the topmost backing store in the stack. One matching call to
2785 * gdk_window_end_paint() is required for each call to
2786 * gdk_window_begin_paint_region().
2790 gdk_window_begin_paint_region (GdkWindow *window,
2791 const GdkRegion *region)
2793 #ifdef USE_BACKING_STORE
2794 GdkWindowObject *private = (GdkWindowObject *)window;
2795 GdkRectangle clip_box;
2796 GdkWindowPaint *paint, *implicit_paint;
2797 GdkWindowObject *impl_window;
2800 g_return_if_fail (GDK_IS_WINDOW (window));
2802 if (GDK_WINDOW_DESTROYED (window))
2805 if (GDK_IS_PAINTABLE (private->impl))
2807 GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
2809 if (iface->begin_paint_region)
2810 iface->begin_paint_region ((GdkPaintable*)private->impl, window, region);
2815 impl_window = gdk_window_get_impl_window (private);
2816 implicit_paint = impl_window->implicit_paint;
2818 paint = g_new (GdkWindowPaint, 1);
2819 paint->region = gdk_region_copy (region);
2820 paint->region_tag = new_region_tag ();
2822 gdk_region_intersect (paint->region, private->clip_region_with_children);
2823 gdk_region_get_clipbox (paint->region, &clip_box);
2825 /* Convert to impl coords */
2826 gdk_region_offset (paint->region, private->abs_x, private->abs_y);
2828 /* Mark the region as valid on the implicit paint */
2831 gdk_region_union (implicit_paint->region, paint->region);
2833 /* Convert back to normal coords */
2834 gdk_region_offset (paint->region, -private->abs_x, -private->abs_y);
2840 paint->uses_implicit = TRUE;
2841 paint->pixmap = g_object_ref (implicit_paint->pixmap);
2842 paint->x_offset = -private->abs_x + implicit_paint->x_offset;
2843 paint->y_offset = -private->abs_y + implicit_paint->y_offset;
2845 gdk_drawable_get_size (paint->pixmap, &width, &height);
2846 paint->surface = _gdk_drawable_create_cairo_surface (paint->pixmap, width, height);
2850 paint->uses_implicit = FALSE;
2851 paint->x_offset = clip_box.x;
2852 paint->y_offset = clip_box.y;
2854 gdk_pixmap_new (window,
2855 MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1);
2856 paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap);
2860 cairo_surface_set_device_offset (paint->surface,
2861 -paint->x_offset, -paint->y_offset);
2863 for (list = private->paint_stack; list != NULL; list = list->next)
2865 GdkWindowPaint *tmp_paint = list->data;
2867 gdk_region_subtract (tmp_paint->region, paint->region);
2870 private->paint_stack = g_slist_prepend (private->paint_stack, paint);
2872 if (!gdk_region_empty (paint->region))
2874 gdk_window_clear_backing_region (window,
2878 #endif /* USE_BACKING_STORE */
2882 setup_redirect_clip (GdkWindow *window,
2887 GdkWindowObject *private = (GdkWindowObject *)window;
2888 GdkRegion *visible_region;
2889 GdkRectangle dest_rect;
2891 GdkWindow *toplevel;
2892 int x_offset, y_offset;
2894 toplevel = GDK_WINDOW (private->redirect->redirected);
2896 /* Get the clip region for gc clip rect + window hierarchy in
2897 window relative coords */
2899 _gdk_window_calculate_full_clip_region (window, toplevel,
2904 /* Compensate for the source pos/size */
2905 x_offset -= private->redirect->src_x;
2906 y_offset -= private->redirect->src_y;
2907 dest_rect.x = -x_offset;
2908 dest_rect.y = -y_offset;
2909 dest_rect.width = private->redirect->width;
2910 dest_rect.height = private->redirect->height;
2911 tmpreg = gdk_region_rectangle (&dest_rect);
2912 gdk_region_intersect (visible_region, tmpreg);
2913 gdk_region_destroy (tmpreg);
2915 /* Compensate for the dest pos */
2916 x_offset += private->redirect->dest_x;
2917 y_offset += private->redirect->dest_y;
2919 gdk_gc_set_clip_region (gc, visible_region); /* This resets clip origin! */
2921 /* offset clip and tiles from window coords to pixmaps coords */
2922 gdk_gc_offset (gc, -x_offset, -y_offset);
2924 gdk_region_destroy (visible_region);
2926 *x_offset_out = x_offset;
2927 *y_offset_out = y_offset;
2931 * gdk_window_end_paint:
2932 * @window: a #GdkWindow
2934 * Indicates that the backing store created by the most recent call to
2935 * gdk_window_begin_paint_region() should be copied onscreen and
2936 * deleted, leaving the next-most-recent backing store or no backing
2937 * store at all as the active paint region. See
2938 * gdk_window_begin_paint_region() for full details. It is an error to
2939 * call this function without a matching
2940 * gdk_window_begin_paint_region() first.
2944 gdk_window_end_paint (GdkWindow *window)
2946 #ifdef USE_BACKING_STORE
2947 GdkWindowObject *private = (GdkWindowObject *)window;
2948 GdkWindowObject *composited;
2949 GdkWindowPaint *paint;
2951 GdkRectangle clip_box;
2952 gint x_offset, y_offset;
2953 GdkRegion *full_clip;
2955 g_return_if_fail (GDK_IS_WINDOW (window));
2957 if (GDK_WINDOW_DESTROYED (window))
2960 if (GDK_IS_PAINTABLE (private->impl))
2962 GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
2964 if (iface->end_paint)
2965 iface->end_paint ((GdkPaintable*)private->impl);
2969 if (private->paint_stack == NULL)
2971 g_warning (G_STRLOC": no preceding call to gdk_window_begin_paint_region(), see documentation");
2975 paint = private->paint_stack->data;
2977 private->paint_stack = g_slist_delete_link (private->paint_stack,
2978 private->paint_stack);
2980 gdk_region_get_clipbox (paint->region, &clip_box);
2982 tmp_gc = _gdk_drawable_get_scratch_gc (window, FALSE);
2984 x_offset = -private->abs_x;
2985 y_offset = -private->abs_y;
2987 if (!paint->uses_implicit)
2989 gdk_window_flush_outstanding_moves (window);
2991 full_clip = gdk_region_copy (private->clip_region_with_children);
2992 gdk_region_intersect (full_clip, paint->region);
2993 _gdk_gc_set_clip_region_internal (tmp_gc, full_clip, TRUE); /* Takes ownership of full_clip */
2994 gdk_gc_set_clip_origin (tmp_gc, - x_offset, - y_offset);
2995 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2996 clip_box.x - paint->x_offset,
2997 clip_box.y - paint->y_offset,
2998 clip_box.x - x_offset, clip_box.y - y_offset,
2999 clip_box.width, clip_box.height);
3002 if (private->redirect)
3004 int x_offset, y_offset;
3006 /* TODO: Should also use paint->region for clipping */
3007 setup_redirect_clip (window, tmp_gc, &x_offset, &y_offset);
3008 gdk_draw_drawable (private->redirect->pixmap, tmp_gc, paint->pixmap,
3009 clip_box.x - paint->x_offset,
3010 clip_box.y - paint->y_offset,
3011 clip_box.x + x_offset,
3012 clip_box.y + y_offset,
3013 clip_box.width, clip_box.height);
3016 /* Reset clip region of the cached GdkGC */
3017 gdk_gc_set_clip_region (tmp_gc, NULL);
3019 cairo_surface_destroy (paint->surface);
3020 g_object_unref (paint->pixmap);
3021 gdk_region_destroy (paint->region);
3024 /* find a composited window in our hierarchy to signal its
3025 * parent to redraw, calculating the clip box as we go...
3027 * stop if parent becomes NULL since then we'd have nowhere
3028 * to draw (ie: 'composited' will always be non-NULL here).
3030 for (composited = private;
3032 composited = composited->parent)
3036 gdk_drawable_get_size (GDK_DRAWABLE (composited->parent),
3039 clip_box.x += composited->x;
3040 clip_box.y += composited->y;
3041 clip_box.width = MIN (clip_box.width, width - clip_box.x);
3042 clip_box.height = MIN (clip_box.height, height - clip_box.y);
3044 if (composited->composited)
3046 gdk_window_invalidate_rect (GDK_WINDOW (composited->parent),
3051 #endif /* USE_BACKING_STORE */
3055 gdk_window_free_paint_stack (GdkWindow *window)
3057 GdkWindowObject *private = (GdkWindowObject *)window;
3059 if (private->paint_stack)
3061 GSList *tmp_list = private->paint_stack;
3065 GdkWindowPaint *paint = tmp_list->data;
3067 if (tmp_list == private->paint_stack)
3068 g_object_unref (paint->pixmap);
3070 gdk_region_destroy (paint->region);
3073 tmp_list = tmp_list->next;
3076 g_slist_free (private->paint_stack);
3077 private->paint_stack = NULL;
3082 do_move_region_bits_on_impl (GdkWindowObject *impl_window,
3083 GdkRegion *dest_region, /* In impl window coords */
3087 GdkRectangle copy_rect;
3088 GdkWindowObject *private;
3089 GdkWindowImplIface *impl_iface;
3091 /* We need to get data from subwindows here, because we might have
3092 * shaped a native window over the moving region (with bg none,
3093 * so the pixels are still there). In fact we might need to get data
3094 * from overlapping native window that are not children of this window,
3095 * so we copy from the toplevel with INCLUDE_INFERIORS.
3097 private = impl_window;
3098 while (!gdk_window_is_toplevel (private))
3100 dx -= private->parent->abs_x + private->x;
3101 dy -= private->parent->abs_y + private->y;
3102 private = gdk_window_get_impl_window (private->parent);
3104 tmp_gc = _gdk_drawable_get_subwindow_scratch_gc ((GdkWindow *)private);
3106 gdk_region_get_clipbox (dest_region, ©_rect);
3107 gdk_gc_set_clip_region (tmp_gc, dest_region);
3109 /* The region area is moved and we queue translations for all expose events
3110 to the source area that were sent prior to the copy */
3111 gdk_region_offset (dest_region, -dx, -dy); /* Move to source region */
3112 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
3114 impl_iface->queue_translation ((GdkWindow *)impl_window,
3116 dest_region, dx, dy);
3118 gdk_draw_drawable (impl_window->impl,
3121 copy_rect.x-dx, copy_rect.y-dy,
3122 copy_rect.x, copy_rect.y,
3123 copy_rect.width, copy_rect.height);
3124 gdk_gc_set_clip_region (tmp_gc, NULL);
3127 static GdkWindowRegionMove *
3128 gdk_window_region_move_new (GdkRegion *region,
3131 GdkWindowRegionMove *move;
3133 move = g_slice_new (GdkWindowRegionMove);
3134 move->dest_region = gdk_region_copy (region);
3142 gdk_window_region_move_free (GdkWindowRegionMove *move)
3144 gdk_region_destroy (move->dest_region);
3145 g_slice_free (GdkWindowRegionMove, move);
3149 append_move_region (GdkWindowObject *impl_window,
3150 GdkRegion *new_dest_region,
3153 GdkWindowRegionMove *move, *old_move;
3154 GdkRegion *new_total_region, *old_total_region;
3155 GdkRegion *source_overlaps_destination;
3156 GdkRegion *non_overwritten;
3157 gboolean added_move;
3160 if (gdk_region_empty (new_dest_region))
3163 /* In principle this could just append the move to the list of outstanding
3164 moves that will be replayed before drawing anything when we're handling
3165 exposes. However, we'd like to do a bit better since its commonly the case
3166 that we get multiple copies where A is copied to B and then B is copied
3167 to C, and we'd like to express this as a simple copy A to C operation. */
3169 /* We approach this by taking the new move and pushing it ahead of moves
3170 starting at the end of the list and stopping when its not safe to do so.
3171 It's not safe to push past a move if either the source of the new move
3172 is in the destination of the old move, or if the destination of the new
3173 move is in the source of the new move, or if the destination of the new
3174 move overlaps the destination of the old move. We simplify this by
3175 just comparing the total regions (src + dest) */
3176 new_total_region = gdk_region_copy (new_dest_region);
3177 gdk_region_offset (new_total_region, -dx, -dy);
3178 gdk_region_union (new_total_region, new_dest_region);
3181 for (l = g_list_last (impl_window->outstanding_moves); l != NULL; l = prev)
3186 old_total_region = gdk_region_copy (old_move->dest_region);
3187 gdk_region_offset (old_total_region, -old_move->dx, -old_move->dy);
3188 gdk_region_union (old_total_region, old_move->dest_region);
3190 gdk_region_intersect (old_total_region, new_total_region);
3191 /* If these regions intersect then its not safe to push the
3192 new region before the old one */
3193 if (!gdk_region_empty (old_total_region))
3195 /* The area where the new moves source overlaps the old ones
3197 source_overlaps_destination = gdk_region_copy (new_dest_region);
3198 gdk_region_offset (source_overlaps_destination, -dx, -dy);
3199 gdk_region_intersect (source_overlaps_destination, old_move->dest_region);
3200 gdk_region_offset (source_overlaps_destination, dx, dy);
3202 /* We can do all sort of optimizations here, but to do things safely it becomes
3203 quite complicated. However, a very common case is that you copy something first,
3204 then copy all that or a subset of it to a new location (i.e. if you scroll twice
3205 in the same direction). We'd like to detect this case and optimize it to one
3207 if (gdk_region_equal (source_overlaps_destination, new_dest_region))
3209 /* This means we might be able to replace the old move and the new one
3210 with the new one read from the old ones source, and a second copy of
3211 the non-overwritten parts of the old move. However, such a split
3212 is only valid if the source in the old move isn't overwritten
3213 by the destination of the new one */
3215 /* the new destination of old move if split is ok: */
3216 non_overwritten = gdk_region_copy (old_move->dest_region);
3217 gdk_region_subtract (non_overwritten, new_dest_region);
3218 /* move to source region */
3219 gdk_region_offset (non_overwritten, -old_move->dx, -old_move->dy);
3221 gdk_region_intersect (non_overwritten, new_dest_region);
3222 if (gdk_region_empty (non_overwritten))
3225 move = gdk_window_region_move_new (new_dest_region,
3229 impl_window->outstanding_moves =
3230 g_list_insert_before (impl_window->outstanding_moves,
3232 gdk_region_subtract (old_move->dest_region, new_dest_region);
3234 gdk_region_destroy (non_overwritten);
3237 gdk_region_destroy (source_overlaps_destination);
3238 gdk_region_destroy (old_total_region);
3241 gdk_region_destroy (old_total_region);
3244 gdk_region_destroy (new_total_region);
3248 move = gdk_window_region_move_new (new_dest_region, dx, dy);
3251 impl_window->outstanding_moves =
3252 g_list_prepend (impl_window->outstanding_moves,
3255 impl_window->outstanding_moves =
3256 g_list_insert_before (impl_window->outstanding_moves,
3261 /* Moves bits and update area by dx/dy in impl window.
3262 Takes ownership of region to avoid copy (because we may change it) */
3264 move_region_on_impl (GdkWindowObject *impl_window,
3265 GdkRegion *region, /* In impl window coords */
3268 if ((dx == 0 && dy == 0) ||
3269 gdk_region_empty (region))
3271 gdk_region_destroy (region);
3275 g_assert (impl_window == gdk_window_get_impl_window (impl_window));
3277 /* Move any old invalid regions in the copy source area by dx/dy */
3278 if (impl_window->update_area)
3280 GdkRegion *update_area;
3282 update_area = gdk_region_copy (region);
3284 /* Convert from target to source */
3285 gdk_region_offset (update_area, -dx, -dy);
3286 gdk_region_intersect (update_area, impl_window->update_area);
3287 /* We only copy the area, so keep the old update area invalid.
3288 It would be safe to remove it too, as code that uses
3289 move_region_on_impl generally also invalidate the source
3290 area. However, it would just use waste cycles. */
3293 gdk_region_offset (update_area, dx, dy);
3294 gdk_region_union (impl_window->update_area, update_area);
3296 /* This area of the destination is now invalid,
3297 so no need to copy to it. */
3298 gdk_region_subtract (region, update_area);
3300 gdk_region_destroy (update_area);
3303 /* If we're currently exposing this window, don't copy to this
3304 destination, as it will be overdrawn when the expose is done,
3305 instead invalidate it and repaint later. */
3306 if (impl_window->implicit_paint)
3308 GdkWindowPaint *implicit_paint = impl_window->implicit_paint;
3309 GdkRegion *exposing;
3311 exposing = gdk_region_copy (implicit_paint->region);
3312 gdk_region_intersect (exposing, region);
3313 gdk_region_subtract (region, exposing);
3315 impl_window_add_update_area (impl_window, exposing);
3316 gdk_region_destroy (exposing);
3319 if (1) /* Enable flicker free handling of moves. */
3320 append_move_region (impl_window, region, dx, dy);
3322 do_move_region_bits_on_impl (impl_window,
3325 gdk_region_destroy (region);
3328 /* Flushes all outstanding changes to the window, call this
3329 * before drawing directly to the window (i.e. outside a begin/end_paint pair).
3332 gdk_window_flush_outstanding_moves (GdkWindow *window)
3334 GdkWindowObject *private;
3335 GdkWindowObject *impl_window;
3337 GdkWindowRegionMove *move;
3339 private = (GdkWindowObject *) window;
3341 impl_window = gdk_window_get_impl_window (private);
3343 for (l = impl_window->outstanding_moves; l != NULL; l = l->next)
3347 do_move_region_bits_on_impl (impl_window,
3348 move->dest_region, move->dx, move->dy);
3350 gdk_window_region_move_free (move);
3353 g_list_free (impl_window->outstanding_moves);
3354 impl_window->outstanding_moves = NULL;
3359 * @window: a #GdkWindow
3361 * Flush all outstanding cached operations on a window, leaving the
3362 * window in a state which reflects all that has been drawn before.
3364 * Gdk uses multiple kinds of caching to get better performance and
3365 * nicer drawing. For instance, during exposes all paints to a window
3366 * using double buffered rendering are keep on a pixmap until the last
3367 * window has been exposed. It also delays window moves/scrolls until
3368 * as long as possible until next update to avoid tearing when moving
3371 * Normally this should be completely invisible to applications, as
3372 * we automatically flush the windows when required, but this might
3373 * be needed if you for instance mix direct native drawing with
3374 * gdk drawing. For Gtk widgets that don't use double buffering this
3375 * will be called automatically before sending the expose event.
3380 gdk_window_flush (GdkWindow *window)
3382 gdk_window_flush_outstanding_moves (window);
3383 gdk_window_flush_implicit_paint (window);
3386 /* If we're about to move/resize or otherwise change the
3387 * hierarchy of a client side window in an impl and we're
3388 * called from an expose event handler then we need to
3389 * flush any already painted parts of the implicit paint
3390 * that are not part of the current paint, as these may
3391 * be used when scrolling or may overdraw the changes
3392 * caused by the hierarchy change.
3395 gdk_window_flush_if_exposing (GdkWindow *window)
3397 GdkWindowObject *private;
3398 GdkWindowObject *impl_window;
3400 private = (GdkWindowObject *) window;
3401 impl_window = gdk_window_get_impl_window (private);
3403 /* If we're in an implicit paint (i.e. in an expose handler, flush
3404 all the already finished exposes to get things to an uptodate state. */
3405 if (impl_window->implicit_paint)
3406 gdk_window_flush (window);
3411 gdk_window_flush_recursive_helper (GdkWindowObject *window,
3414 GdkWindowObject *child;
3417 for (l = window->children; l != NULL; l = l->next)
3421 if (child->impl == impl)
3422 /* Same impl, ignore */
3423 gdk_window_flush_recursive_helper (child, impl);
3425 gdk_window_flush_recursive (child);
3430 gdk_window_flush_recursive (GdkWindowObject *window)
3432 gdk_window_flush ((GdkWindow *)window);
3433 gdk_window_flush_recursive_helper (window, window->impl);
3437 gdk_window_get_offsets (GdkWindow *window,
3441 GdkWindowObject *private = (GdkWindowObject *)window;
3443 if (private->paint_stack)
3445 GdkWindowPaint *paint = private->paint_stack->data;
3446 *x_offset = paint->x_offset;
3447 *y_offset = paint->y_offset;
3451 *x_offset = -private->abs_x;
3452 *y_offset = -private->abs_y;
3457 * gdk_window_get_internal_paint_info:
3458 * @window: a #GdkWindow
3459 * @real_drawable: location to store the drawable to which drawing should be
3461 * @x_offset: location to store the X offset between coordinates in @window,
3462 * and the underlying window system primitive coordinates for
3464 * @y_offset: location to store the Y offset between coordinates in @window,
3465 * and the underlying window system primitive coordinates for
3468 * If you bypass the GDK layer and use windowing system primitives to
3469 * draw directly onto a #GdkWindow, then you need to deal with two
3470 * details: there may be an offset between GDK coordinates and windowing
3471 * system coordinates, and GDK may have redirected drawing to a offscreen
3472 * pixmap as the result of a gdk_window_begin_paint_region() calls.
3473 * This function allows retrieving the information you need to compensate
3474 * for these effects.
3476 * This function exposes details of the GDK implementation, and is thus
3477 * likely to change in future releases of GDK.
3480 gdk_window_get_internal_paint_info (GdkWindow *window,
3481 GdkDrawable **real_drawable,
3487 GdkWindowObject *private;
3489 g_return_if_fail (GDK_IS_WINDOW (window));
3491 private = (GdkWindowObject *)window;
3495 if (private->paint_stack)
3497 GdkWindowPaint *paint = private->paint_stack->data;
3498 *real_drawable = paint->pixmap;
3502 /* This means you're probably gonna be doing some weird shit
3503 directly to the window, so we flush all outstanding stuff */
3504 gdk_window_flush (window);
3505 *real_drawable = window;
3509 gdk_window_get_offsets (window, &x_off, &y_off);
3517 static GdkDrawable *
3518 start_draw_helper (GdkDrawable *drawable,
3523 GdkWindowObject *private = (GdkWindowObject *)drawable;
3524 gint x_offset, y_offset;
3526 gint old_clip_x = gc->clip_x_origin;
3527 gint old_clip_y = gc->clip_y_origin;
3529 guint32 clip_region_tag;
3530 GdkWindowPaint *paint;
3533 if (private->paint_stack)
3534 paint = private->paint_stack->data;
3538 x_offset = paint->x_offset;
3539 y_offset = paint->y_offset;
3543 x_offset = -private->abs_x;
3544 y_offset = -private->abs_y;
3547 if (x_offset != 0 || y_offset != 0)
3549 gdk_gc_set_clip_origin (gc,
3550 old_clip_x - x_offset,
3551 old_clip_y - y_offset);
3552 gdk_gc_set_ts_origin (gc,
3553 gc->ts_x_origin - x_offset,
3554 gc->ts_y_origin - y_offset);
3557 *x_offset_out = x_offset;
3558 *y_offset_out = y_offset;
3560 /* Add client side window clip region to gc */
3564 /* Only need clipping if using implicit paint, otherwise
3565 the pixmap is clipped when copying to the window in end_paint */
3566 if (paint->uses_implicit)
3568 /* This includes the window clip */
3569 clip = paint->region;
3571 clip_region_tag = paint->region_tag;
3573 /* After having set up the drawable clip rect on a GC we need to make sure
3574 * that we draw to th the impl, otherwise the pixmap code will reset the
3576 impl = ((GdkPixmapObject *)(paint->pixmap))->impl;
3580 /* Drawing directly to the window, flush anything outstanding to
3581 guarantee ordering. */
3582 gdk_window_flush ((GdkWindow *)drawable);
3584 /* Don't clip when drawing to root or all native */
3585 if (!_gdk_native_windows && private->window_type != GDK_WINDOW_ROOT)
3587 if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
3588 clip = private->clip_region_with_children;
3590 clip = private->clip_region;
3592 clip_region_tag = private->clip_tag;
3593 impl = private->impl;
3597 _gdk_gc_add_drawable_clip (gc,
3598 clip_region_tag, clip,
3599 /* If there was a clip origin set appart from the
3600 * window offset, need to take that into
3602 -old_clip_x, -old_clip_y);
3607 #define BEGIN_DRAW \
3609 GdkDrawable *impl; \
3610 gint x_offset, y_offset; \
3611 gint old_clip_x = gc->clip_x_origin; \
3612 gint old_clip_y = gc->clip_y_origin; \
3613 gint old_ts_x = gc->ts_x_origin; \
3614 gint old_ts_y = gc->ts_y_origin; \
3615 impl = start_draw_helper (drawable, gc, \
3616 &x_offset, &y_offset);
3619 if (x_offset != 0 || y_offset != 0) \
3621 gdk_gc_set_clip_origin (gc, old_clip_x, old_clip_y); \
3622 gdk_gc_set_ts_origin (gc, old_ts_x, old_ts_y); \
3627 gdk_window_create_gc (GdkDrawable *drawable,
3628 GdkGCValues *values,
3629 GdkGCValuesMask mask)
3631 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
3633 if (GDK_WINDOW_DESTROYED (drawable))
3636 return gdk_gc_new_with_values (((GdkWindowObject *) drawable)->impl,
3641 gdk_window_draw_rectangle (GdkDrawable *drawable,
3649 if (GDK_WINDOW_DESTROYED (drawable))
3653 gdk_draw_rectangle (impl, gc, filled,
3654 x - x_offset, y - y_offset, width, height);
3659 gdk_window_draw_arc (GdkDrawable *drawable,
3669 if (GDK_WINDOW_DESTROYED (drawable))
3673 gdk_draw_arc (impl, gc, filled,
3674 x - x_offset, y - y_offset,
3675 width, height, angle1, angle2);
3680 gdk_window_draw_polygon (GdkDrawable *drawable,
3686 GdkPoint *new_points;
3688 if (GDK_WINDOW_DESTROYED (drawable))
3693 if (x_offset != 0 || y_offset != 0)
3697 new_points = g_new (GdkPoint, npoints);
3698 for (i=0; i<npoints; i++)
3700 new_points[i].x = points[i].x - x_offset;
3701 new_points[i].y = points[i].y - y_offset;
3705 new_points = points;
3707 gdk_draw_polygon (impl, gc, filled, new_points, npoints);
3709 if (new_points != points)
3710 g_free (new_points);
3716 gdk_window_draw_text (GdkDrawable *drawable,
3724 if (GDK_WINDOW_DESTROYED (drawable))
3728 gdk_draw_text (impl, font, gc,
3729 x - x_offset, y - y_offset, text, text_length);
3734 gdk_window_draw_text_wc (GdkDrawable *drawable,
3739 const GdkWChar *text,
3742 if (GDK_WINDOW_DESTROYED (drawable))
3746 gdk_draw_text_wc (impl, font, gc,
3747 x - x_offset, y - y_offset, text, text_length);
3751 static GdkDrawable *
3752 gdk_window_get_source_drawable (GdkDrawable *drawable)
3754 GdkWindow *window = GDK_WINDOW (drawable);
3755 GdkWindowObject *private;
3757 private = (GdkWindowObject *) window;
3758 if (GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable)
3759 return GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable (private->impl);
3764 static GdkDrawable *
3765 gdk_window_get_composite_drawable (GdkDrawable *drawable,
3770 gint *composite_x_offset,
3771 gint *composite_y_offset)
3773 GdkWindowObject *private = (GdkWindowObject *)drawable;
3775 GdkPixmap *tmp_pixmap;
3778 gboolean overlap_buffer;
3779 GdkDrawable *source;
3780 GdkWindowObject *impl_window;
3781 GdkWindowPaint *implicit_paint;
3783 *composite_x_offset = -private->abs_x;
3784 *composite_y_offset = -private->abs_y;
3786 if ((GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable)))
3787 return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
3789 /* See if any buffered part is overlapping the part we want
3795 rect.height = height;
3797 overlap_buffer = FALSE;
3799 for (list = private->paint_stack; list != NULL; list = list->next)
3801 GdkWindowPaint *paint = list->data;
3802 GdkOverlapType overlap;
3804 overlap = gdk_region_rect_in (paint->region, &rect);
3806 if (overlap == GDK_OVERLAP_RECTANGLE_IN)
3808 *composite_x_offset = paint->x_offset;
3809 *composite_y_offset = paint->y_offset;
3811 return g_object_ref (paint->pixmap);
3813 else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
3815 overlap_buffer = TRUE;
3820 impl_window = gdk_window_get_impl_window (private);
3821 implicit_paint = impl_window->implicit_paint;
3824 GdkOverlapType overlap;
3826 rect.x += private->abs_x;
3827 rect.y += private->abs_y;
3829 overlap = gdk_region_rect_in (implicit_paint->region, &rect);
3830 if (overlap == GDK_OVERLAP_RECTANGLE_IN)
3832 *composite_x_offset = -private->abs_x + implicit_paint->x_offset;
3833 *composite_y_offset = -private->abs_y + implicit_paint->y_offset;
3835 return g_object_ref (implicit_paint->pixmap);
3837 else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
3838 overlap_buffer = TRUE;
3841 if (!overlap_buffer)
3842 return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
3844 tmp_pixmap = gdk_pixmap_new (drawable, width, height, -1);
3845 tmp_gc = _gdk_drawable_get_scratch_gc (tmp_pixmap, FALSE);
3847 source = _gdk_drawable_get_source_drawable (drawable);
3849 /* Copy the current window contents */
3850 gdk_draw_drawable (tmp_pixmap,
3852 GDK_WINDOW_OBJECT (source)->impl,
3853 x - *composite_x_offset,
3854 y - *composite_y_offset,
3858 /* paint the backing stores */
3861 GdkWindowPaint *paint = list->data;
3863 gdk_gc_set_clip_region (tmp_gc, paint->region);
3864 gdk_gc_set_clip_origin (tmp_gc, -x - paint->x_offset, -y - paint->y_offset);
3866 gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
3867 x - paint->x_offset,
3868 y - paint->y_offset,
3869 0, 0, width, height);
3872 for (list = private->paint_stack; list != NULL; list = list->next)
3874 GdkWindowPaint *paint = list->data;
3876 if (paint->uses_implicit)
3877 continue; /* We already copied this above */
3879 gdk_gc_set_clip_region (tmp_gc, paint->region);
3880 gdk_gc_set_clip_origin (tmp_gc, -x, -y);
3882 gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
3883 x - paint->x_offset,
3884 y - paint->y_offset,
3885 0, 0, width, height);
3888 /* Reset clip region of the cached GdkGC */
3889 gdk_gc_set_clip_region (tmp_gc, NULL);
3891 /* Set these to location of tmp_pixmap within the window */
3892 *composite_x_offset = x;
3893 *composite_y_offset = y;
3899 gdk_window_get_clip_region (GdkDrawable *drawable)
3901 GdkWindowObject *private = (GdkWindowObject *)drawable;
3904 result = gdk_region_copy (private->clip_region);
3906 if (private->paint_stack)
3908 GdkRegion *paint_region = gdk_region_new ();
3909 GSList *tmp_list = private->paint_stack;
3913 GdkWindowPaint *paint = tmp_list->data;
3915 gdk_region_union (paint_region, paint->region);
3917 tmp_list = tmp_list->next;
3920 gdk_region_intersect (result, paint_region);
3921 gdk_region_destroy (paint_region);
3928 gdk_window_get_visible_region (GdkDrawable *drawable)
3930 GdkWindowObject *private = (GdkWindowObject*) drawable;
3932 return gdk_region_copy (private->clip_region);
3936 gdk_window_draw_drawable (GdkDrawable *drawable,
3945 GdkDrawable *original_src)
3947 GdkWindowObject *private = (GdkWindowObject *)drawable;
3949 if (GDK_WINDOW_DESTROYED (drawable))
3954 /* Call the method directly to avoid getting the composite drawable again */
3955 GDK_DRAWABLE_GET_CLASS (impl)->draw_drawable_with_src (impl, gc,
3963 if (!private->paint_stack)
3965 /* We might have drawn from an obscured part of a client
3966 side window, if so we need to send graphics exposures */
3967 if (_gdk_gc_get_exposures (gc) &&
3968 GDK_IS_WINDOW (original_src))
3970 GdkRegion *exposure_region;
3978 exposure_region = gdk_region_rectangle (&r);
3980 if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
3981 clip = private->clip_region_with_children;
3983 clip = private->clip_region;
3984 gdk_region_intersect (exposure_region, clip);
3986 _gdk_gc_remove_drawable_clip (gc);
3987 clip = _gdk_gc_get_clip_region (gc);
3990 gdk_region_offset (exposure_region,
3993 gdk_region_intersect (exposure_region, clip);
3994 gdk_region_offset (exposure_region,
3999 /* Note: We don't clip by the clip mask if set, so this
4000 may invalidate to much */
4002 /* Remove the area that is correctly copied from the src.
4003 * Note that xsrc/ysrc has been corrected for abs_x/y offsets already,
4004 * which need to be undone */
4005 clip = gdk_drawable_get_visible_region (original_src);
4006 gdk_region_offset (clip,
4007 xdest - (xsrc - GDK_WINDOW_OBJECT (original_src)->abs_x),
4008 ydest - (ysrc - GDK_WINDOW_OBJECT (original_src)->abs_y));
4009 gdk_region_subtract (exposure_region, clip);
4010 gdk_region_destroy (clip);
4012 gdk_window_invalidate_region_full (GDK_WINDOW (private),
4014 _gdk_gc_get_subwindow (gc) == GDK_INCLUDE_INFERIORS,
4017 gdk_region_destroy (exposure_region);
4025 gdk_window_draw_points (GdkDrawable *drawable,
4030 GdkPoint *new_points;
4032 if (GDK_WINDOW_DESTROYED (drawable))
4037 if (x_offset != 0 || y_offset != 0)
4041 new_points = g_new (GdkPoint, npoints);
4042 for (i=0; i<npoints; i++)
4044 new_points[i].x = points[i].x - x_offset;
4045 new_points[i].y = points[i].y - y_offset;
4049 new_points = points;
4051 gdk_draw_points (impl, gc, new_points, npoints);
4053 if (new_points != points)
4054 g_free (new_points);
4060 gdk_window_draw_segments (GdkDrawable *drawable,
4065 GdkSegment *new_segs;
4067 if (GDK_WINDOW_DESTROYED (drawable))
4072 if (x_offset != 0 || y_offset != 0)
4076 new_segs = g_new (GdkSegment, nsegs);
4077 for (i=0; i<nsegs; i++)
4079 new_segs[i].x1 = segs[i].x1 - x_offset;
4080 new_segs[i].y1 = segs[i].y1 - y_offset;
4081 new_segs[i].x2 = segs[i].x2 - x_offset;
4082 new_segs[i].y2 = segs[i].y2 - y_offset;
4088 gdk_draw_segments (impl, gc, new_segs, nsegs);
4090 if (new_segs != segs)
4097 gdk_window_draw_lines (GdkDrawable *drawable,
4102 GdkPoint *new_points;
4104 if (GDK_WINDOW_DESTROYED (drawable))
4109 if (x_offset != 0 || y_offset != 0)
4113 new_points = g_new (GdkPoint, npoints);
4114 for (i=0; i<npoints; i++)
4116 new_points[i].x = points[i].x - x_offset;
4117 new_points[i].y = points[i].y - y_offset;
4121 new_points = points;
4123 gdk_draw_lines (impl, gc, new_points, npoints);
4125 if (new_points != points)
4126 g_free (new_points);
4132 gdk_window_draw_glyphs (GdkDrawable *drawable,
4137 PangoGlyphString *glyphs)
4139 if (GDK_WINDOW_DESTROYED (drawable))
4143 gdk_draw_glyphs (impl, gc, font,
4144 x - x_offset, y - y_offset, glyphs);
4149 gdk_window_draw_glyphs_transformed (GdkDrawable *drawable,
4151 PangoMatrix *matrix,
4155 PangoGlyphString *glyphs)
4157 PangoMatrix tmp_matrix;
4159 if (GDK_WINDOW_DESTROYED (drawable))
4164 if (x_offset != 0 || y_offset != 0)
4168 tmp_matrix = *matrix;
4169 tmp_matrix.x0 -= x_offset;
4170 tmp_matrix.y0 -= y_offset;
4171 matrix = &tmp_matrix;
4173 else if (GDK_PANGO_UNITS_OVERFLOWS (x_offset, y_offset))
4175 PangoMatrix identity = PANGO_MATRIX_INIT;
4177 tmp_matrix = identity;
4178 tmp_matrix.x0 -= x_offset;
4179 tmp_matrix.y0 -= y_offset;
4180 matrix = &tmp_matrix;
4184 x -= x_offset * PANGO_SCALE;
4185 y -= y_offset * PANGO_SCALE;
4189 gdk_draw_glyphs_transformed (impl, gc, matrix, font, x, y, glyphs);
4195 cairo_t *cr; /* if non-null, it means use this cairo context */
4196 GdkGC *gc; /* if non-null, it means use this GC instead */
4197 } BackingRectMethod;
4200 setup_backing_rect_method (BackingRectMethod *method, GdkWindow *window, GdkWindowPaint *paint, int x_offset_cairo, int y_offset_cairo)
4202 GdkWindowObject *private = (GdkWindowObject *)window;
4204 if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
4206 GdkWindowPaint tmp_paint;
4209 tmp_paint.x_offset += private->x;
4210 tmp_paint.y_offset += private->y;
4212 x_offset_cairo += private->x;
4213 y_offset_cairo += private->y;
4215 setup_backing_rect_method (method, GDK_WINDOW (private->parent), &tmp_paint, x_offset_cairo, y_offset_cairo);
4217 else if (private->bg_pixmap &&
4218 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
4219 private->bg_pixmap != GDK_NO_BG)
4221 /* This is a workaround for https://bugs.freedesktop.org/show_bug.cgi?id=4320.
4222 * In it, using a pixmap as a repeating pattern in Cairo, and painting it to a
4223 * pixmap destination surface, can be very slow (on the order of seconds for a
4224 * whole-screen copy). The workaround is to use pretty much the same code that
4225 * we used in GTK+ 2.6 (pre-Cairo), which clears the double-buffer pixmap with
4226 * a tiled GC XFillRectangle().
4229 /* Actually computing this flag is left as an exercise for the reader */
4230 #if defined (G_OS_UNIX)
4231 # define GDK_CAIRO_REPEAT_IS_FAST 0
4233 # define GDK_CAIRO_REPEAT_IS_FAST 1
4236 #if GDK_CAIRO_REPEAT_IS_FAST
4237 cairo_surface_t *surface = _gdk_drawable_ref_cairo_surface (private->bg_pixmap);
4238 cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
4239 cairo_surface_destroy (surface);
4241 if (x_offset_cairo != 0 || y_offset_cairo != 0)
4243 cairo_matrix_t matrix;
4244 cairo_matrix_init_translate (&matrix, x_offset_cairo, y_offset_cairo);
4245 cairo_pattern_set_matrix (pattern, &matrix);
4248 cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
4250 method->cr = cairo_create (paint->surface);
4253 cairo_set_source (method->cr, pattern);
4254 cairo_pattern_destroy (pattern);
4257 GdkGCValues gc_values;
4259 gc_values.fill = GDK_TILED;
4260 gc_values.tile = private->bg_pixmap;
4261 gc_values.ts_x_origin = -x_offset_cairo;
4262 gc_values.ts_y_origin = -y_offset_cairo;
4264 gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN;
4266 method->gc = gdk_gc_new_with_values (paint->pixmap, &gc_values, gc_mask);
4271 method->cr = cairo_create (paint->surface);
4273 gdk_cairo_set_source_color (method->cr, &private->bg_color);
4278 gdk_window_clear_backing_region (GdkWindow *window,
4281 GdkWindowObject *private = (GdkWindowObject *)window;
4282 GdkWindowPaint *paint = private->paint_stack->data;
4283 BackingRectMethod method;
4285 GdkRectangle clipbox;
4291 if (GDK_WINDOW_DESTROYED (window))
4295 timer = g_timer_new ();
4300 setup_backing_rect_method (&method, window, paint, 0, 0);
4302 clip = gdk_region_copy (paint->region);
4303 gdk_region_intersect (clip, region);
4304 gdk_region_get_clipbox (clip, &clipbox);
4309 g_assert (method.gc == NULL);
4311 gdk_cairo_region (method.cr, clip);
4312 cairo_fill (method.cr);
4314 cairo_destroy (method.cr);
4316 elapsed = g_timer_elapsed (timer, NULL);
4317 g_print ("Draw the background with Cairo: %fs\n", elapsed);
4322 g_assert (method.gc != NULL);
4324 gdk_gc_set_clip_region (method.gc, clip);
4325 gdk_draw_rectangle (window, method.gc, TRUE,
4326 clipbox.x, clipbox.y,
4327 clipbox.width, clipbox.height);
4328 g_object_unref (method.gc);
4331 elapsed = g_timer_elapsed (timer, NULL);
4332 g_print ("Draw the background with GDK: %fs\n", elapsed);
4336 gdk_region_destroy (clip);
4339 g_timer_destroy (timer);
4344 gdk_window_clear_backing_region_redirect (GdkWindow *window,
4347 GdkWindowObject *private = (GdkWindowObject *)window;
4348 GdkWindowRedirect *redirect = private->redirect;
4349 GdkRegion *clip_region;
4350 GdkRectangle clipbox;
4351 gint x_offset, y_offset;
4352 BackingRectMethod method;
4353 GdkWindowPaint paint;
4355 if (GDK_WINDOW_DESTROYED (window))
4358 clip_region = _gdk_window_calculate_full_clip_region (window,
4359 GDK_WINDOW (redirect->redirected),
4361 &x_offset, &y_offset);
4362 gdk_region_intersect (clip_region, region);
4364 /* offset is from redirected window origin to window origin, convert to
4365 the offset from the redirected pixmap origin to the window origin */
4366 x_offset += redirect->dest_x - redirect->src_x;
4367 y_offset += redirect->dest_y - redirect->src_y;
4369 /* Convert region to pixmap coords */
4370 gdk_region_offset (clip_region, x_offset, y_offset);
4374 paint.pixmap = redirect->pixmap;
4375 paint.surface = _gdk_drawable_ref_cairo_surface (redirect->pixmap);
4379 setup_backing_rect_method (&method, window, &paint, -x_offset, -y_offset);
4383 g_assert (method.gc == NULL);
4385 gdk_cairo_region (method.cr, clip_region);
4386 cairo_fill (method.cr);
4388 cairo_destroy (method.cr);
4392 g_assert (method.gc != NULL);
4394 gdk_region_get_clipbox (clip_region, &clipbox);
4395 gdk_gc_set_clip_region (method.gc, clip_region);
4396 gdk_draw_rectangle (redirect->pixmap, method.gc, TRUE,
4397 clipbox.x, clipbox.y,
4398 clipbox.width, clipbox.height);
4399 g_object_unref (method.gc);
4403 gdk_region_destroy (clip_region);
4404 cairo_surface_destroy (paint.surface);
4408 gdk_window_clear_backing_region_direct (GdkWindow *window,
4411 GdkWindowObject *private = (GdkWindowObject *)window;
4412 BackingRectMethod method;
4413 GdkWindowPaint paint;
4415 GdkRectangle clipbox;
4417 if (GDK_WINDOW_DESTROYED (window))
4422 paint.pixmap = window;
4423 paint.surface = _gdk_drawable_ref_cairo_surface (window);
4427 setup_backing_rect_method (&method, window, &paint, 0, 0);
4429 clip = gdk_region_copy (private->clip_region_with_children);
4430 gdk_region_intersect (clip, region);
4431 gdk_region_get_clipbox (clip, &clipbox);
4435 g_assert (method.gc == NULL);
4437 gdk_cairo_region (method.cr, clip);
4438 cairo_fill (method.cr);
4440 cairo_destroy (method.cr);
4444 g_assert (method.gc != NULL);
4446 gdk_gc_set_clip_region (method.gc, clip);
4447 gdk_draw_rectangle (window, method.gc, TRUE,
4448 clipbox.x, clipbox.y,
4449 clipbox.width, clipbox.height);
4450 g_object_unref (method.gc);
4454 gdk_region_destroy (clip);
4455 cairo_surface_destroy (paint.surface);
4461 * @window: a #GdkWindow
4463 * Clears an entire @window to the background color or background pixmap.
4466 gdk_window_clear (GdkWindow *window)
4470 g_return_if_fail (GDK_IS_WINDOW (window));
4472 gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height);
4474 gdk_window_clear_area (window, 0, 0,
4478 /* TRUE if the window clears to the same pixels as a native
4479 window clear. This means you can use the native window
4480 clearing operation, and additionally it means any clearing
4481 done by the native window system for you will already be right */
4483 clears_as_native (GdkWindowObject *private)
4485 GdkWindowObject *next;
4491 if (gdk_window_has_impl (private))
4493 next = private->parent;
4495 while (private->bg_pixmap == GDK_PARENT_RELATIVE_BG &&
4496 next && next->window_type != GDK_WINDOW_ROOT);
4501 gdk_window_clear_region_internal (GdkWindow *window,
4503 gboolean send_expose)
4505 GdkWindowObject *private = (GdkWindowObject *)window;
4506 GdkWindowImplIface *impl_iface;
4508 if (private->paint_stack)
4509 gdk_window_clear_backing_region (window, region);
4512 if (private->redirect)
4513 gdk_window_clear_backing_region_redirect (window, region);
4515 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
4517 if (impl_iface->clear_region && clears_as_native (private))
4520 copy = gdk_region_copy (region);
4521 gdk_region_intersect (copy,
4522 private->clip_region_with_children);
4525 /* Drawing directly to the window, flush anything outstanding to
4526 guarantee ordering. */
4527 gdk_window_flush (window);
4528 impl_iface->clear_region (window, copy, send_expose);
4530 gdk_region_destroy (copy);
4534 gdk_window_clear_backing_region_direct (window, region);
4536 gdk_window_invalidate_region (window, region, FALSE);
4542 gdk_window_clear_area_internal (GdkWindow *window,
4547 gboolean send_expose)
4552 g_return_if_fail (GDK_IS_WINDOW (window));
4554 if (GDK_WINDOW_DESTROYED (window))
4557 /* Terminate early to avoid weird interpretation of
4558 zero width/height by XClearArea */
4559 if (width == 0 || height == 0)
4565 rect.height = height;
4567 region = gdk_region_rectangle (&rect);
4568 gdk_window_clear_region_internal (window,
4571 gdk_region_destroy (region);
4576 * gdk_window_clear_area:
4577 * @window: a #GdkWindow
4578 * @x: x coordinate of rectangle to clear
4579 * @y: y coordinate of rectangle to clear
4580 * @width: width of rectangle to clear
4581 * @height: height of rectangle to clear
4583 * Clears an area of @window to the background color or background pixmap.
4587 gdk_window_clear_area (GdkWindow *window,
4593 gdk_window_clear_area_internal (window,
4600 * gdk_window_clear_area_e:
4601 * @window: a #GdkWindow
4602 * @x: x coordinate of rectangle to clear
4603 * @y: y coordinate of rectangle to clear
4604 * @width: width of rectangle to clear
4605 * @height: height of rectangle to clear
4607 * Like gdk_window_clear_area(), but also generates an expose event for
4610 * This function has a stupid name because it dates back to the mists
4611 * time, pre-GDK-1.0.
4615 gdk_window_clear_area_e (GdkWindow *window,
4621 gdk_window_clear_area_internal (window,
4628 gdk_window_draw_image (GdkDrawable *drawable,
4638 if (GDK_WINDOW_DESTROYED (drawable))
4642 gdk_draw_image (impl, gc, image, xsrc, ysrc,
4643 xdest - x_offset, ydest - y_offset,
4649 gdk_window_draw_pixbuf (GdkDrawable *drawable,
4658 GdkRgbDither dither,
4662 GdkWindowObject *private = (GdkWindowObject *)drawable;
4663 GdkDrawableClass *klass;
4665 if (GDK_WINDOW_DESTROYED (drawable))
4668 /* If no gc => no user clipping, but we need clipping
4669 for window emulation, so use a scratch gc */
4671 gc = _gdk_drawable_get_scratch_gc (drawable, FALSE);
4675 klass = GDK_DRAWABLE_GET_CLASS (impl);
4677 if (private->paint_stack)
4678 klass->draw_pixbuf (impl, gc, pixbuf, src_x, src_y,
4679 dest_x - x_offset, dest_y - y_offset,
4681 dither, x_dither - x_offset, y_dither - y_offset);
4683 klass->draw_pixbuf (impl, gc, pixbuf, src_x, src_y,
4684 dest_x - x_offset, dest_y - y_offset,
4686 dither, x_dither, y_dither);
4691 gdk_window_draw_trapezoids (GdkDrawable *drawable,
4693 GdkTrapezoid *trapezoids,
4696 GdkTrapezoid *new_trapezoids = NULL;
4698 if (GDK_WINDOW_DESTROYED (drawable))
4703 if (x_offset != 0 || y_offset != 0)
4707 new_trapezoids = g_new (GdkTrapezoid, n_trapezoids);
4708 for (i=0; i < n_trapezoids; i++)
4710 new_trapezoids[i].y1 = trapezoids[i].y1 - y_offset;
4711 new_trapezoids[i].x11 = trapezoids[i].x11 - x_offset;
4712 new_trapezoids[i].x21 = trapezoids[i].x21 - x_offset;
4713 new_trapezoids[i].y2 = trapezoids[i].y2 - y_offset;
4714 new_trapezoids[i].x12 = trapezoids[i].x12 - x_offset;
4715 new_trapezoids[i].x22 = trapezoids[i].x22 - x_offset;
4718 trapezoids = new_trapezoids;
4721 gdk_draw_trapezoids (impl, gc, trapezoids, n_trapezoids);
4723 g_free (new_trapezoids);
4729 gdk_window_real_get_size (GdkDrawable *drawable,
4733 GdkWindowObject *private = (GdkWindowObject *)drawable;
4736 *width = private->width;
4738 *height = private->height;
4742 gdk_window_real_get_visual (GdkDrawable *drawable)
4744 GdkColormap *colormap;
4746 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4748 colormap = gdk_drawable_get_colormap (drawable);
4749 return colormap ? gdk_colormap_get_visual (colormap) : NULL;
4753 gdk_window_real_get_depth (GdkDrawable *drawable)
4755 g_return_val_if_fail (GDK_IS_WINDOW (drawable), 0);
4757 return ((GdkWindowObject *)GDK_WINDOW (drawable))->depth;
4761 gdk_window_real_get_screen (GdkDrawable *drawable)
4763 return gdk_drawable_get_screen (GDK_WINDOW_OBJECT (drawable)->impl);
4767 gdk_window_real_set_colormap (GdkDrawable *drawable,
4770 GdkWindowObject *private;
4772 g_return_if_fail (GDK_IS_WINDOW (drawable));
4774 if (GDK_WINDOW_DESTROYED (drawable))
4777 private = (GdkWindowObject *)drawable;
4779 /* different colormap than parent, requires native window */
4780 if (!private->input_only &&
4781 cmap != gdk_drawable_get_colormap ((GdkDrawable *)(private->parent)))
4782 gdk_window_ensure_native ((GdkWindow *)drawable);
4784 gdk_drawable_set_colormap (private->impl, cmap);
4788 gdk_window_real_get_colormap (GdkDrawable *drawable)
4790 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4792 if (GDK_WINDOW_DESTROYED (drawable))
4795 return gdk_drawable_get_colormap (((GdkWindowObject*)drawable)->impl);
4799 gdk_window_copy_to_image (GdkDrawable *drawable,
4808 GdkWindowObject *private = (GdkWindowObject *) drawable;
4809 gint x_offset, y_offset;
4811 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4813 if (GDK_WINDOW_DESTROYED (drawable))
4816 /* If we're here, a composite image was not necessary, so
4817 * we can ignore the paint stack.
4820 /* TODO: Is this right? */
4824 return gdk_drawable_copy_to_image (private->impl,
4833 gdk_window_cairo_surface_destroy (void *data)
4835 GdkWindowObject *private = (GdkWindowObject*) data;
4837 private->cairo_surface = NULL;
4840 static cairo_surface_t *
4841 gdk_window_create_cairo_surface (GdkDrawable *drawable,
4845 return _gdk_windowing_create_cairo_surface (GDK_WINDOW_OBJECT(drawable)->impl,
4850 static cairo_surface_t *
4851 gdk_window_ref_cairo_surface (GdkDrawable *drawable)
4853 GdkWindowObject *private = (GdkWindowObject*) drawable;
4854 cairo_surface_t *surface;
4856 if (private->paint_stack)
4858 GdkWindowPaint *paint = private->paint_stack->data;
4860 surface = paint->surface;
4861 cairo_surface_reference (surface);
4866 /* This will be drawing directly to the window, so flush implicit paint */
4867 gdk_window_flush ((GdkWindow *)drawable);
4869 if (!private->cairo_surface)
4872 GdkDrawable *source;
4874 /* It would be nice if we had some cairo support here so we
4875 could set the clip rect on the cairo surface */
4876 width = private->abs_x + private->width;
4877 height = private->abs_y + private->height;
4879 source = _gdk_drawable_get_source_drawable (drawable);
4881 /* TODO: Avoid the typecheck crap by adding virtual call */
4882 private->cairo_surface = _gdk_drawable_create_cairo_surface (source, width, height);
4884 if (private->cairo_surface)
4886 cairo_surface_set_device_offset (private->cairo_surface,
4890 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
4891 drawable, gdk_window_cairo_surface_destroy);
4895 cairo_surface_reference (private->cairo_surface);
4897 surface = private->cairo_surface;
4904 gdk_window_set_cairo_clip (GdkDrawable *drawable,
4907 GdkWindowObject *private = (GdkWindowObject*) drawable;
4909 if (!private->paint_stack)
4911 cairo_reset_clip (cr);
4914 cairo_identity_matrix (cr);
4916 cairo_new_path (cr);
4917 gdk_cairo_region (cr, private->clip_region_with_children);
4924 GdkWindowPaint *paint = private->paint_stack->data;
4926 /* Only needs to clip to region if piggybacking
4927 on an implicit paint pixmap */
4928 cairo_reset_clip (cr);
4929 if (paint->uses_implicit)
4932 cairo_identity_matrix (cr);
4934 cairo_new_path (cr);
4935 gdk_cairo_region (cr, paint->region);
4943 /* Code for dirty-region queueing
4945 static GSList *update_windows = NULL;
4946 static guint update_idle = 0;
4947 static gboolean debug_updates = FALSE;
4949 static inline gboolean
4950 gdk_window_is_ancestor (GdkWindow *window,
4951 GdkWindow *ancestor)
4955 GdkWindow *parent = (GdkWindow*) ((GdkWindowObject*) window)->parent;
4957 if (parent == ancestor)
4967 gdk_window_add_update_window (GdkWindow *window)
4970 GSList *prev = NULL;
4971 gboolean has_ancestor_in_list = FALSE;
4973 for (tmp = update_windows; tmp; tmp = tmp->next)
4975 GdkWindowObject *parent = GDK_WINDOW_OBJECT (window)->parent;
4977 /* check if tmp is an ancestor of "window"; if it is, set a
4978 * flag indicating that all following windows are either
4979 * children of "window" or from a differen hierarchy
4981 if (!has_ancestor_in_list && gdk_window_is_ancestor (window, tmp->data))
4982 has_ancestor_in_list = TRUE;
4984 /* insert in reverse stacking order when adding around siblings,
4985 * so processing updates properly paints over lower stacked windows
4987 if (parent == GDK_WINDOW_OBJECT (tmp->data)->parent)
4989 gint index = g_list_index (parent->children, window);
4990 for (; tmp && parent == GDK_WINDOW_OBJECT (tmp->data)->parent; tmp = tmp->next)
4992 gint sibling_index = g_list_index (parent->children, tmp->data);
4993 if (index > sibling_index)
4997 /* here, tmp got advanced past all lower stacked siblings */
4998 tmp = g_slist_prepend (tmp, window);
5002 update_windows = tmp;
5006 /* if "window" has an ancestor in the list and tmp is one of
5007 * "window's" children, insert "window" before tmp
5009 if (has_ancestor_in_list && gdk_window_is_ancestor (tmp->data, window))
5011 tmp = g_slist_prepend (tmp, window);
5016 update_windows = tmp;
5020 /* if we're at the end of the list and had an ancestor it it,
5021 * append to the list
5023 if (! tmp->next && has_ancestor_in_list)
5025 tmp = g_slist_append (tmp, window);
5032 /* if all above checks failed ("window" is from a different
5033 * hierarchy than what is already in the list) or the list is
5036 update_windows = g_slist_prepend (update_windows, window);
5040 gdk_window_remove_update_window (GdkWindow *window)
5042 update_windows = g_slist_remove (update_windows, window);
5046 gdk_window_update_idle (gpointer data)
5048 gdk_window_process_all_updates ();
5054 gdk_window_is_toplevel_frozen (GdkWindow *window)
5056 GdkWindowObject *toplevel;
5058 toplevel = (GdkWindowObject *)gdk_window_get_toplevel (window);
5060 return toplevel->update_and_descendants_freeze_count > 0;
5064 gdk_window_schedule_update (GdkWindow *window)
5067 (GDK_WINDOW_OBJECT (window)->update_freeze_count ||
5068 gdk_window_is_toplevel_frozen (window)))
5073 gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
5074 gdk_window_update_idle,
5079 _gdk_window_process_updates_recurse (GdkWindow *window,
5080 GdkRegion *expose_region)
5082 GdkWindowObject *private = (GdkWindowObject *)window;
5083 GdkWindowObject *child;
5084 GdkRegion *child_region;
5086 GList *l, *children;
5088 if (gdk_region_empty (expose_region))
5091 /* Make this reentrancy safe for expose handlers freeing windows */
5092 children = g_list_copy (private->children);
5093 g_list_foreach (children, (GFunc)g_object_ref, NULL);
5095 /* Iterate over children, starting at topmost */
5096 for (l = children; l != NULL; l = l->next)
5100 if (child->destroyed || !GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
5103 /* Ignore offscreen children, as they don't draw in their parent and
5104 * don't take part in the clipping */
5105 if (gdk_window_is_offscreen (child))
5110 r.width = child->width;
5111 r.height = child->height;
5113 child_region = gdk_region_rectangle (&r);
5116 /* Adjust shape region to parent window coords */
5117 gdk_region_offset (child->shape, child->x, child->y);
5118 gdk_region_intersect (child_region, child->shape);
5119 gdk_region_offset (child->shape, -child->x, -child->y);
5122 if (child->impl == private->impl)
5124 /* Client side child, expose */
5125 gdk_region_intersect (child_region, expose_region);
5126 gdk_region_subtract (expose_region, child_region);
5127 gdk_region_offset (child_region, -child->x, -child->y);
5128 _gdk_window_process_updates_recurse ((GdkWindow *)child, child_region);
5132 /* Native child, just remove area from expose region */
5133 gdk_region_subtract (expose_region, child_region);
5135 gdk_region_destroy (child_region);
5138 g_list_foreach (children, (GFunc)g_object_unref, NULL);
5139 g_list_free (children);
5141 if (!gdk_region_empty (expose_region) &&
5142 !private->destroyed)
5144 if (private->event_mask & GDK_EXPOSURE_MASK)
5148 event.expose.type = GDK_EXPOSE;
5149 event.expose.window = g_object_ref (window);
5150 event.expose.send_event = FALSE;
5151 event.expose.count = 0;
5152 event.expose.region = expose_region;
5153 gdk_region_get_clipbox (expose_region, &event.expose.area);
5155 (*_gdk_event_func) (&event, _gdk_event_data);
5157 g_object_unref (window);
5159 else if (private->bg_pixmap != GDK_NO_BG &&
5160 private->window_type != GDK_WINDOW_FOREIGN)
5162 /* No exposure mask set, so nothing will be drawn, the
5163 * app relies on the background being what it specified
5164 * for the window. So, we need to clear this manually.
5166 * For foreign windows if expose is not set that generally
5167 * means some other client paints them, so don't clear
5170 * We use begin/end_paint around the clear so that we can
5171 * piggyback on the implicit paint */
5173 gdk_window_begin_paint_region (window, expose_region);
5174 gdk_window_clear_region_internal (window, expose_region, FALSE);
5175 gdk_window_end_paint (window);
5180 /* Process and remove any invalid area on the native window by creating
5181 * expose events for the window and all non-native descendants.
5182 * Also processes any outstanding moves on the window before doing
5183 * any drawing. Note that its possible to have outstanding moves without
5184 * any invalid area as we use the update idle mechanism to coalesce
5185 * multiple moves as well as multiple invalidations.
5188 gdk_window_process_updates_internal (GdkWindow *window)
5190 GdkWindowObject *private = (GdkWindowObject *)window;
5191 GdkWindowImplIface *impl_iface;
5192 gboolean save_region = FALSE;
5193 GdkRectangle clip_box;
5195 /* Ensure the window lives while updating it */
5196 g_object_ref (window);
5198 /* If an update got queued during update processing, we can get a
5199 * window in the update queue that has an empty update_area.
5202 if (private->update_area)
5204 GdkRegion *update_area = private->update_area;
5205 private->update_area = NULL;
5207 if (_gdk_event_func && gdk_window_is_viewable (window))
5209 GdkRegion *expose_region;
5210 gboolean end_implicit;
5212 /* Clip to part visible in toplevel */
5213 gdk_region_intersect (update_area, private->clip_region);
5217 /* Make sure we see the red invalid area before redrawing. */
5218 gdk_display_sync (gdk_drawable_get_display (window));
5222 /* At this point we will be completely redrawing all of update_area.
5223 * If we have any outstanding moves that end up moving stuff inside
5224 * this area we don't actually need to move that as that part would
5225 * be overdrawn by the expose anyway. So, in order to copy less data
5226 * we remove these areas from the outstanding moves.
5228 if (private->outstanding_moves)
5230 GdkWindowRegionMove *move;
5234 remove = gdk_region_copy (update_area);
5235 /* We iterate backwards, starting from the state that would be
5236 if we had applied all the moves. */
5237 for (l = g_list_last (private->outstanding_moves); l != NULL; l = prev)
5242 /* Don't need this area */
5243 gdk_region_subtract (move->dest_region, remove);
5245 /* However if any of the destination we do need has a source
5246 in the updated region we do need that as a destination for
5247 the earlier moves */
5248 gdk_region_offset (move->dest_region, -move->dx, -move->dy);
5249 gdk_region_subtract (remove, move->dest_region);
5251 if (gdk_region_empty (move->dest_region))
5253 gdk_window_region_move_free (move);
5254 private->outstanding_moves =
5255 g_list_delete_link (private->outstanding_moves, l);
5257 else /* move back */
5258 gdk_region_offset (move->dest_region, move->dx, move->dy);
5260 gdk_region_destroy (remove);
5263 /* By now we a set of window moves that should be applied, and then
5264 * an update region that should be repainted. A trivial implementation
5265 * would just do that in order, however in order to get nicer drawing
5266 * we do some tricks:
5268 * First of all, each subwindow expose may be double buffered by
5269 * itself (depending on widget setting) via
5270 * gdk_window_begin/end_paint(). But we also do an "implicit" paint,
5271 * creating a single pixmap the size of the invalid area on the
5272 * native window which all the individual normal paints will draw
5273 * into. This way in the normal case there will be only one pixmap
5274 * allocated and only once pixmap draw done for all the windows
5275 * in this native window.
5276 * There are a couple of reasons this may fail, for instance, some
5277 * backends (like quartz) do its own double buffering, so we disable
5278 * gdk double buffering there. Secondly, some subwindow could be
5279 * non-double buffered and draw directly to the window outside a
5280 * begin/end_paint pair. That will be lead to a gdk_window_flush
5281 * which immediately executes all outstanding moves and paints+removes
5282 * the implicit paint (further paints will allocate their own pixmap).
5284 * Secondly, in the case of implicit double buffering we expose all
5285 * the child windows into the implicit pixmap before we execute
5286 * the outstanding moves. This way we minimize the time between
5287 * doing the moves and rendering the new update area, thus minimizing
5288 * flashing. Of course, if any subwindow is non-double buffered we
5289 * well flush earlier than that.
5291 * Thirdly, after having done the outstanding moves we queue an
5292 * "antiexpose" on the area that will be drawn by the expose, which
5293 * means that any invalid region on the native window side before
5294 * the first expose drawing operation will be discarded, as it
5295 * has by then been overdrawn with valid data. This means we can
5296 * avoid doing the unnecessary repaint any outstanding expose events.
5299 gdk_region_get_clipbox (update_area, &clip_box);
5300 end_implicit = gdk_window_begin_implicit_paint (window, &clip_box);
5301 expose_region = gdk_region_copy (update_area);
5304 /* Rendering is not double buffered by gdk, do outstanding
5305 * moves and queue antiexposure immediately. No need to do
5307 gdk_window_flush_outstanding_moves (window);
5308 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
5309 save_region = impl_iface->queue_antiexpose (window, update_area);
5312 /* Render the invalid areas to the implicit paint, by sending exposes.
5313 * May flush if non-double buffered widget draw. */
5314 _gdk_windowing_window_process_updates_recurse (window, expose_region);
5318 /* Do moves right before exposes are rendered to the window */
5319 gdk_window_flush_outstanding_moves (window);
5321 /* By this time we know that any outstanding expose for this
5322 * area is invalid and we can avoid it, so queue an antiexpose.
5323 * However, it may be that due to an non-double buffered expose
5324 * we have already started drawing to the window, so it would
5325 * be to late to anti-expose now. Since this is merely an
5326 * optimization we just avoid doing it at all in that case.
5328 if (private->implicit_paint != NULL &&
5329 !private->implicit_paint->flushed)
5331 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
5332 save_region = impl_iface->queue_antiexpose (window, update_area);
5335 gdk_window_end_implicit_paint (window);
5337 gdk_region_destroy (expose_region);
5340 gdk_region_destroy (update_area);
5343 if (private->outstanding_moves)
5345 /* Flush any outstanding moves, may happen if we moved a window but got
5346 no actual invalid area */
5347 gdk_window_flush_outstanding_moves (window);
5350 g_object_unref (window);
5354 flush_all_displays (void)
5356 GSList *displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
5359 for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
5360 gdk_display_flush (tmp_list->data);
5362 g_slist_free (displays);
5365 /* Currently it is not possible to override
5366 * gdk_window_process_all_updates in the same manner as
5367 * gdk_window_process_updates and gdk_window_invalidate_maybe_recurse
5368 * by implementing the GdkPaintable interface. If in the future a
5369 * backend would need this, the right solution would be to add a
5370 * method to GdkDisplay that can be optionally
5371 * NULL. gdk_window_process_all_updates can then walk the list of open
5372 * displays and call the mehod.
5376 * gdk_window_process_all_updates:
5378 * Calls gdk_window_process_updates() for all windows (see #GdkWindow)
5379 * in the application.
5383 gdk_window_process_all_updates (void)
5385 GSList *old_update_windows = update_windows;
5386 GSList *tmp_list = update_windows;
5387 static gboolean in_process_all_updates = FALSE;
5388 static gboolean got_recursive_update = FALSE;
5390 if (in_process_all_updates)
5392 /* We can't do this now since that would recurse, so
5393 delay it until after the recursion is done. */
5394 got_recursive_update = TRUE;
5399 in_process_all_updates = TRUE;
5400 got_recursive_update = FALSE;
5403 g_source_remove (update_idle);
5405 update_windows = NULL;
5408 _gdk_windowing_before_process_all_updates ();
5410 g_slist_foreach (old_update_windows, (GFunc)g_object_ref, NULL);
5414 GdkWindowObject *private = (GdkWindowObject *)tmp_list->data;
5416 if (!GDK_WINDOW_DESTROYED (tmp_list->data))
5418 if (private->update_freeze_count ||
5419 gdk_window_is_toplevel_frozen (tmp_list->data))
5420 gdk_window_add_update_window ((GdkWindow *) private);
5422 gdk_window_process_updates_internal (tmp_list->data);
5425 g_object_unref (tmp_list->data);
5426 tmp_list = tmp_list->next;
5429 g_slist_free (old_update_windows);
5431 flush_all_displays ();
5433 _gdk_windowing_after_process_all_updates ();
5435 in_process_all_updates = FALSE;
5437 /* If we ignored a recursive call, schedule a
5438 redraw now so that it eventually happens,
5439 otherwise we could miss an update if nothing
5440 else schedules an update. */
5441 if (got_recursive_update && !update_idle)
5443 gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
5444 gdk_window_update_idle,
5449 * gdk_window_process_updates:
5450 * @window: a #GdkWindow
5451 * @update_children: whether to also process updates for child windows
5453 * Sends one or more expose events to @window. The areas in each
5454 * expose event will cover the entire update area for the window (see
5455 * gdk_window_invalidate_region() for details). Normally GDK calls
5456 * gdk_window_process_all_updates() on your behalf, so there's no
5457 * need to call this function unless you want to force expose events
5458 * to be delivered immediately and synchronously (vs. the usual
5459 * case, where GDK delivers them in an idle handler). Occasionally
5460 * this is useful to produce nicer scrolling behavior, for example.
5464 gdk_window_process_updates (GdkWindow *window,
5465 gboolean update_children)
5467 GdkWindowObject *private = (GdkWindowObject *)window;
5468 GdkWindowObject *impl_window;
5470 g_return_if_fail (GDK_IS_WINDOW (window));
5472 if (GDK_WINDOW_DESTROYED (window))
5475 /* Make sure the window lives during the expose callouts */
5476 g_object_ref (window);
5478 impl_window = gdk_window_get_impl_window (private);
5479 if ((impl_window->update_area ||
5480 impl_window->outstanding_moves) &&
5481 !impl_window->update_freeze_count &&
5482 !gdk_window_is_toplevel_frozen (window) &&
5484 /* Don't recurse into process_updates_internal, we'll
5485 * do the update later when idle instead. */
5486 impl_window->implicit_paint == NULL)
5488 gdk_window_process_updates_internal ((GdkWindow *)impl_window);
5489 gdk_window_remove_update_window ((GdkWindow *)impl_window);
5492 if (update_children)
5494 /* process updates in reverse stacking order so composition or
5495 * painting over achieves the desired effect for offscreen windows
5497 GList *node, *children;
5499 children = g_list_copy (private->children);
5500 g_list_foreach (children, (GFunc)g_object_ref, NULL);
5502 for (node = g_list_last (children); node; node = node->prev)
5504 gdk_window_process_updates (node->data, TRUE);
5505 g_object_unref (node->data);
5508 g_list_free (children);
5511 g_object_unref (window);
5515 gdk_window_invalidate_rect_full (GdkWindow *window,
5516 const GdkRectangle *rect,
5517 gboolean invalidate_children,
5520 GdkRectangle window_rect;
5522 GdkWindowObject *private = (GdkWindowObject *)window;
5524 g_return_if_fail (GDK_IS_WINDOW (window));
5526 if (GDK_WINDOW_DESTROYED (window))
5529 if (private->input_only || !private->viewable)
5536 gdk_drawable_get_size (GDK_DRAWABLE (window),
5538 &window_rect.height);
5539 rect = &window_rect;
5542 region = gdk_region_rectangle (rect);
5543 gdk_window_invalidate_region_full (window, region, invalidate_children, clear_bg);
5544 gdk_region_destroy (region);
5548 * gdk_window_invalidate_rect:
5549 * @window: a #GdkWindow
5550 * @rect: rectangle to invalidate or %NULL to invalidate the whole
5552 * @invalidate_children: whether to also invalidate child windows
5554 * A convenience wrapper around gdk_window_invalidate_region() which
5555 * invalidates a rectangular region. See
5556 * gdk_window_invalidate_region() for details.
5559 gdk_window_invalidate_rect (GdkWindow *window,
5560 const GdkRectangle *rect,
5561 gboolean invalidate_children)
5563 gdk_window_invalidate_rect_full (window, rect, invalidate_children, CLEAR_BG_NONE);
5567 draw_ugly_color (GdkWindow *window,
5568 const GdkRegion *region)
5570 /* Draw ugly color all over the newly-invalid region */
5571 GdkColor ugly_color = { 0, 50000, 10000, 10000 };
5573 GdkRectangle clipbox;
5575 ugly_gc = gdk_gc_new (window);
5576 gdk_gc_set_rgb_fg_color (ugly_gc, &ugly_color);
5577 gdk_gc_set_clip_region (ugly_gc, region);
5579 gdk_region_get_clipbox (region, &clipbox);
5581 gdk_draw_rectangle (window,
5584 clipbox.x, clipbox.y,
5585 clipbox.width, clipbox.height);
5587 g_object_unref (ugly_gc);
5591 impl_window_add_update_area (GdkWindowObject *impl_window,
5594 if (impl_window->update_area)
5595 gdk_region_union (impl_window->update_area, region);
5598 gdk_window_add_update_window ((GdkWindow *)impl_window);
5599 impl_window->update_area = gdk_region_copy (region);
5600 gdk_window_schedule_update ((GdkWindow *)impl_window);
5604 /* clear_bg controls if the region will be cleared to
5605 * the background color/pixmap if the exposure mask is not
5606 * set for the window, whereas this might not otherwise be
5607 * done (unless necessary to emulate background settings).
5608 * Set this to CLEAR_BG_WINCLEARED or CLEAR_BG_ALL if you
5609 * need to clear the background, such as when exposing the area beneath a
5610 * hidden or moved window, but not when an app requests repaint or when the
5611 * windowing system exposes a newly visible area (because then the windowing
5612 * system has already cleared the area).
5615 gdk_window_invalidate_maybe_recurse_full (GdkWindow *window,
5616 const GdkRegion *region,
5618 gboolean (*child_func) (GdkWindow *,
5622 GdkWindowObject *private = (GdkWindowObject *)window;
5623 GdkWindowObject *impl_window;
5624 GdkRegion *visible_region;
5627 g_return_if_fail (GDK_IS_WINDOW (window));
5629 if (GDK_WINDOW_DESTROYED (window))
5632 if (private->input_only ||
5633 !private->viewable ||
5634 gdk_region_empty (region) ||
5635 private->window_type == GDK_WINDOW_ROOT)
5638 visible_region = gdk_drawable_get_visible_region (window);
5639 gdk_region_intersect (visible_region, region);
5641 tmp_list = private->children;
5644 GdkWindowObject *child = tmp_list->data;
5646 if (!child->input_only)
5648 GdkRegion *child_region;
5649 GdkRectangle child_rect;
5651 child_rect.x = child->x;
5652 child_rect.y = child->y;
5653 child_rect.width = child->width;
5654 child_rect.height = child->height;
5655 child_region = gdk_region_rectangle (&child_rect);
5657 /* remove child area from the invalid area of the parent */
5658 if (GDK_WINDOW_IS_MAPPED (child) && !child->shaped &&
5659 !child->composited &&
5660 !gdk_window_is_offscreen (child))
5661 gdk_region_subtract (visible_region, child_region);
5663 if (child_func && (*child_func) ((GdkWindow *)child, user_data))
5665 GdkRegion *tmp = gdk_region_copy (region);
5667 gdk_region_offset (tmp, - child_rect.x, - child_rect.y);
5668 gdk_region_offset (child_region, - child_rect.x, - child_rect.y);
5669 gdk_region_intersect (child_region, tmp);
5671 gdk_window_invalidate_maybe_recurse_full ((GdkWindow *)child,
5672 child_region, clear_bg, child_func, user_data);
5674 gdk_region_destroy (tmp);
5677 gdk_region_destroy (child_region);
5680 tmp_list = tmp_list->next;
5683 impl_window = gdk_window_get_impl_window (private);
5685 if (!gdk_region_empty (visible_region) ||
5686 /* Even if we're not exposing anything, make sure we process
5687 idles for windows with outstanding moves */
5688 (impl_window->outstanding_moves != NULL &&
5689 impl_window->update_area == NULL))
5692 draw_ugly_color (window, region);
5694 /* Convert to impl coords */
5695 gdk_region_offset (visible_region, private->abs_x, private->abs_y);
5697 /* Only invalidate area if app requested expose events or if
5698 we need to clear the area (by request or to emulate background
5699 clearing for non-native windows or native windows with no support
5700 for window backgrounds */
5701 if (private->event_mask & GDK_EXPOSURE_MASK ||
5702 clear_bg == CLEAR_BG_ALL ||
5703 (clear_bg == CLEAR_BG_WINCLEARED &&
5704 (!clears_as_native (private) ||
5705 !GDK_WINDOW_IMPL_GET_IFACE (private->impl)->supports_native_bg)))
5706 impl_window_add_update_area (impl_window, visible_region);
5709 gdk_region_destroy (visible_region);
5713 * gdk_window_invalidate_maybe_recurse:
5714 * @window: a #GdkWindow
5715 * @region: a #GdkRegion
5716 * @child_func: function to use to decide if to recurse to a child,
5717 * %NULL means never recurse.
5718 * @user_data: data passed to @child_func
5720 * Adds @region to the update area for @window. The update area is the
5721 * region that needs to be redrawn, or "dirty region." The call
5722 * gdk_window_process_updates() sends one or more expose events to the
5723 * window, which together cover the entire update area. An
5724 * application would normally redraw the contents of @window in
5725 * response to those expose events.
5727 * GDK will call gdk_window_process_all_updates() on your behalf
5728 * whenever your program returns to the main loop and becomes idle, so
5729 * normally there's no need to do that manually, you just need to
5730 * invalidate regions that you know should be redrawn.
5732 * The @child_func parameter controls whether the region of
5733 * each child window that intersects @region will also be invalidated.
5734 * Only children for which @child_func returns TRUE will have the area
5738 gdk_window_invalidate_maybe_recurse (GdkWindow *window,
5739 const GdkRegion *region,
5740 gboolean (*child_func) (GdkWindow *,
5744 gdk_window_invalidate_maybe_recurse_full (window, region, CLEAR_BG_NONE,
5745 child_func, user_data);
5749 true_predicate (GdkWindow *window,
5756 gdk_window_invalidate_region_full (GdkWindow *window,
5757 const GdkRegion *region,
5758 gboolean invalidate_children,
5761 gdk_window_invalidate_maybe_recurse_full (window, region, clear_bg,
5762 invalidate_children ?
5763 true_predicate : (gboolean (*) (GdkWindow *, gpointer))NULL,
5768 * gdk_window_invalidate_region:
5769 * @window: a #GdkWindow
5770 * @region: a #GdkRegion
5771 * @invalidate_children: %TRUE to also invalidate child windows
5773 * Adds @region to the update area for @window. The update area is the
5774 * region that needs to be redrawn, or "dirty region." The call
5775 * gdk_window_process_updates() sends one or more expose events to the
5776 * window, which together cover the entire update area. An
5777 * application would normally redraw the contents of @window in
5778 * response to those expose events.
5780 * GDK will call gdk_window_process_all_updates() on your behalf
5781 * whenever your program returns to the main loop and becomes idle, so
5782 * normally there's no need to do that manually, you just need to
5783 * invalidate regions that you know should be redrawn.
5785 * The @invalidate_children parameter controls whether the region of
5786 * each child window that intersects @region will also be invalidated.
5787 * If %FALSE, then the update area for child windows will remain
5788 * unaffected. See gdk_window_invalidate_maybe_recurse if you need
5789 * fine grained control over which children are invalidated.
5792 gdk_window_invalidate_region (GdkWindow *window,
5793 const GdkRegion *region,
5794 gboolean invalidate_children)
5796 gdk_window_invalidate_maybe_recurse (window, region,
5797 invalidate_children ?
5798 true_predicate : (gboolean (*) (GdkWindow *, gpointer))NULL,
5803 * _gdk_window_invalidate_for_expose:
5804 * @window: a #GdkWindow
5805 * @region: a #GdkRegion
5807 * Adds @region to the update area for @window. The update area is the
5808 * region that needs to be redrawn, or "dirty region." The call
5809 * gdk_window_process_updates() sends one or more expose events to the
5810 * window, which together cover the entire update area. An
5811 * application would normally redraw the contents of @window in
5812 * response to those expose events.
5814 * GDK will call gdk_window_process_all_updates() on your behalf
5815 * whenever your program returns to the main loop and becomes idle, so
5816 * normally there's no need to do that manually, you just need to
5817 * invalidate regions that you know should be redrawn.
5819 * This version of invalidation is used when you recieve expose events
5820 * from the native window system. It exposes the native window, plus
5821 * any non-native child windows (but not native child windows, as those would
5822 * have gotten their own expose events).
5825 _gdk_window_invalidate_for_expose (GdkWindow *window,
5828 GdkWindowObject *private = (GdkWindowObject *) window;
5829 GdkWindowRegionMove *move;
5830 GdkRegion *move_region;
5833 /* Any invalidations comming from the windowing system will
5834 be in areas that may be moved by outstanding moves,
5835 so we need to modify the expose region correspondingly,
5836 otherwise we would expose in the wrong place, as the
5837 outstanding moves will be copied before we draw the
5839 for (l = private->outstanding_moves; l != NULL; l = l->next)
5843 /* covert to move source region */
5844 move_region = gdk_region_copy (move->dest_region);
5845 gdk_region_offset (move_region, -move->dx, -move->dy);
5847 /* Move area of region that intersects with move source
5848 by dx, dy of the move*/
5849 gdk_region_intersect (move_region, region);
5850 gdk_region_subtract (region, move_region);
5851 gdk_region_offset (move_region, move->dx, move->dy);
5852 gdk_region_union (region, move_region);
5854 gdk_region_destroy (move_region);
5857 gdk_window_invalidate_maybe_recurse_full (window, region, CLEAR_BG_WINCLEARED,
5858 (gboolean (*) (GdkWindow *, gpointer))gdk_window_has_no_impl,
5864 * gdk_window_get_update_area:
5865 * @window: a #GdkWindow
5867 * Transfers ownership of the update area from @window to the caller
5868 * of the function. That is, after calling this function, @window will
5869 * no longer have an invalid/dirty region; the update area is removed
5870 * from @window and handed to you. If a window has no update area,
5871 * gdk_window_get_update_area() returns %NULL. You are responsible for
5872 * calling gdk_region_destroy() on the returned region if it's non-%NULL.
5874 * Return value: the update area for @window
5877 gdk_window_get_update_area (GdkWindow *window)
5879 GdkWindowObject *private = (GdkWindowObject *)window;
5880 GdkWindowObject *impl_window;
5881 GdkRegion *tmp_region;
5883 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
5885 impl_window = gdk_window_get_impl_window (private);
5887 if (impl_window->update_area)
5889 tmp_region = gdk_region_copy (private->clip_region_with_children);
5890 /* Convert to impl coords */
5891 gdk_region_offset (tmp_region, private->abs_x, private->abs_y);
5892 gdk_region_intersect (tmp_region, impl_window->update_area);
5894 if (gdk_region_empty (tmp_region))
5896 gdk_region_destroy (tmp_region);
5901 gdk_region_subtract (impl_window->update_area, tmp_region);
5903 if (gdk_region_empty (impl_window->update_area) &&
5904 impl_window->outstanding_moves == NULL)
5906 gdk_region_destroy (impl_window->update_area);
5907 impl_window->update_area = NULL;
5909 gdk_window_remove_update_window ((GdkWindow *)impl_window);
5912 /* Convert from impl coords */
5913 gdk_region_offset (tmp_region, -private->abs_x, -private->abs_y);
5923 * _gdk_window_clear_update_area:
5924 * @window: a #GdkWindow.
5926 * Internal function to clear the update area for a window. This
5927 * is called when the window is hidden or destroyed.
5930 _gdk_window_clear_update_area (GdkWindow *window)
5932 GdkWindowObject *private = (GdkWindowObject *)window;
5934 g_return_if_fail (GDK_IS_WINDOW (window));
5936 if (private->update_area)
5938 gdk_window_remove_update_window (window);
5940 gdk_region_destroy (private->update_area);
5941 private->update_area = NULL;
5946 * gdk_window_freeze_updates:
5947 * @window: a #GdkWindow
5949 * Temporarily freezes a window such that it won't receive expose
5950 * events. The window will begin receiving expose events again when
5951 * gdk_window_thaw_updates() is called. If gdk_window_freeze_updates()
5952 * has been called more than once, gdk_window_thaw_updates() must be called
5953 * an equal number of times to begin processing exposes.
5956 gdk_window_freeze_updates (GdkWindow *window)
5958 GdkWindowObject *private = (GdkWindowObject *)window;
5959 GdkWindowObject *impl_window;
5961 g_return_if_fail (GDK_IS_WINDOW (window));
5963 impl_window = gdk_window_get_impl_window (private);
5964 impl_window->update_freeze_count++;
5968 * gdk_window_thaw_updates:
5969 * @window: a #GdkWindow
5971 * Thaws a window frozen with gdk_window_freeze_updates().
5974 gdk_window_thaw_updates (GdkWindow *window)
5976 GdkWindowObject *private = (GdkWindowObject *)window;
5977 GdkWindowObject *impl_window;
5979 g_return_if_fail (GDK_IS_WINDOW (window));
5981 impl_window = gdk_window_get_impl_window (private);
5983 g_return_if_fail (impl_window->update_freeze_count > 0);
5985 if (--impl_window->update_freeze_count == 0)
5986 gdk_window_schedule_update (GDK_WINDOW (impl_window));
5990 * gdk_window_freeze_toplevel_updates_libgtk_only:
5991 * @window: a #GdkWindow
5993 * Temporarily freezes a window and all its descendants such that it won't
5994 * receive expose events. The window will begin receiving expose events
5995 * again when gdk_window_thaw_toplevel_updates_libgtk_only() is called. If
5996 * gdk_window_freeze_toplevel_updates_libgtk_only()
5997 * has been called more than once,
5998 * gdk_window_thaw_toplevel_updates_libgtk_only() must be called
5999 * an equal number of times to begin processing exposes.
6001 * This function is not part of the GDK public API and is only
6005 gdk_window_freeze_toplevel_updates_libgtk_only (GdkWindow *window)
6007 GdkWindowObject *private = (GdkWindowObject *)window;
6009 g_return_if_fail (GDK_IS_WINDOW (window));
6010 g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
6012 private->update_and_descendants_freeze_count++;
6016 * gdk_window_thaw_toplevel_updates_libgtk_only:
6017 * @window: a #GdkWindow
6019 * Thaws a window frozen with
6020 * gdk_window_freeze_toplevel_updates_libgtk_only().
6022 * This function is not part of the GDK public API and is only
6026 gdk_window_thaw_toplevel_updates_libgtk_only (GdkWindow *window)
6028 GdkWindowObject *private = (GdkWindowObject *)window;
6030 g_return_if_fail (GDK_IS_WINDOW (window));
6031 g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
6032 g_return_if_fail (private->update_and_descendants_freeze_count > 0);
6034 private->update_and_descendants_freeze_count--;
6036 gdk_window_schedule_update (window);
6040 * gdk_window_set_debug_updates:
6041 * @setting: %TRUE to turn on update debugging
6043 * With update debugging enabled, calls to
6044 * gdk_window_invalidate_region() clear the invalidated region of the
6045 * screen to a noticeable color, and GDK pauses for a short time
6046 * before sending exposes to windows during
6047 * gdk_window_process_updates(). The net effect is that you can see
6048 * the invalid region for each window and watch redraws as they
6049 * occur. This allows you to diagnose inefficiencies in your application.
6051 * In essence, because the GDK rendering model prevents all flicker,
6052 * if you are redrawing the same region 400 times you may never
6053 * notice, aside from noticing a speed problem. Enabling update
6054 * debugging causes GTK to flicker slowly and noticeably, so you can
6055 * see exactly what's being redrawn when, in what order.
6057 * The --gtk-debug=updates command line option passed to GTK+ programs
6058 * enables this debug option at application startup time. That's
6059 * usually more useful than calling gdk_window_set_debug_updates()
6060 * yourself, though you might want to use this function to enable
6061 * updates sometime after application startup time.
6065 gdk_window_set_debug_updates (gboolean setting)
6067 debug_updates = setting;
6071 * gdk_window_constrain_size:
6072 * @geometry: a #GdkGeometry structure
6073 * @flags: a mask indicating what portions of @geometry are set
6074 * @width: desired width of window
6075 * @height: desired height of the window
6076 * @new_width: location to store resulting width
6077 * @new_height: location to store resulting height
6079 * Constrains a desired width and height according to a
6080 * set of geometry hints (such as minimum and maximum size).
6083 gdk_window_constrain_size (GdkGeometry *geometry,
6090 /* This routine is partially borrowed from fvwm.
6092 * Copyright 1993, Robert Nation
6093 * You may use this code for any purpose, as long as the original
6094 * copyright remains in the source code and all documentation
6096 * which in turn borrows parts of the algorithm from uwm
6099 gint min_height = 0;
6100 gint base_width = 0;
6101 gint base_height = 0;
6104 gint max_width = G_MAXINT;
6105 gint max_height = G_MAXINT;
6107 #define FLOOR(value, base) ( ((gint) ((value) / (base))) * (base) )
6109 if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
6111 base_width = geometry->base_width;
6112 base_height = geometry->base_height;
6113 min_width = geometry->min_width;
6114 min_height = geometry->min_height;
6116 else if (flags & GDK_HINT_BASE_SIZE)
6118 base_width = geometry->base_width;
6119 base_height = geometry->base_height;
6120 min_width = geometry->base_width;
6121 min_height = geometry->base_height;
6123 else if (flags & GDK_HINT_MIN_SIZE)
6125 base_width = geometry->min_width;
6126 base_height = geometry->min_height;
6127 min_width = geometry->min_width;
6128 min_height = geometry->min_height;
6131 if (flags & GDK_HINT_MAX_SIZE)
6133 max_width = geometry->max_width ;
6134 max_height = geometry->max_height;
6137 if (flags & GDK_HINT_RESIZE_INC)
6139 xinc = MAX (xinc, geometry->width_inc);
6140 yinc = MAX (yinc, geometry->height_inc);
6143 /* clamp width and height to min and max values
6145 width = CLAMP (width, min_width, max_width);
6146 height = CLAMP (height, min_height, max_height);
6148 /* shrink to base + N * inc
6150 width = base_width + FLOOR (width - base_width, xinc);
6151 height = base_height + FLOOR (height - base_height, yinc);
6153 /* constrain aspect ratio, according to:
6156 * min_aspect <= -------- <= max_aspect
6160 if (flags & GDK_HINT_ASPECT &&
6161 geometry->min_aspect > 0 &&
6162 geometry->max_aspect > 0)
6166 if (geometry->min_aspect * height > width)
6168 delta = FLOOR (height - width / geometry->min_aspect, yinc);
6169 if (height - delta >= min_height)
6173 delta = FLOOR (height * geometry->min_aspect - width, xinc);
6174 if (width + delta <= max_width)
6179 if (geometry->max_aspect * height < width)
6181 delta = FLOOR (width - height * geometry->max_aspect, xinc);
6182 if (width - delta >= min_width)
6186 delta = FLOOR (width / geometry->max_aspect - height, yinc);
6187 if (height + delta <= max_height)
6196 *new_height = height;
6200 * gdk_window_get_pointer:
6201 * @window: a #GdkWindow
6202 * @x: return location for X coordinate of pointer or %NULL to not
6203 * return the X coordinate
6204 * @y: return location for Y coordinate of pointer or %NULL to not
6205 * return the Y coordinate
6206 * @mask: return location for modifier mask or %NULL to not return the
6209 * Obtains the current pointer position and modifier state.
6210 * The position is given in coordinates relative to the upper left
6211 * corner of @window.
6213 * Return value: the window containing the pointer (as with
6214 * gdk_window_at_pointer()), or %NULL if the window containing the
6215 * pointer isn't known to GDK
6218 gdk_window_get_pointer (GdkWindow *window,
6221 GdkModifierType *mask)
6223 GdkDisplay *display;
6225 GdkModifierType tmp_mask;
6228 g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
6232 display = gdk_drawable_get_display (window);
6236 GdkScreen *screen = gdk_screen_get_default ();
6238 display = gdk_screen_get_display (screen);
6239 window = gdk_screen_get_root_window (screen);
6241 GDK_NOTE (MULTIHEAD,
6242 g_message ("Passing NULL for window to gdk_window_get_pointer()\n"
6243 "is not multihead safe"));
6246 child = display->pointer_hooks->window_get_pointer (display, window, &tmp_x, &tmp_y, &tmp_mask);
6255 _gdk_display_enable_motion_hints (display);
6261 * gdk_window_at_pointer:
6262 * @win_x: return location for origin of the window under the pointer
6263 * @win_y: return location for origin of the window under the pointer
6265 * Obtains the window underneath the mouse pointer, returning the
6266 * location of that window in @win_x, @win_y. Returns %NULL if the
6267 * window under the mouse pointer is not known to GDK (if the window
6268 * belongs to another application and a #GdkWindow hasn't been created
6269 * for it with gdk_window_foreign_new())
6271 * NOTE: For multihead-aware widgets or applications use
6272 * gdk_display_get_window_at_pointer() instead.
6274 * Return value: window under the mouse pointer
6277 gdk_window_at_pointer (gint *win_x,
6280 return gdk_display_get_window_at_pointer (gdk_display_get_default (), win_x, win_y);
6284 * gdk_get_default_root_window:
6286 * Obtains the root window (parent all other windows are inside)
6287 * for the default display and screen.
6289 * Return value: the default root window
6292 gdk_get_default_root_window (void)
6294 return gdk_screen_get_root_window (gdk_screen_get_default ());
6298 * gdk_window_foreign_new:
6299 * @anid: a native window handle.
6301 * Wraps a native window for the default display in a #GdkWindow.
6302 * This may fail if the window has been destroyed.
6304 * For example in the X backend, a native window handle is an Xlib
6307 * Return value: the newly-created #GdkWindow wrapper for the
6308 * native window or %NULL if the window has been destroyed.
6311 gdk_window_foreign_new (GdkNativeWindow anid)
6313 return gdk_window_foreign_new_for_display (gdk_display_get_default (), anid);
6317 get_all_native_children (GdkWindowObject *private,
6320 GdkWindowObject *child;
6323 for (l = private->children; l != NULL; l = l->next)
6327 if (gdk_window_has_impl (child))
6328 *native = g_list_prepend (*native, child);
6330 get_all_native_children (child, native);
6336 gdk_window_raise_internal (GdkWindow *window)
6338 GdkWindowObject *private = (GdkWindowObject *)window;
6339 GdkWindowObject *parent = private->parent;
6340 GdkWindowObject *above;
6341 GList *native_children;
6343 GdkWindowImplIface *impl_iface;
6347 parent->children = g_list_remove (parent->children, window);
6348 parent->children = g_list_prepend (parent->children, window);
6351 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
6352 /* Just do native raise for toplevels */
6353 if (gdk_window_is_toplevel (private) ||
6354 /* The restack_under codepath should work correctly even if the parent
6355 is native, but it relies on the order of ->children to be correct,
6356 and some apps like SWT reorder the x windows without gdks knowledge,
6357 so we use raise directly in order to make these behave as before
6358 when using native windows */
6359 (gdk_window_has_impl (private) && gdk_window_has_impl (parent)))
6361 impl_iface->raise (window);
6363 else if (gdk_window_has_impl (private))
6365 above = find_native_sibling_above (parent, private);
6368 listhead.data = window;
6369 listhead.next = NULL;
6370 listhead.prev = NULL;
6371 impl_iface->restack_under ((GdkWindow *)above,
6375 impl_iface->raise (window);
6379 native_children = NULL;
6380 get_all_native_children (private, &native_children);
6381 if (native_children != NULL)
6383 above = find_native_sibling_above (parent, private);
6386 impl_iface->restack_under ((GdkWindow *)above,
6390 /* Right order, since native_children is bottom-topmost first */
6391 for (l = native_children; l != NULL; l = l->next)
6392 impl_iface->raise (l->data);
6395 g_list_free (native_children);
6401 /* Returns TRUE If the native window was mapped or unmapped */
6403 set_viewable (GdkWindowObject *w,
6406 GdkWindowObject *child;
6407 GdkWindowImplIface *impl_iface;
6410 if (w->viewable == val)
6416 recompute_visible_regions (w, FALSE, FALSE);
6418 for (l = w->children; l != NULL; l = l->next)
6422 if (GDK_WINDOW_IS_MAPPED (child) &&
6423 child->window_type != GDK_WINDOW_FOREIGN)
6424 set_viewable (child, val);
6427 if (!_gdk_native_windows &&
6428 gdk_window_has_impl (w) &&
6429 w->window_type != GDK_WINDOW_FOREIGN &&
6430 !gdk_window_is_toplevel (w))
6432 /* For most native windows we show/hide them not when they are
6433 * mapped/unmapped, because that may not produce the correct results.
6434 * For instance, if a native window have a non-native parent which is
6435 * hidden, but its native parent is viewable then showing the window
6436 * would make it viewable to X but its not viewable wrt the non-native
6437 * hierarchy. In order to handle this we track the gdk side viewability
6438 * and only map really viewable windows.
6440 * There are two exceptions though:
6442 * For foreign windows we don't want ever change the mapped state
6443 * except when explicitly done via gdk_window_show/hide, as this may
6444 * cause problems for client owning the foreign window when its window
6445 * is suddenly mapped or unmapped.
6447 * For toplevel windows embedded in a foreign window (e.g. a plug)
6448 * we sometimes synthesize a map of a window, but the native
6449 * window is really shown by the embedder, so we don't want to
6450 * do the show ourselves. We can't really tell this case from the normal
6451 * toplevel show as such toplevels are seen by gdk as parents of the
6452 * root window, so we make an exception for all toplevels.
6454 * Also, when in GDK_NATIVE_WINDOW mode we never need to play games
6455 * like this, so we just always show/hide directly.
6458 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (w->impl);
6460 impl_iface->show ((GdkWindow *)w, FALSE);
6462 impl_iface->hide ((GdkWindow *)w);
6470 /* Returns TRUE If the native window was mapped or unmapped */
6472 _gdk_window_update_viewable (GdkWindow *window)
6474 GdkWindowObject *priv = (GdkWindowObject *)window;
6477 if (priv->window_type == GDK_WINDOW_FOREIGN ||
6478 priv->window_type == GDK_WINDOW_ROOT)
6480 else if (gdk_window_is_toplevel (priv) ||
6481 priv->parent->viewable)
6482 viewable = GDK_WINDOW_IS_MAPPED (priv);
6486 return set_viewable (priv, viewable);
6490 gdk_window_show_internal (GdkWindow *window, gboolean raise)
6492 GdkWindowObject *private;
6493 GdkWindowImplIface *impl_iface;
6494 gboolean was_mapped, was_viewable;
6497 g_return_if_fail (GDK_IS_WINDOW (window));
6499 private = (GdkWindowObject *) window;
6500 if (private->destroyed)
6503 was_mapped = GDK_WINDOW_IS_MAPPED (window);
6504 was_viewable = private->viewable;
6507 /* Keep children in (reverse) stacking order */
6508 gdk_window_raise_internal (window);
6510 if (gdk_window_has_impl (private))
6513 gdk_synthesize_window_state (window,
6514 GDK_WINDOW_STATE_WITHDRAWN,
6522 did_show = _gdk_window_update_viewable (window);
6524 /* If it was already viewable the backend show op won't be called, call it
6525 again to ensure things happen right if the mapped tracking was not right
6526 for e.g. a foreign window.
6527 Dunno if this is strictly needed but its what happened pre-csw.
6528 Also show if not done by gdk_window_update_viewable. */
6529 if (gdk_window_has_impl (private) && (was_viewable || !did_show))
6531 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
6532 impl_iface->show ((GdkWindow *)private,
6533 !did_show ? was_mapped : TRUE);
6536 if (!was_mapped && !gdk_window_has_impl (private))
6538 if (private->event_mask & GDK_STRUCTURE_MASK)
6539 _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
6541 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
6542 _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
6545 if (!was_mapped || raise)
6547 recompute_visible_regions (private, TRUE, FALSE);
6549 /* If any decendants became visible we need to send visibility notify */
6550 gdk_window_update_visibility_recursively (private, NULL);
6552 if (gdk_window_is_viewable (window))
6554 _gdk_synthesize_crossing_events_for_geometry_change (window);
6555 gdk_window_invalidate_rect_full (window, NULL, TRUE, CLEAR_BG_ALL);
6561 * gdk_window_show_unraised:
6562 * @window: a #GdkWindow
6564 * Shows a #GdkWindow onscreen, but does not modify its stacking
6565 * order. In contrast, gdk_window_show() will raise the window
6566 * to the top of the window stack.
6568 * On the X11 platform, in Xlib terms, this function calls
6569 * XMapWindow() (it also updates some internal GDK state, which means
6570 * that you can't really use XMapWindow() directly on a GDK window).
6573 gdk_window_show_unraised (GdkWindow *window)
6575 gdk_window_show_internal (window, FALSE);
6580 * @window: a #GdkWindow
6582 * Raises @window to the top of the Z-order (stacking order), so that
6583 * other windows with the same parent window appear below @window.
6584 * This is true whether or not the windows are visible.
6586 * If @window is a toplevel, the window manager may choose to deny the
6587 * request to move the window in the Z-order, gdk_window_raise() only
6588 * requests the restack, does not guarantee it.
6591 gdk_window_raise (GdkWindow *window)
6593 GdkWindowObject *private;
6594 GdkRegion *old_region, *new_region;
6596 g_return_if_fail (GDK_IS_WINDOW (window));
6598 private = (GdkWindowObject *) window;
6599 if (private->destroyed)
6602 gdk_window_flush_if_exposing (window);
6605 if (gdk_window_is_viewable (window) &&
6606 !private->input_only)
6607 old_region = gdk_region_copy (private->clip_region);
6609 /* Keep children in (reverse) stacking order */
6610 gdk_window_raise_internal (window);
6612 recompute_visible_regions (private, TRUE, FALSE);
6616 new_region = gdk_region_copy (private->clip_region);
6618 gdk_region_subtract (new_region, old_region);
6619 gdk_window_invalidate_region_full (window, new_region, TRUE, CLEAR_BG_ALL);
6621 gdk_region_destroy (old_region);
6622 gdk_region_destroy (new_region);
6627 gdk_window_lower_internal (GdkWindow *window)
6629 GdkWindowObject *private = (GdkWindowObject *)window;
6630 GdkWindowObject *parent = private->parent;
6631 GdkWindowImplIface *impl_iface;
6632 GdkWindowObject *above;
6633 GList *native_children;
6638 parent->children = g_list_remove (parent->children, window);
6639 parent->children = g_list_append (parent->children, window);
6642 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
6643 /* Just do native lower for toplevels */
6644 if (gdk_window_is_toplevel (private) ||
6645 /* The restack_under codepath should work correctly even if the parent
6646 is native, but it relies on the order of ->children to be correct,
6647 and some apps like SWT reorder the x windows without gdks knowledge,
6648 so we use lower directly in order to make these behave as before
6649 when using native windows */
6650 (gdk_window_has_impl (private) && gdk_window_has_impl (parent)))
6652 impl_iface->lower (window);
6654 else if (gdk_window_has_impl (private))
6656 above = find_native_sibling_above (parent, private);
6659 listhead.data = window;
6660 listhead.next = NULL;
6661 listhead.prev = NULL;
6662 impl_iface->restack_under ((GdkWindow *)above, &listhead);
6665 impl_iface->raise (window);
6669 native_children = NULL;
6670 get_all_native_children (private, &native_children);
6671 if (native_children != NULL)
6673 above = find_native_sibling_above (parent, private);
6676 impl_iface->restack_under ((GdkWindow *)above,
6680 /* Right order, since native_children is bottom-topmost first */
6681 for (l = native_children; l != NULL; l = l->next)
6682 impl_iface->raise (l->data);
6685 g_list_free (native_children);
6692 gdk_window_invalidate_in_parent (GdkWindowObject *private)
6694 GdkRectangle r, child;
6696 if (gdk_window_is_toplevel (private))
6699 /* get the visible rectangle of the parent */
6701 r.width = private->parent->width;
6702 r.height = private->parent->height;
6704 child.x = private->x;
6705 child.y = private->y;
6706 child.width = private->width;
6707 child.height = private->height;
6708 gdk_rectangle_intersect (&r, &child, &r);
6710 gdk_window_invalidate_rect_full (GDK_WINDOW (private->parent), &r, TRUE, CLEAR_BG_ALL);
6716 * @window: a #GdkWindow
6718 * Lowers @window to the bottom of the Z-order (stacking order), so that
6719 * other windows with the same parent window appear above @window.
6720 * This is true whether or not the other windows are visible.
6722 * If @window is a toplevel, the window manager may choose to deny the
6723 * request to move the window in the Z-order, gdk_window_lower() only
6724 * requests the restack, does not guarantee it.
6726 * Note that gdk_window_show() raises the window again, so don't call this
6727 * function before gdk_window_show(). (Try gdk_window_show_unraised().)
6730 gdk_window_lower (GdkWindow *window)
6732 GdkWindowObject *private;
6734 g_return_if_fail (GDK_IS_WINDOW (window));
6736 private = (GdkWindowObject *) window;
6737 if (private->destroyed)
6740 gdk_window_flush_if_exposing (window);
6742 /* Keep children in (reverse) stacking order */
6743 gdk_window_lower_internal (window);
6745 recompute_visible_regions (private, TRUE, FALSE);
6747 _gdk_synthesize_crossing_events_for_geometry_change (window);
6748 gdk_window_invalidate_in_parent (private);
6752 * gdk_window_restack:
6753 * @window: a #GdkWindow
6754 * @sibling: a #GdkWindow that is a sibling of @window, or %NULL
6757 * Changes the position of @window in the Z-order (stacking order), so that
6758 * it is above @sibling (if @above is %TRUE) or below @sibling (if @above is
6761 * If @sibling is %NULL, then this either raises (if @above is %TRUE) or
6762 * lowers the window.
6764 * If @window is a toplevel, the window manager may choose to deny the
6765 * request to move the window in the Z-order, gdk_window_restack() only
6766 * requests the restack, does not guarantee it.
6771 gdk_window_restack (GdkWindow *window,
6775 GdkWindowObject *private;
6776 GdkWindowImplIface *impl_iface;
6777 GdkWindowObject *parent;
6778 GdkWindowObject *above_native;
6779 GList *sibling_link;
6780 GList *native_children;
6783 g_return_if_fail (GDK_IS_WINDOW (window));
6784 g_return_if_fail (sibling == NULL || GDK_IS_WINDOW (sibling));
6786 private = (GdkWindowObject *) window;
6787 if (private->destroyed)
6790 if (sibling == NULL)
6793 gdk_window_raise (window);
6795 gdk_window_lower (window);
6799 gdk_window_flush_if_exposing (window);
6801 if (gdk_window_is_toplevel (private))
6803 g_return_if_fail (gdk_window_is_toplevel (GDK_WINDOW_OBJECT (sibling)));
6804 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
6805 impl_iface->restack_toplevel (window, sibling, above);
6809 parent = private->parent;
6812 sibling_link = g_list_find (parent->children, sibling);
6813 g_return_if_fail (sibling_link != NULL);
6814 if (sibling_link == NULL)
6817 parent->children = g_list_remove (parent->children, window);
6819 parent->children = g_list_insert_before (parent->children,
6823 parent->children = g_list_insert_before (parent->children,
6827 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
6828 if (gdk_window_has_impl (private))
6830 above_native = find_native_sibling_above (parent, private);
6833 listhead.data = window;
6834 listhead.next = NULL;
6835 listhead.prev = NULL;
6836 impl_iface->restack_under ((GdkWindow *)above_native, &listhead);
6839 impl_iface->raise (window);
6843 native_children = NULL;
6844 get_all_native_children (private, &native_children);
6845 if (native_children != NULL)
6847 above_native = find_native_sibling_above (parent, private);
6849 impl_iface->restack_under ((GdkWindow *)above_native,
6853 /* Right order, since native_children is bottom-topmost first */
6854 for (l = native_children; l != NULL; l = l->next)
6855 impl_iface->raise (l->data);
6858 g_list_free (native_children);
6863 recompute_visible_regions (private, TRUE, FALSE);
6865 _gdk_synthesize_crossing_events_for_geometry_change (window);
6866 gdk_window_invalidate_in_parent (private);
6872 * @window: a #GdkWindow
6874 * Like gdk_window_show_unraised(), but also raises the window to the
6875 * top of the window stack (moves the window to the front of the
6878 * This function maps a window so it's visible onscreen. Its opposite
6879 * is gdk_window_hide().
6881 * When implementing a #GtkWidget, you should call this function on the widget's
6882 * #GdkWindow as part of the "map" method.
6885 gdk_window_show (GdkWindow *window)
6887 gdk_window_show_internal (window, TRUE);
6892 * @window: a #GdkWindow
6894 * For toplevel windows, withdraws them, so they will no longer be
6895 * known to the window manager; for all windows, unmaps them, so
6896 * they won't be displayed. Normally done automatically as
6897 * part of gtk_widget_hide().
6900 gdk_window_hide (GdkWindow *window)
6902 GdkWindowObject *private;
6903 GdkWindowImplIface *impl_iface;
6904 gboolean was_mapped, did_hide;
6906 g_return_if_fail (GDK_IS_WINDOW (window));
6908 private = (GdkWindowObject *) window;
6909 if (private->destroyed)
6912 was_mapped = GDK_WINDOW_IS_MAPPED (private);
6914 if (gdk_window_has_impl (private))
6917 if (GDK_WINDOW_IS_MAPPED (window))
6918 gdk_synthesize_window_state (window,
6920 GDK_WINDOW_STATE_WITHDRAWN);
6922 else if (was_mapped)
6924 GdkDisplay *display;
6926 /* May need to break grabs on children */
6927 display = gdk_drawable_get_display (window);
6929 if (_gdk_display_end_pointer_grab (display,
6930 _gdk_windowing_window_get_next_serial (display),
6933 gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
6935 if (display->keyboard_grab.window != NULL)
6937 if (is_parent_of (window, display->keyboard_grab.window))
6939 /* Call this ourselves, even though gdk_display_keyboard_ungrab
6940 does so too, since we want to pass implicit == TRUE so the
6941 broken grab event is generated */
6942 _gdk_display_unset_has_keyboard_grab (display,
6944 gdk_display_keyboard_ungrab (display, GDK_CURRENT_TIME);
6948 private->state = GDK_WINDOW_STATE_WITHDRAWN;
6951 did_hide = _gdk_window_update_viewable (window);
6953 /* Hide foreign window as those are not handled by update_viewable. */
6954 if (gdk_window_has_impl (private) && (!did_hide))
6956 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
6957 impl_iface->hide (window);
6960 recompute_visible_regions (private, TRUE, FALSE);
6962 /* all decendants became non-visible, we need to send visibility notify */
6963 gdk_window_update_visibility_recursively (private, NULL);
6965 if (was_mapped && !gdk_window_has_impl (private))
6967 if (private->event_mask & GDK_STRUCTURE_MASK)
6968 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6970 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
6971 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6973 _gdk_synthesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
6976 /* Invalidate the rect */
6978 gdk_window_invalidate_in_parent (private);
6982 * gdk_window_withdraw:
6983 * @window: a toplevel #GdkWindow
6985 * Withdraws a window (unmaps it and asks the window manager to forget about it).
6986 * This function is not really useful as gdk_window_hide() automatically
6987 * withdraws toplevel windows before hiding them.
6990 gdk_window_withdraw (GdkWindow *window)
6992 GdkWindowObject *private;
6993 GdkWindowImplIface *impl_iface;
6994 gboolean was_mapped;
6996 g_return_if_fail (GDK_IS_WINDOW (window));
6998 private = (GdkWindowObject *) window;
6999 if (private->destroyed)
7002 was_mapped = GDK_WINDOW_IS_MAPPED (private);
7004 if (gdk_window_has_impl (private))
7006 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
7007 impl_iface->withdraw (window);
7011 if (private->event_mask & GDK_STRUCTURE_MASK)
7012 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
7014 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
7015 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
7017 _gdk_synthesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
7020 recompute_visible_regions (private, TRUE, FALSE);
7025 * gdk_window_set_events:
7026 * @window: a #GdkWindow
7027 * @event_mask: event mask for @window
7029 * The event mask for a window determines which events will be reported
7030 * for that window. For example, an event mask including #GDK_BUTTON_PRESS_MASK
7031 * means the window should report button press events. The event mask
7032 * is the bitwise OR of values from the #GdkEventMask enumeration.
7035 gdk_window_set_events (GdkWindow *window,
7036 GdkEventMask event_mask)
7038 GdkWindowObject *private;
7039 GdkWindowImplIface *impl_iface;
7040 GdkDisplay *display;
7042 g_return_if_fail (GDK_IS_WINDOW (window));
7044 private = (GdkWindowObject *) window;
7045 if (private->destroyed)
7048 /* If motion hint is disabled, enable motion events again */
7049 display = gdk_drawable_get_display (window);
7050 if ((private->event_mask & GDK_POINTER_MOTION_HINT_MASK) &&
7051 !(event_mask & GDK_POINTER_MOTION_HINT_MASK))
7052 _gdk_display_enable_motion_hints (display);
7054 private->event_mask = event_mask;
7056 if (gdk_window_has_impl (private))
7058 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
7059 impl_iface->set_events (window,
7060 get_native_event_mask (private));
7066 * gdk_window_get_events:
7067 * @window: a #GdkWindow
7069 * Gets the event mask for @window. See gdk_window_set_events().
7071 * Return value: event mask for @window
7074 gdk_window_get_events (GdkWindow *window)
7076 GdkWindowObject *private;
7078 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
7080 private = (GdkWindowObject *) window;
7081 if (private->destroyed)
7084 return private->event_mask;
7088 gdk_window_move_resize_toplevel (GdkWindow *window,
7095 GdkWindowObject *private;
7096 GdkRegion *old_region, *new_region;
7097 GdkWindowImplIface *impl_iface;
7099 int old_x, old_y, old_abs_x, old_abs_y;
7103 private = (GdkWindowObject *) window;
7111 is_resize = (width != -1) || (height != -1);
7113 if (gdk_window_is_viewable (window) &&
7114 !private->input_only)
7117 old_region = gdk_region_copy (private->clip_region);
7120 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
7121 impl_iface->move_resize (window, with_move, x, y, width, height);
7123 dx = private->x - old_x;
7124 dy = private->y - old_y;
7126 old_abs_x = private->abs_x;
7127 old_abs_y = private->abs_y;
7129 /* Avoid recomputing for pure toplevel moves, for performance reasons */
7131 recompute_visible_regions (private, TRUE, FALSE);
7135 new_region = gdk_region_copy (private->clip_region);
7137 /* This is the newly exposed area (due to any resize),
7138 * X will expose it, but lets do that without the
7141 gdk_region_subtract (new_region, old_region);
7142 gdk_window_invalidate_region_full (window, new_region, TRUE, CLEAR_BG_WINCLEARED);
7144 gdk_region_destroy (old_region);
7145 gdk_region_destroy (new_region);
7148 _gdk_synthesize_crossing_events_for_geometry_change (window);
7153 move_native_children (GdkWindowObject *private)
7156 GdkWindowObject *child;
7157 GdkWindowImplIface *impl_iface;
7159 for (l = private->children; l; l = l->next)
7163 if (child->impl != private->impl)
7165 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (child->impl);
7166 impl_iface->move_resize ((GdkWindow *)child, TRUE,
7168 child->width, child->height);
7171 move_native_children (child);
7176 collect_native_child_region_helper (GdkWindowObject *window,
7182 GdkWindowObject *child;
7186 for (l = window->children; l != NULL; l = l->next)
7190 if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only)
7193 if (child->impl != impl)
7195 tmp = gdk_region_copy (child->clip_region);
7196 gdk_region_offset (tmp,
7197 x_offset + child->x,
7198 y_offset + child->y);
7199 if (*region == NULL)
7203 gdk_region_union (*region, tmp);
7204 gdk_region_destroy (tmp);
7208 collect_native_child_region_helper (child, impl, region,
7209 x_offset + child->x,
7210 y_offset + child->y);
7217 collect_native_child_region (GdkWindowObject *window,
7218 gboolean include_this)
7222 if (include_this && gdk_window_has_impl (window) && window->viewable)
7223 return gdk_region_copy (window->clip_region);
7227 collect_native_child_region_helper (window, window->impl, ®ion, 0, 0);
7234 gdk_window_move_resize_internal (GdkWindow *window,
7241 GdkWindowObject *private;
7242 GdkRegion *old_region, *new_region, *copy_area;
7243 GdkRegion *old_native_child_region, *new_native_child_region;
7244 GdkWindowObject *impl_window;
7245 GdkWindowImplIface *impl_iface;
7247 int old_x, old_y, old_abs_x, old_abs_y;
7250 g_return_if_fail (GDK_IS_WINDOW (window));
7252 private = (GdkWindowObject *) window;
7253 if (private->destroyed)
7256 if (gdk_window_is_toplevel (private))
7258 gdk_window_move_resize_toplevel (window, with_move, x, y, width, height);
7262 /* Bail early if no change */
7263 if (private->width == width &&
7264 private->height == height &&
7270 gdk_window_flush_if_exposing (window);
7272 /* Handle child windows */
7277 impl_window = gdk_window_get_impl_window (private);
7282 old_native_child_region = NULL;
7283 if (gdk_window_is_viewable (window) &&
7284 !private->input_only)
7288 old_region = gdk_region_copy (private->clip_region);
7289 /* Adjust region to parent window coords */
7290 gdk_region_offset (old_region, private->x, private->y);
7292 old_native_child_region = collect_native_child_region (private, TRUE);
7293 if (old_native_child_region)
7295 /* Adjust region to parent window coords */
7296 gdk_region_offset (old_native_child_region, private->x, private->y);
7298 /* Any native window move will immediately copy stuff to the destination, which may overwrite a
7299 * source or destination for a delayed GdkWindowRegionMove. So, we need
7300 * to flush those here for the parent window and all overlapped subwindows
7301 * of it. And we need to do this before setting the new clips as those will be
7304 gdk_window_flush_recursive (private->parent);
7308 /* Set the new position and size */
7314 if (!(width < 0 && height < 0))
7318 private->width = width;
7321 private->height = height;
7324 dx = private->x - old_x;
7325 dy = private->y - old_y;
7327 old_abs_x = private->abs_x;
7328 old_abs_y = private->abs_y;
7330 recompute_visible_regions (private, TRUE, FALSE);
7332 new_native_child_region = NULL;
7333 if (old_native_child_region)
7335 new_native_child_region = collect_native_child_region (private, TRUE);
7336 /* Adjust region to parent window coords */
7337 gdk_region_offset (new_native_child_region, private->x, private->y);
7340 if (gdk_window_has_impl (private))
7342 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
7344 /* Do the actual move after recomputing things, as this will have set the shape to
7345 the now correct one, thus avoiding copying regions that should not be copied. */
7346 impl_iface->move_resize (window, TRUE,
7347 private->x, private->y,
7348 private->width, private->height);
7350 else if (old_abs_x != private->abs_x ||
7351 old_abs_y != private->abs_y)
7352 move_native_children (private);
7356 new_region = gdk_region_copy (private->clip_region);
7357 /* Adjust region to parent window coords */
7358 gdk_region_offset (new_region, private->x, private->y);
7361 * Part of the data at the new location can be copied from the
7362 * old location, this area is the intersection of the old region
7363 * moved as the copy will move it and then intersected with
7367 * Everything in the old and new regions that is not copied must be
7368 * invalidated (including children) as this is newly exposed
7370 copy_area = gdk_region_copy (new_region);
7372 gdk_region_union (new_region, old_region);
7374 if (old_native_child_region)
7376 /* Don't copy from inside native children, as this is copied by
7377 * the native window move.
7379 gdk_region_subtract (old_region, old_native_child_region);
7381 gdk_region_offset (old_region, dx, dy);
7383 gdk_region_intersect (copy_area, old_region);
7385 if (new_native_child_region)
7387 /* Don't copy any bits that would cause a read from the moved
7388 native windows, as we can't read that data */
7389 gdk_region_offset (new_native_child_region, dx, dy);
7390 gdk_region_subtract (copy_area, new_native_child_region);
7391 gdk_region_offset (new_native_child_region, -dx, -dy);
7394 gdk_region_subtract (new_region, copy_area);
7396 /* Convert old region to impl coords */
7397 gdk_region_offset (old_region, -dx + private->abs_x - private->x, -dy + private->abs_y - private->y);
7399 /* convert from parent coords to impl */
7400 gdk_region_offset (copy_area, private->abs_x - private->x, private->abs_y - private->y);
7402 move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
7404 /* Invalidate affected part in the parent window
7405 * (no higher window should be affected)
7406 * We also invalidate any children in that area, which could include
7407 * this window if it still overlaps that area.
7409 if (old_native_child_region)
7411 /* No need to expose the region that the native window move copies */
7412 gdk_region_offset (old_native_child_region, dx, dy);
7413 gdk_region_intersect (old_native_child_region, new_native_child_region);
7414 gdk_region_subtract (new_region, old_native_child_region);
7416 gdk_window_invalidate_region_full (GDK_WINDOW (private->parent), new_region, TRUE, CLEAR_BG_ALL);
7418 gdk_region_destroy (old_region);
7419 gdk_region_destroy (new_region);
7422 if (old_native_child_region)
7424 gdk_region_destroy (old_native_child_region);
7425 gdk_region_destroy (new_native_child_region);
7428 _gdk_synthesize_crossing_events_for_geometry_change (window);
7435 * @window: a #GdkWindow
7436 * @x: X coordinate relative to window's parent
7437 * @y: Y coordinate relative to window's parent
7439 * Repositions a window relative to its parent window.
7440 * For toplevel windows, window managers may ignore or modify the move;
7441 * you should probably use gtk_window_move() on a #GtkWindow widget
7442 * anyway, instead of using GDK functions. For child windows,
7443 * the move will reliably succeed.
7445 * If you're also planning to resize the window, use gdk_window_move_resize()
7446 * to both move and resize simultaneously, for a nicer visual effect.
7449 gdk_window_move (GdkWindow *window,
7453 gdk_window_move_resize_internal (window, TRUE, x, y, -1, -1);
7457 * gdk_window_resize:
7458 * @window: a #GdkWindow
7459 * @width: new width of the window
7460 * @height: new height of the window
7462 * Resizes @window; for toplevel windows, asks the window manager to resize
7463 * the window. The window manager may not allow the resize. When using GTK+,
7464 * use gtk_window_resize() instead of this low-level GDK function.
7466 * Windows may not be resized below 1x1.
7468 * If you're also planning to move the window, use gdk_window_move_resize()
7469 * to both move and resize simultaneously, for a nicer visual effect.
7472 gdk_window_resize (GdkWindow *window,
7476 gdk_window_move_resize_internal (window, FALSE, 0, 0, width, height);
7481 * gdk_window_move_resize:
7482 * @window: a #GdkWindow
7483 * @x: new X position relative to window's parent
7484 * @y: new Y position relative to window's parent
7486 * @height: new height
7488 * Equivalent to calling gdk_window_move() and gdk_window_resize(),
7489 * except that both operations are performed at once, avoiding strange
7490 * visual effects. (i.e. the user may be able to see the window first
7491 * move, then resize, if you don't use gdk_window_move_resize().)
7494 gdk_window_move_resize (GdkWindow *window,
7500 gdk_window_move_resize_internal (window, TRUE, x, y, width, height);
7505 * gdk_window_scroll:
7506 * @window: a #GdkWindow
7507 * @dx: Amount to scroll in the X direction
7508 * @dy: Amount to scroll in the Y direction
7510 * Scroll the contents of @window, both pixels and children, by the
7511 * given amount. @window itself does not move. Portions of the window
7512 * that the scroll operation brings in from offscreen areas are
7513 * invalidated. The invalidated region may be bigger than what would
7514 * strictly be necessary.
7516 * For X11, a minimum area will be invalidated if the window has no
7517 * subwindows, or if the edges of the window's parent do not extend
7518 * beyond the edges of the window. In other cases, a multi-step process
7519 * is used to scroll the window which may produce temporary visual
7520 * artifacts and unnecessary invalidations.
7523 gdk_window_scroll (GdkWindow *window,
7527 GdkWindowObject *private = (GdkWindowObject *) window;
7528 GdkWindowObject *impl_window;
7529 GdkRegion *copy_area, *noncopy_area;
7530 GdkRegion *old_native_child_region, *new_native_child_region;
7533 g_return_if_fail (GDK_IS_WINDOW (window));
7535 if (dx == 0 && dy == 0)
7538 if (private->destroyed)
7541 gdk_window_flush_if_exposing (window);
7543 old_native_child_region = collect_native_child_region (private, FALSE);
7544 if (old_native_child_region)
7546 /* Any native window move will immediately copy stuff to the destination, which may overwrite a
7547 * source or destination for a delayed GdkWindowRegionMove. So, we need
7548 * to flush those here for the window and all overlapped subwindows
7549 * of it. And we need to do this before setting the new clips as those will be
7552 gdk_window_flush_recursive (private);
7556 /* First move all child windows, without causing invalidation */
7558 tmp_list = private->children;
7561 GdkWindow *child = GDK_WINDOW (tmp_list->data);
7562 GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
7564 /* Just update the positions, the bits will move with the copy */
7568 tmp_list = tmp_list->next;
7571 recompute_visible_regions (private, FALSE, TRUE);
7573 new_native_child_region = NULL;
7574 if (old_native_child_region)
7575 new_native_child_region = collect_native_child_region (private, FALSE);
7577 move_native_children (private);
7579 /* Then copy the actual bits of the window w/ child windows */
7581 impl_window = gdk_window_get_impl_window (private);
7583 /* Calculate the area that can be gotten by copying the old area */
7584 copy_area = gdk_region_copy (private->clip_region);
7585 if (old_native_child_region)
7587 /* Don't copy from inside native children, as this is copied by
7588 * the native window move.
7590 gdk_region_subtract (copy_area, old_native_child_region);
7592 /* Don't copy any bits that would cause a read from the moved
7593 native windows, as we can't read that data */
7594 gdk_region_subtract (copy_area, new_native_child_region);
7596 gdk_region_offset (copy_area, dx, dy);
7597 gdk_region_intersect (copy_area, private->clip_region);
7599 /* And the rest need to be invalidated */
7600 noncopy_area = gdk_region_copy (private->clip_region);
7601 gdk_region_subtract (noncopy_area, copy_area);
7603 /* convert from window coords to impl */
7604 gdk_region_offset (copy_area, private->abs_x, private->abs_y);
7606 move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
7608 /* Invalidate not copied regions */
7609 if (old_native_child_region)
7611 /* No need to expose the region that the native window move copies */
7612 gdk_region_offset (old_native_child_region, dx, dy);
7613 gdk_region_intersect (old_native_child_region, new_native_child_region);
7614 gdk_region_subtract (noncopy_area, old_native_child_region);
7616 gdk_window_invalidate_region_full (window, noncopy_area, TRUE, CLEAR_BG_ALL);
7618 gdk_region_destroy (noncopy_area);
7620 if (old_native_child_region)
7622 gdk_region_destroy (old_native_child_region);
7623 gdk_region_destroy (new_native_child_region);
7626 _gdk_synthesize_crossing_events_for_geometry_change (window);
7630 * gdk_window_move_region:
7631 * @window: a #GdkWindow
7632 * @region: The #GdkRegion to move
7633 * @dx: Amount to move in the X direction
7634 * @dy: Amount to move in the Y direction
7636 * Move the part of @window indicated by @region by @dy pixels in the Y
7637 * direction and @dx pixels in the X direction. The portions of @region
7638 * that not covered by the new position of @region are invalidated.
7640 * Child windows are not moved.
7645 gdk_window_move_region (GdkWindow *window,
7646 const GdkRegion *region,
7650 GdkWindowObject *private = (GdkWindowObject *) window;
7651 GdkWindowObject *impl_window;
7652 GdkRegion *nocopy_area;
7653 GdkRegion *copy_area;
7655 g_return_if_fail (GDK_IS_WINDOW (window));
7656 g_return_if_fail (region != NULL);
7658 if (dx == 0 && dy == 0)
7661 if (private->destroyed)
7664 impl_window = gdk_window_get_impl_window (private);
7666 /* compute source regions */
7667 copy_area = gdk_region_copy (region);
7668 gdk_region_intersect (copy_area, private->clip_region_with_children);
7670 /* compute destination regions */
7671 gdk_region_offset (copy_area, dx, dy);
7672 gdk_region_intersect (copy_area, private->clip_region_with_children);
7674 /* Invalidate parts of the region (source and dest) not covered
7676 nocopy_area = gdk_region_copy (region);
7677 gdk_region_offset (nocopy_area, dx, dy);
7678 gdk_region_union (nocopy_area, region);
7679 gdk_region_subtract (nocopy_area, copy_area);
7681 /* convert from window coords to impl */
7682 gdk_region_offset (copy_area, private->abs_x, private->abs_y);
7683 move_region_on_impl (impl_window, copy_area, dx, dy); /* Takes ownership of copy_area */
7685 gdk_window_invalidate_region_full (window, nocopy_area, FALSE, CLEAR_BG_ALL);
7686 gdk_region_destroy (nocopy_area);
7690 * gdk_window_set_background:
7691 * @window: a #GdkWindow
7692 * @color: an allocated #GdkColor
7694 * Sets the background color of @window. (However, when using GTK+,
7695 * set the background of a widget with gtk_widget_modify_bg() - if
7696 * you're an application - or gtk_style_set_background() - if you're
7697 * implementing a custom widget.)
7699 * The @color must be allocated; gdk_rgb_find_color() is the best way
7700 * to allocate a color.
7702 * See also gdk_window_set_back_pixmap().
7705 gdk_window_set_background (GdkWindow *window,
7706 const GdkColor *color)
7708 GdkWindowObject *private;
7709 GdkColormap *colormap = gdk_drawable_get_colormap (window);
7710 GdkWindowImplIface *impl_iface;
7712 g_return_if_fail (GDK_IS_WINDOW (window));
7714 private = (GdkWindowObject *) window;
7716 private->bg_color = *color;
7717 gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
7719 if (private->bg_pixmap &&
7720 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
7721 private->bg_pixmap != GDK_NO_BG)
7722 g_object_unref (private->bg_pixmap);
7724 private->bg_pixmap = NULL;
7726 if (!GDK_WINDOW_DESTROYED (window) &&
7727 gdk_window_has_impl (private) &&
7728 !private->input_only)
7730 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
7731 impl_iface->set_background (window, &private->bg_color);
7736 * gdk_window_set_back_pixmap:
7737 * @window: a #GdkWindow
7738 * @pixmap: a #GdkPixmap, or %NULL
7739 * @parent_relative: whether the tiling origin is at the origin of
7742 * Sets the background pixmap of @window. May also be used to set a
7743 * background of "None" on @window, by setting a background pixmap
7746 * A background pixmap will be tiled, positioning the first tile at
7747 * the origin of @window, or if @parent_relative is %TRUE, the tiling
7748 * will be done based on the origin of the parent window (useful to
7749 * align tiles in a parent with tiles in a child).
7751 * A background pixmap of %NULL means that the window will have no
7752 * background. A window with no background will never have its
7753 * background filled by the windowing system, instead the window will
7754 * contain whatever pixels were already in the corresponding area of
7757 * The windowing system will normally fill a window with its background
7758 * when the window is obscured then exposed, and when you call
7759 * gdk_window_clear().
7762 gdk_window_set_back_pixmap (GdkWindow *window,
7764 gboolean parent_relative)
7766 GdkWindowObject *private;
7767 GdkWindowImplIface *impl_iface;
7769 g_return_if_fail (GDK_IS_WINDOW (window));
7770 g_return_if_fail (pixmap == NULL || !parent_relative);
7771 g_return_if_fail (pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap));
7773 private = (GdkWindowObject *) window;
7775 if (pixmap && !gdk_drawable_get_colormap (pixmap))
7777 g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
7781 if (private->bg_pixmap &&
7782 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
7783 private->bg_pixmap != GDK_NO_BG)
7784 g_object_unref (private->bg_pixmap);
7786 if (parent_relative)
7787 private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
7789 private->bg_pixmap = g_object_ref (pixmap);
7791 private->bg_pixmap = GDK_NO_BG;
7793 if (!GDK_WINDOW_DESTROYED (window) &&
7794 gdk_window_has_impl (private) &&
7795 !private->input_only)
7797 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
7798 impl_iface->set_back_pixmap (window, private->bg_pixmap);
7803 * gdk_window_get_cursor:
7804 * @window: a #GdkWindow
7806 * Retrieves a #GdkCursor pointer for the cursor currently set on the
7807 * specified #GdkWindow, or %NULL. If the return value is %NULL then
7808 * there is no custom cursor set on the specified window, and it is
7809 * using the cursor for its parent window.
7811 * Return value: a #GdkCursor, or %NULL. The returned object is owned
7812 * by the #GdkWindow and should not be unreferenced directly. Use
7813 * gdk_window_set_cursor() to unset the cursor of the window
7818 gdk_window_get_cursor (GdkWindow *window)
7820 GdkWindowObject *private;
7822 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
7824 private = (GdkWindowObject *) window;
7826 return private->cursor;
7830 * gdk_window_set_cursor:
7831 * @window: a #GdkWindow
7834 * Sets the mouse pointer for a #GdkWindow. Use gdk_cursor_new_for_display()
7835 * or gdk_cursor_new_from_pixmap() to create the cursor. To make the cursor
7836 * invisible, use %GDK_BLANK_CURSOR. Passing %NULL for the @cursor argument
7837 * to gdk_window_set_cursor() means that @window will use the cursor of its
7838 * parent window. Most windows should use this default.
7841 gdk_window_set_cursor (GdkWindow *window,
7844 GdkWindowObject *private;
7845 GdkWindowImplIface *impl_iface;
7846 GdkDisplay *display;
7848 g_return_if_fail (GDK_IS_WINDOW (window));
7850 private = (GdkWindowObject *) window;
7851 display = gdk_drawable_get_display (window);
7853 if (private->cursor)
7855 gdk_cursor_unref (private->cursor);
7856 private->cursor = NULL;
7859 if (!GDK_WINDOW_DESTROYED (window))
7862 private->cursor = gdk_cursor_ref (cursor);
7864 if (_gdk_native_windows ||
7865 private->window_type == GDK_WINDOW_ROOT ||
7866 private->window_type == GDK_WINDOW_FOREIGN)
7868 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
7869 impl_iface->set_cursor (window, cursor);
7871 else if (_gdk_window_event_parent_of (window, display->pointer_info.window_under_pointer))
7872 update_cursor (display);
7874 g_object_notify (G_OBJECT (window), "cursor");
7879 * gdk_window_get_geometry:
7880 * @window: a #GdkWindow
7881 * @x: return location for X coordinate of window (relative to its parent)
7882 * @y: return location for Y coordinate of window (relative to its parent)
7883 * @width: return location for width of window
7884 * @height: return location for height of window
7885 * @depth: return location for bit depth of window
7887 * Any of the return location arguments to this function may be %NULL,
7888 * if you aren't interested in getting the value of that field.
7890 * The X and Y coordinates returned are relative to the parent window
7891 * of @window, which for toplevels usually means relative to the
7892 * window decorations (titlebar, etc.) rather than relative to the
7893 * root window (screen-size background window).
7895 * On the X11 platform, the geometry is obtained from the X server,
7896 * so reflects the latest position of @window; this may be out-of-sync
7897 * with the position of @window delivered in the most-recently-processed
7898 * #GdkEventConfigure. gdk_window_get_position() in contrast gets the
7899 * position from the most recent configure event.
7902 * If @window is not a toplevel, it is <emphasis>much</emphasis> better
7903 * to call gdk_window_get_position() and gdk_drawable_get_size() instead,
7904 * because it avoids the roundtrip to the X server and because
7905 * gdk_drawable_get_size() supports the full 32-bit coordinate space,
7906 * whereas gdk_window_get_geometry() is restricted to the 16-bit
7907 * coordinates of X11.
7911 gdk_window_get_geometry (GdkWindow *window,
7918 GdkWindowObject *private, *parent;
7919 GdkWindowImplIface *impl_iface;
7923 GDK_NOTE (MULTIHEAD,
7924 g_message ("gdk_window_get_geometry(): Window needs "
7925 "to be non-NULL to be multi head safe"));
7926 window = gdk_screen_get_root_window ((gdk_screen_get_default ()));
7929 g_return_if_fail (GDK_IS_WINDOW (window));
7931 private = (GdkWindowObject *) window;
7933 if (!GDK_WINDOW_DESTROYED (window))
7935 if (gdk_window_has_impl (private))
7937 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
7938 impl_iface->get_geometry (window, x, y,
7941 /* This reports the position wrt to the native parent, we need to convert
7942 it to be relative to the client side parent */
7943 parent = private->parent;
7944 if (parent && !gdk_window_has_impl (parent))
7947 *x -= parent->abs_x;
7949 *y -= parent->abs_y;
7959 *width = private->width;
7961 *height = private->height;
7963 *depth = private->depth;
7969 * gdk_window_get_origin:
7970 * @window: a #GdkWindow
7971 * @x: return location for X coordinate
7972 * @y: return location for Y coordinate
7974 * Obtains the position of a window in root window coordinates.
7975 * (Compare with gdk_window_get_position() and
7976 * gdk_window_get_geometry() which return the position of a window
7977 * relative to its parent window.)
7979 * Return value: not meaningful, ignore
7982 gdk_window_get_origin (GdkWindow *window,
7986 GdkWindowObject *private;
7987 GdkWindowImplIface *impl_iface;
7989 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
7991 if (GDK_WINDOW_DESTROYED (window))
8000 private = (GdkWindowObject *) window;
8002 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
8003 impl_iface->get_root_coords (window,
8012 * gdk_window_get_root_coords:
8013 * @window: a #GdkWindow
8014 * @x: X coordinate in window
8015 * @y: Y coordinate in window
8016 * @root_x: return location for X coordinate
8017 * @root_y: return location for Y coordinate
8019 * Obtains the position of a window position in root
8020 * window coordinates. This is similar to
8021 * gdk_window_get_origin() but allows you go pass
8022 * in any position in the window, not just the origin.
8025 gdk_window_get_root_coords (GdkWindow *window,
8031 GdkWindowObject *private;
8032 GdkWindowImplIface *impl_iface;
8034 g_return_if_fail (GDK_IS_WINDOW (window));
8036 private = (GdkWindowObject *) window;
8038 if (GDK_WINDOW_DESTROYED (window))
8047 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
8048 impl_iface->get_root_coords (window,
8056 * gdk_window_get_deskrelative_origin:
8057 * @window: a toplevel #GdkWindow
8058 * @x: return location for X coordinate
8059 * @y: return location for Y coordinate
8061 * This gets the origin of a #GdkWindow relative to
8062 * an Enlightenment-window-manager desktop. As long as you don't
8063 * assume that the user's desktop/workspace covers the entire
8064 * root window (i.e. you don't assume that the desktop begins
8065 * at root window coordinate 0,0) this function is not necessary.
8066 * It's deprecated for that reason.
8068 * Return value: not meaningful
8071 gdk_window_get_deskrelative_origin (GdkWindow *window,
8075 GdkWindowObject *private;
8076 GdkWindowImplIface *impl_iface;
8077 gboolean return_val = FALSE;
8081 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
8083 private = (GdkWindowObject *) window;
8085 if (!GDK_WINDOW_DESTROYED (window))
8087 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
8088 return_val = impl_iface->get_deskrelative_origin (window, &tx, &ty);
8091 *x = tx + private->abs_x;
8093 *y = ty + private->abs_y;
8100 * gdk_window_shape_combine_mask:
8101 * @window: a #GdkWindow
8103 * @x: X position of shape mask with respect to @window
8104 * @y: Y position of shape mask with respect to @window
8106 * Applies a shape mask to @window. Pixels in @window corresponding to
8107 * set bits in the @mask will be visible; pixels in @window
8108 * corresponding to unset bits in the @mask will be transparent. This
8109 * gives a non-rectangular window.
8111 * If @mask is %NULL, the shape mask will be unset, and the @x/@y
8112 * parameters are not used.
8114 * On the X11 platform, this uses an X server extension which is
8115 * widely available on most common platforms, but not available on
8116 * very old X servers, and occasionally the implementation will be
8117 * buggy. On servers without the shape extension, this function
8120 * This function works on both toplevel and child windows.
8123 gdk_window_shape_combine_mask (GdkWindow *window,
8128 GdkWindowObject *private;
8131 g_return_if_fail (GDK_IS_WINDOW (window));
8133 private = (GdkWindowObject *) window;
8136 region = _gdk_windowing_get_shape_for_mask (mask);
8140 gdk_window_shape_combine_region (window,
8145 gdk_region_destroy (region);
8149 * gdk_window_shape_combine_region:
8150 * @window: a #GdkWindow
8151 * @shape_region: region of window to be non-transparent
8152 * @offset_x: X position of @shape_region in @window coordinates
8153 * @offset_y: Y position of @shape_region in @window coordinates
8155 * Makes pixels in @window outside @shape_region be transparent,
8156 * so that the window may be nonrectangular. See also
8157 * gdk_window_shape_combine_mask() to use a bitmap as the mask.
8159 * If @shape_region is %NULL, the shape will be unset, so the whole
8160 * window will be opaque again. @offset_x and @offset_y are ignored
8161 * if @shape_region is %NULL.
8163 * On the X11 platform, this uses an X server extension which is
8164 * widely available on most common platforms, but not available on
8165 * very old X servers, and occasionally the implementation will be
8166 * buggy. On servers without the shape extension, this function
8169 * This function works on both toplevel and child windows.
8172 gdk_window_shape_combine_region (GdkWindow *window,
8173 const GdkRegion *shape_region,
8177 GdkWindowObject *private;
8178 GdkRegion *old_region, *new_region, *diff;
8180 g_return_if_fail (GDK_IS_WINDOW (window));
8182 private = (GdkWindowObject *) window;
8184 if (GDK_WINDOW_DESTROYED (window))
8187 private->shaped = (shape_region != NULL);
8190 gdk_region_destroy (private->shape);
8193 if (GDK_WINDOW_IS_MAPPED (window))
8194 old_region = gdk_region_copy (private->clip_region);
8198 private->shape = gdk_region_copy (shape_region);
8199 gdk_region_offset (private->shape, offset_x, offset_y);
8202 private->shape = NULL;
8204 recompute_visible_regions (private, TRUE, FALSE);
8206 if (gdk_window_has_impl (private) &&
8207 !should_apply_clip_as_shape (private))
8208 apply_shape (private, private->shape);
8212 new_region = gdk_region_copy (private->clip_region);
8214 /* New area in the window, needs invalidation */
8215 diff = gdk_region_copy (new_region);
8216 gdk_region_subtract (diff, old_region);
8218 gdk_window_invalidate_region_full (window, diff, TRUE, CLEAR_BG_ALL);
8220 gdk_region_destroy (diff);
8222 if (!gdk_window_is_toplevel (private))
8224 /* New area in the non-root parent window, needs invalidation */
8225 diff = gdk_region_copy (old_region);
8226 gdk_region_subtract (diff, new_region);
8228 /* Adjust region to parent window coords */
8229 gdk_region_offset (diff, private->x, private->y);
8231 gdk_window_invalidate_region_full (GDK_WINDOW (private->parent), diff, TRUE, CLEAR_BG_ALL);
8233 gdk_region_destroy (diff);
8236 gdk_region_destroy (new_region);
8237 gdk_region_destroy (old_region);
8242 do_child_shapes (GdkWindow *window,
8245 GdkWindowObject *private;
8249 private = (GdkWindowObject *) window;
8253 r.width = private->width;
8254 r.height = private->height;
8256 region = gdk_region_rectangle (&r);
8257 remove_child_area (private, NULL, FALSE, region);
8259 if (merge && private->shape)
8260 gdk_region_subtract (region, private->shape);
8262 gdk_window_shape_combine_region (window, region, 0, 0);
8266 * gdk_window_set_child_shapes:
8267 * @window: a #GdkWindow
8269 * Sets the shape mask of @window to the union of shape masks
8270 * for all children of @window, ignoring the shape mask of @window
8271 * itself. Contrast with gdk_window_merge_child_shapes() which includes
8272 * the shape mask of @window in the masks to be merged.
8275 gdk_window_set_child_shapes (GdkWindow *window)
8277 g_return_if_fail (GDK_IS_WINDOW (window));
8279 do_child_shapes (window, FALSE);
8283 * gdk_window_merge_child_shapes:
8284 * @window: a #GdkWindow
8286 * Merges the shape masks for any child windows into the
8287 * shape mask for @window. i.e. the union of all masks
8288 * for @window and its children will become the new mask
8289 * for @window. See gdk_window_shape_combine_mask().
8291 * This function is distinct from gdk_window_set_child_shapes()
8292 * because it includes @window's shape mask in the set of shapes to
8296 gdk_window_merge_child_shapes (GdkWindow *window)
8298 g_return_if_fail (GDK_IS_WINDOW (window));
8300 do_child_shapes (window, TRUE);
8304 * gdk_window_input_shape_combine_mask:
8305 * @window: a #GdkWindow
8306 * @mask: shape mask, or %NULL
8307 * @x: X position of shape mask with respect to @window
8308 * @y: Y position of shape mask with respect to @window
8310 * Like gdk_window_shape_combine_mask(), but the shape applies
8311 * only to event handling. Mouse events which happen while
8312 * the pointer position corresponds to an unset bit in the
8313 * mask will be passed on the window below @window.
8315 * An input shape is typically used with RGBA windows.
8316 * The alpha channel of the window defines which pixels are
8317 * invisible and allows for nicely antialiased borders,
8318 * and the input shape controls where the window is
8321 * On the X11 platform, this requires version 1.1 of the
8324 * On the Win32 platform, this functionality is not present and the
8325 * function does nothing.
8330 gdk_window_input_shape_combine_mask (GdkWindow *window,
8335 GdkWindowObject *private;
8338 g_return_if_fail (GDK_IS_WINDOW (window));
8340 private = (GdkWindowObject *) window;
8343 region = _gdk_windowing_get_shape_for_mask (mask);
8347 gdk_window_input_shape_combine_region (window,
8352 gdk_region_destroy (region);
8356 * gdk_window_input_shape_combine_region:
8357 * @window: a #GdkWindow
8358 * @shape_region: region of window to be non-transparent
8359 * @offset_x: X position of @shape_region in @window coordinates
8360 * @offset_y: Y position of @shape_region in @window coordinates
8362 * Like gdk_window_shape_combine_region(), but the shape applies
8363 * only to event handling. Mouse events which happen while
8364 * the pointer position corresponds to an unset bit in the
8365 * mask will be passed on the window below @window.
8367 * An input shape is typically used with RGBA windows.
8368 * The alpha channel of the window defines which pixels are
8369 * invisible and allows for nicely antialiased borders,
8370 * and the input shape controls where the window is
8373 * On the X11 platform, this requires version 1.1 of the
8376 * On the Win32 platform, this functionality is not present and the
8377 * function does nothing.
8382 gdk_window_input_shape_combine_region (GdkWindow *window,
8383 const GdkRegion *shape_region,
8387 GdkWindowObject *private;
8388 GdkWindowImplIface *impl_iface;
8390 g_return_if_fail (GDK_IS_WINDOW (window));
8392 private = (GdkWindowObject *) window;
8394 if (GDK_WINDOW_DESTROYED (window))
8397 if (private->input_shape)
8398 gdk_region_destroy (private->input_shape);
8402 private->input_shape = gdk_region_copy (shape_region);
8403 gdk_region_offset (private->input_shape, offset_x, offset_y);
8406 private->input_shape = NULL;
8408 if (gdk_window_has_impl (private))
8410 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
8411 impl_iface->input_shape_combine_region (window, private->input_shape, 0, 0);
8414 /* Pointer may have e.g. moved outside window due to the input mask change */
8415 _gdk_synthesize_crossing_events_for_geometry_change (window);
8419 do_child_input_shapes (GdkWindow *window,
8422 GdkWindowObject *private;
8426 private = (GdkWindowObject *) window;
8430 r.width = private->width;
8431 r.height = private->height;
8433 region = gdk_region_rectangle (&r);
8434 remove_child_area (private, NULL, TRUE, region);
8436 if (merge && private->shape)
8437 gdk_region_subtract (region, private->shape);
8438 if (merge && private->input_shape)
8439 gdk_region_subtract (region, private->input_shape);
8441 gdk_window_input_shape_combine_region (window, region, 0, 0);
8446 * gdk_window_set_child_input_shapes:
8447 * @window: a #GdkWindow
8449 * Sets the input shape mask of @window to the union of input shape masks
8450 * for all children of @window, ignoring the input shape mask of @window
8451 * itself. Contrast with gdk_window_merge_child_input_shapes() which includes
8452 * the input shape mask of @window in the masks to be merged.
8457 gdk_window_set_child_input_shapes (GdkWindow *window)
8459 g_return_if_fail (GDK_IS_WINDOW (window));
8461 do_child_input_shapes (window, FALSE);
8465 * gdk_window_merge_child_input_shapes:
8466 * @window: a #GdkWindow
8468 * Merges the input shape masks for any child windows into the
8469 * input shape mask for @window. i.e. the union of all input masks
8470 * for @window and its children will become the new input mask
8471 * for @window. See gdk_window_input_shape_combine_mask().
8473 * This function is distinct from gdk_window_set_child_input_shapes()
8474 * because it includes @window's input shape mask in the set of
8475 * shapes to be merged.
8480 gdk_window_merge_child_input_shapes (GdkWindow *window)
8482 g_return_if_fail (GDK_IS_WINDOW (window));
8484 do_child_input_shapes (window, TRUE);
8489 * gdk_window_set_static_gravities:
8490 * @window: a #GdkWindow
8491 * @use_static: %TRUE to turn on static gravity
8493 * Set the bit gravity of the given window to static, and flag it so
8494 * all children get static subwindow gravity. This is used if you are
8495 * implementing scary features that involve deep knowledge of the
8496 * windowing system. Don't worry about it unless you have to.
8498 * Return value: %TRUE if the server supports static gravity
8501 gdk_window_set_static_gravities (GdkWindow *window,
8502 gboolean use_static)
8504 GdkWindowObject *private;
8505 GdkWindowImplIface *impl_iface;
8507 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
8509 private = (GdkWindowObject *) window;
8511 if (gdk_window_has_impl (private))
8513 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
8514 return impl_iface->set_static_gravities (window, use_static);
8521 * gdk_window_set_composited:
8522 * @window: a #GdkWindow
8523 * @composited: %TRUE to set the window as composited
8525 * Sets a #GdkWindow as composited, or unsets it. Composited
8526 * windows do not automatically have their contents drawn to
8527 * the screen. Drawing is redirected to an offscreen buffer
8528 * and an expose event is emitted on the parent of the composited
8529 * window. It is the responsibility of the parent's expose handler
8530 * to manually merge the off-screen content onto the screen in
8531 * whatever way it sees fit. See <xref linkend="composited-window-example"/>
8534 * It only makes sense for child windows to be composited; see
8535 * gdk_window_set_opacity() if you need translucent toplevel
8538 * An additional effect of this call is that the area of this
8539 * window is no longer clipped from regions marked for
8540 * invalidation on its parent. Draws done on the parent
8541 * window are also no longer clipped by the child.
8543 * This call is only supported on some systems (currently,
8544 * only X11 with new enough Xcomposite and Xdamage extensions).
8545 * You must call gdk_display_supports_composite() to check if
8546 * setting a window as composited is supported before
8547 * attempting to do so.
8552 gdk_window_set_composited (GdkWindow *window,
8553 gboolean composited)
8555 GdkWindowObject *private = (GdkWindowObject *)window;
8556 GdkDisplay *display;
8558 g_return_if_fail (GDK_IS_WINDOW (window));
8560 composited = composited != FALSE;
8562 if (private->composited == composited)
8566 gdk_window_ensure_native (window);
8568 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
8570 if (!gdk_display_supports_composite (display) && composited)
8572 g_warning ("gdk_window_set_composited called but "
8573 "compositing is not supported");
8577 _gdk_windowing_window_set_composited (window, composited);
8579 recompute_visible_regions (private, TRUE, FALSE);
8581 if (GDK_WINDOW_IS_MAPPED (window))
8582 gdk_window_invalidate_in_parent (private);
8584 private->composited = composited;
8589 remove_redirect_from_children (GdkWindowObject *private,
8590 GdkWindowRedirect *redirect)
8593 GdkWindowObject *child;
8595 for (l = private->children; l != NULL; l = l->next)
8599 /* Don't redirect this child if it already has another redirect */
8600 if (child->redirect == redirect)
8602 child->redirect = NULL;
8603 remove_redirect_from_children (child, redirect);
8609 * gdk_window_remove_redirection:
8610 * @window: a #GdkWindow
8612 * Removes any active redirection started by
8613 * gdk_window_redirect_to_drawable().
8618 gdk_window_remove_redirection (GdkWindow *window)
8620 GdkWindowObject *private;
8622 g_return_if_fail (GDK_IS_WINDOW (window));
8624 private = (GdkWindowObject *) window;
8626 if (private->redirect &&
8627 private->redirect->redirected == private)
8629 remove_redirect_from_children (private, private->redirect);
8630 gdk_window_redirect_free (private->redirect);
8631 private->redirect = NULL;
8636 apply_redirect_to_children (GdkWindowObject *private,
8637 GdkWindowRedirect *redirect)
8640 GdkWindowObject *child;
8642 for (l = private->children; l != NULL; l = l->next)
8646 /* Don't redirect this child if it already has another redirect */
8647 if (!child->redirect)
8649 child->redirect = redirect;
8650 apply_redirect_to_children (child, redirect);
8656 * gdk_window_redirect_to_drawable:
8657 * @window: a #GdkWindow
8658 * @drawable: a #GdkDrawable
8659 * @src_x: x position in @window
8660 * @src_y: y position in @window
8661 * @dest_x: x position in @drawable
8662 * @dest_y: y position in @drawable
8663 * @width: width of redirection, or -1 to use the width of @window
8664 * @height: height of redirection or -1 to use the height of @window
8666 * Redirects drawing into @window so that drawing to the
8667 * window in the rectangle specified by @src_x, @src_y,
8668 * @width and @height is also drawn into @drawable at
8671 * Only drawing between gdk_window_begin_paint_region() or
8672 * gdk_window_begin_paint_rect() and gdk_window_end_paint() is
8675 * Redirection is active until gdk_window_remove_redirection()
8681 gdk_window_redirect_to_drawable (GdkWindow *window,
8682 GdkDrawable *drawable,
8690 GdkWindowObject *private;
8692 g_return_if_fail (GDK_IS_WINDOW (window));
8693 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
8694 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
8696 private = (GdkWindowObject *) window;
8698 if (private->redirect)
8699 gdk_window_remove_redirection (window);
8701 if (width == -1 || height == -1)
8704 gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
8711 private->redirect = g_new0 (GdkWindowRedirect, 1);
8712 private->redirect->redirected = private;
8713 private->redirect->pixmap = g_object_ref (drawable);
8714 private->redirect->src_x = src_x;
8715 private->redirect->src_y = src_y;
8716 private->redirect->dest_x = dest_x;
8717 private->redirect->dest_y = dest_y;
8718 private->redirect->width = width;
8719 private->redirect->height = height;
8721 apply_redirect_to_children (private, private->redirect);
8725 window_get_size_rectangle (GdkWindow *window,
8728 GdkWindowObject *private = (GdkWindowObject *) window;
8730 rect->x = rect->y = 0;
8731 rect->width = private->width;
8732 rect->height = private->height;
8735 /* Calculates the real clipping region for a window, in window coordinates,
8736 * taking into account other windows, gc clip region and gc clip mask.
8739 _gdk_window_calculate_full_clip_region (GdkWindow *window,
8740 GdkWindow *base_window,
8741 gboolean do_children,
8742 gint *base_x_offset,
8743 gint *base_y_offset)
8745 GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
8746 GdkRectangle visible_rect;
8747 GdkRegion *real_clip_region, *tmpreg;
8748 gint x_offset, y_offset;
8749 GdkWindowObject *parentwin, *lastwin;
8756 if (!private->viewable || private->input_only)
8757 return gdk_region_new ();
8759 window_get_size_rectangle (window, &visible_rect);
8761 /* real_clip_region is in window coordinates */
8762 real_clip_region = gdk_region_rectangle (&visible_rect);
8764 x_offset = y_offset = 0;
8768 parentwin = lastwin;
8770 parentwin = lastwin->parent;
8772 /* Remove the areas of all overlapping windows above parentwin in the hiearachy */
8773 for (; parentwin != NULL &&
8774 (parentwin == private || lastwin != (GdkWindowObject*) base_window);
8775 lastwin = parentwin, parentwin = lastwin->parent)
8778 GdkRectangle real_clip_rect;
8780 if (parentwin != private)
8782 x_offset += GDK_WINDOW_OBJECT (lastwin)->x;
8783 y_offset += GDK_WINDOW_OBJECT (lastwin)->y;
8786 /* children is ordered in reverse stack order */
8787 for (cur = parentwin->children;
8788 cur && cur->data != lastwin;
8791 GdkWindow *child = cur->data;
8792 GdkWindowObject *child_private = (GdkWindowObject *)child;
8794 if (!GDK_WINDOW_IS_MAPPED (child) || child_private->input_only)
8797 /* Ignore offscreen children, as they don't draw in their parent and
8798 * don't take part in the clipping */
8799 if (gdk_window_is_offscreen (child_private))
8802 window_get_size_rectangle (child, &visible_rect);
8804 /* Convert rect to "window" coords */
8805 visible_rect.x += child_private->x - x_offset;
8806 visible_rect.y += child_private->y - y_offset;
8808 /* This shortcut is really necessary for performance when there are a lot of windows */
8809 gdk_region_get_clipbox (real_clip_region, &real_clip_rect);
8810 if (visible_rect.x >= real_clip_rect.x + real_clip_rect.width ||
8811 visible_rect.x + visible_rect.width <= real_clip_rect.x ||
8812 visible_rect.y >= real_clip_rect.y + real_clip_rect.height ||
8813 visible_rect.y + visible_rect.height <= real_clip_rect.y)
8816 tmpreg = gdk_region_rectangle (&visible_rect);
8817 gdk_region_subtract (real_clip_region, tmpreg);
8818 gdk_region_destroy (tmpreg);
8821 /* Clip to the parent */
8822 window_get_size_rectangle ((GdkWindow *)parentwin, &visible_rect);
8823 /* Convert rect to "window" coords */
8824 visible_rect.x += - x_offset;
8825 visible_rect.y += - y_offset;
8827 tmpreg = gdk_region_rectangle (&visible_rect);
8828 gdk_region_intersect (real_clip_region, tmpreg);
8829 gdk_region_destroy (tmpreg);
8833 *base_x_offset = x_offset;
8835 *base_y_offset = y_offset;
8837 return real_clip_region;
8841 _gdk_window_add_damage (GdkWindow *toplevel,
8842 GdkRegion *damaged_region)
8844 GdkDisplay *display;
8845 GdkEvent event = { 0, };
8846 event.expose.type = GDK_DAMAGE;
8847 event.expose.window = toplevel;
8848 event.expose.send_event = FALSE;
8849 event.expose.region = damaged_region;
8850 gdk_region_get_clipbox (event.expose.region, &event.expose.area);
8851 display = gdk_drawable_get_display (event.expose.window);
8852 _gdk_event_queue_append (display, gdk_event_copy (&event));
8856 gdk_window_redirect_free (GdkWindowRedirect *redirect)
8858 g_object_unref (redirect->pixmap);
8862 /* Gets the toplevel for a window as used for events,
8863 i.e. including offscreen parents */
8864 static GdkWindowObject *
8865 get_event_parent (GdkWindowObject *window)
8867 if (window->window_type == GDK_WINDOW_OFFSCREEN)
8868 return (GdkWindowObject *)gdk_offscreen_window_get_embedder ((GdkWindow *)window);
8870 return window->parent;
8873 /* Gets the toplevel for a window as used for events,
8874 i.e. including offscreen parents going up to the native
8877 get_event_toplevel (GdkWindow *w)
8879 GdkWindowObject *private = GDK_WINDOW_OBJECT (w);
8880 GdkWindowObject *parent;
8882 while ((parent = get_event_parent (private)) != NULL &&
8883 (parent->window_type != GDK_WINDOW_ROOT))
8886 return GDK_WINDOW (private);
8890 _gdk_window_event_parent_of (GdkWindow *parent,
8901 w = (GdkWindow *)get_event_parent ((GdkWindowObject *)w);
8908 update_cursor (GdkDisplay *display)
8910 GdkWindowObject *cursor_window, *parent, *toplevel;
8911 GdkWindow *pointer_window;
8912 GdkWindowImplIface *impl_iface;
8913 GdkPointerGrabInfo *grab;
8915 pointer_window = display->pointer_info.window_under_pointer;
8917 /* We ignore the serials here and just pick the last grab
8918 we've sent, as that would shortly be used anyway. */
8919 grab = _gdk_display_get_last_pointer_grab (display);
8922 /* the pointer is not in a descendant of the grab window */
8923 !_gdk_window_event_parent_of (grab->window, pointer_window))
8924 /* use the cursor from the grab window */
8925 cursor_window = (GdkWindowObject *)grab->window;
8927 /* otherwise use the cursor from the pointer window */
8928 cursor_window = (GdkWindowObject *)pointer_window;
8930 /* Find the first window with the cursor actually set, as
8931 the cursor is inherited from the parent */
8932 while (cursor_window->cursor == NULL &&
8933 (parent = get_event_parent (cursor_window)) != NULL &&
8934 parent->window_type != GDK_WINDOW_ROOT)
8935 cursor_window = parent;
8937 /* Set all cursors on toplevel, otherwise its tricky to keep track of
8938 * which native window has what cursor set. */
8939 toplevel = (GdkWindowObject *)get_event_toplevel (pointer_window);
8940 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (toplevel->impl);
8941 impl_iface->set_cursor ((GdkWindow *)toplevel, cursor_window->cursor);
8945 from_embedder (GdkWindowObject *window,
8948 gdouble *offscreen_x,
8949 gdouble *offscreen_y)
8951 g_signal_emit (window,
8952 signals[FROM_EMBEDDER], 0,
8953 embedder_x, embedder_y,
8954 offscreen_x, offscreen_y,
8959 convert_coords_to_child (GdkWindowObject *child,
8965 if (gdk_window_is_offscreen (child))
8967 from_embedder (child, x, y,
8972 *child_x = x - child->x;
8973 *child_y = y - child->y;
8978 point_in_window (GdkWindowObject *window,
8983 x >= 0 && x < window->width &&
8984 y >= 0 && y < window->height &&
8985 (window->shape == NULL ||
8986 gdk_region_point_in (window->shape,
8988 (window->input_shape == NULL ||
8989 gdk_region_point_in (window->input_shape,
8994 convert_native_coords_to_toplevel (GdkWindow *window,
8997 gdouble *toplevel_x,
8998 gdouble *toplevel_y)
9000 GdkWindowObject *private = (GdkWindowObject *)window;
9006 while (!gdk_window_is_toplevel (private))
9010 private = private->parent;
9016 return (GdkWindow *)private;
9020 convert_toplevel_coords_to_window (GdkWindow *window,
9026 GdkWindowObject *private;
9027 GdkWindowObject *parent;
9029 GList *children, *l;
9031 private = GDK_WINDOW_OBJECT (window);
9037 while ((parent = get_event_parent (private)) != NULL &&
9038 (parent->window_type != GDK_WINDOW_ROOT))
9040 children = g_list_prepend (children, private);
9044 for (l = children; l != NULL; l = l->next)
9045 convert_coords_to_child (l->data, x, y, &x, &y);
9047 g_list_free (children);
9053 static GdkWindowObject *
9054 pick_embedded_child (GdkWindowObject *window,
9058 GdkWindowObject *res;
9061 g_signal_emit (window,
9062 signals[PICK_EMBEDDED_CHILD], 0,
9069 _gdk_window_find_child_at (GdkWindow *window,
9073 GdkWindowObject *private, *sub;
9074 double child_x, child_y;
9077 private = (GdkWindowObject *)window;
9079 if (point_in_window (private, x, y))
9081 /* Children is ordered in reverse stack order, i.e. first is topmost */
9082 for (l = private->children; l != NULL; l = l->next)
9086 if (!GDK_WINDOW_IS_MAPPED (sub))
9089 convert_coords_to_child (sub,
9091 &child_x, &child_y);
9092 if (point_in_window (sub, child_x, child_y))
9093 return (GdkWindow *)sub;
9096 if (private->num_offscreen_children > 0)
9098 sub = pick_embedded_child (private,
9101 return (GdkWindow *)sub;
9109 _gdk_window_find_descendant_at (GdkWindow *toplevel,
9115 GdkWindowObject *private, *sub;
9116 gdouble child_x, child_y;
9120 private = (GdkWindowObject *)toplevel;
9122 if (point_in_window (private, x, y))
9127 /* Children is ordered in reverse stack order, i.e. first is topmost */
9128 for (l = private->children; l != NULL; l = l->next)
9132 if (!GDK_WINDOW_IS_MAPPED (sub))
9135 convert_coords_to_child (sub,
9137 &child_x, &child_y);
9138 if (point_in_window (sub, child_x, child_y))
9148 private->num_offscreen_children > 0)
9150 sub = pick_embedded_child (private,
9156 from_embedder (sub, x, y, &x, &y);
9164 /* Not in window at all */
9173 return (GdkWindow *)private;
9178 * @window: a toplevel #GdkWindow
9180 * Emits a short beep associated to @window in the appropriate
9181 * display, if supported. Otherwise, emits a short beep on
9182 * the display just as gdk_display_beep().
9187 gdk_window_beep (GdkWindow *window)
9189 GdkDisplay *display;
9190 GdkWindow *toplevel;
9192 g_return_if_fail (GDK_IS_WINDOW (window));
9194 if (GDK_WINDOW_DESTROYED (window))
9197 toplevel = get_event_toplevel (window);
9198 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
9200 if (toplevel && !gdk_window_is_offscreen ((GdkWindowObject *)toplevel))
9201 _gdk_windowing_window_beep (toplevel);
9203 gdk_display_beep (display);
9206 static const guint type_masks[] = {
9207 GDK_SUBSTRUCTURE_MASK, /* GDK_DELETE = 0 */
9208 GDK_STRUCTURE_MASK, /* GDK_DESTROY = 1 */
9209 GDK_EXPOSURE_MASK, /* GDK_EXPOSE = 2 */
9210 GDK_POINTER_MOTION_MASK, /* GDK_MOTION_NOTIFY = 3 */
9211 GDK_BUTTON_PRESS_MASK, /* GDK_BUTTON_PRESS = 4 */
9212 GDK_BUTTON_PRESS_MASK, /* GDK_2BUTTON_PRESS = 5 */
9213 GDK_BUTTON_PRESS_MASK, /* GDK_3BUTTON_PRESS = 6 */
9214 GDK_BUTTON_RELEASE_MASK, /* GDK_BUTTON_RELEASE = 7 */
9215 GDK_KEY_PRESS_MASK, /* GDK_KEY_PRESS = 8 */
9216 GDK_KEY_RELEASE_MASK, /* GDK_KEY_RELEASE = 9 */
9217 GDK_ENTER_NOTIFY_MASK, /* GDK_ENTER_NOTIFY = 10 */
9218 GDK_LEAVE_NOTIFY_MASK, /* GDK_LEAVE_NOTIFY = 11 */
9219 GDK_FOCUS_CHANGE_MASK, /* GDK_FOCUS_CHANGE = 12 */
9220 GDK_STRUCTURE_MASK, /* GDK_CONFIGURE = 13 */
9221 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_MAP = 14 */
9222 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_UNMAP = 15 */
9223 GDK_PROPERTY_CHANGE_MASK, /* GDK_PROPERTY_NOTIFY = 16 */
9224 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_CLEAR = 17 */
9225 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_REQUEST = 18 */
9226 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_NOTIFY = 19 */
9227 GDK_PROXIMITY_IN_MASK, /* GDK_PROXIMITY_IN = 20 */
9228 GDK_PROXIMITY_OUT_MASK, /* GDK_PROXIMITY_OUT = 21 */
9229 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_ENTER = 22 */
9230 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_LEAVE = 23 */
9231 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_MOTION = 24 */
9232 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_STATUS = 25 */
9233 GDK_ALL_EVENTS_MASK, /* GDK_DROP_START = 26 */
9234 GDK_ALL_EVENTS_MASK, /* GDK_DROP_FINISHED = 27 */
9235 GDK_ALL_EVENTS_MASK, /* GDK_CLIENT_EVENT = 28 */
9236 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_VISIBILITY_NOTIFY = 29 */
9237 GDK_EXPOSURE_MASK, /* GDK_NO_EXPOSE = 30 */
9238 GDK_SCROLL_MASK | GDK_BUTTON_PRESS_MASK,/* GDK_SCROLL= 31 */
9239 0, /* GDK_WINDOW_STATE = 32 */
9240 0, /* GDK_SETTING = 33 */
9241 0, /* GDK_OWNER_CHANGE = 34 */
9242 0, /* GDK_GRAB_BROKEN = 35 */
9243 0, /* GDK_DAMAGE = 36 */
9245 G_STATIC_ASSERT (G_N_ELEMENTS (type_masks) == GDK_EVENT_LAST);
9247 /* send motion events if the right buttons are down */
9249 update_evmask_for_button_motion (guint evmask,
9250 GdkModifierType mask)
9252 if (evmask & GDK_BUTTON_MOTION_MASK &&
9253 mask & (GDK_BUTTON1_MASK |
9258 evmask |= GDK_POINTER_MOTION_MASK;
9260 if ((evmask & GDK_BUTTON1_MOTION_MASK && mask & GDK_BUTTON1_MASK) ||
9261 (evmask & GDK_BUTTON2_MOTION_MASK && mask & GDK_BUTTON2_MASK) ||
9262 (evmask & GDK_BUTTON3_MOTION_MASK && mask & GDK_BUTTON3_MASK))
9263 evmask |= GDK_POINTER_MOTION_MASK;
9269 is_button_type (GdkEventType type)
9271 return type == GDK_BUTTON_PRESS ||
9272 type == GDK_2BUTTON_PRESS ||
9273 type == GDK_3BUTTON_PRESS ||
9274 type == GDK_BUTTON_RELEASE ||
9279 is_motion_type (GdkEventType type)
9281 return type == GDK_MOTION_NOTIFY ||
9282 type == GDK_ENTER_NOTIFY ||
9283 type == GDK_LEAVE_NOTIFY;
9286 static GdkWindowObject *
9287 find_common_ancestor (GdkWindowObject *win1,
9288 GdkWindowObject *win2)
9290 GdkWindowObject *tmp;
9291 GList *path1 = NULL, *path2 = NULL;
9292 GList *list1, *list2;
9295 while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
9297 path1 = g_list_prepend (path1, tmp);
9298 tmp = get_event_parent (tmp);
9302 while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
9304 path2 = g_list_prepend (path2, tmp);
9305 tmp = get_event_parent (tmp);
9311 while (list1 && list2 && (list1->data == list2->data))
9313 tmp = (GdkWindowObject *)list1->data;
9314 list1 = g_list_next (list1);
9315 list2 = g_list_next (list2);
9317 g_list_free (path1);
9318 g_list_free (path2);
9324 _gdk_make_event (GdkWindow *window,
9326 GdkEvent *event_in_queue,
9327 gboolean before_event)
9329 GdkEvent *event = gdk_event_new (type);
9331 GdkModifierType the_state;
9333 the_time = gdk_event_get_time (event_in_queue);
9334 gdk_event_get_state (event_in_queue, &the_state);
9336 event->any.window = g_object_ref (window);
9337 event->any.send_event = FALSE;
9338 if (event_in_queue && event_in_queue->any.send_event)
9339 event->any.send_event = TRUE;
9343 case GDK_MOTION_NOTIFY:
9344 event->motion.time = the_time;
9345 event->motion.axes = NULL;
9346 event->motion.state = the_state;
9349 case GDK_BUTTON_PRESS:
9350 case GDK_2BUTTON_PRESS:
9351 case GDK_3BUTTON_PRESS:
9352 case GDK_BUTTON_RELEASE:
9353 event->button.time = the_time;
9354 event->button.axes = NULL;
9355 event->button.state = the_state;
9359 event->scroll.time = the_time;
9360 event->scroll.state = the_state;
9364 case GDK_KEY_RELEASE:
9365 event->key.time = the_time;
9366 event->key.state = the_state;
9369 case GDK_ENTER_NOTIFY:
9370 case GDK_LEAVE_NOTIFY:
9371 event->crossing.time = the_time;
9372 event->crossing.state = the_state;
9375 case GDK_PROPERTY_NOTIFY:
9376 event->property.time = the_time;
9377 event->property.state = the_state;
9380 case GDK_SELECTION_CLEAR:
9381 case GDK_SELECTION_REQUEST:
9382 case GDK_SELECTION_NOTIFY:
9383 event->selection.time = the_time;
9386 case GDK_PROXIMITY_IN:
9387 case GDK_PROXIMITY_OUT:
9388 event->proximity.time = the_time;
9391 case GDK_DRAG_ENTER:
9392 case GDK_DRAG_LEAVE:
9393 case GDK_DRAG_MOTION:
9394 case GDK_DRAG_STATUS:
9395 case GDK_DROP_START:
9396 case GDK_DROP_FINISHED:
9397 event->dnd.time = the_time;
9400 case GDK_FOCUS_CHANGE:
9404 case GDK_CLIENT_EVENT:
9405 case GDK_VISIBILITY_NOTIFY:
9417 _gdk_event_queue_insert_before (gdk_drawable_get_display (window), event_in_queue, event);
9419 _gdk_event_queue_insert_after (gdk_drawable_get_display (window), event_in_queue, event);
9422 _gdk_event_queue_append (gdk_drawable_get_display (window), event);
9428 send_crossing_event (GdkDisplay *display,
9429 GdkWindowObject *toplevel,
9430 GdkWindowObject *window,
9432 GdkCrossingMode mode,
9433 GdkNotifyType notify_type,
9434 GdkWindow *subwindow,
9437 GdkModifierType mask,
9439 GdkEvent *event_in_queue,
9443 guint32 window_event_mask, type_event_mask;
9444 GdkPointerGrabInfo *grab;
9445 GdkWindowImplIface *impl_iface;
9447 grab = _gdk_display_has_pointer_grab (display, serial);
9450 !grab->owner_events)
9452 /* !owner_event => only report events wrt grab window, ignore rest */
9453 if ((GdkWindow *)window != grab->window)
9455 window_event_mask = grab->event_mask;
9458 window_event_mask = window->event_mask;
9460 if (type == GDK_LEAVE_NOTIFY)
9461 type_event_mask = GDK_LEAVE_NOTIFY_MASK;
9463 type_event_mask = GDK_ENTER_NOTIFY_MASK;
9465 if (window->extension_events != 0)
9467 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (window->impl);
9468 impl_iface->input_window_crossing ((GdkWindow *)window,
9469 type == GDK_ENTER_NOTIFY);
9472 if (window_event_mask & type_event_mask)
9474 event = _gdk_make_event ((GdkWindow *)window, type, event_in_queue, TRUE);
9475 event->crossing.time = time_;
9476 event->crossing.subwindow = subwindow;
9478 g_object_ref (subwindow);
9479 convert_toplevel_coords_to_window ((GdkWindow *)window,
9480 toplevel_x, toplevel_y,
9481 &event->crossing.x, &event->crossing.y);
9482 event->crossing.x_root = toplevel_x + toplevel->x;
9483 event->crossing.y_root = toplevel_y + toplevel->y;
9484 event->crossing.mode = mode;
9485 event->crossing.detail = notify_type;
9486 event->crossing.focus = FALSE;
9487 event->crossing.state = mask;
9492 /* The coordinates are in the toplevel window that src/dest are in.
9493 * src and dest are always (if != NULL) in the same toplevel, as
9494 * we get a leave-notify and set the window_under_pointer to null
9495 * before crossing to another toplevel.
9498 _gdk_synthesize_crossing_events (GdkDisplay *display,
9501 GdkCrossingMode mode,
9504 GdkModifierType mask,
9506 GdkEvent *event_in_queue,
9508 gboolean non_linear)
9511 GdkWindowObject *win, *last, *next;
9515 GdkWindowObject *toplevel;
9516 GdkNotifyType notify_type;
9518 /* TODO: Don't send events to toplevel, as we get those from the windowing system */
9520 a = (GdkWindowObject *)src;
9521 b = (GdkWindowObject *)dest;
9523 return; /* No crossings generated between src and dest */
9525 c = find_common_ancestor (a, b);
9527 non_linear |= (c != a) && (c != b);
9529 if (a) /* There might not be a source (i.e. if no previous pointer_in_window) */
9531 toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)a);
9533 /* Traverse up from a to (excluding) c sending leave events */
9535 notify_type = GDK_NOTIFY_NONLINEAR;
9537 notify_type = GDK_NOTIFY_INFERIOR;
9539 notify_type = GDK_NOTIFY_ANCESTOR;
9540 send_crossing_event (display, toplevel,
9541 a, GDK_LEAVE_NOTIFY,
9545 toplevel_x, toplevel_y,
9553 notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
9555 notify_type = GDK_NOTIFY_VIRTUAL;
9558 win = get_event_parent (a);
9559 while (win != c && win->window_type != GDK_WINDOW_ROOT)
9561 send_crossing_event (display, toplevel,
9562 win, GDK_LEAVE_NOTIFY,
9566 toplevel_x, toplevel_y,
9572 win = get_event_parent (win);
9577 if (b) /* Might not be a dest, e.g. if we're moving out of the window */
9579 toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)b);
9581 /* Traverse down from c to b */
9585 win = get_event_parent (b);
9586 while (win != c && win->window_type != GDK_WINDOW_ROOT)
9588 path = g_list_prepend (path, win);
9589 win = get_event_parent (win);
9593 notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
9595 notify_type = GDK_NOTIFY_VIRTUAL;
9600 win = (GdkWindowObject *)list->data;
9601 list = g_list_next (list);
9603 next = (GdkWindowObject *)list->data;
9607 send_crossing_event (display, toplevel,
9608 win, GDK_ENTER_NOTIFY,
9612 toplevel_x, toplevel_y,
9622 notify_type = GDK_NOTIFY_NONLINEAR;
9624 notify_type = GDK_NOTIFY_ANCESTOR;
9626 notify_type = GDK_NOTIFY_INFERIOR;
9628 send_crossing_event (display, toplevel,
9629 b, GDK_ENTER_NOTIFY,
9633 toplevel_x, toplevel_y,
9640 /* Returns the window inside the event window with the pointer in it
9641 * at the specified coordinates, or NULL if its not in any child of
9642 * the toplevel. It also takes into account !owner_events grabs.
9645 get_pointer_window (GdkDisplay *display,
9646 GdkWindow *event_window,
9651 GdkWindow *pointer_window;
9652 GdkPointerGrabInfo *grab;
9654 if (event_window == display->pointer_info.toplevel_under_pointer)
9656 _gdk_window_find_descendant_at (event_window,
9657 toplevel_x, toplevel_y,
9660 pointer_window = NULL;
9662 grab = _gdk_display_has_pointer_grab (display, serial);
9664 !grab->owner_events &&
9665 pointer_window != grab->window)
9666 pointer_window = NULL;
9668 return pointer_window;
9672 _gdk_display_set_window_under_pointer (GdkDisplay *display,
9675 /* We don't track this if all native, and it can cause issues
9676 with the update_cursor call below */
9677 if (_gdk_native_windows)
9680 if (display->pointer_info.window_under_pointer)
9681 g_object_unref (display->pointer_info.window_under_pointer);
9682 display->pointer_info.window_under_pointer = window;
9684 g_object_ref (window);
9687 update_cursor (display);
9689 _gdk_display_enable_motion_hints (display);
9693 *--------------------------------------------------------------
9696 * Grabs the pointer to a specific window
9699 * "window" is the window which will receive the grab
9700 * "owner_events" specifies whether events will be reported as is,
9701 * or relative to "window"
9702 * "event_mask" masks only interesting events
9703 * "confine_to" limits the cursor movement to the specified window
9704 * "cursor" changes the cursor for the duration of the grab
9705 * "time" specifies the time
9710 * requires a corresponding call to gdk_pointer_ungrab
9712 *--------------------------------------------------------------
9715 gdk_pointer_grab (GdkWindow * window,
9716 gboolean owner_events,
9717 GdkEventMask event_mask,
9718 GdkWindow * confine_to,
9723 GdkDisplay *display;
9727 g_return_val_if_fail (window != NULL, 0);
9728 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
9729 g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
9731 /* We need a native window for confine to to work, ensure we have one */
9734 if (!gdk_window_ensure_native (confine_to))
9736 g_warning ("Can't confine to grabbed window, not native");
9741 /* Non-viewable client side window => fail */
9742 if (!_gdk_window_has_impl (window) &&
9743 !gdk_window_is_viewable (window))
9744 return GDK_GRAB_NOT_VIEWABLE;
9746 if (_gdk_native_windows)
9749 native = gdk_window_get_toplevel (window);
9750 while (gdk_window_is_offscreen ((GdkWindowObject *)native))
9752 native = gdk_offscreen_window_get_embedder (native);
9754 if (native == NULL ||
9755 (!_gdk_window_has_impl (native) &&
9756 !gdk_window_is_viewable (native)))
9757 return GDK_GRAB_NOT_VIEWABLE;
9759 native = gdk_window_get_toplevel (native);
9762 display = gdk_drawable_get_display (window);
9764 serial = _gdk_windowing_window_get_next_serial (display);
9766 res = _gdk_windowing_pointer_grab (window,
9769 get_native_grab_event_mask (event_mask),
9774 if (res == GDK_GRAB_SUCCESS)
9775 _gdk_display_add_pointer_grab (display,
9788 * gdk_window_geometry_changed:
9789 * @window: an embedded offscreen #GdkWindow
9791 * This function informs GDK that the geometry of an embedded
9792 * offscreen window has changed. This is necessary for GDK to keep
9793 * track of which offscreen window the pointer is in.
9798 gdk_window_geometry_changed (GdkWindow *window)
9800 _gdk_synthesize_crossing_events_for_geometry_change (window);
9804 do_synthesize_crossing_event (gpointer data)
9806 GdkDisplay *display;
9807 GdkWindow *changed_toplevel;
9808 GdkWindowObject *changed_toplevel_priv;
9809 GdkWindow *new_window_under_pointer;
9812 changed_toplevel = data;
9813 changed_toplevel_priv = (GdkWindowObject *)changed_toplevel;
9815 changed_toplevel_priv->synthesize_crossing_event_queued = FALSE;
9817 if (GDK_WINDOW_DESTROYED (changed_toplevel))
9820 display = gdk_drawable_get_display (changed_toplevel);
9821 serial = _gdk_windowing_window_get_next_serial (display);
9823 if (changed_toplevel == display->pointer_info.toplevel_under_pointer)
9825 new_window_under_pointer =
9826 get_pointer_window (display, changed_toplevel,
9827 display->pointer_info.toplevel_x,
9828 display->pointer_info.toplevel_y,
9830 if (new_window_under_pointer !=
9831 display->pointer_info.window_under_pointer)
9833 _gdk_synthesize_crossing_events (display,
9834 display->pointer_info.window_under_pointer,
9835 new_window_under_pointer,
9836 GDK_CROSSING_NORMAL,
9837 display->pointer_info.toplevel_x,
9838 display->pointer_info.toplevel_y,
9839 display->pointer_info.state,
9844 _gdk_display_set_window_under_pointer (display, new_window_under_pointer);
9852 _gdk_synthesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
9854 GdkDisplay *display;
9855 GdkWindow *toplevel;
9856 GdkWindowObject *toplevel_priv;
9858 if (_gdk_native_windows)
9859 return; /* We use the native crossing events if all native */
9861 display = gdk_drawable_get_display (changed_window);
9863 toplevel = get_event_toplevel (changed_window);
9864 toplevel_priv = (GdkWindowObject *)toplevel;
9866 if (toplevel == display->pointer_info.toplevel_under_pointer &&
9867 !toplevel_priv->synthesize_crossing_event_queued)
9869 toplevel_priv->synthesize_crossing_event_queued = TRUE;
9870 g_idle_add_full (GDK_PRIORITY_EVENTS - 1,
9871 do_synthesize_crossing_event,
9872 g_object_ref (toplevel),
9877 /* Don't use for crossing events */
9879 get_event_window (GdkDisplay *display,
9880 GdkWindow *pointer_window,
9882 GdkModifierType mask,
9887 GdkWindow *grab_window;
9889 GdkPointerGrabInfo *grab;
9891 grab = _gdk_display_has_pointer_grab (display, serial);
9893 if (grab != NULL && !grab->owner_events)
9895 evmask = grab->event_mask;
9896 evmask = update_evmask_for_button_motion (evmask, mask);
9898 grab_window = grab->window;
9900 if (evmask & type_masks[type])
9903 *evmask_out = evmask;
9910 w = (GdkWindowObject *)pointer_window;
9913 evmask = w->event_mask;
9914 evmask = update_evmask_for_button_motion (evmask, mask);
9916 if (evmask & type_masks[type])
9919 *evmask_out = evmask;
9920 return (GdkWindow *)w;
9923 w = get_event_parent (w);
9929 evmask = grab->event_mask;
9930 evmask = update_evmask_for_button_motion (evmask, mask);
9932 if (evmask & type_masks[type])
9935 *evmask_out = evmask;
9936 return grab->window;
9946 proxy_pointer_event (GdkDisplay *display,
9947 GdkEvent *source_event,
9950 GdkWindow *toplevel_window, *event_window;
9951 GdkWindow *pointer_window;
9954 gdouble toplevel_x, toplevel_y;
9956 gboolean non_linear;
9958 event_window = source_event->any.window;
9959 gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
9960 gdk_event_get_state (source_event, &state);
9961 time_ = gdk_event_get_time (source_event);
9962 toplevel_window = convert_native_coords_to_toplevel (event_window,
9963 toplevel_x, toplevel_y,
9964 &toplevel_x, &toplevel_y);
9967 if ((source_event->type == GDK_LEAVE_NOTIFY ||
9968 source_event->type == GDK_ENTER_NOTIFY) &&
9969 (source_event->crossing.detail == GDK_NOTIFY_NONLINEAR ||
9970 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))
9973 /* If we get crossing events with subwindow unexpectedly being NULL
9974 that means there is a native subwindow that gdk doesn't know about.
9975 We track these and forward them, with the correct virtual window
9977 This is important to get right, as metacity uses gdk for the frame
9978 windows, but gdk doesn't know about the client windows reparented
9980 if (((source_event->type == GDK_LEAVE_NOTIFY &&
9981 source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
9982 (source_event->type == GDK_ENTER_NOTIFY &&
9983 (source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
9984 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
9985 source_event->crossing.subwindow == NULL)
9987 /* Left for an unknown (to gdk) subwindow */
9989 /* Send leave events from window under pointer to event window
9990 that will get the subwindow == NULL window */
9991 _gdk_synthesize_crossing_events (display,
9992 display->pointer_info.window_under_pointer,
9994 source_event->crossing.mode,
9995 toplevel_x, toplevel_y,
10001 /* Send subwindow == NULL event */
10002 send_crossing_event (display,
10003 (GdkWindowObject *)toplevel_window,
10004 (GdkWindowObject *)event_window,
10005 source_event->type,
10006 source_event->crossing.mode,
10007 source_event->crossing.detail,
10009 toplevel_x, toplevel_y,
10014 _gdk_display_set_window_under_pointer (display, NULL);
10018 pointer_window = get_pointer_window (display, toplevel_window,
10019 toplevel_x, toplevel_y, serial);
10021 if (((source_event->type == GDK_ENTER_NOTIFY &&
10022 source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
10023 (source_event->type == GDK_LEAVE_NOTIFY &&
10024 (source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
10025 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
10026 source_event->crossing.subwindow == NULL)
10028 /* Entered from an unknown (to gdk) subwindow */
10030 /* Send subwindow == NULL event */
10031 send_crossing_event (display,
10032 (GdkWindowObject *)toplevel_window,
10033 (GdkWindowObject *)event_window,
10034 source_event->type,
10035 source_event->crossing.mode,
10036 source_event->crossing.detail,
10038 toplevel_x, toplevel_y,
10043 /* Send enter events from event window to pointer_window */
10044 _gdk_synthesize_crossing_events (display,
10047 source_event->crossing.mode,
10048 toplevel_x, toplevel_y,
10051 serial, non_linear);
10052 _gdk_display_set_window_under_pointer (display, pointer_window);
10056 if (display->pointer_info.window_under_pointer != pointer_window)
10058 /* Either a toplevel crossing notify that ended up inside a child window,
10059 or a motion notify that got into another child window */
10061 /* Different than last time, send crossing events */
10062 _gdk_synthesize_crossing_events (display,
10063 display->pointer_info.window_under_pointer,
10065 GDK_CROSSING_NORMAL,
10066 toplevel_x, toplevel_y,
10069 serial, non_linear);
10070 _gdk_display_set_window_under_pointer (display, pointer_window);
10072 else if (source_event->type == GDK_MOTION_NOTIFY)
10074 GdkWindow *event_win;
10078 event_win = get_event_window (display,
10080 source_event->type,
10088 (evmask & GDK_POINTER_MOTION_HINT_MASK))
10090 if (display->pointer_info.motion_hint_serial != 0 &&
10091 serial < display->pointer_info.motion_hint_serial)
10092 event_win = NULL; /* Ignore event */
10096 display->pointer_info.motion_hint_serial = G_MAXULONG;
10100 if (event_win && !display->ignore_core_events)
10102 event = _gdk_make_event (event_win, GDK_MOTION_NOTIFY, source_event, FALSE);
10103 event->motion.time = time_;
10104 convert_toplevel_coords_to_window (event_win,
10105 toplevel_x, toplevel_y,
10106 &event->motion.x, &event->motion.y);
10107 event->motion.x_root = source_event->motion.x_root;
10108 event->motion.y_root = source_event->motion.y_root;;
10109 event->motion.state = state;
10110 event->motion.is_hint = is_hint;
10111 event->motion.device = NULL;
10112 event->motion.device = source_event->motion.device;
10116 /* unlink all move events from queue.
10117 We handle our own, including our emulated masks. */
10121 #define GDK_ANY_BUTTON_MASK (GDK_BUTTON1_MASK | \
10122 GDK_BUTTON2_MASK | \
10123 GDK_BUTTON3_MASK | \
10124 GDK_BUTTON4_MASK | \
10128 proxy_button_event (GdkEvent *source_event,
10131 GdkWindow *toplevel_window, *event_window;
10132 GdkWindow *event_win;
10133 GdkWindow *pointer_window;
10134 GdkWindowObject *parent;
10139 gdouble toplevel_x, toplevel_y;
10140 GdkDisplay *display;
10141 GdkWindowObject *w;
10143 type = source_event->any.type;
10144 event_window = source_event->any.window;
10145 gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
10146 gdk_event_get_state (source_event, &state);
10147 time_ = gdk_event_get_time (source_event);
10148 display = gdk_drawable_get_display (source_event->any.window);
10149 toplevel_window = convert_native_coords_to_toplevel (event_window,
10150 toplevel_x, toplevel_y,
10151 &toplevel_x, &toplevel_y);
10153 if (type == GDK_BUTTON_PRESS &&
10154 !source_event->any.send_event &&
10155 _gdk_display_has_pointer_grab (display, serial) == NULL)
10158 _gdk_window_find_descendant_at (toplevel_window,
10159 toplevel_x, toplevel_y,
10162 /* Find the event window, that gets the grab */
10163 w = (GdkWindowObject *)pointer_window;
10164 while (w != NULL &&
10165 (parent = get_event_parent (w)) != NULL &&
10166 parent->window_type != GDK_WINDOW_ROOT)
10168 if (w->event_mask & GDK_BUTTON_PRESS_MASK)
10172 pointer_window = (GdkWindow *)w;
10174 _gdk_display_add_pointer_grab (display,
10178 gdk_window_get_events (pointer_window),
10182 _gdk_display_pointer_grab_update (display, serial);
10185 pointer_window = get_pointer_window (display, toplevel_window,
10186 toplevel_x, toplevel_y,
10189 event_win = get_event_window (display,
10194 if (event_win == NULL || display->ignore_core_events)
10197 event = _gdk_make_event (event_win, type, source_event, FALSE);
10201 case GDK_BUTTON_PRESS:
10202 case GDK_BUTTON_RELEASE:
10203 event->button.button = source_event->button.button;
10204 convert_toplevel_coords_to_window (event_win,
10205 toplevel_x, toplevel_y,
10206 &event->button.x, &event->button.y);
10207 event->button.x_root = source_event->button.x_root;
10208 event->button.y_root = source_event->button.y_root;
10209 event->button.state = state;
10210 event->button.device = source_event->button.device;
10212 if (type == GDK_BUTTON_PRESS)
10213 _gdk_event_button_generate (display, event);
10217 event->scroll.direction = source_event->scroll.direction;
10218 convert_toplevel_coords_to_window (event_win,
10219 toplevel_x, toplevel_y,
10220 &event->scroll.x, &event->scroll.y);
10221 event->scroll.x_root = source_event->scroll.x_root;
10222 event->scroll.y_root = source_event->scroll.y_root;
10223 event->scroll.state = state;
10224 event->scroll.device = source_event->scroll.device;
10231 return TRUE; /* Always unlink original, we want to obey the emulated event mask */
10234 #ifdef DEBUG_WINDOW_PRINTING
10236 gdk_window_print (GdkWindowObject *window,
10240 const char *window_types[] = {
10250 g_print ("%*s%p: [%s] %d,%d %dx%d", indent, "", window,
10251 window->user_data ? g_type_name_from_instance (window->user_data) : "no widget",
10252 window->x, window->y,
10253 window->width, window->height
10256 if (gdk_window_has_impl (window))
10258 #ifdef GDK_WINDOWING_X11
10259 g_print (" impl(0x%lx)", gdk_x11_drawable_get_xid (GDK_DRAWABLE (window)));
10263 if (window->window_type != GDK_WINDOW_CHILD)
10264 g_print (" %s", window_types[window->window_type]);
10266 if (window->input_only)
10267 g_print (" input-only");
10269 if (window->shaped)
10270 g_print (" shaped");
10272 if (!gdk_window_is_visible ((GdkWindow *)window))
10273 g_print (" hidden");
10275 g_print (" abs[%d,%d]",
10276 window->abs_x, window->abs_y);
10278 gdk_region_get_clipbox (window->clip_region, &r);
10279 if (gdk_region_empty (window->clip_region))
10280 g_print (" clipbox[empty]");
10282 g_print (" clipbox[%d,%d %dx%d]", r.x, r.y, r.width, r.height);
10289 gdk_window_print_tree (GdkWindow *window,
10291 gboolean include_input_only)
10293 GdkWindowObject *private;
10296 private = (GdkWindowObject *)window;
10298 if (private->input_only && !include_input_only)
10301 gdk_window_print (private, indent);
10303 for (l = private->children; l != NULL; l = l->next)
10304 gdk_window_print_tree (l->data, indent + 4, include_input_only);
10307 #endif /* DEBUG_WINDOW_PRINTING */
10310 is_input_event (GdkDisplay *display,
10313 GdkDevice *core_pointer;
10315 core_pointer = gdk_display_get_core_pointer (display);
10316 if ((event->type == GDK_MOTION_NOTIFY &&
10317 event->motion.device != core_pointer) ||
10318 ((event->type == GDK_BUTTON_PRESS ||
10319 event->type == GDK_BUTTON_RELEASE) &&
10320 event->button.device != core_pointer))
10326 _gdk_windowing_got_event (GdkDisplay *display,
10331 GdkWindow *event_window;
10332 GdkWindowObject *event_private;
10334 gboolean unlink_event;
10335 guint old_state, old_button;
10336 GdkPointerGrabInfo *button_release_grab;
10337 gboolean is_toplevel;
10339 if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
10340 display->last_event_time = gdk_event_get_time (event);
10342 _gdk_display_pointer_grab_update (display,
10345 event_window = event->any.window;
10349 event_private = GDK_WINDOW_OBJECT (event_window);
10351 #ifdef DEBUG_WINDOW_PRINTING
10352 if (event->type == GDK_KEY_PRESS &&
10353 (event->key.keyval == 0xa7 ||
10354 event->key.keyval == 0xbd))
10356 gdk_window_print_tree (event_window, 0,
10357 event->key.keyval == 0xbd);
10361 if (_gdk_native_windows)
10363 if (event->type == GDK_BUTTON_PRESS &&
10364 !event->any.send_event &&
10365 _gdk_display_has_pointer_grab (display, serial) == NULL)
10367 _gdk_display_add_pointer_grab (display,
10371 gdk_window_get_events (event_window),
10373 gdk_event_get_time (event),
10375 _gdk_display_pointer_grab_update (display,
10378 if (event->type == GDK_BUTTON_RELEASE &&
10379 !event->any.send_event)
10381 button_release_grab =
10382 _gdk_display_has_pointer_grab (display, serial);
10383 if (button_release_grab &&
10384 button_release_grab->implicit &&
10385 (event->button.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
10387 button_release_grab->serial_end = serial;
10388 button_release_grab->implicit_ungrab = FALSE;
10389 _gdk_display_pointer_grab_update (display, serial);
10393 if (event->type == GDK_BUTTON_PRESS)
10394 _gdk_event_button_generate (display, event);
10399 if (event->type == GDK_VISIBILITY_NOTIFY)
10401 event_private->native_visibility = event->visibility.state;
10402 gdk_window_update_visibility_recursively (event_private,
10407 if (is_input_event (display, event))
10410 if (!(is_button_type (event->type) ||
10411 is_motion_type (event->type)) ||
10412 event_private->window_type == GDK_WINDOW_ROOT)
10415 is_toplevel = gdk_window_is_toplevel (event_private);
10417 if ((event->type == GDK_ENTER_NOTIFY ||
10418 event->type == GDK_LEAVE_NOTIFY) &&
10419 (event->crossing.mode == GDK_CROSSING_GRAB ||
10420 event->crossing.mode == GDK_CROSSING_UNGRAB) &&
10421 (_gdk_display_has_pointer_grab (display, serial) ||
10422 event->crossing.detail == GDK_NOTIFY_INFERIOR))
10424 /* We synthesize all crossing events due to grabs ourselves,
10425 * so we ignore the native ones caused by our native pointer_grab
10426 * calls. Otherwise we would proxy these crossing event and cause
10427 * multiple copies of crossing events for grabs.
10429 * We do want to handle grabs from other clients though, as for
10430 * instance alt-tab in metacity causes grabs like these and
10431 * we want to handle those. Thus the has_pointer_grab check.
10433 * Implicit grabs on child windows create some grabbing events
10434 * that are sent before the button press. This means we can't
10435 * detect these with the has_pointer_grab check (as the implicit
10436 * grab is only noticed when we get button press event), so we
10437 * detect these events by checking for INFERIOR enter or leave
10438 * events. These should never be a problem to filter out.
10441 /* We ended up in this window after some (perhaps other clients)
10442 grab, so update the toplevel_under_window state */
10444 event->type == GDK_ENTER_NOTIFY &&
10445 event->crossing.mode == GDK_CROSSING_UNGRAB)
10447 if (display->pointer_info.toplevel_under_pointer)
10448 g_object_unref (display->pointer_info.toplevel_under_pointer);
10449 display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
10452 unlink_event = TRUE;
10456 /* Track toplevel_under_pointer */
10459 if (event->type == GDK_ENTER_NOTIFY &&
10460 event->crossing.detail != GDK_NOTIFY_INFERIOR)
10462 if (display->pointer_info.toplevel_under_pointer)
10463 g_object_unref (display->pointer_info.toplevel_under_pointer);
10464 display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
10466 else if (event->type == GDK_LEAVE_NOTIFY &&
10467 event->crossing.detail != GDK_NOTIFY_INFERIOR &&
10468 display->pointer_info.toplevel_under_pointer == event_window)
10470 if (display->pointer_info.toplevel_under_pointer)
10471 g_object_unref (display->pointer_info.toplevel_under_pointer);
10472 display->pointer_info.toplevel_under_pointer = NULL;
10476 /* Store last pointer window and position/state */
10477 old_state = display->pointer_info.state;
10478 old_button = display->pointer_info.button;
10480 gdk_event_get_coords (event, &x, &y);
10481 convert_native_coords_to_toplevel (event_window, x, y, &x, &y);
10482 display->pointer_info.toplevel_x = x;
10483 display->pointer_info.toplevel_y = y;
10484 gdk_event_get_state (event, &display->pointer_info.state);
10485 if (event->type == GDK_BUTTON_PRESS ||
10486 event->type == GDK_BUTTON_RELEASE)
10487 display->pointer_info.button = event->button.button;
10489 if (display->pointer_info.state != old_state ||
10490 display->pointer_info.button != old_button)
10491 _gdk_display_enable_motion_hints (display);
10493 unlink_event = FALSE;
10494 if (is_motion_type (event->type))
10495 unlink_event = proxy_pointer_event (display,
10498 else if (is_button_type (event->type))
10499 unlink_event = proxy_button_event (event,
10502 if (event->type == GDK_BUTTON_RELEASE &&
10503 !event->any.send_event)
10505 button_release_grab =
10506 _gdk_display_has_pointer_grab (display, serial);
10507 if (button_release_grab &&
10508 button_release_grab->implicit &&
10509 (event->button.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
10511 button_release_grab->serial_end = serial;
10512 button_release_grab->implicit_ungrab = FALSE;
10513 _gdk_display_pointer_grab_update (display, serial);
10520 _gdk_event_queue_remove_link (display, event_link);
10521 g_list_free_1 (event_link);
10522 gdk_event_free (event);
10528 get_extension_event_window (GdkDisplay *display,
10529 GdkWindow *pointer_window,
10534 GdkWindow *grab_window;
10535 GdkWindowObject *w;
10536 GdkPointerGrabInfo *grab;
10538 grab = _gdk_display_has_pointer_grab (display, serial);
10540 if (grab != NULL && !grab->owner_events)
10542 evmask = grab->event_mask;
10544 grab_window = grab->window;
10546 if (evmask & type_masks[type])
10547 return grab_window;
10552 w = (GdkWindowObject *)pointer_window;
10555 evmask = w->extension_events;
10557 if (evmask & type_masks[type])
10558 return (GdkWindow *)w;
10560 w = get_event_parent (w);
10563 if (grab != NULL &&
10564 grab->owner_events)
10566 evmask = grab->event_mask;
10568 if (evmask & type_masks[type])
10569 return grab->window;
10579 _gdk_window_get_input_window_for_event (GdkWindow *native_window,
10580 GdkEventType event_type,
10584 GdkDisplay *display;
10585 GdkWindow *toplevel_window;
10586 GdkWindow *pointer_window;
10587 GdkWindow *event_win;
10588 gdouble toplevel_x, toplevel_y;
10593 display = gdk_drawable_get_display (native_window);
10594 toplevel_window = convert_native_coords_to_toplevel (native_window,
10595 toplevel_x, toplevel_y,
10596 &toplevel_x, &toplevel_y);
10597 pointer_window = get_pointer_window (display, toplevel_window,
10598 toplevel_x, toplevel_y, serial);
10599 event_win = get_extension_event_window (display,
10608 #define __GDK_WINDOW_C__
10609 #include "gdkaliasdef.c"