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 GET_OFFSCREEN_PARENT,
126 PICK_OFFSCREEN_CHILD, /* only called if has_offscreen_children */
132 struct _GdkWindowPaint
138 cairo_surface_t *surface;
139 guint uses_implicit : 1;
144 GdkRegion *dest_region; /* The destination region */
145 int dx, dy; /* The amount that the source was moved to reach dest_region */
146 } GdkWindowRegionMove;
151 static GdkGC *gdk_window_create_gc (GdkDrawable *drawable,
153 GdkGCValuesMask mask);
154 static void gdk_window_draw_rectangle (GdkDrawable *drawable,
161 static void gdk_window_draw_arc (GdkDrawable *drawable,
170 static void gdk_window_draw_polygon (GdkDrawable *drawable,
175 static void gdk_window_draw_text (GdkDrawable *drawable,
182 static void gdk_window_draw_text_wc (GdkDrawable *drawable,
187 const GdkWChar *text,
189 static void gdk_window_draw_drawable (GdkDrawable *drawable,
192 GdkDrawable *original_src,
199 static void gdk_window_draw_points (GdkDrawable *drawable,
203 static void gdk_window_draw_segments (GdkDrawable *drawable,
207 static void gdk_window_draw_lines (GdkDrawable *drawable,
212 static void gdk_window_draw_glyphs (GdkDrawable *drawable,
217 PangoGlyphString *glyphs);
218 static void gdk_window_draw_glyphs_transformed (GdkDrawable *drawable,
224 PangoGlyphString *glyphs);
226 static void gdk_window_draw_image (GdkDrawable *drawable,
236 static void gdk_window_draw_pixbuf (GdkDrawable *drawable,
249 static void gdk_window_draw_trapezoids (GdkDrawable *drawable,
251 GdkTrapezoid *trapezoids,
254 static GdkImage* gdk_window_copy_to_image (GdkDrawable *drawable,
263 static cairo_surface_t *gdk_window_ref_cairo_surface (GdkDrawable *drawable);
264 static cairo_surface_t *gdk_window_create_cairo_surface (GdkDrawable *drawable,
267 static void gdk_window_set_cairo_clip (GdkDrawable *drawable,
270 static void gdk_window_real_get_size (GdkDrawable *drawable,
274 static GdkVisual* gdk_window_real_get_visual (GdkDrawable *drawable);
275 static gint gdk_window_real_get_depth (GdkDrawable *drawable);
276 static GdkScreen* gdk_window_real_get_screen (GdkDrawable *drawable);
277 static void gdk_window_real_set_colormap (GdkDrawable *drawable,
279 static GdkColormap* gdk_window_real_get_colormap (GdkDrawable *drawable);
281 static GdkDrawable* gdk_window_get_source_drawable (GdkDrawable *drawable);
282 static GdkDrawable* gdk_window_get_composite_drawable (GdkDrawable *drawable,
287 gint *composite_x_offset,
288 gint *composite_y_offset);
289 static GdkRegion* gdk_window_get_clip_region (GdkDrawable *drawable);
290 static GdkRegion* gdk_window_get_visible_region (GdkDrawable *drawable);
292 static void gdk_window_free_paint_stack (GdkWindow *window);
294 static void gdk_window_init (GdkWindowObject *window);
295 static void gdk_window_class_init (GdkWindowObjectClass *klass);
296 static void gdk_window_finalize (GObject *object);
297 static void gdk_window_clear_backing_region (GdkWindow *window,
299 static void gdk_window_redirect_free (GdkWindowRedirect *redirect);
300 static void apply_redirect_to_children (GdkWindowObject *private,
301 GdkWindowRedirect *redirect);
302 static void remove_redirect_from_children (GdkWindowObject *private,
303 GdkWindowRedirect *redirect);
305 static void recompute_visible_regions (GdkWindowObject *private,
306 gboolean recalculate_siblings,
307 gboolean recalculate_children);
308 static void gdk_window_flush_outstanding_moves (GdkWindow *window);
309 static void gdk_window_flush (GdkWindow *window);
310 static void gdk_window_flush_recursive (GdkWindowObject *window);
311 static void do_move_region_bits_on_impl (GdkWindowObject *private,
312 GdkRegion *region, /* In impl window coords */
314 static void gdk_window_invalidate_in_parent (GdkWindowObject *private);
315 static GdkWindow *gdk_window_get_offscreen_parent (GdkWindow *window);
316 static void move_native_children (GdkWindowObject *private);
317 static void update_cursor (GdkDisplay *display);
318 static gboolean is_event_parent_of (GdkWindow *parent,
321 static guint signals[LAST_SIGNAL] = { 0 };
323 static gpointer parent_class = NULL;
325 static const cairo_user_data_key_t gdk_window_cairo_key;
328 new_region_tag (void)
330 static guint32 tag = 0;
336 gdk_window_object_get_type (void)
338 static GType object_type = 0;
341 object_type = g_type_register_static_simple (GDK_TYPE_DRAWABLE,
343 sizeof (GdkWindowObjectClass),
344 (GClassInitFunc) gdk_window_class_init,
345 sizeof (GdkWindowObject),
346 (GInstanceInitFunc) gdk_window_init,
353 _gdk_paintable_get_type (void)
355 static GType paintable_type = 0;
359 const GTypeInfo paintable_info =
361 sizeof (GdkPaintableIface), /* class_size */
362 NULL, /* base_init */
363 NULL, /* base_finalize */
366 paintable_type = g_type_register_static (G_TYPE_INTERFACE,
367 g_intern_static_string ("GdkPaintable"),
370 g_type_interface_add_prerequisite (paintable_type, G_TYPE_OBJECT);
373 return paintable_type;
377 gdk_window_init (GdkWindowObject *window)
379 /* 0-initialization is good for all other fields. */
381 window->window_type = GDK_WINDOW_CHILD;
383 window->state = GDK_WINDOW_STATE_WITHDRAWN;
386 window->toplevel_window_type = -1;
388 window->effective_visibility = GDK_VISIBILITY_NOT_VIEWABLE;
389 window->visibility = GDK_VISIBILITY_FULLY_OBSCURED;
390 /* Default to unobscured since some backends don't send visibility events */
391 window->native_visibility = GDK_VISIBILITY_UNOBSCURED;
394 /* Stop and return on the first non-NULL parent */
396 accumulate_get_window (GSignalInvocationHint *ihint,
398 const GValue *handler_return,
401 g_value_copy (handler_return, return_accu);
402 /* Continue while returning NULL */
403 return g_value_get_object (handler_return) == NULL;
406 static GQuark quark_pointer_window = 0;
409 gdk_window_class_init (GdkWindowObjectClass *klass)
411 GObjectClass *object_class = G_OBJECT_CLASS (klass);
412 GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
414 parent_class = g_type_class_peek_parent (klass);
416 object_class->finalize = gdk_window_finalize;
418 drawable_class->create_gc = gdk_window_create_gc;
419 drawable_class->draw_rectangle = gdk_window_draw_rectangle;
420 drawable_class->draw_arc = gdk_window_draw_arc;
421 drawable_class->draw_polygon = gdk_window_draw_polygon;
422 drawable_class->draw_text = gdk_window_draw_text;
423 drawable_class->draw_text_wc = gdk_window_draw_text_wc;
424 drawable_class->draw_drawable = gdk_window_draw_drawable;
425 drawable_class->draw_points = gdk_window_draw_points;
426 drawable_class->draw_segments = gdk_window_draw_segments;
427 drawable_class->draw_lines = gdk_window_draw_lines;
428 drawable_class->draw_glyphs = gdk_window_draw_glyphs;
429 drawable_class->draw_glyphs_transformed = gdk_window_draw_glyphs_transformed;
430 drawable_class->draw_image = gdk_window_draw_image;
431 drawable_class->draw_pixbuf = gdk_window_draw_pixbuf;
432 drawable_class->draw_trapezoids = gdk_window_draw_trapezoids;
433 drawable_class->get_depth = gdk_window_real_get_depth;
434 drawable_class->get_screen = gdk_window_real_get_screen;
435 drawable_class->get_size = gdk_window_real_get_size;
436 drawable_class->set_colormap = gdk_window_real_set_colormap;
437 drawable_class->get_colormap = gdk_window_real_get_colormap;
438 drawable_class->get_visual = gdk_window_real_get_visual;
439 drawable_class->_copy_to_image = gdk_window_copy_to_image;
440 drawable_class->ref_cairo_surface = gdk_window_ref_cairo_surface;
441 drawable_class->create_cairo_surface = gdk_window_create_cairo_surface;
442 drawable_class->set_cairo_clip = gdk_window_set_cairo_clip;
443 drawable_class->get_clip_region = gdk_window_get_clip_region;
444 drawable_class->get_visible_region = gdk_window_get_visible_region;
445 drawable_class->get_composite_drawable = gdk_window_get_composite_drawable;
446 drawable_class->get_source_drawable = gdk_window_get_source_drawable;
448 quark_pointer_window = g_quark_from_static_string ("gtk-pointer-window");
451 signals[GET_OFFSCREEN_PARENT] =
452 g_signal_new (g_intern_static_string ("get-offscreen-parent"),
453 G_OBJECT_CLASS_TYPE (object_class),
456 accumulate_get_window, NULL,
457 gdk_marshal_OBJECT__VOID,
460 signals[PICK_OFFSCREEN_CHILD] =
461 g_signal_new (g_intern_static_string ("pick-offscreen-child"),
462 G_OBJECT_CLASS_TYPE (object_class),
465 accumulate_get_window, NULL,
466 gdk_marshal_OBJECT__DOUBLE_DOUBLE,
472 g_signal_new (g_intern_static_string ("to-parent"),
473 G_OBJECT_CLASS_TYPE (object_class),
477 gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
484 signals[FROM_PARENT] =
485 g_signal_new (g_intern_static_string ("from-parent"),
486 G_OBJECT_CLASS_TYPE (object_class),
490 gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
500 gdk_window_finalize (GObject *object)
502 GdkWindow *window = GDK_WINDOW (object);
503 GdkWindowObject *obj = (GdkWindowObject *) object;
505 if (!GDK_WINDOW_DESTROYED (window))
507 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
509 g_warning ("losing last reference to undestroyed window\n");
510 _gdk_window_destroy (window, FALSE);
513 /* We use TRUE here, to keep us from actually calling
514 * XDestroyWindow() on the window
516 _gdk_window_destroy (window, TRUE);
521 g_object_unref (obj->impl);
525 if (obj->impl_window != obj)
527 g_object_unref (obj->impl_window);
528 obj->impl_window = NULL;
532 gdk_region_destroy (obj->shape);
534 if (obj->input_shape)
535 gdk_region_destroy (obj->input_shape);
538 gdk_cursor_unref (obj->cursor);
540 G_OBJECT_CLASS (parent_class)->finalize (object);
544 gdk_window_is_offscreen (GdkWindowObject *window)
546 return GDK_WINDOW_TYPE (window) == GDK_WINDOW_OFFSCREEN;
549 static GdkWindowObject *
550 gdk_window_get_impl_window (GdkWindowObject *window)
552 return window->impl_window;
556 _gdk_window_get_impl_window (GdkWindow *window)
558 return (GdkWindow *)gdk_window_get_impl_window ((GdkWindowObject *)window);
562 gdk_window_has_impl (GdkWindowObject *window)
564 return window->impl_window == window;
568 _gdk_window_has_impl (GdkWindow *window)
570 return gdk_window_has_impl ((GdkWindowObject *)window);
574 gdk_window_has_no_impl (GdkWindowObject *window)
576 return window->impl_window != window;
580 remove_child_area (GdkWindowObject *private,
581 GdkWindowObject *until,
585 GdkWindowObject *child;
586 GdkRegion *child_region;
591 for (l = private->children; l; l = l->next)
598 if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
601 /* Ignore offscreen children, as they don't draw in their parent and
602 * don't take part in the clipping */
603 if (gdk_window_is_offscreen (child))
608 r.width = child->width;
609 r.height = child->height;
611 child_region = gdk_region_rectangle (&r);
614 gdk_region_intersect (child_region, child->shape);
615 else if (private->window_type == GDK_WINDOW_FOREIGN)
617 shape = _gdk_windowing_window_get_shape ((GdkWindow *)child);
620 gdk_region_intersect (child_region, shape);
621 gdk_region_destroy (shape);
627 if (child->input_shape)
628 gdk_region_intersect (child_region, child->input_shape);
629 else if (private->window_type == GDK_WINDOW_FOREIGN)
631 shape = _gdk_windowing_window_get_input_shape ((GdkWindow *)child);
634 gdk_region_intersect (child_region, shape);
635 gdk_region_destroy (shape);
640 gdk_region_subtract (region, child_region);
641 gdk_region_destroy (child_region);
646 static GdkVisibilityState
647 effective_visibility (GdkWindowObject *private)
649 GdkVisibilityState native;
651 if (!gdk_window_is_viewable ((GdkWindow *)private))
652 return GDK_VISIBILITY_NOT_VIEWABLE;
654 native = private->impl_window->native_visibility;
656 if (native == GDK_VISIBILITY_FULLY_OBSCURED ||
657 private->visibility == GDK_VISIBILITY_FULLY_OBSCURED)
658 return GDK_VISIBILITY_FULLY_OBSCURED;
659 else if (native == GDK_VISIBILITY_UNOBSCURED)
660 return private->visibility;
661 else /* native PARTIAL, private partial or unobscured */
662 return GDK_VISIBILITY_PARTIAL;
666 gdk_window_update_visibility (GdkWindowObject *private)
668 GdkVisibilityState new_visibility;
671 new_visibility = effective_visibility (private);
673 if (new_visibility != private->effective_visibility)
675 private->effective_visibility = new_visibility;
677 if (new_visibility != GDK_VISIBILITY_NOT_VIEWABLE &&
678 private->event_mask & GDK_VISIBILITY_NOTIFY)
680 event = _gdk_make_event ((GdkWindow *)private, GDK_VISIBILITY_NOTIFY,
682 event->visibility.state = new_visibility;
688 gdk_window_update_visibility_recursively (GdkWindowObject *private,
689 GdkWindowObject *only_for_impl)
691 GdkWindowObject *child;
694 gdk_window_update_visibility (private);
695 for (l = private->children; l != NULL; l = l->next)
698 if ((only_for_impl == NULL) ||
699 (only_for_impl == child->impl_window))
700 gdk_window_update_visibility_recursively (child, only_for_impl);
705 recompute_visible_regions_internal (GdkWindowObject *private,
706 gboolean recalculate_clip,
707 gboolean recalculate_siblings,
708 gboolean recalculate_children)
712 GdkWindowObject *child;
713 GdkRegion *new_clip, *old_clip_region_with_children;
714 gboolean clip_region_changed;
715 gboolean abs_pos_changed;
716 int old_abs_x, old_abs_y;
718 old_abs_x = private->abs_x;
719 old_abs_y = private->abs_y;
721 /* Update absolute position */
722 if (gdk_window_has_impl (private))
724 /* Native window starts here */
730 private->abs_x = private->parent->abs_x + private->x;
731 private->abs_y = private->parent->abs_y + private->y;
735 private->abs_x != old_abs_x ||
736 private->abs_y != old_abs_y;
738 /* Update clip region based on:
741 * siblings in parents above window
743 clip_region_changed = FALSE;
744 if (recalculate_clip)
746 /* Calculate visible region (sans children) in parent window coords */
749 r.width = private->width;
750 r.height = private->height;
751 new_clip = gdk_region_rectangle (&r);
753 if (private->parent != NULL && GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
755 gdk_region_intersect (new_clip, private->parent->clip_region);
757 /* Remove all overlapping children from parent */
758 remove_child_area (private->parent, private, FALSE, new_clip);
761 /* Convert from parent coords to window coords */
762 gdk_region_offset (new_clip, -private->x, -private->y);
765 gdk_region_intersect (new_clip, private->shape);
767 if (private->clip_region == NULL ||
768 !gdk_region_equal (private->clip_region, new_clip))
769 clip_region_changed = TRUE;
771 if (private->clip_region)
772 gdk_region_destroy (private->clip_region);
773 private->clip_region = new_clip;
775 old_clip_region_with_children = private->clip_region_with_children;
776 private->clip_region_with_children = gdk_region_copy (private->clip_region);
777 if (GDK_WINDOW_TYPE (private) != GDK_WINDOW_ROOT)
778 remove_child_area (private, NULL, FALSE, private->clip_region_with_children);
780 if (clip_region_changed ||
781 !gdk_region_equal (private->clip_region_with_children, old_clip_region_with_children))
782 private->clip_tag = new_region_tag ();
784 if (old_clip_region_with_children)
785 gdk_region_destroy (old_clip_region_with_children);
788 if (clip_region_changed)
790 GdkVisibilityState visibility;
791 gboolean fully_visible;
793 if (gdk_region_empty (private->clip_region))
794 visibility = GDK_VISIBILITY_FULLY_OBSCURED;
797 fully_visible = gdk_region_equal (private->clip_region,
803 r.width = private->width;
804 r.height = private->height;
805 fully_visible = gdk_region_rect_equal (private->clip_region, &r);
809 visibility = GDK_VISIBILITY_UNOBSCURED;
811 visibility = GDK_VISIBILITY_PARTIAL;
814 if (private->visibility != visibility)
816 private->visibility = visibility;
817 gdk_window_update_visibility (private);
821 /* Update all children, recursively (except for root, where children are not exact). */
822 if ((abs_pos_changed || clip_region_changed || recalculate_children) &&
823 GDK_WINDOW_TYPE (private) != GDK_WINDOW_ROOT)
825 for (l = private->children; l; l = l->next)
828 /* Only recalculate clip if the the clip region changed, otherwise
829 * there is no way the child clip region could change (its has not e.g. moved)
830 * Except if recalculate_children is set to force child updates
832 recompute_visible_regions_internal (child, recalculate_clip && (clip_region_changed || recalculate_children), FALSE, FALSE);
836 if (clip_region_changed &&
837 gdk_window_has_impl (private) &&
838 /* Not for offscreens */
839 private->window_type != GDK_WINDOW_OFFSCREEN &&
840 /* or for non-shaped toplevels */
842 (private->parent != NULL &&
843 GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)) &&
844 /* or for foreign windows */
845 GDK_WINDOW_TYPE (private) != GDK_WINDOW_FOREIGN &&
846 /* or for the root window */
847 GDK_WINDOW_TYPE (private) != GDK_WINDOW_ROOT
850 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region ((GdkWindow *)private, private->clip_region, 0, 0);
853 if (recalculate_siblings &&
854 private->parent != NULL &&
855 GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
857 /* If we moved a child window in parent or changed the stacking order, then we
858 * need to recompute the visible area of all the other children in the parent
860 for (l = private->parent->children; l; l = l->next)
864 if (child != private)
865 recompute_visible_regions_internal (child, TRUE, FALSE, FALSE);
868 /* We also need to recompute the _with_children clip for the parent */
869 recompute_visible_regions_internal (private->parent, TRUE, FALSE, FALSE);
872 if (private->cairo_surface)
876 /* It would be nice if we had some cairo support here so we
877 could set the clip rect on the cairo surface */
878 width = private->abs_x + private->width;
879 height = private->abs_y + private->height;
881 _gdk_windowing_set_cairo_surface_size (private->cairo_surface,
883 cairo_surface_set_device_offset (private->cairo_surface,
889 /* Call this when private has changed in one or more of these ways:
893 * stacking order of window changed
896 * It will recalculate abs_x/y and the clip regions
898 * Unless the window didn't change stacking order or size/pos, pass in TRUE
899 * for recalculate_siblings. (Mostly used internally for the recursion)
901 * If a child window was removed (and you can't use that child for
902 * recompute_visible_regions), pass in TRUE for recalculate_children on the parent
905 recompute_visible_regions (GdkWindowObject *private,
906 gboolean recalculate_siblings,
907 gboolean recalculate_children)
909 recompute_visible_regions_internal (private,
911 recalculate_siblings,
912 recalculate_children);
916 _gdk_window_update_size (GdkWindow *window)
918 recompute_visible_regions ((GdkWindowObject *)window, TRUE, FALSE);
921 /* Find the native window that would be just above "child"
922 * in the native stacking order if "child" was a native window
923 * (it doesn't have to be native). If there is no such native
924 * window inside this native parent then NULL is returned.
925 * If child is NULL, find lowest native window in parent.
927 static GdkWindowObject *
928 find_native_sibling_above_helper (GdkWindowObject *parent,
929 GdkWindowObject *child)
936 l = g_list_find (parent->children, child);
937 g_assert (l != NULL); /* Better be a child of its parent... */
938 l = l->prev; /* Start looking at the one above the child */
941 l = g_list_last (parent->children);
943 for (; l != NULL; l = l->prev)
947 if (gdk_window_has_impl (w))
950 g_assert (parent != w);
951 w = find_native_sibling_above_helper (w, NULL);
960 static GdkWindowObject *
961 find_native_sibling_above (GdkWindowObject *parent,
962 GdkWindowObject *child)
966 w = find_native_sibling_above_helper (parent, child);
970 if (gdk_window_has_impl (parent))
973 return find_native_sibling_above (parent->parent, parent);
977 get_native_event_mask (GdkWindowObject *private)
979 if (private->window_type != GDK_WINDOW_ROOT &&
980 private->window_type != GDK_WINDOW_FOREIGN)
983 /* We need thse for all native window so we can emulate
984 events on children: */
986 GDK_VISIBILITY_NOTIFY_MASK |
987 GDK_POINTER_MOTION_MASK |
988 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
989 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
991 /* Then do whatever the app asks to, since the app
992 * may be asking for weird things for native windows,
993 * but filter out things that override the above
994 * requests somehow. */
995 (private->event_mask &
996 ~(GDK_POINTER_MOTION_HINT_MASK |
997 GDK_BUTTON_MOTION_MASK |
998 GDK_BUTTON1_MOTION_MASK |
999 GDK_BUTTON2_MOTION_MASK |
1000 GDK_BUTTON3_MOTION_MASK));
1003 return private->event_mask;
1006 /* Puts the native window in the right order wrt the other native windows
1007 in the hierarchy, given the position it has in the client side data.
1008 This is useful if some operation changed the stacking order. */
1010 sync_native_window_stack_position (GdkWindow *window)
1012 GdkWindowObject *above;
1013 GdkWindowObject *private;
1014 GList listhead = {0};
1016 private = (GdkWindowObject *) window;
1018 above = find_native_sibling_above (private->parent, private);
1021 listhead.data = window;
1022 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
1029 * @parent: a #GdkWindow, or %NULL to create the window as a child of
1030 * the default root window for the default display.
1031 * @attributes: attributes of the new window
1032 * @attributes_mask: mask indicating which fields in @attributes are valid
1034 * Creates a new #GdkWindow using the attributes from
1035 * @attributes. See #GdkWindowAttr and #GdkWindowAttributesType for
1036 * more details. Note: to use this on displays other than the default
1037 * display, @parent must be specified.
1039 * Return value: the new #GdkWindow
1042 gdk_window_new (GdkWindow *parent,
1043 GdkWindowAttr *attributes,
1044 gint attributes_mask)
1047 GdkWindowObject *private;
1052 GdkEventMask event_mask;
1053 GdkWindow *real_parent;
1055 g_return_val_if_fail (attributes != NULL, NULL);
1059 GDK_NOTE (MULTIHEAD,
1060 g_warning ("gdk_window_new(): no parent specified reverting to parent = default root window"));
1062 screen = gdk_screen_get_default ();
1063 parent = gdk_screen_get_root_window (screen);
1066 screen = gdk_drawable_get_screen (parent);
1068 g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
1070 if (GDK_WINDOW_DESTROYED (parent))
1073 window = g_object_new (GDK_TYPE_WINDOW, NULL);
1074 private = (GdkWindowObject *) window;
1076 /* Windows with a foreign parent are treated as if they are children
1077 * of the root window, except for actual creation.
1079 real_parent = parent;
1080 if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
1081 parent = gdk_screen_get_root_window (screen);
1083 private->parent = (GdkWindowObject *)parent;
1085 private->accept_focus = TRUE;
1086 private->focus_on_map = TRUE;
1088 if (attributes_mask & GDK_WA_X)
1093 if (attributes_mask & GDK_WA_Y)
1100 private->width = (attributes->width > 1) ? (attributes->width) : (1);
1101 private->height = (attributes->height > 1) ? (attributes->height) : (1);
1103 #ifdef GDK_WINDOWING_X11
1104 /* Work around a bug where Xorg refuses to map toplevel InputOnly windows
1105 * from an untrusted client: http://bugs.freedesktop.org/show_bug.cgi?id=6988
1107 if (attributes->wclass == GDK_INPUT_ONLY &&
1108 GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT &&
1109 !G_LIKELY (GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (parent))->trusted_client))
1111 g_warning ("Coercing GDK_INPUT_ONLY toplevel window to GDK_INPUT_OUTPUT to work around bug in Xorg server");
1112 attributes->wclass = GDK_INPUT_OUTPUT;
1116 if (attributes->wclass == GDK_INPUT_ONLY)
1118 /* Backwards compatiblity - we've always ignored
1119 * attributes->window_type for input-only windows
1122 if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
1123 private->window_type = GDK_WINDOW_TEMP;
1125 private->window_type = GDK_WINDOW_CHILD;
1128 private->window_type = attributes->window_type;
1131 switch (private->window_type)
1133 case GDK_WINDOW_TOPLEVEL:
1134 case GDK_WINDOW_DIALOG:
1135 case GDK_WINDOW_TEMP:
1136 case GDK_WINDOW_OFFSCREEN:
1137 if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
1138 g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
1139 "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
1140 case GDK_WINDOW_CHILD:
1144 g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
1148 if (attributes_mask & GDK_WA_VISUAL)
1149 visual = attributes->visual;
1151 visual = gdk_screen_get_system_visual (screen);
1153 private->event_mask = attributes->event_mask;
1155 if (attributes->wclass == GDK_INPUT_OUTPUT)
1157 private->input_only = FALSE;
1158 private->depth = visual->depth;
1160 private->bg_color.pixel = 0; // TODO: BlackPixel (xdisplay, screen_x11->screen_num);
1161 private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
1163 private->bg_pixmap = NULL;
1168 private->input_only = TRUE;
1171 if (private->parent)
1172 private->parent->children = g_list_prepend (private->parent->children, window);
1174 native = FALSE; /* Default */
1175 if (GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
1176 native = TRUE; /* Always use native windows for toplevels */
1177 else if (!private->input_only &&
1178 ((attributes_mask & GDK_WA_COLORMAP &&
1179 attributes->colormap != gdk_drawable_get_colormap ((GdkDrawable *)private->parent)) ||
1180 (attributes_mask & GDK_WA_VISUAL &&
1181 attributes->visual != gdk_drawable_get_visual ((GdkDrawable *)private->parent))))
1182 native = TRUE; /* InputOutput window with different colormap or visual than parent, needs native window */
1184 if (private->window_type == GDK_WINDOW_OFFSCREEN)
1186 _gdk_offscreen_window_new (window, screen, visual, attributes, attributes_mask);
1187 private->impl_window = private;
1191 event_mask = get_native_event_mask (private);
1193 /* Create the impl */
1194 _gdk_window_impl_new (window, real_parent, screen, visual, event_mask, attributes, attributes_mask);
1195 private->impl_window = private;
1197 /* This will put the native window topmost in the native parent, which may
1198 * be wrong wrt other native windows in the non-native hierarchy, so restack */
1199 sync_native_window_stack_position (window);
1203 private->impl_window = g_object_ref (private->parent->impl_window);
1204 private->impl = g_object_ref (private->impl_window->impl);
1207 recompute_visible_regions (private, TRUE, FALSE);
1209 if (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
1211 /* Inherit redirection from parent */
1212 private->redirect = private->parent->redirect;
1215 gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
1216 (attributes->cursor) :
1223 is_parent_of (GdkWindow *parent,
1234 w = gdk_window_get_parent (w);
1241 change_impl (GdkWindowObject *private,
1242 GdkWindowObject *impl_window,
1246 GdkWindowObject *child;
1247 GdkDrawable *old_impl;
1248 GdkWindowObject *old_impl_window;
1250 old_impl = private->impl;
1251 old_impl_window = private->impl_window;
1252 if (private != impl_window)
1253 private->impl_window = g_object_ref (impl_window);
1255 private->impl_window = private;
1256 private->impl = g_object_ref (new);
1257 if (old_impl_window != private)
1258 g_object_unref (old_impl_window);
1259 g_object_unref (old_impl);
1261 for (l = private->children; l != NULL; l = l->next)
1265 if (child->impl == old_impl)
1266 change_impl (child, impl_window, new);
1271 reparent_to_impl (GdkWindowObject *private)
1274 GdkWindowObject *child;
1277 /* Enumerate in reverse order so we get the right order for the native
1278 windows (first in childrens list is topmost, and reparent places on top) */
1279 for (l = g_list_last (private->children); l != NULL; l = l->prev)
1283 if (child->impl == private->impl)
1284 reparent_to_impl (child);
1287 show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent ((GdkWindow *)child,
1288 (GdkWindow *)private,
1289 child->x, child->y);
1291 gdk_window_show_unraised ((GdkWindow *)child);
1298 * gdk_window_reparent:
1299 * @window: a #GdkWindow
1300 * @new_parent: new parent to move @window into
1301 * @x: X location inside the new parent
1302 * @y: Y location inside the new parent
1304 * Reparents @window into the given @new_parent. The window being
1305 * reparented will be unmapped as a side effect.
1309 gdk_window_reparent (GdkWindow *window,
1310 GdkWindow *new_parent,
1314 GdkWindowObject *private;
1315 GdkWindowObject *new_parent_private;
1316 GdkWindowObject *old_parent;
1317 gboolean show, was_toplevel, was_mapped;
1318 gboolean do_reparent_to_impl;
1320 g_return_if_fail (GDK_IS_WINDOW (window));
1321 g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
1322 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
1324 if (GDK_WINDOW_DESTROYED (window) ||
1325 (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
1329 new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
1331 private = (GdkWindowObject *) window;
1332 new_parent_private = (GdkWindowObject *)new_parent;
1334 /* No input-output children of input-only windows */
1335 if (new_parent_private->input_only && !private->input_only)
1338 /* Don't create loops in hierarchy */
1339 if (is_parent_of (window, new_parent))
1342 if (private->cairo_surface)
1344 /* This might be wrong in the new parent, e.g. for non-native surfaces.
1345 To make sure we're ok, just wipe it. */
1346 cairo_surface_finish (private->cairo_surface);
1347 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
1351 old_parent = private->parent;
1353 /* Break up redirection if inherited */
1354 if (private->redirect && private->redirect->redirected != private)
1356 remove_redirect_from_children (private, private->redirect);
1357 private->redirect = NULL;
1360 was_toplevel = private->parent == NULL;
1361 was_mapped = GDK_WINDOW_IS_MAPPED (window);
1364 /* Reparenting to toplevel. Ensure we have a native window so this can work */
1365 if (new_parent_private->window_type == GDK_WINDOW_ROOT ||
1366 new_parent_private->window_type == GDK_WINDOW_FOREIGN)
1367 gdk_window_ensure_native (window);
1369 do_reparent_to_impl = FALSE;
1370 if (gdk_window_has_impl (private))
1373 show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent (window, new_parent, x, y);
1377 /* This shouldn't happen, as we created a native in this case, check anyway to see if that ever fails */
1378 g_assert (new_parent_private->window_type != GDK_WINDOW_ROOT &&
1379 new_parent_private->window_type != GDK_WINDOW_FOREIGN);
1382 gdk_window_hide (window);
1384 do_reparent_to_impl = TRUE;
1385 change_impl (private,
1386 new_parent_private->impl_window,
1387 new_parent_private->impl);
1390 /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
1393 if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1395 new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
1396 new_parent_private = (GdkWindowObject *)new_parent;
1400 old_parent->children = g_list_remove (old_parent->children, window);
1402 private->parent = new_parent_private;
1406 new_parent_private->children = g_list_prepend (new_parent_private->children, window);
1408 /* Switch the window type as appropriate */
1410 switch (GDK_WINDOW_TYPE (new_parent))
1412 case GDK_WINDOW_ROOT:
1413 case GDK_WINDOW_FOREIGN:
1414 if (private->toplevel_window_type != -1)
1415 GDK_WINDOW_TYPE (window) = private->toplevel_window_type;
1416 else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1417 GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
1419 case GDK_WINDOW_OFFSCREEN:
1420 case GDK_WINDOW_TOPLEVEL:
1421 case GDK_WINDOW_CHILD:
1422 case GDK_WINDOW_DIALOG:
1423 case GDK_WINDOW_TEMP:
1424 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
1425 GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
1427 /* Save the original window type so we can restore it if the
1428 * window is reparented back to be a toplevel
1430 private->toplevel_window_type = GDK_WINDOW_TYPE (window);
1431 GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
1435 /* We might have changed window type for a native windows, so we
1436 need to change the event mask too. */
1437 if (gdk_window_has_impl (private))
1438 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_events (window, get_native_event_mask (private));
1440 /* Inherit parent redirect if we don't have our own */
1441 if (private->parent && private->redirect == NULL)
1443 private->redirect = private->parent->redirect;
1444 apply_redirect_to_children (private, private->redirect);
1447 recompute_visible_regions (private, TRUE, FALSE);
1448 if (old_parent && GDK_WINDOW_TYPE (old_parent) != GDK_WINDOW_ROOT)
1449 recompute_visible_regions (old_parent, FALSE, TRUE);
1451 if (do_reparent_to_impl)
1452 reparent_to_impl (private);
1455 /* The reparent will have put the native window topmost in the native parent,
1456 * which may be wrong wrt other native windows in the non-native hierarchy,
1458 sync_native_window_stack_position (window);
1462 gdk_window_show_unraised (window);
1464 _gdk_synthesize_crossing_events_for_geometry_change (window);
1468 * gdk_window_ensure_native:
1469 * @window: a #GdkWindow
1471 * Tries to ensure that there is a window-system native window for this
1472 * GdkWindow. This may fail in some situations, returning %FALSE.
1474 * Offscreen window and children of them can never have native windows.
1476 * Some backends may not support native child windows.
1478 * Returns: %TRUE if the window has a native window, %FALSE otherwise
1483 gdk_window_ensure_native (GdkWindow *window)
1485 GdkWindowObject *private;
1486 GdkWindowObject *impl_window;
1487 GdkDrawable *new_impl, *old_impl;
1490 GdkWindowAttr attributes;
1491 GdkWindowObject *above;
1494 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
1496 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT ||
1497 GDK_WINDOW_DESTROYED (window))
1500 private = (GdkWindowObject *) window;
1502 impl_window = gdk_window_get_impl_window (private);
1504 if (impl_window->window_type == GDK_WINDOW_OFFSCREEN)
1505 return FALSE; /* native in offscreens not supported */
1507 if (impl_window == private)
1508 /* Already has an impl, and its not offscreen . */
1511 /* Need to create a native window */
1513 screen = gdk_drawable_get_screen (window);
1514 visual = gdk_drawable_get_visual (window);
1516 attributes.colormap = gdk_drawable_get_colormap (window);
1518 old_impl = private->impl;
1519 _gdk_window_impl_new (window, (GdkWindow *)private->parent, screen, visual,
1520 get_native_event_mask (private), &attributes, GDK_WA_COLORMAP);
1521 new_impl = private->impl;
1523 private->impl = old_impl;
1524 change_impl (private, private, new_impl);
1526 /* Native window creation will put the native window topmost in the
1527 * native parent, which may be wrong wrt other native windows in the
1528 * non-native hierarchy, so restack */
1529 above = find_native_sibling_above (private->parent, private);
1532 listhead.data = window;
1533 listhead.prev = NULL;
1534 listhead.next = NULL;
1535 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
1539 recompute_visible_regions (private, FALSE, FALSE);
1541 /* The shape may not have been set, as the clip region doesn't actually
1542 change, so do it here manually */
1543 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region ((GdkWindow *)private, private->clip_region, 0, 0);
1545 reparent_to_impl (private);
1547 if (!private->input_only)
1549 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, &private->bg_color);
1550 if (private->bg_pixmap != NULL)
1551 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, private->bg_pixmap);
1554 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_shape_combine_region ((GdkWindow *)private, private->input_shape, 0, 0);
1556 if (gdk_window_is_viewable (window))
1557 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show (window, FALSE);
1563 window_remove_filters (GdkWindow *window)
1565 GdkWindowObject *obj = (GdkWindowObject*) window;
1571 for (tmp_list = obj->filters; tmp_list; tmp_list = tmp_list->next)
1572 g_free (tmp_list->data);
1574 g_list_free (obj->filters);
1575 obj->filters = NULL;
1580 * _gdk_window_destroy_hierarchy:
1581 * @window: a #GdkWindow
1582 * @recursing: If TRUE, then this is being called because a parent
1584 * @recursing_native: If TRUE, then this is being called because a native parent
1585 * was destroyed. This generally means that the call to the
1586 * windowing system to destroy the window can be omitted, since
1587 * it will be destroyed as a result of the parent being destroyed.
1588 * Unless @foreign_destroy.
1589 * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
1590 * external agency. The window has already been destroyed and no
1591 * windowing system calls should be made. (This may never happen
1592 * for some windowing systems.)
1594 * Internal function to destroy a window. Like gdk_window_destroy(),
1595 * but does not drop the reference count created by gdk_window_new().
1598 _gdk_window_destroy_hierarchy (GdkWindow *window,
1600 gboolean recursing_native,
1601 gboolean foreign_destroy)
1603 GdkWindowObject *private;
1604 GdkWindowObject *temp_private;
1605 GdkWindow *temp_window;
1607 GdkDisplay *display;
1611 g_return_if_fail (GDK_IS_WINDOW (window));
1613 private = (GdkWindowObject*) window;
1615 if (GDK_WINDOW_DESTROYED (window))
1618 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
1619 screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
1620 temp_window = g_object_get_qdata (G_OBJECT (screen), quark_pointer_window);
1621 if (temp_window == window)
1622 g_object_set_qdata (G_OBJECT (screen), quark_pointer_window, NULL);
1625 switch (GDK_WINDOW_TYPE (window))
1627 case GDK_WINDOW_ROOT:
1628 if (!screen->closed)
1630 g_error ("attempted to destroy root window");
1633 /* else fall thru */
1634 case GDK_WINDOW_TOPLEVEL:
1635 case GDK_WINDOW_CHILD:
1636 case GDK_WINDOW_DIALOG:
1637 case GDK_WINDOW_TEMP:
1638 case GDK_WINDOW_FOREIGN:
1639 case GDK_WINDOW_OFFSCREEN:
1640 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN && !foreign_destroy)
1642 /* Logically, it probably makes more sense to send
1643 * a "destroy yourself" message to the foreign window
1644 * whether or not it's in our hierarchy; but for historical
1645 * reasons, we only send "destroy yourself" messages to
1646 * foreign windows in our hierarchy.
1648 if (private->parent)
1649 _gdk_windowing_window_destroy_foreign (window);
1651 /* Also for historical reasons, we remove any filters
1652 * on a foreign window when it or a parent is destroyed;
1653 * this likely causes problems if two separate portions
1654 * of code are maintaining filter lists on a foreign window.
1656 window_remove_filters (window);
1660 if (private->parent)
1662 GdkWindowObject *parent_private = (GdkWindowObject *)private->parent;
1664 if (parent_private->children)
1665 parent_private->children = g_list_remove (parent_private->children, window);
1668 GDK_WINDOW_IS_MAPPED (window))
1670 recompute_visible_regions (private, TRUE, FALSE);
1671 gdk_window_invalidate_in_parent (private);
1675 gdk_window_free_paint_stack (window);
1677 if (private->bg_pixmap &&
1678 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
1679 private->bg_pixmap != GDK_NO_BG)
1681 g_object_unref (private->bg_pixmap);
1682 private->bg_pixmap = NULL;
1685 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN)
1686 g_assert (private->children == NULL);
1689 children = tmp = private->children;
1690 private->children = NULL;
1694 temp_window = tmp->data;
1697 temp_private = (GdkWindowObject*) temp_window;
1699 _gdk_window_destroy_hierarchy (temp_window,
1701 recursing_native || gdk_window_has_impl (private),
1705 g_list_free (children);
1708 _gdk_window_clear_update_area (window);
1710 if (private->cairo_surface)
1712 cairo_surface_finish (private->cairo_surface);
1713 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
1718 if (private->extension_events)
1719 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_window_destroy (window);
1721 if (gdk_window_has_impl (private))
1723 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->destroy (window, recursing_native, foreign_destroy);
1727 /* hide to make sure we repaint and break grabs */
1728 gdk_window_hide (window);
1731 private->state |= GDK_WINDOW_STATE_WITHDRAWN;
1732 private->parent = NULL;
1733 private->destroyed = TRUE;
1735 window_remove_filters (window);
1737 gdk_drawable_set_colormap (GDK_DRAWABLE (window), NULL);
1739 /* If we own the redirect, free it */
1740 if (private->redirect && private->redirect->redirected == private)
1741 gdk_window_redirect_free (private->redirect);
1743 private->redirect = NULL;
1745 if (display->pointer_info.toplevel_under_pointer == window)
1747 g_object_unref (display->pointer_info.toplevel_under_pointer);
1748 display->pointer_info.toplevel_under_pointer = NULL;
1756 * _gdk_window_destroy:
1757 * @window: a #GdkWindow
1758 * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
1759 * external agency. The window has already been destroyed and no
1760 * windowing system calls should be made. (This may never happen
1761 * for some windowing systems.)
1763 * Internal function to destroy a window. Like gdk_window_destroy(),
1764 * but does not drop the reference count created by gdk_window_new().
1767 _gdk_window_destroy (GdkWindow *window,
1768 gboolean foreign_destroy)
1770 _gdk_window_destroy_hierarchy (window, FALSE, FALSE, foreign_destroy);
1774 * gdk_window_destroy:
1775 * @window: a #GdkWindow
1777 * Destroys the window system resources associated with @window and decrements @window's
1778 * reference count. The window system resources for all children of @window are also
1779 * destroyed, but the children's reference counts are not decremented.
1781 * Note that a window will not be destroyed automatically when its reference count
1782 * reaches zero. You must call this function yourself before that happens.
1786 gdk_window_destroy (GdkWindow *window)
1788 _gdk_window_destroy_hierarchy (window, FALSE, FALSE, FALSE);
1789 g_object_unref (window);
1793 * gdk_window_set_user_data:
1794 * @window: a #GdkWindow
1795 * @user_data: user data
1797 * For most purposes this function is deprecated in favor of
1798 * g_object_set_data(). However, for historical reasons GTK+ stores
1799 * the #GtkWidget that owns a #GdkWindow as user data on the
1800 * #GdkWindow. So, custom widget implementations should use
1801 * this function for that. If GTK+ receives an event for a #GdkWindow,
1802 * and the user data for the window is non-%NULL, GTK+ will assume the
1803 * user data is a #GtkWidget, and forward the event to that widget.
1807 gdk_window_set_user_data (GdkWindow *window,
1810 g_return_if_fail (GDK_IS_WINDOW (window));
1812 ((GdkWindowObject*)window)->user_data = user_data;
1816 * gdk_window_get_user_data:
1817 * @window: a #GdkWindow
1818 * @data: return location for user data
1820 * Retrieves the user data for @window, which is normally the widget
1821 * that @window belongs to. See gdk_window_set_user_data().
1825 gdk_window_get_user_data (GdkWindow *window,
1828 g_return_if_fail (GDK_IS_WINDOW (window));
1830 *data = ((GdkWindowObject*)window)->user_data;
1834 * gdk_window_get_window_type:
1835 * @window: a #GdkWindow
1837 * Gets the type of the window. See #GdkWindowType.
1839 * Return value: type of window
1842 gdk_window_get_window_type (GdkWindow *window)
1844 g_return_val_if_fail (GDK_IS_WINDOW (window), (GdkWindowType) -1);
1846 return GDK_WINDOW_TYPE (window);
1850 * gdk_window_get_position:
1851 * @window: a #GdkWindow
1852 * @x: X coordinate of window
1853 * @y: Y coordinate of window
1855 * Obtains the position of the window as reported in the
1856 * most-recently-processed #GdkEventConfigure. Contrast with
1857 * gdk_window_get_geometry() which queries the X server for the
1858 * current window position, regardless of which events have been
1859 * received or processed.
1861 * The position coordinates are relative to the window's parent window.
1865 gdk_window_get_position (GdkWindow *window,
1869 GdkWindowObject *obj;
1871 g_return_if_fail (GDK_IS_WINDOW (window));
1873 obj = (GdkWindowObject*) window;
1882 * gdk_window_get_parent:
1883 * @window: a #GdkWindow
1885 * Obtains the parent of @window, as known to GDK. Does not query the
1886 * X server; thus this returns the parent as passed to gdk_window_new(),
1887 * not the actual parent. This should never matter unless you're using
1888 * Xlib calls mixed with GDK calls on the X11 platform. It may also
1889 * matter for toplevel windows, because the window manager may choose
1892 * Return value: parent of @window
1895 gdk_window_get_parent (GdkWindow *window)
1897 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1899 return (GdkWindow*) ((GdkWindowObject*) window)->parent;
1903 * gdk_window_get_toplevel:
1904 * @window: a #GdkWindow
1906 * Gets the toplevel window that's an ancestor of @window.
1908 * Any window type but %GDK_WINDOW_CHILD is considered a
1909 * toplevel window, as is a %GDK_WINDOW_CHILD window that
1910 * has a root window as parent.
1912 * Return value: the toplevel window containing @window
1915 gdk_window_get_toplevel (GdkWindow *window)
1917 GdkWindowObject *obj;
1919 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1921 obj = (GdkWindowObject *)window;
1923 while (GDK_WINDOW_TYPE (obj) == GDK_WINDOW_CHILD)
1925 if (obj->parent == NULL ||
1926 GDK_WINDOW_TYPE (obj->parent) == GDK_WINDOW_ROOT)
1931 return GDK_WINDOW (obj);
1935 * gdk_window_get_children:
1936 * @window: a #GdkWindow
1938 * Gets the list of children of @window known to GDK.
1939 * This function only returns children created via GDK,
1940 * so for example it's useless when used with the root window;
1941 * it only returns windows an application created itself.
1943 * The returned list must be freed, but the elements in the
1946 * Return value: list of child windows inside @window
1949 gdk_window_get_children (GdkWindow *window)
1951 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1953 if (GDK_WINDOW_DESTROYED (window))
1956 return g_list_copy (GDK_WINDOW_OBJECT (window)->children);
1960 * gdk_window_peek_children:
1961 * @window: a #GdkWindow
1963 * Like gdk_window_get_children(), but does not copy the list of
1964 * children, so the list does not need to be freed.
1966 * Return value: a reference to the list of child windows in @window
1969 gdk_window_peek_children (GdkWindow *window)
1971 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1973 if (GDK_WINDOW_DESTROYED (window))
1976 return GDK_WINDOW_OBJECT (window)->children;
1980 * gdk_window_add_filter:
1981 * @window: a #GdkWindow
1982 * @function: filter callback
1983 * @data: data to pass to filter callback
1985 * Adds an event filter to @window, allowing you to intercept events
1986 * before they reach GDK. This is a low-level operation and makes it
1987 * easy to break GDK and/or GTK+, so you have to know what you're
1988 * doing. Pass %NULL for @window to get all events for all windows,
1989 * instead of events for a specific window.
1991 * See gdk_display_add_client_message_filter() if you are interested
1992 * in X ClientMessage events.
1995 gdk_window_add_filter (GdkWindow *window,
1996 GdkFilterFunc function,
1999 GdkWindowObject *private;
2001 GdkEventFilter *filter;
2003 g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
2005 private = (GdkWindowObject*) window;
2006 if (private && GDK_WINDOW_DESTROYED (window))
2009 /* Filters are for the native events on the native window, so
2010 ensure there is a native window. */
2012 gdk_window_ensure_native (window);
2015 tmp_list = private->filters;
2017 tmp_list = _gdk_default_filters;
2021 filter = (GdkEventFilter *)tmp_list->data;
2022 if ((filter->function == function) && (filter->data == data))
2024 tmp_list = tmp_list->next;
2027 filter = g_new (GdkEventFilter, 1);
2028 filter->function = function;
2029 filter->data = data;
2032 private->filters = g_list_append (private->filters, filter);
2034 _gdk_default_filters = g_list_append (_gdk_default_filters, filter);
2038 * gdk_window_remove_filter:
2039 * @window: a #GdkWindow
2040 * @function: previously-added filter function
2041 * @data: user data for previously-added filter function
2043 * Remove a filter previously added with gdk_window_add_filter().
2047 gdk_window_remove_filter (GdkWindow *window,
2048 GdkFilterFunc function,
2051 GdkWindowObject *private;
2052 GList *tmp_list, *node;
2053 GdkEventFilter *filter;
2055 g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
2057 private = (GdkWindowObject*) window;
2060 tmp_list = private->filters;
2062 tmp_list = _gdk_default_filters;
2066 filter = (GdkEventFilter *)tmp_list->data;
2068 tmp_list = tmp_list->next;
2070 if ((filter->function == function) && (filter->data == data))
2073 private->filters = g_list_remove_link (private->filters, node);
2075 _gdk_default_filters = g_list_remove_link (_gdk_default_filters, node);
2076 g_list_free_1 (node);
2085 * gdk_screen_get_toplevel_windows:
2086 * @screen: The #GdkScreen where the toplevels are located.
2088 * Obtains a list of all toplevel windows known to GDK on the screen @screen.
2089 * A toplevel window is a child of the root window (see
2090 * gdk_get_default_root_window()).
2092 * The returned list should be freed with g_list_free(), but
2093 * its elements need not be freed.
2095 * Return value: list of toplevel windows, free with g_list_free()
2100 gdk_screen_get_toplevel_windows (GdkScreen *screen)
2102 GdkWindow * root_window;
2103 GList *new_list = NULL;
2106 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
2108 root_window = gdk_screen_get_root_window (screen);
2110 tmp_list = ((GdkWindowObject *)root_window)->children;
2113 if (GDK_WINDOW_TYPE (tmp_list->data) != GDK_WINDOW_FOREIGN)
2114 new_list = g_list_prepend (new_list, tmp_list->data);
2115 tmp_list = tmp_list->next;
2122 * gdk_window_get_toplevels:
2124 * Obtains a list of all toplevel windows known to GDK on the default
2125 * screen (see gdk_screen_get_toplevel_windows()).
2126 * A toplevel window is a child of the root window (see
2127 * gdk_get_default_root_window()).
2129 * The returned list should be freed with g_list_free(), but
2130 * its elements need not be freed.
2132 * Return value: list of toplevel windows, free with g_list_free()
2134 * Deprecated: 2.16: Use gdk_screen_get_toplevel_windows() instead.
2137 gdk_window_get_toplevels (void)
2139 return gdk_screen_get_toplevel_windows (gdk_screen_get_default ());
2143 * gdk_window_is_visible:
2144 * @window: a #GdkWindow
2146 * Checks whether the window has been mapped (with gdk_window_show() or
2147 * gdk_window_show_unraised()).
2149 * Return value: %TRUE if the window is mapped
2152 gdk_window_is_visible (GdkWindow *window)
2154 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2156 return GDK_WINDOW_IS_MAPPED (window);
2160 * gdk_window_is_viewable:
2161 * @window: a #GdkWindow
2163 * Check if the window and all ancestors of the window are
2164 * mapped. (This is not necessarily "viewable" in the X sense, since
2165 * we only check as far as we have GDK window parents, not to the root
2168 * Return value: %TRUE if the window is viewable
2171 gdk_window_is_viewable (GdkWindow *window)
2173 GdkWindowObject *private = (GdkWindowObject *)window;
2175 GdkWindow *root_window;
2177 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2179 screen = gdk_drawable_get_screen (window);
2180 root_window = gdk_screen_get_root_window (screen);
2183 (private != (GdkWindowObject *)root_window) &&
2184 (GDK_WINDOW_TYPE (private) != GDK_WINDOW_FOREIGN))
2186 if (GDK_WINDOW_DESTROYED (private) || !GDK_WINDOW_IS_MAPPED (private))
2189 private = (GdkWindowObject *)private->parent;
2196 * gdk_window_get_state:
2197 * @window: a #GdkWindow
2199 * Gets the bitwise OR of the currently active window state flags,
2200 * from the #GdkWindowState enumeration.
2202 * Return value: window state bitfield
2205 gdk_window_get_state (GdkWindow *window)
2207 GdkWindowObject *private = (GdkWindowObject *)window;
2209 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2211 return private->state;
2215 /* This creates an empty "implicit" paint region for the impl window.
2216 * By itself this does nothing, but real paints to this window
2217 * or children of it can use this pixmap as backing to avoid allocating
2218 * multiple pixmaps for subwindow rendering. When doing so they
2219 * add to the region of the implicit paint region, which will be
2220 * pushed to the window when the implicit paint region is ended.
2221 * Such paints should not copy anything to the window on paint end, but
2222 * should rely on the implicit paint end.
2223 * The implicit paint will be automatically ended if someone draws
2224 * directly to the window or a child window.
2227 gdk_window_begin_implicit_paint (GdkWindow *window, GdkRectangle *rect)
2229 GdkWindowObject *private = (GdkWindowObject *)window;
2230 GdkWindowPaint *paint;
2232 g_assert (gdk_window_has_impl (private));
2234 if (GDK_IS_PAINTABLE (private->impl))
2235 return FALSE; /* Implementation does double buffering */
2237 if (private->paint_stack != NULL ||
2238 private->implicit_paint != NULL)
2239 return FALSE; /* Don't stack implicit paints */
2241 paint = g_new (GdkWindowPaint, 1);
2242 paint->region = gdk_region_new (); /* Empty */
2243 paint->x_offset = rect->x;
2244 paint->y_offset = rect->y;
2245 paint->uses_implicit = FALSE;
2246 paint->surface = NULL;
2248 gdk_pixmap_new (window,
2249 MAX (rect->width, 1), MAX (rect->height, 1), -1);
2251 private->implicit_paint = paint;
2256 /* Ensure that all content related to this (sub)window is pushed to the
2257 native region. If there is an active paint then that area is not
2258 pushed, in order to not show partially finished double buffers. */
2260 gdk_window_flush_implicit_paint (GdkWindow *window)
2262 GdkWindowObject *private = (GdkWindowObject *)window;
2263 GdkWindowObject *impl_window;
2264 GdkWindowPaint *paint;
2269 impl_window = gdk_window_get_impl_window (private);
2270 if (impl_window->implicit_paint == NULL)
2273 paint = impl_window->implicit_paint;
2274 region = gdk_region_copy (private->clip_region_with_children);
2276 /* Don't flush active double buffers, as that may show partially done
2278 for (list = private->paint_stack; list != NULL; list = list->next)
2280 GdkWindowPaint *tmp_paint = list->data;
2282 gdk_region_subtract (region, tmp_paint->region);
2285 gdk_region_offset (region, private->abs_x, private->abs_y);
2286 gdk_region_intersect (region, paint->region);
2288 if (!gdk_region_empty (region))
2290 /* Some regions are valid, push these to window now */
2291 tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
2292 _gdk_gc_set_clip_region_internal (tmp_gc, region, TRUE);
2293 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2294 0, 0, paint->x_offset, paint->y_offset, -1, -1);
2295 /* Reset clip region of the cached GdkGC */
2296 gdk_gc_set_clip_region (tmp_gc, NULL);
2298 /* Remove flushed region from the implicit paint */
2299 gdk_region_subtract (paint->region, region);
2302 gdk_region_destroy (region);
2305 /* Ends an implicit paint, paired with gdk_window_begin_implicit_paint returning TRUE */
2307 gdk_window_end_implicit_paint (GdkWindow *window)
2309 GdkWindowObject *private = (GdkWindowObject *)window;
2310 GdkWindowPaint *paint;
2313 g_assert (gdk_window_has_impl (private));
2315 g_assert (private->implicit_paint != NULL);
2317 paint = private->implicit_paint;
2319 private->implicit_paint = NULL;
2321 if (!gdk_region_empty (paint->region))
2323 /* Some regions are valid, push these to window now */
2324 tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
2325 _gdk_gc_set_clip_region_internal (tmp_gc, paint->region, TRUE);
2326 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2327 0, 0, paint->x_offset, paint->y_offset, -1, -1);
2328 /* Reset clip region of the cached GdkGC */
2329 gdk_gc_set_clip_region (tmp_gc, NULL);
2332 g_object_unref (paint->pixmap);
2337 * gdk_window_begin_paint_rect:
2338 * @window: a #GdkWindow
2339 * @rectangle: rectangle you intend to draw to
2341 * A convenience wrapper around gdk_window_begin_paint_region() which
2342 * creates a rectangular region for you. See
2343 * gdk_window_begin_paint_region() for details.
2347 gdk_window_begin_paint_rect (GdkWindow *window,
2348 const GdkRectangle *rectangle)
2352 g_return_if_fail (GDK_IS_WINDOW (window));
2354 region = gdk_region_rectangle (rectangle);
2355 gdk_window_begin_paint_region (window, region);
2356 gdk_region_destroy (region);
2359 #ifdef GDK_WINDOWING_X11
2360 #include "x11/gdkx.h"
2364 * gdk_window_begin_paint_region:
2365 * @window: a #GdkWindow
2366 * @region: region you intend to draw to
2368 * Indicates that you are beginning the process of redrawing @region.
2369 * A backing store (offscreen buffer) large enough to contain @region
2370 * will be created. The backing store will be initialized with the
2371 * background color or background pixmap for @window. Then, all
2372 * drawing operations performed on @window will be diverted to the
2373 * backing store. When you call gdk_window_end_paint(), the backing
2374 * store will be copied to @window, making it visible onscreen. Only
2375 * the part of @window contained in @region will be modified; that is,
2376 * drawing operations are clipped to @region.
2378 * The net result of all this is to remove flicker, because the user
2379 * sees the finished product appear all at once when you call
2380 * gdk_window_end_paint(). If you draw to @window directly without
2381 * calling gdk_window_begin_paint_region(), the user may see flicker
2382 * as individual drawing operations are performed in sequence. The
2383 * clipping and background-initializing features of
2384 * gdk_window_begin_paint_region() are conveniences for the
2385 * programmer, so you can avoid doing that work yourself.
2387 * When using GTK+, the widget system automatically places calls to
2388 * gdk_window_begin_paint_region() and gdk_window_end_paint() around
2389 * emissions of the expose_event signal. That is, if you're writing an
2390 * expose event handler, you can assume that the exposed area in
2391 * #GdkEventExpose has already been cleared to the window background,
2392 * is already set as the clip region, and already has a backing store.
2393 * Therefore in most cases, application code need not call
2394 * gdk_window_begin_paint_region(). (You can disable the automatic
2395 * calls around expose events on a widget-by-widget basis by calling
2396 * gtk_widget_set_double_buffered().)
2398 * If you call this function multiple times before calling the
2399 * matching gdk_window_end_paint(), the backing stores are pushed onto
2400 * a stack. gdk_window_end_paint() copies the topmost backing store
2401 * onscreen, subtracts the topmost region from all other regions in
2402 * the stack, and pops the stack. All drawing operations affect only
2403 * the topmost backing store in the stack. One matching call to
2404 * gdk_window_end_paint() is required for each call to
2405 * gdk_window_begin_paint_region().
2409 gdk_window_begin_paint_region (GdkWindow *window,
2410 const GdkRegion *region)
2412 #ifdef USE_BACKING_STORE
2413 GdkWindowObject *private = (GdkWindowObject *)window;
2414 GdkRectangle clip_box;
2415 GdkWindowPaint *paint, *implicit_paint;
2416 GdkWindowObject *impl_window;
2419 g_return_if_fail (GDK_IS_WINDOW (window));
2421 if (GDK_WINDOW_DESTROYED (window))
2424 if (GDK_IS_PAINTABLE (private->impl))
2426 GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
2428 if (iface->begin_paint_region)
2429 iface->begin_paint_region ((GdkPaintable*)private->impl, window, region);
2434 impl_window = gdk_window_get_impl_window (private);
2435 implicit_paint = impl_window->implicit_paint;
2437 paint = g_new (GdkWindowPaint, 1);
2438 paint->region = gdk_region_copy (region);
2439 paint->region_tag = new_region_tag ();
2441 gdk_region_intersect (paint->region, private->clip_region_with_children);
2442 gdk_region_get_clipbox (paint->region, &clip_box);
2444 /* Convert to impl coords */
2445 gdk_region_offset (paint->region, private->abs_x, private->abs_y);
2447 /* Mark the region as valid on the implicit paint */
2450 gdk_region_union (implicit_paint->region, paint->region);
2452 /* Convert back to normal coords */
2453 gdk_region_offset (paint->region, -private->abs_x, -private->abs_y);
2459 paint->uses_implicit = TRUE;
2460 paint->pixmap = g_object_ref (implicit_paint->pixmap);
2461 paint->x_offset = -private->abs_x + implicit_paint->x_offset;
2462 paint->y_offset = -private->abs_y + implicit_paint->y_offset;
2464 /* It would be nice if we had some cairo support here so we
2465 could set the clip rect on the cairo surface */
2466 width = private->abs_x + private->width;
2467 height = private->abs_y + private->height;
2469 paint->surface = _gdk_drawable_create_cairo_surface (paint->pixmap, width, height);
2474 paint->uses_implicit = FALSE;
2475 paint->x_offset = clip_box.x;
2476 paint->y_offset = clip_box.y;
2478 gdk_pixmap_new (window,
2479 MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1);
2480 paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap);
2484 cairo_surface_set_device_offset (paint->surface,
2485 -paint->x_offset, -paint->y_offset);
2487 for (list = private->paint_stack; list != NULL; list = list->next)
2489 GdkWindowPaint *tmp_paint = list->data;
2491 gdk_region_subtract (tmp_paint->region, paint->region);
2494 private->paint_stack = g_slist_prepend (private->paint_stack, paint);
2496 if (!gdk_region_empty (paint->region))
2498 gdk_window_clear_backing_region (window,
2502 #endif /* USE_BACKING_STORE */
2506 setup_redirect_clip (GdkWindow *window,
2511 GdkWindowObject *private = (GdkWindowObject *)window;
2512 GdkRegion *visible_region;
2513 GdkRectangle dest_rect;
2515 GdkWindow *toplevel;
2516 int x_offset, y_offset;
2518 toplevel = GDK_WINDOW (private->redirect->redirected);
2520 /* Get the clip region for gc clip rect + window hierarchy in
2521 window relative coords */
2523 _gdk_window_calculate_full_clip_region (window, toplevel,
2528 /* Compensate for the source pos/size */
2529 x_offset -= private->redirect->src_x;
2530 y_offset -= private->redirect->src_y;
2531 dest_rect.x = -x_offset;
2532 dest_rect.y = -y_offset;
2533 dest_rect.width = private->redirect->width;
2534 dest_rect.height = private->redirect->height;
2535 tmpreg = gdk_region_rectangle (&dest_rect);
2536 gdk_region_intersect (visible_region, tmpreg);
2537 gdk_region_destroy (tmpreg);
2539 /* Compensate for the dest pos */
2540 x_offset += private->redirect->dest_x;
2541 y_offset += private->redirect->dest_y;
2543 gdk_gc_set_clip_region (gc, visible_region); /* This resets clip origin! */
2545 /* offset clip and tiles from window coords to pixmaps coords */
2546 gdk_gc_offset (gc, -x_offset, -y_offset);
2548 gdk_region_destroy (visible_region);
2550 *x_offset_out = x_offset;
2551 *y_offset_out = y_offset;
2555 * gdk_window_end_paint:
2556 * @window: a #GdkWindow
2558 * Indicates that the backing store created by the most recent call to
2559 * gdk_window_begin_paint_region() should be copied onscreen and
2560 * deleted, leaving the next-most-recent backing store or no backing
2561 * store at all as the active paint region. See
2562 * gdk_window_begin_paint_region() for full details. It is an error to
2563 * call this function without a matching
2564 * gdk_window_begin_paint_region() first.
2568 gdk_window_end_paint (GdkWindow *window)
2570 #ifdef USE_BACKING_STORE
2571 GdkWindowObject *private = (GdkWindowObject *)window;
2572 GdkWindowObject *composited;
2573 GdkWindowPaint *paint;
2575 GdkRectangle clip_box;
2576 gint x_offset, y_offset;
2577 GdkRegion *full_clip;
2579 g_return_if_fail (GDK_IS_WINDOW (window));
2581 if (GDK_WINDOW_DESTROYED (window))
2584 if (GDK_IS_PAINTABLE (private->impl))
2586 GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
2588 if (iface->end_paint)
2589 iface->end_paint ((GdkPaintable*)private->impl);
2593 if (private->paint_stack == NULL)
2595 g_warning (G_STRLOC": no preceding call to gdk_window_begin_paint_region(), see documentation");
2599 paint = private->paint_stack->data;
2601 private->paint_stack = g_slist_delete_link (private->paint_stack,
2602 private->paint_stack);
2604 gdk_region_get_clipbox (paint->region, &clip_box);
2606 tmp_gc = _gdk_drawable_get_scratch_gc (window, FALSE);
2608 x_offset = -private->abs_x;
2609 y_offset = -private->abs_y;
2611 if (!paint->uses_implicit)
2613 gdk_window_flush_outstanding_moves (window);
2615 full_clip = gdk_region_copy (private->clip_region_with_children);
2616 gdk_region_intersect (full_clip, paint->region);
2617 _gdk_gc_set_clip_region_internal (tmp_gc, full_clip, TRUE); /* Takes ownership of full_clip */
2618 gdk_gc_set_clip_origin (tmp_gc, - x_offset, - y_offset);
2619 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2620 clip_box.x - paint->x_offset,
2621 clip_box.y - paint->y_offset,
2622 clip_box.x - x_offset, clip_box.y - y_offset,
2623 clip_box.width, clip_box.height);
2626 if (private->redirect)
2628 int x_offset, y_offset;
2630 /* TODO: Should also use paint->region for clipping */
2631 setup_redirect_clip (window, tmp_gc, &x_offset, &y_offset);
2632 gdk_draw_drawable (private->redirect->pixmap, tmp_gc, paint->pixmap,
2633 clip_box.x - paint->x_offset,
2634 clip_box.y - paint->y_offset,
2635 clip_box.x + x_offset,
2636 clip_box.y + y_offset,
2637 clip_box.width, clip_box.height);
2640 /* Reset clip region of the cached GdkGC */
2641 gdk_gc_set_clip_region (tmp_gc, NULL);
2643 cairo_surface_destroy (paint->surface);
2644 g_object_unref (paint->pixmap);
2645 gdk_region_destroy (paint->region);
2648 /* find a composited window in our hierarchy to signal its
2649 * parent to redraw, calculating the clip box as we go...
2651 * stop if parent becomes NULL since then we'd have nowhere
2652 * to draw (ie: 'composited' will always be non-NULL here).
2654 for (composited = private;
2656 composited = composited->parent)
2660 gdk_drawable_get_size (GDK_DRAWABLE (composited->parent),
2663 clip_box.x += composited->x;
2664 clip_box.y += composited->y;
2665 clip_box.width = MIN (clip_box.width, width - clip_box.x);
2666 clip_box.height = MIN (clip_box.height, height - clip_box.y);
2668 if (composited->composited)
2670 gdk_window_invalidate_rect (GDK_WINDOW (composited->parent),
2675 #endif /* USE_BACKING_STORE */
2679 gdk_window_free_paint_stack (GdkWindow *window)
2681 GdkWindowObject *private = (GdkWindowObject *)window;
2683 if (private->paint_stack)
2685 GSList *tmp_list = private->paint_stack;
2689 GdkWindowPaint *paint = tmp_list->data;
2691 if (tmp_list == private->paint_stack)
2692 g_object_unref (paint->pixmap);
2694 gdk_region_destroy (paint->region);
2697 tmp_list = tmp_list->next;
2700 g_slist_free (private->paint_stack);
2701 private->paint_stack = NULL;
2706 do_move_region_bits_on_impl (GdkWindowObject *impl_window,
2707 GdkRegion *dest_region, /* In impl window coords */
2711 GdkRectangle copy_rect;
2712 GdkWindowObject *private;
2714 /* We need to get data from subwindows here, because we might have
2715 * shaped a native window over the moving region (with bg none,
2716 * so the pixels are still there). In fact we might need to get data
2717 * from overlapping native window that are not children of this window,
2718 * so we copy from the toplevel with INCLUDE_INFERIORS.
2720 private = impl_window;
2721 while (private->parent != NULL &&
2722 GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
2724 dx -= private->parent->abs_x + private->x;
2725 dy -= private->parent->abs_y + private->y;
2726 private = gdk_window_get_impl_window (private->parent);
2728 tmp_gc = _gdk_drawable_get_subwindow_scratch_gc ((GdkWindow *)private);
2730 /* The region area is moved and we queue translations for all expose events
2731 to the source area that were sent prior to the copy */
2732 gdk_region_offset (dest_region, -dx, -dy); /* Temporarily move to source area */
2733 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->queue_translation ((GdkWindow *)impl_window,
2734 dest_region, dx, dy);
2735 gdk_region_offset (dest_region, dx, dy); /* back to dest area */
2737 gdk_region_get_clipbox (dest_region, ©_rect);
2739 gdk_gc_set_clip_region (tmp_gc, dest_region);
2740 gdk_draw_drawable (impl_window->impl,
2743 copy_rect.x-dx, copy_rect.y-dy,
2744 copy_rect.x, copy_rect.y,
2745 copy_rect.width, copy_rect.height);
2746 gdk_gc_set_clip_region (tmp_gc, NULL);
2749 static GdkWindowRegionMove *
2750 gdk_window_region_move_new (GdkRegion *region,
2753 GdkWindowRegionMove *move;
2755 move = g_slice_new (GdkWindowRegionMove);
2756 move->dest_region = gdk_region_copy (region);
2764 gdk_window_region_move_free (GdkWindowRegionMove *move)
2766 gdk_region_destroy (move->dest_region);
2767 g_slice_free (GdkWindowRegionMove, move);
2771 append_move_region (GdkWindowObject *impl_window,
2772 GdkRegion *new_dest_region,
2775 GdkWindowRegionMove *move, *old_move;
2776 GdkRegion *new_total_region, *old_total_region;
2777 GdkRegion *source_overlaps_destination;
2778 GdkRegion *non_overwritten;
2779 gboolean added_move;
2782 if (gdk_region_empty (new_dest_region))
2785 /* In principle this could just append the move to the list of outstanding
2786 moves that will be replayed before drawing anything when we're handling
2787 exposes. However, we'd like to do a bit better since its commonly the case
2788 that we get multiple copies where A is copied to B and then B is copied
2789 to C, and we'd like to express this as a simple copy A to C operation. */
2791 /* We approach this by taking the new move and pushing it ahead of moves
2792 starting at the end of the list and stopping when its not safe to do so.
2793 It's not safe to push past a move if either the source of the new move
2794 is in the destination of the old move, or if the destination of the new
2795 move is in the source of the new move, or if the destination of the new
2796 move overlaps the destination of the old move. We simplify this by
2797 just comparing the total regions (src + dest) */
2798 new_total_region = gdk_region_copy (new_dest_region);
2799 gdk_region_offset (new_total_region, -dx, -dy);
2800 gdk_region_union (new_total_region, new_dest_region);
2803 for (l = g_list_last (impl_window->outstanding_moves); l != NULL; l = prev)
2808 old_total_region = gdk_region_copy (old_move->dest_region);
2809 gdk_region_offset (old_total_region, -old_move->dx, -old_move->dy);
2810 gdk_region_union (old_total_region, old_move->dest_region);
2812 gdk_region_intersect (old_total_region, new_total_region);
2813 /* If these regions intersect then its not safe to push the
2814 new region before the old one */
2815 if (!gdk_region_empty (old_total_region))
2817 /* The area where the new moves source overlaps the old ones
2819 source_overlaps_destination = gdk_region_copy (new_dest_region);
2820 gdk_region_offset (source_overlaps_destination, -dx, -dy);
2821 gdk_region_intersect (source_overlaps_destination, old_move->dest_region);
2822 gdk_region_offset (source_overlaps_destination, dx, dy);
2824 /* We can do all sort of optimizations here, but to do things safely it becomes
2825 quite complicated. However, a very common case is that you copy something first,
2826 then copy all that or a subset of it to a new location (i.e. if you scroll twice
2827 in the same direction). We'd like to detect this case and optimize it to one
2829 if (gdk_region_equal (source_overlaps_destination, new_dest_region))
2831 /* This means we might be able to replace the old move and the new one
2832 with the new one read from the old ones source, and a second copy of
2833 the non-overwritten parts of the old move. However, such a split
2834 is only valid if the source in the old move isn't overwritten
2835 by the destination of the new one */
2837 /* the new destination of old move if split is ok: */
2838 non_overwritten = gdk_region_copy (old_move->dest_region);
2839 gdk_region_subtract (non_overwritten, new_dest_region);
2840 /* move to source region */
2841 gdk_region_offset (non_overwritten, -old_move->dx, -old_move->dy);
2843 gdk_region_intersect (non_overwritten, new_dest_region);
2844 if (gdk_region_empty (non_overwritten))
2847 move = gdk_window_region_move_new (new_dest_region,
2851 impl_window->outstanding_moves =
2852 g_list_insert_before (impl_window->outstanding_moves,
2854 gdk_region_subtract (old_move->dest_region, new_dest_region);
2856 gdk_region_destroy (non_overwritten);
2859 gdk_region_destroy (source_overlaps_destination);
2860 gdk_region_destroy (old_total_region);
2863 gdk_region_destroy (old_total_region);
2866 gdk_region_destroy (new_total_region);
2870 move = gdk_window_region_move_new (new_dest_region, dx, dy);
2873 impl_window->outstanding_moves =
2874 g_list_prepend (impl_window->outstanding_moves,
2877 impl_window->outstanding_moves =
2878 g_list_insert_before (impl_window->outstanding_moves,
2883 /* Moves bits and update area by dx/dy in impl window,
2884 takes ownership of region */
2886 move_region_on_impl (GdkWindowObject *private,
2887 GdkRegion *region, /* In impl window coords */
2890 GdkWindowObject *impl_window;
2892 if ((dx == 0 && dy == 0) ||
2893 gdk_region_empty (region))
2895 gdk_region_destroy (region);
2899 impl_window = gdk_window_get_impl_window (private);
2901 /* Move any old invalid regions in the copy source area by dx/dy */
2902 if (impl_window->update_area)
2904 GdkRegion *update_area;
2905 update_area = gdk_region_copy (region);
2907 /* Convert from target to source */
2908 gdk_region_offset (update_area, -dx, -dy);
2909 gdk_region_intersect (update_area, impl_window->update_area);
2910 gdk_region_subtract (impl_window->update_area, update_area);
2913 gdk_region_offset (update_area, dx, dy);
2914 gdk_region_union (impl_window->update_area, update_area);
2916 /* This area of the destination is now invalid,
2917 so no need to copy to it. */
2918 gdk_region_subtract (region, update_area);
2920 gdk_region_destroy (update_area);
2923 if (1) /* Enable flicker free handling of moves. */
2924 append_move_region (impl_window, region, dx, dy);
2926 do_move_region_bits_on_impl (impl_window,
2929 gdk_region_destroy (region);
2932 /* Flushes all outstanding changes to the window, call this
2933 * before drawing directly to the window (i.e. outside a begin/end_paint pair).
2936 gdk_window_flush_outstanding_moves (GdkWindow *window)
2938 GdkWindowObject *private;
2939 GdkWindowObject *impl_window;
2941 GdkWindowRegionMove *move;
2943 private = (GdkWindowObject *) window;
2945 impl_window = gdk_window_get_impl_window (private);
2947 for (l = impl_window->outstanding_moves; l != NULL; l = l->next)
2951 do_move_region_bits_on_impl (impl_window,
2952 move->dest_region, move->dx, move->dy);
2954 gdk_window_region_move_free (move);
2957 g_list_free (impl_window->outstanding_moves);
2958 impl_window->outstanding_moves = NULL;
2962 gdk_window_flush (GdkWindow *window)
2964 gdk_window_flush_outstanding_moves (window);
2965 gdk_window_flush_implicit_paint (window);
2969 gdk_window_flush_recursive_helper (GdkWindowObject *window,
2972 GdkWindowObject *child;
2975 for (l = window->children; l != NULL; l = l->next)
2979 if (child->impl == impl)
2980 /* Same impl, ignore */
2981 gdk_window_flush_recursive_helper (child, impl);
2983 gdk_window_flush_recursive (child);
2988 gdk_window_flush_recursive (GdkWindowObject *window)
2990 gdk_window_flush ((GdkWindow *)window);
2991 gdk_window_flush_recursive_helper (window, window->impl);
2995 gdk_window_get_offsets (GdkWindow *window,
2999 GdkWindowObject *private = (GdkWindowObject *)window;
3001 if (private->paint_stack)
3003 GdkWindowPaint *paint = private->paint_stack->data;
3004 *x_offset = paint->x_offset;
3005 *y_offset = paint->y_offset;
3009 *x_offset = -private->abs_x;
3010 *y_offset = -private->abs_y;
3015 * gdk_window_get_internal_paint_info:
3016 * @window: a #GdkWindow
3017 * @real_drawable: location to store the drawable to which drawing should be
3019 * @x_offset: location to store the X offset between coordinates in @window,
3020 * and the underlying window system primitive coordinates for
3022 * @y_offset: location to store the Y offset between coordinates in @window,
3023 * and the underlying window system primitive coordinates for
3026 * If you bypass the GDK layer and use windowing system primitives to
3027 * draw directly onto a #GdkWindow, then you need to deal with two
3028 * details: there may be an offset between GDK coordinates and windowing
3029 * system coordinates, and GDK may have redirected drawing to a offscreen
3030 * pixmap as the result of a gdk_window_begin_paint_region() calls.
3031 * This function allows retrieving the information you need to compensate
3032 * for these effects.
3034 * This function exposes details of the GDK implementation, and is thus
3035 * likely to change in future releases of GDK.
3038 gdk_window_get_internal_paint_info (GdkWindow *window,
3039 GdkDrawable **real_drawable,
3045 GdkWindowObject *private;
3047 g_return_if_fail (GDK_IS_WINDOW (window));
3049 private = (GdkWindowObject *)window;
3053 if (private->paint_stack)
3055 GdkWindowPaint *paint = private->paint_stack->data;
3056 *real_drawable = paint->pixmap;
3060 /* This means you're probably gonna be doing some weird shit
3061 directly to the window, so we flush all outstanding stuff */
3062 gdk_window_flush (window);
3063 *real_drawable = window;
3067 gdk_window_get_offsets (window, &x_off, &y_off);
3075 static GdkDrawable *
3076 start_draw_helper (GdkDrawable *drawable,
3081 GdkWindowObject *private = (GdkWindowObject *)drawable;
3082 gint x_offset, y_offset;
3084 gint old_clip_x = gc->clip_x_origin;
3085 gint old_clip_y = gc->clip_y_origin;
3087 guint32 clip_region_tag;
3088 GdkWindowPaint *paint;
3091 if (private->paint_stack)
3092 paint = private->paint_stack->data;
3096 x_offset = paint->x_offset;
3097 y_offset = paint->y_offset;
3101 x_offset = -private->abs_x;
3102 y_offset = -private->abs_y;
3105 if (x_offset != 0 || y_offset != 0)
3107 gdk_gc_set_clip_origin (gc,
3108 old_clip_x - x_offset,
3109 old_clip_y - y_offset);
3110 gdk_gc_set_ts_origin (gc,
3111 gc->ts_x_origin - x_offset,
3112 gc->ts_y_origin - y_offset);
3115 *x_offset_out = x_offset;
3116 *y_offset_out = y_offset;
3118 /* Add client side window clip region to gc */
3122 /* Only need clipping if using implicit paint, otherwise
3123 the pixmap is clipped when copying to the window in end_paint */
3124 if (paint->uses_implicit)
3126 /* This includes the window clip */
3127 clip = paint->region;
3129 clip_region_tag = paint->region_tag;
3131 /* After having set up the drawable clip rect on a GC we need to make sure
3132 * that we draw to th the impl, otherwise the pixmap code will reset the
3134 impl = ((GdkPixmapObject *)(paint->pixmap))->impl;
3138 /* Drawing directly to the window, flush anything outstanding to
3139 guarantee ordering. */
3140 gdk_window_flush ((GdkWindow *)drawable);
3142 /* Don't clip when drawing to root */
3143 if (private->window_type != GDK_WINDOW_ROOT)
3145 if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
3146 clip = private->clip_region_with_children;
3148 clip = private->clip_region;
3150 clip_region_tag = private->clip_tag;
3151 impl = private->impl;
3155 _gdk_gc_add_drawable_clip (gc,
3156 clip_region_tag, clip,
3157 /* If there was a clip origin set appart from the
3158 * window offset, need to take that into
3160 -old_clip_x, -old_clip_y);
3165 #define BEGIN_DRAW \
3167 GdkDrawable *impl; \
3168 gint x_offset, y_offset; \
3169 gint old_clip_x = gc->clip_x_origin; \
3170 gint old_clip_y = gc->clip_y_origin; \
3171 gint old_ts_x = gc->ts_x_origin; \
3172 gint old_ts_y = gc->ts_y_origin; \
3173 impl = start_draw_helper (drawable, gc, \
3174 &x_offset, &y_offset);
3177 if (x_offset != 0 || y_offset != 0) \
3179 gdk_gc_set_clip_origin (gc, old_clip_x, old_clip_y); \
3180 gdk_gc_set_ts_origin (gc, old_ts_x, old_ts_y); \
3185 gdk_window_create_gc (GdkDrawable *drawable,
3186 GdkGCValues *values,
3187 GdkGCValuesMask mask)
3189 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
3191 if (GDK_WINDOW_DESTROYED (drawable))
3194 return gdk_gc_new_with_values (((GdkWindowObject *) drawable)->impl,
3199 gdk_window_draw_rectangle (GdkDrawable *drawable,
3207 if (GDK_WINDOW_DESTROYED (drawable))
3211 gdk_draw_rectangle (impl, gc, filled,
3212 x - x_offset, y - y_offset, width, height);
3217 gdk_window_draw_arc (GdkDrawable *drawable,
3227 if (GDK_WINDOW_DESTROYED (drawable))
3231 gdk_draw_arc (impl, gc, filled,
3232 x - x_offset, y - y_offset,
3233 width, height, angle1, angle2);
3238 gdk_window_draw_polygon (GdkDrawable *drawable,
3244 GdkPoint *new_points;
3246 if (GDK_WINDOW_DESTROYED (drawable))
3251 if (x_offset != 0 || y_offset != 0)
3255 new_points = g_new (GdkPoint, npoints);
3256 for (i=0; i<npoints; i++)
3258 new_points[i].x = points[i].x - x_offset;
3259 new_points[i].y = points[i].y - y_offset;
3263 new_points = points;
3265 gdk_draw_polygon (impl, gc, filled, new_points, npoints);
3267 if (new_points != points)
3268 g_free (new_points);
3274 gdk_window_draw_text (GdkDrawable *drawable,
3282 if (GDK_WINDOW_DESTROYED (drawable))
3286 gdk_draw_text (impl, font, gc,
3287 x - x_offset, y - y_offset, text, text_length);
3292 gdk_window_draw_text_wc (GdkDrawable *drawable,
3297 const GdkWChar *text,
3300 if (GDK_WINDOW_DESTROYED (drawable))
3304 gdk_draw_text_wc (impl, font, gc,
3305 x - x_offset, y - y_offset, text, text_length);
3309 static GdkDrawable *
3310 gdk_window_get_source_drawable (GdkDrawable *drawable)
3312 GdkWindow *window = GDK_WINDOW (drawable);
3313 GdkWindowObject *private;
3315 private = (GdkWindowObject *) window;
3316 if (GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable)
3317 return GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable (private->impl);
3322 static GdkDrawable *
3323 gdk_window_get_composite_drawable (GdkDrawable *drawable,
3328 gint *composite_x_offset,
3329 gint *composite_y_offset)
3331 GdkWindowObject *private = (GdkWindowObject *)drawable;
3333 GdkPixmap *tmp_pixmap;
3336 gboolean overlap_buffer;
3337 GdkDrawable *source;
3338 GdkWindowObject *impl_window;
3339 GdkWindowPaint *implicit_paint;
3341 *composite_x_offset = -private->abs_x;
3342 *composite_y_offset = -private->abs_y;
3344 if ((GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable)))
3345 return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
3347 /* See if any buffered part is overlapping the part we want
3353 rect.height = height;
3355 overlap_buffer = FALSE;
3357 for (list = private->paint_stack; list != NULL; list = list->next)
3359 GdkWindowPaint *paint = list->data;
3360 GdkOverlapType overlap;
3362 overlap = gdk_region_rect_in (paint->region, &rect);
3364 if (overlap == GDK_OVERLAP_RECTANGLE_IN)
3366 *composite_x_offset = paint->x_offset;
3367 *composite_y_offset = paint->y_offset;
3369 return g_object_ref (paint->pixmap);
3371 else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
3373 overlap_buffer = TRUE;
3378 impl_window = gdk_window_get_impl_window (private);
3379 implicit_paint = impl_window->implicit_paint;
3382 GdkOverlapType overlap;
3384 rect.x += private->abs_x;
3385 rect.y += private->abs_y;
3387 overlap = gdk_region_rect_in (implicit_paint->region, &rect);
3388 if (overlap == GDK_OVERLAP_RECTANGLE_IN)
3390 *composite_x_offset = -private->abs_x + implicit_paint->x_offset;
3391 *composite_y_offset = -private->abs_y + implicit_paint->y_offset;
3393 return g_object_ref (implicit_paint->pixmap);
3395 else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
3396 overlap_buffer = TRUE;
3399 if (!overlap_buffer)
3400 return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
3402 tmp_pixmap = gdk_pixmap_new (drawable, width, height, -1);
3403 tmp_gc = _gdk_drawable_get_scratch_gc (tmp_pixmap, FALSE);
3405 source = _gdk_drawable_get_source_drawable (drawable);
3407 /* Copy the current window contents */
3408 gdk_draw_drawable (tmp_pixmap,
3410 GDK_WINDOW_OBJECT (source)->impl,
3411 x - *composite_x_offset,
3412 y - *composite_y_offset,
3416 /* paint the backing stores */
3419 GdkWindowPaint *paint = list->data;
3421 gdk_gc_set_clip_region (tmp_gc, paint->region);
3422 gdk_gc_set_clip_origin (tmp_gc, -x - paint->x_offset, -y - paint->y_offset);
3424 gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
3425 x - paint->x_offset,
3426 y - paint->y_offset,
3427 0, 0, width, height);
3430 for (list = private->paint_stack; list != NULL; list = list->next)
3432 GdkWindowPaint *paint = list->data;
3434 if (paint->uses_implicit)
3435 continue; /* We already copied this above */
3437 gdk_gc_set_clip_region (tmp_gc, paint->region);
3438 gdk_gc_set_clip_origin (tmp_gc, -x, -y);
3440 gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
3441 x - paint->x_offset,
3442 y - paint->y_offset,
3443 0, 0, width, height);
3446 /* Reset clip region of the cached GdkGC */
3447 gdk_gc_set_clip_region (tmp_gc, NULL);
3449 /* Set these to location of tmp_pixmap within the window */
3450 *composite_x_offset = x;
3451 *composite_y_offset = y;
3457 gdk_window_get_clip_region (GdkDrawable *drawable)
3459 GdkWindowObject *private = (GdkWindowObject *)drawable;
3462 result = gdk_region_copy (private->clip_region);
3464 if (private->paint_stack)
3466 GdkRegion *paint_region = gdk_region_new ();
3467 GSList *tmp_list = private->paint_stack;
3471 GdkWindowPaint *paint = tmp_list->data;
3473 gdk_region_union (paint_region, paint->region);
3475 tmp_list = tmp_list->next;
3478 gdk_region_intersect (result, paint_region);
3479 gdk_region_destroy (paint_region);
3486 gdk_window_get_visible_region (GdkDrawable *drawable)
3488 GdkWindowObject *private = (GdkWindowObject*) drawable;
3490 return gdk_region_copy (private->clip_region);
3494 gdk_window_draw_drawable (GdkDrawable *drawable,
3497 GdkDrawable *original_src,
3505 GdkWindowObject *private = (GdkWindowObject *)drawable;
3507 if (GDK_WINDOW_DESTROYED (drawable))
3512 gdk_draw_drawable (impl, gc, src, xsrc, ysrc,
3513 xdest - x_offset, ydest - y_offset, width, height);
3515 if (!private->paint_stack)
3517 /* We might have drawn from an obscured part of a client
3518 side window, if so we need to send graphics exposures */
3519 if (_gdk_gc_get_exposures (gc) &&
3520 GDK_IS_WINDOW (original_src))
3522 GdkRegion *exposure_region;
3530 exposure_region = gdk_region_rectangle (&r);
3532 if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
3533 clip = private->clip_region_with_children;
3535 clip = private->clip_region;
3536 gdk_region_intersect (exposure_region, clip);
3538 clip = _gdk_gc_get_clip_region (gc);
3541 gdk_region_offset (exposure_region,
3544 gdk_region_intersect (exposure_region, clip);
3545 gdk_region_offset (exposure_region,
3550 /* Note: We don't clip by the clip mask if set, so this
3551 may invalidate to much */
3553 /* Remove the area that is correctly copied from the src.
3554 * Note that xsrc/ysrc has been corrected for abs_x/y offsets already,
3555 * which need to be undone */
3556 clip = gdk_drawable_get_visible_region (original_src);
3557 gdk_region_offset (clip,
3558 xdest - (xsrc - GDK_WINDOW_OBJECT (original_src)->abs_x),
3559 ydest - (ysrc - GDK_WINDOW_OBJECT (original_src)->abs_y));
3560 gdk_region_subtract (exposure_region, clip);
3561 gdk_region_destroy (clip);
3563 gdk_window_invalidate_region (GDK_WINDOW (private),
3565 _gdk_gc_get_subwindow (gc) == GDK_INCLUDE_INFERIORS);
3567 gdk_region_destroy (exposure_region);
3575 gdk_window_draw_points (GdkDrawable *drawable,
3580 GdkPoint *new_points;
3582 if (GDK_WINDOW_DESTROYED (drawable))
3587 if (x_offset != 0 || y_offset != 0)
3591 new_points = g_new (GdkPoint, npoints);
3592 for (i=0; i<npoints; i++)
3594 new_points[i].x = points[i].x - x_offset;
3595 new_points[i].y = points[i].y - y_offset;
3599 new_points = points;
3601 gdk_draw_points (impl, gc, new_points, npoints);
3603 if (new_points != points)
3604 g_free (new_points);
3610 gdk_window_draw_segments (GdkDrawable *drawable,
3615 GdkSegment *new_segs;
3617 if (GDK_WINDOW_DESTROYED (drawable))
3622 if (x_offset != 0 || y_offset != 0)
3626 new_segs = g_new (GdkSegment, nsegs);
3627 for (i=0; i<nsegs; i++)
3629 new_segs[i].x1 = segs[i].x1 - x_offset;
3630 new_segs[i].y1 = segs[i].y1 - y_offset;
3631 new_segs[i].x2 = segs[i].x2 - x_offset;
3632 new_segs[i].y2 = segs[i].y2 - y_offset;
3638 gdk_draw_segments (impl, gc, new_segs, nsegs);
3640 if (new_segs != segs)
3647 gdk_window_draw_lines (GdkDrawable *drawable,
3652 GdkPoint *new_points;
3654 if (GDK_WINDOW_DESTROYED (drawable))
3659 if (x_offset != 0 || y_offset != 0)
3663 new_points = g_new (GdkPoint, npoints);
3664 for (i=0; i<npoints; i++)
3666 new_points[i].x = points[i].x - x_offset;
3667 new_points[i].y = points[i].y - y_offset;
3671 new_points = points;
3673 gdk_draw_lines (impl, gc, new_points, npoints);
3675 if (new_points != points)
3676 g_free (new_points);
3682 gdk_window_draw_glyphs (GdkDrawable *drawable,
3687 PangoGlyphString *glyphs)
3689 if (GDK_WINDOW_DESTROYED (drawable))
3693 gdk_draw_glyphs (impl, gc, font,
3694 x - x_offset, y - y_offset, glyphs);
3699 gdk_window_draw_glyphs_transformed (GdkDrawable *drawable,
3701 PangoMatrix *matrix,
3705 PangoGlyphString *glyphs)
3707 PangoMatrix tmp_matrix;
3709 if (GDK_WINDOW_DESTROYED (drawable))
3714 if (x_offset != 0 || y_offset != 0)
3718 tmp_matrix = *matrix;
3719 tmp_matrix.x0 -= x_offset;
3720 tmp_matrix.y0 -= y_offset;
3721 matrix = &tmp_matrix;
3723 else if (GDK_PANGO_UNITS_OVERFLOWS (x_offset, y_offset))
3725 PangoMatrix identity = PANGO_MATRIX_INIT;
3727 tmp_matrix = identity;
3728 tmp_matrix.x0 -= x_offset;
3729 tmp_matrix.y0 -= y_offset;
3730 matrix = &tmp_matrix;
3734 x -= x_offset * PANGO_SCALE;
3735 y -= y_offset * PANGO_SCALE;
3739 gdk_draw_glyphs_transformed (impl, gc, matrix, font, x, y, glyphs);
3745 cairo_t *cr; /* if non-null, it means use this cairo context */
3746 GdkGC *gc; /* if non-null, it means use this GC instead */
3747 } BackingRectMethod;
3750 setup_backing_rect_method (BackingRectMethod *method, GdkWindow *window, GdkWindowPaint *paint, int x_offset_cairo, int y_offset_cairo)
3752 GdkWindowObject *private = (GdkWindowObject *)window;
3754 if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
3756 GdkWindowPaint tmp_paint;
3759 tmp_paint.x_offset += private->x;
3760 tmp_paint.y_offset += private->y;
3762 x_offset_cairo += private->x;
3763 y_offset_cairo += private->y;
3765 setup_backing_rect_method (method, GDK_WINDOW (private->parent), &tmp_paint, x_offset_cairo, y_offset_cairo);
3767 else if (private->bg_pixmap &&
3768 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
3769 private->bg_pixmap != GDK_NO_BG)
3771 /* This is a workaround for https://bugs.freedesktop.org/show_bug.cgi?id=4320.
3772 * In it, using a pixmap as a repeating pattern in Cairo, and painting it to a
3773 * pixmap destination surface, can be very slow (on the order of seconds for a
3774 * whole-screen copy). The workaround is to use pretty much the same code that
3775 * we used in GTK+ 2.6 (pre-Cairo), which clears the double-buffer pixmap with
3776 * a tiled GC XFillRectangle().
3779 /* Actually computing this flag is left as an exercise for the reader */
3780 #if defined (G_OS_UNIX)
3781 # define GDK_CAIRO_REPEAT_IS_FAST 0
3783 # define GDK_CAIRO_REPEAT_IS_FAST 1
3786 #if GDK_CAIRO_REPEAT_IS_FAST
3787 cairo_surface_t *surface = _gdk_drawable_ref_cairo_surface (private->bg_pixmap);
3788 cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
3789 cairo_surface_destroy (surface);
3791 if (x_offset_cairo != 0 || y_offset_cairo != 0)
3793 cairo_matrix_t matrix;
3794 cairo_matrix_init_translate (&matrix, x_offset_cairo, y_offset_cairo);
3795 cairo_pattern_set_matrix (pattern, &matrix);
3798 cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
3800 method->cr = cairo_create (paint->surface);
3803 cairo_set_source (method->cr, pattern);
3804 cairo_pattern_destroy (pattern);
3807 GdkGCValues gc_values;
3809 gc_values.fill = GDK_TILED;
3810 gc_values.tile = private->bg_pixmap;
3811 gc_values.ts_x_origin = -x_offset_cairo;
3812 gc_values.ts_y_origin = -y_offset_cairo;
3814 gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN;
3816 method->gc = gdk_gc_new_with_values (paint->pixmap, &gc_values, gc_mask);
3821 method->cr = cairo_create (paint->surface);
3823 gdk_cairo_set_source_color (method->cr, &private->bg_color);
3828 gdk_window_clear_backing_region (GdkWindow *window,
3831 GdkWindowObject *private = (GdkWindowObject *)window;
3832 GdkWindowPaint *paint = private->paint_stack->data;
3833 BackingRectMethod method;
3835 GdkRectangle clipbox;
3841 if (GDK_WINDOW_DESTROYED (window))
3845 timer = g_timer_new ();
3850 setup_backing_rect_method (&method, window, paint, 0, 0);
3852 clip = gdk_region_copy (paint->region);
3853 gdk_region_intersect (clip, region);
3854 gdk_region_get_clipbox (clip, &clipbox);
3859 g_assert (method.gc == NULL);
3861 gdk_cairo_region (method.cr, clip);
3862 cairo_fill (method.cr);
3864 cairo_destroy (method.cr);
3866 elapsed = g_timer_elapsed (timer, NULL);
3867 g_print ("Draw the background with Cairo: %fs\n", elapsed);
3872 g_assert (method.gc != NULL);
3874 gdk_gc_set_clip_region (method.gc, clip);
3875 gdk_draw_rectangle (window, method.gc, TRUE,
3876 clipbox.x, clipbox.y,
3877 clipbox.width, clipbox.height);
3878 g_object_unref (method.gc);
3881 elapsed = g_timer_elapsed (timer, NULL);
3882 g_print ("Draw the background with GDK: %fs\n", elapsed);
3886 gdk_region_destroy (clip);
3889 g_timer_destroy (timer);
3894 gdk_window_clear_backing_region_redirect (GdkWindow *window,
3897 GdkWindowObject *private = (GdkWindowObject *)window;
3898 GdkWindowRedirect *redirect = private->redirect;
3899 GdkRegion *clip_region;
3900 GdkRectangle clipbox;
3901 gint x_offset, y_offset;
3902 BackingRectMethod method;
3903 GdkWindowPaint paint;
3905 if (GDK_WINDOW_DESTROYED (window))
3908 clip_region = _gdk_window_calculate_full_clip_region (window,
3909 GDK_WINDOW (redirect->redirected),
3911 &x_offset, &y_offset);
3912 gdk_region_intersect (clip_region, region);
3914 /* offset is from redirected window origin to window origin, convert to
3915 the offset from the redirected pixmap origin to the window origin */
3916 x_offset += redirect->dest_x - redirect->src_x;
3917 y_offset += redirect->dest_y - redirect->src_y;
3919 /* Convert region to pixmap coords */
3920 gdk_region_offset (clip_region, x_offset, y_offset);
3924 paint.pixmap = redirect->pixmap;
3925 paint.surface = _gdk_drawable_ref_cairo_surface (redirect->pixmap);
3929 setup_backing_rect_method (&method, window, &paint, -x_offset, -y_offset);
3933 g_assert (method.gc == NULL);
3935 gdk_cairo_region (method.cr, clip_region);
3936 cairo_fill (method.cr);
3938 cairo_destroy (method.cr);
3942 g_assert (method.gc != NULL);
3944 gdk_region_get_clipbox (clip_region, &clipbox);
3945 gdk_gc_set_clip_region (method.gc, clip_region);
3946 gdk_draw_rectangle (redirect->pixmap, method.gc, TRUE,
3947 clipbox.x, clipbox.y,
3948 clipbox.width, clipbox.height);
3949 g_object_unref (method.gc);
3953 gdk_region_destroy (clip_region);
3954 cairo_surface_destroy (paint.surface);
3958 gdk_window_clear_backing_region_direct (GdkWindow *window,
3961 GdkWindowObject *private = (GdkWindowObject *)window;
3962 BackingRectMethod method;
3963 GdkWindowPaint paint;
3965 GdkRectangle clipbox;
3967 if (GDK_WINDOW_DESTROYED (window))
3972 paint.pixmap = window;
3973 paint.surface = _gdk_drawable_ref_cairo_surface (window);
3977 setup_backing_rect_method (&method, window, &paint, 0, 0);
3979 clip = gdk_region_copy (private->clip_region_with_children);
3980 gdk_region_intersect (clip, region);
3981 gdk_region_get_clipbox (clip, &clipbox);
3985 g_assert (method.gc == NULL);
3987 gdk_cairo_region (method.cr, clip);
3988 cairo_fill (method.cr);
3990 cairo_destroy (method.cr);
3994 g_assert (method.gc != NULL);
3996 gdk_gc_set_clip_region (method.gc, clip);
3997 gdk_draw_rectangle (window, method.gc, TRUE,
3998 clipbox.x, clipbox.y,
3999 clipbox.width, clipbox.height);
4000 g_object_unref (method.gc);
4004 gdk_region_destroy (clip);
4005 cairo_surface_destroy (paint.surface);
4011 * @window: a #GdkWindow
4013 * Clears an entire @window to the background color or background pixmap.
4016 gdk_window_clear (GdkWindow *window)
4020 g_return_if_fail (GDK_IS_WINDOW (window));
4022 gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height);
4024 gdk_window_clear_area (window, 0, 0,
4029 gdk_window_clear_region_internal (GdkWindow *window,
4031 gboolean send_expose)
4033 GdkWindowObject *private = (GdkWindowObject *)window;
4035 if (private->paint_stack)
4036 gdk_window_clear_backing_region (window, region);
4039 if (private->redirect)
4040 gdk_window_clear_backing_region_redirect (window, region);
4042 if (GDK_WINDOW_IMPL_GET_IFACE (private->impl)->clear_region &&
4043 gdk_window_has_impl (private))
4046 copy = gdk_region_copy (region);
4047 gdk_region_intersect (copy, private->clip_region_with_children);
4049 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->clear_region
4050 (window, copy, send_expose);
4052 gdk_region_destroy (copy);
4056 gdk_window_clear_backing_region_direct (window, region);
4058 gdk_window_invalidate_region (window, region, FALSE);
4064 gdk_window_clear_area_internal (GdkWindow *window,
4069 gboolean send_expose)
4071 GdkWindowObject *private = (GdkWindowObject *)window;
4075 g_return_if_fail (GDK_IS_WINDOW (window));
4077 if (GDK_WINDOW_DESTROYED (window))
4080 /* This is what XClearArea does, and e.g. GtkCList uses it,
4081 so we need to duplicate that */
4083 width = private->width - x;
4085 height = private->height - y;
4090 rect.height = height;
4092 region = gdk_region_rectangle (&rect);
4093 gdk_window_clear_region_internal (window,
4096 gdk_region_destroy (region);
4101 * gdk_window_clear_area:
4102 * @window: a #GdkWindow
4103 * @x: x coordinate of rectangle to clear
4104 * @y: y coordinate of rectangle to clear
4105 * @width: width of rectangle to clear
4106 * @height: height of rectangle to clear
4108 * Clears an area of @window to the background color or background pixmap.
4112 gdk_window_clear_area (GdkWindow *window,
4118 gdk_window_clear_area_internal (window,
4125 * gdk_window_clear_area_e:
4126 * @window: a #GdkWindow
4127 * @x: x coordinate of rectangle to clear
4128 * @y: y coordinate of rectangle to clear
4129 * @width: width of rectangle to clear
4130 * @height: height of rectangle to clear
4132 * Like gdk_window_clear_area(), but also generates an expose event for
4135 * This function has a stupid name because it dates back to the mists
4136 * time, pre-GDK-1.0.
4140 gdk_window_clear_area_e (GdkWindow *window,
4146 gdk_window_clear_area_internal (window,
4153 gdk_window_draw_image (GdkDrawable *drawable,
4163 if (GDK_WINDOW_DESTROYED (drawable))
4167 gdk_draw_image (impl, gc, image, xsrc, ysrc,
4168 xdest - x_offset, ydest - y_offset,
4174 gdk_window_draw_pixbuf (GdkDrawable *drawable,
4183 GdkRgbDither dither,
4187 GdkWindowObject *private = (GdkWindowObject *)drawable;
4189 if (GDK_WINDOW_DESTROYED (drawable))
4192 /* If no gc => no user clipping, but we need clipping
4193 for window emulation, so use a scratch gc */
4195 gc = _gdk_drawable_get_scratch_gc (drawable, FALSE);
4198 if (private->paint_stack)
4199 gdk_draw_pixbuf (impl, gc, pixbuf, src_x, src_y,
4200 dest_x - x_offset, dest_y - y_offset,
4202 dither, x_dither - x_offset, y_dither - y_offset);
4204 gdk_draw_pixbuf (impl, gc, pixbuf, src_x, src_y,
4205 dest_x - x_offset, dest_y - y_offset,
4207 dither, x_dither, y_dither);
4212 gdk_window_draw_trapezoids (GdkDrawable *drawable,
4214 GdkTrapezoid *trapezoids,
4217 GdkTrapezoid *new_trapezoids = NULL;
4219 if (GDK_WINDOW_DESTROYED (drawable))
4224 if (x_offset != 0 || y_offset != 0)
4228 new_trapezoids = g_new (GdkTrapezoid, n_trapezoids);
4229 for (i=0; i < n_trapezoids; i++)
4231 new_trapezoids[i].y1 = trapezoids[i].y1 - y_offset;
4232 new_trapezoids[i].x11 = trapezoids[i].x11 - x_offset;
4233 new_trapezoids[i].x21 = trapezoids[i].x21 - x_offset;
4234 new_trapezoids[i].y2 = trapezoids[i].y2 - y_offset;
4235 new_trapezoids[i].x12 = trapezoids[i].x12 - x_offset;
4236 new_trapezoids[i].x22 = trapezoids[i].x22 - x_offset;
4239 trapezoids = new_trapezoids;
4242 gdk_draw_trapezoids (impl, gc, trapezoids, n_trapezoids);
4244 g_free (new_trapezoids);
4250 gdk_window_real_get_size (GdkDrawable *drawable,
4254 GdkWindowObject *private = (GdkWindowObject *)drawable;
4257 *width = private->width;
4259 *height = private->height;
4263 gdk_window_real_get_visual (GdkDrawable *drawable)
4265 GdkColormap *colormap;
4267 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4269 colormap = gdk_drawable_get_colormap (drawable);
4270 return colormap ? gdk_colormap_get_visual (colormap) : NULL;
4274 gdk_window_real_get_depth (GdkDrawable *drawable)
4276 g_return_val_if_fail (GDK_IS_WINDOW (drawable), 0);
4278 return ((GdkWindowObject *)GDK_WINDOW (drawable))->depth;
4282 gdk_window_real_get_screen (GdkDrawable *drawable)
4284 return gdk_drawable_get_screen (GDK_WINDOW_OBJECT (drawable)->impl);
4288 gdk_window_real_set_colormap (GdkDrawable *drawable,
4291 GdkWindowObject *private;
4293 g_return_if_fail (GDK_IS_WINDOW (drawable));
4295 if (GDK_WINDOW_DESTROYED (drawable))
4298 private = (GdkWindowObject *)drawable;
4300 /* different colormap than parent, requires native window */
4301 if (!private->input_only &&
4302 cmap != gdk_drawable_get_colormap ((GdkDrawable *)(private->parent)))
4303 gdk_window_ensure_native ((GdkWindow *)drawable);
4305 gdk_drawable_set_colormap (private->impl, cmap);
4309 gdk_window_real_get_colormap (GdkDrawable *drawable)
4311 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4313 if (GDK_WINDOW_DESTROYED (drawable))
4316 return gdk_drawable_get_colormap (((GdkWindowObject*)drawable)->impl);
4320 gdk_window_copy_to_image (GdkDrawable *drawable,
4329 GdkWindowObject *private = (GdkWindowObject *) drawable;
4330 gint x_offset, y_offset;
4332 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4334 if (GDK_WINDOW_DESTROYED (drawable))
4337 /* If we're here, a composite image was not necessary, so
4338 * we can ignore the paint stack.
4341 /* TODO: Is this right? */
4345 return gdk_drawable_copy_to_image (private->impl,
4354 gdk_window_cairo_surface_destroy (void *data)
4356 GdkWindowObject *private = (GdkWindowObject*) data;
4358 private->cairo_surface = NULL;
4361 static cairo_surface_t *
4362 gdk_window_create_cairo_surface (GdkDrawable *drawable,
4366 return _gdk_windowing_create_cairo_surface (GDK_WINDOW_OBJECT(drawable)->impl,
4371 static cairo_surface_t *
4372 gdk_window_ref_cairo_surface (GdkDrawable *drawable)
4374 GdkWindowObject *private = (GdkWindowObject*) drawable;
4375 cairo_surface_t *surface;
4377 if (private->paint_stack)
4379 GdkWindowPaint *paint = private->paint_stack->data;
4381 surface = paint->surface;
4382 cairo_surface_reference (surface);
4387 /* This will be drawing directly to the window, so flush implicit paint */
4388 gdk_window_flush ((GdkWindow *)drawable);
4390 if (!private->cairo_surface)
4393 GdkDrawable *source;
4395 /* It would be nice if we had some cairo support here so we
4396 could set the clip rect on the cairo surface */
4397 width = private->abs_x + private->width;
4398 height = private->abs_y + private->height;
4400 source = _gdk_drawable_get_source_drawable (drawable);
4402 /* TODO: Avoid the typecheck crap by adding virtual call */
4403 private->cairo_surface = _gdk_drawable_create_cairo_surface (source, width, height);
4405 if (private->cairo_surface)
4407 cairo_surface_set_device_offset (private->cairo_surface,
4411 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
4412 drawable, gdk_window_cairo_surface_destroy);
4416 cairo_surface_reference (private->cairo_surface);
4418 surface = private->cairo_surface;
4425 gdk_window_set_cairo_clip (GdkDrawable *drawable,
4428 GdkWindowObject *private = (GdkWindowObject*) drawable;
4430 if (!private->paint_stack)
4433 cairo_identity_matrix (cr);
4435 cairo_reset_clip (cr);
4437 cairo_new_path (cr);
4438 gdk_cairo_region (cr, private->clip_region_with_children);
4445 GdkWindowPaint *paint = private->paint_stack->data;
4447 /* Only needs to clip to region if piggybacking
4448 on an implicit paint pixmap */
4449 if (paint->uses_implicit)
4452 cairo_identity_matrix (cr);
4454 cairo_reset_clip (cr);
4456 cairo_new_path (cr);
4457 gdk_cairo_region (cr, paint->region);
4465 /* Code for dirty-region queueing
4467 static GSList *update_windows = NULL;
4468 static guint update_idle = 0;
4469 static gboolean debug_updates = FALSE;
4471 static inline gboolean
4472 gdk_window_is_ancestor (GdkWindow *window,
4473 GdkWindow *ancestor)
4477 GdkWindow *parent = (GdkWindow*) ((GdkWindowObject*) window)->parent;
4479 if (parent == ancestor)
4489 gdk_window_add_update_window (GdkWindow *window)
4492 GSList *prev = NULL;
4493 gboolean has_ancestor_in_list = FALSE;
4495 for (tmp = update_windows; tmp; tmp = tmp->next)
4497 GdkWindowObject *parent = GDK_WINDOW_OBJECT (window)->parent;
4499 /* check if tmp is an ancestor of "window"; if it is, set a
4500 * flag indicating that all following windows are either
4501 * children of "window" or from a differen hierarchy
4503 if (!has_ancestor_in_list && gdk_window_is_ancestor (window, tmp->data))
4504 has_ancestor_in_list = TRUE;
4506 /* insert in reverse stacking order when adding around siblings,
4507 * so processing updates properly paints over lower stacked windows
4509 if (parent == GDK_WINDOW_OBJECT (tmp->data)->parent)
4511 gint index = g_list_index (parent->children, window);
4512 for (; tmp && parent == GDK_WINDOW_OBJECT (tmp->data)->parent; tmp = tmp->next)
4514 gint sibling_index = g_list_index (parent->children, tmp->data);
4515 if (index > sibling_index)
4519 /* here, tmp got advanced past all lower stacked siblings */
4520 tmp = g_slist_prepend (tmp, window);
4524 update_windows = tmp;
4528 /* if "window" has an ancestor in the list and tmp is one of
4529 * "window's" children, insert "window" before tmp
4531 if (has_ancestor_in_list && gdk_window_is_ancestor (tmp->data, window))
4533 tmp = g_slist_prepend (tmp, window);
4538 update_windows = tmp;
4542 /* if we're at the end of the list and had an ancestor it it,
4543 * append to the list
4545 if (! tmp->next && has_ancestor_in_list)
4547 tmp = g_slist_append (tmp, window);
4554 /* if all above checks failed ("window" is from a different
4555 * hierarchy than what is already in the list) or the list is
4558 update_windows = g_slist_prepend (update_windows, window);
4562 gdk_window_remove_update_window (GdkWindow *window)
4564 update_windows = g_slist_remove (update_windows, window);
4568 gdk_window_update_idle (gpointer data)
4570 gdk_window_process_all_updates ();
4576 gdk_window_is_toplevel_frozen (GdkWindow *window)
4578 GdkWindowObject *toplevel;
4580 toplevel = (GdkWindowObject *)gdk_window_get_toplevel (window);
4582 return toplevel->update_and_descendants_freeze_count > 0;
4586 gdk_window_schedule_update (GdkWindow *window)
4589 (GDK_WINDOW_OBJECT (window)->update_freeze_count ||
4590 gdk_window_is_toplevel_frozen (window)))
4595 update_idle = gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
4596 gdk_window_update_idle, NULL, NULL);
4601 _gdk_window_process_updates_recurse (GdkWindow *window,
4602 GdkRegion *expose_region)
4604 GdkWindowObject *private = (GdkWindowObject *)window;
4605 GdkWindowObject *child;
4606 GdkRegion *child_region;
4610 if (gdk_region_empty (expose_region))
4613 /* Iterate over children, starting at topmost */
4614 for (l = private->children; l != NULL; l = l->next)
4618 if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
4621 /* Ignore offscreen children, as they don't draw in their parent and
4622 * don't take part in the clipping */
4623 if (gdk_window_is_offscreen (child))
4628 r.width = child->width;
4629 r.height = child->height;
4631 child_region = gdk_region_rectangle (&r);
4633 gdk_region_intersect (child_region, child->shape);
4635 if (child->impl == private->impl)
4637 /* Client side child, expose */
4638 gdk_region_intersect (child_region, expose_region);
4639 gdk_region_subtract (expose_region, child_region);
4640 gdk_region_offset (child_region, -child->x, -child->y);
4641 _gdk_window_process_updates_recurse ((GdkWindow *)child, child_region);
4645 /* Native child, just remove area from expose region */
4646 gdk_region_subtract (expose_region, child_region);
4648 gdk_region_destroy (child_region);
4651 if (!gdk_region_empty (expose_region))
4653 if (private->event_mask & GDK_EXPOSURE_MASK)
4657 event.expose.type = GDK_EXPOSE;
4658 event.expose.window = g_object_ref (window);
4659 event.expose.send_event = FALSE;
4660 event.expose.count = 0;
4661 event.expose.region = expose_region;
4662 gdk_region_get_clipbox (expose_region, &event.expose.area);
4664 (*_gdk_event_func) (&event, _gdk_event_data);
4666 g_object_unref (window);
4668 else if (private->bg_pixmap != GDK_NO_BG)
4670 /* No exposure mask set, so nothing will be drawn, the
4671 * app relies on the background being what it specified
4672 * for the window. So, we need to clear this manually.
4674 * We use begin/end_paint around the clear so that we can
4675 * piggyback on the implicit paint */
4677 gdk_window_begin_paint_region (window, expose_region);
4678 gdk_window_clear_region_internal (window, expose_region, FALSE);
4679 gdk_window_end_paint (window);
4685 gdk_window_process_updates_internal (GdkWindow *window)
4687 GdkWindowObject *private = (GdkWindowObject *)window;
4688 gboolean save_region = FALSE;
4689 GdkRectangle clip_box;
4691 /* If an update got queued during update processing, we can get a
4692 * window in the update queue that has an empty update_area.
4695 if (private->update_area)
4697 GdkRegion *update_area = private->update_area;
4698 private->update_area = NULL;
4700 if (_gdk_event_func && gdk_window_is_viewable (window) &&
4701 private->window_type != GDK_WINDOW_FOREIGN)
4703 GdkRectangle window_rect;
4704 GdkRegion *expose_region;
4705 GdkRegion *window_region;
4706 gboolean end_implicit;
4708 /* Clip to part visible in toplevel */
4709 gdk_region_intersect (update_area, private->clip_region);
4713 /* Make sure we see the red invalid area before redrawing. */
4714 gdk_display_sync (gdk_drawable_get_display (window));
4718 save_region = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->queue_antiexpose (window, update_area);
4720 expose_region = gdk_region_copy (update_area);
4722 expose_region = update_area;
4726 window_rect.width = private->width;
4727 window_rect.height = private->height;
4729 window_region = gdk_region_rectangle (&window_rect);
4730 gdk_region_intersect (expose_region,
4732 gdk_region_destroy (window_region);
4735 /* No need to do any moves that will end up over the update area */
4736 if (private->outstanding_moves)
4738 GdkWindowRegionMove *move;
4742 remove = gdk_region_copy (update_area);
4743 for (l = g_list_last (private->outstanding_moves); l != NULL; l = prev)
4747 /* Don't need this area */
4748 gdk_region_subtract (move->dest_region, remove);
4750 /* However if any of the destination we do need has a source
4751 in the updated region we do need that as a destination for
4752 the earlier moves */
4753 gdk_region_offset (move->dest_region, -move->dx, -move->dy);
4754 gdk_region_subtract (remove, move->dest_region);
4756 if (gdk_region_empty (move->dest_region))
4758 gdk_window_region_move_free (move);
4759 private->outstanding_moves =
4760 g_list_delete_link (private->outstanding_moves, l);
4763 gdk_region_offset (move->dest_region, move->dx, move->dy);
4765 gdk_region_destroy (remove);
4768 gdk_region_get_clipbox (expose_region, &clip_box);
4769 end_implicit = gdk_window_begin_implicit_paint (window, &clip_box);
4770 if (end_implicit) /* rendering is not double buffered, do moves now */
4771 gdk_window_flush_outstanding_moves (window);
4772 _gdk_windowing_window_process_updates_recurse (window, expose_region);
4775 /* Do moves right before exposes are rendered */
4776 gdk_window_flush_outstanding_moves (window);
4777 gdk_window_end_implicit_paint (window);
4780 if (expose_region != update_area)
4781 gdk_region_destroy (expose_region);
4784 gdk_region_destroy (update_area);
4787 if (private->outstanding_moves)
4789 /* Flush any outstanding moves, may happen if we moved a window but got
4790 no actual invalid area */
4791 gdk_window_flush_outstanding_moves (window);
4796 flush_all_displays (void)
4798 GSList *displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
4801 for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
4802 gdk_display_flush (tmp_list->data);
4804 g_slist_free (displays);
4807 /* Currently it is not possible to override
4808 * gdk_window_process_all_updates in the same manner as
4809 * gdk_window_process_updates and gdk_window_invalidate_maybe_recurse
4810 * by implementing the GdkPaintable interface. If in the future a
4811 * backend would need this, the right solution would be to add a
4812 * method to GdkDisplay that can be optionally
4813 * NULL. gdk_window_process_all_updates can then walk the list of open
4814 * displays and call the mehod.
4818 * gdk_window_process_all_updates:
4820 * Calls gdk_window_process_updates() for all windows (see #GdkWindow)
4821 * in the application.
4825 gdk_window_process_all_updates (void)
4827 GSList *old_update_windows = update_windows;
4828 GSList *tmp_list = update_windows;
4829 static gboolean in_process_all_updates = FALSE;
4831 if (in_process_all_updates)
4834 in_process_all_updates = TRUE;
4837 g_source_remove (update_idle);
4839 update_windows = NULL;
4842 _gdk_windowing_before_process_all_updates ();
4844 g_slist_foreach (old_update_windows, (GFunc)g_object_ref, NULL);
4848 GdkWindowObject *private = (GdkWindowObject *)tmp_list->data;
4850 if (!GDK_WINDOW_DESTROYED (tmp_list->data))
4852 if (private->update_freeze_count ||
4853 gdk_window_is_toplevel_frozen (tmp_list->data))
4854 gdk_window_add_update_window ((GdkWindow *) private);
4856 gdk_window_process_updates_internal (tmp_list->data);
4859 g_object_unref (tmp_list->data);
4860 tmp_list = tmp_list->next;
4863 g_slist_free (old_update_windows);
4865 flush_all_displays ();
4867 _gdk_windowing_after_process_all_updates ();
4869 in_process_all_updates = FALSE;
4873 * gdk_window_process_updates:
4874 * @window: a #GdkWindow
4875 * @update_children: whether to also process updates for child windows
4877 * Sends one or more expose events to @window. The areas in each
4878 * expose event will cover the entire update area for the window (see
4879 * gdk_window_invalidate_region() for details). Normally GDK calls
4880 * gdk_window_process_all_updates() on your behalf, so there's no
4881 * need to call this function unless you want to force expose events
4882 * to be delivered immediately and synchronously (vs. the usual
4883 * case, where GDK delivers them in an idle handler). Occasionally
4884 * this is useful to produce nicer scrolling behavior, for example.
4888 gdk_window_process_updates (GdkWindow *window,
4889 gboolean update_children)
4891 GdkWindowObject *private = (GdkWindowObject *)window;
4892 GdkWindowObject *impl_window;
4894 g_return_if_fail (GDK_IS_WINDOW (window));
4896 impl_window = gdk_window_get_impl_window (private);
4897 if ((impl_window->update_area ||
4898 impl_window->outstanding_moves) &&
4899 !impl_window->update_freeze_count &&
4900 !gdk_window_is_toplevel_frozen (window))
4902 gdk_window_process_updates_internal ((GdkWindow *)impl_window);
4903 gdk_window_remove_update_window ((GdkWindow *)impl_window);
4906 if (update_children)
4908 /* process updates in reverse stacking order so composition or
4909 * painting over achieves the desired effect for offscreen windows
4912 for (node = g_list_last (private->children); node; node = node->prev)
4913 gdk_window_process_updates (node->data, TRUE);
4918 * gdk_window_invalidate_rect:
4919 * @window: a #GdkWindow
4920 * @rect: rectangle to invalidate or %NULL to invalidate the whole
4922 * @invalidate_children: whether to also invalidate child windows
4924 * A convenience wrapper around gdk_window_invalidate_region() which
4925 * invalidates a rectangular region. See
4926 * gdk_window_invalidate_region() for details.
4929 gdk_window_invalidate_rect (GdkWindow *window,
4930 const GdkRectangle *rect,
4931 gboolean invalidate_children)
4933 GdkRectangle window_rect;
4935 GdkWindowObject *private = (GdkWindowObject *)window;
4937 g_return_if_fail (GDK_IS_WINDOW (window));
4939 if (GDK_WINDOW_DESTROYED (window))
4942 if (private->input_only || !GDK_WINDOW_IS_MAPPED (window))
4949 gdk_drawable_get_size (GDK_DRAWABLE (window),
4951 &window_rect.height);
4952 rect = &window_rect;
4955 region = gdk_region_rectangle (rect);
4956 gdk_window_invalidate_region (window, region, invalidate_children);
4957 gdk_region_destroy (region);
4961 draw_ugly_color (GdkWindow *window,
4962 const GdkRegion *region)
4964 /* Draw ugly color all over the newly-invalid region */
4965 GdkColor ugly_color = { 0, 50000, 10000, 10000 };
4967 GdkRectangle clipbox;
4969 ugly_gc = gdk_gc_new (window);
4970 gdk_gc_set_rgb_fg_color (ugly_gc, &ugly_color);
4971 gdk_gc_set_clip_region (ugly_gc, region);
4973 gdk_region_get_clipbox (region, &clipbox);
4975 gdk_draw_rectangle (window,
4978 clipbox.x, clipbox.y,
4979 clipbox.width, clipbox.height);
4981 g_object_unref (ugly_gc);
4985 * gdk_window_invalidate_maybe_recurse:
4986 * @window: a #GdkWindow
4987 * @region: a #GdkRegion
4988 * @child_func: function to use to decide if to recurse to a child,
4989 * %NULL means never recurse.
4990 * @user_data: data passed to @child_func
4992 * Adds @region to the update area for @window. The update area is the
4993 * region that needs to be redrawn, or "dirty region." The call
4994 * gdk_window_process_updates() sends one or more expose events to the
4995 * window, which together cover the entire update area. An
4996 * application would normally redraw the contents of @window in
4997 * response to those expose events.
4999 * GDK will call gdk_window_process_all_updates() on your behalf
5000 * whenever your program returns to the main loop and becomes idle, so
5001 * normally there's no need to do that manually, you just need to
5002 * invalidate regions that you know should be redrawn.
5004 * The @child_func parameter controls whether the region of
5005 * each child window that intersects @region will also be invalidated.
5006 * Only children for which @child_func returns TRUE will have the area
5010 gdk_window_invalidate_maybe_recurse (GdkWindow *window,
5011 const GdkRegion *region,
5012 gboolean (*child_func) (GdkWindow *,
5016 GdkWindowObject *private = (GdkWindowObject *)window;
5017 GdkWindowObject *impl_window;
5018 GdkRegion *visible_region;
5021 g_return_if_fail (GDK_IS_WINDOW (window));
5023 if (GDK_WINDOW_DESTROYED (window))
5026 if (private->input_only ||
5027 !GDK_WINDOW_IS_MAPPED (window) ||
5028 gdk_region_empty (region))
5031 visible_region = gdk_drawable_get_visible_region (window);
5032 gdk_region_intersect (visible_region, region);
5034 tmp_list = private->children;
5037 GdkWindowObject *child = tmp_list->data;
5039 if (!child->input_only)
5041 GdkRegion *child_region;
5042 GdkRectangle child_rect;
5044 child_rect.x = child->x;
5045 child_rect.y = child->y;
5046 child_rect.width = child->width;
5047 child_rect.height = child->height;
5048 child_region = gdk_region_rectangle (&child_rect);
5050 /* remove child area from the invalid area of the parent */
5051 if (GDK_WINDOW_IS_MAPPED (child) && !child->shaped &&
5052 !child->composited &&
5053 !gdk_window_is_offscreen (child))
5054 gdk_region_subtract (visible_region, child_region);
5056 if (child_func && (*child_func) ((GdkWindow *)child, user_data))
5058 GdkRegion *tmp = gdk_region_copy (region);
5060 gdk_region_offset (tmp, - child_rect.x, - child_rect.y);
5061 gdk_region_offset (child_region, - child_rect.x, - child_rect.y);
5062 gdk_region_intersect (child_region, tmp);
5064 gdk_window_invalidate_maybe_recurse ((GdkWindow *)child,
5065 child_region, child_func, user_data);
5067 gdk_region_destroy (tmp);
5070 gdk_region_destroy (child_region);
5073 tmp_list = tmp_list->next;
5076 impl_window = gdk_window_get_impl_window (private);
5078 if (!gdk_region_empty (visible_region) ||
5079 /* Even if we're not exposing anything, make sure we process
5080 idles for windows with outstanding moves */
5081 (impl_window->outstanding_moves != NULL &&
5082 impl_window->update_area == NULL))
5085 draw_ugly_color (window, region);
5087 /* Convert to impl coords */
5088 gdk_region_offset (visible_region, private->abs_x, private->abs_y);
5089 if (impl_window->update_area)
5091 gdk_region_union (impl_window->update_area, visible_region);
5095 gdk_window_add_update_window ((GdkWindow *)impl_window);
5096 impl_window->update_area = gdk_region_copy (visible_region);
5098 gdk_window_schedule_update ((GdkWindow *)impl_window);
5102 gdk_region_destroy (visible_region);
5106 true_predicate (GdkWindow *window,
5113 * gdk_window_invalidate_region:
5114 * @window: a #GdkWindow
5115 * @region: a #GdkRegion
5116 * @invalidate_children: %TRUE to also invalidate child windows
5118 * Adds @region to the update area for @window. The update area is the
5119 * region that needs to be redrawn, or "dirty region." The call
5120 * gdk_window_process_updates() sends one or more expose events to the
5121 * window, which together cover the entire update area. An
5122 * application would normally redraw the contents of @window in
5123 * response to those expose events.
5125 * GDK will call gdk_window_process_all_updates() on your behalf
5126 * whenever your program returns to the main loop and becomes idle, so
5127 * normally there's no need to do that manually, you just need to
5128 * invalidate regions that you know should be redrawn.
5130 * The @invalidate_children parameter controls whether the region of
5131 * each child window that intersects @region will also be invalidated.
5132 * If %FALSE, then the update area for child windows will remain
5133 * unaffected. See gdk_window_invalidate_maybe_recurse if you need
5134 * fine grained control over which children are invalidated.
5137 gdk_window_invalidate_region (GdkWindow *window,
5138 const GdkRegion *region,
5139 gboolean invalidate_children)
5141 gdk_window_invalidate_maybe_recurse (window, region,
5142 invalidate_children ?
5143 true_predicate : (gboolean (*) (GdkWindow *, gpointer))NULL,
5148 * _gdk_window_invalidate_for_expose:
5149 * @window: a #GdkWindow
5150 * @region: a #GdkRegion
5152 * Adds @region to the update area for @window. The update area is the
5153 * region that needs to be redrawn, or "dirty region." The call
5154 * gdk_window_process_updates() sends one or more expose events to the
5155 * window, which together cover the entire update area. An
5156 * application would normally redraw the contents of @window in
5157 * response to those expose events.
5159 * GDK will call gdk_window_process_all_updates() on your behalf
5160 * whenever your program returns to the main loop and becomes idle, so
5161 * normally there's no need to do that manually, you just need to
5162 * invalidate regions that you know should be redrawn.
5164 * This version of invalidation is used when you recieve expose events
5165 * from the native window system. It exposes the native window, plus
5166 * any non-native child windows (but not native child windows, as those would
5167 * have gotten their own expose events).
5170 _gdk_window_invalidate_for_expose (GdkWindow *window,
5171 const GdkRegion *region)
5173 gdk_window_invalidate_maybe_recurse (window, region,
5174 (gboolean (*) (GdkWindow *, gpointer))gdk_window_has_no_impl,
5180 * gdk_window_get_update_area:
5181 * @window: a #GdkWindow
5183 * Transfers ownership of the update area from @window to the caller
5184 * of the function. That is, after calling this function, @window will
5185 * no longer have an invalid/dirty region; the update area is removed
5186 * from @window and handed to you. If a window has no update area,
5187 * gdk_window_get_update_area() returns %NULL. You are responsible for
5188 * calling gdk_region_destroy() on the returned region if it's non-%NULL.
5190 * Return value: the update area for @window
5193 gdk_window_get_update_area (GdkWindow *window)
5195 GdkWindowObject *private = (GdkWindowObject *)window;
5196 GdkWindowObject *impl_window;
5197 GdkRegion *tmp_region;
5199 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
5201 impl_window = gdk_window_get_impl_window (private);
5203 if (impl_window->update_area)
5205 tmp_region = gdk_region_copy (private->clip_region_with_children);
5206 /* Convert to impl coords */
5207 gdk_region_offset (tmp_region, private->abs_x, private->abs_y);
5208 gdk_region_intersect (tmp_region, impl_window->update_area);
5210 if (gdk_region_empty (tmp_region))
5212 gdk_region_destroy (tmp_region);
5217 gdk_region_subtract (impl_window->update_area, tmp_region);
5219 if (gdk_region_empty (impl_window->update_area) &&
5220 impl_window->outstanding_moves == NULL)
5222 gdk_region_destroy (impl_window->update_area);
5223 impl_window->update_area = NULL;
5225 gdk_window_remove_update_window ((GdkWindow *)impl_window);
5228 /* Convert from impl coords */
5229 gdk_region_offset (tmp_region, -private->abs_x, -private->abs_y);
5239 * _gdk_window_clear_update_area:
5240 * @window: a #GdkWindow.
5242 * Internal function to clear the update area for a window. This
5243 * is called when the window is hidden or destroyed.
5246 _gdk_window_clear_update_area (GdkWindow *window)
5248 GdkWindowObject *private = (GdkWindowObject *)window;
5250 g_return_if_fail (GDK_IS_WINDOW (window));
5252 if (private->update_area)
5254 gdk_window_remove_update_window (window);
5256 gdk_region_destroy (private->update_area);
5257 private->update_area = NULL;
5262 * gdk_window_freeze_updates:
5263 * @window: a #GdkWindow
5265 * Temporarily freezes a window such that it won't receive expose
5266 * events. The window will begin receiving expose events again when
5267 * gdk_window_thaw_updates() is called. If gdk_window_freeze_updates()
5268 * has been called more than once, gdk_window_thaw_updates() must be called
5269 * an equal number of times to begin processing exposes.
5272 gdk_window_freeze_updates (GdkWindow *window)
5274 GdkWindowObject *private = (GdkWindowObject *)window;
5275 GdkWindowObject *impl_window;
5277 g_return_if_fail (GDK_IS_WINDOW (window));
5279 impl_window = gdk_window_get_impl_window (private);
5280 impl_window->update_freeze_count++;
5284 * gdk_window_thaw_updates:
5285 * @window: a #GdkWindow
5287 * Thaws a window frozen with gdk_window_freeze_updates().
5290 gdk_window_thaw_updates (GdkWindow *window)
5292 GdkWindowObject *private = (GdkWindowObject *)window;
5293 GdkWindowObject *impl_window;
5295 g_return_if_fail (GDK_IS_WINDOW (window));
5297 impl_window = gdk_window_get_impl_window (private);
5299 g_return_if_fail (impl_window->update_freeze_count > 0);
5301 if (--impl_window->update_freeze_count == 0)
5302 gdk_window_schedule_update (GDK_WINDOW (impl_window));
5306 * gdk_window_freeze_toplevel_updates_libgtk_only:
5307 * @window: a #GdkWindow
5309 * Temporarily freezes a window and all its descendants such that it won't
5310 * receive expose events. The window will begin receiving expose events
5311 * again when gdk_window_thaw_toplevel_updates_libgtk_only() is called. If
5312 * gdk_window_freeze_toplevel_updates_libgtk_only()
5313 * has been called more than once,
5314 * gdk_window_thaw_toplevel_updates_libgtk_only() must be called
5315 * an equal number of times to begin processing exposes.
5317 * This function is not part of the GDK public API and is only
5321 gdk_window_freeze_toplevel_updates_libgtk_only (GdkWindow *window)
5323 GdkWindowObject *private = (GdkWindowObject *)window;
5325 g_return_if_fail (GDK_IS_WINDOW (window));
5326 g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
5328 private->update_and_descendants_freeze_count++;
5332 * gdk_window_thaw_toplevel_updates_libgtk_only:
5333 * @window: a #GdkWindow
5335 * Thaws a window frozen with
5336 * gdk_window_freeze_toplevel_updates_libgtk_only().
5338 * This function is not part of the GDK public API and is only
5342 gdk_window_thaw_toplevel_updates_libgtk_only (GdkWindow *window)
5344 GdkWindowObject *private = (GdkWindowObject *)window;
5346 g_return_if_fail (GDK_IS_WINDOW (window));
5347 g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
5348 g_return_if_fail (private->update_and_descendants_freeze_count > 0);
5350 private->update_and_descendants_freeze_count--;
5352 gdk_window_schedule_update (window);
5356 * gdk_window_set_debug_updates:
5357 * @setting: %TRUE to turn on update debugging
5359 * With update debugging enabled, calls to
5360 * gdk_window_invalidate_region() clear the invalidated region of the
5361 * screen to a noticeable color, and GDK pauses for a short time
5362 * before sending exposes to windows during
5363 * gdk_window_process_updates(). The net effect is that you can see
5364 * the invalid region for each window and watch redraws as they
5365 * occur. This allows you to diagnose inefficiencies in your application.
5367 * In essence, because the GDK rendering model prevents all flicker,
5368 * if you are redrawing the same region 400 times you may never
5369 * notice, aside from noticing a speed problem. Enabling update
5370 * debugging causes GTK to flicker slowly and noticeably, so you can
5371 * see exactly what's being redrawn when, in what order.
5373 * The --gtk-debug=updates command line option passed to GTK+ programs
5374 * enables this debug option at application startup time. That's
5375 * usually more useful than calling gdk_window_set_debug_updates()
5376 * yourself, though you might want to use this function to enable
5377 * updates sometime after application startup time.
5381 gdk_window_set_debug_updates (gboolean setting)
5383 debug_updates = setting;
5387 * gdk_window_constrain_size:
5388 * @geometry: a #GdkGeometry structure
5389 * @flags: a mask indicating what portions of @geometry are set
5390 * @width: desired width of window
5391 * @height: desired height of the window
5392 * @new_width: location to store resulting width
5393 * @new_height: location to store resulting height
5395 * Constrains a desired width and height according to a
5396 * set of geometry hints (such as minimum and maximum size).
5399 gdk_window_constrain_size (GdkGeometry *geometry,
5406 /* This routine is partially borrowed from fvwm.
5408 * Copyright 1993, Robert Nation
5409 * You may use this code for any purpose, as long as the original
5410 * copyright remains in the source code and all documentation
5412 * which in turn borrows parts of the algorithm from uwm
5415 gint min_height = 0;
5416 gint base_width = 0;
5417 gint base_height = 0;
5420 gint max_width = G_MAXINT;
5421 gint max_height = G_MAXINT;
5423 #define FLOOR(value, base) ( ((gint) ((value) / (base))) * (base) )
5425 if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
5427 base_width = geometry->base_width;
5428 base_height = geometry->base_height;
5429 min_width = geometry->min_width;
5430 min_height = geometry->min_height;
5432 else if (flags & GDK_HINT_BASE_SIZE)
5434 base_width = geometry->base_width;
5435 base_height = geometry->base_height;
5436 min_width = geometry->base_width;
5437 min_height = geometry->base_height;
5439 else if (flags & GDK_HINT_MIN_SIZE)
5441 base_width = geometry->min_width;
5442 base_height = geometry->min_height;
5443 min_width = geometry->min_width;
5444 min_height = geometry->min_height;
5447 if (flags & GDK_HINT_MAX_SIZE)
5449 max_width = geometry->max_width ;
5450 max_height = geometry->max_height;
5453 if (flags & GDK_HINT_RESIZE_INC)
5455 xinc = MAX (xinc, geometry->width_inc);
5456 yinc = MAX (yinc, geometry->height_inc);
5459 /* clamp width and height to min and max values
5461 width = CLAMP (width, min_width, max_width);
5462 height = CLAMP (height, min_height, max_height);
5464 /* shrink to base + N * inc
5466 width = base_width + FLOOR (width - base_width, xinc);
5467 height = base_height + FLOOR (height - base_height, yinc);
5469 /* constrain aspect ratio, according to:
5472 * min_aspect <= -------- <= max_aspect
5476 if (flags & GDK_HINT_ASPECT &&
5477 geometry->min_aspect > 0 &&
5478 geometry->max_aspect > 0)
5482 if (geometry->min_aspect * height > width)
5484 delta = FLOOR (height - width / geometry->min_aspect, yinc);
5485 if (height - delta >= min_height)
5489 delta = FLOOR (height * geometry->min_aspect - width, xinc);
5490 if (width + delta <= max_width)
5495 if (geometry->max_aspect * height < width)
5497 delta = FLOOR (width - height * geometry->max_aspect, xinc);
5498 if (width - delta >= min_width)
5502 delta = FLOOR (width / geometry->max_aspect - height, yinc);
5503 if (height + delta <= max_height)
5512 *new_height = height;
5516 * gdk_window_get_pointer:
5517 * @window: a #GdkWindow
5518 * @x: return location for X coordinate of pointer or %NULL to not
5519 * return the X coordinate
5520 * @y: return location for Y coordinate of pointer or %NULL to not
5521 * return the Y coordinate
5522 * @mask: return location for modifier mask or %NULL to not return the
5525 * Obtains the current pointer position and modifier state.
5526 * The position is given in coordinates relative to the upper left
5527 * corner of @window.
5529 * Return value: the window containing the pointer (as with
5530 * gdk_window_at_pointer()), or %NULL if the window containing the
5531 * pointer isn't known to GDK
5534 gdk_window_get_pointer (GdkWindow *window,
5537 GdkModifierType *mask)
5539 GdkDisplay *display;
5541 GdkModifierType tmp_mask;
5544 g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
5548 display = gdk_drawable_get_display (window);
5552 GdkScreen *screen = gdk_screen_get_default ();
5554 display = gdk_screen_get_display (screen);
5555 window = gdk_screen_get_root_window (screen);
5557 GDK_NOTE (MULTIHEAD,
5558 g_message ("Passing NULL for window to gdk_window_get_pointer()\n"
5559 "is not multihead safe"));
5562 child = display->pointer_hooks->window_get_pointer (display, window, &tmp_x, &tmp_y, &tmp_mask);
5571 _gdk_display_enable_motion_hints (display);
5577 * gdk_window_at_pointer:
5578 * @win_x: return location for origin of the window under the pointer
5579 * @win_y: return location for origin of the window under the pointer
5581 * Obtains the window underneath the mouse pointer, returning the
5582 * location of that window in @win_x, @win_y. Returns %NULL if the
5583 * window under the mouse pointer is not known to GDK (if the window
5584 * belongs to another application and a #GdkWindow hasn't been created
5585 * for it with gdk_window_foreign_new())
5587 * NOTE: For multihead-aware widgets or applications use
5588 * gdk_display_get_window_at_pointer() instead.
5590 * Return value: window under the mouse pointer
5593 gdk_window_at_pointer (gint *win_x,
5596 return gdk_display_get_window_at_pointer (gdk_display_get_default (), win_x, win_y);
5600 * gdk_get_default_root_window:
5602 * Obtains the root window (parent all other windows are inside)
5603 * for the default display and screen.
5605 * Return value: the default root window
5608 gdk_get_default_root_window (void)
5610 return gdk_screen_get_root_window (gdk_screen_get_default ());
5614 * gdk_window_foreign_new:
5615 * @anid: a native window handle.
5617 * Wraps a native window for the default display in a #GdkWindow.
5618 * This may fail if the window has been destroyed.
5620 * For example in the X backend, a native window handle is an Xlib
5623 * Return value: the newly-created #GdkWindow wrapper for the
5624 * native window or %NULL if the window has been destroyed.
5627 gdk_window_foreign_new (GdkNativeWindow anid)
5629 return gdk_window_foreign_new_for_display (gdk_display_get_default (), anid);
5633 get_all_native_children (GdkWindowObject *private,
5636 GdkWindowObject *child;
5639 for (l = private->children; l != NULL; l = l->next)
5643 if (gdk_window_has_impl (child))
5644 *native = g_list_prepend (*native, child);
5646 get_all_native_children (child, native);
5652 gdk_window_raise_internal (GdkWindow *window)
5654 GdkWindowObject *private = (GdkWindowObject *)window;
5655 GdkWindowObject *parent = private->parent;
5656 GdkWindowObject *above;
5657 GList *native_children;
5662 parent->children = g_list_remove (parent->children, window);
5663 parent->children = g_list_prepend (parent->children, window);
5666 /* Just do native raise for toplevels */
5667 if (private->parent == NULL ||
5668 GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
5670 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
5672 else if (gdk_window_has_impl (private))
5674 above = find_native_sibling_above (parent, private);
5677 listhead.data = window;
5678 listhead.next = NULL;
5679 listhead.prev = NULL;
5680 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
5684 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
5688 native_children = NULL;
5689 get_all_native_children (private, &native_children);
5690 if (native_children != NULL)
5692 above = find_native_sibling_above (parent, private);
5695 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
5699 /* Right order, since native_children is bottom-topmost first */
5700 for (l = native_children; l != NULL; l = l->next)
5701 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (l->data);
5704 g_list_free (native_children);
5710 /* Showing a non-native parent may cause children to become visible,
5711 we need to handle this by manually showing them then. To simplify
5712 things we hide them all when they are not visible. */
5714 show_all_visible_impls (GdkWindowObject *private, gboolean already_mapped)
5716 GdkWindowObject *child;
5719 for (l = private->children; l != NULL; l = l->next)
5723 /* For foreign windows, only show if if was
5724 explicitly hidden, otherwise we might cause
5725 suprising things to happen to the other client. */
5726 if (GDK_WINDOW_IS_MAPPED (child) &&
5727 GDK_WINDOW_TYPE (child) != GDK_WINDOW_FOREIGN)
5728 show_all_visible_impls (child, FALSE);
5731 if (gdk_window_has_impl (private))
5732 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show ((GdkWindow *)private, already_mapped);
5736 gdk_window_show_internal (GdkWindow *window, gboolean raise)
5738 GdkWindowObject *private;
5739 gboolean was_mapped;
5741 g_return_if_fail (GDK_IS_WINDOW (window));
5743 private = (GdkWindowObject *) window;
5744 if (private->destroyed)
5747 was_mapped = GDK_WINDOW_IS_MAPPED (window);
5750 /* Keep children in (reverse) stacking order */
5751 gdk_window_raise_internal (window);
5753 if (gdk_window_has_impl (private))
5756 gdk_synthesize_window_state (window,
5757 GDK_WINDOW_STATE_WITHDRAWN,
5765 if (gdk_window_is_viewable (window))
5766 show_all_visible_impls (private, was_mapped);
5770 if (private->event_mask & GDK_STRUCTURE_MASK)
5771 _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
5773 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
5774 _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
5777 if (!was_mapped || raise)
5779 recompute_visible_regions (private, TRUE, FALSE);
5781 /* If any decendants became visible we need to send visibility notify */
5782 gdk_window_update_visibility_recursively (private, NULL);
5784 if (gdk_window_is_viewable (window))
5786 _gdk_synthesize_crossing_events_for_geometry_change (window);
5787 gdk_window_invalidate_rect (window, NULL, TRUE);
5793 * gdk_window_show_unraised:
5794 * @window: a #GdkWindow
5796 * Shows a #GdkWindow onscreen, but does not modify its stacking
5797 * order. In contrast, gdk_window_show() will raise the window
5798 * to the top of the window stack.
5800 * On the X11 platform, in Xlib terms, this function calls
5801 * XMapWindow() (it also updates some internal GDK state, which means
5802 * that you can't really use XMapWindow() directly on a GDK window).
5805 gdk_window_show_unraised (GdkWindow *window)
5807 gdk_window_show_internal (window, FALSE);
5812 * @window: a #GdkWindow
5814 * Raises @window to the top of the Z-order (stacking order), so that
5815 * other windows with the same parent window appear below @window.
5816 * This is true whether or not the windows are visible.
5818 * If @window is a toplevel, the window manager may choose to deny the
5819 * request to move the window in the Z-order, gdk_window_raise() only
5820 * requests the restack, does not guarantee it.
5823 gdk_window_raise (GdkWindow *window)
5825 GdkWindowObject *private;
5827 g_return_if_fail (GDK_IS_WINDOW (window));
5829 private = (GdkWindowObject *) window;
5830 if (private->destroyed)
5833 /* Keep children in (reverse) stacking order */
5834 gdk_window_raise_internal (window);
5836 recompute_visible_regions (private, TRUE, FALSE);
5838 gdk_window_invalidate_rect (window, NULL, TRUE);
5842 gdk_window_lower_internal (GdkWindow *window)
5844 GdkWindowObject *private = (GdkWindowObject *)window;
5845 GdkWindowObject *parent = private->parent;
5846 GdkWindowObject *above;
5847 GList *native_children;
5852 parent->children = g_list_remove (parent->children, window);
5853 parent->children = g_list_append (parent->children, window);
5856 /* Just do native lower for toplevels */
5857 if (private->parent == NULL ||
5858 GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
5860 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->lower (window);
5862 else if (gdk_window_has_impl (private))
5864 above = find_native_sibling_above (parent, private);
5867 listhead.data = window;
5868 listhead.next = NULL;
5869 listhead.prev = NULL;
5870 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
5874 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
5878 native_children = NULL;
5879 get_all_native_children (private, &native_children);
5880 if (native_children != NULL)
5882 above = find_native_sibling_above (parent, private);
5885 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
5889 /* Right order, since native_children is bottom-topmost first */
5890 for (l = native_children; l != NULL; l = l->next)
5891 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (l->data);
5894 g_list_free (native_children);
5901 gdk_window_invalidate_in_parent (GdkWindowObject *private)
5903 GdkRectangle r, child;
5905 if (private->parent == NULL ||
5906 GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
5909 /* get the visible rectangle of the parent */
5911 r.width = private->parent->width;
5912 r.height = private->parent->height;
5914 child.x = private->x;
5915 child.y = private->y;
5916 child.width = private->width;
5917 child.height = private->height;
5918 gdk_rectangle_intersect (&r, &child, &r);
5920 gdk_window_invalidate_rect (GDK_WINDOW (private->parent), &r, TRUE);
5926 * @window: a #GdkWindow
5928 * Lowers @window to the bottom of the Z-order (stacking order), so that
5929 * other windows with the same parent window appear above @window.
5930 * This is true whether or not the other windows are visible.
5932 * If @window is a toplevel, the window manager may choose to deny the
5933 * request to move the window in the Z-order, gdk_window_lower() only
5934 * requests the restack, does not guarantee it.
5936 * Note that gdk_window_show() raises the window again, so don't call this
5937 * function before gdk_window_show(). (Try gdk_window_show_unraised().)
5940 gdk_window_lower (GdkWindow *window)
5942 GdkWindowObject *private;
5944 g_return_if_fail (GDK_IS_WINDOW (window));
5946 private = (GdkWindowObject *) window;
5947 if (private->destroyed)
5950 /* Keep children in (reverse) stacking order */
5951 gdk_window_lower_internal (window);
5953 recompute_visible_regions (private, TRUE, FALSE);
5955 _gdk_synthesize_crossing_events_for_geometry_change (window);
5956 gdk_window_invalidate_in_parent (private);
5961 * @window: a #GdkWindow
5963 * Like gdk_window_show_unraised(), but also raises the window to the
5964 * top of the window stack (moves the window to the front of the
5967 * This function maps a window so it's visible onscreen. Its opposite
5968 * is gdk_window_hide().
5970 * When implementing a #GtkWidget, you should call this function on the widget's
5971 * #GdkWindow as part of the "map" method.
5974 gdk_window_show (GdkWindow *window)
5976 gdk_window_show_internal (window, TRUE);
5979 /* Hiding a non-native parent may cause parents to become non-visible,
5980 even if their parent native window is visible. We need to handle this
5981 by manually hiding them then. To simplify things we hide them all
5982 when they are not visible. */
5984 hide_all_visible_impls (GdkWindowObject *private)
5986 GdkWindowObject *child;
5989 for (l = private->children; l != NULL; l = l->next)
5993 /* For foreign windows, only hide if if was
5994 explicitly hidden, otherwise we might cause
5995 suprising things to happen to the other client. */
5996 if (GDK_WINDOW_IS_MAPPED (child) &&
5997 GDK_WINDOW_TYPE (child) != GDK_WINDOW_FOREIGN)
5998 hide_all_visible_impls (child);
6001 if (gdk_window_has_impl (private))
6002 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->hide ((GdkWindow *)private);
6008 * @window: a #GdkWindow
6010 * For toplevel windows, withdraws them, so they will no longer be
6011 * known to the window manager; for all windows, unmaps them, so
6012 * they won't be displayed. Normally done automatically as
6013 * part of gtk_widget_hide().
6016 gdk_window_hide (GdkWindow *window)
6018 GdkWindowObject *private;
6019 gboolean was_mapped, was_viewable;
6021 g_return_if_fail (GDK_IS_WINDOW (window));
6023 private = (GdkWindowObject *) window;
6024 if (private->destroyed)
6027 was_mapped = GDK_WINDOW_IS_MAPPED (private);
6028 was_viewable = gdk_window_is_viewable (window);
6030 if (gdk_window_has_impl (private))
6033 if (GDK_WINDOW_IS_MAPPED (window))
6034 gdk_synthesize_window_state (window,
6036 GDK_WINDOW_STATE_WITHDRAWN);
6038 else if (was_mapped)
6040 GdkDisplay *display;
6042 /* May need to break grabs on children */
6043 display = gdk_drawable_get_display (window);
6045 if (_gdk_display_end_pointer_grab (display,
6046 _gdk_windowing_window_get_next_serial (display),
6049 gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
6051 if (display->keyboard_grab.window != NULL)
6053 if (is_parent_of (window, display->keyboard_grab.window))
6055 /* Call this ourselves, even though gdk_display_keyboard_ungrab
6056 does so too, since we want to pass implicit == TRUE so the
6057 broken grab event is generated */
6058 _gdk_display_unset_has_keyboard_grab (display,
6060 gdk_display_keyboard_ungrab (display, GDK_CURRENT_TIME);
6064 private->state = GDK_WINDOW_STATE_WITHDRAWN;
6068 hide_all_visible_impls (private);
6070 recompute_visible_regions (private, TRUE, FALSE);
6072 /* all decendants became non-visible, we need to send visibility notify */
6073 gdk_window_update_visibility_recursively (private, NULL);
6077 if (private->event_mask & GDK_STRUCTURE_MASK)
6078 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6080 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
6081 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6083 _gdk_synthesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
6086 /* Invalidate the rect */
6087 gdk_window_invalidate_in_parent (private);
6091 * gdk_window_withdraw:
6092 * @window: a toplevel #GdkWindow
6094 * Withdraws a window (unmaps it and asks the window manager to forget about it).
6095 * This function is not really useful as gdk_window_hide() automatically
6096 * withdraws toplevel windows before hiding them.
6099 gdk_window_withdraw (GdkWindow *window)
6101 GdkWindowObject *private;
6102 gboolean was_mapped;
6104 g_return_if_fail (GDK_IS_WINDOW (window));
6106 private = (GdkWindowObject *) window;
6107 if (private->destroyed)
6110 was_mapped = GDK_WINDOW_IS_MAPPED (private);
6112 if (gdk_window_has_impl (private))
6114 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->withdraw (window);
6118 if (private->event_mask & GDK_STRUCTURE_MASK)
6119 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6121 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
6122 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6124 _gdk_synthesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
6127 recompute_visible_regions (private, TRUE, FALSE);
6132 * gdk_window_set_events:
6133 * @window: a #GdkWindow
6134 * @event_mask: event mask for @window
6136 * The event mask for a window determines which events will be reported
6137 * for that window. For example, an event mask including #GDK_BUTTON_PRESS_MASK
6138 * means the window should report button press events. The event mask
6139 * is the bitwise OR of values from the #GdkEventMask enumeration.
6142 gdk_window_set_events (GdkWindow *window,
6143 GdkEventMask event_mask)
6145 GdkWindowObject *private;
6146 GdkDisplay *display;
6149 g_return_if_fail (GDK_IS_WINDOW (window));
6151 private = (GdkWindowObject *) window;
6152 if (private->destroyed)
6155 /* If motion hint is disabled, enable motion events again */
6156 display = gdk_drawable_get_display (window);
6157 if ((private->event_mask & GDK_POINTER_MOTION_HINT_MASK) &&
6158 !(event_mask & GDK_POINTER_MOTION_HINT_MASK))
6159 _gdk_display_enable_motion_hints (display);
6161 private->event_mask = event_mask;
6163 if (gdk_window_has_impl (private))
6164 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_events (window,
6165 get_native_event_mask (private));
6170 * gdk_window_get_events:
6171 * @window: a #GdkWindow
6173 * Gets the event mask for @window. See gdk_window_set_events().
6175 * Return value: event mask for @window
6178 gdk_window_get_events (GdkWindow *window)
6180 GdkWindowObject *private;
6182 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
6184 private = (GdkWindowObject *) window;
6185 if (private->destroyed)
6188 return private->event_mask;
6192 gdk_window_move_resize_toplevel (GdkWindow *window,
6199 GdkWindowObject *private;
6200 GdkRegion *old_region, *new_region;
6201 GdkWindowObject *impl_window;
6203 int old_x, old_y, old_abs_x, old_abs_y;
6207 private = (GdkWindowObject *) window;
6212 impl_window = gdk_window_get_impl_window (private);
6217 is_resize = (width != -1) || (height != -1);
6219 if (GDK_WINDOW_IS_MAPPED (window) &&
6220 !private->input_only)
6223 old_region = gdk_region_copy (private->clip_region);
6226 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, with_move, x, y, width, height);
6228 dx = private->x - old_x;
6229 dy = private->y - old_y;
6231 old_abs_x = private->abs_x;
6232 old_abs_y = private->abs_y;
6234 /* Avoid recomputing for pure toplevel moves, for performance reasons */
6236 recompute_visible_regions (private, TRUE, FALSE);
6240 new_region = gdk_region_copy (private->clip_region);
6242 /* This is the newly exposed area (due to any resize),
6243 * X will expose it, but lets do that without the
6246 gdk_region_subtract (new_region, old_region);
6247 gdk_window_invalidate_region (window, new_region, TRUE);
6249 gdk_region_destroy (old_region);
6250 gdk_region_destroy (new_region);
6253 _gdk_synthesize_crossing_events_for_geometry_change (window);
6258 move_native_children (GdkWindowObject *private)
6261 GdkWindowObject *child;
6263 for (l = private->children; l; l = l->next)
6267 if (child->impl != private->impl)
6268 GDK_WINDOW_IMPL_GET_IFACE (child->impl)->move_resize ((GdkWindow *)child, TRUE, child->x, child->y, child->width, child->height);
6270 move_native_children (child);
6275 collect_native_child_region_helper (GdkWindowObject *window,
6281 GdkWindowObject *child;
6285 for (l = window->children; l != NULL; l = l->next)
6289 if (child->impl != impl)
6291 tmp = gdk_region_copy (child->clip_region);
6292 gdk_region_offset (tmp,
6293 x_offset + child->x,
6294 y_offset + child->y);
6295 if (*region == NULL)
6299 gdk_region_union (*region, tmp);
6300 gdk_region_destroy (tmp);
6304 collect_native_child_region_helper (child, impl, region,
6305 x_offset + child->x,
6306 y_offset + child->y);
6313 collect_native_child_region (GdkWindowObject *window,
6314 gboolean include_this)
6318 if (include_this && gdk_window_has_impl (window))
6319 return gdk_region_copy (window->clip_region);
6323 collect_native_child_region_helper (window, window->impl, ®ion, 0, 0);
6330 gdk_window_move_resize_internal (GdkWindow *window,
6337 GdkWindowObject *private;
6338 GdkRegion *old_region, *new_region, *copy_area;
6339 GdkRegion *old_native_child_region, *new_native_child_region;
6340 GdkWindowObject *impl_window;
6342 int old_x, old_y, old_abs_x, old_abs_y;
6345 g_return_if_fail (GDK_IS_WINDOW (window));
6347 private = (GdkWindowObject *) window;
6348 if (private->destroyed)
6351 if (private->parent == NULL ||
6352 GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
6354 gdk_window_move_resize_toplevel (window, with_move, x, y, width, height);
6358 /* Handle child windows */
6363 impl_window = gdk_window_get_impl_window (private);
6368 if (GDK_WINDOW_IS_MAPPED (window) &&
6369 !private->input_only)
6373 old_region = gdk_region_copy (private->clip_region);
6374 /* Adjust region to parent window coords */
6375 gdk_region_offset (old_region, private->x, private->y);
6378 old_native_child_region = collect_native_child_region (private, TRUE);
6379 if (old_native_child_region)
6381 /* Adjust region to parent window coords */
6382 gdk_region_offset (old_native_child_region, private->x, private->y);
6384 /* Any native window move will immediately copy stuff to the destination, which may overwrite a
6385 * source or destination for a delayed GdkWindowRegionMove. So, we need
6386 * to flush those here for the parent window and all overlapped subwindows
6387 * of it. And we need to do this before setting the new clips as those will be
6390 gdk_window_flush_recursive (private->parent);
6393 /* Set the new position and size */
6399 if (!(width < 0 && height < 0))
6403 private->width = width;
6406 private->height = height;
6409 dx = private->x - old_x;
6410 dy = private->y - old_y;
6412 old_abs_x = private->abs_x;
6413 old_abs_y = private->abs_y;
6415 recompute_visible_regions (private, TRUE, FALSE);
6417 new_native_child_region = NULL;
6418 if (old_native_child_region)
6420 new_native_child_region = collect_native_child_region (private, TRUE);
6421 /* Adjust region to parent window coords */
6422 gdk_region_offset (new_native_child_region, private->x, private->y);
6425 if (gdk_window_has_impl (private))
6427 /* Do the actual move after recomputing things, as this will have set the shape to
6428 the now correct one, thus avoiding copying regions that should not be copied. */
6429 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, TRUE, private->x, private->y, private->width, private->height);
6431 else if (old_abs_x != private->abs_x ||
6432 old_abs_y != private->abs_y)
6433 move_native_children (private);
6437 new_region = gdk_region_copy (private->clip_region);
6438 /* Adjust region to parent window coords */
6439 gdk_region_offset (new_region, private->x, private->y);
6442 * Part of the data at the new location can be copied from the
6443 * old location, this area is the intersection of the old region
6444 * moved as the copy will move it and then intersected with
6448 * Everything in the old and new regions that is not copied must be
6449 * invalidated (including children) as this is newly exposed
6451 copy_area = gdk_region_copy (new_region);
6453 gdk_region_union (new_region, old_region);
6455 if (old_native_child_region)
6457 /* Don't copy from inside native children, as this is copied by
6458 * the native window move.
6460 gdk_region_subtract (old_region, old_native_child_region);
6462 gdk_region_offset (old_region, dx, dy);
6464 gdk_region_intersect (copy_area, old_region);
6466 if (new_native_child_region)
6468 /* Don't copy any bits that would cause a read from the moved
6469 native windows, as we can't read that data */
6470 gdk_region_offset (new_native_child_region, dx, dy);
6471 gdk_region_subtract (copy_area, new_native_child_region);
6474 gdk_region_subtract (new_region, copy_area);
6476 /* Convert old region to impl coords */
6477 gdk_region_offset (old_region, -dx + private->abs_x - private->x, -dy + private->abs_y - private->y);
6479 /* convert from parent coords to impl */
6480 gdk_region_offset (copy_area, private->abs_x - private->x, private->abs_y - private->y);
6482 move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
6484 /* Invalidate affected part in the parent window
6485 * (no higher window should be affected)
6486 * We also invalidate any children in that area, which could include
6487 * this window if it still overlaps that area.
6489 gdk_window_invalidate_region (GDK_WINDOW (private->parent), new_region, TRUE);
6491 gdk_region_destroy (old_region);
6492 gdk_region_destroy (new_region);
6495 if (old_native_child_region)
6497 gdk_region_destroy (old_native_child_region);
6498 gdk_region_destroy (new_native_child_region);
6501 _gdk_synthesize_crossing_events_for_geometry_change (window);
6508 * @window: a #GdkWindow
6509 * @x: X coordinate relative to window's parent
6510 * @y: Y coordinate relative to window's parent
6512 * Repositions a window relative to its parent window.
6513 * For toplevel windows, window managers may ignore or modify the move;
6514 * you should probably use gtk_window_move() on a #GtkWindow widget
6515 * anyway, instead of using GDK functions. For child windows,
6516 * the move will reliably succeed.
6518 * If you're also planning to resize the window, use gdk_window_move_resize()
6519 * to both move and resize simultaneously, for a nicer visual effect.
6522 gdk_window_move (GdkWindow *window,
6526 gdk_window_move_resize_internal (window, TRUE, x, y, -1, -1);
6530 * gdk_window_resize:
6531 * @window: a #GdkWindow
6532 * @width: new width of the window
6533 * @height: new height of the window
6535 * Resizes @window; for toplevel windows, asks the window manager to resize
6536 * the window. The window manager may not allow the resize. When using GTK+,
6537 * use gtk_window_resize() instead of this low-level GDK function.
6539 * Windows may not be resized below 1x1.
6541 * If you're also planning to move the window, use gdk_window_move_resize()
6542 * to both move and resize simultaneously, for a nicer visual effect.
6545 gdk_window_resize (GdkWindow *window,
6549 gdk_window_move_resize_internal (window, FALSE, 0, 0, width, height);
6554 * gdk_window_move_resize:
6555 * @window: a #GdkWindow
6556 * @x: new X position relative to window's parent
6557 * @y: new Y position relative to window's parent
6559 * @height: new height
6561 * Equivalent to calling gdk_window_move() and gdk_window_resize(),
6562 * except that both operations are performed at once, avoiding strange
6563 * visual effects. (i.e. the user may be able to see the window first
6564 * move, then resize, if you don't use gdk_window_move_resize().)
6567 gdk_window_move_resize (GdkWindow *window,
6573 gdk_window_move_resize_internal (window, TRUE, x, y, width, height);
6578 * gdk_window_scroll:
6579 * @window: a #GdkWindow
6580 * @dx: Amount to scroll in the X direction
6581 * @dy: Amount to scroll in the Y direction
6583 * Scroll the contents of @window, both pixels and children, by the
6584 * given amount. @window itself does not move. Portions of the window
6585 * that the scroll operation brings in from offscreen areas are
6586 * invalidated. The invalidated region may be bigger than what would
6587 * strictly be necessary.
6589 * For X11, a minimum area will be invalidated if the window has no
6590 * subwindows, or if the edges of the window's parent do not extend
6591 * beyond the edges of the window. In other cases, a multi-step process
6592 * is used to scroll the window which may produce temporary visual
6593 * artifacts and unnecessary invalidations.
6596 gdk_window_scroll (GdkWindow *window,
6600 GdkWindowObject *private = (GdkWindowObject *) window;
6601 GdkWindowObject *impl_window;
6602 GdkRegion *copy_area, *noncopy_area;
6603 GdkRegion *old_native_child_region, *new_native_child_region;
6606 g_return_if_fail (GDK_IS_WINDOW (window));
6608 if (dx == 0 && dy == 0)
6611 if (private->destroyed)
6614 old_native_child_region = collect_native_child_region (private, FALSE);
6615 if (old_native_child_region)
6617 /* Any native window move will immediately copy stuff to the destination, which may overwrite a
6618 * source or destination for a delayed GdkWindowRegionMove. So, we need
6619 * to flush those here for the window and all overlapped subwindows
6620 * of it. And we need to do this before setting the new clips as those will be
6623 gdk_window_flush_recursive (private);
6627 /* First move all child windows, without causing invalidation */
6629 tmp_list = private->children;
6632 GdkWindow *child = GDK_WINDOW (tmp_list->data);
6633 GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
6635 /* Just update the positions, the bits will move with the copy */
6639 tmp_list = tmp_list->next;
6642 recompute_visible_regions (private, FALSE, TRUE);
6644 new_native_child_region = NULL;
6645 if (old_native_child_region)
6646 new_native_child_region = collect_native_child_region (private, FALSE);
6648 move_native_children (private);
6650 /* Then copy the actual bits of the window w/ child windows */
6652 impl_window = gdk_window_get_impl_window (private);
6654 /* Calculate the area that can be gotten by copying the old area */
6655 copy_area = gdk_region_copy (private->clip_region);
6656 if (old_native_child_region)
6658 /* Don't copy from inside native children, as this is copied by
6659 * the native window move.
6661 gdk_region_subtract (copy_area, old_native_child_region);
6663 /* Don't copy any bits that would cause a read from the moved
6664 native windows, as we can't read that data */
6665 gdk_region_subtract (copy_area, new_native_child_region);
6667 gdk_region_offset (copy_area, dx, dy);
6668 gdk_region_intersect (copy_area, private->clip_region);
6670 /* And the rest need to be invalidated */
6671 noncopy_area = gdk_region_copy (private->clip_region);
6672 gdk_region_subtract (noncopy_area, copy_area);
6674 /* convert from window coords to impl */
6675 gdk_region_offset (copy_area, private->abs_x, private->abs_y);
6677 move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
6679 /* Invalidate not copied regions */
6680 gdk_window_invalidate_region (window, noncopy_area, TRUE);
6682 gdk_region_destroy (noncopy_area);
6684 if (old_native_child_region)
6686 gdk_region_destroy (old_native_child_region);
6687 gdk_region_destroy (new_native_child_region);
6690 _gdk_synthesize_crossing_events_for_geometry_change (window);
6694 * gdk_window_move_region:
6695 * @window: a #GdkWindow
6696 * @region: The #GdkRegion to move
6697 * @dx: Amount to move in the X direction
6698 * @dy: Amount to move in the Y direction
6700 * Move the part of @window indicated by @region by @dy pixels in the Y
6701 * direction and @dx pixels in the X direction. The portions of @region
6702 * that not covered by the new position of @region are invalidated.
6704 * Child windows are not moved.
6709 gdk_window_move_region (GdkWindow *window,
6710 const GdkRegion *region,
6714 GdkWindowObject *private = (GdkWindowObject *) window;
6715 GdkWindowObject *impl_window;
6716 GdkRegion *nocopy_area;
6717 GdkRegion *copy_area;
6719 g_return_if_fail (GDK_IS_WINDOW (window));
6720 g_return_if_fail (region != NULL);
6722 if (dx == 0 && dy == 0)
6725 if (private->destroyed)
6728 impl_window = gdk_window_get_impl_window (private);
6730 /* compute source regions */
6731 copy_area = gdk_region_copy (region);
6732 gdk_region_intersect (copy_area, private->clip_region_with_children);
6734 /* compute destination regions */
6735 gdk_region_offset (copy_area, dx, dy);
6736 gdk_region_intersect (copy_area, private->clip_region_with_children);
6738 /* invalidate parts of the region not covered by the copy */
6739 nocopy_area = gdk_region_copy (region);
6740 gdk_region_offset (nocopy_area, dx, dy);
6741 gdk_region_subtract (nocopy_area, copy_area);
6742 gdk_window_invalidate_region (window, nocopy_area, FALSE);
6743 gdk_region_destroy (nocopy_area);
6745 /* convert from window coords to impl */
6746 gdk_region_offset (copy_area, private->abs_x, private->abs_y);
6748 move_region_on_impl (impl_window, copy_area, dx, dy); /* Takes ownership of copy_area */
6752 * gdk_window_set_background:
6753 * @window: a #GdkWindow
6754 * @color: an allocated #GdkColor
6756 * Sets the background color of @window. (However, when using GTK+,
6757 * set the background of a widget with gtk_widget_modify_bg() - if
6758 * you're an application - or gtk_style_set_background() - if you're
6759 * implementing a custom widget.)
6761 * The @color must be allocated; gdk_rgb_find_color() is the best way
6762 * to allocate a color.
6764 * See also gdk_window_set_back_pixmap().
6767 gdk_window_set_background (GdkWindow *window,
6768 const GdkColor *color)
6770 GdkWindowObject *private;
6771 GdkColormap *colormap = gdk_drawable_get_colormap (window);
6773 g_return_if_fail (GDK_IS_WINDOW (window));
6775 private = (GdkWindowObject *) window;
6777 private->bg_color = *color;
6778 gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
6780 if (private->bg_pixmap &&
6781 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
6782 private->bg_pixmap != GDK_NO_BG)
6783 g_object_unref (private->bg_pixmap);
6785 private->bg_pixmap = NULL;
6787 if (!GDK_WINDOW_DESTROYED (window) &&
6788 gdk_window_has_impl (private) &&
6789 !private->input_only)
6790 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, &private->bg_color);
6794 * gdk_window_set_back_pixmap:
6795 * @window: a #GdkWindow
6796 * @pixmap: a #GdkPixmap, or %NULL
6797 * @parent_relative: whether the tiling origin is at the origin of
6800 * Sets the background pixmap of @window. May also be used to set a
6801 * background of "None" on @window, by setting a background pixmap
6804 * A background pixmap will be tiled, positioning the first tile at
6805 * the origin of @window, or if @parent_relative is %TRUE, the tiling
6806 * will be done based on the origin of the parent window (useful to
6807 * align tiles in a parent with tiles in a child).
6809 * A background pixmap of %NULL means that the window will have no
6810 * background. A window with no background will never have its
6811 * background filled by the windowing system, instead the window will
6812 * contain whatever pixels were already in the corresponding area of
6815 * The windowing system will normally fill a window with its background
6816 * when the window is obscured then exposed, and when you call
6817 * gdk_window_clear().
6820 gdk_window_set_back_pixmap (GdkWindow *window,
6822 gboolean parent_relative)
6824 GdkWindowObject *private;
6826 g_return_if_fail (GDK_IS_WINDOW (window));
6827 g_return_if_fail (pixmap == NULL || !parent_relative);
6828 g_return_if_fail (pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap));
6830 private = (GdkWindowObject *) window;
6832 if (pixmap && !gdk_drawable_get_colormap (pixmap))
6834 g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
6838 if (private->bg_pixmap &&
6839 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
6840 private->bg_pixmap != GDK_NO_BG)
6841 g_object_unref (private->bg_pixmap);
6843 if (parent_relative)
6844 private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
6846 private->bg_pixmap = g_object_ref (pixmap);
6848 private->bg_pixmap = GDK_NO_BG;
6850 if (!GDK_WINDOW_DESTROYED (window) &&
6851 gdk_window_has_impl (private) &&
6852 !private->input_only)
6853 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, private->bg_pixmap);
6857 * gdk_window_set_cursor:
6858 * @window: a #GdkWindow
6861 * Sets the mouse pointer for a #GdkWindow. Use gdk_cursor_new_for_display()
6862 * or gdk_cursor_new_from_pixmap() to create the cursor. To make the cursor
6863 * invisible, use %GDK_BLANK_CURSOR. Passing %NULL for the @cursor argument
6864 * to gdk_window_set_cursor() means that @window will use the cursor of its
6865 * parent window. Most windows should use this default.
6868 gdk_window_set_cursor (GdkWindow *window,
6871 GdkWindowObject *private;
6872 GdkDisplay *display;
6874 g_return_if_fail (GDK_IS_WINDOW (window));
6876 private = (GdkWindowObject *) window;
6877 display = gdk_drawable_get_display (window);
6879 if (private->cursor)
6881 gdk_cursor_unref (private->cursor);
6882 private->cursor = NULL;
6885 if (!GDK_WINDOW_DESTROYED (window))
6888 private->cursor = gdk_cursor_ref (cursor);
6890 if (is_event_parent_of (window, display->pointer_info.window_under_pointer))
6891 update_cursor (display);
6896 * gdk_window_get_geometry:
6897 * @window: a #GdkWindow
6898 * @x: return location for X coordinate of window (relative to its parent)
6899 * @y: return location for Y coordinate of window (relative to its parent)
6900 * @width: return location for width of window
6901 * @height: return location for height of window
6902 * @depth: return location for bit depth of window
6904 * Any of the return location arguments to this function may be %NULL,
6905 * if you aren't interested in getting the value of that field.
6907 * The X and Y coordinates returned are relative to the parent window
6908 * of @window, which for toplevels usually means relative to the
6909 * window decorations (titlebar, etc.) rather than relative to the
6910 * root window (screen-size background window).
6912 * On the X11 platform, the geometry is obtained from the X server,
6913 * so reflects the latest position of @window; this may be out-of-sync
6914 * with the position of @window delivered in the most-recently-processed
6915 * #GdkEventConfigure. gdk_window_get_position() in contrast gets the
6916 * position from the most recent configure event.
6919 * If @window is not a toplevel, it is <emphasis>much</emphasis> better
6920 * to call gdk_window_get_position() and gdk_drawable_get_size() instead,
6921 * because it avoids the roundtrip to the X server and because
6922 * gdk_drawable_get_size() supports the full 32-bit coordinate space,
6923 * whereas gdk_window_get_geometry() is restricted to the 16-bit
6924 * coordinates of X11.
6928 gdk_window_get_geometry (GdkWindow *window,
6935 GdkWindowObject *private;
6939 GDK_NOTE (MULTIHEAD,
6940 g_message ("gdk_window_get_geometry(): Window needs "
6941 "to be non-NULL to be multi head safe"));
6942 window = gdk_screen_get_root_window ((gdk_screen_get_default ()));
6945 g_return_if_fail (GDK_IS_WINDOW (window));
6947 private = (GdkWindowObject *) window;
6949 if (!GDK_WINDOW_DESTROYED (window))
6951 if (gdk_window_has_impl (private))
6952 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_geometry (window, x, y,
6962 *width = private->width;
6964 *height = private->height;
6966 *depth = private->depth;
6972 * gdk_window_get_origin:
6973 * @window: a #GdkWindow
6974 * @x: return location for X coordinate
6975 * @y: return location for Y coordinate
6977 * Obtains the position of a window in root window coordinates.
6978 * (Compare with gdk_window_get_position() and
6979 * gdk_window_get_geometry() which return the position of a window
6980 * relative to its parent window.)
6982 * Return value: not meaningful, ignore
6985 gdk_window_get_origin (GdkWindow *window,
6989 GdkWindowObject *private;
6991 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
6993 if (GDK_WINDOW_DESTROYED (window))
7002 private = (GdkWindowObject *) window;
7004 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_root_coords (window,
7013 * gdk_window_get_root_coords:
7014 * @window: a #GdkWindow
7015 * @x: X coordinate in window
7016 * @y: Y coordinate in window
7017 * @root_x: return location for X coordinate
7018 * @root_y: return location for Y coordinate
7020 * Obtains the position of a window position in root
7021 * window coordinates. This is similar to
7022 * gdk_window_get_origin() but allows you go pass
7023 * in any position in the window, not just the origin.
7026 gdk_window_get_root_coords (GdkWindow *window,
7032 GdkWindowObject *private;
7034 g_return_if_fail (GDK_IS_WINDOW (window));
7036 private = (GdkWindowObject *) window;
7038 if (GDK_WINDOW_DESTROYED (window))
7047 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_root_coords (window,
7055 * gdk_window_get_deskrelative_origin:
7056 * @window: a toplevel #GdkWindow
7057 * @x: return location for X coordinate
7058 * @y: return location for Y coordinate
7060 * This gets the origin of a #GdkWindow relative to
7061 * an Enlightenment-window-manager desktop. As long as you don't
7062 * assume that the user's desktop/workspace covers the entire
7063 * root window (i.e. you don't assume that the desktop begins
7064 * at root window coordinate 0,0) this function is not necessary.
7065 * It's deprecated for that reason.
7067 * Return value: not meaningful
7070 gdk_window_get_deskrelative_origin (GdkWindow *window,
7074 GdkWindowObject *private;
7075 gboolean return_val = FALSE;
7079 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
7081 private = (GdkWindowObject *) window;
7083 if (!GDK_WINDOW_DESTROYED (window))
7085 return_val = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_deskrelative_origin (window, &tx, &ty);
7088 *x = tx + private->abs_x;
7090 *y = ty + private->abs_y;
7097 * gdk_window_shape_combine_mask:
7098 * @window: a #GdkWindow
7100 * @x: X position of shape mask with respect to @window
7101 * @y: Y position of shape mask with respect to @window
7103 * Applies a shape mask to @window. Pixels in @window corresponding to
7104 * set bits in the @mask will be visible; pixels in @window
7105 * corresponding to unset bits in the @mask will be transparent. This
7106 * gives a non-rectangular window.
7108 * If @mask is %NULL, the shape mask will be unset, and the @x/@y
7109 * parameters are not used.
7111 * On the X11 platform, this uses an X server extension which is
7112 * widely available on most common platforms, but not available on
7113 * very old X servers, and occasionally the implementation will be
7114 * buggy. On servers without the shape extension, this function
7117 * This function works on both toplevel and child windows.
7120 gdk_window_shape_combine_mask (GdkWindow *window,
7125 GdkWindowObject *private;
7128 g_return_if_fail (GDK_IS_WINDOW (window));
7130 private = (GdkWindowObject *) window;
7133 region = _gdk_windowing_get_shape_for_mask (mask);
7137 gdk_window_shape_combine_region (window,
7142 gdk_region_destroy (region);
7146 * gdk_window_shape_combine_region:
7147 * @window: a #GdkWindow
7148 * @shape_region: region of window to be non-transparent
7149 * @offset_x: X position of @shape_region in @window coordinates
7150 * @offset_y: Y position of @shape_region in @window coordinates
7152 * Makes pixels in @window outside @shape_region be transparent,
7153 * so that the window may be nonrectangular. See also
7154 * gdk_window_shape_combine_mask() to use a bitmap as the mask.
7156 * If @shape_region is %NULL, the shape will be unset, so the whole
7157 * window will be opaque again. @offset_x and @offset_y are ignored
7158 * if @shape_region is %NULL.
7160 * On the X11 platform, this uses an X server extension which is
7161 * widely available on most common platforms, but not available on
7162 * very old X servers, and occasionally the implementation will be
7163 * buggy. On servers without the shape extension, this function
7166 * This function works on both toplevel and child windows.
7169 gdk_window_shape_combine_region (GdkWindow *window,
7170 const GdkRegion *shape_region,
7174 GdkWindowObject *private;
7175 GdkRegion *old_region, *new_region, *diff;
7177 g_return_if_fail (GDK_IS_WINDOW (window));
7179 private = (GdkWindowObject *) window;
7181 if (GDK_WINDOW_DESTROYED (window))
7184 private->shaped = (shape_region != NULL);
7187 gdk_region_destroy (private->shape);
7190 if (GDK_WINDOW_IS_MAPPED (window))
7191 old_region = gdk_region_copy (private->clip_region);
7195 private->shape = gdk_region_copy (shape_region);
7196 gdk_region_offset (private->shape, offset_x, offset_y);
7199 private->shape = NULL;
7201 recompute_visible_regions (private, TRUE, FALSE);
7205 new_region = gdk_region_copy (private->clip_region);
7207 /* New area in the window, needs invalidation */
7208 diff = gdk_region_copy (new_region);
7209 gdk_region_subtract (diff, old_region);
7211 gdk_window_invalidate_region (window, diff, TRUE);
7213 gdk_region_destroy (diff);
7215 if (private->parent != NULL &&
7216 GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
7218 /* New area in the non-root parent window, needs invalidation */
7219 diff = gdk_region_copy (old_region);
7220 gdk_region_subtract (diff, new_region);
7222 /* Adjust region to parent window coords */
7223 gdk_region_offset (diff, private->x, private->y);
7225 gdk_window_invalidate_region (GDK_WINDOW (private->parent), diff, TRUE);
7227 gdk_region_destroy (diff);
7230 gdk_region_destroy (new_region);
7231 gdk_region_destroy (old_region);
7236 do_child_shapes (GdkWindow *window,
7239 GdkWindowObject *private;
7243 private = (GdkWindowObject *) window;
7247 r.width = private->width;
7248 r.height = private->height;
7250 region = gdk_region_rectangle (&r);
7251 remove_child_area (private, NULL, FALSE, region);
7253 if (merge && private->shape)
7254 gdk_region_subtract (region, private->shape);
7256 gdk_window_shape_combine_region (window, region, 0, 0);
7260 * gdk_window_set_child_shapes:
7261 * @window: a #GdkWindow
7263 * Sets the shape mask of @window to the union of shape masks
7264 * for all children of @window, ignoring the shape mask of @window
7265 * itself. Contrast with gdk_window_merge_child_shapes() which includes
7266 * the shape mask of @window in the masks to be merged.
7269 gdk_window_set_child_shapes (GdkWindow *window)
7271 g_return_if_fail (GDK_IS_WINDOW (window));
7273 do_child_shapes (window, FALSE);
7277 * gdk_window_merge_child_shapes:
7278 * @window: a #GdkWindow
7280 * Merges the shape masks for any child windows into the
7281 * shape mask for @window. i.e. the union of all masks
7282 * for @window and its children will become the new mask
7283 * for @window. See gdk_window_shape_combine_mask().
7285 * This function is distinct from gdk_window_set_child_shapes()
7286 * because it includes @window's shape mask in the set of shapes to
7290 gdk_window_merge_child_shapes (GdkWindow *window)
7292 g_return_if_fail (GDK_IS_WINDOW (window));
7294 do_child_shapes (window, TRUE);
7298 * gdk_window_input_shape_combine_mask:
7299 * @window: a #GdkWindow
7301 * @x: X position of shape mask with respect to @window
7302 * @y: Y position of shape mask with respect to @window
7304 * Like gdk_window_shape_combine_mask(), but the shape applies
7305 * only to event handling. Mouse events which happen while
7306 * the pointer position corresponds to an unset bit in the
7307 * mask will be passed on the window below @window.
7309 * An input shape is typically used with RGBA windows.
7310 * The alpha channel of the window defines which pixels are
7311 * invisible and allows for nicely antialiased borders,
7312 * and the input shape controls where the window is
7315 * On the X11 platform, this requires version 1.1 of the
7318 * On the Win32 platform, this functionality is not present and the
7319 * function does nothing.
7324 gdk_window_input_shape_combine_mask (GdkWindow *window,
7329 GdkWindowObject *private;
7332 g_return_if_fail (GDK_IS_WINDOW (window));
7334 private = (GdkWindowObject *) window;
7337 region = _gdk_windowing_get_shape_for_mask (mask);
7341 gdk_window_input_shape_combine_region (window,
7345 gdk_region_destroy (region);
7349 * gdk_window_input_shape_combine_region:
7350 * @window: a #GdkWindow
7351 * @shape_region: region of window to be non-transparent
7352 * @offset_x: X position of @shape_region in @window coordinates
7353 * @offset_y: Y position of @shape_region in @window coordinates
7355 * Like gdk_window_shape_combine_region(), but the shape applies
7356 * only to event handling. Mouse events which happen while
7357 * the pointer position corresponds to an unset bit in the
7358 * mask will be passed on the window below @window.
7360 * An input shape is typically used with RGBA windows.
7361 * The alpha channel of the window defines which pixels are
7362 * invisible and allows for nicely antialiased borders,
7363 * and the input shape controls where the window is
7366 * On the X11 platform, this requires version 1.1 of the
7369 * On the Win32 platform, this functionality is not present and the
7370 * function does nothing.
7375 gdk_window_input_shape_combine_region (GdkWindow *window,
7376 const GdkRegion *shape_region,
7380 GdkWindowObject *private;
7382 g_return_if_fail (GDK_IS_WINDOW (window));
7384 private = (GdkWindowObject *) window;
7386 if (GDK_WINDOW_DESTROYED (window))
7389 if (private->input_shape)
7390 gdk_region_destroy (private->input_shape);
7394 private->input_shape = gdk_region_copy (shape_region);
7395 gdk_region_offset (private->input_shape, offset_x, offset_y);
7398 private->input_shape = NULL;
7400 if (gdk_window_has_impl (private))
7401 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_shape_combine_region ((GdkWindow *)private, private->input_shape, 0, 0);
7403 /* Pointer may have e.g. moved outside window due to the input mask change */
7404 _gdk_synthesize_crossing_events_for_geometry_change (window);
7408 do_child_input_shapes (GdkWindow *window,
7411 GdkWindowObject *private;
7415 private = (GdkWindowObject *) window;
7419 r.width = private->width;
7420 r.height = private->height;
7422 region = gdk_region_rectangle (&r);
7423 remove_child_area (private, NULL, TRUE, region);
7425 if (merge && private->shape)
7426 gdk_region_subtract (region, private->shape);
7427 if (merge && private->input_shape)
7428 gdk_region_subtract (region, private->input_shape);
7430 gdk_window_input_shape_combine_region (window, region, 0, 0);
7435 * gdk_window_set_child_input_shapes:
7436 * @window: a #GdkWindow
7438 * Sets the input shape mask of @window to the union of input shape masks
7439 * for all children of @window, ignoring the input shape mask of @window
7440 * itself. Contrast with gdk_window_merge_child_input_shapes() which includes
7441 * the input shape mask of @window in the masks to be merged.
7446 gdk_window_set_child_input_shapes (GdkWindow *window)
7448 g_return_if_fail (GDK_IS_WINDOW (window));
7450 do_child_input_shapes (window, FALSE);
7454 * gdk_window_merge_child_input_shapes:
7455 * @window: a #GdkWindow
7457 * Merges the input shape masks for any child windows into the
7458 * input shape mask for @window. i.e. the union of all input masks
7459 * for @window and its children will become the new input mask
7460 * for @window. See gdk_window_input_shape_combine_mask().
7462 * This function is distinct from gdk_window_set_child_input_shapes()
7463 * because it includes @window's input shape mask in the set of
7464 * shapes to be merged.
7469 gdk_window_merge_child_input_shapes (GdkWindow *window)
7471 g_return_if_fail (GDK_IS_WINDOW (window));
7473 do_child_input_shapes (window, TRUE);
7478 * gdk_window_set_static_gravities:
7479 * @window: a #GdkWindow
7480 * @use_static: %TRUE to turn on static gravity
7482 * Set the bit gravity of the given window to static, and flag it so
7483 * all children get static subwindow gravity. This is used if you are
7484 * implementing scary features that involve deep knowledge of the
7485 * windowing system. Don't worry about it unless you have to.
7487 * Return value: %TRUE if the server supports static gravity
7490 gdk_window_set_static_gravities (GdkWindow *window,
7491 gboolean use_static)
7493 GdkWindowObject *private;
7495 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
7497 private = (GdkWindowObject *) window;
7499 if (gdk_window_has_impl (private))
7500 return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_static_gravities (window, use_static);
7506 * gdk_window_set_composited:
7507 * @window: a #GdkWindow
7508 * @composited: %TRUE to set the window as composited
7510 * Sets a #GdkWindow as composited, or unsets it. Composited
7511 * windows do not automatically have their contents drawn to
7512 * the screen. Drawing is redirected to an offscreen buffer
7513 * and an expose event is emitted on the parent of the composited
7514 * window. It is the responsibility of the parent's expose handler
7515 * to manually merge the off-screen content onto the screen in
7516 * whatever way it sees fit. See <xref linkend="composited-window-example"/>
7519 * It only makes sense for child windows to be composited; see
7520 * gdk_window_set_opacity() if you need translucent toplevel
7523 * An additional effect of this call is that the area of this
7524 * window is no longer clipped from regions marked for
7525 * invalidation on its parent. Draws done on the parent
7526 * window are also no longer clipped by the child.
7528 * This call is only supported on some systems (currently,
7529 * only X11 with new enough Xcomposite and Xdamage extensions).
7530 * You must call gdk_display_supports_composite() to check if
7531 * setting a window as composited is supported before
7532 * attempting to do so.
7537 gdk_window_set_composited (GdkWindow *window,
7538 gboolean composited)
7540 GdkWindowObject *private = (GdkWindowObject *)window;
7541 GdkDisplay *display;
7543 g_return_if_fail (GDK_IS_WINDOW (window));
7545 composited = composited != FALSE;
7547 if (private->composited == composited)
7551 gdk_window_ensure_native (window);
7553 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
7555 if (!gdk_display_supports_composite (display) && composited)
7557 g_warning ("gdk_window_set_composited called but "
7558 "compositing is not supported");
7562 _gdk_windowing_window_set_composited (window, composited);
7564 recompute_visible_regions (private, TRUE, FALSE);
7566 if (GDK_WINDOW_IS_MAPPED (window))
7567 gdk_window_invalidate_in_parent (private);
7569 private->composited = composited;
7574 remove_redirect_from_children (GdkWindowObject *private,
7575 GdkWindowRedirect *redirect)
7578 GdkWindowObject *child;
7580 for (l = private->children; l != NULL; l = l->next)
7584 /* Don't redirect this child if it already has another redirect */
7585 if (child->redirect == redirect)
7587 child->redirect = NULL;
7588 remove_redirect_from_children (child, redirect);
7594 * gdk_window_remove_redirection:
7595 * @window: a #GdkWindow
7597 * Removes any active redirection started by
7598 * gdk_window_redirect_to_drawable().
7603 gdk_window_remove_redirection (GdkWindow *window)
7605 GdkWindowObject *private;
7607 g_return_if_fail (GDK_IS_WINDOW (window));
7609 private = (GdkWindowObject *) window;
7611 if (private->redirect &&
7612 private->redirect->redirected == private)
7614 remove_redirect_from_children (private, private->redirect);
7615 gdk_window_redirect_free (private->redirect);
7616 private->redirect = NULL;
7621 apply_redirect_to_children (GdkWindowObject *private,
7622 GdkWindowRedirect *redirect)
7625 GdkWindowObject *child;
7627 for (l = private->children; l != NULL; l = l->next)
7631 /* Don't redirect this child if it already has another redirect */
7632 if (!child->redirect)
7634 child->redirect = redirect;
7635 apply_redirect_to_children (child, redirect);
7641 * gdk_window_redirect_to_drawable:
7642 * @window: a #GdkWindow
7643 * @drawable: a #GdkDrawable
7644 * @src_x: x position in @window
7645 * @src_y: y position in @window
7646 * @dest_x: x position in @drawable
7647 * @dest_y: y position in @drawable
7648 * @width: width of redirection
7649 * @height: height of redirection
7651 * Redirects drawing into @window so that drawing to the
7652 * window in the rectangle specified by @src_x, @src_y,
7653 * @width and @height is also drawn into @drawable at
7656 * Only drawing between gdk_window_begin_paint_region() or
7657 * gdk_window_begin_paint_rect() and gdk_window_end_paint() is
7660 * Redirection is active until gdk_window_remove_redirection()
7666 gdk_window_redirect_to_drawable (GdkWindow *window,
7667 GdkDrawable *drawable,
7675 GdkWindowObject *private;
7677 g_return_if_fail (GDK_IS_WINDOW (window));
7678 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
7679 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
7681 private = (GdkWindowObject *) window;
7683 if (private->redirect)
7684 gdk_window_remove_redirection (window);
7686 if (width == -1 || height == -1)
7689 gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
7696 private->redirect = g_new0 (GdkWindowRedirect, 1);
7697 private->redirect->redirected = private;
7698 private->redirect->pixmap = g_object_ref (drawable);
7699 private->redirect->src_x = src_x;
7700 private->redirect->src_y = src_y;
7701 private->redirect->dest_x = dest_x;
7702 private->redirect->dest_y = dest_y;
7703 private->redirect->width = width;
7704 private->redirect->height = height;
7706 apply_redirect_to_children (private, private->redirect);
7710 window_get_size_rectangle (GdkWindow *window,
7713 GdkWindowObject *private = (GdkWindowObject *) window;
7715 rect->x = rect->y = 0;
7716 rect->width = private->width;
7717 rect->height = private->height;
7720 /* Calculates the real clipping region for a window, in window coordinates,
7721 * taking into account other windows, gc clip region and gc clip mask.
7724 _gdk_window_calculate_full_clip_region (GdkWindow *window,
7725 GdkWindow *base_window,
7726 gboolean do_children,
7727 gint *base_x_offset,
7728 gint *base_y_offset)
7730 GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
7731 GdkRectangle visible_rect;
7732 GdkRegion *real_clip_region, *tmpreg;
7733 gint x_offset, y_offset;
7734 GdkWindowObject *parentwin, *lastwin;
7741 if (!GDK_WINDOW_IS_MAPPED (window) || private->input_only)
7742 return gdk_region_new ();
7744 window_get_size_rectangle (window, &visible_rect);
7746 /* real_clip_region is in window coordinates */
7747 real_clip_region = gdk_region_rectangle (&visible_rect);
7749 x_offset = y_offset = 0;
7753 parentwin = lastwin;
7755 parentwin = lastwin->parent;
7757 /* Remove the areas of all overlapping windows above parentwin in the hiearachy */
7758 for (; parentwin != NULL &&
7759 (parentwin == private || lastwin != (GdkWindowObject*) base_window);
7760 lastwin = parentwin, parentwin = lastwin->parent)
7763 GdkRectangle real_clip_rect;
7764 gboolean is_offscreen;
7766 if (parentwin != private)
7768 x_offset += GDK_WINDOW_OBJECT (lastwin)->x;
7769 y_offset += GDK_WINDOW_OBJECT (lastwin)->y;
7772 is_offscreen = gdk_window_is_offscreen (parentwin);
7774 /* children is ordered in reverse stack order */
7775 for (cur = parentwin->children;
7776 cur && cur->data != lastwin;
7779 GdkWindow *child = cur->data;
7780 GdkWindowObject *child_private = (GdkWindowObject *)child;
7782 if (!GDK_WINDOW_IS_MAPPED (child) || child_private->input_only)
7785 /* Ignore offscreen children, as they don't draw in their parent and
7786 * don't take part in the clipping */
7787 if (gdk_window_is_offscreen (child_private))
7790 window_get_size_rectangle (child, &visible_rect);
7792 /* Convert rect to "window" coords */
7793 visible_rect.x += child_private->x - x_offset;
7794 visible_rect.y += child_private->y - y_offset;
7796 /* This shortcut is really necessary for performance when there are a lot of windows */
7797 gdk_region_get_clipbox (real_clip_region, &real_clip_rect);
7798 if (visible_rect.x >= real_clip_rect.x + real_clip_rect.width ||
7799 visible_rect.x + visible_rect.width <= real_clip_rect.x ||
7800 visible_rect.y >= real_clip_rect.y + real_clip_rect.height ||
7801 visible_rect.y + visible_rect.height <= real_clip_rect.y)
7804 tmpreg = gdk_region_rectangle (&visible_rect);
7805 gdk_region_subtract (real_clip_region, tmpreg);
7806 gdk_region_destroy (tmpreg);
7809 /* Clip to the parent */
7810 window_get_size_rectangle ((GdkWindow *)parentwin, &visible_rect);
7811 /* Convert rect to "window" coords */
7812 visible_rect.x += - x_offset;
7813 visible_rect.y += - y_offset;
7815 tmpreg = gdk_region_rectangle (&visible_rect);
7816 gdk_region_intersect (real_clip_region, tmpreg);
7817 gdk_region_destroy (tmpreg);
7821 *base_x_offset = x_offset;
7823 *base_y_offset = y_offset;
7825 return real_clip_region;
7829 _gdk_window_add_damage (GdkWindow *toplevel,
7830 GdkRegion *damaged_region)
7832 GdkDisplay *display;
7833 GdkEvent event = { 0, };
7834 event.expose.type = GDK_DAMAGE;
7835 event.expose.window = toplevel;
7836 event.expose.send_event = FALSE;
7837 event.expose.region = damaged_region;
7838 gdk_region_get_clipbox (event.expose.region, &event.expose.area);
7839 display = gdk_drawable_get_display (event.expose.window);
7840 _gdk_event_queue_append (display, gdk_event_copy (&event));
7844 gdk_window_redirect_free (GdkWindowRedirect *redirect)
7846 g_object_unref (redirect->pixmap);
7850 /* Gets the toplevel for a window as used for events,
7851 i.e. including offscreen parents */
7852 static GdkWindowObject *
7853 get_event_parent (GdkWindowObject *window)
7855 if (window->window_type ==GDK_WINDOW_OFFSCREEN)
7856 return (GdkWindowObject *)gdk_window_get_offscreen_parent ((GdkWindow *)window);
7858 return window->parent;
7861 /* Gets the toplevel for a window as used for events,
7862 i.e. including offscreen parents going up to the native
7865 get_event_toplevel (GdkWindow *w)
7867 GdkWindowObject *private = GDK_WINDOW_OBJECT (w);
7868 GdkWindowObject *parent;
7870 while ((parent = get_event_parent (private)) != NULL &&
7871 (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT))
7874 return GDK_WINDOW (private);
7878 is_event_parent_of (GdkWindow *parent,
7889 w = (GdkWindow *)get_event_parent ((GdkWindowObject *)w);
7896 update_cursor (GdkDisplay *display)
7898 GdkWindowObject *pointer_window, *cursor_window, *parent, *toplevel;
7899 GdkPointerGrabInfo *grab;
7901 pointer_window = (GdkWindowObject *)display->pointer_info.window_under_pointer;
7903 cursor_window = pointer_window;
7904 while (cursor_window->cursor == NULL &&
7905 (parent = get_event_parent (cursor_window)) != NULL &&
7906 parent->window_type != GDK_WINDOW_ROOT)
7907 cursor_window = parent;
7909 /* We ignore the serials here and just pick the last grab
7910 we've sent, as that would shortly be used anyway. */
7911 grab = _gdk_display_get_last_pointer_grab (display);
7913 !is_event_parent_of (grab->window, (GdkWindow *)cursor_window))
7914 cursor_window = (GdkWindowObject *)grab->window;
7916 /* Set all cursors on toplevel, otherwise its tricky to keep track of
7917 * which native window has what cursor set. */
7918 toplevel = (GdkWindowObject *)get_event_toplevel ((GdkWindow *)pointer_window);
7919 GDK_WINDOW_IMPL_GET_IFACE (toplevel->impl)->set_cursor
7920 ((GdkWindow *)toplevel, cursor_window->cursor);
7924 from_parent (GdkWindowObject *window,
7925 double parent_x, double parent_y,
7926 double *offscreen_x, double *offscreen_y)
7928 g_signal_emit (window,
7929 signals[FROM_PARENT], 0,
7931 offscreen_x, offscreen_y,
7936 convert_coords_to_child (GdkWindowObject *child,
7938 double *child_x, double *child_y)
7940 if (gdk_window_is_offscreen (child))
7942 from_parent (child, x, y,
7947 *child_x = x - child->x;
7948 *child_y = y - child->y;
7953 point_in_window (GdkWindowObject *window,
7957 x >= 0 && x < window->width &&
7958 y >= 0 && y < window->height &&
7959 (window->shape == NULL ||
7960 gdk_region_point_in (window->shape,
7962 (window->input_shape == NULL ||
7963 gdk_region_point_in (window->input_shape,
7968 convert_native_coords_to_toplevel (GdkWindow *window,
7969 double child_x, double child_y,
7970 double *toplevel_x, double *toplevel_y)
7972 GdkWindowObject *private = (GdkWindowObject *)window;
7978 while (private->parent != NULL &&
7979 (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT))
7983 private = private->parent;
7989 return (GdkWindow *)private;
7993 convert_toplevel_coords_to_window (GdkWindow *window,
7999 GdkWindowObject *private;
8000 GdkWindowObject *parent;
8002 GList *children, *l;
8004 private = GDK_WINDOW_OBJECT (window);
8010 while ((parent = get_event_parent (private)) != NULL &&
8011 (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT))
8013 children = g_list_prepend (children, private);
8017 for (l = children; l != NULL; l = l->next)
8018 convert_coords_to_child (l->data, x, y, &x, &y);
8020 g_list_free (children);
8026 static GdkWindowObject *
8027 pick_offscreen_child (GdkWindowObject *window,
8030 GdkWindowObject *res;
8033 g_signal_emit (window,
8034 signals[PICK_OFFSCREEN_CHILD], 0,
8041 _gdk_window_find_child_at (GdkWindow *window,
8044 GdkWindowObject *private, *sub;
8045 double child_x, child_y;
8048 private = (GdkWindowObject *)window;
8050 if (point_in_window (private, x, y))
8052 /* Children is ordered in reverse stack order, i.e. first is topmost */
8053 for (l = private->children; l != NULL; l = l->next)
8057 if (!GDK_WINDOW_IS_MAPPED (sub))
8060 convert_coords_to_child (sub,
8062 &child_x, &child_y);
8063 if (point_in_window (sub, child_x, child_y))
8064 return (GdkWindow *)sub;
8067 if (private->has_offscreen_children)
8069 sub = pick_offscreen_child (private,
8072 return (GdkWindow *)sub;
8080 _gdk_window_find_descendant_at (GdkWindow *toplevel,
8085 GdkWindowObject *private, *sub;
8086 double child_x, child_y;
8090 private = (GdkWindowObject *)toplevel;
8092 if (point_in_window (private, x, y))
8097 /* Children is ordered in reverse stack order, i.e. first is topmost */
8098 for (l = private->children; l != NULL; l = l->next)
8102 if (!GDK_WINDOW_IS_MAPPED (sub))
8105 convert_coords_to_child (sub,
8107 &child_x, &child_y);
8108 if (point_in_window (sub, child_x, child_y))
8118 private->has_offscreen_children)
8120 sub = pick_offscreen_child (private,
8126 from_parent (sub, x, y, &x, &y);
8134 /* Not in window at all */
8143 return (GdkWindow *)private;
8148 * @window: a toplevel #GdkWindow
8150 * Emits a short beep associated to @window in the appropriate
8151 * display, if supported. Otherwise, emits a short beep on
8152 * the display just as gdk_display_beep().
8157 gdk_window_beep (GdkWindow *window)
8159 GdkDisplay *display;
8160 GdkWindow *toplevel;
8162 g_return_if_fail (GDK_IS_WINDOW (window));
8164 if (GDK_WINDOW_DESTROYED (window))
8167 toplevel = get_event_toplevel (window);
8168 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
8170 if (toplevel && gdk_window_is_offscreen ((GdkWindowObject *)toplevel))
8171 _gdk_windowing_window_beep (toplevel);
8173 gdk_display_beep (display);
8176 static const guint type_masks[] = {
8177 GDK_SUBSTRUCTURE_MASK, /* GDK_DELETE = 0 */
8178 GDK_STRUCTURE_MASK, /* GDK_DESTROY = 1 */
8179 GDK_EXPOSURE_MASK, /* GDK_EXPOSE = 2 */
8180 GDK_POINTER_MOTION_MASK, /* GDK_MOTION_NOTIFY = 3 */
8181 GDK_BUTTON_PRESS_MASK, /* GDK_BUTTON_PRESS = 4 */
8182 GDK_BUTTON_PRESS_MASK, /* GDK_2BUTTON_PRESS = 5 */
8183 GDK_BUTTON_PRESS_MASK, /* GDK_3BUTTON_PRESS = 6 */
8184 GDK_BUTTON_RELEASE_MASK, /* GDK_BUTTON_RELEASE = 7 */
8185 GDK_KEY_PRESS_MASK, /* GDK_KEY_PRESS = 8 */
8186 GDK_KEY_RELEASE_MASK, /* GDK_KEY_RELEASE = 9 */
8187 GDK_ENTER_NOTIFY_MASK, /* GDK_ENTER_NOTIFY = 10 */
8188 GDK_LEAVE_NOTIFY_MASK, /* GDK_LEAVE_NOTIFY = 11 */
8189 GDK_FOCUS_CHANGE_MASK, /* GDK_FOCUS_CHANGE = 12 */
8190 GDK_STRUCTURE_MASK, /* GDK_CONFIGURE = 13 */
8191 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_MAP = 14 */
8192 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_UNMAP = 15 */
8193 GDK_PROPERTY_CHANGE_MASK, /* GDK_PROPERTY_NOTIFY = 16 */
8194 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_CLEAR = 17 */
8195 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_REQUEST = 18 */
8196 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_NOTIFY = 19 */
8197 GDK_PROXIMITY_IN_MASK, /* GDK_PROXIMITY_IN = 20 */
8198 GDK_PROXIMITY_OUT_MASK, /* GDK_PROXIMITY_OUT = 21 */
8199 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_ENTER = 22 */
8200 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_LEAVE = 23 */
8201 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_MOTION = 24 */
8202 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_STATUS = 25 */
8203 GDK_ALL_EVENTS_MASK, /* GDK_DROP_START = 26 */
8204 GDK_ALL_EVENTS_MASK, /* GDK_DROP_FINISHED = 27 */
8205 GDK_ALL_EVENTS_MASK, /* GDK_CLIENT_EVENT = 28 */
8206 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_VISIBILITY_NOTIFY = 29 */
8207 GDK_EXPOSURE_MASK, /* GDK_NO_EXPOSE = 30 */
8208 GDK_SCROLL_MASK | GDK_BUTTON_PRESS_MASK,/* GDK_SCROLL= 31 */
8209 0, /* GDK_WINDOW_STATE = 32 */
8210 0, /* GDK_SETTING = 33 */
8211 0, /* GDK_OWNER_CHANGE = 34 */
8212 0, /* GDK_GRAB_BROKEN = 35 */
8213 0, /* GDK_DAMAGE = 36 */
8215 G_STATIC_ASSERT (G_N_ELEMENTS (type_masks) == GDK_EVENT_LAST);
8217 /* send motion events if the right buttons are down */
8219 update_evmask_for_button_motion (guint evmask,
8220 GdkModifierType mask)
8222 if (evmask & GDK_BUTTON_MOTION_MASK &&
8223 mask & (GDK_BUTTON1_MASK |
8228 evmask |= GDK_POINTER_MOTION_MASK;
8230 if ((evmask & GDK_BUTTON1_MOTION_MASK && mask & GDK_BUTTON1_MASK) ||
8231 (evmask & GDK_BUTTON2_MOTION_MASK && mask & GDK_BUTTON2_MASK) ||
8232 (evmask & GDK_BUTTON3_MOTION_MASK && mask & GDK_BUTTON3_MASK))
8233 evmask |= GDK_POINTER_MOTION_MASK;
8239 is_button_type (GdkEventType type)
8241 return type == GDK_BUTTON_PRESS ||
8242 type == GDK_2BUTTON_PRESS ||
8243 type == GDK_3BUTTON_PRESS ||
8244 type == GDK_BUTTON_RELEASE ||
8249 is_motion_type (GdkEventType type)
8251 return type == GDK_MOTION_NOTIFY ||
8252 type == GDK_ENTER_NOTIFY ||
8253 type == GDK_LEAVE_NOTIFY;
8256 static GdkWindowObject *
8257 find_common_ancestor (GdkWindowObject *win1,
8258 GdkWindowObject *win2)
8260 GdkWindowObject *tmp;
8261 GList *path1 = NULL, *path2 = NULL;
8262 GList *list1, *list2;
8265 while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
8267 path1 = g_list_prepend (path1, tmp);
8268 tmp = get_event_parent (tmp);
8272 while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
8274 path2 = g_list_prepend (path2, tmp);
8275 tmp = get_event_parent (tmp);
8281 while (list1 && list2 && (list1->data == list2->data))
8283 tmp = (GdkWindowObject *)list1->data;
8284 list1 = g_list_next (list1);
8285 list2 = g_list_next (list2);
8287 g_list_free (path1);
8288 g_list_free (path2);
8294 _gdk_make_event (GdkWindow *window,
8296 GdkEvent *event_in_queue,
8297 gboolean before_event)
8299 GdkEvent *event = gdk_event_new (type);
8301 GdkModifierType the_state;
8303 the_time = gdk_event_get_time (event_in_queue);
8304 gdk_event_get_state (event_in_queue, &the_state);
8306 event->any.window = g_object_ref (window);
8307 event->any.send_event = FALSE;
8311 case GDK_MOTION_NOTIFY:
8312 event->motion.time = the_time;
8313 event->motion.axes = NULL;
8314 event->motion.state = the_state;
8317 case GDK_BUTTON_PRESS:
8318 case GDK_2BUTTON_PRESS:
8319 case GDK_3BUTTON_PRESS:
8320 case GDK_BUTTON_RELEASE:
8321 event->button.time = the_time;
8322 event->button.axes = NULL;
8323 event->button.state = the_state;
8327 event->scroll.time = the_time;
8328 event->scroll.state = the_state;
8332 case GDK_KEY_RELEASE:
8333 event->key.time = the_time;
8334 event->key.state = the_state;
8337 case GDK_ENTER_NOTIFY:
8338 case GDK_LEAVE_NOTIFY:
8339 event->crossing.time = the_time;
8340 event->crossing.state = the_state;
8343 case GDK_PROPERTY_NOTIFY:
8344 event->property.time = the_time;
8345 event->property.state = the_state;
8348 case GDK_SELECTION_CLEAR:
8349 case GDK_SELECTION_REQUEST:
8350 case GDK_SELECTION_NOTIFY:
8351 event->selection.time = the_time;
8354 case GDK_PROXIMITY_IN:
8355 case GDK_PROXIMITY_OUT:
8356 event->proximity.time = the_time;
8359 case GDK_DRAG_ENTER:
8360 case GDK_DRAG_LEAVE:
8361 case GDK_DRAG_MOTION:
8362 case GDK_DRAG_STATUS:
8363 case GDK_DROP_START:
8364 case GDK_DROP_FINISHED:
8365 event->dnd.time = the_time;
8368 case GDK_FOCUS_CHANGE:
8372 case GDK_CLIENT_EVENT:
8373 case GDK_VISIBILITY_NOTIFY:
8385 _gdk_event_queue_insert_before (gdk_drawable_get_display (window), event_in_queue, event);
8387 _gdk_event_queue_insert_after (gdk_drawable_get_display (window), event_in_queue, event);
8390 _gdk_event_queue_append (gdk_drawable_get_display (window), event);
8396 send_crossing_event (GdkDisplay *display,
8397 GdkWindowObject *toplevel,
8398 GdkWindowObject *window,
8400 GdkCrossingMode mode,
8401 GdkNotifyType notify_type,
8402 GdkWindow *subwindow,
8405 GdkModifierType mask,
8407 GdkEvent *event_in_queue,
8412 GdkPointerGrabInfo *grab;
8414 grab = _gdk_display_has_pointer_grab (display, serial);
8417 !grab->owner_events &&
8418 (GdkWindow *)window != grab->window)
8421 if (type == GDK_LEAVE_NOTIFY)
8422 event_mask = GDK_LEAVE_NOTIFY_MASK;
8424 event_mask = GDK_ENTER_NOTIFY_MASK;
8426 if (window->extension_events != 0)
8427 GDK_WINDOW_IMPL_GET_IFACE (window->impl)->input_window_crossing ((GdkWindow *)window,
8428 type == GDK_ENTER_NOTIFY);
8430 if (window->event_mask & event_mask)
8432 event = _gdk_make_event ((GdkWindow *)window, type, event_in_queue, TRUE);
8433 event->crossing.time = time_;
8434 event->crossing.subwindow = subwindow;
8436 g_object_ref (subwindow);
8437 convert_toplevel_coords_to_window ((GdkWindow *)window,
8438 toplevel_x, toplevel_y,
8439 &event->crossing.x, &event->crossing.y);
8440 event->crossing.x_root = toplevel_x + toplevel->x;
8441 event->crossing.y_root = toplevel_y + toplevel->y;
8442 event->crossing.mode = mode;
8443 event->crossing.detail = notify_type;
8444 event->crossing.focus = FALSE;
8445 event->crossing.state = mask;
8450 /* The coordinates are in the toplevel window that src/dest are in.
8451 * src and dest are always (if != NULL) in the same toplevel, as
8452 * we get a leave-notify and set the window_under_pointer to null
8453 * before crossing to another toplevel.
8456 _gdk_synthesize_crossing_events (GdkDisplay *display,
8459 GdkCrossingMode mode,
8462 GdkModifierType mask,
8464 GdkEvent *event_in_queue,
8468 GdkWindowObject *win, *last, *next;
8470 gboolean non_linear;
8473 GdkWindowObject *toplevel;
8474 GdkNotifyType notify_type;
8476 /* TODO: Don't send events to toplevel, as we get those from the windowing system */
8478 a = (GdkWindowObject *)src;
8479 b = (GdkWindowObject *)dest;
8481 return; /* No crossings generated between src and dest */
8483 c = find_common_ancestor (a, b);
8485 non_linear = (c != a) && (c != b);
8487 if (a) /* There might not be a source (i.e. if no previous pointer_in_window) */
8489 toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)a);
8491 /* Traverse up from a to (excluding) c sending leave events */
8493 notify_type = GDK_NOTIFY_NONLINEAR;
8495 notify_type = GDK_NOTIFY_INFERIOR;
8497 notify_type = GDK_NOTIFY_ANCESTOR;
8498 send_crossing_event (display, toplevel,
8499 a, GDK_LEAVE_NOTIFY,
8503 toplevel_x, toplevel_y,
8511 notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
8513 notify_type = GDK_NOTIFY_VIRTUAL;
8516 win = get_event_parent (a);
8517 while (win != c && GDK_WINDOW_TYPE (win) != GDK_WINDOW_ROOT)
8519 send_crossing_event (display, toplevel,
8520 win, GDK_LEAVE_NOTIFY,
8524 toplevel_x, toplevel_y,
8530 win = get_event_parent (win);
8535 if (b) /* Might not be a dest, e.g. if we're moving out of the window */
8537 toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)b);
8539 /* Traverse down from c to b */
8543 win = get_event_parent (b);
8544 while (win != c && GDK_WINDOW_TYPE (win) != GDK_WINDOW_ROOT)
8546 path = g_list_prepend (path, win);
8547 win = get_event_parent (win);
8551 notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
8553 notify_type = GDK_NOTIFY_VIRTUAL;
8558 win = (GdkWindowObject *)list->data;
8559 list = g_list_next (list);
8561 next = (GdkWindowObject *)list->data;
8565 send_crossing_event (display, toplevel,
8566 win, GDK_ENTER_NOTIFY,
8570 toplevel_x, toplevel_y,
8580 notify_type = GDK_NOTIFY_NONLINEAR;
8582 notify_type = GDK_NOTIFY_ANCESTOR;
8584 notify_type = GDK_NOTIFY_INFERIOR;
8586 send_crossing_event (display, toplevel,
8587 b, GDK_ENTER_NOTIFY,
8591 toplevel_x, toplevel_y,
8598 /* Returns the window inside the event window with the pointer in it
8599 * at the specified coordinates, or NULL if its not in any child of
8600 * the toplevel. It also takes into account !owner_events grabs.
8603 get_pointer_window (GdkDisplay *display,
8604 GdkWindow *event_window,
8609 GdkWindow *pointer_window;
8610 GdkPointerGrabInfo *grab;
8612 if (event_window == display->pointer_info.toplevel_under_pointer)
8614 _gdk_window_find_descendant_at (event_window,
8615 toplevel_x, toplevel_y,
8618 pointer_window = NULL;
8620 grab = _gdk_display_has_pointer_grab (display, serial);
8622 !grab->owner_events &&
8623 pointer_window != grab->window)
8624 pointer_window = NULL;
8626 return pointer_window;
8630 _gdk_display_set_window_under_pointer (GdkDisplay *display,
8633 GdkWindowObject *private;
8635 private = (GdkWindowObject *)window;
8637 if (display->pointer_info.window_under_pointer)
8638 g_object_unref (display->pointer_info.window_under_pointer);
8639 display->pointer_info.window_under_pointer = window;
8641 g_object_ref (window);
8644 update_cursor (display);
8646 _gdk_display_enable_motion_hints (display);
8650 gdk_window_get_offscreen_parent (GdkWindow *window)
8652 GdkWindowObject *private = (GdkWindowObject *)window;
8656 g_signal_emit (private->impl_window,
8657 signals[GET_OFFSCREEN_PARENT], 0,
8664 *--------------------------------------------------------------
8667 * Grabs the pointer to a specific window
8670 * "window" is the window which will receive the grab
8671 * "owner_events" specifies whether events will be reported as is,
8672 * or relative to "window"
8673 * "event_mask" masks only interesting events
8674 * "confine_to" limits the cursor movement to the specified window
8675 * "cursor" changes the cursor for the duration of the grab
8676 * "time" specifies the time
8681 * requires a corresponding call to gdk_pointer_ungrab
8683 *--------------------------------------------------------------
8686 gdk_pointer_grab (GdkWindow * window,
8687 gboolean owner_events,
8688 GdkEventMask event_mask,
8689 GdkWindow * confine_to,
8694 GdkDisplay *display;
8698 g_return_val_if_fail (window != NULL, 0);
8699 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
8700 g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
8702 /* We need a native window for confine to to work, ensure we have one */
8705 if (!gdk_window_ensure_native (confine_to))
8707 g_warning ("Can't confine to grabbed window, not native");
8712 /* Non-viewable client side window => fail */
8713 if (!_gdk_window_has_impl (window) &&
8714 !gdk_window_is_viewable (window))
8715 return GDK_GRAB_NOT_VIEWABLE;
8717 native = gdk_window_get_toplevel (window);
8718 while (gdk_window_is_offscreen ((GdkWindowObject *)native))
8720 native = gdk_window_get_offscreen_parent (native);
8722 if (native == NULL ||
8723 (!_gdk_window_has_impl (native) &&
8724 !gdk_window_is_viewable (native)))
8725 return GDK_GRAB_NOT_VIEWABLE;
8727 native = gdk_window_get_toplevel (native);
8730 display = gdk_drawable_get_display (window);
8732 serial = _gdk_windowing_window_get_next_serial (display);
8734 res = _gdk_windowing_pointer_grab (window,
8742 if (res == GDK_GRAB_SUCCESS)
8743 _gdk_display_add_pointer_grab (display,
8756 gdk_window_set_has_offscreen_children (GdkWindow *window,
8757 gboolean has_offscreen_children)
8759 GdkWindowObject *private = (GdkWindowObject *)window;
8761 private->has_offscreen_children = !!has_offscreen_children;
8765 gdk_window_get_has_offscreen_children (GdkWindow *window)
8767 GdkWindowObject *private = (GdkWindowObject *)window;
8769 return private->has_offscreen_children;
8773 gdk_window_offscreen_children_changed (GdkWindow *window)
8775 _gdk_synthesize_crossing_events_for_geometry_change (window);
8779 do_synthesize_crossing_event (gpointer data)
8781 GdkDisplay *display;
8782 GdkWindow *changed_toplevel;
8783 GdkWindowObject *changed_toplevel_priv;
8784 GdkWindow *new_window_under_pointer;
8787 changed_toplevel = data;
8788 changed_toplevel_priv = (GdkWindowObject *)changed_toplevel;
8790 changed_toplevel_priv->synthesize_crossing_event_queued = FALSE;
8792 if (GDK_WINDOW_DESTROYED (changed_toplevel))
8795 display = gdk_drawable_get_display (changed_toplevel);
8796 serial = _gdk_windowing_window_get_next_serial (display);
8798 if (changed_toplevel == display->pointer_info.toplevel_under_pointer)
8800 new_window_under_pointer =
8801 get_pointer_window (display, changed_toplevel,
8802 display->pointer_info.toplevel_x,
8803 display->pointer_info.toplevel_y,
8805 if (new_window_under_pointer !=
8806 display->pointer_info.window_under_pointer)
8808 _gdk_synthesize_crossing_events (display,
8809 display->pointer_info.window_under_pointer,
8810 new_window_under_pointer,
8811 GDK_CROSSING_NORMAL,
8812 display->pointer_info.toplevel_x,
8813 display->pointer_info.toplevel_y,
8814 display->pointer_info.state,
8818 _gdk_display_set_window_under_pointer (display, new_window_under_pointer);
8826 _gdk_synthesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
8828 GdkDisplay *display;
8829 GdkWindow *toplevel;
8830 GdkWindowObject *toplevel_priv;
8832 display = gdk_drawable_get_display (changed_window);
8834 toplevel = get_event_toplevel (changed_window);
8835 toplevel_priv = (GdkWindowObject *)toplevel;
8837 if (toplevel == display->pointer_info.toplevel_under_pointer &&
8838 !toplevel_priv->synthesize_crossing_event_queued)
8840 toplevel_priv->synthesize_crossing_event_queued = TRUE;
8841 g_idle_add_full (GDK_PRIORITY_EVENTS - 1,
8842 do_synthesize_crossing_event,
8843 g_object_ref (toplevel),
8848 /* Don't use for crossing events */
8850 get_event_window (GdkDisplay *display,
8851 GdkWindow *pointer_window,
8853 GdkModifierType mask,
8858 GdkWindow *grab_window;
8860 GdkPointerGrabInfo *grab;
8862 grab = _gdk_display_has_pointer_grab (display, serial);
8864 if (grab != NULL && !grab->owner_events)
8866 evmask = grab->event_mask;
8867 evmask = update_evmask_for_button_motion (evmask, mask);
8869 grab_window = grab->window;
8871 if (evmask & type_masks[type])
8874 *evmask_out = evmask;
8881 w = (GdkWindowObject *)pointer_window;
8884 evmask = w->event_mask;
8885 evmask = update_evmask_for_button_motion (evmask, mask);
8887 if (evmask & type_masks[type])
8890 *evmask_out = evmask;
8891 return (GdkWindow *)w;
8894 w = get_event_parent (w);
8900 evmask = grab->event_mask;
8901 evmask = update_evmask_for_button_motion (evmask, mask);
8903 if (evmask & type_masks[type])
8906 *evmask_out = evmask;
8907 return grab->window;
8917 proxy_pointer_event (GdkDisplay *display,
8918 GdkEvent *source_event,
8921 GdkWindow *toplevel_window, *event_window;
8922 GdkWindow *pointer_window;
8925 gdouble toplevel_x, toplevel_y;
8928 event_window = source_event->any.window;
8929 gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
8930 gdk_event_get_state (source_event, &state);
8931 time_ = gdk_event_get_time (source_event);
8932 toplevel_window = convert_native_coords_to_toplevel (event_window,
8933 toplevel_x, toplevel_y,
8934 &toplevel_x, &toplevel_y);
8937 /* If we get crossing events with subwindow unexpectedly being NULL
8938 that means there is a native subwindow that gdk doesn't know about.
8939 We track these and forward them, with the correct virtual window
8941 This is important to get right, as metacity uses gdk for the frame
8942 windows, but gdk doesn't know about the client windows reparented
8944 if (((source_event->type == GDK_LEAVE_NOTIFY &&
8945 source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
8946 (source_event->type == GDK_ENTER_NOTIFY &&
8947 (source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
8948 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
8949 source_event->crossing.subwindow == NULL)
8951 /* Left for an unknown (to gdk) subwindow */
8953 /* Send leave events from window under pointer to event window
8954 that will get the subwindow == NULL window */
8955 _gdk_synthesize_crossing_events (display,
8956 display->pointer_info.window_under_pointer,
8958 source_event->crossing.mode,
8959 toplevel_x, toplevel_y,
8964 /* Send subwindow == NULL event */
8965 send_crossing_event (display,
8966 (GdkWindowObject *)toplevel_window,
8967 (GdkWindowObject *)event_window,
8969 source_event->crossing.mode,
8970 source_event->crossing.detail,
8972 toplevel_x, toplevel_y,
8977 _gdk_display_set_window_under_pointer (display, NULL);
8981 pointer_window = get_pointer_window (display, toplevel_window,
8982 toplevel_x, toplevel_y, serial);
8984 if (((source_event->type == GDK_ENTER_NOTIFY &&
8985 source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
8986 (source_event->type == GDK_LEAVE_NOTIFY &&
8987 (source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
8988 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
8989 source_event->crossing.subwindow == NULL)
8991 /* Entered from an unknown (to gdk) subwindow */
8993 /* Send subwindow == NULL event */
8994 send_crossing_event (display,
8995 (GdkWindowObject *)toplevel_window,
8996 (GdkWindowObject *)event_window,
8998 source_event->crossing.mode,
8999 source_event->crossing.detail,
9001 toplevel_x, toplevel_y,
9006 /* Send enter events from event window to pointer_window */
9007 _gdk_synthesize_crossing_events (display,
9010 source_event->crossing.mode,
9011 toplevel_x, toplevel_y,
9015 _gdk_display_set_window_under_pointer (display, pointer_window);
9019 if (display->pointer_info.window_under_pointer != pointer_window)
9021 /* Either a toplevel crossing notify that ended up inside a child window,
9022 or a motion notify that got into another child window */
9024 /* Different than last time, send crossing events */
9025 _gdk_synthesize_crossing_events (display,
9026 display->pointer_info.window_under_pointer,
9028 GDK_CROSSING_NORMAL,
9029 toplevel_x, toplevel_y,
9033 _gdk_display_set_window_under_pointer (display, pointer_window);
9035 else if (source_event->type == GDK_MOTION_NOTIFY)
9037 GdkWindow *event_win;
9041 event_win = get_event_window (display,
9051 (evmask & GDK_POINTER_MOTION_HINT_MASK))
9053 if (display->pointer_info.motion_hint_serial != 0 &&
9054 serial < display->pointer_info.motion_hint_serial)
9055 event_win = NULL; /* Ignore event */
9059 display->pointer_info.motion_hint_serial = G_MAXULONG;
9063 if (event_win && !display->ignore_core_events)
9065 event = _gdk_make_event (event_win, GDK_MOTION_NOTIFY, source_event, FALSE);
9066 event->motion.time = time_;
9067 convert_toplevel_coords_to_window (event_win,
9068 toplevel_x, toplevel_y,
9069 &event->motion.x, &event->motion.y);
9070 event->motion.x_root = source_event->motion.x_root;
9071 event->motion.y_root = source_event->motion.y_root;;
9072 event->motion.state = state;
9073 event->motion.is_hint = is_hint;
9074 event->motion.device = NULL;
9075 event->motion.device = source_event->motion.device;
9079 /* unlink all move events from queue.
9080 We handle our own, including our emulated masks. */
9084 #define GDK_ANY_BUTTON_MASK (GDK_BUTTON1_MASK | \
9085 GDK_BUTTON2_MASK | \
9086 GDK_BUTTON3_MASK | \
9087 GDK_BUTTON4_MASK | \
9091 proxy_button_event (GdkEvent *source_event,
9094 GdkWindow *toplevel_window, *event_window;
9095 GdkWindow *event_win;
9096 GdkWindow *pointer_window;
9097 GdkWindowObject *parent;
9102 gdouble toplevel_x, toplevel_y;
9103 GdkDisplay *display;
9106 type = source_event->any.type;
9107 event_window = source_event->any.window;
9108 gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
9109 gdk_event_get_state (source_event, &state);
9110 time_ = gdk_event_get_time (source_event);
9111 display = gdk_drawable_get_display (source_event->any.window);
9112 toplevel_window = convert_native_coords_to_toplevel (event_window,
9113 toplevel_x, toplevel_y,
9114 &toplevel_x, &toplevel_y);
9116 if (type == GDK_BUTTON_PRESS &&
9117 _gdk_display_has_pointer_grab (display, serial) == NULL)
9120 _gdk_window_find_descendant_at (toplevel_window,
9121 toplevel_x, toplevel_y,
9124 /* Find the event window, that gets the grab */
9125 w = (GdkWindowObject *)pointer_window;
9127 (parent = get_event_parent (w)) != NULL &&
9128 parent->window_type != GDK_WINDOW_ROOT)
9130 if (w->event_mask & GDK_BUTTON_PRESS_MASK)
9134 pointer_window = (GdkWindow *)w;
9136 _gdk_display_add_pointer_grab (display,
9140 gdk_window_get_events (pointer_window),
9144 _gdk_display_pointer_grab_update (display, serial);
9147 pointer_window = get_pointer_window (display, toplevel_window,
9148 toplevel_x, toplevel_y,
9151 event_win = get_event_window (display,
9156 if (event_win == NULL || display->ignore_core_events)
9159 event = _gdk_make_event (event_win, type, source_event, FALSE);
9163 case GDK_BUTTON_PRESS:
9164 case GDK_BUTTON_RELEASE:
9165 event->button.button = source_event->button.button;
9166 convert_toplevel_coords_to_window (event_win,
9167 toplevel_x, toplevel_y,
9168 &event->button.x, &event->button.y);
9169 event->button.x_root = source_event->button.x_root;
9170 event->button.y_root = source_event->button.y_root;
9171 event->button.state = state;
9172 event->button.device = source_event->button.device;
9174 if (type == GDK_BUTTON_PRESS)
9175 _gdk_event_button_generate (display, event);
9179 event->scroll.direction = source_event->scroll.direction;
9180 convert_toplevel_coords_to_window (event_win,
9181 toplevel_x, toplevel_y,
9182 &event->scroll.x, &event->scroll.y);
9183 event->scroll.x_root = source_event->scroll.x_root;
9184 event->scroll.y_root = source_event->scroll.y_root;
9185 event->scroll.state = state;
9186 event->scroll.device = source_event->scroll.device;
9193 return TRUE; /* Always unlink original, we want to obey the emulated event mask */
9196 #ifdef DEBUG_WINDOW_PRINTING
9198 gdk_window_print (GdkWindowObject *window,
9203 g_print ("%*s%p: [%s] %d,%d %dx%d", indent, "", window,
9204 window->user_data ? g_type_name_from_instance (window->user_data) : "no widget",
9205 window->x, window->y,
9206 window->width, window->height
9209 if (gdk_window_has_impl (window))
9211 #ifdef GDK_WINDOWING_X11
9212 g_print (" impl(0x%lx)", gdk_x11_drawable_get_xid (GDK_DRAWABLE (window)));
9216 if (window->input_only)
9217 g_print (" input-only");
9219 if (!gdk_window_is_visible ((GdkWindow *)window))
9220 g_print (" hidden");
9222 g_print (" abs[%d,%d]",
9223 window->abs_x, window->abs_y);
9225 gdk_region_get_clipbox (window->clip_region, &r);
9226 if (gdk_region_empty (window->clip_region))
9227 g_print (" clipbox[empty]");
9229 g_print (" clipbox[%d,%d %dx%d]", r.x, r.y, r.width, r.height);
9236 gdk_window_print_tree (GdkWindow *window,
9238 gboolean include_input_only)
9240 GdkWindowObject *private;
9243 private = (GdkWindowObject *)window;
9245 if (private->input_only && !include_input_only)
9248 gdk_window_print (private, indent);
9250 for (l = private->children; l != NULL; l = l->next)
9251 gdk_window_print_tree (l->data, indent + 4, include_input_only);
9254 #endif /* DEBUG_WINDOW_PRINTING */
9257 is_input_event (GdkDisplay *display,
9260 GdkDevice *core_pointer;
9262 core_pointer = gdk_display_get_core_pointer (display);
9263 if ((event->type == GDK_MOTION_NOTIFY &&
9264 event->motion.device != core_pointer) ||
9265 ((event->type == GDK_BUTTON_PRESS ||
9266 event->type == GDK_BUTTON_RELEASE) &&
9267 event->button.device != core_pointer))
9273 _gdk_windowing_got_event (GdkDisplay *display,
9278 GdkWindow *event_window;
9279 GdkWindowObject *event_private;
9281 gboolean unlink_event;
9282 guint old_state, old_button;
9283 GdkPointerGrabInfo *button_release_grab;
9284 gboolean is_toplevel;
9286 if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
9287 display->last_event_time = gdk_event_get_time (event);
9289 _gdk_display_pointer_grab_update (display,
9292 event_window = event->any.window;
9296 event_private = GDK_WINDOW_OBJECT (event_window);
9298 #ifdef DEBUG_WINDOW_PRINTING
9299 if (event->type == GDK_KEY_PRESS &&
9300 (event->key.keyval == 0xa7 ||
9301 event->key.keyval == 0xbd))
9303 gdk_window_print_tree (event_window, 0,
9304 event->key.keyval == 0xbd);
9308 if (event->type == GDK_VISIBILITY_NOTIFY)
9310 event_private->native_visibility = event->visibility.state;
9311 gdk_window_update_visibility_recursively (event_private,
9316 if (is_input_event (display, event))
9319 if (!(is_button_type (event->type) ||
9320 is_motion_type (event->type)) ||
9321 GDK_WINDOW_TYPE (event_private) == GDK_WINDOW_ROOT)
9325 event_private->parent == NULL ||
9326 GDK_WINDOW_TYPE (event_private->parent) == GDK_WINDOW_ROOT;
9328 if ((event->type == GDK_ENTER_NOTIFY ||
9329 event->type == GDK_LEAVE_NOTIFY) &&
9330 (event->crossing.mode == GDK_CROSSING_GRAB ||
9331 event->crossing.mode == GDK_CROSSING_UNGRAB) &&
9332 (_gdk_display_has_pointer_grab (display, serial) ||
9333 event->crossing.detail == GDK_NOTIFY_INFERIOR))
9335 /* We synthesize all crossing events due to grabs ourselves,
9336 * so we ignore the native ones caused by our native pointer_grab
9337 * calls. Otherwise we would proxy these crossing event and cause
9338 * multiple copies of crossing events for grabs.
9340 * We do want to handle grabs from other clients though, as for
9341 * instance alt-tab in metacity causes grabs like these and
9342 * we want to handle those. Thus the has_pointer_grab check.
9344 * Implicit grabs on child windows create some grabbing events
9345 * that are sent before the button press. This means we can't
9346 * detect these with the has_pointer_grab check (as the implicit
9347 * grab is only noticed when we get button press event), so we
9348 * detect these events by checking for INFERIOR enter or leave
9349 * events. These should never be a problem to filter out.
9352 /* We ended up in this window after some (perhaps other clients)
9353 grab, so update the toplevel_under_window state */
9355 event->type == GDK_ENTER_NOTIFY &&
9356 event->crossing.mode == GDK_CROSSING_UNGRAB)
9358 if (display->pointer_info.toplevel_under_pointer)
9359 g_object_unref (display->pointer_info.toplevel_under_pointer);
9360 display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
9363 unlink_event = TRUE;
9367 /* Track toplevel_under_pointer */
9370 if (event->type == GDK_ENTER_NOTIFY &&
9371 event->crossing.detail != GDK_NOTIFY_INFERIOR)
9373 if (display->pointer_info.toplevel_under_pointer)
9374 g_object_unref (display->pointer_info.toplevel_under_pointer);
9375 display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
9377 else if (event->type == GDK_LEAVE_NOTIFY &&
9378 event->crossing.detail != GDK_NOTIFY_INFERIOR &&
9379 display->pointer_info.toplevel_under_pointer == event_window)
9381 if (display->pointer_info.toplevel_under_pointer)
9382 g_object_unref (display->pointer_info.toplevel_under_pointer);
9383 display->pointer_info.toplevel_under_pointer = NULL;
9387 /* Store last pointer window and position/state */
9388 old_state = display->pointer_info.state;
9389 old_button = display->pointer_info.button;
9391 gdk_event_get_coords (event, &x, &y);
9392 convert_native_coords_to_toplevel (event_window, x, y, &x, &y);
9393 display->pointer_info.toplevel_x = x;
9394 display->pointer_info.toplevel_y = y;
9395 gdk_event_get_state (event, &display->pointer_info.state);
9396 if (event->type == GDK_BUTTON_PRESS ||
9397 event->type == GDK_BUTTON_RELEASE)
9398 display->pointer_info.button = event->button.button;
9400 if (display->pointer_info.state != old_state ||
9401 display->pointer_info.button != old_button)
9402 _gdk_display_enable_motion_hints (display);
9404 unlink_event = FALSE;
9405 if (is_motion_type (event->type))
9406 unlink_event = proxy_pointer_event (display,
9409 else if (is_button_type (event->type))
9410 unlink_event = proxy_button_event (event,
9413 if (event->type == GDK_BUTTON_RELEASE)
9415 button_release_grab =
9416 _gdk_display_has_pointer_grab (display, serial);
9417 if (button_release_grab &&
9418 button_release_grab->implicit &&
9419 (event->button.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
9421 button_release_grab->serial_end = serial;
9422 button_release_grab->implicit_ungrab = TRUE;
9423 _gdk_display_pointer_grab_update (display, serial);
9430 _gdk_event_queue_remove_link (display, event_link);
9431 g_list_free_1 (event_link);
9432 gdk_event_free (event);
9438 get_extension_event_window (GdkDisplay *display,
9439 GdkWindow *pointer_window,
9444 GdkWindow *grab_window;
9446 GdkPointerGrabInfo *grab;
9448 grab = _gdk_display_has_pointer_grab (display, serial);
9450 if (grab != NULL && !grab->owner_events)
9452 evmask = grab->event_mask;
9454 grab_window = grab->window;
9456 if (evmask & type_masks[type])
9462 w = (GdkWindowObject *)pointer_window;
9465 evmask = w->extension_events;
9467 if (evmask & type_masks[type])
9468 return (GdkWindow *)w;
9470 w = get_event_parent (w);
9476 evmask = grab->event_mask;
9478 if (evmask & type_masks[type])
9479 return grab->window;
9489 _gdk_window_get_input_window_for_event (GdkWindow *native_window,
9490 GdkEventType event_type,
9494 GdkDisplay *display;
9495 GdkWindow *toplevel_window;
9496 GdkWindow *pointer_window;
9497 GdkWindow *event_win;
9498 gdouble toplevel_x, toplevel_y;
9503 display = gdk_drawable_get_display (native_window);
9504 toplevel_window = convert_native_coords_to_toplevel (native_window,
9505 toplevel_x, toplevel_y,
9506 &toplevel_x, &toplevel_y);
9507 pointer_window = get_pointer_window (display, toplevel_window,
9508 toplevel_x, toplevel_y, serial);
9509 event_win = get_extension_event_window (display,
9518 #define __GDK_WINDOW_C__
9519 #include "gdkaliasdef.c"