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"
35 #include "gdkscreen.h"
36 #include "gdkmarshalers.h"
39 #undef DEBUG_WINDOW_PRINTING
41 #ifdef GDK_WINDOWING_X11
42 #include "x11/gdkx.h" /* For workaround */
47 /* Historically a GdkWindow always matches a platform native window,
48 * be it a toplevel window or a child window. In this setup the
49 * GdkWindow (and other GdkDrawables) were platform independent classes,
50 * and the actual platform specific implementation was in a delegate
51 * object availible as "impl" in the window object.
53 * With the addition of client side windows and offscreen windows this
54 * changes a bit. The application-visible GdkWindow object behaves as
55 * it did before, but not all such windows now have a corresponding native
56 * window. Instead windows that are "client side" are emulated by the gdk
57 * code such that clipping, drawing, moving, events etc work as expected.
59 * For GdkWindows that have a native window the "impl" object is the
60 * same as before. However, for all client side windows the impl object
61 * is shared with its parent (i.e. all client windows descendants of one
62 * native window has the same impl.
64 * Additionally there is a new type of platform independent impl object,
65 * GdkOffscreenWindow. All windows of type GDK_WINDOW_OFFSCREEN get an impl
66 * of this type (while their children are generally GDK_WINDOW_CHILD virtual
67 * windows). Such windows work by allocating a GdkPixmap as the backing store
68 * for drawing operations, which is resized with the window.
70 * GdkWindows have a pointer to the "impl window" they are in, i.e.
71 * the topmost GdkWindow which have the same "impl" value. This is stored
72 * in impl_window, which is different from the window itself only for client
74 * All GdkWindows (native or not) track the position of the window in the parent
75 * (x, y), the size of the window (width, height), the position of the window
76 * with respect to the impl window (abs_x, abs_y). We also track the clip
77 * region of the window wrt parent windows and siblings, in window-relative
78 * coordinates with and without child windows included (clip_region,
79 * clip_region_with_children).
81 * All toplevel windows are native windows, but also child windows can be
82 * native (although not children of offscreens). We always listen to
83 * a basic set of events (see get_native_event_mask) for these windows
84 * so that we can emulate events for any client side children.
86 * For native windows we apply the calculated clip region as a window shape
87 * so that eg. client side siblings that overlap the native child properly
88 * draws over the native child window.
90 * In order to minimize flicker and for performance we use a couple of cacheing
91 * tricks. First of all, every time we do a window to window copy area, for instance
92 * when moving a client side window or when scrolling/moving a region in a window
93 * we store this in outstanding_moves instead of applying immediately. We then
94 * delay this move until we really need it (because something depends on being
95 * able to read it), or until we're handing a redraw from an expose/invalidation
96 * (actually we delay it past redraw, but before blitting the double buffer pixmap
97 * to the window). This gives us two advantages. First of all it minimizes the time
98 * from the window is moved to the exposes related to that move, secondly it allows
99 * us to be smart about how to do the copy. We combine multiple moves into one (when
100 * possible) and we don't actually do copies to anything that is or will be
101 * invalidated and exposed anyway.
103 * Secondly, we use something called a "implicit paint" during repaint handling.
104 * An implicit paint is similar to a regular paint for the paint stack, but it is
105 * not put on the stack. Instead, it is set on the impl window, and later when
106 * regular gdk_window_begin_paint_region() happen on a window of this impl window
107 * we reuse the pixmap from the implicit paint. During repaint we create and at the
108 * end flush an implicit paint, which means we can collect all the paints on
109 * multiple client side windows in the same backing store pixmap.
111 * All drawing to windows are wrapped with macros that set up the GC such that
112 * the offsets and clip region is right for drawing to the paint object or
113 * directly to the emulated window. It also automatically handles any flushing
114 * needed when drawing directly to a window. Adding window/paint clipping is
115 * done using _gdk_gc_add_drawable_clip which lets us efficiently add and then
116 * remove a custom clip region.
119 #define USE_BACKING_STORE /* Appears to work on Win32, too, now. */
121 /* This adds a local value to the GdkVisibilityState enum */
122 #define GDK_VISIBILITY_NOT_VIEWABLE 3
125 PICK_EMBEDDED_CHILD, /* only called if children are embedded */
131 struct _GdkWindowPaint
137 cairo_surface_t *surface;
138 guint uses_implicit : 1;
143 GdkRegion *dest_region; /* The destination region */
144 int dx, dy; /* The amount that the source was moved to reach dest_region */
145 } GdkWindowRegionMove;
150 static GdkGC *gdk_window_create_gc (GdkDrawable *drawable,
152 GdkGCValuesMask mask);
153 static void gdk_window_draw_rectangle (GdkDrawable *drawable,
160 static void gdk_window_draw_arc (GdkDrawable *drawable,
169 static void gdk_window_draw_polygon (GdkDrawable *drawable,
174 static void gdk_window_draw_text (GdkDrawable *drawable,
181 static void gdk_window_draw_text_wc (GdkDrawable *drawable,
186 const GdkWChar *text,
188 static void gdk_window_draw_drawable (GdkDrawable *drawable,
197 GdkDrawable *original_src);
198 static void gdk_window_draw_points (GdkDrawable *drawable,
202 static void gdk_window_draw_segments (GdkDrawable *drawable,
206 static void gdk_window_draw_lines (GdkDrawable *drawable,
211 static void gdk_window_draw_glyphs (GdkDrawable *drawable,
216 PangoGlyphString *glyphs);
217 static void gdk_window_draw_glyphs_transformed (GdkDrawable *drawable,
223 PangoGlyphString *glyphs);
225 static void gdk_window_draw_image (GdkDrawable *drawable,
235 static void gdk_window_draw_pixbuf (GdkDrawable *drawable,
248 static void gdk_window_draw_trapezoids (GdkDrawable *drawable,
250 GdkTrapezoid *trapezoids,
253 static GdkImage* gdk_window_copy_to_image (GdkDrawable *drawable,
262 static cairo_surface_t *gdk_window_ref_cairo_surface (GdkDrawable *drawable);
263 static cairo_surface_t *gdk_window_create_cairo_surface (GdkDrawable *drawable,
266 static void gdk_window_set_cairo_clip (GdkDrawable *drawable,
269 static void gdk_window_real_get_size (GdkDrawable *drawable,
273 static GdkVisual* gdk_window_real_get_visual (GdkDrawable *drawable);
274 static gint gdk_window_real_get_depth (GdkDrawable *drawable);
275 static GdkScreen* gdk_window_real_get_screen (GdkDrawable *drawable);
276 static void gdk_window_real_set_colormap (GdkDrawable *drawable,
278 static GdkColormap* gdk_window_real_get_colormap (GdkDrawable *drawable);
280 static GdkDrawable* gdk_window_get_source_drawable (GdkDrawable *drawable);
281 static GdkDrawable* gdk_window_get_composite_drawable (GdkDrawable *drawable,
286 gint *composite_x_offset,
287 gint *composite_y_offset);
288 static GdkRegion* gdk_window_get_clip_region (GdkDrawable *drawable);
289 static GdkRegion* gdk_window_get_visible_region (GdkDrawable *drawable);
291 static void gdk_window_free_paint_stack (GdkWindow *window);
293 static void gdk_window_init (GdkWindowObject *window);
294 static void gdk_window_class_init (GdkWindowObjectClass *klass);
295 static void gdk_window_finalize (GObject *object);
296 static void gdk_window_clear_backing_region (GdkWindow *window,
298 static void gdk_window_redirect_free (GdkWindowRedirect *redirect);
299 static void apply_redirect_to_children (GdkWindowObject *private,
300 GdkWindowRedirect *redirect);
301 static void remove_redirect_from_children (GdkWindowObject *private,
302 GdkWindowRedirect *redirect);
304 static void recompute_visible_regions (GdkWindowObject *private,
305 gboolean recalculate_siblings,
306 gboolean recalculate_children);
307 static void gdk_window_flush_outstanding_moves (GdkWindow *window);
308 static void gdk_window_flush (GdkWindow *window);
309 static void gdk_window_flush_recursive (GdkWindowObject *window);
310 static void do_move_region_bits_on_impl (GdkWindowObject *private,
311 GdkRegion *region, /* In impl window coords */
313 static void gdk_window_invalidate_in_parent (GdkWindowObject *private);
314 static void move_native_children (GdkWindowObject *private);
315 static void update_cursor (GdkDisplay *display);
317 static guint signals[LAST_SIGNAL] = { 0 };
319 static gpointer parent_class = NULL;
321 static const cairo_user_data_key_t gdk_window_cairo_key;
324 new_region_tag (void)
326 static guint32 tag = 0;
332 gdk_window_object_get_type (void)
334 static GType object_type = 0;
337 object_type = g_type_register_static_simple (GDK_TYPE_DRAWABLE,
339 sizeof (GdkWindowObjectClass),
340 (GClassInitFunc) gdk_window_class_init,
341 sizeof (GdkWindowObject),
342 (GInstanceInitFunc) gdk_window_init,
349 _gdk_paintable_get_type (void)
351 static GType paintable_type = 0;
355 const GTypeInfo paintable_info =
357 sizeof (GdkPaintableIface), /* class_size */
358 NULL, /* base_init */
359 NULL, /* base_finalize */
362 paintable_type = g_type_register_static (G_TYPE_INTERFACE,
363 g_intern_static_string ("GdkPaintable"),
366 g_type_interface_add_prerequisite (paintable_type, G_TYPE_OBJECT);
369 return paintable_type;
373 gdk_window_init (GdkWindowObject *window)
375 /* 0-initialization is good for all other fields. */
377 window->window_type = GDK_WINDOW_CHILD;
379 window->state = GDK_WINDOW_STATE_WITHDRAWN;
382 window->toplevel_window_type = -1;
384 window->effective_visibility = GDK_VISIBILITY_NOT_VIEWABLE;
385 window->visibility = GDK_VISIBILITY_FULLY_OBSCURED;
386 /* Default to unobscured since some backends don't send visibility events */
387 window->native_visibility = GDK_VISIBILITY_UNOBSCURED;
390 /* Stop and return on the first non-NULL parent */
392 accumulate_get_window (GSignalInvocationHint *ihint,
394 const GValue *handler_return,
397 g_value_copy (handler_return, return_accu);
398 /* Continue while returning NULL */
399 return g_value_get_object (handler_return) == NULL;
402 static GQuark quark_pointer_window = 0;
405 gdk_window_class_init (GdkWindowObjectClass *klass)
407 GObjectClass *object_class = G_OBJECT_CLASS (klass);
408 GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
410 parent_class = g_type_class_peek_parent (klass);
412 object_class->finalize = gdk_window_finalize;
414 drawable_class->create_gc = gdk_window_create_gc;
415 drawable_class->draw_rectangle = gdk_window_draw_rectangle;
416 drawable_class->draw_arc = gdk_window_draw_arc;
417 drawable_class->draw_polygon = gdk_window_draw_polygon;
418 drawable_class->draw_text = gdk_window_draw_text;
419 drawable_class->draw_text_wc = gdk_window_draw_text_wc;
420 drawable_class->draw_drawable_with_src = gdk_window_draw_drawable;
421 drawable_class->draw_points = gdk_window_draw_points;
422 drawable_class->draw_segments = gdk_window_draw_segments;
423 drawable_class->draw_lines = gdk_window_draw_lines;
424 drawable_class->draw_glyphs = gdk_window_draw_glyphs;
425 drawable_class->draw_glyphs_transformed = gdk_window_draw_glyphs_transformed;
426 drawable_class->draw_image = gdk_window_draw_image;
427 drawable_class->draw_pixbuf = gdk_window_draw_pixbuf;
428 drawable_class->draw_trapezoids = gdk_window_draw_trapezoids;
429 drawable_class->get_depth = gdk_window_real_get_depth;
430 drawable_class->get_screen = gdk_window_real_get_screen;
431 drawable_class->get_size = gdk_window_real_get_size;
432 drawable_class->set_colormap = gdk_window_real_set_colormap;
433 drawable_class->get_colormap = gdk_window_real_get_colormap;
434 drawable_class->get_visual = gdk_window_real_get_visual;
435 drawable_class->_copy_to_image = gdk_window_copy_to_image;
436 drawable_class->ref_cairo_surface = gdk_window_ref_cairo_surface;
437 drawable_class->create_cairo_surface = gdk_window_create_cairo_surface;
438 drawable_class->set_cairo_clip = gdk_window_set_cairo_clip;
439 drawable_class->get_clip_region = gdk_window_get_clip_region;
440 drawable_class->get_visible_region = gdk_window_get_visible_region;
441 drawable_class->get_composite_drawable = gdk_window_get_composite_drawable;
442 drawable_class->get_source_drawable = gdk_window_get_source_drawable;
444 quark_pointer_window = g_quark_from_static_string ("gtk-pointer-window");
448 * GdkWindow::pick-embedded-child:
449 * @window: the window on which the signal is emitted
450 * @x: x coordinate in the window
451 * @y: y coordinate in the window
453 * The ::pick-embedded-child signal is emitted to find an embedded
454 * child at the given position.
456 * Returns: the GdkWindow of the embedded child at @x, @y, or %NULL
460 signals[PICK_EMBEDDED_CHILD] =
461 g_signal_new (g_intern_static_string ("pick-embedded-child"),
462 G_OBJECT_CLASS_TYPE (object_class),
465 accumulate_get_window, NULL,
466 _gdk_marshal_OBJECT__DOUBLE_DOUBLE,
473 * GdkWindow::to-embedder:
474 * @window: the offscreen window on which the signal is emitted
475 * @offscreen-x: x coordinate in the offscreen window
476 * @offscreen-y: y coordinate in the offscreen window
477 * @embedder-x: return location for the x coordinate in the embedder window
478 * @embedder-y: return location for the y coordinate in the embedder window
480 * The ::to-embedder signal is emitted to translate coordinates
481 * in an offscreen window to its embedder.
485 signals[TO_EMBEDDER] =
486 g_signal_new (g_intern_static_string ("to-embedder"),
487 G_OBJECT_CLASS_TYPE (object_class),
491 _gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
500 * GdkWindow::from-embedder:
501 * @window: the offscreen window on which the signal is emitted
502 * @embedder-x: x coordinate in the embedder window
503 * @embedder-y: y coordinate in the embedder window
504 * @offscreen-x: return location for the x coordinate in the offscreen window
505 * @offscreen-y: return location for the y coordinate in the offscreen window
507 * The ::from-embedder signal is emitted to translate coordinates
508 * in the embedder of an offscreen window to the offscreen window.
512 signals[FROM_EMBEDDER] =
513 g_signal_new (g_intern_static_string ("from-embedder"),
514 G_OBJECT_CLASS_TYPE (object_class),
518 _gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
528 gdk_window_finalize (GObject *object)
530 GdkWindow *window = GDK_WINDOW (object);
531 GdkWindowObject *obj = (GdkWindowObject *) object;
533 if (!GDK_WINDOW_DESTROYED (window))
535 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
537 g_warning ("losing last reference to undestroyed window\n");
538 _gdk_window_destroy (window, FALSE);
541 /* We use TRUE here, to keep us from actually calling
542 * XDestroyWindow() on the window
544 _gdk_window_destroy (window, TRUE);
549 g_object_unref (obj->impl);
553 if (obj->impl_window != obj)
555 g_object_unref (obj->impl_window);
556 obj->impl_window = NULL;
560 gdk_region_destroy (obj->shape);
562 if (obj->input_shape)
563 gdk_region_destroy (obj->input_shape);
566 gdk_cursor_unref (obj->cursor);
568 G_OBJECT_CLASS (parent_class)->finalize (object);
572 gdk_window_is_offscreen (GdkWindowObject *window)
574 return GDK_WINDOW_TYPE (window) == GDK_WINDOW_OFFSCREEN;
577 static GdkWindowObject *
578 gdk_window_get_impl_window (GdkWindowObject *window)
580 return window->impl_window;
584 _gdk_window_get_impl_window (GdkWindow *window)
586 return (GdkWindow *)gdk_window_get_impl_window ((GdkWindowObject *)window);
590 gdk_window_has_impl (GdkWindowObject *window)
592 return window->impl_window == window;
596 _gdk_window_has_impl (GdkWindow *window)
598 return gdk_window_has_impl ((GdkWindowObject *)window);
602 gdk_window_has_no_impl (GdkWindowObject *window)
604 return window->impl_window != window;
608 remove_child_area (GdkWindowObject *private,
609 GdkWindowObject *until,
613 GdkWindowObject *child;
614 GdkRegion *child_region;
619 for (l = private->children; l; l = l->next)
626 if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
629 /* Ignore offscreen children, as they don't draw in their parent and
630 * don't take part in the clipping */
631 if (gdk_window_is_offscreen (child))
636 r.width = child->width;
637 r.height = child->height;
639 child_region = gdk_region_rectangle (&r);
643 /* Adjust shape region to parent window coords */
644 gdk_region_offset (child->shape, child->x, child->y);
645 gdk_region_intersect (child_region, child->shape);
646 gdk_region_offset (child->shape, -child->x, -child->y);
648 else if (private->window_type == GDK_WINDOW_FOREIGN)
650 shape = _gdk_windowing_window_get_shape ((GdkWindow *)child);
653 gdk_region_intersect (child_region, shape);
654 gdk_region_destroy (shape);
660 if (child->input_shape)
661 gdk_region_intersect (child_region, child->input_shape);
662 else if (private->window_type == GDK_WINDOW_FOREIGN)
664 shape = _gdk_windowing_window_get_input_shape ((GdkWindow *)child);
667 gdk_region_intersect (child_region, shape);
668 gdk_region_destroy (shape);
673 gdk_region_subtract (region, child_region);
674 gdk_region_destroy (child_region);
679 static GdkVisibilityState
680 effective_visibility (GdkWindowObject *private)
682 GdkVisibilityState native;
684 if (!gdk_window_is_viewable ((GdkWindow *)private))
685 return GDK_VISIBILITY_NOT_VIEWABLE;
687 native = private->impl_window->native_visibility;
689 if (native == GDK_VISIBILITY_FULLY_OBSCURED ||
690 private->visibility == GDK_VISIBILITY_FULLY_OBSCURED)
691 return GDK_VISIBILITY_FULLY_OBSCURED;
692 else if (native == GDK_VISIBILITY_UNOBSCURED)
693 return private->visibility;
694 else /* native PARTIAL, private partial or unobscured */
695 return GDK_VISIBILITY_PARTIAL;
699 gdk_window_update_visibility (GdkWindowObject *private)
701 GdkVisibilityState new_visibility;
704 new_visibility = effective_visibility (private);
706 if (new_visibility != private->effective_visibility)
708 private->effective_visibility = new_visibility;
710 if (new_visibility != GDK_VISIBILITY_NOT_VIEWABLE &&
711 private->event_mask & GDK_VISIBILITY_NOTIFY)
713 event = _gdk_make_event ((GdkWindow *)private, GDK_VISIBILITY_NOTIFY,
715 event->visibility.state = new_visibility;
721 gdk_window_update_visibility_recursively (GdkWindowObject *private,
722 GdkWindowObject *only_for_impl)
724 GdkWindowObject *child;
727 gdk_window_update_visibility (private);
728 for (l = private->children; l != NULL; l = l->next)
731 if ((only_for_impl == NULL) ||
732 (only_for_impl == child->impl_window))
733 gdk_window_update_visibility_recursively (child, only_for_impl);
738 recompute_visible_regions_internal (GdkWindowObject *private,
739 gboolean recalculate_clip,
740 gboolean recalculate_siblings,
741 gboolean recalculate_children)
745 GdkWindowObject *child;
746 GdkRegion *new_clip, *old_clip_region_with_children;
747 gboolean clip_region_changed;
748 gboolean abs_pos_changed;
749 int old_abs_x, old_abs_y;
751 old_abs_x = private->abs_x;
752 old_abs_y = private->abs_y;
754 /* Update absolute position */
755 if (gdk_window_has_impl (private))
757 /* Native window starts here */
763 private->abs_x = private->parent->abs_x + private->x;
764 private->abs_y = private->parent->abs_y + private->y;
768 private->abs_x != old_abs_x ||
769 private->abs_y != old_abs_y;
771 /* Update clip region based on:
774 * siblings in parents above window
776 clip_region_changed = FALSE;
777 if (recalculate_clip)
779 /* Calculate visible region (sans children) in parent window coords */
782 r.width = private->width;
783 r.height = private->height;
784 new_clip = gdk_region_rectangle (&r);
786 if (private->parent != NULL && GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
788 gdk_region_intersect (new_clip, private->parent->clip_region);
790 /* Remove all overlapping children from parent */
791 remove_child_area (private->parent, private, FALSE, new_clip);
794 /* Convert from parent coords to window coords */
795 gdk_region_offset (new_clip, -private->x, -private->y);
798 gdk_region_intersect (new_clip, private->shape);
800 if (private->clip_region == NULL ||
801 !gdk_region_equal (private->clip_region, new_clip))
802 clip_region_changed = TRUE;
804 if (private->clip_region)
805 gdk_region_destroy (private->clip_region);
806 private->clip_region = new_clip;
808 old_clip_region_with_children = private->clip_region_with_children;
809 private->clip_region_with_children = gdk_region_copy (private->clip_region);
810 if (GDK_WINDOW_TYPE (private) != GDK_WINDOW_ROOT)
811 remove_child_area (private, NULL, FALSE, private->clip_region_with_children);
813 if (clip_region_changed ||
814 !gdk_region_equal (private->clip_region_with_children, old_clip_region_with_children))
815 private->clip_tag = new_region_tag ();
817 if (old_clip_region_with_children)
818 gdk_region_destroy (old_clip_region_with_children);
821 if (clip_region_changed)
823 GdkVisibilityState visibility;
824 gboolean fully_visible;
826 if (gdk_region_empty (private->clip_region))
827 visibility = GDK_VISIBILITY_FULLY_OBSCURED;
830 fully_visible = gdk_region_equal (private->clip_region,
836 r.width = private->width;
837 r.height = private->height;
838 fully_visible = gdk_region_rect_equal (private->clip_region, &r);
842 visibility = GDK_VISIBILITY_UNOBSCURED;
844 visibility = GDK_VISIBILITY_PARTIAL;
847 if (private->visibility != visibility)
849 private->visibility = visibility;
850 gdk_window_update_visibility (private);
854 /* Update all children, recursively (except for root, where children are not exact). */
855 if ((abs_pos_changed || clip_region_changed || recalculate_children) &&
856 GDK_WINDOW_TYPE (private) != GDK_WINDOW_ROOT)
858 for (l = private->children; l; l = l->next)
861 /* Only recalculate clip if the the clip region changed, otherwise
862 * there is no way the child clip region could change (its has not e.g. moved)
863 * Except if recalculate_children is set to force child updates
865 recompute_visible_regions_internal (child, recalculate_clip && (clip_region_changed || recalculate_children), FALSE, FALSE);
869 if (clip_region_changed &&
870 gdk_window_has_impl (private) &&
871 /* Not for offscreens */
872 private->window_type != GDK_WINDOW_OFFSCREEN &&
873 /* or for non-shaped toplevels */
875 (private->parent != NULL &&
876 GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)) &&
877 /* or for foreign windows */
878 GDK_WINDOW_TYPE (private) != GDK_WINDOW_FOREIGN &&
879 /* or for the root window */
880 GDK_WINDOW_TYPE (private) != GDK_WINDOW_ROOT
883 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region ((GdkWindow *)private, private->clip_region, 0, 0);
886 if (recalculate_siblings &&
887 private->parent != NULL &&
888 GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
890 /* If we moved a child window in parent or changed the stacking order, then we
891 * need to recompute the visible area of all the other children in the parent
893 for (l = private->parent->children; l; l = l->next)
897 if (child != private)
898 recompute_visible_regions_internal (child, TRUE, FALSE, FALSE);
901 /* We also need to recompute the _with_children clip for the parent */
902 recompute_visible_regions_internal (private->parent, TRUE, FALSE, FALSE);
905 if (private->cairo_surface)
909 /* It would be nice if we had some cairo support here so we
910 could set the clip rect on the cairo surface */
911 width = private->abs_x + private->width;
912 height = private->abs_y + private->height;
914 _gdk_windowing_set_cairo_surface_size (private->cairo_surface,
916 cairo_surface_set_device_offset (private->cairo_surface,
922 /* Call this when private has changed in one or more of these ways:
926 * stacking order of window changed
929 * It will recalculate abs_x/y and the clip regions
931 * Unless the window didn't change stacking order or size/pos, pass in TRUE
932 * for recalculate_siblings. (Mostly used internally for the recursion)
934 * If a child window was removed (and you can't use that child for
935 * recompute_visible_regions), pass in TRUE for recalculate_children on the parent
938 recompute_visible_regions (GdkWindowObject *private,
939 gboolean recalculate_siblings,
940 gboolean recalculate_children)
942 recompute_visible_regions_internal (private,
944 recalculate_siblings,
945 recalculate_children);
949 _gdk_window_update_size (GdkWindow *window)
951 recompute_visible_regions ((GdkWindowObject *)window, TRUE, FALSE);
954 /* Find the native window that would be just above "child"
955 * in the native stacking order if "child" was a native window
956 * (it doesn't have to be native). If there is no such native
957 * window inside this native parent then NULL is returned.
958 * If child is NULL, find lowest native window in parent.
960 static GdkWindowObject *
961 find_native_sibling_above_helper (GdkWindowObject *parent,
962 GdkWindowObject *child)
969 l = g_list_find (parent->children, child);
970 g_assert (l != NULL); /* Better be a child of its parent... */
971 l = l->prev; /* Start looking at the one above the child */
974 l = g_list_last (parent->children);
976 for (; l != NULL; l = l->prev)
980 if (gdk_window_has_impl (w))
983 g_assert (parent != w);
984 w = find_native_sibling_above_helper (w, NULL);
993 static GdkWindowObject *
994 find_native_sibling_above (GdkWindowObject *parent,
995 GdkWindowObject *child)
999 w = find_native_sibling_above_helper (parent, child);
1003 if (gdk_window_has_impl (parent))
1006 return find_native_sibling_above (parent->parent, parent);
1010 get_native_event_mask (GdkWindowObject *private)
1012 if (private->window_type != GDK_WINDOW_ROOT &&
1013 private->window_type != GDK_WINDOW_FOREIGN)
1016 /* We need thse for all native window so we can emulate
1017 events on children: */
1019 GDK_VISIBILITY_NOTIFY_MASK |
1020 GDK_POINTER_MOTION_MASK |
1021 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
1022 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
1024 /* Then do whatever the app asks to, since the app
1025 * may be asking for weird things for native windows,
1026 * but filter out things that override the above
1027 * requests somehow. */
1028 (private->event_mask &
1029 ~(GDK_POINTER_MOTION_HINT_MASK |
1030 GDK_BUTTON_MOTION_MASK |
1031 GDK_BUTTON1_MOTION_MASK |
1032 GDK_BUTTON2_MOTION_MASK |
1033 GDK_BUTTON3_MOTION_MASK));
1036 return private->event_mask;
1039 /* Puts the native window in the right order wrt the other native windows
1040 in the hierarchy, given the position it has in the client side data.
1041 This is useful if some operation changed the stacking order. */
1043 sync_native_window_stack_position (GdkWindow *window)
1045 GdkWindowObject *above;
1046 GdkWindowObject *private;
1047 GList listhead = {0};
1049 private = (GdkWindowObject *) window;
1051 above = find_native_sibling_above (private->parent, private);
1054 listhead.data = window;
1055 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
1062 * @parent: a #GdkWindow, or %NULL to create the window as a child of
1063 * the default root window for the default display.
1064 * @attributes: attributes of the new window
1065 * @attributes_mask: mask indicating which fields in @attributes are valid
1067 * Creates a new #GdkWindow using the attributes from
1068 * @attributes. See #GdkWindowAttr and #GdkWindowAttributesType for
1069 * more details. Note: to use this on displays other than the default
1070 * display, @parent must be specified.
1072 * Return value: the new #GdkWindow
1075 gdk_window_new (GdkWindow *parent,
1076 GdkWindowAttr *attributes,
1077 gint attributes_mask)
1080 GdkWindowObject *private;
1085 GdkEventMask event_mask;
1086 GdkWindow *real_parent;
1088 g_return_val_if_fail (attributes != NULL, NULL);
1092 GDK_NOTE (MULTIHEAD,
1093 g_warning ("gdk_window_new(): no parent specified reverting to parent = default root window"));
1095 screen = gdk_screen_get_default ();
1096 parent = gdk_screen_get_root_window (screen);
1099 screen = gdk_drawable_get_screen (parent);
1101 g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
1103 if (GDK_WINDOW_DESTROYED (parent))
1106 window = g_object_new (GDK_TYPE_WINDOW, NULL);
1107 private = (GdkWindowObject *) window;
1109 /* Windows with a foreign parent are treated as if they are children
1110 * of the root window, except for actual creation.
1112 real_parent = parent;
1113 if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
1114 parent = gdk_screen_get_root_window (screen);
1116 private->parent = (GdkWindowObject *)parent;
1118 private->accept_focus = TRUE;
1119 private->focus_on_map = TRUE;
1121 if (attributes_mask & GDK_WA_X)
1126 if (attributes_mask & GDK_WA_Y)
1133 private->width = (attributes->width > 1) ? (attributes->width) : (1);
1134 private->height = (attributes->height > 1) ? (attributes->height) : (1);
1136 #ifdef GDK_WINDOWING_X11
1137 /* Work around a bug where Xorg refuses to map toplevel InputOnly windows
1138 * from an untrusted client: http://bugs.freedesktop.org/show_bug.cgi?id=6988
1140 if (attributes->wclass == GDK_INPUT_ONLY &&
1141 GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT &&
1142 !G_LIKELY (GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (parent))->trusted_client))
1144 g_warning ("Coercing GDK_INPUT_ONLY toplevel window to GDK_INPUT_OUTPUT to work around bug in Xorg server");
1145 attributes->wclass = GDK_INPUT_OUTPUT;
1149 if (attributes->wclass == GDK_INPUT_ONLY)
1151 /* Backwards compatiblity - we've always ignored
1152 * attributes->window_type for input-only windows
1155 if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
1156 private->window_type = GDK_WINDOW_TEMP;
1158 private->window_type = GDK_WINDOW_CHILD;
1161 private->window_type = attributes->window_type;
1164 switch (private->window_type)
1166 case GDK_WINDOW_TOPLEVEL:
1167 case GDK_WINDOW_DIALOG:
1168 case GDK_WINDOW_TEMP:
1169 case GDK_WINDOW_OFFSCREEN:
1170 if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
1171 g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
1172 "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
1173 case GDK_WINDOW_CHILD:
1177 g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
1181 if (attributes_mask & GDK_WA_VISUAL)
1182 visual = attributes->visual;
1184 visual = gdk_screen_get_system_visual (screen);
1186 private->event_mask = attributes->event_mask;
1188 if (attributes->wclass == GDK_INPUT_OUTPUT)
1190 private->input_only = FALSE;
1191 private->depth = visual->depth;
1193 private->bg_color.pixel = 0; // TODO: BlackPixel (xdisplay, screen_x11->screen_num);
1194 private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
1196 private->bg_pixmap = NULL;
1201 private->input_only = TRUE;
1204 if (private->parent)
1205 private->parent->children = g_list_prepend (private->parent->children, window);
1207 native = FALSE; /* Default */
1208 if (GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
1209 native = TRUE; /* Always use native windows for toplevels */
1210 else if (!private->input_only &&
1211 ((attributes_mask & GDK_WA_COLORMAP &&
1212 attributes->colormap != gdk_drawable_get_colormap ((GdkDrawable *)private->parent)) ||
1213 (attributes_mask & GDK_WA_VISUAL &&
1214 attributes->visual != gdk_drawable_get_visual ((GdkDrawable *)private->parent))))
1215 native = TRUE; /* InputOutput window with different colormap or visual than parent, needs native window */
1217 if (private->window_type == GDK_WINDOW_OFFSCREEN)
1219 _gdk_offscreen_window_new (window, screen, visual, attributes, attributes_mask);
1220 private->impl_window = private;
1224 event_mask = get_native_event_mask (private);
1226 /* Create the impl */
1227 _gdk_window_impl_new (window, real_parent, screen, visual, event_mask, attributes, attributes_mask);
1228 private->impl_window = private;
1230 /* This will put the native window topmost in the native parent, which may
1231 * be wrong wrt other native windows in the non-native hierarchy, so restack */
1232 sync_native_window_stack_position (window);
1236 private->impl_window = g_object_ref (private->parent->impl_window);
1237 private->impl = g_object_ref (private->impl_window->impl);
1240 recompute_visible_regions (private, TRUE, FALSE);
1242 if (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
1244 /* Inherit redirection from parent */
1245 private->redirect = private->parent->redirect;
1248 gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
1249 (attributes->cursor) :
1256 is_parent_of (GdkWindow *parent,
1267 w = gdk_window_get_parent (w);
1274 change_impl (GdkWindowObject *private,
1275 GdkWindowObject *impl_window,
1279 GdkWindowObject *child;
1280 GdkDrawable *old_impl;
1281 GdkWindowObject *old_impl_window;
1283 old_impl = private->impl;
1284 old_impl_window = private->impl_window;
1285 if (private != impl_window)
1286 private->impl_window = g_object_ref (impl_window);
1288 private->impl_window = private;
1289 private->impl = g_object_ref (new);
1290 if (old_impl_window != private)
1291 g_object_unref (old_impl_window);
1292 g_object_unref (old_impl);
1294 for (l = private->children; l != NULL; l = l->next)
1298 if (child->impl == old_impl)
1299 change_impl (child, impl_window, new);
1304 reparent_to_impl (GdkWindowObject *private)
1307 GdkWindowObject *child;
1310 /* Enumerate in reverse order so we get the right order for the native
1311 windows (first in childrens list is topmost, and reparent places on top) */
1312 for (l = g_list_last (private->children); l != NULL; l = l->prev)
1316 if (child->impl == private->impl)
1317 reparent_to_impl (child);
1320 show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent ((GdkWindow *)child,
1321 (GdkWindow *)private,
1322 child->x, child->y);
1324 gdk_window_show_unraised ((GdkWindow *)child);
1331 * gdk_window_reparent:
1332 * @window: a #GdkWindow
1333 * @new_parent: new parent to move @window into
1334 * @x: X location inside the new parent
1335 * @y: Y location inside the new parent
1337 * Reparents @window into the given @new_parent. The window being
1338 * reparented will be unmapped as a side effect.
1342 gdk_window_reparent (GdkWindow *window,
1343 GdkWindow *new_parent,
1347 GdkWindowObject *private;
1348 GdkWindowObject *new_parent_private;
1349 GdkWindowObject *old_parent;
1351 gboolean show, was_toplevel, was_mapped;
1352 gboolean do_reparent_to_impl;
1354 g_return_if_fail (GDK_IS_WINDOW (window));
1355 g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
1356 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
1358 if (GDK_WINDOW_DESTROYED (window) ||
1359 (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
1362 screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
1364 new_parent = gdk_screen_get_root_window (screen);
1366 private = (GdkWindowObject *) window;
1367 new_parent_private = (GdkWindowObject *)new_parent;
1369 /* No input-output children of input-only windows */
1370 if (new_parent_private->input_only && !private->input_only)
1373 /* Don't create loops in hierarchy */
1374 if (is_parent_of (window, new_parent))
1377 if (private->cairo_surface)
1379 /* This might be wrong in the new parent, e.g. for non-native surfaces.
1380 To make sure we're ok, just wipe it. */
1381 cairo_surface_finish (private->cairo_surface);
1382 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
1386 old_parent = private->parent;
1388 /* Break up redirection if inherited */
1389 if (private->redirect && private->redirect->redirected != private)
1391 remove_redirect_from_children (private, private->redirect);
1392 private->redirect = NULL;
1395 was_toplevel = private->parent == NULL;
1396 was_mapped = GDK_WINDOW_IS_MAPPED (window);
1399 /* Reparenting to toplevel. Ensure we have a native window so this can work */
1400 if (new_parent_private->window_type == GDK_WINDOW_ROOT ||
1401 new_parent_private->window_type == GDK_WINDOW_FOREIGN)
1402 gdk_window_ensure_native (window);
1404 do_reparent_to_impl = FALSE;
1405 if (gdk_window_has_impl (private))
1408 show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent (window, new_parent, x, y);
1412 /* This shouldn't happen, as we created a native in this case, check anyway to see if that ever fails */
1413 g_assert (new_parent_private->window_type != GDK_WINDOW_ROOT &&
1414 new_parent_private->window_type != GDK_WINDOW_FOREIGN);
1417 gdk_window_hide (window);
1419 do_reparent_to_impl = TRUE;
1420 change_impl (private,
1421 new_parent_private->impl_window,
1422 new_parent_private->impl);
1425 /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
1428 if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1430 new_parent = gdk_screen_get_root_window (screen);
1431 new_parent_private = (GdkWindowObject *)new_parent;
1435 old_parent->children = g_list_remove (old_parent->children, window);
1437 private->parent = new_parent_private;
1441 new_parent_private->children = g_list_prepend (new_parent_private->children, window);
1443 /* Switch the window type as appropriate */
1445 switch (GDK_WINDOW_TYPE (new_parent))
1447 case GDK_WINDOW_ROOT:
1448 case GDK_WINDOW_FOREIGN:
1449 if (private->toplevel_window_type != -1)
1450 GDK_WINDOW_TYPE (window) = private->toplevel_window_type;
1451 else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1452 GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
1454 case GDK_WINDOW_OFFSCREEN:
1455 case GDK_WINDOW_TOPLEVEL:
1456 case GDK_WINDOW_CHILD:
1457 case GDK_WINDOW_DIALOG:
1458 case GDK_WINDOW_TEMP:
1459 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
1460 GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
1462 /* Save the original window type so we can restore it if the
1463 * window is reparented back to be a toplevel
1465 private->toplevel_window_type = GDK_WINDOW_TYPE (window);
1466 GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
1470 /* We might have changed window type for a native windows, so we
1471 need to change the event mask too. */
1472 if (gdk_window_has_impl (private))
1473 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_events (window, get_native_event_mask (private));
1475 /* Inherit parent redirect if we don't have our own */
1476 if (private->parent && private->redirect == NULL)
1478 private->redirect = private->parent->redirect;
1479 apply_redirect_to_children (private, private->redirect);
1482 recompute_visible_regions (private, TRUE, FALSE);
1483 if (old_parent && GDK_WINDOW_TYPE (old_parent) != GDK_WINDOW_ROOT)
1484 recompute_visible_regions (old_parent, FALSE, TRUE);
1486 if (do_reparent_to_impl)
1487 reparent_to_impl (private);
1490 /* The reparent will have put the native window topmost in the native parent,
1491 * which may be wrong wrt other native windows in the non-native hierarchy,
1493 sync_native_window_stack_position (window);
1497 gdk_window_show_unraised (window);
1499 _gdk_synthesize_crossing_events_for_geometry_change (window);
1503 * gdk_window_ensure_native:
1504 * @window: a #GdkWindow
1506 * Tries to ensure that there is a window-system native window for this
1507 * GdkWindow. This may fail in some situations, returning %FALSE.
1509 * Offscreen window and children of them can never have native windows.
1511 * Some backends may not support native child windows.
1513 * Returns: %TRUE if the window has a native window, %FALSE otherwise
1518 gdk_window_ensure_native (GdkWindow *window)
1520 GdkWindowObject *private;
1521 GdkWindowObject *impl_window;
1522 GdkDrawable *new_impl, *old_impl;
1525 GdkWindowAttr attributes;
1526 GdkWindowObject *above;
1529 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
1531 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT ||
1532 GDK_WINDOW_DESTROYED (window))
1535 private = (GdkWindowObject *) window;
1537 impl_window = gdk_window_get_impl_window (private);
1539 if (impl_window->window_type == GDK_WINDOW_OFFSCREEN)
1540 return FALSE; /* native in offscreens not supported */
1542 if (impl_window == private)
1543 /* Already has an impl, and its not offscreen . */
1546 /* Need to create a native window */
1548 screen = gdk_drawable_get_screen (window);
1549 visual = gdk_drawable_get_visual (window);
1551 attributes.colormap = gdk_drawable_get_colormap (window);
1553 old_impl = private->impl;
1554 _gdk_window_impl_new (window, (GdkWindow *)private->parent, screen, visual,
1555 get_native_event_mask (private), &attributes, GDK_WA_COLORMAP);
1556 new_impl = private->impl;
1558 private->impl = old_impl;
1559 change_impl (private, private, new_impl);
1561 /* Native window creation will put the native window topmost in the
1562 * native parent, which may be wrong wrt other native windows in the
1563 * non-native hierarchy, so restack */
1564 above = find_native_sibling_above (private->parent, private);
1567 listhead.data = window;
1568 listhead.prev = NULL;
1569 listhead.next = NULL;
1570 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
1574 recompute_visible_regions (private, FALSE, FALSE);
1576 /* The shape may not have been set, as the clip region doesn't actually
1577 change, so do it here manually */
1578 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region ((GdkWindow *)private, private->clip_region, 0, 0);
1580 reparent_to_impl (private);
1582 if (!private->input_only)
1584 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, &private->bg_color);
1585 if (private->bg_pixmap != NULL)
1586 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, private->bg_pixmap);
1589 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_shape_combine_region ((GdkWindow *)private, private->input_shape, 0, 0);
1591 if (gdk_window_is_viewable (window))
1592 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show (window, FALSE);
1598 window_remove_filters (GdkWindow *window)
1600 GdkWindowObject *obj = (GdkWindowObject*) window;
1606 for (tmp_list = obj->filters; tmp_list; tmp_list = tmp_list->next)
1607 g_free (tmp_list->data);
1609 g_list_free (obj->filters);
1610 obj->filters = NULL;
1615 * _gdk_window_destroy_hierarchy:
1616 * @window: a #GdkWindow
1617 * @recursing: If TRUE, then this is being called because a parent
1619 * @recursing_native: If TRUE, then this is being called because a native parent
1620 * was destroyed. This generally means that the call to the
1621 * windowing system to destroy the window can be omitted, since
1622 * it will be destroyed as a result of the parent being destroyed.
1623 * Unless @foreign_destroy.
1624 * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
1625 * external agency. The window has already been destroyed and no
1626 * windowing system calls should be made. (This may never happen
1627 * for some windowing systems.)
1629 * Internal function to destroy a window. Like gdk_window_destroy(),
1630 * but does not drop the reference count created by gdk_window_new().
1633 _gdk_window_destroy_hierarchy (GdkWindow *window,
1635 gboolean recursing_native,
1636 gboolean foreign_destroy)
1638 GdkWindowObject *private;
1639 GdkWindowObject *temp_private;
1640 GdkWindow *temp_window;
1642 GdkDisplay *display;
1646 g_return_if_fail (GDK_IS_WINDOW (window));
1648 private = (GdkWindowObject*) window;
1650 if (GDK_WINDOW_DESTROYED (window))
1653 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
1654 screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
1655 temp_window = g_object_get_qdata (G_OBJECT (screen), quark_pointer_window);
1656 if (temp_window == window)
1657 g_object_set_qdata (G_OBJECT (screen), quark_pointer_window, NULL);
1660 switch (GDK_WINDOW_TYPE (window))
1662 case GDK_WINDOW_ROOT:
1663 if (!screen->closed)
1665 g_error ("attempted to destroy root window");
1668 /* else fall thru */
1669 case GDK_WINDOW_TOPLEVEL:
1670 case GDK_WINDOW_CHILD:
1671 case GDK_WINDOW_DIALOG:
1672 case GDK_WINDOW_TEMP:
1673 case GDK_WINDOW_FOREIGN:
1674 case GDK_WINDOW_OFFSCREEN:
1675 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN && !foreign_destroy)
1677 /* Logically, it probably makes more sense to send
1678 * a "destroy yourself" message to the foreign window
1679 * whether or not it's in our hierarchy; but for historical
1680 * reasons, we only send "destroy yourself" messages to
1681 * foreign windows in our hierarchy.
1683 if (private->parent)
1684 _gdk_windowing_window_destroy_foreign (window);
1686 /* Also for historical reasons, we remove any filters
1687 * on a foreign window when it or a parent is destroyed;
1688 * this likely causes problems if two separate portions
1689 * of code are maintaining filter lists on a foreign window.
1691 window_remove_filters (window);
1695 if (private->parent)
1697 GdkWindowObject *parent_private = (GdkWindowObject *)private->parent;
1699 if (parent_private->children)
1700 parent_private->children = g_list_remove (parent_private->children, window);
1703 GDK_WINDOW_IS_MAPPED (window))
1705 recompute_visible_regions (private, TRUE, FALSE);
1706 gdk_window_invalidate_in_parent (private);
1710 gdk_window_free_paint_stack (window);
1712 if (private->bg_pixmap &&
1713 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
1714 private->bg_pixmap != GDK_NO_BG)
1716 g_object_unref (private->bg_pixmap);
1717 private->bg_pixmap = NULL;
1720 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN)
1721 g_assert (private->children == NULL);
1724 children = tmp = private->children;
1725 private->children = NULL;
1729 temp_window = tmp->data;
1732 temp_private = (GdkWindowObject*) temp_window;
1734 _gdk_window_destroy_hierarchy (temp_window,
1736 recursing_native || gdk_window_has_impl (private),
1740 g_list_free (children);
1743 _gdk_window_clear_update_area (window);
1745 if (private->cairo_surface)
1747 cairo_surface_finish (private->cairo_surface);
1748 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
1753 if (private->extension_events)
1754 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_window_destroy (window);
1756 if (gdk_window_has_impl (private))
1758 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->destroy (window, recursing_native, foreign_destroy);
1762 /* hide to make sure we repaint and break grabs */
1763 gdk_window_hide (window);
1766 private->state |= GDK_WINDOW_STATE_WITHDRAWN;
1767 private->parent = NULL;
1768 private->destroyed = TRUE;
1770 window_remove_filters (window);
1772 gdk_drawable_set_colormap (GDK_DRAWABLE (window), NULL);
1774 /* If we own the redirect, free it */
1775 if (private->redirect && private->redirect->redirected == private)
1776 gdk_window_redirect_free (private->redirect);
1778 private->redirect = NULL;
1780 if (display->pointer_info.toplevel_under_pointer == window)
1782 g_object_unref (display->pointer_info.toplevel_under_pointer);
1783 display->pointer_info.toplevel_under_pointer = NULL;
1791 * _gdk_window_destroy:
1792 * @window: a #GdkWindow
1793 * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
1794 * external agency. The window has already been destroyed and no
1795 * windowing system calls should be made. (This may never happen
1796 * for some windowing systems.)
1798 * Internal function to destroy a window. Like gdk_window_destroy(),
1799 * but does not drop the reference count created by gdk_window_new().
1802 _gdk_window_destroy (GdkWindow *window,
1803 gboolean foreign_destroy)
1805 _gdk_window_destroy_hierarchy (window, FALSE, FALSE, foreign_destroy);
1809 * gdk_window_destroy:
1810 * @window: a #GdkWindow
1812 * Destroys the window system resources associated with @window and decrements @window's
1813 * reference count. The window system resources for all children of @window are also
1814 * destroyed, but the children's reference counts are not decremented.
1816 * Note that a window will not be destroyed automatically when its reference count
1817 * reaches zero. You must call this function yourself before that happens.
1821 gdk_window_destroy (GdkWindow *window)
1823 _gdk_window_destroy_hierarchy (window, FALSE, FALSE, FALSE);
1824 g_object_unref (window);
1828 * gdk_window_set_user_data:
1829 * @window: a #GdkWindow
1830 * @user_data: user data
1832 * For most purposes this function is deprecated in favor of
1833 * g_object_set_data(). However, for historical reasons GTK+ stores
1834 * the #GtkWidget that owns a #GdkWindow as user data on the
1835 * #GdkWindow. So, custom widget implementations should use
1836 * this function for that. If GTK+ receives an event for a #GdkWindow,
1837 * and the user data for the window is non-%NULL, GTK+ will assume the
1838 * user data is a #GtkWidget, and forward the event to that widget.
1842 gdk_window_set_user_data (GdkWindow *window,
1845 g_return_if_fail (GDK_IS_WINDOW (window));
1847 ((GdkWindowObject*)window)->user_data = user_data;
1851 * gdk_window_get_user_data:
1852 * @window: a #GdkWindow
1853 * @data: return location for user data
1855 * Retrieves the user data for @window, which is normally the widget
1856 * that @window belongs to. See gdk_window_set_user_data().
1860 gdk_window_get_user_data (GdkWindow *window,
1863 g_return_if_fail (GDK_IS_WINDOW (window));
1865 *data = ((GdkWindowObject*)window)->user_data;
1869 * gdk_window_get_window_type:
1870 * @window: a #GdkWindow
1872 * Gets the type of the window. See #GdkWindowType.
1874 * Return value: type of window
1877 gdk_window_get_window_type (GdkWindow *window)
1879 g_return_val_if_fail (GDK_IS_WINDOW (window), (GdkWindowType) -1);
1881 return GDK_WINDOW_TYPE (window);
1885 * gdk_window_get_position:
1886 * @window: a #GdkWindow
1887 * @x: X coordinate of window
1888 * @y: Y coordinate of window
1890 * Obtains the position of the window as reported in the
1891 * most-recently-processed #GdkEventConfigure. Contrast with
1892 * gdk_window_get_geometry() which queries the X server for the
1893 * current window position, regardless of which events have been
1894 * received or processed.
1896 * The position coordinates are relative to the window's parent window.
1900 gdk_window_get_position (GdkWindow *window,
1904 GdkWindowObject *obj;
1906 g_return_if_fail (GDK_IS_WINDOW (window));
1908 obj = (GdkWindowObject*) window;
1917 * gdk_window_get_parent:
1918 * @window: a #GdkWindow
1920 * Obtains the parent of @window, as known to GDK. Does not query the
1921 * X server; thus this returns the parent as passed to gdk_window_new(),
1922 * not the actual parent. This should never matter unless you're using
1923 * Xlib calls mixed with GDK calls on the X11 platform. It may also
1924 * matter for toplevel windows, because the window manager may choose
1927 * Return value: parent of @window
1930 gdk_window_get_parent (GdkWindow *window)
1932 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1934 return (GdkWindow*) ((GdkWindowObject*) window)->parent;
1938 * gdk_window_get_toplevel:
1939 * @window: a #GdkWindow
1941 * Gets the toplevel window that's an ancestor of @window.
1943 * Any window type but %GDK_WINDOW_CHILD is considered a
1944 * toplevel window, as is a %GDK_WINDOW_CHILD window that
1945 * has a root window as parent.
1947 * Return value: the toplevel window containing @window
1950 gdk_window_get_toplevel (GdkWindow *window)
1952 GdkWindowObject *obj;
1954 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1956 obj = (GdkWindowObject *)window;
1958 while (GDK_WINDOW_TYPE (obj) == GDK_WINDOW_CHILD)
1960 if (obj->parent == NULL ||
1961 GDK_WINDOW_TYPE (obj->parent) == GDK_WINDOW_ROOT)
1966 return GDK_WINDOW (obj);
1970 * gdk_window_get_children:
1971 * @window: a #GdkWindow
1973 * Gets the list of children of @window known to GDK.
1974 * This function only returns children created via GDK,
1975 * so for example it's useless when used with the root window;
1976 * it only returns windows an application created itself.
1978 * The returned list must be freed, but the elements in the
1981 * Return value: list of child windows inside @window
1984 gdk_window_get_children (GdkWindow *window)
1986 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1988 if (GDK_WINDOW_DESTROYED (window))
1991 return g_list_copy (GDK_WINDOW_OBJECT (window)->children);
1995 * gdk_window_peek_children:
1996 * @window: a #GdkWindow
1998 * Like gdk_window_get_children(), but does not copy the list of
1999 * children, so the list does not need to be freed.
2001 * Return value: a reference to the list of child windows in @window
2004 gdk_window_peek_children (GdkWindow *window)
2006 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2008 if (GDK_WINDOW_DESTROYED (window))
2011 return GDK_WINDOW_OBJECT (window)->children;
2015 * gdk_window_add_filter:
2016 * @window: a #GdkWindow
2017 * @function: filter callback
2018 * @data: data to pass to filter callback
2020 * Adds an event filter to @window, allowing you to intercept events
2021 * before they reach GDK. This is a low-level operation and makes it
2022 * easy to break GDK and/or GTK+, so you have to know what you're
2023 * doing. Pass %NULL for @window to get all events for all windows,
2024 * instead of events for a specific window.
2026 * See gdk_display_add_client_message_filter() if you are interested
2027 * in X ClientMessage events.
2030 gdk_window_add_filter (GdkWindow *window,
2031 GdkFilterFunc function,
2034 GdkWindowObject *private;
2036 GdkEventFilter *filter;
2038 g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
2040 private = (GdkWindowObject*) window;
2041 if (private && GDK_WINDOW_DESTROYED (window))
2044 /* Filters are for the native events on the native window, so
2045 ensure there is a native window. */
2047 gdk_window_ensure_native (window);
2050 tmp_list = private->filters;
2052 tmp_list = _gdk_default_filters;
2056 filter = (GdkEventFilter *)tmp_list->data;
2057 if ((filter->function == function) && (filter->data == data))
2059 tmp_list = tmp_list->next;
2062 filter = g_new (GdkEventFilter, 1);
2063 filter->function = function;
2064 filter->data = data;
2067 private->filters = g_list_append (private->filters, filter);
2069 _gdk_default_filters = g_list_append (_gdk_default_filters, filter);
2073 * gdk_window_remove_filter:
2074 * @window: a #GdkWindow
2075 * @function: previously-added filter function
2076 * @data: user data for previously-added filter function
2078 * Remove a filter previously added with gdk_window_add_filter().
2082 gdk_window_remove_filter (GdkWindow *window,
2083 GdkFilterFunc function,
2086 GdkWindowObject *private;
2087 GList *tmp_list, *node;
2088 GdkEventFilter *filter;
2090 g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
2092 private = (GdkWindowObject*) window;
2095 tmp_list = private->filters;
2097 tmp_list = _gdk_default_filters;
2101 filter = (GdkEventFilter *)tmp_list->data;
2103 tmp_list = tmp_list->next;
2105 if ((filter->function == function) && (filter->data == data))
2108 private->filters = g_list_remove_link (private->filters, node);
2110 _gdk_default_filters = g_list_remove_link (_gdk_default_filters, node);
2111 g_list_free_1 (node);
2120 * gdk_screen_get_toplevel_windows:
2121 * @screen: The #GdkScreen where the toplevels are located.
2123 * Obtains a list of all toplevel windows known to GDK on the screen @screen.
2124 * A toplevel window is a child of the root window (see
2125 * gdk_get_default_root_window()).
2127 * The returned list should be freed with g_list_free(), but
2128 * its elements need not be freed.
2130 * Return value: list of toplevel windows, free with g_list_free()
2135 gdk_screen_get_toplevel_windows (GdkScreen *screen)
2137 GdkWindow * root_window;
2138 GList *new_list = NULL;
2141 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
2143 root_window = gdk_screen_get_root_window (screen);
2145 tmp_list = ((GdkWindowObject *)root_window)->children;
2148 if (GDK_WINDOW_TYPE (tmp_list->data) != GDK_WINDOW_FOREIGN)
2149 new_list = g_list_prepend (new_list, tmp_list->data);
2150 tmp_list = tmp_list->next;
2157 * gdk_window_get_toplevels:
2159 * Obtains a list of all toplevel windows known to GDK on the default
2160 * screen (see gdk_screen_get_toplevel_windows()).
2161 * A toplevel window is a child of the root window (see
2162 * gdk_get_default_root_window()).
2164 * The returned list should be freed with g_list_free(), but
2165 * its elements need not be freed.
2167 * Return value: list of toplevel windows, free with g_list_free()
2169 * Deprecated: 2.16: Use gdk_screen_get_toplevel_windows() instead.
2172 gdk_window_get_toplevels (void)
2174 return gdk_screen_get_toplevel_windows (gdk_screen_get_default ());
2178 * gdk_window_is_visible:
2179 * @window: a #GdkWindow
2181 * Checks whether the window has been mapped (with gdk_window_show() or
2182 * gdk_window_show_unraised()).
2184 * Return value: %TRUE if the window is mapped
2187 gdk_window_is_visible (GdkWindow *window)
2189 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2191 return GDK_WINDOW_IS_MAPPED (window);
2195 * gdk_window_is_viewable:
2196 * @window: a #GdkWindow
2198 * Check if the window and all ancestors of the window are
2199 * mapped. (This is not necessarily "viewable" in the X sense, since
2200 * we only check as far as we have GDK window parents, not to the root
2203 * Return value: %TRUE if the window is viewable
2206 gdk_window_is_viewable (GdkWindow *window)
2208 GdkWindowObject *private = (GdkWindowObject *)window;
2210 GdkWindow *root_window;
2212 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2214 screen = gdk_drawable_get_screen (window);
2215 root_window = gdk_screen_get_root_window (screen);
2218 (private != (GdkWindowObject *)root_window) &&
2219 (GDK_WINDOW_TYPE (private) != GDK_WINDOW_FOREIGN))
2221 if (GDK_WINDOW_DESTROYED (private) || !GDK_WINDOW_IS_MAPPED (private))
2224 private = (GdkWindowObject *)private->parent;
2231 * gdk_window_get_state:
2232 * @window: a #GdkWindow
2234 * Gets the bitwise OR of the currently active window state flags,
2235 * from the #GdkWindowState enumeration.
2237 * Return value: window state bitfield
2240 gdk_window_get_state (GdkWindow *window)
2242 GdkWindowObject *private = (GdkWindowObject *)window;
2244 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2246 return private->state;
2250 /* This creates an empty "implicit" paint region for the impl window.
2251 * By itself this does nothing, but real paints to this window
2252 * or children of it can use this pixmap as backing to avoid allocating
2253 * multiple pixmaps for subwindow rendering. When doing so they
2254 * add to the region of the implicit paint region, which will be
2255 * pushed to the window when the implicit paint region is ended.
2256 * Such paints should not copy anything to the window on paint end, but
2257 * should rely on the implicit paint end.
2258 * The implicit paint will be automatically ended if someone draws
2259 * directly to the window or a child window.
2262 gdk_window_begin_implicit_paint (GdkWindow *window, GdkRectangle *rect)
2264 GdkWindowObject *private = (GdkWindowObject *)window;
2265 GdkWindowPaint *paint;
2267 g_assert (gdk_window_has_impl (private));
2269 if (GDK_IS_PAINTABLE (private->impl))
2270 return FALSE; /* Implementation does double buffering */
2272 if (private->paint_stack != NULL ||
2273 private->implicit_paint != NULL)
2274 return FALSE; /* Don't stack implicit paints */
2276 paint = g_new (GdkWindowPaint, 1);
2277 paint->region = gdk_region_new (); /* Empty */
2278 paint->x_offset = rect->x;
2279 paint->y_offset = rect->y;
2280 paint->uses_implicit = FALSE;
2281 paint->surface = NULL;
2283 gdk_pixmap_new (window,
2284 MAX (rect->width, 1), MAX (rect->height, 1), -1);
2286 private->implicit_paint = paint;
2291 /* Ensure that all content related to this (sub)window is pushed to the
2292 native region. If there is an active paint then that area is not
2293 pushed, in order to not show partially finished double buffers. */
2295 gdk_window_flush_implicit_paint (GdkWindow *window)
2297 GdkWindowObject *private = (GdkWindowObject *)window;
2298 GdkWindowObject *impl_window;
2299 GdkWindowPaint *paint;
2304 impl_window = gdk_window_get_impl_window (private);
2305 if (impl_window->implicit_paint == NULL)
2308 paint = impl_window->implicit_paint;
2309 region = gdk_region_copy (private->clip_region_with_children);
2311 /* Don't flush active double buffers, as that may show partially done
2313 for (list = private->paint_stack; list != NULL; list = list->next)
2315 GdkWindowPaint *tmp_paint = list->data;
2317 gdk_region_subtract (region, tmp_paint->region);
2320 gdk_region_offset (region, private->abs_x, private->abs_y);
2321 gdk_region_intersect (region, paint->region);
2323 if (!gdk_region_empty (region))
2325 /* Some regions are valid, push these to window now */
2326 tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
2327 _gdk_gc_set_clip_region_internal (tmp_gc, region, TRUE);
2328 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2329 0, 0, paint->x_offset, paint->y_offset, -1, -1);
2330 /* Reset clip region of the cached GdkGC */
2331 gdk_gc_set_clip_region (tmp_gc, NULL);
2333 /* Remove flushed region from the implicit paint */
2334 gdk_region_subtract (paint->region, region);
2337 gdk_region_destroy (region);
2340 /* Ends an implicit paint, paired with gdk_window_begin_implicit_paint returning TRUE */
2342 gdk_window_end_implicit_paint (GdkWindow *window)
2344 GdkWindowObject *private = (GdkWindowObject *)window;
2345 GdkWindowPaint *paint;
2348 g_assert (gdk_window_has_impl (private));
2350 g_assert (private->implicit_paint != NULL);
2352 paint = private->implicit_paint;
2354 private->implicit_paint = NULL;
2356 if (!gdk_region_empty (paint->region))
2358 /* Some regions are valid, push these to window now */
2359 tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
2360 _gdk_gc_set_clip_region_internal (tmp_gc, paint->region, TRUE);
2361 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2362 0, 0, paint->x_offset, paint->y_offset, -1, -1);
2363 /* Reset clip region of the cached GdkGC */
2364 gdk_gc_set_clip_region (tmp_gc, NULL);
2367 g_object_unref (paint->pixmap);
2372 * gdk_window_begin_paint_rect:
2373 * @window: a #GdkWindow
2374 * @rectangle: rectangle you intend to draw to
2376 * A convenience wrapper around gdk_window_begin_paint_region() which
2377 * creates a rectangular region for you. See
2378 * gdk_window_begin_paint_region() for details.
2382 gdk_window_begin_paint_rect (GdkWindow *window,
2383 const GdkRectangle *rectangle)
2387 g_return_if_fail (GDK_IS_WINDOW (window));
2389 region = gdk_region_rectangle (rectangle);
2390 gdk_window_begin_paint_region (window, region);
2391 gdk_region_destroy (region);
2394 #ifdef GDK_WINDOWING_X11
2395 #include "x11/gdkx.h"
2399 * gdk_window_begin_paint_region:
2400 * @window: a #GdkWindow
2401 * @region: region you intend to draw to
2403 * Indicates that you are beginning the process of redrawing @region.
2404 * A backing store (offscreen buffer) large enough to contain @region
2405 * will be created. The backing store will be initialized with the
2406 * background color or background pixmap for @window. Then, all
2407 * drawing operations performed on @window will be diverted to the
2408 * backing store. When you call gdk_window_end_paint(), the backing
2409 * store will be copied to @window, making it visible onscreen. Only
2410 * the part of @window contained in @region will be modified; that is,
2411 * drawing operations are clipped to @region.
2413 * The net result of all this is to remove flicker, because the user
2414 * sees the finished product appear all at once when you call
2415 * gdk_window_end_paint(). If you draw to @window directly without
2416 * calling gdk_window_begin_paint_region(), the user may see flicker
2417 * as individual drawing operations are performed in sequence. The
2418 * clipping and background-initializing features of
2419 * gdk_window_begin_paint_region() are conveniences for the
2420 * programmer, so you can avoid doing that work yourself.
2422 * When using GTK+, the widget system automatically places calls to
2423 * gdk_window_begin_paint_region() and gdk_window_end_paint() around
2424 * emissions of the expose_event signal. That is, if you're writing an
2425 * expose event handler, you can assume that the exposed area in
2426 * #GdkEventExpose has already been cleared to the window background,
2427 * is already set as the clip region, and already has a backing store.
2428 * Therefore in most cases, application code need not call
2429 * gdk_window_begin_paint_region(). (You can disable the automatic
2430 * calls around expose events on a widget-by-widget basis by calling
2431 * gtk_widget_set_double_buffered().)
2433 * If you call this function multiple times before calling the
2434 * matching gdk_window_end_paint(), the backing stores are pushed onto
2435 * a stack. gdk_window_end_paint() copies the topmost backing store
2436 * onscreen, subtracts the topmost region from all other regions in
2437 * the stack, and pops the stack. All drawing operations affect only
2438 * the topmost backing store in the stack. One matching call to
2439 * gdk_window_end_paint() is required for each call to
2440 * gdk_window_begin_paint_region().
2444 gdk_window_begin_paint_region (GdkWindow *window,
2445 const GdkRegion *region)
2447 #ifdef USE_BACKING_STORE
2448 GdkWindowObject *private = (GdkWindowObject *)window;
2449 GdkRectangle clip_box;
2450 GdkWindowPaint *paint, *implicit_paint;
2451 GdkWindowObject *impl_window;
2454 g_return_if_fail (GDK_IS_WINDOW (window));
2456 if (GDK_WINDOW_DESTROYED (window))
2459 if (GDK_IS_PAINTABLE (private->impl))
2461 GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
2463 if (iface->begin_paint_region)
2464 iface->begin_paint_region ((GdkPaintable*)private->impl, window, region);
2469 impl_window = gdk_window_get_impl_window (private);
2470 implicit_paint = impl_window->implicit_paint;
2472 paint = g_new (GdkWindowPaint, 1);
2473 paint->region = gdk_region_copy (region);
2474 paint->region_tag = new_region_tag ();
2476 gdk_region_intersect (paint->region, private->clip_region_with_children);
2477 gdk_region_get_clipbox (paint->region, &clip_box);
2479 /* Convert to impl coords */
2480 gdk_region_offset (paint->region, private->abs_x, private->abs_y);
2482 /* Mark the region as valid on the implicit paint */
2485 gdk_region_union (implicit_paint->region, paint->region);
2487 /* Convert back to normal coords */
2488 gdk_region_offset (paint->region, -private->abs_x, -private->abs_y);
2494 paint->uses_implicit = TRUE;
2495 paint->pixmap = g_object_ref (implicit_paint->pixmap);
2496 paint->x_offset = -private->abs_x + implicit_paint->x_offset;
2497 paint->y_offset = -private->abs_y + implicit_paint->y_offset;
2499 /* It would be nice if we had some cairo support here so we
2500 could set the clip rect on the cairo surface */
2501 width = private->abs_x + private->width;
2502 height = private->abs_y + private->height;
2504 paint->surface = _gdk_drawable_create_cairo_surface (paint->pixmap, width, height);
2509 paint->uses_implicit = FALSE;
2510 paint->x_offset = clip_box.x;
2511 paint->y_offset = clip_box.y;
2513 gdk_pixmap_new (window,
2514 MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1);
2515 paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap);
2519 cairo_surface_set_device_offset (paint->surface,
2520 -paint->x_offset, -paint->y_offset);
2522 for (list = private->paint_stack; list != NULL; list = list->next)
2524 GdkWindowPaint *tmp_paint = list->data;
2526 gdk_region_subtract (tmp_paint->region, paint->region);
2529 private->paint_stack = g_slist_prepend (private->paint_stack, paint);
2531 if (!gdk_region_empty (paint->region))
2533 gdk_window_clear_backing_region (window,
2537 #endif /* USE_BACKING_STORE */
2541 setup_redirect_clip (GdkWindow *window,
2546 GdkWindowObject *private = (GdkWindowObject *)window;
2547 GdkRegion *visible_region;
2548 GdkRectangle dest_rect;
2550 GdkWindow *toplevel;
2551 int x_offset, y_offset;
2553 toplevel = GDK_WINDOW (private->redirect->redirected);
2555 /* Get the clip region for gc clip rect + window hierarchy in
2556 window relative coords */
2558 _gdk_window_calculate_full_clip_region (window, toplevel,
2563 /* Compensate for the source pos/size */
2564 x_offset -= private->redirect->src_x;
2565 y_offset -= private->redirect->src_y;
2566 dest_rect.x = -x_offset;
2567 dest_rect.y = -y_offset;
2568 dest_rect.width = private->redirect->width;
2569 dest_rect.height = private->redirect->height;
2570 tmpreg = gdk_region_rectangle (&dest_rect);
2571 gdk_region_intersect (visible_region, tmpreg);
2572 gdk_region_destroy (tmpreg);
2574 /* Compensate for the dest pos */
2575 x_offset += private->redirect->dest_x;
2576 y_offset += private->redirect->dest_y;
2578 gdk_gc_set_clip_region (gc, visible_region); /* This resets clip origin! */
2580 /* offset clip and tiles from window coords to pixmaps coords */
2581 gdk_gc_offset (gc, -x_offset, -y_offset);
2583 gdk_region_destroy (visible_region);
2585 *x_offset_out = x_offset;
2586 *y_offset_out = y_offset;
2590 * gdk_window_end_paint:
2591 * @window: a #GdkWindow
2593 * Indicates that the backing store created by the most recent call to
2594 * gdk_window_begin_paint_region() should be copied onscreen and
2595 * deleted, leaving the next-most-recent backing store or no backing
2596 * store at all as the active paint region. See
2597 * gdk_window_begin_paint_region() for full details. It is an error to
2598 * call this function without a matching
2599 * gdk_window_begin_paint_region() first.
2603 gdk_window_end_paint (GdkWindow *window)
2605 #ifdef USE_BACKING_STORE
2606 GdkWindowObject *private = (GdkWindowObject *)window;
2607 GdkWindowObject *composited;
2608 GdkWindowPaint *paint;
2610 GdkRectangle clip_box;
2611 gint x_offset, y_offset;
2612 GdkRegion *full_clip;
2614 g_return_if_fail (GDK_IS_WINDOW (window));
2616 if (GDK_WINDOW_DESTROYED (window))
2619 if (GDK_IS_PAINTABLE (private->impl))
2621 GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
2623 if (iface->end_paint)
2624 iface->end_paint ((GdkPaintable*)private->impl);
2628 if (private->paint_stack == NULL)
2630 g_warning (G_STRLOC": no preceding call to gdk_window_begin_paint_region(), see documentation");
2634 paint = private->paint_stack->data;
2636 private->paint_stack = g_slist_delete_link (private->paint_stack,
2637 private->paint_stack);
2639 gdk_region_get_clipbox (paint->region, &clip_box);
2641 tmp_gc = _gdk_drawable_get_scratch_gc (window, FALSE);
2643 x_offset = -private->abs_x;
2644 y_offset = -private->abs_y;
2646 if (!paint->uses_implicit)
2648 gdk_window_flush_outstanding_moves (window);
2650 full_clip = gdk_region_copy (private->clip_region_with_children);
2651 gdk_region_intersect (full_clip, paint->region);
2652 _gdk_gc_set_clip_region_internal (tmp_gc, full_clip, TRUE); /* Takes ownership of full_clip */
2653 gdk_gc_set_clip_origin (tmp_gc, - x_offset, - y_offset);
2654 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2655 clip_box.x - paint->x_offset,
2656 clip_box.y - paint->y_offset,
2657 clip_box.x - x_offset, clip_box.y - y_offset,
2658 clip_box.width, clip_box.height);
2661 if (private->redirect)
2663 int x_offset, y_offset;
2665 /* TODO: Should also use paint->region for clipping */
2666 setup_redirect_clip (window, tmp_gc, &x_offset, &y_offset);
2667 gdk_draw_drawable (private->redirect->pixmap, tmp_gc, paint->pixmap,
2668 clip_box.x - paint->x_offset,
2669 clip_box.y - paint->y_offset,
2670 clip_box.x + x_offset,
2671 clip_box.y + y_offset,
2672 clip_box.width, clip_box.height);
2675 /* Reset clip region of the cached GdkGC */
2676 gdk_gc_set_clip_region (tmp_gc, NULL);
2678 cairo_surface_destroy (paint->surface);
2679 g_object_unref (paint->pixmap);
2680 gdk_region_destroy (paint->region);
2683 /* find a composited window in our hierarchy to signal its
2684 * parent to redraw, calculating the clip box as we go...
2686 * stop if parent becomes NULL since then we'd have nowhere
2687 * to draw (ie: 'composited' will always be non-NULL here).
2689 for (composited = private;
2691 composited = composited->parent)
2695 gdk_drawable_get_size (GDK_DRAWABLE (composited->parent),
2698 clip_box.x += composited->x;
2699 clip_box.y += composited->y;
2700 clip_box.width = MIN (clip_box.width, width - clip_box.x);
2701 clip_box.height = MIN (clip_box.height, height - clip_box.y);
2703 if (composited->composited)
2705 gdk_window_invalidate_rect (GDK_WINDOW (composited->parent),
2710 #endif /* USE_BACKING_STORE */
2714 gdk_window_free_paint_stack (GdkWindow *window)
2716 GdkWindowObject *private = (GdkWindowObject *)window;
2718 if (private->paint_stack)
2720 GSList *tmp_list = private->paint_stack;
2724 GdkWindowPaint *paint = tmp_list->data;
2726 if (tmp_list == private->paint_stack)
2727 g_object_unref (paint->pixmap);
2729 gdk_region_destroy (paint->region);
2732 tmp_list = tmp_list->next;
2735 g_slist_free (private->paint_stack);
2736 private->paint_stack = NULL;
2741 do_move_region_bits_on_impl (GdkWindowObject *impl_window,
2742 GdkRegion *dest_region, /* In impl window coords */
2746 GdkRectangle copy_rect;
2747 GdkWindowObject *private;
2749 /* We need to get data from subwindows here, because we might have
2750 * shaped a native window over the moving region (with bg none,
2751 * so the pixels are still there). In fact we might need to get data
2752 * from overlapping native window that are not children of this window,
2753 * so we copy from the toplevel with INCLUDE_INFERIORS.
2755 private = impl_window;
2756 while (private->parent != NULL &&
2757 GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
2759 dx -= private->parent->abs_x + private->x;
2760 dy -= private->parent->abs_y + private->y;
2761 private = gdk_window_get_impl_window (private->parent);
2763 tmp_gc = _gdk_drawable_get_subwindow_scratch_gc ((GdkWindow *)private);
2765 /* The region area is moved and we queue translations for all expose events
2766 to the source area that were sent prior to the copy */
2767 gdk_region_offset (dest_region, -dx, -dy); /* Temporarily move to source area */
2768 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->queue_translation ((GdkWindow *)impl_window,
2769 dest_region, dx, dy);
2770 gdk_region_offset (dest_region, dx, dy); /* back to dest area */
2772 gdk_region_get_clipbox (dest_region, ©_rect);
2774 gdk_gc_set_clip_region (tmp_gc, dest_region);
2775 gdk_draw_drawable (impl_window->impl,
2778 copy_rect.x-dx, copy_rect.y-dy,
2779 copy_rect.x, copy_rect.y,
2780 copy_rect.width, copy_rect.height);
2781 gdk_gc_set_clip_region (tmp_gc, NULL);
2784 static GdkWindowRegionMove *
2785 gdk_window_region_move_new (GdkRegion *region,
2788 GdkWindowRegionMove *move;
2790 move = g_slice_new (GdkWindowRegionMove);
2791 move->dest_region = gdk_region_copy (region);
2799 gdk_window_region_move_free (GdkWindowRegionMove *move)
2801 gdk_region_destroy (move->dest_region);
2802 g_slice_free (GdkWindowRegionMove, move);
2806 append_move_region (GdkWindowObject *impl_window,
2807 GdkRegion *new_dest_region,
2810 GdkWindowRegionMove *move, *old_move;
2811 GdkRegion *new_total_region, *old_total_region;
2812 GdkRegion *source_overlaps_destination;
2813 GdkRegion *non_overwritten;
2814 gboolean added_move;
2817 if (gdk_region_empty (new_dest_region))
2820 /* In principle this could just append the move to the list of outstanding
2821 moves that will be replayed before drawing anything when we're handling
2822 exposes. However, we'd like to do a bit better since its commonly the case
2823 that we get multiple copies where A is copied to B and then B is copied
2824 to C, and we'd like to express this as a simple copy A to C operation. */
2826 /* We approach this by taking the new move and pushing it ahead of moves
2827 starting at the end of the list and stopping when its not safe to do so.
2828 It's not safe to push past a move if either the source of the new move
2829 is in the destination of the old move, or if the destination of the new
2830 move is in the source of the new move, or if the destination of the new
2831 move overlaps the destination of the old move. We simplify this by
2832 just comparing the total regions (src + dest) */
2833 new_total_region = gdk_region_copy (new_dest_region);
2834 gdk_region_offset (new_total_region, -dx, -dy);
2835 gdk_region_union (new_total_region, new_dest_region);
2838 for (l = g_list_last (impl_window->outstanding_moves); l != NULL; l = prev)
2843 old_total_region = gdk_region_copy (old_move->dest_region);
2844 gdk_region_offset (old_total_region, -old_move->dx, -old_move->dy);
2845 gdk_region_union (old_total_region, old_move->dest_region);
2847 gdk_region_intersect (old_total_region, new_total_region);
2848 /* If these regions intersect then its not safe to push the
2849 new region before the old one */
2850 if (!gdk_region_empty (old_total_region))
2852 /* The area where the new moves source overlaps the old ones
2854 source_overlaps_destination = gdk_region_copy (new_dest_region);
2855 gdk_region_offset (source_overlaps_destination, -dx, -dy);
2856 gdk_region_intersect (source_overlaps_destination, old_move->dest_region);
2857 gdk_region_offset (source_overlaps_destination, dx, dy);
2859 /* We can do all sort of optimizations here, but to do things safely it becomes
2860 quite complicated. However, a very common case is that you copy something first,
2861 then copy all that or a subset of it to a new location (i.e. if you scroll twice
2862 in the same direction). We'd like to detect this case and optimize it to one
2864 if (gdk_region_equal (source_overlaps_destination, new_dest_region))
2866 /* This means we might be able to replace the old move and the new one
2867 with the new one read from the old ones source, and a second copy of
2868 the non-overwritten parts of the old move. However, such a split
2869 is only valid if the source in the old move isn't overwritten
2870 by the destination of the new one */
2872 /* the new destination of old move if split is ok: */
2873 non_overwritten = gdk_region_copy (old_move->dest_region);
2874 gdk_region_subtract (non_overwritten, new_dest_region);
2875 /* move to source region */
2876 gdk_region_offset (non_overwritten, -old_move->dx, -old_move->dy);
2878 gdk_region_intersect (non_overwritten, new_dest_region);
2879 if (gdk_region_empty (non_overwritten))
2882 move = gdk_window_region_move_new (new_dest_region,
2886 impl_window->outstanding_moves =
2887 g_list_insert_before (impl_window->outstanding_moves,
2889 gdk_region_subtract (old_move->dest_region, new_dest_region);
2891 gdk_region_destroy (non_overwritten);
2894 gdk_region_destroy (source_overlaps_destination);
2895 gdk_region_destroy (old_total_region);
2898 gdk_region_destroy (old_total_region);
2901 gdk_region_destroy (new_total_region);
2905 move = gdk_window_region_move_new (new_dest_region, dx, dy);
2908 impl_window->outstanding_moves =
2909 g_list_prepend (impl_window->outstanding_moves,
2912 impl_window->outstanding_moves =
2913 g_list_insert_before (impl_window->outstanding_moves,
2918 /* Moves bits and update area by dx/dy in impl window,
2919 takes ownership of region */
2921 move_region_on_impl (GdkWindowObject *private,
2922 GdkRegion *region, /* In impl window coords */
2925 GdkWindowObject *impl_window;
2927 if ((dx == 0 && dy == 0) ||
2928 gdk_region_empty (region))
2930 gdk_region_destroy (region);
2934 impl_window = gdk_window_get_impl_window (private);
2936 /* Move any old invalid regions in the copy source area by dx/dy */
2937 if (impl_window->update_area)
2939 GdkRegion *update_area;
2940 update_area = gdk_region_copy (region);
2942 /* Convert from target to source */
2943 gdk_region_offset (update_area, -dx, -dy);
2944 gdk_region_intersect (update_area, impl_window->update_area);
2945 gdk_region_subtract (impl_window->update_area, update_area);
2948 gdk_region_offset (update_area, dx, dy);
2949 gdk_region_union (impl_window->update_area, update_area);
2951 /* This area of the destination is now invalid,
2952 so no need to copy to it. */
2953 gdk_region_subtract (region, update_area);
2955 gdk_region_destroy (update_area);
2958 if (1) /* Enable flicker free handling of moves. */
2959 append_move_region (impl_window, region, dx, dy);
2961 do_move_region_bits_on_impl (impl_window,
2964 gdk_region_destroy (region);
2967 /* Flushes all outstanding changes to the window, call this
2968 * before drawing directly to the window (i.e. outside a begin/end_paint pair).
2971 gdk_window_flush_outstanding_moves (GdkWindow *window)
2973 GdkWindowObject *private;
2974 GdkWindowObject *impl_window;
2976 GdkWindowRegionMove *move;
2978 private = (GdkWindowObject *) window;
2980 impl_window = gdk_window_get_impl_window (private);
2982 for (l = impl_window->outstanding_moves; l != NULL; l = l->next)
2986 do_move_region_bits_on_impl (impl_window,
2987 move->dest_region, move->dx, move->dy);
2989 gdk_window_region_move_free (move);
2992 g_list_free (impl_window->outstanding_moves);
2993 impl_window->outstanding_moves = NULL;
2997 gdk_window_flush (GdkWindow *window)
2999 gdk_window_flush_outstanding_moves (window);
3000 gdk_window_flush_implicit_paint (window);
3004 gdk_window_flush_recursive_helper (GdkWindowObject *window,
3007 GdkWindowObject *child;
3010 for (l = window->children; l != NULL; l = l->next)
3014 if (child->impl == impl)
3015 /* Same impl, ignore */
3016 gdk_window_flush_recursive_helper (child, impl);
3018 gdk_window_flush_recursive (child);
3023 gdk_window_flush_recursive (GdkWindowObject *window)
3025 gdk_window_flush ((GdkWindow *)window);
3026 gdk_window_flush_recursive_helper (window, window->impl);
3030 gdk_window_get_offsets (GdkWindow *window,
3034 GdkWindowObject *private = (GdkWindowObject *)window;
3036 if (private->paint_stack)
3038 GdkWindowPaint *paint = private->paint_stack->data;
3039 *x_offset = paint->x_offset;
3040 *y_offset = paint->y_offset;
3044 *x_offset = -private->abs_x;
3045 *y_offset = -private->abs_y;
3050 * gdk_window_get_internal_paint_info:
3051 * @window: a #GdkWindow
3052 * @real_drawable: location to store the drawable to which drawing should be
3054 * @x_offset: location to store the X offset between coordinates in @window,
3055 * and the underlying window system primitive coordinates for
3057 * @y_offset: location to store the Y offset between coordinates in @window,
3058 * and the underlying window system primitive coordinates for
3061 * If you bypass the GDK layer and use windowing system primitives to
3062 * draw directly onto a #GdkWindow, then you need to deal with two
3063 * details: there may be an offset between GDK coordinates and windowing
3064 * system coordinates, and GDK may have redirected drawing to a offscreen
3065 * pixmap as the result of a gdk_window_begin_paint_region() calls.
3066 * This function allows retrieving the information you need to compensate
3067 * for these effects.
3069 * This function exposes details of the GDK implementation, and is thus
3070 * likely to change in future releases of GDK.
3073 gdk_window_get_internal_paint_info (GdkWindow *window,
3074 GdkDrawable **real_drawable,
3080 GdkWindowObject *private;
3082 g_return_if_fail (GDK_IS_WINDOW (window));
3084 private = (GdkWindowObject *)window;
3088 if (private->paint_stack)
3090 GdkWindowPaint *paint = private->paint_stack->data;
3091 *real_drawable = paint->pixmap;
3095 /* This means you're probably gonna be doing some weird shit
3096 directly to the window, so we flush all outstanding stuff */
3097 gdk_window_flush (window);
3098 *real_drawable = window;
3102 gdk_window_get_offsets (window, &x_off, &y_off);
3110 static GdkDrawable *
3111 start_draw_helper (GdkDrawable *drawable,
3116 GdkWindowObject *private = (GdkWindowObject *)drawable;
3117 gint x_offset, y_offset;
3119 gint old_clip_x = gc->clip_x_origin;
3120 gint old_clip_y = gc->clip_y_origin;
3122 guint32 clip_region_tag;
3123 GdkWindowPaint *paint;
3126 if (private->paint_stack)
3127 paint = private->paint_stack->data;
3131 x_offset = paint->x_offset;
3132 y_offset = paint->y_offset;
3136 x_offset = -private->abs_x;
3137 y_offset = -private->abs_y;
3140 if (x_offset != 0 || y_offset != 0)
3142 gdk_gc_set_clip_origin (gc,
3143 old_clip_x - x_offset,
3144 old_clip_y - y_offset);
3145 gdk_gc_set_ts_origin (gc,
3146 gc->ts_x_origin - x_offset,
3147 gc->ts_y_origin - y_offset);
3150 *x_offset_out = x_offset;
3151 *y_offset_out = y_offset;
3153 /* Add client side window clip region to gc */
3157 /* Only need clipping if using implicit paint, otherwise
3158 the pixmap is clipped when copying to the window in end_paint */
3159 if (paint->uses_implicit)
3161 /* This includes the window clip */
3162 clip = paint->region;
3164 clip_region_tag = paint->region_tag;
3166 /* After having set up the drawable clip rect on a GC we need to make sure
3167 * that we draw to th the impl, otherwise the pixmap code will reset the
3169 impl = ((GdkPixmapObject *)(paint->pixmap))->impl;
3173 /* Drawing directly to the window, flush anything outstanding to
3174 guarantee ordering. */
3175 gdk_window_flush ((GdkWindow *)drawable);
3177 /* Don't clip when drawing to root */
3178 if (private->window_type != GDK_WINDOW_ROOT)
3180 if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
3181 clip = private->clip_region_with_children;
3183 clip = private->clip_region;
3185 clip_region_tag = private->clip_tag;
3186 impl = private->impl;
3190 _gdk_gc_add_drawable_clip (gc,
3191 clip_region_tag, clip,
3192 /* If there was a clip origin set appart from the
3193 * window offset, need to take that into
3195 -old_clip_x, -old_clip_y);
3200 #define BEGIN_DRAW \
3202 GdkDrawable *impl; \
3203 gint x_offset, y_offset; \
3204 gint old_clip_x = gc->clip_x_origin; \
3205 gint old_clip_y = gc->clip_y_origin; \
3206 gint old_ts_x = gc->ts_x_origin; \
3207 gint old_ts_y = gc->ts_y_origin; \
3208 impl = start_draw_helper (drawable, gc, \
3209 &x_offset, &y_offset);
3212 if (x_offset != 0 || y_offset != 0) \
3214 gdk_gc_set_clip_origin (gc, old_clip_x, old_clip_y); \
3215 gdk_gc_set_ts_origin (gc, old_ts_x, old_ts_y); \
3220 gdk_window_create_gc (GdkDrawable *drawable,
3221 GdkGCValues *values,
3222 GdkGCValuesMask mask)
3224 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
3226 if (GDK_WINDOW_DESTROYED (drawable))
3229 return gdk_gc_new_with_values (((GdkWindowObject *) drawable)->impl,
3234 gdk_window_draw_rectangle (GdkDrawable *drawable,
3242 if (GDK_WINDOW_DESTROYED (drawable))
3246 gdk_draw_rectangle (impl, gc, filled,
3247 x - x_offset, y - y_offset, width, height);
3252 gdk_window_draw_arc (GdkDrawable *drawable,
3262 if (GDK_WINDOW_DESTROYED (drawable))
3266 gdk_draw_arc (impl, gc, filled,
3267 x - x_offset, y - y_offset,
3268 width, height, angle1, angle2);
3273 gdk_window_draw_polygon (GdkDrawable *drawable,
3279 GdkPoint *new_points;
3281 if (GDK_WINDOW_DESTROYED (drawable))
3286 if (x_offset != 0 || y_offset != 0)
3290 new_points = g_new (GdkPoint, npoints);
3291 for (i=0; i<npoints; i++)
3293 new_points[i].x = points[i].x - x_offset;
3294 new_points[i].y = points[i].y - y_offset;
3298 new_points = points;
3300 gdk_draw_polygon (impl, gc, filled, new_points, npoints);
3302 if (new_points != points)
3303 g_free (new_points);
3309 gdk_window_draw_text (GdkDrawable *drawable,
3317 if (GDK_WINDOW_DESTROYED (drawable))
3321 gdk_draw_text (impl, font, gc,
3322 x - x_offset, y - y_offset, text, text_length);
3327 gdk_window_draw_text_wc (GdkDrawable *drawable,
3332 const GdkWChar *text,
3335 if (GDK_WINDOW_DESTROYED (drawable))
3339 gdk_draw_text_wc (impl, font, gc,
3340 x - x_offset, y - y_offset, text, text_length);
3344 static GdkDrawable *
3345 gdk_window_get_source_drawable (GdkDrawable *drawable)
3347 GdkWindow *window = GDK_WINDOW (drawable);
3348 GdkWindowObject *private;
3350 private = (GdkWindowObject *) window;
3351 if (GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable)
3352 return GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable (private->impl);
3357 static GdkDrawable *
3358 gdk_window_get_composite_drawable (GdkDrawable *drawable,
3363 gint *composite_x_offset,
3364 gint *composite_y_offset)
3366 GdkWindowObject *private = (GdkWindowObject *)drawable;
3368 GdkPixmap *tmp_pixmap;
3371 gboolean overlap_buffer;
3372 GdkDrawable *source;
3373 GdkWindowObject *impl_window;
3374 GdkWindowPaint *implicit_paint;
3376 *composite_x_offset = -private->abs_x;
3377 *composite_y_offset = -private->abs_y;
3379 if ((GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable)))
3380 return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
3382 /* See if any buffered part is overlapping the part we want
3388 rect.height = height;
3390 overlap_buffer = FALSE;
3392 for (list = private->paint_stack; list != NULL; list = list->next)
3394 GdkWindowPaint *paint = list->data;
3395 GdkOverlapType overlap;
3397 overlap = gdk_region_rect_in (paint->region, &rect);
3399 if (overlap == GDK_OVERLAP_RECTANGLE_IN)
3401 *composite_x_offset = paint->x_offset;
3402 *composite_y_offset = paint->y_offset;
3404 return g_object_ref (paint->pixmap);
3406 else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
3408 overlap_buffer = TRUE;
3413 impl_window = gdk_window_get_impl_window (private);
3414 implicit_paint = impl_window->implicit_paint;
3417 GdkOverlapType overlap;
3419 rect.x += private->abs_x;
3420 rect.y += private->abs_y;
3422 overlap = gdk_region_rect_in (implicit_paint->region, &rect);
3423 if (overlap == GDK_OVERLAP_RECTANGLE_IN)
3425 *composite_x_offset = -private->abs_x + implicit_paint->x_offset;
3426 *composite_y_offset = -private->abs_y + implicit_paint->y_offset;
3428 return g_object_ref (implicit_paint->pixmap);
3430 else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
3431 overlap_buffer = TRUE;
3434 if (!overlap_buffer)
3435 return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
3437 tmp_pixmap = gdk_pixmap_new (drawable, width, height, -1);
3438 tmp_gc = _gdk_drawable_get_scratch_gc (tmp_pixmap, FALSE);
3440 source = _gdk_drawable_get_source_drawable (drawable);
3442 /* Copy the current window contents */
3443 gdk_draw_drawable (tmp_pixmap,
3445 GDK_WINDOW_OBJECT (source)->impl,
3446 x - *composite_x_offset,
3447 y - *composite_y_offset,
3451 /* paint the backing stores */
3454 GdkWindowPaint *paint = list->data;
3456 gdk_gc_set_clip_region (tmp_gc, paint->region);
3457 gdk_gc_set_clip_origin (tmp_gc, -x - paint->x_offset, -y - paint->y_offset);
3459 gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
3460 x - paint->x_offset,
3461 y - paint->y_offset,
3462 0, 0, width, height);
3465 for (list = private->paint_stack; list != NULL; list = list->next)
3467 GdkWindowPaint *paint = list->data;
3469 if (paint->uses_implicit)
3470 continue; /* We already copied this above */
3472 gdk_gc_set_clip_region (tmp_gc, paint->region);
3473 gdk_gc_set_clip_origin (tmp_gc, -x, -y);
3475 gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
3476 x - paint->x_offset,
3477 y - paint->y_offset,
3478 0, 0, width, height);
3481 /* Reset clip region of the cached GdkGC */
3482 gdk_gc_set_clip_region (tmp_gc, NULL);
3484 /* Set these to location of tmp_pixmap within the window */
3485 *composite_x_offset = x;
3486 *composite_y_offset = y;
3492 gdk_window_get_clip_region (GdkDrawable *drawable)
3494 GdkWindowObject *private = (GdkWindowObject *)drawable;
3497 result = gdk_region_copy (private->clip_region);
3499 if (private->paint_stack)
3501 GdkRegion *paint_region = gdk_region_new ();
3502 GSList *tmp_list = private->paint_stack;
3506 GdkWindowPaint *paint = tmp_list->data;
3508 gdk_region_union (paint_region, paint->region);
3510 tmp_list = tmp_list->next;
3513 gdk_region_intersect (result, paint_region);
3514 gdk_region_destroy (paint_region);
3521 gdk_window_get_visible_region (GdkDrawable *drawable)
3523 GdkWindowObject *private = (GdkWindowObject*) drawable;
3525 return gdk_region_copy (private->clip_region);
3529 gdk_window_draw_drawable (GdkDrawable *drawable,
3538 GdkDrawable *original_src)
3540 GdkWindowObject *private = (GdkWindowObject *)drawable;
3542 if (GDK_WINDOW_DESTROYED (drawable))
3547 gdk_draw_drawable (impl, gc, src, xsrc, ysrc,
3548 xdest - x_offset, ydest - y_offset, width, height);
3550 if (!private->paint_stack)
3552 /* We might have drawn from an obscured part of a client
3553 side window, if so we need to send graphics exposures */
3554 if (_gdk_gc_get_exposures (gc) &&
3555 GDK_IS_WINDOW (original_src))
3557 GdkRegion *exposure_region;
3565 exposure_region = gdk_region_rectangle (&r);
3567 if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
3568 clip = private->clip_region_with_children;
3570 clip = private->clip_region;
3571 gdk_region_intersect (exposure_region, clip);
3573 clip = _gdk_gc_get_clip_region (gc);
3576 gdk_region_offset (exposure_region,
3579 gdk_region_intersect (exposure_region, clip);
3580 gdk_region_offset (exposure_region,
3585 /* Note: We don't clip by the clip mask if set, so this
3586 may invalidate to much */
3588 /* Remove the area that is correctly copied from the src.
3589 * Note that xsrc/ysrc has been corrected for abs_x/y offsets already,
3590 * which need to be undone */
3591 clip = gdk_drawable_get_visible_region (original_src);
3592 gdk_region_offset (clip,
3593 xdest - (xsrc - GDK_WINDOW_OBJECT (original_src)->abs_x),
3594 ydest - (ysrc - GDK_WINDOW_OBJECT (original_src)->abs_y));
3595 gdk_region_subtract (exposure_region, clip);
3596 gdk_region_destroy (clip);
3598 gdk_window_invalidate_region (GDK_WINDOW (private),
3600 _gdk_gc_get_subwindow (gc) == GDK_INCLUDE_INFERIORS);
3602 gdk_region_destroy (exposure_region);
3610 gdk_window_draw_points (GdkDrawable *drawable,
3615 GdkPoint *new_points;
3617 if (GDK_WINDOW_DESTROYED (drawable))
3622 if (x_offset != 0 || y_offset != 0)
3626 new_points = g_new (GdkPoint, npoints);
3627 for (i=0; i<npoints; i++)
3629 new_points[i].x = points[i].x - x_offset;
3630 new_points[i].y = points[i].y - y_offset;
3634 new_points = points;
3636 gdk_draw_points (impl, gc, new_points, npoints);
3638 if (new_points != points)
3639 g_free (new_points);
3645 gdk_window_draw_segments (GdkDrawable *drawable,
3650 GdkSegment *new_segs;
3652 if (GDK_WINDOW_DESTROYED (drawable))
3657 if (x_offset != 0 || y_offset != 0)
3661 new_segs = g_new (GdkSegment, nsegs);
3662 for (i=0; i<nsegs; i++)
3664 new_segs[i].x1 = segs[i].x1 - x_offset;
3665 new_segs[i].y1 = segs[i].y1 - y_offset;
3666 new_segs[i].x2 = segs[i].x2 - x_offset;
3667 new_segs[i].y2 = segs[i].y2 - y_offset;
3673 gdk_draw_segments (impl, gc, new_segs, nsegs);
3675 if (new_segs != segs)
3682 gdk_window_draw_lines (GdkDrawable *drawable,
3687 GdkPoint *new_points;
3689 if (GDK_WINDOW_DESTROYED (drawable))
3694 if (x_offset != 0 || y_offset != 0)
3698 new_points = g_new (GdkPoint, npoints);
3699 for (i=0; i<npoints; i++)
3701 new_points[i].x = points[i].x - x_offset;
3702 new_points[i].y = points[i].y - y_offset;
3706 new_points = points;
3708 gdk_draw_lines (impl, gc, new_points, npoints);
3710 if (new_points != points)
3711 g_free (new_points);
3717 gdk_window_draw_glyphs (GdkDrawable *drawable,
3722 PangoGlyphString *glyphs)
3724 if (GDK_WINDOW_DESTROYED (drawable))
3728 gdk_draw_glyphs (impl, gc, font,
3729 x - x_offset, y - y_offset, glyphs);
3734 gdk_window_draw_glyphs_transformed (GdkDrawable *drawable,
3736 PangoMatrix *matrix,
3740 PangoGlyphString *glyphs)
3742 PangoMatrix tmp_matrix;
3744 if (GDK_WINDOW_DESTROYED (drawable))
3749 if (x_offset != 0 || y_offset != 0)
3753 tmp_matrix = *matrix;
3754 tmp_matrix.x0 -= x_offset;
3755 tmp_matrix.y0 -= y_offset;
3756 matrix = &tmp_matrix;
3758 else if (GDK_PANGO_UNITS_OVERFLOWS (x_offset, y_offset))
3760 PangoMatrix identity = PANGO_MATRIX_INIT;
3762 tmp_matrix = identity;
3763 tmp_matrix.x0 -= x_offset;
3764 tmp_matrix.y0 -= y_offset;
3765 matrix = &tmp_matrix;
3769 x -= x_offset * PANGO_SCALE;
3770 y -= y_offset * PANGO_SCALE;
3774 gdk_draw_glyphs_transformed (impl, gc, matrix, font, x, y, glyphs);
3780 cairo_t *cr; /* if non-null, it means use this cairo context */
3781 GdkGC *gc; /* if non-null, it means use this GC instead */
3782 } BackingRectMethod;
3785 setup_backing_rect_method (BackingRectMethod *method, GdkWindow *window, GdkWindowPaint *paint, int x_offset_cairo, int y_offset_cairo)
3787 GdkWindowObject *private = (GdkWindowObject *)window;
3789 if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
3791 GdkWindowPaint tmp_paint;
3794 tmp_paint.x_offset += private->x;
3795 tmp_paint.y_offset += private->y;
3797 x_offset_cairo += private->x;
3798 y_offset_cairo += private->y;
3800 setup_backing_rect_method (method, GDK_WINDOW (private->parent), &tmp_paint, x_offset_cairo, y_offset_cairo);
3802 else if (private->bg_pixmap &&
3803 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
3804 private->bg_pixmap != GDK_NO_BG)
3806 /* This is a workaround for https://bugs.freedesktop.org/show_bug.cgi?id=4320.
3807 * In it, using a pixmap as a repeating pattern in Cairo, and painting it to a
3808 * pixmap destination surface, can be very slow (on the order of seconds for a
3809 * whole-screen copy). The workaround is to use pretty much the same code that
3810 * we used in GTK+ 2.6 (pre-Cairo), which clears the double-buffer pixmap with
3811 * a tiled GC XFillRectangle().
3814 /* Actually computing this flag is left as an exercise for the reader */
3815 #if defined (G_OS_UNIX)
3816 # define GDK_CAIRO_REPEAT_IS_FAST 0
3818 # define GDK_CAIRO_REPEAT_IS_FAST 1
3821 #if GDK_CAIRO_REPEAT_IS_FAST
3822 cairo_surface_t *surface = _gdk_drawable_ref_cairo_surface (private->bg_pixmap);
3823 cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
3824 cairo_surface_destroy (surface);
3826 if (x_offset_cairo != 0 || y_offset_cairo != 0)
3828 cairo_matrix_t matrix;
3829 cairo_matrix_init_translate (&matrix, x_offset_cairo, y_offset_cairo);
3830 cairo_pattern_set_matrix (pattern, &matrix);
3833 cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
3835 method->cr = cairo_create (paint->surface);
3838 cairo_set_source (method->cr, pattern);
3839 cairo_pattern_destroy (pattern);
3842 GdkGCValues gc_values;
3844 gc_values.fill = GDK_TILED;
3845 gc_values.tile = private->bg_pixmap;
3846 gc_values.ts_x_origin = -x_offset_cairo;
3847 gc_values.ts_y_origin = -y_offset_cairo;
3849 gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN;
3851 method->gc = gdk_gc_new_with_values (paint->pixmap, &gc_values, gc_mask);
3856 method->cr = cairo_create (paint->surface);
3858 gdk_cairo_set_source_color (method->cr, &private->bg_color);
3863 gdk_window_clear_backing_region (GdkWindow *window,
3866 GdkWindowObject *private = (GdkWindowObject *)window;
3867 GdkWindowPaint *paint = private->paint_stack->data;
3868 BackingRectMethod method;
3870 GdkRectangle clipbox;
3876 if (GDK_WINDOW_DESTROYED (window))
3880 timer = g_timer_new ();
3885 setup_backing_rect_method (&method, window, paint, 0, 0);
3887 clip = gdk_region_copy (paint->region);
3888 gdk_region_intersect (clip, region);
3889 gdk_region_get_clipbox (clip, &clipbox);
3894 g_assert (method.gc == NULL);
3896 gdk_cairo_region (method.cr, clip);
3897 cairo_fill (method.cr);
3899 cairo_destroy (method.cr);
3901 elapsed = g_timer_elapsed (timer, NULL);
3902 g_print ("Draw the background with Cairo: %fs\n", elapsed);
3907 g_assert (method.gc != NULL);
3909 gdk_gc_set_clip_region (method.gc, clip);
3910 gdk_draw_rectangle (window, method.gc, TRUE,
3911 clipbox.x, clipbox.y,
3912 clipbox.width, clipbox.height);
3913 g_object_unref (method.gc);
3916 elapsed = g_timer_elapsed (timer, NULL);
3917 g_print ("Draw the background with GDK: %fs\n", elapsed);
3921 gdk_region_destroy (clip);
3924 g_timer_destroy (timer);
3929 gdk_window_clear_backing_region_redirect (GdkWindow *window,
3932 GdkWindowObject *private = (GdkWindowObject *)window;
3933 GdkWindowRedirect *redirect = private->redirect;
3934 GdkRegion *clip_region;
3935 GdkRectangle clipbox;
3936 gint x_offset, y_offset;
3937 BackingRectMethod method;
3938 GdkWindowPaint paint;
3940 if (GDK_WINDOW_DESTROYED (window))
3943 clip_region = _gdk_window_calculate_full_clip_region (window,
3944 GDK_WINDOW (redirect->redirected),
3946 &x_offset, &y_offset);
3947 gdk_region_intersect (clip_region, region);
3949 /* offset is from redirected window origin to window origin, convert to
3950 the offset from the redirected pixmap origin to the window origin */
3951 x_offset += redirect->dest_x - redirect->src_x;
3952 y_offset += redirect->dest_y - redirect->src_y;
3954 /* Convert region to pixmap coords */
3955 gdk_region_offset (clip_region, x_offset, y_offset);
3959 paint.pixmap = redirect->pixmap;
3960 paint.surface = _gdk_drawable_ref_cairo_surface (redirect->pixmap);
3964 setup_backing_rect_method (&method, window, &paint, -x_offset, -y_offset);
3968 g_assert (method.gc == NULL);
3970 gdk_cairo_region (method.cr, clip_region);
3971 cairo_fill (method.cr);
3973 cairo_destroy (method.cr);
3977 g_assert (method.gc != NULL);
3979 gdk_region_get_clipbox (clip_region, &clipbox);
3980 gdk_gc_set_clip_region (method.gc, clip_region);
3981 gdk_draw_rectangle (redirect->pixmap, method.gc, TRUE,
3982 clipbox.x, clipbox.y,
3983 clipbox.width, clipbox.height);
3984 g_object_unref (method.gc);
3988 gdk_region_destroy (clip_region);
3989 cairo_surface_destroy (paint.surface);
3993 gdk_window_clear_backing_region_direct (GdkWindow *window,
3996 GdkWindowObject *private = (GdkWindowObject *)window;
3997 BackingRectMethod method;
3998 GdkWindowPaint paint;
4000 GdkRectangle clipbox;
4002 if (GDK_WINDOW_DESTROYED (window))
4007 paint.pixmap = window;
4008 paint.surface = _gdk_drawable_ref_cairo_surface (window);
4012 setup_backing_rect_method (&method, window, &paint, 0, 0);
4014 clip = gdk_region_copy (private->clip_region_with_children);
4015 gdk_region_intersect (clip, region);
4016 gdk_region_get_clipbox (clip, &clipbox);
4020 g_assert (method.gc == NULL);
4022 gdk_cairo_region (method.cr, clip);
4023 cairo_fill (method.cr);
4025 cairo_destroy (method.cr);
4029 g_assert (method.gc != NULL);
4031 gdk_gc_set_clip_region (method.gc, clip);
4032 gdk_draw_rectangle (window, method.gc, TRUE,
4033 clipbox.x, clipbox.y,
4034 clipbox.width, clipbox.height);
4035 g_object_unref (method.gc);
4039 gdk_region_destroy (clip);
4040 cairo_surface_destroy (paint.surface);
4046 * @window: a #GdkWindow
4048 * Clears an entire @window to the background color or background pixmap.
4051 gdk_window_clear (GdkWindow *window)
4055 g_return_if_fail (GDK_IS_WINDOW (window));
4057 gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height);
4059 gdk_window_clear_area (window, 0, 0,
4064 gdk_window_clear_region_internal (GdkWindow *window,
4066 gboolean send_expose)
4068 GdkWindowObject *private = (GdkWindowObject *)window;
4070 if (private->paint_stack)
4071 gdk_window_clear_backing_region (window, region);
4074 if (private->redirect)
4075 gdk_window_clear_backing_region_redirect (window, region);
4077 if (GDK_WINDOW_IMPL_GET_IFACE (private->impl)->clear_region &&
4078 gdk_window_has_impl (private))
4081 copy = gdk_region_copy (region);
4082 gdk_region_intersect (copy, private->clip_region_with_children);
4084 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->clear_region
4085 (window, copy, send_expose);
4087 gdk_region_destroy (copy);
4091 gdk_window_clear_backing_region_direct (window, region);
4093 gdk_window_invalidate_region (window, region, FALSE);
4099 gdk_window_clear_area_internal (GdkWindow *window,
4104 gboolean send_expose)
4106 GdkWindowObject *private = (GdkWindowObject *)window;
4110 g_return_if_fail (GDK_IS_WINDOW (window));
4112 if (GDK_WINDOW_DESTROYED (window))
4115 /* This is what XClearArea does, and e.g. GtkCList uses it,
4116 so we need to duplicate that */
4118 width = private->width - x;
4120 height = private->height - y;
4125 rect.height = height;
4127 region = gdk_region_rectangle (&rect);
4128 gdk_window_clear_region_internal (window,
4131 gdk_region_destroy (region);
4136 * gdk_window_clear_area:
4137 * @window: a #GdkWindow
4138 * @x: x coordinate of rectangle to clear
4139 * @y: y coordinate of rectangle to clear
4140 * @width: width of rectangle to clear
4141 * @height: height of rectangle to clear
4143 * Clears an area of @window to the background color or background pixmap.
4147 gdk_window_clear_area (GdkWindow *window,
4153 gdk_window_clear_area_internal (window,
4160 * gdk_window_clear_area_e:
4161 * @window: a #GdkWindow
4162 * @x: x coordinate of rectangle to clear
4163 * @y: y coordinate of rectangle to clear
4164 * @width: width of rectangle to clear
4165 * @height: height of rectangle to clear
4167 * Like gdk_window_clear_area(), but also generates an expose event for
4170 * This function has a stupid name because it dates back to the mists
4171 * time, pre-GDK-1.0.
4175 gdk_window_clear_area_e (GdkWindow *window,
4181 gdk_window_clear_area_internal (window,
4188 gdk_window_draw_image (GdkDrawable *drawable,
4198 if (GDK_WINDOW_DESTROYED (drawable))
4202 gdk_draw_image (impl, gc, image, xsrc, ysrc,
4203 xdest - x_offset, ydest - y_offset,
4209 gdk_window_draw_pixbuf (GdkDrawable *drawable,
4218 GdkRgbDither dither,
4222 GdkWindowObject *private = (GdkWindowObject *)drawable;
4224 if (GDK_WINDOW_DESTROYED (drawable))
4227 /* If no gc => no user clipping, but we need clipping
4228 for window emulation, so use a scratch gc */
4230 gc = _gdk_drawable_get_scratch_gc (drawable, FALSE);
4233 if (private->paint_stack)
4234 gdk_draw_pixbuf (impl, gc, pixbuf, src_x, src_y,
4235 dest_x - x_offset, dest_y - y_offset,
4237 dither, x_dither - x_offset, y_dither - y_offset);
4239 gdk_draw_pixbuf (impl, gc, pixbuf, src_x, src_y,
4240 dest_x - x_offset, dest_y - y_offset,
4242 dither, x_dither, y_dither);
4247 gdk_window_draw_trapezoids (GdkDrawable *drawable,
4249 GdkTrapezoid *trapezoids,
4252 GdkTrapezoid *new_trapezoids = NULL;
4254 if (GDK_WINDOW_DESTROYED (drawable))
4259 if (x_offset != 0 || y_offset != 0)
4263 new_trapezoids = g_new (GdkTrapezoid, n_trapezoids);
4264 for (i=0; i < n_trapezoids; i++)
4266 new_trapezoids[i].y1 = trapezoids[i].y1 - y_offset;
4267 new_trapezoids[i].x11 = trapezoids[i].x11 - x_offset;
4268 new_trapezoids[i].x21 = trapezoids[i].x21 - x_offset;
4269 new_trapezoids[i].y2 = trapezoids[i].y2 - y_offset;
4270 new_trapezoids[i].x12 = trapezoids[i].x12 - x_offset;
4271 new_trapezoids[i].x22 = trapezoids[i].x22 - x_offset;
4274 trapezoids = new_trapezoids;
4277 gdk_draw_trapezoids (impl, gc, trapezoids, n_trapezoids);
4279 g_free (new_trapezoids);
4285 gdk_window_real_get_size (GdkDrawable *drawable,
4289 GdkWindowObject *private = (GdkWindowObject *)drawable;
4292 *width = private->width;
4294 *height = private->height;
4298 gdk_window_real_get_visual (GdkDrawable *drawable)
4300 GdkColormap *colormap;
4302 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4304 colormap = gdk_drawable_get_colormap (drawable);
4305 return colormap ? gdk_colormap_get_visual (colormap) : NULL;
4309 gdk_window_real_get_depth (GdkDrawable *drawable)
4311 g_return_val_if_fail (GDK_IS_WINDOW (drawable), 0);
4313 return ((GdkWindowObject *)GDK_WINDOW (drawable))->depth;
4317 gdk_window_real_get_screen (GdkDrawable *drawable)
4319 return gdk_drawable_get_screen (GDK_WINDOW_OBJECT (drawable)->impl);
4323 gdk_window_real_set_colormap (GdkDrawable *drawable,
4326 GdkWindowObject *private;
4328 g_return_if_fail (GDK_IS_WINDOW (drawable));
4330 if (GDK_WINDOW_DESTROYED (drawable))
4333 private = (GdkWindowObject *)drawable;
4335 /* different colormap than parent, requires native window */
4336 if (!private->input_only &&
4337 cmap != gdk_drawable_get_colormap ((GdkDrawable *)(private->parent)))
4338 gdk_window_ensure_native ((GdkWindow *)drawable);
4340 gdk_drawable_set_colormap (private->impl, cmap);
4344 gdk_window_real_get_colormap (GdkDrawable *drawable)
4346 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4348 if (GDK_WINDOW_DESTROYED (drawable))
4351 return gdk_drawable_get_colormap (((GdkWindowObject*)drawable)->impl);
4355 gdk_window_copy_to_image (GdkDrawable *drawable,
4364 GdkWindowObject *private = (GdkWindowObject *) drawable;
4365 gint x_offset, y_offset;
4367 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4369 if (GDK_WINDOW_DESTROYED (drawable))
4372 /* If we're here, a composite image was not necessary, so
4373 * we can ignore the paint stack.
4376 /* TODO: Is this right? */
4380 return gdk_drawable_copy_to_image (private->impl,
4389 gdk_window_cairo_surface_destroy (void *data)
4391 GdkWindowObject *private = (GdkWindowObject*) data;
4393 private->cairo_surface = NULL;
4396 static cairo_surface_t *
4397 gdk_window_create_cairo_surface (GdkDrawable *drawable,
4401 return _gdk_windowing_create_cairo_surface (GDK_WINDOW_OBJECT(drawable)->impl,
4406 static cairo_surface_t *
4407 gdk_window_ref_cairo_surface (GdkDrawable *drawable)
4409 GdkWindowObject *private = (GdkWindowObject*) drawable;
4410 cairo_surface_t *surface;
4412 if (private->paint_stack)
4414 GdkWindowPaint *paint = private->paint_stack->data;
4416 surface = paint->surface;
4417 cairo_surface_reference (surface);
4422 /* This will be drawing directly to the window, so flush implicit paint */
4423 gdk_window_flush ((GdkWindow *)drawable);
4425 if (!private->cairo_surface)
4428 GdkDrawable *source;
4430 /* It would be nice if we had some cairo support here so we
4431 could set the clip rect on the cairo surface */
4432 width = private->abs_x + private->width;
4433 height = private->abs_y + private->height;
4435 source = _gdk_drawable_get_source_drawable (drawable);
4437 /* TODO: Avoid the typecheck crap by adding virtual call */
4438 private->cairo_surface = _gdk_drawable_create_cairo_surface (source, width, height);
4440 if (private->cairo_surface)
4442 cairo_surface_set_device_offset (private->cairo_surface,
4446 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
4447 drawable, gdk_window_cairo_surface_destroy);
4451 cairo_surface_reference (private->cairo_surface);
4453 surface = private->cairo_surface;
4460 gdk_window_set_cairo_clip (GdkDrawable *drawable,
4463 GdkWindowObject *private = (GdkWindowObject*) drawable;
4465 if (!private->paint_stack)
4468 cairo_identity_matrix (cr);
4470 cairo_reset_clip (cr);
4472 cairo_new_path (cr);
4473 gdk_cairo_region (cr, private->clip_region_with_children);
4480 GdkWindowPaint *paint = private->paint_stack->data;
4482 /* Only needs to clip to region if piggybacking
4483 on an implicit paint pixmap */
4484 if (paint->uses_implicit)
4487 cairo_identity_matrix (cr);
4489 cairo_reset_clip (cr);
4491 cairo_new_path (cr);
4492 gdk_cairo_region (cr, paint->region);
4500 /* Code for dirty-region queueing
4502 static GSList *update_windows = NULL;
4503 static guint update_idle = 0;
4504 static gboolean debug_updates = FALSE;
4506 static inline gboolean
4507 gdk_window_is_ancestor (GdkWindow *window,
4508 GdkWindow *ancestor)
4512 GdkWindow *parent = (GdkWindow*) ((GdkWindowObject*) window)->parent;
4514 if (parent == ancestor)
4524 gdk_window_add_update_window (GdkWindow *window)
4527 GSList *prev = NULL;
4528 gboolean has_ancestor_in_list = FALSE;
4530 for (tmp = update_windows; tmp; tmp = tmp->next)
4532 GdkWindowObject *parent = GDK_WINDOW_OBJECT (window)->parent;
4534 /* check if tmp is an ancestor of "window"; if it is, set a
4535 * flag indicating that all following windows are either
4536 * children of "window" or from a differen hierarchy
4538 if (!has_ancestor_in_list && gdk_window_is_ancestor (window, tmp->data))
4539 has_ancestor_in_list = TRUE;
4541 /* insert in reverse stacking order when adding around siblings,
4542 * so processing updates properly paints over lower stacked windows
4544 if (parent == GDK_WINDOW_OBJECT (tmp->data)->parent)
4546 gint index = g_list_index (parent->children, window);
4547 for (; tmp && parent == GDK_WINDOW_OBJECT (tmp->data)->parent; tmp = tmp->next)
4549 gint sibling_index = g_list_index (parent->children, tmp->data);
4550 if (index > sibling_index)
4554 /* here, tmp got advanced past all lower stacked siblings */
4555 tmp = g_slist_prepend (tmp, window);
4559 update_windows = tmp;
4563 /* if "window" has an ancestor in the list and tmp is one of
4564 * "window's" children, insert "window" before tmp
4566 if (has_ancestor_in_list && gdk_window_is_ancestor (tmp->data, window))
4568 tmp = g_slist_prepend (tmp, window);
4573 update_windows = tmp;
4577 /* if we're at the end of the list and had an ancestor it it,
4578 * append to the list
4580 if (! tmp->next && has_ancestor_in_list)
4582 tmp = g_slist_append (tmp, window);
4589 /* if all above checks failed ("window" is from a different
4590 * hierarchy than what is already in the list) or the list is
4593 update_windows = g_slist_prepend (update_windows, window);
4597 gdk_window_remove_update_window (GdkWindow *window)
4599 update_windows = g_slist_remove (update_windows, window);
4603 gdk_window_update_idle (gpointer data)
4605 gdk_window_process_all_updates ();
4611 gdk_window_is_toplevel_frozen (GdkWindow *window)
4613 GdkWindowObject *toplevel;
4615 toplevel = (GdkWindowObject *)gdk_window_get_toplevel (window);
4617 return toplevel->update_and_descendants_freeze_count > 0;
4621 gdk_window_schedule_update (GdkWindow *window)
4624 (GDK_WINDOW_OBJECT (window)->update_freeze_count ||
4625 gdk_window_is_toplevel_frozen (window)))
4630 update_idle = gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
4631 gdk_window_update_idle, NULL, NULL);
4636 _gdk_window_process_updates_recurse (GdkWindow *window,
4637 GdkRegion *expose_region)
4639 GdkWindowObject *private = (GdkWindowObject *)window;
4640 GdkWindowObject *child;
4641 GdkRegion *child_region;
4645 if (gdk_region_empty (expose_region))
4648 /* Iterate over children, starting at topmost */
4649 for (l = private->children; l != NULL; l = l->next)
4653 if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
4656 /* Ignore offscreen children, as they don't draw in their parent and
4657 * don't take part in the clipping */
4658 if (gdk_window_is_offscreen (child))
4663 r.width = child->width;
4664 r.height = child->height;
4666 child_region = gdk_region_rectangle (&r);
4669 /* Adjust shape region to parent window coords */
4670 gdk_region_offset (child->shape, child->x, child->y);
4671 gdk_region_intersect (child_region, child->shape);
4672 gdk_region_offset (child->shape, -child->x, -child->y);
4675 if (child->impl == private->impl)
4677 /* Client side child, expose */
4678 gdk_region_intersect (child_region, expose_region);
4679 gdk_region_subtract (expose_region, child_region);
4680 gdk_region_offset (child_region, -child->x, -child->y);
4681 _gdk_window_process_updates_recurse ((GdkWindow *)child, child_region);
4685 /* Native child, just remove area from expose region */
4686 gdk_region_subtract (expose_region, child_region);
4688 gdk_region_destroy (child_region);
4691 if (!gdk_region_empty (expose_region))
4693 if (private->event_mask & GDK_EXPOSURE_MASK)
4697 event.expose.type = GDK_EXPOSE;
4698 event.expose.window = g_object_ref (window);
4699 event.expose.send_event = FALSE;
4700 event.expose.count = 0;
4701 event.expose.region = expose_region;
4702 gdk_region_get_clipbox (expose_region, &event.expose.area);
4704 (*_gdk_event_func) (&event, _gdk_event_data);
4706 g_object_unref (window);
4708 else if (private->bg_pixmap != GDK_NO_BG)
4710 /* No exposure mask set, so nothing will be drawn, the
4711 * app relies on the background being what it specified
4712 * for the window. So, we need to clear this manually.
4714 * We use begin/end_paint around the clear so that we can
4715 * piggyback on the implicit paint */
4717 gdk_window_begin_paint_region (window, expose_region);
4718 gdk_window_clear_region_internal (window, expose_region, FALSE);
4719 gdk_window_end_paint (window);
4725 gdk_window_process_updates_internal (GdkWindow *window)
4727 GdkWindowObject *private = (GdkWindowObject *)window;
4728 gboolean save_region = FALSE;
4729 GdkRectangle clip_box;
4731 /* If an update got queued during update processing, we can get a
4732 * window in the update queue that has an empty update_area.
4735 if (private->update_area)
4737 GdkRegion *update_area = private->update_area;
4738 private->update_area = NULL;
4740 if (_gdk_event_func && gdk_window_is_viewable (window) &&
4741 private->window_type != GDK_WINDOW_FOREIGN)
4743 GdkRectangle window_rect;
4744 GdkRegion *expose_region;
4745 GdkRegion *window_region;
4746 gboolean end_implicit;
4748 /* Clip to part visible in toplevel */
4749 gdk_region_intersect (update_area, private->clip_region);
4753 /* Make sure we see the red invalid area before redrawing. */
4754 gdk_display_sync (gdk_drawable_get_display (window));
4758 save_region = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->queue_antiexpose (window, update_area);
4760 expose_region = gdk_region_copy (update_area);
4762 expose_region = update_area;
4766 window_rect.width = private->width;
4767 window_rect.height = private->height;
4769 window_region = gdk_region_rectangle (&window_rect);
4770 gdk_region_intersect (expose_region,
4772 gdk_region_destroy (window_region);
4775 /* No need to do any moves that will end up over the update area */
4776 if (private->outstanding_moves)
4778 GdkWindowRegionMove *move;
4782 remove = gdk_region_copy (update_area);
4783 for (l = g_list_last (private->outstanding_moves); l != NULL; l = prev)
4787 /* Don't need this area */
4788 gdk_region_subtract (move->dest_region, remove);
4790 /* However if any of the destination we do need has a source
4791 in the updated region we do need that as a destination for
4792 the earlier moves */
4793 gdk_region_offset (move->dest_region, -move->dx, -move->dy);
4794 gdk_region_subtract (remove, move->dest_region);
4796 if (gdk_region_empty (move->dest_region))
4798 gdk_window_region_move_free (move);
4799 private->outstanding_moves =
4800 g_list_delete_link (private->outstanding_moves, l);
4803 gdk_region_offset (move->dest_region, move->dx, move->dy);
4805 gdk_region_destroy (remove);
4808 gdk_region_get_clipbox (expose_region, &clip_box);
4809 end_implicit = gdk_window_begin_implicit_paint (window, &clip_box);
4810 if (end_implicit) /* rendering is not double buffered, do moves now */
4811 gdk_window_flush_outstanding_moves (window);
4812 _gdk_windowing_window_process_updates_recurse (window, expose_region);
4815 /* Do moves right before exposes are rendered */
4816 gdk_window_flush_outstanding_moves (window);
4817 gdk_window_end_implicit_paint (window);
4820 if (expose_region != update_area)
4821 gdk_region_destroy (expose_region);
4824 gdk_region_destroy (update_area);
4827 if (private->outstanding_moves)
4829 /* Flush any outstanding moves, may happen if we moved a window but got
4830 no actual invalid area */
4831 gdk_window_flush_outstanding_moves (window);
4836 flush_all_displays (void)
4838 GSList *displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
4841 for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
4842 gdk_display_flush (tmp_list->data);
4844 g_slist_free (displays);
4847 /* Currently it is not possible to override
4848 * gdk_window_process_all_updates in the same manner as
4849 * gdk_window_process_updates and gdk_window_invalidate_maybe_recurse
4850 * by implementing the GdkPaintable interface. If in the future a
4851 * backend would need this, the right solution would be to add a
4852 * method to GdkDisplay that can be optionally
4853 * NULL. gdk_window_process_all_updates can then walk the list of open
4854 * displays and call the mehod.
4858 * gdk_window_process_all_updates:
4860 * Calls gdk_window_process_updates() for all windows (see #GdkWindow)
4861 * in the application.
4865 gdk_window_process_all_updates (void)
4867 GSList *old_update_windows = update_windows;
4868 GSList *tmp_list = update_windows;
4869 static gboolean in_process_all_updates = FALSE;
4871 if (in_process_all_updates)
4874 in_process_all_updates = TRUE;
4877 g_source_remove (update_idle);
4879 update_windows = NULL;
4882 _gdk_windowing_before_process_all_updates ();
4884 g_slist_foreach (old_update_windows, (GFunc)g_object_ref, NULL);
4888 GdkWindowObject *private = (GdkWindowObject *)tmp_list->data;
4890 if (!GDK_WINDOW_DESTROYED (tmp_list->data))
4892 if (private->update_freeze_count ||
4893 gdk_window_is_toplevel_frozen (tmp_list->data))
4894 gdk_window_add_update_window ((GdkWindow *) private);
4896 gdk_window_process_updates_internal (tmp_list->data);
4899 g_object_unref (tmp_list->data);
4900 tmp_list = tmp_list->next;
4903 g_slist_free (old_update_windows);
4905 flush_all_displays ();
4907 _gdk_windowing_after_process_all_updates ();
4909 in_process_all_updates = FALSE;
4913 * gdk_window_process_updates:
4914 * @window: a #GdkWindow
4915 * @update_children: whether to also process updates for child windows
4917 * Sends one or more expose events to @window. The areas in each
4918 * expose event will cover the entire update area for the window (see
4919 * gdk_window_invalidate_region() for details). Normally GDK calls
4920 * gdk_window_process_all_updates() on your behalf, so there's no
4921 * need to call this function unless you want to force expose events
4922 * to be delivered immediately and synchronously (vs. the usual
4923 * case, where GDK delivers them in an idle handler). Occasionally
4924 * this is useful to produce nicer scrolling behavior, for example.
4928 gdk_window_process_updates (GdkWindow *window,
4929 gboolean update_children)
4931 GdkWindowObject *private = (GdkWindowObject *)window;
4932 GdkWindowObject *impl_window;
4934 g_return_if_fail (GDK_IS_WINDOW (window));
4936 impl_window = gdk_window_get_impl_window (private);
4937 if ((impl_window->update_area ||
4938 impl_window->outstanding_moves) &&
4939 !impl_window->update_freeze_count &&
4940 !gdk_window_is_toplevel_frozen (window))
4942 gdk_window_process_updates_internal ((GdkWindow *)impl_window);
4943 gdk_window_remove_update_window ((GdkWindow *)impl_window);
4946 if (update_children)
4948 /* process updates in reverse stacking order so composition or
4949 * painting over achieves the desired effect for offscreen windows
4952 for (node = g_list_last (private->children); node; node = node->prev)
4953 gdk_window_process_updates (node->data, TRUE);
4958 * gdk_window_invalidate_rect:
4959 * @window: a #GdkWindow
4960 * @rect: rectangle to invalidate or %NULL to invalidate the whole
4962 * @invalidate_children: whether to also invalidate child windows
4964 * A convenience wrapper around gdk_window_invalidate_region() which
4965 * invalidates a rectangular region. See
4966 * gdk_window_invalidate_region() for details.
4969 gdk_window_invalidate_rect (GdkWindow *window,
4970 const GdkRectangle *rect,
4971 gboolean invalidate_children)
4973 GdkRectangle window_rect;
4975 GdkWindowObject *private = (GdkWindowObject *)window;
4977 g_return_if_fail (GDK_IS_WINDOW (window));
4979 if (GDK_WINDOW_DESTROYED (window))
4982 if (private->input_only || !GDK_WINDOW_IS_MAPPED (window))
4989 gdk_drawable_get_size (GDK_DRAWABLE (window),
4991 &window_rect.height);
4992 rect = &window_rect;
4995 region = gdk_region_rectangle (rect);
4996 gdk_window_invalidate_region (window, region, invalidate_children);
4997 gdk_region_destroy (region);
5001 draw_ugly_color (GdkWindow *window,
5002 const GdkRegion *region)
5004 /* Draw ugly color all over the newly-invalid region */
5005 GdkColor ugly_color = { 0, 50000, 10000, 10000 };
5007 GdkRectangle clipbox;
5009 ugly_gc = gdk_gc_new (window);
5010 gdk_gc_set_rgb_fg_color (ugly_gc, &ugly_color);
5011 gdk_gc_set_clip_region (ugly_gc, region);
5013 gdk_region_get_clipbox (region, &clipbox);
5015 gdk_draw_rectangle (window,
5018 clipbox.x, clipbox.y,
5019 clipbox.width, clipbox.height);
5021 g_object_unref (ugly_gc);
5025 * gdk_window_invalidate_maybe_recurse:
5026 * @window: a #GdkWindow
5027 * @region: a #GdkRegion
5028 * @child_func: function to use to decide if to recurse to a child,
5029 * %NULL means never recurse.
5030 * @user_data: data passed to @child_func
5032 * Adds @region to the update area for @window. The update area is the
5033 * region that needs to be redrawn, or "dirty region." The call
5034 * gdk_window_process_updates() sends one or more expose events to the
5035 * window, which together cover the entire update area. An
5036 * application would normally redraw the contents of @window in
5037 * response to those expose events.
5039 * GDK will call gdk_window_process_all_updates() on your behalf
5040 * whenever your program returns to the main loop and becomes idle, so
5041 * normally there's no need to do that manually, you just need to
5042 * invalidate regions that you know should be redrawn.
5044 * The @child_func parameter controls whether the region of
5045 * each child window that intersects @region will also be invalidated.
5046 * Only children for which @child_func returns TRUE will have the area
5050 gdk_window_invalidate_maybe_recurse (GdkWindow *window,
5051 const GdkRegion *region,
5052 gboolean (*child_func) (GdkWindow *,
5056 GdkWindowObject *private = (GdkWindowObject *)window;
5057 GdkWindowObject *impl_window;
5058 GdkRegion *visible_region;
5061 g_return_if_fail (GDK_IS_WINDOW (window));
5063 if (GDK_WINDOW_DESTROYED (window))
5066 if (private->input_only ||
5067 !GDK_WINDOW_IS_MAPPED (window) ||
5068 gdk_region_empty (region))
5071 visible_region = gdk_drawable_get_visible_region (window);
5072 gdk_region_intersect (visible_region, region);
5074 tmp_list = private->children;
5077 GdkWindowObject *child = tmp_list->data;
5079 if (!child->input_only)
5081 GdkRegion *child_region;
5082 GdkRectangle child_rect;
5084 child_rect.x = child->x;
5085 child_rect.y = child->y;
5086 child_rect.width = child->width;
5087 child_rect.height = child->height;
5088 child_region = gdk_region_rectangle (&child_rect);
5090 /* remove child area from the invalid area of the parent */
5091 if (GDK_WINDOW_IS_MAPPED (child) && !child->shaped &&
5092 !child->composited &&
5093 !gdk_window_is_offscreen (child))
5094 gdk_region_subtract (visible_region, child_region);
5096 if (child_func && (*child_func) ((GdkWindow *)child, user_data))
5098 GdkRegion *tmp = gdk_region_copy (region);
5100 gdk_region_offset (tmp, - child_rect.x, - child_rect.y);
5101 gdk_region_offset (child_region, - child_rect.x, - child_rect.y);
5102 gdk_region_intersect (child_region, tmp);
5104 gdk_window_invalidate_maybe_recurse ((GdkWindow *)child,
5105 child_region, child_func, user_data);
5107 gdk_region_destroy (tmp);
5110 gdk_region_destroy (child_region);
5113 tmp_list = tmp_list->next;
5116 impl_window = gdk_window_get_impl_window (private);
5118 if (!gdk_region_empty (visible_region) ||
5119 /* Even if we're not exposing anything, make sure we process
5120 idles for windows with outstanding moves */
5121 (impl_window->outstanding_moves != NULL &&
5122 impl_window->update_area == NULL))
5125 draw_ugly_color (window, region);
5127 /* Convert to impl coords */
5128 gdk_region_offset (visible_region, private->abs_x, private->abs_y);
5129 if (impl_window->update_area)
5131 gdk_region_union (impl_window->update_area, visible_region);
5135 gdk_window_add_update_window ((GdkWindow *)impl_window);
5136 impl_window->update_area = gdk_region_copy (visible_region);
5138 gdk_window_schedule_update ((GdkWindow *)impl_window);
5142 gdk_region_destroy (visible_region);
5146 true_predicate (GdkWindow *window,
5153 * gdk_window_invalidate_region:
5154 * @window: a #GdkWindow
5155 * @region: a #GdkRegion
5156 * @invalidate_children: %TRUE to also invalidate child windows
5158 * Adds @region to the update area for @window. The update area is the
5159 * region that needs to be redrawn, or "dirty region." The call
5160 * gdk_window_process_updates() sends one or more expose events to the
5161 * window, which together cover the entire update area. An
5162 * application would normally redraw the contents of @window in
5163 * response to those expose events.
5165 * GDK will call gdk_window_process_all_updates() on your behalf
5166 * whenever your program returns to the main loop and becomes idle, so
5167 * normally there's no need to do that manually, you just need to
5168 * invalidate regions that you know should be redrawn.
5170 * The @invalidate_children parameter controls whether the region of
5171 * each child window that intersects @region will also be invalidated.
5172 * If %FALSE, then the update area for child windows will remain
5173 * unaffected. See gdk_window_invalidate_maybe_recurse if you need
5174 * fine grained control over which children are invalidated.
5177 gdk_window_invalidate_region (GdkWindow *window,
5178 const GdkRegion *region,
5179 gboolean invalidate_children)
5181 gdk_window_invalidate_maybe_recurse (window, region,
5182 invalidate_children ?
5183 true_predicate : (gboolean (*) (GdkWindow *, gpointer))NULL,
5188 * _gdk_window_invalidate_for_expose:
5189 * @window: a #GdkWindow
5190 * @region: a #GdkRegion
5192 * Adds @region to the update area for @window. The update area is the
5193 * region that needs to be redrawn, or "dirty region." The call
5194 * gdk_window_process_updates() sends one or more expose events to the
5195 * window, which together cover the entire update area. An
5196 * application would normally redraw the contents of @window in
5197 * response to those expose events.
5199 * GDK will call gdk_window_process_all_updates() on your behalf
5200 * whenever your program returns to the main loop and becomes idle, so
5201 * normally there's no need to do that manually, you just need to
5202 * invalidate regions that you know should be redrawn.
5204 * This version of invalidation is used when you recieve expose events
5205 * from the native window system. It exposes the native window, plus
5206 * any non-native child windows (but not native child windows, as those would
5207 * have gotten their own expose events).
5210 _gdk_window_invalidate_for_expose (GdkWindow *window,
5211 const GdkRegion *region)
5213 gdk_window_invalidate_maybe_recurse (window, region,
5214 (gboolean (*) (GdkWindow *, gpointer))gdk_window_has_no_impl,
5220 * gdk_window_get_update_area:
5221 * @window: a #GdkWindow
5223 * Transfers ownership of the update area from @window to the caller
5224 * of the function. That is, after calling this function, @window will
5225 * no longer have an invalid/dirty region; the update area is removed
5226 * from @window and handed to you. If a window has no update area,
5227 * gdk_window_get_update_area() returns %NULL. You are responsible for
5228 * calling gdk_region_destroy() on the returned region if it's non-%NULL.
5230 * Return value: the update area for @window
5233 gdk_window_get_update_area (GdkWindow *window)
5235 GdkWindowObject *private = (GdkWindowObject *)window;
5236 GdkWindowObject *impl_window;
5237 GdkRegion *tmp_region;
5239 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
5241 impl_window = gdk_window_get_impl_window (private);
5243 if (impl_window->update_area)
5245 tmp_region = gdk_region_copy (private->clip_region_with_children);
5246 /* Convert to impl coords */
5247 gdk_region_offset (tmp_region, private->abs_x, private->abs_y);
5248 gdk_region_intersect (tmp_region, impl_window->update_area);
5250 if (gdk_region_empty (tmp_region))
5252 gdk_region_destroy (tmp_region);
5257 gdk_region_subtract (impl_window->update_area, tmp_region);
5259 if (gdk_region_empty (impl_window->update_area) &&
5260 impl_window->outstanding_moves == NULL)
5262 gdk_region_destroy (impl_window->update_area);
5263 impl_window->update_area = NULL;
5265 gdk_window_remove_update_window ((GdkWindow *)impl_window);
5268 /* Convert from impl coords */
5269 gdk_region_offset (tmp_region, -private->abs_x, -private->abs_y);
5279 * _gdk_window_clear_update_area:
5280 * @window: a #GdkWindow.
5282 * Internal function to clear the update area for a window. This
5283 * is called when the window is hidden or destroyed.
5286 _gdk_window_clear_update_area (GdkWindow *window)
5288 GdkWindowObject *private = (GdkWindowObject *)window;
5290 g_return_if_fail (GDK_IS_WINDOW (window));
5292 if (private->update_area)
5294 gdk_window_remove_update_window (window);
5296 gdk_region_destroy (private->update_area);
5297 private->update_area = NULL;
5302 * gdk_window_freeze_updates:
5303 * @window: a #GdkWindow
5305 * Temporarily freezes a window such that it won't receive expose
5306 * events. The window will begin receiving expose events again when
5307 * gdk_window_thaw_updates() is called. If gdk_window_freeze_updates()
5308 * has been called more than once, gdk_window_thaw_updates() must be called
5309 * an equal number of times to begin processing exposes.
5312 gdk_window_freeze_updates (GdkWindow *window)
5314 GdkWindowObject *private = (GdkWindowObject *)window;
5315 GdkWindowObject *impl_window;
5317 g_return_if_fail (GDK_IS_WINDOW (window));
5319 impl_window = gdk_window_get_impl_window (private);
5320 impl_window->update_freeze_count++;
5324 * gdk_window_thaw_updates:
5325 * @window: a #GdkWindow
5327 * Thaws a window frozen with gdk_window_freeze_updates().
5330 gdk_window_thaw_updates (GdkWindow *window)
5332 GdkWindowObject *private = (GdkWindowObject *)window;
5333 GdkWindowObject *impl_window;
5335 g_return_if_fail (GDK_IS_WINDOW (window));
5337 impl_window = gdk_window_get_impl_window (private);
5339 g_return_if_fail (impl_window->update_freeze_count > 0);
5341 if (--impl_window->update_freeze_count == 0)
5342 gdk_window_schedule_update (GDK_WINDOW (impl_window));
5346 * gdk_window_freeze_toplevel_updates_libgtk_only:
5347 * @window: a #GdkWindow
5349 * Temporarily freezes a window and all its descendants such that it won't
5350 * receive expose events. The window will begin receiving expose events
5351 * again when gdk_window_thaw_toplevel_updates_libgtk_only() is called. If
5352 * gdk_window_freeze_toplevel_updates_libgtk_only()
5353 * has been called more than once,
5354 * gdk_window_thaw_toplevel_updates_libgtk_only() must be called
5355 * an equal number of times to begin processing exposes.
5357 * This function is not part of the GDK public API and is only
5361 gdk_window_freeze_toplevel_updates_libgtk_only (GdkWindow *window)
5363 GdkWindowObject *private = (GdkWindowObject *)window;
5365 g_return_if_fail (GDK_IS_WINDOW (window));
5366 g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
5368 private->update_and_descendants_freeze_count++;
5372 * gdk_window_thaw_toplevel_updates_libgtk_only:
5373 * @window: a #GdkWindow
5375 * Thaws a window frozen with
5376 * gdk_window_freeze_toplevel_updates_libgtk_only().
5378 * This function is not part of the GDK public API and is only
5382 gdk_window_thaw_toplevel_updates_libgtk_only (GdkWindow *window)
5384 GdkWindowObject *private = (GdkWindowObject *)window;
5386 g_return_if_fail (GDK_IS_WINDOW (window));
5387 g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
5388 g_return_if_fail (private->update_and_descendants_freeze_count > 0);
5390 private->update_and_descendants_freeze_count--;
5392 gdk_window_schedule_update (window);
5396 * gdk_window_set_debug_updates:
5397 * @setting: %TRUE to turn on update debugging
5399 * With update debugging enabled, calls to
5400 * gdk_window_invalidate_region() clear the invalidated region of the
5401 * screen to a noticeable color, and GDK pauses for a short time
5402 * before sending exposes to windows during
5403 * gdk_window_process_updates(). The net effect is that you can see
5404 * the invalid region for each window and watch redraws as they
5405 * occur. This allows you to diagnose inefficiencies in your application.
5407 * In essence, because the GDK rendering model prevents all flicker,
5408 * if you are redrawing the same region 400 times you may never
5409 * notice, aside from noticing a speed problem. Enabling update
5410 * debugging causes GTK to flicker slowly and noticeably, so you can
5411 * see exactly what's being redrawn when, in what order.
5413 * The --gtk-debug=updates command line option passed to GTK+ programs
5414 * enables this debug option at application startup time. That's
5415 * usually more useful than calling gdk_window_set_debug_updates()
5416 * yourself, though you might want to use this function to enable
5417 * updates sometime after application startup time.
5421 gdk_window_set_debug_updates (gboolean setting)
5423 debug_updates = setting;
5427 * gdk_window_constrain_size:
5428 * @geometry: a #GdkGeometry structure
5429 * @flags: a mask indicating what portions of @geometry are set
5430 * @width: desired width of window
5431 * @height: desired height of the window
5432 * @new_width: location to store resulting width
5433 * @new_height: location to store resulting height
5435 * Constrains a desired width and height according to a
5436 * set of geometry hints (such as minimum and maximum size).
5439 gdk_window_constrain_size (GdkGeometry *geometry,
5446 /* This routine is partially borrowed from fvwm.
5448 * Copyright 1993, Robert Nation
5449 * You may use this code for any purpose, as long as the original
5450 * copyright remains in the source code and all documentation
5452 * which in turn borrows parts of the algorithm from uwm
5455 gint min_height = 0;
5456 gint base_width = 0;
5457 gint base_height = 0;
5460 gint max_width = G_MAXINT;
5461 gint max_height = G_MAXINT;
5463 #define FLOOR(value, base) ( ((gint) ((value) / (base))) * (base) )
5465 if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
5467 base_width = geometry->base_width;
5468 base_height = geometry->base_height;
5469 min_width = geometry->min_width;
5470 min_height = geometry->min_height;
5472 else if (flags & GDK_HINT_BASE_SIZE)
5474 base_width = geometry->base_width;
5475 base_height = geometry->base_height;
5476 min_width = geometry->base_width;
5477 min_height = geometry->base_height;
5479 else if (flags & GDK_HINT_MIN_SIZE)
5481 base_width = geometry->min_width;
5482 base_height = geometry->min_height;
5483 min_width = geometry->min_width;
5484 min_height = geometry->min_height;
5487 if (flags & GDK_HINT_MAX_SIZE)
5489 max_width = geometry->max_width ;
5490 max_height = geometry->max_height;
5493 if (flags & GDK_HINT_RESIZE_INC)
5495 xinc = MAX (xinc, geometry->width_inc);
5496 yinc = MAX (yinc, geometry->height_inc);
5499 /* clamp width and height to min and max values
5501 width = CLAMP (width, min_width, max_width);
5502 height = CLAMP (height, min_height, max_height);
5504 /* shrink to base + N * inc
5506 width = base_width + FLOOR (width - base_width, xinc);
5507 height = base_height + FLOOR (height - base_height, yinc);
5509 /* constrain aspect ratio, according to:
5512 * min_aspect <= -------- <= max_aspect
5516 if (flags & GDK_HINT_ASPECT &&
5517 geometry->min_aspect > 0 &&
5518 geometry->max_aspect > 0)
5522 if (geometry->min_aspect * height > width)
5524 delta = FLOOR (height - width / geometry->min_aspect, yinc);
5525 if (height - delta >= min_height)
5529 delta = FLOOR (height * geometry->min_aspect - width, xinc);
5530 if (width + delta <= max_width)
5535 if (geometry->max_aspect * height < width)
5537 delta = FLOOR (width - height * geometry->max_aspect, xinc);
5538 if (width - delta >= min_width)
5542 delta = FLOOR (width / geometry->max_aspect - height, yinc);
5543 if (height + delta <= max_height)
5552 *new_height = height;
5556 * gdk_window_get_pointer:
5557 * @window: a #GdkWindow
5558 * @x: return location for X coordinate of pointer or %NULL to not
5559 * return the X coordinate
5560 * @y: return location for Y coordinate of pointer or %NULL to not
5561 * return the Y coordinate
5562 * @mask: return location for modifier mask or %NULL to not return the
5565 * Obtains the current pointer position and modifier state.
5566 * The position is given in coordinates relative to the upper left
5567 * corner of @window.
5569 * Return value: the window containing the pointer (as with
5570 * gdk_window_at_pointer()), or %NULL if the window containing the
5571 * pointer isn't known to GDK
5574 gdk_window_get_pointer (GdkWindow *window,
5577 GdkModifierType *mask)
5579 GdkDisplay *display;
5581 GdkModifierType tmp_mask;
5584 g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
5588 display = gdk_drawable_get_display (window);
5592 GdkScreen *screen = gdk_screen_get_default ();
5594 display = gdk_screen_get_display (screen);
5595 window = gdk_screen_get_root_window (screen);
5597 GDK_NOTE (MULTIHEAD,
5598 g_message ("Passing NULL for window to gdk_window_get_pointer()\n"
5599 "is not multihead safe"));
5602 child = display->pointer_hooks->window_get_pointer (display, window, &tmp_x, &tmp_y, &tmp_mask);
5611 _gdk_display_enable_motion_hints (display);
5617 * gdk_window_at_pointer:
5618 * @win_x: return location for origin of the window under the pointer
5619 * @win_y: return location for origin of the window under the pointer
5621 * Obtains the window underneath the mouse pointer, returning the
5622 * location of that window in @win_x, @win_y. Returns %NULL if the
5623 * window under the mouse pointer is not known to GDK (if the window
5624 * belongs to another application and a #GdkWindow hasn't been created
5625 * for it with gdk_window_foreign_new())
5627 * NOTE: For multihead-aware widgets or applications use
5628 * gdk_display_get_window_at_pointer() instead.
5630 * Return value: window under the mouse pointer
5633 gdk_window_at_pointer (gint *win_x,
5636 return gdk_display_get_window_at_pointer (gdk_display_get_default (), win_x, win_y);
5640 * gdk_get_default_root_window:
5642 * Obtains the root window (parent all other windows are inside)
5643 * for the default display and screen.
5645 * Return value: the default root window
5648 gdk_get_default_root_window (void)
5650 return gdk_screen_get_root_window (gdk_screen_get_default ());
5654 * gdk_window_foreign_new:
5655 * @anid: a native window handle.
5657 * Wraps a native window for the default display in a #GdkWindow.
5658 * This may fail if the window has been destroyed.
5660 * For example in the X backend, a native window handle is an Xlib
5663 * Return value: the newly-created #GdkWindow wrapper for the
5664 * native window or %NULL if the window has been destroyed.
5667 gdk_window_foreign_new (GdkNativeWindow anid)
5669 return gdk_window_foreign_new_for_display (gdk_display_get_default (), anid);
5673 get_all_native_children (GdkWindowObject *private,
5676 GdkWindowObject *child;
5679 for (l = private->children; l != NULL; l = l->next)
5683 if (gdk_window_has_impl (child))
5684 *native = g_list_prepend (*native, child);
5686 get_all_native_children (child, native);
5692 gdk_window_raise_internal (GdkWindow *window)
5694 GdkWindowObject *private = (GdkWindowObject *)window;
5695 GdkWindowObject *parent = private->parent;
5696 GdkWindowObject *above;
5697 GList *native_children;
5702 parent->children = g_list_remove (parent->children, window);
5703 parent->children = g_list_prepend (parent->children, window);
5706 /* Just do native raise for toplevels */
5707 if (private->parent == NULL ||
5708 GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
5710 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
5712 else if (gdk_window_has_impl (private))
5714 above = find_native_sibling_above (parent, private);
5717 listhead.data = window;
5718 listhead.next = NULL;
5719 listhead.prev = NULL;
5720 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
5724 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
5728 native_children = NULL;
5729 get_all_native_children (private, &native_children);
5730 if (native_children != NULL)
5732 above = find_native_sibling_above (parent, private);
5735 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
5739 /* Right order, since native_children is bottom-topmost first */
5740 for (l = native_children; l != NULL; l = l->next)
5741 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (l->data);
5744 g_list_free (native_children);
5750 /* Showing a non-native parent may cause children to become visible,
5751 we need to handle this by manually showing them then. To simplify
5752 things we hide them all when they are not visible. */
5754 show_all_visible_impls (GdkWindowObject *private, gboolean already_mapped)
5756 GdkWindowObject *child;
5759 for (l = private->children; l != NULL; l = l->next)
5763 /* For foreign windows, only show if if was
5764 explicitly hidden, otherwise we might cause
5765 suprising things to happen to the other client. */
5766 if (GDK_WINDOW_IS_MAPPED (child) &&
5767 GDK_WINDOW_TYPE (child) != GDK_WINDOW_FOREIGN)
5768 show_all_visible_impls (child, FALSE);
5771 if (gdk_window_has_impl (private))
5772 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show ((GdkWindow *)private, already_mapped);
5776 gdk_window_show_internal (GdkWindow *window, gboolean raise)
5778 GdkWindowObject *private;
5779 gboolean was_mapped;
5781 g_return_if_fail (GDK_IS_WINDOW (window));
5783 private = (GdkWindowObject *) window;
5784 if (private->destroyed)
5787 was_mapped = GDK_WINDOW_IS_MAPPED (window);
5790 /* Keep children in (reverse) stacking order */
5791 gdk_window_raise_internal (window);
5793 if (gdk_window_has_impl (private))
5796 gdk_synthesize_window_state (window,
5797 GDK_WINDOW_STATE_WITHDRAWN,
5805 if (gdk_window_is_viewable (window))
5806 show_all_visible_impls (private, was_mapped);
5808 if (!was_mapped && !gdk_window_has_impl (private))
5810 if (private->event_mask & GDK_STRUCTURE_MASK)
5811 _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
5813 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
5814 _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
5817 if (!was_mapped || raise)
5819 recompute_visible_regions (private, TRUE, FALSE);
5821 /* If any decendants became visible we need to send visibility notify */
5822 gdk_window_update_visibility_recursively (private, NULL);
5824 if (gdk_window_is_viewable (window))
5826 _gdk_synthesize_crossing_events_for_geometry_change (window);
5827 gdk_window_invalidate_rect (window, NULL, TRUE);
5833 * gdk_window_show_unraised:
5834 * @window: a #GdkWindow
5836 * Shows a #GdkWindow onscreen, but does not modify its stacking
5837 * order. In contrast, gdk_window_show() will raise the window
5838 * to the top of the window stack.
5840 * On the X11 platform, in Xlib terms, this function calls
5841 * XMapWindow() (it also updates some internal GDK state, which means
5842 * that you can't really use XMapWindow() directly on a GDK window).
5845 gdk_window_show_unraised (GdkWindow *window)
5847 gdk_window_show_internal (window, FALSE);
5852 * @window: a #GdkWindow
5854 * Raises @window to the top of the Z-order (stacking order), so that
5855 * other windows with the same parent window appear below @window.
5856 * This is true whether or not the windows are visible.
5858 * If @window is a toplevel, the window manager may choose to deny the
5859 * request to move the window in the Z-order, gdk_window_raise() only
5860 * requests the restack, does not guarantee it.
5863 gdk_window_raise (GdkWindow *window)
5865 GdkWindowObject *private;
5867 g_return_if_fail (GDK_IS_WINDOW (window));
5869 private = (GdkWindowObject *) window;
5870 if (private->destroyed)
5873 /* Keep children in (reverse) stacking order */
5874 gdk_window_raise_internal (window);
5876 recompute_visible_regions (private, TRUE, FALSE);
5878 gdk_window_invalidate_rect (window, NULL, TRUE);
5882 gdk_window_lower_internal (GdkWindow *window)
5884 GdkWindowObject *private = (GdkWindowObject *)window;
5885 GdkWindowObject *parent = private->parent;
5886 GdkWindowObject *above;
5887 GList *native_children;
5892 parent->children = g_list_remove (parent->children, window);
5893 parent->children = g_list_append (parent->children, window);
5896 /* Just do native lower for toplevels */
5897 if (private->parent == NULL ||
5898 GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
5900 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->lower (window);
5902 else if (gdk_window_has_impl (private))
5904 above = find_native_sibling_above (parent, private);
5907 listhead.data = window;
5908 listhead.next = NULL;
5909 listhead.prev = NULL;
5910 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
5914 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
5918 native_children = NULL;
5919 get_all_native_children (private, &native_children);
5920 if (native_children != NULL)
5922 above = find_native_sibling_above (parent, private);
5925 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
5929 /* Right order, since native_children is bottom-topmost first */
5930 for (l = native_children; l != NULL; l = l->next)
5931 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (l->data);
5934 g_list_free (native_children);
5941 gdk_window_invalidate_in_parent (GdkWindowObject *private)
5943 GdkRectangle r, child;
5945 if (private->parent == NULL ||
5946 GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
5949 /* get the visible rectangle of the parent */
5951 r.width = private->parent->width;
5952 r.height = private->parent->height;
5954 child.x = private->x;
5955 child.y = private->y;
5956 child.width = private->width;
5957 child.height = private->height;
5958 gdk_rectangle_intersect (&r, &child, &r);
5960 gdk_window_invalidate_rect (GDK_WINDOW (private->parent), &r, TRUE);
5966 * @window: a #GdkWindow
5968 * Lowers @window to the bottom of the Z-order (stacking order), so that
5969 * other windows with the same parent window appear above @window.
5970 * This is true whether or not the other windows are visible.
5972 * If @window is a toplevel, the window manager may choose to deny the
5973 * request to move the window in the Z-order, gdk_window_lower() only
5974 * requests the restack, does not guarantee it.
5976 * Note that gdk_window_show() raises the window again, so don't call this
5977 * function before gdk_window_show(). (Try gdk_window_show_unraised().)
5980 gdk_window_lower (GdkWindow *window)
5982 GdkWindowObject *private;
5984 g_return_if_fail (GDK_IS_WINDOW (window));
5986 private = (GdkWindowObject *) window;
5987 if (private->destroyed)
5990 /* Keep children in (reverse) stacking order */
5991 gdk_window_lower_internal (window);
5993 recompute_visible_regions (private, TRUE, FALSE);
5995 _gdk_synthesize_crossing_events_for_geometry_change (window);
5996 gdk_window_invalidate_in_parent (private);
6001 * @window: a #GdkWindow
6003 * Like gdk_window_show_unraised(), but also raises the window to the
6004 * top of the window stack (moves the window to the front of the
6007 * This function maps a window so it's visible onscreen. Its opposite
6008 * is gdk_window_hide().
6010 * When implementing a #GtkWidget, you should call this function on the widget's
6011 * #GdkWindow as part of the "map" method.
6014 gdk_window_show (GdkWindow *window)
6016 gdk_window_show_internal (window, TRUE);
6019 /* Hiding a non-native parent may cause parents to become non-visible,
6020 even if their parent native window is visible. We need to handle this
6021 by manually hiding them then. To simplify things we hide them all
6022 when they are not visible. */
6024 hide_all_visible_impls (GdkWindowObject *private)
6026 GdkWindowObject *child;
6029 for (l = private->children; l != NULL; l = l->next)
6033 /* For foreign windows, only hide if if was
6034 explicitly hidden, otherwise we might cause
6035 suprising things to happen to the other client. */
6036 if (GDK_WINDOW_IS_MAPPED (child) &&
6037 GDK_WINDOW_TYPE (child) != GDK_WINDOW_FOREIGN)
6038 hide_all_visible_impls (child);
6041 if (gdk_window_has_impl (private))
6042 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->hide ((GdkWindow *)private);
6048 * @window: a #GdkWindow
6050 * For toplevel windows, withdraws them, so they will no longer be
6051 * known to the window manager; for all windows, unmaps them, so
6052 * they won't be displayed. Normally done automatically as
6053 * part of gtk_widget_hide().
6056 gdk_window_hide (GdkWindow *window)
6058 GdkWindowObject *private;
6059 gboolean was_mapped, was_viewable;
6061 g_return_if_fail (GDK_IS_WINDOW (window));
6063 private = (GdkWindowObject *) window;
6064 if (private->destroyed)
6067 was_mapped = GDK_WINDOW_IS_MAPPED (private);
6068 was_viewable = gdk_window_is_viewable (window);
6070 if (gdk_window_has_impl (private))
6073 if (GDK_WINDOW_IS_MAPPED (window))
6074 gdk_synthesize_window_state (window,
6076 GDK_WINDOW_STATE_WITHDRAWN);
6078 else if (was_mapped)
6080 GdkDisplay *display;
6082 /* May need to break grabs on children */
6083 display = gdk_drawable_get_display (window);
6085 if (_gdk_display_end_pointer_grab (display,
6086 _gdk_windowing_window_get_next_serial (display),
6089 gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
6091 if (display->keyboard_grab.window != NULL)
6093 if (is_parent_of (window, display->keyboard_grab.window))
6095 /* Call this ourselves, even though gdk_display_keyboard_ungrab
6096 does so too, since we want to pass implicit == TRUE so the
6097 broken grab event is generated */
6098 _gdk_display_unset_has_keyboard_grab (display,
6100 gdk_display_keyboard_ungrab (display, GDK_CURRENT_TIME);
6104 private->state = GDK_WINDOW_STATE_WITHDRAWN;
6108 hide_all_visible_impls (private);
6110 recompute_visible_regions (private, TRUE, FALSE);
6112 /* all decendants became non-visible, we need to send visibility notify */
6113 gdk_window_update_visibility_recursively (private, NULL);
6115 if (was_mapped && !gdk_window_has_impl (private))
6117 if (private->event_mask & GDK_STRUCTURE_MASK)
6118 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6120 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
6121 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6123 _gdk_synthesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
6126 /* Invalidate the rect */
6127 gdk_window_invalidate_in_parent (private);
6131 * gdk_window_withdraw:
6132 * @window: a toplevel #GdkWindow
6134 * Withdraws a window (unmaps it and asks the window manager to forget about it).
6135 * This function is not really useful as gdk_window_hide() automatically
6136 * withdraws toplevel windows before hiding them.
6139 gdk_window_withdraw (GdkWindow *window)
6141 GdkWindowObject *private;
6142 gboolean was_mapped;
6144 g_return_if_fail (GDK_IS_WINDOW (window));
6146 private = (GdkWindowObject *) window;
6147 if (private->destroyed)
6150 was_mapped = GDK_WINDOW_IS_MAPPED (private);
6152 if (gdk_window_has_impl (private))
6154 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->withdraw (window);
6158 if (private->event_mask & GDK_STRUCTURE_MASK)
6159 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6161 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
6162 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6164 _gdk_synthesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
6167 recompute_visible_regions (private, TRUE, FALSE);
6172 * gdk_window_set_events:
6173 * @window: a #GdkWindow
6174 * @event_mask: event mask for @window
6176 * The event mask for a window determines which events will be reported
6177 * for that window. For example, an event mask including #GDK_BUTTON_PRESS_MASK
6178 * means the window should report button press events. The event mask
6179 * is the bitwise OR of values from the #GdkEventMask enumeration.
6182 gdk_window_set_events (GdkWindow *window,
6183 GdkEventMask event_mask)
6185 GdkWindowObject *private;
6186 GdkDisplay *display;
6189 g_return_if_fail (GDK_IS_WINDOW (window));
6191 private = (GdkWindowObject *) window;
6192 if (private->destroyed)
6195 /* If motion hint is disabled, enable motion events again */
6196 display = gdk_drawable_get_display (window);
6197 if ((private->event_mask & GDK_POINTER_MOTION_HINT_MASK) &&
6198 !(event_mask & GDK_POINTER_MOTION_HINT_MASK))
6199 _gdk_display_enable_motion_hints (display);
6201 private->event_mask = event_mask;
6203 if (gdk_window_has_impl (private))
6204 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_events (window,
6205 get_native_event_mask (private));
6210 * gdk_window_get_events:
6211 * @window: a #GdkWindow
6213 * Gets the event mask for @window. See gdk_window_set_events().
6215 * Return value: event mask for @window
6218 gdk_window_get_events (GdkWindow *window)
6220 GdkWindowObject *private;
6222 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
6224 private = (GdkWindowObject *) window;
6225 if (private->destroyed)
6228 return private->event_mask;
6232 gdk_window_move_resize_toplevel (GdkWindow *window,
6239 GdkWindowObject *private;
6240 GdkRegion *old_region, *new_region;
6241 GdkWindowObject *impl_window;
6243 int old_x, old_y, old_abs_x, old_abs_y;
6247 private = (GdkWindowObject *) window;
6252 impl_window = gdk_window_get_impl_window (private);
6257 is_resize = (width != -1) || (height != -1);
6259 if (gdk_window_is_viewable (window) &&
6260 !private->input_only)
6263 old_region = gdk_region_copy (private->clip_region);
6266 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, with_move, x, y, width, height);
6268 dx = private->x - old_x;
6269 dy = private->y - old_y;
6271 old_abs_x = private->abs_x;
6272 old_abs_y = private->abs_y;
6274 /* Avoid recomputing for pure toplevel moves, for performance reasons */
6276 recompute_visible_regions (private, TRUE, FALSE);
6280 new_region = gdk_region_copy (private->clip_region);
6282 /* This is the newly exposed area (due to any resize),
6283 * X will expose it, but lets do that without the
6286 gdk_region_subtract (new_region, old_region);
6287 gdk_window_invalidate_region (window, new_region, TRUE);
6289 gdk_region_destroy (old_region);
6290 gdk_region_destroy (new_region);
6293 _gdk_synthesize_crossing_events_for_geometry_change (window);
6298 move_native_children (GdkWindowObject *private)
6301 GdkWindowObject *child;
6303 for (l = private->children; l; l = l->next)
6307 if (child->impl != private->impl)
6308 GDK_WINDOW_IMPL_GET_IFACE (child->impl)->move_resize ((GdkWindow *)child, TRUE, child->x, child->y, child->width, child->height);
6310 move_native_children (child);
6315 collect_native_child_region_helper (GdkWindowObject *window,
6321 GdkWindowObject *child;
6325 for (l = window->children; l != NULL; l = l->next)
6329 if (child->impl != impl)
6331 tmp = gdk_region_copy (child->clip_region);
6332 gdk_region_offset (tmp,
6333 x_offset + child->x,
6334 y_offset + child->y);
6335 if (*region == NULL)
6339 gdk_region_union (*region, tmp);
6340 gdk_region_destroy (tmp);
6344 collect_native_child_region_helper (child, impl, region,
6345 x_offset + child->x,
6346 y_offset + child->y);
6353 collect_native_child_region (GdkWindowObject *window,
6354 gboolean include_this)
6358 if (include_this && gdk_window_has_impl (window))
6359 return gdk_region_copy (window->clip_region);
6363 collect_native_child_region_helper (window, window->impl, ®ion, 0, 0);
6370 gdk_window_move_resize_internal (GdkWindow *window,
6377 GdkWindowObject *private;
6378 GdkRegion *old_region, *new_region, *copy_area;
6379 GdkRegion *old_native_child_region, *new_native_child_region;
6380 GdkWindowObject *impl_window;
6382 int old_x, old_y, old_abs_x, old_abs_y;
6385 g_return_if_fail (GDK_IS_WINDOW (window));
6387 private = (GdkWindowObject *) window;
6388 if (private->destroyed)
6391 if (private->parent == NULL ||
6392 GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
6394 gdk_window_move_resize_toplevel (window, with_move, x, y, width, height);
6398 /* Handle child windows */
6403 impl_window = gdk_window_get_impl_window (private);
6408 if (gdk_window_is_viewable (window) &&
6409 !private->input_only)
6413 old_region = gdk_region_copy (private->clip_region);
6414 /* Adjust region to parent window coords */
6415 gdk_region_offset (old_region, private->x, private->y);
6418 old_native_child_region = collect_native_child_region (private, TRUE);
6419 if (old_native_child_region)
6421 /* Adjust region to parent window coords */
6422 gdk_region_offset (old_native_child_region, private->x, private->y);
6424 /* Any native window move will immediately copy stuff to the destination, which may overwrite a
6425 * source or destination for a delayed GdkWindowRegionMove. So, we need
6426 * to flush those here for the parent window and all overlapped subwindows
6427 * of it. And we need to do this before setting the new clips as those will be
6430 gdk_window_flush_recursive (private->parent);
6433 /* Set the new position and size */
6439 if (!(width < 0 && height < 0))
6443 private->width = width;
6446 private->height = height;
6449 dx = private->x - old_x;
6450 dy = private->y - old_y;
6452 old_abs_x = private->abs_x;
6453 old_abs_y = private->abs_y;
6455 recompute_visible_regions (private, TRUE, FALSE);
6457 new_native_child_region = NULL;
6458 if (old_native_child_region)
6460 new_native_child_region = collect_native_child_region (private, TRUE);
6461 /* Adjust region to parent window coords */
6462 gdk_region_offset (new_native_child_region, private->x, private->y);
6465 if (gdk_window_has_impl (private))
6467 /* Do the actual move after recomputing things, as this will have set the shape to
6468 the now correct one, thus avoiding copying regions that should not be copied. */
6469 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, TRUE, private->x, private->y, private->width, private->height);
6471 else if (old_abs_x != private->abs_x ||
6472 old_abs_y != private->abs_y)
6473 move_native_children (private);
6477 new_region = gdk_region_copy (private->clip_region);
6478 /* Adjust region to parent window coords */
6479 gdk_region_offset (new_region, private->x, private->y);
6482 * Part of the data at the new location can be copied from the
6483 * old location, this area is the intersection of the old region
6484 * moved as the copy will move it and then intersected with
6488 * Everything in the old and new regions that is not copied must be
6489 * invalidated (including children) as this is newly exposed
6491 copy_area = gdk_region_copy (new_region);
6493 gdk_region_union (new_region, old_region);
6495 if (old_native_child_region)
6497 /* Don't copy from inside native children, as this is copied by
6498 * the native window move.
6500 gdk_region_subtract (old_region, old_native_child_region);
6502 gdk_region_offset (old_region, dx, dy);
6504 gdk_region_intersect (copy_area, old_region);
6506 if (new_native_child_region)
6508 /* Don't copy any bits that would cause a read from the moved
6509 native windows, as we can't read that data */
6510 gdk_region_offset (new_native_child_region, dx, dy);
6511 gdk_region_subtract (copy_area, new_native_child_region);
6514 gdk_region_subtract (new_region, copy_area);
6516 /* Convert old region to impl coords */
6517 gdk_region_offset (old_region, -dx + private->abs_x - private->x, -dy + private->abs_y - private->y);
6519 /* convert from parent coords to impl */
6520 gdk_region_offset (copy_area, private->abs_x - private->x, private->abs_y - private->y);
6522 move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
6524 /* Invalidate affected part in the parent window
6525 * (no higher window should be affected)
6526 * We also invalidate any children in that area, which could include
6527 * this window if it still overlaps that area.
6529 gdk_window_invalidate_region (GDK_WINDOW (private->parent), new_region, TRUE);
6531 gdk_region_destroy (old_region);
6532 gdk_region_destroy (new_region);
6535 if (old_native_child_region)
6537 gdk_region_destroy (old_native_child_region);
6538 gdk_region_destroy (new_native_child_region);
6541 _gdk_synthesize_crossing_events_for_geometry_change (window);
6548 * @window: a #GdkWindow
6549 * @x: X coordinate relative to window's parent
6550 * @y: Y coordinate relative to window's parent
6552 * Repositions a window relative to its parent window.
6553 * For toplevel windows, window managers may ignore or modify the move;
6554 * you should probably use gtk_window_move() on a #GtkWindow widget
6555 * anyway, instead of using GDK functions. For child windows,
6556 * the move will reliably succeed.
6558 * If you're also planning to resize the window, use gdk_window_move_resize()
6559 * to both move and resize simultaneously, for a nicer visual effect.
6562 gdk_window_move (GdkWindow *window,
6566 gdk_window_move_resize_internal (window, TRUE, x, y, -1, -1);
6570 * gdk_window_resize:
6571 * @window: a #GdkWindow
6572 * @width: new width of the window
6573 * @height: new height of the window
6575 * Resizes @window; for toplevel windows, asks the window manager to resize
6576 * the window. The window manager may not allow the resize. When using GTK+,
6577 * use gtk_window_resize() instead of this low-level GDK function.
6579 * Windows may not be resized below 1x1.
6581 * If you're also planning to move the window, use gdk_window_move_resize()
6582 * to both move and resize simultaneously, for a nicer visual effect.
6585 gdk_window_resize (GdkWindow *window,
6589 gdk_window_move_resize_internal (window, FALSE, 0, 0, width, height);
6594 * gdk_window_move_resize:
6595 * @window: a #GdkWindow
6596 * @x: new X position relative to window's parent
6597 * @y: new Y position relative to window's parent
6599 * @height: new height
6601 * Equivalent to calling gdk_window_move() and gdk_window_resize(),
6602 * except that both operations are performed at once, avoiding strange
6603 * visual effects. (i.e. the user may be able to see the window first
6604 * move, then resize, if you don't use gdk_window_move_resize().)
6607 gdk_window_move_resize (GdkWindow *window,
6613 gdk_window_move_resize_internal (window, TRUE, x, y, width, height);
6618 * gdk_window_scroll:
6619 * @window: a #GdkWindow
6620 * @dx: Amount to scroll in the X direction
6621 * @dy: Amount to scroll in the Y direction
6623 * Scroll the contents of @window, both pixels and children, by the
6624 * given amount. @window itself does not move. Portions of the window
6625 * that the scroll operation brings in from offscreen areas are
6626 * invalidated. The invalidated region may be bigger than what would
6627 * strictly be necessary.
6629 * For X11, a minimum area will be invalidated if the window has no
6630 * subwindows, or if the edges of the window's parent do not extend
6631 * beyond the edges of the window. In other cases, a multi-step process
6632 * is used to scroll the window which may produce temporary visual
6633 * artifacts and unnecessary invalidations.
6636 gdk_window_scroll (GdkWindow *window,
6640 GdkWindowObject *private = (GdkWindowObject *) window;
6641 GdkWindowObject *impl_window;
6642 GdkRegion *copy_area, *noncopy_area;
6643 GdkRegion *old_native_child_region, *new_native_child_region;
6646 g_return_if_fail (GDK_IS_WINDOW (window));
6648 if (dx == 0 && dy == 0)
6651 if (private->destroyed)
6654 old_native_child_region = collect_native_child_region (private, FALSE);
6655 if (old_native_child_region)
6657 /* Any native window move will immediately copy stuff to the destination, which may overwrite a
6658 * source or destination for a delayed GdkWindowRegionMove. So, we need
6659 * to flush those here for the window and all overlapped subwindows
6660 * of it. And we need to do this before setting the new clips as those will be
6663 gdk_window_flush_recursive (private);
6667 /* First move all child windows, without causing invalidation */
6669 tmp_list = private->children;
6672 GdkWindow *child = GDK_WINDOW (tmp_list->data);
6673 GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
6675 /* Just update the positions, the bits will move with the copy */
6679 tmp_list = tmp_list->next;
6682 recompute_visible_regions (private, FALSE, TRUE);
6684 new_native_child_region = NULL;
6685 if (old_native_child_region)
6686 new_native_child_region = collect_native_child_region (private, FALSE);
6688 move_native_children (private);
6690 /* Then copy the actual bits of the window w/ child windows */
6692 impl_window = gdk_window_get_impl_window (private);
6694 /* Calculate the area that can be gotten by copying the old area */
6695 copy_area = gdk_region_copy (private->clip_region);
6696 if (old_native_child_region)
6698 /* Don't copy from inside native children, as this is copied by
6699 * the native window move.
6701 gdk_region_subtract (copy_area, old_native_child_region);
6703 /* Don't copy any bits that would cause a read from the moved
6704 native windows, as we can't read that data */
6705 gdk_region_subtract (copy_area, new_native_child_region);
6707 gdk_region_offset (copy_area, dx, dy);
6708 gdk_region_intersect (copy_area, private->clip_region);
6710 /* And the rest need to be invalidated */
6711 noncopy_area = gdk_region_copy (private->clip_region);
6712 gdk_region_subtract (noncopy_area, copy_area);
6714 /* convert from window coords to impl */
6715 gdk_region_offset (copy_area, private->abs_x, private->abs_y);
6717 move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
6719 /* Invalidate not copied regions */
6720 gdk_window_invalidate_region (window, noncopy_area, TRUE);
6722 gdk_region_destroy (noncopy_area);
6724 if (old_native_child_region)
6726 gdk_region_destroy (old_native_child_region);
6727 gdk_region_destroy (new_native_child_region);
6730 _gdk_synthesize_crossing_events_for_geometry_change (window);
6734 * gdk_window_move_region:
6735 * @window: a #GdkWindow
6736 * @region: The #GdkRegion to move
6737 * @dx: Amount to move in the X direction
6738 * @dy: Amount to move in the Y direction
6740 * Move the part of @window indicated by @region by @dy pixels in the Y
6741 * direction and @dx pixels in the X direction. The portions of @region
6742 * that not covered by the new position of @region are invalidated.
6744 * Child windows are not moved.
6749 gdk_window_move_region (GdkWindow *window,
6750 const GdkRegion *region,
6754 GdkWindowObject *private = (GdkWindowObject *) window;
6755 GdkWindowObject *impl_window;
6756 GdkRegion *nocopy_area;
6757 GdkRegion *copy_area;
6759 g_return_if_fail (GDK_IS_WINDOW (window));
6760 g_return_if_fail (region != NULL);
6762 if (dx == 0 && dy == 0)
6765 if (private->destroyed)
6768 impl_window = gdk_window_get_impl_window (private);
6770 /* compute source regions */
6771 copy_area = gdk_region_copy (region);
6772 gdk_region_intersect (copy_area, private->clip_region_with_children);
6774 /* compute destination regions */
6775 gdk_region_offset (copy_area, dx, dy);
6776 gdk_region_intersect (copy_area, private->clip_region_with_children);
6778 /* invalidate parts of the region not covered by the copy */
6779 nocopy_area = gdk_region_copy (region);
6780 gdk_region_offset (nocopy_area, dx, dy);
6781 gdk_region_subtract (nocopy_area, copy_area);
6782 gdk_window_invalidate_region (window, nocopy_area, FALSE);
6783 gdk_region_destroy (nocopy_area);
6785 /* convert from window coords to impl */
6786 gdk_region_offset (copy_area, private->abs_x, private->abs_y);
6788 move_region_on_impl (impl_window, copy_area, dx, dy); /* Takes ownership of copy_area */
6792 * gdk_window_set_background:
6793 * @window: a #GdkWindow
6794 * @color: an allocated #GdkColor
6796 * Sets the background color of @window. (However, when using GTK+,
6797 * set the background of a widget with gtk_widget_modify_bg() - if
6798 * you're an application - or gtk_style_set_background() - if you're
6799 * implementing a custom widget.)
6801 * The @color must be allocated; gdk_rgb_find_color() is the best way
6802 * to allocate a color.
6804 * See also gdk_window_set_back_pixmap().
6807 gdk_window_set_background (GdkWindow *window,
6808 const GdkColor *color)
6810 GdkWindowObject *private;
6811 GdkColormap *colormap = gdk_drawable_get_colormap (window);
6813 g_return_if_fail (GDK_IS_WINDOW (window));
6815 private = (GdkWindowObject *) window;
6817 private->bg_color = *color;
6818 gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
6820 if (private->bg_pixmap &&
6821 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
6822 private->bg_pixmap != GDK_NO_BG)
6823 g_object_unref (private->bg_pixmap);
6825 private->bg_pixmap = NULL;
6827 if (!GDK_WINDOW_DESTROYED (window) &&
6828 gdk_window_has_impl (private) &&
6829 !private->input_only)
6830 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, &private->bg_color);
6834 * gdk_window_set_back_pixmap:
6835 * @window: a #GdkWindow
6836 * @pixmap: a #GdkPixmap, or %NULL
6837 * @parent_relative: whether the tiling origin is at the origin of
6840 * Sets the background pixmap of @window. May also be used to set a
6841 * background of "None" on @window, by setting a background pixmap
6844 * A background pixmap will be tiled, positioning the first tile at
6845 * the origin of @window, or if @parent_relative is %TRUE, the tiling
6846 * will be done based on the origin of the parent window (useful to
6847 * align tiles in a parent with tiles in a child).
6849 * A background pixmap of %NULL means that the window will have no
6850 * background. A window with no background will never have its
6851 * background filled by the windowing system, instead the window will
6852 * contain whatever pixels were already in the corresponding area of
6855 * The windowing system will normally fill a window with its background
6856 * when the window is obscured then exposed, and when you call
6857 * gdk_window_clear().
6860 gdk_window_set_back_pixmap (GdkWindow *window,
6862 gboolean parent_relative)
6864 GdkWindowObject *private;
6866 g_return_if_fail (GDK_IS_WINDOW (window));
6867 g_return_if_fail (pixmap == NULL || !parent_relative);
6868 g_return_if_fail (pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap));
6870 private = (GdkWindowObject *) window;
6872 if (pixmap && !gdk_drawable_get_colormap (pixmap))
6874 g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
6878 if (private->bg_pixmap &&
6879 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
6880 private->bg_pixmap != GDK_NO_BG)
6881 g_object_unref (private->bg_pixmap);
6883 if (parent_relative)
6884 private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
6886 private->bg_pixmap = g_object_ref (pixmap);
6888 private->bg_pixmap = GDK_NO_BG;
6890 if (!GDK_WINDOW_DESTROYED (window) &&
6891 gdk_window_has_impl (private) &&
6892 !private->input_only)
6893 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, private->bg_pixmap);
6897 * gdk_window_set_cursor:
6898 * @window: a #GdkWindow
6901 * Sets the mouse pointer for a #GdkWindow. Use gdk_cursor_new_for_display()
6902 * or gdk_cursor_new_from_pixmap() to create the cursor. To make the cursor
6903 * invisible, use %GDK_BLANK_CURSOR. Passing %NULL for the @cursor argument
6904 * to gdk_window_set_cursor() means that @window will use the cursor of its
6905 * parent window. Most windows should use this default.
6908 gdk_window_set_cursor (GdkWindow *window,
6911 GdkWindowObject *private;
6912 GdkDisplay *display;
6914 g_return_if_fail (GDK_IS_WINDOW (window));
6916 private = (GdkWindowObject *) window;
6917 display = gdk_drawable_get_display (window);
6919 if (private->cursor)
6921 gdk_cursor_unref (private->cursor);
6922 private->cursor = NULL;
6925 if (!GDK_WINDOW_DESTROYED (window))
6928 private->cursor = gdk_cursor_ref (cursor);
6930 if (_gdk_window_event_parent_of (window, display->pointer_info.window_under_pointer))
6931 update_cursor (display);
6936 * gdk_window_get_geometry:
6937 * @window: a #GdkWindow
6938 * @x: return location for X coordinate of window (relative to its parent)
6939 * @y: return location for Y coordinate of window (relative to its parent)
6940 * @width: return location for width of window
6941 * @height: return location for height of window
6942 * @depth: return location for bit depth of window
6944 * Any of the return location arguments to this function may be %NULL,
6945 * if you aren't interested in getting the value of that field.
6947 * The X and Y coordinates returned are relative to the parent window
6948 * of @window, which for toplevels usually means relative to the
6949 * window decorations (titlebar, etc.) rather than relative to the
6950 * root window (screen-size background window).
6952 * On the X11 platform, the geometry is obtained from the X server,
6953 * so reflects the latest position of @window; this may be out-of-sync
6954 * with the position of @window delivered in the most-recently-processed
6955 * #GdkEventConfigure. gdk_window_get_position() in contrast gets the
6956 * position from the most recent configure event.
6959 * If @window is not a toplevel, it is <emphasis>much</emphasis> better
6960 * to call gdk_window_get_position() and gdk_drawable_get_size() instead,
6961 * because it avoids the roundtrip to the X server and because
6962 * gdk_drawable_get_size() supports the full 32-bit coordinate space,
6963 * whereas gdk_window_get_geometry() is restricted to the 16-bit
6964 * coordinates of X11.
6968 gdk_window_get_geometry (GdkWindow *window,
6975 GdkWindowObject *private;
6979 GDK_NOTE (MULTIHEAD,
6980 g_message ("gdk_window_get_geometry(): Window needs "
6981 "to be non-NULL to be multi head safe"));
6982 window = gdk_screen_get_root_window ((gdk_screen_get_default ()));
6985 g_return_if_fail (GDK_IS_WINDOW (window));
6987 private = (GdkWindowObject *) window;
6989 if (!GDK_WINDOW_DESTROYED (window))
6991 if (gdk_window_has_impl (private))
6992 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_geometry (window, x, y,
7002 *width = private->width;
7004 *height = private->height;
7006 *depth = private->depth;
7012 * gdk_window_get_origin:
7013 * @window: a #GdkWindow
7014 * @x: return location for X coordinate
7015 * @y: return location for Y coordinate
7017 * Obtains the position of a window in root window coordinates.
7018 * (Compare with gdk_window_get_position() and
7019 * gdk_window_get_geometry() which return the position of a window
7020 * relative to its parent window.)
7022 * Return value: not meaningful, ignore
7025 gdk_window_get_origin (GdkWindow *window,
7029 GdkWindowObject *private;
7031 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
7033 if (GDK_WINDOW_DESTROYED (window))
7042 private = (GdkWindowObject *) window;
7044 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_root_coords (window,
7053 * gdk_window_get_root_coords:
7054 * @window: a #GdkWindow
7055 * @x: X coordinate in window
7056 * @y: Y coordinate in window
7057 * @root_x: return location for X coordinate
7058 * @root_y: return location for Y coordinate
7060 * Obtains the position of a window position in root
7061 * window coordinates. This is similar to
7062 * gdk_window_get_origin() but allows you go pass
7063 * in any position in the window, not just the origin.
7066 gdk_window_get_root_coords (GdkWindow *window,
7072 GdkWindowObject *private;
7074 g_return_if_fail (GDK_IS_WINDOW (window));
7076 private = (GdkWindowObject *) window;
7078 if (GDK_WINDOW_DESTROYED (window))
7087 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_root_coords (window,
7095 * gdk_window_get_deskrelative_origin:
7096 * @window: a toplevel #GdkWindow
7097 * @x: return location for X coordinate
7098 * @y: return location for Y coordinate
7100 * This gets the origin of a #GdkWindow relative to
7101 * an Enlightenment-window-manager desktop. As long as you don't
7102 * assume that the user's desktop/workspace covers the entire
7103 * root window (i.e. you don't assume that the desktop begins
7104 * at root window coordinate 0,0) this function is not necessary.
7105 * It's deprecated for that reason.
7107 * Return value: not meaningful
7110 gdk_window_get_deskrelative_origin (GdkWindow *window,
7114 GdkWindowObject *private;
7115 gboolean return_val = FALSE;
7119 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
7121 private = (GdkWindowObject *) window;
7123 if (!GDK_WINDOW_DESTROYED (window))
7125 return_val = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_deskrelative_origin (window, &tx, &ty);
7128 *x = tx + private->abs_x;
7130 *y = ty + private->abs_y;
7137 * gdk_window_shape_combine_mask:
7138 * @window: a #GdkWindow
7140 * @x: X position of shape mask with respect to @window
7141 * @y: Y position of shape mask with respect to @window
7143 * Applies a shape mask to @window. Pixels in @window corresponding to
7144 * set bits in the @mask will be visible; pixels in @window
7145 * corresponding to unset bits in the @mask will be transparent. This
7146 * gives a non-rectangular window.
7148 * If @mask is %NULL, the shape mask will be unset, and the @x/@y
7149 * parameters are not used.
7151 * On the X11 platform, this uses an X server extension which is
7152 * widely available on most common platforms, but not available on
7153 * very old X servers, and occasionally the implementation will be
7154 * buggy. On servers without the shape extension, this function
7157 * This function works on both toplevel and child windows.
7160 gdk_window_shape_combine_mask (GdkWindow *window,
7165 GdkWindowObject *private;
7168 g_return_if_fail (GDK_IS_WINDOW (window));
7170 private = (GdkWindowObject *) window;
7173 region = _gdk_windowing_get_shape_for_mask (mask);
7177 gdk_window_shape_combine_region (window,
7182 gdk_region_destroy (region);
7186 * gdk_window_shape_combine_region:
7187 * @window: a #GdkWindow
7188 * @shape_region: region of window to be non-transparent
7189 * @offset_x: X position of @shape_region in @window coordinates
7190 * @offset_y: Y position of @shape_region in @window coordinates
7192 * Makes pixels in @window outside @shape_region be transparent,
7193 * so that the window may be nonrectangular. See also
7194 * gdk_window_shape_combine_mask() to use a bitmap as the mask.
7196 * If @shape_region is %NULL, the shape will be unset, so the whole
7197 * window will be opaque again. @offset_x and @offset_y are ignored
7198 * if @shape_region is %NULL.
7200 * On the X11 platform, this uses an X server extension which is
7201 * widely available on most common platforms, but not available on
7202 * very old X servers, and occasionally the implementation will be
7203 * buggy. On servers without the shape extension, this function
7206 * This function works on both toplevel and child windows.
7209 gdk_window_shape_combine_region (GdkWindow *window,
7210 const GdkRegion *shape_region,
7214 GdkWindowObject *private;
7215 GdkRegion *old_region, *new_region, *diff;
7217 g_return_if_fail (GDK_IS_WINDOW (window));
7219 private = (GdkWindowObject *) window;
7221 if (GDK_WINDOW_DESTROYED (window))
7224 private->shaped = (shape_region != NULL);
7227 gdk_region_destroy (private->shape);
7230 if (GDK_WINDOW_IS_MAPPED (window))
7231 old_region = gdk_region_copy (private->clip_region);
7235 private->shape = gdk_region_copy (shape_region);
7236 gdk_region_offset (private->shape, offset_x, offset_y);
7239 private->shape = NULL;
7241 recompute_visible_regions (private, TRUE, FALSE);
7245 new_region = gdk_region_copy (private->clip_region);
7247 /* New area in the window, needs invalidation */
7248 diff = gdk_region_copy (new_region);
7249 gdk_region_subtract (diff, old_region);
7251 gdk_window_invalidate_region (window, diff, TRUE);
7253 gdk_region_destroy (diff);
7255 if (private->parent != NULL &&
7256 GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
7258 /* New area in the non-root parent window, needs invalidation */
7259 diff = gdk_region_copy (old_region);
7260 gdk_region_subtract (diff, new_region);
7262 /* Adjust region to parent window coords */
7263 gdk_region_offset (diff, private->x, private->y);
7265 gdk_window_invalidate_region (GDK_WINDOW (private->parent), diff, TRUE);
7267 gdk_region_destroy (diff);
7270 gdk_region_destroy (new_region);
7271 gdk_region_destroy (old_region);
7276 do_child_shapes (GdkWindow *window,
7279 GdkWindowObject *private;
7283 private = (GdkWindowObject *) window;
7287 r.width = private->width;
7288 r.height = private->height;
7290 region = gdk_region_rectangle (&r);
7291 remove_child_area (private, NULL, FALSE, region);
7293 if (merge && private->shape)
7294 gdk_region_subtract (region, private->shape);
7296 gdk_window_shape_combine_region (window, region, 0, 0);
7300 * gdk_window_set_child_shapes:
7301 * @window: a #GdkWindow
7303 * Sets the shape mask of @window to the union of shape masks
7304 * for all children of @window, ignoring the shape mask of @window
7305 * itself. Contrast with gdk_window_merge_child_shapes() which includes
7306 * the shape mask of @window in the masks to be merged.
7309 gdk_window_set_child_shapes (GdkWindow *window)
7311 g_return_if_fail (GDK_IS_WINDOW (window));
7313 do_child_shapes (window, FALSE);
7317 * gdk_window_merge_child_shapes:
7318 * @window: a #GdkWindow
7320 * Merges the shape masks for any child windows into the
7321 * shape mask for @window. i.e. the union of all masks
7322 * for @window and its children will become the new mask
7323 * for @window. See gdk_window_shape_combine_mask().
7325 * This function is distinct from gdk_window_set_child_shapes()
7326 * because it includes @window's shape mask in the set of shapes to
7330 gdk_window_merge_child_shapes (GdkWindow *window)
7332 g_return_if_fail (GDK_IS_WINDOW (window));
7334 do_child_shapes (window, TRUE);
7338 * gdk_window_input_shape_combine_mask:
7339 * @window: a #GdkWindow
7341 * @x: X position of shape mask with respect to @window
7342 * @y: Y position of shape mask with respect to @window
7344 * Like gdk_window_shape_combine_mask(), but the shape applies
7345 * only to event handling. Mouse events which happen while
7346 * the pointer position corresponds to an unset bit in the
7347 * mask will be passed on the window below @window.
7349 * An input shape is typically used with RGBA windows.
7350 * The alpha channel of the window defines which pixels are
7351 * invisible and allows for nicely antialiased borders,
7352 * and the input shape controls where the window is
7355 * On the X11 platform, this requires version 1.1 of the
7358 * On the Win32 platform, this functionality is not present and the
7359 * function does nothing.
7364 gdk_window_input_shape_combine_mask (GdkWindow *window,
7369 GdkWindowObject *private;
7372 g_return_if_fail (GDK_IS_WINDOW (window));
7374 private = (GdkWindowObject *) window;
7377 region = _gdk_windowing_get_shape_for_mask (mask);
7381 gdk_window_input_shape_combine_region (window,
7385 gdk_region_destroy (region);
7389 * gdk_window_input_shape_combine_region:
7390 * @window: a #GdkWindow
7391 * @shape_region: region of window to be non-transparent
7392 * @offset_x: X position of @shape_region in @window coordinates
7393 * @offset_y: Y position of @shape_region in @window coordinates
7395 * Like gdk_window_shape_combine_region(), but the shape applies
7396 * only to event handling. Mouse events which happen while
7397 * the pointer position corresponds to an unset bit in the
7398 * mask will be passed on the window below @window.
7400 * An input shape is typically used with RGBA windows.
7401 * The alpha channel of the window defines which pixels are
7402 * invisible and allows for nicely antialiased borders,
7403 * and the input shape controls where the window is
7406 * On the X11 platform, this requires version 1.1 of the
7409 * On the Win32 platform, this functionality is not present and the
7410 * function does nothing.
7415 gdk_window_input_shape_combine_region (GdkWindow *window,
7416 const GdkRegion *shape_region,
7420 GdkWindowObject *private;
7422 g_return_if_fail (GDK_IS_WINDOW (window));
7424 private = (GdkWindowObject *) window;
7426 if (GDK_WINDOW_DESTROYED (window))
7429 if (private->input_shape)
7430 gdk_region_destroy (private->input_shape);
7434 private->input_shape = gdk_region_copy (shape_region);
7435 gdk_region_offset (private->input_shape, offset_x, offset_y);
7438 private->input_shape = NULL;
7440 if (gdk_window_has_impl (private))
7441 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_shape_combine_region ((GdkWindow *)private, private->input_shape, 0, 0);
7443 /* Pointer may have e.g. moved outside window due to the input mask change */
7444 _gdk_synthesize_crossing_events_for_geometry_change (window);
7448 do_child_input_shapes (GdkWindow *window,
7451 GdkWindowObject *private;
7455 private = (GdkWindowObject *) window;
7459 r.width = private->width;
7460 r.height = private->height;
7462 region = gdk_region_rectangle (&r);
7463 remove_child_area (private, NULL, TRUE, region);
7465 if (merge && private->shape)
7466 gdk_region_subtract (region, private->shape);
7467 if (merge && private->input_shape)
7468 gdk_region_subtract (region, private->input_shape);
7470 gdk_window_input_shape_combine_region (window, region, 0, 0);
7475 * gdk_window_set_child_input_shapes:
7476 * @window: a #GdkWindow
7478 * Sets the input shape mask of @window to the union of input shape masks
7479 * for all children of @window, ignoring the input shape mask of @window
7480 * itself. Contrast with gdk_window_merge_child_input_shapes() which includes
7481 * the input shape mask of @window in the masks to be merged.
7486 gdk_window_set_child_input_shapes (GdkWindow *window)
7488 g_return_if_fail (GDK_IS_WINDOW (window));
7490 do_child_input_shapes (window, FALSE);
7494 * gdk_window_merge_child_input_shapes:
7495 * @window: a #GdkWindow
7497 * Merges the input shape masks for any child windows into the
7498 * input shape mask for @window. i.e. the union of all input masks
7499 * for @window and its children will become the new input mask
7500 * for @window. See gdk_window_input_shape_combine_mask().
7502 * This function is distinct from gdk_window_set_child_input_shapes()
7503 * because it includes @window's input shape mask in the set of
7504 * shapes to be merged.
7509 gdk_window_merge_child_input_shapes (GdkWindow *window)
7511 g_return_if_fail (GDK_IS_WINDOW (window));
7513 do_child_input_shapes (window, TRUE);
7518 * gdk_window_set_static_gravities:
7519 * @window: a #GdkWindow
7520 * @use_static: %TRUE to turn on static gravity
7522 * Set the bit gravity of the given window to static, and flag it so
7523 * all children get static subwindow gravity. This is used if you are
7524 * implementing scary features that involve deep knowledge of the
7525 * windowing system. Don't worry about it unless you have to.
7527 * Return value: %TRUE if the server supports static gravity
7530 gdk_window_set_static_gravities (GdkWindow *window,
7531 gboolean use_static)
7533 GdkWindowObject *private;
7535 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
7537 private = (GdkWindowObject *) window;
7539 if (gdk_window_has_impl (private))
7540 return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_static_gravities (window, use_static);
7546 * gdk_window_set_composited:
7547 * @window: a #GdkWindow
7548 * @composited: %TRUE to set the window as composited
7550 * Sets a #GdkWindow as composited, or unsets it. Composited
7551 * windows do not automatically have their contents drawn to
7552 * the screen. Drawing is redirected to an offscreen buffer
7553 * and an expose event is emitted on the parent of the composited
7554 * window. It is the responsibility of the parent's expose handler
7555 * to manually merge the off-screen content onto the screen in
7556 * whatever way it sees fit. See <xref linkend="composited-window-example"/>
7559 * It only makes sense for child windows to be composited; see
7560 * gdk_window_set_opacity() if you need translucent toplevel
7563 * An additional effect of this call is that the area of this
7564 * window is no longer clipped from regions marked for
7565 * invalidation on its parent. Draws done on the parent
7566 * window are also no longer clipped by the child.
7568 * This call is only supported on some systems (currently,
7569 * only X11 with new enough Xcomposite and Xdamage extensions).
7570 * You must call gdk_display_supports_composite() to check if
7571 * setting a window as composited is supported before
7572 * attempting to do so.
7577 gdk_window_set_composited (GdkWindow *window,
7578 gboolean composited)
7580 GdkWindowObject *private = (GdkWindowObject *)window;
7581 GdkDisplay *display;
7583 g_return_if_fail (GDK_IS_WINDOW (window));
7585 composited = composited != FALSE;
7587 if (private->composited == composited)
7591 gdk_window_ensure_native (window);
7593 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
7595 if (!gdk_display_supports_composite (display) && composited)
7597 g_warning ("gdk_window_set_composited called but "
7598 "compositing is not supported");
7602 _gdk_windowing_window_set_composited (window, composited);
7604 recompute_visible_regions (private, TRUE, FALSE);
7606 if (GDK_WINDOW_IS_MAPPED (window))
7607 gdk_window_invalidate_in_parent (private);
7609 private->composited = composited;
7614 remove_redirect_from_children (GdkWindowObject *private,
7615 GdkWindowRedirect *redirect)
7618 GdkWindowObject *child;
7620 for (l = private->children; l != NULL; l = l->next)
7624 /* Don't redirect this child if it already has another redirect */
7625 if (child->redirect == redirect)
7627 child->redirect = NULL;
7628 remove_redirect_from_children (child, redirect);
7634 * gdk_window_remove_redirection:
7635 * @window: a #GdkWindow
7637 * Removes any active redirection started by
7638 * gdk_window_redirect_to_drawable().
7643 gdk_window_remove_redirection (GdkWindow *window)
7645 GdkWindowObject *private;
7647 g_return_if_fail (GDK_IS_WINDOW (window));
7649 private = (GdkWindowObject *) window;
7651 if (private->redirect &&
7652 private->redirect->redirected == private)
7654 remove_redirect_from_children (private, private->redirect);
7655 gdk_window_redirect_free (private->redirect);
7656 private->redirect = NULL;
7661 apply_redirect_to_children (GdkWindowObject *private,
7662 GdkWindowRedirect *redirect)
7665 GdkWindowObject *child;
7667 for (l = private->children; l != NULL; l = l->next)
7671 /* Don't redirect this child if it already has another redirect */
7672 if (!child->redirect)
7674 child->redirect = redirect;
7675 apply_redirect_to_children (child, redirect);
7681 * gdk_window_redirect_to_drawable:
7682 * @window: a #GdkWindow
7683 * @drawable: a #GdkDrawable
7684 * @src_x: x position in @window
7685 * @src_y: y position in @window
7686 * @dest_x: x position in @drawable
7687 * @dest_y: y position in @drawable
7688 * @width: width of redirection
7689 * @height: height of redirection
7691 * Redirects drawing into @window so that drawing to the
7692 * window in the rectangle specified by @src_x, @src_y,
7693 * @width and @height is also drawn into @drawable at
7696 * Only drawing between gdk_window_begin_paint_region() or
7697 * gdk_window_begin_paint_rect() and gdk_window_end_paint() is
7700 * Redirection is active until gdk_window_remove_redirection()
7706 gdk_window_redirect_to_drawable (GdkWindow *window,
7707 GdkDrawable *drawable,
7715 GdkWindowObject *private;
7717 g_return_if_fail (GDK_IS_WINDOW (window));
7718 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
7719 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
7721 private = (GdkWindowObject *) window;
7723 if (private->redirect)
7724 gdk_window_remove_redirection (window);
7726 if (width == -1 || height == -1)
7729 gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
7736 private->redirect = g_new0 (GdkWindowRedirect, 1);
7737 private->redirect->redirected = private;
7738 private->redirect->pixmap = g_object_ref (drawable);
7739 private->redirect->src_x = src_x;
7740 private->redirect->src_y = src_y;
7741 private->redirect->dest_x = dest_x;
7742 private->redirect->dest_y = dest_y;
7743 private->redirect->width = width;
7744 private->redirect->height = height;
7746 apply_redirect_to_children (private, private->redirect);
7750 window_get_size_rectangle (GdkWindow *window,
7753 GdkWindowObject *private = (GdkWindowObject *) window;
7755 rect->x = rect->y = 0;
7756 rect->width = private->width;
7757 rect->height = private->height;
7760 /* Calculates the real clipping region for a window, in window coordinates,
7761 * taking into account other windows, gc clip region and gc clip mask.
7764 _gdk_window_calculate_full_clip_region (GdkWindow *window,
7765 GdkWindow *base_window,
7766 gboolean do_children,
7767 gint *base_x_offset,
7768 gint *base_y_offset)
7770 GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
7771 GdkRectangle visible_rect;
7772 GdkRegion *real_clip_region, *tmpreg;
7773 gint x_offset, y_offset;
7774 GdkWindowObject *parentwin, *lastwin;
7781 if (!GDK_WINDOW_IS_MAPPED (window) || private->input_only)
7782 return gdk_region_new ();
7784 window_get_size_rectangle (window, &visible_rect);
7786 /* real_clip_region is in window coordinates */
7787 real_clip_region = gdk_region_rectangle (&visible_rect);
7789 x_offset = y_offset = 0;
7793 parentwin = lastwin;
7795 parentwin = lastwin->parent;
7797 /* Remove the areas of all overlapping windows above parentwin in the hiearachy */
7798 for (; parentwin != NULL &&
7799 (parentwin == private || lastwin != (GdkWindowObject*) base_window);
7800 lastwin = parentwin, parentwin = lastwin->parent)
7803 GdkRectangle real_clip_rect;
7804 gboolean is_offscreen;
7806 if (parentwin != private)
7808 x_offset += GDK_WINDOW_OBJECT (lastwin)->x;
7809 y_offset += GDK_WINDOW_OBJECT (lastwin)->y;
7812 is_offscreen = gdk_window_is_offscreen (parentwin);
7814 /* children is ordered in reverse stack order */
7815 for (cur = parentwin->children;
7816 cur && cur->data != lastwin;
7819 GdkWindow *child = cur->data;
7820 GdkWindowObject *child_private = (GdkWindowObject *)child;
7822 if (!GDK_WINDOW_IS_MAPPED (child) || child_private->input_only)
7825 /* Ignore offscreen children, as they don't draw in their parent and
7826 * don't take part in the clipping */
7827 if (gdk_window_is_offscreen (child_private))
7830 window_get_size_rectangle (child, &visible_rect);
7832 /* Convert rect to "window" coords */
7833 visible_rect.x += child_private->x - x_offset;
7834 visible_rect.y += child_private->y - y_offset;
7836 /* This shortcut is really necessary for performance when there are a lot of windows */
7837 gdk_region_get_clipbox (real_clip_region, &real_clip_rect);
7838 if (visible_rect.x >= real_clip_rect.x + real_clip_rect.width ||
7839 visible_rect.x + visible_rect.width <= real_clip_rect.x ||
7840 visible_rect.y >= real_clip_rect.y + real_clip_rect.height ||
7841 visible_rect.y + visible_rect.height <= real_clip_rect.y)
7844 tmpreg = gdk_region_rectangle (&visible_rect);
7845 gdk_region_subtract (real_clip_region, tmpreg);
7846 gdk_region_destroy (tmpreg);
7849 /* Clip to the parent */
7850 window_get_size_rectangle ((GdkWindow *)parentwin, &visible_rect);
7851 /* Convert rect to "window" coords */
7852 visible_rect.x += - x_offset;
7853 visible_rect.y += - y_offset;
7855 tmpreg = gdk_region_rectangle (&visible_rect);
7856 gdk_region_intersect (real_clip_region, tmpreg);
7857 gdk_region_destroy (tmpreg);
7861 *base_x_offset = x_offset;
7863 *base_y_offset = y_offset;
7865 return real_clip_region;
7869 _gdk_window_add_damage (GdkWindow *toplevel,
7870 GdkRegion *damaged_region)
7872 GdkDisplay *display;
7873 GdkEvent event = { 0, };
7874 event.expose.type = GDK_DAMAGE;
7875 event.expose.window = toplevel;
7876 event.expose.send_event = FALSE;
7877 event.expose.region = damaged_region;
7878 gdk_region_get_clipbox (event.expose.region, &event.expose.area);
7879 display = gdk_drawable_get_display (event.expose.window);
7880 _gdk_event_queue_append (display, gdk_event_copy (&event));
7884 gdk_window_redirect_free (GdkWindowRedirect *redirect)
7886 g_object_unref (redirect->pixmap);
7890 /* Gets the toplevel for a window as used for events,
7891 i.e. including offscreen parents */
7892 static GdkWindowObject *
7893 get_event_parent (GdkWindowObject *window)
7895 if (window->window_type == GDK_WINDOW_OFFSCREEN)
7896 return (GdkWindowObject *)gdk_offscreen_window_get_embedder ((GdkWindow *)window);
7898 return window->parent;
7901 /* Gets the toplevel for a window as used for events,
7902 i.e. including offscreen parents going up to the native
7905 get_event_toplevel (GdkWindow *w)
7907 GdkWindowObject *private = GDK_WINDOW_OBJECT (w);
7908 GdkWindowObject *parent;
7910 while ((parent = get_event_parent (private)) != NULL &&
7911 (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT))
7914 return GDK_WINDOW (private);
7918 _gdk_window_event_parent_of (GdkWindow *parent,
7929 w = (GdkWindow *)get_event_parent ((GdkWindowObject *)w);
7936 update_cursor (GdkDisplay *display)
7938 GdkWindowObject *pointer_window, *cursor_window, *parent, *toplevel;
7939 GdkPointerGrabInfo *grab;
7941 pointer_window = (GdkWindowObject *)display->pointer_info.window_under_pointer;
7943 cursor_window = pointer_window;
7944 while (cursor_window->cursor == NULL &&
7945 (parent = get_event_parent (cursor_window)) != NULL &&
7946 parent->window_type != GDK_WINDOW_ROOT)
7947 cursor_window = parent;
7949 /* We ignore the serials here and just pick the last grab
7950 we've sent, as that would shortly be used anyway. */
7951 grab = _gdk_display_get_last_pointer_grab (display);
7953 !_gdk_window_event_parent_of (grab->window, (GdkWindow *)cursor_window))
7954 cursor_window = (GdkWindowObject *)grab->window;
7956 /* Set all cursors on toplevel, otherwise its tricky to keep track of
7957 * which native window has what cursor set. */
7958 toplevel = (GdkWindowObject *)get_event_toplevel ((GdkWindow *)pointer_window);
7959 GDK_WINDOW_IMPL_GET_IFACE (toplevel->impl)->set_cursor
7960 ((GdkWindow *)toplevel, cursor_window->cursor);
7964 from_embedder (GdkWindowObject *window,
7965 double embedder_x, double embedder_y,
7966 double *offscreen_x, double *offscreen_y)
7968 g_signal_emit (window,
7969 signals[FROM_EMBEDDER], 0,
7970 embedder_x, embedder_y,
7971 offscreen_x, offscreen_y,
7976 convert_coords_to_child (GdkWindowObject *child,
7978 double *child_x, double *child_y)
7980 if (gdk_window_is_offscreen (child))
7982 from_embedder (child, x, y,
7987 *child_x = x - child->x;
7988 *child_y = y - child->y;
7993 point_in_window (GdkWindowObject *window,
7997 x >= 0 && x < window->width &&
7998 y >= 0 && y < window->height &&
7999 (window->shape == NULL ||
8000 gdk_region_point_in (window->shape,
8002 (window->input_shape == NULL ||
8003 gdk_region_point_in (window->input_shape,
8008 convert_native_coords_to_toplevel (GdkWindow *window,
8009 double child_x, double child_y,
8010 double *toplevel_x, double *toplevel_y)
8012 GdkWindowObject *private = (GdkWindowObject *)window;
8018 while (private->parent != NULL &&
8019 (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT))
8023 private = private->parent;
8029 return (GdkWindow *)private;
8033 convert_toplevel_coords_to_window (GdkWindow *window,
8039 GdkWindowObject *private;
8040 GdkWindowObject *parent;
8042 GList *children, *l;
8044 private = GDK_WINDOW_OBJECT (window);
8050 while ((parent = get_event_parent (private)) != NULL &&
8051 (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT))
8053 children = g_list_prepend (children, private);
8057 for (l = children; l != NULL; l = l->next)
8058 convert_coords_to_child (l->data, x, y, &x, &y);
8060 g_list_free (children);
8066 static GdkWindowObject *
8067 pick_embedded_child (GdkWindowObject *window,
8070 GdkWindowObject *res;
8073 g_signal_emit (window,
8074 signals[PICK_EMBEDDED_CHILD], 0,
8081 _gdk_window_find_child_at (GdkWindow *window,
8084 GdkWindowObject *private, *sub;
8085 double child_x, child_y;
8088 private = (GdkWindowObject *)window;
8090 if (point_in_window (private, x, y))
8092 /* Children is ordered in reverse stack order, i.e. first is topmost */
8093 for (l = private->children; l != NULL; l = l->next)
8097 if (!GDK_WINDOW_IS_MAPPED (sub))
8100 convert_coords_to_child (sub,
8102 &child_x, &child_y);
8103 if (point_in_window (sub, child_x, child_y))
8104 return (GdkWindow *)sub;
8107 if (private->num_offscreen_children > 0)
8109 sub = pick_embedded_child (private,
8112 return (GdkWindow *)sub;
8120 _gdk_window_find_descendant_at (GdkWindow *toplevel,
8125 GdkWindowObject *private, *sub;
8126 double child_x, child_y;
8130 private = (GdkWindowObject *)toplevel;
8132 if (point_in_window (private, x, y))
8137 /* Children is ordered in reverse stack order, i.e. first is topmost */
8138 for (l = private->children; l != NULL; l = l->next)
8142 if (!GDK_WINDOW_IS_MAPPED (sub))
8145 convert_coords_to_child (sub,
8147 &child_x, &child_y);
8148 if (point_in_window (sub, child_x, child_y))
8158 private->num_offscreen_children > 0)
8160 sub = pick_embedded_child (private,
8166 from_embedder (sub, x, y, &x, &y);
8174 /* Not in window at all */
8183 return (GdkWindow *)private;
8188 * @window: a toplevel #GdkWindow
8190 * Emits a short beep associated to @window in the appropriate
8191 * display, if supported. Otherwise, emits a short beep on
8192 * the display just as gdk_display_beep().
8197 gdk_window_beep (GdkWindow *window)
8199 GdkDisplay *display;
8200 GdkWindow *toplevel;
8202 g_return_if_fail (GDK_IS_WINDOW (window));
8204 if (GDK_WINDOW_DESTROYED (window))
8207 toplevel = get_event_toplevel (window);
8208 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
8210 if (toplevel && gdk_window_is_offscreen ((GdkWindowObject *)toplevel))
8211 _gdk_windowing_window_beep (toplevel);
8213 gdk_display_beep (display);
8216 static const guint type_masks[] = {
8217 GDK_SUBSTRUCTURE_MASK, /* GDK_DELETE = 0 */
8218 GDK_STRUCTURE_MASK, /* GDK_DESTROY = 1 */
8219 GDK_EXPOSURE_MASK, /* GDK_EXPOSE = 2 */
8220 GDK_POINTER_MOTION_MASK, /* GDK_MOTION_NOTIFY = 3 */
8221 GDK_BUTTON_PRESS_MASK, /* GDK_BUTTON_PRESS = 4 */
8222 GDK_BUTTON_PRESS_MASK, /* GDK_2BUTTON_PRESS = 5 */
8223 GDK_BUTTON_PRESS_MASK, /* GDK_3BUTTON_PRESS = 6 */
8224 GDK_BUTTON_RELEASE_MASK, /* GDK_BUTTON_RELEASE = 7 */
8225 GDK_KEY_PRESS_MASK, /* GDK_KEY_PRESS = 8 */
8226 GDK_KEY_RELEASE_MASK, /* GDK_KEY_RELEASE = 9 */
8227 GDK_ENTER_NOTIFY_MASK, /* GDK_ENTER_NOTIFY = 10 */
8228 GDK_LEAVE_NOTIFY_MASK, /* GDK_LEAVE_NOTIFY = 11 */
8229 GDK_FOCUS_CHANGE_MASK, /* GDK_FOCUS_CHANGE = 12 */
8230 GDK_STRUCTURE_MASK, /* GDK_CONFIGURE = 13 */
8231 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_MAP = 14 */
8232 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_UNMAP = 15 */
8233 GDK_PROPERTY_CHANGE_MASK, /* GDK_PROPERTY_NOTIFY = 16 */
8234 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_CLEAR = 17 */
8235 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_REQUEST = 18 */
8236 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_NOTIFY = 19 */
8237 GDK_PROXIMITY_IN_MASK, /* GDK_PROXIMITY_IN = 20 */
8238 GDK_PROXIMITY_OUT_MASK, /* GDK_PROXIMITY_OUT = 21 */
8239 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_ENTER = 22 */
8240 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_LEAVE = 23 */
8241 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_MOTION = 24 */
8242 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_STATUS = 25 */
8243 GDK_ALL_EVENTS_MASK, /* GDK_DROP_START = 26 */
8244 GDK_ALL_EVENTS_MASK, /* GDK_DROP_FINISHED = 27 */
8245 GDK_ALL_EVENTS_MASK, /* GDK_CLIENT_EVENT = 28 */
8246 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_VISIBILITY_NOTIFY = 29 */
8247 GDK_EXPOSURE_MASK, /* GDK_NO_EXPOSE = 30 */
8248 GDK_SCROLL_MASK | GDK_BUTTON_PRESS_MASK,/* GDK_SCROLL= 31 */
8249 0, /* GDK_WINDOW_STATE = 32 */
8250 0, /* GDK_SETTING = 33 */
8251 0, /* GDK_OWNER_CHANGE = 34 */
8252 0, /* GDK_GRAB_BROKEN = 35 */
8253 0, /* GDK_DAMAGE = 36 */
8255 G_STATIC_ASSERT (G_N_ELEMENTS (type_masks) == GDK_EVENT_LAST);
8257 /* send motion events if the right buttons are down */
8259 update_evmask_for_button_motion (guint evmask,
8260 GdkModifierType mask)
8262 if (evmask & GDK_BUTTON_MOTION_MASK &&
8263 mask & (GDK_BUTTON1_MASK |
8268 evmask |= GDK_POINTER_MOTION_MASK;
8270 if ((evmask & GDK_BUTTON1_MOTION_MASK && mask & GDK_BUTTON1_MASK) ||
8271 (evmask & GDK_BUTTON2_MOTION_MASK && mask & GDK_BUTTON2_MASK) ||
8272 (evmask & GDK_BUTTON3_MOTION_MASK && mask & GDK_BUTTON3_MASK))
8273 evmask |= GDK_POINTER_MOTION_MASK;
8279 is_button_type (GdkEventType type)
8281 return type == GDK_BUTTON_PRESS ||
8282 type == GDK_2BUTTON_PRESS ||
8283 type == GDK_3BUTTON_PRESS ||
8284 type == GDK_BUTTON_RELEASE ||
8289 is_motion_type (GdkEventType type)
8291 return type == GDK_MOTION_NOTIFY ||
8292 type == GDK_ENTER_NOTIFY ||
8293 type == GDK_LEAVE_NOTIFY;
8296 static GdkWindowObject *
8297 find_common_ancestor (GdkWindowObject *win1,
8298 GdkWindowObject *win2)
8300 GdkWindowObject *tmp;
8301 GList *path1 = NULL, *path2 = NULL;
8302 GList *list1, *list2;
8305 while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
8307 path1 = g_list_prepend (path1, tmp);
8308 tmp = get_event_parent (tmp);
8312 while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
8314 path2 = g_list_prepend (path2, tmp);
8315 tmp = get_event_parent (tmp);
8321 while (list1 && list2 && (list1->data == list2->data))
8323 tmp = (GdkWindowObject *)list1->data;
8324 list1 = g_list_next (list1);
8325 list2 = g_list_next (list2);
8327 g_list_free (path1);
8328 g_list_free (path2);
8334 _gdk_make_event (GdkWindow *window,
8336 GdkEvent *event_in_queue,
8337 gboolean before_event)
8339 GdkEvent *event = gdk_event_new (type);
8341 GdkModifierType the_state;
8343 the_time = gdk_event_get_time (event_in_queue);
8344 gdk_event_get_state (event_in_queue, &the_state);
8346 event->any.window = g_object_ref (window);
8347 event->any.send_event = FALSE;
8351 case GDK_MOTION_NOTIFY:
8352 event->motion.time = the_time;
8353 event->motion.axes = NULL;
8354 event->motion.state = the_state;
8357 case GDK_BUTTON_PRESS:
8358 case GDK_2BUTTON_PRESS:
8359 case GDK_3BUTTON_PRESS:
8360 case GDK_BUTTON_RELEASE:
8361 event->button.time = the_time;
8362 event->button.axes = NULL;
8363 event->button.state = the_state;
8367 event->scroll.time = the_time;
8368 event->scroll.state = the_state;
8372 case GDK_KEY_RELEASE:
8373 event->key.time = the_time;
8374 event->key.state = the_state;
8377 case GDK_ENTER_NOTIFY:
8378 case GDK_LEAVE_NOTIFY:
8379 event->crossing.time = the_time;
8380 event->crossing.state = the_state;
8383 case GDK_PROPERTY_NOTIFY:
8384 event->property.time = the_time;
8385 event->property.state = the_state;
8388 case GDK_SELECTION_CLEAR:
8389 case GDK_SELECTION_REQUEST:
8390 case GDK_SELECTION_NOTIFY:
8391 event->selection.time = the_time;
8394 case GDK_PROXIMITY_IN:
8395 case GDK_PROXIMITY_OUT:
8396 event->proximity.time = the_time;
8399 case GDK_DRAG_ENTER:
8400 case GDK_DRAG_LEAVE:
8401 case GDK_DRAG_MOTION:
8402 case GDK_DRAG_STATUS:
8403 case GDK_DROP_START:
8404 case GDK_DROP_FINISHED:
8405 event->dnd.time = the_time;
8408 case GDK_FOCUS_CHANGE:
8412 case GDK_CLIENT_EVENT:
8413 case GDK_VISIBILITY_NOTIFY:
8425 _gdk_event_queue_insert_before (gdk_drawable_get_display (window), event_in_queue, event);
8427 _gdk_event_queue_insert_after (gdk_drawable_get_display (window), event_in_queue, event);
8430 _gdk_event_queue_append (gdk_drawable_get_display (window), event);
8436 send_crossing_event (GdkDisplay *display,
8437 GdkWindowObject *toplevel,
8438 GdkWindowObject *window,
8440 GdkCrossingMode mode,
8441 GdkNotifyType notify_type,
8442 GdkWindow *subwindow,
8445 GdkModifierType mask,
8447 GdkEvent *event_in_queue,
8452 GdkPointerGrabInfo *grab;
8454 grab = _gdk_display_has_pointer_grab (display, serial);
8457 !grab->owner_events &&
8458 (GdkWindow *)window != grab->window)
8461 if (type == GDK_LEAVE_NOTIFY)
8462 event_mask = GDK_LEAVE_NOTIFY_MASK;
8464 event_mask = GDK_ENTER_NOTIFY_MASK;
8466 if (window->extension_events != 0)
8467 GDK_WINDOW_IMPL_GET_IFACE (window->impl)->input_window_crossing ((GdkWindow *)window,
8468 type == GDK_ENTER_NOTIFY);
8470 if (window->event_mask & event_mask)
8472 event = _gdk_make_event ((GdkWindow *)window, type, event_in_queue, TRUE);
8473 event->crossing.time = time_;
8474 event->crossing.subwindow = subwindow;
8476 g_object_ref (subwindow);
8477 convert_toplevel_coords_to_window ((GdkWindow *)window,
8478 toplevel_x, toplevel_y,
8479 &event->crossing.x, &event->crossing.y);
8480 event->crossing.x_root = toplevel_x + toplevel->x;
8481 event->crossing.y_root = toplevel_y + toplevel->y;
8482 event->crossing.mode = mode;
8483 event->crossing.detail = notify_type;
8484 event->crossing.focus = FALSE;
8485 event->crossing.state = mask;
8490 /* The coordinates are in the toplevel window that src/dest are in.
8491 * src and dest are always (if != NULL) in the same toplevel, as
8492 * we get a leave-notify and set the window_under_pointer to null
8493 * before crossing to another toplevel.
8496 _gdk_synthesize_crossing_events (GdkDisplay *display,
8499 GdkCrossingMode mode,
8502 GdkModifierType mask,
8504 GdkEvent *event_in_queue,
8506 gboolean non_linear)
8509 GdkWindowObject *win, *last, *next;
8513 GdkWindowObject *toplevel;
8514 GdkNotifyType notify_type;
8516 /* TODO: Don't send events to toplevel, as we get those from the windowing system */
8518 a = (GdkWindowObject *)src;
8519 b = (GdkWindowObject *)dest;
8521 return; /* No crossings generated between src and dest */
8523 c = find_common_ancestor (a, b);
8525 non_linear |= (c != a) && (c != b);
8527 if (a) /* There might not be a source (i.e. if no previous pointer_in_window) */
8529 toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)a);
8531 /* Traverse up from a to (excluding) c sending leave events */
8533 notify_type = GDK_NOTIFY_NONLINEAR;
8535 notify_type = GDK_NOTIFY_INFERIOR;
8537 notify_type = GDK_NOTIFY_ANCESTOR;
8538 send_crossing_event (display, toplevel,
8539 a, GDK_LEAVE_NOTIFY,
8543 toplevel_x, toplevel_y,
8551 notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
8553 notify_type = GDK_NOTIFY_VIRTUAL;
8556 win = get_event_parent (a);
8557 while (win != c && GDK_WINDOW_TYPE (win) != GDK_WINDOW_ROOT)
8559 send_crossing_event (display, toplevel,
8560 win, GDK_LEAVE_NOTIFY,
8564 toplevel_x, toplevel_y,
8570 win = get_event_parent (win);
8575 if (b) /* Might not be a dest, e.g. if we're moving out of the window */
8577 toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)b);
8579 /* Traverse down from c to b */
8583 win = get_event_parent (b);
8584 while (win != c && GDK_WINDOW_TYPE (win) != GDK_WINDOW_ROOT)
8586 path = g_list_prepend (path, win);
8587 win = get_event_parent (win);
8591 notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
8593 notify_type = GDK_NOTIFY_VIRTUAL;
8598 win = (GdkWindowObject *)list->data;
8599 list = g_list_next (list);
8601 next = (GdkWindowObject *)list->data;
8605 send_crossing_event (display, toplevel,
8606 win, GDK_ENTER_NOTIFY,
8610 toplevel_x, toplevel_y,
8620 notify_type = GDK_NOTIFY_NONLINEAR;
8622 notify_type = GDK_NOTIFY_ANCESTOR;
8624 notify_type = GDK_NOTIFY_INFERIOR;
8626 send_crossing_event (display, toplevel,
8627 b, GDK_ENTER_NOTIFY,
8631 toplevel_x, toplevel_y,
8638 /* Returns the window inside the event window with the pointer in it
8639 * at the specified coordinates, or NULL if its not in any child of
8640 * the toplevel. It also takes into account !owner_events grabs.
8643 get_pointer_window (GdkDisplay *display,
8644 GdkWindow *event_window,
8649 GdkWindow *pointer_window;
8650 GdkPointerGrabInfo *grab;
8652 if (event_window == display->pointer_info.toplevel_under_pointer)
8654 _gdk_window_find_descendant_at (event_window,
8655 toplevel_x, toplevel_y,
8658 pointer_window = NULL;
8660 grab = _gdk_display_has_pointer_grab (display, serial);
8662 !grab->owner_events &&
8663 pointer_window != grab->window)
8664 pointer_window = NULL;
8666 return pointer_window;
8670 _gdk_display_set_window_under_pointer (GdkDisplay *display,
8673 GdkWindowObject *private;
8675 private = (GdkWindowObject *)window;
8677 if (display->pointer_info.window_under_pointer)
8678 g_object_unref (display->pointer_info.window_under_pointer);
8679 display->pointer_info.window_under_pointer = window;
8681 g_object_ref (window);
8684 update_cursor (display);
8686 _gdk_display_enable_motion_hints (display);
8690 *--------------------------------------------------------------
8693 * Grabs the pointer to a specific window
8696 * "window" is the window which will receive the grab
8697 * "owner_events" specifies whether events will be reported as is,
8698 * or relative to "window"
8699 * "event_mask" masks only interesting events
8700 * "confine_to" limits the cursor movement to the specified window
8701 * "cursor" changes the cursor for the duration of the grab
8702 * "time" specifies the time
8707 * requires a corresponding call to gdk_pointer_ungrab
8709 *--------------------------------------------------------------
8712 gdk_pointer_grab (GdkWindow * window,
8713 gboolean owner_events,
8714 GdkEventMask event_mask,
8715 GdkWindow * confine_to,
8720 GdkDisplay *display;
8724 g_return_val_if_fail (window != NULL, 0);
8725 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
8726 g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
8728 /* We need a native window for confine to to work, ensure we have one */
8731 if (!gdk_window_ensure_native (confine_to))
8733 g_warning ("Can't confine to grabbed window, not native");
8738 /* Non-viewable client side window => fail */
8739 if (!_gdk_window_has_impl (window) &&
8740 !gdk_window_is_viewable (window))
8741 return GDK_GRAB_NOT_VIEWABLE;
8743 native = gdk_window_get_toplevel (window);
8744 while (gdk_window_is_offscreen ((GdkWindowObject *)native))
8746 native = gdk_offscreen_window_get_embedder (native);
8748 if (native == NULL ||
8749 (!_gdk_window_has_impl (native) &&
8750 !gdk_window_is_viewable (native)))
8751 return GDK_GRAB_NOT_VIEWABLE;
8753 native = gdk_window_get_toplevel (native);
8756 display = gdk_drawable_get_display (window);
8758 serial = _gdk_windowing_window_get_next_serial (display);
8760 res = _gdk_windowing_pointer_grab (window,
8768 if (res == GDK_GRAB_SUCCESS)
8769 _gdk_display_add_pointer_grab (display,
8782 * gdk_window_geometry_changed:
8783 * @window: a #GdkWindow
8788 gdk_window_geometry_changed (GdkWindow *window)
8790 _gdk_synthesize_crossing_events_for_geometry_change (window);
8794 do_synthesize_crossing_event (gpointer data)
8796 GdkDisplay *display;
8797 GdkWindow *changed_toplevel;
8798 GdkWindowObject *changed_toplevel_priv;
8799 GdkWindow *new_window_under_pointer;
8802 changed_toplevel = data;
8803 changed_toplevel_priv = (GdkWindowObject *)changed_toplevel;
8805 changed_toplevel_priv->synthesize_crossing_event_queued = FALSE;
8807 if (GDK_WINDOW_DESTROYED (changed_toplevel))
8810 display = gdk_drawable_get_display (changed_toplevel);
8811 serial = _gdk_windowing_window_get_next_serial (display);
8813 if (changed_toplevel == display->pointer_info.toplevel_under_pointer)
8815 new_window_under_pointer =
8816 get_pointer_window (display, changed_toplevel,
8817 display->pointer_info.toplevel_x,
8818 display->pointer_info.toplevel_y,
8820 if (new_window_under_pointer !=
8821 display->pointer_info.window_under_pointer)
8823 _gdk_synthesize_crossing_events (display,
8824 display->pointer_info.window_under_pointer,
8825 new_window_under_pointer,
8826 GDK_CROSSING_NORMAL,
8827 display->pointer_info.toplevel_x,
8828 display->pointer_info.toplevel_y,
8829 display->pointer_info.state,
8834 _gdk_display_set_window_under_pointer (display, new_window_under_pointer);
8842 _gdk_synthesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
8844 GdkDisplay *display;
8845 GdkWindow *toplevel;
8846 GdkWindowObject *toplevel_priv;
8848 display = gdk_drawable_get_display (changed_window);
8850 toplevel = get_event_toplevel (changed_window);
8851 toplevel_priv = (GdkWindowObject *)toplevel;
8853 if (toplevel == display->pointer_info.toplevel_under_pointer &&
8854 !toplevel_priv->synthesize_crossing_event_queued)
8856 toplevel_priv->synthesize_crossing_event_queued = TRUE;
8857 g_idle_add_full (GDK_PRIORITY_EVENTS - 1,
8858 do_synthesize_crossing_event,
8859 g_object_ref (toplevel),
8864 /* Don't use for crossing events */
8866 get_event_window (GdkDisplay *display,
8867 GdkWindow *pointer_window,
8869 GdkModifierType mask,
8874 GdkWindow *grab_window;
8876 GdkPointerGrabInfo *grab;
8878 grab = _gdk_display_has_pointer_grab (display, serial);
8880 if (grab != NULL && !grab->owner_events)
8882 evmask = grab->event_mask;
8883 evmask = update_evmask_for_button_motion (evmask, mask);
8885 grab_window = grab->window;
8887 if (evmask & type_masks[type])
8890 *evmask_out = evmask;
8897 w = (GdkWindowObject *)pointer_window;
8900 evmask = w->event_mask;
8901 evmask = update_evmask_for_button_motion (evmask, mask);
8903 if (evmask & type_masks[type])
8906 *evmask_out = evmask;
8907 return (GdkWindow *)w;
8910 w = get_event_parent (w);
8916 evmask = grab->event_mask;
8917 evmask = update_evmask_for_button_motion (evmask, mask);
8919 if (evmask & type_masks[type])
8922 *evmask_out = evmask;
8923 return grab->window;
8933 proxy_pointer_event (GdkDisplay *display,
8934 GdkEvent *source_event,
8937 GdkWindow *toplevel_window, *event_window;
8938 GdkWindow *pointer_window;
8941 gdouble toplevel_x, toplevel_y;
8943 gboolean non_linear;
8945 event_window = source_event->any.window;
8946 gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
8947 gdk_event_get_state (source_event, &state);
8948 time_ = gdk_event_get_time (source_event);
8949 toplevel_window = convert_native_coords_to_toplevel (event_window,
8950 toplevel_x, toplevel_y,
8951 &toplevel_x, &toplevel_y);
8954 if ((source_event->type == GDK_LEAVE_NOTIFY ||
8955 source_event->type == GDK_ENTER_NOTIFY) &&
8956 (source_event->crossing.detail == GDK_NOTIFY_NONLINEAR ||
8957 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))
8960 /* If we get crossing events with subwindow unexpectedly being NULL
8961 that means there is a native subwindow that gdk doesn't know about.
8962 We track these and forward them, with the correct virtual window
8964 This is important to get right, as metacity uses gdk for the frame
8965 windows, but gdk doesn't know about the client windows reparented
8967 if (((source_event->type == GDK_LEAVE_NOTIFY &&
8968 source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
8969 (source_event->type == GDK_ENTER_NOTIFY &&
8970 (source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
8971 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
8972 source_event->crossing.subwindow == NULL)
8974 /* Left for an unknown (to gdk) subwindow */
8976 /* Send leave events from window under pointer to event window
8977 that will get the subwindow == NULL window */
8978 _gdk_synthesize_crossing_events (display,
8979 display->pointer_info.window_under_pointer,
8981 source_event->crossing.mode,
8982 toplevel_x, toplevel_y,
8988 /* Send subwindow == NULL event */
8989 send_crossing_event (display,
8990 (GdkWindowObject *)toplevel_window,
8991 (GdkWindowObject *)event_window,
8993 source_event->crossing.mode,
8994 source_event->crossing.detail,
8996 toplevel_x, toplevel_y,
9001 _gdk_display_set_window_under_pointer (display, NULL);
9005 pointer_window = get_pointer_window (display, toplevel_window,
9006 toplevel_x, toplevel_y, serial);
9008 if (((source_event->type == GDK_ENTER_NOTIFY &&
9009 source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
9010 (source_event->type == GDK_LEAVE_NOTIFY &&
9011 (source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
9012 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
9013 source_event->crossing.subwindow == NULL)
9015 /* Entered from an unknown (to gdk) subwindow */
9017 /* Send subwindow == NULL event */
9018 send_crossing_event (display,
9019 (GdkWindowObject *)toplevel_window,
9020 (GdkWindowObject *)event_window,
9022 source_event->crossing.mode,
9023 source_event->crossing.detail,
9025 toplevel_x, toplevel_y,
9030 /* Send enter events from event window to pointer_window */
9031 _gdk_synthesize_crossing_events (display,
9034 source_event->crossing.mode,
9035 toplevel_x, toplevel_y,
9038 serial, non_linear);
9039 _gdk_display_set_window_under_pointer (display, pointer_window);
9043 if (display->pointer_info.window_under_pointer != pointer_window)
9045 /* Either a toplevel crossing notify that ended up inside a child window,
9046 or a motion notify that got into another child window */
9048 /* Different than last time, send crossing events */
9049 _gdk_synthesize_crossing_events (display,
9050 display->pointer_info.window_under_pointer,
9052 GDK_CROSSING_NORMAL,
9053 toplevel_x, toplevel_y,
9056 serial, non_linear);
9057 _gdk_display_set_window_under_pointer (display, pointer_window);
9059 else if (source_event->type == GDK_MOTION_NOTIFY)
9061 GdkWindow *event_win;
9065 event_win = get_event_window (display,
9075 (evmask & GDK_POINTER_MOTION_HINT_MASK))
9077 if (display->pointer_info.motion_hint_serial != 0 &&
9078 serial < display->pointer_info.motion_hint_serial)
9079 event_win = NULL; /* Ignore event */
9083 display->pointer_info.motion_hint_serial = G_MAXULONG;
9087 if (event_win && !display->ignore_core_events)
9089 event = _gdk_make_event (event_win, GDK_MOTION_NOTIFY, source_event, FALSE);
9090 event->motion.time = time_;
9091 convert_toplevel_coords_to_window (event_win,
9092 toplevel_x, toplevel_y,
9093 &event->motion.x, &event->motion.y);
9094 event->motion.x_root = source_event->motion.x_root;
9095 event->motion.y_root = source_event->motion.y_root;;
9096 event->motion.state = state;
9097 event->motion.is_hint = is_hint;
9098 event->motion.device = NULL;
9099 event->motion.device = source_event->motion.device;
9103 /* unlink all move events from queue.
9104 We handle our own, including our emulated masks. */
9108 #define GDK_ANY_BUTTON_MASK (GDK_BUTTON1_MASK | \
9109 GDK_BUTTON2_MASK | \
9110 GDK_BUTTON3_MASK | \
9111 GDK_BUTTON4_MASK | \
9115 proxy_button_event (GdkEvent *source_event,
9118 GdkWindow *toplevel_window, *event_window;
9119 GdkWindow *event_win;
9120 GdkWindow *pointer_window;
9121 GdkWindowObject *parent;
9126 gdouble toplevel_x, toplevel_y;
9127 GdkDisplay *display;
9130 type = source_event->any.type;
9131 event_window = source_event->any.window;
9132 gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
9133 gdk_event_get_state (source_event, &state);
9134 time_ = gdk_event_get_time (source_event);
9135 display = gdk_drawable_get_display (source_event->any.window);
9136 toplevel_window = convert_native_coords_to_toplevel (event_window,
9137 toplevel_x, toplevel_y,
9138 &toplevel_x, &toplevel_y);
9140 if (type == GDK_BUTTON_PRESS &&
9141 _gdk_display_has_pointer_grab (display, serial) == NULL)
9144 _gdk_window_find_descendant_at (toplevel_window,
9145 toplevel_x, toplevel_y,
9148 /* Find the event window, that gets the grab */
9149 w = (GdkWindowObject *)pointer_window;
9151 (parent = get_event_parent (w)) != NULL &&
9152 parent->window_type != GDK_WINDOW_ROOT)
9154 if (w->event_mask & GDK_BUTTON_PRESS_MASK)
9158 pointer_window = (GdkWindow *)w;
9160 _gdk_display_add_pointer_grab (display,
9164 gdk_window_get_events (pointer_window),
9168 _gdk_display_pointer_grab_update (display, serial);
9171 pointer_window = get_pointer_window (display, toplevel_window,
9172 toplevel_x, toplevel_y,
9175 event_win = get_event_window (display,
9180 if (event_win == NULL || display->ignore_core_events)
9183 event = _gdk_make_event (event_win, type, source_event, FALSE);
9187 case GDK_BUTTON_PRESS:
9188 case GDK_BUTTON_RELEASE:
9189 event->button.button = source_event->button.button;
9190 convert_toplevel_coords_to_window (event_win,
9191 toplevel_x, toplevel_y,
9192 &event->button.x, &event->button.y);
9193 event->button.x_root = source_event->button.x_root;
9194 event->button.y_root = source_event->button.y_root;
9195 event->button.state = state;
9196 event->button.device = source_event->button.device;
9198 if (type == GDK_BUTTON_PRESS)
9199 _gdk_event_button_generate (display, event);
9203 event->scroll.direction = source_event->scroll.direction;
9204 convert_toplevel_coords_to_window (event_win,
9205 toplevel_x, toplevel_y,
9206 &event->scroll.x, &event->scroll.y);
9207 event->scroll.x_root = source_event->scroll.x_root;
9208 event->scroll.y_root = source_event->scroll.y_root;
9209 event->scroll.state = state;
9210 event->scroll.device = source_event->scroll.device;
9217 return TRUE; /* Always unlink original, we want to obey the emulated event mask */
9220 #ifdef DEBUG_WINDOW_PRINTING
9222 gdk_window_print (GdkWindowObject *window,
9227 g_print ("%*s%p: [%s] %d,%d %dx%d", indent, "", window,
9228 window->user_data ? g_type_name_from_instance (window->user_data) : "no widget",
9229 window->x, window->y,
9230 window->width, window->height
9233 if (gdk_window_has_impl (window))
9235 #ifdef GDK_WINDOWING_X11
9236 g_print (" impl(0x%lx)", gdk_x11_drawable_get_xid (GDK_DRAWABLE (window)));
9240 if (window->input_only)
9241 g_print (" input-only");
9243 if (!gdk_window_is_visible ((GdkWindow *)window))
9244 g_print (" hidden");
9246 g_print (" abs[%d,%d]",
9247 window->abs_x, window->abs_y);
9249 gdk_region_get_clipbox (window->clip_region, &r);
9250 if (gdk_region_empty (window->clip_region))
9251 g_print (" clipbox[empty]");
9253 g_print (" clipbox[%d,%d %dx%d]", r.x, r.y, r.width, r.height);
9260 gdk_window_print_tree (GdkWindow *window,
9262 gboolean include_input_only)
9264 GdkWindowObject *private;
9267 private = (GdkWindowObject *)window;
9269 if (private->input_only && !include_input_only)
9272 gdk_window_print (private, indent);
9274 for (l = private->children; l != NULL; l = l->next)
9275 gdk_window_print_tree (l->data, indent + 4, include_input_only);
9278 #endif /* DEBUG_WINDOW_PRINTING */
9281 is_input_event (GdkDisplay *display,
9284 GdkDevice *core_pointer;
9286 core_pointer = gdk_display_get_core_pointer (display);
9287 if ((event->type == GDK_MOTION_NOTIFY &&
9288 event->motion.device != core_pointer) ||
9289 ((event->type == GDK_BUTTON_PRESS ||
9290 event->type == GDK_BUTTON_RELEASE) &&
9291 event->button.device != core_pointer))
9297 _gdk_windowing_got_event (GdkDisplay *display,
9302 GdkWindow *event_window;
9303 GdkWindowObject *event_private;
9305 gboolean unlink_event;
9306 guint old_state, old_button;
9307 GdkPointerGrabInfo *button_release_grab;
9308 gboolean is_toplevel;
9310 if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
9311 display->last_event_time = gdk_event_get_time (event);
9313 _gdk_display_pointer_grab_update (display,
9316 event_window = event->any.window;
9320 event_private = GDK_WINDOW_OBJECT (event_window);
9322 #ifdef DEBUG_WINDOW_PRINTING
9323 if (event->type == GDK_KEY_PRESS &&
9324 (event->key.keyval == 0xa7 ||
9325 event->key.keyval == 0xbd))
9327 gdk_window_print_tree (event_window, 0,
9328 event->key.keyval == 0xbd);
9332 if (event->type == GDK_VISIBILITY_NOTIFY)
9334 event_private->native_visibility = event->visibility.state;
9335 gdk_window_update_visibility_recursively (event_private,
9340 if (is_input_event (display, event))
9343 if (!(is_button_type (event->type) ||
9344 is_motion_type (event->type)) ||
9345 GDK_WINDOW_TYPE (event_private) == GDK_WINDOW_ROOT)
9349 event_private->parent == NULL ||
9350 GDK_WINDOW_TYPE (event_private->parent) == GDK_WINDOW_ROOT;
9352 if ((event->type == GDK_ENTER_NOTIFY ||
9353 event->type == GDK_LEAVE_NOTIFY) &&
9354 (event->crossing.mode == GDK_CROSSING_GRAB ||
9355 event->crossing.mode == GDK_CROSSING_UNGRAB) &&
9356 (_gdk_display_has_pointer_grab (display, serial) ||
9357 event->crossing.detail == GDK_NOTIFY_INFERIOR))
9359 /* We synthesize all crossing events due to grabs ourselves,
9360 * so we ignore the native ones caused by our native pointer_grab
9361 * calls. Otherwise we would proxy these crossing event and cause
9362 * multiple copies of crossing events for grabs.
9364 * We do want to handle grabs from other clients though, as for
9365 * instance alt-tab in metacity causes grabs like these and
9366 * we want to handle those. Thus the has_pointer_grab check.
9368 * Implicit grabs on child windows create some grabbing events
9369 * that are sent before the button press. This means we can't
9370 * detect these with the has_pointer_grab check (as the implicit
9371 * grab is only noticed when we get button press event), so we
9372 * detect these events by checking for INFERIOR enter or leave
9373 * events. These should never be a problem to filter out.
9376 /* We ended up in this window after some (perhaps other clients)
9377 grab, so update the toplevel_under_window state */
9379 event->type == GDK_ENTER_NOTIFY &&
9380 event->crossing.mode == GDK_CROSSING_UNGRAB)
9382 if (display->pointer_info.toplevel_under_pointer)
9383 g_object_unref (display->pointer_info.toplevel_under_pointer);
9384 display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
9387 unlink_event = TRUE;
9391 /* Track toplevel_under_pointer */
9394 if (event->type == GDK_ENTER_NOTIFY &&
9395 event->crossing.detail != GDK_NOTIFY_INFERIOR)
9397 if (display->pointer_info.toplevel_under_pointer)
9398 g_object_unref (display->pointer_info.toplevel_under_pointer);
9399 display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
9401 else if (event->type == GDK_LEAVE_NOTIFY &&
9402 event->crossing.detail != GDK_NOTIFY_INFERIOR &&
9403 display->pointer_info.toplevel_under_pointer == event_window)
9405 if (display->pointer_info.toplevel_under_pointer)
9406 g_object_unref (display->pointer_info.toplevel_under_pointer);
9407 display->pointer_info.toplevel_under_pointer = NULL;
9411 /* Store last pointer window and position/state */
9412 old_state = display->pointer_info.state;
9413 old_button = display->pointer_info.button;
9415 gdk_event_get_coords (event, &x, &y);
9416 convert_native_coords_to_toplevel (event_window, x, y, &x, &y);
9417 display->pointer_info.toplevel_x = x;
9418 display->pointer_info.toplevel_y = y;
9419 gdk_event_get_state (event, &display->pointer_info.state);
9420 if (event->type == GDK_BUTTON_PRESS ||
9421 event->type == GDK_BUTTON_RELEASE)
9422 display->pointer_info.button = event->button.button;
9424 if (display->pointer_info.state != old_state ||
9425 display->pointer_info.button != old_button)
9426 _gdk_display_enable_motion_hints (display);
9428 unlink_event = FALSE;
9429 if (is_motion_type (event->type))
9430 unlink_event = proxy_pointer_event (display,
9433 else if (is_button_type (event->type))
9434 unlink_event = proxy_button_event (event,
9437 if (event->type == GDK_BUTTON_RELEASE)
9439 button_release_grab =
9440 _gdk_display_has_pointer_grab (display, serial);
9441 if (button_release_grab &&
9442 button_release_grab->implicit &&
9443 (event->button.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
9445 button_release_grab->serial_end = serial;
9446 button_release_grab->implicit_ungrab = TRUE;
9447 _gdk_display_pointer_grab_update (display, serial);
9454 _gdk_event_queue_remove_link (display, event_link);
9455 g_list_free_1 (event_link);
9456 gdk_event_free (event);
9462 get_extension_event_window (GdkDisplay *display,
9463 GdkWindow *pointer_window,
9468 GdkWindow *grab_window;
9470 GdkPointerGrabInfo *grab;
9472 grab = _gdk_display_has_pointer_grab (display, serial);
9474 if (grab != NULL && !grab->owner_events)
9476 evmask = grab->event_mask;
9478 grab_window = grab->window;
9480 if (evmask & type_masks[type])
9486 w = (GdkWindowObject *)pointer_window;
9489 evmask = w->extension_events;
9491 if (evmask & type_masks[type])
9492 return (GdkWindow *)w;
9494 w = get_event_parent (w);
9500 evmask = grab->event_mask;
9502 if (evmask & type_masks[type])
9503 return grab->window;
9513 _gdk_window_get_input_window_for_event (GdkWindow *native_window,
9514 GdkEventType event_type,
9518 GdkDisplay *display;
9519 GdkWindow *toplevel_window;
9520 GdkWindow *pointer_window;
9521 GdkWindow *event_win;
9522 gdouble toplevel_x, toplevel_y;
9527 display = gdk_drawable_get_display (native_window);
9528 toplevel_window = convert_native_coords_to_toplevel (native_window,
9529 toplevel_x, toplevel_y,
9530 &toplevel_x, &toplevel_y);
9531 pointer_window = get_pointer_window (display, toplevel_window,
9532 toplevel_x, toplevel_y, serial);
9533 event_win = get_extension_event_window (display,
9542 #define __GDK_WINDOW_C__
9543 #include "gdkaliasdef.c"