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");
487 * The mouse pointer for a #GdkWindow. See gdk_window_set_cursor() and
488 * gdk_window_get_cursor() for details.
492 g_object_class_install_property (object_class,
494 g_param_spec_boxed ("cursor",
501 * GdkWindow::pick-embedded-child:
502 * @window: the window on which the signal is emitted
503 * @x: x coordinate in the window
504 * @y: y coordinate in the window
506 * The ::pick-embedded-child signal is emitted to find an embedded
507 * child at the given position.
509 * Returns: the #GdkWindow of the embedded child at @x, @y, or %NULL
513 signals[PICK_EMBEDDED_CHILD] =
514 g_signal_new (g_intern_static_string ("pick-embedded-child"),
515 G_OBJECT_CLASS_TYPE (object_class),
518 accumulate_get_window, NULL,
519 _gdk_marshal_OBJECT__DOUBLE_DOUBLE,
526 * GdkWindow::to-embedder:
527 * @window: the offscreen window on which the signal is emitted
528 * @offscreen-x: x coordinate in the offscreen window
529 * @offscreen-y: y coordinate in the offscreen window
530 * @embedder-x: return location for the x coordinate in the embedder window
531 * @embedder-y: return location for the y coordinate in the embedder window
533 * The ::to-embedder signal is emitted to translate coordinates
534 * in an offscreen window to its embedder.
536 * See also #GtkWindow::from-embedder.
540 signals[TO_EMBEDDER] =
541 g_signal_new (g_intern_static_string ("to-embedder"),
542 G_OBJECT_CLASS_TYPE (object_class),
546 _gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
555 * GdkWindow::from-embedder:
556 * @window: the offscreen window on which the signal is emitted
557 * @embedder-x: x coordinate in the embedder window
558 * @embedder-y: y coordinate in the embedder window
559 * @offscreen-x: return location for the x coordinate in the offscreen window
560 * @offscreen-y: return location for the y coordinate in the offscreen window
562 * The ::from-embedder signal is emitted to translate coordinates
563 * in the embedder of an offscreen window to the offscreen window.
565 * See also #GtkWindow::to-embedder.
569 signals[FROM_EMBEDDER] =
570 g_signal_new (g_intern_static_string ("from-embedder"),
571 G_OBJECT_CLASS_TYPE (object_class),
575 _gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
585 gdk_window_finalize (GObject *object)
587 GdkWindow *window = GDK_WINDOW (object);
588 GdkWindowObject *obj = (GdkWindowObject *) object;
590 if (!GDK_WINDOW_DESTROYED (window))
592 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
594 g_warning ("losing last reference to undestroyed window\n");
595 _gdk_window_destroy (window, FALSE);
598 /* We use TRUE here, to keep us from actually calling
599 * XDestroyWindow() on the window
601 _gdk_window_destroy (window, TRUE);
606 g_object_unref (obj->impl);
610 if (obj->impl_window != obj)
612 g_object_unref (obj->impl_window);
613 obj->impl_window = NULL;
617 gdk_region_destroy (obj->shape);
619 if (obj->input_shape)
620 gdk_region_destroy (obj->input_shape);
623 gdk_cursor_unref (obj->cursor);
625 G_OBJECT_CLASS (parent_class)->finalize (object);
629 gdk_window_set_property (GObject *object,
634 GdkWindow *window = (GdkWindow *)object;
639 gdk_window_set_cursor (window, g_value_get_boxed (value));
643 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
649 gdk_window_get_property (GObject *object,
654 GdkWindow *window = (GdkWindow *) object;
659 g_value_set_boxed (value, gdk_window_get_cursor (window));
663 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
669 gdk_window_is_offscreen (GdkWindowObject *window)
671 return window->window_type == GDK_WINDOW_OFFSCREEN;
674 static GdkWindowObject *
675 gdk_window_get_impl_window (GdkWindowObject *window)
677 return window->impl_window;
681 _gdk_window_get_impl_window (GdkWindow *window)
683 return (GdkWindow *)gdk_window_get_impl_window ((GdkWindowObject *)window);
687 gdk_window_has_impl (GdkWindowObject *window)
689 return window->impl_window == window;
693 gdk_window_is_toplevel (GdkWindowObject *window)
696 window->parent == NULL ||
697 window->parent->window_type == GDK_WINDOW_ROOT;
701 _gdk_window_has_impl (GdkWindow *window)
703 return gdk_window_has_impl ((GdkWindowObject *)window);
707 gdk_window_has_no_impl (GdkWindowObject *window)
709 return window->impl_window != window;
713 remove_child_area (GdkWindowObject *private,
714 GdkWindowObject *until,
718 GdkWindowObject *child;
719 GdkRegion *child_region;
724 for (l = private->children; l; l = l->next)
731 /* If region is empty already, no need to do
732 anything potentially costly */
733 if (gdk_region_empty (region))
736 if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
739 /* Ignore offscreen children, as they don't draw in their parent and
740 * don't take part in the clipping */
741 if (gdk_window_is_offscreen (child))
746 r.width = child->width;
747 r.height = child->height;
749 /* Bail early if child totally outside region */
750 if (gdk_region_rect_in (region, &r) == GDK_OVERLAP_RECTANGLE_OUT)
753 child_region = gdk_region_rectangle (&r);
757 /* Adjust shape region to parent window coords */
758 gdk_region_offset (child->shape, child->x, child->y);
759 gdk_region_intersect (child_region, child->shape);
760 gdk_region_offset (child->shape, -child->x, -child->y);
762 else if (private->window_type == GDK_WINDOW_FOREIGN)
764 shape = _gdk_windowing_window_get_shape ((GdkWindow *)child);
767 gdk_region_intersect (child_region, shape);
768 gdk_region_destroy (shape);
774 if (child->input_shape)
775 gdk_region_intersect (child_region, child->input_shape);
776 else if (private->window_type == GDK_WINDOW_FOREIGN)
778 shape = _gdk_windowing_window_get_input_shape ((GdkWindow *)child);
781 gdk_region_intersect (child_region, shape);
782 gdk_region_destroy (shape);
787 gdk_region_subtract (region, child_region);
788 gdk_region_destroy (child_region);
793 static GdkVisibilityState
794 effective_visibility (GdkWindowObject *private)
796 GdkVisibilityState native;
798 if (!gdk_window_is_viewable ((GdkWindow *)private))
799 return GDK_VISIBILITY_NOT_VIEWABLE;
801 native = private->impl_window->native_visibility;
803 if (native == GDK_VISIBILITY_FULLY_OBSCURED ||
804 private->visibility == GDK_VISIBILITY_FULLY_OBSCURED)
805 return GDK_VISIBILITY_FULLY_OBSCURED;
806 else if (native == GDK_VISIBILITY_UNOBSCURED)
807 return private->visibility;
808 else /* native PARTIAL, private partial or unobscured */
809 return GDK_VISIBILITY_PARTIAL;
813 gdk_window_update_visibility (GdkWindowObject *private)
815 GdkVisibilityState new_visibility;
818 new_visibility = effective_visibility (private);
820 if (new_visibility != private->effective_visibility)
822 private->effective_visibility = new_visibility;
824 if (new_visibility != GDK_VISIBILITY_NOT_VIEWABLE &&
825 private->event_mask & GDK_VISIBILITY_NOTIFY)
827 event = _gdk_make_event ((GdkWindow *)private, GDK_VISIBILITY_NOTIFY,
829 event->visibility.state = new_visibility;
835 gdk_window_update_visibility_recursively (GdkWindowObject *private,
836 GdkWindowObject *only_for_impl)
838 GdkWindowObject *child;
841 gdk_window_update_visibility (private);
842 for (l = private->children; l != NULL; l = l->next)
845 if ((only_for_impl == NULL) ||
846 (only_for_impl == child->impl_window))
847 gdk_window_update_visibility_recursively (child, only_for_impl);
852 should_apply_clip_as_shape (GdkWindowObject *private)
855 gdk_window_has_impl (private) &&
856 /* Not for offscreens */
857 private->window_type != GDK_WINDOW_OFFSCREEN &&
858 /* or for toplevels */
859 !gdk_window_is_toplevel (private) &&
860 /* or for foreign windows */
861 private->window_type != GDK_WINDOW_FOREIGN &&
862 /* or for the root window */
863 private->window_type != GDK_WINDOW_ROOT;
867 apply_shape (GdkWindowObject *private,
870 GdkWindowImplIface *impl_iface;
872 /* We trash whether we applied a shape so that
873 we can avoid unsetting it many times, which
874 could happen in e.g. apply_clip_as_shape as
875 windows get resized */
876 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
878 impl_iface->shape_combine_region ((GdkWindow *)private,
880 else if (private->applied_shape)
881 impl_iface->shape_combine_region ((GdkWindow *)private,
884 private->applied_shape = region != NULL;
888 apply_clip_as_shape (GdkWindowObject *private)
893 r.width = private->width;
894 r.height = private->height;
896 /* We only apply the clip region if would differ
897 from the actual clip region implied by the size
898 of the window. This is to avoid unneccessarily
899 adding meaningless shapes to all native subwindows */
900 if (!gdk_region_rect_equal (private->clip_region, &r))
901 apply_shape (private, private->clip_region);
903 apply_shape (private, NULL);
907 recompute_visible_regions_internal (GdkWindowObject *private,
908 gboolean recalculate_clip,
909 gboolean recalculate_siblings,
910 gboolean recalculate_children)
914 GdkWindowObject *child;
915 GdkRegion *new_clip, *old_clip_region_with_children;
916 gboolean clip_region_changed;
917 gboolean abs_pos_changed;
918 int old_abs_x, old_abs_y;
920 old_abs_x = private->abs_x;
921 old_abs_y = private->abs_y;
923 /* Update absolute position */
924 if (gdk_window_has_impl (private))
926 /* Native window starts here */
932 private->abs_x = private->parent->abs_x + private->x;
933 private->abs_y = private->parent->abs_y + private->y;
937 private->abs_x != old_abs_x ||
938 private->abs_y != old_abs_y;
940 /* Update clip region based on:
943 * siblings in parents above window
945 clip_region_changed = FALSE;
946 if (recalculate_clip)
948 if (private->viewable)
950 /* Calculate visible region (sans children) in parent window coords */
953 r.width = private->width;
954 r.height = private->height;
955 new_clip = gdk_region_rectangle (&r);
957 if (!gdk_window_is_toplevel (private))
959 gdk_region_intersect (new_clip, private->parent->clip_region);
961 /* Remove all overlapping children from parent.
962 * Unless we're all native, because then we don't need to take
963 * siblings into account since X does that clipping for us.
964 * This makes things like SWT that modify the raw X stacking
965 * order without GDKs knowledge work.
967 if (!_gdk_native_windows)
968 remove_child_area (private->parent, private, FALSE, new_clip);
971 /* Convert from parent coords to window coords */
972 gdk_region_offset (new_clip, -private->x, -private->y);
975 gdk_region_intersect (new_clip, private->shape);
978 new_clip = gdk_region_new ();
980 if (private->clip_region == NULL ||
981 !gdk_region_equal (private->clip_region, new_clip))
982 clip_region_changed = TRUE;
984 if (private->clip_region)
985 gdk_region_destroy (private->clip_region);
986 private->clip_region = new_clip;
988 old_clip_region_with_children = private->clip_region_with_children;
989 private->clip_region_with_children = gdk_region_copy (private->clip_region);
990 if (private->window_type != GDK_WINDOW_ROOT)
991 remove_child_area (private, NULL, FALSE, private->clip_region_with_children);
993 if (clip_region_changed ||
994 !gdk_region_equal (private->clip_region_with_children, old_clip_region_with_children))
995 private->clip_tag = new_region_tag ();
997 if (old_clip_region_with_children)
998 gdk_region_destroy (old_clip_region_with_children);
1001 if (clip_region_changed)
1003 GdkVisibilityState visibility;
1004 gboolean fully_visible;
1006 if (gdk_region_empty (private->clip_region))
1007 visibility = GDK_VISIBILITY_FULLY_OBSCURED;
1012 fully_visible = gdk_region_equal (private->clip_region,
1019 r.width = private->width;
1020 r.height = private->height;
1021 fully_visible = gdk_region_rect_equal (private->clip_region, &r);
1025 visibility = GDK_VISIBILITY_UNOBSCURED;
1027 visibility = GDK_VISIBILITY_PARTIAL;
1030 if (private->visibility != visibility)
1032 private->visibility = visibility;
1033 gdk_window_update_visibility (private);
1037 /* Update all children, recursively (except for root, where children are not exact). */
1038 if ((abs_pos_changed || clip_region_changed || recalculate_children) &&
1039 private->window_type != GDK_WINDOW_ROOT)
1041 for (l = private->children; l; l = l->next)
1044 /* Only recalculate clip if the the clip region changed, otherwise
1045 * there is no way the child clip region could change (its has not e.g. moved)
1046 * Except if recalculate_children is set to force child updates
1048 recompute_visible_regions_internal (child,
1049 recalculate_clip && (clip_region_changed || recalculate_children),
1054 if (clip_region_changed &&
1055 should_apply_clip_as_shape (private))
1056 apply_clip_as_shape (private);
1058 if (recalculate_siblings &&
1059 !gdk_window_is_toplevel (private))
1061 /* If we moved a child window in parent or changed the stacking order, then we
1062 * need to recompute the visible area of all the other children in the parent
1064 for (l = private->parent->children; l; l = l->next)
1068 if (child != private)
1069 recompute_visible_regions_internal (child, TRUE, FALSE, FALSE);
1072 /* We also need to recompute the _with_children clip for the parent */
1073 recompute_visible_regions_internal (private->parent, TRUE, FALSE, FALSE);
1076 if (private->cairo_surface)
1080 /* It would be nice if we had some cairo support here so we
1081 could set the clip rect on the cairo surface */
1082 width = private->abs_x + private->width;
1083 height = private->abs_y + private->height;
1085 _gdk_windowing_set_cairo_surface_size (private->cairo_surface,
1087 cairo_surface_set_device_offset (private->cairo_surface,
1093 /* Call this when private has changed in one or more of these ways:
1097 * stacking order of window changed
1100 * It will recalculate abs_x/y and the clip regions
1102 * Unless the window didn't change stacking order or size/pos, pass in TRUE
1103 * for recalculate_siblings. (Mostly used internally for the recursion)
1105 * If a child window was removed (and you can't use that child for
1106 * recompute_visible_regions), pass in TRUE for recalculate_children on the parent
1109 recompute_visible_regions (GdkWindowObject *private,
1110 gboolean recalculate_siblings,
1111 gboolean recalculate_children)
1113 recompute_visible_regions_internal (private,
1115 recalculate_siblings,
1116 recalculate_children);
1120 _gdk_window_update_size (GdkWindow *window)
1122 recompute_visible_regions ((GdkWindowObject *)window, TRUE, FALSE);
1125 /* Find the native window that would be just above "child"
1126 * in the native stacking order if "child" was a native window
1127 * (it doesn't have to be native). If there is no such native
1128 * window inside this native parent then NULL is returned.
1129 * If child is NULL, find lowest native window in parent.
1131 static GdkWindowObject *
1132 find_native_sibling_above_helper (GdkWindowObject *parent,
1133 GdkWindowObject *child)
1140 l = g_list_find (parent->children, child);
1141 g_assert (l != NULL); /* Better be a child of its parent... */
1142 l = l->prev; /* Start looking at the one above the child */
1145 l = g_list_last (parent->children);
1147 for (; l != NULL; l = l->prev)
1151 if (gdk_window_has_impl (w))
1154 g_assert (parent != w);
1155 w = find_native_sibling_above_helper (w, NULL);
1164 static GdkWindowObject *
1165 find_native_sibling_above (GdkWindowObject *parent,
1166 GdkWindowObject *child)
1170 w = find_native_sibling_above_helper (parent, child);
1174 if (gdk_window_has_impl (parent))
1177 return find_native_sibling_above (parent->parent, parent);
1181 get_native_event_mask (GdkWindowObject *private)
1183 if (_gdk_native_windows ||
1184 private->window_type == GDK_WINDOW_ROOT ||
1185 private->window_type == GDK_WINDOW_FOREIGN)
1186 return private->event_mask;
1191 /* Do whatever the app asks to, since the app
1192 * may be asking for weird things for native windows,
1193 * but don't use motion hints as that may affect non-native
1194 * child windows that don't want it. Also, we need to
1195 * set all the app-specified masks since they will be picked
1196 * up by any implicit grabs (i.e. if they were not set as
1197 * native we would not get the events we need). */
1198 mask = private->event_mask & ~GDK_POINTER_MOTION_HINT_MASK;
1200 /* We need thse for all native windows so we can
1201 emulate events on children: */
1204 GDK_VISIBILITY_NOTIFY_MASK |
1205 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK;
1207 /* Additionally we select for pointer and button events
1208 * for toplevels as we need to get these to emulate
1209 * them for non-native subwindows. Even though we don't
1210 * select on them for all native windows we will get them
1211 * as the events are propagated out to the first window
1212 * that select for them.
1213 * Not selecting for button press on all windows is an
1214 * important thing, because in X only one client can do
1215 * so, and we don't want to unexpectedly prevent another
1216 * client from doing it.
1218 if (gdk_window_is_toplevel (private))
1220 GDK_POINTER_MOTION_MASK |
1221 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
1229 get_native_grab_event_mask (GdkEventMask grab_mask)
1231 /* Similar to the above but for pointer events only */
1233 GDK_POINTER_MOTION_MASK |
1234 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
1235 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
1238 ~GDK_POINTER_MOTION_HINT_MASK);
1241 /* Puts the native window in the right order wrt the other native windows
1242 * in the hierarchy, given the position it has in the client side data.
1243 * This is useful if some operation changed the stacking order.
1244 * This calls assumes the native window is now topmost in its native parent.
1247 sync_native_window_stack_position (GdkWindow *window)
1249 GdkWindowObject *above;
1250 GdkWindowObject *private;
1251 GdkWindowImplIface *impl_iface;
1252 GList listhead = {0};
1254 private = (GdkWindowObject *) window;
1255 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
1257 above = find_native_sibling_above (private->parent, private);
1260 listhead.data = window;
1261 impl_iface->restack_under ((GdkWindow *)above,
1268 * @parent: (allow-none): a #GdkWindow, or %NULL to create the window as a child of
1269 * the default root window for the default display.
1270 * @attributes: attributes of the new window
1271 * @attributes_mask: mask indicating which fields in @attributes are valid
1273 * Creates a new #GdkWindow using the attributes from
1274 * @attributes. See #GdkWindowAttr and #GdkWindowAttributesType for
1275 * more details. Note: to use this on displays other than the default
1276 * display, @parent must be specified.
1278 * Return value: (transfer none): the new #GdkWindow
1281 gdk_window_new (GdkWindow *parent,
1282 GdkWindowAttr *attributes,
1283 gint attributes_mask)
1286 GdkWindowObject *private;
1291 GdkEventMask event_mask;
1292 GdkWindow *real_parent;
1294 g_return_val_if_fail (attributes != NULL, NULL);
1298 GDK_NOTE (MULTIHEAD,
1299 g_warning ("gdk_window_new(): no parent specified reverting to parent = default root window"));
1301 screen = gdk_screen_get_default ();
1302 parent = gdk_screen_get_root_window (screen);
1305 screen = gdk_drawable_get_screen (parent);
1307 g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
1309 if (GDK_WINDOW_DESTROYED (parent))
1311 g_warning ("gdk_window_new(): parent is destroyed\n");
1315 if (attributes->window_type == GDK_WINDOW_OFFSCREEN &&
1316 _gdk_native_windows)
1318 g_warning ("Offscreen windows not supported with native-windows gdk");
1322 window = g_object_new (GDK_TYPE_WINDOW, NULL);
1323 private = (GdkWindowObject *) window;
1325 /* Windows with a foreign parent are treated as if they are children
1326 * of the root window, except for actual creation.
1328 real_parent = parent;
1329 if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
1330 parent = gdk_screen_get_root_window (screen);
1332 private->parent = (GdkWindowObject *)parent;
1334 private->accept_focus = TRUE;
1335 private->focus_on_map = TRUE;
1337 if (attributes_mask & GDK_WA_X)
1342 if (attributes_mask & GDK_WA_Y)
1349 private->width = (attributes->width > 1) ? (attributes->width) : (1);
1350 private->height = (attributes->height > 1) ? (attributes->height) : (1);
1352 #ifdef GDK_WINDOWING_X11
1353 /* Work around a bug where Xorg refuses to map toplevel InputOnly windows
1354 * from an untrusted client: http://bugs.freedesktop.org/show_bug.cgi?id=6988
1356 if (attributes->wclass == GDK_INPUT_ONLY &&
1357 private->parent->window_type == GDK_WINDOW_ROOT &&
1358 !G_LIKELY (GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (parent))->trusted_client))
1360 g_warning ("Coercing GDK_INPUT_ONLY toplevel window to GDK_INPUT_OUTPUT to work around bug in Xorg server");
1361 attributes->wclass = GDK_INPUT_OUTPUT;
1365 if (attributes->wclass == GDK_INPUT_ONLY)
1367 /* Backwards compatiblity - we've always ignored
1368 * attributes->window_type for input-only windows
1371 if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
1372 private->window_type = GDK_WINDOW_TEMP;
1374 private->window_type = GDK_WINDOW_CHILD;
1377 private->window_type = attributes->window_type;
1380 switch (private->window_type)
1382 case GDK_WINDOW_TOPLEVEL:
1383 case GDK_WINDOW_DIALOG:
1384 case GDK_WINDOW_TEMP:
1385 case GDK_WINDOW_OFFSCREEN:
1386 if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
1387 g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
1388 "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
1389 case GDK_WINDOW_CHILD:
1393 g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
1397 if (attributes_mask & GDK_WA_VISUAL)
1398 visual = attributes->visual;
1400 visual = gdk_screen_get_system_visual (screen);
1402 private->event_mask = attributes->event_mask;
1404 if (attributes->wclass == GDK_INPUT_OUTPUT)
1406 private->input_only = FALSE;
1407 private->depth = visual->depth;
1409 private->bg_color.pixel = 0; /* TODO: BlackPixel (xdisplay, screen_x11->screen_num); */
1410 private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
1412 private->bg_pixmap = NULL;
1417 private->input_only = TRUE;
1420 if (private->parent)
1421 private->parent->children = g_list_prepend (private->parent->children, window);
1423 native = _gdk_native_windows; /* Default */
1424 if (private->parent->window_type == GDK_WINDOW_ROOT)
1425 native = TRUE; /* Always use native windows for toplevels */
1426 else if (!private->input_only &&
1427 ((attributes_mask & GDK_WA_COLORMAP &&
1428 attributes->colormap != gdk_drawable_get_colormap ((GdkDrawable *)private->parent)) ||
1429 (attributes_mask & GDK_WA_VISUAL &&
1430 attributes->visual != gdk_drawable_get_visual ((GdkDrawable *)private->parent))))
1431 native = TRUE; /* InputOutput window with different colormap or visual than parent, needs native window */
1433 if (private->window_type == GDK_WINDOW_OFFSCREEN)
1435 _gdk_offscreen_window_new (window, screen, visual, attributes, attributes_mask);
1436 private->impl_window = private;
1440 event_mask = get_native_event_mask (private);
1442 /* Create the impl */
1443 _gdk_window_impl_new (window, real_parent, screen, visual, event_mask, attributes, attributes_mask);
1444 private->impl_window = private;
1446 /* This will put the native window topmost in the native parent, which may
1447 * be wrong wrt other native windows in the non-native hierarchy, so restack */
1448 if (!_gdk_window_has_impl (real_parent))
1449 sync_native_window_stack_position (window);
1453 private->impl_window = g_object_ref (private->parent->impl_window);
1454 private->impl = g_object_ref (private->impl_window->impl);
1457 recompute_visible_regions (private, TRUE, FALSE);
1459 if (private->parent->window_type != GDK_WINDOW_ROOT)
1461 /* Inherit redirection from parent */
1462 private->redirect = private->parent->redirect;
1465 gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
1466 (attributes->cursor) :
1473 is_parent_of (GdkWindow *parent,
1484 w = gdk_window_get_parent (w);
1491 change_impl (GdkWindowObject *private,
1492 GdkWindowObject *impl_window,
1496 GdkWindowObject *child;
1497 GdkDrawable *old_impl;
1498 GdkWindowObject *old_impl_window;
1500 old_impl = private->impl;
1501 old_impl_window = private->impl_window;
1502 if (private != impl_window)
1503 private->impl_window = g_object_ref (impl_window);
1505 private->impl_window = private;
1506 private->impl = g_object_ref (new);
1507 if (old_impl_window != private)
1508 g_object_unref (old_impl_window);
1509 g_object_unref (old_impl);
1511 for (l = private->children; l != NULL; l = l->next)
1515 if (child->impl == old_impl)
1516 change_impl (child, impl_window, new);
1521 reparent_to_impl (GdkWindowObject *private)
1524 GdkWindowObject *child;
1526 GdkWindowImplIface *impl_iface;
1528 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
1530 /* Enumerate in reverse order so we get the right order for the native
1531 windows (first in childrens list is topmost, and reparent places on top) */
1532 for (l = g_list_last (private->children); l != NULL; l = l->prev)
1536 if (child->impl == private->impl)
1537 reparent_to_impl (child);
1540 show = impl_iface->reparent ((GdkWindow *)child,
1541 (GdkWindow *)private,
1542 child->x, child->y);
1544 gdk_window_show_unraised ((GdkWindow *)child);
1551 * gdk_window_reparent:
1552 * @window: a #GdkWindow
1553 * @new_parent: new parent to move @window into
1554 * @x: X location inside the new parent
1555 * @y: Y location inside the new parent
1557 * Reparents @window into the given @new_parent. The window being
1558 * reparented will be unmapped as a side effect.
1562 gdk_window_reparent (GdkWindow *window,
1563 GdkWindow *new_parent,
1567 GdkWindowObject *private;
1568 GdkWindowObject *new_parent_private;
1569 GdkWindowObject *old_parent;
1571 gboolean show, was_mapped, applied_clip_as_shape;
1572 gboolean do_reparent_to_impl;
1573 GdkEventMask old_native_event_mask;
1574 GdkWindowImplIface *impl_iface;
1576 g_return_if_fail (GDK_IS_WINDOW (window));
1577 g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
1578 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
1580 if (GDK_WINDOW_DESTROYED (window) ||
1581 (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
1584 screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
1586 new_parent = gdk_screen_get_root_window (screen);
1588 private = (GdkWindowObject *) window;
1589 new_parent_private = (GdkWindowObject *)new_parent;
1591 /* No input-output children of input-only windows */
1592 if (new_parent_private->input_only && !private->input_only)
1595 /* Don't create loops in hierarchy */
1596 if (is_parent_of (window, new_parent))
1599 if (private->cairo_surface)
1601 /* This might be wrong in the new parent, e.g. for non-native surfaces.
1602 To make sure we're ok, just wipe it. */
1603 cairo_surface_finish (private->cairo_surface);
1604 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
1608 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
1609 old_parent = private->parent;
1611 /* Break up redirection if inherited */
1612 if (private->redirect && private->redirect->redirected != private)
1614 remove_redirect_from_children (private, private->redirect);
1615 private->redirect = NULL;
1618 was_mapped = GDK_WINDOW_IS_MAPPED (window);
1621 /* Reparenting to toplevel. Ensure we have a native window so this can work */
1622 if (new_parent_private->window_type == GDK_WINDOW_ROOT ||
1623 new_parent_private->window_type == GDK_WINDOW_FOREIGN)
1624 gdk_window_ensure_native (window);
1626 applied_clip_as_shape = should_apply_clip_as_shape (private);
1628 old_native_event_mask = 0;
1629 do_reparent_to_impl = FALSE;
1630 if (gdk_window_has_impl (private))
1632 old_native_event_mask = get_native_event_mask (private);
1634 show = impl_iface->reparent (window, new_parent, x, y);
1638 /* This shouldn't happen, as we created a native in this case, check anyway to see if that ever fails */
1639 g_assert (new_parent_private->window_type != GDK_WINDOW_ROOT &&
1640 new_parent_private->window_type != GDK_WINDOW_FOREIGN);
1643 gdk_window_hide (window);
1645 do_reparent_to_impl = TRUE;
1646 change_impl (private,
1647 new_parent_private->impl_window,
1648 new_parent_private->impl);
1651 /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
1654 if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1656 new_parent = gdk_screen_get_root_window (screen);
1657 new_parent_private = (GdkWindowObject *)new_parent;
1661 old_parent->children = g_list_remove (old_parent->children, window);
1663 private->parent = new_parent_private;
1667 new_parent_private->children = g_list_prepend (new_parent_private->children, window);
1669 /* Switch the window type as appropriate */
1671 switch (GDK_WINDOW_TYPE (new_parent))
1673 case GDK_WINDOW_ROOT:
1674 case GDK_WINDOW_FOREIGN:
1675 if (private->toplevel_window_type != -1)
1676 GDK_WINDOW_TYPE (window) = private->toplevel_window_type;
1677 else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1678 GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
1680 case GDK_WINDOW_OFFSCREEN:
1681 case GDK_WINDOW_TOPLEVEL:
1682 case GDK_WINDOW_CHILD:
1683 case GDK_WINDOW_DIALOG:
1684 case GDK_WINDOW_TEMP:
1685 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
1686 GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
1688 /* Save the original window type so we can restore it if the
1689 * window is reparented back to be a toplevel
1691 private->toplevel_window_type = GDK_WINDOW_TYPE (window);
1692 GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
1696 /* We might have changed window type for a native windows, so we
1697 need to change the event mask too. */
1698 if (gdk_window_has_impl (private))
1700 GdkEventMask native_event_mask = get_native_event_mask (private);
1702 if (native_event_mask != old_native_event_mask)
1703 impl_iface->set_events (window, native_event_mask);
1706 /* Inherit parent redirect if we don't have our own */
1707 if (private->parent && private->redirect == NULL)
1709 private->redirect = private->parent->redirect;
1710 apply_redirect_to_children (private, private->redirect);
1713 _gdk_window_update_viewable (window);
1715 recompute_visible_regions (private, TRUE, FALSE);
1716 if (old_parent && GDK_WINDOW_TYPE (old_parent) != GDK_WINDOW_ROOT)
1717 recompute_visible_regions (old_parent, FALSE, TRUE);
1719 /* We used to apply the clip as the shape, but no more.
1720 Reset this to the real shape */
1721 if (gdk_window_has_impl (private) &&
1722 applied_clip_as_shape &&
1723 !should_apply_clip_as_shape (private))
1724 apply_shape (private, private->shape);
1726 if (do_reparent_to_impl)
1727 reparent_to_impl (private);
1730 /* The reparent will have put the native window topmost in the native parent,
1731 * which may be wrong wrt other native windows in the non-native hierarchy,
1733 if (!gdk_window_has_impl (new_parent_private))
1734 sync_native_window_stack_position (window);
1738 gdk_window_show_unraised (window);
1740 _gdk_synthesize_crossing_events_for_geometry_change (window);
1744 temporary_disable_extension_events (GdkWindowObject *window)
1746 GdkWindowObject *child;
1750 if (window->extension_events != 0)
1752 g_object_set_data (G_OBJECT (window),
1753 "gdk-window-extension-events",
1754 GINT_TO_POINTER (window->extension_events));
1755 gdk_input_set_extension_events ((GdkWindow *)window, 0,
1756 GDK_EXTENSION_EVENTS_NONE);
1761 for (l = window->children; l != NULL; l = l->next)
1765 if (window->impl_window == child->impl_window)
1766 res |= temporary_disable_extension_events (child);
1773 reenable_extension_events (GdkWindowObject *window)
1775 GdkWindowObject *child;
1779 mask = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (window),
1780 "gdk-window-extension-events"));
1784 /* We don't have the mode here, so we pass in cursor.
1785 This works with the current code since mode is not
1786 stored except as part of the mask, and cursor doesn't
1788 gdk_input_set_extension_events ((GdkWindow *)window, mask,
1789 GDK_EXTENSION_EVENTS_CURSOR);
1790 g_object_set_data (G_OBJECT (window),
1791 "gdk-window-extension-events",
1795 for (l = window->children; l != NULL; l = l->next)
1799 if (window->impl_window == child->impl_window)
1800 reenable_extension_events (window);
1805 * gdk_window_ensure_native:
1806 * @window: a #GdkWindow
1808 * Tries to ensure that there is a window-system native window for this
1809 * GdkWindow. This may fail in some situations, returning %FALSE.
1811 * Offscreen window and children of them can never have native windows.
1813 * Some backends may not support native child windows.
1815 * Returns: %TRUE if the window has a native window, %FALSE otherwise
1820 gdk_window_ensure_native (GdkWindow *window)
1822 GdkWindowObject *private;
1823 GdkWindowObject *impl_window;
1824 GdkDrawable *new_impl, *old_impl;
1827 GdkWindowAttr attributes;
1828 GdkWindowObject *above;
1830 GdkWindowImplIface *impl_iface;
1831 gboolean disabled_extension_events;
1833 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
1835 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT ||
1836 GDK_WINDOW_DESTROYED (window))
1839 private = (GdkWindowObject *) window;
1841 impl_window = gdk_window_get_impl_window (private);
1843 if (impl_window->window_type == GDK_WINDOW_OFFSCREEN)
1844 return FALSE; /* native in offscreens not supported */
1846 if (impl_window == private)
1847 /* Already has an impl, and its not offscreen . */
1850 /* Need to create a native window */
1852 /* First we disable any extension events on the window or its
1853 descendants to handle the native input window moving */
1854 disabled_extension_events = FALSE;
1855 if (impl_window->input_window)
1856 disabled_extension_events = temporary_disable_extension_events (private);
1858 screen = gdk_drawable_get_screen (window);
1859 visual = gdk_drawable_get_visual (window);
1861 attributes.colormap = gdk_drawable_get_colormap (window);
1863 old_impl = private->impl;
1864 _gdk_window_impl_new (window, (GdkWindow *)private->parent,
1866 get_native_event_mask (private),
1867 &attributes, GDK_WA_COLORMAP);
1868 new_impl = private->impl;
1870 private->impl = old_impl;
1871 change_impl (private, private, new_impl);
1873 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
1875 /* Native window creation will put the native window topmost in the
1876 * native parent, which may be wrong wrt the position of the previous
1877 * non-native window wrt to the other non-native children, so correct this.
1879 above = find_native_sibling_above (private->parent, private);
1882 listhead.data = window;
1883 listhead.prev = NULL;
1884 listhead.next = NULL;
1885 impl_iface->restack_under ((GdkWindow *)above, &listhead);
1888 recompute_visible_regions (private, FALSE, FALSE);
1890 /* The shape may not have been set, as the clip region doesn't actually
1891 change, so do it here manually */
1892 if (should_apply_clip_as_shape (private))
1893 apply_clip_as_shape (private);
1895 reparent_to_impl (private);
1897 if (!private->input_only)
1899 impl_iface->set_background (window, &private->bg_color);
1900 if (private->bg_pixmap != NULL)
1901 impl_iface->set_back_pixmap (window, private->bg_pixmap);
1904 impl_iface->input_shape_combine_region (window,
1905 private->input_shape,
1908 if (gdk_window_is_viewable (window))
1909 impl_iface->show (window, FALSE);
1911 if (disabled_extension_events)
1912 reenable_extension_events (private);
1918 window_remove_filters (GdkWindow *window)
1920 GdkWindowObject *obj = (GdkWindowObject*) window;
1926 for (tmp_list = obj->filters; tmp_list; tmp_list = tmp_list->next)
1927 g_free (tmp_list->data);
1929 g_list_free (obj->filters);
1930 obj->filters = NULL;
1935 * _gdk_window_destroy_hierarchy:
1936 * @window: a #GdkWindow
1937 * @recursing: If TRUE, then this is being called because a parent
1939 * @recursing_native: If TRUE, then this is being called because a native parent
1940 * was destroyed. This generally means that the call to the
1941 * windowing system to destroy the window can be omitted, since
1942 * it will be destroyed as a result of the parent being destroyed.
1943 * Unless @foreign_destroy.
1944 * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
1945 * external agency. The window has already been destroyed and no
1946 * windowing system calls should be made. (This may never happen
1947 * for some windowing systems.)
1949 * Internal function to destroy a window. Like gdk_window_destroy(),
1950 * but does not drop the reference count created by gdk_window_new().
1953 _gdk_window_destroy_hierarchy (GdkWindow *window,
1955 gboolean recursing_native,
1956 gboolean foreign_destroy)
1958 GdkWindowObject *private;
1959 GdkWindowObject *temp_private;
1960 GdkWindowImplIface *impl_iface;
1961 GdkWindow *temp_window;
1963 GdkDisplay *display;
1967 g_return_if_fail (GDK_IS_WINDOW (window));
1969 private = (GdkWindowObject*) window;
1971 if (GDK_WINDOW_DESTROYED (window))
1974 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
1975 screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
1976 temp_window = g_object_get_qdata (G_OBJECT (screen), quark_pointer_window);
1977 if (temp_window == window)
1978 g_object_set_qdata (G_OBJECT (screen), quark_pointer_window, NULL);
1981 switch (private->window_type)
1983 case GDK_WINDOW_ROOT:
1984 if (!screen->closed)
1986 g_error ("attempted to destroy root window");
1989 /* else fall thru */
1990 case GDK_WINDOW_TOPLEVEL:
1991 case GDK_WINDOW_CHILD:
1992 case GDK_WINDOW_DIALOG:
1993 case GDK_WINDOW_TEMP:
1994 case GDK_WINDOW_FOREIGN:
1995 case GDK_WINDOW_OFFSCREEN:
1996 if (private->window_type == GDK_WINDOW_FOREIGN && !foreign_destroy)
1998 /* Logically, it probably makes more sense to send
1999 * a "destroy yourself" message to the foreign window
2000 * whether or not it's in our hierarchy; but for historical
2001 * reasons, we only send "destroy yourself" messages to
2002 * foreign windows in our hierarchy.
2004 if (private->parent)
2005 _gdk_windowing_window_destroy_foreign (window);
2007 /* Also for historical reasons, we remove any filters
2008 * on a foreign window when it or a parent is destroyed;
2009 * this likely causes problems if two separate portions
2010 * of code are maintaining filter lists on a foreign window.
2012 window_remove_filters (window);
2016 if (private->parent)
2018 GdkWindowObject *parent_private = (GdkWindowObject *)private->parent;
2020 if (parent_private->children)
2021 parent_private->children = g_list_remove (parent_private->children, window);
2024 GDK_WINDOW_IS_MAPPED (window))
2026 recompute_visible_regions (private, TRUE, FALSE);
2027 gdk_window_invalidate_in_parent (private);
2031 gdk_window_free_paint_stack (window);
2033 if (private->bg_pixmap &&
2034 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
2035 private->bg_pixmap != GDK_NO_BG)
2037 g_object_unref (private->bg_pixmap);
2038 private->bg_pixmap = NULL;
2041 if (private->window_type == GDK_WINDOW_FOREIGN)
2042 g_assert (private->children == NULL);
2045 children = tmp = private->children;
2046 private->children = NULL;
2050 temp_window = tmp->data;
2053 temp_private = (GdkWindowObject*) temp_window;
2055 _gdk_window_destroy_hierarchy (temp_window,
2057 recursing_native || gdk_window_has_impl (private),
2061 g_list_free (children);
2064 _gdk_window_clear_update_area (window);
2066 if (private->cairo_surface)
2068 cairo_surface_finish (private->cairo_surface);
2069 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
2074 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
2076 if (private->extension_events)
2077 impl_iface->input_window_destroy (window);
2079 if (gdk_window_has_impl (private))
2080 impl_iface->destroy (window, recursing_native,
2084 /* hide to make sure we repaint and break grabs */
2085 gdk_window_hide (window);
2088 private->state |= GDK_WINDOW_STATE_WITHDRAWN;
2089 private->parent = NULL;
2090 private->destroyed = TRUE;
2092 window_remove_filters (window);
2094 gdk_drawable_set_colormap (GDK_DRAWABLE (window), NULL);
2096 /* If we own the redirect, free it */
2097 if (private->redirect && private->redirect->redirected == private)
2098 gdk_window_redirect_free (private->redirect);
2100 private->redirect = NULL;
2102 if (display->pointer_info.toplevel_under_pointer == window)
2104 g_object_unref (display->pointer_info.toplevel_under_pointer);
2105 display->pointer_info.toplevel_under_pointer = NULL;
2108 if (private->clip_region)
2110 gdk_region_destroy (private->clip_region);
2111 private->clip_region = NULL;
2114 if (private->clip_region_with_children)
2116 gdk_region_destroy (private->clip_region_with_children);
2117 private->clip_region_with_children = NULL;
2120 if (private->outstanding_moves)
2122 g_list_foreach (private->outstanding_moves, (GFunc)gdk_window_region_move_free, NULL);
2123 g_list_free (private->outstanding_moves);
2124 private->outstanding_moves = NULL;
2132 * _gdk_window_destroy:
2133 * @window: a #GdkWindow
2134 * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
2135 * external agency. The window has already been destroyed and no
2136 * windowing system calls should be made. (This may never happen
2137 * for some windowing systems.)
2139 * Internal function to destroy a window. Like gdk_window_destroy(),
2140 * but does not drop the reference count created by gdk_window_new().
2143 _gdk_window_destroy (GdkWindow *window,
2144 gboolean foreign_destroy)
2146 _gdk_window_destroy_hierarchy (window, FALSE, FALSE, foreign_destroy);
2150 * gdk_window_destroy:
2151 * @window: a #GdkWindow
2153 * Destroys the window system resources associated with @window and decrements @window's
2154 * reference count. The window system resources for all children of @window are also
2155 * destroyed, but the children's reference counts are not decremented.
2157 * Note that a window will not be destroyed automatically when its reference count
2158 * reaches zero. You must call this function yourself before that happens.
2162 gdk_window_destroy (GdkWindow *window)
2164 _gdk_window_destroy_hierarchy (window, FALSE, FALSE, FALSE);
2165 g_object_unref (window);
2169 * gdk_window_set_user_data:
2170 * @window: a #GdkWindow
2171 * @user_data: user data
2173 * For most purposes this function is deprecated in favor of
2174 * g_object_set_data(). However, for historical reasons GTK+ stores
2175 * the #GtkWidget that owns a #GdkWindow as user data on the
2176 * #GdkWindow. So, custom widget implementations should use
2177 * this function for that. If GTK+ receives an event for a #GdkWindow,
2178 * and the user data for the window is non-%NULL, GTK+ will assume the
2179 * user data is a #GtkWidget, and forward the event to that widget.
2183 gdk_window_set_user_data (GdkWindow *window,
2186 g_return_if_fail (GDK_IS_WINDOW (window));
2188 ((GdkWindowObject*)window)->user_data = user_data;
2192 * gdk_window_get_user_data:
2193 * @window: a #GdkWindow
2194 * @data: return location for user data
2196 * Retrieves the user data for @window, which is normally the widget
2197 * that @window belongs to. See gdk_window_set_user_data().
2201 gdk_window_get_user_data (GdkWindow *window,
2204 g_return_if_fail (GDK_IS_WINDOW (window));
2206 *data = ((GdkWindowObject*)window)->user_data;
2210 * gdk_window_get_window_type:
2211 * @window: a #GdkWindow
2213 * Gets the type of the window. See #GdkWindowType.
2215 * Return value: type of window
2218 gdk_window_get_window_type (GdkWindow *window)
2220 g_return_val_if_fail (GDK_IS_WINDOW (window), (GdkWindowType) -1);
2222 return GDK_WINDOW_TYPE (window);
2226 * gdk_window_is_destroyed:
2227 * @window: a #GdkWindow
2229 * Check to see if a window is destroyed..
2231 * Return value: %TRUE if the window is destroyed
2236 gdk_window_is_destroyed (GdkWindow *window)
2238 return GDK_WINDOW_DESTROYED (window);
2242 * gdk_window_get_position:
2243 * @window: a #GdkWindow
2244 * @x: X coordinate of window
2245 * @y: Y coordinate of window
2247 * Obtains the position of the window as reported in the
2248 * most-recently-processed #GdkEventConfigure. Contrast with
2249 * gdk_window_get_geometry() which queries the X server for the
2250 * current window position, regardless of which events have been
2251 * received or processed.
2253 * The position coordinates are relative to the window's parent window.
2257 gdk_window_get_position (GdkWindow *window,
2261 GdkWindowObject *obj;
2263 g_return_if_fail (GDK_IS_WINDOW (window));
2265 obj = (GdkWindowObject*) window;
2274 * gdk_window_get_parent:
2275 * @window: a #GdkWindow
2277 * Obtains the parent of @window, as known to GDK. Does not query the
2278 * X server; thus this returns the parent as passed to gdk_window_new(),
2279 * not the actual parent. This should never matter unless you're using
2280 * Xlib calls mixed with GDK calls on the X11 platform. It may also
2281 * matter for toplevel windows, because the window manager may choose
2284 * Return value: parent of @window
2287 gdk_window_get_parent (GdkWindow *window)
2289 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2291 return (GdkWindow*) ((GdkWindowObject*) window)->parent;
2295 * gdk_window_get_toplevel:
2296 * @window: a #GdkWindow
2298 * Gets the toplevel window that's an ancestor of @window.
2300 * Any window type but %GDK_WINDOW_CHILD is considered a
2301 * toplevel window, as is a %GDK_WINDOW_CHILD window that
2302 * has a root window as parent.
2304 * Return value: the toplevel window containing @window
2307 gdk_window_get_toplevel (GdkWindow *window)
2309 GdkWindowObject *obj;
2311 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2313 obj = (GdkWindowObject *)window;
2315 while (obj->window_type == GDK_WINDOW_CHILD)
2317 if (gdk_window_is_toplevel (obj))
2322 return GDK_WINDOW (obj);
2326 * gdk_window_get_children:
2327 * @window: a #GdkWindow
2329 * Gets the list of children of @window known to GDK.
2330 * This function only returns children created via GDK,
2331 * so for example it's useless when used with the root window;
2332 * it only returns windows an application created itself.
2334 * The returned list must be freed, but the elements in the
2337 * Return value: list of child windows inside @window
2340 gdk_window_get_children (GdkWindow *window)
2342 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2344 if (GDK_WINDOW_DESTROYED (window))
2347 return g_list_copy (GDK_WINDOW_OBJECT (window)->children);
2351 * gdk_window_peek_children:
2352 * @window: a #GdkWindow
2354 * Like gdk_window_get_children(), but does not copy the list of
2355 * children, so the list does not need to be freed.
2357 * Return value: a reference to the list of child windows in @window
2360 gdk_window_peek_children (GdkWindow *window)
2362 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2364 if (GDK_WINDOW_DESTROYED (window))
2367 return GDK_WINDOW_OBJECT (window)->children;
2371 * gdk_window_add_filter:
2372 * @window: a #GdkWindow
2373 * @function: filter callback
2374 * @data: data to pass to filter callback
2376 * Adds an event filter to @window, allowing you to intercept events
2377 * before they reach GDK. This is a low-level operation and makes it
2378 * easy to break GDK and/or GTK+, so you have to know what you're
2379 * doing. Pass %NULL for @window to get all events for all windows,
2380 * instead of events for a specific window.
2382 * See gdk_display_add_client_message_filter() if you are interested
2383 * in X ClientMessage events.
2386 gdk_window_add_filter (GdkWindow *window,
2387 GdkFilterFunc function,
2390 GdkWindowObject *private;
2392 GdkEventFilter *filter;
2394 g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
2396 private = (GdkWindowObject*) window;
2397 if (private && GDK_WINDOW_DESTROYED (window))
2400 /* Filters are for the native events on the native window, so
2401 ensure there is a native window. */
2403 gdk_window_ensure_native (window);
2406 tmp_list = private->filters;
2408 tmp_list = _gdk_default_filters;
2412 filter = (GdkEventFilter *)tmp_list->data;
2413 if ((filter->function == function) && (filter->data == data))
2415 tmp_list = tmp_list->next;
2418 filter = g_new (GdkEventFilter, 1);
2419 filter->function = function;
2420 filter->data = data;
2423 private->filters = g_list_append (private->filters, filter);
2425 _gdk_default_filters = g_list_append (_gdk_default_filters, filter);
2429 * gdk_window_remove_filter:
2430 * @window: a #GdkWindow
2431 * @function: previously-added filter function
2432 * @data: user data for previously-added filter function
2434 * Remove a filter previously added with gdk_window_add_filter().
2438 gdk_window_remove_filter (GdkWindow *window,
2439 GdkFilterFunc function,
2442 GdkWindowObject *private;
2443 GList *tmp_list, *node;
2444 GdkEventFilter *filter;
2446 g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
2448 private = (GdkWindowObject*) window;
2451 tmp_list = private->filters;
2453 tmp_list = _gdk_default_filters;
2457 filter = (GdkEventFilter *)tmp_list->data;
2459 tmp_list = tmp_list->next;
2461 if ((filter->function == function) && (filter->data == data))
2464 private->filters = g_list_remove_link (private->filters, node);
2466 _gdk_default_filters = g_list_remove_link (_gdk_default_filters, node);
2467 g_list_free_1 (node);
2476 * gdk_screen_get_toplevel_windows:
2477 * @screen: The #GdkScreen where the toplevels are located.
2479 * Obtains a list of all toplevel windows known to GDK on the screen @screen.
2480 * A toplevel window is a child of the root window (see
2481 * gdk_get_default_root_window()).
2483 * The returned list should be freed with g_list_free(), but
2484 * its elements need not be freed.
2486 * Return value: list of toplevel windows, free with g_list_free()
2491 gdk_screen_get_toplevel_windows (GdkScreen *screen)
2493 GdkWindow * root_window;
2494 GList *new_list = NULL;
2497 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
2499 root_window = gdk_screen_get_root_window (screen);
2501 tmp_list = ((GdkWindowObject *)root_window)->children;
2504 GdkWindowObject *w = tmp_list->data;
2506 if (w->window_type != GDK_WINDOW_FOREIGN)
2507 new_list = g_list_prepend (new_list, w);
2508 tmp_list = tmp_list->next;
2515 * gdk_window_get_toplevels:
2517 * Obtains a list of all toplevel windows known to GDK on the default
2518 * screen (see gdk_screen_get_toplevel_windows()).
2519 * A toplevel window is a child of the root window (see
2520 * gdk_get_default_root_window()).
2522 * The returned list should be freed with g_list_free(), but
2523 * its elements need not be freed.
2525 * Return value: list of toplevel windows, free with g_list_free()
2527 * Deprecated: 2.16: Use gdk_screen_get_toplevel_windows() instead.
2530 gdk_window_get_toplevels (void)
2532 return gdk_screen_get_toplevel_windows (gdk_screen_get_default ());
2536 * gdk_window_is_visible:
2537 * @window: a #GdkWindow
2539 * Checks whether the window has been mapped (with gdk_window_show() or
2540 * gdk_window_show_unraised()).
2542 * Return value: %TRUE if the window is mapped
2545 gdk_window_is_visible (GdkWindow *window)
2547 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2549 return GDK_WINDOW_IS_MAPPED (window);
2553 * gdk_window_is_viewable:
2554 * @window: a #GdkWindow
2556 * Check if the window and all ancestors of the window are
2557 * mapped. (This is not necessarily "viewable" in the X sense, since
2558 * we only check as far as we have GDK window parents, not to the root
2561 * Return value: %TRUE if the window is viewable
2564 gdk_window_is_viewable (GdkWindow *window)
2566 GdkWindowObject *private = (GdkWindowObject *)window;
2568 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2570 if (private->destroyed)
2573 return private->viewable;
2577 * gdk_window_get_state:
2578 * @window: a #GdkWindow
2580 * Gets the bitwise OR of the currently active window state flags,
2581 * from the #GdkWindowState enumeration.
2583 * Return value: window state bitfield
2586 gdk_window_get_state (GdkWindow *window)
2588 GdkWindowObject *private = (GdkWindowObject *)window;
2590 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2592 return private->state;
2596 /* This creates an empty "implicit" paint region for the impl window.
2597 * By itself this does nothing, but real paints to this window
2598 * or children of it can use this pixmap as backing to avoid allocating
2599 * multiple pixmaps for subwindow rendering. When doing so they
2600 * add to the region of the implicit paint region, which will be
2601 * pushed to the window when the implicit paint region is ended.
2602 * Such paints should not copy anything to the window on paint end, but
2603 * should rely on the implicit paint end.
2604 * The implicit paint will be automatically ended if someone draws
2605 * directly to the window or a child window.
2608 gdk_window_begin_implicit_paint (GdkWindow *window, GdkRectangle *rect)
2610 GdkWindowObject *private = (GdkWindowObject *)window;
2611 GdkWindowPaint *paint;
2613 g_assert (gdk_window_has_impl (private));
2615 if (_gdk_native_windows)
2616 return FALSE; /* No need for implicit paints since we can't merge draws anyway */
2618 if (GDK_IS_PAINTABLE (private->impl))
2619 return FALSE; /* Implementation does double buffering */
2621 if (private->paint_stack != NULL ||
2622 private->implicit_paint != NULL)
2623 return FALSE; /* Don't stack implicit paints */
2625 /* Never do implicit paints for foreign windows, they don't need
2626 * double buffer combination since they have no client side children,
2627 * and creating pixmaps for them is risky since they could disappear
2630 if (private->window_type == GDK_WINDOW_FOREIGN)
2633 paint = g_new (GdkWindowPaint, 1);
2634 paint->region = gdk_region_new (); /* Empty */
2635 paint->x_offset = rect->x;
2636 paint->y_offset = rect->y;
2637 paint->uses_implicit = FALSE;
2638 paint->flushed = FALSE;
2639 paint->surface = NULL;
2641 gdk_pixmap_new (window,
2642 MAX (rect->width, 1), MAX (rect->height, 1), -1);
2644 private->implicit_paint = paint;
2649 /* Ensure that all content related to this (sub)window is pushed to the
2650 native region. If there is an active paint then that area is not
2651 pushed, in order to not show partially finished double buffers. */
2653 gdk_window_flush_implicit_paint (GdkWindow *window)
2655 GdkWindowObject *private = (GdkWindowObject *)window;
2656 GdkWindowObject *impl_window;
2657 GdkWindowPaint *paint;
2662 impl_window = gdk_window_get_impl_window (private);
2663 if (impl_window->implicit_paint == NULL)
2666 paint = impl_window->implicit_paint;
2667 paint->flushed = TRUE;
2668 region = gdk_region_copy (private->clip_region_with_children);
2670 /* Don't flush active double buffers, as that may show partially done
2672 for (list = private->paint_stack; list != NULL; list = list->next)
2674 GdkWindowPaint *tmp_paint = list->data;
2676 gdk_region_subtract (region, tmp_paint->region);
2679 gdk_region_offset (region, private->abs_x, private->abs_y);
2680 gdk_region_intersect (region, paint->region);
2682 if (!GDK_WINDOW_DESTROYED (window) && !gdk_region_empty (region))
2684 /* Remove flushed region from the implicit paint */
2685 gdk_region_subtract (paint->region, region);
2687 /* Some regions are valid, push these to window now */
2688 tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
2689 _gdk_gc_set_clip_region_internal (tmp_gc, region, TRUE);
2690 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2691 0, 0, paint->x_offset, paint->y_offset, -1, -1);
2692 /* Reset clip region of the cached GdkGC */
2693 gdk_gc_set_clip_region (tmp_gc, NULL);
2696 gdk_region_destroy (region);
2699 /* Ends an implicit paint, paired with gdk_window_begin_implicit_paint returning TRUE */
2701 gdk_window_end_implicit_paint (GdkWindow *window)
2703 GdkWindowObject *private = (GdkWindowObject *)window;
2704 GdkWindowPaint *paint;
2707 g_assert (gdk_window_has_impl (private));
2709 g_assert (private->implicit_paint != NULL);
2711 paint = private->implicit_paint;
2713 private->implicit_paint = NULL;
2715 if (!GDK_WINDOW_DESTROYED (window) && !gdk_region_empty (paint->region))
2717 /* Some regions are valid, push these to window now */
2718 tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
2719 _gdk_gc_set_clip_region_internal (tmp_gc, paint->region, TRUE);
2720 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2721 0, 0, paint->x_offset, paint->y_offset, -1, -1);
2722 /* Reset clip region of the cached GdkGC */
2723 gdk_gc_set_clip_region (tmp_gc, NULL);
2726 gdk_region_destroy (paint->region);
2728 g_object_unref (paint->pixmap);
2733 * gdk_window_begin_paint_rect:
2734 * @window: a #GdkWindow
2735 * @rectangle: rectangle you intend to draw to
2737 * A convenience wrapper around gdk_window_begin_paint_region() which
2738 * creates a rectangular region for you. See
2739 * gdk_window_begin_paint_region() for details.
2743 gdk_window_begin_paint_rect (GdkWindow *window,
2744 const GdkRectangle *rectangle)
2748 g_return_if_fail (GDK_IS_WINDOW (window));
2750 region = gdk_region_rectangle (rectangle);
2751 gdk_window_begin_paint_region (window, region);
2752 gdk_region_destroy (region);
2756 * gdk_window_begin_paint_region:
2757 * @window: a #GdkWindow
2758 * @region: region you intend to draw to
2760 * Indicates that you are beginning the process of redrawing @region.
2761 * A backing store (offscreen buffer) large enough to contain @region
2762 * will be created. The backing store will be initialized with the
2763 * background color or background pixmap for @window. Then, all
2764 * drawing operations performed on @window will be diverted to the
2765 * backing store. When you call gdk_window_end_paint(), the backing
2766 * store will be copied to @window, making it visible onscreen. Only
2767 * the part of @window contained in @region will be modified; that is,
2768 * drawing operations are clipped to @region.
2770 * The net result of all this is to remove flicker, because the user
2771 * sees the finished product appear all at once when you call
2772 * gdk_window_end_paint(). If you draw to @window directly without
2773 * calling gdk_window_begin_paint_region(), the user may see flicker
2774 * as individual drawing operations are performed in sequence. The
2775 * clipping and background-initializing features of
2776 * gdk_window_begin_paint_region() are conveniences for the
2777 * programmer, so you can avoid doing that work yourself.
2779 * When using GTK+, the widget system automatically places calls to
2780 * gdk_window_begin_paint_region() and gdk_window_end_paint() around
2781 * emissions of the expose_event signal. That is, if you're writing an
2782 * expose event handler, you can assume that the exposed area in
2783 * #GdkEventExpose has already been cleared to the window background,
2784 * is already set as the clip region, and already has a backing store.
2785 * Therefore in most cases, application code need not call
2786 * gdk_window_begin_paint_region(). (You can disable the automatic
2787 * calls around expose events on a widget-by-widget basis by calling
2788 * gtk_widget_set_double_buffered().)
2790 * If you call this function multiple times before calling the
2791 * matching gdk_window_end_paint(), the backing stores are pushed onto
2792 * a stack. gdk_window_end_paint() copies the topmost backing store
2793 * onscreen, subtracts the topmost region from all other regions in
2794 * the stack, and pops the stack. All drawing operations affect only
2795 * the topmost backing store in the stack. One matching call to
2796 * gdk_window_end_paint() is required for each call to
2797 * gdk_window_begin_paint_region().
2801 gdk_window_begin_paint_region (GdkWindow *window,
2802 const GdkRegion *region)
2804 #ifdef USE_BACKING_STORE
2805 GdkWindowObject *private = (GdkWindowObject *)window;
2806 GdkRectangle clip_box;
2807 GdkWindowPaint *paint, *implicit_paint;
2808 GdkWindowObject *impl_window;
2811 g_return_if_fail (GDK_IS_WINDOW (window));
2813 if (GDK_WINDOW_DESTROYED (window))
2816 if (GDK_IS_PAINTABLE (private->impl))
2818 GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
2820 if (iface->begin_paint_region)
2821 iface->begin_paint_region ((GdkPaintable*)private->impl, window, region);
2826 impl_window = gdk_window_get_impl_window (private);
2827 implicit_paint = impl_window->implicit_paint;
2829 paint = g_new (GdkWindowPaint, 1);
2830 paint->region = gdk_region_copy (region);
2831 paint->region_tag = new_region_tag ();
2833 gdk_region_intersect (paint->region, private->clip_region_with_children);
2834 gdk_region_get_clipbox (paint->region, &clip_box);
2836 /* Convert to impl coords */
2837 gdk_region_offset (paint->region, private->abs_x, private->abs_y);
2839 /* Mark the region as valid on the implicit paint */
2842 gdk_region_union (implicit_paint->region, paint->region);
2844 /* Convert back to normal coords */
2845 gdk_region_offset (paint->region, -private->abs_x, -private->abs_y);
2851 paint->uses_implicit = TRUE;
2852 paint->pixmap = g_object_ref (implicit_paint->pixmap);
2853 paint->x_offset = -private->abs_x + implicit_paint->x_offset;
2854 paint->y_offset = -private->abs_y + implicit_paint->y_offset;
2856 gdk_drawable_get_size (paint->pixmap, &width, &height);
2857 paint->surface = _gdk_drawable_create_cairo_surface (paint->pixmap, width, height);
2861 paint->uses_implicit = FALSE;
2862 paint->x_offset = clip_box.x;
2863 paint->y_offset = clip_box.y;
2865 gdk_pixmap_new (window,
2866 MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1);
2867 paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap);
2871 cairo_surface_set_device_offset (paint->surface,
2872 -paint->x_offset, -paint->y_offset);
2874 for (list = private->paint_stack; list != NULL; list = list->next)
2876 GdkWindowPaint *tmp_paint = list->data;
2878 gdk_region_subtract (tmp_paint->region, paint->region);
2881 private->paint_stack = g_slist_prepend (private->paint_stack, paint);
2883 if (!gdk_region_empty (paint->region))
2885 gdk_window_clear_backing_region (window,
2889 #endif /* USE_BACKING_STORE */
2893 setup_redirect_clip (GdkWindow *window,
2898 GdkWindowObject *private = (GdkWindowObject *)window;
2899 GdkRegion *visible_region;
2900 GdkRectangle dest_rect;
2902 GdkWindow *toplevel;
2903 int x_offset, y_offset;
2905 toplevel = GDK_WINDOW (private->redirect->redirected);
2907 /* Get the clip region for gc clip rect + window hierarchy in
2908 window relative coords */
2910 _gdk_window_calculate_full_clip_region (window, toplevel,
2915 /* Compensate for the source pos/size */
2916 x_offset -= private->redirect->src_x;
2917 y_offset -= private->redirect->src_y;
2918 dest_rect.x = -x_offset;
2919 dest_rect.y = -y_offset;
2920 dest_rect.width = private->redirect->width;
2921 dest_rect.height = private->redirect->height;
2922 tmpreg = gdk_region_rectangle (&dest_rect);
2923 gdk_region_intersect (visible_region, tmpreg);
2924 gdk_region_destroy (tmpreg);
2926 /* Compensate for the dest pos */
2927 x_offset += private->redirect->dest_x;
2928 y_offset += private->redirect->dest_y;
2930 gdk_gc_set_clip_region (gc, visible_region); /* This resets clip origin! */
2932 /* offset clip and tiles from window coords to pixmaps coords */
2933 gdk_gc_offset (gc, -x_offset, -y_offset);
2935 gdk_region_destroy (visible_region);
2937 *x_offset_out = x_offset;
2938 *y_offset_out = y_offset;
2942 * gdk_window_end_paint:
2943 * @window: a #GdkWindow
2945 * Indicates that the backing store created by the most recent call to
2946 * gdk_window_begin_paint_region() should be copied onscreen and
2947 * deleted, leaving the next-most-recent backing store or no backing
2948 * store at all as the active paint region. See
2949 * gdk_window_begin_paint_region() for full details. It is an error to
2950 * call this function without a matching
2951 * gdk_window_begin_paint_region() first.
2955 gdk_window_end_paint (GdkWindow *window)
2957 #ifdef USE_BACKING_STORE
2958 GdkWindowObject *private = (GdkWindowObject *)window;
2959 GdkWindowObject *composited;
2960 GdkWindowPaint *paint;
2962 GdkRectangle clip_box;
2963 gint x_offset, y_offset;
2964 GdkRegion *full_clip;
2966 g_return_if_fail (GDK_IS_WINDOW (window));
2968 if (GDK_WINDOW_DESTROYED (window))
2971 if (GDK_IS_PAINTABLE (private->impl))
2973 GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
2975 if (iface->end_paint)
2976 iface->end_paint ((GdkPaintable*)private->impl);
2980 if (private->paint_stack == NULL)
2982 g_warning (G_STRLOC": no preceding call to gdk_window_begin_paint_region(), see documentation");
2986 paint = private->paint_stack->data;
2988 private->paint_stack = g_slist_delete_link (private->paint_stack,
2989 private->paint_stack);
2991 gdk_region_get_clipbox (paint->region, &clip_box);
2993 tmp_gc = _gdk_drawable_get_scratch_gc (window, FALSE);
2995 x_offset = -private->abs_x;
2996 y_offset = -private->abs_y;
2998 if (!paint->uses_implicit)
3000 gdk_window_flush_outstanding_moves (window);
3002 full_clip = gdk_region_copy (private->clip_region_with_children);
3003 gdk_region_intersect (full_clip, paint->region);
3004 _gdk_gc_set_clip_region_internal (tmp_gc, full_clip, TRUE); /* Takes ownership of full_clip */
3005 gdk_gc_set_clip_origin (tmp_gc, - x_offset, - y_offset);
3006 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
3007 clip_box.x - paint->x_offset,
3008 clip_box.y - paint->y_offset,
3009 clip_box.x - x_offset, clip_box.y - y_offset,
3010 clip_box.width, clip_box.height);
3013 if (private->redirect)
3015 int x_offset, y_offset;
3017 /* TODO: Should also use paint->region for clipping */
3018 setup_redirect_clip (window, tmp_gc, &x_offset, &y_offset);
3019 gdk_draw_drawable (private->redirect->pixmap, tmp_gc, paint->pixmap,
3020 clip_box.x - paint->x_offset,
3021 clip_box.y - paint->y_offset,
3022 clip_box.x + x_offset,
3023 clip_box.y + y_offset,
3024 clip_box.width, clip_box.height);
3027 /* Reset clip region of the cached GdkGC */
3028 gdk_gc_set_clip_region (tmp_gc, NULL);
3030 cairo_surface_destroy (paint->surface);
3031 g_object_unref (paint->pixmap);
3032 gdk_region_destroy (paint->region);
3035 /* find a composited window in our hierarchy to signal its
3036 * parent to redraw, calculating the clip box as we go...
3038 * stop if parent becomes NULL since then we'd have nowhere
3039 * to draw (ie: 'composited' will always be non-NULL here).
3041 for (composited = private;
3043 composited = composited->parent)
3047 gdk_drawable_get_size (GDK_DRAWABLE (composited->parent),
3050 clip_box.x += composited->x;
3051 clip_box.y += composited->y;
3052 clip_box.width = MIN (clip_box.width, width - clip_box.x);
3053 clip_box.height = MIN (clip_box.height, height - clip_box.y);
3055 if (composited->composited)
3057 gdk_window_invalidate_rect (GDK_WINDOW (composited->parent),
3062 #endif /* USE_BACKING_STORE */
3066 gdk_window_free_paint_stack (GdkWindow *window)
3068 GdkWindowObject *private = (GdkWindowObject *)window;
3070 if (private->paint_stack)
3072 GSList *tmp_list = private->paint_stack;
3076 GdkWindowPaint *paint = tmp_list->data;
3078 if (tmp_list == private->paint_stack)
3079 g_object_unref (paint->pixmap);
3081 gdk_region_destroy (paint->region);
3084 tmp_list = tmp_list->next;
3087 g_slist_free (private->paint_stack);
3088 private->paint_stack = NULL;
3093 do_move_region_bits_on_impl (GdkWindowObject *impl_window,
3094 GdkRegion *dest_region, /* In impl window coords */
3098 GdkRectangle copy_rect;
3099 GdkWindowObject *private;
3100 GdkWindowImplIface *impl_iface;
3102 /* We need to get data from subwindows here, because we might have
3103 * shaped a native window over the moving region (with bg none,
3104 * so the pixels are still there). In fact we might need to get data
3105 * from overlapping native window that are not children of this window,
3106 * so we copy from the toplevel with INCLUDE_INFERIORS.
3108 private = impl_window;
3109 while (!gdk_window_is_toplevel (private))
3111 dx -= private->parent->abs_x + private->x;
3112 dy -= private->parent->abs_y + private->y;
3113 private = gdk_window_get_impl_window (private->parent);
3115 tmp_gc = _gdk_drawable_get_subwindow_scratch_gc ((GdkWindow *)private);
3117 gdk_region_get_clipbox (dest_region, ©_rect);
3118 gdk_gc_set_clip_region (tmp_gc, dest_region);
3120 /* The region area is moved and we queue translations for all expose events
3121 to the source area that were sent prior to the copy */
3122 gdk_region_offset (dest_region, -dx, -dy); /* Move to source region */
3123 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
3125 impl_iface->queue_translation ((GdkWindow *)impl_window,
3127 dest_region, dx, dy);
3129 gdk_draw_drawable (impl_window->impl,
3132 copy_rect.x-dx, copy_rect.y-dy,
3133 copy_rect.x, copy_rect.y,
3134 copy_rect.width, copy_rect.height);
3135 gdk_gc_set_clip_region (tmp_gc, NULL);
3138 static GdkWindowRegionMove *
3139 gdk_window_region_move_new (GdkRegion *region,
3142 GdkWindowRegionMove *move;
3144 move = g_slice_new (GdkWindowRegionMove);
3145 move->dest_region = gdk_region_copy (region);
3153 gdk_window_region_move_free (GdkWindowRegionMove *move)
3155 gdk_region_destroy (move->dest_region);
3156 g_slice_free (GdkWindowRegionMove, move);
3160 append_move_region (GdkWindowObject *impl_window,
3161 GdkRegion *new_dest_region,
3164 GdkWindowRegionMove *move, *old_move;
3165 GdkRegion *new_total_region, *old_total_region;
3166 GdkRegion *source_overlaps_destination;
3167 GdkRegion *non_overwritten;
3168 gboolean added_move;
3171 if (gdk_region_empty (new_dest_region))
3174 /* In principle this could just append the move to the list of outstanding
3175 moves that will be replayed before drawing anything when we're handling
3176 exposes. However, we'd like to do a bit better since its commonly the case
3177 that we get multiple copies where A is copied to B and then B is copied
3178 to C, and we'd like to express this as a simple copy A to C operation. */
3180 /* We approach this by taking the new move and pushing it ahead of moves
3181 starting at the end of the list and stopping when its not safe to do so.
3182 It's not safe to push past a move if either the source of the new move
3183 is in the destination of the old move, or if the destination of the new
3184 move is in the source of the new move, or if the destination of the new
3185 move overlaps the destination of the old move. We simplify this by
3186 just comparing the total regions (src + dest) */
3187 new_total_region = gdk_region_copy (new_dest_region);
3188 gdk_region_offset (new_total_region, -dx, -dy);
3189 gdk_region_union (new_total_region, new_dest_region);
3192 for (l = g_list_last (impl_window->outstanding_moves); l != NULL; l = prev)
3197 old_total_region = gdk_region_copy (old_move->dest_region);
3198 gdk_region_offset (old_total_region, -old_move->dx, -old_move->dy);
3199 gdk_region_union (old_total_region, old_move->dest_region);
3201 gdk_region_intersect (old_total_region, new_total_region);
3202 /* If these regions intersect then its not safe to push the
3203 new region before the old one */
3204 if (!gdk_region_empty (old_total_region))
3206 /* The area where the new moves source overlaps the old ones
3208 source_overlaps_destination = gdk_region_copy (new_dest_region);
3209 gdk_region_offset (source_overlaps_destination, -dx, -dy);
3210 gdk_region_intersect (source_overlaps_destination, old_move->dest_region);
3211 gdk_region_offset (source_overlaps_destination, dx, dy);
3213 /* We can do all sort of optimizations here, but to do things safely it becomes
3214 quite complicated. However, a very common case is that you copy something first,
3215 then copy all that or a subset of it to a new location (i.e. if you scroll twice
3216 in the same direction). We'd like to detect this case and optimize it to one
3218 if (gdk_region_equal (source_overlaps_destination, new_dest_region))
3220 /* This means we might be able to replace the old move and the new one
3221 with the new one read from the old ones source, and a second copy of
3222 the non-overwritten parts of the old move. However, such a split
3223 is only valid if the source in the old move isn't overwritten
3224 by the destination of the new one */
3226 /* the new destination of old move if split is ok: */
3227 non_overwritten = gdk_region_copy (old_move->dest_region);
3228 gdk_region_subtract (non_overwritten, new_dest_region);
3229 /* move to source region */
3230 gdk_region_offset (non_overwritten, -old_move->dx, -old_move->dy);
3232 gdk_region_intersect (non_overwritten, new_dest_region);
3233 if (gdk_region_empty (non_overwritten))
3236 move = gdk_window_region_move_new (new_dest_region,
3240 impl_window->outstanding_moves =
3241 g_list_insert_before (impl_window->outstanding_moves,
3243 gdk_region_subtract (old_move->dest_region, new_dest_region);
3245 gdk_region_destroy (non_overwritten);
3248 gdk_region_destroy (source_overlaps_destination);
3249 gdk_region_destroy (old_total_region);
3252 gdk_region_destroy (old_total_region);
3255 gdk_region_destroy (new_total_region);
3259 move = gdk_window_region_move_new (new_dest_region, dx, dy);
3262 impl_window->outstanding_moves =
3263 g_list_prepend (impl_window->outstanding_moves,
3266 impl_window->outstanding_moves =
3267 g_list_insert_before (impl_window->outstanding_moves,
3272 /* Moves bits and update area by dx/dy in impl window.
3273 Takes ownership of region to avoid copy (because we may change it) */
3275 move_region_on_impl (GdkWindowObject *impl_window,
3276 GdkRegion *region, /* In impl window coords */
3279 if ((dx == 0 && dy == 0) ||
3280 gdk_region_empty (region))
3282 gdk_region_destroy (region);
3286 g_assert (impl_window == gdk_window_get_impl_window (impl_window));
3288 /* Move any old invalid regions in the copy source area by dx/dy */
3289 if (impl_window->update_area)
3291 GdkRegion *update_area;
3293 update_area = gdk_region_copy (region);
3295 /* Convert from target to source */
3296 gdk_region_offset (update_area, -dx, -dy);
3297 gdk_region_intersect (update_area, impl_window->update_area);
3298 /* We only copy the area, so keep the old update area invalid.
3299 It would be safe to remove it too, as code that uses
3300 move_region_on_impl generally also invalidate the source
3301 area. However, it would just use waste cycles. */
3304 gdk_region_offset (update_area, dx, dy);
3305 gdk_region_union (impl_window->update_area, update_area);
3307 /* This area of the destination is now invalid,
3308 so no need to copy to it. */
3309 gdk_region_subtract (region, update_area);
3311 gdk_region_destroy (update_area);
3314 /* If we're currently exposing this window, don't copy to this
3315 destination, as it will be overdrawn when the expose is done,
3316 instead invalidate it and repaint later. */
3317 if (impl_window->implicit_paint)
3319 GdkWindowPaint *implicit_paint = impl_window->implicit_paint;
3320 GdkRegion *exposing;
3322 exposing = gdk_region_copy (implicit_paint->region);
3323 gdk_region_intersect (exposing, region);
3324 gdk_region_subtract (region, exposing);
3326 impl_window_add_update_area (impl_window, exposing);
3327 gdk_region_destroy (exposing);
3330 if (1) /* Enable flicker free handling of moves. */
3331 append_move_region (impl_window, region, dx, dy);
3333 do_move_region_bits_on_impl (impl_window,
3336 gdk_region_destroy (region);
3339 /* Flushes all outstanding changes to the window, call this
3340 * before drawing directly to the window (i.e. outside a begin/end_paint pair).
3343 gdk_window_flush_outstanding_moves (GdkWindow *window)
3345 GdkWindowObject *private;
3346 GdkWindowObject *impl_window;
3348 GdkWindowRegionMove *move;
3350 private = (GdkWindowObject *) window;
3352 impl_window = gdk_window_get_impl_window (private);
3354 for (l = impl_window->outstanding_moves; l != NULL; l = l->next)
3358 do_move_region_bits_on_impl (impl_window,
3359 move->dest_region, move->dx, move->dy);
3361 gdk_window_region_move_free (move);
3364 g_list_free (impl_window->outstanding_moves);
3365 impl_window->outstanding_moves = NULL;
3370 * @window: a #GdkWindow
3372 * Flush all outstanding cached operations on a window, leaving the
3373 * window in a state which reflects all that has been drawn before.
3375 * Gdk uses multiple kinds of caching to get better performance and
3376 * nicer drawing. For instance, during exposes all paints to a window
3377 * using double buffered rendering are keep on a pixmap until the last
3378 * window has been exposed. It also delays window moves/scrolls until
3379 * as long as possible until next update to avoid tearing when moving
3382 * Normally this should be completely invisible to applications, as
3383 * we automatically flush the windows when required, but this might
3384 * be needed if you for instance mix direct native drawing with
3385 * gdk drawing. For Gtk widgets that don't use double buffering this
3386 * will be called automatically before sending the expose event.
3391 gdk_window_flush (GdkWindow *window)
3393 gdk_window_flush_outstanding_moves (window);
3394 gdk_window_flush_implicit_paint (window);
3397 /* If we're about to move/resize or otherwise change the
3398 * hierarchy of a client side window in an impl and we're
3399 * called from an expose event handler then we need to
3400 * flush any already painted parts of the implicit paint
3401 * that are not part of the current paint, as these may
3402 * be used when scrolling or may overdraw the changes
3403 * caused by the hierarchy change.
3406 gdk_window_flush_if_exposing (GdkWindow *window)
3408 GdkWindowObject *private;
3409 GdkWindowObject *impl_window;
3411 private = (GdkWindowObject *) window;
3412 impl_window = gdk_window_get_impl_window (private);
3414 /* If we're in an implicit paint (i.e. in an expose handler, flush
3415 all the already finished exposes to get things to an uptodate state. */
3416 if (impl_window->implicit_paint)
3417 gdk_window_flush (window);
3422 gdk_window_flush_recursive_helper (GdkWindowObject *window,
3425 GdkWindowObject *child;
3428 for (l = window->children; l != NULL; l = l->next)
3432 if (child->impl == impl)
3433 /* Same impl, ignore */
3434 gdk_window_flush_recursive_helper (child, impl);
3436 gdk_window_flush_recursive (child);
3441 gdk_window_flush_recursive (GdkWindowObject *window)
3443 gdk_window_flush ((GdkWindow *)window);
3444 gdk_window_flush_recursive_helper (window, window->impl);
3448 gdk_window_get_offsets (GdkWindow *window,
3452 GdkWindowObject *private = (GdkWindowObject *)window;
3454 if (private->paint_stack)
3456 GdkWindowPaint *paint = private->paint_stack->data;
3457 *x_offset = paint->x_offset;
3458 *y_offset = paint->y_offset;
3462 *x_offset = -private->abs_x;
3463 *y_offset = -private->abs_y;
3468 * gdk_window_get_internal_paint_info:
3469 * @window: a #GdkWindow
3470 * @real_drawable: (out): location to store the drawable to which drawing should be
3472 * @x_offset: (out): location to store the X offset between coordinates in @window,
3473 * and the underlying window system primitive coordinates for
3475 * @y_offset: (out): location to store the Y offset between coordinates in @window,
3476 * and the underlying window system primitive coordinates for
3479 * If you bypass the GDK layer and use windowing system primitives to
3480 * draw directly onto a #GdkWindow, then you need to deal with two
3481 * details: there may be an offset between GDK coordinates and windowing
3482 * system coordinates, and GDK may have redirected drawing to a offscreen
3483 * pixmap as the result of a gdk_window_begin_paint_region() calls.
3484 * This function allows retrieving the information you need to compensate
3485 * for these effects.
3487 * This function exposes details of the GDK implementation, and is thus
3488 * likely to change in future releases of GDK.
3491 gdk_window_get_internal_paint_info (GdkWindow *window,
3492 GdkDrawable **real_drawable,
3498 GdkWindowObject *private;
3500 g_return_if_fail (GDK_IS_WINDOW (window));
3502 private = (GdkWindowObject *)window;
3506 if (private->paint_stack)
3508 GdkWindowPaint *paint = private->paint_stack->data;
3509 *real_drawable = paint->pixmap;
3513 /* This means you're probably gonna be doing some weird shit
3514 directly to the window, so we flush all outstanding stuff */
3515 gdk_window_flush (window);
3516 *real_drawable = window;
3520 gdk_window_get_offsets (window, &x_off, &y_off);
3528 static GdkDrawable *
3529 start_draw_helper (GdkDrawable *drawable,
3534 GdkWindowObject *private = (GdkWindowObject *)drawable;
3535 gint x_offset, y_offset;
3537 gint old_clip_x = gc->clip_x_origin;
3538 gint old_clip_y = gc->clip_y_origin;
3540 guint32 clip_region_tag;
3541 GdkWindowPaint *paint;
3544 if (private->paint_stack)
3545 paint = private->paint_stack->data;
3549 x_offset = paint->x_offset;
3550 y_offset = paint->y_offset;
3554 x_offset = -private->abs_x;
3555 y_offset = -private->abs_y;
3558 if (x_offset != 0 || y_offset != 0)
3560 gdk_gc_set_clip_origin (gc,
3561 old_clip_x - x_offset,
3562 old_clip_y - y_offset);
3563 gdk_gc_set_ts_origin (gc,
3564 gc->ts_x_origin - x_offset,
3565 gc->ts_y_origin - y_offset);
3568 *x_offset_out = x_offset;
3569 *y_offset_out = y_offset;
3571 /* Add client side window clip region to gc */
3575 /* Only need clipping if using implicit paint, otherwise
3576 the pixmap is clipped when copying to the window in end_paint */
3577 if (paint->uses_implicit)
3579 /* This includes the window clip */
3580 clip = paint->region;
3582 clip_region_tag = paint->region_tag;
3584 /* After having set up the drawable clip rect on a GC we need to make sure
3585 * that we draw to th the impl, otherwise the pixmap code will reset the
3587 impl = ((GdkPixmapObject *)(paint->pixmap))->impl;
3591 /* Drawing directly to the window, flush anything outstanding to
3592 guarantee ordering. */
3593 gdk_window_flush ((GdkWindow *)drawable);
3595 /* Don't clip when drawing to root or all native */
3596 if (!_gdk_native_windows && private->window_type != GDK_WINDOW_ROOT)
3598 if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
3599 clip = private->clip_region_with_children;
3601 clip = private->clip_region;
3603 clip_region_tag = private->clip_tag;
3604 impl = private->impl;
3608 _gdk_gc_add_drawable_clip (gc,
3609 clip_region_tag, clip,
3610 /* If there was a clip origin set appart from the
3611 * window offset, need to take that into
3613 -old_clip_x, -old_clip_y);
3618 #define BEGIN_DRAW \
3620 GdkDrawable *impl; \
3621 gint x_offset, y_offset; \
3622 gint old_clip_x = gc->clip_x_origin; \
3623 gint old_clip_y = gc->clip_y_origin; \
3624 gint old_ts_x = gc->ts_x_origin; \
3625 gint old_ts_y = gc->ts_y_origin; \
3626 impl = start_draw_helper (drawable, gc, \
3627 &x_offset, &y_offset);
3630 if (x_offset != 0 || y_offset != 0) \
3632 gdk_gc_set_clip_origin (gc, old_clip_x, old_clip_y); \
3633 gdk_gc_set_ts_origin (gc, old_ts_x, old_ts_y); \
3638 gdk_window_create_gc (GdkDrawable *drawable,
3639 GdkGCValues *values,
3640 GdkGCValuesMask mask)
3642 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
3644 if (GDK_WINDOW_DESTROYED (drawable))
3647 return gdk_gc_new_with_values (((GdkWindowObject *) drawable)->impl,
3652 gdk_window_draw_rectangle (GdkDrawable *drawable,
3660 if (GDK_WINDOW_DESTROYED (drawable))
3664 gdk_draw_rectangle (impl, gc, filled,
3665 x - x_offset, y - y_offset, width, height);
3670 gdk_window_draw_arc (GdkDrawable *drawable,
3680 if (GDK_WINDOW_DESTROYED (drawable))
3684 gdk_draw_arc (impl, gc, filled,
3685 x - x_offset, y - y_offset,
3686 width, height, angle1, angle2);
3691 gdk_window_draw_polygon (GdkDrawable *drawable,
3697 GdkPoint *new_points;
3699 if (GDK_WINDOW_DESTROYED (drawable))
3704 if (x_offset != 0 || y_offset != 0)
3708 new_points = g_new (GdkPoint, npoints);
3709 for (i=0; i<npoints; i++)
3711 new_points[i].x = points[i].x - x_offset;
3712 new_points[i].y = points[i].y - y_offset;
3716 new_points = points;
3718 gdk_draw_polygon (impl, gc, filled, new_points, npoints);
3720 if (new_points != points)
3721 g_free (new_points);
3727 gdk_window_draw_text (GdkDrawable *drawable,
3735 if (GDK_WINDOW_DESTROYED (drawable))
3739 gdk_draw_text (impl, font, gc,
3740 x - x_offset, y - y_offset, text, text_length);
3745 gdk_window_draw_text_wc (GdkDrawable *drawable,
3750 const GdkWChar *text,
3753 if (GDK_WINDOW_DESTROYED (drawable))
3757 gdk_draw_text_wc (impl, font, gc,
3758 x - x_offset, y - y_offset, text, text_length);
3762 static GdkDrawable *
3763 gdk_window_get_source_drawable (GdkDrawable *drawable)
3765 GdkWindow *window = GDK_WINDOW (drawable);
3766 GdkWindowObject *private;
3768 private = (GdkWindowObject *) window;
3769 if (GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable)
3770 return GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable (private->impl);
3775 static GdkDrawable *
3776 gdk_window_get_composite_drawable (GdkDrawable *drawable,
3781 gint *composite_x_offset,
3782 gint *composite_y_offset)
3784 GdkWindowObject *private = (GdkWindowObject *)drawable;
3786 GdkPixmap *tmp_pixmap;
3789 gboolean overlap_buffer;
3790 GdkDrawable *source;
3791 GdkWindowObject *impl_window;
3792 GdkWindowPaint *implicit_paint;
3794 *composite_x_offset = -private->abs_x;
3795 *composite_y_offset = -private->abs_y;
3797 if ((GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable)))
3798 return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
3800 /* See if any buffered part is overlapping the part we want
3806 rect.height = height;
3808 overlap_buffer = FALSE;
3810 for (list = private->paint_stack; list != NULL; list = list->next)
3812 GdkWindowPaint *paint = list->data;
3813 GdkOverlapType overlap;
3815 overlap = gdk_region_rect_in (paint->region, &rect);
3817 if (overlap == GDK_OVERLAP_RECTANGLE_IN)
3819 *composite_x_offset = paint->x_offset;
3820 *composite_y_offset = paint->y_offset;
3822 return g_object_ref (paint->pixmap);
3824 else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
3826 overlap_buffer = TRUE;
3831 impl_window = gdk_window_get_impl_window (private);
3832 implicit_paint = impl_window->implicit_paint;
3835 GdkOverlapType overlap;
3837 rect.x += private->abs_x;
3838 rect.y += private->abs_y;
3840 overlap = gdk_region_rect_in (implicit_paint->region, &rect);
3841 if (overlap == GDK_OVERLAP_RECTANGLE_IN)
3843 *composite_x_offset = -private->abs_x + implicit_paint->x_offset;
3844 *composite_y_offset = -private->abs_y + implicit_paint->y_offset;
3846 return g_object_ref (implicit_paint->pixmap);
3848 else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
3849 overlap_buffer = TRUE;
3852 if (!overlap_buffer)
3853 return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
3855 tmp_pixmap = gdk_pixmap_new (drawable, width, height, -1);
3856 tmp_gc = _gdk_drawable_get_scratch_gc (tmp_pixmap, FALSE);
3858 source = _gdk_drawable_get_source_drawable (drawable);
3860 /* Copy the current window contents */
3861 gdk_draw_drawable (tmp_pixmap,
3863 GDK_WINDOW_OBJECT (source)->impl,
3864 x - *composite_x_offset,
3865 y - *composite_y_offset,
3869 /* paint the backing stores */
3872 GdkWindowPaint *paint = list->data;
3874 gdk_gc_set_clip_region (tmp_gc, paint->region);
3875 gdk_gc_set_clip_origin (tmp_gc, -x - paint->x_offset, -y - paint->y_offset);
3877 gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
3878 x - paint->x_offset,
3879 y - paint->y_offset,
3880 0, 0, width, height);
3883 for (list = private->paint_stack; list != NULL; list = list->next)
3885 GdkWindowPaint *paint = list->data;
3887 if (paint->uses_implicit)
3888 continue; /* We already copied this above */
3890 gdk_gc_set_clip_region (tmp_gc, paint->region);
3891 gdk_gc_set_clip_origin (tmp_gc, -x, -y);
3893 gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
3894 x - paint->x_offset,
3895 y - paint->y_offset,
3896 0, 0, width, height);
3899 /* Reset clip region of the cached GdkGC */
3900 gdk_gc_set_clip_region (tmp_gc, NULL);
3902 /* Set these to location of tmp_pixmap within the window */
3903 *composite_x_offset = x;
3904 *composite_y_offset = y;
3910 gdk_window_get_clip_region (GdkDrawable *drawable)
3912 GdkWindowObject *private = (GdkWindowObject *)drawable;
3915 result = gdk_region_copy (private->clip_region);
3917 if (private->paint_stack)
3919 GdkRegion *paint_region = gdk_region_new ();
3920 GSList *tmp_list = private->paint_stack;
3924 GdkWindowPaint *paint = tmp_list->data;
3926 gdk_region_union (paint_region, paint->region);
3928 tmp_list = tmp_list->next;
3931 gdk_region_intersect (result, paint_region);
3932 gdk_region_destroy (paint_region);
3939 gdk_window_get_visible_region (GdkDrawable *drawable)
3941 GdkWindowObject *private = (GdkWindowObject*) drawable;
3943 return gdk_region_copy (private->clip_region);
3947 gdk_window_draw_drawable (GdkDrawable *drawable,
3956 GdkDrawable *original_src)
3958 GdkWindowObject *private = (GdkWindowObject *)drawable;
3960 if (GDK_WINDOW_DESTROYED (drawable))
3965 /* Call the method directly to avoid getting the composite drawable again */
3966 GDK_DRAWABLE_GET_CLASS (impl)->draw_drawable_with_src (impl, gc,
3974 if (!private->paint_stack)
3976 /* We might have drawn from an obscured part of a client
3977 side window, if so we need to send graphics exposures */
3978 if (_gdk_gc_get_exposures (gc) &&
3979 GDK_IS_WINDOW (original_src))
3981 GdkRegion *exposure_region;
3989 exposure_region = gdk_region_rectangle (&r);
3991 if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
3992 clip = private->clip_region_with_children;
3994 clip = private->clip_region;
3995 gdk_region_intersect (exposure_region, clip);
3997 _gdk_gc_remove_drawable_clip (gc);
3998 clip = _gdk_gc_get_clip_region (gc);
4001 gdk_region_offset (exposure_region,
4004 gdk_region_intersect (exposure_region, clip);
4005 gdk_region_offset (exposure_region,
4010 /* Note: We don't clip by the clip mask if set, so this
4011 may invalidate to much */
4013 /* Remove the area that is correctly copied from the src.
4014 * Note that xsrc/ysrc has been corrected for abs_x/y offsets already,
4015 * which need to be undone */
4016 clip = gdk_drawable_get_visible_region (original_src);
4017 gdk_region_offset (clip,
4018 xdest - (xsrc - GDK_WINDOW_OBJECT (original_src)->abs_x),
4019 ydest - (ysrc - GDK_WINDOW_OBJECT (original_src)->abs_y));
4020 gdk_region_subtract (exposure_region, clip);
4021 gdk_region_destroy (clip);
4023 gdk_window_invalidate_region_full (GDK_WINDOW (private),
4025 _gdk_gc_get_subwindow (gc) == GDK_INCLUDE_INFERIORS,
4028 gdk_region_destroy (exposure_region);
4036 gdk_window_draw_points (GdkDrawable *drawable,
4041 GdkPoint *new_points;
4043 if (GDK_WINDOW_DESTROYED (drawable))
4048 if (x_offset != 0 || y_offset != 0)
4052 new_points = g_new (GdkPoint, npoints);
4053 for (i=0; i<npoints; i++)
4055 new_points[i].x = points[i].x - x_offset;
4056 new_points[i].y = points[i].y - y_offset;
4060 new_points = points;
4062 gdk_draw_points (impl, gc, new_points, npoints);
4064 if (new_points != points)
4065 g_free (new_points);
4071 gdk_window_draw_segments (GdkDrawable *drawable,
4076 GdkSegment *new_segs;
4078 if (GDK_WINDOW_DESTROYED (drawable))
4083 if (x_offset != 0 || y_offset != 0)
4087 new_segs = g_new (GdkSegment, nsegs);
4088 for (i=0; i<nsegs; i++)
4090 new_segs[i].x1 = segs[i].x1 - x_offset;
4091 new_segs[i].y1 = segs[i].y1 - y_offset;
4092 new_segs[i].x2 = segs[i].x2 - x_offset;
4093 new_segs[i].y2 = segs[i].y2 - y_offset;
4099 gdk_draw_segments (impl, gc, new_segs, nsegs);
4101 if (new_segs != segs)
4108 gdk_window_draw_lines (GdkDrawable *drawable,
4113 GdkPoint *new_points;
4115 if (GDK_WINDOW_DESTROYED (drawable))
4120 if (x_offset != 0 || y_offset != 0)
4124 new_points = g_new (GdkPoint, npoints);
4125 for (i=0; i<npoints; i++)
4127 new_points[i].x = points[i].x - x_offset;
4128 new_points[i].y = points[i].y - y_offset;
4132 new_points = points;
4134 gdk_draw_lines (impl, gc, new_points, npoints);
4136 if (new_points != points)
4137 g_free (new_points);
4143 gdk_window_draw_glyphs (GdkDrawable *drawable,
4148 PangoGlyphString *glyphs)
4150 if (GDK_WINDOW_DESTROYED (drawable))
4154 gdk_draw_glyphs (impl, gc, font,
4155 x - x_offset, y - y_offset, glyphs);
4160 gdk_window_draw_glyphs_transformed (GdkDrawable *drawable,
4162 PangoMatrix *matrix,
4166 PangoGlyphString *glyphs)
4168 PangoMatrix tmp_matrix;
4170 if (GDK_WINDOW_DESTROYED (drawable))
4175 if (x_offset != 0 || y_offset != 0)
4179 tmp_matrix = *matrix;
4180 tmp_matrix.x0 -= x_offset;
4181 tmp_matrix.y0 -= y_offset;
4182 matrix = &tmp_matrix;
4184 else if (GDK_PANGO_UNITS_OVERFLOWS (x_offset, y_offset))
4186 PangoMatrix identity = PANGO_MATRIX_INIT;
4188 tmp_matrix = identity;
4189 tmp_matrix.x0 -= x_offset;
4190 tmp_matrix.y0 -= y_offset;
4191 matrix = &tmp_matrix;
4195 x -= x_offset * PANGO_SCALE;
4196 y -= y_offset * PANGO_SCALE;
4200 gdk_draw_glyphs_transformed (impl, gc, matrix, font, x, y, glyphs);
4206 cairo_t *cr; /* if non-null, it means use this cairo context */
4207 GdkGC *gc; /* if non-null, it means use this GC instead */
4208 } BackingRectMethod;
4211 setup_backing_rect_method (BackingRectMethod *method, GdkWindow *window, GdkWindowPaint *paint, int x_offset_cairo, int y_offset_cairo)
4213 GdkWindowObject *private = (GdkWindowObject *)window;
4215 if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
4217 GdkWindowPaint tmp_paint;
4220 tmp_paint.x_offset += private->x;
4221 tmp_paint.y_offset += private->y;
4223 x_offset_cairo += private->x;
4224 y_offset_cairo += private->y;
4226 setup_backing_rect_method (method, GDK_WINDOW (private->parent), &tmp_paint, x_offset_cairo, y_offset_cairo);
4228 else if (private->bg_pixmap &&
4229 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
4230 private->bg_pixmap != GDK_NO_BG)
4232 /* This is a workaround for https://bugs.freedesktop.org/show_bug.cgi?id=4320.
4233 * In it, using a pixmap as a repeating pattern in Cairo, and painting it to a
4234 * pixmap destination surface, can be very slow (on the order of seconds for a
4235 * whole-screen copy). The workaround is to use pretty much the same code that
4236 * we used in GTK+ 2.6 (pre-Cairo), which clears the double-buffer pixmap with
4237 * a tiled GC XFillRectangle().
4240 /* Actually computing this flag is left as an exercise for the reader */
4241 #if defined (G_OS_UNIX)
4242 # define GDK_CAIRO_REPEAT_IS_FAST 0
4244 # define GDK_CAIRO_REPEAT_IS_FAST 1
4247 #if GDK_CAIRO_REPEAT_IS_FAST
4248 cairo_surface_t *surface = _gdk_drawable_ref_cairo_surface (private->bg_pixmap);
4249 cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
4250 cairo_surface_destroy (surface);
4252 if (x_offset_cairo != 0 || y_offset_cairo != 0)
4254 cairo_matrix_t matrix;
4255 cairo_matrix_init_translate (&matrix, x_offset_cairo, y_offset_cairo);
4256 cairo_pattern_set_matrix (pattern, &matrix);
4259 cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
4261 method->cr = cairo_create (paint->surface);
4264 cairo_set_source (method->cr, pattern);
4265 cairo_pattern_destroy (pattern);
4268 GdkGCValues gc_values;
4270 gc_values.fill = GDK_TILED;
4271 gc_values.tile = private->bg_pixmap;
4272 gc_values.ts_x_origin = -x_offset_cairo;
4273 gc_values.ts_y_origin = -y_offset_cairo;
4275 gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN;
4277 method->gc = gdk_gc_new_with_values (paint->pixmap, &gc_values, gc_mask);
4282 method->cr = cairo_create (paint->surface);
4284 gdk_cairo_set_source_color (method->cr, &private->bg_color);
4289 gdk_window_clear_backing_region (GdkWindow *window,
4292 GdkWindowObject *private = (GdkWindowObject *)window;
4293 GdkWindowPaint *paint = private->paint_stack->data;
4294 BackingRectMethod method;
4296 GdkRectangle clipbox;
4302 if (GDK_WINDOW_DESTROYED (window))
4306 timer = g_timer_new ();
4311 setup_backing_rect_method (&method, window, paint, 0, 0);
4313 clip = gdk_region_copy (paint->region);
4314 gdk_region_intersect (clip, region);
4315 gdk_region_get_clipbox (clip, &clipbox);
4320 g_assert (method.gc == NULL);
4322 gdk_cairo_region (method.cr, clip);
4323 cairo_fill (method.cr);
4325 cairo_destroy (method.cr);
4327 elapsed = g_timer_elapsed (timer, NULL);
4328 g_print ("Draw the background with Cairo: %fs\n", elapsed);
4333 g_assert (method.gc != NULL);
4335 gdk_gc_set_clip_region (method.gc, clip);
4336 gdk_draw_rectangle (window, method.gc, TRUE,
4337 clipbox.x, clipbox.y,
4338 clipbox.width, clipbox.height);
4339 g_object_unref (method.gc);
4342 elapsed = g_timer_elapsed (timer, NULL);
4343 g_print ("Draw the background with GDK: %fs\n", elapsed);
4347 gdk_region_destroy (clip);
4350 g_timer_destroy (timer);
4355 gdk_window_clear_backing_region_redirect (GdkWindow *window,
4358 GdkWindowObject *private = (GdkWindowObject *)window;
4359 GdkWindowRedirect *redirect = private->redirect;
4360 GdkRegion *clip_region;
4361 GdkRectangle clipbox;
4362 gint x_offset, y_offset;
4363 BackingRectMethod method;
4364 GdkWindowPaint paint;
4366 if (GDK_WINDOW_DESTROYED (window))
4369 clip_region = _gdk_window_calculate_full_clip_region (window,
4370 GDK_WINDOW (redirect->redirected),
4372 &x_offset, &y_offset);
4373 gdk_region_intersect (clip_region, region);
4375 /* offset is from redirected window origin to window origin, convert to
4376 the offset from the redirected pixmap origin to the window origin */
4377 x_offset += redirect->dest_x - redirect->src_x;
4378 y_offset += redirect->dest_y - redirect->src_y;
4380 /* Convert region to pixmap coords */
4381 gdk_region_offset (clip_region, x_offset, y_offset);
4385 paint.pixmap = redirect->pixmap;
4386 paint.surface = _gdk_drawable_ref_cairo_surface (redirect->pixmap);
4390 setup_backing_rect_method (&method, window, &paint, -x_offset, -y_offset);
4394 g_assert (method.gc == NULL);
4396 gdk_cairo_region (method.cr, clip_region);
4397 cairo_fill (method.cr);
4399 cairo_destroy (method.cr);
4403 g_assert (method.gc != NULL);
4405 gdk_region_get_clipbox (clip_region, &clipbox);
4406 gdk_gc_set_clip_region (method.gc, clip_region);
4407 gdk_draw_rectangle (redirect->pixmap, method.gc, TRUE,
4408 clipbox.x, clipbox.y,
4409 clipbox.width, clipbox.height);
4410 g_object_unref (method.gc);
4414 gdk_region_destroy (clip_region);
4415 cairo_surface_destroy (paint.surface);
4419 gdk_window_clear_backing_region_direct (GdkWindow *window,
4422 GdkWindowObject *private = (GdkWindowObject *)window;
4423 BackingRectMethod method;
4424 GdkWindowPaint paint;
4426 GdkRectangle clipbox;
4428 if (GDK_WINDOW_DESTROYED (window))
4433 paint.pixmap = window;
4434 paint.surface = _gdk_drawable_ref_cairo_surface (window);
4438 setup_backing_rect_method (&method, window, &paint, 0, 0);
4440 clip = gdk_region_copy (private->clip_region_with_children);
4441 gdk_region_intersect (clip, region);
4442 gdk_region_get_clipbox (clip, &clipbox);
4446 g_assert (method.gc == NULL);
4448 gdk_cairo_region (method.cr, clip);
4449 cairo_fill (method.cr);
4451 cairo_destroy (method.cr);
4455 g_assert (method.gc != NULL);
4457 gdk_gc_set_clip_region (method.gc, clip);
4458 gdk_draw_rectangle (window, method.gc, TRUE,
4459 clipbox.x, clipbox.y,
4460 clipbox.width, clipbox.height);
4461 g_object_unref (method.gc);
4465 gdk_region_destroy (clip);
4466 cairo_surface_destroy (paint.surface);
4472 * @window: a #GdkWindow
4474 * Clears an entire @window to the background color or background pixmap.
4477 gdk_window_clear (GdkWindow *window)
4481 g_return_if_fail (GDK_IS_WINDOW (window));
4483 gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height);
4485 gdk_window_clear_area (window, 0, 0,
4489 /* TRUE if the window clears to the same pixels as a native
4490 window clear. This means you can use the native window
4491 clearing operation, and additionally it means any clearing
4492 done by the native window system for you will already be right */
4494 clears_as_native (GdkWindowObject *private)
4496 GdkWindowObject *next;
4502 if (gdk_window_has_impl (private))
4504 next = private->parent;
4506 while (private->bg_pixmap == GDK_PARENT_RELATIVE_BG &&
4507 next && next->window_type != GDK_WINDOW_ROOT);
4512 gdk_window_clear_region_internal (GdkWindow *window,
4514 gboolean send_expose)
4516 GdkWindowObject *private = (GdkWindowObject *)window;
4517 GdkWindowImplIface *impl_iface;
4519 if (private->paint_stack)
4520 gdk_window_clear_backing_region (window, region);
4523 if (private->redirect)
4524 gdk_window_clear_backing_region_redirect (window, region);
4526 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
4528 if (impl_iface->clear_region && clears_as_native (private))
4531 copy = gdk_region_copy (region);
4532 gdk_region_intersect (copy,
4533 private->clip_region_with_children);
4536 /* Drawing directly to the window, flush anything outstanding to
4537 guarantee ordering. */
4538 gdk_window_flush (window);
4539 impl_iface->clear_region (window, copy, send_expose);
4541 gdk_region_destroy (copy);
4545 gdk_window_clear_backing_region_direct (window, region);
4547 gdk_window_invalidate_region (window, region, FALSE);
4553 gdk_window_clear_area_internal (GdkWindow *window,
4558 gboolean send_expose)
4563 g_return_if_fail (GDK_IS_WINDOW (window));
4565 if (GDK_WINDOW_DESTROYED (window))
4568 /* Terminate early to avoid weird interpretation of
4569 zero width/height by XClearArea */
4570 if (width == 0 || height == 0)
4576 rect.height = height;
4578 region = gdk_region_rectangle (&rect);
4579 gdk_window_clear_region_internal (window,
4582 gdk_region_destroy (region);
4587 * gdk_window_clear_area:
4588 * @window: a #GdkWindow
4589 * @x: x coordinate of rectangle to clear
4590 * @y: y coordinate of rectangle to clear
4591 * @width: width of rectangle to clear
4592 * @height: height of rectangle to clear
4594 * Clears an area of @window to the background color or background pixmap.
4598 gdk_window_clear_area (GdkWindow *window,
4604 gdk_window_clear_area_internal (window,
4611 * gdk_window_clear_area_e:
4612 * @window: a #GdkWindow
4613 * @x: x coordinate of rectangle to clear
4614 * @y: y coordinate of rectangle to clear
4615 * @width: width of rectangle to clear
4616 * @height: height of rectangle to clear
4618 * Like gdk_window_clear_area(), but also generates an expose event for
4621 * This function has a stupid name because it dates back to the mists
4622 * time, pre-GDK-1.0.
4626 gdk_window_clear_area_e (GdkWindow *window,
4632 gdk_window_clear_area_internal (window,
4639 gdk_window_draw_image (GdkDrawable *drawable,
4649 if (GDK_WINDOW_DESTROYED (drawable))
4653 gdk_draw_image (impl, gc, image, xsrc, ysrc,
4654 xdest - x_offset, ydest - y_offset,
4660 gdk_window_draw_pixbuf (GdkDrawable *drawable,
4669 GdkRgbDither dither,
4673 GdkWindowObject *private = (GdkWindowObject *)drawable;
4674 GdkDrawableClass *klass;
4676 if (GDK_WINDOW_DESTROYED (drawable))
4679 /* If no gc => no user clipping, but we need clipping
4680 for window emulation, so use a scratch gc */
4682 gc = _gdk_drawable_get_scratch_gc (drawable, FALSE);
4686 klass = GDK_DRAWABLE_GET_CLASS (impl);
4688 if (private->paint_stack)
4689 klass->draw_pixbuf (impl, gc, pixbuf, src_x, src_y,
4690 dest_x - x_offset, dest_y - y_offset,
4692 dither, x_dither - x_offset, y_dither - y_offset);
4694 klass->draw_pixbuf (impl, gc, pixbuf, src_x, src_y,
4695 dest_x - x_offset, dest_y - y_offset,
4697 dither, x_dither, y_dither);
4702 gdk_window_draw_trapezoids (GdkDrawable *drawable,
4704 GdkTrapezoid *trapezoids,
4707 GdkTrapezoid *new_trapezoids = NULL;
4709 if (GDK_WINDOW_DESTROYED (drawable))
4714 if (x_offset != 0 || y_offset != 0)
4718 new_trapezoids = g_new (GdkTrapezoid, n_trapezoids);
4719 for (i=0; i < n_trapezoids; i++)
4721 new_trapezoids[i].y1 = trapezoids[i].y1 - y_offset;
4722 new_trapezoids[i].x11 = trapezoids[i].x11 - x_offset;
4723 new_trapezoids[i].x21 = trapezoids[i].x21 - x_offset;
4724 new_trapezoids[i].y2 = trapezoids[i].y2 - y_offset;
4725 new_trapezoids[i].x12 = trapezoids[i].x12 - x_offset;
4726 new_trapezoids[i].x22 = trapezoids[i].x22 - x_offset;
4729 trapezoids = new_trapezoids;
4732 gdk_draw_trapezoids (impl, gc, trapezoids, n_trapezoids);
4734 g_free (new_trapezoids);
4740 gdk_window_real_get_size (GdkDrawable *drawable,
4744 GdkWindowObject *private = (GdkWindowObject *)drawable;
4747 *width = private->width;
4749 *height = private->height;
4753 gdk_window_real_get_visual (GdkDrawable *drawable)
4755 GdkColormap *colormap;
4757 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4759 colormap = gdk_drawable_get_colormap (drawable);
4760 return colormap ? gdk_colormap_get_visual (colormap) : NULL;
4764 gdk_window_real_get_depth (GdkDrawable *drawable)
4766 g_return_val_if_fail (GDK_IS_WINDOW (drawable), 0);
4768 return ((GdkWindowObject *)GDK_WINDOW (drawable))->depth;
4772 gdk_window_real_get_screen (GdkDrawable *drawable)
4774 return gdk_drawable_get_screen (GDK_WINDOW_OBJECT (drawable)->impl);
4778 gdk_window_real_set_colormap (GdkDrawable *drawable,
4781 GdkWindowObject *private;
4783 g_return_if_fail (GDK_IS_WINDOW (drawable));
4785 if (GDK_WINDOW_DESTROYED (drawable))
4788 private = (GdkWindowObject *)drawable;
4790 /* different colormap than parent, requires native window */
4791 if (!private->input_only &&
4792 cmap != gdk_drawable_get_colormap ((GdkDrawable *)(private->parent)))
4793 gdk_window_ensure_native ((GdkWindow *)drawable);
4795 gdk_drawable_set_colormap (private->impl, cmap);
4799 gdk_window_real_get_colormap (GdkDrawable *drawable)
4801 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4803 if (GDK_WINDOW_DESTROYED (drawable))
4806 return gdk_drawable_get_colormap (((GdkWindowObject*)drawable)->impl);
4810 gdk_window_copy_to_image (GdkDrawable *drawable,
4819 GdkWindowObject *private = (GdkWindowObject *) drawable;
4820 gint x_offset, y_offset;
4822 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4824 if (GDK_WINDOW_DESTROYED (drawable))
4827 /* If we're here, a composite image was not necessary, so
4828 * we can ignore the paint stack.
4831 /* TODO: Is this right? */
4835 return gdk_drawable_copy_to_image (private->impl,
4844 gdk_window_cairo_surface_destroy (void *data)
4846 GdkWindowObject *private = (GdkWindowObject*) data;
4848 private->cairo_surface = NULL;
4851 static cairo_surface_t *
4852 gdk_window_create_cairo_surface (GdkDrawable *drawable,
4856 return _gdk_windowing_create_cairo_surface (GDK_WINDOW_OBJECT(drawable)->impl,
4861 static cairo_surface_t *
4862 gdk_window_ref_cairo_surface (GdkDrawable *drawable)
4864 GdkWindowObject *private = (GdkWindowObject*) drawable;
4865 cairo_surface_t *surface;
4867 if (private->paint_stack)
4869 GdkWindowPaint *paint = private->paint_stack->data;
4871 surface = paint->surface;
4872 cairo_surface_reference (surface);
4877 /* This will be drawing directly to the window, so flush implicit paint */
4878 gdk_window_flush ((GdkWindow *)drawable);
4880 if (!private->cairo_surface)
4883 GdkDrawable *source;
4885 /* It would be nice if we had some cairo support here so we
4886 could set the clip rect on the cairo surface */
4887 width = private->abs_x + private->width;
4888 height = private->abs_y + private->height;
4890 source = _gdk_drawable_get_source_drawable (drawable);
4892 /* TODO: Avoid the typecheck crap by adding virtual call */
4893 private->cairo_surface = _gdk_drawable_create_cairo_surface (source, width, height);
4895 if (private->cairo_surface)
4897 cairo_surface_set_device_offset (private->cairo_surface,
4901 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
4902 drawable, gdk_window_cairo_surface_destroy);
4906 cairo_surface_reference (private->cairo_surface);
4908 surface = private->cairo_surface;
4915 gdk_window_set_cairo_clip (GdkDrawable *drawable,
4918 GdkWindowObject *private = (GdkWindowObject*) drawable;
4920 if (!private->paint_stack)
4922 cairo_reset_clip (cr);
4925 cairo_identity_matrix (cr);
4927 cairo_new_path (cr);
4928 gdk_cairo_region (cr, private->clip_region_with_children);
4935 GdkWindowPaint *paint = private->paint_stack->data;
4937 /* Only needs to clip to region if piggybacking
4938 on an implicit paint pixmap */
4939 cairo_reset_clip (cr);
4940 if (paint->uses_implicit)
4943 cairo_identity_matrix (cr);
4945 cairo_new_path (cr);
4946 gdk_cairo_region (cr, paint->region);
4954 /* Code for dirty-region queueing
4956 static GSList *update_windows = NULL;
4957 static guint update_idle = 0;
4958 static gboolean debug_updates = FALSE;
4960 static inline gboolean
4961 gdk_window_is_ancestor (GdkWindow *window,
4962 GdkWindow *ancestor)
4966 GdkWindow *parent = (GdkWindow*) ((GdkWindowObject*) window)->parent;
4968 if (parent == ancestor)
4978 gdk_window_add_update_window (GdkWindow *window)
4981 GSList *prev = NULL;
4982 gboolean has_ancestor_in_list = FALSE;
4984 for (tmp = update_windows; tmp; tmp = tmp->next)
4986 GdkWindowObject *parent = GDK_WINDOW_OBJECT (window)->parent;
4988 /* check if tmp is an ancestor of "window"; if it is, set a
4989 * flag indicating that all following windows are either
4990 * children of "window" or from a differen hierarchy
4992 if (!has_ancestor_in_list && gdk_window_is_ancestor (window, tmp->data))
4993 has_ancestor_in_list = TRUE;
4995 /* insert in reverse stacking order when adding around siblings,
4996 * so processing updates properly paints over lower stacked windows
4998 if (parent == GDK_WINDOW_OBJECT (tmp->data)->parent)
5000 gint index = g_list_index (parent->children, window);
5001 for (; tmp && parent == GDK_WINDOW_OBJECT (tmp->data)->parent; tmp = tmp->next)
5003 gint sibling_index = g_list_index (parent->children, tmp->data);
5004 if (index > sibling_index)
5008 /* here, tmp got advanced past all lower stacked siblings */
5009 tmp = g_slist_prepend (tmp, window);
5013 update_windows = tmp;
5017 /* if "window" has an ancestor in the list and tmp is one of
5018 * "window's" children, insert "window" before tmp
5020 if (has_ancestor_in_list && gdk_window_is_ancestor (tmp->data, window))
5022 tmp = g_slist_prepend (tmp, window);
5027 update_windows = tmp;
5031 /* if we're at the end of the list and had an ancestor it it,
5032 * append to the list
5034 if (! tmp->next && has_ancestor_in_list)
5036 tmp = g_slist_append (tmp, window);
5043 /* if all above checks failed ("window" is from a different
5044 * hierarchy than what is already in the list) or the list is
5047 update_windows = g_slist_prepend (update_windows, window);
5051 gdk_window_remove_update_window (GdkWindow *window)
5053 update_windows = g_slist_remove (update_windows, window);
5057 gdk_window_update_idle (gpointer data)
5059 gdk_window_process_all_updates ();
5065 gdk_window_is_toplevel_frozen (GdkWindow *window)
5067 GdkWindowObject *toplevel;
5069 toplevel = (GdkWindowObject *)gdk_window_get_toplevel (window);
5071 return toplevel->update_and_descendants_freeze_count > 0;
5075 gdk_window_schedule_update (GdkWindow *window)
5078 (GDK_WINDOW_OBJECT (window)->update_freeze_count ||
5079 gdk_window_is_toplevel_frozen (window)))
5084 gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
5085 gdk_window_update_idle,
5090 _gdk_window_process_updates_recurse (GdkWindow *window,
5091 GdkRegion *expose_region)
5093 GdkWindowObject *private = (GdkWindowObject *)window;
5094 GdkWindowObject *child;
5095 GdkRegion *child_region;
5097 GList *l, *children;
5099 if (gdk_region_empty (expose_region))
5102 /* Make this reentrancy safe for expose handlers freeing windows */
5103 children = g_list_copy (private->children);
5104 g_list_foreach (children, (GFunc)g_object_ref, NULL);
5106 /* Iterate over children, starting at topmost */
5107 for (l = children; l != NULL; l = l->next)
5111 if (child->destroyed || !GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
5114 /* Ignore offscreen children, as they don't draw in their parent and
5115 * don't take part in the clipping */
5116 if (gdk_window_is_offscreen (child))
5121 r.width = child->width;
5122 r.height = child->height;
5124 child_region = gdk_region_rectangle (&r);
5127 /* Adjust shape region to parent window coords */
5128 gdk_region_offset (child->shape, child->x, child->y);
5129 gdk_region_intersect (child_region, child->shape);
5130 gdk_region_offset (child->shape, -child->x, -child->y);
5133 if (child->impl == private->impl)
5135 /* Client side child, expose */
5136 gdk_region_intersect (child_region, expose_region);
5137 gdk_region_subtract (expose_region, child_region);
5138 gdk_region_offset (child_region, -child->x, -child->y);
5139 _gdk_window_process_updates_recurse ((GdkWindow *)child, child_region);
5143 /* Native child, just remove area from expose region */
5144 gdk_region_subtract (expose_region, child_region);
5146 gdk_region_destroy (child_region);
5149 g_list_foreach (children, (GFunc)g_object_unref, NULL);
5150 g_list_free (children);
5152 if (!gdk_region_empty (expose_region) &&
5153 !private->destroyed)
5155 if (private->event_mask & GDK_EXPOSURE_MASK)
5159 event.expose.type = GDK_EXPOSE;
5160 event.expose.window = g_object_ref (window);
5161 event.expose.send_event = FALSE;
5162 event.expose.count = 0;
5163 event.expose.region = expose_region;
5164 gdk_region_get_clipbox (expose_region, &event.expose.area);
5166 (*_gdk_event_func) (&event, _gdk_event_data);
5168 g_object_unref (window);
5170 else if (private->bg_pixmap != GDK_NO_BG &&
5171 private->window_type != GDK_WINDOW_FOREIGN)
5173 /* No exposure mask set, so nothing will be drawn, the
5174 * app relies on the background being what it specified
5175 * for the window. So, we need to clear this manually.
5177 * For foreign windows if expose is not set that generally
5178 * means some other client paints them, so don't clear
5181 * We use begin/end_paint around the clear so that we can
5182 * piggyback on the implicit paint */
5184 gdk_window_begin_paint_region (window, expose_region);
5185 gdk_window_clear_region_internal (window, expose_region, FALSE);
5186 gdk_window_end_paint (window);
5191 /* Process and remove any invalid area on the native window by creating
5192 * expose events for the window and all non-native descendants.
5193 * Also processes any outstanding moves on the window before doing
5194 * any drawing. Note that its possible to have outstanding moves without
5195 * any invalid area as we use the update idle mechanism to coalesce
5196 * multiple moves as well as multiple invalidations.
5199 gdk_window_process_updates_internal (GdkWindow *window)
5201 GdkWindowObject *private = (GdkWindowObject *)window;
5202 GdkWindowImplIface *impl_iface;
5203 gboolean save_region = FALSE;
5204 GdkRectangle clip_box;
5206 /* Ensure the window lives while updating it */
5207 g_object_ref (window);
5209 /* If an update got queued during update processing, we can get a
5210 * window in the update queue that has an empty update_area.
5213 if (private->update_area)
5215 GdkRegion *update_area = private->update_area;
5216 private->update_area = NULL;
5218 if (_gdk_event_func && gdk_window_is_viewable (window))
5220 GdkRegion *expose_region;
5221 gboolean end_implicit;
5223 /* Clip to part visible in toplevel */
5224 gdk_region_intersect (update_area, private->clip_region);
5228 /* Make sure we see the red invalid area before redrawing. */
5229 gdk_display_sync (gdk_drawable_get_display (window));
5233 /* At this point we will be completely redrawing all of update_area.
5234 * If we have any outstanding moves that end up moving stuff inside
5235 * this area we don't actually need to move that as that part would
5236 * be overdrawn by the expose anyway. So, in order to copy less data
5237 * we remove these areas from the outstanding moves.
5239 if (private->outstanding_moves)
5241 GdkWindowRegionMove *move;
5245 remove = gdk_region_copy (update_area);
5246 /* We iterate backwards, starting from the state that would be
5247 if we had applied all the moves. */
5248 for (l = g_list_last (private->outstanding_moves); l != NULL; l = prev)
5253 /* Don't need this area */
5254 gdk_region_subtract (move->dest_region, remove);
5256 /* However if any of the destination we do need has a source
5257 in the updated region we do need that as a destination for
5258 the earlier moves */
5259 gdk_region_offset (move->dest_region, -move->dx, -move->dy);
5260 gdk_region_subtract (remove, move->dest_region);
5262 if (gdk_region_empty (move->dest_region))
5264 gdk_window_region_move_free (move);
5265 private->outstanding_moves =
5266 g_list_delete_link (private->outstanding_moves, l);
5268 else /* move back */
5269 gdk_region_offset (move->dest_region, move->dx, move->dy);
5271 gdk_region_destroy (remove);
5274 /* By now we a set of window moves that should be applied, and then
5275 * an update region that should be repainted. A trivial implementation
5276 * would just do that in order, however in order to get nicer drawing
5277 * we do some tricks:
5279 * First of all, each subwindow expose may be double buffered by
5280 * itself (depending on widget setting) via
5281 * gdk_window_begin/end_paint(). But we also do an "implicit" paint,
5282 * creating a single pixmap the size of the invalid area on the
5283 * native window which all the individual normal paints will draw
5284 * into. This way in the normal case there will be only one pixmap
5285 * allocated and only once pixmap draw done for all the windows
5286 * in this native window.
5287 * There are a couple of reasons this may fail, for instance, some
5288 * backends (like quartz) do its own double buffering, so we disable
5289 * gdk double buffering there. Secondly, some subwindow could be
5290 * non-double buffered and draw directly to the window outside a
5291 * begin/end_paint pair. That will be lead to a gdk_window_flush
5292 * which immediately executes all outstanding moves and paints+removes
5293 * the implicit paint (further paints will allocate their own pixmap).
5295 * Secondly, in the case of implicit double buffering we expose all
5296 * the child windows into the implicit pixmap before we execute
5297 * the outstanding moves. This way we minimize the time between
5298 * doing the moves and rendering the new update area, thus minimizing
5299 * flashing. Of course, if any subwindow is non-double buffered we
5300 * well flush earlier than that.
5302 * Thirdly, after having done the outstanding moves we queue an
5303 * "antiexpose" on the area that will be drawn by the expose, which
5304 * means that any invalid region on the native window side before
5305 * the first expose drawing operation will be discarded, as it
5306 * has by then been overdrawn with valid data. This means we can
5307 * avoid doing the unnecessary repaint any outstanding expose events.
5310 gdk_region_get_clipbox (update_area, &clip_box);
5311 end_implicit = gdk_window_begin_implicit_paint (window, &clip_box);
5312 expose_region = gdk_region_copy (update_area);
5315 /* Rendering is not double buffered by gdk, do outstanding
5316 * moves and queue antiexposure immediately. No need to do
5318 gdk_window_flush_outstanding_moves (window);
5319 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
5320 save_region = impl_iface->queue_antiexpose (window, update_area);
5323 /* Render the invalid areas to the implicit paint, by sending exposes.
5324 * May flush if non-double buffered widget draw. */
5325 _gdk_windowing_window_process_updates_recurse (window, expose_region);
5329 /* Do moves right before exposes are rendered to the window */
5330 gdk_window_flush_outstanding_moves (window);
5332 /* By this time we know that any outstanding expose for this
5333 * area is invalid and we can avoid it, so queue an antiexpose.
5334 * However, it may be that due to an non-double buffered expose
5335 * we have already started drawing to the window, so it would
5336 * be to late to anti-expose now. Since this is merely an
5337 * optimization we just avoid doing it at all in that case.
5339 if (private->implicit_paint != NULL &&
5340 !private->implicit_paint->flushed)
5342 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
5343 save_region = impl_iface->queue_antiexpose (window, update_area);
5346 gdk_window_end_implicit_paint (window);
5348 gdk_region_destroy (expose_region);
5351 gdk_region_destroy (update_area);
5354 if (private->outstanding_moves)
5356 /* Flush any outstanding moves, may happen if we moved a window but got
5357 no actual invalid area */
5358 gdk_window_flush_outstanding_moves (window);
5361 g_object_unref (window);
5365 flush_all_displays (void)
5367 GSList *displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
5370 for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
5371 gdk_display_flush (tmp_list->data);
5373 g_slist_free (displays);
5376 /* Currently it is not possible to override
5377 * gdk_window_process_all_updates in the same manner as
5378 * gdk_window_process_updates and gdk_window_invalidate_maybe_recurse
5379 * by implementing the GdkPaintable interface. If in the future a
5380 * backend would need this, the right solution would be to add a
5381 * method to GdkDisplay that can be optionally
5382 * NULL. gdk_window_process_all_updates can then walk the list of open
5383 * displays and call the mehod.
5387 * gdk_window_process_all_updates:
5389 * Calls gdk_window_process_updates() for all windows (see #GdkWindow)
5390 * in the application.
5394 gdk_window_process_all_updates (void)
5396 GSList *old_update_windows = update_windows;
5397 GSList *tmp_list = update_windows;
5398 static gboolean in_process_all_updates = FALSE;
5399 static gboolean got_recursive_update = FALSE;
5401 if (in_process_all_updates)
5403 /* We can't do this now since that would recurse, so
5404 delay it until after the recursion is done. */
5405 got_recursive_update = TRUE;
5410 in_process_all_updates = TRUE;
5411 got_recursive_update = FALSE;
5414 g_source_remove (update_idle);
5416 update_windows = NULL;
5419 _gdk_windowing_before_process_all_updates ();
5421 g_slist_foreach (old_update_windows, (GFunc)g_object_ref, NULL);
5425 GdkWindowObject *private = (GdkWindowObject *)tmp_list->data;
5427 if (!GDK_WINDOW_DESTROYED (tmp_list->data))
5429 if (private->update_freeze_count ||
5430 gdk_window_is_toplevel_frozen (tmp_list->data))
5431 gdk_window_add_update_window ((GdkWindow *) private);
5433 gdk_window_process_updates_internal (tmp_list->data);
5436 g_object_unref (tmp_list->data);
5437 tmp_list = tmp_list->next;
5440 g_slist_free (old_update_windows);
5442 flush_all_displays ();
5444 _gdk_windowing_after_process_all_updates ();
5446 in_process_all_updates = FALSE;
5448 /* If we ignored a recursive call, schedule a
5449 redraw now so that it eventually happens,
5450 otherwise we could miss an update if nothing
5451 else schedules an update. */
5452 if (got_recursive_update && !update_idle)
5454 gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
5455 gdk_window_update_idle,
5460 * gdk_window_process_updates:
5461 * @window: a #GdkWindow
5462 * @update_children: whether to also process updates for child windows
5464 * Sends one or more expose events to @window. The areas in each
5465 * expose event will cover the entire update area for the window (see
5466 * gdk_window_invalidate_region() for details). Normally GDK calls
5467 * gdk_window_process_all_updates() on your behalf, so there's no
5468 * need to call this function unless you want to force expose events
5469 * to be delivered immediately and synchronously (vs. the usual
5470 * case, where GDK delivers them in an idle handler). Occasionally
5471 * this is useful to produce nicer scrolling behavior, for example.
5475 gdk_window_process_updates (GdkWindow *window,
5476 gboolean update_children)
5478 GdkWindowObject *private = (GdkWindowObject *)window;
5479 GdkWindowObject *impl_window;
5481 g_return_if_fail (GDK_IS_WINDOW (window));
5483 if (GDK_WINDOW_DESTROYED (window))
5486 /* Make sure the window lives during the expose callouts */
5487 g_object_ref (window);
5489 impl_window = gdk_window_get_impl_window (private);
5490 if ((impl_window->update_area ||
5491 impl_window->outstanding_moves) &&
5492 !impl_window->update_freeze_count &&
5493 !gdk_window_is_toplevel_frozen (window) &&
5495 /* Don't recurse into process_updates_internal, we'll
5496 * do the update later when idle instead. */
5497 impl_window->implicit_paint == NULL)
5499 gdk_window_process_updates_internal ((GdkWindow *)impl_window);
5500 gdk_window_remove_update_window ((GdkWindow *)impl_window);
5503 if (update_children)
5505 /* process updates in reverse stacking order so composition or
5506 * painting over achieves the desired effect for offscreen windows
5508 GList *node, *children;
5510 children = g_list_copy (private->children);
5511 g_list_foreach (children, (GFunc)g_object_ref, NULL);
5513 for (node = g_list_last (children); node; node = node->prev)
5515 gdk_window_process_updates (node->data, TRUE);
5516 g_object_unref (node->data);
5519 g_list_free (children);
5522 g_object_unref (window);
5526 gdk_window_invalidate_rect_full (GdkWindow *window,
5527 const GdkRectangle *rect,
5528 gboolean invalidate_children,
5531 GdkRectangle window_rect;
5533 GdkWindowObject *private = (GdkWindowObject *)window;
5535 g_return_if_fail (GDK_IS_WINDOW (window));
5537 if (GDK_WINDOW_DESTROYED (window))
5540 if (private->input_only || !private->viewable)
5547 gdk_drawable_get_size (GDK_DRAWABLE (window),
5549 &window_rect.height);
5550 rect = &window_rect;
5553 region = gdk_region_rectangle (rect);
5554 gdk_window_invalidate_region_full (window, region, invalidate_children, clear_bg);
5555 gdk_region_destroy (region);
5559 * gdk_window_invalidate_rect:
5560 * @window: a #GdkWindow
5561 * @rect: rectangle to invalidate or %NULL to invalidate the whole
5563 * @invalidate_children: whether to also invalidate child windows
5565 * A convenience wrapper around gdk_window_invalidate_region() which
5566 * invalidates a rectangular region. See
5567 * gdk_window_invalidate_region() for details.
5570 gdk_window_invalidate_rect (GdkWindow *window,
5571 const GdkRectangle *rect,
5572 gboolean invalidate_children)
5574 gdk_window_invalidate_rect_full (window, rect, invalidate_children, CLEAR_BG_NONE);
5578 draw_ugly_color (GdkWindow *window,
5579 const GdkRegion *region)
5581 /* Draw ugly color all over the newly-invalid region */
5582 GdkColor ugly_color = { 0, 50000, 10000, 10000 };
5584 GdkRectangle clipbox;
5586 ugly_gc = gdk_gc_new (window);
5587 gdk_gc_set_rgb_fg_color (ugly_gc, &ugly_color);
5588 gdk_gc_set_clip_region (ugly_gc, region);
5590 gdk_region_get_clipbox (region, &clipbox);
5592 gdk_draw_rectangle (window,
5595 clipbox.x, clipbox.y,
5596 clipbox.width, clipbox.height);
5598 g_object_unref (ugly_gc);
5602 impl_window_add_update_area (GdkWindowObject *impl_window,
5605 if (impl_window->update_area)
5606 gdk_region_union (impl_window->update_area, region);
5609 gdk_window_add_update_window ((GdkWindow *)impl_window);
5610 impl_window->update_area = gdk_region_copy (region);
5611 gdk_window_schedule_update ((GdkWindow *)impl_window);
5615 /* clear_bg controls if the region will be cleared to
5616 * the background color/pixmap if the exposure mask is not
5617 * set for the window, whereas this might not otherwise be
5618 * done (unless necessary to emulate background settings).
5619 * Set this to CLEAR_BG_WINCLEARED or CLEAR_BG_ALL if you
5620 * need to clear the background, such as when exposing the area beneath a
5621 * hidden or moved window, but not when an app requests repaint or when the
5622 * windowing system exposes a newly visible area (because then the windowing
5623 * system has already cleared the area).
5626 gdk_window_invalidate_maybe_recurse_full (GdkWindow *window,
5627 const GdkRegion *region,
5629 gboolean (*child_func) (GdkWindow *,
5633 GdkWindowObject *private = (GdkWindowObject *)window;
5634 GdkWindowObject *impl_window;
5635 GdkRegion *visible_region;
5638 g_return_if_fail (GDK_IS_WINDOW (window));
5640 if (GDK_WINDOW_DESTROYED (window))
5643 if (private->input_only ||
5644 !private->viewable ||
5645 gdk_region_empty (region) ||
5646 private->window_type == GDK_WINDOW_ROOT)
5649 visible_region = gdk_drawable_get_visible_region (window);
5650 gdk_region_intersect (visible_region, region);
5652 tmp_list = private->children;
5655 GdkWindowObject *child = tmp_list->data;
5657 if (!child->input_only)
5659 GdkRegion *child_region;
5660 GdkRectangle child_rect;
5662 child_rect.x = child->x;
5663 child_rect.y = child->y;
5664 child_rect.width = child->width;
5665 child_rect.height = child->height;
5666 child_region = gdk_region_rectangle (&child_rect);
5668 /* remove child area from the invalid area of the parent */
5669 if (GDK_WINDOW_IS_MAPPED (child) && !child->shaped &&
5670 !child->composited &&
5671 !gdk_window_is_offscreen (child))
5672 gdk_region_subtract (visible_region, child_region);
5674 if (child_func && (*child_func) ((GdkWindow *)child, user_data))
5676 GdkRegion *tmp = gdk_region_copy (region);
5678 gdk_region_offset (tmp, - child_rect.x, - child_rect.y);
5679 gdk_region_offset (child_region, - child_rect.x, - child_rect.y);
5680 gdk_region_intersect (child_region, tmp);
5682 gdk_window_invalidate_maybe_recurse_full ((GdkWindow *)child,
5683 child_region, clear_bg, child_func, user_data);
5685 gdk_region_destroy (tmp);
5688 gdk_region_destroy (child_region);
5691 tmp_list = tmp_list->next;
5694 impl_window = gdk_window_get_impl_window (private);
5696 if (!gdk_region_empty (visible_region) ||
5697 /* Even if we're not exposing anything, make sure we process
5698 idles for windows with outstanding moves */
5699 (impl_window->outstanding_moves != NULL &&
5700 impl_window->update_area == NULL))
5703 draw_ugly_color (window, region);
5705 /* Convert to impl coords */
5706 gdk_region_offset (visible_region, private->abs_x, private->abs_y);
5708 /* Only invalidate area if app requested expose events or if
5709 we need to clear the area (by request or to emulate background
5710 clearing for non-native windows or native windows with no support
5711 for window backgrounds */
5712 if (private->event_mask & GDK_EXPOSURE_MASK ||
5713 clear_bg == CLEAR_BG_ALL ||
5714 (clear_bg == CLEAR_BG_WINCLEARED &&
5715 (!clears_as_native (private) ||
5716 !GDK_WINDOW_IMPL_GET_IFACE (private->impl)->supports_native_bg)))
5717 impl_window_add_update_area (impl_window, visible_region);
5720 gdk_region_destroy (visible_region);
5724 * gdk_window_invalidate_maybe_recurse:
5725 * @window: a #GdkWindow
5726 * @region: a #GdkRegion
5727 * @child_func: function to use to decide if to recurse to a child,
5728 * %NULL means never recurse.
5729 * @user_data: data passed to @child_func
5731 * Adds @region to the update area for @window. The update area is the
5732 * region that needs to be redrawn, or "dirty region." The call
5733 * gdk_window_process_updates() sends one or more expose events to the
5734 * window, which together cover the entire update area. An
5735 * application would normally redraw the contents of @window in
5736 * response to those expose events.
5738 * GDK will call gdk_window_process_all_updates() on your behalf
5739 * whenever your program returns to the main loop and becomes idle, so
5740 * normally there's no need to do that manually, you just need to
5741 * invalidate regions that you know should be redrawn.
5743 * The @child_func parameter controls whether the region of
5744 * each child window that intersects @region will also be invalidated.
5745 * Only children for which @child_func returns TRUE will have the area
5749 gdk_window_invalidate_maybe_recurse (GdkWindow *window,
5750 const GdkRegion *region,
5751 gboolean (*child_func) (GdkWindow *,
5755 gdk_window_invalidate_maybe_recurse_full (window, region, CLEAR_BG_NONE,
5756 child_func, user_data);
5760 true_predicate (GdkWindow *window,
5767 gdk_window_invalidate_region_full (GdkWindow *window,
5768 const GdkRegion *region,
5769 gboolean invalidate_children,
5772 gdk_window_invalidate_maybe_recurse_full (window, region, clear_bg,
5773 invalidate_children ?
5774 true_predicate : (gboolean (*) (GdkWindow *, gpointer))NULL,
5779 * gdk_window_invalidate_region:
5780 * @window: a #GdkWindow
5781 * @region: a #GdkRegion
5782 * @invalidate_children: %TRUE to also invalidate child windows
5784 * Adds @region to the update area for @window. The update area is the
5785 * region that needs to be redrawn, or "dirty region." The call
5786 * gdk_window_process_updates() sends one or more expose events to the
5787 * window, which together cover the entire update area. An
5788 * application would normally redraw the contents of @window in
5789 * response to those expose events.
5791 * GDK will call gdk_window_process_all_updates() on your behalf
5792 * whenever your program returns to the main loop and becomes idle, so
5793 * normally there's no need to do that manually, you just need to
5794 * invalidate regions that you know should be redrawn.
5796 * The @invalidate_children parameter controls whether the region of
5797 * each child window that intersects @region will also be invalidated.
5798 * If %FALSE, then the update area for child windows will remain
5799 * unaffected. See gdk_window_invalidate_maybe_recurse if you need
5800 * fine grained control over which children are invalidated.
5803 gdk_window_invalidate_region (GdkWindow *window,
5804 const GdkRegion *region,
5805 gboolean invalidate_children)
5807 gdk_window_invalidate_maybe_recurse (window, region,
5808 invalidate_children ?
5809 true_predicate : (gboolean (*) (GdkWindow *, gpointer))NULL,
5814 * _gdk_window_invalidate_for_expose:
5815 * @window: a #GdkWindow
5816 * @region: a #GdkRegion
5818 * Adds @region to the update area for @window. The update area is the
5819 * region that needs to be redrawn, or "dirty region." The call
5820 * gdk_window_process_updates() sends one or more expose events to the
5821 * window, which together cover the entire update area. An
5822 * application would normally redraw the contents of @window in
5823 * response to those expose events.
5825 * GDK will call gdk_window_process_all_updates() on your behalf
5826 * whenever your program returns to the main loop and becomes idle, so
5827 * normally there's no need to do that manually, you just need to
5828 * invalidate regions that you know should be redrawn.
5830 * This version of invalidation is used when you recieve expose events
5831 * from the native window system. It exposes the native window, plus
5832 * any non-native child windows (but not native child windows, as those would
5833 * have gotten their own expose events).
5836 _gdk_window_invalidate_for_expose (GdkWindow *window,
5839 GdkWindowObject *private = (GdkWindowObject *) window;
5840 GdkWindowRegionMove *move;
5841 GdkRegion *move_region;
5844 /* Any invalidations comming from the windowing system will
5845 be in areas that may be moved by outstanding moves,
5846 so we need to modify the expose region correspondingly,
5847 otherwise we would expose in the wrong place, as the
5848 outstanding moves will be copied before we draw the
5850 for (l = private->outstanding_moves; l != NULL; l = l->next)
5854 /* covert to move source region */
5855 move_region = gdk_region_copy (move->dest_region);
5856 gdk_region_offset (move_region, -move->dx, -move->dy);
5858 /* Move area of region that intersects with move source
5859 by dx, dy of the move*/
5860 gdk_region_intersect (move_region, region);
5861 gdk_region_subtract (region, move_region);
5862 gdk_region_offset (move_region, move->dx, move->dy);
5863 gdk_region_union (region, move_region);
5865 gdk_region_destroy (move_region);
5868 gdk_window_invalidate_maybe_recurse_full (window, region, CLEAR_BG_WINCLEARED,
5869 (gboolean (*) (GdkWindow *, gpointer))gdk_window_has_no_impl,
5875 * gdk_window_get_update_area:
5876 * @window: a #GdkWindow
5878 * Transfers ownership of the update area from @window to the caller
5879 * of the function. That is, after calling this function, @window will
5880 * no longer have an invalid/dirty region; the update area is removed
5881 * from @window and handed to you. If a window has no update area,
5882 * gdk_window_get_update_area() returns %NULL. You are responsible for
5883 * calling gdk_region_destroy() on the returned region if it's non-%NULL.
5885 * Return value: the update area for @window
5888 gdk_window_get_update_area (GdkWindow *window)
5890 GdkWindowObject *private = (GdkWindowObject *)window;
5891 GdkWindowObject *impl_window;
5892 GdkRegion *tmp_region;
5894 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
5896 impl_window = gdk_window_get_impl_window (private);
5898 if (impl_window->update_area)
5900 tmp_region = gdk_region_copy (private->clip_region_with_children);
5901 /* Convert to impl coords */
5902 gdk_region_offset (tmp_region, private->abs_x, private->abs_y);
5903 gdk_region_intersect (tmp_region, impl_window->update_area);
5905 if (gdk_region_empty (tmp_region))
5907 gdk_region_destroy (tmp_region);
5912 gdk_region_subtract (impl_window->update_area, tmp_region);
5914 if (gdk_region_empty (impl_window->update_area) &&
5915 impl_window->outstanding_moves == NULL)
5917 gdk_region_destroy (impl_window->update_area);
5918 impl_window->update_area = NULL;
5920 gdk_window_remove_update_window ((GdkWindow *)impl_window);
5923 /* Convert from impl coords */
5924 gdk_region_offset (tmp_region, -private->abs_x, -private->abs_y);
5934 * _gdk_window_clear_update_area:
5935 * @window: a #GdkWindow.
5937 * Internal function to clear the update area for a window. This
5938 * is called when the window is hidden or destroyed.
5941 _gdk_window_clear_update_area (GdkWindow *window)
5943 GdkWindowObject *private = (GdkWindowObject *)window;
5945 g_return_if_fail (GDK_IS_WINDOW (window));
5947 if (private->update_area)
5949 gdk_window_remove_update_window (window);
5951 gdk_region_destroy (private->update_area);
5952 private->update_area = NULL;
5957 * gdk_window_freeze_updates:
5958 * @window: a #GdkWindow
5960 * Temporarily freezes a window such that it won't receive expose
5961 * events. The window will begin receiving expose events again when
5962 * gdk_window_thaw_updates() is called. If gdk_window_freeze_updates()
5963 * has been called more than once, gdk_window_thaw_updates() must be called
5964 * an equal number of times to begin processing exposes.
5967 gdk_window_freeze_updates (GdkWindow *window)
5969 GdkWindowObject *private = (GdkWindowObject *)window;
5970 GdkWindowObject *impl_window;
5972 g_return_if_fail (GDK_IS_WINDOW (window));
5974 impl_window = gdk_window_get_impl_window (private);
5975 impl_window->update_freeze_count++;
5979 * gdk_window_thaw_updates:
5980 * @window: a #GdkWindow
5982 * Thaws a window frozen with gdk_window_freeze_updates().
5985 gdk_window_thaw_updates (GdkWindow *window)
5987 GdkWindowObject *private = (GdkWindowObject *)window;
5988 GdkWindowObject *impl_window;
5990 g_return_if_fail (GDK_IS_WINDOW (window));
5992 impl_window = gdk_window_get_impl_window (private);
5994 g_return_if_fail (impl_window->update_freeze_count > 0);
5996 if (--impl_window->update_freeze_count == 0)
5997 gdk_window_schedule_update (GDK_WINDOW (impl_window));
6001 * gdk_window_freeze_toplevel_updates_libgtk_only:
6002 * @window: a #GdkWindow
6004 * Temporarily freezes a window and all its descendants such that it won't
6005 * receive expose events. The window will begin receiving expose events
6006 * again when gdk_window_thaw_toplevel_updates_libgtk_only() is called. If
6007 * gdk_window_freeze_toplevel_updates_libgtk_only()
6008 * has been called more than once,
6009 * gdk_window_thaw_toplevel_updates_libgtk_only() must be called
6010 * an equal number of times to begin processing exposes.
6012 * This function is not part of the GDK public API and is only
6016 gdk_window_freeze_toplevel_updates_libgtk_only (GdkWindow *window)
6018 GdkWindowObject *private = (GdkWindowObject *)window;
6020 g_return_if_fail (GDK_IS_WINDOW (window));
6021 g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
6023 private->update_and_descendants_freeze_count++;
6027 * gdk_window_thaw_toplevel_updates_libgtk_only:
6028 * @window: a #GdkWindow
6030 * Thaws a window frozen with
6031 * gdk_window_freeze_toplevel_updates_libgtk_only().
6033 * This function is not part of the GDK public API and is only
6037 gdk_window_thaw_toplevel_updates_libgtk_only (GdkWindow *window)
6039 GdkWindowObject *private = (GdkWindowObject *)window;
6041 g_return_if_fail (GDK_IS_WINDOW (window));
6042 g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
6043 g_return_if_fail (private->update_and_descendants_freeze_count > 0);
6045 private->update_and_descendants_freeze_count--;
6047 gdk_window_schedule_update (window);
6051 * gdk_window_set_debug_updates:
6052 * @setting: %TRUE to turn on update debugging
6054 * With update debugging enabled, calls to
6055 * gdk_window_invalidate_region() clear the invalidated region of the
6056 * screen to a noticeable color, and GDK pauses for a short time
6057 * before sending exposes to windows during
6058 * gdk_window_process_updates(). The net effect is that you can see
6059 * the invalid region for each window and watch redraws as they
6060 * occur. This allows you to diagnose inefficiencies in your application.
6062 * In essence, because the GDK rendering model prevents all flicker,
6063 * if you are redrawing the same region 400 times you may never
6064 * notice, aside from noticing a speed problem. Enabling update
6065 * debugging causes GTK to flicker slowly and noticeably, so you can
6066 * see exactly what's being redrawn when, in what order.
6068 * The --gtk-debug=updates command line option passed to GTK+ programs
6069 * enables this debug option at application startup time. That's
6070 * usually more useful than calling gdk_window_set_debug_updates()
6071 * yourself, though you might want to use this function to enable
6072 * updates sometime after application startup time.
6076 gdk_window_set_debug_updates (gboolean setting)
6078 debug_updates = setting;
6082 * gdk_window_constrain_size:
6083 * @geometry: a #GdkGeometry structure
6084 * @flags: a mask indicating what portions of @geometry are set
6085 * @width: desired width of window
6086 * @height: desired height of the window
6087 * @new_width: location to store resulting width
6088 * @new_height: location to store resulting height
6090 * Constrains a desired width and height according to a
6091 * set of geometry hints (such as minimum and maximum size).
6094 gdk_window_constrain_size (GdkGeometry *geometry,
6101 /* This routine is partially borrowed from fvwm.
6103 * Copyright 1993, Robert Nation
6104 * You may use this code for any purpose, as long as the original
6105 * copyright remains in the source code and all documentation
6107 * which in turn borrows parts of the algorithm from uwm
6110 gint min_height = 0;
6111 gint base_width = 0;
6112 gint base_height = 0;
6115 gint max_width = G_MAXINT;
6116 gint max_height = G_MAXINT;
6118 #define FLOOR(value, base) ( ((gint) ((value) / (base))) * (base) )
6120 if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
6122 base_width = geometry->base_width;
6123 base_height = geometry->base_height;
6124 min_width = geometry->min_width;
6125 min_height = geometry->min_height;
6127 else if (flags & GDK_HINT_BASE_SIZE)
6129 base_width = geometry->base_width;
6130 base_height = geometry->base_height;
6131 min_width = geometry->base_width;
6132 min_height = geometry->base_height;
6134 else if (flags & GDK_HINT_MIN_SIZE)
6136 base_width = geometry->min_width;
6137 base_height = geometry->min_height;
6138 min_width = geometry->min_width;
6139 min_height = geometry->min_height;
6142 if (flags & GDK_HINT_MAX_SIZE)
6144 max_width = geometry->max_width ;
6145 max_height = geometry->max_height;
6148 if (flags & GDK_HINT_RESIZE_INC)
6150 xinc = MAX (xinc, geometry->width_inc);
6151 yinc = MAX (yinc, geometry->height_inc);
6154 /* clamp width and height to min and max values
6156 width = CLAMP (width, min_width, max_width);
6157 height = CLAMP (height, min_height, max_height);
6159 /* shrink to base + N * inc
6161 width = base_width + FLOOR (width - base_width, xinc);
6162 height = base_height + FLOOR (height - base_height, yinc);
6164 /* constrain aspect ratio, according to:
6167 * min_aspect <= -------- <= max_aspect
6171 if (flags & GDK_HINT_ASPECT &&
6172 geometry->min_aspect > 0 &&
6173 geometry->max_aspect > 0)
6177 if (geometry->min_aspect * height > width)
6179 delta = FLOOR (height - width / geometry->min_aspect, yinc);
6180 if (height - delta >= min_height)
6184 delta = FLOOR (height * geometry->min_aspect - width, xinc);
6185 if (width + delta <= max_width)
6190 if (geometry->max_aspect * height < width)
6192 delta = FLOOR (width - height * geometry->max_aspect, xinc);
6193 if (width - delta >= min_width)
6197 delta = FLOOR (width / geometry->max_aspect - height, yinc);
6198 if (height + delta <= max_height)
6207 *new_height = height;
6211 * gdk_window_get_pointer:
6212 * @window: a #GdkWindow
6213 * @x: (out) (allow-none): return location for X coordinate of pointer or %NULL to not
6214 * return the X coordinate
6215 * @y: (out) (allow-none): return location for Y coordinate of pointer or %NULL to not
6216 * return the Y coordinate
6217 * @mask: (out) (allow-none): return location for modifier mask or %NULL to not return the
6220 * Obtains the current pointer position and modifier state.
6221 * The position is given in coordinates relative to the upper left
6222 * corner of @window.
6224 * Return value: (transfer none): the window containing the pointer (as with
6225 * gdk_window_at_pointer()), or %NULL if the window containing the
6226 * pointer isn't known to GDK
6229 gdk_window_get_pointer (GdkWindow *window,
6232 GdkModifierType *mask)
6234 GdkDisplay *display;
6236 GdkModifierType tmp_mask;
6239 g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
6243 display = gdk_drawable_get_display (window);
6247 GdkScreen *screen = gdk_screen_get_default ();
6249 display = gdk_screen_get_display (screen);
6250 window = gdk_screen_get_root_window (screen);
6252 GDK_NOTE (MULTIHEAD,
6253 g_message ("Passing NULL for window to gdk_window_get_pointer()\n"
6254 "is not multihead safe"));
6257 child = display->pointer_hooks->window_get_pointer (display, window, &tmp_x, &tmp_y, &tmp_mask);
6266 _gdk_display_enable_motion_hints (display);
6272 * gdk_window_at_pointer:
6273 * @win_x: (out) (allow-none): return location for origin of the window under the pointer
6274 * @win_y: (out) (allow-none): return location for origin of the window under the pointer
6276 * Obtains the window underneath the mouse pointer, returning the
6277 * location of that window in @win_x, @win_y. Returns %NULL if the
6278 * window under the mouse pointer is not known to GDK (if the window
6279 * belongs to another application and a #GdkWindow hasn't been created
6280 * for it with gdk_window_foreign_new())
6282 * NOTE: For multihead-aware widgets or applications use
6283 * gdk_display_get_window_at_pointer() instead.
6285 * Return value: (transfer none): window under the mouse pointer
6288 gdk_window_at_pointer (gint *win_x,
6291 return gdk_display_get_window_at_pointer (gdk_display_get_default (), win_x, win_y);
6295 * gdk_get_default_root_window:
6297 * Obtains the root window (parent all other windows are inside)
6298 * for the default display and screen.
6300 * Return value: the default root window
6303 gdk_get_default_root_window (void)
6305 return gdk_screen_get_root_window (gdk_screen_get_default ());
6309 * gdk_window_foreign_new:
6310 * @anid: a native window handle.
6312 * Wraps a native window for the default display in a #GdkWindow.
6313 * This may fail if the window has been destroyed.
6315 * For example in the X backend, a native window handle is an Xlib
6318 * Return value: the newly-created #GdkWindow wrapper for the
6319 * native window or %NULL if the window has been destroyed.
6322 gdk_window_foreign_new (GdkNativeWindow anid)
6324 return gdk_window_foreign_new_for_display (gdk_display_get_default (), anid);
6328 get_all_native_children (GdkWindowObject *private,
6331 GdkWindowObject *child;
6334 for (l = private->children; l != NULL; l = l->next)
6338 if (gdk_window_has_impl (child))
6339 *native = g_list_prepend (*native, child);
6341 get_all_native_children (child, native);
6347 gdk_window_raise_internal (GdkWindow *window)
6349 GdkWindowObject *private = (GdkWindowObject *)window;
6350 GdkWindowObject *parent = private->parent;
6351 GdkWindowObject *above;
6352 GList *native_children;
6354 GdkWindowImplIface *impl_iface;
6358 parent->children = g_list_remove (parent->children, window);
6359 parent->children = g_list_prepend (parent->children, window);
6362 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
6363 /* Just do native raise for toplevels */
6364 if (gdk_window_is_toplevel (private) ||
6365 /* The restack_under codepath should work correctly even if the parent
6366 is native, but it relies on the order of ->children to be correct,
6367 and some apps like SWT reorder the x windows without gdks knowledge,
6368 so we use raise directly in order to make these behave as before
6369 when using native windows */
6370 (gdk_window_has_impl (private) && gdk_window_has_impl (parent)))
6372 impl_iface->raise (window);
6374 else if (gdk_window_has_impl (private))
6376 above = find_native_sibling_above (parent, private);
6379 listhead.data = window;
6380 listhead.next = NULL;
6381 listhead.prev = NULL;
6382 impl_iface->restack_under ((GdkWindow *)above,
6386 impl_iface->raise (window);
6390 native_children = NULL;
6391 get_all_native_children (private, &native_children);
6392 if (native_children != NULL)
6394 above = find_native_sibling_above (parent, private);
6397 impl_iface->restack_under ((GdkWindow *)above,
6401 /* Right order, since native_children is bottom-topmost first */
6402 for (l = native_children; l != NULL; l = l->next)
6403 impl_iface->raise (l->data);
6406 g_list_free (native_children);
6412 /* Returns TRUE If the native window was mapped or unmapped */
6414 set_viewable (GdkWindowObject *w,
6417 GdkWindowObject *child;
6418 GdkWindowImplIface *impl_iface;
6421 if (w->viewable == val)
6427 recompute_visible_regions (w, FALSE, FALSE);
6429 for (l = w->children; l != NULL; l = l->next)
6433 if (GDK_WINDOW_IS_MAPPED (child) &&
6434 child->window_type != GDK_WINDOW_FOREIGN)
6435 set_viewable (child, val);
6438 if (!_gdk_native_windows &&
6439 gdk_window_has_impl (w) &&
6440 w->window_type != GDK_WINDOW_FOREIGN &&
6441 !gdk_window_is_toplevel (w))
6443 /* For most native windows we show/hide them not when they are
6444 * mapped/unmapped, because that may not produce the correct results.
6445 * For instance, if a native window have a non-native parent which is
6446 * hidden, but its native parent is viewable then showing the window
6447 * would make it viewable to X but its not viewable wrt the non-native
6448 * hierarchy. In order to handle this we track the gdk side viewability
6449 * and only map really viewable windows.
6451 * There are two exceptions though:
6453 * For foreign windows we don't want ever change the mapped state
6454 * except when explicitly done via gdk_window_show/hide, as this may
6455 * cause problems for client owning the foreign window when its window
6456 * is suddenly mapped or unmapped.
6458 * For toplevel windows embedded in a foreign window (e.g. a plug)
6459 * we sometimes synthesize a map of a window, but the native
6460 * window is really shown by the embedder, so we don't want to
6461 * do the show ourselves. We can't really tell this case from the normal
6462 * toplevel show as such toplevels are seen by gdk as parents of the
6463 * root window, so we make an exception for all toplevels.
6465 * Also, when in GDK_NATIVE_WINDOW mode we never need to play games
6466 * like this, so we just always show/hide directly.
6469 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (w->impl);
6471 impl_iface->show ((GdkWindow *)w, FALSE);
6473 impl_iface->hide ((GdkWindow *)w);
6481 /* Returns TRUE If the native window was mapped or unmapped */
6483 _gdk_window_update_viewable (GdkWindow *window)
6485 GdkWindowObject *priv = (GdkWindowObject *)window;
6488 if (priv->window_type == GDK_WINDOW_FOREIGN ||
6489 priv->window_type == GDK_WINDOW_ROOT)
6491 else if (gdk_window_is_toplevel (priv) ||
6492 priv->parent->viewable)
6493 viewable = GDK_WINDOW_IS_MAPPED (priv);
6497 return set_viewable (priv, viewable);
6501 gdk_window_show_internal (GdkWindow *window, gboolean raise)
6503 GdkWindowObject *private;
6504 GdkWindowImplIface *impl_iface;
6505 gboolean was_mapped, was_viewable;
6508 g_return_if_fail (GDK_IS_WINDOW (window));
6510 private = (GdkWindowObject *) window;
6511 if (private->destroyed)
6514 was_mapped = GDK_WINDOW_IS_MAPPED (window);
6515 was_viewable = private->viewable;
6518 /* Keep children in (reverse) stacking order */
6519 gdk_window_raise_internal (window);
6521 if (gdk_window_has_impl (private))
6524 gdk_synthesize_window_state (window,
6525 GDK_WINDOW_STATE_WITHDRAWN,
6533 did_show = _gdk_window_update_viewable (window);
6535 /* If it was already viewable the backend show op won't be called, call it
6536 again to ensure things happen right if the mapped tracking was not right
6537 for e.g. a foreign window.
6538 Dunno if this is strictly needed but its what happened pre-csw.
6539 Also show if not done by gdk_window_update_viewable. */
6540 if (gdk_window_has_impl (private) && (was_viewable || !did_show))
6542 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
6543 impl_iface->show ((GdkWindow *)private,
6544 !did_show ? was_mapped : TRUE);
6547 if (!was_mapped && !gdk_window_has_impl (private))
6549 if (private->event_mask & GDK_STRUCTURE_MASK)
6550 _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
6552 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
6553 _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
6556 if (!was_mapped || raise)
6558 recompute_visible_regions (private, TRUE, FALSE);
6560 /* If any decendants became visible we need to send visibility notify */
6561 gdk_window_update_visibility_recursively (private, NULL);
6563 if (gdk_window_is_viewable (window))
6565 _gdk_synthesize_crossing_events_for_geometry_change (window);
6566 gdk_window_invalidate_rect_full (window, NULL, TRUE, CLEAR_BG_ALL);
6572 * gdk_window_show_unraised:
6573 * @window: a #GdkWindow
6575 * Shows a #GdkWindow onscreen, but does not modify its stacking
6576 * order. In contrast, gdk_window_show() will raise the window
6577 * to the top of the window stack.
6579 * On the X11 platform, in Xlib terms, this function calls
6580 * XMapWindow() (it also updates some internal GDK state, which means
6581 * that you can't really use XMapWindow() directly on a GDK window).
6584 gdk_window_show_unraised (GdkWindow *window)
6586 gdk_window_show_internal (window, FALSE);
6591 * @window: a #GdkWindow
6593 * Raises @window to the top of the Z-order (stacking order), so that
6594 * other windows with the same parent window appear below @window.
6595 * This is true whether or not the windows are visible.
6597 * If @window is a toplevel, the window manager may choose to deny the
6598 * request to move the window in the Z-order, gdk_window_raise() only
6599 * requests the restack, does not guarantee it.
6602 gdk_window_raise (GdkWindow *window)
6604 GdkWindowObject *private;
6605 GdkRegion *old_region, *new_region;
6607 g_return_if_fail (GDK_IS_WINDOW (window));
6609 private = (GdkWindowObject *) window;
6610 if (private->destroyed)
6613 gdk_window_flush_if_exposing (window);
6616 if (gdk_window_is_viewable (window) &&
6617 !private->input_only)
6618 old_region = gdk_region_copy (private->clip_region);
6620 /* Keep children in (reverse) stacking order */
6621 gdk_window_raise_internal (window);
6623 recompute_visible_regions (private, TRUE, FALSE);
6627 new_region = gdk_region_copy (private->clip_region);
6629 gdk_region_subtract (new_region, old_region);
6630 gdk_window_invalidate_region_full (window, new_region, TRUE, CLEAR_BG_ALL);
6632 gdk_region_destroy (old_region);
6633 gdk_region_destroy (new_region);
6638 gdk_window_lower_internal (GdkWindow *window)
6640 GdkWindowObject *private = (GdkWindowObject *)window;
6641 GdkWindowObject *parent = private->parent;
6642 GdkWindowImplIface *impl_iface;
6643 GdkWindowObject *above;
6644 GList *native_children;
6649 parent->children = g_list_remove (parent->children, window);
6650 parent->children = g_list_append (parent->children, window);
6653 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
6654 /* Just do native lower for toplevels */
6655 if (gdk_window_is_toplevel (private) ||
6656 /* The restack_under codepath should work correctly even if the parent
6657 is native, but it relies on the order of ->children to be correct,
6658 and some apps like SWT reorder the x windows without gdks knowledge,
6659 so we use lower directly in order to make these behave as before
6660 when using native windows */
6661 (gdk_window_has_impl (private) && gdk_window_has_impl (parent)))
6663 impl_iface->lower (window);
6665 else if (gdk_window_has_impl (private))
6667 above = find_native_sibling_above (parent, private);
6670 listhead.data = window;
6671 listhead.next = NULL;
6672 listhead.prev = NULL;
6673 impl_iface->restack_under ((GdkWindow *)above, &listhead);
6676 impl_iface->raise (window);
6680 native_children = NULL;
6681 get_all_native_children (private, &native_children);
6682 if (native_children != NULL)
6684 above = find_native_sibling_above (parent, private);
6687 impl_iface->restack_under ((GdkWindow *)above,
6691 /* Right order, since native_children is bottom-topmost first */
6692 for (l = native_children; l != NULL; l = l->next)
6693 impl_iface->raise (l->data);
6696 g_list_free (native_children);
6703 gdk_window_invalidate_in_parent (GdkWindowObject *private)
6705 GdkRectangle r, child;
6707 if (gdk_window_is_toplevel (private))
6710 /* get the visible rectangle of the parent */
6712 r.width = private->parent->width;
6713 r.height = private->parent->height;
6715 child.x = private->x;
6716 child.y = private->y;
6717 child.width = private->width;
6718 child.height = private->height;
6719 gdk_rectangle_intersect (&r, &child, &r);
6721 gdk_window_invalidate_rect_full (GDK_WINDOW (private->parent), &r, TRUE, CLEAR_BG_ALL);
6727 * @window: a #GdkWindow
6729 * Lowers @window to the bottom of the Z-order (stacking order), so that
6730 * other windows with the same parent window appear above @window.
6731 * This is true whether or not the other windows are visible.
6733 * If @window is a toplevel, the window manager may choose to deny the
6734 * request to move the window in the Z-order, gdk_window_lower() only
6735 * requests the restack, does not guarantee it.
6737 * Note that gdk_window_show() raises the window again, so don't call this
6738 * function before gdk_window_show(). (Try gdk_window_show_unraised().)
6741 gdk_window_lower (GdkWindow *window)
6743 GdkWindowObject *private;
6745 g_return_if_fail (GDK_IS_WINDOW (window));
6747 private = (GdkWindowObject *) window;
6748 if (private->destroyed)
6751 gdk_window_flush_if_exposing (window);
6753 /* Keep children in (reverse) stacking order */
6754 gdk_window_lower_internal (window);
6756 recompute_visible_regions (private, TRUE, FALSE);
6758 _gdk_synthesize_crossing_events_for_geometry_change (window);
6759 gdk_window_invalidate_in_parent (private);
6763 * gdk_window_restack:
6764 * @window: a #GdkWindow
6765 * @sibling: a #GdkWindow that is a sibling of @window, or %NULL
6768 * Changes the position of @window in the Z-order (stacking order), so that
6769 * it is above @sibling (if @above is %TRUE) or below @sibling (if @above is
6772 * If @sibling is %NULL, then this either raises (if @above is %TRUE) or
6773 * lowers the window.
6775 * If @window is a toplevel, the window manager may choose to deny the
6776 * request to move the window in the Z-order, gdk_window_restack() only
6777 * requests the restack, does not guarantee it.
6782 gdk_window_restack (GdkWindow *window,
6786 GdkWindowObject *private;
6787 GdkWindowImplIface *impl_iface;
6788 GdkWindowObject *parent;
6789 GdkWindowObject *above_native;
6790 GList *sibling_link;
6791 GList *native_children;
6794 g_return_if_fail (GDK_IS_WINDOW (window));
6795 g_return_if_fail (sibling == NULL || GDK_IS_WINDOW (sibling));
6797 private = (GdkWindowObject *) window;
6798 if (private->destroyed)
6801 if (sibling == NULL)
6804 gdk_window_raise (window);
6806 gdk_window_lower (window);
6810 gdk_window_flush_if_exposing (window);
6812 if (gdk_window_is_toplevel (private))
6814 g_return_if_fail (gdk_window_is_toplevel (GDK_WINDOW_OBJECT (sibling)));
6815 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
6816 impl_iface->restack_toplevel (window, sibling, above);
6820 parent = private->parent;
6823 sibling_link = g_list_find (parent->children, sibling);
6824 g_return_if_fail (sibling_link != NULL);
6825 if (sibling_link == NULL)
6828 parent->children = g_list_remove (parent->children, window);
6830 parent->children = g_list_insert_before (parent->children,
6834 parent->children = g_list_insert_before (parent->children,
6838 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
6839 if (gdk_window_has_impl (private))
6841 above_native = find_native_sibling_above (parent, private);
6844 listhead.data = window;
6845 listhead.next = NULL;
6846 listhead.prev = NULL;
6847 impl_iface->restack_under ((GdkWindow *)above_native, &listhead);
6850 impl_iface->raise (window);
6854 native_children = NULL;
6855 get_all_native_children (private, &native_children);
6856 if (native_children != NULL)
6858 above_native = find_native_sibling_above (parent, private);
6860 impl_iface->restack_under ((GdkWindow *)above_native,
6864 /* Right order, since native_children is bottom-topmost first */
6865 for (l = native_children; l != NULL; l = l->next)
6866 impl_iface->raise (l->data);
6869 g_list_free (native_children);
6874 recompute_visible_regions (private, TRUE, FALSE);
6876 _gdk_synthesize_crossing_events_for_geometry_change (window);
6877 gdk_window_invalidate_in_parent (private);
6883 * @window: a #GdkWindow
6885 * Like gdk_window_show_unraised(), but also raises the window to the
6886 * top of the window stack (moves the window to the front of the
6889 * This function maps a window so it's visible onscreen. Its opposite
6890 * is gdk_window_hide().
6892 * When implementing a #GtkWidget, you should call this function on the widget's
6893 * #GdkWindow as part of the "map" method.
6896 gdk_window_show (GdkWindow *window)
6898 gdk_window_show_internal (window, TRUE);
6903 * @window: a #GdkWindow
6905 * For toplevel windows, withdraws them, so they will no longer be
6906 * known to the window manager; for all windows, unmaps them, so
6907 * they won't be displayed. Normally done automatically as
6908 * part of gtk_widget_hide().
6911 gdk_window_hide (GdkWindow *window)
6913 GdkWindowObject *private;
6914 GdkWindowImplIface *impl_iface;
6915 gboolean was_mapped, did_hide;
6917 g_return_if_fail (GDK_IS_WINDOW (window));
6919 private = (GdkWindowObject *) window;
6920 if (private->destroyed)
6923 was_mapped = GDK_WINDOW_IS_MAPPED (private);
6925 if (gdk_window_has_impl (private))
6928 if (GDK_WINDOW_IS_MAPPED (window))
6929 gdk_synthesize_window_state (window,
6931 GDK_WINDOW_STATE_WITHDRAWN);
6933 else if (was_mapped)
6935 GdkDisplay *display;
6937 /* May need to break grabs on children */
6938 display = gdk_drawable_get_display (window);
6940 if (_gdk_display_end_pointer_grab (display,
6941 _gdk_windowing_window_get_next_serial (display),
6944 gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
6946 if (display->keyboard_grab.window != NULL)
6948 if (is_parent_of (window, display->keyboard_grab.window))
6950 /* Call this ourselves, even though gdk_display_keyboard_ungrab
6951 does so too, since we want to pass implicit == TRUE so the
6952 broken grab event is generated */
6953 _gdk_display_unset_has_keyboard_grab (display,
6955 gdk_display_keyboard_ungrab (display, GDK_CURRENT_TIME);
6959 private->state = GDK_WINDOW_STATE_WITHDRAWN;
6962 did_hide = _gdk_window_update_viewable (window);
6964 /* Hide foreign window as those are not handled by update_viewable. */
6965 if (gdk_window_has_impl (private) && (!did_hide))
6967 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
6968 impl_iface->hide (window);
6971 recompute_visible_regions (private, TRUE, FALSE);
6973 /* all decendants became non-visible, we need to send visibility notify */
6974 gdk_window_update_visibility_recursively (private, NULL);
6976 if (was_mapped && !gdk_window_has_impl (private))
6978 if (private->event_mask & GDK_STRUCTURE_MASK)
6979 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6981 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
6982 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6984 _gdk_synthesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
6987 /* Invalidate the rect */
6989 gdk_window_invalidate_in_parent (private);
6993 * gdk_window_withdraw:
6994 * @window: a toplevel #GdkWindow
6996 * Withdraws a window (unmaps it and asks the window manager to forget about it).
6997 * This function is not really useful as gdk_window_hide() automatically
6998 * withdraws toplevel windows before hiding them.
7001 gdk_window_withdraw (GdkWindow *window)
7003 GdkWindowObject *private;
7004 GdkWindowImplIface *impl_iface;
7005 gboolean was_mapped;
7007 g_return_if_fail (GDK_IS_WINDOW (window));
7009 private = (GdkWindowObject *) window;
7010 if (private->destroyed)
7013 was_mapped = GDK_WINDOW_IS_MAPPED (private);
7015 if (gdk_window_has_impl (private))
7017 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
7018 impl_iface->withdraw (window);
7022 if (private->event_mask & GDK_STRUCTURE_MASK)
7023 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
7025 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
7026 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
7028 _gdk_synthesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
7031 recompute_visible_regions (private, TRUE, FALSE);
7036 * gdk_window_set_events:
7037 * @window: a #GdkWindow
7038 * @event_mask: event mask for @window
7040 * The event mask for a window determines which events will be reported
7041 * for that window. For example, an event mask including #GDK_BUTTON_PRESS_MASK
7042 * means the window should report button press events. The event mask
7043 * is the bitwise OR of values from the #GdkEventMask enumeration.
7046 gdk_window_set_events (GdkWindow *window,
7047 GdkEventMask event_mask)
7049 GdkWindowObject *private;
7050 GdkWindowImplIface *impl_iface;
7051 GdkDisplay *display;
7053 g_return_if_fail (GDK_IS_WINDOW (window));
7055 private = (GdkWindowObject *) window;
7056 if (private->destroyed)
7059 /* If motion hint is disabled, enable motion events again */
7060 display = gdk_drawable_get_display (window);
7061 if ((private->event_mask & GDK_POINTER_MOTION_HINT_MASK) &&
7062 !(event_mask & GDK_POINTER_MOTION_HINT_MASK))
7063 _gdk_display_enable_motion_hints (display);
7065 private->event_mask = event_mask;
7067 if (gdk_window_has_impl (private))
7069 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
7070 impl_iface->set_events (window,
7071 get_native_event_mask (private));
7077 * gdk_window_get_events:
7078 * @window: a #GdkWindow
7080 * Gets the event mask for @window. See gdk_window_set_events().
7082 * Return value: event mask for @window
7085 gdk_window_get_events (GdkWindow *window)
7087 GdkWindowObject *private;
7089 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
7091 private = (GdkWindowObject *) window;
7092 if (private->destroyed)
7095 return private->event_mask;
7099 gdk_window_move_resize_toplevel (GdkWindow *window,
7106 GdkWindowObject *private;
7107 GdkRegion *old_region, *new_region;
7108 GdkWindowImplIface *impl_iface;
7110 int old_x, old_y, old_abs_x, old_abs_y;
7114 private = (GdkWindowObject *) window;
7122 is_resize = (width != -1) || (height != -1);
7124 if (gdk_window_is_viewable (window) &&
7125 !private->input_only)
7128 old_region = gdk_region_copy (private->clip_region);
7131 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
7132 impl_iface->move_resize (window, with_move, x, y, width, height);
7134 dx = private->x - old_x;
7135 dy = private->y - old_y;
7137 old_abs_x = private->abs_x;
7138 old_abs_y = private->abs_y;
7140 /* Avoid recomputing for pure toplevel moves, for performance reasons */
7142 recompute_visible_regions (private, TRUE, FALSE);
7146 new_region = gdk_region_copy (private->clip_region);
7148 /* This is the newly exposed area (due to any resize),
7149 * X will expose it, but lets do that without the
7152 gdk_region_subtract (new_region, old_region);
7153 gdk_window_invalidate_region_full (window, new_region, TRUE, CLEAR_BG_WINCLEARED);
7155 gdk_region_destroy (old_region);
7156 gdk_region_destroy (new_region);
7159 _gdk_synthesize_crossing_events_for_geometry_change (window);
7164 move_native_children (GdkWindowObject *private)
7167 GdkWindowObject *child;
7168 GdkWindowImplIface *impl_iface;
7170 for (l = private->children; l; l = l->next)
7174 if (child->impl != private->impl)
7176 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (child->impl);
7177 impl_iface->move_resize ((GdkWindow *)child, TRUE,
7179 child->width, child->height);
7182 move_native_children (child);
7187 collect_native_child_region_helper (GdkWindowObject *window,
7193 GdkWindowObject *child;
7197 for (l = window->children; l != NULL; l = l->next)
7201 if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only)
7204 if (child->impl != impl)
7206 tmp = gdk_region_copy (child->clip_region);
7207 gdk_region_offset (tmp,
7208 x_offset + child->x,
7209 y_offset + child->y);
7210 if (*region == NULL)
7214 gdk_region_union (*region, tmp);
7215 gdk_region_destroy (tmp);
7219 collect_native_child_region_helper (child, impl, region,
7220 x_offset + child->x,
7221 y_offset + child->y);
7228 collect_native_child_region (GdkWindowObject *window,
7229 gboolean include_this)
7233 if (include_this && gdk_window_has_impl (window) && window->viewable)
7234 return gdk_region_copy (window->clip_region);
7238 collect_native_child_region_helper (window, window->impl, ®ion, 0, 0);
7245 gdk_window_move_resize_internal (GdkWindow *window,
7252 GdkWindowObject *private;
7253 GdkRegion *old_region, *new_region, *copy_area;
7254 GdkRegion *old_native_child_region, *new_native_child_region;
7255 GdkWindowObject *impl_window;
7256 GdkWindowImplIface *impl_iface;
7258 int old_x, old_y, old_abs_x, old_abs_y;
7261 g_return_if_fail (GDK_IS_WINDOW (window));
7263 private = (GdkWindowObject *) window;
7264 if (private->destroyed)
7267 if (gdk_window_is_toplevel (private))
7269 gdk_window_move_resize_toplevel (window, with_move, x, y, width, height);
7273 /* Bail early if no change */
7274 if (private->width == width &&
7275 private->height == height &&
7281 gdk_window_flush_if_exposing (window);
7283 /* Handle child windows */
7288 impl_window = gdk_window_get_impl_window (private);
7293 old_native_child_region = NULL;
7294 if (gdk_window_is_viewable (window) &&
7295 !private->input_only)
7299 old_region = gdk_region_copy (private->clip_region);
7300 /* Adjust region to parent window coords */
7301 gdk_region_offset (old_region, private->x, private->y);
7303 old_native_child_region = collect_native_child_region (private, TRUE);
7304 if (old_native_child_region)
7306 /* Adjust region to parent window coords */
7307 gdk_region_offset (old_native_child_region, private->x, private->y);
7309 /* Any native window move will immediately copy stuff to the destination, which may overwrite a
7310 * source or destination for a delayed GdkWindowRegionMove. So, we need
7311 * to flush those here for the parent window and all overlapped subwindows
7312 * of it. And we need to do this before setting the new clips as those will be
7315 gdk_window_flush_recursive (private->parent);
7319 /* Set the new position and size */
7325 if (!(width < 0 && height < 0))
7329 private->width = width;
7332 private->height = height;
7335 dx = private->x - old_x;
7336 dy = private->y - old_y;
7338 old_abs_x = private->abs_x;
7339 old_abs_y = private->abs_y;
7341 recompute_visible_regions (private, TRUE, FALSE);
7343 new_native_child_region = NULL;
7344 if (old_native_child_region)
7346 new_native_child_region = collect_native_child_region (private, TRUE);
7347 /* Adjust region to parent window coords */
7348 gdk_region_offset (new_native_child_region, private->x, private->y);
7351 if (gdk_window_has_impl (private))
7353 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
7355 /* Do the actual move after recomputing things, as this will have set the shape to
7356 the now correct one, thus avoiding copying regions that should not be copied. */
7357 impl_iface->move_resize (window, TRUE,
7358 private->x, private->y,
7359 private->width, private->height);
7361 else if (old_abs_x != private->abs_x ||
7362 old_abs_y != private->abs_y)
7363 move_native_children (private);
7367 new_region = gdk_region_copy (private->clip_region);
7368 /* Adjust region to parent window coords */
7369 gdk_region_offset (new_region, private->x, private->y);
7372 * Part of the data at the new location can be copied from the
7373 * old location, this area is the intersection of the old region
7374 * moved as the copy will move it and then intersected with
7378 * Everything in the old and new regions that is not copied must be
7379 * invalidated (including children) as this is newly exposed
7381 copy_area = gdk_region_copy (new_region);
7383 gdk_region_union (new_region, old_region);
7385 if (old_native_child_region)
7387 /* Don't copy from inside native children, as this is copied by
7388 * the native window move.
7390 gdk_region_subtract (old_region, old_native_child_region);
7392 gdk_region_offset (old_region, dx, dy);
7394 gdk_region_intersect (copy_area, old_region);
7396 if (new_native_child_region)
7398 /* Don't copy any bits that would cause a read from the moved
7399 native windows, as we can't read that data */
7400 gdk_region_offset (new_native_child_region, dx, dy);
7401 gdk_region_subtract (copy_area, new_native_child_region);
7402 gdk_region_offset (new_native_child_region, -dx, -dy);
7405 gdk_region_subtract (new_region, copy_area);
7407 /* Convert old region to impl coords */
7408 gdk_region_offset (old_region, -dx + private->abs_x - private->x, -dy + private->abs_y - private->y);
7410 /* convert from parent coords to impl */
7411 gdk_region_offset (copy_area, private->abs_x - private->x, private->abs_y - private->y);
7413 move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
7415 /* Invalidate affected part in the parent window
7416 * (no higher window should be affected)
7417 * We also invalidate any children in that area, which could include
7418 * this window if it still overlaps that area.
7420 if (old_native_child_region)
7422 /* No need to expose the region that the native window move copies */
7423 gdk_region_offset (old_native_child_region, dx, dy);
7424 gdk_region_intersect (old_native_child_region, new_native_child_region);
7425 gdk_region_subtract (new_region, old_native_child_region);
7427 gdk_window_invalidate_region_full (GDK_WINDOW (private->parent), new_region, TRUE, CLEAR_BG_ALL);
7429 gdk_region_destroy (old_region);
7430 gdk_region_destroy (new_region);
7433 if (old_native_child_region)
7435 gdk_region_destroy (old_native_child_region);
7436 gdk_region_destroy (new_native_child_region);
7439 _gdk_synthesize_crossing_events_for_geometry_change (window);
7446 * @window: a #GdkWindow
7447 * @x: X coordinate relative to window's parent
7448 * @y: Y coordinate relative to window's parent
7450 * Repositions a window relative to its parent window.
7451 * For toplevel windows, window managers may ignore or modify the move;
7452 * you should probably use gtk_window_move() on a #GtkWindow widget
7453 * anyway, instead of using GDK functions. For child windows,
7454 * the move will reliably succeed.
7456 * If you're also planning to resize the window, use gdk_window_move_resize()
7457 * to both move and resize simultaneously, for a nicer visual effect.
7460 gdk_window_move (GdkWindow *window,
7464 gdk_window_move_resize_internal (window, TRUE, x, y, -1, -1);
7468 * gdk_window_resize:
7469 * @window: a #GdkWindow
7470 * @width: new width of the window
7471 * @height: new height of the window
7473 * Resizes @window; for toplevel windows, asks the window manager to resize
7474 * the window. The window manager may not allow the resize. When using GTK+,
7475 * use gtk_window_resize() instead of this low-level GDK function.
7477 * Windows may not be resized below 1x1.
7479 * If you're also planning to move the window, use gdk_window_move_resize()
7480 * to both move and resize simultaneously, for a nicer visual effect.
7483 gdk_window_resize (GdkWindow *window,
7487 gdk_window_move_resize_internal (window, FALSE, 0, 0, width, height);
7492 * gdk_window_move_resize:
7493 * @window: a #GdkWindow
7494 * @x: new X position relative to window's parent
7495 * @y: new Y position relative to window's parent
7497 * @height: new height
7499 * Equivalent to calling gdk_window_move() and gdk_window_resize(),
7500 * except that both operations are performed at once, avoiding strange
7501 * visual effects. (i.e. the user may be able to see the window first
7502 * move, then resize, if you don't use gdk_window_move_resize().)
7505 gdk_window_move_resize (GdkWindow *window,
7511 gdk_window_move_resize_internal (window, TRUE, x, y, width, height);
7516 * gdk_window_scroll:
7517 * @window: a #GdkWindow
7518 * @dx: Amount to scroll in the X direction
7519 * @dy: Amount to scroll in the Y direction
7521 * Scroll the contents of @window, both pixels and children, by the
7522 * given amount. @window itself does not move. Portions of the window
7523 * that the scroll operation brings in from offscreen areas are
7524 * invalidated. The invalidated region may be bigger than what would
7525 * strictly be necessary.
7527 * For X11, a minimum area will be invalidated if the window has no
7528 * subwindows, or if the edges of the window's parent do not extend
7529 * beyond the edges of the window. In other cases, a multi-step process
7530 * is used to scroll the window which may produce temporary visual
7531 * artifacts and unnecessary invalidations.
7534 gdk_window_scroll (GdkWindow *window,
7538 GdkWindowObject *private = (GdkWindowObject *) window;
7539 GdkWindowObject *impl_window;
7540 GdkRegion *copy_area, *noncopy_area;
7541 GdkRegion *old_native_child_region, *new_native_child_region;
7544 g_return_if_fail (GDK_IS_WINDOW (window));
7546 if (dx == 0 && dy == 0)
7549 if (private->destroyed)
7552 gdk_window_flush_if_exposing (window);
7554 old_native_child_region = collect_native_child_region (private, FALSE);
7555 if (old_native_child_region)
7557 /* Any native window move will immediately copy stuff to the destination, which may overwrite a
7558 * source or destination for a delayed GdkWindowRegionMove. So, we need
7559 * to flush those here for the window and all overlapped subwindows
7560 * of it. And we need to do this before setting the new clips as those will be
7563 gdk_window_flush_recursive (private);
7567 /* First move all child windows, without causing invalidation */
7569 tmp_list = private->children;
7572 GdkWindow *child = GDK_WINDOW (tmp_list->data);
7573 GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
7575 /* Just update the positions, the bits will move with the copy */
7579 tmp_list = tmp_list->next;
7582 recompute_visible_regions (private, FALSE, TRUE);
7584 new_native_child_region = NULL;
7585 if (old_native_child_region)
7586 new_native_child_region = collect_native_child_region (private, FALSE);
7588 move_native_children (private);
7590 /* Then copy the actual bits of the window w/ child windows */
7592 impl_window = gdk_window_get_impl_window (private);
7594 /* Calculate the area that can be gotten by copying the old area */
7595 copy_area = gdk_region_copy (private->clip_region);
7596 if (old_native_child_region)
7598 /* Don't copy from inside native children, as this is copied by
7599 * the native window move.
7601 gdk_region_subtract (copy_area, old_native_child_region);
7603 /* Don't copy any bits that would cause a read from the moved
7604 native windows, as we can't read that data */
7605 gdk_region_subtract (copy_area, new_native_child_region);
7607 gdk_region_offset (copy_area, dx, dy);
7608 gdk_region_intersect (copy_area, private->clip_region);
7610 /* And the rest need to be invalidated */
7611 noncopy_area = gdk_region_copy (private->clip_region);
7612 gdk_region_subtract (noncopy_area, copy_area);
7614 /* convert from window coords to impl */
7615 gdk_region_offset (copy_area, private->abs_x, private->abs_y);
7617 move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
7619 /* Invalidate not copied regions */
7620 if (old_native_child_region)
7622 /* No need to expose the region that the native window move copies */
7623 gdk_region_offset (old_native_child_region, dx, dy);
7624 gdk_region_intersect (old_native_child_region, new_native_child_region);
7625 gdk_region_subtract (noncopy_area, old_native_child_region);
7627 gdk_window_invalidate_region_full (window, noncopy_area, TRUE, CLEAR_BG_ALL);
7629 gdk_region_destroy (noncopy_area);
7631 if (old_native_child_region)
7633 gdk_region_destroy (old_native_child_region);
7634 gdk_region_destroy (new_native_child_region);
7637 _gdk_synthesize_crossing_events_for_geometry_change (window);
7641 * gdk_window_move_region:
7642 * @window: a #GdkWindow
7643 * @region: The #GdkRegion to move
7644 * @dx: Amount to move in the X direction
7645 * @dy: Amount to move in the Y direction
7647 * Move the part of @window indicated by @region by @dy pixels in the Y
7648 * direction and @dx pixels in the X direction. The portions of @region
7649 * that not covered by the new position of @region are invalidated.
7651 * Child windows are not moved.
7656 gdk_window_move_region (GdkWindow *window,
7657 const GdkRegion *region,
7661 GdkWindowObject *private = (GdkWindowObject *) window;
7662 GdkWindowObject *impl_window;
7663 GdkRegion *nocopy_area;
7664 GdkRegion *copy_area;
7666 g_return_if_fail (GDK_IS_WINDOW (window));
7667 g_return_if_fail (region != NULL);
7669 if (dx == 0 && dy == 0)
7672 if (private->destroyed)
7675 impl_window = gdk_window_get_impl_window (private);
7677 /* compute source regions */
7678 copy_area = gdk_region_copy (region);
7679 gdk_region_intersect (copy_area, private->clip_region_with_children);
7681 /* compute destination regions */
7682 gdk_region_offset (copy_area, dx, dy);
7683 gdk_region_intersect (copy_area, private->clip_region_with_children);
7685 /* Invalidate parts of the region (source and dest) not covered
7687 nocopy_area = gdk_region_copy (region);
7688 gdk_region_offset (nocopy_area, dx, dy);
7689 gdk_region_union (nocopy_area, region);
7690 gdk_region_subtract (nocopy_area, copy_area);
7692 /* convert from window coords to impl */
7693 gdk_region_offset (copy_area, private->abs_x, private->abs_y);
7694 move_region_on_impl (impl_window, copy_area, dx, dy); /* Takes ownership of copy_area */
7696 gdk_window_invalidate_region_full (window, nocopy_area, FALSE, CLEAR_BG_ALL);
7697 gdk_region_destroy (nocopy_area);
7701 * gdk_window_set_background:
7702 * @window: a #GdkWindow
7703 * @color: an allocated #GdkColor
7705 * Sets the background color of @window. (However, when using GTK+,
7706 * set the background of a widget with gtk_widget_modify_bg() - if
7707 * you're an application - or gtk_style_set_background() - if you're
7708 * implementing a custom widget.)
7710 * The @color must be allocated; gdk_rgb_find_color() is the best way
7711 * to allocate a color.
7713 * See also gdk_window_set_back_pixmap().
7716 gdk_window_set_background (GdkWindow *window,
7717 const GdkColor *color)
7719 GdkWindowObject *private;
7720 GdkColormap *colormap = gdk_drawable_get_colormap (window);
7721 GdkWindowImplIface *impl_iface;
7723 g_return_if_fail (GDK_IS_WINDOW (window));
7725 private = (GdkWindowObject *) window;
7727 private->bg_color = *color;
7728 gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
7730 if (private->bg_pixmap &&
7731 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
7732 private->bg_pixmap != GDK_NO_BG)
7733 g_object_unref (private->bg_pixmap);
7735 private->bg_pixmap = NULL;
7737 if (!GDK_WINDOW_DESTROYED (window) &&
7738 gdk_window_has_impl (private) &&
7739 !private->input_only)
7741 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
7742 impl_iface->set_background (window, &private->bg_color);
7747 * gdk_window_set_back_pixmap:
7748 * @window: a #GdkWindow
7749 * @pixmap: a #GdkPixmap, or %NULL
7750 * @parent_relative: whether the tiling origin is at the origin of
7753 * Sets the background pixmap of @window. May also be used to set a
7754 * background of "None" on @window, by setting a background pixmap
7757 * A background pixmap will be tiled, positioning the first tile at
7758 * the origin of @window, or if @parent_relative is %TRUE, the tiling
7759 * will be done based on the origin of the parent window (useful to
7760 * align tiles in a parent with tiles in a child).
7762 * A background pixmap of %NULL means that the window will have no
7763 * background. A window with no background will never have its
7764 * background filled by the windowing system, instead the window will
7765 * contain whatever pixels were already in the corresponding area of
7768 * The windowing system will normally fill a window with its background
7769 * when the window is obscured then exposed, and when you call
7770 * gdk_window_clear().
7773 gdk_window_set_back_pixmap (GdkWindow *window,
7775 gboolean parent_relative)
7777 GdkWindowObject *private;
7778 GdkWindowImplIface *impl_iface;
7780 g_return_if_fail (GDK_IS_WINDOW (window));
7781 g_return_if_fail (pixmap == NULL || !parent_relative);
7782 g_return_if_fail (pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap));
7784 private = (GdkWindowObject *) window;
7786 if (pixmap && !gdk_drawable_get_colormap (pixmap))
7788 g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
7792 if (private->bg_pixmap &&
7793 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
7794 private->bg_pixmap != GDK_NO_BG)
7795 g_object_unref (private->bg_pixmap);
7797 if (parent_relative)
7798 private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
7800 private->bg_pixmap = g_object_ref (pixmap);
7802 private->bg_pixmap = GDK_NO_BG;
7804 if (!GDK_WINDOW_DESTROYED (window) &&
7805 gdk_window_has_impl (private) &&
7806 !private->input_only)
7808 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
7809 impl_iface->set_back_pixmap (window, private->bg_pixmap);
7814 * gdk_window_get_cursor:
7815 * @window: a #GdkWindow
7817 * Retrieves a #GdkCursor pointer for the cursor currently set on the
7818 * specified #GdkWindow, or %NULL. If the return value is %NULL then
7819 * there is no custom cursor set on the specified window, and it is
7820 * using the cursor for its parent window.
7822 * Return value: a #GdkCursor, or %NULL. The returned object is owned
7823 * by the #GdkWindow and should not be unreferenced directly. Use
7824 * gdk_window_set_cursor() to unset the cursor of the window
7829 gdk_window_get_cursor (GdkWindow *window)
7831 GdkWindowObject *private;
7833 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
7835 private = (GdkWindowObject *) window;
7837 return private->cursor;
7841 * gdk_window_set_cursor:
7842 * @window: a #GdkWindow
7845 * Sets the mouse pointer for a #GdkWindow. Use gdk_cursor_new_for_display()
7846 * or gdk_cursor_new_from_pixmap() to create the cursor. To make the cursor
7847 * invisible, use %GDK_BLANK_CURSOR. Passing %NULL for the @cursor argument
7848 * to gdk_window_set_cursor() means that @window will use the cursor of its
7849 * parent window. Most windows should use this default.
7852 gdk_window_set_cursor (GdkWindow *window,
7855 GdkWindowObject *private;
7856 GdkWindowImplIface *impl_iface;
7857 GdkDisplay *display;
7859 g_return_if_fail (GDK_IS_WINDOW (window));
7861 private = (GdkWindowObject *) window;
7862 display = gdk_drawable_get_display (window);
7864 if (private->cursor)
7866 gdk_cursor_unref (private->cursor);
7867 private->cursor = NULL;
7870 if (!GDK_WINDOW_DESTROYED (window))
7873 private->cursor = gdk_cursor_ref (cursor);
7875 if (_gdk_native_windows ||
7876 private->window_type == GDK_WINDOW_ROOT ||
7877 private->window_type == GDK_WINDOW_FOREIGN)
7879 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
7880 impl_iface->set_cursor (window, cursor);
7882 else if (_gdk_window_event_parent_of (window, display->pointer_info.window_under_pointer))
7883 update_cursor (display);
7885 g_object_notify (G_OBJECT (window), "cursor");
7890 * gdk_window_get_geometry:
7891 * @window: a #GdkWindow
7892 * @x: return location for X coordinate of window (relative to its parent)
7893 * @y: return location for Y coordinate of window (relative to its parent)
7894 * @width: return location for width of window
7895 * @height: return location for height of window
7896 * @depth: return location for bit depth of window
7898 * Any of the return location arguments to this function may be %NULL,
7899 * if you aren't interested in getting the value of that field.
7901 * The X and Y coordinates returned are relative to the parent window
7902 * of @window, which for toplevels usually means relative to the
7903 * window decorations (titlebar, etc.) rather than relative to the
7904 * root window (screen-size background window).
7906 * On the X11 platform, the geometry is obtained from the X server,
7907 * so reflects the latest position of @window; this may be out-of-sync
7908 * with the position of @window delivered in the most-recently-processed
7909 * #GdkEventConfigure. gdk_window_get_position() in contrast gets the
7910 * position from the most recent configure event.
7913 * If @window is not a toplevel, it is <emphasis>much</emphasis> better
7914 * to call gdk_window_get_position() and gdk_drawable_get_size() instead,
7915 * because it avoids the roundtrip to the X server and because
7916 * gdk_drawable_get_size() supports the full 32-bit coordinate space,
7917 * whereas gdk_window_get_geometry() is restricted to the 16-bit
7918 * coordinates of X11.
7922 gdk_window_get_geometry (GdkWindow *window,
7929 GdkWindowObject *private, *parent;
7930 GdkWindowImplIface *impl_iface;
7934 GDK_NOTE (MULTIHEAD,
7935 g_message ("gdk_window_get_geometry(): Window needs "
7936 "to be non-NULL to be multi head safe"));
7937 window = gdk_screen_get_root_window ((gdk_screen_get_default ()));
7940 g_return_if_fail (GDK_IS_WINDOW (window));
7942 private = (GdkWindowObject *) window;
7944 if (!GDK_WINDOW_DESTROYED (window))
7946 if (gdk_window_has_impl (private))
7948 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
7949 impl_iface->get_geometry (window, x, y,
7952 /* This reports the position wrt to the native parent, we need to convert
7953 it to be relative to the client side parent */
7954 parent = private->parent;
7955 if (parent && !gdk_window_has_impl (parent))
7958 *x -= parent->abs_x;
7960 *y -= parent->abs_y;
7970 *width = private->width;
7972 *height = private->height;
7974 *depth = private->depth;
7980 * gdk_window_get_origin:
7981 * @window: a #GdkWindow
7982 * @x: return location for X coordinate
7983 * @y: return location for Y coordinate
7985 * Obtains the position of a window in root window coordinates.
7986 * (Compare with gdk_window_get_position() and
7987 * gdk_window_get_geometry() which return the position of a window
7988 * relative to its parent window.)
7990 * Return value: not meaningful, ignore
7993 gdk_window_get_origin (GdkWindow *window,
7997 GdkWindowObject *private;
7998 GdkWindowImplIface *impl_iface;
8000 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
8002 if (GDK_WINDOW_DESTROYED (window))
8011 private = (GdkWindowObject *) window;
8013 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
8014 impl_iface->get_root_coords (window,
8023 * gdk_window_get_root_coords:
8024 * @window: a #GdkWindow
8025 * @x: X coordinate in window
8026 * @y: Y coordinate in window
8027 * @root_x: return location for X coordinate
8028 * @root_y: return location for Y coordinate
8030 * Obtains the position of a window position in root
8031 * window coordinates. This is similar to
8032 * gdk_window_get_origin() but allows you go pass
8033 * in any position in the window, not just the origin.
8038 gdk_window_get_root_coords (GdkWindow *window,
8044 GdkWindowObject *private;
8045 GdkWindowImplIface *impl_iface;
8047 g_return_if_fail (GDK_IS_WINDOW (window));
8049 private = (GdkWindowObject *) window;
8051 if (GDK_WINDOW_DESTROYED (window))
8060 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
8061 impl_iface->get_root_coords (window,
8069 * gdk_window_get_deskrelative_origin:
8070 * @window: a toplevel #GdkWindow
8071 * @x: return location for X coordinate
8072 * @y: return location for Y coordinate
8074 * This gets the origin of a #GdkWindow relative to
8075 * an Enlightenment-window-manager desktop. As long as you don't
8076 * assume that the user's desktop/workspace covers the entire
8077 * root window (i.e. you don't assume that the desktop begins
8078 * at root window coordinate 0,0) this function is not necessary.
8079 * It's deprecated for that reason.
8081 * Return value: not meaningful
8084 gdk_window_get_deskrelative_origin (GdkWindow *window,
8088 GdkWindowObject *private;
8089 GdkWindowImplIface *impl_iface;
8090 gboolean return_val = FALSE;
8094 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
8096 private = (GdkWindowObject *) window;
8098 if (!GDK_WINDOW_DESTROYED (window))
8100 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
8101 return_val = impl_iface->get_deskrelative_origin (window, &tx, &ty);
8104 *x = tx + private->abs_x;
8106 *y = ty + private->abs_y;
8113 * gdk_window_shape_combine_mask:
8114 * @window: a #GdkWindow
8116 * @x: X position of shape mask with respect to @window
8117 * @y: Y position of shape mask with respect to @window
8119 * Applies a shape mask to @window. Pixels in @window corresponding to
8120 * set bits in the @mask will be visible; pixels in @window
8121 * corresponding to unset bits in the @mask will be transparent. This
8122 * gives a non-rectangular window.
8124 * If @mask is %NULL, the shape mask will be unset, and the @x/@y
8125 * parameters are not used.
8127 * On the X11 platform, this uses an X server extension which is
8128 * widely available on most common platforms, but not available on
8129 * very old X servers, and occasionally the implementation will be
8130 * buggy. On servers without the shape extension, this function
8133 * This function works on both toplevel and child windows.
8136 gdk_window_shape_combine_mask (GdkWindow *window,
8141 GdkWindowObject *private;
8144 g_return_if_fail (GDK_IS_WINDOW (window));
8146 private = (GdkWindowObject *) window;
8149 region = _gdk_windowing_get_shape_for_mask (mask);
8153 gdk_window_shape_combine_region (window,
8158 gdk_region_destroy (region);
8162 * gdk_window_shape_combine_region:
8163 * @window: a #GdkWindow
8164 * @shape_region: region of window to be non-transparent
8165 * @offset_x: X position of @shape_region in @window coordinates
8166 * @offset_y: Y position of @shape_region in @window coordinates
8168 * Makes pixels in @window outside @shape_region be transparent,
8169 * so that the window may be nonrectangular. See also
8170 * gdk_window_shape_combine_mask() to use a bitmap as the mask.
8172 * If @shape_region is %NULL, the shape will be unset, so the whole
8173 * window will be opaque again. @offset_x and @offset_y are ignored
8174 * if @shape_region is %NULL.
8176 * On the X11 platform, this uses an X server extension which is
8177 * widely available on most common platforms, but not available on
8178 * very old X servers, and occasionally the implementation will be
8179 * buggy. On servers without the shape extension, this function
8182 * This function works on both toplevel and child windows.
8185 gdk_window_shape_combine_region (GdkWindow *window,
8186 const GdkRegion *shape_region,
8190 GdkWindowObject *private;
8191 GdkRegion *old_region, *new_region, *diff;
8193 g_return_if_fail (GDK_IS_WINDOW (window));
8195 private = (GdkWindowObject *) window;
8197 if (GDK_WINDOW_DESTROYED (window))
8200 private->shaped = (shape_region != NULL);
8203 gdk_region_destroy (private->shape);
8206 if (GDK_WINDOW_IS_MAPPED (window))
8207 old_region = gdk_region_copy (private->clip_region);
8211 private->shape = gdk_region_copy (shape_region);
8212 gdk_region_offset (private->shape, offset_x, offset_y);
8215 private->shape = NULL;
8217 recompute_visible_regions (private, TRUE, FALSE);
8219 if (gdk_window_has_impl (private) &&
8220 !should_apply_clip_as_shape (private))
8221 apply_shape (private, private->shape);
8225 new_region = gdk_region_copy (private->clip_region);
8227 /* New area in the window, needs invalidation */
8228 diff = gdk_region_copy (new_region);
8229 gdk_region_subtract (diff, old_region);
8231 gdk_window_invalidate_region_full (window, diff, TRUE, CLEAR_BG_ALL);
8233 gdk_region_destroy (diff);
8235 if (!gdk_window_is_toplevel (private))
8237 /* New area in the non-root parent window, needs invalidation */
8238 diff = gdk_region_copy (old_region);
8239 gdk_region_subtract (diff, new_region);
8241 /* Adjust region to parent window coords */
8242 gdk_region_offset (diff, private->x, private->y);
8244 gdk_window_invalidate_region_full (GDK_WINDOW (private->parent), diff, TRUE, CLEAR_BG_ALL);
8246 gdk_region_destroy (diff);
8249 gdk_region_destroy (new_region);
8250 gdk_region_destroy (old_region);
8255 do_child_shapes (GdkWindow *window,
8258 GdkWindowObject *private;
8262 private = (GdkWindowObject *) window;
8266 r.width = private->width;
8267 r.height = private->height;
8269 region = gdk_region_rectangle (&r);
8270 remove_child_area (private, NULL, FALSE, region);
8272 if (merge && private->shape)
8273 gdk_region_subtract (region, private->shape);
8275 gdk_window_shape_combine_region (window, region, 0, 0);
8279 * gdk_window_set_child_shapes:
8280 * @window: a #GdkWindow
8282 * Sets the shape mask of @window to the union of shape masks
8283 * for all children of @window, ignoring the shape mask of @window
8284 * itself. Contrast with gdk_window_merge_child_shapes() which includes
8285 * the shape mask of @window in the masks to be merged.
8288 gdk_window_set_child_shapes (GdkWindow *window)
8290 g_return_if_fail (GDK_IS_WINDOW (window));
8292 do_child_shapes (window, FALSE);
8296 * gdk_window_merge_child_shapes:
8297 * @window: a #GdkWindow
8299 * Merges the shape masks for any child windows into the
8300 * shape mask for @window. i.e. the union of all masks
8301 * for @window and its children will become the new mask
8302 * for @window. See gdk_window_shape_combine_mask().
8304 * This function is distinct from gdk_window_set_child_shapes()
8305 * because it includes @window's shape mask in the set of shapes to
8309 gdk_window_merge_child_shapes (GdkWindow *window)
8311 g_return_if_fail (GDK_IS_WINDOW (window));
8313 do_child_shapes (window, TRUE);
8317 * gdk_window_input_shape_combine_mask:
8318 * @window: a #GdkWindow
8319 * @mask: shape mask, or %NULL
8320 * @x: X position of shape mask with respect to @window
8321 * @y: Y position of shape mask with respect to @window
8323 * Like gdk_window_shape_combine_mask(), but the shape applies
8324 * only to event handling. Mouse events which happen while
8325 * the pointer position corresponds to an unset bit in the
8326 * mask will be passed on the window below @window.
8328 * An input shape is typically used with RGBA windows.
8329 * The alpha channel of the window defines which pixels are
8330 * invisible and allows for nicely antialiased borders,
8331 * and the input shape controls where the window is
8334 * On the X11 platform, this requires version 1.1 of the
8337 * On the Win32 platform, this functionality is not present and the
8338 * function does nothing.
8343 gdk_window_input_shape_combine_mask (GdkWindow *window,
8348 GdkWindowObject *private;
8351 g_return_if_fail (GDK_IS_WINDOW (window));
8353 private = (GdkWindowObject *) window;
8356 region = _gdk_windowing_get_shape_for_mask (mask);
8360 gdk_window_input_shape_combine_region (window,
8365 gdk_region_destroy (region);
8369 * gdk_window_input_shape_combine_region:
8370 * @window: a #GdkWindow
8371 * @shape_region: region of window to be non-transparent
8372 * @offset_x: X position of @shape_region in @window coordinates
8373 * @offset_y: Y position of @shape_region in @window coordinates
8375 * Like gdk_window_shape_combine_region(), but the shape applies
8376 * only to event handling. Mouse events which happen while
8377 * the pointer position corresponds to an unset bit in the
8378 * mask will be passed on the window below @window.
8380 * An input shape is typically used with RGBA windows.
8381 * The alpha channel of the window defines which pixels are
8382 * invisible and allows for nicely antialiased borders,
8383 * and the input shape controls where the window is
8386 * On the X11 platform, this requires version 1.1 of the
8389 * On the Win32 platform, this functionality is not present and the
8390 * function does nothing.
8395 gdk_window_input_shape_combine_region (GdkWindow *window,
8396 const GdkRegion *shape_region,
8400 GdkWindowObject *private;
8401 GdkWindowImplIface *impl_iface;
8403 g_return_if_fail (GDK_IS_WINDOW (window));
8405 private = (GdkWindowObject *) window;
8407 if (GDK_WINDOW_DESTROYED (window))
8410 if (private->input_shape)
8411 gdk_region_destroy (private->input_shape);
8415 private->input_shape = gdk_region_copy (shape_region);
8416 gdk_region_offset (private->input_shape, offset_x, offset_y);
8419 private->input_shape = NULL;
8421 if (gdk_window_has_impl (private))
8423 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
8424 impl_iface->input_shape_combine_region (window, private->input_shape, 0, 0);
8427 /* Pointer may have e.g. moved outside window due to the input mask change */
8428 _gdk_synthesize_crossing_events_for_geometry_change (window);
8432 do_child_input_shapes (GdkWindow *window,
8435 GdkWindowObject *private;
8439 private = (GdkWindowObject *) window;
8443 r.width = private->width;
8444 r.height = private->height;
8446 region = gdk_region_rectangle (&r);
8447 remove_child_area (private, NULL, TRUE, region);
8449 if (merge && private->shape)
8450 gdk_region_subtract (region, private->shape);
8451 if (merge && private->input_shape)
8452 gdk_region_subtract (region, private->input_shape);
8454 gdk_window_input_shape_combine_region (window, region, 0, 0);
8459 * gdk_window_set_child_input_shapes:
8460 * @window: a #GdkWindow
8462 * Sets the input shape mask of @window to the union of input shape masks
8463 * for all children of @window, ignoring the input shape mask of @window
8464 * itself. Contrast with gdk_window_merge_child_input_shapes() which includes
8465 * the input shape mask of @window in the masks to be merged.
8470 gdk_window_set_child_input_shapes (GdkWindow *window)
8472 g_return_if_fail (GDK_IS_WINDOW (window));
8474 do_child_input_shapes (window, FALSE);
8478 * gdk_window_merge_child_input_shapes:
8479 * @window: a #GdkWindow
8481 * Merges the input shape masks for any child windows into the
8482 * input shape mask for @window. i.e. the union of all input masks
8483 * for @window and its children will become the new input mask
8484 * for @window. See gdk_window_input_shape_combine_mask().
8486 * This function is distinct from gdk_window_set_child_input_shapes()
8487 * because it includes @window's input shape mask in the set of
8488 * shapes to be merged.
8493 gdk_window_merge_child_input_shapes (GdkWindow *window)
8495 g_return_if_fail (GDK_IS_WINDOW (window));
8497 do_child_input_shapes (window, TRUE);
8502 * gdk_window_set_static_gravities:
8503 * @window: a #GdkWindow
8504 * @use_static: %TRUE to turn on static gravity
8506 * Set the bit gravity of the given window to static, and flag it so
8507 * all children get static subwindow gravity. This is used if you are
8508 * implementing scary features that involve deep knowledge of the
8509 * windowing system. Don't worry about it unless you have to.
8511 * Return value: %TRUE if the server supports static gravity
8514 gdk_window_set_static_gravities (GdkWindow *window,
8515 gboolean use_static)
8517 GdkWindowObject *private;
8518 GdkWindowImplIface *impl_iface;
8520 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
8522 private = (GdkWindowObject *) window;
8524 if (gdk_window_has_impl (private))
8526 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
8527 return impl_iface->set_static_gravities (window, use_static);
8534 * gdk_window_set_composited:
8535 * @window: a #GdkWindow
8536 * @composited: %TRUE to set the window as composited
8538 * Sets a #GdkWindow as composited, or unsets it. Composited
8539 * windows do not automatically have their contents drawn to
8540 * the screen. Drawing is redirected to an offscreen buffer
8541 * and an expose event is emitted on the parent of the composited
8542 * window. It is the responsibility of the parent's expose handler
8543 * to manually merge the off-screen content onto the screen in
8544 * whatever way it sees fit. See <xref linkend="composited-window-example"/>
8547 * It only makes sense for child windows to be composited; see
8548 * gdk_window_set_opacity() if you need translucent toplevel
8551 * An additional effect of this call is that the area of this
8552 * window is no longer clipped from regions marked for
8553 * invalidation on its parent. Draws done on the parent
8554 * window are also no longer clipped by the child.
8556 * This call is only supported on some systems (currently,
8557 * only X11 with new enough Xcomposite and Xdamage extensions).
8558 * You must call gdk_display_supports_composite() to check if
8559 * setting a window as composited is supported before
8560 * attempting to do so.
8565 gdk_window_set_composited (GdkWindow *window,
8566 gboolean composited)
8568 GdkWindowObject *private = (GdkWindowObject *)window;
8569 GdkDisplay *display;
8571 g_return_if_fail (GDK_IS_WINDOW (window));
8573 composited = composited != FALSE;
8575 if (private->composited == composited)
8579 gdk_window_ensure_native (window);
8581 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
8583 if (!gdk_display_supports_composite (display) && composited)
8585 g_warning ("gdk_window_set_composited called but "
8586 "compositing is not supported");
8590 _gdk_windowing_window_set_composited (window, composited);
8592 recompute_visible_regions (private, TRUE, FALSE);
8594 if (GDK_WINDOW_IS_MAPPED (window))
8595 gdk_window_invalidate_in_parent (private);
8597 private->composited = composited;
8602 remove_redirect_from_children (GdkWindowObject *private,
8603 GdkWindowRedirect *redirect)
8606 GdkWindowObject *child;
8608 for (l = private->children; l != NULL; l = l->next)
8612 /* Don't redirect this child if it already has another redirect */
8613 if (child->redirect == redirect)
8615 child->redirect = NULL;
8616 remove_redirect_from_children (child, redirect);
8622 * gdk_window_remove_redirection:
8623 * @window: a #GdkWindow
8625 * Removes any active redirection started by
8626 * gdk_window_redirect_to_drawable().
8631 gdk_window_remove_redirection (GdkWindow *window)
8633 GdkWindowObject *private;
8635 g_return_if_fail (GDK_IS_WINDOW (window));
8637 private = (GdkWindowObject *) window;
8639 if (private->redirect &&
8640 private->redirect->redirected == private)
8642 remove_redirect_from_children (private, private->redirect);
8643 gdk_window_redirect_free (private->redirect);
8644 private->redirect = NULL;
8649 apply_redirect_to_children (GdkWindowObject *private,
8650 GdkWindowRedirect *redirect)
8653 GdkWindowObject *child;
8655 for (l = private->children; l != NULL; l = l->next)
8659 /* Don't redirect this child if it already has another redirect */
8660 if (!child->redirect)
8662 child->redirect = redirect;
8663 apply_redirect_to_children (child, redirect);
8669 * gdk_window_redirect_to_drawable:
8670 * @window: a #GdkWindow
8671 * @drawable: a #GdkDrawable
8672 * @src_x: x position in @window
8673 * @src_y: y position in @window
8674 * @dest_x: x position in @drawable
8675 * @dest_y: y position in @drawable
8676 * @width: width of redirection, or -1 to use the width of @window
8677 * @height: height of redirection or -1 to use the height of @window
8679 * Redirects drawing into @window so that drawing to the
8680 * window in the rectangle specified by @src_x, @src_y,
8681 * @width and @height is also drawn into @drawable at
8684 * Only drawing between gdk_window_begin_paint_region() or
8685 * gdk_window_begin_paint_rect() and gdk_window_end_paint() is
8688 * Redirection is active until gdk_window_remove_redirection()
8694 gdk_window_redirect_to_drawable (GdkWindow *window,
8695 GdkDrawable *drawable,
8703 GdkWindowObject *private;
8705 g_return_if_fail (GDK_IS_WINDOW (window));
8706 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
8707 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
8709 private = (GdkWindowObject *) window;
8711 if (private->redirect)
8712 gdk_window_remove_redirection (window);
8714 if (width == -1 || height == -1)
8717 gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
8724 private->redirect = g_new0 (GdkWindowRedirect, 1);
8725 private->redirect->redirected = private;
8726 private->redirect->pixmap = g_object_ref (drawable);
8727 private->redirect->src_x = src_x;
8728 private->redirect->src_y = src_y;
8729 private->redirect->dest_x = dest_x;
8730 private->redirect->dest_y = dest_y;
8731 private->redirect->width = width;
8732 private->redirect->height = height;
8734 apply_redirect_to_children (private, private->redirect);
8738 window_get_size_rectangle (GdkWindow *window,
8741 GdkWindowObject *private = (GdkWindowObject *) window;
8743 rect->x = rect->y = 0;
8744 rect->width = private->width;
8745 rect->height = private->height;
8748 /* Calculates the real clipping region for a window, in window coordinates,
8749 * taking into account other windows, gc clip region and gc clip mask.
8752 _gdk_window_calculate_full_clip_region (GdkWindow *window,
8753 GdkWindow *base_window,
8754 gboolean do_children,
8755 gint *base_x_offset,
8756 gint *base_y_offset)
8758 GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
8759 GdkRectangle visible_rect;
8760 GdkRegion *real_clip_region, *tmpreg;
8761 gint x_offset, y_offset;
8762 GdkWindowObject *parentwin, *lastwin;
8769 if (!private->viewable || private->input_only)
8770 return gdk_region_new ();
8772 window_get_size_rectangle (window, &visible_rect);
8774 /* real_clip_region is in window coordinates */
8775 real_clip_region = gdk_region_rectangle (&visible_rect);
8777 x_offset = y_offset = 0;
8781 parentwin = lastwin;
8783 parentwin = lastwin->parent;
8785 /* Remove the areas of all overlapping windows above parentwin in the hiearachy */
8786 for (; parentwin != NULL &&
8787 (parentwin == private || lastwin != (GdkWindowObject*) base_window);
8788 lastwin = parentwin, parentwin = lastwin->parent)
8791 GdkRectangle real_clip_rect;
8793 if (parentwin != private)
8795 x_offset += GDK_WINDOW_OBJECT (lastwin)->x;
8796 y_offset += GDK_WINDOW_OBJECT (lastwin)->y;
8799 /* children is ordered in reverse stack order */
8800 for (cur = parentwin->children;
8801 cur && cur->data != lastwin;
8804 GdkWindow *child = cur->data;
8805 GdkWindowObject *child_private = (GdkWindowObject *)child;
8807 if (!GDK_WINDOW_IS_MAPPED (child) || child_private->input_only)
8810 /* Ignore offscreen children, as they don't draw in their parent and
8811 * don't take part in the clipping */
8812 if (gdk_window_is_offscreen (child_private))
8815 window_get_size_rectangle (child, &visible_rect);
8817 /* Convert rect to "window" coords */
8818 visible_rect.x += child_private->x - x_offset;
8819 visible_rect.y += child_private->y - y_offset;
8821 /* This shortcut is really necessary for performance when there are a lot of windows */
8822 gdk_region_get_clipbox (real_clip_region, &real_clip_rect);
8823 if (visible_rect.x >= real_clip_rect.x + real_clip_rect.width ||
8824 visible_rect.x + visible_rect.width <= real_clip_rect.x ||
8825 visible_rect.y >= real_clip_rect.y + real_clip_rect.height ||
8826 visible_rect.y + visible_rect.height <= real_clip_rect.y)
8829 tmpreg = gdk_region_rectangle (&visible_rect);
8830 gdk_region_subtract (real_clip_region, tmpreg);
8831 gdk_region_destroy (tmpreg);
8834 /* Clip to the parent */
8835 window_get_size_rectangle ((GdkWindow *)parentwin, &visible_rect);
8836 /* Convert rect to "window" coords */
8837 visible_rect.x += - x_offset;
8838 visible_rect.y += - y_offset;
8840 tmpreg = gdk_region_rectangle (&visible_rect);
8841 gdk_region_intersect (real_clip_region, tmpreg);
8842 gdk_region_destroy (tmpreg);
8846 *base_x_offset = x_offset;
8848 *base_y_offset = y_offset;
8850 return real_clip_region;
8854 _gdk_window_add_damage (GdkWindow *toplevel,
8855 GdkRegion *damaged_region)
8857 GdkDisplay *display;
8858 GdkEvent event = { 0, };
8859 event.expose.type = GDK_DAMAGE;
8860 event.expose.window = toplevel;
8861 event.expose.send_event = FALSE;
8862 event.expose.region = damaged_region;
8863 gdk_region_get_clipbox (event.expose.region, &event.expose.area);
8864 display = gdk_drawable_get_display (event.expose.window);
8865 _gdk_event_queue_append (display, gdk_event_copy (&event));
8869 gdk_window_redirect_free (GdkWindowRedirect *redirect)
8871 g_object_unref (redirect->pixmap);
8875 /* Gets the toplevel for a window as used for events,
8876 i.e. including offscreen parents */
8877 static GdkWindowObject *
8878 get_event_parent (GdkWindowObject *window)
8880 if (window->window_type == GDK_WINDOW_OFFSCREEN)
8881 return (GdkWindowObject *)gdk_offscreen_window_get_embedder ((GdkWindow *)window);
8883 return window->parent;
8886 /* Gets the toplevel for a window as used for events,
8887 i.e. including offscreen parents going up to the native
8890 get_event_toplevel (GdkWindow *w)
8892 GdkWindowObject *private = GDK_WINDOW_OBJECT (w);
8893 GdkWindowObject *parent;
8895 while ((parent = get_event_parent (private)) != NULL &&
8896 (parent->window_type != GDK_WINDOW_ROOT))
8899 return GDK_WINDOW (private);
8903 _gdk_window_event_parent_of (GdkWindow *parent,
8914 w = (GdkWindow *)get_event_parent ((GdkWindowObject *)w);
8921 update_cursor (GdkDisplay *display)
8923 GdkWindowObject *cursor_window, *parent, *toplevel;
8924 GdkWindow *pointer_window;
8925 GdkWindowImplIface *impl_iface;
8926 GdkPointerGrabInfo *grab;
8928 pointer_window = display->pointer_info.window_under_pointer;
8930 /* We ignore the serials here and just pick the last grab
8931 we've sent, as that would shortly be used anyway. */
8932 grab = _gdk_display_get_last_pointer_grab (display);
8935 /* the pointer is not in a descendant of the grab window */
8936 !_gdk_window_event_parent_of (grab->window, pointer_window))
8937 /* use the cursor from the grab window */
8938 cursor_window = (GdkWindowObject *)grab->window;
8940 /* otherwise use the cursor from the pointer window */
8941 cursor_window = (GdkWindowObject *)pointer_window;
8943 /* Find the first window with the cursor actually set, as
8944 the cursor is inherited from the parent */
8945 while (cursor_window->cursor == NULL &&
8946 (parent = get_event_parent (cursor_window)) != NULL &&
8947 parent->window_type != GDK_WINDOW_ROOT)
8948 cursor_window = parent;
8950 /* Set all cursors on toplevel, otherwise its tricky to keep track of
8951 * which native window has what cursor set. */
8952 toplevel = (GdkWindowObject *)get_event_toplevel (pointer_window);
8953 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (toplevel->impl);
8954 impl_iface->set_cursor ((GdkWindow *)toplevel, cursor_window->cursor);
8958 from_embedder (GdkWindowObject *window,
8961 gdouble *offscreen_x,
8962 gdouble *offscreen_y)
8964 g_signal_emit (window,
8965 signals[FROM_EMBEDDER], 0,
8966 embedder_x, embedder_y,
8967 offscreen_x, offscreen_y,
8972 convert_coords_to_child (GdkWindowObject *child,
8978 if (gdk_window_is_offscreen (child))
8980 from_embedder (child, x, y,
8985 *child_x = x - child->x;
8986 *child_y = y - child->y;
8991 point_in_window (GdkWindowObject *window,
8996 x >= 0 && x < window->width &&
8997 y >= 0 && y < window->height &&
8998 (window->shape == NULL ||
8999 gdk_region_point_in (window->shape,
9001 (window->input_shape == NULL ||
9002 gdk_region_point_in (window->input_shape,
9007 convert_native_coords_to_toplevel (GdkWindow *window,
9010 gdouble *toplevel_x,
9011 gdouble *toplevel_y)
9013 GdkWindowObject *private = (GdkWindowObject *)window;
9019 while (!gdk_window_is_toplevel (private))
9023 private = private->parent;
9029 return (GdkWindow *)private;
9033 convert_toplevel_coords_to_window (GdkWindow *window,
9039 GdkWindowObject *private;
9040 GdkWindowObject *parent;
9042 GList *children, *l;
9044 private = GDK_WINDOW_OBJECT (window);
9050 while ((parent = get_event_parent (private)) != NULL &&
9051 (parent->window_type != GDK_WINDOW_ROOT))
9053 children = g_list_prepend (children, private);
9057 for (l = children; l != NULL; l = l->next)
9058 convert_coords_to_child (l->data, x, y, &x, &y);
9060 g_list_free (children);
9066 static GdkWindowObject *
9067 pick_embedded_child (GdkWindowObject *window,
9071 GdkWindowObject *res;
9074 g_signal_emit (window,
9075 signals[PICK_EMBEDDED_CHILD], 0,
9082 _gdk_window_find_child_at (GdkWindow *window,
9086 GdkWindowObject *private, *sub;
9087 double child_x, child_y;
9090 private = (GdkWindowObject *)window;
9092 if (point_in_window (private, x, y))
9094 /* Children is ordered in reverse stack order, i.e. first is topmost */
9095 for (l = private->children; l != NULL; l = l->next)
9099 if (!GDK_WINDOW_IS_MAPPED (sub))
9102 convert_coords_to_child (sub,
9104 &child_x, &child_y);
9105 if (point_in_window (sub, child_x, child_y))
9106 return (GdkWindow *)sub;
9109 if (private->num_offscreen_children > 0)
9111 sub = pick_embedded_child (private,
9114 return (GdkWindow *)sub;
9122 _gdk_window_find_descendant_at (GdkWindow *toplevel,
9128 GdkWindowObject *private, *sub;
9129 gdouble child_x, child_y;
9133 private = (GdkWindowObject *)toplevel;
9135 if (point_in_window (private, x, y))
9140 /* Children is ordered in reverse stack order, i.e. first is topmost */
9141 for (l = private->children; l != NULL; l = l->next)
9145 if (!GDK_WINDOW_IS_MAPPED (sub))
9148 convert_coords_to_child (sub,
9150 &child_x, &child_y);
9151 if (point_in_window (sub, child_x, child_y))
9161 private->num_offscreen_children > 0)
9163 sub = pick_embedded_child (private,
9169 from_embedder (sub, x, y, &x, &y);
9177 /* Not in window at all */
9186 return (GdkWindow *)private;
9191 * @window: a toplevel #GdkWindow
9193 * Emits a short beep associated to @window in the appropriate
9194 * display, if supported. Otherwise, emits a short beep on
9195 * the display just as gdk_display_beep().
9200 gdk_window_beep (GdkWindow *window)
9202 GdkDisplay *display;
9203 GdkWindow *toplevel;
9205 g_return_if_fail (GDK_IS_WINDOW (window));
9207 if (GDK_WINDOW_DESTROYED (window))
9210 toplevel = get_event_toplevel (window);
9211 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
9213 if (toplevel && !gdk_window_is_offscreen ((GdkWindowObject *)toplevel))
9214 _gdk_windowing_window_beep (toplevel);
9216 gdk_display_beep (display);
9219 static const guint type_masks[] = {
9220 GDK_SUBSTRUCTURE_MASK, /* GDK_DELETE = 0 */
9221 GDK_STRUCTURE_MASK, /* GDK_DESTROY = 1 */
9222 GDK_EXPOSURE_MASK, /* GDK_EXPOSE = 2 */
9223 GDK_POINTER_MOTION_MASK, /* GDK_MOTION_NOTIFY = 3 */
9224 GDK_BUTTON_PRESS_MASK, /* GDK_BUTTON_PRESS = 4 */
9225 GDK_BUTTON_PRESS_MASK, /* GDK_2BUTTON_PRESS = 5 */
9226 GDK_BUTTON_PRESS_MASK, /* GDK_3BUTTON_PRESS = 6 */
9227 GDK_BUTTON_RELEASE_MASK, /* GDK_BUTTON_RELEASE = 7 */
9228 GDK_KEY_PRESS_MASK, /* GDK_KEY_PRESS = 8 */
9229 GDK_KEY_RELEASE_MASK, /* GDK_KEY_RELEASE = 9 */
9230 GDK_ENTER_NOTIFY_MASK, /* GDK_ENTER_NOTIFY = 10 */
9231 GDK_LEAVE_NOTIFY_MASK, /* GDK_LEAVE_NOTIFY = 11 */
9232 GDK_FOCUS_CHANGE_MASK, /* GDK_FOCUS_CHANGE = 12 */
9233 GDK_STRUCTURE_MASK, /* GDK_CONFIGURE = 13 */
9234 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_MAP = 14 */
9235 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_UNMAP = 15 */
9236 GDK_PROPERTY_CHANGE_MASK, /* GDK_PROPERTY_NOTIFY = 16 */
9237 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_CLEAR = 17 */
9238 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_REQUEST = 18 */
9239 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_NOTIFY = 19 */
9240 GDK_PROXIMITY_IN_MASK, /* GDK_PROXIMITY_IN = 20 */
9241 GDK_PROXIMITY_OUT_MASK, /* GDK_PROXIMITY_OUT = 21 */
9242 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_ENTER = 22 */
9243 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_LEAVE = 23 */
9244 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_MOTION = 24 */
9245 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_STATUS = 25 */
9246 GDK_ALL_EVENTS_MASK, /* GDK_DROP_START = 26 */
9247 GDK_ALL_EVENTS_MASK, /* GDK_DROP_FINISHED = 27 */
9248 GDK_ALL_EVENTS_MASK, /* GDK_CLIENT_EVENT = 28 */
9249 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_VISIBILITY_NOTIFY = 29 */
9250 GDK_EXPOSURE_MASK, /* GDK_NO_EXPOSE = 30 */
9251 GDK_SCROLL_MASK | GDK_BUTTON_PRESS_MASK,/* GDK_SCROLL= 31 */
9252 0, /* GDK_WINDOW_STATE = 32 */
9253 0, /* GDK_SETTING = 33 */
9254 0, /* GDK_OWNER_CHANGE = 34 */
9255 0, /* GDK_GRAB_BROKEN = 35 */
9256 0, /* GDK_DAMAGE = 36 */
9258 G_STATIC_ASSERT (G_N_ELEMENTS (type_masks) == GDK_EVENT_LAST);
9260 /* send motion events if the right buttons are down */
9262 update_evmask_for_button_motion (guint evmask,
9263 GdkModifierType mask)
9265 if (evmask & GDK_BUTTON_MOTION_MASK &&
9266 mask & (GDK_BUTTON1_MASK |
9271 evmask |= GDK_POINTER_MOTION_MASK;
9273 if ((evmask & GDK_BUTTON1_MOTION_MASK && mask & GDK_BUTTON1_MASK) ||
9274 (evmask & GDK_BUTTON2_MOTION_MASK && mask & GDK_BUTTON2_MASK) ||
9275 (evmask & GDK_BUTTON3_MOTION_MASK && mask & GDK_BUTTON3_MASK))
9276 evmask |= GDK_POINTER_MOTION_MASK;
9282 is_button_type (GdkEventType type)
9284 return type == GDK_BUTTON_PRESS ||
9285 type == GDK_2BUTTON_PRESS ||
9286 type == GDK_3BUTTON_PRESS ||
9287 type == GDK_BUTTON_RELEASE ||
9292 is_motion_type (GdkEventType type)
9294 return type == GDK_MOTION_NOTIFY ||
9295 type == GDK_ENTER_NOTIFY ||
9296 type == GDK_LEAVE_NOTIFY;
9299 static GdkWindowObject *
9300 find_common_ancestor (GdkWindowObject *win1,
9301 GdkWindowObject *win2)
9303 GdkWindowObject *tmp;
9304 GList *path1 = NULL, *path2 = NULL;
9305 GList *list1, *list2;
9308 while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
9310 path1 = g_list_prepend (path1, tmp);
9311 tmp = get_event_parent (tmp);
9315 while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
9317 path2 = g_list_prepend (path2, tmp);
9318 tmp = get_event_parent (tmp);
9324 while (list1 && list2 && (list1->data == list2->data))
9326 tmp = (GdkWindowObject *)list1->data;
9327 list1 = g_list_next (list1);
9328 list2 = g_list_next (list2);
9330 g_list_free (path1);
9331 g_list_free (path2);
9337 _gdk_make_event (GdkWindow *window,
9339 GdkEvent *event_in_queue,
9340 gboolean before_event)
9342 GdkEvent *event = gdk_event_new (type);
9344 GdkModifierType the_state;
9346 the_time = gdk_event_get_time (event_in_queue);
9347 gdk_event_get_state (event_in_queue, &the_state);
9349 event->any.window = g_object_ref (window);
9350 event->any.send_event = FALSE;
9351 if (event_in_queue && event_in_queue->any.send_event)
9352 event->any.send_event = TRUE;
9356 case GDK_MOTION_NOTIFY:
9357 event->motion.time = the_time;
9358 event->motion.axes = NULL;
9359 event->motion.state = the_state;
9362 case GDK_BUTTON_PRESS:
9363 case GDK_2BUTTON_PRESS:
9364 case GDK_3BUTTON_PRESS:
9365 case GDK_BUTTON_RELEASE:
9366 event->button.time = the_time;
9367 event->button.axes = NULL;
9368 event->button.state = the_state;
9372 event->scroll.time = the_time;
9373 event->scroll.state = the_state;
9377 case GDK_KEY_RELEASE:
9378 event->key.time = the_time;
9379 event->key.state = the_state;
9382 case GDK_ENTER_NOTIFY:
9383 case GDK_LEAVE_NOTIFY:
9384 event->crossing.time = the_time;
9385 event->crossing.state = the_state;
9388 case GDK_PROPERTY_NOTIFY:
9389 event->property.time = the_time;
9390 event->property.state = the_state;
9393 case GDK_SELECTION_CLEAR:
9394 case GDK_SELECTION_REQUEST:
9395 case GDK_SELECTION_NOTIFY:
9396 event->selection.time = the_time;
9399 case GDK_PROXIMITY_IN:
9400 case GDK_PROXIMITY_OUT:
9401 event->proximity.time = the_time;
9404 case GDK_DRAG_ENTER:
9405 case GDK_DRAG_LEAVE:
9406 case GDK_DRAG_MOTION:
9407 case GDK_DRAG_STATUS:
9408 case GDK_DROP_START:
9409 case GDK_DROP_FINISHED:
9410 event->dnd.time = the_time;
9413 case GDK_FOCUS_CHANGE:
9417 case GDK_CLIENT_EVENT:
9418 case GDK_VISIBILITY_NOTIFY:
9430 _gdk_event_queue_insert_before (gdk_drawable_get_display (window), event_in_queue, event);
9432 _gdk_event_queue_insert_after (gdk_drawable_get_display (window), event_in_queue, event);
9435 _gdk_event_queue_append (gdk_drawable_get_display (window), event);
9441 send_crossing_event (GdkDisplay *display,
9442 GdkWindowObject *toplevel,
9443 GdkWindowObject *window,
9445 GdkCrossingMode mode,
9446 GdkNotifyType notify_type,
9447 GdkWindow *subwindow,
9450 GdkModifierType mask,
9452 GdkEvent *event_in_queue,
9456 guint32 window_event_mask, type_event_mask;
9457 GdkPointerGrabInfo *grab;
9458 GdkWindowImplIface *impl_iface;
9460 grab = _gdk_display_has_pointer_grab (display, serial);
9463 !grab->owner_events)
9465 /* !owner_event => only report events wrt grab window, ignore rest */
9466 if ((GdkWindow *)window != grab->window)
9468 window_event_mask = grab->event_mask;
9471 window_event_mask = window->event_mask;
9473 if (type == GDK_LEAVE_NOTIFY)
9474 type_event_mask = GDK_LEAVE_NOTIFY_MASK;
9476 type_event_mask = GDK_ENTER_NOTIFY_MASK;
9478 if (window->extension_events != 0)
9480 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (window->impl);
9481 impl_iface->input_window_crossing ((GdkWindow *)window,
9482 type == GDK_ENTER_NOTIFY);
9485 if (window_event_mask & type_event_mask)
9487 event = _gdk_make_event ((GdkWindow *)window, type, event_in_queue, TRUE);
9488 event->crossing.time = time_;
9489 event->crossing.subwindow = subwindow;
9491 g_object_ref (subwindow);
9492 convert_toplevel_coords_to_window ((GdkWindow *)window,
9493 toplevel_x, toplevel_y,
9494 &event->crossing.x, &event->crossing.y);
9495 event->crossing.x_root = toplevel_x + toplevel->x;
9496 event->crossing.y_root = toplevel_y + toplevel->y;
9497 event->crossing.mode = mode;
9498 event->crossing.detail = notify_type;
9499 event->crossing.focus = FALSE;
9500 event->crossing.state = mask;
9505 /* The coordinates are in the toplevel window that src/dest are in.
9506 * src and dest are always (if != NULL) in the same toplevel, as
9507 * we get a leave-notify and set the window_under_pointer to null
9508 * before crossing to another toplevel.
9511 _gdk_synthesize_crossing_events (GdkDisplay *display,
9514 GdkCrossingMode mode,
9517 GdkModifierType mask,
9519 GdkEvent *event_in_queue,
9521 gboolean non_linear)
9524 GdkWindowObject *win, *last, *next;
9528 GdkWindowObject *toplevel;
9529 GdkNotifyType notify_type;
9531 /* TODO: Don't send events to toplevel, as we get those from the windowing system */
9533 a = (GdkWindowObject *)src;
9534 b = (GdkWindowObject *)dest;
9536 return; /* No crossings generated between src and dest */
9538 c = find_common_ancestor (a, b);
9540 non_linear |= (c != a) && (c != b);
9542 if (a) /* There might not be a source (i.e. if no previous pointer_in_window) */
9544 toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)a);
9546 /* Traverse up from a to (excluding) c sending leave events */
9548 notify_type = GDK_NOTIFY_NONLINEAR;
9550 notify_type = GDK_NOTIFY_INFERIOR;
9552 notify_type = GDK_NOTIFY_ANCESTOR;
9553 send_crossing_event (display, toplevel,
9554 a, GDK_LEAVE_NOTIFY,
9558 toplevel_x, toplevel_y,
9566 notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
9568 notify_type = GDK_NOTIFY_VIRTUAL;
9571 win = get_event_parent (a);
9572 while (win != c && win->window_type != GDK_WINDOW_ROOT)
9574 send_crossing_event (display, toplevel,
9575 win, GDK_LEAVE_NOTIFY,
9579 toplevel_x, toplevel_y,
9585 win = get_event_parent (win);
9590 if (b) /* Might not be a dest, e.g. if we're moving out of the window */
9592 toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)b);
9594 /* Traverse down from c to b */
9598 win = get_event_parent (b);
9599 while (win != c && win->window_type != GDK_WINDOW_ROOT)
9601 path = g_list_prepend (path, win);
9602 win = get_event_parent (win);
9606 notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
9608 notify_type = GDK_NOTIFY_VIRTUAL;
9613 win = (GdkWindowObject *)list->data;
9614 list = g_list_next (list);
9616 next = (GdkWindowObject *)list->data;
9620 send_crossing_event (display, toplevel,
9621 win, GDK_ENTER_NOTIFY,
9625 toplevel_x, toplevel_y,
9635 notify_type = GDK_NOTIFY_NONLINEAR;
9637 notify_type = GDK_NOTIFY_ANCESTOR;
9639 notify_type = GDK_NOTIFY_INFERIOR;
9641 send_crossing_event (display, toplevel,
9642 b, GDK_ENTER_NOTIFY,
9646 toplevel_x, toplevel_y,
9653 /* Returns the window inside the event window with the pointer in it
9654 * at the specified coordinates, or NULL if its not in any child of
9655 * the toplevel. It also takes into account !owner_events grabs.
9658 get_pointer_window (GdkDisplay *display,
9659 GdkWindow *event_window,
9664 GdkWindow *pointer_window;
9665 GdkPointerGrabInfo *grab;
9667 if (event_window == display->pointer_info.toplevel_under_pointer)
9669 _gdk_window_find_descendant_at (event_window,
9670 toplevel_x, toplevel_y,
9673 pointer_window = NULL;
9675 grab = _gdk_display_has_pointer_grab (display, serial);
9677 !grab->owner_events &&
9678 pointer_window != grab->window)
9679 pointer_window = NULL;
9681 return pointer_window;
9685 _gdk_display_set_window_under_pointer (GdkDisplay *display,
9688 /* We don't track this if all native, and it can cause issues
9689 with the update_cursor call below */
9690 if (_gdk_native_windows)
9693 if (display->pointer_info.window_under_pointer)
9694 g_object_unref (display->pointer_info.window_under_pointer);
9695 display->pointer_info.window_under_pointer = window;
9697 g_object_ref (window);
9700 update_cursor (display);
9702 _gdk_display_enable_motion_hints (display);
9706 *--------------------------------------------------------------
9709 * Grabs the pointer to a specific window
9712 * "window" is the window which will receive the grab
9713 * "owner_events" specifies whether events will be reported as is,
9714 * or relative to "window"
9715 * "event_mask" masks only interesting events
9716 * "confine_to" limits the cursor movement to the specified window
9717 * "cursor" changes the cursor for the duration of the grab
9718 * "time" specifies the time
9723 * requires a corresponding call to gdk_pointer_ungrab
9725 *--------------------------------------------------------------
9728 gdk_pointer_grab (GdkWindow * window,
9729 gboolean owner_events,
9730 GdkEventMask event_mask,
9731 GdkWindow * confine_to,
9736 GdkDisplay *display;
9740 g_return_val_if_fail (window != NULL, 0);
9741 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
9742 g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
9744 /* We need a native window for confine to to work, ensure we have one */
9747 if (!gdk_window_ensure_native (confine_to))
9749 g_warning ("Can't confine to grabbed window, not native");
9754 /* Non-viewable client side window => fail */
9755 if (!_gdk_window_has_impl (window) &&
9756 !gdk_window_is_viewable (window))
9757 return GDK_GRAB_NOT_VIEWABLE;
9759 if (_gdk_native_windows)
9762 native = gdk_window_get_toplevel (window);
9763 while (gdk_window_is_offscreen ((GdkWindowObject *)native))
9765 native = gdk_offscreen_window_get_embedder (native);
9767 if (native == NULL ||
9768 (!_gdk_window_has_impl (native) &&
9769 !gdk_window_is_viewable (native)))
9770 return GDK_GRAB_NOT_VIEWABLE;
9772 native = gdk_window_get_toplevel (native);
9775 display = gdk_drawable_get_display (window);
9777 serial = _gdk_windowing_window_get_next_serial (display);
9779 res = _gdk_windowing_pointer_grab (window,
9782 get_native_grab_event_mask (event_mask),
9787 if (res == GDK_GRAB_SUCCESS)
9788 _gdk_display_add_pointer_grab (display,
9801 * gdk_window_geometry_changed:
9802 * @window: an embedded offscreen #GdkWindow
9804 * This function informs GDK that the geometry of an embedded
9805 * offscreen window has changed. This is necessary for GDK to keep
9806 * track of which offscreen window the pointer is in.
9811 gdk_window_geometry_changed (GdkWindow *window)
9813 _gdk_synthesize_crossing_events_for_geometry_change (window);
9817 do_synthesize_crossing_event (gpointer data)
9819 GdkDisplay *display;
9820 GdkWindow *changed_toplevel;
9821 GdkWindowObject *changed_toplevel_priv;
9822 GdkWindow *new_window_under_pointer;
9825 changed_toplevel = data;
9826 changed_toplevel_priv = (GdkWindowObject *)changed_toplevel;
9828 changed_toplevel_priv->synthesize_crossing_event_queued = FALSE;
9830 if (GDK_WINDOW_DESTROYED (changed_toplevel))
9833 display = gdk_drawable_get_display (changed_toplevel);
9834 serial = _gdk_windowing_window_get_next_serial (display);
9836 if (changed_toplevel == display->pointer_info.toplevel_under_pointer)
9838 new_window_under_pointer =
9839 get_pointer_window (display, changed_toplevel,
9840 display->pointer_info.toplevel_x,
9841 display->pointer_info.toplevel_y,
9843 if (new_window_under_pointer !=
9844 display->pointer_info.window_under_pointer)
9846 _gdk_synthesize_crossing_events (display,
9847 display->pointer_info.window_under_pointer,
9848 new_window_under_pointer,
9849 GDK_CROSSING_NORMAL,
9850 display->pointer_info.toplevel_x,
9851 display->pointer_info.toplevel_y,
9852 display->pointer_info.state,
9857 _gdk_display_set_window_under_pointer (display, new_window_under_pointer);
9865 _gdk_synthesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
9867 GdkDisplay *display;
9868 GdkWindow *toplevel;
9869 GdkWindowObject *toplevel_priv;
9871 if (_gdk_native_windows)
9872 return; /* We use the native crossing events if all native */
9874 display = gdk_drawable_get_display (changed_window);
9876 toplevel = get_event_toplevel (changed_window);
9877 toplevel_priv = (GdkWindowObject *)toplevel;
9879 if (toplevel == display->pointer_info.toplevel_under_pointer &&
9880 !toplevel_priv->synthesize_crossing_event_queued)
9882 toplevel_priv->synthesize_crossing_event_queued = TRUE;
9883 g_idle_add_full (GDK_PRIORITY_EVENTS - 1,
9884 do_synthesize_crossing_event,
9885 g_object_ref (toplevel),
9890 /* Don't use for crossing events */
9892 get_event_window (GdkDisplay *display,
9893 GdkWindow *pointer_window,
9895 GdkModifierType mask,
9900 GdkWindow *grab_window;
9902 GdkPointerGrabInfo *grab;
9904 grab = _gdk_display_has_pointer_grab (display, serial);
9906 if (grab != NULL && !grab->owner_events)
9908 evmask = grab->event_mask;
9909 evmask = update_evmask_for_button_motion (evmask, mask);
9911 grab_window = grab->window;
9913 if (evmask & type_masks[type])
9916 *evmask_out = evmask;
9923 w = (GdkWindowObject *)pointer_window;
9926 evmask = w->event_mask;
9927 evmask = update_evmask_for_button_motion (evmask, mask);
9929 if (evmask & type_masks[type])
9932 *evmask_out = evmask;
9933 return (GdkWindow *)w;
9936 w = get_event_parent (w);
9942 evmask = grab->event_mask;
9943 evmask = update_evmask_for_button_motion (evmask, mask);
9945 if (evmask & type_masks[type])
9948 *evmask_out = evmask;
9949 return grab->window;
9959 proxy_pointer_event (GdkDisplay *display,
9960 GdkEvent *source_event,
9963 GdkWindow *toplevel_window, *event_window;
9964 GdkWindow *pointer_window;
9967 gdouble toplevel_x, toplevel_y;
9969 gboolean non_linear;
9971 event_window = source_event->any.window;
9972 gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
9973 gdk_event_get_state (source_event, &state);
9974 time_ = gdk_event_get_time (source_event);
9975 toplevel_window = convert_native_coords_to_toplevel (event_window,
9976 toplevel_x, toplevel_y,
9977 &toplevel_x, &toplevel_y);
9980 if ((source_event->type == GDK_LEAVE_NOTIFY ||
9981 source_event->type == GDK_ENTER_NOTIFY) &&
9982 (source_event->crossing.detail == GDK_NOTIFY_NONLINEAR ||
9983 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))
9986 /* If we get crossing events with subwindow unexpectedly being NULL
9987 that means there is a native subwindow that gdk doesn't know about.
9988 We track these and forward them, with the correct virtual window
9990 This is important to get right, as metacity uses gdk for the frame
9991 windows, but gdk doesn't know about the client windows reparented
9993 if (((source_event->type == GDK_LEAVE_NOTIFY &&
9994 source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
9995 (source_event->type == GDK_ENTER_NOTIFY &&
9996 (source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
9997 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
9998 source_event->crossing.subwindow == NULL)
10000 /* Left for an unknown (to gdk) subwindow */
10002 /* Send leave events from window under pointer to event window
10003 that will get the subwindow == NULL window */
10004 _gdk_synthesize_crossing_events (display,
10005 display->pointer_info.window_under_pointer,
10007 source_event->crossing.mode,
10008 toplevel_x, toplevel_y,
10014 /* Send subwindow == NULL event */
10015 send_crossing_event (display,
10016 (GdkWindowObject *)toplevel_window,
10017 (GdkWindowObject *)event_window,
10018 source_event->type,
10019 source_event->crossing.mode,
10020 source_event->crossing.detail,
10022 toplevel_x, toplevel_y,
10027 _gdk_display_set_window_under_pointer (display, NULL);
10031 pointer_window = get_pointer_window (display, toplevel_window,
10032 toplevel_x, toplevel_y, serial);
10034 if (((source_event->type == GDK_ENTER_NOTIFY &&
10035 source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
10036 (source_event->type == GDK_LEAVE_NOTIFY &&
10037 (source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
10038 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
10039 source_event->crossing.subwindow == NULL)
10041 /* Entered from an unknown (to gdk) subwindow */
10043 /* Send subwindow == NULL event */
10044 send_crossing_event (display,
10045 (GdkWindowObject *)toplevel_window,
10046 (GdkWindowObject *)event_window,
10047 source_event->type,
10048 source_event->crossing.mode,
10049 source_event->crossing.detail,
10051 toplevel_x, toplevel_y,
10056 /* Send enter events from event window to pointer_window */
10057 _gdk_synthesize_crossing_events (display,
10060 source_event->crossing.mode,
10061 toplevel_x, toplevel_y,
10064 serial, non_linear);
10065 _gdk_display_set_window_under_pointer (display, pointer_window);
10069 if (display->pointer_info.window_under_pointer != pointer_window)
10071 /* Either a toplevel crossing notify that ended up inside a child window,
10072 or a motion notify that got into another child window */
10074 /* Different than last time, send crossing events */
10075 _gdk_synthesize_crossing_events (display,
10076 display->pointer_info.window_under_pointer,
10078 GDK_CROSSING_NORMAL,
10079 toplevel_x, toplevel_y,
10082 serial, non_linear);
10083 _gdk_display_set_window_under_pointer (display, pointer_window);
10085 else if (source_event->type == GDK_MOTION_NOTIFY)
10087 GdkWindow *event_win;
10091 event_win = get_event_window (display,
10093 source_event->type,
10101 (evmask & GDK_POINTER_MOTION_HINT_MASK))
10103 if (display->pointer_info.motion_hint_serial != 0 &&
10104 serial < display->pointer_info.motion_hint_serial)
10105 event_win = NULL; /* Ignore event */
10109 display->pointer_info.motion_hint_serial = G_MAXULONG;
10113 if (event_win && !display->ignore_core_events)
10115 event = _gdk_make_event (event_win, GDK_MOTION_NOTIFY, source_event, FALSE);
10116 event->motion.time = time_;
10117 convert_toplevel_coords_to_window (event_win,
10118 toplevel_x, toplevel_y,
10119 &event->motion.x, &event->motion.y);
10120 event->motion.x_root = source_event->motion.x_root;
10121 event->motion.y_root = source_event->motion.y_root;;
10122 event->motion.state = state;
10123 event->motion.is_hint = is_hint;
10124 event->motion.device = NULL;
10125 event->motion.device = source_event->motion.device;
10129 /* unlink all move events from queue.
10130 We handle our own, including our emulated masks. */
10134 #define GDK_ANY_BUTTON_MASK (GDK_BUTTON1_MASK | \
10135 GDK_BUTTON2_MASK | \
10136 GDK_BUTTON3_MASK | \
10137 GDK_BUTTON4_MASK | \
10141 proxy_button_event (GdkEvent *source_event,
10144 GdkWindow *toplevel_window, *event_window;
10145 GdkWindow *event_win;
10146 GdkWindow *pointer_window;
10147 GdkWindowObject *parent;
10152 gdouble toplevel_x, toplevel_y;
10153 GdkDisplay *display;
10154 GdkWindowObject *w;
10156 type = source_event->any.type;
10157 event_window = source_event->any.window;
10158 gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
10159 gdk_event_get_state (source_event, &state);
10160 time_ = gdk_event_get_time (source_event);
10161 display = gdk_drawable_get_display (source_event->any.window);
10162 toplevel_window = convert_native_coords_to_toplevel (event_window,
10163 toplevel_x, toplevel_y,
10164 &toplevel_x, &toplevel_y);
10166 if (type == GDK_BUTTON_PRESS &&
10167 !source_event->any.send_event &&
10168 _gdk_display_has_pointer_grab (display, serial) == NULL)
10171 _gdk_window_find_descendant_at (toplevel_window,
10172 toplevel_x, toplevel_y,
10175 /* Find the event window, that gets the grab */
10176 w = (GdkWindowObject *)pointer_window;
10177 while (w != NULL &&
10178 (parent = get_event_parent (w)) != NULL &&
10179 parent->window_type != GDK_WINDOW_ROOT)
10181 if (w->event_mask & GDK_BUTTON_PRESS_MASK)
10185 pointer_window = (GdkWindow *)w;
10187 _gdk_display_add_pointer_grab (display,
10191 gdk_window_get_events (pointer_window),
10195 _gdk_display_pointer_grab_update (display, serial);
10198 pointer_window = get_pointer_window (display, toplevel_window,
10199 toplevel_x, toplevel_y,
10202 event_win = get_event_window (display,
10207 if (event_win == NULL || display->ignore_core_events)
10210 event = _gdk_make_event (event_win, type, source_event, FALSE);
10214 case GDK_BUTTON_PRESS:
10215 case GDK_BUTTON_RELEASE:
10216 event->button.button = source_event->button.button;
10217 convert_toplevel_coords_to_window (event_win,
10218 toplevel_x, toplevel_y,
10219 &event->button.x, &event->button.y);
10220 event->button.x_root = source_event->button.x_root;
10221 event->button.y_root = source_event->button.y_root;
10222 event->button.state = state;
10223 event->button.device = source_event->button.device;
10225 if (type == GDK_BUTTON_PRESS)
10226 _gdk_event_button_generate (display, event);
10230 event->scroll.direction = source_event->scroll.direction;
10231 convert_toplevel_coords_to_window (event_win,
10232 toplevel_x, toplevel_y,
10233 &event->scroll.x, &event->scroll.y);
10234 event->scroll.x_root = source_event->scroll.x_root;
10235 event->scroll.y_root = source_event->scroll.y_root;
10236 event->scroll.state = state;
10237 event->scroll.device = source_event->scroll.device;
10244 return TRUE; /* Always unlink original, we want to obey the emulated event mask */
10247 #ifdef DEBUG_WINDOW_PRINTING
10249 gdk_window_print (GdkWindowObject *window,
10253 const char *window_types[] = {
10263 g_print ("%*s%p: [%s] %d,%d %dx%d", indent, "", window,
10264 window->user_data ? g_type_name_from_instance (window->user_data) : "no widget",
10265 window->x, window->y,
10266 window->width, window->height
10269 if (gdk_window_has_impl (window))
10271 #ifdef GDK_WINDOWING_X11
10272 g_print (" impl(0x%lx)", gdk_x11_drawable_get_xid (GDK_DRAWABLE (window)));
10276 if (window->window_type != GDK_WINDOW_CHILD)
10277 g_print (" %s", window_types[window->window_type]);
10279 if (window->input_only)
10280 g_print (" input-only");
10282 if (window->shaped)
10283 g_print (" shaped");
10285 if (!gdk_window_is_visible ((GdkWindow *)window))
10286 g_print (" hidden");
10288 g_print (" abs[%d,%d]",
10289 window->abs_x, window->abs_y);
10291 gdk_region_get_clipbox (window->clip_region, &r);
10292 if (gdk_region_empty (window->clip_region))
10293 g_print (" clipbox[empty]");
10295 g_print (" clipbox[%d,%d %dx%d]", r.x, r.y, r.width, r.height);
10302 gdk_window_print_tree (GdkWindow *window,
10304 gboolean include_input_only)
10306 GdkWindowObject *private;
10309 private = (GdkWindowObject *)window;
10311 if (private->input_only && !include_input_only)
10314 gdk_window_print (private, indent);
10316 for (l = private->children; l != NULL; l = l->next)
10317 gdk_window_print_tree (l->data, indent + 4, include_input_only);
10320 #endif /* DEBUG_WINDOW_PRINTING */
10323 is_input_event (GdkDisplay *display,
10326 GdkDevice *core_pointer;
10328 core_pointer = gdk_display_get_core_pointer (display);
10329 if ((event->type == GDK_MOTION_NOTIFY &&
10330 event->motion.device != core_pointer) ||
10331 ((event->type == GDK_BUTTON_PRESS ||
10332 event->type == GDK_BUTTON_RELEASE) &&
10333 event->button.device != core_pointer))
10339 _gdk_windowing_got_event (GdkDisplay *display,
10344 GdkWindow *event_window;
10345 GdkWindowObject *event_private;
10347 gboolean unlink_event;
10348 guint old_state, old_button;
10349 GdkPointerGrabInfo *button_release_grab;
10350 gboolean is_toplevel;
10352 if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
10353 display->last_event_time = gdk_event_get_time (event);
10355 _gdk_display_pointer_grab_update (display,
10358 event_window = event->any.window;
10362 event_private = GDK_WINDOW_OBJECT (event_window);
10364 #ifdef DEBUG_WINDOW_PRINTING
10365 if (event->type == GDK_KEY_PRESS &&
10366 (event->key.keyval == 0xa7 ||
10367 event->key.keyval == 0xbd))
10369 gdk_window_print_tree (event_window, 0,
10370 event->key.keyval == 0xbd);
10374 if (_gdk_native_windows)
10376 if (event->type == GDK_BUTTON_PRESS &&
10377 !event->any.send_event &&
10378 _gdk_display_has_pointer_grab (display, serial) == NULL)
10380 _gdk_display_add_pointer_grab (display,
10384 gdk_window_get_events (event_window),
10386 gdk_event_get_time (event),
10388 _gdk_display_pointer_grab_update (display,
10391 if (event->type == GDK_BUTTON_RELEASE &&
10392 !event->any.send_event)
10394 button_release_grab =
10395 _gdk_display_has_pointer_grab (display, serial);
10396 if (button_release_grab &&
10397 button_release_grab->implicit &&
10398 (event->button.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
10400 button_release_grab->serial_end = serial;
10401 button_release_grab->implicit_ungrab = FALSE;
10402 _gdk_display_pointer_grab_update (display, serial);
10406 if (event->type == GDK_BUTTON_PRESS)
10407 _gdk_event_button_generate (display, event);
10412 if (event->type == GDK_VISIBILITY_NOTIFY)
10414 event_private->native_visibility = event->visibility.state;
10415 gdk_window_update_visibility_recursively (event_private,
10420 if (is_input_event (display, event))
10423 if (!(is_button_type (event->type) ||
10424 is_motion_type (event->type)) ||
10425 event_private->window_type == GDK_WINDOW_ROOT)
10428 is_toplevel = gdk_window_is_toplevel (event_private);
10430 if ((event->type == GDK_ENTER_NOTIFY ||
10431 event->type == GDK_LEAVE_NOTIFY) &&
10432 (event->crossing.mode == GDK_CROSSING_GRAB ||
10433 event->crossing.mode == GDK_CROSSING_UNGRAB) &&
10434 (_gdk_display_has_pointer_grab (display, serial) ||
10435 event->crossing.detail == GDK_NOTIFY_INFERIOR))
10437 /* We synthesize all crossing events due to grabs ourselves,
10438 * so we ignore the native ones caused by our native pointer_grab
10439 * calls. Otherwise we would proxy these crossing event and cause
10440 * multiple copies of crossing events for grabs.
10442 * We do want to handle grabs from other clients though, as for
10443 * instance alt-tab in metacity causes grabs like these and
10444 * we want to handle those. Thus the has_pointer_grab check.
10446 * Implicit grabs on child windows create some grabbing events
10447 * that are sent before the button press. This means we can't
10448 * detect these with the has_pointer_grab check (as the implicit
10449 * grab is only noticed when we get button press event), so we
10450 * detect these events by checking for INFERIOR enter or leave
10451 * events. These should never be a problem to filter out.
10454 /* We ended up in this window after some (perhaps other clients)
10455 grab, so update the toplevel_under_window state */
10457 event->type == GDK_ENTER_NOTIFY &&
10458 event->crossing.mode == GDK_CROSSING_UNGRAB)
10460 if (display->pointer_info.toplevel_under_pointer)
10461 g_object_unref (display->pointer_info.toplevel_under_pointer);
10462 display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
10465 unlink_event = TRUE;
10469 /* Track toplevel_under_pointer */
10472 if (event->type == GDK_ENTER_NOTIFY &&
10473 event->crossing.detail != GDK_NOTIFY_INFERIOR)
10475 if (display->pointer_info.toplevel_under_pointer)
10476 g_object_unref (display->pointer_info.toplevel_under_pointer);
10477 display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
10479 else if (event->type == GDK_LEAVE_NOTIFY &&
10480 event->crossing.detail != GDK_NOTIFY_INFERIOR &&
10481 display->pointer_info.toplevel_under_pointer == event_window)
10483 if (display->pointer_info.toplevel_under_pointer)
10484 g_object_unref (display->pointer_info.toplevel_under_pointer);
10485 display->pointer_info.toplevel_under_pointer = NULL;
10489 /* Store last pointer window and position/state */
10490 old_state = display->pointer_info.state;
10491 old_button = display->pointer_info.button;
10493 gdk_event_get_coords (event, &x, &y);
10494 convert_native_coords_to_toplevel (event_window, x, y, &x, &y);
10495 display->pointer_info.toplevel_x = x;
10496 display->pointer_info.toplevel_y = y;
10497 gdk_event_get_state (event, &display->pointer_info.state);
10498 if (event->type == GDK_BUTTON_PRESS ||
10499 event->type == GDK_BUTTON_RELEASE)
10500 display->pointer_info.button = event->button.button;
10502 if (display->pointer_info.state != old_state ||
10503 display->pointer_info.button != old_button)
10504 _gdk_display_enable_motion_hints (display);
10506 unlink_event = FALSE;
10507 if (is_motion_type (event->type))
10508 unlink_event = proxy_pointer_event (display,
10511 else if (is_button_type (event->type))
10512 unlink_event = proxy_button_event (event,
10515 if (event->type == GDK_BUTTON_RELEASE &&
10516 !event->any.send_event)
10518 button_release_grab =
10519 _gdk_display_has_pointer_grab (display, serial);
10520 if (button_release_grab &&
10521 button_release_grab->implicit &&
10522 (event->button.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
10524 button_release_grab->serial_end = serial;
10525 button_release_grab->implicit_ungrab = FALSE;
10526 _gdk_display_pointer_grab_update (display, serial);
10533 _gdk_event_queue_remove_link (display, event_link);
10534 g_list_free_1 (event_link);
10535 gdk_event_free (event);
10541 get_extension_event_window (GdkDisplay *display,
10542 GdkWindow *pointer_window,
10547 GdkWindow *grab_window;
10548 GdkWindowObject *w;
10549 GdkPointerGrabInfo *grab;
10551 grab = _gdk_display_has_pointer_grab (display, serial);
10553 if (grab != NULL && !grab->owner_events)
10555 evmask = grab->event_mask;
10557 grab_window = grab->window;
10559 if (evmask & type_masks[type])
10560 return grab_window;
10565 w = (GdkWindowObject *)pointer_window;
10568 evmask = w->extension_events;
10570 if (evmask & type_masks[type])
10571 return (GdkWindow *)w;
10573 w = get_event_parent (w);
10576 if (grab != NULL &&
10577 grab->owner_events)
10579 evmask = grab->event_mask;
10581 if (evmask & type_masks[type])
10582 return grab->window;
10592 _gdk_window_get_input_window_for_event (GdkWindow *native_window,
10593 GdkEventType event_type,
10597 GdkDisplay *display;
10598 GdkWindow *toplevel_window;
10599 GdkWindow *pointer_window;
10600 GdkWindow *event_win;
10601 gdouble toplevel_x, toplevel_y;
10606 display = gdk_drawable_get_display (native_window);
10607 toplevel_window = convert_native_coords_to_toplevel (native_window,
10608 toplevel_x, toplevel_y,
10609 &toplevel_x, &toplevel_y);
10610 pointer_window = get_pointer_window (display, toplevel_window,
10611 toplevel_x, toplevel_y, serial);
10612 event_win = get_extension_event_window (display,
10621 #define __GDK_WINDOW_C__
10622 #include "gdkaliasdef.c"