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 */
137 struct _GdkWindowPaint
143 cairo_surface_t *surface;
144 guint uses_implicit : 1;
149 GdkRegion *dest_region; /* The destination region */
150 int dx, dy; /* The amount that the source was moved to reach dest_region */
151 } GdkWindowRegionMove;
156 static GdkGC *gdk_window_create_gc (GdkDrawable *drawable,
158 GdkGCValuesMask mask);
159 static void gdk_window_draw_rectangle (GdkDrawable *drawable,
166 static void gdk_window_draw_arc (GdkDrawable *drawable,
175 static void gdk_window_draw_polygon (GdkDrawable *drawable,
180 static void gdk_window_draw_text (GdkDrawable *drawable,
187 static void gdk_window_draw_text_wc (GdkDrawable *drawable,
192 const GdkWChar *text,
194 static void gdk_window_draw_drawable (GdkDrawable *drawable,
203 GdkDrawable *original_src);
204 static void gdk_window_draw_points (GdkDrawable *drawable,
208 static void gdk_window_draw_segments (GdkDrawable *drawable,
212 static void gdk_window_draw_lines (GdkDrawable *drawable,
217 static void gdk_window_draw_glyphs (GdkDrawable *drawable,
222 PangoGlyphString *glyphs);
223 static void gdk_window_draw_glyphs_transformed (GdkDrawable *drawable,
229 PangoGlyphString *glyphs);
231 static void gdk_window_draw_image (GdkDrawable *drawable,
241 static void gdk_window_draw_pixbuf (GdkDrawable *drawable,
254 static void gdk_window_draw_trapezoids (GdkDrawable *drawable,
256 GdkTrapezoid *trapezoids,
259 static GdkImage* gdk_window_copy_to_image (GdkDrawable *drawable,
268 static cairo_surface_t *gdk_window_ref_cairo_surface (GdkDrawable *drawable);
269 static cairo_surface_t *gdk_window_create_cairo_surface (GdkDrawable *drawable,
272 static void gdk_window_set_cairo_clip (GdkDrawable *drawable,
275 static void gdk_window_real_get_size (GdkDrawable *drawable,
279 static GdkVisual* gdk_window_real_get_visual (GdkDrawable *drawable);
280 static gint gdk_window_real_get_depth (GdkDrawable *drawable);
281 static GdkScreen* gdk_window_real_get_screen (GdkDrawable *drawable);
282 static void gdk_window_real_set_colormap (GdkDrawable *drawable,
284 static GdkColormap* gdk_window_real_get_colormap (GdkDrawable *drawable);
286 static GdkDrawable* gdk_window_get_source_drawable (GdkDrawable *drawable);
287 static GdkDrawable* gdk_window_get_composite_drawable (GdkDrawable *drawable,
292 gint *composite_x_offset,
293 gint *composite_y_offset);
294 static GdkRegion* gdk_window_get_clip_region (GdkDrawable *drawable);
295 static GdkRegion* gdk_window_get_visible_region (GdkDrawable *drawable);
297 static void gdk_window_free_paint_stack (GdkWindow *window);
299 static void gdk_window_init (GdkWindowObject *window);
300 static void gdk_window_class_init (GdkWindowObjectClass *klass);
301 static void gdk_window_finalize (GObject *object);
303 static void gdk_window_set_property (GObject *object,
307 static void gdk_window_get_property (GObject *object,
312 static void gdk_window_clear_backing_region (GdkWindow *window,
314 static void gdk_window_redirect_free (GdkWindowRedirect *redirect);
315 static void apply_redirect_to_children (GdkWindowObject *private,
316 GdkWindowRedirect *redirect);
317 static void remove_redirect_from_children (GdkWindowObject *private,
318 GdkWindowRedirect *redirect);
320 static void recompute_visible_regions (GdkWindowObject *private,
321 gboolean recalculate_siblings,
322 gboolean recalculate_children);
323 static void gdk_window_flush_outstanding_moves (GdkWindow *window);
324 static void gdk_window_flush (GdkWindow *window);
325 static void gdk_window_flush_recursive (GdkWindowObject *window);
326 static void do_move_region_bits_on_impl (GdkWindowObject *private,
327 GdkRegion *region, /* In impl window coords */
329 static void gdk_window_invalidate_in_parent (GdkWindowObject *private);
330 static void move_native_children (GdkWindowObject *private);
331 static void update_cursor (GdkDisplay *display);
333 static guint signals[LAST_SIGNAL] = { 0 };
335 static gpointer parent_class = NULL;
337 static const cairo_user_data_key_t gdk_window_cairo_key;
340 new_region_tag (void)
342 static guint32 tag = 0;
348 gdk_window_object_get_type (void)
350 static GType object_type = 0;
353 object_type = g_type_register_static_simple (GDK_TYPE_DRAWABLE,
355 sizeof (GdkWindowObjectClass),
356 (GClassInitFunc) gdk_window_class_init,
357 sizeof (GdkWindowObject),
358 (GInstanceInitFunc) gdk_window_init,
365 _gdk_paintable_get_type (void)
367 static GType paintable_type = 0;
371 const GTypeInfo paintable_info =
373 sizeof (GdkPaintableIface), /* class_size */
374 NULL, /* base_init */
375 NULL, /* base_finalize */
378 paintable_type = g_type_register_static (G_TYPE_INTERFACE,
379 g_intern_static_string ("GdkPaintable"),
382 g_type_interface_add_prerequisite (paintable_type, G_TYPE_OBJECT);
385 return paintable_type;
389 gdk_window_init (GdkWindowObject *window)
391 /* 0-initialization is good for all other fields. */
393 window->window_type = GDK_WINDOW_CHILD;
395 window->state = GDK_WINDOW_STATE_WITHDRAWN;
398 window->toplevel_window_type = -1;
400 window->effective_visibility = GDK_VISIBILITY_NOT_VIEWABLE;
401 window->visibility = GDK_VISIBILITY_FULLY_OBSCURED;
402 /* Default to unobscured since some backends don't send visibility events */
403 window->native_visibility = GDK_VISIBILITY_UNOBSCURED;
406 /* Stop and return on the first non-NULL parent */
408 accumulate_get_window (GSignalInvocationHint *ihint,
410 const GValue *handler_return,
413 g_value_copy (handler_return, return_accu);
414 /* Continue while returning NULL */
415 return g_value_get_object (handler_return) == NULL;
418 static GQuark quark_pointer_window = 0;
421 gdk_window_class_init (GdkWindowObjectClass *klass)
423 GObjectClass *object_class = G_OBJECT_CLASS (klass);
424 GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
426 parent_class = g_type_class_peek_parent (klass);
428 object_class->finalize = gdk_window_finalize;
429 object_class->set_property = gdk_window_set_property;
430 object_class->get_property = gdk_window_get_property;
432 drawable_class->create_gc = gdk_window_create_gc;
433 drawable_class->draw_rectangle = gdk_window_draw_rectangle;
434 drawable_class->draw_arc = gdk_window_draw_arc;
435 drawable_class->draw_polygon = gdk_window_draw_polygon;
436 drawable_class->draw_text = gdk_window_draw_text;
437 drawable_class->draw_text_wc = gdk_window_draw_text_wc;
438 drawable_class->draw_drawable_with_src = gdk_window_draw_drawable;
439 drawable_class->draw_points = gdk_window_draw_points;
440 drawable_class->draw_segments = gdk_window_draw_segments;
441 drawable_class->draw_lines = gdk_window_draw_lines;
442 drawable_class->draw_glyphs = gdk_window_draw_glyphs;
443 drawable_class->draw_glyphs_transformed = gdk_window_draw_glyphs_transformed;
444 drawable_class->draw_image = gdk_window_draw_image;
445 drawable_class->draw_pixbuf = gdk_window_draw_pixbuf;
446 drawable_class->draw_trapezoids = gdk_window_draw_trapezoids;
447 drawable_class->get_depth = gdk_window_real_get_depth;
448 drawable_class->get_screen = gdk_window_real_get_screen;
449 drawable_class->get_size = gdk_window_real_get_size;
450 drawable_class->set_colormap = gdk_window_real_set_colormap;
451 drawable_class->get_colormap = gdk_window_real_get_colormap;
452 drawable_class->get_visual = gdk_window_real_get_visual;
453 drawable_class->_copy_to_image = gdk_window_copy_to_image;
454 drawable_class->ref_cairo_surface = gdk_window_ref_cairo_surface;
455 drawable_class->create_cairo_surface = gdk_window_create_cairo_surface;
456 drawable_class->set_cairo_clip = gdk_window_set_cairo_clip;
457 drawable_class->get_clip_region = gdk_window_get_clip_region;
458 drawable_class->get_visible_region = gdk_window_get_visible_region;
459 drawable_class->get_composite_drawable = gdk_window_get_composite_drawable;
460 drawable_class->get_source_drawable = gdk_window_get_source_drawable;
462 quark_pointer_window = g_quark_from_static_string ("gtk-pointer-window");
466 g_object_class_install_property (object_class,
468 g_param_spec_pointer ("cursor",
474 * GdkWindow::pick-embedded-child:
475 * @window: the window on which the signal is emitted
476 * @x: x coordinate in the window
477 * @y: y coordinate in the window
479 * The ::pick-embedded-child signal is emitted to find an embedded
480 * child at the given position.
482 * Returns: the GdkWindow of the embedded child at @x, @y, or %NULL
486 signals[PICK_EMBEDDED_CHILD] =
487 g_signal_new (g_intern_static_string ("pick-embedded-child"),
488 G_OBJECT_CLASS_TYPE (object_class),
491 accumulate_get_window, NULL,
492 _gdk_marshal_OBJECT__DOUBLE_DOUBLE,
499 * GdkWindow::to-embedder:
500 * @window: the offscreen window on which the signal is emitted
501 * @offscreen-x: x coordinate in the offscreen window
502 * @offscreen-y: y coordinate in the offscreen window
503 * @embedder-x: return location for the x coordinate in the embedder window
504 * @embedder-y: return location for the y coordinate in the embedder window
506 * The ::to-embedder signal is emitted to translate coordinates
507 * in an offscreen window to its embedder.
511 signals[TO_EMBEDDER] =
512 g_signal_new (g_intern_static_string ("to-embedder"),
513 G_OBJECT_CLASS_TYPE (object_class),
517 _gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
526 * GdkWindow::from-embedder:
527 * @window: the offscreen window on which the signal is emitted
528 * @embedder-x: x coordinate in the embedder window
529 * @embedder-y: y coordinate in the embedder window
530 * @offscreen-x: return location for the x coordinate in the offscreen window
531 * @offscreen-y: return location for the y coordinate in the offscreen window
533 * The ::from-embedder signal is emitted to translate coordinates
534 * in the embedder of an offscreen window to the offscreen window.
538 signals[FROM_EMBEDDER] =
539 g_signal_new (g_intern_static_string ("from-embedder"),
540 G_OBJECT_CLASS_TYPE (object_class),
544 _gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
554 gdk_window_finalize (GObject *object)
556 GdkWindow *window = GDK_WINDOW (object);
557 GdkWindowObject *obj = (GdkWindowObject *) object;
559 if (!GDK_WINDOW_DESTROYED (window))
561 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
563 g_warning ("losing last reference to undestroyed window\n");
564 _gdk_window_destroy (window, FALSE);
567 /* We use TRUE here, to keep us from actually calling
568 * XDestroyWindow() on the window
570 _gdk_window_destroy (window, TRUE);
575 g_object_unref (obj->impl);
579 if (obj->impl_window != obj)
581 g_object_unref (obj->impl_window);
582 obj->impl_window = NULL;
586 gdk_region_destroy (obj->shape);
588 if (obj->input_shape)
589 gdk_region_destroy (obj->input_shape);
592 gdk_cursor_unref (obj->cursor);
594 G_OBJECT_CLASS (parent_class)->finalize (object);
598 gdk_window_set_property (GObject *object,
603 GdkWindow *window = (GdkWindow *)object;
608 gdk_window_set_cursor (window, g_value_get_pointer (value));
612 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
618 gdk_window_get_property (GObject *object,
623 GdkWindow *window = (GdkWindow *) object;
628 g_value_set_pointer (value, gdk_window_get_cursor (window));
632 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
638 gdk_window_is_offscreen (GdkWindowObject *window)
640 return window->window_type == GDK_WINDOW_OFFSCREEN;
643 static GdkWindowObject *
644 gdk_window_get_impl_window (GdkWindowObject *window)
646 return window->impl_window;
650 _gdk_window_get_impl_window (GdkWindow *window)
652 return (GdkWindow *)gdk_window_get_impl_window ((GdkWindowObject *)window);
656 gdk_window_has_impl (GdkWindowObject *window)
658 return window->impl_window == window;
662 _gdk_window_has_impl (GdkWindow *window)
664 return gdk_window_has_impl ((GdkWindowObject *)window);
668 gdk_window_has_no_impl (GdkWindowObject *window)
670 return window->impl_window != window;
674 remove_child_area (GdkWindowObject *private,
675 GdkWindowObject *until,
679 GdkWindowObject *child;
680 GdkRegion *child_region;
685 for (l = private->children; l; l = l->next)
692 /* If region is empty already, no need to do
693 anything potentially costly */
694 if (gdk_region_empty (region))
697 if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
700 /* Ignore offscreen children, as they don't draw in their parent and
701 * don't take part in the clipping */
702 if (gdk_window_is_offscreen (child))
707 r.width = child->width;
708 r.height = child->height;
710 /* Bail early if child totally outside region */
711 if (gdk_region_rect_in (region, &r) == GDK_OVERLAP_RECTANGLE_OUT)
714 child_region = gdk_region_rectangle (&r);
718 /* Adjust shape region to parent window coords */
719 gdk_region_offset (child->shape, child->x, child->y);
720 gdk_region_intersect (child_region, child->shape);
721 gdk_region_offset (child->shape, -child->x, -child->y);
723 else if (private->window_type == GDK_WINDOW_FOREIGN)
725 shape = _gdk_windowing_window_get_shape ((GdkWindow *)child);
728 gdk_region_intersect (child_region, shape);
729 gdk_region_destroy (shape);
735 if (child->input_shape)
736 gdk_region_intersect (child_region, child->input_shape);
737 else if (private->window_type == GDK_WINDOW_FOREIGN)
739 shape = _gdk_windowing_window_get_input_shape ((GdkWindow *)child);
742 gdk_region_intersect (child_region, shape);
743 gdk_region_destroy (shape);
748 gdk_region_subtract (region, child_region);
749 gdk_region_destroy (child_region);
754 static GdkVisibilityState
755 effective_visibility (GdkWindowObject *private)
757 GdkVisibilityState native;
759 if (!gdk_window_is_viewable ((GdkWindow *)private))
760 return GDK_VISIBILITY_NOT_VIEWABLE;
762 native = private->impl_window->native_visibility;
764 if (native == GDK_VISIBILITY_FULLY_OBSCURED ||
765 private->visibility == GDK_VISIBILITY_FULLY_OBSCURED)
766 return GDK_VISIBILITY_FULLY_OBSCURED;
767 else if (native == GDK_VISIBILITY_UNOBSCURED)
768 return private->visibility;
769 else /* native PARTIAL, private partial or unobscured */
770 return GDK_VISIBILITY_PARTIAL;
774 gdk_window_update_visibility (GdkWindowObject *private)
776 GdkVisibilityState new_visibility;
779 new_visibility = effective_visibility (private);
781 if (new_visibility != private->effective_visibility)
783 private->effective_visibility = new_visibility;
785 if (new_visibility != GDK_VISIBILITY_NOT_VIEWABLE &&
786 private->event_mask & GDK_VISIBILITY_NOTIFY)
788 event = _gdk_make_event ((GdkWindow *)private, GDK_VISIBILITY_NOTIFY,
790 event->visibility.state = new_visibility;
796 gdk_window_update_visibility_recursively (GdkWindowObject *private,
797 GdkWindowObject *only_for_impl)
799 GdkWindowObject *child;
802 gdk_window_update_visibility (private);
803 for (l = private->children; l != NULL; l = l->next)
806 if ((only_for_impl == NULL) ||
807 (only_for_impl == child->impl_window))
808 gdk_window_update_visibility_recursively (child, only_for_impl);
813 recompute_visible_regions_internal (GdkWindowObject *private,
814 gboolean recalculate_clip,
815 gboolean recalculate_siblings,
816 gboolean recalculate_children)
820 GdkWindowObject *child;
821 GdkRegion *new_clip, *old_clip_region_with_children;
822 gboolean clip_region_changed;
823 gboolean abs_pos_changed;
824 int old_abs_x, old_abs_y;
826 old_abs_x = private->abs_x;
827 old_abs_y = private->abs_y;
829 /* Update absolute position */
830 if (gdk_window_has_impl (private))
832 /* Native window starts here */
838 private->abs_x = private->parent->abs_x + private->x;
839 private->abs_y = private->parent->abs_y + private->y;
843 private->abs_x != old_abs_x ||
844 private->abs_y != old_abs_y;
846 /* Update clip region based on:
849 * siblings in parents above window
851 clip_region_changed = FALSE;
852 if (recalculate_clip)
854 if (private->viewable)
856 /* Calculate visible region (sans children) in parent window coords */
859 r.width = private->width;
860 r.height = private->height;
861 new_clip = gdk_region_rectangle (&r);
863 if (private->parent != NULL &&
864 private->parent->window_type != GDK_WINDOW_ROOT)
866 gdk_region_intersect (new_clip, private->parent->clip_region);
868 /* Remove all overlapping children from parent */
869 remove_child_area (private->parent, private, FALSE, new_clip);
872 /* Convert from parent coords to window coords */
873 gdk_region_offset (new_clip, -private->x, -private->y);
876 gdk_region_intersect (new_clip, private->shape);
879 new_clip = gdk_region_new ();
881 if (private->clip_region == NULL ||
882 !gdk_region_equal (private->clip_region, new_clip))
883 clip_region_changed = TRUE;
885 if (private->clip_region)
886 gdk_region_destroy (private->clip_region);
887 private->clip_region = new_clip;
889 old_clip_region_with_children = private->clip_region_with_children;
890 private->clip_region_with_children = gdk_region_copy (private->clip_region);
891 if (private->window_type != GDK_WINDOW_ROOT)
892 remove_child_area (private, NULL, FALSE, private->clip_region_with_children);
894 if (clip_region_changed ||
895 !gdk_region_equal (private->clip_region_with_children, old_clip_region_with_children))
896 private->clip_tag = new_region_tag ();
898 if (old_clip_region_with_children)
899 gdk_region_destroy (old_clip_region_with_children);
902 if (clip_region_changed)
904 GdkVisibilityState visibility;
905 gboolean fully_visible;
907 if (gdk_region_empty (private->clip_region))
908 visibility = GDK_VISIBILITY_FULLY_OBSCURED;
911 fully_visible = gdk_region_equal (private->clip_region,
917 r.width = private->width;
918 r.height = private->height;
919 fully_visible = gdk_region_rect_equal (private->clip_region, &r);
923 visibility = GDK_VISIBILITY_UNOBSCURED;
925 visibility = GDK_VISIBILITY_PARTIAL;
928 if (private->visibility != visibility)
930 private->visibility = visibility;
931 gdk_window_update_visibility (private);
935 /* Update all children, recursively (except for root, where children are not exact). */
936 if ((abs_pos_changed || clip_region_changed || recalculate_children) &&
937 private->window_type != GDK_WINDOW_ROOT)
939 for (l = private->children; l; l = l->next)
942 /* Only recalculate clip if the the clip region changed, otherwise
943 * there is no way the child clip region could change (its has not e.g. moved)
944 * Except if recalculate_children is set to force child updates
946 recompute_visible_regions_internal (child,
947 recalculate_clip && (clip_region_changed || recalculate_children),
952 if (clip_region_changed &&
953 gdk_window_has_impl (private) &&
954 /* Not for offscreens */
955 private->window_type != GDK_WINDOW_OFFSCREEN &&
956 /* or for non-shaped toplevels */
958 (private->parent != NULL &&
959 private->parent->window_type != GDK_WINDOW_ROOT)) &&
960 /* or for foreign windows */
961 private->window_type != GDK_WINDOW_FOREIGN &&
962 /* or for the root window */
963 private->window_type != GDK_WINDOW_ROOT
966 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region ((GdkWindow *)private, private->clip_region, 0, 0);
969 if (recalculate_siblings &&
970 private->parent != NULL &&
971 private->parent->window_type != GDK_WINDOW_ROOT)
973 /* If we moved a child window in parent or changed the stacking order, then we
974 * need to recompute the visible area of all the other children in the parent
976 for (l = private->parent->children; l; l = l->next)
980 if (child != private)
981 recompute_visible_regions_internal (child, TRUE, FALSE, FALSE);
984 /* We also need to recompute the _with_children clip for the parent */
985 recompute_visible_regions_internal (private->parent, TRUE, FALSE, FALSE);
988 if (private->cairo_surface)
992 /* It would be nice if we had some cairo support here so we
993 could set the clip rect on the cairo surface */
994 width = private->abs_x + private->width;
995 height = private->abs_y + private->height;
997 _gdk_windowing_set_cairo_surface_size (private->cairo_surface,
999 cairo_surface_set_device_offset (private->cairo_surface,
1005 /* Call this when private has changed in one or more of these ways:
1009 * stacking order of window changed
1012 * It will recalculate abs_x/y and the clip regions
1014 * Unless the window didn't change stacking order or size/pos, pass in TRUE
1015 * for recalculate_siblings. (Mostly used internally for the recursion)
1017 * If a child window was removed (and you can't use that child for
1018 * recompute_visible_regions), pass in TRUE for recalculate_children on the parent
1021 recompute_visible_regions (GdkWindowObject *private,
1022 gboolean recalculate_siblings,
1023 gboolean recalculate_children)
1025 recompute_visible_regions_internal (private,
1027 recalculate_siblings,
1028 recalculate_children);
1032 _gdk_window_update_size (GdkWindow *window)
1034 recompute_visible_regions ((GdkWindowObject *)window, TRUE, FALSE);
1037 /* Find the native window that would be just above "child"
1038 * in the native stacking order if "child" was a native window
1039 * (it doesn't have to be native). If there is no such native
1040 * window inside this native parent then NULL is returned.
1041 * If child is NULL, find lowest native window in parent.
1043 static GdkWindowObject *
1044 find_native_sibling_above_helper (GdkWindowObject *parent,
1045 GdkWindowObject *child)
1052 l = g_list_find (parent->children, child);
1053 g_assert (l != NULL); /* Better be a child of its parent... */
1054 l = l->prev; /* Start looking at the one above the child */
1057 l = g_list_last (parent->children);
1059 for (; l != NULL; l = l->prev)
1063 if (gdk_window_has_impl (w))
1066 g_assert (parent != w);
1067 w = find_native_sibling_above_helper (w, NULL);
1076 static GdkWindowObject *
1077 find_native_sibling_above (GdkWindowObject *parent,
1078 GdkWindowObject *child)
1082 w = find_native_sibling_above_helper (parent, child);
1086 if (gdk_window_has_impl (parent))
1089 return find_native_sibling_above (parent->parent, parent);
1093 get_native_event_mask (GdkWindowObject *private)
1095 if (private->window_type != GDK_WINDOW_ROOT &&
1096 private->window_type != GDK_WINDOW_FOREIGN)
1099 /* We need thse for all native window so we can emulate
1100 events on children: */
1102 GDK_VISIBILITY_NOTIFY_MASK |
1103 GDK_POINTER_MOTION_MASK |
1104 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
1105 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
1107 /* Then do whatever the app asks to, since the app
1108 * may be asking for weird things for native windows,
1109 * but filter out things that override the above
1110 * requests somehow. */
1111 (private->event_mask &
1112 ~(GDK_POINTER_MOTION_HINT_MASK |
1113 GDK_BUTTON_MOTION_MASK |
1114 GDK_BUTTON1_MOTION_MASK |
1115 GDK_BUTTON2_MOTION_MASK |
1116 GDK_BUTTON3_MOTION_MASK));
1119 return private->event_mask;
1122 /* Puts the native window in the right order wrt the other native windows
1123 in the hierarchy, given the position it has in the client side data.
1124 This is useful if some operation changed the stacking order. */
1126 sync_native_window_stack_position (GdkWindow *window)
1128 GdkWindowObject *above;
1129 GdkWindowObject *private;
1130 GList listhead = {0};
1132 private = (GdkWindowObject *) window;
1134 above = find_native_sibling_above (private->parent, private);
1137 listhead.data = window;
1138 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
1145 * @parent: a #GdkWindow, or %NULL to create the window as a child of
1146 * the default root window for the default display.
1147 * @attributes: attributes of the new window
1148 * @attributes_mask: mask indicating which fields in @attributes are valid
1150 * Creates a new #GdkWindow using the attributes from
1151 * @attributes. See #GdkWindowAttr and #GdkWindowAttributesType for
1152 * more details. Note: to use this on displays other than the default
1153 * display, @parent must be specified.
1155 * Return value: the new #GdkWindow
1158 gdk_window_new (GdkWindow *parent,
1159 GdkWindowAttr *attributes,
1160 gint attributes_mask)
1163 GdkWindowObject *private;
1168 GdkEventMask event_mask;
1169 GdkWindow *real_parent;
1171 g_return_val_if_fail (attributes != NULL, NULL);
1175 GDK_NOTE (MULTIHEAD,
1176 g_warning ("gdk_window_new(): no parent specified reverting to parent = default root window"));
1178 screen = gdk_screen_get_default ();
1179 parent = gdk_screen_get_root_window (screen);
1182 screen = gdk_drawable_get_screen (parent);
1184 g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
1186 if (GDK_WINDOW_DESTROYED (parent))
1189 window = g_object_new (GDK_TYPE_WINDOW, NULL);
1190 private = (GdkWindowObject *) window;
1192 /* Windows with a foreign parent are treated as if they are children
1193 * of the root window, except for actual creation.
1195 real_parent = parent;
1196 if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
1197 parent = gdk_screen_get_root_window (screen);
1199 private->parent = (GdkWindowObject *)parent;
1201 private->accept_focus = TRUE;
1202 private->focus_on_map = TRUE;
1204 if (attributes_mask & GDK_WA_X)
1209 if (attributes_mask & GDK_WA_Y)
1216 private->width = (attributes->width > 1) ? (attributes->width) : (1);
1217 private->height = (attributes->height > 1) ? (attributes->height) : (1);
1219 #ifdef GDK_WINDOWING_X11
1220 /* Work around a bug where Xorg refuses to map toplevel InputOnly windows
1221 * from an untrusted client: http://bugs.freedesktop.org/show_bug.cgi?id=6988
1223 if (attributes->wclass == GDK_INPUT_ONLY &&
1224 private->parent->window_type == GDK_WINDOW_ROOT &&
1225 !G_LIKELY (GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (parent))->trusted_client))
1227 g_warning ("Coercing GDK_INPUT_ONLY toplevel window to GDK_INPUT_OUTPUT to work around bug in Xorg server");
1228 attributes->wclass = GDK_INPUT_OUTPUT;
1232 if (attributes->wclass == GDK_INPUT_ONLY)
1234 /* Backwards compatiblity - we've always ignored
1235 * attributes->window_type for input-only windows
1238 if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
1239 private->window_type = GDK_WINDOW_TEMP;
1241 private->window_type = GDK_WINDOW_CHILD;
1244 private->window_type = attributes->window_type;
1247 switch (private->window_type)
1249 case GDK_WINDOW_TOPLEVEL:
1250 case GDK_WINDOW_DIALOG:
1251 case GDK_WINDOW_TEMP:
1252 case GDK_WINDOW_OFFSCREEN:
1253 if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
1254 g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
1255 "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
1256 case GDK_WINDOW_CHILD:
1260 g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
1264 if (attributes_mask & GDK_WA_VISUAL)
1265 visual = attributes->visual;
1267 visual = gdk_screen_get_system_visual (screen);
1269 private->event_mask = attributes->event_mask;
1271 if (attributes->wclass == GDK_INPUT_OUTPUT)
1273 private->input_only = FALSE;
1274 private->depth = visual->depth;
1276 private->bg_color.pixel = 0; /* TODO: BlackPixel (xdisplay, screen_x11->screen_num); */
1277 private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
1279 private->bg_pixmap = NULL;
1284 private->input_only = TRUE;
1287 if (private->parent)
1288 private->parent->children = g_list_prepend (private->parent->children, window);
1290 native = FALSE; /* Default */
1291 if (private->parent->window_type == GDK_WINDOW_ROOT)
1292 native = TRUE; /* Always use native windows for toplevels */
1293 else if (!private->input_only &&
1294 ((attributes_mask & GDK_WA_COLORMAP &&
1295 attributes->colormap != gdk_drawable_get_colormap ((GdkDrawable *)private->parent)) ||
1296 (attributes_mask & GDK_WA_VISUAL &&
1297 attributes->visual != gdk_drawable_get_visual ((GdkDrawable *)private->parent))))
1298 native = TRUE; /* InputOutput window with different colormap or visual than parent, needs native window */
1300 if (private->window_type == GDK_WINDOW_OFFSCREEN)
1302 _gdk_offscreen_window_new (window, screen, visual, attributes, attributes_mask);
1303 private->impl_window = private;
1307 event_mask = get_native_event_mask (private);
1309 /* Create the impl */
1310 _gdk_window_impl_new (window, real_parent, screen, visual, event_mask, attributes, attributes_mask);
1311 private->impl_window = private;
1313 /* This will put the native window topmost in the native parent, which may
1314 * be wrong wrt other native windows in the non-native hierarchy, so restack */
1315 sync_native_window_stack_position (window);
1319 private->impl_window = g_object_ref (private->parent->impl_window);
1320 private->impl = g_object_ref (private->impl_window->impl);
1323 recompute_visible_regions (private, TRUE, FALSE);
1325 if (private->parent->window_type != GDK_WINDOW_ROOT)
1327 /* Inherit redirection from parent */
1328 private->redirect = private->parent->redirect;
1331 gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
1332 (attributes->cursor) :
1339 is_parent_of (GdkWindow *parent,
1350 w = gdk_window_get_parent (w);
1357 change_impl (GdkWindowObject *private,
1358 GdkWindowObject *impl_window,
1362 GdkWindowObject *child;
1363 GdkDrawable *old_impl;
1364 GdkWindowObject *old_impl_window;
1366 old_impl = private->impl;
1367 old_impl_window = private->impl_window;
1368 if (private != impl_window)
1369 private->impl_window = g_object_ref (impl_window);
1371 private->impl_window = private;
1372 private->impl = g_object_ref (new);
1373 if (old_impl_window != private)
1374 g_object_unref (old_impl_window);
1375 g_object_unref (old_impl);
1377 for (l = private->children; l != NULL; l = l->next)
1381 if (child->impl == old_impl)
1382 change_impl (child, impl_window, new);
1387 reparent_to_impl (GdkWindowObject *private)
1390 GdkWindowObject *child;
1393 /* Enumerate in reverse order so we get the right order for the native
1394 windows (first in childrens list is topmost, and reparent places on top) */
1395 for (l = g_list_last (private->children); l != NULL; l = l->prev)
1399 if (child->impl == private->impl)
1400 reparent_to_impl (child);
1403 show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent ((GdkWindow *)child,
1404 (GdkWindow *)private,
1405 child->x, child->y);
1407 gdk_window_show_unraised ((GdkWindow *)child);
1414 * gdk_window_reparent:
1415 * @window: a #GdkWindow
1416 * @new_parent: new parent to move @window into
1417 * @x: X location inside the new parent
1418 * @y: Y location inside the new parent
1420 * Reparents @window into the given @new_parent. The window being
1421 * reparented will be unmapped as a side effect.
1425 gdk_window_reparent (GdkWindow *window,
1426 GdkWindow *new_parent,
1430 GdkWindowObject *private;
1431 GdkWindowObject *new_parent_private;
1432 GdkWindowObject *old_parent;
1434 gboolean show, was_toplevel, was_mapped;
1435 gboolean do_reparent_to_impl;
1437 g_return_if_fail (GDK_IS_WINDOW (window));
1438 g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
1439 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
1441 if (GDK_WINDOW_DESTROYED (window) ||
1442 (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
1445 screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
1447 new_parent = gdk_screen_get_root_window (screen);
1449 private = (GdkWindowObject *) window;
1450 new_parent_private = (GdkWindowObject *)new_parent;
1452 /* No input-output children of input-only windows */
1453 if (new_parent_private->input_only && !private->input_only)
1456 /* Don't create loops in hierarchy */
1457 if (is_parent_of (window, new_parent))
1460 if (private->cairo_surface)
1462 /* This might be wrong in the new parent, e.g. for non-native surfaces.
1463 To make sure we're ok, just wipe it. */
1464 cairo_surface_finish (private->cairo_surface);
1465 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
1469 old_parent = private->parent;
1471 /* Break up redirection if inherited */
1472 if (private->redirect && private->redirect->redirected != private)
1474 remove_redirect_from_children (private, private->redirect);
1475 private->redirect = NULL;
1478 was_toplevel = private->parent == NULL;
1479 was_mapped = GDK_WINDOW_IS_MAPPED (window);
1482 /* Reparenting to toplevel. Ensure we have a native window so this can work */
1483 if (new_parent_private->window_type == GDK_WINDOW_ROOT ||
1484 new_parent_private->window_type == GDK_WINDOW_FOREIGN)
1485 gdk_window_ensure_native (window);
1487 do_reparent_to_impl = FALSE;
1488 if (gdk_window_has_impl (private))
1491 show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent (window, new_parent, x, y);
1495 /* This shouldn't happen, as we created a native in this case, check anyway to see if that ever fails */
1496 g_assert (new_parent_private->window_type != GDK_WINDOW_ROOT &&
1497 new_parent_private->window_type != GDK_WINDOW_FOREIGN);
1500 gdk_window_hide (window);
1502 do_reparent_to_impl = TRUE;
1503 change_impl (private,
1504 new_parent_private->impl_window,
1505 new_parent_private->impl);
1508 /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
1511 if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1513 new_parent = gdk_screen_get_root_window (screen);
1514 new_parent_private = (GdkWindowObject *)new_parent;
1518 old_parent->children = g_list_remove (old_parent->children, window);
1520 private->parent = new_parent_private;
1524 new_parent_private->children = g_list_prepend (new_parent_private->children, window);
1526 /* Switch the window type as appropriate */
1528 switch (GDK_WINDOW_TYPE (new_parent))
1530 case GDK_WINDOW_ROOT:
1531 case GDK_WINDOW_FOREIGN:
1532 if (private->toplevel_window_type != -1)
1533 GDK_WINDOW_TYPE (window) = private->toplevel_window_type;
1534 else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1535 GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
1537 case GDK_WINDOW_OFFSCREEN:
1538 case GDK_WINDOW_TOPLEVEL:
1539 case GDK_WINDOW_CHILD:
1540 case GDK_WINDOW_DIALOG:
1541 case GDK_WINDOW_TEMP:
1542 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
1543 GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
1545 /* Save the original window type so we can restore it if the
1546 * window is reparented back to be a toplevel
1548 private->toplevel_window_type = GDK_WINDOW_TYPE (window);
1549 GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
1553 /* We might have changed window type for a native windows, so we
1554 need to change the event mask too. */
1555 if (gdk_window_has_impl (private))
1556 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_events (window, get_native_event_mask (private));
1558 /* Inherit parent redirect if we don't have our own */
1559 if (private->parent && private->redirect == NULL)
1561 private->redirect = private->parent->redirect;
1562 apply_redirect_to_children (private, private->redirect);
1565 _gdk_window_update_viewable (window);
1567 recompute_visible_regions (private, TRUE, FALSE);
1568 if (old_parent && GDK_WINDOW_TYPE (old_parent) != GDK_WINDOW_ROOT)
1569 recompute_visible_regions (old_parent, FALSE, TRUE);
1571 if (do_reparent_to_impl)
1572 reparent_to_impl (private);
1575 /* The reparent will have put the native window topmost in the native parent,
1576 * which may be wrong wrt other native windows in the non-native hierarchy,
1578 sync_native_window_stack_position (window);
1582 gdk_window_show_unraised (window);
1584 _gdk_synthesize_crossing_events_for_geometry_change (window);
1588 * gdk_window_ensure_native:
1589 * @window: a #GdkWindow
1591 * Tries to ensure that there is a window-system native window for this
1592 * GdkWindow. This may fail in some situations, returning %FALSE.
1594 * Offscreen window and children of them can never have native windows.
1596 * Some backends may not support native child windows.
1598 * Returns: %TRUE if the window has a native window, %FALSE otherwise
1603 gdk_window_ensure_native (GdkWindow *window)
1605 GdkWindowObject *private;
1606 GdkWindowObject *impl_window;
1607 GdkDrawable *new_impl, *old_impl;
1610 GdkWindowAttr attributes;
1611 GdkWindowObject *above;
1614 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
1616 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT ||
1617 GDK_WINDOW_DESTROYED (window))
1620 private = (GdkWindowObject *) window;
1622 impl_window = gdk_window_get_impl_window (private);
1624 if (impl_window->window_type == GDK_WINDOW_OFFSCREEN)
1625 return FALSE; /* native in offscreens not supported */
1627 if (impl_window == private)
1628 /* Already has an impl, and its not offscreen . */
1631 /* Need to create a native window */
1633 screen = gdk_drawable_get_screen (window);
1634 visual = gdk_drawable_get_visual (window);
1636 attributes.colormap = gdk_drawable_get_colormap (window);
1638 old_impl = private->impl;
1639 _gdk_window_impl_new (window, (GdkWindow *)private->parent, screen, visual,
1640 get_native_event_mask (private), &attributes, GDK_WA_COLORMAP);
1641 new_impl = private->impl;
1643 private->impl = old_impl;
1644 change_impl (private, private, new_impl);
1646 /* Native window creation will put the native window topmost in the
1647 * native parent, which may be wrong wrt other native windows in the
1648 * non-native hierarchy, so restack */
1649 above = find_native_sibling_above (private->parent, private);
1652 listhead.data = window;
1653 listhead.prev = NULL;
1654 listhead.next = NULL;
1655 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
1659 recompute_visible_regions (private, FALSE, FALSE);
1661 /* The shape may not have been set, as the clip region doesn't actually
1662 change, so do it here manually */
1663 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region ((GdkWindow *)private, private->clip_region, 0, 0);
1665 reparent_to_impl (private);
1667 if (!private->input_only)
1669 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, &private->bg_color);
1670 if (private->bg_pixmap != NULL)
1671 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, private->bg_pixmap);
1674 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_shape_combine_region ((GdkWindow *)private, private->input_shape, 0, 0);
1676 if (gdk_window_is_viewable (window))
1677 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show (window, FALSE);
1683 window_remove_filters (GdkWindow *window)
1685 GdkWindowObject *obj = (GdkWindowObject*) window;
1691 for (tmp_list = obj->filters; tmp_list; tmp_list = tmp_list->next)
1692 g_free (tmp_list->data);
1694 g_list_free (obj->filters);
1695 obj->filters = NULL;
1700 * _gdk_window_destroy_hierarchy:
1701 * @window: a #GdkWindow
1702 * @recursing: If TRUE, then this is being called because a parent
1704 * @recursing_native: If TRUE, then this is being called because a native parent
1705 * was destroyed. This generally means that the call to the
1706 * windowing system to destroy the window can be omitted, since
1707 * it will be destroyed as a result of the parent being destroyed.
1708 * Unless @foreign_destroy.
1709 * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
1710 * external agency. The window has already been destroyed and no
1711 * windowing system calls should be made. (This may never happen
1712 * for some windowing systems.)
1714 * Internal function to destroy a window. Like gdk_window_destroy(),
1715 * but does not drop the reference count created by gdk_window_new().
1718 _gdk_window_destroy_hierarchy (GdkWindow *window,
1720 gboolean recursing_native,
1721 gboolean foreign_destroy)
1723 GdkWindowObject *private;
1724 GdkWindowObject *temp_private;
1725 GdkWindow *temp_window;
1727 GdkDisplay *display;
1731 g_return_if_fail (GDK_IS_WINDOW (window));
1733 private = (GdkWindowObject*) window;
1735 if (GDK_WINDOW_DESTROYED (window))
1738 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
1739 screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
1740 temp_window = g_object_get_qdata (G_OBJECT (screen), quark_pointer_window);
1741 if (temp_window == window)
1742 g_object_set_qdata (G_OBJECT (screen), quark_pointer_window, NULL);
1745 switch (private->window_type)
1747 case GDK_WINDOW_ROOT:
1748 if (!screen->closed)
1750 g_error ("attempted to destroy root window");
1753 /* else fall thru */
1754 case GDK_WINDOW_TOPLEVEL:
1755 case GDK_WINDOW_CHILD:
1756 case GDK_WINDOW_DIALOG:
1757 case GDK_WINDOW_TEMP:
1758 case GDK_WINDOW_FOREIGN:
1759 case GDK_WINDOW_OFFSCREEN:
1760 if (private->window_type == GDK_WINDOW_FOREIGN && !foreign_destroy)
1762 /* Logically, it probably makes more sense to send
1763 * a "destroy yourself" message to the foreign window
1764 * whether or not it's in our hierarchy; but for historical
1765 * reasons, we only send "destroy yourself" messages to
1766 * foreign windows in our hierarchy.
1768 if (private->parent)
1769 _gdk_windowing_window_destroy_foreign (window);
1771 /* Also for historical reasons, we remove any filters
1772 * on a foreign window when it or a parent is destroyed;
1773 * this likely causes problems if two separate portions
1774 * of code are maintaining filter lists on a foreign window.
1776 window_remove_filters (window);
1780 if (private->parent)
1782 GdkWindowObject *parent_private = (GdkWindowObject *)private->parent;
1784 if (parent_private->children)
1785 parent_private->children = g_list_remove (parent_private->children, window);
1788 GDK_WINDOW_IS_MAPPED (window))
1790 recompute_visible_regions (private, TRUE, FALSE);
1791 gdk_window_invalidate_in_parent (private);
1795 gdk_window_free_paint_stack (window);
1797 if (private->bg_pixmap &&
1798 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
1799 private->bg_pixmap != GDK_NO_BG)
1801 g_object_unref (private->bg_pixmap);
1802 private->bg_pixmap = NULL;
1805 if (private->window_type == GDK_WINDOW_FOREIGN)
1806 g_assert (private->children == NULL);
1809 children = tmp = private->children;
1810 private->children = NULL;
1814 temp_window = tmp->data;
1817 temp_private = (GdkWindowObject*) temp_window;
1819 _gdk_window_destroy_hierarchy (temp_window,
1821 recursing_native || gdk_window_has_impl (private),
1825 g_list_free (children);
1828 _gdk_window_clear_update_area (window);
1830 if (private->cairo_surface)
1832 cairo_surface_finish (private->cairo_surface);
1833 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
1838 if (private->extension_events)
1839 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_window_destroy (window);
1841 if (gdk_window_has_impl (private))
1843 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->destroy (window, recursing_native, foreign_destroy);
1847 /* hide to make sure we repaint and break grabs */
1848 gdk_window_hide (window);
1851 private->state |= GDK_WINDOW_STATE_WITHDRAWN;
1852 private->parent = NULL;
1853 private->destroyed = TRUE;
1855 window_remove_filters (window);
1857 gdk_drawable_set_colormap (GDK_DRAWABLE (window), NULL);
1859 /* If we own the redirect, free it */
1860 if (private->redirect && private->redirect->redirected == private)
1861 gdk_window_redirect_free (private->redirect);
1863 private->redirect = NULL;
1865 if (display->pointer_info.toplevel_under_pointer == window)
1867 g_object_unref (display->pointer_info.toplevel_under_pointer);
1868 display->pointer_info.toplevel_under_pointer = NULL;
1876 * _gdk_window_destroy:
1877 * @window: a #GdkWindow
1878 * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
1879 * external agency. The window has already been destroyed and no
1880 * windowing system calls should be made. (This may never happen
1881 * for some windowing systems.)
1883 * Internal function to destroy a window. Like gdk_window_destroy(),
1884 * but does not drop the reference count created by gdk_window_new().
1887 _gdk_window_destroy (GdkWindow *window,
1888 gboolean foreign_destroy)
1890 _gdk_window_destroy_hierarchy (window, FALSE, FALSE, foreign_destroy);
1894 * gdk_window_destroy:
1895 * @window: a #GdkWindow
1897 * Destroys the window system resources associated with @window and decrements @window's
1898 * reference count. The window system resources for all children of @window are also
1899 * destroyed, but the children's reference counts are not decremented.
1901 * Note that a window will not be destroyed automatically when its reference count
1902 * reaches zero. You must call this function yourself before that happens.
1906 gdk_window_destroy (GdkWindow *window)
1908 _gdk_window_destroy_hierarchy (window, FALSE, FALSE, FALSE);
1909 g_object_unref (window);
1913 * gdk_window_set_user_data:
1914 * @window: a #GdkWindow
1915 * @user_data: user data
1917 * For most purposes this function is deprecated in favor of
1918 * g_object_set_data(). However, for historical reasons GTK+ stores
1919 * the #GtkWidget that owns a #GdkWindow as user data on the
1920 * #GdkWindow. So, custom widget implementations should use
1921 * this function for that. If GTK+ receives an event for a #GdkWindow,
1922 * and the user data for the window is non-%NULL, GTK+ will assume the
1923 * user data is a #GtkWidget, and forward the event to that widget.
1927 gdk_window_set_user_data (GdkWindow *window,
1930 g_return_if_fail (GDK_IS_WINDOW (window));
1932 ((GdkWindowObject*)window)->user_data = user_data;
1936 * gdk_window_get_user_data:
1937 * @window: a #GdkWindow
1938 * @data: return location for user data
1940 * Retrieves the user data for @window, which is normally the widget
1941 * that @window belongs to. See gdk_window_set_user_data().
1945 gdk_window_get_user_data (GdkWindow *window,
1948 g_return_if_fail (GDK_IS_WINDOW (window));
1950 *data = ((GdkWindowObject*)window)->user_data;
1954 * gdk_window_get_window_type:
1955 * @window: a #GdkWindow
1957 * Gets the type of the window. See #GdkWindowType.
1959 * Return value: type of window
1962 gdk_window_get_window_type (GdkWindow *window)
1964 g_return_val_if_fail (GDK_IS_WINDOW (window), (GdkWindowType) -1);
1966 return GDK_WINDOW_TYPE (window);
1970 * gdk_window_get_position:
1971 * @window: a #GdkWindow
1972 * @x: X coordinate of window
1973 * @y: Y coordinate of window
1975 * Obtains the position of the window as reported in the
1976 * most-recently-processed #GdkEventConfigure. Contrast with
1977 * gdk_window_get_geometry() which queries the X server for the
1978 * current window position, regardless of which events have been
1979 * received or processed.
1981 * The position coordinates are relative to the window's parent window.
1985 gdk_window_get_position (GdkWindow *window,
1989 GdkWindowObject *obj;
1991 g_return_if_fail (GDK_IS_WINDOW (window));
1993 obj = (GdkWindowObject*) window;
2002 * gdk_window_get_parent:
2003 * @window: a #GdkWindow
2005 * Obtains the parent of @window, as known to GDK. Does not query the
2006 * X server; thus this returns the parent as passed to gdk_window_new(),
2007 * not the actual parent. This should never matter unless you're using
2008 * Xlib calls mixed with GDK calls on the X11 platform. It may also
2009 * matter for toplevel windows, because the window manager may choose
2012 * Return value: parent of @window
2015 gdk_window_get_parent (GdkWindow *window)
2017 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2019 return (GdkWindow*) ((GdkWindowObject*) window)->parent;
2023 * gdk_window_get_toplevel:
2024 * @window: a #GdkWindow
2026 * Gets the toplevel window that's an ancestor of @window.
2028 * Any window type but %GDK_WINDOW_CHILD is considered a
2029 * toplevel window, as is a %GDK_WINDOW_CHILD window that
2030 * has a root window as parent.
2032 * Return value: the toplevel window containing @window
2035 gdk_window_get_toplevel (GdkWindow *window)
2037 GdkWindowObject *obj;
2039 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2041 obj = (GdkWindowObject *)window;
2043 while (obj->window_type == GDK_WINDOW_CHILD)
2045 if (obj->parent == NULL ||
2046 obj->parent->window_type == GDK_WINDOW_ROOT)
2051 return GDK_WINDOW (obj);
2055 * gdk_window_get_children:
2056 * @window: a #GdkWindow
2058 * Gets the list of children of @window known to GDK.
2059 * This function only returns children created via GDK,
2060 * so for example it's useless when used with the root window;
2061 * it only returns windows an application created itself.
2063 * The returned list must be freed, but the elements in the
2066 * Return value: list of child windows inside @window
2069 gdk_window_get_children (GdkWindow *window)
2071 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2073 if (GDK_WINDOW_DESTROYED (window))
2076 return g_list_copy (GDK_WINDOW_OBJECT (window)->children);
2080 * gdk_window_peek_children:
2081 * @window: a #GdkWindow
2083 * Like gdk_window_get_children(), but does not copy the list of
2084 * children, so the list does not need to be freed.
2086 * Return value: a reference to the list of child windows in @window
2089 gdk_window_peek_children (GdkWindow *window)
2091 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2093 if (GDK_WINDOW_DESTROYED (window))
2096 return GDK_WINDOW_OBJECT (window)->children;
2100 * gdk_window_add_filter:
2101 * @window: a #GdkWindow
2102 * @function: filter callback
2103 * @data: data to pass to filter callback
2105 * Adds an event filter to @window, allowing you to intercept events
2106 * before they reach GDK. This is a low-level operation and makes it
2107 * easy to break GDK and/or GTK+, so you have to know what you're
2108 * doing. Pass %NULL for @window to get all events for all windows,
2109 * instead of events for a specific window.
2111 * See gdk_display_add_client_message_filter() if you are interested
2112 * in X ClientMessage events.
2115 gdk_window_add_filter (GdkWindow *window,
2116 GdkFilterFunc function,
2119 GdkWindowObject *private;
2121 GdkEventFilter *filter;
2123 g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
2125 private = (GdkWindowObject*) window;
2126 if (private && GDK_WINDOW_DESTROYED (window))
2129 /* Filters are for the native events on the native window, so
2130 ensure there is a native window. */
2132 gdk_window_ensure_native (window);
2135 tmp_list = private->filters;
2137 tmp_list = _gdk_default_filters;
2141 filter = (GdkEventFilter *)tmp_list->data;
2142 if ((filter->function == function) && (filter->data == data))
2144 tmp_list = tmp_list->next;
2147 filter = g_new (GdkEventFilter, 1);
2148 filter->function = function;
2149 filter->data = data;
2152 private->filters = g_list_append (private->filters, filter);
2154 _gdk_default_filters = g_list_append (_gdk_default_filters, filter);
2158 * gdk_window_remove_filter:
2159 * @window: a #GdkWindow
2160 * @function: previously-added filter function
2161 * @data: user data for previously-added filter function
2163 * Remove a filter previously added with gdk_window_add_filter().
2167 gdk_window_remove_filter (GdkWindow *window,
2168 GdkFilterFunc function,
2171 GdkWindowObject *private;
2172 GList *tmp_list, *node;
2173 GdkEventFilter *filter;
2175 g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
2177 private = (GdkWindowObject*) window;
2180 tmp_list = private->filters;
2182 tmp_list = _gdk_default_filters;
2186 filter = (GdkEventFilter *)tmp_list->data;
2188 tmp_list = tmp_list->next;
2190 if ((filter->function == function) && (filter->data == data))
2193 private->filters = g_list_remove_link (private->filters, node);
2195 _gdk_default_filters = g_list_remove_link (_gdk_default_filters, node);
2196 g_list_free_1 (node);
2205 * gdk_screen_get_toplevel_windows:
2206 * @screen: The #GdkScreen where the toplevels are located.
2208 * Obtains a list of all toplevel windows known to GDK on the screen @screen.
2209 * A toplevel window is a child of the root window (see
2210 * gdk_get_default_root_window()).
2212 * The returned list should be freed with g_list_free(), but
2213 * its elements need not be freed.
2215 * Return value: list of toplevel windows, free with g_list_free()
2220 gdk_screen_get_toplevel_windows (GdkScreen *screen)
2222 GdkWindow * root_window;
2223 GList *new_list = NULL;
2226 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
2228 root_window = gdk_screen_get_root_window (screen);
2230 tmp_list = ((GdkWindowObject *)root_window)->children;
2233 GdkWindowObject *w = tmp_list->data;
2235 if (w->window_type != GDK_WINDOW_FOREIGN)
2236 new_list = g_list_prepend (new_list, w);
2237 tmp_list = tmp_list->next;
2244 * gdk_window_get_toplevels:
2246 * Obtains a list of all toplevel windows known to GDK on the default
2247 * screen (see gdk_screen_get_toplevel_windows()).
2248 * A toplevel window is a child of the root window (see
2249 * gdk_get_default_root_window()).
2251 * The returned list should be freed with g_list_free(), but
2252 * its elements need not be freed.
2254 * Return value: list of toplevel windows, free with g_list_free()
2256 * Deprecated: 2.16: Use gdk_screen_get_toplevel_windows() instead.
2259 gdk_window_get_toplevels (void)
2261 return gdk_screen_get_toplevel_windows (gdk_screen_get_default ());
2265 * gdk_window_is_visible:
2266 * @window: a #GdkWindow
2268 * Checks whether the window has been mapped (with gdk_window_show() or
2269 * gdk_window_show_unraised()).
2271 * Return value: %TRUE if the window is mapped
2274 gdk_window_is_visible (GdkWindow *window)
2276 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2278 return GDK_WINDOW_IS_MAPPED (window);
2282 * gdk_window_is_viewable:
2283 * @window: a #GdkWindow
2285 * Check if the window and all ancestors of the window are
2286 * mapped. (This is not necessarily "viewable" in the X sense, since
2287 * we only check as far as we have GDK window parents, not to the root
2290 * Return value: %TRUE if the window is viewable
2293 gdk_window_is_viewable (GdkWindow *window)
2295 GdkWindowObject *private = (GdkWindowObject *)window;
2297 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2299 if (private->destroyed)
2302 return private->viewable;
2306 * gdk_window_get_state:
2307 * @window: a #GdkWindow
2309 * Gets the bitwise OR of the currently active window state flags,
2310 * from the #GdkWindowState enumeration.
2312 * Return value: window state bitfield
2315 gdk_window_get_state (GdkWindow *window)
2317 GdkWindowObject *private = (GdkWindowObject *)window;
2319 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2321 return private->state;
2325 /* This creates an empty "implicit" paint region for the impl window.
2326 * By itself this does nothing, but real paints to this window
2327 * or children of it can use this pixmap as backing to avoid allocating
2328 * multiple pixmaps for subwindow rendering. When doing so they
2329 * add to the region of the implicit paint region, which will be
2330 * pushed to the window when the implicit paint region is ended.
2331 * Such paints should not copy anything to the window on paint end, but
2332 * should rely on the implicit paint end.
2333 * The implicit paint will be automatically ended if someone draws
2334 * directly to the window or a child window.
2337 gdk_window_begin_implicit_paint (GdkWindow *window, GdkRectangle *rect)
2339 GdkWindowObject *private = (GdkWindowObject *)window;
2340 GdkWindowPaint *paint;
2342 g_assert (gdk_window_has_impl (private));
2344 if (GDK_IS_PAINTABLE (private->impl))
2345 return FALSE; /* Implementation does double buffering */
2347 if (private->paint_stack != NULL ||
2348 private->implicit_paint != NULL)
2349 return FALSE; /* Don't stack implicit paints */
2351 paint = g_new (GdkWindowPaint, 1);
2352 paint->region = gdk_region_new (); /* Empty */
2353 paint->x_offset = rect->x;
2354 paint->y_offset = rect->y;
2355 paint->uses_implicit = FALSE;
2356 paint->surface = NULL;
2358 gdk_pixmap_new (window,
2359 MAX (rect->width, 1), MAX (rect->height, 1), -1);
2361 private->implicit_paint = paint;
2366 /* Ensure that all content related to this (sub)window is pushed to the
2367 native region. If there is an active paint then that area is not
2368 pushed, in order to not show partially finished double buffers. */
2370 gdk_window_flush_implicit_paint (GdkWindow *window)
2372 GdkWindowObject *private = (GdkWindowObject *)window;
2373 GdkWindowObject *impl_window;
2374 GdkWindowPaint *paint;
2379 impl_window = gdk_window_get_impl_window (private);
2380 if (impl_window->implicit_paint == NULL)
2383 paint = impl_window->implicit_paint;
2384 region = gdk_region_copy (private->clip_region_with_children);
2386 /* Don't flush active double buffers, as that may show partially done
2388 for (list = private->paint_stack; list != NULL; list = list->next)
2390 GdkWindowPaint *tmp_paint = list->data;
2392 gdk_region_subtract (region, tmp_paint->region);
2395 gdk_region_offset (region, private->abs_x, private->abs_y);
2396 gdk_region_intersect (region, paint->region);
2398 if (!gdk_region_empty (region))
2400 /* Some regions are valid, push these to window now */
2401 tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
2402 _gdk_gc_set_clip_region_internal (tmp_gc, region, TRUE);
2403 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2404 0, 0, paint->x_offset, paint->y_offset, -1, -1);
2405 /* Reset clip region of the cached GdkGC */
2406 gdk_gc_set_clip_region (tmp_gc, NULL);
2408 /* Remove flushed region from the implicit paint */
2409 gdk_region_subtract (paint->region, region);
2412 gdk_region_destroy (region);
2415 /* Ends an implicit paint, paired with gdk_window_begin_implicit_paint returning TRUE */
2417 gdk_window_end_implicit_paint (GdkWindow *window)
2419 GdkWindowObject *private = (GdkWindowObject *)window;
2420 GdkWindowPaint *paint;
2423 g_assert (gdk_window_has_impl (private));
2425 g_assert (private->implicit_paint != NULL);
2427 paint = private->implicit_paint;
2429 private->implicit_paint = NULL;
2431 if (!gdk_region_empty (paint->region))
2433 /* Some regions are valid, push these to window now */
2434 tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
2435 _gdk_gc_set_clip_region_internal (tmp_gc, paint->region, TRUE);
2436 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2437 0, 0, paint->x_offset, paint->y_offset, -1, -1);
2438 /* Reset clip region of the cached GdkGC */
2439 gdk_gc_set_clip_region (tmp_gc, NULL);
2442 g_object_unref (paint->pixmap);
2447 * gdk_window_begin_paint_rect:
2448 * @window: a #GdkWindow
2449 * @rectangle: rectangle you intend to draw to
2451 * A convenience wrapper around gdk_window_begin_paint_region() which
2452 * creates a rectangular region for you. See
2453 * gdk_window_begin_paint_region() for details.
2457 gdk_window_begin_paint_rect (GdkWindow *window,
2458 const GdkRectangle *rectangle)
2462 g_return_if_fail (GDK_IS_WINDOW (window));
2464 region = gdk_region_rectangle (rectangle);
2465 gdk_window_begin_paint_region (window, region);
2466 gdk_region_destroy (region);
2470 * gdk_window_begin_paint_region:
2471 * @window: a #GdkWindow
2472 * @region: region you intend to draw to
2474 * Indicates that you are beginning the process of redrawing @region.
2475 * A backing store (offscreen buffer) large enough to contain @region
2476 * will be created. The backing store will be initialized with the
2477 * background color or background pixmap for @window. Then, all
2478 * drawing operations performed on @window will be diverted to the
2479 * backing store. When you call gdk_window_end_paint(), the backing
2480 * store will be copied to @window, making it visible onscreen. Only
2481 * the part of @window contained in @region will be modified; that is,
2482 * drawing operations are clipped to @region.
2484 * The net result of all this is to remove flicker, because the user
2485 * sees the finished product appear all at once when you call
2486 * gdk_window_end_paint(). If you draw to @window directly without
2487 * calling gdk_window_begin_paint_region(), the user may see flicker
2488 * as individual drawing operations are performed in sequence. The
2489 * clipping and background-initializing features of
2490 * gdk_window_begin_paint_region() are conveniences for the
2491 * programmer, so you can avoid doing that work yourself.
2493 * When using GTK+, the widget system automatically places calls to
2494 * gdk_window_begin_paint_region() and gdk_window_end_paint() around
2495 * emissions of the expose_event signal. That is, if you're writing an
2496 * expose event handler, you can assume that the exposed area in
2497 * #GdkEventExpose has already been cleared to the window background,
2498 * is already set as the clip region, and already has a backing store.
2499 * Therefore in most cases, application code need not call
2500 * gdk_window_begin_paint_region(). (You can disable the automatic
2501 * calls around expose events on a widget-by-widget basis by calling
2502 * gtk_widget_set_double_buffered().)
2504 * If you call this function multiple times before calling the
2505 * matching gdk_window_end_paint(), the backing stores are pushed onto
2506 * a stack. gdk_window_end_paint() copies the topmost backing store
2507 * onscreen, subtracts the topmost region from all other regions in
2508 * the stack, and pops the stack. All drawing operations affect only
2509 * the topmost backing store in the stack. One matching call to
2510 * gdk_window_end_paint() is required for each call to
2511 * gdk_window_begin_paint_region().
2515 gdk_window_begin_paint_region (GdkWindow *window,
2516 const GdkRegion *region)
2518 #ifdef USE_BACKING_STORE
2519 GdkWindowObject *private = (GdkWindowObject *)window;
2520 GdkRectangle clip_box;
2521 GdkWindowPaint *paint, *implicit_paint;
2522 GdkWindowObject *impl_window;
2525 g_return_if_fail (GDK_IS_WINDOW (window));
2527 if (GDK_WINDOW_DESTROYED (window))
2530 if (GDK_IS_PAINTABLE (private->impl))
2532 GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
2534 if (iface->begin_paint_region)
2535 iface->begin_paint_region ((GdkPaintable*)private->impl, window, region);
2540 impl_window = gdk_window_get_impl_window (private);
2541 implicit_paint = impl_window->implicit_paint;
2543 paint = g_new (GdkWindowPaint, 1);
2544 paint->region = gdk_region_copy (region);
2545 paint->region_tag = new_region_tag ();
2547 gdk_region_intersect (paint->region, private->clip_region_with_children);
2548 gdk_region_get_clipbox (paint->region, &clip_box);
2550 /* Convert to impl coords */
2551 gdk_region_offset (paint->region, private->abs_x, private->abs_y);
2553 /* Mark the region as valid on the implicit paint */
2556 gdk_region_union (implicit_paint->region, paint->region);
2558 /* Convert back to normal coords */
2559 gdk_region_offset (paint->region, -private->abs_x, -private->abs_y);
2565 paint->uses_implicit = TRUE;
2566 paint->pixmap = g_object_ref (implicit_paint->pixmap);
2567 paint->x_offset = -private->abs_x + implicit_paint->x_offset;
2568 paint->y_offset = -private->abs_y + implicit_paint->y_offset;
2570 gdk_drawable_get_size (paint->pixmap, &width, &height);
2571 paint->surface = _gdk_drawable_create_cairo_surface (paint->pixmap, width, height);
2575 paint->uses_implicit = FALSE;
2576 paint->x_offset = clip_box.x;
2577 paint->y_offset = clip_box.y;
2579 gdk_pixmap_new (window,
2580 MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1);
2581 paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap);
2585 cairo_surface_set_device_offset (paint->surface,
2586 -paint->x_offset, -paint->y_offset);
2588 for (list = private->paint_stack; list != NULL; list = list->next)
2590 GdkWindowPaint *tmp_paint = list->data;
2592 gdk_region_subtract (tmp_paint->region, paint->region);
2595 private->paint_stack = g_slist_prepend (private->paint_stack, paint);
2597 if (!gdk_region_empty (paint->region))
2599 gdk_window_clear_backing_region (window,
2603 #endif /* USE_BACKING_STORE */
2607 setup_redirect_clip (GdkWindow *window,
2612 GdkWindowObject *private = (GdkWindowObject *)window;
2613 GdkRegion *visible_region;
2614 GdkRectangle dest_rect;
2616 GdkWindow *toplevel;
2617 int x_offset, y_offset;
2619 toplevel = GDK_WINDOW (private->redirect->redirected);
2621 /* Get the clip region for gc clip rect + window hierarchy in
2622 window relative coords */
2624 _gdk_window_calculate_full_clip_region (window, toplevel,
2629 /* Compensate for the source pos/size */
2630 x_offset -= private->redirect->src_x;
2631 y_offset -= private->redirect->src_y;
2632 dest_rect.x = -x_offset;
2633 dest_rect.y = -y_offset;
2634 dest_rect.width = private->redirect->width;
2635 dest_rect.height = private->redirect->height;
2636 tmpreg = gdk_region_rectangle (&dest_rect);
2637 gdk_region_intersect (visible_region, tmpreg);
2638 gdk_region_destroy (tmpreg);
2640 /* Compensate for the dest pos */
2641 x_offset += private->redirect->dest_x;
2642 y_offset += private->redirect->dest_y;
2644 gdk_gc_set_clip_region (gc, visible_region); /* This resets clip origin! */
2646 /* offset clip and tiles from window coords to pixmaps coords */
2647 gdk_gc_offset (gc, -x_offset, -y_offset);
2649 gdk_region_destroy (visible_region);
2651 *x_offset_out = x_offset;
2652 *y_offset_out = y_offset;
2656 * gdk_window_end_paint:
2657 * @window: a #GdkWindow
2659 * Indicates that the backing store created by the most recent call to
2660 * gdk_window_begin_paint_region() should be copied onscreen and
2661 * deleted, leaving the next-most-recent backing store or no backing
2662 * store at all as the active paint region. See
2663 * gdk_window_begin_paint_region() for full details. It is an error to
2664 * call this function without a matching
2665 * gdk_window_begin_paint_region() first.
2669 gdk_window_end_paint (GdkWindow *window)
2671 #ifdef USE_BACKING_STORE
2672 GdkWindowObject *private = (GdkWindowObject *)window;
2673 GdkWindowObject *composited;
2674 GdkWindowPaint *paint;
2676 GdkRectangle clip_box;
2677 gint x_offset, y_offset;
2678 GdkRegion *full_clip;
2680 g_return_if_fail (GDK_IS_WINDOW (window));
2682 if (GDK_WINDOW_DESTROYED (window))
2685 if (GDK_IS_PAINTABLE (private->impl))
2687 GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
2689 if (iface->end_paint)
2690 iface->end_paint ((GdkPaintable*)private->impl);
2694 if (private->paint_stack == NULL)
2696 g_warning (G_STRLOC": no preceding call to gdk_window_begin_paint_region(), see documentation");
2700 paint = private->paint_stack->data;
2702 private->paint_stack = g_slist_delete_link (private->paint_stack,
2703 private->paint_stack);
2705 gdk_region_get_clipbox (paint->region, &clip_box);
2707 tmp_gc = _gdk_drawable_get_scratch_gc (window, FALSE);
2709 x_offset = -private->abs_x;
2710 y_offset = -private->abs_y;
2712 if (!paint->uses_implicit)
2714 gdk_window_flush_outstanding_moves (window);
2716 full_clip = gdk_region_copy (private->clip_region_with_children);
2717 gdk_region_intersect (full_clip, paint->region);
2718 _gdk_gc_set_clip_region_internal (tmp_gc, full_clip, TRUE); /* Takes ownership of full_clip */
2719 gdk_gc_set_clip_origin (tmp_gc, - x_offset, - y_offset);
2720 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2721 clip_box.x - paint->x_offset,
2722 clip_box.y - paint->y_offset,
2723 clip_box.x - x_offset, clip_box.y - y_offset,
2724 clip_box.width, clip_box.height);
2727 if (private->redirect)
2729 int x_offset, y_offset;
2731 /* TODO: Should also use paint->region for clipping */
2732 setup_redirect_clip (window, tmp_gc, &x_offset, &y_offset);
2733 gdk_draw_drawable (private->redirect->pixmap, tmp_gc, paint->pixmap,
2734 clip_box.x - paint->x_offset,
2735 clip_box.y - paint->y_offset,
2736 clip_box.x + x_offset,
2737 clip_box.y + y_offset,
2738 clip_box.width, clip_box.height);
2741 /* Reset clip region of the cached GdkGC */
2742 gdk_gc_set_clip_region (tmp_gc, NULL);
2744 cairo_surface_destroy (paint->surface);
2745 g_object_unref (paint->pixmap);
2746 gdk_region_destroy (paint->region);
2749 /* find a composited window in our hierarchy to signal its
2750 * parent to redraw, calculating the clip box as we go...
2752 * stop if parent becomes NULL since then we'd have nowhere
2753 * to draw (ie: 'composited' will always be non-NULL here).
2755 for (composited = private;
2757 composited = composited->parent)
2761 gdk_drawable_get_size (GDK_DRAWABLE (composited->parent),
2764 clip_box.x += composited->x;
2765 clip_box.y += composited->y;
2766 clip_box.width = MIN (clip_box.width, width - clip_box.x);
2767 clip_box.height = MIN (clip_box.height, height - clip_box.y);
2769 if (composited->composited)
2771 gdk_window_invalidate_rect (GDK_WINDOW (composited->parent),
2776 #endif /* USE_BACKING_STORE */
2780 gdk_window_free_paint_stack (GdkWindow *window)
2782 GdkWindowObject *private = (GdkWindowObject *)window;
2784 if (private->paint_stack)
2786 GSList *tmp_list = private->paint_stack;
2790 GdkWindowPaint *paint = tmp_list->data;
2792 if (tmp_list == private->paint_stack)
2793 g_object_unref (paint->pixmap);
2795 gdk_region_destroy (paint->region);
2798 tmp_list = tmp_list->next;
2801 g_slist_free (private->paint_stack);
2802 private->paint_stack = NULL;
2807 do_move_region_bits_on_impl (GdkWindowObject *impl_window,
2808 GdkRegion *dest_region, /* In impl window coords */
2812 GdkRectangle copy_rect;
2813 GdkWindowObject *private;
2815 /* We need to get data from subwindows here, because we might have
2816 * shaped a native window over the moving region (with bg none,
2817 * so the pixels are still there). In fact we might need to get data
2818 * from overlapping native window that are not children of this window,
2819 * so we copy from the toplevel with INCLUDE_INFERIORS.
2821 private = impl_window;
2822 while (private->parent != NULL &&
2823 private->parent->window_type != GDK_WINDOW_ROOT)
2825 dx -= private->parent->abs_x + private->x;
2826 dy -= private->parent->abs_y + private->y;
2827 private = gdk_window_get_impl_window (private->parent);
2829 tmp_gc = _gdk_drawable_get_subwindow_scratch_gc ((GdkWindow *)private);
2831 /* The region area is moved and we queue translations for all expose events
2832 to the source area that were sent prior to the copy */
2833 gdk_region_offset (dest_region, -dx, -dy); /* Temporarily move to source area */
2834 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->queue_translation ((GdkWindow *)impl_window,
2835 dest_region, dx, dy);
2836 gdk_region_offset (dest_region, dx, dy); /* back to dest area */
2838 gdk_region_get_clipbox (dest_region, ©_rect);
2840 gdk_gc_set_clip_region (tmp_gc, dest_region);
2841 gdk_draw_drawable (impl_window->impl,
2844 copy_rect.x-dx, copy_rect.y-dy,
2845 copy_rect.x, copy_rect.y,
2846 copy_rect.width, copy_rect.height);
2847 gdk_gc_set_clip_region (tmp_gc, NULL);
2850 static GdkWindowRegionMove *
2851 gdk_window_region_move_new (GdkRegion *region,
2854 GdkWindowRegionMove *move;
2856 move = g_slice_new (GdkWindowRegionMove);
2857 move->dest_region = gdk_region_copy (region);
2865 gdk_window_region_move_free (GdkWindowRegionMove *move)
2867 gdk_region_destroy (move->dest_region);
2868 g_slice_free (GdkWindowRegionMove, move);
2872 append_move_region (GdkWindowObject *impl_window,
2873 GdkRegion *new_dest_region,
2876 GdkWindowRegionMove *move, *old_move;
2877 GdkRegion *new_total_region, *old_total_region;
2878 GdkRegion *source_overlaps_destination;
2879 GdkRegion *non_overwritten;
2880 gboolean added_move;
2883 if (gdk_region_empty (new_dest_region))
2886 /* In principle this could just append the move to the list of outstanding
2887 moves that will be replayed before drawing anything when we're handling
2888 exposes. However, we'd like to do a bit better since its commonly the case
2889 that we get multiple copies where A is copied to B and then B is copied
2890 to C, and we'd like to express this as a simple copy A to C operation. */
2892 /* We approach this by taking the new move and pushing it ahead of moves
2893 starting at the end of the list and stopping when its not safe to do so.
2894 It's not safe to push past a move if either the source of the new move
2895 is in the destination of the old move, or if the destination of the new
2896 move is in the source of the new move, or if the destination of the new
2897 move overlaps the destination of the old move. We simplify this by
2898 just comparing the total regions (src + dest) */
2899 new_total_region = gdk_region_copy (new_dest_region);
2900 gdk_region_offset (new_total_region, -dx, -dy);
2901 gdk_region_union (new_total_region, new_dest_region);
2904 for (l = g_list_last (impl_window->outstanding_moves); l != NULL; l = prev)
2909 old_total_region = gdk_region_copy (old_move->dest_region);
2910 gdk_region_offset (old_total_region, -old_move->dx, -old_move->dy);
2911 gdk_region_union (old_total_region, old_move->dest_region);
2913 gdk_region_intersect (old_total_region, new_total_region);
2914 /* If these regions intersect then its not safe to push the
2915 new region before the old one */
2916 if (!gdk_region_empty (old_total_region))
2918 /* The area where the new moves source overlaps the old ones
2920 source_overlaps_destination = gdk_region_copy (new_dest_region);
2921 gdk_region_offset (source_overlaps_destination, -dx, -dy);
2922 gdk_region_intersect (source_overlaps_destination, old_move->dest_region);
2923 gdk_region_offset (source_overlaps_destination, dx, dy);
2925 /* We can do all sort of optimizations here, but to do things safely it becomes
2926 quite complicated. However, a very common case is that you copy something first,
2927 then copy all that or a subset of it to a new location (i.e. if you scroll twice
2928 in the same direction). We'd like to detect this case and optimize it to one
2930 if (gdk_region_equal (source_overlaps_destination, new_dest_region))
2932 /* This means we might be able to replace the old move and the new one
2933 with the new one read from the old ones source, and a second copy of
2934 the non-overwritten parts of the old move. However, such a split
2935 is only valid if the source in the old move isn't overwritten
2936 by the destination of the new one */
2938 /* the new destination of old move if split is ok: */
2939 non_overwritten = gdk_region_copy (old_move->dest_region);
2940 gdk_region_subtract (non_overwritten, new_dest_region);
2941 /* move to source region */
2942 gdk_region_offset (non_overwritten, -old_move->dx, -old_move->dy);
2944 gdk_region_intersect (non_overwritten, new_dest_region);
2945 if (gdk_region_empty (non_overwritten))
2948 move = gdk_window_region_move_new (new_dest_region,
2952 impl_window->outstanding_moves =
2953 g_list_insert_before (impl_window->outstanding_moves,
2955 gdk_region_subtract (old_move->dest_region, new_dest_region);
2957 gdk_region_destroy (non_overwritten);
2960 gdk_region_destroy (source_overlaps_destination);
2961 gdk_region_destroy (old_total_region);
2964 gdk_region_destroy (old_total_region);
2967 gdk_region_destroy (new_total_region);
2971 move = gdk_window_region_move_new (new_dest_region, dx, dy);
2974 impl_window->outstanding_moves =
2975 g_list_prepend (impl_window->outstanding_moves,
2978 impl_window->outstanding_moves =
2979 g_list_insert_before (impl_window->outstanding_moves,
2984 /* Moves bits and update area by dx/dy in impl window.
2985 Takes ownership of region to avoid copy (because we may change it) */
2987 move_region_on_impl (GdkWindowObject *private,
2988 GdkRegion *region, /* In impl window coords */
2991 GdkWindowObject *impl_window;
2993 if ((dx == 0 && dy == 0) ||
2994 gdk_region_empty (region))
2996 gdk_region_destroy (region);
3000 impl_window = gdk_window_get_impl_window (private);
3002 /* Move any old invalid regions in the copy source area by dx/dy */
3003 if (impl_window->update_area)
3005 GdkRegion *update_area;
3006 update_area = gdk_region_copy (region);
3008 /* Convert from target to source */
3009 gdk_region_offset (update_area, -dx, -dy);
3010 gdk_region_intersect (update_area, impl_window->update_area);
3011 /* We only copy the area, so keep the old update area invalid.
3012 It would be safe to remove it too, as code that uses
3013 move_region_on_impl generally also invalidate the source
3014 area. However, it would just use waste cycles. */
3017 gdk_region_offset (update_area, dx, dy);
3018 gdk_region_union (impl_window->update_area, update_area);
3020 /* This area of the destination is now invalid,
3021 so no need to copy to it. */
3022 gdk_region_subtract (region, update_area);
3024 gdk_region_destroy (update_area);
3027 if (1) /* Enable flicker free handling of moves. */
3028 append_move_region (impl_window, region, dx, dy);
3030 do_move_region_bits_on_impl (impl_window,
3033 gdk_region_destroy (region);
3036 /* Flushes all outstanding changes to the window, call this
3037 * before drawing directly to the window (i.e. outside a begin/end_paint pair).
3040 gdk_window_flush_outstanding_moves (GdkWindow *window)
3042 GdkWindowObject *private;
3043 GdkWindowObject *impl_window;
3045 GdkWindowRegionMove *move;
3047 private = (GdkWindowObject *) window;
3049 impl_window = gdk_window_get_impl_window (private);
3051 for (l = impl_window->outstanding_moves; l != NULL; l = l->next)
3055 do_move_region_bits_on_impl (impl_window,
3056 move->dest_region, move->dx, move->dy);
3058 gdk_window_region_move_free (move);
3061 g_list_free (impl_window->outstanding_moves);
3062 impl_window->outstanding_moves = NULL;
3066 gdk_window_flush (GdkWindow *window)
3068 gdk_window_flush_outstanding_moves (window);
3069 gdk_window_flush_implicit_paint (window);
3073 gdk_window_flush_recursive_helper (GdkWindowObject *window,
3076 GdkWindowObject *child;
3079 for (l = window->children; l != NULL; l = l->next)
3083 if (child->impl == impl)
3084 /* Same impl, ignore */
3085 gdk_window_flush_recursive_helper (child, impl);
3087 gdk_window_flush_recursive (child);
3092 gdk_window_flush_recursive (GdkWindowObject *window)
3094 gdk_window_flush ((GdkWindow *)window);
3095 gdk_window_flush_recursive_helper (window, window->impl);
3099 gdk_window_get_offsets (GdkWindow *window,
3103 GdkWindowObject *private = (GdkWindowObject *)window;
3105 if (private->paint_stack)
3107 GdkWindowPaint *paint = private->paint_stack->data;
3108 *x_offset = paint->x_offset;
3109 *y_offset = paint->y_offset;
3113 *x_offset = -private->abs_x;
3114 *y_offset = -private->abs_y;
3119 * gdk_window_get_internal_paint_info:
3120 * @window: a #GdkWindow
3121 * @real_drawable: location to store the drawable to which drawing should be
3123 * @x_offset: location to store the X offset between coordinates in @window,
3124 * and the underlying window system primitive coordinates for
3126 * @y_offset: location to store the Y offset between coordinates in @window,
3127 * and the underlying window system primitive coordinates for
3130 * If you bypass the GDK layer and use windowing system primitives to
3131 * draw directly onto a #GdkWindow, then you need to deal with two
3132 * details: there may be an offset between GDK coordinates and windowing
3133 * system coordinates, and GDK may have redirected drawing to a offscreen
3134 * pixmap as the result of a gdk_window_begin_paint_region() calls.
3135 * This function allows retrieving the information you need to compensate
3136 * for these effects.
3138 * This function exposes details of the GDK implementation, and is thus
3139 * likely to change in future releases of GDK.
3142 gdk_window_get_internal_paint_info (GdkWindow *window,
3143 GdkDrawable **real_drawable,
3149 GdkWindowObject *private;
3151 g_return_if_fail (GDK_IS_WINDOW (window));
3153 private = (GdkWindowObject *)window;
3157 if (private->paint_stack)
3159 GdkWindowPaint *paint = private->paint_stack->data;
3160 *real_drawable = paint->pixmap;
3164 /* This means you're probably gonna be doing some weird shit
3165 directly to the window, so we flush all outstanding stuff */
3166 gdk_window_flush (window);
3167 *real_drawable = window;
3171 gdk_window_get_offsets (window, &x_off, &y_off);
3179 static GdkDrawable *
3180 start_draw_helper (GdkDrawable *drawable,
3185 GdkWindowObject *private = (GdkWindowObject *)drawable;
3186 gint x_offset, y_offset;
3188 gint old_clip_x = gc->clip_x_origin;
3189 gint old_clip_y = gc->clip_y_origin;
3191 guint32 clip_region_tag;
3192 GdkWindowPaint *paint;
3195 if (private->paint_stack)
3196 paint = private->paint_stack->data;
3200 x_offset = paint->x_offset;
3201 y_offset = paint->y_offset;
3205 x_offset = -private->abs_x;
3206 y_offset = -private->abs_y;
3209 if (x_offset != 0 || y_offset != 0)
3211 gdk_gc_set_clip_origin (gc,
3212 old_clip_x - x_offset,
3213 old_clip_y - y_offset);
3214 gdk_gc_set_ts_origin (gc,
3215 gc->ts_x_origin - x_offset,
3216 gc->ts_y_origin - y_offset);
3219 *x_offset_out = x_offset;
3220 *y_offset_out = y_offset;
3222 /* Add client side window clip region to gc */
3226 /* Only need clipping if using implicit paint, otherwise
3227 the pixmap is clipped when copying to the window in end_paint */
3228 if (paint->uses_implicit)
3230 /* This includes the window clip */
3231 clip = paint->region;
3233 clip_region_tag = paint->region_tag;
3235 /* After having set up the drawable clip rect on a GC we need to make sure
3236 * that we draw to th the impl, otherwise the pixmap code will reset the
3238 impl = ((GdkPixmapObject *)(paint->pixmap))->impl;
3242 /* Drawing directly to the window, flush anything outstanding to
3243 guarantee ordering. */
3244 gdk_window_flush ((GdkWindow *)drawable);
3246 /* Don't clip when drawing to root */
3247 if (private->window_type != GDK_WINDOW_ROOT)
3249 if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
3250 clip = private->clip_region_with_children;
3252 clip = private->clip_region;
3254 clip_region_tag = private->clip_tag;
3255 impl = private->impl;
3259 _gdk_gc_add_drawable_clip (gc,
3260 clip_region_tag, clip,
3261 /* If there was a clip origin set appart from the
3262 * window offset, need to take that into
3264 -old_clip_x, -old_clip_y);
3269 #define BEGIN_DRAW \
3271 GdkDrawable *impl; \
3272 gint x_offset, y_offset; \
3273 gint old_clip_x = gc->clip_x_origin; \
3274 gint old_clip_y = gc->clip_y_origin; \
3275 gint old_ts_x = gc->ts_x_origin; \
3276 gint old_ts_y = gc->ts_y_origin; \
3277 impl = start_draw_helper (drawable, gc, \
3278 &x_offset, &y_offset);
3281 if (x_offset != 0 || y_offset != 0) \
3283 gdk_gc_set_clip_origin (gc, old_clip_x, old_clip_y); \
3284 gdk_gc_set_ts_origin (gc, old_ts_x, old_ts_y); \
3289 gdk_window_create_gc (GdkDrawable *drawable,
3290 GdkGCValues *values,
3291 GdkGCValuesMask mask)
3293 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
3295 if (GDK_WINDOW_DESTROYED (drawable))
3298 return gdk_gc_new_with_values (((GdkWindowObject *) drawable)->impl,
3303 gdk_window_draw_rectangle (GdkDrawable *drawable,
3311 if (GDK_WINDOW_DESTROYED (drawable))
3315 gdk_draw_rectangle (impl, gc, filled,
3316 x - x_offset, y - y_offset, width, height);
3321 gdk_window_draw_arc (GdkDrawable *drawable,
3331 if (GDK_WINDOW_DESTROYED (drawable))
3335 gdk_draw_arc (impl, gc, filled,
3336 x - x_offset, y - y_offset,
3337 width, height, angle1, angle2);
3342 gdk_window_draw_polygon (GdkDrawable *drawable,
3348 GdkPoint *new_points;
3350 if (GDK_WINDOW_DESTROYED (drawable))
3355 if (x_offset != 0 || y_offset != 0)
3359 new_points = g_new (GdkPoint, npoints);
3360 for (i=0; i<npoints; i++)
3362 new_points[i].x = points[i].x - x_offset;
3363 new_points[i].y = points[i].y - y_offset;
3367 new_points = points;
3369 gdk_draw_polygon (impl, gc, filled, new_points, npoints);
3371 if (new_points != points)
3372 g_free (new_points);
3378 gdk_window_draw_text (GdkDrawable *drawable,
3386 if (GDK_WINDOW_DESTROYED (drawable))
3390 gdk_draw_text (impl, font, gc,
3391 x - x_offset, y - y_offset, text, text_length);
3396 gdk_window_draw_text_wc (GdkDrawable *drawable,
3401 const GdkWChar *text,
3404 if (GDK_WINDOW_DESTROYED (drawable))
3408 gdk_draw_text_wc (impl, font, gc,
3409 x - x_offset, y - y_offset, text, text_length);
3413 static GdkDrawable *
3414 gdk_window_get_source_drawable (GdkDrawable *drawable)
3416 GdkWindow *window = GDK_WINDOW (drawable);
3417 GdkWindowObject *private;
3419 private = (GdkWindowObject *) window;
3420 if (GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable)
3421 return GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable (private->impl);
3426 static GdkDrawable *
3427 gdk_window_get_composite_drawable (GdkDrawable *drawable,
3432 gint *composite_x_offset,
3433 gint *composite_y_offset)
3435 GdkWindowObject *private = (GdkWindowObject *)drawable;
3437 GdkPixmap *tmp_pixmap;
3440 gboolean overlap_buffer;
3441 GdkDrawable *source;
3442 GdkWindowObject *impl_window;
3443 GdkWindowPaint *implicit_paint;
3445 *composite_x_offset = -private->abs_x;
3446 *composite_y_offset = -private->abs_y;
3448 if ((GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable)))
3449 return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
3451 /* See if any buffered part is overlapping the part we want
3457 rect.height = height;
3459 overlap_buffer = FALSE;
3461 for (list = private->paint_stack; list != NULL; list = list->next)
3463 GdkWindowPaint *paint = list->data;
3464 GdkOverlapType overlap;
3466 overlap = gdk_region_rect_in (paint->region, &rect);
3468 if (overlap == GDK_OVERLAP_RECTANGLE_IN)
3470 *composite_x_offset = paint->x_offset;
3471 *composite_y_offset = paint->y_offset;
3473 return g_object_ref (paint->pixmap);
3475 else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
3477 overlap_buffer = TRUE;
3482 impl_window = gdk_window_get_impl_window (private);
3483 implicit_paint = impl_window->implicit_paint;
3486 GdkOverlapType overlap;
3488 rect.x += private->abs_x;
3489 rect.y += private->abs_y;
3491 overlap = gdk_region_rect_in (implicit_paint->region, &rect);
3492 if (overlap == GDK_OVERLAP_RECTANGLE_IN)
3494 *composite_x_offset = -private->abs_x + implicit_paint->x_offset;
3495 *composite_y_offset = -private->abs_y + implicit_paint->y_offset;
3497 return g_object_ref (implicit_paint->pixmap);
3499 else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
3500 overlap_buffer = TRUE;
3503 if (!overlap_buffer)
3504 return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
3506 tmp_pixmap = gdk_pixmap_new (drawable, width, height, -1);
3507 tmp_gc = _gdk_drawable_get_scratch_gc (tmp_pixmap, FALSE);
3509 source = _gdk_drawable_get_source_drawable (drawable);
3511 /* Copy the current window contents */
3512 gdk_draw_drawable (tmp_pixmap,
3514 GDK_WINDOW_OBJECT (source)->impl,
3515 x - *composite_x_offset,
3516 y - *composite_y_offset,
3520 /* paint the backing stores */
3523 GdkWindowPaint *paint = list->data;
3525 gdk_gc_set_clip_region (tmp_gc, paint->region);
3526 gdk_gc_set_clip_origin (tmp_gc, -x - paint->x_offset, -y - paint->y_offset);
3528 gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
3529 x - paint->x_offset,
3530 y - paint->y_offset,
3531 0, 0, width, height);
3534 for (list = private->paint_stack; list != NULL; list = list->next)
3536 GdkWindowPaint *paint = list->data;
3538 if (paint->uses_implicit)
3539 continue; /* We already copied this above */
3541 gdk_gc_set_clip_region (tmp_gc, paint->region);
3542 gdk_gc_set_clip_origin (tmp_gc, -x, -y);
3544 gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
3545 x - paint->x_offset,
3546 y - paint->y_offset,
3547 0, 0, width, height);
3550 /* Reset clip region of the cached GdkGC */
3551 gdk_gc_set_clip_region (tmp_gc, NULL);
3553 /* Set these to location of tmp_pixmap within the window */
3554 *composite_x_offset = x;
3555 *composite_y_offset = y;
3561 gdk_window_get_clip_region (GdkDrawable *drawable)
3563 GdkWindowObject *private = (GdkWindowObject *)drawable;
3566 result = gdk_region_copy (private->clip_region);
3568 if (private->paint_stack)
3570 GdkRegion *paint_region = gdk_region_new ();
3571 GSList *tmp_list = private->paint_stack;
3575 GdkWindowPaint *paint = tmp_list->data;
3577 gdk_region_union (paint_region, paint->region);
3579 tmp_list = tmp_list->next;
3582 gdk_region_intersect (result, paint_region);
3583 gdk_region_destroy (paint_region);
3590 gdk_window_get_visible_region (GdkDrawable *drawable)
3592 GdkWindowObject *private = (GdkWindowObject*) drawable;
3594 return gdk_region_copy (private->clip_region);
3598 gdk_window_draw_drawable (GdkDrawable *drawable,
3607 GdkDrawable *original_src)
3609 GdkWindowObject *private = (GdkWindowObject *)drawable;
3611 if (GDK_WINDOW_DESTROYED (drawable))
3616 gdk_draw_drawable (impl, gc, src, xsrc, ysrc,
3617 xdest - x_offset, ydest - y_offset, width, height);
3619 if (!private->paint_stack)
3621 /* We might have drawn from an obscured part of a client
3622 side window, if so we need to send graphics exposures */
3623 if (_gdk_gc_get_exposures (gc) &&
3624 GDK_IS_WINDOW (original_src))
3626 GdkRegion *exposure_region;
3634 exposure_region = gdk_region_rectangle (&r);
3636 if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
3637 clip = private->clip_region_with_children;
3639 clip = private->clip_region;
3640 gdk_region_intersect (exposure_region, clip);
3642 clip = _gdk_gc_get_clip_region (gc);
3645 gdk_region_offset (exposure_region,
3648 gdk_region_intersect (exposure_region, clip);
3649 gdk_region_offset (exposure_region,
3654 /* Note: We don't clip by the clip mask if set, so this
3655 may invalidate to much */
3657 /* Remove the area that is correctly copied from the src.
3658 * Note that xsrc/ysrc has been corrected for abs_x/y offsets already,
3659 * which need to be undone */
3660 clip = gdk_drawable_get_visible_region (original_src);
3661 gdk_region_offset (clip,
3662 xdest - (xsrc - GDK_WINDOW_OBJECT (original_src)->abs_x),
3663 ydest - (ysrc - GDK_WINDOW_OBJECT (original_src)->abs_y));
3664 gdk_region_subtract (exposure_region, clip);
3665 gdk_region_destroy (clip);
3667 gdk_window_invalidate_region (GDK_WINDOW (private),
3669 _gdk_gc_get_subwindow (gc) == GDK_INCLUDE_INFERIORS);
3671 gdk_region_destroy (exposure_region);
3679 gdk_window_draw_points (GdkDrawable *drawable,
3684 GdkPoint *new_points;
3686 if (GDK_WINDOW_DESTROYED (drawable))
3691 if (x_offset != 0 || y_offset != 0)
3695 new_points = g_new (GdkPoint, npoints);
3696 for (i=0; i<npoints; i++)
3698 new_points[i].x = points[i].x - x_offset;
3699 new_points[i].y = points[i].y - y_offset;
3703 new_points = points;
3705 gdk_draw_points (impl, gc, new_points, npoints);
3707 if (new_points != points)
3708 g_free (new_points);
3714 gdk_window_draw_segments (GdkDrawable *drawable,
3719 GdkSegment *new_segs;
3721 if (GDK_WINDOW_DESTROYED (drawable))
3726 if (x_offset != 0 || y_offset != 0)
3730 new_segs = g_new (GdkSegment, nsegs);
3731 for (i=0; i<nsegs; i++)
3733 new_segs[i].x1 = segs[i].x1 - x_offset;
3734 new_segs[i].y1 = segs[i].y1 - y_offset;
3735 new_segs[i].x2 = segs[i].x2 - x_offset;
3736 new_segs[i].y2 = segs[i].y2 - y_offset;
3742 gdk_draw_segments (impl, gc, new_segs, nsegs);
3744 if (new_segs != segs)
3751 gdk_window_draw_lines (GdkDrawable *drawable,
3756 GdkPoint *new_points;
3758 if (GDK_WINDOW_DESTROYED (drawable))
3763 if (x_offset != 0 || y_offset != 0)
3767 new_points = g_new (GdkPoint, npoints);
3768 for (i=0; i<npoints; i++)
3770 new_points[i].x = points[i].x - x_offset;
3771 new_points[i].y = points[i].y - y_offset;
3775 new_points = points;
3777 gdk_draw_lines (impl, gc, new_points, npoints);
3779 if (new_points != points)
3780 g_free (new_points);
3786 gdk_window_draw_glyphs (GdkDrawable *drawable,
3791 PangoGlyphString *glyphs)
3793 if (GDK_WINDOW_DESTROYED (drawable))
3797 gdk_draw_glyphs (impl, gc, font,
3798 x - x_offset, y - y_offset, glyphs);
3803 gdk_window_draw_glyphs_transformed (GdkDrawable *drawable,
3805 PangoMatrix *matrix,
3809 PangoGlyphString *glyphs)
3811 PangoMatrix tmp_matrix;
3813 if (GDK_WINDOW_DESTROYED (drawable))
3818 if (x_offset != 0 || y_offset != 0)
3822 tmp_matrix = *matrix;
3823 tmp_matrix.x0 -= x_offset;
3824 tmp_matrix.y0 -= y_offset;
3825 matrix = &tmp_matrix;
3827 else if (GDK_PANGO_UNITS_OVERFLOWS (x_offset, y_offset))
3829 PangoMatrix identity = PANGO_MATRIX_INIT;
3831 tmp_matrix = identity;
3832 tmp_matrix.x0 -= x_offset;
3833 tmp_matrix.y0 -= y_offset;
3834 matrix = &tmp_matrix;
3838 x -= x_offset * PANGO_SCALE;
3839 y -= y_offset * PANGO_SCALE;
3843 gdk_draw_glyphs_transformed (impl, gc, matrix, font, x, y, glyphs);
3849 cairo_t *cr; /* if non-null, it means use this cairo context */
3850 GdkGC *gc; /* if non-null, it means use this GC instead */
3851 } BackingRectMethod;
3854 setup_backing_rect_method (BackingRectMethod *method, GdkWindow *window, GdkWindowPaint *paint, int x_offset_cairo, int y_offset_cairo)
3856 GdkWindowObject *private = (GdkWindowObject *)window;
3858 if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
3860 GdkWindowPaint tmp_paint;
3863 tmp_paint.x_offset += private->x;
3864 tmp_paint.y_offset += private->y;
3866 x_offset_cairo += private->x;
3867 y_offset_cairo += private->y;
3869 setup_backing_rect_method (method, GDK_WINDOW (private->parent), &tmp_paint, x_offset_cairo, y_offset_cairo);
3871 else if (private->bg_pixmap &&
3872 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
3873 private->bg_pixmap != GDK_NO_BG)
3875 /* This is a workaround for https://bugs.freedesktop.org/show_bug.cgi?id=4320.
3876 * In it, using a pixmap as a repeating pattern in Cairo, and painting it to a
3877 * pixmap destination surface, can be very slow (on the order of seconds for a
3878 * whole-screen copy). The workaround is to use pretty much the same code that
3879 * we used in GTK+ 2.6 (pre-Cairo), which clears the double-buffer pixmap with
3880 * a tiled GC XFillRectangle().
3883 /* Actually computing this flag is left as an exercise for the reader */
3884 #if defined (G_OS_UNIX)
3885 # define GDK_CAIRO_REPEAT_IS_FAST 0
3887 # define GDK_CAIRO_REPEAT_IS_FAST 1
3890 #if GDK_CAIRO_REPEAT_IS_FAST
3891 cairo_surface_t *surface = _gdk_drawable_ref_cairo_surface (private->bg_pixmap);
3892 cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
3893 cairo_surface_destroy (surface);
3895 if (x_offset_cairo != 0 || y_offset_cairo != 0)
3897 cairo_matrix_t matrix;
3898 cairo_matrix_init_translate (&matrix, x_offset_cairo, y_offset_cairo);
3899 cairo_pattern_set_matrix (pattern, &matrix);
3902 cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
3904 method->cr = cairo_create (paint->surface);
3907 cairo_set_source (method->cr, pattern);
3908 cairo_pattern_destroy (pattern);
3911 GdkGCValues gc_values;
3913 gc_values.fill = GDK_TILED;
3914 gc_values.tile = private->bg_pixmap;
3915 gc_values.ts_x_origin = -x_offset_cairo;
3916 gc_values.ts_y_origin = -y_offset_cairo;
3918 gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN;
3920 method->gc = gdk_gc_new_with_values (paint->pixmap, &gc_values, gc_mask);
3925 method->cr = cairo_create (paint->surface);
3927 gdk_cairo_set_source_color (method->cr, &private->bg_color);
3932 gdk_window_clear_backing_region (GdkWindow *window,
3935 GdkWindowObject *private = (GdkWindowObject *)window;
3936 GdkWindowPaint *paint = private->paint_stack->data;
3937 BackingRectMethod method;
3939 GdkRectangle clipbox;
3945 if (GDK_WINDOW_DESTROYED (window))
3949 timer = g_timer_new ();
3954 setup_backing_rect_method (&method, window, paint, 0, 0);
3956 clip = gdk_region_copy (paint->region);
3957 gdk_region_intersect (clip, region);
3958 gdk_region_get_clipbox (clip, &clipbox);
3963 g_assert (method.gc == NULL);
3965 gdk_cairo_region (method.cr, clip);
3966 cairo_fill (method.cr);
3968 cairo_destroy (method.cr);
3970 elapsed = g_timer_elapsed (timer, NULL);
3971 g_print ("Draw the background with Cairo: %fs\n", elapsed);
3976 g_assert (method.gc != NULL);
3978 gdk_gc_set_clip_region (method.gc, clip);
3979 gdk_draw_rectangle (window, method.gc, TRUE,
3980 clipbox.x, clipbox.y,
3981 clipbox.width, clipbox.height);
3982 g_object_unref (method.gc);
3985 elapsed = g_timer_elapsed (timer, NULL);
3986 g_print ("Draw the background with GDK: %fs\n", elapsed);
3990 gdk_region_destroy (clip);
3993 g_timer_destroy (timer);
3998 gdk_window_clear_backing_region_redirect (GdkWindow *window,
4001 GdkWindowObject *private = (GdkWindowObject *)window;
4002 GdkWindowRedirect *redirect = private->redirect;
4003 GdkRegion *clip_region;
4004 GdkRectangle clipbox;
4005 gint x_offset, y_offset;
4006 BackingRectMethod method;
4007 GdkWindowPaint paint;
4009 if (GDK_WINDOW_DESTROYED (window))
4012 clip_region = _gdk_window_calculate_full_clip_region (window,
4013 GDK_WINDOW (redirect->redirected),
4015 &x_offset, &y_offset);
4016 gdk_region_intersect (clip_region, region);
4018 /* offset is from redirected window origin to window origin, convert to
4019 the offset from the redirected pixmap origin to the window origin */
4020 x_offset += redirect->dest_x - redirect->src_x;
4021 y_offset += redirect->dest_y - redirect->src_y;
4023 /* Convert region to pixmap coords */
4024 gdk_region_offset (clip_region, x_offset, y_offset);
4028 paint.pixmap = redirect->pixmap;
4029 paint.surface = _gdk_drawable_ref_cairo_surface (redirect->pixmap);
4033 setup_backing_rect_method (&method, window, &paint, -x_offset, -y_offset);
4037 g_assert (method.gc == NULL);
4039 gdk_cairo_region (method.cr, clip_region);
4040 cairo_fill (method.cr);
4042 cairo_destroy (method.cr);
4046 g_assert (method.gc != NULL);
4048 gdk_region_get_clipbox (clip_region, &clipbox);
4049 gdk_gc_set_clip_region (method.gc, clip_region);
4050 gdk_draw_rectangle (redirect->pixmap, method.gc, TRUE,
4051 clipbox.x, clipbox.y,
4052 clipbox.width, clipbox.height);
4053 g_object_unref (method.gc);
4057 gdk_region_destroy (clip_region);
4058 cairo_surface_destroy (paint.surface);
4062 gdk_window_clear_backing_region_direct (GdkWindow *window,
4065 GdkWindowObject *private = (GdkWindowObject *)window;
4066 BackingRectMethod method;
4067 GdkWindowPaint paint;
4069 GdkRectangle clipbox;
4071 if (GDK_WINDOW_DESTROYED (window))
4076 paint.pixmap = window;
4077 paint.surface = _gdk_drawable_ref_cairo_surface (window);
4081 setup_backing_rect_method (&method, window, &paint, 0, 0);
4083 clip = gdk_region_copy (private->clip_region_with_children);
4084 gdk_region_intersect (clip, region);
4085 gdk_region_get_clipbox (clip, &clipbox);
4089 g_assert (method.gc == NULL);
4091 gdk_cairo_region (method.cr, clip);
4092 cairo_fill (method.cr);
4094 cairo_destroy (method.cr);
4098 g_assert (method.gc != NULL);
4100 gdk_gc_set_clip_region (method.gc, clip);
4101 gdk_draw_rectangle (window, method.gc, TRUE,
4102 clipbox.x, clipbox.y,
4103 clipbox.width, clipbox.height);
4104 g_object_unref (method.gc);
4108 gdk_region_destroy (clip);
4109 cairo_surface_destroy (paint.surface);
4115 * @window: a #GdkWindow
4117 * Clears an entire @window to the background color or background pixmap.
4120 gdk_window_clear (GdkWindow *window)
4124 g_return_if_fail (GDK_IS_WINDOW (window));
4126 gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height);
4128 gdk_window_clear_area (window, 0, 0,
4133 clears_on_native (GdkWindowObject *private)
4135 GdkWindowObject *next;
4141 if (gdk_window_has_impl (private))
4143 next = private->parent;
4145 while (private->bg_pixmap == GDK_PARENT_RELATIVE_BG &&
4146 next && next->window_type != GDK_WINDOW_ROOT);
4151 gdk_window_clear_region_internal (GdkWindow *window,
4153 gboolean send_expose)
4155 GdkWindowObject *private = (GdkWindowObject *)window;
4157 if (private->paint_stack)
4158 gdk_window_clear_backing_region (window, region);
4161 if (private->redirect)
4162 gdk_window_clear_backing_region_redirect (window, region);
4164 if (GDK_WINDOW_IMPL_GET_IFACE (private->impl)->clear_region &&
4165 clears_on_native (private))
4168 copy = gdk_region_copy (region);
4169 gdk_region_intersect (copy, private->clip_region_with_children);
4171 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->clear_region
4172 (window, copy, send_expose);
4174 gdk_region_destroy (copy);
4178 gdk_window_clear_backing_region_direct (window, region);
4180 gdk_window_invalidate_region (window, region, FALSE);
4186 gdk_window_clear_area_internal (GdkWindow *window,
4191 gboolean send_expose)
4193 GdkWindowObject *private = (GdkWindowObject *)window;
4197 g_return_if_fail (GDK_IS_WINDOW (window));
4199 if (GDK_WINDOW_DESTROYED (window))
4202 /* This is what XClearArea does, and e.g. GtkCList uses it,
4203 so we need to duplicate that */
4205 width = private->width - x;
4207 height = private->height - y;
4212 rect.height = height;
4214 region = gdk_region_rectangle (&rect);
4215 gdk_window_clear_region_internal (window,
4218 gdk_region_destroy (region);
4223 * gdk_window_clear_area:
4224 * @window: a #GdkWindow
4225 * @x: x coordinate of rectangle to clear
4226 * @y: y coordinate of rectangle to clear
4227 * @width: width of rectangle to clear
4228 * @height: height of rectangle to clear
4230 * Clears an area of @window to the background color or background pixmap.
4234 gdk_window_clear_area (GdkWindow *window,
4240 gdk_window_clear_area_internal (window,
4247 * gdk_window_clear_area_e:
4248 * @window: a #GdkWindow
4249 * @x: x coordinate of rectangle to clear
4250 * @y: y coordinate of rectangle to clear
4251 * @width: width of rectangle to clear
4252 * @height: height of rectangle to clear
4254 * Like gdk_window_clear_area(), but also generates an expose event for
4257 * This function has a stupid name because it dates back to the mists
4258 * time, pre-GDK-1.0.
4262 gdk_window_clear_area_e (GdkWindow *window,
4268 gdk_window_clear_area_internal (window,
4275 gdk_window_draw_image (GdkDrawable *drawable,
4285 if (GDK_WINDOW_DESTROYED (drawable))
4289 gdk_draw_image (impl, gc, image, xsrc, ysrc,
4290 xdest - x_offset, ydest - y_offset,
4296 gdk_window_draw_pixbuf (GdkDrawable *drawable,
4305 GdkRgbDither dither,
4309 GdkWindowObject *private = (GdkWindowObject *)drawable;
4310 GdkDrawableClass *klass;
4312 if (GDK_WINDOW_DESTROYED (drawable))
4315 /* If no gc => no user clipping, but we need clipping
4316 for window emulation, so use a scratch gc */
4318 gc = _gdk_drawable_get_scratch_gc (drawable, FALSE);
4322 klass = GDK_DRAWABLE_GET_CLASS (impl);
4324 if (private->paint_stack)
4325 klass->draw_pixbuf (impl, gc, pixbuf, src_x, src_y,
4326 dest_x - x_offset, dest_y - y_offset,
4328 dither, x_dither - x_offset, y_dither - y_offset);
4330 klass->draw_pixbuf (impl, gc, pixbuf, src_x, src_y,
4331 dest_x - x_offset, dest_y - y_offset,
4333 dither, x_dither, y_dither);
4338 gdk_window_draw_trapezoids (GdkDrawable *drawable,
4340 GdkTrapezoid *trapezoids,
4343 GdkTrapezoid *new_trapezoids = NULL;
4345 if (GDK_WINDOW_DESTROYED (drawable))
4350 if (x_offset != 0 || y_offset != 0)
4354 new_trapezoids = g_new (GdkTrapezoid, n_trapezoids);
4355 for (i=0; i < n_trapezoids; i++)
4357 new_trapezoids[i].y1 = trapezoids[i].y1 - y_offset;
4358 new_trapezoids[i].x11 = trapezoids[i].x11 - x_offset;
4359 new_trapezoids[i].x21 = trapezoids[i].x21 - x_offset;
4360 new_trapezoids[i].y2 = trapezoids[i].y2 - y_offset;
4361 new_trapezoids[i].x12 = trapezoids[i].x12 - x_offset;
4362 new_trapezoids[i].x22 = trapezoids[i].x22 - x_offset;
4365 trapezoids = new_trapezoids;
4368 gdk_draw_trapezoids (impl, gc, trapezoids, n_trapezoids);
4370 g_free (new_trapezoids);
4376 gdk_window_real_get_size (GdkDrawable *drawable,
4380 GdkWindowObject *private = (GdkWindowObject *)drawable;
4383 *width = private->width;
4385 *height = private->height;
4389 gdk_window_real_get_visual (GdkDrawable *drawable)
4391 GdkColormap *colormap;
4393 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4395 colormap = gdk_drawable_get_colormap (drawable);
4396 return colormap ? gdk_colormap_get_visual (colormap) : NULL;
4400 gdk_window_real_get_depth (GdkDrawable *drawable)
4402 g_return_val_if_fail (GDK_IS_WINDOW (drawable), 0);
4404 return ((GdkWindowObject *)GDK_WINDOW (drawable))->depth;
4408 gdk_window_real_get_screen (GdkDrawable *drawable)
4410 return gdk_drawable_get_screen (GDK_WINDOW_OBJECT (drawable)->impl);
4414 gdk_window_real_set_colormap (GdkDrawable *drawable,
4417 GdkWindowObject *private;
4419 g_return_if_fail (GDK_IS_WINDOW (drawable));
4421 if (GDK_WINDOW_DESTROYED (drawable))
4424 private = (GdkWindowObject *)drawable;
4426 /* different colormap than parent, requires native window */
4427 if (!private->input_only &&
4428 cmap != gdk_drawable_get_colormap ((GdkDrawable *)(private->parent)))
4429 gdk_window_ensure_native ((GdkWindow *)drawable);
4431 gdk_drawable_set_colormap (private->impl, cmap);
4435 gdk_window_real_get_colormap (GdkDrawable *drawable)
4437 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4439 if (GDK_WINDOW_DESTROYED (drawable))
4442 return gdk_drawable_get_colormap (((GdkWindowObject*)drawable)->impl);
4446 gdk_window_copy_to_image (GdkDrawable *drawable,
4455 GdkWindowObject *private = (GdkWindowObject *) drawable;
4456 gint x_offset, y_offset;
4458 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4460 if (GDK_WINDOW_DESTROYED (drawable))
4463 /* If we're here, a composite image was not necessary, so
4464 * we can ignore the paint stack.
4467 /* TODO: Is this right? */
4471 return gdk_drawable_copy_to_image (private->impl,
4480 gdk_window_cairo_surface_destroy (void *data)
4482 GdkWindowObject *private = (GdkWindowObject*) data;
4484 private->cairo_surface = NULL;
4487 static cairo_surface_t *
4488 gdk_window_create_cairo_surface (GdkDrawable *drawable,
4492 return _gdk_windowing_create_cairo_surface (GDK_WINDOW_OBJECT(drawable)->impl,
4497 static cairo_surface_t *
4498 gdk_window_ref_cairo_surface (GdkDrawable *drawable)
4500 GdkWindowObject *private = (GdkWindowObject*) drawable;
4501 cairo_surface_t *surface;
4503 if (private->paint_stack)
4505 GdkWindowPaint *paint = private->paint_stack->data;
4507 surface = paint->surface;
4508 cairo_surface_reference (surface);
4513 /* This will be drawing directly to the window, so flush implicit paint */
4514 gdk_window_flush ((GdkWindow *)drawable);
4516 if (!private->cairo_surface)
4519 GdkDrawable *source;
4521 /* It would be nice if we had some cairo support here so we
4522 could set the clip rect on the cairo surface */
4523 width = private->abs_x + private->width;
4524 height = private->abs_y + private->height;
4526 source = _gdk_drawable_get_source_drawable (drawable);
4528 /* TODO: Avoid the typecheck crap by adding virtual call */
4529 private->cairo_surface = _gdk_drawable_create_cairo_surface (source, width, height);
4531 if (private->cairo_surface)
4533 cairo_surface_set_device_offset (private->cairo_surface,
4537 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
4538 drawable, gdk_window_cairo_surface_destroy);
4542 cairo_surface_reference (private->cairo_surface);
4544 surface = private->cairo_surface;
4551 gdk_window_set_cairo_clip (GdkDrawable *drawable,
4554 GdkWindowObject *private = (GdkWindowObject*) drawable;
4556 if (!private->paint_stack)
4559 cairo_identity_matrix (cr);
4561 cairo_reset_clip (cr);
4563 cairo_new_path (cr);
4564 gdk_cairo_region (cr, private->clip_region_with_children);
4571 GdkWindowPaint *paint = private->paint_stack->data;
4573 /* Only needs to clip to region if piggybacking
4574 on an implicit paint pixmap */
4575 if (paint->uses_implicit)
4578 cairo_identity_matrix (cr);
4580 cairo_reset_clip (cr);
4582 cairo_new_path (cr);
4583 gdk_cairo_region (cr, paint->region);
4591 /* Code for dirty-region queueing
4593 static GSList *update_windows = NULL;
4594 static guint update_idle = 0;
4595 static gboolean debug_updates = FALSE;
4597 static inline gboolean
4598 gdk_window_is_ancestor (GdkWindow *window,
4599 GdkWindow *ancestor)
4603 GdkWindow *parent = (GdkWindow*) ((GdkWindowObject*) window)->parent;
4605 if (parent == ancestor)
4615 gdk_window_add_update_window (GdkWindow *window)
4618 GSList *prev = NULL;
4619 gboolean has_ancestor_in_list = FALSE;
4621 for (tmp = update_windows; tmp; tmp = tmp->next)
4623 GdkWindowObject *parent = GDK_WINDOW_OBJECT (window)->parent;
4625 /* check if tmp is an ancestor of "window"; if it is, set a
4626 * flag indicating that all following windows are either
4627 * children of "window" or from a differen hierarchy
4629 if (!has_ancestor_in_list && gdk_window_is_ancestor (window, tmp->data))
4630 has_ancestor_in_list = TRUE;
4632 /* insert in reverse stacking order when adding around siblings,
4633 * so processing updates properly paints over lower stacked windows
4635 if (parent == GDK_WINDOW_OBJECT (tmp->data)->parent)
4637 gint index = g_list_index (parent->children, window);
4638 for (; tmp && parent == GDK_WINDOW_OBJECT (tmp->data)->parent; tmp = tmp->next)
4640 gint sibling_index = g_list_index (parent->children, tmp->data);
4641 if (index > sibling_index)
4645 /* here, tmp got advanced past all lower stacked siblings */
4646 tmp = g_slist_prepend (tmp, window);
4650 update_windows = tmp;
4654 /* if "window" has an ancestor in the list and tmp is one of
4655 * "window's" children, insert "window" before tmp
4657 if (has_ancestor_in_list && gdk_window_is_ancestor (tmp->data, window))
4659 tmp = g_slist_prepend (tmp, window);
4664 update_windows = tmp;
4668 /* if we're at the end of the list and had an ancestor it it,
4669 * append to the list
4671 if (! tmp->next && has_ancestor_in_list)
4673 tmp = g_slist_append (tmp, window);
4680 /* if all above checks failed ("window" is from a different
4681 * hierarchy than what is already in the list) or the list is
4684 update_windows = g_slist_prepend (update_windows, window);
4688 gdk_window_remove_update_window (GdkWindow *window)
4690 update_windows = g_slist_remove (update_windows, window);
4694 gdk_window_update_idle (gpointer data)
4696 gdk_window_process_all_updates ();
4702 gdk_window_is_toplevel_frozen (GdkWindow *window)
4704 GdkWindowObject *toplevel;
4706 toplevel = (GdkWindowObject *)gdk_window_get_toplevel (window);
4708 return toplevel->update_and_descendants_freeze_count > 0;
4712 gdk_window_schedule_update (GdkWindow *window)
4715 (GDK_WINDOW_OBJECT (window)->update_freeze_count ||
4716 gdk_window_is_toplevel_frozen (window)))
4721 update_idle = gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
4722 gdk_window_update_idle, NULL, NULL);
4727 _gdk_window_process_updates_recurse (GdkWindow *window,
4728 GdkRegion *expose_region)
4730 GdkWindowObject *private = (GdkWindowObject *)window;
4731 GdkWindowObject *child;
4732 GdkRegion *child_region;
4736 if (gdk_region_empty (expose_region))
4739 /* Iterate over children, starting at topmost */
4740 for (l = private->children; l != NULL; l = l->next)
4744 if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
4747 /* Ignore offscreen children, as they don't draw in their parent and
4748 * don't take part in the clipping */
4749 if (gdk_window_is_offscreen (child))
4754 r.width = child->width;
4755 r.height = child->height;
4757 child_region = gdk_region_rectangle (&r);
4760 /* Adjust shape region to parent window coords */
4761 gdk_region_offset (child->shape, child->x, child->y);
4762 gdk_region_intersect (child_region, child->shape);
4763 gdk_region_offset (child->shape, -child->x, -child->y);
4766 if (child->impl == private->impl)
4768 /* Client side child, expose */
4769 gdk_region_intersect (child_region, expose_region);
4770 gdk_region_subtract (expose_region, child_region);
4771 gdk_region_offset (child_region, -child->x, -child->y);
4772 _gdk_window_process_updates_recurse ((GdkWindow *)child, child_region);
4776 /* Native child, just remove area from expose region */
4777 gdk_region_subtract (expose_region, child_region);
4779 gdk_region_destroy (child_region);
4782 if (!gdk_region_empty (expose_region))
4784 if (private->event_mask & GDK_EXPOSURE_MASK)
4788 event.expose.type = GDK_EXPOSE;
4789 event.expose.window = g_object_ref (window);
4790 event.expose.send_event = FALSE;
4791 event.expose.count = 0;
4792 event.expose.region = expose_region;
4793 gdk_region_get_clipbox (expose_region, &event.expose.area);
4795 (*_gdk_event_func) (&event, _gdk_event_data);
4797 g_object_unref (window);
4799 else if (private->bg_pixmap != GDK_NO_BG)
4801 /* No exposure mask set, so nothing will be drawn, the
4802 * app relies on the background being what it specified
4803 * for the window. So, we need to clear this manually.
4805 * We use begin/end_paint around the clear so that we can
4806 * piggyback on the implicit paint */
4808 gdk_window_begin_paint_region (window, expose_region);
4809 gdk_window_clear_region_internal (window, expose_region, FALSE);
4810 gdk_window_end_paint (window);
4816 gdk_window_process_updates_internal (GdkWindow *window)
4818 GdkWindowObject *private = (GdkWindowObject *)window;
4819 gboolean save_region = FALSE;
4820 GdkRectangle clip_box;
4822 /* If an update got queued during update processing, we can get a
4823 * window in the update queue that has an empty update_area.
4826 if (private->update_area)
4828 GdkRegion *update_area = private->update_area;
4829 private->update_area = NULL;
4831 if (_gdk_event_func && gdk_window_is_viewable (window) &&
4832 private->window_type != GDK_WINDOW_FOREIGN)
4834 GdkRectangle window_rect;
4835 GdkRegion *expose_region;
4836 GdkRegion *window_region;
4837 gboolean end_implicit;
4839 /* Clip to part visible in toplevel */
4840 gdk_region_intersect (update_area, private->clip_region);
4844 /* Make sure we see the red invalid area before redrawing. */
4845 gdk_display_sync (gdk_drawable_get_display (window));
4849 save_region = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->queue_antiexpose (window, update_area);
4851 expose_region = gdk_region_copy (update_area);
4853 expose_region = update_area;
4857 window_rect.width = private->width;
4858 window_rect.height = private->height;
4860 window_region = gdk_region_rectangle (&window_rect);
4861 gdk_region_intersect (expose_region,
4863 gdk_region_destroy (window_region);
4866 /* No need to do any moves that will end up over the update area */
4867 if (private->outstanding_moves)
4869 GdkWindowRegionMove *move;
4873 remove = gdk_region_copy (update_area);
4874 for (l = g_list_last (private->outstanding_moves); l != NULL; l = prev)
4878 /* Don't need this area */
4879 gdk_region_subtract (move->dest_region, remove);
4881 /* However if any of the destination we do need has a source
4882 in the updated region we do need that as a destination for
4883 the earlier moves */
4884 gdk_region_offset (move->dest_region, -move->dx, -move->dy);
4885 gdk_region_subtract (remove, move->dest_region);
4887 if (gdk_region_empty (move->dest_region))
4889 gdk_window_region_move_free (move);
4890 private->outstanding_moves =
4891 g_list_delete_link (private->outstanding_moves, l);
4894 gdk_region_offset (move->dest_region, move->dx, move->dy);
4896 gdk_region_destroy (remove);
4899 gdk_region_get_clipbox (expose_region, &clip_box);
4900 end_implicit = gdk_window_begin_implicit_paint (window, &clip_box);
4901 if (end_implicit) /* rendering is not double buffered, do moves now */
4902 gdk_window_flush_outstanding_moves (window);
4903 _gdk_windowing_window_process_updates_recurse (window, expose_region);
4906 /* Do moves right before exposes are rendered */
4907 gdk_window_flush_outstanding_moves (window);
4908 gdk_window_end_implicit_paint (window);
4911 if (expose_region != update_area)
4912 gdk_region_destroy (expose_region);
4915 gdk_region_destroy (update_area);
4918 if (private->outstanding_moves)
4920 /* Flush any outstanding moves, may happen if we moved a window but got
4921 no actual invalid area */
4922 gdk_window_flush_outstanding_moves (window);
4927 flush_all_displays (void)
4929 GSList *displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
4932 for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
4933 gdk_display_flush (tmp_list->data);
4935 g_slist_free (displays);
4938 /* Currently it is not possible to override
4939 * gdk_window_process_all_updates in the same manner as
4940 * gdk_window_process_updates and gdk_window_invalidate_maybe_recurse
4941 * by implementing the GdkPaintable interface. If in the future a
4942 * backend would need this, the right solution would be to add a
4943 * method to GdkDisplay that can be optionally
4944 * NULL. gdk_window_process_all_updates can then walk the list of open
4945 * displays and call the mehod.
4949 * gdk_window_process_all_updates:
4951 * Calls gdk_window_process_updates() for all windows (see #GdkWindow)
4952 * in the application.
4956 gdk_window_process_all_updates (void)
4958 GSList *old_update_windows = update_windows;
4959 GSList *tmp_list = update_windows;
4960 static gboolean in_process_all_updates = FALSE;
4962 if (in_process_all_updates)
4965 in_process_all_updates = TRUE;
4968 g_source_remove (update_idle);
4970 update_windows = NULL;
4973 _gdk_windowing_before_process_all_updates ();
4975 g_slist_foreach (old_update_windows, (GFunc)g_object_ref, NULL);
4979 GdkWindowObject *private = (GdkWindowObject *)tmp_list->data;
4981 if (!GDK_WINDOW_DESTROYED (tmp_list->data))
4983 if (private->update_freeze_count ||
4984 gdk_window_is_toplevel_frozen (tmp_list->data))
4985 gdk_window_add_update_window ((GdkWindow *) private);
4987 gdk_window_process_updates_internal (tmp_list->data);
4990 g_object_unref (tmp_list->data);
4991 tmp_list = tmp_list->next;
4994 g_slist_free (old_update_windows);
4996 flush_all_displays ();
4998 _gdk_windowing_after_process_all_updates ();
5000 in_process_all_updates = FALSE;
5004 * gdk_window_process_updates:
5005 * @window: a #GdkWindow
5006 * @update_children: whether to also process updates for child windows
5008 * Sends one or more expose events to @window. The areas in each
5009 * expose event will cover the entire update area for the window (see
5010 * gdk_window_invalidate_region() for details). Normally GDK calls
5011 * gdk_window_process_all_updates() on your behalf, so there's no
5012 * need to call this function unless you want to force expose events
5013 * to be delivered immediately and synchronously (vs. the usual
5014 * case, where GDK delivers them in an idle handler). Occasionally
5015 * this is useful to produce nicer scrolling behavior, for example.
5019 gdk_window_process_updates (GdkWindow *window,
5020 gboolean update_children)
5022 GdkWindowObject *private = (GdkWindowObject *)window;
5023 GdkWindowObject *impl_window;
5025 g_return_if_fail (GDK_IS_WINDOW (window));
5027 impl_window = gdk_window_get_impl_window (private);
5028 if ((impl_window->update_area ||
5029 impl_window->outstanding_moves) &&
5030 !impl_window->update_freeze_count &&
5031 !gdk_window_is_toplevel_frozen (window))
5033 gdk_window_process_updates_internal ((GdkWindow *)impl_window);
5034 gdk_window_remove_update_window ((GdkWindow *)impl_window);
5037 if (update_children)
5039 /* process updates in reverse stacking order so composition or
5040 * painting over achieves the desired effect for offscreen windows
5043 for (node = g_list_last (private->children); node; node = node->prev)
5044 gdk_window_process_updates (node->data, TRUE);
5049 * gdk_window_invalidate_rect:
5050 * @window: a #GdkWindow
5051 * @rect: rectangle to invalidate or %NULL to invalidate the whole
5053 * @invalidate_children: whether to also invalidate child windows
5055 * A convenience wrapper around gdk_window_invalidate_region() which
5056 * invalidates a rectangular region. See
5057 * gdk_window_invalidate_region() for details.
5060 gdk_window_invalidate_rect (GdkWindow *window,
5061 const GdkRectangle *rect,
5062 gboolean invalidate_children)
5064 GdkRectangle window_rect;
5066 GdkWindowObject *private = (GdkWindowObject *)window;
5068 g_return_if_fail (GDK_IS_WINDOW (window));
5070 if (GDK_WINDOW_DESTROYED (window))
5073 if (private->input_only || !private->viewable)
5080 gdk_drawable_get_size (GDK_DRAWABLE (window),
5082 &window_rect.height);
5083 rect = &window_rect;
5086 region = gdk_region_rectangle (rect);
5087 gdk_window_invalidate_region (window, region, invalidate_children);
5088 gdk_region_destroy (region);
5092 draw_ugly_color (GdkWindow *window,
5093 const GdkRegion *region)
5095 /* Draw ugly color all over the newly-invalid region */
5096 GdkColor ugly_color = { 0, 50000, 10000, 10000 };
5098 GdkRectangle clipbox;
5100 ugly_gc = gdk_gc_new (window);
5101 gdk_gc_set_rgb_fg_color (ugly_gc, &ugly_color);
5102 gdk_gc_set_clip_region (ugly_gc, region);
5104 gdk_region_get_clipbox (region, &clipbox);
5106 gdk_draw_rectangle (window,
5109 clipbox.x, clipbox.y,
5110 clipbox.width, clipbox.height);
5112 g_object_unref (ugly_gc);
5116 * gdk_window_invalidate_maybe_recurse:
5117 * @window: a #GdkWindow
5118 * @region: a #GdkRegion
5119 * @child_func: function to use to decide if to recurse to a child,
5120 * %NULL means never recurse.
5121 * @user_data: data passed to @child_func
5123 * Adds @region to the update area for @window. The update area is the
5124 * region that needs to be redrawn, or "dirty region." The call
5125 * gdk_window_process_updates() sends one or more expose events to the
5126 * window, which together cover the entire update area. An
5127 * application would normally redraw the contents of @window in
5128 * response to those expose events.
5130 * GDK will call gdk_window_process_all_updates() on your behalf
5131 * whenever your program returns to the main loop and becomes idle, so
5132 * normally there's no need to do that manually, you just need to
5133 * invalidate regions that you know should be redrawn.
5135 * The @child_func parameter controls whether the region of
5136 * each child window that intersects @region will also be invalidated.
5137 * Only children for which @child_func returns TRUE will have the area
5141 gdk_window_invalidate_maybe_recurse (GdkWindow *window,
5142 const GdkRegion *region,
5143 gboolean (*child_func) (GdkWindow *,
5147 GdkWindowObject *private = (GdkWindowObject *)window;
5148 GdkWindowObject *impl_window;
5149 GdkRegion *visible_region;
5152 g_return_if_fail (GDK_IS_WINDOW (window));
5154 if (GDK_WINDOW_DESTROYED (window))
5157 if (private->input_only ||
5158 !private->viewable ||
5159 gdk_region_empty (region) ||
5160 private->window_type == GDK_WINDOW_ROOT)
5163 visible_region = gdk_drawable_get_visible_region (window);
5164 gdk_region_intersect (visible_region, region);
5166 tmp_list = private->children;
5169 GdkWindowObject *child = tmp_list->data;
5171 if (!child->input_only)
5173 GdkRegion *child_region;
5174 GdkRectangle child_rect;
5176 child_rect.x = child->x;
5177 child_rect.y = child->y;
5178 child_rect.width = child->width;
5179 child_rect.height = child->height;
5180 child_region = gdk_region_rectangle (&child_rect);
5182 /* remove child area from the invalid area of the parent */
5183 if (GDK_WINDOW_IS_MAPPED (child) && !child->shaped &&
5184 !child->composited &&
5185 !gdk_window_is_offscreen (child))
5186 gdk_region_subtract (visible_region, child_region);
5188 if (child_func && (*child_func) ((GdkWindow *)child, user_data))
5190 GdkRegion *tmp = gdk_region_copy (region);
5192 gdk_region_offset (tmp, - child_rect.x, - child_rect.y);
5193 gdk_region_offset (child_region, - child_rect.x, - child_rect.y);
5194 gdk_region_intersect (child_region, tmp);
5196 gdk_window_invalidate_maybe_recurse ((GdkWindow *)child,
5197 child_region, child_func, user_data);
5199 gdk_region_destroy (tmp);
5202 gdk_region_destroy (child_region);
5205 tmp_list = tmp_list->next;
5208 impl_window = gdk_window_get_impl_window (private);
5210 if (!gdk_region_empty (visible_region) ||
5211 /* Even if we're not exposing anything, make sure we process
5212 idles for windows with outstanding moves */
5213 (impl_window->outstanding_moves != NULL &&
5214 impl_window->update_area == NULL))
5217 draw_ugly_color (window, region);
5219 /* Convert to impl coords */
5220 gdk_region_offset (visible_region, private->abs_x, private->abs_y);
5221 if (impl_window->update_area)
5223 gdk_region_union (impl_window->update_area, visible_region);
5227 gdk_window_add_update_window ((GdkWindow *)impl_window);
5228 impl_window->update_area = gdk_region_copy (visible_region);
5230 gdk_window_schedule_update ((GdkWindow *)impl_window);
5234 gdk_region_destroy (visible_region);
5238 true_predicate (GdkWindow *window,
5245 * gdk_window_invalidate_region:
5246 * @window: a #GdkWindow
5247 * @region: a #GdkRegion
5248 * @invalidate_children: %TRUE to also invalidate child windows
5250 * Adds @region to the update area for @window. The update area is the
5251 * region that needs to be redrawn, or "dirty region." The call
5252 * gdk_window_process_updates() sends one or more expose events to the
5253 * window, which together cover the entire update area. An
5254 * application would normally redraw the contents of @window in
5255 * response to those expose events.
5257 * GDK will call gdk_window_process_all_updates() on your behalf
5258 * whenever your program returns to the main loop and becomes idle, so
5259 * normally there's no need to do that manually, you just need to
5260 * invalidate regions that you know should be redrawn.
5262 * The @invalidate_children parameter controls whether the region of
5263 * each child window that intersects @region will also be invalidated.
5264 * If %FALSE, then the update area for child windows will remain
5265 * unaffected. See gdk_window_invalidate_maybe_recurse if you need
5266 * fine grained control over which children are invalidated.
5269 gdk_window_invalidate_region (GdkWindow *window,
5270 const GdkRegion *region,
5271 gboolean invalidate_children)
5273 gdk_window_invalidate_maybe_recurse (window, region,
5274 invalidate_children ?
5275 true_predicate : (gboolean (*) (GdkWindow *, gpointer))NULL,
5280 * _gdk_window_invalidate_for_expose:
5281 * @window: a #GdkWindow
5282 * @region: a #GdkRegion
5284 * Adds @region to the update area for @window. The update area is the
5285 * region that needs to be redrawn, or "dirty region." The call
5286 * gdk_window_process_updates() sends one or more expose events to the
5287 * window, which together cover the entire update area. An
5288 * application would normally redraw the contents of @window in
5289 * response to those expose events.
5291 * GDK will call gdk_window_process_all_updates() on your behalf
5292 * whenever your program returns to the main loop and becomes idle, so
5293 * normally there's no need to do that manually, you just need to
5294 * invalidate regions that you know should be redrawn.
5296 * This version of invalidation is used when you recieve expose events
5297 * from the native window system. It exposes the native window, plus
5298 * any non-native child windows (but not native child windows, as those would
5299 * have gotten their own expose events).
5302 _gdk_window_invalidate_for_expose (GdkWindow *window,
5305 GdkWindowObject *private = (GdkWindowObject *) window;
5306 GdkWindowRegionMove *move;
5307 GdkRegion *move_region;
5310 /* Any invalidations comming from the windowing system will
5311 be in areas that may be moved by outstanding moves,
5312 so we need to modify the expose region correspondingly,
5313 otherwise we would expose in the wrong place, as the
5314 outstanding moves will be copied before we draw the
5316 for (l = private->outstanding_moves; l != NULL; l = l->next)
5320 /* covert to move source region */
5321 move_region = gdk_region_copy (move->dest_region);
5322 gdk_region_offset (move_region, -move->dx, -move->dy);
5324 /* Move area of region that intersects with move source
5325 by dx, dy of the move*/
5326 gdk_region_intersect (move_region, region);
5327 gdk_region_subtract (region, move_region);
5328 gdk_region_offset (move_region, move->dx, move->dy);
5329 gdk_region_union (region, move_region);
5331 gdk_region_destroy (move_region);
5334 gdk_window_invalidate_maybe_recurse (window, region,
5335 (gboolean (*) (GdkWindow *, gpointer))gdk_window_has_no_impl,
5341 * gdk_window_get_update_area:
5342 * @window: a #GdkWindow
5344 * Transfers ownership of the update area from @window to the caller
5345 * of the function. That is, after calling this function, @window will
5346 * no longer have an invalid/dirty region; the update area is removed
5347 * from @window and handed to you. If a window has no update area,
5348 * gdk_window_get_update_area() returns %NULL. You are responsible for
5349 * calling gdk_region_destroy() on the returned region if it's non-%NULL.
5351 * Return value: the update area for @window
5354 gdk_window_get_update_area (GdkWindow *window)
5356 GdkWindowObject *private = (GdkWindowObject *)window;
5357 GdkWindowObject *impl_window;
5358 GdkRegion *tmp_region;
5360 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
5362 impl_window = gdk_window_get_impl_window (private);
5364 if (impl_window->update_area)
5366 tmp_region = gdk_region_copy (private->clip_region_with_children);
5367 /* Convert to impl coords */
5368 gdk_region_offset (tmp_region, private->abs_x, private->abs_y);
5369 gdk_region_intersect (tmp_region, impl_window->update_area);
5371 if (gdk_region_empty (tmp_region))
5373 gdk_region_destroy (tmp_region);
5378 gdk_region_subtract (impl_window->update_area, tmp_region);
5380 if (gdk_region_empty (impl_window->update_area) &&
5381 impl_window->outstanding_moves == NULL)
5383 gdk_region_destroy (impl_window->update_area);
5384 impl_window->update_area = NULL;
5386 gdk_window_remove_update_window ((GdkWindow *)impl_window);
5389 /* Convert from impl coords */
5390 gdk_region_offset (tmp_region, -private->abs_x, -private->abs_y);
5400 * _gdk_window_clear_update_area:
5401 * @window: a #GdkWindow.
5403 * Internal function to clear the update area for a window. This
5404 * is called when the window is hidden or destroyed.
5407 _gdk_window_clear_update_area (GdkWindow *window)
5409 GdkWindowObject *private = (GdkWindowObject *)window;
5411 g_return_if_fail (GDK_IS_WINDOW (window));
5413 if (private->update_area)
5415 gdk_window_remove_update_window (window);
5417 gdk_region_destroy (private->update_area);
5418 private->update_area = NULL;
5423 * gdk_window_freeze_updates:
5424 * @window: a #GdkWindow
5426 * Temporarily freezes a window such that it won't receive expose
5427 * events. The window will begin receiving expose events again when
5428 * gdk_window_thaw_updates() is called. If gdk_window_freeze_updates()
5429 * has been called more than once, gdk_window_thaw_updates() must be called
5430 * an equal number of times to begin processing exposes.
5433 gdk_window_freeze_updates (GdkWindow *window)
5435 GdkWindowObject *private = (GdkWindowObject *)window;
5436 GdkWindowObject *impl_window;
5438 g_return_if_fail (GDK_IS_WINDOW (window));
5440 impl_window = gdk_window_get_impl_window (private);
5441 impl_window->update_freeze_count++;
5445 * gdk_window_thaw_updates:
5446 * @window: a #GdkWindow
5448 * Thaws a window frozen with gdk_window_freeze_updates().
5451 gdk_window_thaw_updates (GdkWindow *window)
5453 GdkWindowObject *private = (GdkWindowObject *)window;
5454 GdkWindowObject *impl_window;
5456 g_return_if_fail (GDK_IS_WINDOW (window));
5458 impl_window = gdk_window_get_impl_window (private);
5460 g_return_if_fail (impl_window->update_freeze_count > 0);
5462 if (--impl_window->update_freeze_count == 0)
5463 gdk_window_schedule_update (GDK_WINDOW (impl_window));
5467 * gdk_window_freeze_toplevel_updates_libgtk_only:
5468 * @window: a #GdkWindow
5470 * Temporarily freezes a window and all its descendants such that it won't
5471 * receive expose events. The window will begin receiving expose events
5472 * again when gdk_window_thaw_toplevel_updates_libgtk_only() is called. If
5473 * gdk_window_freeze_toplevel_updates_libgtk_only()
5474 * has been called more than once,
5475 * gdk_window_thaw_toplevel_updates_libgtk_only() must be called
5476 * an equal number of times to begin processing exposes.
5478 * This function is not part of the GDK public API and is only
5482 gdk_window_freeze_toplevel_updates_libgtk_only (GdkWindow *window)
5484 GdkWindowObject *private = (GdkWindowObject *)window;
5486 g_return_if_fail (GDK_IS_WINDOW (window));
5487 g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
5489 private->update_and_descendants_freeze_count++;
5493 * gdk_window_thaw_toplevel_updates_libgtk_only:
5494 * @window: a #GdkWindow
5496 * Thaws a window frozen with
5497 * gdk_window_freeze_toplevel_updates_libgtk_only().
5499 * This function is not part of the GDK public API and is only
5503 gdk_window_thaw_toplevel_updates_libgtk_only (GdkWindow *window)
5505 GdkWindowObject *private = (GdkWindowObject *)window;
5507 g_return_if_fail (GDK_IS_WINDOW (window));
5508 g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
5509 g_return_if_fail (private->update_and_descendants_freeze_count > 0);
5511 private->update_and_descendants_freeze_count--;
5513 gdk_window_schedule_update (window);
5517 * gdk_window_set_debug_updates:
5518 * @setting: %TRUE to turn on update debugging
5520 * With update debugging enabled, calls to
5521 * gdk_window_invalidate_region() clear the invalidated region of the
5522 * screen to a noticeable color, and GDK pauses for a short time
5523 * before sending exposes to windows during
5524 * gdk_window_process_updates(). The net effect is that you can see
5525 * the invalid region for each window and watch redraws as they
5526 * occur. This allows you to diagnose inefficiencies in your application.
5528 * In essence, because the GDK rendering model prevents all flicker,
5529 * if you are redrawing the same region 400 times you may never
5530 * notice, aside from noticing a speed problem. Enabling update
5531 * debugging causes GTK to flicker slowly and noticeably, so you can
5532 * see exactly what's being redrawn when, in what order.
5534 * The --gtk-debug=updates command line option passed to GTK+ programs
5535 * enables this debug option at application startup time. That's
5536 * usually more useful than calling gdk_window_set_debug_updates()
5537 * yourself, though you might want to use this function to enable
5538 * updates sometime after application startup time.
5542 gdk_window_set_debug_updates (gboolean setting)
5544 debug_updates = setting;
5548 * gdk_window_constrain_size:
5549 * @geometry: a #GdkGeometry structure
5550 * @flags: a mask indicating what portions of @geometry are set
5551 * @width: desired width of window
5552 * @height: desired height of the window
5553 * @new_width: location to store resulting width
5554 * @new_height: location to store resulting height
5556 * Constrains a desired width and height according to a
5557 * set of geometry hints (such as minimum and maximum size).
5560 gdk_window_constrain_size (GdkGeometry *geometry,
5567 /* This routine is partially borrowed from fvwm.
5569 * Copyright 1993, Robert Nation
5570 * You may use this code for any purpose, as long as the original
5571 * copyright remains in the source code and all documentation
5573 * which in turn borrows parts of the algorithm from uwm
5576 gint min_height = 0;
5577 gint base_width = 0;
5578 gint base_height = 0;
5581 gint max_width = G_MAXINT;
5582 gint max_height = G_MAXINT;
5584 #define FLOOR(value, base) ( ((gint) ((value) / (base))) * (base) )
5586 if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
5588 base_width = geometry->base_width;
5589 base_height = geometry->base_height;
5590 min_width = geometry->min_width;
5591 min_height = geometry->min_height;
5593 else if (flags & GDK_HINT_BASE_SIZE)
5595 base_width = geometry->base_width;
5596 base_height = geometry->base_height;
5597 min_width = geometry->base_width;
5598 min_height = geometry->base_height;
5600 else if (flags & GDK_HINT_MIN_SIZE)
5602 base_width = geometry->min_width;
5603 base_height = geometry->min_height;
5604 min_width = geometry->min_width;
5605 min_height = geometry->min_height;
5608 if (flags & GDK_HINT_MAX_SIZE)
5610 max_width = geometry->max_width ;
5611 max_height = geometry->max_height;
5614 if (flags & GDK_HINT_RESIZE_INC)
5616 xinc = MAX (xinc, geometry->width_inc);
5617 yinc = MAX (yinc, geometry->height_inc);
5620 /* clamp width and height to min and max values
5622 width = CLAMP (width, min_width, max_width);
5623 height = CLAMP (height, min_height, max_height);
5625 /* shrink to base + N * inc
5627 width = base_width + FLOOR (width - base_width, xinc);
5628 height = base_height + FLOOR (height - base_height, yinc);
5630 /* constrain aspect ratio, according to:
5633 * min_aspect <= -------- <= max_aspect
5637 if (flags & GDK_HINT_ASPECT &&
5638 geometry->min_aspect > 0 &&
5639 geometry->max_aspect > 0)
5643 if (geometry->min_aspect * height > width)
5645 delta = FLOOR (height - width / geometry->min_aspect, yinc);
5646 if (height - delta >= min_height)
5650 delta = FLOOR (height * geometry->min_aspect - width, xinc);
5651 if (width + delta <= max_width)
5656 if (geometry->max_aspect * height < width)
5658 delta = FLOOR (width - height * geometry->max_aspect, xinc);
5659 if (width - delta >= min_width)
5663 delta = FLOOR (width / geometry->max_aspect - height, yinc);
5664 if (height + delta <= max_height)
5673 *new_height = height;
5677 * gdk_window_get_pointer:
5678 * @window: a #GdkWindow
5679 * @x: return location for X coordinate of pointer or %NULL to not
5680 * return the X coordinate
5681 * @y: return location for Y coordinate of pointer or %NULL to not
5682 * return the Y coordinate
5683 * @mask: return location for modifier mask or %NULL to not return the
5686 * Obtains the current pointer position and modifier state.
5687 * The position is given in coordinates relative to the upper left
5688 * corner of @window.
5690 * Return value: the window containing the pointer (as with
5691 * gdk_window_at_pointer()), or %NULL if the window containing the
5692 * pointer isn't known to GDK
5695 gdk_window_get_pointer (GdkWindow *window,
5698 GdkModifierType *mask)
5700 GdkDisplay *display;
5702 GdkModifierType tmp_mask;
5705 g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
5709 display = gdk_drawable_get_display (window);
5713 GdkScreen *screen = gdk_screen_get_default ();
5715 display = gdk_screen_get_display (screen);
5716 window = gdk_screen_get_root_window (screen);
5718 GDK_NOTE (MULTIHEAD,
5719 g_message ("Passing NULL for window to gdk_window_get_pointer()\n"
5720 "is not multihead safe"));
5723 child = display->pointer_hooks->window_get_pointer (display, window, &tmp_x, &tmp_y, &tmp_mask);
5732 _gdk_display_enable_motion_hints (display);
5738 * gdk_window_at_pointer:
5739 * @win_x: return location for origin of the window under the pointer
5740 * @win_y: return location for origin of the window under the pointer
5742 * Obtains the window underneath the mouse pointer, returning the
5743 * location of that window in @win_x, @win_y. Returns %NULL if the
5744 * window under the mouse pointer is not known to GDK (if the window
5745 * belongs to another application and a #GdkWindow hasn't been created
5746 * for it with gdk_window_foreign_new())
5748 * NOTE: For multihead-aware widgets or applications use
5749 * gdk_display_get_window_at_pointer() instead.
5751 * Return value: window under the mouse pointer
5754 gdk_window_at_pointer (gint *win_x,
5757 return gdk_display_get_window_at_pointer (gdk_display_get_default (), win_x, win_y);
5761 * gdk_get_default_root_window:
5763 * Obtains the root window (parent all other windows are inside)
5764 * for the default display and screen.
5766 * Return value: the default root window
5769 gdk_get_default_root_window (void)
5771 return gdk_screen_get_root_window (gdk_screen_get_default ());
5775 * gdk_window_foreign_new:
5776 * @anid: a native window handle.
5778 * Wraps a native window for the default display in a #GdkWindow.
5779 * This may fail if the window has been destroyed.
5781 * For example in the X backend, a native window handle is an Xlib
5784 * Return value: the newly-created #GdkWindow wrapper for the
5785 * native window or %NULL if the window has been destroyed.
5788 gdk_window_foreign_new (GdkNativeWindow anid)
5790 return gdk_window_foreign_new_for_display (gdk_display_get_default (), anid);
5794 get_all_native_children (GdkWindowObject *private,
5797 GdkWindowObject *child;
5800 for (l = private->children; l != NULL; l = l->next)
5804 if (gdk_window_has_impl (child))
5805 *native = g_list_prepend (*native, child);
5807 get_all_native_children (child, native);
5813 gdk_window_raise_internal (GdkWindow *window)
5815 GdkWindowObject *private = (GdkWindowObject *)window;
5816 GdkWindowObject *parent = private->parent;
5817 GdkWindowObject *above;
5818 GList *native_children;
5823 parent->children = g_list_remove (parent->children, window);
5824 parent->children = g_list_prepend (parent->children, window);
5827 /* Just do native raise for toplevels */
5828 if (private->parent == NULL ||
5829 private->parent->window_type == GDK_WINDOW_ROOT)
5831 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
5833 else if (gdk_window_has_impl (private))
5835 above = find_native_sibling_above (parent, private);
5838 listhead.data = window;
5839 listhead.next = NULL;
5840 listhead.prev = NULL;
5841 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
5845 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
5849 native_children = NULL;
5850 get_all_native_children (private, &native_children);
5851 if (native_children != NULL)
5853 above = find_native_sibling_above (parent, private);
5856 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
5860 /* Right order, since native_children is bottom-topmost first */
5861 for (l = native_children; l != NULL; l = l->next)
5862 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (l->data);
5865 g_list_free (native_children);
5871 /* Returns TRUE If the native window was mapped or unmapped */
5873 set_viewable (GdkWindowObject *w,
5876 GdkWindowObject *child;
5879 if (w->viewable == val)
5885 recompute_visible_regions (w, FALSE, FALSE);
5887 for (l = w->children; l != NULL; l = l->next)
5891 if (GDK_WINDOW_IS_MAPPED (child) &&
5892 child->window_type != GDK_WINDOW_FOREIGN)
5893 set_viewable (child, val);
5896 if (gdk_window_has_impl (w) &&
5897 w->window_type != GDK_WINDOW_FOREIGN &&
5898 w->parent != NULL &&
5899 w->parent->window_type != GDK_WINDOW_ROOT)
5901 /* For most native windows we show/hide them not when they are
5902 * mapped/unmapped, because that may not produce the correct results.
5903 * For instance, if a native window have a non-native parent which is
5904 * hidden, but its native parent is viewable then showing the window
5905 * would make it viewable to X but its not viewable wrt the non-native
5906 * hierarchy. In order to handle this we track the gdk side viewability
5907 * and only map really viewable windows.
5909 * There are two exceptions though:
5911 * For foreign windows we don't want ever change the mapped state
5912 * except when explicitly done via gdk_window_show/hide, as this may
5913 * cause problems for client owning the foreign window when its window
5914 * is suddenly mapped or unmapped.
5916 * For toplevel windows embedded in a foreign window (e.g. a plug)
5917 * we sometimes synthesize a map of a window, but the native
5918 * window is really shown by the embedder, so we don't want to
5919 * do the show ourselves. We can't really tell this case from the normal
5920 * toplevel show as such toplevels are seen by gdk as parents of the
5921 * root window, so we make an exception for all toplevels.
5925 GDK_WINDOW_IMPL_GET_IFACE (w->impl)->show ((GdkWindow *)w, FALSE);
5927 GDK_WINDOW_IMPL_GET_IFACE (w->impl)->hide ((GdkWindow *)w);
5935 /* Returns TRUE If the native window was mapped or unmapped */
5937 _gdk_window_update_viewable (GdkWindow *window)
5939 GdkWindowObject *priv = (GdkWindowObject *)window;
5942 if (priv->window_type == GDK_WINDOW_FOREIGN ||
5943 priv->window_type == GDK_WINDOW_ROOT)
5945 else if (priv->parent == NULL ||
5946 priv->parent->window_type == GDK_WINDOW_ROOT ||
5947 priv->parent->viewable)
5948 viewable = GDK_WINDOW_IS_MAPPED (priv);
5952 return set_viewable (priv, viewable);
5956 gdk_window_show_internal (GdkWindow *window, gboolean raise)
5958 GdkWindowObject *private;
5959 gboolean was_mapped, was_viewable;
5962 g_return_if_fail (GDK_IS_WINDOW (window));
5964 private = (GdkWindowObject *) window;
5965 if (private->destroyed)
5968 was_mapped = GDK_WINDOW_IS_MAPPED (window);
5969 was_viewable = private->viewable;
5972 /* Keep children in (reverse) stacking order */
5973 gdk_window_raise_internal (window);
5975 if (gdk_window_has_impl (private))
5978 gdk_synthesize_window_state (window,
5979 GDK_WINDOW_STATE_WITHDRAWN,
5987 did_show = _gdk_window_update_viewable (window);
5989 /* If it was already viewable the backend show op won't be called, call it
5990 again to ensure things happen right if the mapped tracking was not right
5991 for e.g. a foreign window.
5992 Dunno if this is strictly needed but its what happened pre-csw.
5993 Also show if not done by gdk_window_update_viewable. */
5994 if (gdk_window_has_impl (private) && (was_viewable || !did_show))
5995 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show ((GdkWindow *)private,
5999 if (!was_mapped && !gdk_window_has_impl (private))
6001 if (private->event_mask & GDK_STRUCTURE_MASK)
6002 _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
6004 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
6005 _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
6008 if (!was_mapped || raise)
6010 recompute_visible_regions (private, TRUE, FALSE);
6012 /* If any decendants became visible we need to send visibility notify */
6013 gdk_window_update_visibility_recursively (private, NULL);
6015 if (gdk_window_is_viewable (window))
6017 _gdk_synthesize_crossing_events_for_geometry_change (window);
6018 gdk_window_invalidate_rect (window, NULL, TRUE);
6024 * gdk_window_show_unraised:
6025 * @window: a #GdkWindow
6027 * Shows a #GdkWindow onscreen, but does not modify its stacking
6028 * order. In contrast, gdk_window_show() will raise the window
6029 * to the top of the window stack.
6031 * On the X11 platform, in Xlib terms, this function calls
6032 * XMapWindow() (it also updates some internal GDK state, which means
6033 * that you can't really use XMapWindow() directly on a GDK window).
6036 gdk_window_show_unraised (GdkWindow *window)
6038 gdk_window_show_internal (window, FALSE);
6043 * @window: a #GdkWindow
6045 * Raises @window to the top of the Z-order (stacking order), so that
6046 * other windows with the same parent window appear below @window.
6047 * This is true whether or not the windows are visible.
6049 * If @window is a toplevel, the window manager may choose to deny the
6050 * request to move the window in the Z-order, gdk_window_raise() only
6051 * requests the restack, does not guarantee it.
6054 gdk_window_raise (GdkWindow *window)
6056 GdkWindowObject *private;
6057 GdkRegion *old_region, *new_region;
6059 g_return_if_fail (GDK_IS_WINDOW (window));
6061 private = (GdkWindowObject *) window;
6062 if (private->destroyed)
6066 if (gdk_window_is_viewable (window) &&
6067 !private->input_only)
6068 old_region = gdk_region_copy (private->clip_region);
6070 /* Keep children in (reverse) stacking order */
6071 gdk_window_raise_internal (window);
6073 recompute_visible_regions (private, TRUE, FALSE);
6077 new_region = gdk_region_copy (private->clip_region);
6079 gdk_region_subtract (new_region, old_region);
6080 gdk_window_invalidate_region (window, new_region, TRUE);
6082 gdk_region_destroy (old_region);
6083 gdk_region_destroy (new_region);
6088 gdk_window_lower_internal (GdkWindow *window)
6090 GdkWindowObject *private = (GdkWindowObject *)window;
6091 GdkWindowObject *parent = private->parent;
6092 GdkWindowObject *above;
6093 GList *native_children;
6098 parent->children = g_list_remove (parent->children, window);
6099 parent->children = g_list_append (parent->children, window);
6102 /* Just do native lower for toplevels */
6103 if (private->parent == NULL ||
6104 private->parent->window_type == GDK_WINDOW_ROOT)
6106 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->lower (window);
6108 else if (gdk_window_has_impl (private))
6110 above = find_native_sibling_above (parent, private);
6113 listhead.data = window;
6114 listhead.next = NULL;
6115 listhead.prev = NULL;
6116 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
6120 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
6124 native_children = NULL;
6125 get_all_native_children (private, &native_children);
6126 if (native_children != NULL)
6128 above = find_native_sibling_above (parent, private);
6131 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
6135 /* Right order, since native_children is bottom-topmost first */
6136 for (l = native_children; l != NULL; l = l->next)
6137 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (l->data);
6140 g_list_free (native_children);
6147 gdk_window_invalidate_in_parent (GdkWindowObject *private)
6149 GdkRectangle r, child;
6151 if (private->parent == NULL ||
6152 private->parent->window_type == GDK_WINDOW_ROOT)
6155 /* get the visible rectangle of the parent */
6157 r.width = private->parent->width;
6158 r.height = private->parent->height;
6160 child.x = private->x;
6161 child.y = private->y;
6162 child.width = private->width;
6163 child.height = private->height;
6164 gdk_rectangle_intersect (&r, &child, &r);
6166 gdk_window_invalidate_rect (GDK_WINDOW (private->parent), &r, TRUE);
6172 * @window: a #GdkWindow
6174 * Lowers @window to the bottom of the Z-order (stacking order), so that
6175 * other windows with the same parent window appear above @window.
6176 * This is true whether or not the other windows are visible.
6178 * If @window is a toplevel, the window manager may choose to deny the
6179 * request to move the window in the Z-order, gdk_window_lower() only
6180 * requests the restack, does not guarantee it.
6182 * Note that gdk_window_show() raises the window again, so don't call this
6183 * function before gdk_window_show(). (Try gdk_window_show_unraised().)
6186 gdk_window_lower (GdkWindow *window)
6188 GdkWindowObject *private;
6190 g_return_if_fail (GDK_IS_WINDOW (window));
6192 private = (GdkWindowObject *) window;
6193 if (private->destroyed)
6196 /* Keep children in (reverse) stacking order */
6197 gdk_window_lower_internal (window);
6199 recompute_visible_regions (private, TRUE, FALSE);
6201 _gdk_synthesize_crossing_events_for_geometry_change (window);
6202 gdk_window_invalidate_in_parent (private);
6207 * @window: a #GdkWindow
6209 * Like gdk_window_show_unraised(), but also raises the window to the
6210 * top of the window stack (moves the window to the front of the
6213 * This function maps a window so it's visible onscreen. Its opposite
6214 * is gdk_window_hide().
6216 * When implementing a #GtkWidget, you should call this function on the widget's
6217 * #GdkWindow as part of the "map" method.
6220 gdk_window_show (GdkWindow *window)
6222 gdk_window_show_internal (window, TRUE);
6227 * @window: a #GdkWindow
6229 * For toplevel windows, withdraws them, so they will no longer be
6230 * known to the window manager; for all windows, unmaps them, so
6231 * they won't be displayed. Normally done automatically as
6232 * part of gtk_widget_hide().
6235 gdk_window_hide (GdkWindow *window)
6237 GdkWindowObject *private;
6238 gboolean was_mapped, did_hide;
6240 g_return_if_fail (GDK_IS_WINDOW (window));
6242 private = (GdkWindowObject *) window;
6243 if (private->destroyed)
6246 was_mapped = GDK_WINDOW_IS_MAPPED (private);
6248 if (gdk_window_has_impl (private))
6251 if (GDK_WINDOW_IS_MAPPED (window))
6252 gdk_synthesize_window_state (window,
6254 GDK_WINDOW_STATE_WITHDRAWN);
6256 else if (was_mapped)
6258 GdkDisplay *display;
6260 /* May need to break grabs on children */
6261 display = gdk_drawable_get_display (window);
6263 if (_gdk_display_end_pointer_grab (display,
6264 _gdk_windowing_window_get_next_serial (display),
6267 gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
6269 if (display->keyboard_grab.window != NULL)
6271 if (is_parent_of (window, display->keyboard_grab.window))
6273 /* Call this ourselves, even though gdk_display_keyboard_ungrab
6274 does so too, since we want to pass implicit == TRUE so the
6275 broken grab event is generated */
6276 _gdk_display_unset_has_keyboard_grab (display,
6278 gdk_display_keyboard_ungrab (display, GDK_CURRENT_TIME);
6282 private->state = GDK_WINDOW_STATE_WITHDRAWN;
6285 did_hide = _gdk_window_update_viewable (window);
6287 /* Hide foreign window as those are not handled by update_viewable. */
6288 if (gdk_window_has_impl (private) && (!did_hide))
6289 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->hide ((GdkWindow *)private);
6291 recompute_visible_regions (private, TRUE, FALSE);
6293 /* all decendants became non-visible, we need to send visibility notify */
6294 gdk_window_update_visibility_recursively (private, NULL);
6296 if (was_mapped && !gdk_window_has_impl (private))
6298 if (private->event_mask & GDK_STRUCTURE_MASK)
6299 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6301 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
6302 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6304 _gdk_synthesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
6307 /* Invalidate the rect */
6308 gdk_window_invalidate_in_parent (private);
6312 * gdk_window_withdraw:
6313 * @window: a toplevel #GdkWindow
6315 * Withdraws a window (unmaps it and asks the window manager to forget about it).
6316 * This function is not really useful as gdk_window_hide() automatically
6317 * withdraws toplevel windows before hiding them.
6320 gdk_window_withdraw (GdkWindow *window)
6322 GdkWindowObject *private;
6323 gboolean was_mapped;
6325 g_return_if_fail (GDK_IS_WINDOW (window));
6327 private = (GdkWindowObject *) window;
6328 if (private->destroyed)
6331 was_mapped = GDK_WINDOW_IS_MAPPED (private);
6333 if (gdk_window_has_impl (private))
6335 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->withdraw (window);
6339 if (private->event_mask & GDK_STRUCTURE_MASK)
6340 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6342 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
6343 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6345 _gdk_synthesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
6348 recompute_visible_regions (private, TRUE, FALSE);
6353 * gdk_window_set_events:
6354 * @window: a #GdkWindow
6355 * @event_mask: event mask for @window
6357 * The event mask for a window determines which events will be reported
6358 * for that window. For example, an event mask including #GDK_BUTTON_PRESS_MASK
6359 * means the window should report button press events. The event mask
6360 * is the bitwise OR of values from the #GdkEventMask enumeration.
6363 gdk_window_set_events (GdkWindow *window,
6364 GdkEventMask event_mask)
6366 GdkWindowObject *private;
6367 GdkDisplay *display;
6370 g_return_if_fail (GDK_IS_WINDOW (window));
6372 private = (GdkWindowObject *) window;
6373 if (private->destroyed)
6376 /* If motion hint is disabled, enable motion events again */
6377 display = gdk_drawable_get_display (window);
6378 if ((private->event_mask & GDK_POINTER_MOTION_HINT_MASK) &&
6379 !(event_mask & GDK_POINTER_MOTION_HINT_MASK))
6380 _gdk_display_enable_motion_hints (display);
6382 private->event_mask = event_mask;
6384 if (gdk_window_has_impl (private))
6385 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_events (window,
6386 get_native_event_mask (private));
6391 * gdk_window_get_events:
6392 * @window: a #GdkWindow
6394 * Gets the event mask for @window. See gdk_window_set_events().
6396 * Return value: event mask for @window
6399 gdk_window_get_events (GdkWindow *window)
6401 GdkWindowObject *private;
6403 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
6405 private = (GdkWindowObject *) window;
6406 if (private->destroyed)
6409 return private->event_mask;
6413 gdk_window_move_resize_toplevel (GdkWindow *window,
6420 GdkWindowObject *private;
6421 GdkRegion *old_region, *new_region;
6422 GdkWindowObject *impl_window;
6424 int old_x, old_y, old_abs_x, old_abs_y;
6428 private = (GdkWindowObject *) window;
6433 impl_window = gdk_window_get_impl_window (private);
6438 is_resize = (width != -1) || (height != -1);
6440 if (gdk_window_is_viewable (window) &&
6441 !private->input_only)
6444 old_region = gdk_region_copy (private->clip_region);
6447 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, with_move, x, y, width, height);
6449 dx = private->x - old_x;
6450 dy = private->y - old_y;
6452 old_abs_x = private->abs_x;
6453 old_abs_y = private->abs_y;
6455 /* Avoid recomputing for pure toplevel moves, for performance reasons */
6457 recompute_visible_regions (private, TRUE, FALSE);
6461 new_region = gdk_region_copy (private->clip_region);
6463 /* This is the newly exposed area (due to any resize),
6464 * X will expose it, but lets do that without the
6467 gdk_region_subtract (new_region, old_region);
6468 gdk_window_invalidate_region (window, new_region, TRUE);
6470 gdk_region_destroy (old_region);
6471 gdk_region_destroy (new_region);
6474 _gdk_synthesize_crossing_events_for_geometry_change (window);
6479 move_native_children (GdkWindowObject *private)
6482 GdkWindowObject *child;
6484 for (l = private->children; l; l = l->next)
6488 if (child->impl != private->impl)
6489 GDK_WINDOW_IMPL_GET_IFACE (child->impl)->move_resize ((GdkWindow *)child, TRUE, child->x, child->y, child->width, child->height);
6491 move_native_children (child);
6496 collect_native_child_region_helper (GdkWindowObject *window,
6502 GdkWindowObject *child;
6506 for (l = window->children; l != NULL; l = l->next)
6510 if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only)
6513 if (child->impl != impl)
6515 tmp = gdk_region_copy (child->clip_region);
6516 gdk_region_offset (tmp,
6517 x_offset + child->x,
6518 y_offset + child->y);
6519 if (*region == NULL)
6523 gdk_region_union (*region, tmp);
6524 gdk_region_destroy (tmp);
6528 collect_native_child_region_helper (child, impl, region,
6529 x_offset + child->x,
6530 y_offset + child->y);
6537 collect_native_child_region (GdkWindowObject *window,
6538 gboolean include_this)
6542 if (include_this && gdk_window_has_impl (window) && window->viewable)
6543 return gdk_region_copy (window->clip_region);
6547 collect_native_child_region_helper (window, window->impl, ®ion, 0, 0);
6554 gdk_window_move_resize_internal (GdkWindow *window,
6561 GdkWindowObject *private;
6562 GdkRegion *old_region, *new_region, *copy_area;
6563 GdkRegion *old_native_child_region, *new_native_child_region;
6564 GdkWindowObject *impl_window;
6566 int old_x, old_y, old_abs_x, old_abs_y;
6569 g_return_if_fail (GDK_IS_WINDOW (window));
6571 private = (GdkWindowObject *) window;
6572 if (private->destroyed)
6575 if (private->parent == NULL ||
6576 private->parent->window_type == GDK_WINDOW_ROOT)
6578 gdk_window_move_resize_toplevel (window, with_move, x, y, width, height);
6582 /* Handle child windows */
6587 impl_window = gdk_window_get_impl_window (private);
6592 old_native_child_region = NULL;
6593 if (gdk_window_is_viewable (window) &&
6594 !private->input_only)
6598 old_region = gdk_region_copy (private->clip_region);
6599 /* Adjust region to parent window coords */
6600 gdk_region_offset (old_region, private->x, private->y);
6602 old_native_child_region = collect_native_child_region (private, TRUE);
6603 if (old_native_child_region)
6605 /* Adjust region to parent window coords */
6606 gdk_region_offset (old_native_child_region, private->x, private->y);
6608 /* Any native window move will immediately copy stuff to the destination, which may overwrite a
6609 * source or destination for a delayed GdkWindowRegionMove. So, we need
6610 * to flush those here for the parent window and all overlapped subwindows
6611 * of it. And we need to do this before setting the new clips as those will be
6614 gdk_window_flush_recursive (private->parent);
6618 /* Set the new position and size */
6624 if (!(width < 0 && height < 0))
6628 private->width = width;
6631 private->height = height;
6634 dx = private->x - old_x;
6635 dy = private->y - old_y;
6637 old_abs_x = private->abs_x;
6638 old_abs_y = private->abs_y;
6640 recompute_visible_regions (private, TRUE, FALSE);
6642 new_native_child_region = NULL;
6643 if (old_native_child_region)
6645 new_native_child_region = collect_native_child_region (private, TRUE);
6646 /* Adjust region to parent window coords */
6647 gdk_region_offset (new_native_child_region, private->x, private->y);
6650 if (gdk_window_has_impl (private))
6652 /* Do the actual move after recomputing things, as this will have set the shape to
6653 the now correct one, thus avoiding copying regions that should not be copied. */
6654 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, TRUE, private->x, private->y, private->width, private->height);
6656 else if (old_abs_x != private->abs_x ||
6657 old_abs_y != private->abs_y)
6658 move_native_children (private);
6662 new_region = gdk_region_copy (private->clip_region);
6663 /* Adjust region to parent window coords */
6664 gdk_region_offset (new_region, private->x, private->y);
6667 * Part of the data at the new location can be copied from the
6668 * old location, this area is the intersection of the old region
6669 * moved as the copy will move it and then intersected with
6673 * Everything in the old and new regions that is not copied must be
6674 * invalidated (including children) as this is newly exposed
6676 copy_area = gdk_region_copy (new_region);
6678 gdk_region_union (new_region, old_region);
6680 if (old_native_child_region)
6682 /* Don't copy from inside native children, as this is copied by
6683 * the native window move.
6685 gdk_region_subtract (old_region, old_native_child_region);
6687 gdk_region_offset (old_region, dx, dy);
6689 gdk_region_intersect (copy_area, old_region);
6691 if (new_native_child_region)
6693 /* Don't copy any bits that would cause a read from the moved
6694 native windows, as we can't read that data */
6695 gdk_region_offset (new_native_child_region, dx, dy);
6696 gdk_region_subtract (copy_area, new_native_child_region);
6699 gdk_region_subtract (new_region, copy_area);
6701 /* Convert old region to impl coords */
6702 gdk_region_offset (old_region, -dx + private->abs_x - private->x, -dy + private->abs_y - private->y);
6704 /* convert from parent coords to impl */
6705 gdk_region_offset (copy_area, private->abs_x - private->x, private->abs_y - private->y);
6707 move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
6709 /* Invalidate affected part in the parent window
6710 * (no higher window should be affected)
6711 * We also invalidate any children in that area, which could include
6712 * this window if it still overlaps that area.
6714 gdk_window_invalidate_region (GDK_WINDOW (private->parent), new_region, TRUE);
6716 gdk_region_destroy (old_region);
6717 gdk_region_destroy (new_region);
6720 if (old_native_child_region)
6722 gdk_region_destroy (old_native_child_region);
6723 gdk_region_destroy (new_native_child_region);
6726 _gdk_synthesize_crossing_events_for_geometry_change (window);
6733 * @window: a #GdkWindow
6734 * @x: X coordinate relative to window's parent
6735 * @y: Y coordinate relative to window's parent
6737 * Repositions a window relative to its parent window.
6738 * For toplevel windows, window managers may ignore or modify the move;
6739 * you should probably use gtk_window_move() on a #GtkWindow widget
6740 * anyway, instead of using GDK functions. For child windows,
6741 * the move will reliably succeed.
6743 * If you're also planning to resize the window, use gdk_window_move_resize()
6744 * to both move and resize simultaneously, for a nicer visual effect.
6747 gdk_window_move (GdkWindow *window,
6751 gdk_window_move_resize_internal (window, TRUE, x, y, -1, -1);
6755 * gdk_window_resize:
6756 * @window: a #GdkWindow
6757 * @width: new width of the window
6758 * @height: new height of the window
6760 * Resizes @window; for toplevel windows, asks the window manager to resize
6761 * the window. The window manager may not allow the resize. When using GTK+,
6762 * use gtk_window_resize() instead of this low-level GDK function.
6764 * Windows may not be resized below 1x1.
6766 * If you're also planning to move the window, use gdk_window_move_resize()
6767 * to both move and resize simultaneously, for a nicer visual effect.
6770 gdk_window_resize (GdkWindow *window,
6774 gdk_window_move_resize_internal (window, FALSE, 0, 0, width, height);
6779 * gdk_window_move_resize:
6780 * @window: a #GdkWindow
6781 * @x: new X position relative to window's parent
6782 * @y: new Y position relative to window's parent
6784 * @height: new height
6786 * Equivalent to calling gdk_window_move() and gdk_window_resize(),
6787 * except that both operations are performed at once, avoiding strange
6788 * visual effects. (i.e. the user may be able to see the window first
6789 * move, then resize, if you don't use gdk_window_move_resize().)
6792 gdk_window_move_resize (GdkWindow *window,
6798 gdk_window_move_resize_internal (window, TRUE, x, y, width, height);
6803 * gdk_window_scroll:
6804 * @window: a #GdkWindow
6805 * @dx: Amount to scroll in the X direction
6806 * @dy: Amount to scroll in the Y direction
6808 * Scroll the contents of @window, both pixels and children, by the
6809 * given amount. @window itself does not move. Portions of the window
6810 * that the scroll operation brings in from offscreen areas are
6811 * invalidated. The invalidated region may be bigger than what would
6812 * strictly be necessary.
6814 * For X11, a minimum area will be invalidated if the window has no
6815 * subwindows, or if the edges of the window's parent do not extend
6816 * beyond the edges of the window. In other cases, a multi-step process
6817 * is used to scroll the window which may produce temporary visual
6818 * artifacts and unnecessary invalidations.
6821 gdk_window_scroll (GdkWindow *window,
6825 GdkWindowObject *private = (GdkWindowObject *) window;
6826 GdkWindowObject *impl_window;
6827 GdkRegion *copy_area, *noncopy_area;
6828 GdkRegion *old_native_child_region, *new_native_child_region;
6831 g_return_if_fail (GDK_IS_WINDOW (window));
6833 if (dx == 0 && dy == 0)
6836 if (private->destroyed)
6839 old_native_child_region = collect_native_child_region (private, FALSE);
6840 if (old_native_child_region)
6842 /* Any native window move will immediately copy stuff to the destination, which may overwrite a
6843 * source or destination for a delayed GdkWindowRegionMove. So, we need
6844 * to flush those here for the window and all overlapped subwindows
6845 * of it. And we need to do this before setting the new clips as those will be
6848 gdk_window_flush_recursive (private);
6852 /* First move all child windows, without causing invalidation */
6854 tmp_list = private->children;
6857 GdkWindow *child = GDK_WINDOW (tmp_list->data);
6858 GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
6860 /* Just update the positions, the bits will move with the copy */
6864 tmp_list = tmp_list->next;
6867 recompute_visible_regions (private, FALSE, TRUE);
6869 new_native_child_region = NULL;
6870 if (old_native_child_region)
6871 new_native_child_region = collect_native_child_region (private, FALSE);
6873 move_native_children (private);
6875 /* Then copy the actual bits of the window w/ child windows */
6877 impl_window = gdk_window_get_impl_window (private);
6879 /* Calculate the area that can be gotten by copying the old area */
6880 copy_area = gdk_region_copy (private->clip_region);
6881 if (old_native_child_region)
6883 /* Don't copy from inside native children, as this is copied by
6884 * the native window move.
6886 gdk_region_subtract (copy_area, old_native_child_region);
6888 /* Don't copy any bits that would cause a read from the moved
6889 native windows, as we can't read that data */
6890 gdk_region_subtract (copy_area, new_native_child_region);
6892 gdk_region_offset (copy_area, dx, dy);
6893 gdk_region_intersect (copy_area, private->clip_region);
6895 /* And the rest need to be invalidated */
6896 noncopy_area = gdk_region_copy (private->clip_region);
6897 gdk_region_subtract (noncopy_area, copy_area);
6899 /* convert from window coords to impl */
6900 gdk_region_offset (copy_area, private->abs_x, private->abs_y);
6902 move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
6904 /* Invalidate not copied regions */
6905 gdk_window_invalidate_region (window, noncopy_area, TRUE);
6907 gdk_region_destroy (noncopy_area);
6909 if (old_native_child_region)
6911 gdk_region_destroy (old_native_child_region);
6912 gdk_region_destroy (new_native_child_region);
6915 _gdk_synthesize_crossing_events_for_geometry_change (window);
6919 * gdk_window_move_region:
6920 * @window: a #GdkWindow
6921 * @region: The #GdkRegion to move
6922 * @dx: Amount to move in the X direction
6923 * @dy: Amount to move in the Y direction
6925 * Move the part of @window indicated by @region by @dy pixels in the Y
6926 * direction and @dx pixels in the X direction. The portions of @region
6927 * that not covered by the new position of @region are invalidated.
6929 * Child windows are not moved.
6934 gdk_window_move_region (GdkWindow *window,
6935 const GdkRegion *region,
6939 GdkWindowObject *private = (GdkWindowObject *) window;
6940 GdkWindowObject *impl_window;
6941 GdkRegion *nocopy_area;
6942 GdkRegion *copy_area;
6944 g_return_if_fail (GDK_IS_WINDOW (window));
6945 g_return_if_fail (region != NULL);
6947 if (dx == 0 && dy == 0)
6950 if (private->destroyed)
6953 impl_window = gdk_window_get_impl_window (private);
6955 /* compute source regions */
6956 copy_area = gdk_region_copy (region);
6957 gdk_region_intersect (copy_area, private->clip_region_with_children);
6959 /* compute destination regions */
6960 gdk_region_offset (copy_area, dx, dy);
6961 gdk_region_intersect (copy_area, private->clip_region_with_children);
6963 /* Invalidate parts of the region (source and dest) not covered
6965 nocopy_area = gdk_region_copy (region);
6966 gdk_region_offset (nocopy_area, dx, dy);
6967 gdk_region_union (nocopy_area, region);
6968 gdk_region_subtract (nocopy_area, copy_area);
6970 /* convert from window coords to impl */
6971 gdk_region_offset (copy_area, private->abs_x, private->abs_y);
6972 move_region_on_impl (impl_window, copy_area, dx, dy); /* Takes ownership of copy_area */
6974 gdk_window_invalidate_region (window, nocopy_area, FALSE);
6975 gdk_region_destroy (nocopy_area);
6979 * gdk_window_set_background:
6980 * @window: a #GdkWindow
6981 * @color: an allocated #GdkColor
6983 * Sets the background color of @window. (However, when using GTK+,
6984 * set the background of a widget with gtk_widget_modify_bg() - if
6985 * you're an application - or gtk_style_set_background() - if you're
6986 * implementing a custom widget.)
6988 * The @color must be allocated; gdk_rgb_find_color() is the best way
6989 * to allocate a color.
6991 * See also gdk_window_set_back_pixmap().
6994 gdk_window_set_background (GdkWindow *window,
6995 const GdkColor *color)
6997 GdkWindowObject *private;
6998 GdkColormap *colormap = gdk_drawable_get_colormap (window);
7000 g_return_if_fail (GDK_IS_WINDOW (window));
7002 private = (GdkWindowObject *) window;
7004 private->bg_color = *color;
7005 gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
7007 if (private->bg_pixmap &&
7008 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
7009 private->bg_pixmap != GDK_NO_BG)
7010 g_object_unref (private->bg_pixmap);
7012 private->bg_pixmap = NULL;
7014 if (!GDK_WINDOW_DESTROYED (window) &&
7015 gdk_window_has_impl (private) &&
7016 !private->input_only)
7017 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, &private->bg_color);
7021 * gdk_window_set_back_pixmap:
7022 * @window: a #GdkWindow
7023 * @pixmap: a #GdkPixmap, or %NULL
7024 * @parent_relative: whether the tiling origin is at the origin of
7027 * Sets the background pixmap of @window. May also be used to set a
7028 * background of "None" on @window, by setting a background pixmap
7031 * A background pixmap will be tiled, positioning the first tile at
7032 * the origin of @window, or if @parent_relative is %TRUE, the tiling
7033 * will be done based on the origin of the parent window (useful to
7034 * align tiles in a parent with tiles in a child).
7036 * A background pixmap of %NULL means that the window will have no
7037 * background. A window with no background will never have its
7038 * background filled by the windowing system, instead the window will
7039 * contain whatever pixels were already in the corresponding area of
7042 * The windowing system will normally fill a window with its background
7043 * when the window is obscured then exposed, and when you call
7044 * gdk_window_clear().
7047 gdk_window_set_back_pixmap (GdkWindow *window,
7049 gboolean parent_relative)
7051 GdkWindowObject *private;
7053 g_return_if_fail (GDK_IS_WINDOW (window));
7054 g_return_if_fail (pixmap == NULL || !parent_relative);
7055 g_return_if_fail (pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap));
7057 private = (GdkWindowObject *) window;
7059 if (pixmap && !gdk_drawable_get_colormap (pixmap))
7061 g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
7065 if (private->bg_pixmap &&
7066 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
7067 private->bg_pixmap != GDK_NO_BG)
7068 g_object_unref (private->bg_pixmap);
7070 if (parent_relative)
7071 private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
7073 private->bg_pixmap = g_object_ref (pixmap);
7075 private->bg_pixmap = GDK_NO_BG;
7077 if (!GDK_WINDOW_DESTROYED (window) &&
7078 gdk_window_has_impl (private) &&
7079 !private->input_only)
7080 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, private->bg_pixmap);
7084 * gdk_window_get_cursor:
7085 * @window: a #GdkWindow
7088 * Retrieves a #GdkCursor pointer for the cursor currently set on the
7089 * specified #GdkWindow, or %NULL. If the return value is %NULL then
7090 * there is no custom cursor set on the specified window, and it is
7091 * using the cursor for its parent window.
7093 * Return value: a #GdkCursor, or %NULL. The returned object is owned
7094 * by the #GdkWindow and should not be unreferenced directly. Use
7095 * gdk_window_set_cursor() to unset the cursor of the window
7100 gdk_window_get_cursor (GdkWindow *window)
7102 GdkWindowObject *private;
7104 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
7106 private = (GdkWindowObject *) window;
7108 return private->cursor;
7112 * gdk_window_set_cursor:
7113 * @window: a #GdkWindow
7116 * Sets the mouse pointer for a #GdkWindow. Use gdk_cursor_new_for_display()
7117 * or gdk_cursor_new_from_pixmap() to create the cursor. To make the cursor
7118 * invisible, use %GDK_BLANK_CURSOR. Passing %NULL for the @cursor argument
7119 * to gdk_window_set_cursor() means that @window will use the cursor of its
7120 * parent window. Most windows should use this default.
7123 gdk_window_set_cursor (GdkWindow *window,
7126 GdkWindowObject *private;
7127 GdkDisplay *display;
7129 g_return_if_fail (GDK_IS_WINDOW (window));
7131 private = (GdkWindowObject *) window;
7132 display = gdk_drawable_get_display (window);
7134 if (private->cursor)
7136 gdk_cursor_unref (private->cursor);
7137 private->cursor = NULL;
7140 if (!GDK_WINDOW_DESTROYED (window))
7143 private->cursor = gdk_cursor_ref (cursor);
7145 if (private->window_type == GDK_WINDOW_ROOT ||
7146 private->window_type == GDK_WINDOW_FOREIGN)
7147 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_cursor (window, cursor);
7148 else if (_gdk_window_event_parent_of (window, display->pointer_info.window_under_pointer))
7149 update_cursor (display);
7151 g_object_notify (G_OBJECT (window), "cursor");
7156 * gdk_window_get_geometry:
7157 * @window: a #GdkWindow
7158 * @x: return location for X coordinate of window (relative to its parent)
7159 * @y: return location for Y coordinate of window (relative to its parent)
7160 * @width: return location for width of window
7161 * @height: return location for height of window
7162 * @depth: return location for bit depth of window
7164 * Any of the return location arguments to this function may be %NULL,
7165 * if you aren't interested in getting the value of that field.
7167 * The X and Y coordinates returned are relative to the parent window
7168 * of @window, which for toplevels usually means relative to the
7169 * window decorations (titlebar, etc.) rather than relative to the
7170 * root window (screen-size background window).
7172 * On the X11 platform, the geometry is obtained from the X server,
7173 * so reflects the latest position of @window; this may be out-of-sync
7174 * with the position of @window delivered in the most-recently-processed
7175 * #GdkEventConfigure. gdk_window_get_position() in contrast gets the
7176 * position from the most recent configure event.
7179 * If @window is not a toplevel, it is <emphasis>much</emphasis> better
7180 * to call gdk_window_get_position() and gdk_drawable_get_size() instead,
7181 * because it avoids the roundtrip to the X server and because
7182 * gdk_drawable_get_size() supports the full 32-bit coordinate space,
7183 * whereas gdk_window_get_geometry() is restricted to the 16-bit
7184 * coordinates of X11.
7188 gdk_window_get_geometry (GdkWindow *window,
7195 GdkWindowObject *private;
7199 GDK_NOTE (MULTIHEAD,
7200 g_message ("gdk_window_get_geometry(): Window needs "
7201 "to be non-NULL to be multi head safe"));
7202 window = gdk_screen_get_root_window ((gdk_screen_get_default ()));
7205 g_return_if_fail (GDK_IS_WINDOW (window));
7207 private = (GdkWindowObject *) window;
7209 if (!GDK_WINDOW_DESTROYED (window))
7211 if (gdk_window_has_impl (private))
7212 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_geometry (window, x, y,
7222 *width = private->width;
7224 *height = private->height;
7226 *depth = private->depth;
7232 * gdk_window_get_origin:
7233 * @window: a #GdkWindow
7234 * @x: return location for X coordinate
7235 * @y: return location for Y coordinate
7237 * Obtains the position of a window in root window coordinates.
7238 * (Compare with gdk_window_get_position() and
7239 * gdk_window_get_geometry() which return the position of a window
7240 * relative to its parent window.)
7242 * Return value: not meaningful, ignore
7245 gdk_window_get_origin (GdkWindow *window,
7249 GdkWindowObject *private;
7251 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
7253 if (GDK_WINDOW_DESTROYED (window))
7262 private = (GdkWindowObject *) window;
7264 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_root_coords (window,
7273 * gdk_window_get_root_coords:
7274 * @window: a #GdkWindow
7275 * @x: X coordinate in window
7276 * @y: Y coordinate in window
7277 * @root_x: return location for X coordinate
7278 * @root_y: return location for Y coordinate
7280 * Obtains the position of a window position in root
7281 * window coordinates. This is similar to
7282 * gdk_window_get_origin() but allows you go pass
7283 * in any position in the window, not just the origin.
7286 gdk_window_get_root_coords (GdkWindow *window,
7292 GdkWindowObject *private;
7294 g_return_if_fail (GDK_IS_WINDOW (window));
7296 private = (GdkWindowObject *) window;
7298 if (GDK_WINDOW_DESTROYED (window))
7307 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_root_coords (window,
7315 * gdk_window_get_deskrelative_origin:
7316 * @window: a toplevel #GdkWindow
7317 * @x: return location for X coordinate
7318 * @y: return location for Y coordinate
7320 * This gets the origin of a #GdkWindow relative to
7321 * an Enlightenment-window-manager desktop. As long as you don't
7322 * assume that the user's desktop/workspace covers the entire
7323 * root window (i.e. you don't assume that the desktop begins
7324 * at root window coordinate 0,0) this function is not necessary.
7325 * It's deprecated for that reason.
7327 * Return value: not meaningful
7330 gdk_window_get_deskrelative_origin (GdkWindow *window,
7334 GdkWindowObject *private;
7335 gboolean return_val = FALSE;
7339 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
7341 private = (GdkWindowObject *) window;
7343 if (!GDK_WINDOW_DESTROYED (window))
7345 return_val = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_deskrelative_origin (window, &tx, &ty);
7348 *x = tx + private->abs_x;
7350 *y = ty + private->abs_y;
7357 * gdk_window_shape_combine_mask:
7358 * @window: a #GdkWindow
7360 * @x: X position of shape mask with respect to @window
7361 * @y: Y position of shape mask with respect to @window
7363 * Applies a shape mask to @window. Pixels in @window corresponding to
7364 * set bits in the @mask will be visible; pixels in @window
7365 * corresponding to unset bits in the @mask will be transparent. This
7366 * gives a non-rectangular window.
7368 * If @mask is %NULL, the shape mask will be unset, and the @x/@y
7369 * parameters are not used.
7371 * On the X11 platform, this uses an X server extension which is
7372 * widely available on most common platforms, but not available on
7373 * very old X servers, and occasionally the implementation will be
7374 * buggy. On servers without the shape extension, this function
7377 * This function works on both toplevel and child windows.
7380 gdk_window_shape_combine_mask (GdkWindow *window,
7385 GdkWindowObject *private;
7388 g_return_if_fail (GDK_IS_WINDOW (window));
7390 private = (GdkWindowObject *) window;
7393 region = _gdk_windowing_get_shape_for_mask (mask);
7397 gdk_window_shape_combine_region (window,
7402 gdk_region_destroy (region);
7406 * gdk_window_shape_combine_region:
7407 * @window: a #GdkWindow
7408 * @shape_region: region of window to be non-transparent
7409 * @offset_x: X position of @shape_region in @window coordinates
7410 * @offset_y: Y position of @shape_region in @window coordinates
7412 * Makes pixels in @window outside @shape_region be transparent,
7413 * so that the window may be nonrectangular. See also
7414 * gdk_window_shape_combine_mask() to use a bitmap as the mask.
7416 * If @shape_region is %NULL, the shape will be unset, so the whole
7417 * window will be opaque again. @offset_x and @offset_y are ignored
7418 * if @shape_region is %NULL.
7420 * On the X11 platform, this uses an X server extension which is
7421 * widely available on most common platforms, but not available on
7422 * very old X servers, and occasionally the implementation will be
7423 * buggy. On servers without the shape extension, this function
7426 * This function works on both toplevel and child windows.
7429 gdk_window_shape_combine_region (GdkWindow *window,
7430 const GdkRegion *shape_region,
7434 GdkWindowObject *private;
7435 GdkRegion *old_region, *new_region, *diff;
7437 g_return_if_fail (GDK_IS_WINDOW (window));
7439 private = (GdkWindowObject *) window;
7441 if (GDK_WINDOW_DESTROYED (window))
7444 private->shaped = (shape_region != NULL);
7447 gdk_region_destroy (private->shape);
7450 if (GDK_WINDOW_IS_MAPPED (window))
7451 old_region = gdk_region_copy (private->clip_region);
7455 private->shape = gdk_region_copy (shape_region);
7456 gdk_region_offset (private->shape, offset_x, offset_y);
7459 private->shape = NULL;
7461 recompute_visible_regions (private, TRUE, FALSE);
7465 new_region = gdk_region_copy (private->clip_region);
7467 /* New area in the window, needs invalidation */
7468 diff = gdk_region_copy (new_region);
7469 gdk_region_subtract (diff, old_region);
7471 gdk_window_invalidate_region (window, diff, TRUE);
7473 gdk_region_destroy (diff);
7475 if (private->parent != NULL &&
7476 private->parent->window_type != GDK_WINDOW_ROOT)
7478 /* New area in the non-root parent window, needs invalidation */
7479 diff = gdk_region_copy (old_region);
7480 gdk_region_subtract (diff, new_region);
7482 /* Adjust region to parent window coords */
7483 gdk_region_offset (diff, private->x, private->y);
7485 gdk_window_invalidate_region (GDK_WINDOW (private->parent), diff, TRUE);
7487 gdk_region_destroy (diff);
7490 gdk_region_destroy (new_region);
7491 gdk_region_destroy (old_region);
7496 do_child_shapes (GdkWindow *window,
7499 GdkWindowObject *private;
7503 private = (GdkWindowObject *) window;
7507 r.width = private->width;
7508 r.height = private->height;
7510 region = gdk_region_rectangle (&r);
7511 remove_child_area (private, NULL, FALSE, region);
7513 if (merge && private->shape)
7514 gdk_region_subtract (region, private->shape);
7516 gdk_window_shape_combine_region (window, region, 0, 0);
7520 * gdk_window_set_child_shapes:
7521 * @window: a #GdkWindow
7523 * Sets the shape mask of @window to the union of shape masks
7524 * for all children of @window, ignoring the shape mask of @window
7525 * itself. Contrast with gdk_window_merge_child_shapes() which includes
7526 * the shape mask of @window in the masks to be merged.
7529 gdk_window_set_child_shapes (GdkWindow *window)
7531 g_return_if_fail (GDK_IS_WINDOW (window));
7533 do_child_shapes (window, FALSE);
7537 * gdk_window_merge_child_shapes:
7538 * @window: a #GdkWindow
7540 * Merges the shape masks for any child windows into the
7541 * shape mask for @window. i.e. the union of all masks
7542 * for @window and its children will become the new mask
7543 * for @window. See gdk_window_shape_combine_mask().
7545 * This function is distinct from gdk_window_set_child_shapes()
7546 * because it includes @window's shape mask in the set of shapes to
7550 gdk_window_merge_child_shapes (GdkWindow *window)
7552 g_return_if_fail (GDK_IS_WINDOW (window));
7554 do_child_shapes (window, TRUE);
7558 * gdk_window_input_shape_combine_mask:
7559 * @window: a #GdkWindow
7560 * @mask: shape mask, or %NULL
7561 * @x: X position of shape mask with respect to @window
7562 * @y: Y position of shape mask with respect to @window
7564 * Like gdk_window_shape_combine_mask(), but the shape applies
7565 * only to event handling. Mouse events which happen while
7566 * the pointer position corresponds to an unset bit in the
7567 * mask will be passed on the window below @window.
7569 * An input shape is typically used with RGBA windows.
7570 * The alpha channel of the window defines which pixels are
7571 * invisible and allows for nicely antialiased borders,
7572 * and the input shape controls where the window is
7575 * On the X11 platform, this requires version 1.1 of the
7578 * On the Win32 platform, this functionality is not present and the
7579 * function does nothing.
7584 gdk_window_input_shape_combine_mask (GdkWindow *window,
7589 GdkWindowObject *private;
7592 g_return_if_fail (GDK_IS_WINDOW (window));
7594 private = (GdkWindowObject *) window;
7597 region = _gdk_windowing_get_shape_for_mask (mask);
7601 gdk_window_input_shape_combine_region (window,
7606 gdk_region_destroy (region);
7610 * gdk_window_input_shape_combine_region:
7611 * @window: a #GdkWindow
7612 * @shape_region: region of window to be non-transparent
7613 * @offset_x: X position of @shape_region in @window coordinates
7614 * @offset_y: Y position of @shape_region in @window coordinates
7616 * Like gdk_window_shape_combine_region(), but the shape applies
7617 * only to event handling. Mouse events which happen while
7618 * the pointer position corresponds to an unset bit in the
7619 * mask will be passed on the window below @window.
7621 * An input shape is typically used with RGBA windows.
7622 * The alpha channel of the window defines which pixels are
7623 * invisible and allows for nicely antialiased borders,
7624 * and the input shape controls where the window is
7627 * On the X11 platform, this requires version 1.1 of the
7630 * On the Win32 platform, this functionality is not present and the
7631 * function does nothing.
7636 gdk_window_input_shape_combine_region (GdkWindow *window,
7637 const GdkRegion *shape_region,
7641 GdkWindowObject *private;
7643 g_return_if_fail (GDK_IS_WINDOW (window));
7645 private = (GdkWindowObject *) window;
7647 if (GDK_WINDOW_DESTROYED (window))
7650 if (private->input_shape)
7651 gdk_region_destroy (private->input_shape);
7655 private->input_shape = gdk_region_copy (shape_region);
7656 gdk_region_offset (private->input_shape, offset_x, offset_y);
7659 private->input_shape = NULL;
7661 if (gdk_window_has_impl (private))
7662 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_shape_combine_region ((GdkWindow *)private, private->input_shape, 0, 0);
7664 /* Pointer may have e.g. moved outside window due to the input mask change */
7665 _gdk_synthesize_crossing_events_for_geometry_change (window);
7669 do_child_input_shapes (GdkWindow *window,
7672 GdkWindowObject *private;
7676 private = (GdkWindowObject *) window;
7680 r.width = private->width;
7681 r.height = private->height;
7683 region = gdk_region_rectangle (&r);
7684 remove_child_area (private, NULL, TRUE, region);
7686 if (merge && private->shape)
7687 gdk_region_subtract (region, private->shape);
7688 if (merge && private->input_shape)
7689 gdk_region_subtract (region, private->input_shape);
7691 gdk_window_input_shape_combine_region (window, region, 0, 0);
7696 * gdk_window_set_child_input_shapes:
7697 * @window: a #GdkWindow
7699 * Sets the input shape mask of @window to the union of input shape masks
7700 * for all children of @window, ignoring the input shape mask of @window
7701 * itself. Contrast with gdk_window_merge_child_input_shapes() which includes
7702 * the input shape mask of @window in the masks to be merged.
7707 gdk_window_set_child_input_shapes (GdkWindow *window)
7709 g_return_if_fail (GDK_IS_WINDOW (window));
7711 do_child_input_shapes (window, FALSE);
7715 * gdk_window_merge_child_input_shapes:
7716 * @window: a #GdkWindow
7718 * Merges the input shape masks for any child windows into the
7719 * input shape mask for @window. i.e. the union of all input masks
7720 * for @window and its children will become the new input mask
7721 * for @window. See gdk_window_input_shape_combine_mask().
7723 * This function is distinct from gdk_window_set_child_input_shapes()
7724 * because it includes @window's input shape mask in the set of
7725 * shapes to be merged.
7730 gdk_window_merge_child_input_shapes (GdkWindow *window)
7732 g_return_if_fail (GDK_IS_WINDOW (window));
7734 do_child_input_shapes (window, TRUE);
7739 * gdk_window_set_static_gravities:
7740 * @window: a #GdkWindow
7741 * @use_static: %TRUE to turn on static gravity
7743 * Set the bit gravity of the given window to static, and flag it so
7744 * all children get static subwindow gravity. This is used if you are
7745 * implementing scary features that involve deep knowledge of the
7746 * windowing system. Don't worry about it unless you have to.
7748 * Return value: %TRUE if the server supports static gravity
7751 gdk_window_set_static_gravities (GdkWindow *window,
7752 gboolean use_static)
7754 GdkWindowObject *private;
7756 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
7758 private = (GdkWindowObject *) window;
7760 if (gdk_window_has_impl (private))
7761 return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_static_gravities (window, use_static);
7767 * gdk_window_set_composited:
7768 * @window: a #GdkWindow
7769 * @composited: %TRUE to set the window as composited
7771 * Sets a #GdkWindow as composited, or unsets it. Composited
7772 * windows do not automatically have their contents drawn to
7773 * the screen. Drawing is redirected to an offscreen buffer
7774 * and an expose event is emitted on the parent of the composited
7775 * window. It is the responsibility of the parent's expose handler
7776 * to manually merge the off-screen content onto the screen in
7777 * whatever way it sees fit. See <xref linkend="composited-window-example"/>
7780 * It only makes sense for child windows to be composited; see
7781 * gdk_window_set_opacity() if you need translucent toplevel
7784 * An additional effect of this call is that the area of this
7785 * window is no longer clipped from regions marked for
7786 * invalidation on its parent. Draws done on the parent
7787 * window are also no longer clipped by the child.
7789 * This call is only supported on some systems (currently,
7790 * only X11 with new enough Xcomposite and Xdamage extensions).
7791 * You must call gdk_display_supports_composite() to check if
7792 * setting a window as composited is supported before
7793 * attempting to do so.
7798 gdk_window_set_composited (GdkWindow *window,
7799 gboolean composited)
7801 GdkWindowObject *private = (GdkWindowObject *)window;
7802 GdkDisplay *display;
7804 g_return_if_fail (GDK_IS_WINDOW (window));
7806 composited = composited != FALSE;
7808 if (private->composited == composited)
7812 gdk_window_ensure_native (window);
7814 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
7816 if (!gdk_display_supports_composite (display) && composited)
7818 g_warning ("gdk_window_set_composited called but "
7819 "compositing is not supported");
7823 _gdk_windowing_window_set_composited (window, composited);
7825 recompute_visible_regions (private, TRUE, FALSE);
7827 if (GDK_WINDOW_IS_MAPPED (window))
7828 gdk_window_invalidate_in_parent (private);
7830 private->composited = composited;
7835 remove_redirect_from_children (GdkWindowObject *private,
7836 GdkWindowRedirect *redirect)
7839 GdkWindowObject *child;
7841 for (l = private->children; l != NULL; l = l->next)
7845 /* Don't redirect this child if it already has another redirect */
7846 if (child->redirect == redirect)
7848 child->redirect = NULL;
7849 remove_redirect_from_children (child, redirect);
7855 * gdk_window_remove_redirection:
7856 * @window: a #GdkWindow
7858 * Removes any active redirection started by
7859 * gdk_window_redirect_to_drawable().
7864 gdk_window_remove_redirection (GdkWindow *window)
7866 GdkWindowObject *private;
7868 g_return_if_fail (GDK_IS_WINDOW (window));
7870 private = (GdkWindowObject *) window;
7872 if (private->redirect &&
7873 private->redirect->redirected == private)
7875 remove_redirect_from_children (private, private->redirect);
7876 gdk_window_redirect_free (private->redirect);
7877 private->redirect = NULL;
7882 apply_redirect_to_children (GdkWindowObject *private,
7883 GdkWindowRedirect *redirect)
7886 GdkWindowObject *child;
7888 for (l = private->children; l != NULL; l = l->next)
7892 /* Don't redirect this child if it already has another redirect */
7893 if (!child->redirect)
7895 child->redirect = redirect;
7896 apply_redirect_to_children (child, redirect);
7902 * gdk_window_redirect_to_drawable:
7903 * @window: a #GdkWindow
7904 * @drawable: a #GdkDrawable
7905 * @src_x: x position in @window
7906 * @src_y: y position in @window
7907 * @dest_x: x position in @drawable
7908 * @dest_y: y position in @drawable
7909 * @width: width of redirection
7910 * @height: height of redirection
7912 * Redirects drawing into @window so that drawing to the
7913 * window in the rectangle specified by @src_x, @src_y,
7914 * @width and @height is also drawn into @drawable at
7917 * Only drawing between gdk_window_begin_paint_region() or
7918 * gdk_window_begin_paint_rect() and gdk_window_end_paint() is
7921 * Redirection is active until gdk_window_remove_redirection()
7927 gdk_window_redirect_to_drawable (GdkWindow *window,
7928 GdkDrawable *drawable,
7936 GdkWindowObject *private;
7938 g_return_if_fail (GDK_IS_WINDOW (window));
7939 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
7940 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
7942 private = (GdkWindowObject *) window;
7944 if (private->redirect)
7945 gdk_window_remove_redirection (window);
7947 if (width == -1 || height == -1)
7950 gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
7957 private->redirect = g_new0 (GdkWindowRedirect, 1);
7958 private->redirect->redirected = private;
7959 private->redirect->pixmap = g_object_ref (drawable);
7960 private->redirect->src_x = src_x;
7961 private->redirect->src_y = src_y;
7962 private->redirect->dest_x = dest_x;
7963 private->redirect->dest_y = dest_y;
7964 private->redirect->width = width;
7965 private->redirect->height = height;
7967 apply_redirect_to_children (private, private->redirect);
7971 window_get_size_rectangle (GdkWindow *window,
7974 GdkWindowObject *private = (GdkWindowObject *) window;
7976 rect->x = rect->y = 0;
7977 rect->width = private->width;
7978 rect->height = private->height;
7981 /* Calculates the real clipping region for a window, in window coordinates,
7982 * taking into account other windows, gc clip region and gc clip mask.
7985 _gdk_window_calculate_full_clip_region (GdkWindow *window,
7986 GdkWindow *base_window,
7987 gboolean do_children,
7988 gint *base_x_offset,
7989 gint *base_y_offset)
7991 GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
7992 GdkRectangle visible_rect;
7993 GdkRegion *real_clip_region, *tmpreg;
7994 gint x_offset, y_offset;
7995 GdkWindowObject *parentwin, *lastwin;
8002 if (!private->viewable || private->input_only)
8003 return gdk_region_new ();
8005 window_get_size_rectangle (window, &visible_rect);
8007 /* real_clip_region is in window coordinates */
8008 real_clip_region = gdk_region_rectangle (&visible_rect);
8010 x_offset = y_offset = 0;
8014 parentwin = lastwin;
8016 parentwin = lastwin->parent;
8018 /* Remove the areas of all overlapping windows above parentwin in the hiearachy */
8019 for (; parentwin != NULL &&
8020 (parentwin == private || lastwin != (GdkWindowObject*) base_window);
8021 lastwin = parentwin, parentwin = lastwin->parent)
8024 GdkRectangle real_clip_rect;
8025 gboolean is_offscreen;
8027 if (parentwin != private)
8029 x_offset += GDK_WINDOW_OBJECT (lastwin)->x;
8030 y_offset += GDK_WINDOW_OBJECT (lastwin)->y;
8033 is_offscreen = gdk_window_is_offscreen (parentwin);
8035 /* children is ordered in reverse stack order */
8036 for (cur = parentwin->children;
8037 cur && cur->data != lastwin;
8040 GdkWindow *child = cur->data;
8041 GdkWindowObject *child_private = (GdkWindowObject *)child;
8043 if (!GDK_WINDOW_IS_MAPPED (child) || child_private->input_only)
8046 /* Ignore offscreen children, as they don't draw in their parent and
8047 * don't take part in the clipping */
8048 if (gdk_window_is_offscreen (child_private))
8051 window_get_size_rectangle (child, &visible_rect);
8053 /* Convert rect to "window" coords */
8054 visible_rect.x += child_private->x - x_offset;
8055 visible_rect.y += child_private->y - y_offset;
8057 /* This shortcut is really necessary for performance when there are a lot of windows */
8058 gdk_region_get_clipbox (real_clip_region, &real_clip_rect);
8059 if (visible_rect.x >= real_clip_rect.x + real_clip_rect.width ||
8060 visible_rect.x + visible_rect.width <= real_clip_rect.x ||
8061 visible_rect.y >= real_clip_rect.y + real_clip_rect.height ||
8062 visible_rect.y + visible_rect.height <= real_clip_rect.y)
8065 tmpreg = gdk_region_rectangle (&visible_rect);
8066 gdk_region_subtract (real_clip_region, tmpreg);
8067 gdk_region_destroy (tmpreg);
8070 /* Clip to the parent */
8071 window_get_size_rectangle ((GdkWindow *)parentwin, &visible_rect);
8072 /* Convert rect to "window" coords */
8073 visible_rect.x += - x_offset;
8074 visible_rect.y += - y_offset;
8076 tmpreg = gdk_region_rectangle (&visible_rect);
8077 gdk_region_intersect (real_clip_region, tmpreg);
8078 gdk_region_destroy (tmpreg);
8082 *base_x_offset = x_offset;
8084 *base_y_offset = y_offset;
8086 return real_clip_region;
8090 _gdk_window_add_damage (GdkWindow *toplevel,
8091 GdkRegion *damaged_region)
8093 GdkDisplay *display;
8094 GdkEvent event = { 0, };
8095 event.expose.type = GDK_DAMAGE;
8096 event.expose.window = toplevel;
8097 event.expose.send_event = FALSE;
8098 event.expose.region = damaged_region;
8099 gdk_region_get_clipbox (event.expose.region, &event.expose.area);
8100 display = gdk_drawable_get_display (event.expose.window);
8101 _gdk_event_queue_append (display, gdk_event_copy (&event));
8105 gdk_window_redirect_free (GdkWindowRedirect *redirect)
8107 g_object_unref (redirect->pixmap);
8111 /* Gets the toplevel for a window as used for events,
8112 i.e. including offscreen parents */
8113 static GdkWindowObject *
8114 get_event_parent (GdkWindowObject *window)
8116 if (window->window_type == GDK_WINDOW_OFFSCREEN)
8117 return (GdkWindowObject *)gdk_offscreen_window_get_embedder ((GdkWindow *)window);
8119 return window->parent;
8122 /* Gets the toplevel for a window as used for events,
8123 i.e. including offscreen parents going up to the native
8126 get_event_toplevel (GdkWindow *w)
8128 GdkWindowObject *private = GDK_WINDOW_OBJECT (w);
8129 GdkWindowObject *parent;
8131 while ((parent = get_event_parent (private)) != NULL &&
8132 (parent->window_type != GDK_WINDOW_ROOT))
8135 return GDK_WINDOW (private);
8139 _gdk_window_event_parent_of (GdkWindow *parent,
8150 w = (GdkWindow *)get_event_parent ((GdkWindowObject *)w);
8157 update_cursor (GdkDisplay *display)
8159 GdkWindowObject *pointer_window, *cursor_window, *parent, *toplevel;
8160 GdkPointerGrabInfo *grab;
8162 pointer_window = (GdkWindowObject *)display->pointer_info.window_under_pointer;
8164 cursor_window = pointer_window;
8165 while (cursor_window->cursor == NULL &&
8166 (parent = get_event_parent (cursor_window)) != NULL &&
8167 parent->window_type != GDK_WINDOW_ROOT)
8168 cursor_window = parent;
8170 /* We ignore the serials here and just pick the last grab
8171 we've sent, as that would shortly be used anyway. */
8172 grab = _gdk_display_get_last_pointer_grab (display);
8174 !_gdk_window_event_parent_of (grab->window, (GdkWindow *)cursor_window))
8175 cursor_window = (GdkWindowObject *)grab->window;
8177 /* Set all cursors on toplevel, otherwise its tricky to keep track of
8178 * which native window has what cursor set. */
8179 toplevel = (GdkWindowObject *)get_event_toplevel ((GdkWindow *)pointer_window);
8180 GDK_WINDOW_IMPL_GET_IFACE (toplevel->impl)->set_cursor
8181 ((GdkWindow *)toplevel, cursor_window->cursor);
8185 from_embedder (GdkWindowObject *window,
8186 double embedder_x, double embedder_y,
8187 double *offscreen_x, double *offscreen_y)
8189 g_signal_emit (window,
8190 signals[FROM_EMBEDDER], 0,
8191 embedder_x, embedder_y,
8192 offscreen_x, offscreen_y,
8197 convert_coords_to_child (GdkWindowObject *child,
8199 double *child_x, double *child_y)
8201 if (gdk_window_is_offscreen (child))
8203 from_embedder (child, x, y,
8208 *child_x = x - child->x;
8209 *child_y = y - child->y;
8214 point_in_window (GdkWindowObject *window,
8218 x >= 0 && x < window->width &&
8219 y >= 0 && y < window->height &&
8220 (window->shape == NULL ||
8221 gdk_region_point_in (window->shape,
8223 (window->input_shape == NULL ||
8224 gdk_region_point_in (window->input_shape,
8229 convert_native_coords_to_toplevel (GdkWindow *window,
8230 double child_x, double child_y,
8231 double *toplevel_x, double *toplevel_y)
8233 GdkWindowObject *private = (GdkWindowObject *)window;
8239 while (private->parent != NULL &&
8240 (private->parent->window_type != GDK_WINDOW_ROOT))
8244 private = private->parent;
8250 return (GdkWindow *)private;
8254 convert_toplevel_coords_to_window (GdkWindow *window,
8260 GdkWindowObject *private;
8261 GdkWindowObject *parent;
8263 GList *children, *l;
8265 private = GDK_WINDOW_OBJECT (window);
8271 while ((parent = get_event_parent (private)) != NULL &&
8272 (parent->window_type != GDK_WINDOW_ROOT))
8274 children = g_list_prepend (children, private);
8278 for (l = children; l != NULL; l = l->next)
8279 convert_coords_to_child (l->data, x, y, &x, &y);
8281 g_list_free (children);
8287 static GdkWindowObject *
8288 pick_embedded_child (GdkWindowObject *window,
8291 GdkWindowObject *res;
8294 g_signal_emit (window,
8295 signals[PICK_EMBEDDED_CHILD], 0,
8302 _gdk_window_find_child_at (GdkWindow *window,
8305 GdkWindowObject *private, *sub;
8306 double child_x, child_y;
8309 private = (GdkWindowObject *)window;
8311 if (point_in_window (private, x, y))
8313 /* Children is ordered in reverse stack order, i.e. first is topmost */
8314 for (l = private->children; l != NULL; l = l->next)
8318 if (!GDK_WINDOW_IS_MAPPED (sub))
8321 convert_coords_to_child (sub,
8323 &child_x, &child_y);
8324 if (point_in_window (sub, child_x, child_y))
8325 return (GdkWindow *)sub;
8328 if (private->num_offscreen_children > 0)
8330 sub = pick_embedded_child (private,
8333 return (GdkWindow *)sub;
8341 _gdk_window_find_descendant_at (GdkWindow *toplevel,
8346 GdkWindowObject *private, *sub;
8347 double child_x, child_y;
8351 private = (GdkWindowObject *)toplevel;
8353 if (point_in_window (private, x, y))
8358 /* Children is ordered in reverse stack order, i.e. first is topmost */
8359 for (l = private->children; l != NULL; l = l->next)
8363 if (!GDK_WINDOW_IS_MAPPED (sub))
8366 convert_coords_to_child (sub,
8368 &child_x, &child_y);
8369 if (point_in_window (sub, child_x, child_y))
8379 private->num_offscreen_children > 0)
8381 sub = pick_embedded_child (private,
8387 from_embedder (sub, x, y, &x, &y);
8395 /* Not in window at all */
8404 return (GdkWindow *)private;
8409 * @window: a toplevel #GdkWindow
8411 * Emits a short beep associated to @window in the appropriate
8412 * display, if supported. Otherwise, emits a short beep on
8413 * the display just as gdk_display_beep().
8418 gdk_window_beep (GdkWindow *window)
8420 GdkDisplay *display;
8421 GdkWindow *toplevel;
8423 g_return_if_fail (GDK_IS_WINDOW (window));
8425 if (GDK_WINDOW_DESTROYED (window))
8428 toplevel = get_event_toplevel (window);
8429 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
8431 if (toplevel && gdk_window_is_offscreen ((GdkWindowObject *)toplevel))
8432 _gdk_windowing_window_beep (toplevel);
8434 gdk_display_beep (display);
8437 static const guint type_masks[] = {
8438 GDK_SUBSTRUCTURE_MASK, /* GDK_DELETE = 0 */
8439 GDK_STRUCTURE_MASK, /* GDK_DESTROY = 1 */
8440 GDK_EXPOSURE_MASK, /* GDK_EXPOSE = 2 */
8441 GDK_POINTER_MOTION_MASK, /* GDK_MOTION_NOTIFY = 3 */
8442 GDK_BUTTON_PRESS_MASK, /* GDK_BUTTON_PRESS = 4 */
8443 GDK_BUTTON_PRESS_MASK, /* GDK_2BUTTON_PRESS = 5 */
8444 GDK_BUTTON_PRESS_MASK, /* GDK_3BUTTON_PRESS = 6 */
8445 GDK_BUTTON_RELEASE_MASK, /* GDK_BUTTON_RELEASE = 7 */
8446 GDK_KEY_PRESS_MASK, /* GDK_KEY_PRESS = 8 */
8447 GDK_KEY_RELEASE_MASK, /* GDK_KEY_RELEASE = 9 */
8448 GDK_ENTER_NOTIFY_MASK, /* GDK_ENTER_NOTIFY = 10 */
8449 GDK_LEAVE_NOTIFY_MASK, /* GDK_LEAVE_NOTIFY = 11 */
8450 GDK_FOCUS_CHANGE_MASK, /* GDK_FOCUS_CHANGE = 12 */
8451 GDK_STRUCTURE_MASK, /* GDK_CONFIGURE = 13 */
8452 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_MAP = 14 */
8453 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_UNMAP = 15 */
8454 GDK_PROPERTY_CHANGE_MASK, /* GDK_PROPERTY_NOTIFY = 16 */
8455 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_CLEAR = 17 */
8456 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_REQUEST = 18 */
8457 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_NOTIFY = 19 */
8458 GDK_PROXIMITY_IN_MASK, /* GDK_PROXIMITY_IN = 20 */
8459 GDK_PROXIMITY_OUT_MASK, /* GDK_PROXIMITY_OUT = 21 */
8460 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_ENTER = 22 */
8461 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_LEAVE = 23 */
8462 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_MOTION = 24 */
8463 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_STATUS = 25 */
8464 GDK_ALL_EVENTS_MASK, /* GDK_DROP_START = 26 */
8465 GDK_ALL_EVENTS_MASK, /* GDK_DROP_FINISHED = 27 */
8466 GDK_ALL_EVENTS_MASK, /* GDK_CLIENT_EVENT = 28 */
8467 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_VISIBILITY_NOTIFY = 29 */
8468 GDK_EXPOSURE_MASK, /* GDK_NO_EXPOSE = 30 */
8469 GDK_SCROLL_MASK | GDK_BUTTON_PRESS_MASK,/* GDK_SCROLL= 31 */
8470 0, /* GDK_WINDOW_STATE = 32 */
8471 0, /* GDK_SETTING = 33 */
8472 0, /* GDK_OWNER_CHANGE = 34 */
8473 0, /* GDK_GRAB_BROKEN = 35 */
8474 0, /* GDK_DAMAGE = 36 */
8476 G_STATIC_ASSERT (G_N_ELEMENTS (type_masks) == GDK_EVENT_LAST);
8478 /* send motion events if the right buttons are down */
8480 update_evmask_for_button_motion (guint evmask,
8481 GdkModifierType mask)
8483 if (evmask & GDK_BUTTON_MOTION_MASK &&
8484 mask & (GDK_BUTTON1_MASK |
8489 evmask |= GDK_POINTER_MOTION_MASK;
8491 if ((evmask & GDK_BUTTON1_MOTION_MASK && mask & GDK_BUTTON1_MASK) ||
8492 (evmask & GDK_BUTTON2_MOTION_MASK && mask & GDK_BUTTON2_MASK) ||
8493 (evmask & GDK_BUTTON3_MOTION_MASK && mask & GDK_BUTTON3_MASK))
8494 evmask |= GDK_POINTER_MOTION_MASK;
8500 is_button_type (GdkEventType type)
8502 return type == GDK_BUTTON_PRESS ||
8503 type == GDK_2BUTTON_PRESS ||
8504 type == GDK_3BUTTON_PRESS ||
8505 type == GDK_BUTTON_RELEASE ||
8510 is_motion_type (GdkEventType type)
8512 return type == GDK_MOTION_NOTIFY ||
8513 type == GDK_ENTER_NOTIFY ||
8514 type == GDK_LEAVE_NOTIFY;
8517 static GdkWindowObject *
8518 find_common_ancestor (GdkWindowObject *win1,
8519 GdkWindowObject *win2)
8521 GdkWindowObject *tmp;
8522 GList *path1 = NULL, *path2 = NULL;
8523 GList *list1, *list2;
8526 while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
8528 path1 = g_list_prepend (path1, tmp);
8529 tmp = get_event_parent (tmp);
8533 while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
8535 path2 = g_list_prepend (path2, tmp);
8536 tmp = get_event_parent (tmp);
8542 while (list1 && list2 && (list1->data == list2->data))
8544 tmp = (GdkWindowObject *)list1->data;
8545 list1 = g_list_next (list1);
8546 list2 = g_list_next (list2);
8548 g_list_free (path1);
8549 g_list_free (path2);
8555 _gdk_make_event (GdkWindow *window,
8557 GdkEvent *event_in_queue,
8558 gboolean before_event)
8560 GdkEvent *event = gdk_event_new (type);
8562 GdkModifierType the_state;
8564 the_time = gdk_event_get_time (event_in_queue);
8565 gdk_event_get_state (event_in_queue, &the_state);
8567 event->any.window = g_object_ref (window);
8568 event->any.send_event = FALSE;
8572 case GDK_MOTION_NOTIFY:
8573 event->motion.time = the_time;
8574 event->motion.axes = NULL;
8575 event->motion.state = the_state;
8578 case GDK_BUTTON_PRESS:
8579 case GDK_2BUTTON_PRESS:
8580 case GDK_3BUTTON_PRESS:
8581 case GDK_BUTTON_RELEASE:
8582 event->button.time = the_time;
8583 event->button.axes = NULL;
8584 event->button.state = the_state;
8588 event->scroll.time = the_time;
8589 event->scroll.state = the_state;
8593 case GDK_KEY_RELEASE:
8594 event->key.time = the_time;
8595 event->key.state = the_state;
8598 case GDK_ENTER_NOTIFY:
8599 case GDK_LEAVE_NOTIFY:
8600 event->crossing.time = the_time;
8601 event->crossing.state = the_state;
8604 case GDK_PROPERTY_NOTIFY:
8605 event->property.time = the_time;
8606 event->property.state = the_state;
8609 case GDK_SELECTION_CLEAR:
8610 case GDK_SELECTION_REQUEST:
8611 case GDK_SELECTION_NOTIFY:
8612 event->selection.time = the_time;
8615 case GDK_PROXIMITY_IN:
8616 case GDK_PROXIMITY_OUT:
8617 event->proximity.time = the_time;
8620 case GDK_DRAG_ENTER:
8621 case GDK_DRAG_LEAVE:
8622 case GDK_DRAG_MOTION:
8623 case GDK_DRAG_STATUS:
8624 case GDK_DROP_START:
8625 case GDK_DROP_FINISHED:
8626 event->dnd.time = the_time;
8629 case GDK_FOCUS_CHANGE:
8633 case GDK_CLIENT_EVENT:
8634 case GDK_VISIBILITY_NOTIFY:
8646 _gdk_event_queue_insert_before (gdk_drawable_get_display (window), event_in_queue, event);
8648 _gdk_event_queue_insert_after (gdk_drawable_get_display (window), event_in_queue, event);
8651 _gdk_event_queue_append (gdk_drawable_get_display (window), event);
8657 send_crossing_event (GdkDisplay *display,
8658 GdkWindowObject *toplevel,
8659 GdkWindowObject *window,
8661 GdkCrossingMode mode,
8662 GdkNotifyType notify_type,
8663 GdkWindow *subwindow,
8666 GdkModifierType mask,
8668 GdkEvent *event_in_queue,
8673 GdkPointerGrabInfo *grab;
8675 grab = _gdk_display_has_pointer_grab (display, serial);
8678 !grab->owner_events &&
8679 (GdkWindow *)window != grab->window)
8682 if (type == GDK_LEAVE_NOTIFY)
8683 event_mask = GDK_LEAVE_NOTIFY_MASK;
8685 event_mask = GDK_ENTER_NOTIFY_MASK;
8687 if (window->extension_events != 0)
8688 GDK_WINDOW_IMPL_GET_IFACE (window->impl)->input_window_crossing ((GdkWindow *)window,
8689 type == GDK_ENTER_NOTIFY);
8691 if (window->event_mask & event_mask)
8693 event = _gdk_make_event ((GdkWindow *)window, type, event_in_queue, TRUE);
8694 event->crossing.time = time_;
8695 event->crossing.subwindow = subwindow;
8697 g_object_ref (subwindow);
8698 convert_toplevel_coords_to_window ((GdkWindow *)window,
8699 toplevel_x, toplevel_y,
8700 &event->crossing.x, &event->crossing.y);
8701 event->crossing.x_root = toplevel_x + toplevel->x;
8702 event->crossing.y_root = toplevel_y + toplevel->y;
8703 event->crossing.mode = mode;
8704 event->crossing.detail = notify_type;
8705 event->crossing.focus = FALSE;
8706 event->crossing.state = mask;
8711 /* The coordinates are in the toplevel window that src/dest are in.
8712 * src and dest are always (if != NULL) in the same toplevel, as
8713 * we get a leave-notify and set the window_under_pointer to null
8714 * before crossing to another toplevel.
8717 _gdk_synthesize_crossing_events (GdkDisplay *display,
8720 GdkCrossingMode mode,
8723 GdkModifierType mask,
8725 GdkEvent *event_in_queue,
8727 gboolean non_linear)
8730 GdkWindowObject *win, *last, *next;
8734 GdkWindowObject *toplevel;
8735 GdkNotifyType notify_type;
8737 /* TODO: Don't send events to toplevel, as we get those from the windowing system */
8739 a = (GdkWindowObject *)src;
8740 b = (GdkWindowObject *)dest;
8742 return; /* No crossings generated between src and dest */
8744 c = find_common_ancestor (a, b);
8746 non_linear |= (c != a) && (c != b);
8748 if (a) /* There might not be a source (i.e. if no previous pointer_in_window) */
8750 toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)a);
8752 /* Traverse up from a to (excluding) c sending leave events */
8754 notify_type = GDK_NOTIFY_NONLINEAR;
8756 notify_type = GDK_NOTIFY_INFERIOR;
8758 notify_type = GDK_NOTIFY_ANCESTOR;
8759 send_crossing_event (display, toplevel,
8760 a, GDK_LEAVE_NOTIFY,
8764 toplevel_x, toplevel_y,
8772 notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
8774 notify_type = GDK_NOTIFY_VIRTUAL;
8777 win = get_event_parent (a);
8778 while (win != c && win->window_type != GDK_WINDOW_ROOT)
8780 send_crossing_event (display, toplevel,
8781 win, GDK_LEAVE_NOTIFY,
8785 toplevel_x, toplevel_y,
8791 win = get_event_parent (win);
8796 if (b) /* Might not be a dest, e.g. if we're moving out of the window */
8798 toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)b);
8800 /* Traverse down from c to b */
8804 win = get_event_parent (b);
8805 while (win != c && win->window_type != GDK_WINDOW_ROOT)
8807 path = g_list_prepend (path, win);
8808 win = get_event_parent (win);
8812 notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
8814 notify_type = GDK_NOTIFY_VIRTUAL;
8819 win = (GdkWindowObject *)list->data;
8820 list = g_list_next (list);
8822 next = (GdkWindowObject *)list->data;
8826 send_crossing_event (display, toplevel,
8827 win, GDK_ENTER_NOTIFY,
8831 toplevel_x, toplevel_y,
8841 notify_type = GDK_NOTIFY_NONLINEAR;
8843 notify_type = GDK_NOTIFY_ANCESTOR;
8845 notify_type = GDK_NOTIFY_INFERIOR;
8847 send_crossing_event (display, toplevel,
8848 b, GDK_ENTER_NOTIFY,
8852 toplevel_x, toplevel_y,
8859 /* Returns the window inside the event window with the pointer in it
8860 * at the specified coordinates, or NULL if its not in any child of
8861 * the toplevel. It also takes into account !owner_events grabs.
8864 get_pointer_window (GdkDisplay *display,
8865 GdkWindow *event_window,
8870 GdkWindow *pointer_window;
8871 GdkPointerGrabInfo *grab;
8873 if (event_window == display->pointer_info.toplevel_under_pointer)
8875 _gdk_window_find_descendant_at (event_window,
8876 toplevel_x, toplevel_y,
8879 pointer_window = NULL;
8881 grab = _gdk_display_has_pointer_grab (display, serial);
8883 !grab->owner_events &&
8884 pointer_window != grab->window)
8885 pointer_window = NULL;
8887 return pointer_window;
8891 _gdk_display_set_window_under_pointer (GdkDisplay *display,
8894 GdkWindowObject *private;
8896 private = (GdkWindowObject *)window;
8898 if (display->pointer_info.window_under_pointer)
8899 g_object_unref (display->pointer_info.window_under_pointer);
8900 display->pointer_info.window_under_pointer = window;
8902 g_object_ref (window);
8905 update_cursor (display);
8907 _gdk_display_enable_motion_hints (display);
8911 *--------------------------------------------------------------
8914 * Grabs the pointer to a specific window
8917 * "window" is the window which will receive the grab
8918 * "owner_events" specifies whether events will be reported as is,
8919 * or relative to "window"
8920 * "event_mask" masks only interesting events
8921 * "confine_to" limits the cursor movement to the specified window
8922 * "cursor" changes the cursor for the duration of the grab
8923 * "time" specifies the time
8928 * requires a corresponding call to gdk_pointer_ungrab
8930 *--------------------------------------------------------------
8933 gdk_pointer_grab (GdkWindow * window,
8934 gboolean owner_events,
8935 GdkEventMask event_mask,
8936 GdkWindow * confine_to,
8941 GdkDisplay *display;
8945 g_return_val_if_fail (window != NULL, 0);
8946 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
8947 g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
8949 /* We need a native window for confine to to work, ensure we have one */
8952 if (!gdk_window_ensure_native (confine_to))
8954 g_warning ("Can't confine to grabbed window, not native");
8959 /* Non-viewable client side window => fail */
8960 if (!_gdk_window_has_impl (window) &&
8961 !gdk_window_is_viewable (window))
8962 return GDK_GRAB_NOT_VIEWABLE;
8964 native = gdk_window_get_toplevel (window);
8965 while (gdk_window_is_offscreen ((GdkWindowObject *)native))
8967 native = gdk_offscreen_window_get_embedder (native);
8969 if (native == NULL ||
8970 (!_gdk_window_has_impl (native) &&
8971 !gdk_window_is_viewable (native)))
8972 return GDK_GRAB_NOT_VIEWABLE;
8974 native = gdk_window_get_toplevel (native);
8977 display = gdk_drawable_get_display (window);
8979 serial = _gdk_windowing_window_get_next_serial (display);
8981 res = _gdk_windowing_pointer_grab (window,
8989 if (res == GDK_GRAB_SUCCESS)
8990 _gdk_display_add_pointer_grab (display,
9003 * gdk_window_geometry_changed:
9004 * @window: a #GdkWindow
9009 gdk_window_geometry_changed (GdkWindow *window)
9011 _gdk_synthesize_crossing_events_for_geometry_change (window);
9015 do_synthesize_crossing_event (gpointer data)
9017 GdkDisplay *display;
9018 GdkWindow *changed_toplevel;
9019 GdkWindowObject *changed_toplevel_priv;
9020 GdkWindow *new_window_under_pointer;
9023 changed_toplevel = data;
9024 changed_toplevel_priv = (GdkWindowObject *)changed_toplevel;
9026 changed_toplevel_priv->synthesize_crossing_event_queued = FALSE;
9028 if (GDK_WINDOW_DESTROYED (changed_toplevel))
9031 display = gdk_drawable_get_display (changed_toplevel);
9032 serial = _gdk_windowing_window_get_next_serial (display);
9034 if (changed_toplevel == display->pointer_info.toplevel_under_pointer)
9036 new_window_under_pointer =
9037 get_pointer_window (display, changed_toplevel,
9038 display->pointer_info.toplevel_x,
9039 display->pointer_info.toplevel_y,
9041 if (new_window_under_pointer !=
9042 display->pointer_info.window_under_pointer)
9044 _gdk_synthesize_crossing_events (display,
9045 display->pointer_info.window_under_pointer,
9046 new_window_under_pointer,
9047 GDK_CROSSING_NORMAL,
9048 display->pointer_info.toplevel_x,
9049 display->pointer_info.toplevel_y,
9050 display->pointer_info.state,
9055 _gdk_display_set_window_under_pointer (display, new_window_under_pointer);
9063 _gdk_synthesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
9065 GdkDisplay *display;
9066 GdkWindow *toplevel;
9067 GdkWindowObject *toplevel_priv;
9069 display = gdk_drawable_get_display (changed_window);
9071 toplevel = get_event_toplevel (changed_window);
9072 toplevel_priv = (GdkWindowObject *)toplevel;
9074 if (toplevel == display->pointer_info.toplevel_under_pointer &&
9075 !toplevel_priv->synthesize_crossing_event_queued)
9077 toplevel_priv->synthesize_crossing_event_queued = TRUE;
9078 g_idle_add_full (GDK_PRIORITY_EVENTS - 1,
9079 do_synthesize_crossing_event,
9080 g_object_ref (toplevel),
9085 /* Don't use for crossing events */
9087 get_event_window (GdkDisplay *display,
9088 GdkWindow *pointer_window,
9090 GdkModifierType mask,
9095 GdkWindow *grab_window;
9097 GdkPointerGrabInfo *grab;
9099 grab = _gdk_display_has_pointer_grab (display, serial);
9101 if (grab != NULL && !grab->owner_events)
9103 evmask = grab->event_mask;
9104 evmask = update_evmask_for_button_motion (evmask, mask);
9106 grab_window = grab->window;
9108 if (evmask & type_masks[type])
9111 *evmask_out = evmask;
9118 w = (GdkWindowObject *)pointer_window;
9121 evmask = w->event_mask;
9122 evmask = update_evmask_for_button_motion (evmask, mask);
9124 if (evmask & type_masks[type])
9127 *evmask_out = evmask;
9128 return (GdkWindow *)w;
9131 w = get_event_parent (w);
9137 evmask = grab->event_mask;
9138 evmask = update_evmask_for_button_motion (evmask, mask);
9140 if (evmask & type_masks[type])
9143 *evmask_out = evmask;
9144 return grab->window;
9154 proxy_pointer_event (GdkDisplay *display,
9155 GdkEvent *source_event,
9158 GdkWindow *toplevel_window, *event_window;
9159 GdkWindow *pointer_window;
9162 gdouble toplevel_x, toplevel_y;
9164 gboolean non_linear;
9166 event_window = source_event->any.window;
9167 gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
9168 gdk_event_get_state (source_event, &state);
9169 time_ = gdk_event_get_time (source_event);
9170 toplevel_window = convert_native_coords_to_toplevel (event_window,
9171 toplevel_x, toplevel_y,
9172 &toplevel_x, &toplevel_y);
9175 if ((source_event->type == GDK_LEAVE_NOTIFY ||
9176 source_event->type == GDK_ENTER_NOTIFY) &&
9177 (source_event->crossing.detail == GDK_NOTIFY_NONLINEAR ||
9178 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))
9181 /* If we get crossing events with subwindow unexpectedly being NULL
9182 that means there is a native subwindow that gdk doesn't know about.
9183 We track these and forward them, with the correct virtual window
9185 This is important to get right, as metacity uses gdk for the frame
9186 windows, but gdk doesn't know about the client windows reparented
9188 if (((source_event->type == GDK_LEAVE_NOTIFY &&
9189 source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
9190 (source_event->type == GDK_ENTER_NOTIFY &&
9191 (source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
9192 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
9193 source_event->crossing.subwindow == NULL)
9195 /* Left for an unknown (to gdk) subwindow */
9197 /* Send leave events from window under pointer to event window
9198 that will get the subwindow == NULL window */
9199 _gdk_synthesize_crossing_events (display,
9200 display->pointer_info.window_under_pointer,
9202 source_event->crossing.mode,
9203 toplevel_x, toplevel_y,
9209 /* Send subwindow == NULL event */
9210 send_crossing_event (display,
9211 (GdkWindowObject *)toplevel_window,
9212 (GdkWindowObject *)event_window,
9214 source_event->crossing.mode,
9215 source_event->crossing.detail,
9217 toplevel_x, toplevel_y,
9222 _gdk_display_set_window_under_pointer (display, NULL);
9226 pointer_window = get_pointer_window (display, toplevel_window,
9227 toplevel_x, toplevel_y, serial);
9229 if (((source_event->type == GDK_ENTER_NOTIFY &&
9230 source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
9231 (source_event->type == GDK_LEAVE_NOTIFY &&
9232 (source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
9233 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
9234 source_event->crossing.subwindow == NULL)
9236 /* Entered from an unknown (to gdk) subwindow */
9238 /* Send subwindow == NULL event */
9239 send_crossing_event (display,
9240 (GdkWindowObject *)toplevel_window,
9241 (GdkWindowObject *)event_window,
9243 source_event->crossing.mode,
9244 source_event->crossing.detail,
9246 toplevel_x, toplevel_y,
9251 /* Send enter events from event window to pointer_window */
9252 _gdk_synthesize_crossing_events (display,
9255 source_event->crossing.mode,
9256 toplevel_x, toplevel_y,
9259 serial, non_linear);
9260 _gdk_display_set_window_under_pointer (display, pointer_window);
9264 if (display->pointer_info.window_under_pointer != pointer_window)
9266 /* Either a toplevel crossing notify that ended up inside a child window,
9267 or a motion notify that got into another child window */
9269 /* Different than last time, send crossing events */
9270 _gdk_synthesize_crossing_events (display,
9271 display->pointer_info.window_under_pointer,
9273 GDK_CROSSING_NORMAL,
9274 toplevel_x, toplevel_y,
9277 serial, non_linear);
9278 _gdk_display_set_window_under_pointer (display, pointer_window);
9280 else if (source_event->type == GDK_MOTION_NOTIFY)
9282 GdkWindow *event_win;
9286 event_win = get_event_window (display,
9296 (evmask & GDK_POINTER_MOTION_HINT_MASK))
9298 if (display->pointer_info.motion_hint_serial != 0 &&
9299 serial < display->pointer_info.motion_hint_serial)
9300 event_win = NULL; /* Ignore event */
9304 display->pointer_info.motion_hint_serial = G_MAXULONG;
9308 if (event_win && !display->ignore_core_events)
9310 event = _gdk_make_event (event_win, GDK_MOTION_NOTIFY, source_event, FALSE);
9311 event->motion.time = time_;
9312 convert_toplevel_coords_to_window (event_win,
9313 toplevel_x, toplevel_y,
9314 &event->motion.x, &event->motion.y);
9315 event->motion.x_root = source_event->motion.x_root;
9316 event->motion.y_root = source_event->motion.y_root;;
9317 event->motion.state = state;
9318 event->motion.is_hint = is_hint;
9319 event->motion.device = NULL;
9320 event->motion.device = source_event->motion.device;
9324 /* unlink all move events from queue.
9325 We handle our own, including our emulated masks. */
9329 #define GDK_ANY_BUTTON_MASK (GDK_BUTTON1_MASK | \
9330 GDK_BUTTON2_MASK | \
9331 GDK_BUTTON3_MASK | \
9332 GDK_BUTTON4_MASK | \
9336 proxy_button_event (GdkEvent *source_event,
9339 GdkWindow *toplevel_window, *event_window;
9340 GdkWindow *event_win;
9341 GdkWindow *pointer_window;
9342 GdkWindowObject *parent;
9347 gdouble toplevel_x, toplevel_y;
9348 GdkDisplay *display;
9351 type = source_event->any.type;
9352 event_window = source_event->any.window;
9353 gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
9354 gdk_event_get_state (source_event, &state);
9355 time_ = gdk_event_get_time (source_event);
9356 display = gdk_drawable_get_display (source_event->any.window);
9357 toplevel_window = convert_native_coords_to_toplevel (event_window,
9358 toplevel_x, toplevel_y,
9359 &toplevel_x, &toplevel_y);
9361 if (type == GDK_BUTTON_PRESS &&
9362 _gdk_display_has_pointer_grab (display, serial) == NULL)
9365 _gdk_window_find_descendant_at (toplevel_window,
9366 toplevel_x, toplevel_y,
9369 /* Find the event window, that gets the grab */
9370 w = (GdkWindowObject *)pointer_window;
9372 (parent = get_event_parent (w)) != NULL &&
9373 parent->window_type != GDK_WINDOW_ROOT)
9375 if (w->event_mask & GDK_BUTTON_PRESS_MASK)
9379 pointer_window = (GdkWindow *)w;
9381 _gdk_display_add_pointer_grab (display,
9385 gdk_window_get_events (pointer_window),
9389 _gdk_display_pointer_grab_update (display, serial);
9392 pointer_window = get_pointer_window (display, toplevel_window,
9393 toplevel_x, toplevel_y,
9396 event_win = get_event_window (display,
9401 if (event_win == NULL || display->ignore_core_events)
9404 event = _gdk_make_event (event_win, type, source_event, FALSE);
9408 case GDK_BUTTON_PRESS:
9409 case GDK_BUTTON_RELEASE:
9410 event->button.button = source_event->button.button;
9411 convert_toplevel_coords_to_window (event_win,
9412 toplevel_x, toplevel_y,
9413 &event->button.x, &event->button.y);
9414 event->button.x_root = source_event->button.x_root;
9415 event->button.y_root = source_event->button.y_root;
9416 event->button.state = state;
9417 event->button.device = source_event->button.device;
9419 if (type == GDK_BUTTON_PRESS)
9420 _gdk_event_button_generate (display, event);
9424 event->scroll.direction = source_event->scroll.direction;
9425 convert_toplevel_coords_to_window (event_win,
9426 toplevel_x, toplevel_y,
9427 &event->scroll.x, &event->scroll.y);
9428 event->scroll.x_root = source_event->scroll.x_root;
9429 event->scroll.y_root = source_event->scroll.y_root;
9430 event->scroll.state = state;
9431 event->scroll.device = source_event->scroll.device;
9438 return TRUE; /* Always unlink original, we want to obey the emulated event mask */
9441 #ifdef DEBUG_WINDOW_PRINTING
9443 gdk_window_print (GdkWindowObject *window,
9448 g_print ("%*s%p: [%s] %d,%d %dx%d", indent, "", window,
9449 window->user_data ? g_type_name_from_instance (window->user_data) : "no widget",
9450 window->x, window->y,
9451 window->width, window->height
9454 if (gdk_window_has_impl (window))
9456 #ifdef GDK_WINDOWING_X11
9457 g_print (" impl(0x%lx)", gdk_x11_drawable_get_xid (GDK_DRAWABLE (window)));
9461 if (window->input_only)
9462 g_print (" input-only");
9464 if (!gdk_window_is_visible ((GdkWindow *)window))
9465 g_print (" hidden");
9467 g_print (" abs[%d,%d]",
9468 window->abs_x, window->abs_y);
9470 gdk_region_get_clipbox (window->clip_region, &r);
9471 if (gdk_region_empty (window->clip_region))
9472 g_print (" clipbox[empty]");
9474 g_print (" clipbox[%d,%d %dx%d]", r.x, r.y, r.width, r.height);
9481 gdk_window_print_tree (GdkWindow *window,
9483 gboolean include_input_only)
9485 GdkWindowObject *private;
9488 private = (GdkWindowObject *)window;
9490 if (private->input_only && !include_input_only)
9493 gdk_window_print (private, indent);
9495 for (l = private->children; l != NULL; l = l->next)
9496 gdk_window_print_tree (l->data, indent + 4, include_input_only);
9499 #endif /* DEBUG_WINDOW_PRINTING */
9502 is_input_event (GdkDisplay *display,
9505 GdkDevice *core_pointer;
9507 core_pointer = gdk_display_get_core_pointer (display);
9508 if ((event->type == GDK_MOTION_NOTIFY &&
9509 event->motion.device != core_pointer) ||
9510 ((event->type == GDK_BUTTON_PRESS ||
9511 event->type == GDK_BUTTON_RELEASE) &&
9512 event->button.device != core_pointer))
9518 _gdk_windowing_got_event (GdkDisplay *display,
9523 GdkWindow *event_window;
9524 GdkWindowObject *event_private;
9526 gboolean unlink_event;
9527 guint old_state, old_button;
9528 GdkPointerGrabInfo *button_release_grab;
9529 gboolean is_toplevel;
9531 if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
9532 display->last_event_time = gdk_event_get_time (event);
9534 _gdk_display_pointer_grab_update (display,
9537 event_window = event->any.window;
9541 event_private = GDK_WINDOW_OBJECT (event_window);
9543 #ifdef DEBUG_WINDOW_PRINTING
9544 if (event->type == GDK_KEY_PRESS &&
9545 (event->key.keyval == 0xa7 ||
9546 event->key.keyval == 0xbd))
9548 gdk_window_print_tree (event_window, 0,
9549 event->key.keyval == 0xbd);
9553 if (event->type == GDK_VISIBILITY_NOTIFY)
9555 event_private->native_visibility = event->visibility.state;
9556 gdk_window_update_visibility_recursively (event_private,
9561 if (is_input_event (display, event))
9564 if (!(is_button_type (event->type) ||
9565 is_motion_type (event->type)) ||
9566 event_private->window_type == GDK_WINDOW_ROOT)
9570 event_private->parent == NULL ||
9571 event_private->parent->window_type == GDK_WINDOW_ROOT;
9573 if ((event->type == GDK_ENTER_NOTIFY ||
9574 event->type == GDK_LEAVE_NOTIFY) &&
9575 (event->crossing.mode == GDK_CROSSING_GRAB ||
9576 event->crossing.mode == GDK_CROSSING_UNGRAB) &&
9577 (_gdk_display_has_pointer_grab (display, serial) ||
9578 event->crossing.detail == GDK_NOTIFY_INFERIOR))
9580 /* We synthesize all crossing events due to grabs ourselves,
9581 * so we ignore the native ones caused by our native pointer_grab
9582 * calls. Otherwise we would proxy these crossing event and cause
9583 * multiple copies of crossing events for grabs.
9585 * We do want to handle grabs from other clients though, as for
9586 * instance alt-tab in metacity causes grabs like these and
9587 * we want to handle those. Thus the has_pointer_grab check.
9589 * Implicit grabs on child windows create some grabbing events
9590 * that are sent before the button press. This means we can't
9591 * detect these with the has_pointer_grab check (as the implicit
9592 * grab is only noticed when we get button press event), so we
9593 * detect these events by checking for INFERIOR enter or leave
9594 * events. These should never be a problem to filter out.
9597 /* We ended up in this window after some (perhaps other clients)
9598 grab, so update the toplevel_under_window state */
9600 event->type == GDK_ENTER_NOTIFY &&
9601 event->crossing.mode == GDK_CROSSING_UNGRAB)
9603 if (display->pointer_info.toplevel_under_pointer)
9604 g_object_unref (display->pointer_info.toplevel_under_pointer);
9605 display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
9608 unlink_event = TRUE;
9612 /* Track toplevel_under_pointer */
9615 if (event->type == GDK_ENTER_NOTIFY &&
9616 event->crossing.detail != GDK_NOTIFY_INFERIOR)
9618 if (display->pointer_info.toplevel_under_pointer)
9619 g_object_unref (display->pointer_info.toplevel_under_pointer);
9620 display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
9622 else if (event->type == GDK_LEAVE_NOTIFY &&
9623 event->crossing.detail != GDK_NOTIFY_INFERIOR &&
9624 display->pointer_info.toplevel_under_pointer == event_window)
9626 if (display->pointer_info.toplevel_under_pointer)
9627 g_object_unref (display->pointer_info.toplevel_under_pointer);
9628 display->pointer_info.toplevel_under_pointer = NULL;
9632 /* Store last pointer window and position/state */
9633 old_state = display->pointer_info.state;
9634 old_button = display->pointer_info.button;
9636 gdk_event_get_coords (event, &x, &y);
9637 convert_native_coords_to_toplevel (event_window, x, y, &x, &y);
9638 display->pointer_info.toplevel_x = x;
9639 display->pointer_info.toplevel_y = y;
9640 gdk_event_get_state (event, &display->pointer_info.state);
9641 if (event->type == GDK_BUTTON_PRESS ||
9642 event->type == GDK_BUTTON_RELEASE)
9643 display->pointer_info.button = event->button.button;
9645 if (display->pointer_info.state != old_state ||
9646 display->pointer_info.button != old_button)
9647 _gdk_display_enable_motion_hints (display);
9649 unlink_event = FALSE;
9650 if (is_motion_type (event->type))
9651 unlink_event = proxy_pointer_event (display,
9654 else if (is_button_type (event->type))
9655 unlink_event = proxy_button_event (event,
9658 if (event->type == GDK_BUTTON_RELEASE)
9660 button_release_grab =
9661 _gdk_display_has_pointer_grab (display, serial);
9662 if (button_release_grab &&
9663 button_release_grab->implicit &&
9664 (event->button.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
9666 button_release_grab->serial_end = serial;
9667 button_release_grab->implicit_ungrab = TRUE;
9668 _gdk_display_pointer_grab_update (display, serial);
9675 _gdk_event_queue_remove_link (display, event_link);
9676 g_list_free_1 (event_link);
9677 gdk_event_free (event);
9683 get_extension_event_window (GdkDisplay *display,
9684 GdkWindow *pointer_window,
9689 GdkWindow *grab_window;
9691 GdkPointerGrabInfo *grab;
9693 grab = _gdk_display_has_pointer_grab (display, serial);
9695 if (grab != NULL && !grab->owner_events)
9697 evmask = grab->event_mask;
9699 grab_window = grab->window;
9701 if (evmask & type_masks[type])
9707 w = (GdkWindowObject *)pointer_window;
9710 evmask = w->extension_events;
9712 if (evmask & type_masks[type])
9713 return (GdkWindow *)w;
9715 w = get_event_parent (w);
9721 evmask = grab->event_mask;
9723 if (evmask & type_masks[type])
9724 return grab->window;
9734 _gdk_window_get_input_window_for_event (GdkWindow *native_window,
9735 GdkEventType event_type,
9739 GdkDisplay *display;
9740 GdkWindow *toplevel_window;
9741 GdkWindow *pointer_window;
9742 GdkWindow *event_win;
9743 gdouble toplevel_x, toplevel_y;
9748 display = gdk_drawable_get_display (native_window);
9749 toplevel_window = convert_native_coords_to_toplevel (native_window,
9750 toplevel_x, toplevel_y,
9751 &toplevel_x, &toplevel_y);
9752 pointer_window = get_pointer_window (display, toplevel_window,
9753 toplevel_x, toplevel_y, serial);
9754 event_win = get_extension_event_window (display,
9763 #define __GDK_WINDOW_C__
9764 #include "gdkaliasdef.c"