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 */
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 gdk_region_subtract (impl_window->update_area, update_area);
3014 gdk_region_offset (update_area, dx, dy);
3015 gdk_region_union (impl_window->update_area, update_area);
3017 /* This area of the destination is now invalid,
3018 so no need to copy to it. */
3019 gdk_region_subtract (region, update_area);
3021 gdk_region_destroy (update_area);
3024 if (1) /* Enable flicker free handling of moves. */
3025 append_move_region (impl_window, region, dx, dy);
3027 do_move_region_bits_on_impl (impl_window,
3030 gdk_region_destroy (region);
3033 /* Flushes all outstanding changes to the window, call this
3034 * before drawing directly to the window (i.e. outside a begin/end_paint pair).
3037 gdk_window_flush_outstanding_moves (GdkWindow *window)
3039 GdkWindowObject *private;
3040 GdkWindowObject *impl_window;
3042 GdkWindowRegionMove *move;
3044 private = (GdkWindowObject *) window;
3046 impl_window = gdk_window_get_impl_window (private);
3048 for (l = impl_window->outstanding_moves; l != NULL; l = l->next)
3052 do_move_region_bits_on_impl (impl_window,
3053 move->dest_region, move->dx, move->dy);
3055 gdk_window_region_move_free (move);
3058 g_list_free (impl_window->outstanding_moves);
3059 impl_window->outstanding_moves = NULL;
3063 gdk_window_flush (GdkWindow *window)
3065 gdk_window_flush_outstanding_moves (window);
3066 gdk_window_flush_implicit_paint (window);
3070 gdk_window_flush_recursive_helper (GdkWindowObject *window,
3073 GdkWindowObject *child;
3076 for (l = window->children; l != NULL; l = l->next)
3080 if (child->impl == impl)
3081 /* Same impl, ignore */
3082 gdk_window_flush_recursive_helper (child, impl);
3084 gdk_window_flush_recursive (child);
3089 gdk_window_flush_recursive (GdkWindowObject *window)
3091 gdk_window_flush ((GdkWindow *)window);
3092 gdk_window_flush_recursive_helper (window, window->impl);
3096 gdk_window_get_offsets (GdkWindow *window,
3100 GdkWindowObject *private = (GdkWindowObject *)window;
3102 if (private->paint_stack)
3104 GdkWindowPaint *paint = private->paint_stack->data;
3105 *x_offset = paint->x_offset;
3106 *y_offset = paint->y_offset;
3110 *x_offset = -private->abs_x;
3111 *y_offset = -private->abs_y;
3116 * gdk_window_get_internal_paint_info:
3117 * @window: a #GdkWindow
3118 * @real_drawable: location to store the drawable to which drawing should be
3120 * @x_offset: location to store the X offset between coordinates in @window,
3121 * and the underlying window system primitive coordinates for
3123 * @y_offset: location to store the Y offset between coordinates in @window,
3124 * and the underlying window system primitive coordinates for
3127 * If you bypass the GDK layer and use windowing system primitives to
3128 * draw directly onto a #GdkWindow, then you need to deal with two
3129 * details: there may be an offset between GDK coordinates and windowing
3130 * system coordinates, and GDK may have redirected drawing to a offscreen
3131 * pixmap as the result of a gdk_window_begin_paint_region() calls.
3132 * This function allows retrieving the information you need to compensate
3133 * for these effects.
3135 * This function exposes details of the GDK implementation, and is thus
3136 * likely to change in future releases of GDK.
3139 gdk_window_get_internal_paint_info (GdkWindow *window,
3140 GdkDrawable **real_drawable,
3146 GdkWindowObject *private;
3148 g_return_if_fail (GDK_IS_WINDOW (window));
3150 private = (GdkWindowObject *)window;
3154 if (private->paint_stack)
3156 GdkWindowPaint *paint = private->paint_stack->data;
3157 *real_drawable = paint->pixmap;
3161 /* This means you're probably gonna be doing some weird shit
3162 directly to the window, so we flush all outstanding stuff */
3163 gdk_window_flush (window);
3164 *real_drawable = window;
3168 gdk_window_get_offsets (window, &x_off, &y_off);
3176 static GdkDrawable *
3177 start_draw_helper (GdkDrawable *drawable,
3182 GdkWindowObject *private = (GdkWindowObject *)drawable;
3183 gint x_offset, y_offset;
3185 gint old_clip_x = gc->clip_x_origin;
3186 gint old_clip_y = gc->clip_y_origin;
3188 guint32 clip_region_tag;
3189 GdkWindowPaint *paint;
3192 if (private->paint_stack)
3193 paint = private->paint_stack->data;
3197 x_offset = paint->x_offset;
3198 y_offset = paint->y_offset;
3202 x_offset = -private->abs_x;
3203 y_offset = -private->abs_y;
3206 if (x_offset != 0 || y_offset != 0)
3208 gdk_gc_set_clip_origin (gc,
3209 old_clip_x - x_offset,
3210 old_clip_y - y_offset);
3211 gdk_gc_set_ts_origin (gc,
3212 gc->ts_x_origin - x_offset,
3213 gc->ts_y_origin - y_offset);
3216 *x_offset_out = x_offset;
3217 *y_offset_out = y_offset;
3219 /* Add client side window clip region to gc */
3223 /* Only need clipping if using implicit paint, otherwise
3224 the pixmap is clipped when copying to the window in end_paint */
3225 if (paint->uses_implicit)
3227 /* This includes the window clip */
3228 clip = paint->region;
3230 clip_region_tag = paint->region_tag;
3232 /* After having set up the drawable clip rect on a GC we need to make sure
3233 * that we draw to th the impl, otherwise the pixmap code will reset the
3235 impl = ((GdkPixmapObject *)(paint->pixmap))->impl;
3239 /* Drawing directly to the window, flush anything outstanding to
3240 guarantee ordering. */
3241 gdk_window_flush ((GdkWindow *)drawable);
3243 /* Don't clip when drawing to root */
3244 if (private->window_type != GDK_WINDOW_ROOT)
3246 if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
3247 clip = private->clip_region_with_children;
3249 clip = private->clip_region;
3251 clip_region_tag = private->clip_tag;
3252 impl = private->impl;
3256 _gdk_gc_add_drawable_clip (gc,
3257 clip_region_tag, clip,
3258 /* If there was a clip origin set appart from the
3259 * window offset, need to take that into
3261 -old_clip_x, -old_clip_y);
3266 #define BEGIN_DRAW \
3268 GdkDrawable *impl; \
3269 gint x_offset, y_offset; \
3270 gint old_clip_x = gc->clip_x_origin; \
3271 gint old_clip_y = gc->clip_y_origin; \
3272 gint old_ts_x = gc->ts_x_origin; \
3273 gint old_ts_y = gc->ts_y_origin; \
3274 impl = start_draw_helper (drawable, gc, \
3275 &x_offset, &y_offset);
3278 if (x_offset != 0 || y_offset != 0) \
3280 gdk_gc_set_clip_origin (gc, old_clip_x, old_clip_y); \
3281 gdk_gc_set_ts_origin (gc, old_ts_x, old_ts_y); \
3286 gdk_window_create_gc (GdkDrawable *drawable,
3287 GdkGCValues *values,
3288 GdkGCValuesMask mask)
3290 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
3292 if (GDK_WINDOW_DESTROYED (drawable))
3295 return gdk_gc_new_with_values (((GdkWindowObject *) drawable)->impl,
3300 gdk_window_draw_rectangle (GdkDrawable *drawable,
3308 if (GDK_WINDOW_DESTROYED (drawable))
3312 gdk_draw_rectangle (impl, gc, filled,
3313 x - x_offset, y - y_offset, width, height);
3318 gdk_window_draw_arc (GdkDrawable *drawable,
3328 if (GDK_WINDOW_DESTROYED (drawable))
3332 gdk_draw_arc (impl, gc, filled,
3333 x - x_offset, y - y_offset,
3334 width, height, angle1, angle2);
3339 gdk_window_draw_polygon (GdkDrawable *drawable,
3345 GdkPoint *new_points;
3347 if (GDK_WINDOW_DESTROYED (drawable))
3352 if (x_offset != 0 || y_offset != 0)
3356 new_points = g_new (GdkPoint, npoints);
3357 for (i=0; i<npoints; i++)
3359 new_points[i].x = points[i].x - x_offset;
3360 new_points[i].y = points[i].y - y_offset;
3364 new_points = points;
3366 gdk_draw_polygon (impl, gc, filled, new_points, npoints);
3368 if (new_points != points)
3369 g_free (new_points);
3375 gdk_window_draw_text (GdkDrawable *drawable,
3383 if (GDK_WINDOW_DESTROYED (drawable))
3387 gdk_draw_text (impl, font, gc,
3388 x - x_offset, y - y_offset, text, text_length);
3393 gdk_window_draw_text_wc (GdkDrawable *drawable,
3398 const GdkWChar *text,
3401 if (GDK_WINDOW_DESTROYED (drawable))
3405 gdk_draw_text_wc (impl, font, gc,
3406 x - x_offset, y - y_offset, text, text_length);
3410 static GdkDrawable *
3411 gdk_window_get_source_drawable (GdkDrawable *drawable)
3413 GdkWindow *window = GDK_WINDOW (drawable);
3414 GdkWindowObject *private;
3416 private = (GdkWindowObject *) window;
3417 if (GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable)
3418 return GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable (private->impl);
3423 static GdkDrawable *
3424 gdk_window_get_composite_drawable (GdkDrawable *drawable,
3429 gint *composite_x_offset,
3430 gint *composite_y_offset)
3432 GdkWindowObject *private = (GdkWindowObject *)drawable;
3434 GdkPixmap *tmp_pixmap;
3437 gboolean overlap_buffer;
3438 GdkDrawable *source;
3439 GdkWindowObject *impl_window;
3440 GdkWindowPaint *implicit_paint;
3442 *composite_x_offset = -private->abs_x;
3443 *composite_y_offset = -private->abs_y;
3445 if ((GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable)))
3446 return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
3448 /* See if any buffered part is overlapping the part we want
3454 rect.height = height;
3456 overlap_buffer = FALSE;
3458 for (list = private->paint_stack; list != NULL; list = list->next)
3460 GdkWindowPaint *paint = list->data;
3461 GdkOverlapType overlap;
3463 overlap = gdk_region_rect_in (paint->region, &rect);
3465 if (overlap == GDK_OVERLAP_RECTANGLE_IN)
3467 *composite_x_offset = paint->x_offset;
3468 *composite_y_offset = paint->y_offset;
3470 return g_object_ref (paint->pixmap);
3472 else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
3474 overlap_buffer = TRUE;
3479 impl_window = gdk_window_get_impl_window (private);
3480 implicit_paint = impl_window->implicit_paint;
3483 GdkOverlapType overlap;
3485 rect.x += private->abs_x;
3486 rect.y += private->abs_y;
3488 overlap = gdk_region_rect_in (implicit_paint->region, &rect);
3489 if (overlap == GDK_OVERLAP_RECTANGLE_IN)
3491 *composite_x_offset = -private->abs_x + implicit_paint->x_offset;
3492 *composite_y_offset = -private->abs_y + implicit_paint->y_offset;
3494 return g_object_ref (implicit_paint->pixmap);
3496 else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
3497 overlap_buffer = TRUE;
3500 if (!overlap_buffer)
3501 return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
3503 tmp_pixmap = gdk_pixmap_new (drawable, width, height, -1);
3504 tmp_gc = _gdk_drawable_get_scratch_gc (tmp_pixmap, FALSE);
3506 source = _gdk_drawable_get_source_drawable (drawable);
3508 /* Copy the current window contents */
3509 gdk_draw_drawable (tmp_pixmap,
3511 GDK_WINDOW_OBJECT (source)->impl,
3512 x - *composite_x_offset,
3513 y - *composite_y_offset,
3517 /* paint the backing stores */
3520 GdkWindowPaint *paint = list->data;
3522 gdk_gc_set_clip_region (tmp_gc, paint->region);
3523 gdk_gc_set_clip_origin (tmp_gc, -x - paint->x_offset, -y - paint->y_offset);
3525 gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
3526 x - paint->x_offset,
3527 y - paint->y_offset,
3528 0, 0, width, height);
3531 for (list = private->paint_stack; list != NULL; list = list->next)
3533 GdkWindowPaint *paint = list->data;
3535 if (paint->uses_implicit)
3536 continue; /* We already copied this above */
3538 gdk_gc_set_clip_region (tmp_gc, paint->region);
3539 gdk_gc_set_clip_origin (tmp_gc, -x, -y);
3541 gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
3542 x - paint->x_offset,
3543 y - paint->y_offset,
3544 0, 0, width, height);
3547 /* Reset clip region of the cached GdkGC */
3548 gdk_gc_set_clip_region (tmp_gc, NULL);
3550 /* Set these to location of tmp_pixmap within the window */
3551 *composite_x_offset = x;
3552 *composite_y_offset = y;
3558 gdk_window_get_clip_region (GdkDrawable *drawable)
3560 GdkWindowObject *private = (GdkWindowObject *)drawable;
3563 result = gdk_region_copy (private->clip_region);
3565 if (private->paint_stack)
3567 GdkRegion *paint_region = gdk_region_new ();
3568 GSList *tmp_list = private->paint_stack;
3572 GdkWindowPaint *paint = tmp_list->data;
3574 gdk_region_union (paint_region, paint->region);
3576 tmp_list = tmp_list->next;
3579 gdk_region_intersect (result, paint_region);
3580 gdk_region_destroy (paint_region);
3587 gdk_window_get_visible_region (GdkDrawable *drawable)
3589 GdkWindowObject *private = (GdkWindowObject*) drawable;
3591 return gdk_region_copy (private->clip_region);
3595 gdk_window_draw_drawable (GdkDrawable *drawable,
3604 GdkDrawable *original_src)
3606 GdkWindowObject *private = (GdkWindowObject *)drawable;
3608 if (GDK_WINDOW_DESTROYED (drawable))
3613 gdk_draw_drawable (impl, gc, src, xsrc, ysrc,
3614 xdest - x_offset, ydest - y_offset, width, height);
3616 if (!private->paint_stack)
3618 /* We might have drawn from an obscured part of a client
3619 side window, if so we need to send graphics exposures */
3620 if (_gdk_gc_get_exposures (gc) &&
3621 GDK_IS_WINDOW (original_src))
3623 GdkRegion *exposure_region;
3631 exposure_region = gdk_region_rectangle (&r);
3633 if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
3634 clip = private->clip_region_with_children;
3636 clip = private->clip_region;
3637 gdk_region_intersect (exposure_region, clip);
3639 clip = _gdk_gc_get_clip_region (gc);
3642 gdk_region_offset (exposure_region,
3645 gdk_region_intersect (exposure_region, clip);
3646 gdk_region_offset (exposure_region,
3651 /* Note: We don't clip by the clip mask if set, so this
3652 may invalidate to much */
3654 /* Remove the area that is correctly copied from the src.
3655 * Note that xsrc/ysrc has been corrected for abs_x/y offsets already,
3656 * which need to be undone */
3657 clip = gdk_drawable_get_visible_region (original_src);
3658 gdk_region_offset (clip,
3659 xdest - (xsrc - GDK_WINDOW_OBJECT (original_src)->abs_x),
3660 ydest - (ysrc - GDK_WINDOW_OBJECT (original_src)->abs_y));
3661 gdk_region_subtract (exposure_region, clip);
3662 gdk_region_destroy (clip);
3664 gdk_window_invalidate_region (GDK_WINDOW (private),
3666 _gdk_gc_get_subwindow (gc) == GDK_INCLUDE_INFERIORS);
3668 gdk_region_destroy (exposure_region);
3676 gdk_window_draw_points (GdkDrawable *drawable,
3681 GdkPoint *new_points;
3683 if (GDK_WINDOW_DESTROYED (drawable))
3688 if (x_offset != 0 || y_offset != 0)
3692 new_points = g_new (GdkPoint, npoints);
3693 for (i=0; i<npoints; i++)
3695 new_points[i].x = points[i].x - x_offset;
3696 new_points[i].y = points[i].y - y_offset;
3700 new_points = points;
3702 gdk_draw_points (impl, gc, new_points, npoints);
3704 if (new_points != points)
3705 g_free (new_points);
3711 gdk_window_draw_segments (GdkDrawable *drawable,
3716 GdkSegment *new_segs;
3718 if (GDK_WINDOW_DESTROYED (drawable))
3723 if (x_offset != 0 || y_offset != 0)
3727 new_segs = g_new (GdkSegment, nsegs);
3728 for (i=0; i<nsegs; i++)
3730 new_segs[i].x1 = segs[i].x1 - x_offset;
3731 new_segs[i].y1 = segs[i].y1 - y_offset;
3732 new_segs[i].x2 = segs[i].x2 - x_offset;
3733 new_segs[i].y2 = segs[i].y2 - y_offset;
3739 gdk_draw_segments (impl, gc, new_segs, nsegs);
3741 if (new_segs != segs)
3748 gdk_window_draw_lines (GdkDrawable *drawable,
3753 GdkPoint *new_points;
3755 if (GDK_WINDOW_DESTROYED (drawable))
3760 if (x_offset != 0 || y_offset != 0)
3764 new_points = g_new (GdkPoint, npoints);
3765 for (i=0; i<npoints; i++)
3767 new_points[i].x = points[i].x - x_offset;
3768 new_points[i].y = points[i].y - y_offset;
3772 new_points = points;
3774 gdk_draw_lines (impl, gc, new_points, npoints);
3776 if (new_points != points)
3777 g_free (new_points);
3783 gdk_window_draw_glyphs (GdkDrawable *drawable,
3788 PangoGlyphString *glyphs)
3790 if (GDK_WINDOW_DESTROYED (drawable))
3794 gdk_draw_glyphs (impl, gc, font,
3795 x - x_offset, y - y_offset, glyphs);
3800 gdk_window_draw_glyphs_transformed (GdkDrawable *drawable,
3802 PangoMatrix *matrix,
3806 PangoGlyphString *glyphs)
3808 PangoMatrix tmp_matrix;
3810 if (GDK_WINDOW_DESTROYED (drawable))
3815 if (x_offset != 0 || y_offset != 0)
3819 tmp_matrix = *matrix;
3820 tmp_matrix.x0 -= x_offset;
3821 tmp_matrix.y0 -= y_offset;
3822 matrix = &tmp_matrix;
3824 else if (GDK_PANGO_UNITS_OVERFLOWS (x_offset, y_offset))
3826 PangoMatrix identity = PANGO_MATRIX_INIT;
3828 tmp_matrix = identity;
3829 tmp_matrix.x0 -= x_offset;
3830 tmp_matrix.y0 -= y_offset;
3831 matrix = &tmp_matrix;
3835 x -= x_offset * PANGO_SCALE;
3836 y -= y_offset * PANGO_SCALE;
3840 gdk_draw_glyphs_transformed (impl, gc, matrix, font, x, y, glyphs);
3846 cairo_t *cr; /* if non-null, it means use this cairo context */
3847 GdkGC *gc; /* if non-null, it means use this GC instead */
3848 } BackingRectMethod;
3851 setup_backing_rect_method (BackingRectMethod *method, GdkWindow *window, GdkWindowPaint *paint, int x_offset_cairo, int y_offset_cairo)
3853 GdkWindowObject *private = (GdkWindowObject *)window;
3855 if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
3857 GdkWindowPaint tmp_paint;
3860 tmp_paint.x_offset += private->x;
3861 tmp_paint.y_offset += private->y;
3863 x_offset_cairo += private->x;
3864 y_offset_cairo += private->y;
3866 setup_backing_rect_method (method, GDK_WINDOW (private->parent), &tmp_paint, x_offset_cairo, y_offset_cairo);
3868 else if (private->bg_pixmap &&
3869 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
3870 private->bg_pixmap != GDK_NO_BG)
3872 /* This is a workaround for https://bugs.freedesktop.org/show_bug.cgi?id=4320.
3873 * In it, using a pixmap as a repeating pattern in Cairo, and painting it to a
3874 * pixmap destination surface, can be very slow (on the order of seconds for a
3875 * whole-screen copy). The workaround is to use pretty much the same code that
3876 * we used in GTK+ 2.6 (pre-Cairo), which clears the double-buffer pixmap with
3877 * a tiled GC XFillRectangle().
3880 /* Actually computing this flag is left as an exercise for the reader */
3881 #if defined (G_OS_UNIX)
3882 # define GDK_CAIRO_REPEAT_IS_FAST 0
3884 # define GDK_CAIRO_REPEAT_IS_FAST 1
3887 #if GDK_CAIRO_REPEAT_IS_FAST
3888 cairo_surface_t *surface = _gdk_drawable_ref_cairo_surface (private->bg_pixmap);
3889 cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
3890 cairo_surface_destroy (surface);
3892 if (x_offset_cairo != 0 || y_offset_cairo != 0)
3894 cairo_matrix_t matrix;
3895 cairo_matrix_init_translate (&matrix, x_offset_cairo, y_offset_cairo);
3896 cairo_pattern_set_matrix (pattern, &matrix);
3899 cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
3901 method->cr = cairo_create (paint->surface);
3904 cairo_set_source (method->cr, pattern);
3905 cairo_pattern_destroy (pattern);
3908 GdkGCValues gc_values;
3910 gc_values.fill = GDK_TILED;
3911 gc_values.tile = private->bg_pixmap;
3912 gc_values.ts_x_origin = -x_offset_cairo;
3913 gc_values.ts_y_origin = -y_offset_cairo;
3915 gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN;
3917 method->gc = gdk_gc_new_with_values (paint->pixmap, &gc_values, gc_mask);
3922 method->cr = cairo_create (paint->surface);
3924 gdk_cairo_set_source_color (method->cr, &private->bg_color);
3929 gdk_window_clear_backing_region (GdkWindow *window,
3932 GdkWindowObject *private = (GdkWindowObject *)window;
3933 GdkWindowPaint *paint = private->paint_stack->data;
3934 BackingRectMethod method;
3936 GdkRectangle clipbox;
3942 if (GDK_WINDOW_DESTROYED (window))
3946 timer = g_timer_new ();
3951 setup_backing_rect_method (&method, window, paint, 0, 0);
3953 clip = gdk_region_copy (paint->region);
3954 gdk_region_intersect (clip, region);
3955 gdk_region_get_clipbox (clip, &clipbox);
3960 g_assert (method.gc == NULL);
3962 gdk_cairo_region (method.cr, clip);
3963 cairo_fill (method.cr);
3965 cairo_destroy (method.cr);
3967 elapsed = g_timer_elapsed (timer, NULL);
3968 g_print ("Draw the background with Cairo: %fs\n", elapsed);
3973 g_assert (method.gc != NULL);
3975 gdk_gc_set_clip_region (method.gc, clip);
3976 gdk_draw_rectangle (window, method.gc, TRUE,
3977 clipbox.x, clipbox.y,
3978 clipbox.width, clipbox.height);
3979 g_object_unref (method.gc);
3982 elapsed = g_timer_elapsed (timer, NULL);
3983 g_print ("Draw the background with GDK: %fs\n", elapsed);
3987 gdk_region_destroy (clip);
3990 g_timer_destroy (timer);
3995 gdk_window_clear_backing_region_redirect (GdkWindow *window,
3998 GdkWindowObject *private = (GdkWindowObject *)window;
3999 GdkWindowRedirect *redirect = private->redirect;
4000 GdkRegion *clip_region;
4001 GdkRectangle clipbox;
4002 gint x_offset, y_offset;
4003 BackingRectMethod method;
4004 GdkWindowPaint paint;
4006 if (GDK_WINDOW_DESTROYED (window))
4009 clip_region = _gdk_window_calculate_full_clip_region (window,
4010 GDK_WINDOW (redirect->redirected),
4012 &x_offset, &y_offset);
4013 gdk_region_intersect (clip_region, region);
4015 /* offset is from redirected window origin to window origin, convert to
4016 the offset from the redirected pixmap origin to the window origin */
4017 x_offset += redirect->dest_x - redirect->src_x;
4018 y_offset += redirect->dest_y - redirect->src_y;
4020 /* Convert region to pixmap coords */
4021 gdk_region_offset (clip_region, x_offset, y_offset);
4025 paint.pixmap = redirect->pixmap;
4026 paint.surface = _gdk_drawable_ref_cairo_surface (redirect->pixmap);
4030 setup_backing_rect_method (&method, window, &paint, -x_offset, -y_offset);
4034 g_assert (method.gc == NULL);
4036 gdk_cairo_region (method.cr, clip_region);
4037 cairo_fill (method.cr);
4039 cairo_destroy (method.cr);
4043 g_assert (method.gc != NULL);
4045 gdk_region_get_clipbox (clip_region, &clipbox);
4046 gdk_gc_set_clip_region (method.gc, clip_region);
4047 gdk_draw_rectangle (redirect->pixmap, method.gc, TRUE,
4048 clipbox.x, clipbox.y,
4049 clipbox.width, clipbox.height);
4050 g_object_unref (method.gc);
4054 gdk_region_destroy (clip_region);
4055 cairo_surface_destroy (paint.surface);
4059 gdk_window_clear_backing_region_direct (GdkWindow *window,
4062 GdkWindowObject *private = (GdkWindowObject *)window;
4063 BackingRectMethod method;
4064 GdkWindowPaint paint;
4066 GdkRectangle clipbox;
4068 if (GDK_WINDOW_DESTROYED (window))
4073 paint.pixmap = window;
4074 paint.surface = _gdk_drawable_ref_cairo_surface (window);
4078 setup_backing_rect_method (&method, window, &paint, 0, 0);
4080 clip = gdk_region_copy (private->clip_region_with_children);
4081 gdk_region_intersect (clip, region);
4082 gdk_region_get_clipbox (clip, &clipbox);
4086 g_assert (method.gc == NULL);
4088 gdk_cairo_region (method.cr, clip);
4089 cairo_fill (method.cr);
4091 cairo_destroy (method.cr);
4095 g_assert (method.gc != NULL);
4097 gdk_gc_set_clip_region (method.gc, clip);
4098 gdk_draw_rectangle (window, method.gc, TRUE,
4099 clipbox.x, clipbox.y,
4100 clipbox.width, clipbox.height);
4101 g_object_unref (method.gc);
4105 gdk_region_destroy (clip);
4106 cairo_surface_destroy (paint.surface);
4112 * @window: a #GdkWindow
4114 * Clears an entire @window to the background color or background pixmap.
4117 gdk_window_clear (GdkWindow *window)
4121 g_return_if_fail (GDK_IS_WINDOW (window));
4123 gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height);
4125 gdk_window_clear_area (window, 0, 0,
4130 gdk_window_clear_region_internal (GdkWindow *window,
4132 gboolean send_expose)
4134 GdkWindowObject *private = (GdkWindowObject *)window;
4136 if (private->paint_stack)
4137 gdk_window_clear_backing_region (window, region);
4140 if (private->redirect)
4141 gdk_window_clear_backing_region_redirect (window, region);
4143 if (GDK_WINDOW_IMPL_GET_IFACE (private->impl)->clear_region &&
4144 gdk_window_has_impl (private))
4147 copy = gdk_region_copy (region);
4148 gdk_region_intersect (copy, private->clip_region_with_children);
4150 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->clear_region
4151 (window, copy, send_expose);
4153 gdk_region_destroy (copy);
4157 gdk_window_clear_backing_region_direct (window, region);
4159 gdk_window_invalidate_region (window, region, FALSE);
4165 gdk_window_clear_area_internal (GdkWindow *window,
4170 gboolean send_expose)
4172 GdkWindowObject *private = (GdkWindowObject *)window;
4176 g_return_if_fail (GDK_IS_WINDOW (window));
4178 if (GDK_WINDOW_DESTROYED (window))
4181 /* This is what XClearArea does, and e.g. GtkCList uses it,
4182 so we need to duplicate that */
4184 width = private->width - x;
4186 height = private->height - y;
4191 rect.height = height;
4193 region = gdk_region_rectangle (&rect);
4194 gdk_window_clear_region_internal (window,
4197 gdk_region_destroy (region);
4202 * gdk_window_clear_area:
4203 * @window: a #GdkWindow
4204 * @x: x coordinate of rectangle to clear
4205 * @y: y coordinate of rectangle to clear
4206 * @width: width of rectangle to clear
4207 * @height: height of rectangle to clear
4209 * Clears an area of @window to the background color or background pixmap.
4213 gdk_window_clear_area (GdkWindow *window,
4219 gdk_window_clear_area_internal (window,
4226 * gdk_window_clear_area_e:
4227 * @window: a #GdkWindow
4228 * @x: x coordinate of rectangle to clear
4229 * @y: y coordinate of rectangle to clear
4230 * @width: width of rectangle to clear
4231 * @height: height of rectangle to clear
4233 * Like gdk_window_clear_area(), but also generates an expose event for
4236 * This function has a stupid name because it dates back to the mists
4237 * time, pre-GDK-1.0.
4241 gdk_window_clear_area_e (GdkWindow *window,
4247 gdk_window_clear_area_internal (window,
4254 gdk_window_draw_image (GdkDrawable *drawable,
4264 if (GDK_WINDOW_DESTROYED (drawable))
4268 gdk_draw_image (impl, gc, image, xsrc, ysrc,
4269 xdest - x_offset, ydest - y_offset,
4275 gdk_window_draw_pixbuf (GdkDrawable *drawable,
4284 GdkRgbDither dither,
4288 GdkWindowObject *private = (GdkWindowObject *)drawable;
4289 GdkDrawableClass *klass;
4291 if (GDK_WINDOW_DESTROYED (drawable))
4294 /* If no gc => no user clipping, but we need clipping
4295 for window emulation, so use a scratch gc */
4297 gc = _gdk_drawable_get_scratch_gc (drawable, FALSE);
4301 klass = GDK_DRAWABLE_GET_CLASS (impl);
4303 if (private->paint_stack)
4304 klass->draw_pixbuf (impl, gc, pixbuf, src_x, src_y,
4305 dest_x - x_offset, dest_y - y_offset,
4307 dither, x_dither - x_offset, y_dither - y_offset);
4309 klass->draw_pixbuf (impl, gc, pixbuf, src_x, src_y,
4310 dest_x - x_offset, dest_y - y_offset,
4312 dither, x_dither, y_dither);
4317 gdk_window_draw_trapezoids (GdkDrawable *drawable,
4319 GdkTrapezoid *trapezoids,
4322 GdkTrapezoid *new_trapezoids = NULL;
4324 if (GDK_WINDOW_DESTROYED (drawable))
4329 if (x_offset != 0 || y_offset != 0)
4333 new_trapezoids = g_new (GdkTrapezoid, n_trapezoids);
4334 for (i=0; i < n_trapezoids; i++)
4336 new_trapezoids[i].y1 = trapezoids[i].y1 - y_offset;
4337 new_trapezoids[i].x11 = trapezoids[i].x11 - x_offset;
4338 new_trapezoids[i].x21 = trapezoids[i].x21 - x_offset;
4339 new_trapezoids[i].y2 = trapezoids[i].y2 - y_offset;
4340 new_trapezoids[i].x12 = trapezoids[i].x12 - x_offset;
4341 new_trapezoids[i].x22 = trapezoids[i].x22 - x_offset;
4344 trapezoids = new_trapezoids;
4347 gdk_draw_trapezoids (impl, gc, trapezoids, n_trapezoids);
4349 g_free (new_trapezoids);
4355 gdk_window_real_get_size (GdkDrawable *drawable,
4359 GdkWindowObject *private = (GdkWindowObject *)drawable;
4362 *width = private->width;
4364 *height = private->height;
4368 gdk_window_real_get_visual (GdkDrawable *drawable)
4370 GdkColormap *colormap;
4372 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4374 colormap = gdk_drawable_get_colormap (drawable);
4375 return colormap ? gdk_colormap_get_visual (colormap) : NULL;
4379 gdk_window_real_get_depth (GdkDrawable *drawable)
4381 g_return_val_if_fail (GDK_IS_WINDOW (drawable), 0);
4383 return ((GdkWindowObject *)GDK_WINDOW (drawable))->depth;
4387 gdk_window_real_get_screen (GdkDrawable *drawable)
4389 return gdk_drawable_get_screen (GDK_WINDOW_OBJECT (drawable)->impl);
4393 gdk_window_real_set_colormap (GdkDrawable *drawable,
4396 GdkWindowObject *private;
4398 g_return_if_fail (GDK_IS_WINDOW (drawable));
4400 if (GDK_WINDOW_DESTROYED (drawable))
4403 private = (GdkWindowObject *)drawable;
4405 /* different colormap than parent, requires native window */
4406 if (!private->input_only &&
4407 cmap != gdk_drawable_get_colormap ((GdkDrawable *)(private->parent)))
4408 gdk_window_ensure_native ((GdkWindow *)drawable);
4410 gdk_drawable_set_colormap (private->impl, cmap);
4414 gdk_window_real_get_colormap (GdkDrawable *drawable)
4416 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4418 if (GDK_WINDOW_DESTROYED (drawable))
4421 return gdk_drawable_get_colormap (((GdkWindowObject*)drawable)->impl);
4425 gdk_window_copy_to_image (GdkDrawable *drawable,
4434 GdkWindowObject *private = (GdkWindowObject *) drawable;
4435 gint x_offset, y_offset;
4437 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4439 if (GDK_WINDOW_DESTROYED (drawable))
4442 /* If we're here, a composite image was not necessary, so
4443 * we can ignore the paint stack.
4446 /* TODO: Is this right? */
4450 return gdk_drawable_copy_to_image (private->impl,
4459 gdk_window_cairo_surface_destroy (void *data)
4461 GdkWindowObject *private = (GdkWindowObject*) data;
4463 private->cairo_surface = NULL;
4466 static cairo_surface_t *
4467 gdk_window_create_cairo_surface (GdkDrawable *drawable,
4471 return _gdk_windowing_create_cairo_surface (GDK_WINDOW_OBJECT(drawable)->impl,
4476 static cairo_surface_t *
4477 gdk_window_ref_cairo_surface (GdkDrawable *drawable)
4479 GdkWindowObject *private = (GdkWindowObject*) drawable;
4480 cairo_surface_t *surface;
4482 if (private->paint_stack)
4484 GdkWindowPaint *paint = private->paint_stack->data;
4486 surface = paint->surface;
4487 cairo_surface_reference (surface);
4492 /* This will be drawing directly to the window, so flush implicit paint */
4493 gdk_window_flush ((GdkWindow *)drawable);
4495 if (!private->cairo_surface)
4498 GdkDrawable *source;
4500 /* It would be nice if we had some cairo support here so we
4501 could set the clip rect on the cairo surface */
4502 width = private->abs_x + private->width;
4503 height = private->abs_y + private->height;
4505 source = _gdk_drawable_get_source_drawable (drawable);
4507 /* TODO: Avoid the typecheck crap by adding virtual call */
4508 private->cairo_surface = _gdk_drawable_create_cairo_surface (source, width, height);
4510 if (private->cairo_surface)
4512 cairo_surface_set_device_offset (private->cairo_surface,
4516 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
4517 drawable, gdk_window_cairo_surface_destroy);
4521 cairo_surface_reference (private->cairo_surface);
4523 surface = private->cairo_surface;
4530 gdk_window_set_cairo_clip (GdkDrawable *drawable,
4533 GdkWindowObject *private = (GdkWindowObject*) drawable;
4535 if (!private->paint_stack)
4538 cairo_identity_matrix (cr);
4540 cairo_reset_clip (cr);
4542 cairo_new_path (cr);
4543 gdk_cairo_region (cr, private->clip_region_with_children);
4550 GdkWindowPaint *paint = private->paint_stack->data;
4552 /* Only needs to clip to region if piggybacking
4553 on an implicit paint pixmap */
4554 if (paint->uses_implicit)
4557 cairo_identity_matrix (cr);
4559 cairo_reset_clip (cr);
4561 cairo_new_path (cr);
4562 gdk_cairo_region (cr, paint->region);
4570 /* Code for dirty-region queueing
4572 static GSList *update_windows = NULL;
4573 static guint update_idle = 0;
4574 static gboolean debug_updates = FALSE;
4576 static inline gboolean
4577 gdk_window_is_ancestor (GdkWindow *window,
4578 GdkWindow *ancestor)
4582 GdkWindow *parent = (GdkWindow*) ((GdkWindowObject*) window)->parent;
4584 if (parent == ancestor)
4594 gdk_window_add_update_window (GdkWindow *window)
4597 GSList *prev = NULL;
4598 gboolean has_ancestor_in_list = FALSE;
4600 for (tmp = update_windows; tmp; tmp = tmp->next)
4602 GdkWindowObject *parent = GDK_WINDOW_OBJECT (window)->parent;
4604 /* check if tmp is an ancestor of "window"; if it is, set a
4605 * flag indicating that all following windows are either
4606 * children of "window" or from a differen hierarchy
4608 if (!has_ancestor_in_list && gdk_window_is_ancestor (window, tmp->data))
4609 has_ancestor_in_list = TRUE;
4611 /* insert in reverse stacking order when adding around siblings,
4612 * so processing updates properly paints over lower stacked windows
4614 if (parent == GDK_WINDOW_OBJECT (tmp->data)->parent)
4616 gint index = g_list_index (parent->children, window);
4617 for (; tmp && parent == GDK_WINDOW_OBJECT (tmp->data)->parent; tmp = tmp->next)
4619 gint sibling_index = g_list_index (parent->children, tmp->data);
4620 if (index > sibling_index)
4624 /* here, tmp got advanced past all lower stacked siblings */
4625 tmp = g_slist_prepend (tmp, window);
4629 update_windows = tmp;
4633 /* if "window" has an ancestor in the list and tmp is one of
4634 * "window's" children, insert "window" before tmp
4636 if (has_ancestor_in_list && gdk_window_is_ancestor (tmp->data, window))
4638 tmp = g_slist_prepend (tmp, window);
4643 update_windows = tmp;
4647 /* if we're at the end of the list and had an ancestor it it,
4648 * append to the list
4650 if (! tmp->next && has_ancestor_in_list)
4652 tmp = g_slist_append (tmp, window);
4659 /* if all above checks failed ("window" is from a different
4660 * hierarchy than what is already in the list) or the list is
4663 update_windows = g_slist_prepend (update_windows, window);
4667 gdk_window_remove_update_window (GdkWindow *window)
4669 update_windows = g_slist_remove (update_windows, window);
4673 gdk_window_update_idle (gpointer data)
4675 gdk_window_process_all_updates ();
4681 gdk_window_is_toplevel_frozen (GdkWindow *window)
4683 GdkWindowObject *toplevel;
4685 toplevel = (GdkWindowObject *)gdk_window_get_toplevel (window);
4687 return toplevel->update_and_descendants_freeze_count > 0;
4691 gdk_window_schedule_update (GdkWindow *window)
4694 (GDK_WINDOW_OBJECT (window)->update_freeze_count ||
4695 gdk_window_is_toplevel_frozen (window)))
4700 update_idle = gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
4701 gdk_window_update_idle, NULL, NULL);
4706 _gdk_window_process_updates_recurse (GdkWindow *window,
4707 GdkRegion *expose_region)
4709 GdkWindowObject *private = (GdkWindowObject *)window;
4710 GdkWindowObject *child;
4711 GdkRegion *child_region;
4715 if (gdk_region_empty (expose_region))
4718 /* Iterate over children, starting at topmost */
4719 for (l = private->children; l != NULL; l = l->next)
4723 if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
4726 /* Ignore offscreen children, as they don't draw in their parent and
4727 * don't take part in the clipping */
4728 if (gdk_window_is_offscreen (child))
4733 r.width = child->width;
4734 r.height = child->height;
4736 child_region = gdk_region_rectangle (&r);
4739 /* Adjust shape region to parent window coords */
4740 gdk_region_offset (child->shape, child->x, child->y);
4741 gdk_region_intersect (child_region, child->shape);
4742 gdk_region_offset (child->shape, -child->x, -child->y);
4745 if (child->impl == private->impl)
4747 /* Client side child, expose */
4748 gdk_region_intersect (child_region, expose_region);
4749 gdk_region_subtract (expose_region, child_region);
4750 gdk_region_offset (child_region, -child->x, -child->y);
4751 _gdk_window_process_updates_recurse ((GdkWindow *)child, child_region);
4755 /* Native child, just remove area from expose region */
4756 gdk_region_subtract (expose_region, child_region);
4758 gdk_region_destroy (child_region);
4761 if (!gdk_region_empty (expose_region))
4763 if (private->event_mask & GDK_EXPOSURE_MASK)
4767 event.expose.type = GDK_EXPOSE;
4768 event.expose.window = g_object_ref (window);
4769 event.expose.send_event = FALSE;
4770 event.expose.count = 0;
4771 event.expose.region = expose_region;
4772 gdk_region_get_clipbox (expose_region, &event.expose.area);
4774 (*_gdk_event_func) (&event, _gdk_event_data);
4776 g_object_unref (window);
4778 else if (private->bg_pixmap != GDK_NO_BG)
4780 /* No exposure mask set, so nothing will be drawn, the
4781 * app relies on the background being what it specified
4782 * for the window. So, we need to clear this manually.
4784 * We use begin/end_paint around the clear so that we can
4785 * piggyback on the implicit paint */
4787 gdk_window_begin_paint_region (window, expose_region);
4788 gdk_window_clear_region_internal (window, expose_region, FALSE);
4789 gdk_window_end_paint (window);
4795 gdk_window_process_updates_internal (GdkWindow *window)
4797 GdkWindowObject *private = (GdkWindowObject *)window;
4798 gboolean save_region = FALSE;
4799 GdkRectangle clip_box;
4801 /* If an update got queued during update processing, we can get a
4802 * window in the update queue that has an empty update_area.
4805 if (private->update_area)
4807 GdkRegion *update_area = private->update_area;
4808 private->update_area = NULL;
4810 if (_gdk_event_func && gdk_window_is_viewable (window) &&
4811 private->window_type != GDK_WINDOW_FOREIGN)
4813 GdkRectangle window_rect;
4814 GdkRegion *expose_region;
4815 GdkRegion *window_region;
4816 gboolean end_implicit;
4818 /* Clip to part visible in toplevel */
4819 gdk_region_intersect (update_area, private->clip_region);
4823 /* Make sure we see the red invalid area before redrawing. */
4824 gdk_display_sync (gdk_drawable_get_display (window));
4828 save_region = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->queue_antiexpose (window, update_area);
4830 expose_region = gdk_region_copy (update_area);
4832 expose_region = update_area;
4836 window_rect.width = private->width;
4837 window_rect.height = private->height;
4839 window_region = gdk_region_rectangle (&window_rect);
4840 gdk_region_intersect (expose_region,
4842 gdk_region_destroy (window_region);
4845 /* No need to do any moves that will end up over the update area */
4846 if (private->outstanding_moves)
4848 GdkWindowRegionMove *move;
4852 remove = gdk_region_copy (update_area);
4853 for (l = g_list_last (private->outstanding_moves); l != NULL; l = prev)
4857 /* Don't need this area */
4858 gdk_region_subtract (move->dest_region, remove);
4860 /* However if any of the destination we do need has a source
4861 in the updated region we do need that as a destination for
4862 the earlier moves */
4863 gdk_region_offset (move->dest_region, -move->dx, -move->dy);
4864 gdk_region_subtract (remove, move->dest_region);
4866 if (gdk_region_empty (move->dest_region))
4868 gdk_window_region_move_free (move);
4869 private->outstanding_moves =
4870 g_list_delete_link (private->outstanding_moves, l);
4873 gdk_region_offset (move->dest_region, move->dx, move->dy);
4875 gdk_region_destroy (remove);
4878 gdk_region_get_clipbox (expose_region, &clip_box);
4879 end_implicit = gdk_window_begin_implicit_paint (window, &clip_box);
4880 if (end_implicit) /* rendering is not double buffered, do moves now */
4881 gdk_window_flush_outstanding_moves (window);
4882 _gdk_windowing_window_process_updates_recurse (window, expose_region);
4885 /* Do moves right before exposes are rendered */
4886 gdk_window_flush_outstanding_moves (window);
4887 gdk_window_end_implicit_paint (window);
4890 if (expose_region != update_area)
4891 gdk_region_destroy (expose_region);
4894 gdk_region_destroy (update_area);
4897 if (private->outstanding_moves)
4899 /* Flush any outstanding moves, may happen if we moved a window but got
4900 no actual invalid area */
4901 gdk_window_flush_outstanding_moves (window);
4906 flush_all_displays (void)
4908 GSList *displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
4911 for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
4912 gdk_display_flush (tmp_list->data);
4914 g_slist_free (displays);
4917 /* Currently it is not possible to override
4918 * gdk_window_process_all_updates in the same manner as
4919 * gdk_window_process_updates and gdk_window_invalidate_maybe_recurse
4920 * by implementing the GdkPaintable interface. If in the future a
4921 * backend would need this, the right solution would be to add a
4922 * method to GdkDisplay that can be optionally
4923 * NULL. gdk_window_process_all_updates can then walk the list of open
4924 * displays and call the mehod.
4928 * gdk_window_process_all_updates:
4930 * Calls gdk_window_process_updates() for all windows (see #GdkWindow)
4931 * in the application.
4935 gdk_window_process_all_updates (void)
4937 GSList *old_update_windows = update_windows;
4938 GSList *tmp_list = update_windows;
4939 static gboolean in_process_all_updates = FALSE;
4941 if (in_process_all_updates)
4944 in_process_all_updates = TRUE;
4947 g_source_remove (update_idle);
4949 update_windows = NULL;
4952 _gdk_windowing_before_process_all_updates ();
4954 g_slist_foreach (old_update_windows, (GFunc)g_object_ref, NULL);
4958 GdkWindowObject *private = (GdkWindowObject *)tmp_list->data;
4960 if (!GDK_WINDOW_DESTROYED (tmp_list->data))
4962 if (private->update_freeze_count ||
4963 gdk_window_is_toplevel_frozen (tmp_list->data))
4964 gdk_window_add_update_window ((GdkWindow *) private);
4966 gdk_window_process_updates_internal (tmp_list->data);
4969 g_object_unref (tmp_list->data);
4970 tmp_list = tmp_list->next;
4973 g_slist_free (old_update_windows);
4975 flush_all_displays ();
4977 _gdk_windowing_after_process_all_updates ();
4979 in_process_all_updates = FALSE;
4983 * gdk_window_process_updates:
4984 * @window: a #GdkWindow
4985 * @update_children: whether to also process updates for child windows
4987 * Sends one or more expose events to @window. The areas in each
4988 * expose event will cover the entire update area for the window (see
4989 * gdk_window_invalidate_region() for details). Normally GDK calls
4990 * gdk_window_process_all_updates() on your behalf, so there's no
4991 * need to call this function unless you want to force expose events
4992 * to be delivered immediately and synchronously (vs. the usual
4993 * case, where GDK delivers them in an idle handler). Occasionally
4994 * this is useful to produce nicer scrolling behavior, for example.
4998 gdk_window_process_updates (GdkWindow *window,
4999 gboolean update_children)
5001 GdkWindowObject *private = (GdkWindowObject *)window;
5002 GdkWindowObject *impl_window;
5004 g_return_if_fail (GDK_IS_WINDOW (window));
5006 impl_window = gdk_window_get_impl_window (private);
5007 if ((impl_window->update_area ||
5008 impl_window->outstanding_moves) &&
5009 !impl_window->update_freeze_count &&
5010 !gdk_window_is_toplevel_frozen (window))
5012 gdk_window_process_updates_internal ((GdkWindow *)impl_window);
5013 gdk_window_remove_update_window ((GdkWindow *)impl_window);
5016 if (update_children)
5018 /* process updates in reverse stacking order so composition or
5019 * painting over achieves the desired effect for offscreen windows
5022 for (node = g_list_last (private->children); node; node = node->prev)
5023 gdk_window_process_updates (node->data, TRUE);
5028 * gdk_window_invalidate_rect:
5029 * @window: a #GdkWindow
5030 * @rect: rectangle to invalidate or %NULL to invalidate the whole
5032 * @invalidate_children: whether to also invalidate child windows
5034 * A convenience wrapper around gdk_window_invalidate_region() which
5035 * invalidates a rectangular region. See
5036 * gdk_window_invalidate_region() for details.
5039 gdk_window_invalidate_rect (GdkWindow *window,
5040 const GdkRectangle *rect,
5041 gboolean invalidate_children)
5043 GdkRectangle window_rect;
5045 GdkWindowObject *private = (GdkWindowObject *)window;
5047 g_return_if_fail (GDK_IS_WINDOW (window));
5049 if (GDK_WINDOW_DESTROYED (window))
5052 if (private->input_only || !private->viewable)
5059 gdk_drawable_get_size (GDK_DRAWABLE (window),
5061 &window_rect.height);
5062 rect = &window_rect;
5065 region = gdk_region_rectangle (rect);
5066 gdk_window_invalidate_region (window, region, invalidate_children);
5067 gdk_region_destroy (region);
5071 draw_ugly_color (GdkWindow *window,
5072 const GdkRegion *region)
5074 /* Draw ugly color all over the newly-invalid region */
5075 GdkColor ugly_color = { 0, 50000, 10000, 10000 };
5077 GdkRectangle clipbox;
5079 ugly_gc = gdk_gc_new (window);
5080 gdk_gc_set_rgb_fg_color (ugly_gc, &ugly_color);
5081 gdk_gc_set_clip_region (ugly_gc, region);
5083 gdk_region_get_clipbox (region, &clipbox);
5085 gdk_draw_rectangle (window,
5088 clipbox.x, clipbox.y,
5089 clipbox.width, clipbox.height);
5091 g_object_unref (ugly_gc);
5095 * gdk_window_invalidate_maybe_recurse:
5096 * @window: a #GdkWindow
5097 * @region: a #GdkRegion
5098 * @child_func: function to use to decide if to recurse to a child,
5099 * %NULL means never recurse.
5100 * @user_data: data passed to @child_func
5102 * Adds @region to the update area for @window. The update area is the
5103 * region that needs to be redrawn, or "dirty region." The call
5104 * gdk_window_process_updates() sends one or more expose events to the
5105 * window, which together cover the entire update area. An
5106 * application would normally redraw the contents of @window in
5107 * response to those expose events.
5109 * GDK will call gdk_window_process_all_updates() on your behalf
5110 * whenever your program returns to the main loop and becomes idle, so
5111 * normally there's no need to do that manually, you just need to
5112 * invalidate regions that you know should be redrawn.
5114 * The @child_func parameter controls whether the region of
5115 * each child window that intersects @region will also be invalidated.
5116 * Only children for which @child_func returns TRUE will have the area
5120 gdk_window_invalidate_maybe_recurse (GdkWindow *window,
5121 const GdkRegion *region,
5122 gboolean (*child_func) (GdkWindow *,
5126 GdkWindowObject *private = (GdkWindowObject *)window;
5127 GdkWindowObject *impl_window;
5128 GdkRegion *visible_region;
5131 g_return_if_fail (GDK_IS_WINDOW (window));
5133 if (GDK_WINDOW_DESTROYED (window))
5136 if (private->input_only ||
5137 !private->viewable ||
5138 gdk_region_empty (region) ||
5139 private->window_type == GDK_WINDOW_ROOT)
5142 visible_region = gdk_drawable_get_visible_region (window);
5143 gdk_region_intersect (visible_region, region);
5145 tmp_list = private->children;
5148 GdkWindowObject *child = tmp_list->data;
5150 if (!child->input_only)
5152 GdkRegion *child_region;
5153 GdkRectangle child_rect;
5155 child_rect.x = child->x;
5156 child_rect.y = child->y;
5157 child_rect.width = child->width;
5158 child_rect.height = child->height;
5159 child_region = gdk_region_rectangle (&child_rect);
5161 /* remove child area from the invalid area of the parent */
5162 if (GDK_WINDOW_IS_MAPPED (child) && !child->shaped &&
5163 !child->composited &&
5164 !gdk_window_is_offscreen (child))
5165 gdk_region_subtract (visible_region, child_region);
5167 if (child_func && (*child_func) ((GdkWindow *)child, user_data))
5169 GdkRegion *tmp = gdk_region_copy (region);
5171 gdk_region_offset (tmp, - child_rect.x, - child_rect.y);
5172 gdk_region_offset (child_region, - child_rect.x, - child_rect.y);
5173 gdk_region_intersect (child_region, tmp);
5175 gdk_window_invalidate_maybe_recurse ((GdkWindow *)child,
5176 child_region, child_func, user_data);
5178 gdk_region_destroy (tmp);
5181 gdk_region_destroy (child_region);
5184 tmp_list = tmp_list->next;
5187 impl_window = gdk_window_get_impl_window (private);
5189 if (!gdk_region_empty (visible_region) ||
5190 /* Even if we're not exposing anything, make sure we process
5191 idles for windows with outstanding moves */
5192 (impl_window->outstanding_moves != NULL &&
5193 impl_window->update_area == NULL))
5196 draw_ugly_color (window, region);
5198 /* Convert to impl coords */
5199 gdk_region_offset (visible_region, private->abs_x, private->abs_y);
5200 if (impl_window->update_area)
5202 gdk_region_union (impl_window->update_area, visible_region);
5206 gdk_window_add_update_window ((GdkWindow *)impl_window);
5207 impl_window->update_area = gdk_region_copy (visible_region);
5209 gdk_window_schedule_update ((GdkWindow *)impl_window);
5213 gdk_region_destroy (visible_region);
5217 true_predicate (GdkWindow *window,
5224 * gdk_window_invalidate_region:
5225 * @window: a #GdkWindow
5226 * @region: a #GdkRegion
5227 * @invalidate_children: %TRUE to also invalidate child windows
5229 * Adds @region to the update area for @window. The update area is the
5230 * region that needs to be redrawn, or "dirty region." The call
5231 * gdk_window_process_updates() sends one or more expose events to the
5232 * window, which together cover the entire update area. An
5233 * application would normally redraw the contents of @window in
5234 * response to those expose events.
5236 * GDK will call gdk_window_process_all_updates() on your behalf
5237 * whenever your program returns to the main loop and becomes idle, so
5238 * normally there's no need to do that manually, you just need to
5239 * invalidate regions that you know should be redrawn.
5241 * The @invalidate_children parameter controls whether the region of
5242 * each child window that intersects @region will also be invalidated.
5243 * If %FALSE, then the update area for child windows will remain
5244 * unaffected. See gdk_window_invalidate_maybe_recurse if you need
5245 * fine grained control over which children are invalidated.
5248 gdk_window_invalidate_region (GdkWindow *window,
5249 const GdkRegion *region,
5250 gboolean invalidate_children)
5252 gdk_window_invalidate_maybe_recurse (window, region,
5253 invalidate_children ?
5254 true_predicate : (gboolean (*) (GdkWindow *, gpointer))NULL,
5259 * _gdk_window_invalidate_for_expose:
5260 * @window: a #GdkWindow
5261 * @region: a #GdkRegion
5263 * Adds @region to the update area for @window. The update area is the
5264 * region that needs to be redrawn, or "dirty region." The call
5265 * gdk_window_process_updates() sends one or more expose events to the
5266 * window, which together cover the entire update area. An
5267 * application would normally redraw the contents of @window in
5268 * response to those expose events.
5270 * GDK will call gdk_window_process_all_updates() on your behalf
5271 * whenever your program returns to the main loop and becomes idle, so
5272 * normally there's no need to do that manually, you just need to
5273 * invalidate regions that you know should be redrawn.
5275 * This version of invalidation is used when you recieve expose events
5276 * from the native window system. It exposes the native window, plus
5277 * any non-native child windows (but not native child windows, as those would
5278 * have gotten their own expose events).
5281 _gdk_window_invalidate_for_expose (GdkWindow *window,
5282 const GdkRegion *region)
5284 gdk_window_invalidate_maybe_recurse (window, region,
5285 (gboolean (*) (GdkWindow *, gpointer))gdk_window_has_no_impl,
5291 * gdk_window_get_update_area:
5292 * @window: a #GdkWindow
5294 * Transfers ownership of the update area from @window to the caller
5295 * of the function. That is, after calling this function, @window will
5296 * no longer have an invalid/dirty region; the update area is removed
5297 * from @window and handed to you. If a window has no update area,
5298 * gdk_window_get_update_area() returns %NULL. You are responsible for
5299 * calling gdk_region_destroy() on the returned region if it's non-%NULL.
5301 * Return value: the update area for @window
5304 gdk_window_get_update_area (GdkWindow *window)
5306 GdkWindowObject *private = (GdkWindowObject *)window;
5307 GdkWindowObject *impl_window;
5308 GdkRegion *tmp_region;
5310 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
5312 impl_window = gdk_window_get_impl_window (private);
5314 if (impl_window->update_area)
5316 tmp_region = gdk_region_copy (private->clip_region_with_children);
5317 /* Convert to impl coords */
5318 gdk_region_offset (tmp_region, private->abs_x, private->abs_y);
5319 gdk_region_intersect (tmp_region, impl_window->update_area);
5321 if (gdk_region_empty (tmp_region))
5323 gdk_region_destroy (tmp_region);
5328 gdk_region_subtract (impl_window->update_area, tmp_region);
5330 if (gdk_region_empty (impl_window->update_area) &&
5331 impl_window->outstanding_moves == NULL)
5333 gdk_region_destroy (impl_window->update_area);
5334 impl_window->update_area = NULL;
5336 gdk_window_remove_update_window ((GdkWindow *)impl_window);
5339 /* Convert from impl coords */
5340 gdk_region_offset (tmp_region, -private->abs_x, -private->abs_y);
5350 * _gdk_window_clear_update_area:
5351 * @window: a #GdkWindow.
5353 * Internal function to clear the update area for a window. This
5354 * is called when the window is hidden or destroyed.
5357 _gdk_window_clear_update_area (GdkWindow *window)
5359 GdkWindowObject *private = (GdkWindowObject *)window;
5361 g_return_if_fail (GDK_IS_WINDOW (window));
5363 if (private->update_area)
5365 gdk_window_remove_update_window (window);
5367 gdk_region_destroy (private->update_area);
5368 private->update_area = NULL;
5373 * gdk_window_freeze_updates:
5374 * @window: a #GdkWindow
5376 * Temporarily freezes a window such that it won't receive expose
5377 * events. The window will begin receiving expose events again when
5378 * gdk_window_thaw_updates() is called. If gdk_window_freeze_updates()
5379 * has been called more than once, gdk_window_thaw_updates() must be called
5380 * an equal number of times to begin processing exposes.
5383 gdk_window_freeze_updates (GdkWindow *window)
5385 GdkWindowObject *private = (GdkWindowObject *)window;
5386 GdkWindowObject *impl_window;
5388 g_return_if_fail (GDK_IS_WINDOW (window));
5390 impl_window = gdk_window_get_impl_window (private);
5391 impl_window->update_freeze_count++;
5395 * gdk_window_thaw_updates:
5396 * @window: a #GdkWindow
5398 * Thaws a window frozen with gdk_window_freeze_updates().
5401 gdk_window_thaw_updates (GdkWindow *window)
5403 GdkWindowObject *private = (GdkWindowObject *)window;
5404 GdkWindowObject *impl_window;
5406 g_return_if_fail (GDK_IS_WINDOW (window));
5408 impl_window = gdk_window_get_impl_window (private);
5410 g_return_if_fail (impl_window->update_freeze_count > 0);
5412 if (--impl_window->update_freeze_count == 0)
5413 gdk_window_schedule_update (GDK_WINDOW (impl_window));
5417 * gdk_window_freeze_toplevel_updates_libgtk_only:
5418 * @window: a #GdkWindow
5420 * Temporarily freezes a window and all its descendants such that it won't
5421 * receive expose events. The window will begin receiving expose events
5422 * again when gdk_window_thaw_toplevel_updates_libgtk_only() is called. If
5423 * gdk_window_freeze_toplevel_updates_libgtk_only()
5424 * has been called more than once,
5425 * gdk_window_thaw_toplevel_updates_libgtk_only() must be called
5426 * an equal number of times to begin processing exposes.
5428 * This function is not part of the GDK public API and is only
5432 gdk_window_freeze_toplevel_updates_libgtk_only (GdkWindow *window)
5434 GdkWindowObject *private = (GdkWindowObject *)window;
5436 g_return_if_fail (GDK_IS_WINDOW (window));
5437 g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
5439 private->update_and_descendants_freeze_count++;
5443 * gdk_window_thaw_toplevel_updates_libgtk_only:
5444 * @window: a #GdkWindow
5446 * Thaws a window frozen with
5447 * gdk_window_freeze_toplevel_updates_libgtk_only().
5449 * This function is not part of the GDK public API and is only
5453 gdk_window_thaw_toplevel_updates_libgtk_only (GdkWindow *window)
5455 GdkWindowObject *private = (GdkWindowObject *)window;
5457 g_return_if_fail (GDK_IS_WINDOW (window));
5458 g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
5459 g_return_if_fail (private->update_and_descendants_freeze_count > 0);
5461 private->update_and_descendants_freeze_count--;
5463 gdk_window_schedule_update (window);
5467 * gdk_window_set_debug_updates:
5468 * @setting: %TRUE to turn on update debugging
5470 * With update debugging enabled, calls to
5471 * gdk_window_invalidate_region() clear the invalidated region of the
5472 * screen to a noticeable color, and GDK pauses for a short time
5473 * before sending exposes to windows during
5474 * gdk_window_process_updates(). The net effect is that you can see
5475 * the invalid region for each window and watch redraws as they
5476 * occur. This allows you to diagnose inefficiencies in your application.
5478 * In essence, because the GDK rendering model prevents all flicker,
5479 * if you are redrawing the same region 400 times you may never
5480 * notice, aside from noticing a speed problem. Enabling update
5481 * debugging causes GTK to flicker slowly and noticeably, so you can
5482 * see exactly what's being redrawn when, in what order.
5484 * The --gtk-debug=updates command line option passed to GTK+ programs
5485 * enables this debug option at application startup time. That's
5486 * usually more useful than calling gdk_window_set_debug_updates()
5487 * yourself, though you might want to use this function to enable
5488 * updates sometime after application startup time.
5492 gdk_window_set_debug_updates (gboolean setting)
5494 debug_updates = setting;
5498 * gdk_window_constrain_size:
5499 * @geometry: a #GdkGeometry structure
5500 * @flags: a mask indicating what portions of @geometry are set
5501 * @width: desired width of window
5502 * @height: desired height of the window
5503 * @new_width: location to store resulting width
5504 * @new_height: location to store resulting height
5506 * Constrains a desired width and height according to a
5507 * set of geometry hints (such as minimum and maximum size).
5510 gdk_window_constrain_size (GdkGeometry *geometry,
5517 /* This routine is partially borrowed from fvwm.
5519 * Copyright 1993, Robert Nation
5520 * You may use this code for any purpose, as long as the original
5521 * copyright remains in the source code and all documentation
5523 * which in turn borrows parts of the algorithm from uwm
5526 gint min_height = 0;
5527 gint base_width = 0;
5528 gint base_height = 0;
5531 gint max_width = G_MAXINT;
5532 gint max_height = G_MAXINT;
5534 #define FLOOR(value, base) ( ((gint) ((value) / (base))) * (base) )
5536 if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
5538 base_width = geometry->base_width;
5539 base_height = geometry->base_height;
5540 min_width = geometry->min_width;
5541 min_height = geometry->min_height;
5543 else if (flags & GDK_HINT_BASE_SIZE)
5545 base_width = geometry->base_width;
5546 base_height = geometry->base_height;
5547 min_width = geometry->base_width;
5548 min_height = geometry->base_height;
5550 else if (flags & GDK_HINT_MIN_SIZE)
5552 base_width = geometry->min_width;
5553 base_height = geometry->min_height;
5554 min_width = geometry->min_width;
5555 min_height = geometry->min_height;
5558 if (flags & GDK_HINT_MAX_SIZE)
5560 max_width = geometry->max_width ;
5561 max_height = geometry->max_height;
5564 if (flags & GDK_HINT_RESIZE_INC)
5566 xinc = MAX (xinc, geometry->width_inc);
5567 yinc = MAX (yinc, geometry->height_inc);
5570 /* clamp width and height to min and max values
5572 width = CLAMP (width, min_width, max_width);
5573 height = CLAMP (height, min_height, max_height);
5575 /* shrink to base + N * inc
5577 width = base_width + FLOOR (width - base_width, xinc);
5578 height = base_height + FLOOR (height - base_height, yinc);
5580 /* constrain aspect ratio, according to:
5583 * min_aspect <= -------- <= max_aspect
5587 if (flags & GDK_HINT_ASPECT &&
5588 geometry->min_aspect > 0 &&
5589 geometry->max_aspect > 0)
5593 if (geometry->min_aspect * height > width)
5595 delta = FLOOR (height - width / geometry->min_aspect, yinc);
5596 if (height - delta >= min_height)
5600 delta = FLOOR (height * geometry->min_aspect - width, xinc);
5601 if (width + delta <= max_width)
5606 if (geometry->max_aspect * height < width)
5608 delta = FLOOR (width - height * geometry->max_aspect, xinc);
5609 if (width - delta >= min_width)
5613 delta = FLOOR (width / geometry->max_aspect - height, yinc);
5614 if (height + delta <= max_height)
5623 *new_height = height;
5627 * gdk_window_get_pointer:
5628 * @window: a #GdkWindow
5629 * @x: return location for X coordinate of pointer or %NULL to not
5630 * return the X coordinate
5631 * @y: return location for Y coordinate of pointer or %NULL to not
5632 * return the Y coordinate
5633 * @mask: return location for modifier mask or %NULL to not return the
5636 * Obtains the current pointer position and modifier state.
5637 * The position is given in coordinates relative to the upper left
5638 * corner of @window.
5640 * Return value: the window containing the pointer (as with
5641 * gdk_window_at_pointer()), or %NULL if the window containing the
5642 * pointer isn't known to GDK
5645 gdk_window_get_pointer (GdkWindow *window,
5648 GdkModifierType *mask)
5650 GdkDisplay *display;
5652 GdkModifierType tmp_mask;
5655 g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
5659 display = gdk_drawable_get_display (window);
5663 GdkScreen *screen = gdk_screen_get_default ();
5665 display = gdk_screen_get_display (screen);
5666 window = gdk_screen_get_root_window (screen);
5668 GDK_NOTE (MULTIHEAD,
5669 g_message ("Passing NULL for window to gdk_window_get_pointer()\n"
5670 "is not multihead safe"));
5673 child = display->pointer_hooks->window_get_pointer (display, window, &tmp_x, &tmp_y, &tmp_mask);
5682 _gdk_display_enable_motion_hints (display);
5688 * gdk_window_at_pointer:
5689 * @win_x: return location for origin of the window under the pointer
5690 * @win_y: return location for origin of the window under the pointer
5692 * Obtains the window underneath the mouse pointer, returning the
5693 * location of that window in @win_x, @win_y. Returns %NULL if the
5694 * window under the mouse pointer is not known to GDK (if the window
5695 * belongs to another application and a #GdkWindow hasn't been created
5696 * for it with gdk_window_foreign_new())
5698 * NOTE: For multihead-aware widgets or applications use
5699 * gdk_display_get_window_at_pointer() instead.
5701 * Return value: window under the mouse pointer
5704 gdk_window_at_pointer (gint *win_x,
5707 return gdk_display_get_window_at_pointer (gdk_display_get_default (), win_x, win_y);
5711 * gdk_get_default_root_window:
5713 * Obtains the root window (parent all other windows are inside)
5714 * for the default display and screen.
5716 * Return value: the default root window
5719 gdk_get_default_root_window (void)
5721 return gdk_screen_get_root_window (gdk_screen_get_default ());
5725 * gdk_window_foreign_new:
5726 * @anid: a native window handle.
5728 * Wraps a native window for the default display in a #GdkWindow.
5729 * This may fail if the window has been destroyed.
5731 * For example in the X backend, a native window handle is an Xlib
5734 * Return value: the newly-created #GdkWindow wrapper for the
5735 * native window or %NULL if the window has been destroyed.
5738 gdk_window_foreign_new (GdkNativeWindow anid)
5740 return gdk_window_foreign_new_for_display (gdk_display_get_default (), anid);
5744 get_all_native_children (GdkWindowObject *private,
5747 GdkWindowObject *child;
5750 for (l = private->children; l != NULL; l = l->next)
5754 if (gdk_window_has_impl (child))
5755 *native = g_list_prepend (*native, child);
5757 get_all_native_children (child, native);
5763 gdk_window_raise_internal (GdkWindow *window)
5765 GdkWindowObject *private = (GdkWindowObject *)window;
5766 GdkWindowObject *parent = private->parent;
5767 GdkWindowObject *above;
5768 GList *native_children;
5773 parent->children = g_list_remove (parent->children, window);
5774 parent->children = g_list_prepend (parent->children, window);
5777 /* Just do native raise for toplevels */
5778 if (private->parent == NULL ||
5779 private->parent->window_type == GDK_WINDOW_ROOT)
5781 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
5783 else if (gdk_window_has_impl (private))
5785 above = find_native_sibling_above (parent, private);
5788 listhead.data = window;
5789 listhead.next = NULL;
5790 listhead.prev = NULL;
5791 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
5795 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
5799 native_children = NULL;
5800 get_all_native_children (private, &native_children);
5801 if (native_children != NULL)
5803 above = find_native_sibling_above (parent, private);
5806 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
5810 /* Right order, since native_children is bottom-topmost first */
5811 for (l = native_children; l != NULL; l = l->next)
5812 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (l->data);
5815 g_list_free (native_children);
5821 /* Showing a non-native parent may cause children to become visible,
5822 we need to handle this by manually showing them then. To simplify
5823 things we hide them all when they are not visible. */
5825 show_all_visible_impls (GdkWindowObject *private, gboolean already_mapped)
5827 GdkWindowObject *child;
5830 for (l = private->children; l != NULL; l = l->next)
5834 /* For foreign windows, only show if if was
5835 explicitly hidden, otherwise we might cause
5836 suprising things to happen to the other client. */
5837 if (GDK_WINDOW_IS_MAPPED (child) &&
5838 child->window_type != GDK_WINDOW_FOREIGN)
5839 show_all_visible_impls (child, FALSE);
5842 if (gdk_window_has_impl (private))
5843 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show ((GdkWindow *)private, already_mapped);
5847 set_viewable (GdkWindowObject *w,
5850 GdkWindowObject *child;
5856 recompute_visible_regions (w, FALSE, FALSE);
5858 for (l = w->children; l != NULL; l = l->next)
5862 if (GDK_WINDOW_IS_MAPPED (child) &&
5863 child->window_type != GDK_WINDOW_FOREIGN)
5864 set_viewable (child, val);
5869 _gdk_window_update_viewable (GdkWindow *window)
5871 GdkWindowObject *priv = (GdkWindowObject *)window;
5874 if (priv->window_type == GDK_WINDOW_FOREIGN ||
5875 priv->window_type == GDK_WINDOW_ROOT)
5877 else if (priv->parent == NULL ||
5878 priv->parent->window_type == GDK_WINDOW_ROOT ||
5879 priv->parent->viewable)
5880 viewable = GDK_WINDOW_IS_MAPPED (priv);
5884 if (priv->viewable != viewable)
5885 set_viewable (priv, viewable);
5889 gdk_window_show_internal (GdkWindow *window, gboolean raise)
5891 GdkWindowObject *private;
5892 gboolean was_mapped;
5894 g_return_if_fail (GDK_IS_WINDOW (window));
5896 private = (GdkWindowObject *) window;
5897 if (private->destroyed)
5900 was_mapped = GDK_WINDOW_IS_MAPPED (window);
5903 /* Keep children in (reverse) stacking order */
5904 gdk_window_raise_internal (window);
5906 if (gdk_window_has_impl (private))
5909 gdk_synthesize_window_state (window,
5910 GDK_WINDOW_STATE_WITHDRAWN,
5918 _gdk_window_update_viewable (window);
5920 if (gdk_window_is_viewable (window))
5921 show_all_visible_impls (private, was_mapped);
5923 if (!was_mapped && !gdk_window_has_impl (private))
5925 if (private->event_mask & GDK_STRUCTURE_MASK)
5926 _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
5928 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
5929 _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
5932 if (!was_mapped || raise)
5934 recompute_visible_regions (private, TRUE, FALSE);
5936 /* If any decendants became visible we need to send visibility notify */
5937 gdk_window_update_visibility_recursively (private, NULL);
5939 if (gdk_window_is_viewable (window))
5941 _gdk_synthesize_crossing_events_for_geometry_change (window);
5942 gdk_window_invalidate_rect (window, NULL, TRUE);
5948 * gdk_window_show_unraised:
5949 * @window: a #GdkWindow
5951 * Shows a #GdkWindow onscreen, but does not modify its stacking
5952 * order. In contrast, gdk_window_show() will raise the window
5953 * to the top of the window stack.
5955 * On the X11 platform, in Xlib terms, this function calls
5956 * XMapWindow() (it also updates some internal GDK state, which means
5957 * that you can't really use XMapWindow() directly on a GDK window).
5960 gdk_window_show_unraised (GdkWindow *window)
5962 gdk_window_show_internal (window, FALSE);
5967 * @window: a #GdkWindow
5969 * Raises @window to the top of the Z-order (stacking order), so that
5970 * other windows with the same parent window appear below @window.
5971 * This is true whether or not the windows are visible.
5973 * If @window is a toplevel, the window manager may choose to deny the
5974 * request to move the window in the Z-order, gdk_window_raise() only
5975 * requests the restack, does not guarantee it.
5978 gdk_window_raise (GdkWindow *window)
5980 GdkWindowObject *private;
5982 g_return_if_fail (GDK_IS_WINDOW (window));
5984 private = (GdkWindowObject *) window;
5985 if (private->destroyed)
5988 /* Keep children in (reverse) stacking order */
5989 gdk_window_raise_internal (window);
5991 recompute_visible_regions (private, TRUE, FALSE);
5993 gdk_window_invalidate_rect (window, NULL, TRUE);
5997 gdk_window_lower_internal (GdkWindow *window)
5999 GdkWindowObject *private = (GdkWindowObject *)window;
6000 GdkWindowObject *parent = private->parent;
6001 GdkWindowObject *above;
6002 GList *native_children;
6007 parent->children = g_list_remove (parent->children, window);
6008 parent->children = g_list_append (parent->children, window);
6011 /* Just do native lower for toplevels */
6012 if (private->parent == NULL ||
6013 private->parent->window_type == GDK_WINDOW_ROOT)
6015 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->lower (window);
6017 else if (gdk_window_has_impl (private))
6019 above = find_native_sibling_above (parent, private);
6022 listhead.data = window;
6023 listhead.next = NULL;
6024 listhead.prev = NULL;
6025 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
6029 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
6033 native_children = NULL;
6034 get_all_native_children (private, &native_children);
6035 if (native_children != NULL)
6037 above = find_native_sibling_above (parent, private);
6040 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
6044 /* Right order, since native_children is bottom-topmost first */
6045 for (l = native_children; l != NULL; l = l->next)
6046 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (l->data);
6049 g_list_free (native_children);
6056 gdk_window_invalidate_in_parent (GdkWindowObject *private)
6058 GdkRectangle r, child;
6060 if (private->parent == NULL ||
6061 private->parent->window_type == GDK_WINDOW_ROOT)
6064 /* get the visible rectangle of the parent */
6066 r.width = private->parent->width;
6067 r.height = private->parent->height;
6069 child.x = private->x;
6070 child.y = private->y;
6071 child.width = private->width;
6072 child.height = private->height;
6073 gdk_rectangle_intersect (&r, &child, &r);
6075 gdk_window_invalidate_rect (GDK_WINDOW (private->parent), &r, TRUE);
6081 * @window: a #GdkWindow
6083 * Lowers @window to the bottom of the Z-order (stacking order), so that
6084 * other windows with the same parent window appear above @window.
6085 * This is true whether or not the other windows are visible.
6087 * If @window is a toplevel, the window manager may choose to deny the
6088 * request to move the window in the Z-order, gdk_window_lower() only
6089 * requests the restack, does not guarantee it.
6091 * Note that gdk_window_show() raises the window again, so don't call this
6092 * function before gdk_window_show(). (Try gdk_window_show_unraised().)
6095 gdk_window_lower (GdkWindow *window)
6097 GdkWindowObject *private;
6099 g_return_if_fail (GDK_IS_WINDOW (window));
6101 private = (GdkWindowObject *) window;
6102 if (private->destroyed)
6105 /* Keep children in (reverse) stacking order */
6106 gdk_window_lower_internal (window);
6108 recompute_visible_regions (private, TRUE, FALSE);
6110 _gdk_synthesize_crossing_events_for_geometry_change (window);
6111 gdk_window_invalidate_in_parent (private);
6116 * @window: a #GdkWindow
6118 * Like gdk_window_show_unraised(), but also raises the window to the
6119 * top of the window stack (moves the window to the front of the
6122 * This function maps a window so it's visible onscreen. Its opposite
6123 * is gdk_window_hide().
6125 * When implementing a #GtkWidget, you should call this function on the widget's
6126 * #GdkWindow as part of the "map" method.
6129 gdk_window_show (GdkWindow *window)
6131 gdk_window_show_internal (window, TRUE);
6134 /* Hiding a non-native parent may cause parents to become non-visible,
6135 even if their parent native window is visible. We need to handle this
6136 by manually hiding them then. To simplify things we hide them all
6137 when they are not visible. */
6139 hide_all_visible_impls (GdkWindowObject *private)
6141 GdkWindowObject *child;
6144 for (l = private->children; l != NULL; l = l->next)
6148 /* For foreign windows, only hide if if was
6149 explicitly hidden, otherwise we might cause
6150 suprising things to happen to the other client. */
6151 if (GDK_WINDOW_IS_MAPPED (child) &&
6152 child->window_type != GDK_WINDOW_FOREIGN)
6153 hide_all_visible_impls (child);
6156 if (gdk_window_has_impl (private))
6157 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->hide ((GdkWindow *)private);
6163 * @window: a #GdkWindow
6165 * For toplevel windows, withdraws them, so they will no longer be
6166 * known to the window manager; for all windows, unmaps them, so
6167 * they won't be displayed. Normally done automatically as
6168 * part of gtk_widget_hide().
6171 gdk_window_hide (GdkWindow *window)
6173 GdkWindowObject *private;
6174 gboolean was_mapped, was_viewable;
6176 g_return_if_fail (GDK_IS_WINDOW (window));
6178 private = (GdkWindowObject *) window;
6179 if (private->destroyed)
6182 was_mapped = GDK_WINDOW_IS_MAPPED (private);
6183 was_viewable = gdk_window_is_viewable (window);
6185 if (gdk_window_has_impl (private))
6188 if (GDK_WINDOW_IS_MAPPED (window))
6189 gdk_synthesize_window_state (window,
6191 GDK_WINDOW_STATE_WITHDRAWN);
6193 else if (was_mapped)
6195 GdkDisplay *display;
6197 /* May need to break grabs on children */
6198 display = gdk_drawable_get_display (window);
6200 if (_gdk_display_end_pointer_grab (display,
6201 _gdk_windowing_window_get_next_serial (display),
6204 gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
6206 if (display->keyboard_grab.window != NULL)
6208 if (is_parent_of (window, display->keyboard_grab.window))
6210 /* Call this ourselves, even though gdk_display_keyboard_ungrab
6211 does so too, since we want to pass implicit == TRUE so the
6212 broken grab event is generated */
6213 _gdk_display_unset_has_keyboard_grab (display,
6215 gdk_display_keyboard_ungrab (display, GDK_CURRENT_TIME);
6219 private->state = GDK_WINDOW_STATE_WITHDRAWN;
6222 _gdk_window_update_viewable (window);
6225 hide_all_visible_impls (private);
6227 recompute_visible_regions (private, TRUE, FALSE);
6229 /* all decendants became non-visible, we need to send visibility notify */
6230 gdk_window_update_visibility_recursively (private, NULL);
6232 if (was_mapped && !gdk_window_has_impl (private))
6234 if (private->event_mask & GDK_STRUCTURE_MASK)
6235 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6237 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
6238 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6240 _gdk_synthesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
6243 /* Invalidate the rect */
6244 gdk_window_invalidate_in_parent (private);
6248 * gdk_window_withdraw:
6249 * @window: a toplevel #GdkWindow
6251 * Withdraws a window (unmaps it and asks the window manager to forget about it).
6252 * This function is not really useful as gdk_window_hide() automatically
6253 * withdraws toplevel windows before hiding them.
6256 gdk_window_withdraw (GdkWindow *window)
6258 GdkWindowObject *private;
6259 gboolean was_mapped;
6261 g_return_if_fail (GDK_IS_WINDOW (window));
6263 private = (GdkWindowObject *) window;
6264 if (private->destroyed)
6267 was_mapped = GDK_WINDOW_IS_MAPPED (private);
6269 if (gdk_window_has_impl (private))
6271 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->withdraw (window);
6275 if (private->event_mask & GDK_STRUCTURE_MASK)
6276 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6278 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
6279 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6281 _gdk_synthesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
6284 recompute_visible_regions (private, TRUE, FALSE);
6289 * gdk_window_set_events:
6290 * @window: a #GdkWindow
6291 * @event_mask: event mask for @window
6293 * The event mask for a window determines which events will be reported
6294 * for that window. For example, an event mask including #GDK_BUTTON_PRESS_MASK
6295 * means the window should report button press events. The event mask
6296 * is the bitwise OR of values from the #GdkEventMask enumeration.
6299 gdk_window_set_events (GdkWindow *window,
6300 GdkEventMask event_mask)
6302 GdkWindowObject *private;
6303 GdkDisplay *display;
6306 g_return_if_fail (GDK_IS_WINDOW (window));
6308 private = (GdkWindowObject *) window;
6309 if (private->destroyed)
6312 /* If motion hint is disabled, enable motion events again */
6313 display = gdk_drawable_get_display (window);
6314 if ((private->event_mask & GDK_POINTER_MOTION_HINT_MASK) &&
6315 !(event_mask & GDK_POINTER_MOTION_HINT_MASK))
6316 _gdk_display_enable_motion_hints (display);
6318 private->event_mask = event_mask;
6320 if (gdk_window_has_impl (private))
6321 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_events (window,
6322 get_native_event_mask (private));
6327 * gdk_window_get_events:
6328 * @window: a #GdkWindow
6330 * Gets the event mask for @window. See gdk_window_set_events().
6332 * Return value: event mask for @window
6335 gdk_window_get_events (GdkWindow *window)
6337 GdkWindowObject *private;
6339 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
6341 private = (GdkWindowObject *) window;
6342 if (private->destroyed)
6345 return private->event_mask;
6349 gdk_window_move_resize_toplevel (GdkWindow *window,
6356 GdkWindowObject *private;
6357 GdkRegion *old_region, *new_region;
6358 GdkWindowObject *impl_window;
6360 int old_x, old_y, old_abs_x, old_abs_y;
6364 private = (GdkWindowObject *) window;
6369 impl_window = gdk_window_get_impl_window (private);
6374 is_resize = (width != -1) || (height != -1);
6376 if (gdk_window_is_viewable (window) &&
6377 !private->input_only)
6380 old_region = gdk_region_copy (private->clip_region);
6383 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, with_move, x, y, width, height);
6385 dx = private->x - old_x;
6386 dy = private->y - old_y;
6388 old_abs_x = private->abs_x;
6389 old_abs_y = private->abs_y;
6391 /* Avoid recomputing for pure toplevel moves, for performance reasons */
6393 recompute_visible_regions (private, TRUE, FALSE);
6397 new_region = gdk_region_copy (private->clip_region);
6399 /* This is the newly exposed area (due to any resize),
6400 * X will expose it, but lets do that without the
6403 gdk_region_subtract (new_region, old_region);
6404 gdk_window_invalidate_region (window, new_region, TRUE);
6406 gdk_region_destroy (old_region);
6407 gdk_region_destroy (new_region);
6410 _gdk_synthesize_crossing_events_for_geometry_change (window);
6415 move_native_children (GdkWindowObject *private)
6418 GdkWindowObject *child;
6420 for (l = private->children; l; l = l->next)
6424 if (child->impl != private->impl)
6425 GDK_WINDOW_IMPL_GET_IFACE (child->impl)->move_resize ((GdkWindow *)child, TRUE, child->x, child->y, child->width, child->height);
6427 move_native_children (child);
6432 collect_native_child_region_helper (GdkWindowObject *window,
6438 GdkWindowObject *child;
6442 for (l = window->children; l != NULL; l = l->next)
6446 if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only)
6449 if (child->impl != impl)
6451 tmp = gdk_region_copy (child->clip_region);
6452 gdk_region_offset (tmp,
6453 x_offset + child->x,
6454 y_offset + child->y);
6455 if (*region == NULL)
6459 gdk_region_union (*region, tmp);
6460 gdk_region_destroy (tmp);
6464 collect_native_child_region_helper (child, impl, region,
6465 x_offset + child->x,
6466 y_offset + child->y);
6473 collect_native_child_region (GdkWindowObject *window,
6474 gboolean include_this)
6478 if (include_this && gdk_window_has_impl (window) && window->viewable)
6479 return gdk_region_copy (window->clip_region);
6483 collect_native_child_region_helper (window, window->impl, ®ion, 0, 0);
6490 gdk_window_move_resize_internal (GdkWindow *window,
6497 GdkWindowObject *private;
6498 GdkRegion *old_region, *new_region, *copy_area;
6499 GdkRegion *old_native_child_region, *new_native_child_region;
6500 GdkWindowObject *impl_window;
6502 int old_x, old_y, old_abs_x, old_abs_y;
6505 g_return_if_fail (GDK_IS_WINDOW (window));
6507 private = (GdkWindowObject *) window;
6508 if (private->destroyed)
6511 if (private->parent == NULL ||
6512 private->parent->window_type == GDK_WINDOW_ROOT)
6514 gdk_window_move_resize_toplevel (window, with_move, x, y, width, height);
6518 /* Handle child windows */
6523 impl_window = gdk_window_get_impl_window (private);
6528 old_native_child_region = NULL;
6529 if (gdk_window_is_viewable (window) &&
6530 !private->input_only)
6534 old_region = gdk_region_copy (private->clip_region);
6535 /* Adjust region to parent window coords */
6536 gdk_region_offset (old_region, private->x, private->y);
6538 old_native_child_region = collect_native_child_region (private, TRUE);
6539 if (old_native_child_region)
6541 /* Adjust region to parent window coords */
6542 gdk_region_offset (old_native_child_region, private->x, private->y);
6544 /* Any native window move will immediately copy stuff to the destination, which may overwrite a
6545 * source or destination for a delayed GdkWindowRegionMove. So, we need
6546 * to flush those here for the parent window and all overlapped subwindows
6547 * of it. And we need to do this before setting the new clips as those will be
6550 gdk_window_flush_recursive (private->parent);
6554 /* Set the new position and size */
6560 if (!(width < 0 && height < 0))
6564 private->width = width;
6567 private->height = height;
6570 dx = private->x - old_x;
6571 dy = private->y - old_y;
6573 old_abs_x = private->abs_x;
6574 old_abs_y = private->abs_y;
6576 recompute_visible_regions (private, TRUE, FALSE);
6578 new_native_child_region = NULL;
6579 if (old_native_child_region)
6581 new_native_child_region = collect_native_child_region (private, TRUE);
6582 /* Adjust region to parent window coords */
6583 gdk_region_offset (new_native_child_region, private->x, private->y);
6586 if (gdk_window_has_impl (private))
6588 /* Do the actual move after recomputing things, as this will have set the shape to
6589 the now correct one, thus avoiding copying regions that should not be copied. */
6590 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, TRUE, private->x, private->y, private->width, private->height);
6592 else if (old_abs_x != private->abs_x ||
6593 old_abs_y != private->abs_y)
6594 move_native_children (private);
6598 new_region = gdk_region_copy (private->clip_region);
6599 /* Adjust region to parent window coords */
6600 gdk_region_offset (new_region, private->x, private->y);
6603 * Part of the data at the new location can be copied from the
6604 * old location, this area is the intersection of the old region
6605 * moved as the copy will move it and then intersected with
6609 * Everything in the old and new regions that is not copied must be
6610 * invalidated (including children) as this is newly exposed
6612 copy_area = gdk_region_copy (new_region);
6614 gdk_region_union (new_region, old_region);
6616 if (old_native_child_region)
6618 /* Don't copy from inside native children, as this is copied by
6619 * the native window move.
6621 gdk_region_subtract (old_region, old_native_child_region);
6623 gdk_region_offset (old_region, dx, dy);
6625 gdk_region_intersect (copy_area, old_region);
6627 if (new_native_child_region)
6629 /* Don't copy any bits that would cause a read from the moved
6630 native windows, as we can't read that data */
6631 gdk_region_offset (new_native_child_region, dx, dy);
6632 gdk_region_subtract (copy_area, new_native_child_region);
6635 gdk_region_subtract (new_region, copy_area);
6637 /* Convert old region to impl coords */
6638 gdk_region_offset (old_region, -dx + private->abs_x - private->x, -dy + private->abs_y - private->y);
6640 /* convert from parent coords to impl */
6641 gdk_region_offset (copy_area, private->abs_x - private->x, private->abs_y - private->y);
6643 move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
6645 /* Invalidate affected part in the parent window
6646 * (no higher window should be affected)
6647 * We also invalidate any children in that area, which could include
6648 * this window if it still overlaps that area.
6650 gdk_window_invalidate_region (GDK_WINDOW (private->parent), new_region, TRUE);
6652 gdk_region_destroy (old_region);
6653 gdk_region_destroy (new_region);
6656 if (old_native_child_region)
6658 gdk_region_destroy (old_native_child_region);
6659 gdk_region_destroy (new_native_child_region);
6662 _gdk_synthesize_crossing_events_for_geometry_change (window);
6669 * @window: a #GdkWindow
6670 * @x: X coordinate relative to window's parent
6671 * @y: Y coordinate relative to window's parent
6673 * Repositions a window relative to its parent window.
6674 * For toplevel windows, window managers may ignore or modify the move;
6675 * you should probably use gtk_window_move() on a #GtkWindow widget
6676 * anyway, instead of using GDK functions. For child windows,
6677 * the move will reliably succeed.
6679 * If you're also planning to resize the window, use gdk_window_move_resize()
6680 * to both move and resize simultaneously, for a nicer visual effect.
6683 gdk_window_move (GdkWindow *window,
6687 gdk_window_move_resize_internal (window, TRUE, x, y, -1, -1);
6691 * gdk_window_resize:
6692 * @window: a #GdkWindow
6693 * @width: new width of the window
6694 * @height: new height of the window
6696 * Resizes @window; for toplevel windows, asks the window manager to resize
6697 * the window. The window manager may not allow the resize. When using GTK+,
6698 * use gtk_window_resize() instead of this low-level GDK function.
6700 * Windows may not be resized below 1x1.
6702 * If you're also planning to move the window, use gdk_window_move_resize()
6703 * to both move and resize simultaneously, for a nicer visual effect.
6706 gdk_window_resize (GdkWindow *window,
6710 gdk_window_move_resize_internal (window, FALSE, 0, 0, width, height);
6715 * gdk_window_move_resize:
6716 * @window: a #GdkWindow
6717 * @x: new X position relative to window's parent
6718 * @y: new Y position relative to window's parent
6720 * @height: new height
6722 * Equivalent to calling gdk_window_move() and gdk_window_resize(),
6723 * except that both operations are performed at once, avoiding strange
6724 * visual effects. (i.e. the user may be able to see the window first
6725 * move, then resize, if you don't use gdk_window_move_resize().)
6728 gdk_window_move_resize (GdkWindow *window,
6734 gdk_window_move_resize_internal (window, TRUE, x, y, width, height);
6739 * gdk_window_scroll:
6740 * @window: a #GdkWindow
6741 * @dx: Amount to scroll in the X direction
6742 * @dy: Amount to scroll in the Y direction
6744 * Scroll the contents of @window, both pixels and children, by the
6745 * given amount. @window itself does not move. Portions of the window
6746 * that the scroll operation brings in from offscreen areas are
6747 * invalidated. The invalidated region may be bigger than what would
6748 * strictly be necessary.
6750 * For X11, a minimum area will be invalidated if the window has no
6751 * subwindows, or if the edges of the window's parent do not extend
6752 * beyond the edges of the window. In other cases, a multi-step process
6753 * is used to scroll the window which may produce temporary visual
6754 * artifacts and unnecessary invalidations.
6757 gdk_window_scroll (GdkWindow *window,
6761 GdkWindowObject *private = (GdkWindowObject *) window;
6762 GdkWindowObject *impl_window;
6763 GdkRegion *copy_area, *noncopy_area;
6764 GdkRegion *old_native_child_region, *new_native_child_region;
6767 g_return_if_fail (GDK_IS_WINDOW (window));
6769 if (dx == 0 && dy == 0)
6772 if (private->destroyed)
6775 old_native_child_region = collect_native_child_region (private, FALSE);
6776 if (old_native_child_region)
6778 /* Any native window move will immediately copy stuff to the destination, which may overwrite a
6779 * source or destination for a delayed GdkWindowRegionMove. So, we need
6780 * to flush those here for the window and all overlapped subwindows
6781 * of it. And we need to do this before setting the new clips as those will be
6784 gdk_window_flush_recursive (private);
6788 /* First move all child windows, without causing invalidation */
6790 tmp_list = private->children;
6793 GdkWindow *child = GDK_WINDOW (tmp_list->data);
6794 GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
6796 /* Just update the positions, the bits will move with the copy */
6800 tmp_list = tmp_list->next;
6803 recompute_visible_regions (private, FALSE, TRUE);
6805 new_native_child_region = NULL;
6806 if (old_native_child_region)
6807 new_native_child_region = collect_native_child_region (private, FALSE);
6809 move_native_children (private);
6811 /* Then copy the actual bits of the window w/ child windows */
6813 impl_window = gdk_window_get_impl_window (private);
6815 /* Calculate the area that can be gotten by copying the old area */
6816 copy_area = gdk_region_copy (private->clip_region);
6817 if (old_native_child_region)
6819 /* Don't copy from inside native children, as this is copied by
6820 * the native window move.
6822 gdk_region_subtract (copy_area, old_native_child_region);
6824 /* Don't copy any bits that would cause a read from the moved
6825 native windows, as we can't read that data */
6826 gdk_region_subtract (copy_area, new_native_child_region);
6828 gdk_region_offset (copy_area, dx, dy);
6829 gdk_region_intersect (copy_area, private->clip_region);
6831 /* And the rest need to be invalidated */
6832 noncopy_area = gdk_region_copy (private->clip_region);
6833 gdk_region_subtract (noncopy_area, copy_area);
6835 /* convert from window coords to impl */
6836 gdk_region_offset (copy_area, private->abs_x, private->abs_y);
6838 move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
6840 /* Invalidate not copied regions */
6841 gdk_window_invalidate_region (window, noncopy_area, TRUE);
6843 gdk_region_destroy (noncopy_area);
6845 if (old_native_child_region)
6847 gdk_region_destroy (old_native_child_region);
6848 gdk_region_destroy (new_native_child_region);
6851 _gdk_synthesize_crossing_events_for_geometry_change (window);
6855 * gdk_window_move_region:
6856 * @window: a #GdkWindow
6857 * @region: The #GdkRegion to move
6858 * @dx: Amount to move in the X direction
6859 * @dy: Amount to move in the Y direction
6861 * Move the part of @window indicated by @region by @dy pixels in the Y
6862 * direction and @dx pixels in the X direction. The portions of @region
6863 * that not covered by the new position of @region are invalidated.
6865 * Child windows are not moved.
6870 gdk_window_move_region (GdkWindow *window,
6871 const GdkRegion *region,
6875 GdkWindowObject *private = (GdkWindowObject *) window;
6876 GdkWindowObject *impl_window;
6877 GdkRegion *nocopy_area;
6878 GdkRegion *copy_area;
6880 g_return_if_fail (GDK_IS_WINDOW (window));
6881 g_return_if_fail (region != NULL);
6883 if (dx == 0 && dy == 0)
6886 if (private->destroyed)
6889 impl_window = gdk_window_get_impl_window (private);
6891 /* compute source regions */
6892 copy_area = gdk_region_copy (region);
6893 gdk_region_intersect (copy_area, private->clip_region_with_children);
6895 /* compute destination regions */
6896 gdk_region_offset (copy_area, dx, dy);
6897 gdk_region_intersect (copy_area, private->clip_region_with_children);
6899 /* invalidate parts of the region not covered by the copy */
6900 nocopy_area = gdk_region_copy (region);
6901 gdk_region_offset (nocopy_area, dx, dy);
6902 gdk_region_subtract (nocopy_area, copy_area);
6903 gdk_window_invalidate_region (window, nocopy_area, FALSE);
6904 gdk_region_destroy (nocopy_area);
6906 /* convert from window coords to impl */
6907 gdk_region_offset (copy_area, private->abs_x, private->abs_y);
6909 move_region_on_impl (impl_window, copy_area, dx, dy); /* Takes ownership of copy_area */
6913 * gdk_window_set_background:
6914 * @window: a #GdkWindow
6915 * @color: an allocated #GdkColor
6917 * Sets the background color of @window. (However, when using GTK+,
6918 * set the background of a widget with gtk_widget_modify_bg() - if
6919 * you're an application - or gtk_style_set_background() - if you're
6920 * implementing a custom widget.)
6922 * The @color must be allocated; gdk_rgb_find_color() is the best way
6923 * to allocate a color.
6925 * See also gdk_window_set_back_pixmap().
6928 gdk_window_set_background (GdkWindow *window,
6929 const GdkColor *color)
6931 GdkWindowObject *private;
6932 GdkColormap *colormap = gdk_drawable_get_colormap (window);
6934 g_return_if_fail (GDK_IS_WINDOW (window));
6936 private = (GdkWindowObject *) window;
6938 private->bg_color = *color;
6939 gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
6941 if (private->bg_pixmap &&
6942 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
6943 private->bg_pixmap != GDK_NO_BG)
6944 g_object_unref (private->bg_pixmap);
6946 private->bg_pixmap = NULL;
6948 if (!GDK_WINDOW_DESTROYED (window) &&
6949 gdk_window_has_impl (private) &&
6950 !private->input_only)
6951 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, &private->bg_color);
6955 * gdk_window_set_back_pixmap:
6956 * @window: a #GdkWindow
6957 * @pixmap: a #GdkPixmap, or %NULL
6958 * @parent_relative: whether the tiling origin is at the origin of
6961 * Sets the background pixmap of @window. May also be used to set a
6962 * background of "None" on @window, by setting a background pixmap
6965 * A background pixmap will be tiled, positioning the first tile at
6966 * the origin of @window, or if @parent_relative is %TRUE, the tiling
6967 * will be done based on the origin of the parent window (useful to
6968 * align tiles in a parent with tiles in a child).
6970 * A background pixmap of %NULL means that the window will have no
6971 * background. A window with no background will never have its
6972 * background filled by the windowing system, instead the window will
6973 * contain whatever pixels were already in the corresponding area of
6976 * The windowing system will normally fill a window with its background
6977 * when the window is obscured then exposed, and when you call
6978 * gdk_window_clear().
6981 gdk_window_set_back_pixmap (GdkWindow *window,
6983 gboolean parent_relative)
6985 GdkWindowObject *private;
6987 g_return_if_fail (GDK_IS_WINDOW (window));
6988 g_return_if_fail (pixmap == NULL || !parent_relative);
6989 g_return_if_fail (pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap));
6991 private = (GdkWindowObject *) window;
6993 if (pixmap && !gdk_drawable_get_colormap (pixmap))
6995 g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
6999 if (private->bg_pixmap &&
7000 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
7001 private->bg_pixmap != GDK_NO_BG)
7002 g_object_unref (private->bg_pixmap);
7004 if (parent_relative)
7005 private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
7007 private->bg_pixmap = g_object_ref (pixmap);
7009 private->bg_pixmap = GDK_NO_BG;
7011 if (!GDK_WINDOW_DESTROYED (window) &&
7012 gdk_window_has_impl (private) &&
7013 !private->input_only)
7014 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, private->bg_pixmap);
7018 * gdk_window_get_cursor:
7019 * @window: a #GdkWindow
7022 * Retrieves a #GdkCursor pointer for the cursor currently set on the
7023 * specified #GdkWindow, or %NULL. If the return value is %NULL then
7024 * there is no custom cursor set on the specified window, and it is
7025 * using the cursor for its parent window.
7027 * Return value: a #GdkCursor, or %NULL. The returned object is owned
7028 * by the #GdkWindow and should not be unreferenced directly. Use
7029 * gdk_window_set_cursor() to unset the cursor of the window
7034 gdk_window_get_cursor (GdkWindow *window)
7036 GdkWindowObject *private;
7038 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
7040 private = (GdkWindowObject *) window;
7042 return private->cursor;
7046 * gdk_window_set_cursor:
7047 * @window: a #GdkWindow
7050 * Sets the mouse pointer for a #GdkWindow. Use gdk_cursor_new_for_display()
7051 * or gdk_cursor_new_from_pixmap() to create the cursor. To make the cursor
7052 * invisible, use %GDK_BLANK_CURSOR. Passing %NULL for the @cursor argument
7053 * to gdk_window_set_cursor() means that @window will use the cursor of its
7054 * parent window. Most windows should use this default.
7057 gdk_window_set_cursor (GdkWindow *window,
7060 GdkWindowObject *private;
7061 GdkDisplay *display;
7063 g_return_if_fail (GDK_IS_WINDOW (window));
7065 private = (GdkWindowObject *) window;
7066 display = gdk_drawable_get_display (window);
7068 if (private->cursor)
7070 gdk_cursor_unref (private->cursor);
7071 private->cursor = NULL;
7074 if (!GDK_WINDOW_DESTROYED (window))
7077 private->cursor = gdk_cursor_ref (cursor);
7079 if (_gdk_window_event_parent_of (window, display->pointer_info.window_under_pointer))
7080 update_cursor (display);
7082 g_object_notify (G_OBJECT (window), "cursor");
7087 * gdk_window_get_geometry:
7088 * @window: a #GdkWindow
7089 * @x: return location for X coordinate of window (relative to its parent)
7090 * @y: return location for Y coordinate of window (relative to its parent)
7091 * @width: return location for width of window
7092 * @height: return location for height of window
7093 * @depth: return location for bit depth of window
7095 * Any of the return location arguments to this function may be %NULL,
7096 * if you aren't interested in getting the value of that field.
7098 * The X and Y coordinates returned are relative to the parent window
7099 * of @window, which for toplevels usually means relative to the
7100 * window decorations (titlebar, etc.) rather than relative to the
7101 * root window (screen-size background window).
7103 * On the X11 platform, the geometry is obtained from the X server,
7104 * so reflects the latest position of @window; this may be out-of-sync
7105 * with the position of @window delivered in the most-recently-processed
7106 * #GdkEventConfigure. gdk_window_get_position() in contrast gets the
7107 * position from the most recent configure event.
7110 * If @window is not a toplevel, it is <emphasis>much</emphasis> better
7111 * to call gdk_window_get_position() and gdk_drawable_get_size() instead,
7112 * because it avoids the roundtrip to the X server and because
7113 * gdk_drawable_get_size() supports the full 32-bit coordinate space,
7114 * whereas gdk_window_get_geometry() is restricted to the 16-bit
7115 * coordinates of X11.
7119 gdk_window_get_geometry (GdkWindow *window,
7126 GdkWindowObject *private;
7130 GDK_NOTE (MULTIHEAD,
7131 g_message ("gdk_window_get_geometry(): Window needs "
7132 "to be non-NULL to be multi head safe"));
7133 window = gdk_screen_get_root_window ((gdk_screen_get_default ()));
7136 g_return_if_fail (GDK_IS_WINDOW (window));
7138 private = (GdkWindowObject *) window;
7140 if (!GDK_WINDOW_DESTROYED (window))
7142 if (gdk_window_has_impl (private))
7143 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_geometry (window, x, y,
7153 *width = private->width;
7155 *height = private->height;
7157 *depth = private->depth;
7163 * gdk_window_get_origin:
7164 * @window: a #GdkWindow
7165 * @x: return location for X coordinate
7166 * @y: return location for Y coordinate
7168 * Obtains the position of a window in root window coordinates.
7169 * (Compare with gdk_window_get_position() and
7170 * gdk_window_get_geometry() which return the position of a window
7171 * relative to its parent window.)
7173 * Return value: not meaningful, ignore
7176 gdk_window_get_origin (GdkWindow *window,
7180 GdkWindowObject *private;
7182 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
7184 if (GDK_WINDOW_DESTROYED (window))
7193 private = (GdkWindowObject *) window;
7195 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_root_coords (window,
7204 * gdk_window_get_root_coords:
7205 * @window: a #GdkWindow
7206 * @x: X coordinate in window
7207 * @y: Y coordinate in window
7208 * @root_x: return location for X coordinate
7209 * @root_y: return location for Y coordinate
7211 * Obtains the position of a window position in root
7212 * window coordinates. This is similar to
7213 * gdk_window_get_origin() but allows you go pass
7214 * in any position in the window, not just the origin.
7217 gdk_window_get_root_coords (GdkWindow *window,
7223 GdkWindowObject *private;
7225 g_return_if_fail (GDK_IS_WINDOW (window));
7227 private = (GdkWindowObject *) window;
7229 if (GDK_WINDOW_DESTROYED (window))
7238 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_root_coords (window,
7246 * gdk_window_get_deskrelative_origin:
7247 * @window: a toplevel #GdkWindow
7248 * @x: return location for X coordinate
7249 * @y: return location for Y coordinate
7251 * This gets the origin of a #GdkWindow relative to
7252 * an Enlightenment-window-manager desktop. As long as you don't
7253 * assume that the user's desktop/workspace covers the entire
7254 * root window (i.e. you don't assume that the desktop begins
7255 * at root window coordinate 0,0) this function is not necessary.
7256 * It's deprecated for that reason.
7258 * Return value: not meaningful
7261 gdk_window_get_deskrelative_origin (GdkWindow *window,
7265 GdkWindowObject *private;
7266 gboolean return_val = FALSE;
7270 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
7272 private = (GdkWindowObject *) window;
7274 if (!GDK_WINDOW_DESTROYED (window))
7276 return_val = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_deskrelative_origin (window, &tx, &ty);
7279 *x = tx + private->abs_x;
7281 *y = ty + private->abs_y;
7288 * gdk_window_shape_combine_mask:
7289 * @window: a #GdkWindow
7291 * @x: X position of shape mask with respect to @window
7292 * @y: Y position of shape mask with respect to @window
7294 * Applies a shape mask to @window. Pixels in @window corresponding to
7295 * set bits in the @mask will be visible; pixels in @window
7296 * corresponding to unset bits in the @mask will be transparent. This
7297 * gives a non-rectangular window.
7299 * If @mask is %NULL, the shape mask will be unset, and the @x/@y
7300 * parameters are not used.
7302 * On the X11 platform, this uses an X server extension which is
7303 * widely available on most common platforms, but not available on
7304 * very old X servers, and occasionally the implementation will be
7305 * buggy. On servers without the shape extension, this function
7308 * This function works on both toplevel and child windows.
7311 gdk_window_shape_combine_mask (GdkWindow *window,
7316 GdkWindowObject *private;
7319 g_return_if_fail (GDK_IS_WINDOW (window));
7321 private = (GdkWindowObject *) window;
7324 region = _gdk_windowing_get_shape_for_mask (mask);
7328 gdk_window_shape_combine_region (window,
7333 gdk_region_destroy (region);
7337 * gdk_window_shape_combine_region:
7338 * @window: a #GdkWindow
7339 * @shape_region: region of window to be non-transparent
7340 * @offset_x: X position of @shape_region in @window coordinates
7341 * @offset_y: Y position of @shape_region in @window coordinates
7343 * Makes pixels in @window outside @shape_region be transparent,
7344 * so that the window may be nonrectangular. See also
7345 * gdk_window_shape_combine_mask() to use a bitmap as the mask.
7347 * If @shape_region is %NULL, the shape will be unset, so the whole
7348 * window will be opaque again. @offset_x and @offset_y are ignored
7349 * if @shape_region is %NULL.
7351 * On the X11 platform, this uses an X server extension which is
7352 * widely available on most common platforms, but not available on
7353 * very old X servers, and occasionally the implementation will be
7354 * buggy. On servers without the shape extension, this function
7357 * This function works on both toplevel and child windows.
7360 gdk_window_shape_combine_region (GdkWindow *window,
7361 const GdkRegion *shape_region,
7365 GdkWindowObject *private;
7366 GdkRegion *old_region, *new_region, *diff;
7368 g_return_if_fail (GDK_IS_WINDOW (window));
7370 private = (GdkWindowObject *) window;
7372 if (GDK_WINDOW_DESTROYED (window))
7375 private->shaped = (shape_region != NULL);
7378 gdk_region_destroy (private->shape);
7381 if (GDK_WINDOW_IS_MAPPED (window))
7382 old_region = gdk_region_copy (private->clip_region);
7386 private->shape = gdk_region_copy (shape_region);
7387 gdk_region_offset (private->shape, offset_x, offset_y);
7390 private->shape = NULL;
7392 recompute_visible_regions (private, TRUE, FALSE);
7396 new_region = gdk_region_copy (private->clip_region);
7398 /* New area in the window, needs invalidation */
7399 diff = gdk_region_copy (new_region);
7400 gdk_region_subtract (diff, old_region);
7402 gdk_window_invalidate_region (window, diff, TRUE);
7404 gdk_region_destroy (diff);
7406 if (private->parent != NULL &&
7407 private->parent->window_type != GDK_WINDOW_ROOT)
7409 /* New area in the non-root parent window, needs invalidation */
7410 diff = gdk_region_copy (old_region);
7411 gdk_region_subtract (diff, new_region);
7413 /* Adjust region to parent window coords */
7414 gdk_region_offset (diff, private->x, private->y);
7416 gdk_window_invalidate_region (GDK_WINDOW (private->parent), diff, TRUE);
7418 gdk_region_destroy (diff);
7421 gdk_region_destroy (new_region);
7422 gdk_region_destroy (old_region);
7427 do_child_shapes (GdkWindow *window,
7430 GdkWindowObject *private;
7434 private = (GdkWindowObject *) window;
7438 r.width = private->width;
7439 r.height = private->height;
7441 region = gdk_region_rectangle (&r);
7442 remove_child_area (private, NULL, FALSE, region);
7444 if (merge && private->shape)
7445 gdk_region_subtract (region, private->shape);
7447 gdk_window_shape_combine_region (window, region, 0, 0);
7451 * gdk_window_set_child_shapes:
7452 * @window: a #GdkWindow
7454 * Sets the shape mask of @window to the union of shape masks
7455 * for all children of @window, ignoring the shape mask of @window
7456 * itself. Contrast with gdk_window_merge_child_shapes() which includes
7457 * the shape mask of @window in the masks to be merged.
7460 gdk_window_set_child_shapes (GdkWindow *window)
7462 g_return_if_fail (GDK_IS_WINDOW (window));
7464 do_child_shapes (window, FALSE);
7468 * gdk_window_merge_child_shapes:
7469 * @window: a #GdkWindow
7471 * Merges the shape masks for any child windows into the
7472 * shape mask for @window. i.e. the union of all masks
7473 * for @window and its children will become the new mask
7474 * for @window. See gdk_window_shape_combine_mask().
7476 * This function is distinct from gdk_window_set_child_shapes()
7477 * because it includes @window's shape mask in the set of shapes to
7481 gdk_window_merge_child_shapes (GdkWindow *window)
7483 g_return_if_fail (GDK_IS_WINDOW (window));
7485 do_child_shapes (window, TRUE);
7489 * gdk_window_input_shape_combine_mask:
7490 * @window: a #GdkWindow
7491 * @mask: shape mask, or %NULL
7492 * @x: X position of shape mask with respect to @window
7493 * @y: Y position of shape mask with respect to @window
7495 * Like gdk_window_shape_combine_mask(), but the shape applies
7496 * only to event handling. Mouse events which happen while
7497 * the pointer position corresponds to an unset bit in the
7498 * mask will be passed on the window below @window.
7500 * An input shape is typically used with RGBA windows.
7501 * The alpha channel of the window defines which pixels are
7502 * invisible and allows for nicely antialiased borders,
7503 * and the input shape controls where the window is
7506 * On the X11 platform, this requires version 1.1 of the
7509 * On the Win32 platform, this functionality is not present and the
7510 * function does nothing.
7515 gdk_window_input_shape_combine_mask (GdkWindow *window,
7520 GdkWindowObject *private;
7523 g_return_if_fail (GDK_IS_WINDOW (window));
7525 private = (GdkWindowObject *) window;
7528 region = _gdk_windowing_get_shape_for_mask (mask);
7532 gdk_window_input_shape_combine_region (window,
7537 gdk_region_destroy (region);
7541 * gdk_window_input_shape_combine_region:
7542 * @window: a #GdkWindow
7543 * @shape_region: region of window to be non-transparent
7544 * @offset_x: X position of @shape_region in @window coordinates
7545 * @offset_y: Y position of @shape_region in @window coordinates
7547 * Like gdk_window_shape_combine_region(), but the shape applies
7548 * only to event handling. Mouse events which happen while
7549 * the pointer position corresponds to an unset bit in the
7550 * mask will be passed on the window below @window.
7552 * An input shape is typically used with RGBA windows.
7553 * The alpha channel of the window defines which pixels are
7554 * invisible and allows for nicely antialiased borders,
7555 * and the input shape controls where the window is
7558 * On the X11 platform, this requires version 1.1 of the
7561 * On the Win32 platform, this functionality is not present and the
7562 * function does nothing.
7567 gdk_window_input_shape_combine_region (GdkWindow *window,
7568 const GdkRegion *shape_region,
7572 GdkWindowObject *private;
7574 g_return_if_fail (GDK_IS_WINDOW (window));
7576 private = (GdkWindowObject *) window;
7578 if (GDK_WINDOW_DESTROYED (window))
7581 if (private->input_shape)
7582 gdk_region_destroy (private->input_shape);
7586 private->input_shape = gdk_region_copy (shape_region);
7587 gdk_region_offset (private->input_shape, offset_x, offset_y);
7590 private->input_shape = NULL;
7592 if (gdk_window_has_impl (private))
7593 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_shape_combine_region ((GdkWindow *)private, private->input_shape, 0, 0);
7595 /* Pointer may have e.g. moved outside window due to the input mask change */
7596 _gdk_synthesize_crossing_events_for_geometry_change (window);
7600 do_child_input_shapes (GdkWindow *window,
7603 GdkWindowObject *private;
7607 private = (GdkWindowObject *) window;
7611 r.width = private->width;
7612 r.height = private->height;
7614 region = gdk_region_rectangle (&r);
7615 remove_child_area (private, NULL, TRUE, region);
7617 if (merge && private->shape)
7618 gdk_region_subtract (region, private->shape);
7619 if (merge && private->input_shape)
7620 gdk_region_subtract (region, private->input_shape);
7622 gdk_window_input_shape_combine_region (window, region, 0, 0);
7627 * gdk_window_set_child_input_shapes:
7628 * @window: a #GdkWindow
7630 * Sets the input shape mask of @window to the union of input shape masks
7631 * for all children of @window, ignoring the input shape mask of @window
7632 * itself. Contrast with gdk_window_merge_child_input_shapes() which includes
7633 * the input shape mask of @window in the masks to be merged.
7638 gdk_window_set_child_input_shapes (GdkWindow *window)
7640 g_return_if_fail (GDK_IS_WINDOW (window));
7642 do_child_input_shapes (window, FALSE);
7646 * gdk_window_merge_child_input_shapes:
7647 * @window: a #GdkWindow
7649 * Merges the input shape masks for any child windows into the
7650 * input shape mask for @window. i.e. the union of all input masks
7651 * for @window and its children will become the new input mask
7652 * for @window. See gdk_window_input_shape_combine_mask().
7654 * This function is distinct from gdk_window_set_child_input_shapes()
7655 * because it includes @window's input shape mask in the set of
7656 * shapes to be merged.
7661 gdk_window_merge_child_input_shapes (GdkWindow *window)
7663 g_return_if_fail (GDK_IS_WINDOW (window));
7665 do_child_input_shapes (window, TRUE);
7670 * gdk_window_set_static_gravities:
7671 * @window: a #GdkWindow
7672 * @use_static: %TRUE to turn on static gravity
7674 * Set the bit gravity of the given window to static, and flag it so
7675 * all children get static subwindow gravity. This is used if you are
7676 * implementing scary features that involve deep knowledge of the
7677 * windowing system. Don't worry about it unless you have to.
7679 * Return value: %TRUE if the server supports static gravity
7682 gdk_window_set_static_gravities (GdkWindow *window,
7683 gboolean use_static)
7685 GdkWindowObject *private;
7687 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
7689 private = (GdkWindowObject *) window;
7691 if (gdk_window_has_impl (private))
7692 return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_static_gravities (window, use_static);
7698 * gdk_window_set_composited:
7699 * @window: a #GdkWindow
7700 * @composited: %TRUE to set the window as composited
7702 * Sets a #GdkWindow as composited, or unsets it. Composited
7703 * windows do not automatically have their contents drawn to
7704 * the screen. Drawing is redirected to an offscreen buffer
7705 * and an expose event is emitted on the parent of the composited
7706 * window. It is the responsibility of the parent's expose handler
7707 * to manually merge the off-screen content onto the screen in
7708 * whatever way it sees fit. See <xref linkend="composited-window-example"/>
7711 * It only makes sense for child windows to be composited; see
7712 * gdk_window_set_opacity() if you need translucent toplevel
7715 * An additional effect of this call is that the area of this
7716 * window is no longer clipped from regions marked for
7717 * invalidation on its parent. Draws done on the parent
7718 * window are also no longer clipped by the child.
7720 * This call is only supported on some systems (currently,
7721 * only X11 with new enough Xcomposite and Xdamage extensions).
7722 * You must call gdk_display_supports_composite() to check if
7723 * setting a window as composited is supported before
7724 * attempting to do so.
7729 gdk_window_set_composited (GdkWindow *window,
7730 gboolean composited)
7732 GdkWindowObject *private = (GdkWindowObject *)window;
7733 GdkDisplay *display;
7735 g_return_if_fail (GDK_IS_WINDOW (window));
7737 composited = composited != FALSE;
7739 if (private->composited == composited)
7743 gdk_window_ensure_native (window);
7745 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
7747 if (!gdk_display_supports_composite (display) && composited)
7749 g_warning ("gdk_window_set_composited called but "
7750 "compositing is not supported");
7754 _gdk_windowing_window_set_composited (window, composited);
7756 recompute_visible_regions (private, TRUE, FALSE);
7758 if (GDK_WINDOW_IS_MAPPED (window))
7759 gdk_window_invalidate_in_parent (private);
7761 private->composited = composited;
7766 remove_redirect_from_children (GdkWindowObject *private,
7767 GdkWindowRedirect *redirect)
7770 GdkWindowObject *child;
7772 for (l = private->children; l != NULL; l = l->next)
7776 /* Don't redirect this child if it already has another redirect */
7777 if (child->redirect == redirect)
7779 child->redirect = NULL;
7780 remove_redirect_from_children (child, redirect);
7786 * gdk_window_remove_redirection:
7787 * @window: a #GdkWindow
7789 * Removes any active redirection started by
7790 * gdk_window_redirect_to_drawable().
7795 gdk_window_remove_redirection (GdkWindow *window)
7797 GdkWindowObject *private;
7799 g_return_if_fail (GDK_IS_WINDOW (window));
7801 private = (GdkWindowObject *) window;
7803 if (private->redirect &&
7804 private->redirect->redirected == private)
7806 remove_redirect_from_children (private, private->redirect);
7807 gdk_window_redirect_free (private->redirect);
7808 private->redirect = NULL;
7813 apply_redirect_to_children (GdkWindowObject *private,
7814 GdkWindowRedirect *redirect)
7817 GdkWindowObject *child;
7819 for (l = private->children; l != NULL; l = l->next)
7823 /* Don't redirect this child if it already has another redirect */
7824 if (!child->redirect)
7826 child->redirect = redirect;
7827 apply_redirect_to_children (child, redirect);
7833 * gdk_window_redirect_to_drawable:
7834 * @window: a #GdkWindow
7835 * @drawable: a #GdkDrawable
7836 * @src_x: x position in @window
7837 * @src_y: y position in @window
7838 * @dest_x: x position in @drawable
7839 * @dest_y: y position in @drawable
7840 * @width: width of redirection
7841 * @height: height of redirection
7843 * Redirects drawing into @window so that drawing to the
7844 * window in the rectangle specified by @src_x, @src_y,
7845 * @width and @height is also drawn into @drawable at
7848 * Only drawing between gdk_window_begin_paint_region() or
7849 * gdk_window_begin_paint_rect() and gdk_window_end_paint() is
7852 * Redirection is active until gdk_window_remove_redirection()
7858 gdk_window_redirect_to_drawable (GdkWindow *window,
7859 GdkDrawable *drawable,
7867 GdkWindowObject *private;
7869 g_return_if_fail (GDK_IS_WINDOW (window));
7870 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
7871 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
7873 private = (GdkWindowObject *) window;
7875 if (private->redirect)
7876 gdk_window_remove_redirection (window);
7878 if (width == -1 || height == -1)
7881 gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
7888 private->redirect = g_new0 (GdkWindowRedirect, 1);
7889 private->redirect->redirected = private;
7890 private->redirect->pixmap = g_object_ref (drawable);
7891 private->redirect->src_x = src_x;
7892 private->redirect->src_y = src_y;
7893 private->redirect->dest_x = dest_x;
7894 private->redirect->dest_y = dest_y;
7895 private->redirect->width = width;
7896 private->redirect->height = height;
7898 apply_redirect_to_children (private, private->redirect);
7902 window_get_size_rectangle (GdkWindow *window,
7905 GdkWindowObject *private = (GdkWindowObject *) window;
7907 rect->x = rect->y = 0;
7908 rect->width = private->width;
7909 rect->height = private->height;
7912 /* Calculates the real clipping region for a window, in window coordinates,
7913 * taking into account other windows, gc clip region and gc clip mask.
7916 _gdk_window_calculate_full_clip_region (GdkWindow *window,
7917 GdkWindow *base_window,
7918 gboolean do_children,
7919 gint *base_x_offset,
7920 gint *base_y_offset)
7922 GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
7923 GdkRectangle visible_rect;
7924 GdkRegion *real_clip_region, *tmpreg;
7925 gint x_offset, y_offset;
7926 GdkWindowObject *parentwin, *lastwin;
7933 if (!private->viewable || private->input_only)
7934 return gdk_region_new ();
7936 window_get_size_rectangle (window, &visible_rect);
7938 /* real_clip_region is in window coordinates */
7939 real_clip_region = gdk_region_rectangle (&visible_rect);
7941 x_offset = y_offset = 0;
7945 parentwin = lastwin;
7947 parentwin = lastwin->parent;
7949 /* Remove the areas of all overlapping windows above parentwin in the hiearachy */
7950 for (; parentwin != NULL &&
7951 (parentwin == private || lastwin != (GdkWindowObject*) base_window);
7952 lastwin = parentwin, parentwin = lastwin->parent)
7955 GdkRectangle real_clip_rect;
7956 gboolean is_offscreen;
7958 if (parentwin != private)
7960 x_offset += GDK_WINDOW_OBJECT (lastwin)->x;
7961 y_offset += GDK_WINDOW_OBJECT (lastwin)->y;
7964 is_offscreen = gdk_window_is_offscreen (parentwin);
7966 /* children is ordered in reverse stack order */
7967 for (cur = parentwin->children;
7968 cur && cur->data != lastwin;
7971 GdkWindow *child = cur->data;
7972 GdkWindowObject *child_private = (GdkWindowObject *)child;
7974 if (!GDK_WINDOW_IS_MAPPED (child) || child_private->input_only)
7977 /* Ignore offscreen children, as they don't draw in their parent and
7978 * don't take part in the clipping */
7979 if (gdk_window_is_offscreen (child_private))
7982 window_get_size_rectangle (child, &visible_rect);
7984 /* Convert rect to "window" coords */
7985 visible_rect.x += child_private->x - x_offset;
7986 visible_rect.y += child_private->y - y_offset;
7988 /* This shortcut is really necessary for performance when there are a lot of windows */
7989 gdk_region_get_clipbox (real_clip_region, &real_clip_rect);
7990 if (visible_rect.x >= real_clip_rect.x + real_clip_rect.width ||
7991 visible_rect.x + visible_rect.width <= real_clip_rect.x ||
7992 visible_rect.y >= real_clip_rect.y + real_clip_rect.height ||
7993 visible_rect.y + visible_rect.height <= real_clip_rect.y)
7996 tmpreg = gdk_region_rectangle (&visible_rect);
7997 gdk_region_subtract (real_clip_region, tmpreg);
7998 gdk_region_destroy (tmpreg);
8001 /* Clip to the parent */
8002 window_get_size_rectangle ((GdkWindow *)parentwin, &visible_rect);
8003 /* Convert rect to "window" coords */
8004 visible_rect.x += - x_offset;
8005 visible_rect.y += - y_offset;
8007 tmpreg = gdk_region_rectangle (&visible_rect);
8008 gdk_region_intersect (real_clip_region, tmpreg);
8009 gdk_region_destroy (tmpreg);
8013 *base_x_offset = x_offset;
8015 *base_y_offset = y_offset;
8017 return real_clip_region;
8021 _gdk_window_add_damage (GdkWindow *toplevel,
8022 GdkRegion *damaged_region)
8024 GdkDisplay *display;
8025 GdkEvent event = { 0, };
8026 event.expose.type = GDK_DAMAGE;
8027 event.expose.window = toplevel;
8028 event.expose.send_event = FALSE;
8029 event.expose.region = damaged_region;
8030 gdk_region_get_clipbox (event.expose.region, &event.expose.area);
8031 display = gdk_drawable_get_display (event.expose.window);
8032 _gdk_event_queue_append (display, gdk_event_copy (&event));
8036 gdk_window_redirect_free (GdkWindowRedirect *redirect)
8038 g_object_unref (redirect->pixmap);
8042 /* Gets the toplevel for a window as used for events,
8043 i.e. including offscreen parents */
8044 static GdkWindowObject *
8045 get_event_parent (GdkWindowObject *window)
8047 if (window->window_type == GDK_WINDOW_OFFSCREEN)
8048 return (GdkWindowObject *)gdk_offscreen_window_get_embedder ((GdkWindow *)window);
8050 return window->parent;
8053 /* Gets the toplevel for a window as used for events,
8054 i.e. including offscreen parents going up to the native
8057 get_event_toplevel (GdkWindow *w)
8059 GdkWindowObject *private = GDK_WINDOW_OBJECT (w);
8060 GdkWindowObject *parent;
8062 while ((parent = get_event_parent (private)) != NULL &&
8063 (parent->window_type != GDK_WINDOW_ROOT))
8066 return GDK_WINDOW (private);
8070 _gdk_window_event_parent_of (GdkWindow *parent,
8081 w = (GdkWindow *)get_event_parent ((GdkWindowObject *)w);
8088 update_cursor (GdkDisplay *display)
8090 GdkWindowObject *pointer_window, *cursor_window, *parent, *toplevel;
8091 GdkPointerGrabInfo *grab;
8093 pointer_window = (GdkWindowObject *)display->pointer_info.window_under_pointer;
8095 cursor_window = pointer_window;
8096 while (cursor_window->cursor == NULL &&
8097 (parent = get_event_parent (cursor_window)) != NULL &&
8098 parent->window_type != GDK_WINDOW_ROOT)
8099 cursor_window = parent;
8101 /* We ignore the serials here and just pick the last grab
8102 we've sent, as that would shortly be used anyway. */
8103 grab = _gdk_display_get_last_pointer_grab (display);
8105 !_gdk_window_event_parent_of (grab->window, (GdkWindow *)cursor_window))
8106 cursor_window = (GdkWindowObject *)grab->window;
8108 /* Set all cursors on toplevel, otherwise its tricky to keep track of
8109 * which native window has what cursor set. */
8110 toplevel = (GdkWindowObject *)get_event_toplevel ((GdkWindow *)pointer_window);
8111 GDK_WINDOW_IMPL_GET_IFACE (toplevel->impl)->set_cursor
8112 ((GdkWindow *)toplevel, cursor_window->cursor);
8116 from_embedder (GdkWindowObject *window,
8117 double embedder_x, double embedder_y,
8118 double *offscreen_x, double *offscreen_y)
8120 g_signal_emit (window,
8121 signals[FROM_EMBEDDER], 0,
8122 embedder_x, embedder_y,
8123 offscreen_x, offscreen_y,
8128 convert_coords_to_child (GdkWindowObject *child,
8130 double *child_x, double *child_y)
8132 if (gdk_window_is_offscreen (child))
8134 from_embedder (child, x, y,
8139 *child_x = x - child->x;
8140 *child_y = y - child->y;
8145 point_in_window (GdkWindowObject *window,
8149 x >= 0 && x < window->width &&
8150 y >= 0 && y < window->height &&
8151 (window->shape == NULL ||
8152 gdk_region_point_in (window->shape,
8154 (window->input_shape == NULL ||
8155 gdk_region_point_in (window->input_shape,
8160 convert_native_coords_to_toplevel (GdkWindow *window,
8161 double child_x, double child_y,
8162 double *toplevel_x, double *toplevel_y)
8164 GdkWindowObject *private = (GdkWindowObject *)window;
8170 while (private->parent != NULL &&
8171 (private->parent->window_type != GDK_WINDOW_ROOT))
8175 private = private->parent;
8181 return (GdkWindow *)private;
8185 convert_toplevel_coords_to_window (GdkWindow *window,
8191 GdkWindowObject *private;
8192 GdkWindowObject *parent;
8194 GList *children, *l;
8196 private = GDK_WINDOW_OBJECT (window);
8202 while ((parent = get_event_parent (private)) != NULL &&
8203 (parent->window_type != GDK_WINDOW_ROOT))
8205 children = g_list_prepend (children, private);
8209 for (l = children; l != NULL; l = l->next)
8210 convert_coords_to_child (l->data, x, y, &x, &y);
8212 g_list_free (children);
8218 static GdkWindowObject *
8219 pick_embedded_child (GdkWindowObject *window,
8222 GdkWindowObject *res;
8225 g_signal_emit (window,
8226 signals[PICK_EMBEDDED_CHILD], 0,
8233 _gdk_window_find_child_at (GdkWindow *window,
8236 GdkWindowObject *private, *sub;
8237 double child_x, child_y;
8240 private = (GdkWindowObject *)window;
8242 if (point_in_window (private, x, y))
8244 /* Children is ordered in reverse stack order, i.e. first is topmost */
8245 for (l = private->children; l != NULL; l = l->next)
8249 if (!GDK_WINDOW_IS_MAPPED (sub))
8252 convert_coords_to_child (sub,
8254 &child_x, &child_y);
8255 if (point_in_window (sub, child_x, child_y))
8256 return (GdkWindow *)sub;
8259 if (private->num_offscreen_children > 0)
8261 sub = pick_embedded_child (private,
8264 return (GdkWindow *)sub;
8272 _gdk_window_find_descendant_at (GdkWindow *toplevel,
8277 GdkWindowObject *private, *sub;
8278 double child_x, child_y;
8282 private = (GdkWindowObject *)toplevel;
8284 if (point_in_window (private, x, y))
8289 /* Children is ordered in reverse stack order, i.e. first is topmost */
8290 for (l = private->children; l != NULL; l = l->next)
8294 if (!GDK_WINDOW_IS_MAPPED (sub))
8297 convert_coords_to_child (sub,
8299 &child_x, &child_y);
8300 if (point_in_window (sub, child_x, child_y))
8310 private->num_offscreen_children > 0)
8312 sub = pick_embedded_child (private,
8318 from_embedder (sub, x, y, &x, &y);
8326 /* Not in window at all */
8335 return (GdkWindow *)private;
8340 * @window: a toplevel #GdkWindow
8342 * Emits a short beep associated to @window in the appropriate
8343 * display, if supported. Otherwise, emits a short beep on
8344 * the display just as gdk_display_beep().
8349 gdk_window_beep (GdkWindow *window)
8351 GdkDisplay *display;
8352 GdkWindow *toplevel;
8354 g_return_if_fail (GDK_IS_WINDOW (window));
8356 if (GDK_WINDOW_DESTROYED (window))
8359 toplevel = get_event_toplevel (window);
8360 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
8362 if (toplevel && gdk_window_is_offscreen ((GdkWindowObject *)toplevel))
8363 _gdk_windowing_window_beep (toplevel);
8365 gdk_display_beep (display);
8368 static const guint type_masks[] = {
8369 GDK_SUBSTRUCTURE_MASK, /* GDK_DELETE = 0 */
8370 GDK_STRUCTURE_MASK, /* GDK_DESTROY = 1 */
8371 GDK_EXPOSURE_MASK, /* GDK_EXPOSE = 2 */
8372 GDK_POINTER_MOTION_MASK, /* GDK_MOTION_NOTIFY = 3 */
8373 GDK_BUTTON_PRESS_MASK, /* GDK_BUTTON_PRESS = 4 */
8374 GDK_BUTTON_PRESS_MASK, /* GDK_2BUTTON_PRESS = 5 */
8375 GDK_BUTTON_PRESS_MASK, /* GDK_3BUTTON_PRESS = 6 */
8376 GDK_BUTTON_RELEASE_MASK, /* GDK_BUTTON_RELEASE = 7 */
8377 GDK_KEY_PRESS_MASK, /* GDK_KEY_PRESS = 8 */
8378 GDK_KEY_RELEASE_MASK, /* GDK_KEY_RELEASE = 9 */
8379 GDK_ENTER_NOTIFY_MASK, /* GDK_ENTER_NOTIFY = 10 */
8380 GDK_LEAVE_NOTIFY_MASK, /* GDK_LEAVE_NOTIFY = 11 */
8381 GDK_FOCUS_CHANGE_MASK, /* GDK_FOCUS_CHANGE = 12 */
8382 GDK_STRUCTURE_MASK, /* GDK_CONFIGURE = 13 */
8383 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_MAP = 14 */
8384 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_UNMAP = 15 */
8385 GDK_PROPERTY_CHANGE_MASK, /* GDK_PROPERTY_NOTIFY = 16 */
8386 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_CLEAR = 17 */
8387 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_REQUEST = 18 */
8388 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_NOTIFY = 19 */
8389 GDK_PROXIMITY_IN_MASK, /* GDK_PROXIMITY_IN = 20 */
8390 GDK_PROXIMITY_OUT_MASK, /* GDK_PROXIMITY_OUT = 21 */
8391 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_ENTER = 22 */
8392 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_LEAVE = 23 */
8393 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_MOTION = 24 */
8394 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_STATUS = 25 */
8395 GDK_ALL_EVENTS_MASK, /* GDK_DROP_START = 26 */
8396 GDK_ALL_EVENTS_MASK, /* GDK_DROP_FINISHED = 27 */
8397 GDK_ALL_EVENTS_MASK, /* GDK_CLIENT_EVENT = 28 */
8398 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_VISIBILITY_NOTIFY = 29 */
8399 GDK_EXPOSURE_MASK, /* GDK_NO_EXPOSE = 30 */
8400 GDK_SCROLL_MASK | GDK_BUTTON_PRESS_MASK,/* GDK_SCROLL= 31 */
8401 0, /* GDK_WINDOW_STATE = 32 */
8402 0, /* GDK_SETTING = 33 */
8403 0, /* GDK_OWNER_CHANGE = 34 */
8404 0, /* GDK_GRAB_BROKEN = 35 */
8405 0, /* GDK_DAMAGE = 36 */
8407 G_STATIC_ASSERT (G_N_ELEMENTS (type_masks) == GDK_EVENT_LAST);
8409 /* send motion events if the right buttons are down */
8411 update_evmask_for_button_motion (guint evmask,
8412 GdkModifierType mask)
8414 if (evmask & GDK_BUTTON_MOTION_MASK &&
8415 mask & (GDK_BUTTON1_MASK |
8420 evmask |= GDK_POINTER_MOTION_MASK;
8422 if ((evmask & GDK_BUTTON1_MOTION_MASK && mask & GDK_BUTTON1_MASK) ||
8423 (evmask & GDK_BUTTON2_MOTION_MASK && mask & GDK_BUTTON2_MASK) ||
8424 (evmask & GDK_BUTTON3_MOTION_MASK && mask & GDK_BUTTON3_MASK))
8425 evmask |= GDK_POINTER_MOTION_MASK;
8431 is_button_type (GdkEventType type)
8433 return type == GDK_BUTTON_PRESS ||
8434 type == GDK_2BUTTON_PRESS ||
8435 type == GDK_3BUTTON_PRESS ||
8436 type == GDK_BUTTON_RELEASE ||
8441 is_motion_type (GdkEventType type)
8443 return type == GDK_MOTION_NOTIFY ||
8444 type == GDK_ENTER_NOTIFY ||
8445 type == GDK_LEAVE_NOTIFY;
8448 static GdkWindowObject *
8449 find_common_ancestor (GdkWindowObject *win1,
8450 GdkWindowObject *win2)
8452 GdkWindowObject *tmp;
8453 GList *path1 = NULL, *path2 = NULL;
8454 GList *list1, *list2;
8457 while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
8459 path1 = g_list_prepend (path1, tmp);
8460 tmp = get_event_parent (tmp);
8464 while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
8466 path2 = g_list_prepend (path2, tmp);
8467 tmp = get_event_parent (tmp);
8473 while (list1 && list2 && (list1->data == list2->data))
8475 tmp = (GdkWindowObject *)list1->data;
8476 list1 = g_list_next (list1);
8477 list2 = g_list_next (list2);
8479 g_list_free (path1);
8480 g_list_free (path2);
8486 _gdk_make_event (GdkWindow *window,
8488 GdkEvent *event_in_queue,
8489 gboolean before_event)
8491 GdkEvent *event = gdk_event_new (type);
8493 GdkModifierType the_state;
8495 the_time = gdk_event_get_time (event_in_queue);
8496 gdk_event_get_state (event_in_queue, &the_state);
8498 event->any.window = g_object_ref (window);
8499 event->any.send_event = FALSE;
8503 case GDK_MOTION_NOTIFY:
8504 event->motion.time = the_time;
8505 event->motion.axes = NULL;
8506 event->motion.state = the_state;
8509 case GDK_BUTTON_PRESS:
8510 case GDK_2BUTTON_PRESS:
8511 case GDK_3BUTTON_PRESS:
8512 case GDK_BUTTON_RELEASE:
8513 event->button.time = the_time;
8514 event->button.axes = NULL;
8515 event->button.state = the_state;
8519 event->scroll.time = the_time;
8520 event->scroll.state = the_state;
8524 case GDK_KEY_RELEASE:
8525 event->key.time = the_time;
8526 event->key.state = the_state;
8529 case GDK_ENTER_NOTIFY:
8530 case GDK_LEAVE_NOTIFY:
8531 event->crossing.time = the_time;
8532 event->crossing.state = the_state;
8535 case GDK_PROPERTY_NOTIFY:
8536 event->property.time = the_time;
8537 event->property.state = the_state;
8540 case GDK_SELECTION_CLEAR:
8541 case GDK_SELECTION_REQUEST:
8542 case GDK_SELECTION_NOTIFY:
8543 event->selection.time = the_time;
8546 case GDK_PROXIMITY_IN:
8547 case GDK_PROXIMITY_OUT:
8548 event->proximity.time = the_time;
8551 case GDK_DRAG_ENTER:
8552 case GDK_DRAG_LEAVE:
8553 case GDK_DRAG_MOTION:
8554 case GDK_DRAG_STATUS:
8555 case GDK_DROP_START:
8556 case GDK_DROP_FINISHED:
8557 event->dnd.time = the_time;
8560 case GDK_FOCUS_CHANGE:
8564 case GDK_CLIENT_EVENT:
8565 case GDK_VISIBILITY_NOTIFY:
8577 _gdk_event_queue_insert_before (gdk_drawable_get_display (window), event_in_queue, event);
8579 _gdk_event_queue_insert_after (gdk_drawable_get_display (window), event_in_queue, event);
8582 _gdk_event_queue_append (gdk_drawable_get_display (window), event);
8588 send_crossing_event (GdkDisplay *display,
8589 GdkWindowObject *toplevel,
8590 GdkWindowObject *window,
8592 GdkCrossingMode mode,
8593 GdkNotifyType notify_type,
8594 GdkWindow *subwindow,
8597 GdkModifierType mask,
8599 GdkEvent *event_in_queue,
8604 GdkPointerGrabInfo *grab;
8606 grab = _gdk_display_has_pointer_grab (display, serial);
8609 !grab->owner_events &&
8610 (GdkWindow *)window != grab->window)
8613 if (type == GDK_LEAVE_NOTIFY)
8614 event_mask = GDK_LEAVE_NOTIFY_MASK;
8616 event_mask = GDK_ENTER_NOTIFY_MASK;
8618 if (window->extension_events != 0)
8619 GDK_WINDOW_IMPL_GET_IFACE (window->impl)->input_window_crossing ((GdkWindow *)window,
8620 type == GDK_ENTER_NOTIFY);
8622 if (window->event_mask & event_mask)
8624 event = _gdk_make_event ((GdkWindow *)window, type, event_in_queue, TRUE);
8625 event->crossing.time = time_;
8626 event->crossing.subwindow = subwindow;
8628 g_object_ref (subwindow);
8629 convert_toplevel_coords_to_window ((GdkWindow *)window,
8630 toplevel_x, toplevel_y,
8631 &event->crossing.x, &event->crossing.y);
8632 event->crossing.x_root = toplevel_x + toplevel->x;
8633 event->crossing.y_root = toplevel_y + toplevel->y;
8634 event->crossing.mode = mode;
8635 event->crossing.detail = notify_type;
8636 event->crossing.focus = FALSE;
8637 event->crossing.state = mask;
8642 /* The coordinates are in the toplevel window that src/dest are in.
8643 * src and dest are always (if != NULL) in the same toplevel, as
8644 * we get a leave-notify and set the window_under_pointer to null
8645 * before crossing to another toplevel.
8648 _gdk_synthesize_crossing_events (GdkDisplay *display,
8651 GdkCrossingMode mode,
8654 GdkModifierType mask,
8656 GdkEvent *event_in_queue,
8658 gboolean non_linear)
8661 GdkWindowObject *win, *last, *next;
8665 GdkWindowObject *toplevel;
8666 GdkNotifyType notify_type;
8668 /* TODO: Don't send events to toplevel, as we get those from the windowing system */
8670 a = (GdkWindowObject *)src;
8671 b = (GdkWindowObject *)dest;
8673 return; /* No crossings generated between src and dest */
8675 c = find_common_ancestor (a, b);
8677 non_linear |= (c != a) && (c != b);
8679 if (a) /* There might not be a source (i.e. if no previous pointer_in_window) */
8681 toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)a);
8683 /* Traverse up from a to (excluding) c sending leave events */
8685 notify_type = GDK_NOTIFY_NONLINEAR;
8687 notify_type = GDK_NOTIFY_INFERIOR;
8689 notify_type = GDK_NOTIFY_ANCESTOR;
8690 send_crossing_event (display, toplevel,
8691 a, GDK_LEAVE_NOTIFY,
8695 toplevel_x, toplevel_y,
8703 notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
8705 notify_type = GDK_NOTIFY_VIRTUAL;
8708 win = get_event_parent (a);
8709 while (win != c && win->window_type != GDK_WINDOW_ROOT)
8711 send_crossing_event (display, toplevel,
8712 win, GDK_LEAVE_NOTIFY,
8716 toplevel_x, toplevel_y,
8722 win = get_event_parent (win);
8727 if (b) /* Might not be a dest, e.g. if we're moving out of the window */
8729 toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)b);
8731 /* Traverse down from c to b */
8735 win = get_event_parent (b);
8736 while (win != c && win->window_type != GDK_WINDOW_ROOT)
8738 path = g_list_prepend (path, win);
8739 win = get_event_parent (win);
8743 notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
8745 notify_type = GDK_NOTIFY_VIRTUAL;
8750 win = (GdkWindowObject *)list->data;
8751 list = g_list_next (list);
8753 next = (GdkWindowObject *)list->data;
8757 send_crossing_event (display, toplevel,
8758 win, GDK_ENTER_NOTIFY,
8762 toplevel_x, toplevel_y,
8772 notify_type = GDK_NOTIFY_NONLINEAR;
8774 notify_type = GDK_NOTIFY_ANCESTOR;
8776 notify_type = GDK_NOTIFY_INFERIOR;
8778 send_crossing_event (display, toplevel,
8779 b, GDK_ENTER_NOTIFY,
8783 toplevel_x, toplevel_y,
8790 /* Returns the window inside the event window with the pointer in it
8791 * at the specified coordinates, or NULL if its not in any child of
8792 * the toplevel. It also takes into account !owner_events grabs.
8795 get_pointer_window (GdkDisplay *display,
8796 GdkWindow *event_window,
8801 GdkWindow *pointer_window;
8802 GdkPointerGrabInfo *grab;
8804 if (event_window == display->pointer_info.toplevel_under_pointer)
8806 _gdk_window_find_descendant_at (event_window,
8807 toplevel_x, toplevel_y,
8810 pointer_window = NULL;
8812 grab = _gdk_display_has_pointer_grab (display, serial);
8814 !grab->owner_events &&
8815 pointer_window != grab->window)
8816 pointer_window = NULL;
8818 return pointer_window;
8822 _gdk_display_set_window_under_pointer (GdkDisplay *display,
8825 GdkWindowObject *private;
8827 private = (GdkWindowObject *)window;
8829 if (display->pointer_info.window_under_pointer)
8830 g_object_unref (display->pointer_info.window_under_pointer);
8831 display->pointer_info.window_under_pointer = window;
8833 g_object_ref (window);
8836 update_cursor (display);
8838 _gdk_display_enable_motion_hints (display);
8842 *--------------------------------------------------------------
8845 * Grabs the pointer to a specific window
8848 * "window" is the window which will receive the grab
8849 * "owner_events" specifies whether events will be reported as is,
8850 * or relative to "window"
8851 * "event_mask" masks only interesting events
8852 * "confine_to" limits the cursor movement to the specified window
8853 * "cursor" changes the cursor for the duration of the grab
8854 * "time" specifies the time
8859 * requires a corresponding call to gdk_pointer_ungrab
8861 *--------------------------------------------------------------
8864 gdk_pointer_grab (GdkWindow * window,
8865 gboolean owner_events,
8866 GdkEventMask event_mask,
8867 GdkWindow * confine_to,
8872 GdkDisplay *display;
8876 g_return_val_if_fail (window != NULL, 0);
8877 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
8878 g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
8880 /* We need a native window for confine to to work, ensure we have one */
8883 if (!gdk_window_ensure_native (confine_to))
8885 g_warning ("Can't confine to grabbed window, not native");
8890 /* Non-viewable client side window => fail */
8891 if (!_gdk_window_has_impl (window) &&
8892 !gdk_window_is_viewable (window))
8893 return GDK_GRAB_NOT_VIEWABLE;
8895 native = gdk_window_get_toplevel (window);
8896 while (gdk_window_is_offscreen ((GdkWindowObject *)native))
8898 native = gdk_offscreen_window_get_embedder (native);
8900 if (native == NULL ||
8901 (!_gdk_window_has_impl (native) &&
8902 !gdk_window_is_viewable (native)))
8903 return GDK_GRAB_NOT_VIEWABLE;
8905 native = gdk_window_get_toplevel (native);
8908 display = gdk_drawable_get_display (window);
8910 serial = _gdk_windowing_window_get_next_serial (display);
8912 res = _gdk_windowing_pointer_grab (window,
8920 if (res == GDK_GRAB_SUCCESS)
8921 _gdk_display_add_pointer_grab (display,
8934 * gdk_window_geometry_changed:
8935 * @window: a #GdkWindow
8940 gdk_window_geometry_changed (GdkWindow *window)
8942 _gdk_synthesize_crossing_events_for_geometry_change (window);
8946 do_synthesize_crossing_event (gpointer data)
8948 GdkDisplay *display;
8949 GdkWindow *changed_toplevel;
8950 GdkWindowObject *changed_toplevel_priv;
8951 GdkWindow *new_window_under_pointer;
8954 changed_toplevel = data;
8955 changed_toplevel_priv = (GdkWindowObject *)changed_toplevel;
8957 changed_toplevel_priv->synthesize_crossing_event_queued = FALSE;
8959 if (GDK_WINDOW_DESTROYED (changed_toplevel))
8962 display = gdk_drawable_get_display (changed_toplevel);
8963 serial = _gdk_windowing_window_get_next_serial (display);
8965 if (changed_toplevel == display->pointer_info.toplevel_under_pointer)
8967 new_window_under_pointer =
8968 get_pointer_window (display, changed_toplevel,
8969 display->pointer_info.toplevel_x,
8970 display->pointer_info.toplevel_y,
8972 if (new_window_under_pointer !=
8973 display->pointer_info.window_under_pointer)
8975 _gdk_synthesize_crossing_events (display,
8976 display->pointer_info.window_under_pointer,
8977 new_window_under_pointer,
8978 GDK_CROSSING_NORMAL,
8979 display->pointer_info.toplevel_x,
8980 display->pointer_info.toplevel_y,
8981 display->pointer_info.state,
8986 _gdk_display_set_window_under_pointer (display, new_window_under_pointer);
8994 _gdk_synthesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
8996 GdkDisplay *display;
8997 GdkWindow *toplevel;
8998 GdkWindowObject *toplevel_priv;
9000 display = gdk_drawable_get_display (changed_window);
9002 toplevel = get_event_toplevel (changed_window);
9003 toplevel_priv = (GdkWindowObject *)toplevel;
9005 if (toplevel == display->pointer_info.toplevel_under_pointer &&
9006 !toplevel_priv->synthesize_crossing_event_queued)
9008 toplevel_priv->synthesize_crossing_event_queued = TRUE;
9009 g_idle_add_full (GDK_PRIORITY_EVENTS - 1,
9010 do_synthesize_crossing_event,
9011 g_object_ref (toplevel),
9016 /* Don't use for crossing events */
9018 get_event_window (GdkDisplay *display,
9019 GdkWindow *pointer_window,
9021 GdkModifierType mask,
9026 GdkWindow *grab_window;
9028 GdkPointerGrabInfo *grab;
9030 grab = _gdk_display_has_pointer_grab (display, serial);
9032 if (grab != NULL && !grab->owner_events)
9034 evmask = grab->event_mask;
9035 evmask = update_evmask_for_button_motion (evmask, mask);
9037 grab_window = grab->window;
9039 if (evmask & type_masks[type])
9042 *evmask_out = evmask;
9049 w = (GdkWindowObject *)pointer_window;
9052 evmask = w->event_mask;
9053 evmask = update_evmask_for_button_motion (evmask, mask);
9055 if (evmask & type_masks[type])
9058 *evmask_out = evmask;
9059 return (GdkWindow *)w;
9062 w = get_event_parent (w);
9068 evmask = grab->event_mask;
9069 evmask = update_evmask_for_button_motion (evmask, mask);
9071 if (evmask & type_masks[type])
9074 *evmask_out = evmask;
9075 return grab->window;
9085 proxy_pointer_event (GdkDisplay *display,
9086 GdkEvent *source_event,
9089 GdkWindow *toplevel_window, *event_window;
9090 GdkWindow *pointer_window;
9093 gdouble toplevel_x, toplevel_y;
9095 gboolean non_linear;
9097 event_window = source_event->any.window;
9098 gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
9099 gdk_event_get_state (source_event, &state);
9100 time_ = gdk_event_get_time (source_event);
9101 toplevel_window = convert_native_coords_to_toplevel (event_window,
9102 toplevel_x, toplevel_y,
9103 &toplevel_x, &toplevel_y);
9106 if ((source_event->type == GDK_LEAVE_NOTIFY ||
9107 source_event->type == GDK_ENTER_NOTIFY) &&
9108 (source_event->crossing.detail == GDK_NOTIFY_NONLINEAR ||
9109 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))
9112 /* If we get crossing events with subwindow unexpectedly being NULL
9113 that means there is a native subwindow that gdk doesn't know about.
9114 We track these and forward them, with the correct virtual window
9116 This is important to get right, as metacity uses gdk for the frame
9117 windows, but gdk doesn't know about the client windows reparented
9119 if (((source_event->type == GDK_LEAVE_NOTIFY &&
9120 source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
9121 (source_event->type == GDK_ENTER_NOTIFY &&
9122 (source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
9123 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
9124 source_event->crossing.subwindow == NULL)
9126 /* Left for an unknown (to gdk) subwindow */
9128 /* Send leave events from window under pointer to event window
9129 that will get the subwindow == NULL window */
9130 _gdk_synthesize_crossing_events (display,
9131 display->pointer_info.window_under_pointer,
9133 source_event->crossing.mode,
9134 toplevel_x, toplevel_y,
9140 /* Send subwindow == NULL event */
9141 send_crossing_event (display,
9142 (GdkWindowObject *)toplevel_window,
9143 (GdkWindowObject *)event_window,
9145 source_event->crossing.mode,
9146 source_event->crossing.detail,
9148 toplevel_x, toplevel_y,
9153 _gdk_display_set_window_under_pointer (display, NULL);
9157 pointer_window = get_pointer_window (display, toplevel_window,
9158 toplevel_x, toplevel_y, serial);
9160 if (((source_event->type == GDK_ENTER_NOTIFY &&
9161 source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
9162 (source_event->type == GDK_LEAVE_NOTIFY &&
9163 (source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
9164 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
9165 source_event->crossing.subwindow == NULL)
9167 /* Entered from an unknown (to gdk) subwindow */
9169 /* Send subwindow == NULL event */
9170 send_crossing_event (display,
9171 (GdkWindowObject *)toplevel_window,
9172 (GdkWindowObject *)event_window,
9174 source_event->crossing.mode,
9175 source_event->crossing.detail,
9177 toplevel_x, toplevel_y,
9182 /* Send enter events from event window to pointer_window */
9183 _gdk_synthesize_crossing_events (display,
9186 source_event->crossing.mode,
9187 toplevel_x, toplevel_y,
9190 serial, non_linear);
9191 _gdk_display_set_window_under_pointer (display, pointer_window);
9195 if (display->pointer_info.window_under_pointer != pointer_window)
9197 /* Either a toplevel crossing notify that ended up inside a child window,
9198 or a motion notify that got into another child window */
9200 /* Different than last time, send crossing events */
9201 _gdk_synthesize_crossing_events (display,
9202 display->pointer_info.window_under_pointer,
9204 GDK_CROSSING_NORMAL,
9205 toplevel_x, toplevel_y,
9208 serial, non_linear);
9209 _gdk_display_set_window_under_pointer (display, pointer_window);
9211 else if (source_event->type == GDK_MOTION_NOTIFY)
9213 GdkWindow *event_win;
9217 event_win = get_event_window (display,
9227 (evmask & GDK_POINTER_MOTION_HINT_MASK))
9229 if (display->pointer_info.motion_hint_serial != 0 &&
9230 serial < display->pointer_info.motion_hint_serial)
9231 event_win = NULL; /* Ignore event */
9235 display->pointer_info.motion_hint_serial = G_MAXULONG;
9239 if (event_win && !display->ignore_core_events)
9241 event = _gdk_make_event (event_win, GDK_MOTION_NOTIFY, source_event, FALSE);
9242 event->motion.time = time_;
9243 convert_toplevel_coords_to_window (event_win,
9244 toplevel_x, toplevel_y,
9245 &event->motion.x, &event->motion.y);
9246 event->motion.x_root = source_event->motion.x_root;
9247 event->motion.y_root = source_event->motion.y_root;;
9248 event->motion.state = state;
9249 event->motion.is_hint = is_hint;
9250 event->motion.device = NULL;
9251 event->motion.device = source_event->motion.device;
9255 /* unlink all move events from queue.
9256 We handle our own, including our emulated masks. */
9260 #define GDK_ANY_BUTTON_MASK (GDK_BUTTON1_MASK | \
9261 GDK_BUTTON2_MASK | \
9262 GDK_BUTTON3_MASK | \
9263 GDK_BUTTON4_MASK | \
9267 proxy_button_event (GdkEvent *source_event,
9270 GdkWindow *toplevel_window, *event_window;
9271 GdkWindow *event_win;
9272 GdkWindow *pointer_window;
9273 GdkWindowObject *parent;
9278 gdouble toplevel_x, toplevel_y;
9279 GdkDisplay *display;
9282 type = source_event->any.type;
9283 event_window = source_event->any.window;
9284 gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
9285 gdk_event_get_state (source_event, &state);
9286 time_ = gdk_event_get_time (source_event);
9287 display = gdk_drawable_get_display (source_event->any.window);
9288 toplevel_window = convert_native_coords_to_toplevel (event_window,
9289 toplevel_x, toplevel_y,
9290 &toplevel_x, &toplevel_y);
9292 if (type == GDK_BUTTON_PRESS &&
9293 _gdk_display_has_pointer_grab (display, serial) == NULL)
9296 _gdk_window_find_descendant_at (toplevel_window,
9297 toplevel_x, toplevel_y,
9300 /* Find the event window, that gets the grab */
9301 w = (GdkWindowObject *)pointer_window;
9303 (parent = get_event_parent (w)) != NULL &&
9304 parent->window_type != GDK_WINDOW_ROOT)
9306 if (w->event_mask & GDK_BUTTON_PRESS_MASK)
9310 pointer_window = (GdkWindow *)w;
9312 _gdk_display_add_pointer_grab (display,
9316 gdk_window_get_events (pointer_window),
9320 _gdk_display_pointer_grab_update (display, serial);
9323 pointer_window = get_pointer_window (display, toplevel_window,
9324 toplevel_x, toplevel_y,
9327 event_win = get_event_window (display,
9332 if (event_win == NULL || display->ignore_core_events)
9335 event = _gdk_make_event (event_win, type, source_event, FALSE);
9339 case GDK_BUTTON_PRESS:
9340 case GDK_BUTTON_RELEASE:
9341 event->button.button = source_event->button.button;
9342 convert_toplevel_coords_to_window (event_win,
9343 toplevel_x, toplevel_y,
9344 &event->button.x, &event->button.y);
9345 event->button.x_root = source_event->button.x_root;
9346 event->button.y_root = source_event->button.y_root;
9347 event->button.state = state;
9348 event->button.device = source_event->button.device;
9350 if (type == GDK_BUTTON_PRESS)
9351 _gdk_event_button_generate (display, event);
9355 event->scroll.direction = source_event->scroll.direction;
9356 convert_toplevel_coords_to_window (event_win,
9357 toplevel_x, toplevel_y,
9358 &event->scroll.x, &event->scroll.y);
9359 event->scroll.x_root = source_event->scroll.x_root;
9360 event->scroll.y_root = source_event->scroll.y_root;
9361 event->scroll.state = state;
9362 event->scroll.device = source_event->scroll.device;
9369 return TRUE; /* Always unlink original, we want to obey the emulated event mask */
9372 #ifdef DEBUG_WINDOW_PRINTING
9374 gdk_window_print (GdkWindowObject *window,
9379 g_print ("%*s%p: [%s] %d,%d %dx%d", indent, "", window,
9380 window->user_data ? g_type_name_from_instance (window->user_data) : "no widget",
9381 window->x, window->y,
9382 window->width, window->height
9385 if (gdk_window_has_impl (window))
9387 #ifdef GDK_WINDOWING_X11
9388 g_print (" impl(0x%lx)", gdk_x11_drawable_get_xid (GDK_DRAWABLE (window)));
9392 if (window->input_only)
9393 g_print (" input-only");
9395 if (!gdk_window_is_visible ((GdkWindow *)window))
9396 g_print (" hidden");
9398 g_print (" abs[%d,%d]",
9399 window->abs_x, window->abs_y);
9401 gdk_region_get_clipbox (window->clip_region, &r);
9402 if (gdk_region_empty (window->clip_region))
9403 g_print (" clipbox[empty]");
9405 g_print (" clipbox[%d,%d %dx%d]", r.x, r.y, r.width, r.height);
9412 gdk_window_print_tree (GdkWindow *window,
9414 gboolean include_input_only)
9416 GdkWindowObject *private;
9419 private = (GdkWindowObject *)window;
9421 if (private->input_only && !include_input_only)
9424 gdk_window_print (private, indent);
9426 for (l = private->children; l != NULL; l = l->next)
9427 gdk_window_print_tree (l->data, indent + 4, include_input_only);
9430 #endif /* DEBUG_WINDOW_PRINTING */
9433 is_input_event (GdkDisplay *display,
9436 GdkDevice *core_pointer;
9438 core_pointer = gdk_display_get_core_pointer (display);
9439 if ((event->type == GDK_MOTION_NOTIFY &&
9440 event->motion.device != core_pointer) ||
9441 ((event->type == GDK_BUTTON_PRESS ||
9442 event->type == GDK_BUTTON_RELEASE) &&
9443 event->button.device != core_pointer))
9449 _gdk_windowing_got_event (GdkDisplay *display,
9454 GdkWindow *event_window;
9455 GdkWindowObject *event_private;
9457 gboolean unlink_event;
9458 guint old_state, old_button;
9459 GdkPointerGrabInfo *button_release_grab;
9460 gboolean is_toplevel;
9462 if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
9463 display->last_event_time = gdk_event_get_time (event);
9465 _gdk_display_pointer_grab_update (display,
9468 event_window = event->any.window;
9472 event_private = GDK_WINDOW_OBJECT (event_window);
9474 #ifdef DEBUG_WINDOW_PRINTING
9475 if (event->type == GDK_KEY_PRESS &&
9476 (event->key.keyval == 0xa7 ||
9477 event->key.keyval == 0xbd))
9479 gdk_window_print_tree (event_window, 0,
9480 event->key.keyval == 0xbd);
9484 if (event->type == GDK_VISIBILITY_NOTIFY)
9486 event_private->native_visibility = event->visibility.state;
9487 gdk_window_update_visibility_recursively (event_private,
9492 if (is_input_event (display, event))
9495 if (!(is_button_type (event->type) ||
9496 is_motion_type (event->type)) ||
9497 event_private->window_type == GDK_WINDOW_ROOT)
9501 event_private->parent == NULL ||
9502 event_private->parent->window_type == GDK_WINDOW_ROOT;
9504 if ((event->type == GDK_ENTER_NOTIFY ||
9505 event->type == GDK_LEAVE_NOTIFY) &&
9506 (event->crossing.mode == GDK_CROSSING_GRAB ||
9507 event->crossing.mode == GDK_CROSSING_UNGRAB) &&
9508 (_gdk_display_has_pointer_grab (display, serial) ||
9509 event->crossing.detail == GDK_NOTIFY_INFERIOR))
9511 /* We synthesize all crossing events due to grabs ourselves,
9512 * so we ignore the native ones caused by our native pointer_grab
9513 * calls. Otherwise we would proxy these crossing event and cause
9514 * multiple copies of crossing events for grabs.
9516 * We do want to handle grabs from other clients though, as for
9517 * instance alt-tab in metacity causes grabs like these and
9518 * we want to handle those. Thus the has_pointer_grab check.
9520 * Implicit grabs on child windows create some grabbing events
9521 * that are sent before the button press. This means we can't
9522 * detect these with the has_pointer_grab check (as the implicit
9523 * grab is only noticed when we get button press event), so we
9524 * detect these events by checking for INFERIOR enter or leave
9525 * events. These should never be a problem to filter out.
9528 /* We ended up in this window after some (perhaps other clients)
9529 grab, so update the toplevel_under_window state */
9531 event->type == GDK_ENTER_NOTIFY &&
9532 event->crossing.mode == GDK_CROSSING_UNGRAB)
9534 if (display->pointer_info.toplevel_under_pointer)
9535 g_object_unref (display->pointer_info.toplevel_under_pointer);
9536 display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
9539 unlink_event = TRUE;
9543 /* Track toplevel_under_pointer */
9546 if (event->type == GDK_ENTER_NOTIFY &&
9547 event->crossing.detail != GDK_NOTIFY_INFERIOR)
9549 if (display->pointer_info.toplevel_under_pointer)
9550 g_object_unref (display->pointer_info.toplevel_under_pointer);
9551 display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
9553 else if (event->type == GDK_LEAVE_NOTIFY &&
9554 event->crossing.detail != GDK_NOTIFY_INFERIOR &&
9555 display->pointer_info.toplevel_under_pointer == event_window)
9557 if (display->pointer_info.toplevel_under_pointer)
9558 g_object_unref (display->pointer_info.toplevel_under_pointer);
9559 display->pointer_info.toplevel_under_pointer = NULL;
9563 /* Store last pointer window and position/state */
9564 old_state = display->pointer_info.state;
9565 old_button = display->pointer_info.button;
9567 gdk_event_get_coords (event, &x, &y);
9568 convert_native_coords_to_toplevel (event_window, x, y, &x, &y);
9569 display->pointer_info.toplevel_x = x;
9570 display->pointer_info.toplevel_y = y;
9571 gdk_event_get_state (event, &display->pointer_info.state);
9572 if (event->type == GDK_BUTTON_PRESS ||
9573 event->type == GDK_BUTTON_RELEASE)
9574 display->pointer_info.button = event->button.button;
9576 if (display->pointer_info.state != old_state ||
9577 display->pointer_info.button != old_button)
9578 _gdk_display_enable_motion_hints (display);
9580 unlink_event = FALSE;
9581 if (is_motion_type (event->type))
9582 unlink_event = proxy_pointer_event (display,
9585 else if (is_button_type (event->type))
9586 unlink_event = proxy_button_event (event,
9589 if (event->type == GDK_BUTTON_RELEASE)
9591 button_release_grab =
9592 _gdk_display_has_pointer_grab (display, serial);
9593 if (button_release_grab &&
9594 button_release_grab->implicit &&
9595 (event->button.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
9597 button_release_grab->serial_end = serial;
9598 button_release_grab->implicit_ungrab = TRUE;
9599 _gdk_display_pointer_grab_update (display, serial);
9606 _gdk_event_queue_remove_link (display, event_link);
9607 g_list_free_1 (event_link);
9608 gdk_event_free (event);
9614 get_extension_event_window (GdkDisplay *display,
9615 GdkWindow *pointer_window,
9620 GdkWindow *grab_window;
9622 GdkPointerGrabInfo *grab;
9624 grab = _gdk_display_has_pointer_grab (display, serial);
9626 if (grab != NULL && !grab->owner_events)
9628 evmask = grab->event_mask;
9630 grab_window = grab->window;
9632 if (evmask & type_masks[type])
9638 w = (GdkWindowObject *)pointer_window;
9641 evmask = w->extension_events;
9643 if (evmask & type_masks[type])
9644 return (GdkWindow *)w;
9646 w = get_event_parent (w);
9652 evmask = grab->event_mask;
9654 if (evmask & type_masks[type])
9655 return grab->window;
9665 _gdk_window_get_input_window_for_event (GdkWindow *native_window,
9666 GdkEventType event_type,
9670 GdkDisplay *display;
9671 GdkWindow *toplevel_window;
9672 GdkWindow *pointer_window;
9673 GdkWindow *event_win;
9674 gdouble toplevel_x, toplevel_y;
9679 display = gdk_drawable_get_display (native_window);
9680 toplevel_window = convert_native_coords_to_toplevel (native_window,
9681 toplevel_x, toplevel_y,
9682 &toplevel_x, &toplevel_y);
9683 pointer_window = get_pointer_window (display, toplevel_window,
9684 toplevel_x, toplevel_y, serial);
9685 event_win = get_extension_event_window (display,
9694 #define __GDK_WINDOW_C__
9695 #include "gdkaliasdef.c"