1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-2007 Peter Mattis, Spencer Kimball,
3 * Josh MacDonald, Ryan Lortie
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
22 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
23 * file for a list of people on the GTK+ Team. See the ChangeLog
24 * files for a list of changes. These files are distributed with
25 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
29 #include "gdkwindow.h"
30 #include "gdkwindowimpl.h"
31 #include "gdkinternals.h"
32 #include "gdk.h" /* For gdk_rectangle_union() */
33 #include "gdkpixmap.h"
34 #include "gdkdrawable.h"
35 #include "gdkscreen.h"
36 #include "gdkmarshalers.h"
39 #undef DEBUG_WINDOW_PRINTING
41 #ifdef GDK_WINDOWING_X11
42 #include "x11/gdkx.h" /* For workaround */
47 /* Historically a GdkWindow always matches a platform native window,
48 * be it a toplevel window or a child window. In this setup the
49 * GdkWindow (and other GdkDrawables) were platform independent classes,
50 * and the actual platform specific implementation was in a delegate
51 * object availible as "impl" in the window object.
53 * With the addition of client side windows and offscreen windows this
54 * changes a bit. The application-visible GdkWindow object behaves as
55 * it did before, but not all such windows now have a corresponding native
56 * window. Instead windows that are "client side" are emulated by the gdk
57 * code such that clipping, drawing, moving, events etc work as expected.
59 * For GdkWindows that have a native window the "impl" object is the
60 * same as before. However, for all client side windows the impl object
61 * is shared with its parent (i.e. all client windows descendants of one
62 * native window has the same impl.
64 * Additionally there is a new type of platform independent impl object,
65 * GdkOffscreenWindow. All windows of type GDK_WINDOW_OFFSCREEN get an impl
66 * of this type (while their children are generally GDK_WINDOW_CHILD virtual
67 * windows). Such windows work by allocating a GdkPixmap as the backing store
68 * for drawing operations, which is resized with the window.
70 * GdkWindows have a pointer to the "impl window" they are in, i.e.
71 * the topmost GdkWindow which have the same "impl" value. This is stored
72 * in impl_window, which is different from the window itself only for client
74 * All GdkWindows (native or not) track the position of the window in the parent
75 * (x, y), the size of the window (width, height), the position of the window
76 * with respect to the impl window (abs_x, abs_y). We also track the clip
77 * region of the window wrt parent windows and siblings, in window-relative
78 * coordinates with and without child windows included (clip_region,
79 * clip_region_with_children).
81 * All toplevel windows are native windows, but also child windows can be
82 * native (although not children of offscreens). We always listen to
83 * a basic set of events (see get_native_event_mask) for these windows
84 * so that we can emulate events for any client side children.
86 * For native windows we apply the calculated clip region as a window shape
87 * so that eg. client side siblings that overlap the native child properly
88 * draws over the native child window.
90 * In order to minimize flicker and for performance we use a couple of cacheing
91 * tricks. First of all, every time we do a window to window copy area, for instance
92 * when moving a client side window or when scrolling/moving a region in a window
93 * we store this in outstanding_moves instead of applying immediately. We then
94 * delay this move until we really need it (because something depends on being
95 * able to read it), or until we're handing a redraw from an expose/invalidation
96 * (actually we delay it past redraw, but before blitting the double buffer pixmap
97 * to the window). This gives us two advantages. First of all it minimizes the time
98 * from the window is moved to the exposes related to that move, secondly it allows
99 * us to be smart about how to do the copy. We combine multiple moves into one (when
100 * possible) and we don't actually do copies to anything that is or will be
101 * invalidated and exposed anyway.
103 * Secondly, we use something called a "implicit paint" during repaint handling.
104 * An implicit paint is similar to a regular paint for the paint stack, but it is
105 * not put on the stack. Instead, it is set on the impl window, and later when
106 * regular gdk_window_begin_paint_region() happen on a window of this impl window
107 * we reuse the pixmap from the implicit paint. During repaint we create and at the
108 * end flush an implicit paint, which means we can collect all the paints on
109 * multiple client side windows in the same backing store pixmap.
111 * All drawing to windows are wrapped with macros that set up the GC such that
112 * the offsets and clip region is right for drawing to the paint object or
113 * directly to the emulated window. It also automatically handles any flushing
114 * needed when drawing directly to a window. Adding window/paint clipping is
115 * done using _gdk_gc_add_drawable_clip which lets us efficiently add and then
116 * remove a custom clip region.
119 #define USE_BACKING_STORE /* Appears to work on Win32, too, now. */
121 /* This adds a local value to the GdkVisibilityState enum */
122 #define GDK_VISIBILITY_NOT_VIEWABLE 3
125 PICK_EMBEDDED_CHILD, /* only called if children are embedded */
131 struct _GdkWindowPaint
137 cairo_surface_t *surface;
138 guint uses_implicit : 1;
143 GdkRegion *dest_region; /* The destination region */
144 int dx, dy; /* The amount that the source was moved to reach dest_region */
145 } GdkWindowRegionMove;
150 static GdkGC *gdk_window_create_gc (GdkDrawable *drawable,
152 GdkGCValuesMask mask);
153 static void gdk_window_draw_rectangle (GdkDrawable *drawable,
160 static void gdk_window_draw_arc (GdkDrawable *drawable,
169 static void gdk_window_draw_polygon (GdkDrawable *drawable,
174 static void gdk_window_draw_text (GdkDrawable *drawable,
181 static void gdk_window_draw_text_wc (GdkDrawable *drawable,
186 const GdkWChar *text,
188 static void gdk_window_draw_drawable (GdkDrawable *drawable,
197 GdkDrawable *original_src);
198 static void gdk_window_draw_points (GdkDrawable *drawable,
202 static void gdk_window_draw_segments (GdkDrawable *drawable,
206 static void gdk_window_draw_lines (GdkDrawable *drawable,
211 static void gdk_window_draw_glyphs (GdkDrawable *drawable,
216 PangoGlyphString *glyphs);
217 static void gdk_window_draw_glyphs_transformed (GdkDrawable *drawable,
223 PangoGlyphString *glyphs);
225 static void gdk_window_draw_image (GdkDrawable *drawable,
235 static void gdk_window_draw_pixbuf (GdkDrawable *drawable,
248 static void gdk_window_draw_trapezoids (GdkDrawable *drawable,
250 GdkTrapezoid *trapezoids,
253 static GdkImage* gdk_window_copy_to_image (GdkDrawable *drawable,
262 static cairo_surface_t *gdk_window_ref_cairo_surface (GdkDrawable *drawable);
263 static cairo_surface_t *gdk_window_create_cairo_surface (GdkDrawable *drawable,
266 static void gdk_window_set_cairo_clip (GdkDrawable *drawable,
269 static void gdk_window_real_get_size (GdkDrawable *drawable,
273 static GdkVisual* gdk_window_real_get_visual (GdkDrawable *drawable);
274 static gint gdk_window_real_get_depth (GdkDrawable *drawable);
275 static GdkScreen* gdk_window_real_get_screen (GdkDrawable *drawable);
276 static void gdk_window_real_set_colormap (GdkDrawable *drawable,
278 static GdkColormap* gdk_window_real_get_colormap (GdkDrawable *drawable);
280 static GdkDrawable* gdk_window_get_source_drawable (GdkDrawable *drawable);
281 static GdkDrawable* gdk_window_get_composite_drawable (GdkDrawable *drawable,
286 gint *composite_x_offset,
287 gint *composite_y_offset);
288 static GdkRegion* gdk_window_get_clip_region (GdkDrawable *drawable);
289 static GdkRegion* gdk_window_get_visible_region (GdkDrawable *drawable);
291 static void gdk_window_free_paint_stack (GdkWindow *window);
293 static void gdk_window_init (GdkWindowObject *window);
294 static void gdk_window_class_init (GdkWindowObjectClass *klass);
295 static void gdk_window_finalize (GObject *object);
296 static void gdk_window_clear_backing_region (GdkWindow *window,
298 static void gdk_window_redirect_free (GdkWindowRedirect *redirect);
299 static void apply_redirect_to_children (GdkWindowObject *private,
300 GdkWindowRedirect *redirect);
301 static void remove_redirect_from_children (GdkWindowObject *private,
302 GdkWindowRedirect *redirect);
304 static void recompute_visible_regions (GdkWindowObject *private,
305 gboolean recalculate_siblings,
306 gboolean recalculate_children);
307 static void gdk_window_flush_outstanding_moves (GdkWindow *window);
308 static void gdk_window_flush (GdkWindow *window);
309 static void gdk_window_flush_recursive (GdkWindowObject *window);
310 static void do_move_region_bits_on_impl (GdkWindowObject *private,
311 GdkRegion *region, /* In impl window coords */
313 static void gdk_window_invalidate_in_parent (GdkWindowObject *private);
314 static void move_native_children (GdkWindowObject *private);
315 static void update_cursor (GdkDisplay *display);
317 static guint signals[LAST_SIGNAL] = { 0 };
319 static gpointer parent_class = NULL;
321 static const cairo_user_data_key_t gdk_window_cairo_key;
324 new_region_tag (void)
326 static guint32 tag = 0;
332 gdk_window_object_get_type (void)
334 static GType object_type = 0;
337 object_type = g_type_register_static_simple (GDK_TYPE_DRAWABLE,
339 sizeof (GdkWindowObjectClass),
340 (GClassInitFunc) gdk_window_class_init,
341 sizeof (GdkWindowObject),
342 (GInstanceInitFunc) gdk_window_init,
349 _gdk_paintable_get_type (void)
351 static GType paintable_type = 0;
355 const GTypeInfo paintable_info =
357 sizeof (GdkPaintableIface), /* class_size */
358 NULL, /* base_init */
359 NULL, /* base_finalize */
362 paintable_type = g_type_register_static (G_TYPE_INTERFACE,
363 g_intern_static_string ("GdkPaintable"),
366 g_type_interface_add_prerequisite (paintable_type, G_TYPE_OBJECT);
369 return paintable_type;
373 gdk_window_init (GdkWindowObject *window)
375 /* 0-initialization is good for all other fields. */
377 window->window_type = GDK_WINDOW_CHILD;
379 window->state = GDK_WINDOW_STATE_WITHDRAWN;
382 window->toplevel_window_type = -1;
384 window->effective_visibility = GDK_VISIBILITY_NOT_VIEWABLE;
385 window->visibility = GDK_VISIBILITY_FULLY_OBSCURED;
386 /* Default to unobscured since some backends don't send visibility events */
387 window->native_visibility = GDK_VISIBILITY_UNOBSCURED;
390 /* Stop and return on the first non-NULL parent */
392 accumulate_get_window (GSignalInvocationHint *ihint,
394 const GValue *handler_return,
397 g_value_copy (handler_return, return_accu);
398 /* Continue while returning NULL */
399 return g_value_get_object (handler_return) == NULL;
402 static GQuark quark_pointer_window = 0;
405 gdk_window_class_init (GdkWindowObjectClass *klass)
407 GObjectClass *object_class = G_OBJECT_CLASS (klass);
408 GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
410 parent_class = g_type_class_peek_parent (klass);
412 object_class->finalize = gdk_window_finalize;
414 drawable_class->create_gc = gdk_window_create_gc;
415 drawable_class->draw_rectangle = gdk_window_draw_rectangle;
416 drawable_class->draw_arc = gdk_window_draw_arc;
417 drawable_class->draw_polygon = gdk_window_draw_polygon;
418 drawable_class->draw_text = gdk_window_draw_text;
419 drawable_class->draw_text_wc = gdk_window_draw_text_wc;
420 drawable_class->draw_drawable_with_src = gdk_window_draw_drawable;
421 drawable_class->draw_points = gdk_window_draw_points;
422 drawable_class->draw_segments = gdk_window_draw_segments;
423 drawable_class->draw_lines = gdk_window_draw_lines;
424 drawable_class->draw_glyphs = gdk_window_draw_glyphs;
425 drawable_class->draw_glyphs_transformed = gdk_window_draw_glyphs_transformed;
426 drawable_class->draw_image = gdk_window_draw_image;
427 drawable_class->draw_pixbuf = gdk_window_draw_pixbuf;
428 drawable_class->draw_trapezoids = gdk_window_draw_trapezoids;
429 drawable_class->get_depth = gdk_window_real_get_depth;
430 drawable_class->get_screen = gdk_window_real_get_screen;
431 drawable_class->get_size = gdk_window_real_get_size;
432 drawable_class->set_colormap = gdk_window_real_set_colormap;
433 drawable_class->get_colormap = gdk_window_real_get_colormap;
434 drawable_class->get_visual = gdk_window_real_get_visual;
435 drawable_class->_copy_to_image = gdk_window_copy_to_image;
436 drawable_class->ref_cairo_surface = gdk_window_ref_cairo_surface;
437 drawable_class->create_cairo_surface = gdk_window_create_cairo_surface;
438 drawable_class->set_cairo_clip = gdk_window_set_cairo_clip;
439 drawable_class->get_clip_region = gdk_window_get_clip_region;
440 drawable_class->get_visible_region = gdk_window_get_visible_region;
441 drawable_class->get_composite_drawable = gdk_window_get_composite_drawable;
442 drawable_class->get_source_drawable = gdk_window_get_source_drawable;
444 quark_pointer_window = g_quark_from_static_string ("gtk-pointer-window");
448 * GdkWindow::pick-embedded-child:
449 * @window: the window on which the signal is emitted
450 * @x: x coordinate in the window
451 * @y: y coordinate in the window
453 * The ::pick-embedded-child signal is emitted to find an embedded
454 * child at the given position.
456 * Returns: the GdkWindow of the embedded child at @x, @y, or %NULL
460 signals[PICK_EMBEDDED_CHILD] =
461 g_signal_new (g_intern_static_string ("pick-embedded-child"),
462 G_OBJECT_CLASS_TYPE (object_class),
465 accumulate_get_window, NULL,
466 _gdk_marshal_OBJECT__DOUBLE_DOUBLE,
473 * GdkWindow::to-embedder:
474 * @window: the offscreen window on which the signal is emitted
475 * @offscreen-x: x coordinate in the offscreen window
476 * @offscreen-y: y coordinate in the offscreen window
477 * @embedder-x: return location for the x coordinate in the embedder window
478 * @embedder-y: return location for the y coordinate in the embedder window
480 * The ::to-embedder signal is emitted to translate coordinates
481 * in an offscreen window to its embedder.
485 signals[TO_EMBEDDER] =
486 g_signal_new (g_intern_static_string ("to-embedder"),
487 G_OBJECT_CLASS_TYPE (object_class),
491 _gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
500 * GdkWindow::from-embedder:
501 * @window: the offscreen window on which the signal is emitted
502 * @embedder-x: x coordinate in the embedder window
503 * @embedder-y: y coordinate in the embedder window
504 * @offscreen-x: return location for the x coordinate in the offscreen window
505 * @offscreen-y: return location for the y coordinate in the offscreen window
507 * The ::from-embedder signal is emitted to translate coordinates
508 * in the embedder of an offscreen window to the offscreen window.
512 signals[FROM_EMBEDDER] =
513 g_signal_new (g_intern_static_string ("from-embedder"),
514 G_OBJECT_CLASS_TYPE (object_class),
518 _gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
528 gdk_window_finalize (GObject *object)
530 GdkWindow *window = GDK_WINDOW (object);
531 GdkWindowObject *obj = (GdkWindowObject *) object;
533 if (!GDK_WINDOW_DESTROYED (window))
535 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
537 g_warning ("losing last reference to undestroyed window\n");
538 _gdk_window_destroy (window, FALSE);
541 /* We use TRUE here, to keep us from actually calling
542 * XDestroyWindow() on the window
544 _gdk_window_destroy (window, TRUE);
549 g_object_unref (obj->impl);
553 if (obj->impl_window != obj)
555 g_object_unref (obj->impl_window);
556 obj->impl_window = NULL;
560 gdk_region_destroy (obj->shape);
562 if (obj->input_shape)
563 gdk_region_destroy (obj->input_shape);
566 gdk_cursor_unref (obj->cursor);
568 G_OBJECT_CLASS (parent_class)->finalize (object);
572 gdk_window_is_offscreen (GdkWindowObject *window)
574 return window->window_type == GDK_WINDOW_OFFSCREEN;
577 static GdkWindowObject *
578 gdk_window_get_impl_window (GdkWindowObject *window)
580 return window->impl_window;
584 _gdk_window_get_impl_window (GdkWindow *window)
586 return (GdkWindow *)gdk_window_get_impl_window ((GdkWindowObject *)window);
590 gdk_window_has_impl (GdkWindowObject *window)
592 return window->impl_window == window;
596 _gdk_window_has_impl (GdkWindow *window)
598 return gdk_window_has_impl ((GdkWindowObject *)window);
602 gdk_window_has_no_impl (GdkWindowObject *window)
604 return window->impl_window != window;
608 remove_child_area (GdkWindowObject *private,
609 GdkWindowObject *until,
613 GdkWindowObject *child;
614 GdkRegion *child_region;
619 for (l = private->children; l; l = l->next)
626 /* If region is empty already, no need to do
627 anything potentially costly */
628 if (gdk_region_empty (region))
631 if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
634 /* Ignore offscreen children, as they don't draw in their parent and
635 * don't take part in the clipping */
636 if (gdk_window_is_offscreen (child))
641 r.width = child->width;
642 r.height = child->height;
644 /* Bail early if child totally outside region */
645 if (gdk_region_rect_in (region, &r) == GDK_OVERLAP_RECTANGLE_OUT)
648 child_region = gdk_region_rectangle (&r);
652 /* Adjust shape region to parent window coords */
653 gdk_region_offset (child->shape, child->x, child->y);
654 gdk_region_intersect (child_region, child->shape);
655 gdk_region_offset (child->shape, -child->x, -child->y);
657 else if (private->window_type == GDK_WINDOW_FOREIGN)
659 shape = _gdk_windowing_window_get_shape ((GdkWindow *)child);
662 gdk_region_intersect (child_region, shape);
663 gdk_region_destroy (shape);
669 if (child->input_shape)
670 gdk_region_intersect (child_region, child->input_shape);
671 else if (private->window_type == GDK_WINDOW_FOREIGN)
673 shape = _gdk_windowing_window_get_input_shape ((GdkWindow *)child);
676 gdk_region_intersect (child_region, shape);
677 gdk_region_destroy (shape);
682 gdk_region_subtract (region, child_region);
683 gdk_region_destroy (child_region);
688 static GdkVisibilityState
689 effective_visibility (GdkWindowObject *private)
691 GdkVisibilityState native;
693 if (!gdk_window_is_viewable ((GdkWindow *)private))
694 return GDK_VISIBILITY_NOT_VIEWABLE;
696 native = private->impl_window->native_visibility;
698 if (native == GDK_VISIBILITY_FULLY_OBSCURED ||
699 private->visibility == GDK_VISIBILITY_FULLY_OBSCURED)
700 return GDK_VISIBILITY_FULLY_OBSCURED;
701 else if (native == GDK_VISIBILITY_UNOBSCURED)
702 return private->visibility;
703 else /* native PARTIAL, private partial or unobscured */
704 return GDK_VISIBILITY_PARTIAL;
708 gdk_window_update_visibility (GdkWindowObject *private)
710 GdkVisibilityState new_visibility;
713 new_visibility = effective_visibility (private);
715 if (new_visibility != private->effective_visibility)
717 private->effective_visibility = new_visibility;
719 if (new_visibility != GDK_VISIBILITY_NOT_VIEWABLE &&
720 private->event_mask & GDK_VISIBILITY_NOTIFY)
722 event = _gdk_make_event ((GdkWindow *)private, GDK_VISIBILITY_NOTIFY,
724 event->visibility.state = new_visibility;
730 gdk_window_update_visibility_recursively (GdkWindowObject *private,
731 GdkWindowObject *only_for_impl)
733 GdkWindowObject *child;
736 gdk_window_update_visibility (private);
737 for (l = private->children; l != NULL; l = l->next)
740 if ((only_for_impl == NULL) ||
741 (only_for_impl == child->impl_window))
742 gdk_window_update_visibility_recursively (child, only_for_impl);
747 recompute_visible_regions_internal (GdkWindowObject *private,
748 gboolean recalculate_clip,
749 gboolean recalculate_siblings,
750 gboolean recalculate_children)
754 GdkWindowObject *child;
755 GdkRegion *new_clip, *old_clip_region_with_children;
756 gboolean clip_region_changed;
757 gboolean abs_pos_changed;
758 int old_abs_x, old_abs_y;
760 old_abs_x = private->abs_x;
761 old_abs_y = private->abs_y;
763 /* Update absolute position */
764 if (gdk_window_has_impl (private))
766 /* Native window starts here */
772 private->abs_x = private->parent->abs_x + private->x;
773 private->abs_y = private->parent->abs_y + private->y;
777 private->abs_x != old_abs_x ||
778 private->abs_y != old_abs_y;
780 /* Update clip region based on:
783 * siblings in parents above window
785 clip_region_changed = FALSE;
786 if (recalculate_clip && private->viewable)
788 /* Calculate visible region (sans children) in parent window coords */
791 r.width = private->width;
792 r.height = private->height;
793 new_clip = gdk_region_rectangle (&r);
795 if (private->parent != NULL &&
796 private->parent->window_type != GDK_WINDOW_ROOT &&
797 /* For foreign children, don't remove local parents, as parent
798 may not be mapped yet, and the non-native parents are not really
799 enforced for it anyways. */
800 private->window_type != GDK_WINDOW_FOREIGN)
802 gdk_region_intersect (new_clip, private->parent->clip_region);
804 /* Remove all overlapping children from parent */
805 remove_child_area (private->parent, private, FALSE, new_clip);
808 /* Convert from parent coords to window coords */
809 gdk_region_offset (new_clip, -private->x, -private->y);
812 gdk_region_intersect (new_clip, private->shape);
814 if (private->clip_region == NULL ||
815 !gdk_region_equal (private->clip_region, new_clip))
816 clip_region_changed = TRUE;
818 if (private->clip_region)
819 gdk_region_destroy (private->clip_region);
820 private->clip_region = new_clip;
822 old_clip_region_with_children = private->clip_region_with_children;
823 private->clip_region_with_children = gdk_region_copy (private->clip_region);
824 if (private->window_type != GDK_WINDOW_ROOT)
825 remove_child_area (private, NULL, FALSE, private->clip_region_with_children);
827 if (clip_region_changed ||
828 !gdk_region_equal (private->clip_region_with_children, old_clip_region_with_children))
829 private->clip_tag = new_region_tag ();
831 if (old_clip_region_with_children)
832 gdk_region_destroy (old_clip_region_with_children);
835 if (clip_region_changed)
837 GdkVisibilityState visibility;
838 gboolean fully_visible;
840 if (gdk_region_empty (private->clip_region))
841 visibility = GDK_VISIBILITY_FULLY_OBSCURED;
844 fully_visible = gdk_region_equal (private->clip_region,
850 r.width = private->width;
851 r.height = private->height;
852 fully_visible = gdk_region_rect_equal (private->clip_region, &r);
856 visibility = GDK_VISIBILITY_UNOBSCURED;
858 visibility = GDK_VISIBILITY_PARTIAL;
861 if (private->visibility != visibility)
863 private->visibility = visibility;
864 gdk_window_update_visibility (private);
868 /* Update all children, recursively (except for root, where children are not exact). */
869 if ((abs_pos_changed || clip_region_changed || recalculate_children) &&
870 private->window_type != GDK_WINDOW_ROOT)
872 for (l = private->children; l; l = l->next)
875 /* Only recalculate clip if the the clip region changed, otherwise
876 * there is no way the child clip region could change (its has not e.g. moved)
877 * Except if recalculate_children is set to force child updates
879 recompute_visible_regions_internal (child,
880 recalculate_clip && (clip_region_changed || recalculate_children),
885 if (clip_region_changed &&
886 gdk_window_has_impl (private) &&
887 /* Not for offscreens */
888 private->window_type != GDK_WINDOW_OFFSCREEN &&
889 /* or for non-shaped toplevels */
891 (private->parent != NULL &&
892 private->parent->window_type != GDK_WINDOW_ROOT)) &&
893 /* or for foreign windows */
894 private->window_type != GDK_WINDOW_FOREIGN &&
895 /* or for the root window */
896 private->window_type != GDK_WINDOW_ROOT
899 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region ((GdkWindow *)private, private->clip_region, 0, 0);
902 if (recalculate_siblings &&
903 private->parent != NULL &&
904 private->parent->window_type != GDK_WINDOW_ROOT)
906 /* If we moved a child window in parent or changed the stacking order, then we
907 * need to recompute the visible area of all the other children in the parent
909 for (l = private->parent->children; l; l = l->next)
913 if (child != private)
914 recompute_visible_regions_internal (child, TRUE, FALSE, FALSE);
917 /* We also need to recompute the _with_children clip for the parent */
918 recompute_visible_regions_internal (private->parent, TRUE, FALSE, FALSE);
921 if (private->cairo_surface)
925 /* It would be nice if we had some cairo support here so we
926 could set the clip rect on the cairo surface */
927 width = private->abs_x + private->width;
928 height = private->abs_y + private->height;
930 _gdk_windowing_set_cairo_surface_size (private->cairo_surface,
932 cairo_surface_set_device_offset (private->cairo_surface,
938 /* Call this when private has changed in one or more of these ways:
942 * stacking order of window changed
945 * It will recalculate abs_x/y and the clip regions
947 * Unless the window didn't change stacking order or size/pos, pass in TRUE
948 * for recalculate_siblings. (Mostly used internally for the recursion)
950 * If a child window was removed (and you can't use that child for
951 * recompute_visible_regions), pass in TRUE for recalculate_children on the parent
954 recompute_visible_regions (GdkWindowObject *private,
955 gboolean recalculate_siblings,
956 gboolean recalculate_children)
958 recompute_visible_regions_internal (private,
960 recalculate_siblings,
961 recalculate_children);
965 _gdk_window_update_size (GdkWindow *window)
967 recompute_visible_regions ((GdkWindowObject *)window, TRUE, FALSE);
970 /* Find the native window that would be just above "child"
971 * in the native stacking order if "child" was a native window
972 * (it doesn't have to be native). If there is no such native
973 * window inside this native parent then NULL is returned.
974 * If child is NULL, find lowest native window in parent.
976 static GdkWindowObject *
977 find_native_sibling_above_helper (GdkWindowObject *parent,
978 GdkWindowObject *child)
985 l = g_list_find (parent->children, child);
986 g_assert (l != NULL); /* Better be a child of its parent... */
987 l = l->prev; /* Start looking at the one above the child */
990 l = g_list_last (parent->children);
992 for (; l != NULL; l = l->prev)
996 if (gdk_window_has_impl (w))
999 g_assert (parent != w);
1000 w = find_native_sibling_above_helper (w, NULL);
1009 static GdkWindowObject *
1010 find_native_sibling_above (GdkWindowObject *parent,
1011 GdkWindowObject *child)
1015 w = find_native_sibling_above_helper (parent, child);
1019 if (gdk_window_has_impl (parent))
1022 return find_native_sibling_above (parent->parent, parent);
1026 get_native_event_mask (GdkWindowObject *private)
1028 if (private->window_type != GDK_WINDOW_ROOT &&
1029 private->window_type != GDK_WINDOW_FOREIGN)
1032 /* We need thse for all native window so we can emulate
1033 events on children: */
1035 GDK_VISIBILITY_NOTIFY_MASK |
1036 GDK_POINTER_MOTION_MASK |
1037 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
1038 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
1040 /* Then do whatever the app asks to, since the app
1041 * may be asking for weird things for native windows,
1042 * but filter out things that override the above
1043 * requests somehow. */
1044 (private->event_mask &
1045 ~(GDK_POINTER_MOTION_HINT_MASK |
1046 GDK_BUTTON_MOTION_MASK |
1047 GDK_BUTTON1_MOTION_MASK |
1048 GDK_BUTTON2_MOTION_MASK |
1049 GDK_BUTTON3_MOTION_MASK));
1052 return private->event_mask;
1055 /* Puts the native window in the right order wrt the other native windows
1056 in the hierarchy, given the position it has in the client side data.
1057 This is useful if some operation changed the stacking order. */
1059 sync_native_window_stack_position (GdkWindow *window)
1061 GdkWindowObject *above;
1062 GdkWindowObject *private;
1063 GList listhead = {0};
1065 private = (GdkWindowObject *) window;
1067 above = find_native_sibling_above (private->parent, private);
1070 listhead.data = window;
1071 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
1078 * @parent: a #GdkWindow, or %NULL to create the window as a child of
1079 * the default root window for the default display.
1080 * @attributes: attributes of the new window
1081 * @attributes_mask: mask indicating which fields in @attributes are valid
1083 * Creates a new #GdkWindow using the attributes from
1084 * @attributes. See #GdkWindowAttr and #GdkWindowAttributesType for
1085 * more details. Note: to use this on displays other than the default
1086 * display, @parent must be specified.
1088 * Return value: the new #GdkWindow
1091 gdk_window_new (GdkWindow *parent,
1092 GdkWindowAttr *attributes,
1093 gint attributes_mask)
1096 GdkWindowObject *private;
1101 GdkEventMask event_mask;
1102 GdkWindow *real_parent;
1104 g_return_val_if_fail (attributes != NULL, NULL);
1108 GDK_NOTE (MULTIHEAD,
1109 g_warning ("gdk_window_new(): no parent specified reverting to parent = default root window"));
1111 screen = gdk_screen_get_default ();
1112 parent = gdk_screen_get_root_window (screen);
1115 screen = gdk_drawable_get_screen (parent);
1117 g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
1119 if (GDK_WINDOW_DESTROYED (parent))
1122 window = g_object_new (GDK_TYPE_WINDOW, NULL);
1123 private = (GdkWindowObject *) window;
1125 /* Windows with a foreign parent are treated as if they are children
1126 * of the root window, except for actual creation.
1128 real_parent = parent;
1129 if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
1130 parent = gdk_screen_get_root_window (screen);
1132 private->parent = (GdkWindowObject *)parent;
1134 private->accept_focus = TRUE;
1135 private->focus_on_map = TRUE;
1137 if (attributes_mask & GDK_WA_X)
1142 if (attributes_mask & GDK_WA_Y)
1149 private->width = (attributes->width > 1) ? (attributes->width) : (1);
1150 private->height = (attributes->height > 1) ? (attributes->height) : (1);
1152 #ifdef GDK_WINDOWING_X11
1153 /* Work around a bug where Xorg refuses to map toplevel InputOnly windows
1154 * from an untrusted client: http://bugs.freedesktop.org/show_bug.cgi?id=6988
1156 if (attributes->wclass == GDK_INPUT_ONLY &&
1157 private->parent->window_type == GDK_WINDOW_ROOT &&
1158 !G_LIKELY (GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (parent))->trusted_client))
1160 g_warning ("Coercing GDK_INPUT_ONLY toplevel window to GDK_INPUT_OUTPUT to work around bug in Xorg server");
1161 attributes->wclass = GDK_INPUT_OUTPUT;
1165 if (attributes->wclass == GDK_INPUT_ONLY)
1167 /* Backwards compatiblity - we've always ignored
1168 * attributes->window_type for input-only windows
1171 if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
1172 private->window_type = GDK_WINDOW_TEMP;
1174 private->window_type = GDK_WINDOW_CHILD;
1177 private->window_type = attributes->window_type;
1180 switch (private->window_type)
1182 case GDK_WINDOW_TOPLEVEL:
1183 case GDK_WINDOW_DIALOG:
1184 case GDK_WINDOW_TEMP:
1185 case GDK_WINDOW_OFFSCREEN:
1186 if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
1187 g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
1188 "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
1189 case GDK_WINDOW_CHILD:
1193 g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
1197 if (attributes_mask & GDK_WA_VISUAL)
1198 visual = attributes->visual;
1200 visual = gdk_screen_get_system_visual (screen);
1202 private->event_mask = attributes->event_mask;
1204 if (attributes->wclass == GDK_INPUT_OUTPUT)
1206 private->input_only = FALSE;
1207 private->depth = visual->depth;
1209 private->bg_color.pixel = 0; // TODO: BlackPixel (xdisplay, screen_x11->screen_num);
1210 private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
1212 private->bg_pixmap = NULL;
1217 private->input_only = TRUE;
1220 if (private->parent)
1221 private->parent->children = g_list_prepend (private->parent->children, window);
1223 native = FALSE; /* Default */
1224 if (private->parent->window_type == GDK_WINDOW_ROOT)
1225 native = TRUE; /* Always use native windows for toplevels */
1226 else if (!private->input_only &&
1227 ((attributes_mask & GDK_WA_COLORMAP &&
1228 attributes->colormap != gdk_drawable_get_colormap ((GdkDrawable *)private->parent)) ||
1229 (attributes_mask & GDK_WA_VISUAL &&
1230 attributes->visual != gdk_drawable_get_visual ((GdkDrawable *)private->parent))))
1231 native = TRUE; /* InputOutput window with different colormap or visual than parent, needs native window */
1233 if (private->window_type == GDK_WINDOW_OFFSCREEN)
1235 _gdk_offscreen_window_new (window, screen, visual, attributes, attributes_mask);
1236 private->impl_window = private;
1240 event_mask = get_native_event_mask (private);
1242 /* Create the impl */
1243 _gdk_window_impl_new (window, real_parent, screen, visual, event_mask, attributes, attributes_mask);
1244 private->impl_window = private;
1246 /* This will put the native window topmost in the native parent, which may
1247 * be wrong wrt other native windows in the non-native hierarchy, so restack */
1248 sync_native_window_stack_position (window);
1252 private->impl_window = g_object_ref (private->parent->impl_window);
1253 private->impl = g_object_ref (private->impl_window->impl);
1256 recompute_visible_regions (private, TRUE, FALSE);
1258 if (private->parent->window_type != GDK_WINDOW_ROOT)
1260 /* Inherit redirection from parent */
1261 private->redirect = private->parent->redirect;
1264 gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
1265 (attributes->cursor) :
1272 is_parent_of (GdkWindow *parent,
1283 w = gdk_window_get_parent (w);
1290 change_impl (GdkWindowObject *private,
1291 GdkWindowObject *impl_window,
1295 GdkWindowObject *child;
1296 GdkDrawable *old_impl;
1297 GdkWindowObject *old_impl_window;
1299 old_impl = private->impl;
1300 old_impl_window = private->impl_window;
1301 if (private != impl_window)
1302 private->impl_window = g_object_ref (impl_window);
1304 private->impl_window = private;
1305 private->impl = g_object_ref (new);
1306 if (old_impl_window != private)
1307 g_object_unref (old_impl_window);
1308 g_object_unref (old_impl);
1310 for (l = private->children; l != NULL; l = l->next)
1314 if (child->impl == old_impl)
1315 change_impl (child, impl_window, new);
1320 reparent_to_impl (GdkWindowObject *private)
1323 GdkWindowObject *child;
1326 /* Enumerate in reverse order so we get the right order for the native
1327 windows (first in childrens list is topmost, and reparent places on top) */
1328 for (l = g_list_last (private->children); l != NULL; l = l->prev)
1332 if (child->impl == private->impl)
1333 reparent_to_impl (child);
1336 show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent ((GdkWindow *)child,
1337 (GdkWindow *)private,
1338 child->x, child->y);
1340 gdk_window_show_unraised ((GdkWindow *)child);
1347 * gdk_window_reparent:
1348 * @window: a #GdkWindow
1349 * @new_parent: new parent to move @window into
1350 * @x: X location inside the new parent
1351 * @y: Y location inside the new parent
1353 * Reparents @window into the given @new_parent. The window being
1354 * reparented will be unmapped as a side effect.
1358 gdk_window_reparent (GdkWindow *window,
1359 GdkWindow *new_parent,
1363 GdkWindowObject *private;
1364 GdkWindowObject *new_parent_private;
1365 GdkWindowObject *old_parent;
1367 gboolean show, was_toplevel, was_mapped;
1368 gboolean do_reparent_to_impl;
1370 g_return_if_fail (GDK_IS_WINDOW (window));
1371 g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
1372 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
1374 if (GDK_WINDOW_DESTROYED (window) ||
1375 (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
1378 screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
1380 new_parent = gdk_screen_get_root_window (screen);
1382 private = (GdkWindowObject *) window;
1383 new_parent_private = (GdkWindowObject *)new_parent;
1385 /* No input-output children of input-only windows */
1386 if (new_parent_private->input_only && !private->input_only)
1389 /* Don't create loops in hierarchy */
1390 if (is_parent_of (window, new_parent))
1393 if (private->cairo_surface)
1395 /* This might be wrong in the new parent, e.g. for non-native surfaces.
1396 To make sure we're ok, just wipe it. */
1397 cairo_surface_finish (private->cairo_surface);
1398 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
1402 old_parent = private->parent;
1404 /* Break up redirection if inherited */
1405 if (private->redirect && private->redirect->redirected != private)
1407 remove_redirect_from_children (private, private->redirect);
1408 private->redirect = NULL;
1411 was_toplevel = private->parent == NULL;
1412 was_mapped = GDK_WINDOW_IS_MAPPED (window);
1415 /* Reparenting to toplevel. Ensure we have a native window so this can work */
1416 if (new_parent_private->window_type == GDK_WINDOW_ROOT ||
1417 new_parent_private->window_type == GDK_WINDOW_FOREIGN)
1418 gdk_window_ensure_native (window);
1420 do_reparent_to_impl = FALSE;
1421 if (gdk_window_has_impl (private))
1424 show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent (window, new_parent, x, y);
1428 /* This shouldn't happen, as we created a native in this case, check anyway to see if that ever fails */
1429 g_assert (new_parent_private->window_type != GDK_WINDOW_ROOT &&
1430 new_parent_private->window_type != GDK_WINDOW_FOREIGN);
1433 gdk_window_hide (window);
1435 do_reparent_to_impl = TRUE;
1436 change_impl (private,
1437 new_parent_private->impl_window,
1438 new_parent_private->impl);
1441 /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
1444 if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1446 new_parent = gdk_screen_get_root_window (screen);
1447 new_parent_private = (GdkWindowObject *)new_parent;
1451 old_parent->children = g_list_remove (old_parent->children, window);
1453 private->parent = new_parent_private;
1457 new_parent_private->children = g_list_prepend (new_parent_private->children, window);
1459 /* Switch the window type as appropriate */
1461 switch (GDK_WINDOW_TYPE (new_parent))
1463 case GDK_WINDOW_ROOT:
1464 case GDK_WINDOW_FOREIGN:
1465 if (private->toplevel_window_type != -1)
1466 GDK_WINDOW_TYPE (window) = private->toplevel_window_type;
1467 else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1468 GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
1470 case GDK_WINDOW_OFFSCREEN:
1471 case GDK_WINDOW_TOPLEVEL:
1472 case GDK_WINDOW_CHILD:
1473 case GDK_WINDOW_DIALOG:
1474 case GDK_WINDOW_TEMP:
1475 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
1476 GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
1478 /* Save the original window type so we can restore it if the
1479 * window is reparented back to be a toplevel
1481 private->toplevel_window_type = GDK_WINDOW_TYPE (window);
1482 GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
1486 /* We might have changed window type for a native windows, so we
1487 need to change the event mask too. */
1488 if (gdk_window_has_impl (private))
1489 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_events (window, get_native_event_mask (private));
1491 /* Inherit parent redirect if we don't have our own */
1492 if (private->parent && private->redirect == NULL)
1494 private->redirect = private->parent->redirect;
1495 apply_redirect_to_children (private, private->redirect);
1498 _gdk_window_update_viewable (window);
1500 recompute_visible_regions (private, TRUE, FALSE);
1501 if (old_parent && GDK_WINDOW_TYPE (old_parent) != GDK_WINDOW_ROOT)
1502 recompute_visible_regions (old_parent, FALSE, TRUE);
1504 if (do_reparent_to_impl)
1505 reparent_to_impl (private);
1508 /* The reparent will have put the native window topmost in the native parent,
1509 * which may be wrong wrt other native windows in the non-native hierarchy,
1511 sync_native_window_stack_position (window);
1515 gdk_window_show_unraised (window);
1517 _gdk_synthesize_crossing_events_for_geometry_change (window);
1521 * gdk_window_ensure_native:
1522 * @window: a #GdkWindow
1524 * Tries to ensure that there is a window-system native window for this
1525 * GdkWindow. This may fail in some situations, returning %FALSE.
1527 * Offscreen window and children of them can never have native windows.
1529 * Some backends may not support native child windows.
1531 * Returns: %TRUE if the window has a native window, %FALSE otherwise
1536 gdk_window_ensure_native (GdkWindow *window)
1538 GdkWindowObject *private;
1539 GdkWindowObject *impl_window;
1540 GdkDrawable *new_impl, *old_impl;
1543 GdkWindowAttr attributes;
1544 GdkWindowObject *above;
1547 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
1549 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT ||
1550 GDK_WINDOW_DESTROYED (window))
1553 private = (GdkWindowObject *) window;
1555 impl_window = gdk_window_get_impl_window (private);
1557 if (impl_window->window_type == GDK_WINDOW_OFFSCREEN)
1558 return FALSE; /* native in offscreens not supported */
1560 if (impl_window == private)
1561 /* Already has an impl, and its not offscreen . */
1564 /* Need to create a native window */
1566 screen = gdk_drawable_get_screen (window);
1567 visual = gdk_drawable_get_visual (window);
1569 attributes.colormap = gdk_drawable_get_colormap (window);
1571 old_impl = private->impl;
1572 _gdk_window_impl_new (window, (GdkWindow *)private->parent, screen, visual,
1573 get_native_event_mask (private), &attributes, GDK_WA_COLORMAP);
1574 new_impl = private->impl;
1576 private->impl = old_impl;
1577 change_impl (private, private, new_impl);
1579 /* Native window creation will put the native window topmost in the
1580 * native parent, which may be wrong wrt other native windows in the
1581 * non-native hierarchy, so restack */
1582 above = find_native_sibling_above (private->parent, private);
1585 listhead.data = window;
1586 listhead.prev = NULL;
1587 listhead.next = NULL;
1588 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
1592 recompute_visible_regions (private, FALSE, FALSE);
1594 /* The shape may not have been set, as the clip region doesn't actually
1595 change, so do it here manually */
1596 if (private->viewable)
1597 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region ((GdkWindow *)private, private->clip_region, 0, 0);
1599 reparent_to_impl (private);
1601 if (!private->input_only)
1603 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, &private->bg_color);
1604 if (private->bg_pixmap != NULL)
1605 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, private->bg_pixmap);
1608 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_shape_combine_region ((GdkWindow *)private, private->input_shape, 0, 0);
1610 if (gdk_window_is_viewable (window))
1611 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show (window, FALSE);
1617 window_remove_filters (GdkWindow *window)
1619 GdkWindowObject *obj = (GdkWindowObject*) window;
1625 for (tmp_list = obj->filters; tmp_list; tmp_list = tmp_list->next)
1626 g_free (tmp_list->data);
1628 g_list_free (obj->filters);
1629 obj->filters = NULL;
1634 * _gdk_window_destroy_hierarchy:
1635 * @window: a #GdkWindow
1636 * @recursing: If TRUE, then this is being called because a parent
1638 * @recursing_native: If TRUE, then this is being called because a native parent
1639 * was destroyed. This generally means that the call to the
1640 * windowing system to destroy the window can be omitted, since
1641 * it will be destroyed as a result of the parent being destroyed.
1642 * Unless @foreign_destroy.
1643 * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
1644 * external agency. The window has already been destroyed and no
1645 * windowing system calls should be made. (This may never happen
1646 * for some windowing systems.)
1648 * Internal function to destroy a window. Like gdk_window_destroy(),
1649 * but does not drop the reference count created by gdk_window_new().
1652 _gdk_window_destroy_hierarchy (GdkWindow *window,
1654 gboolean recursing_native,
1655 gboolean foreign_destroy)
1657 GdkWindowObject *private;
1658 GdkWindowObject *temp_private;
1659 GdkWindow *temp_window;
1661 GdkDisplay *display;
1665 g_return_if_fail (GDK_IS_WINDOW (window));
1667 private = (GdkWindowObject*) window;
1669 if (GDK_WINDOW_DESTROYED (window))
1672 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
1673 screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
1674 temp_window = g_object_get_qdata (G_OBJECT (screen), quark_pointer_window);
1675 if (temp_window == window)
1676 g_object_set_qdata (G_OBJECT (screen), quark_pointer_window, NULL);
1679 switch (private->window_type)
1681 case GDK_WINDOW_ROOT:
1682 if (!screen->closed)
1684 g_error ("attempted to destroy root window");
1687 /* else fall thru */
1688 case GDK_WINDOW_TOPLEVEL:
1689 case GDK_WINDOW_CHILD:
1690 case GDK_WINDOW_DIALOG:
1691 case GDK_WINDOW_TEMP:
1692 case GDK_WINDOW_FOREIGN:
1693 case GDK_WINDOW_OFFSCREEN:
1694 if (private->window_type == GDK_WINDOW_FOREIGN && !foreign_destroy)
1696 /* Logically, it probably makes more sense to send
1697 * a "destroy yourself" message to the foreign window
1698 * whether or not it's in our hierarchy; but for historical
1699 * reasons, we only send "destroy yourself" messages to
1700 * foreign windows in our hierarchy.
1702 if (private->parent)
1703 _gdk_windowing_window_destroy_foreign (window);
1705 /* Also for historical reasons, we remove any filters
1706 * on a foreign window when it or a parent is destroyed;
1707 * this likely causes problems if two separate portions
1708 * of code are maintaining filter lists on a foreign window.
1710 window_remove_filters (window);
1714 if (private->parent)
1716 GdkWindowObject *parent_private = (GdkWindowObject *)private->parent;
1718 if (parent_private->children)
1719 parent_private->children = g_list_remove (parent_private->children, window);
1722 GDK_WINDOW_IS_MAPPED (window))
1724 recompute_visible_regions (private, TRUE, FALSE);
1725 gdk_window_invalidate_in_parent (private);
1729 gdk_window_free_paint_stack (window);
1731 if (private->bg_pixmap &&
1732 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
1733 private->bg_pixmap != GDK_NO_BG)
1735 g_object_unref (private->bg_pixmap);
1736 private->bg_pixmap = NULL;
1739 if (private->window_type == GDK_WINDOW_FOREIGN)
1740 g_assert (private->children == NULL);
1743 children = tmp = private->children;
1744 private->children = NULL;
1748 temp_window = tmp->data;
1751 temp_private = (GdkWindowObject*) temp_window;
1753 _gdk_window_destroy_hierarchy (temp_window,
1755 recursing_native || gdk_window_has_impl (private),
1759 g_list_free (children);
1762 _gdk_window_clear_update_area (window);
1764 if (private->cairo_surface)
1766 cairo_surface_finish (private->cairo_surface);
1767 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
1772 if (private->extension_events)
1773 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_window_destroy (window);
1775 if (gdk_window_has_impl (private))
1777 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->destroy (window, recursing_native, foreign_destroy);
1781 /* hide to make sure we repaint and break grabs */
1782 gdk_window_hide (window);
1785 private->state |= GDK_WINDOW_STATE_WITHDRAWN;
1786 private->parent = NULL;
1787 private->destroyed = TRUE;
1789 window_remove_filters (window);
1791 gdk_drawable_set_colormap (GDK_DRAWABLE (window), NULL);
1793 /* If we own the redirect, free it */
1794 if (private->redirect && private->redirect->redirected == private)
1795 gdk_window_redirect_free (private->redirect);
1797 private->redirect = NULL;
1799 if (display->pointer_info.toplevel_under_pointer == window)
1801 g_object_unref (display->pointer_info.toplevel_under_pointer);
1802 display->pointer_info.toplevel_under_pointer = NULL;
1810 * _gdk_window_destroy:
1811 * @window: a #GdkWindow
1812 * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
1813 * external agency. The window has already been destroyed and no
1814 * windowing system calls should be made. (This may never happen
1815 * for some windowing systems.)
1817 * Internal function to destroy a window. Like gdk_window_destroy(),
1818 * but does not drop the reference count created by gdk_window_new().
1821 _gdk_window_destroy (GdkWindow *window,
1822 gboolean foreign_destroy)
1824 _gdk_window_destroy_hierarchy (window, FALSE, FALSE, foreign_destroy);
1828 * gdk_window_destroy:
1829 * @window: a #GdkWindow
1831 * Destroys the window system resources associated with @window and decrements @window's
1832 * reference count. The window system resources for all children of @window are also
1833 * destroyed, but the children's reference counts are not decremented.
1835 * Note that a window will not be destroyed automatically when its reference count
1836 * reaches zero. You must call this function yourself before that happens.
1840 gdk_window_destroy (GdkWindow *window)
1842 _gdk_window_destroy_hierarchy (window, FALSE, FALSE, FALSE);
1843 g_object_unref (window);
1847 * gdk_window_set_user_data:
1848 * @window: a #GdkWindow
1849 * @user_data: user data
1851 * For most purposes this function is deprecated in favor of
1852 * g_object_set_data(). However, for historical reasons GTK+ stores
1853 * the #GtkWidget that owns a #GdkWindow as user data on the
1854 * #GdkWindow. So, custom widget implementations should use
1855 * this function for that. If GTK+ receives an event for a #GdkWindow,
1856 * and the user data for the window is non-%NULL, GTK+ will assume the
1857 * user data is a #GtkWidget, and forward the event to that widget.
1861 gdk_window_set_user_data (GdkWindow *window,
1864 g_return_if_fail (GDK_IS_WINDOW (window));
1866 ((GdkWindowObject*)window)->user_data = user_data;
1870 * gdk_window_get_user_data:
1871 * @window: a #GdkWindow
1872 * @data: return location for user data
1874 * Retrieves the user data for @window, which is normally the widget
1875 * that @window belongs to. See gdk_window_set_user_data().
1879 gdk_window_get_user_data (GdkWindow *window,
1882 g_return_if_fail (GDK_IS_WINDOW (window));
1884 *data = ((GdkWindowObject*)window)->user_data;
1888 * gdk_window_get_window_type:
1889 * @window: a #GdkWindow
1891 * Gets the type of the window. See #GdkWindowType.
1893 * Return value: type of window
1896 gdk_window_get_window_type (GdkWindow *window)
1898 g_return_val_if_fail (GDK_IS_WINDOW (window), (GdkWindowType) -1);
1900 return GDK_WINDOW_TYPE (window);
1904 * gdk_window_get_position:
1905 * @window: a #GdkWindow
1906 * @x: X coordinate of window
1907 * @y: Y coordinate of window
1909 * Obtains the position of the window as reported in the
1910 * most-recently-processed #GdkEventConfigure. Contrast with
1911 * gdk_window_get_geometry() which queries the X server for the
1912 * current window position, regardless of which events have been
1913 * received or processed.
1915 * The position coordinates are relative to the window's parent window.
1919 gdk_window_get_position (GdkWindow *window,
1923 GdkWindowObject *obj;
1925 g_return_if_fail (GDK_IS_WINDOW (window));
1927 obj = (GdkWindowObject*) window;
1936 * gdk_window_get_parent:
1937 * @window: a #GdkWindow
1939 * Obtains the parent of @window, as known to GDK. Does not query the
1940 * X server; thus this returns the parent as passed to gdk_window_new(),
1941 * not the actual parent. This should never matter unless you're using
1942 * Xlib calls mixed with GDK calls on the X11 platform. It may also
1943 * matter for toplevel windows, because the window manager may choose
1946 * Return value: parent of @window
1949 gdk_window_get_parent (GdkWindow *window)
1951 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1953 return (GdkWindow*) ((GdkWindowObject*) window)->parent;
1957 * gdk_window_get_toplevel:
1958 * @window: a #GdkWindow
1960 * Gets the toplevel window that's an ancestor of @window.
1962 * Any window type but %GDK_WINDOW_CHILD is considered a
1963 * toplevel window, as is a %GDK_WINDOW_CHILD window that
1964 * has a root window as parent.
1966 * Return value: the toplevel window containing @window
1969 gdk_window_get_toplevel (GdkWindow *window)
1971 GdkWindowObject *obj;
1973 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1975 obj = (GdkWindowObject *)window;
1977 while (obj->window_type == GDK_WINDOW_CHILD)
1979 if (obj->parent == NULL ||
1980 obj->parent->window_type == GDK_WINDOW_ROOT)
1985 return GDK_WINDOW (obj);
1989 * gdk_window_get_children:
1990 * @window: a #GdkWindow
1992 * Gets the list of children of @window known to GDK.
1993 * This function only returns children created via GDK,
1994 * so for example it's useless when used with the root window;
1995 * it only returns windows an application created itself.
1997 * The returned list must be freed, but the elements in the
2000 * Return value: list of child windows inside @window
2003 gdk_window_get_children (GdkWindow *window)
2005 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2007 if (GDK_WINDOW_DESTROYED (window))
2010 return g_list_copy (GDK_WINDOW_OBJECT (window)->children);
2014 * gdk_window_peek_children:
2015 * @window: a #GdkWindow
2017 * Like gdk_window_get_children(), but does not copy the list of
2018 * children, so the list does not need to be freed.
2020 * Return value: a reference to the list of child windows in @window
2023 gdk_window_peek_children (GdkWindow *window)
2025 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2027 if (GDK_WINDOW_DESTROYED (window))
2030 return GDK_WINDOW_OBJECT (window)->children;
2034 * gdk_window_add_filter:
2035 * @window: a #GdkWindow
2036 * @function: filter callback
2037 * @data: data to pass to filter callback
2039 * Adds an event filter to @window, allowing you to intercept events
2040 * before they reach GDK. This is a low-level operation and makes it
2041 * easy to break GDK and/or GTK+, so you have to know what you're
2042 * doing. Pass %NULL for @window to get all events for all windows,
2043 * instead of events for a specific window.
2045 * See gdk_display_add_client_message_filter() if you are interested
2046 * in X ClientMessage events.
2049 gdk_window_add_filter (GdkWindow *window,
2050 GdkFilterFunc function,
2053 GdkWindowObject *private;
2055 GdkEventFilter *filter;
2057 g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
2059 private = (GdkWindowObject*) window;
2060 if (private && GDK_WINDOW_DESTROYED (window))
2063 /* Filters are for the native events on the native window, so
2064 ensure there is a native window. */
2066 gdk_window_ensure_native (window);
2069 tmp_list = private->filters;
2071 tmp_list = _gdk_default_filters;
2075 filter = (GdkEventFilter *)tmp_list->data;
2076 if ((filter->function == function) && (filter->data == data))
2078 tmp_list = tmp_list->next;
2081 filter = g_new (GdkEventFilter, 1);
2082 filter->function = function;
2083 filter->data = data;
2086 private->filters = g_list_append (private->filters, filter);
2088 _gdk_default_filters = g_list_append (_gdk_default_filters, filter);
2092 * gdk_window_remove_filter:
2093 * @window: a #GdkWindow
2094 * @function: previously-added filter function
2095 * @data: user data for previously-added filter function
2097 * Remove a filter previously added with gdk_window_add_filter().
2101 gdk_window_remove_filter (GdkWindow *window,
2102 GdkFilterFunc function,
2105 GdkWindowObject *private;
2106 GList *tmp_list, *node;
2107 GdkEventFilter *filter;
2109 g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
2111 private = (GdkWindowObject*) window;
2114 tmp_list = private->filters;
2116 tmp_list = _gdk_default_filters;
2120 filter = (GdkEventFilter *)tmp_list->data;
2122 tmp_list = tmp_list->next;
2124 if ((filter->function == function) && (filter->data == data))
2127 private->filters = g_list_remove_link (private->filters, node);
2129 _gdk_default_filters = g_list_remove_link (_gdk_default_filters, node);
2130 g_list_free_1 (node);
2139 * gdk_screen_get_toplevel_windows:
2140 * @screen: The #GdkScreen where the toplevels are located.
2142 * Obtains a list of all toplevel windows known to GDK on the screen @screen.
2143 * A toplevel window is a child of the root window (see
2144 * gdk_get_default_root_window()).
2146 * The returned list should be freed with g_list_free(), but
2147 * its elements need not be freed.
2149 * Return value: list of toplevel windows, free with g_list_free()
2154 gdk_screen_get_toplevel_windows (GdkScreen *screen)
2156 GdkWindow * root_window;
2157 GList *new_list = NULL;
2160 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
2162 root_window = gdk_screen_get_root_window (screen);
2164 tmp_list = ((GdkWindowObject *)root_window)->children;
2167 GdkWindowObject *w = tmp_list->data;
2169 if (w->window_type != GDK_WINDOW_FOREIGN)
2170 new_list = g_list_prepend (new_list, w);
2171 tmp_list = tmp_list->next;
2178 * gdk_window_get_toplevels:
2180 * Obtains a list of all toplevel windows known to GDK on the default
2181 * screen (see gdk_screen_get_toplevel_windows()).
2182 * A toplevel window is a child of the root window (see
2183 * gdk_get_default_root_window()).
2185 * The returned list should be freed with g_list_free(), but
2186 * its elements need not be freed.
2188 * Return value: list of toplevel windows, free with g_list_free()
2190 * Deprecated: 2.16: Use gdk_screen_get_toplevel_windows() instead.
2193 gdk_window_get_toplevels (void)
2195 return gdk_screen_get_toplevel_windows (gdk_screen_get_default ());
2199 * gdk_window_is_visible:
2200 * @window: a #GdkWindow
2202 * Checks whether the window has been mapped (with gdk_window_show() or
2203 * gdk_window_show_unraised()).
2205 * Return value: %TRUE if the window is mapped
2208 gdk_window_is_visible (GdkWindow *window)
2210 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2212 return GDK_WINDOW_IS_MAPPED (window);
2216 * gdk_window_is_viewable:
2217 * @window: a #GdkWindow
2219 * Check if the window and all ancestors of the window are
2220 * mapped. (This is not necessarily "viewable" in the X sense, since
2221 * we only check as far as we have GDK window parents, not to the root
2224 * Return value: %TRUE if the window is viewable
2227 gdk_window_is_viewable (GdkWindow *window)
2229 GdkWindowObject *private = (GdkWindowObject *)window;
2231 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2233 if (private->destroyed)
2236 return private->viewable;
2240 * gdk_window_get_state:
2241 * @window: a #GdkWindow
2243 * Gets the bitwise OR of the currently active window state flags,
2244 * from the #GdkWindowState enumeration.
2246 * Return value: window state bitfield
2249 gdk_window_get_state (GdkWindow *window)
2251 GdkWindowObject *private = (GdkWindowObject *)window;
2253 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2255 return private->state;
2259 /* This creates an empty "implicit" paint region for the impl window.
2260 * By itself this does nothing, but real paints to this window
2261 * or children of it can use this pixmap as backing to avoid allocating
2262 * multiple pixmaps for subwindow rendering. When doing so they
2263 * add to the region of the implicit paint region, which will be
2264 * pushed to the window when the implicit paint region is ended.
2265 * Such paints should not copy anything to the window on paint end, but
2266 * should rely on the implicit paint end.
2267 * The implicit paint will be automatically ended if someone draws
2268 * directly to the window or a child window.
2271 gdk_window_begin_implicit_paint (GdkWindow *window, GdkRectangle *rect)
2273 GdkWindowObject *private = (GdkWindowObject *)window;
2274 GdkWindowPaint *paint;
2276 g_assert (gdk_window_has_impl (private));
2278 if (GDK_IS_PAINTABLE (private->impl))
2279 return FALSE; /* Implementation does double buffering */
2281 if (private->paint_stack != NULL ||
2282 private->implicit_paint != NULL)
2283 return FALSE; /* Don't stack implicit paints */
2285 paint = g_new (GdkWindowPaint, 1);
2286 paint->region = gdk_region_new (); /* Empty */
2287 paint->x_offset = rect->x;
2288 paint->y_offset = rect->y;
2289 paint->uses_implicit = FALSE;
2290 paint->surface = NULL;
2292 gdk_pixmap_new (window,
2293 MAX (rect->width, 1), MAX (rect->height, 1), -1);
2295 private->implicit_paint = paint;
2300 /* Ensure that all content related to this (sub)window is pushed to the
2301 native region. If there is an active paint then that area is not
2302 pushed, in order to not show partially finished double buffers. */
2304 gdk_window_flush_implicit_paint (GdkWindow *window)
2306 GdkWindowObject *private = (GdkWindowObject *)window;
2307 GdkWindowObject *impl_window;
2308 GdkWindowPaint *paint;
2313 impl_window = gdk_window_get_impl_window (private);
2314 if (impl_window->implicit_paint == NULL)
2317 paint = impl_window->implicit_paint;
2318 region = gdk_region_copy (private->clip_region_with_children);
2320 /* Don't flush active double buffers, as that may show partially done
2322 for (list = private->paint_stack; list != NULL; list = list->next)
2324 GdkWindowPaint *tmp_paint = list->data;
2326 gdk_region_subtract (region, tmp_paint->region);
2329 gdk_region_offset (region, private->abs_x, private->abs_y);
2330 gdk_region_intersect (region, paint->region);
2332 if (!gdk_region_empty (region))
2334 /* Some regions are valid, push these to window now */
2335 tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
2336 _gdk_gc_set_clip_region_internal (tmp_gc, region, TRUE);
2337 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2338 0, 0, paint->x_offset, paint->y_offset, -1, -1);
2339 /* Reset clip region of the cached GdkGC */
2340 gdk_gc_set_clip_region (tmp_gc, NULL);
2342 /* Remove flushed region from the implicit paint */
2343 gdk_region_subtract (paint->region, region);
2346 gdk_region_destroy (region);
2349 /* Ends an implicit paint, paired with gdk_window_begin_implicit_paint returning TRUE */
2351 gdk_window_end_implicit_paint (GdkWindow *window)
2353 GdkWindowObject *private = (GdkWindowObject *)window;
2354 GdkWindowPaint *paint;
2357 g_assert (gdk_window_has_impl (private));
2359 g_assert (private->implicit_paint != NULL);
2361 paint = private->implicit_paint;
2363 private->implicit_paint = NULL;
2365 if (!gdk_region_empty (paint->region))
2367 /* Some regions are valid, push these to window now */
2368 tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
2369 _gdk_gc_set_clip_region_internal (tmp_gc, paint->region, TRUE);
2370 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2371 0, 0, paint->x_offset, paint->y_offset, -1, -1);
2372 /* Reset clip region of the cached GdkGC */
2373 gdk_gc_set_clip_region (tmp_gc, NULL);
2376 g_object_unref (paint->pixmap);
2381 * gdk_window_begin_paint_rect:
2382 * @window: a #GdkWindow
2383 * @rectangle: rectangle you intend to draw to
2385 * A convenience wrapper around gdk_window_begin_paint_region() which
2386 * creates a rectangular region for you. See
2387 * gdk_window_begin_paint_region() for details.
2391 gdk_window_begin_paint_rect (GdkWindow *window,
2392 const GdkRectangle *rectangle)
2396 g_return_if_fail (GDK_IS_WINDOW (window));
2398 region = gdk_region_rectangle (rectangle);
2399 gdk_window_begin_paint_region (window, region);
2400 gdk_region_destroy (region);
2404 * gdk_window_begin_paint_region:
2405 * @window: a #GdkWindow
2406 * @region: region you intend to draw to
2408 * Indicates that you are beginning the process of redrawing @region.
2409 * A backing store (offscreen buffer) large enough to contain @region
2410 * will be created. The backing store will be initialized with the
2411 * background color or background pixmap for @window. Then, all
2412 * drawing operations performed on @window will be diverted to the
2413 * backing store. When you call gdk_window_end_paint(), the backing
2414 * store will be copied to @window, making it visible onscreen. Only
2415 * the part of @window contained in @region will be modified; that is,
2416 * drawing operations are clipped to @region.
2418 * The net result of all this is to remove flicker, because the user
2419 * sees the finished product appear all at once when you call
2420 * gdk_window_end_paint(). If you draw to @window directly without
2421 * calling gdk_window_begin_paint_region(), the user may see flicker
2422 * as individual drawing operations are performed in sequence. The
2423 * clipping and background-initializing features of
2424 * gdk_window_begin_paint_region() are conveniences for the
2425 * programmer, so you can avoid doing that work yourself.
2427 * When using GTK+, the widget system automatically places calls to
2428 * gdk_window_begin_paint_region() and gdk_window_end_paint() around
2429 * emissions of the expose_event signal. That is, if you're writing an
2430 * expose event handler, you can assume that the exposed area in
2431 * #GdkEventExpose has already been cleared to the window background,
2432 * is already set as the clip region, and already has a backing store.
2433 * Therefore in most cases, application code need not call
2434 * gdk_window_begin_paint_region(). (You can disable the automatic
2435 * calls around expose events on a widget-by-widget basis by calling
2436 * gtk_widget_set_double_buffered().)
2438 * If you call this function multiple times before calling the
2439 * matching gdk_window_end_paint(), the backing stores are pushed onto
2440 * a stack. gdk_window_end_paint() copies the topmost backing store
2441 * onscreen, subtracts the topmost region from all other regions in
2442 * the stack, and pops the stack. All drawing operations affect only
2443 * the topmost backing store in the stack. One matching call to
2444 * gdk_window_end_paint() is required for each call to
2445 * gdk_window_begin_paint_region().
2449 gdk_window_begin_paint_region (GdkWindow *window,
2450 const GdkRegion *region)
2452 #ifdef USE_BACKING_STORE
2453 GdkWindowObject *private = (GdkWindowObject *)window;
2454 GdkRectangle clip_box;
2455 GdkWindowPaint *paint, *implicit_paint;
2456 GdkWindowObject *impl_window;
2459 g_return_if_fail (GDK_IS_WINDOW (window));
2461 if (GDK_WINDOW_DESTROYED (window))
2464 if (GDK_IS_PAINTABLE (private->impl))
2466 GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
2468 if (iface->begin_paint_region)
2469 iface->begin_paint_region ((GdkPaintable*)private->impl, window, region);
2474 impl_window = gdk_window_get_impl_window (private);
2475 implicit_paint = impl_window->implicit_paint;
2477 paint = g_new (GdkWindowPaint, 1);
2478 paint->region = gdk_region_copy (region);
2479 paint->region_tag = new_region_tag ();
2481 gdk_region_intersect (paint->region, private->clip_region_with_children);
2482 gdk_region_get_clipbox (paint->region, &clip_box);
2484 /* Convert to impl coords */
2485 gdk_region_offset (paint->region, private->abs_x, private->abs_y);
2487 /* Mark the region as valid on the implicit paint */
2490 gdk_region_union (implicit_paint->region, paint->region);
2492 /* Convert back to normal coords */
2493 gdk_region_offset (paint->region, -private->abs_x, -private->abs_y);
2499 paint->uses_implicit = TRUE;
2500 paint->pixmap = g_object_ref (implicit_paint->pixmap);
2501 paint->x_offset = -private->abs_x + implicit_paint->x_offset;
2502 paint->y_offset = -private->abs_y + implicit_paint->y_offset;
2504 /* It would be nice if we had some cairo support here so we
2505 could set the clip rect on the cairo surface */
2506 width = private->abs_x + private->width;
2507 height = private->abs_y + private->height;
2509 paint->surface = _gdk_drawable_create_cairo_surface (paint->pixmap, width, height);
2514 paint->uses_implicit = FALSE;
2515 paint->x_offset = clip_box.x;
2516 paint->y_offset = clip_box.y;
2518 gdk_pixmap_new (window,
2519 MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1);
2520 paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap);
2524 cairo_surface_set_device_offset (paint->surface,
2525 -paint->x_offset, -paint->y_offset);
2527 for (list = private->paint_stack; list != NULL; list = list->next)
2529 GdkWindowPaint *tmp_paint = list->data;
2531 gdk_region_subtract (tmp_paint->region, paint->region);
2534 private->paint_stack = g_slist_prepend (private->paint_stack, paint);
2536 if (!gdk_region_empty (paint->region))
2538 gdk_window_clear_backing_region (window,
2542 #endif /* USE_BACKING_STORE */
2546 setup_redirect_clip (GdkWindow *window,
2551 GdkWindowObject *private = (GdkWindowObject *)window;
2552 GdkRegion *visible_region;
2553 GdkRectangle dest_rect;
2555 GdkWindow *toplevel;
2556 int x_offset, y_offset;
2558 toplevel = GDK_WINDOW (private->redirect->redirected);
2560 /* Get the clip region for gc clip rect + window hierarchy in
2561 window relative coords */
2563 _gdk_window_calculate_full_clip_region (window, toplevel,
2568 /* Compensate for the source pos/size */
2569 x_offset -= private->redirect->src_x;
2570 y_offset -= private->redirect->src_y;
2571 dest_rect.x = -x_offset;
2572 dest_rect.y = -y_offset;
2573 dest_rect.width = private->redirect->width;
2574 dest_rect.height = private->redirect->height;
2575 tmpreg = gdk_region_rectangle (&dest_rect);
2576 gdk_region_intersect (visible_region, tmpreg);
2577 gdk_region_destroy (tmpreg);
2579 /* Compensate for the dest pos */
2580 x_offset += private->redirect->dest_x;
2581 y_offset += private->redirect->dest_y;
2583 gdk_gc_set_clip_region (gc, visible_region); /* This resets clip origin! */
2585 /* offset clip and tiles from window coords to pixmaps coords */
2586 gdk_gc_offset (gc, -x_offset, -y_offset);
2588 gdk_region_destroy (visible_region);
2590 *x_offset_out = x_offset;
2591 *y_offset_out = y_offset;
2595 * gdk_window_end_paint:
2596 * @window: a #GdkWindow
2598 * Indicates that the backing store created by the most recent call to
2599 * gdk_window_begin_paint_region() should be copied onscreen and
2600 * deleted, leaving the next-most-recent backing store or no backing
2601 * store at all as the active paint region. See
2602 * gdk_window_begin_paint_region() for full details. It is an error to
2603 * call this function without a matching
2604 * gdk_window_begin_paint_region() first.
2608 gdk_window_end_paint (GdkWindow *window)
2610 #ifdef USE_BACKING_STORE
2611 GdkWindowObject *private = (GdkWindowObject *)window;
2612 GdkWindowObject *composited;
2613 GdkWindowPaint *paint;
2615 GdkRectangle clip_box;
2616 gint x_offset, y_offset;
2617 GdkRegion *full_clip;
2619 g_return_if_fail (GDK_IS_WINDOW (window));
2621 if (GDK_WINDOW_DESTROYED (window))
2624 if (GDK_IS_PAINTABLE (private->impl))
2626 GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
2628 if (iface->end_paint)
2629 iface->end_paint ((GdkPaintable*)private->impl);
2633 if (private->paint_stack == NULL)
2635 g_warning (G_STRLOC": no preceding call to gdk_window_begin_paint_region(), see documentation");
2639 paint = private->paint_stack->data;
2641 private->paint_stack = g_slist_delete_link (private->paint_stack,
2642 private->paint_stack);
2644 gdk_region_get_clipbox (paint->region, &clip_box);
2646 tmp_gc = _gdk_drawable_get_scratch_gc (window, FALSE);
2648 x_offset = -private->abs_x;
2649 y_offset = -private->abs_y;
2651 if (!paint->uses_implicit)
2653 gdk_window_flush_outstanding_moves (window);
2655 full_clip = gdk_region_copy (private->clip_region_with_children);
2656 gdk_region_intersect (full_clip, paint->region);
2657 _gdk_gc_set_clip_region_internal (tmp_gc, full_clip, TRUE); /* Takes ownership of full_clip */
2658 gdk_gc_set_clip_origin (tmp_gc, - x_offset, - y_offset);
2659 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2660 clip_box.x - paint->x_offset,
2661 clip_box.y - paint->y_offset,
2662 clip_box.x - x_offset, clip_box.y - y_offset,
2663 clip_box.width, clip_box.height);
2666 if (private->redirect)
2668 int x_offset, y_offset;
2670 /* TODO: Should also use paint->region for clipping */
2671 setup_redirect_clip (window, tmp_gc, &x_offset, &y_offset);
2672 gdk_draw_drawable (private->redirect->pixmap, tmp_gc, paint->pixmap,
2673 clip_box.x - paint->x_offset,
2674 clip_box.y - paint->y_offset,
2675 clip_box.x + x_offset,
2676 clip_box.y + y_offset,
2677 clip_box.width, clip_box.height);
2680 /* Reset clip region of the cached GdkGC */
2681 gdk_gc_set_clip_region (tmp_gc, NULL);
2683 cairo_surface_destroy (paint->surface);
2684 g_object_unref (paint->pixmap);
2685 gdk_region_destroy (paint->region);
2688 /* find a composited window in our hierarchy to signal its
2689 * parent to redraw, calculating the clip box as we go...
2691 * stop if parent becomes NULL since then we'd have nowhere
2692 * to draw (ie: 'composited' will always be non-NULL here).
2694 for (composited = private;
2696 composited = composited->parent)
2700 gdk_drawable_get_size (GDK_DRAWABLE (composited->parent),
2703 clip_box.x += composited->x;
2704 clip_box.y += composited->y;
2705 clip_box.width = MIN (clip_box.width, width - clip_box.x);
2706 clip_box.height = MIN (clip_box.height, height - clip_box.y);
2708 if (composited->composited)
2710 gdk_window_invalidate_rect (GDK_WINDOW (composited->parent),
2715 #endif /* USE_BACKING_STORE */
2719 gdk_window_free_paint_stack (GdkWindow *window)
2721 GdkWindowObject *private = (GdkWindowObject *)window;
2723 if (private->paint_stack)
2725 GSList *tmp_list = private->paint_stack;
2729 GdkWindowPaint *paint = tmp_list->data;
2731 if (tmp_list == private->paint_stack)
2732 g_object_unref (paint->pixmap);
2734 gdk_region_destroy (paint->region);
2737 tmp_list = tmp_list->next;
2740 g_slist_free (private->paint_stack);
2741 private->paint_stack = NULL;
2746 do_move_region_bits_on_impl (GdkWindowObject *impl_window,
2747 GdkRegion *dest_region, /* In impl window coords */
2751 GdkRectangle copy_rect;
2752 GdkWindowObject *private;
2754 /* We need to get data from subwindows here, because we might have
2755 * shaped a native window over the moving region (with bg none,
2756 * so the pixels are still there). In fact we might need to get data
2757 * from overlapping native window that are not children of this window,
2758 * so we copy from the toplevel with INCLUDE_INFERIORS.
2760 private = impl_window;
2761 while (private->parent != NULL &&
2762 private->parent->window_type != GDK_WINDOW_ROOT)
2764 dx -= private->parent->abs_x + private->x;
2765 dy -= private->parent->abs_y + private->y;
2766 private = gdk_window_get_impl_window (private->parent);
2768 tmp_gc = _gdk_drawable_get_subwindow_scratch_gc ((GdkWindow *)private);
2770 /* The region area is moved and we queue translations for all expose events
2771 to the source area that were sent prior to the copy */
2772 gdk_region_offset (dest_region, -dx, -dy); /* Temporarily move to source area */
2773 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->queue_translation ((GdkWindow *)impl_window,
2774 dest_region, dx, dy);
2775 gdk_region_offset (dest_region, dx, dy); /* back to dest area */
2777 gdk_region_get_clipbox (dest_region, ©_rect);
2779 gdk_gc_set_clip_region (tmp_gc, dest_region);
2780 gdk_draw_drawable (impl_window->impl,
2783 copy_rect.x-dx, copy_rect.y-dy,
2784 copy_rect.x, copy_rect.y,
2785 copy_rect.width, copy_rect.height);
2786 gdk_gc_set_clip_region (tmp_gc, NULL);
2789 static GdkWindowRegionMove *
2790 gdk_window_region_move_new (GdkRegion *region,
2793 GdkWindowRegionMove *move;
2795 move = g_slice_new (GdkWindowRegionMove);
2796 move->dest_region = gdk_region_copy (region);
2804 gdk_window_region_move_free (GdkWindowRegionMove *move)
2806 gdk_region_destroy (move->dest_region);
2807 g_slice_free (GdkWindowRegionMove, move);
2811 append_move_region (GdkWindowObject *impl_window,
2812 GdkRegion *new_dest_region,
2815 GdkWindowRegionMove *move, *old_move;
2816 GdkRegion *new_total_region, *old_total_region;
2817 GdkRegion *source_overlaps_destination;
2818 GdkRegion *non_overwritten;
2819 gboolean added_move;
2822 if (gdk_region_empty (new_dest_region))
2825 /* In principle this could just append the move to the list of outstanding
2826 moves that will be replayed before drawing anything when we're handling
2827 exposes. However, we'd like to do a bit better since its commonly the case
2828 that we get multiple copies where A is copied to B and then B is copied
2829 to C, and we'd like to express this as a simple copy A to C operation. */
2831 /* We approach this by taking the new move and pushing it ahead of moves
2832 starting at the end of the list and stopping when its not safe to do so.
2833 It's not safe to push past a move if either the source of the new move
2834 is in the destination of the old move, or if the destination of the new
2835 move is in the source of the new move, or if the destination of the new
2836 move overlaps the destination of the old move. We simplify this by
2837 just comparing the total regions (src + dest) */
2838 new_total_region = gdk_region_copy (new_dest_region);
2839 gdk_region_offset (new_total_region, -dx, -dy);
2840 gdk_region_union (new_total_region, new_dest_region);
2843 for (l = g_list_last (impl_window->outstanding_moves); l != NULL; l = prev)
2848 old_total_region = gdk_region_copy (old_move->dest_region);
2849 gdk_region_offset (old_total_region, -old_move->dx, -old_move->dy);
2850 gdk_region_union (old_total_region, old_move->dest_region);
2852 gdk_region_intersect (old_total_region, new_total_region);
2853 /* If these regions intersect then its not safe to push the
2854 new region before the old one */
2855 if (!gdk_region_empty (old_total_region))
2857 /* The area where the new moves source overlaps the old ones
2859 source_overlaps_destination = gdk_region_copy (new_dest_region);
2860 gdk_region_offset (source_overlaps_destination, -dx, -dy);
2861 gdk_region_intersect (source_overlaps_destination, old_move->dest_region);
2862 gdk_region_offset (source_overlaps_destination, dx, dy);
2864 /* We can do all sort of optimizations here, but to do things safely it becomes
2865 quite complicated. However, a very common case is that you copy something first,
2866 then copy all that or a subset of it to a new location (i.e. if you scroll twice
2867 in the same direction). We'd like to detect this case and optimize it to one
2869 if (gdk_region_equal (source_overlaps_destination, new_dest_region))
2871 /* This means we might be able to replace the old move and the new one
2872 with the new one read from the old ones source, and a second copy of
2873 the non-overwritten parts of the old move. However, such a split
2874 is only valid if the source in the old move isn't overwritten
2875 by the destination of the new one */
2877 /* the new destination of old move if split is ok: */
2878 non_overwritten = gdk_region_copy (old_move->dest_region);
2879 gdk_region_subtract (non_overwritten, new_dest_region);
2880 /* move to source region */
2881 gdk_region_offset (non_overwritten, -old_move->dx, -old_move->dy);
2883 gdk_region_intersect (non_overwritten, new_dest_region);
2884 if (gdk_region_empty (non_overwritten))
2887 move = gdk_window_region_move_new (new_dest_region,
2891 impl_window->outstanding_moves =
2892 g_list_insert_before (impl_window->outstanding_moves,
2894 gdk_region_subtract (old_move->dest_region, new_dest_region);
2896 gdk_region_destroy (non_overwritten);
2899 gdk_region_destroy (source_overlaps_destination);
2900 gdk_region_destroy (old_total_region);
2903 gdk_region_destroy (old_total_region);
2906 gdk_region_destroy (new_total_region);
2910 move = gdk_window_region_move_new (new_dest_region, dx, dy);
2913 impl_window->outstanding_moves =
2914 g_list_prepend (impl_window->outstanding_moves,
2917 impl_window->outstanding_moves =
2918 g_list_insert_before (impl_window->outstanding_moves,
2923 /* Moves bits and update area by dx/dy in impl window,
2924 takes ownership of region */
2926 move_region_on_impl (GdkWindowObject *private,
2927 GdkRegion *region, /* In impl window coords */
2930 GdkWindowObject *impl_window;
2932 if ((dx == 0 && dy == 0) ||
2933 gdk_region_empty (region))
2935 gdk_region_destroy (region);
2939 impl_window = gdk_window_get_impl_window (private);
2941 /* Move any old invalid regions in the copy source area by dx/dy */
2942 if (impl_window->update_area)
2944 GdkRegion *update_area;
2945 update_area = gdk_region_copy (region);
2947 /* Convert from target to source */
2948 gdk_region_offset (update_area, -dx, -dy);
2949 gdk_region_intersect (update_area, impl_window->update_area);
2950 gdk_region_subtract (impl_window->update_area, update_area);
2953 gdk_region_offset (update_area, dx, dy);
2954 gdk_region_union (impl_window->update_area, update_area);
2956 /* This area of the destination is now invalid,
2957 so no need to copy to it. */
2958 gdk_region_subtract (region, update_area);
2960 gdk_region_destroy (update_area);
2963 if (1) /* Enable flicker free handling of moves. */
2964 append_move_region (impl_window, region, dx, dy);
2966 do_move_region_bits_on_impl (impl_window,
2969 gdk_region_destroy (region);
2972 /* Flushes all outstanding changes to the window, call this
2973 * before drawing directly to the window (i.e. outside a begin/end_paint pair).
2976 gdk_window_flush_outstanding_moves (GdkWindow *window)
2978 GdkWindowObject *private;
2979 GdkWindowObject *impl_window;
2981 GdkWindowRegionMove *move;
2983 private = (GdkWindowObject *) window;
2985 impl_window = gdk_window_get_impl_window (private);
2987 for (l = impl_window->outstanding_moves; l != NULL; l = l->next)
2991 do_move_region_bits_on_impl (impl_window,
2992 move->dest_region, move->dx, move->dy);
2994 gdk_window_region_move_free (move);
2997 g_list_free (impl_window->outstanding_moves);
2998 impl_window->outstanding_moves = NULL;
3002 gdk_window_flush (GdkWindow *window)
3004 gdk_window_flush_outstanding_moves (window);
3005 gdk_window_flush_implicit_paint (window);
3009 gdk_window_flush_recursive_helper (GdkWindowObject *window,
3012 GdkWindowObject *child;
3015 for (l = window->children; l != NULL; l = l->next)
3019 if (child->impl == impl)
3020 /* Same impl, ignore */
3021 gdk_window_flush_recursive_helper (child, impl);
3023 gdk_window_flush_recursive (child);
3028 gdk_window_flush_recursive (GdkWindowObject *window)
3030 gdk_window_flush ((GdkWindow *)window);
3031 gdk_window_flush_recursive_helper (window, window->impl);
3035 gdk_window_get_offsets (GdkWindow *window,
3039 GdkWindowObject *private = (GdkWindowObject *)window;
3041 if (private->paint_stack)
3043 GdkWindowPaint *paint = private->paint_stack->data;
3044 *x_offset = paint->x_offset;
3045 *y_offset = paint->y_offset;
3049 *x_offset = -private->abs_x;
3050 *y_offset = -private->abs_y;
3055 * gdk_window_get_internal_paint_info:
3056 * @window: a #GdkWindow
3057 * @real_drawable: location to store the drawable to which drawing should be
3059 * @x_offset: location to store the X offset between coordinates in @window,
3060 * and the underlying window system primitive coordinates for
3062 * @y_offset: location to store the Y offset between coordinates in @window,
3063 * and the underlying window system primitive coordinates for
3066 * If you bypass the GDK layer and use windowing system primitives to
3067 * draw directly onto a #GdkWindow, then you need to deal with two
3068 * details: there may be an offset between GDK coordinates and windowing
3069 * system coordinates, and GDK may have redirected drawing to a offscreen
3070 * pixmap as the result of a gdk_window_begin_paint_region() calls.
3071 * This function allows retrieving the information you need to compensate
3072 * for these effects.
3074 * This function exposes details of the GDK implementation, and is thus
3075 * likely to change in future releases of GDK.
3078 gdk_window_get_internal_paint_info (GdkWindow *window,
3079 GdkDrawable **real_drawable,
3085 GdkWindowObject *private;
3087 g_return_if_fail (GDK_IS_WINDOW (window));
3089 private = (GdkWindowObject *)window;
3093 if (private->paint_stack)
3095 GdkWindowPaint *paint = private->paint_stack->data;
3096 *real_drawable = paint->pixmap;
3100 /* This means you're probably gonna be doing some weird shit
3101 directly to the window, so we flush all outstanding stuff */
3102 gdk_window_flush (window);
3103 *real_drawable = window;
3107 gdk_window_get_offsets (window, &x_off, &y_off);
3115 static GdkDrawable *
3116 start_draw_helper (GdkDrawable *drawable,
3121 GdkWindowObject *private = (GdkWindowObject *)drawable;
3122 gint x_offset, y_offset;
3124 gint old_clip_x = gc->clip_x_origin;
3125 gint old_clip_y = gc->clip_y_origin;
3127 guint32 clip_region_tag;
3128 GdkWindowPaint *paint;
3131 if (private->paint_stack)
3132 paint = private->paint_stack->data;
3136 x_offset = paint->x_offset;
3137 y_offset = paint->y_offset;
3141 x_offset = -private->abs_x;
3142 y_offset = -private->abs_y;
3145 if (x_offset != 0 || y_offset != 0)
3147 gdk_gc_set_clip_origin (gc,
3148 old_clip_x - x_offset,
3149 old_clip_y - y_offset);
3150 gdk_gc_set_ts_origin (gc,
3151 gc->ts_x_origin - x_offset,
3152 gc->ts_y_origin - y_offset);
3155 *x_offset_out = x_offset;
3156 *y_offset_out = y_offset;
3158 /* Add client side window clip region to gc */
3162 /* Only need clipping if using implicit paint, otherwise
3163 the pixmap is clipped when copying to the window in end_paint */
3164 if (paint->uses_implicit)
3166 /* This includes the window clip */
3167 clip = paint->region;
3169 clip_region_tag = paint->region_tag;
3171 /* After having set up the drawable clip rect on a GC we need to make sure
3172 * that we draw to th the impl, otherwise the pixmap code will reset the
3174 impl = ((GdkPixmapObject *)(paint->pixmap))->impl;
3178 /* Drawing directly to the window, flush anything outstanding to
3179 guarantee ordering. */
3180 gdk_window_flush ((GdkWindow *)drawable);
3182 /* Don't clip when drawing to root */
3183 if (private->window_type != GDK_WINDOW_ROOT)
3185 if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
3186 clip = private->clip_region_with_children;
3188 clip = private->clip_region;
3190 clip_region_tag = private->clip_tag;
3191 impl = private->impl;
3195 _gdk_gc_add_drawable_clip (gc,
3196 clip_region_tag, clip,
3197 /* If there was a clip origin set appart from the
3198 * window offset, need to take that into
3200 -old_clip_x, -old_clip_y);
3205 #define BEGIN_DRAW \
3207 GdkDrawable *impl; \
3208 gint x_offset, y_offset; \
3209 gint old_clip_x = gc->clip_x_origin; \
3210 gint old_clip_y = gc->clip_y_origin; \
3211 gint old_ts_x = gc->ts_x_origin; \
3212 gint old_ts_y = gc->ts_y_origin; \
3213 impl = start_draw_helper (drawable, gc, \
3214 &x_offset, &y_offset);
3217 if (x_offset != 0 || y_offset != 0) \
3219 gdk_gc_set_clip_origin (gc, old_clip_x, old_clip_y); \
3220 gdk_gc_set_ts_origin (gc, old_ts_x, old_ts_y); \
3225 gdk_window_create_gc (GdkDrawable *drawable,
3226 GdkGCValues *values,
3227 GdkGCValuesMask mask)
3229 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
3231 if (GDK_WINDOW_DESTROYED (drawable))
3234 return gdk_gc_new_with_values (((GdkWindowObject *) drawable)->impl,
3239 gdk_window_draw_rectangle (GdkDrawable *drawable,
3247 if (GDK_WINDOW_DESTROYED (drawable))
3251 gdk_draw_rectangle (impl, gc, filled,
3252 x - x_offset, y - y_offset, width, height);
3257 gdk_window_draw_arc (GdkDrawable *drawable,
3267 if (GDK_WINDOW_DESTROYED (drawable))
3271 gdk_draw_arc (impl, gc, filled,
3272 x - x_offset, y - y_offset,
3273 width, height, angle1, angle2);
3278 gdk_window_draw_polygon (GdkDrawable *drawable,
3284 GdkPoint *new_points;
3286 if (GDK_WINDOW_DESTROYED (drawable))
3291 if (x_offset != 0 || y_offset != 0)
3295 new_points = g_new (GdkPoint, npoints);
3296 for (i=0; i<npoints; i++)
3298 new_points[i].x = points[i].x - x_offset;
3299 new_points[i].y = points[i].y - y_offset;
3303 new_points = points;
3305 gdk_draw_polygon (impl, gc, filled, new_points, npoints);
3307 if (new_points != points)
3308 g_free (new_points);
3314 gdk_window_draw_text (GdkDrawable *drawable,
3322 if (GDK_WINDOW_DESTROYED (drawable))
3326 gdk_draw_text (impl, font, gc,
3327 x - x_offset, y - y_offset, text, text_length);
3332 gdk_window_draw_text_wc (GdkDrawable *drawable,
3337 const GdkWChar *text,
3340 if (GDK_WINDOW_DESTROYED (drawable))
3344 gdk_draw_text_wc (impl, font, gc,
3345 x - x_offset, y - y_offset, text, text_length);
3349 static GdkDrawable *
3350 gdk_window_get_source_drawable (GdkDrawable *drawable)
3352 GdkWindow *window = GDK_WINDOW (drawable);
3353 GdkWindowObject *private;
3355 private = (GdkWindowObject *) window;
3356 if (GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable)
3357 return GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable (private->impl);
3362 static GdkDrawable *
3363 gdk_window_get_composite_drawable (GdkDrawable *drawable,
3368 gint *composite_x_offset,
3369 gint *composite_y_offset)
3371 GdkWindowObject *private = (GdkWindowObject *)drawable;
3373 GdkPixmap *tmp_pixmap;
3376 gboolean overlap_buffer;
3377 GdkDrawable *source;
3378 GdkWindowObject *impl_window;
3379 GdkWindowPaint *implicit_paint;
3381 *composite_x_offset = -private->abs_x;
3382 *composite_y_offset = -private->abs_y;
3384 if ((GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable)))
3385 return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
3387 /* See if any buffered part is overlapping the part we want
3393 rect.height = height;
3395 overlap_buffer = FALSE;
3397 for (list = private->paint_stack; list != NULL; list = list->next)
3399 GdkWindowPaint *paint = list->data;
3400 GdkOverlapType overlap;
3402 overlap = gdk_region_rect_in (paint->region, &rect);
3404 if (overlap == GDK_OVERLAP_RECTANGLE_IN)
3406 *composite_x_offset = paint->x_offset;
3407 *composite_y_offset = paint->y_offset;
3409 return g_object_ref (paint->pixmap);
3411 else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
3413 overlap_buffer = TRUE;
3418 impl_window = gdk_window_get_impl_window (private);
3419 implicit_paint = impl_window->implicit_paint;
3422 GdkOverlapType overlap;
3424 rect.x += private->abs_x;
3425 rect.y += private->abs_y;
3427 overlap = gdk_region_rect_in (implicit_paint->region, &rect);
3428 if (overlap == GDK_OVERLAP_RECTANGLE_IN)
3430 *composite_x_offset = -private->abs_x + implicit_paint->x_offset;
3431 *composite_y_offset = -private->abs_y + implicit_paint->y_offset;
3433 return g_object_ref (implicit_paint->pixmap);
3435 else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
3436 overlap_buffer = TRUE;
3439 if (!overlap_buffer)
3440 return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
3442 tmp_pixmap = gdk_pixmap_new (drawable, width, height, -1);
3443 tmp_gc = _gdk_drawable_get_scratch_gc (tmp_pixmap, FALSE);
3445 source = _gdk_drawable_get_source_drawable (drawable);
3447 /* Copy the current window contents */
3448 gdk_draw_drawable (tmp_pixmap,
3450 GDK_WINDOW_OBJECT (source)->impl,
3451 x - *composite_x_offset,
3452 y - *composite_y_offset,
3456 /* paint the backing stores */
3459 GdkWindowPaint *paint = list->data;
3461 gdk_gc_set_clip_region (tmp_gc, paint->region);
3462 gdk_gc_set_clip_origin (tmp_gc, -x - paint->x_offset, -y - paint->y_offset);
3464 gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
3465 x - paint->x_offset,
3466 y - paint->y_offset,
3467 0, 0, width, height);
3470 for (list = private->paint_stack; list != NULL; list = list->next)
3472 GdkWindowPaint *paint = list->data;
3474 if (paint->uses_implicit)
3475 continue; /* We already copied this above */
3477 gdk_gc_set_clip_region (tmp_gc, paint->region);
3478 gdk_gc_set_clip_origin (tmp_gc, -x, -y);
3480 gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
3481 x - paint->x_offset,
3482 y - paint->y_offset,
3483 0, 0, width, height);
3486 /* Reset clip region of the cached GdkGC */
3487 gdk_gc_set_clip_region (tmp_gc, NULL);
3489 /* Set these to location of tmp_pixmap within the window */
3490 *composite_x_offset = x;
3491 *composite_y_offset = y;
3497 gdk_window_get_clip_region (GdkDrawable *drawable)
3499 GdkWindowObject *private = (GdkWindowObject *)drawable;
3502 result = gdk_region_copy (private->clip_region);
3504 if (private->paint_stack)
3506 GdkRegion *paint_region = gdk_region_new ();
3507 GSList *tmp_list = private->paint_stack;
3511 GdkWindowPaint *paint = tmp_list->data;
3513 gdk_region_union (paint_region, paint->region);
3515 tmp_list = tmp_list->next;
3518 gdk_region_intersect (result, paint_region);
3519 gdk_region_destroy (paint_region);
3526 gdk_window_get_visible_region (GdkDrawable *drawable)
3528 GdkWindowObject *private = (GdkWindowObject*) drawable;
3530 return gdk_region_copy (private->clip_region);
3534 gdk_window_draw_drawable (GdkDrawable *drawable,
3543 GdkDrawable *original_src)
3545 GdkWindowObject *private = (GdkWindowObject *)drawable;
3547 if (GDK_WINDOW_DESTROYED (drawable))
3552 gdk_draw_drawable (impl, gc, src, xsrc, ysrc,
3553 xdest - x_offset, ydest - y_offset, width, height);
3555 if (!private->paint_stack)
3557 /* We might have drawn from an obscured part of a client
3558 side window, if so we need to send graphics exposures */
3559 if (_gdk_gc_get_exposures (gc) &&
3560 GDK_IS_WINDOW (original_src))
3562 GdkRegion *exposure_region;
3570 exposure_region = gdk_region_rectangle (&r);
3572 if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
3573 clip = private->clip_region_with_children;
3575 clip = private->clip_region;
3576 gdk_region_intersect (exposure_region, clip);
3578 clip = _gdk_gc_get_clip_region (gc);
3581 gdk_region_offset (exposure_region,
3584 gdk_region_intersect (exposure_region, clip);
3585 gdk_region_offset (exposure_region,
3590 /* Note: We don't clip by the clip mask if set, so this
3591 may invalidate to much */
3593 /* Remove the area that is correctly copied from the src.
3594 * Note that xsrc/ysrc has been corrected for abs_x/y offsets already,
3595 * which need to be undone */
3596 clip = gdk_drawable_get_visible_region (original_src);
3597 gdk_region_offset (clip,
3598 xdest - (xsrc - GDK_WINDOW_OBJECT (original_src)->abs_x),
3599 ydest - (ysrc - GDK_WINDOW_OBJECT (original_src)->abs_y));
3600 gdk_region_subtract (exposure_region, clip);
3601 gdk_region_destroy (clip);
3603 gdk_window_invalidate_region (GDK_WINDOW (private),
3605 _gdk_gc_get_subwindow (gc) == GDK_INCLUDE_INFERIORS);
3607 gdk_region_destroy (exposure_region);
3615 gdk_window_draw_points (GdkDrawable *drawable,
3620 GdkPoint *new_points;
3622 if (GDK_WINDOW_DESTROYED (drawable))
3627 if (x_offset != 0 || y_offset != 0)
3631 new_points = g_new (GdkPoint, npoints);
3632 for (i=0; i<npoints; i++)
3634 new_points[i].x = points[i].x - x_offset;
3635 new_points[i].y = points[i].y - y_offset;
3639 new_points = points;
3641 gdk_draw_points (impl, gc, new_points, npoints);
3643 if (new_points != points)
3644 g_free (new_points);
3650 gdk_window_draw_segments (GdkDrawable *drawable,
3655 GdkSegment *new_segs;
3657 if (GDK_WINDOW_DESTROYED (drawable))
3662 if (x_offset != 0 || y_offset != 0)
3666 new_segs = g_new (GdkSegment, nsegs);
3667 for (i=0; i<nsegs; i++)
3669 new_segs[i].x1 = segs[i].x1 - x_offset;
3670 new_segs[i].y1 = segs[i].y1 - y_offset;
3671 new_segs[i].x2 = segs[i].x2 - x_offset;
3672 new_segs[i].y2 = segs[i].y2 - y_offset;
3678 gdk_draw_segments (impl, gc, new_segs, nsegs);
3680 if (new_segs != segs)
3687 gdk_window_draw_lines (GdkDrawable *drawable,
3692 GdkPoint *new_points;
3694 if (GDK_WINDOW_DESTROYED (drawable))
3699 if (x_offset != 0 || y_offset != 0)
3703 new_points = g_new (GdkPoint, npoints);
3704 for (i=0; i<npoints; i++)
3706 new_points[i].x = points[i].x - x_offset;
3707 new_points[i].y = points[i].y - y_offset;
3711 new_points = points;
3713 gdk_draw_lines (impl, gc, new_points, npoints);
3715 if (new_points != points)
3716 g_free (new_points);
3722 gdk_window_draw_glyphs (GdkDrawable *drawable,
3727 PangoGlyphString *glyphs)
3729 if (GDK_WINDOW_DESTROYED (drawable))
3733 gdk_draw_glyphs (impl, gc, font,
3734 x - x_offset, y - y_offset, glyphs);
3739 gdk_window_draw_glyphs_transformed (GdkDrawable *drawable,
3741 PangoMatrix *matrix,
3745 PangoGlyphString *glyphs)
3747 PangoMatrix tmp_matrix;
3749 if (GDK_WINDOW_DESTROYED (drawable))
3754 if (x_offset != 0 || y_offset != 0)
3758 tmp_matrix = *matrix;
3759 tmp_matrix.x0 -= x_offset;
3760 tmp_matrix.y0 -= y_offset;
3761 matrix = &tmp_matrix;
3763 else if (GDK_PANGO_UNITS_OVERFLOWS (x_offset, y_offset))
3765 PangoMatrix identity = PANGO_MATRIX_INIT;
3767 tmp_matrix = identity;
3768 tmp_matrix.x0 -= x_offset;
3769 tmp_matrix.y0 -= y_offset;
3770 matrix = &tmp_matrix;
3774 x -= x_offset * PANGO_SCALE;
3775 y -= y_offset * PANGO_SCALE;
3779 gdk_draw_glyphs_transformed (impl, gc, matrix, font, x, y, glyphs);
3785 cairo_t *cr; /* if non-null, it means use this cairo context */
3786 GdkGC *gc; /* if non-null, it means use this GC instead */
3787 } BackingRectMethod;
3790 setup_backing_rect_method (BackingRectMethod *method, GdkWindow *window, GdkWindowPaint *paint, int x_offset_cairo, int y_offset_cairo)
3792 GdkWindowObject *private = (GdkWindowObject *)window;
3794 if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
3796 GdkWindowPaint tmp_paint;
3799 tmp_paint.x_offset += private->x;
3800 tmp_paint.y_offset += private->y;
3802 x_offset_cairo += private->x;
3803 y_offset_cairo += private->y;
3805 setup_backing_rect_method (method, GDK_WINDOW (private->parent), &tmp_paint, x_offset_cairo, y_offset_cairo);
3807 else if (private->bg_pixmap &&
3808 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
3809 private->bg_pixmap != GDK_NO_BG)
3811 /* This is a workaround for https://bugs.freedesktop.org/show_bug.cgi?id=4320.
3812 * In it, using a pixmap as a repeating pattern in Cairo, and painting it to a
3813 * pixmap destination surface, can be very slow (on the order of seconds for a
3814 * whole-screen copy). The workaround is to use pretty much the same code that
3815 * we used in GTK+ 2.6 (pre-Cairo), which clears the double-buffer pixmap with
3816 * a tiled GC XFillRectangle().
3819 /* Actually computing this flag is left as an exercise for the reader */
3820 #if defined (G_OS_UNIX)
3821 # define GDK_CAIRO_REPEAT_IS_FAST 0
3823 # define GDK_CAIRO_REPEAT_IS_FAST 1
3826 #if GDK_CAIRO_REPEAT_IS_FAST
3827 cairo_surface_t *surface = _gdk_drawable_ref_cairo_surface (private->bg_pixmap);
3828 cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
3829 cairo_surface_destroy (surface);
3831 if (x_offset_cairo != 0 || y_offset_cairo != 0)
3833 cairo_matrix_t matrix;
3834 cairo_matrix_init_translate (&matrix, x_offset_cairo, y_offset_cairo);
3835 cairo_pattern_set_matrix (pattern, &matrix);
3838 cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
3840 method->cr = cairo_create (paint->surface);
3843 cairo_set_source (method->cr, pattern);
3844 cairo_pattern_destroy (pattern);
3847 GdkGCValues gc_values;
3849 gc_values.fill = GDK_TILED;
3850 gc_values.tile = private->bg_pixmap;
3851 gc_values.ts_x_origin = -x_offset_cairo;
3852 gc_values.ts_y_origin = -y_offset_cairo;
3854 gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN;
3856 method->gc = gdk_gc_new_with_values (paint->pixmap, &gc_values, gc_mask);
3861 method->cr = cairo_create (paint->surface);
3863 gdk_cairo_set_source_color (method->cr, &private->bg_color);
3868 gdk_window_clear_backing_region (GdkWindow *window,
3871 GdkWindowObject *private = (GdkWindowObject *)window;
3872 GdkWindowPaint *paint = private->paint_stack->data;
3873 BackingRectMethod method;
3875 GdkRectangle clipbox;
3881 if (GDK_WINDOW_DESTROYED (window))
3885 timer = g_timer_new ();
3890 setup_backing_rect_method (&method, window, paint, 0, 0);
3892 clip = gdk_region_copy (paint->region);
3893 gdk_region_intersect (clip, region);
3894 gdk_region_get_clipbox (clip, &clipbox);
3899 g_assert (method.gc == NULL);
3901 gdk_cairo_region (method.cr, clip);
3902 cairo_fill (method.cr);
3904 cairo_destroy (method.cr);
3906 elapsed = g_timer_elapsed (timer, NULL);
3907 g_print ("Draw the background with Cairo: %fs\n", elapsed);
3912 g_assert (method.gc != NULL);
3914 gdk_gc_set_clip_region (method.gc, clip);
3915 gdk_draw_rectangle (window, method.gc, TRUE,
3916 clipbox.x, clipbox.y,
3917 clipbox.width, clipbox.height);
3918 g_object_unref (method.gc);
3921 elapsed = g_timer_elapsed (timer, NULL);
3922 g_print ("Draw the background with GDK: %fs\n", elapsed);
3926 gdk_region_destroy (clip);
3929 g_timer_destroy (timer);
3934 gdk_window_clear_backing_region_redirect (GdkWindow *window,
3937 GdkWindowObject *private = (GdkWindowObject *)window;
3938 GdkWindowRedirect *redirect = private->redirect;
3939 GdkRegion *clip_region;
3940 GdkRectangle clipbox;
3941 gint x_offset, y_offset;
3942 BackingRectMethod method;
3943 GdkWindowPaint paint;
3945 if (GDK_WINDOW_DESTROYED (window))
3948 clip_region = _gdk_window_calculate_full_clip_region (window,
3949 GDK_WINDOW (redirect->redirected),
3951 &x_offset, &y_offset);
3952 gdk_region_intersect (clip_region, region);
3954 /* offset is from redirected window origin to window origin, convert to
3955 the offset from the redirected pixmap origin to the window origin */
3956 x_offset += redirect->dest_x - redirect->src_x;
3957 y_offset += redirect->dest_y - redirect->src_y;
3959 /* Convert region to pixmap coords */
3960 gdk_region_offset (clip_region, x_offset, y_offset);
3964 paint.pixmap = redirect->pixmap;
3965 paint.surface = _gdk_drawable_ref_cairo_surface (redirect->pixmap);
3969 setup_backing_rect_method (&method, window, &paint, -x_offset, -y_offset);
3973 g_assert (method.gc == NULL);
3975 gdk_cairo_region (method.cr, clip_region);
3976 cairo_fill (method.cr);
3978 cairo_destroy (method.cr);
3982 g_assert (method.gc != NULL);
3984 gdk_region_get_clipbox (clip_region, &clipbox);
3985 gdk_gc_set_clip_region (method.gc, clip_region);
3986 gdk_draw_rectangle (redirect->pixmap, method.gc, TRUE,
3987 clipbox.x, clipbox.y,
3988 clipbox.width, clipbox.height);
3989 g_object_unref (method.gc);
3993 gdk_region_destroy (clip_region);
3994 cairo_surface_destroy (paint.surface);
3998 gdk_window_clear_backing_region_direct (GdkWindow *window,
4001 GdkWindowObject *private = (GdkWindowObject *)window;
4002 BackingRectMethod method;
4003 GdkWindowPaint paint;
4005 GdkRectangle clipbox;
4007 if (GDK_WINDOW_DESTROYED (window))
4012 paint.pixmap = window;
4013 paint.surface = _gdk_drawable_ref_cairo_surface (window);
4017 setup_backing_rect_method (&method, window, &paint, 0, 0);
4019 clip = gdk_region_copy (private->clip_region_with_children);
4020 gdk_region_intersect (clip, region);
4021 gdk_region_get_clipbox (clip, &clipbox);
4025 g_assert (method.gc == NULL);
4027 gdk_cairo_region (method.cr, clip);
4028 cairo_fill (method.cr);
4030 cairo_destroy (method.cr);
4034 g_assert (method.gc != NULL);
4036 gdk_gc_set_clip_region (method.gc, clip);
4037 gdk_draw_rectangle (window, method.gc, TRUE,
4038 clipbox.x, clipbox.y,
4039 clipbox.width, clipbox.height);
4040 g_object_unref (method.gc);
4044 gdk_region_destroy (clip);
4045 cairo_surface_destroy (paint.surface);
4051 * @window: a #GdkWindow
4053 * Clears an entire @window to the background color or background pixmap.
4056 gdk_window_clear (GdkWindow *window)
4060 g_return_if_fail (GDK_IS_WINDOW (window));
4062 gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height);
4064 gdk_window_clear_area (window, 0, 0,
4069 gdk_window_clear_region_internal (GdkWindow *window,
4071 gboolean send_expose)
4073 GdkWindowObject *private = (GdkWindowObject *)window;
4075 if (private->paint_stack)
4076 gdk_window_clear_backing_region (window, region);
4079 if (private->redirect)
4080 gdk_window_clear_backing_region_redirect (window, region);
4082 if (GDK_WINDOW_IMPL_GET_IFACE (private->impl)->clear_region &&
4083 gdk_window_has_impl (private))
4086 copy = gdk_region_copy (region);
4087 gdk_region_intersect (copy, private->clip_region_with_children);
4089 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->clear_region
4090 (window, copy, send_expose);
4092 gdk_region_destroy (copy);
4096 gdk_window_clear_backing_region_direct (window, region);
4098 gdk_window_invalidate_region (window, region, FALSE);
4104 gdk_window_clear_area_internal (GdkWindow *window,
4109 gboolean send_expose)
4111 GdkWindowObject *private = (GdkWindowObject *)window;
4115 g_return_if_fail (GDK_IS_WINDOW (window));
4117 if (GDK_WINDOW_DESTROYED (window))
4120 /* This is what XClearArea does, and e.g. GtkCList uses it,
4121 so we need to duplicate that */
4123 width = private->width - x;
4125 height = private->height - y;
4130 rect.height = height;
4132 region = gdk_region_rectangle (&rect);
4133 gdk_window_clear_region_internal (window,
4136 gdk_region_destroy (region);
4141 * gdk_window_clear_area:
4142 * @window: a #GdkWindow
4143 * @x: x coordinate of rectangle to clear
4144 * @y: y coordinate of rectangle to clear
4145 * @width: width of rectangle to clear
4146 * @height: height of rectangle to clear
4148 * Clears an area of @window to the background color or background pixmap.
4152 gdk_window_clear_area (GdkWindow *window,
4158 gdk_window_clear_area_internal (window,
4165 * gdk_window_clear_area_e:
4166 * @window: a #GdkWindow
4167 * @x: x coordinate of rectangle to clear
4168 * @y: y coordinate of rectangle to clear
4169 * @width: width of rectangle to clear
4170 * @height: height of rectangle to clear
4172 * Like gdk_window_clear_area(), but also generates an expose event for
4175 * This function has a stupid name because it dates back to the mists
4176 * time, pre-GDK-1.0.
4180 gdk_window_clear_area_e (GdkWindow *window,
4186 gdk_window_clear_area_internal (window,
4193 gdk_window_draw_image (GdkDrawable *drawable,
4203 if (GDK_WINDOW_DESTROYED (drawable))
4207 gdk_draw_image (impl, gc, image, xsrc, ysrc,
4208 xdest - x_offset, ydest - y_offset,
4214 gdk_window_draw_pixbuf (GdkDrawable *drawable,
4223 GdkRgbDither dither,
4227 GdkWindowObject *private = (GdkWindowObject *)drawable;
4229 if (GDK_WINDOW_DESTROYED (drawable))
4232 /* If no gc => no user clipping, but we need clipping
4233 for window emulation, so use a scratch gc */
4235 gc = _gdk_drawable_get_scratch_gc (drawable, FALSE);
4238 if (private->paint_stack)
4239 gdk_draw_pixbuf (impl, gc, pixbuf, src_x, src_y,
4240 dest_x - x_offset, dest_y - y_offset,
4242 dither, x_dither - x_offset, y_dither - y_offset);
4244 gdk_draw_pixbuf (impl, gc, pixbuf, src_x, src_y,
4245 dest_x - x_offset, dest_y - y_offset,
4247 dither, x_dither, y_dither);
4252 gdk_window_draw_trapezoids (GdkDrawable *drawable,
4254 GdkTrapezoid *trapezoids,
4257 GdkTrapezoid *new_trapezoids = NULL;
4259 if (GDK_WINDOW_DESTROYED (drawable))
4264 if (x_offset != 0 || y_offset != 0)
4268 new_trapezoids = g_new (GdkTrapezoid, n_trapezoids);
4269 for (i=0; i < n_trapezoids; i++)
4271 new_trapezoids[i].y1 = trapezoids[i].y1 - y_offset;
4272 new_trapezoids[i].x11 = trapezoids[i].x11 - x_offset;
4273 new_trapezoids[i].x21 = trapezoids[i].x21 - x_offset;
4274 new_trapezoids[i].y2 = trapezoids[i].y2 - y_offset;
4275 new_trapezoids[i].x12 = trapezoids[i].x12 - x_offset;
4276 new_trapezoids[i].x22 = trapezoids[i].x22 - x_offset;
4279 trapezoids = new_trapezoids;
4282 gdk_draw_trapezoids (impl, gc, trapezoids, n_trapezoids);
4284 g_free (new_trapezoids);
4290 gdk_window_real_get_size (GdkDrawable *drawable,
4294 GdkWindowObject *private = (GdkWindowObject *)drawable;
4297 *width = private->width;
4299 *height = private->height;
4303 gdk_window_real_get_visual (GdkDrawable *drawable)
4305 GdkColormap *colormap;
4307 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4309 colormap = gdk_drawable_get_colormap (drawable);
4310 return colormap ? gdk_colormap_get_visual (colormap) : NULL;
4314 gdk_window_real_get_depth (GdkDrawable *drawable)
4316 g_return_val_if_fail (GDK_IS_WINDOW (drawable), 0);
4318 return ((GdkWindowObject *)GDK_WINDOW (drawable))->depth;
4322 gdk_window_real_get_screen (GdkDrawable *drawable)
4324 return gdk_drawable_get_screen (GDK_WINDOW_OBJECT (drawable)->impl);
4328 gdk_window_real_set_colormap (GdkDrawable *drawable,
4331 GdkWindowObject *private;
4333 g_return_if_fail (GDK_IS_WINDOW (drawable));
4335 if (GDK_WINDOW_DESTROYED (drawable))
4338 private = (GdkWindowObject *)drawable;
4340 /* different colormap than parent, requires native window */
4341 if (!private->input_only &&
4342 cmap != gdk_drawable_get_colormap ((GdkDrawable *)(private->parent)))
4343 gdk_window_ensure_native ((GdkWindow *)drawable);
4345 gdk_drawable_set_colormap (private->impl, cmap);
4349 gdk_window_real_get_colormap (GdkDrawable *drawable)
4351 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4353 if (GDK_WINDOW_DESTROYED (drawable))
4356 return gdk_drawable_get_colormap (((GdkWindowObject*)drawable)->impl);
4360 gdk_window_copy_to_image (GdkDrawable *drawable,
4369 GdkWindowObject *private = (GdkWindowObject *) drawable;
4370 gint x_offset, y_offset;
4372 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4374 if (GDK_WINDOW_DESTROYED (drawable))
4377 /* If we're here, a composite image was not necessary, so
4378 * we can ignore the paint stack.
4381 /* TODO: Is this right? */
4385 return gdk_drawable_copy_to_image (private->impl,
4394 gdk_window_cairo_surface_destroy (void *data)
4396 GdkWindowObject *private = (GdkWindowObject*) data;
4398 private->cairo_surface = NULL;
4401 static cairo_surface_t *
4402 gdk_window_create_cairo_surface (GdkDrawable *drawable,
4406 return _gdk_windowing_create_cairo_surface (GDK_WINDOW_OBJECT(drawable)->impl,
4411 static cairo_surface_t *
4412 gdk_window_ref_cairo_surface (GdkDrawable *drawable)
4414 GdkWindowObject *private = (GdkWindowObject*) drawable;
4415 cairo_surface_t *surface;
4417 if (private->paint_stack)
4419 GdkWindowPaint *paint = private->paint_stack->data;
4421 surface = paint->surface;
4422 cairo_surface_reference (surface);
4427 /* This will be drawing directly to the window, so flush implicit paint */
4428 gdk_window_flush ((GdkWindow *)drawable);
4430 if (!private->cairo_surface)
4433 GdkDrawable *source;
4435 /* It would be nice if we had some cairo support here so we
4436 could set the clip rect on the cairo surface */
4437 width = private->abs_x + private->width;
4438 height = private->abs_y + private->height;
4440 source = _gdk_drawable_get_source_drawable (drawable);
4442 /* TODO: Avoid the typecheck crap by adding virtual call */
4443 private->cairo_surface = _gdk_drawable_create_cairo_surface (source, width, height);
4445 if (private->cairo_surface)
4447 cairo_surface_set_device_offset (private->cairo_surface,
4451 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
4452 drawable, gdk_window_cairo_surface_destroy);
4456 cairo_surface_reference (private->cairo_surface);
4458 surface = private->cairo_surface;
4465 gdk_window_set_cairo_clip (GdkDrawable *drawable,
4468 GdkWindowObject *private = (GdkWindowObject*) drawable;
4470 if (!private->paint_stack)
4473 cairo_identity_matrix (cr);
4475 cairo_reset_clip (cr);
4477 cairo_new_path (cr);
4478 gdk_cairo_region (cr, private->clip_region_with_children);
4485 GdkWindowPaint *paint = private->paint_stack->data;
4487 /* Only needs to clip to region if piggybacking
4488 on an implicit paint pixmap */
4489 if (paint->uses_implicit)
4492 cairo_identity_matrix (cr);
4494 cairo_reset_clip (cr);
4496 cairo_new_path (cr);
4497 gdk_cairo_region (cr, paint->region);
4505 /* Code for dirty-region queueing
4507 static GSList *update_windows = NULL;
4508 static guint update_idle = 0;
4509 static gboolean debug_updates = FALSE;
4511 static inline gboolean
4512 gdk_window_is_ancestor (GdkWindow *window,
4513 GdkWindow *ancestor)
4517 GdkWindow *parent = (GdkWindow*) ((GdkWindowObject*) window)->parent;
4519 if (parent == ancestor)
4529 gdk_window_add_update_window (GdkWindow *window)
4532 GSList *prev = NULL;
4533 gboolean has_ancestor_in_list = FALSE;
4535 for (tmp = update_windows; tmp; tmp = tmp->next)
4537 GdkWindowObject *parent = GDK_WINDOW_OBJECT (window)->parent;
4539 /* check if tmp is an ancestor of "window"; if it is, set a
4540 * flag indicating that all following windows are either
4541 * children of "window" or from a differen hierarchy
4543 if (!has_ancestor_in_list && gdk_window_is_ancestor (window, tmp->data))
4544 has_ancestor_in_list = TRUE;
4546 /* insert in reverse stacking order when adding around siblings,
4547 * so processing updates properly paints over lower stacked windows
4549 if (parent == GDK_WINDOW_OBJECT (tmp->data)->parent)
4551 gint index = g_list_index (parent->children, window);
4552 for (; tmp && parent == GDK_WINDOW_OBJECT (tmp->data)->parent; tmp = tmp->next)
4554 gint sibling_index = g_list_index (parent->children, tmp->data);
4555 if (index > sibling_index)
4559 /* here, tmp got advanced past all lower stacked siblings */
4560 tmp = g_slist_prepend (tmp, window);
4564 update_windows = tmp;
4568 /* if "window" has an ancestor in the list and tmp is one of
4569 * "window's" children, insert "window" before tmp
4571 if (has_ancestor_in_list && gdk_window_is_ancestor (tmp->data, window))
4573 tmp = g_slist_prepend (tmp, window);
4578 update_windows = tmp;
4582 /* if we're at the end of the list and had an ancestor it it,
4583 * append to the list
4585 if (! tmp->next && has_ancestor_in_list)
4587 tmp = g_slist_append (tmp, window);
4594 /* if all above checks failed ("window" is from a different
4595 * hierarchy than what is already in the list) or the list is
4598 update_windows = g_slist_prepend (update_windows, window);
4602 gdk_window_remove_update_window (GdkWindow *window)
4604 update_windows = g_slist_remove (update_windows, window);
4608 gdk_window_update_idle (gpointer data)
4610 gdk_window_process_all_updates ();
4616 gdk_window_is_toplevel_frozen (GdkWindow *window)
4618 GdkWindowObject *toplevel;
4620 toplevel = (GdkWindowObject *)gdk_window_get_toplevel (window);
4622 return toplevel->update_and_descendants_freeze_count > 0;
4626 gdk_window_schedule_update (GdkWindow *window)
4629 (GDK_WINDOW_OBJECT (window)->update_freeze_count ||
4630 gdk_window_is_toplevel_frozen (window)))
4635 update_idle = gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
4636 gdk_window_update_idle, NULL, NULL);
4641 _gdk_window_process_updates_recurse (GdkWindow *window,
4642 GdkRegion *expose_region)
4644 GdkWindowObject *private = (GdkWindowObject *)window;
4645 GdkWindowObject *child;
4646 GdkRegion *child_region;
4650 if (gdk_region_empty (expose_region))
4653 /* Iterate over children, starting at topmost */
4654 for (l = private->children; l != NULL; l = l->next)
4658 if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
4661 /* Ignore offscreen children, as they don't draw in their parent and
4662 * don't take part in the clipping */
4663 if (gdk_window_is_offscreen (child))
4668 r.width = child->width;
4669 r.height = child->height;
4671 child_region = gdk_region_rectangle (&r);
4674 /* Adjust shape region to parent window coords */
4675 gdk_region_offset (child->shape, child->x, child->y);
4676 gdk_region_intersect (child_region, child->shape);
4677 gdk_region_offset (child->shape, -child->x, -child->y);
4680 if (child->impl == private->impl)
4682 /* Client side child, expose */
4683 gdk_region_intersect (child_region, expose_region);
4684 gdk_region_subtract (expose_region, child_region);
4685 gdk_region_offset (child_region, -child->x, -child->y);
4686 _gdk_window_process_updates_recurse ((GdkWindow *)child, child_region);
4690 /* Native child, just remove area from expose region */
4691 gdk_region_subtract (expose_region, child_region);
4693 gdk_region_destroy (child_region);
4696 if (!gdk_region_empty (expose_region))
4698 if (private->event_mask & GDK_EXPOSURE_MASK)
4702 event.expose.type = GDK_EXPOSE;
4703 event.expose.window = g_object_ref (window);
4704 event.expose.send_event = FALSE;
4705 event.expose.count = 0;
4706 event.expose.region = expose_region;
4707 gdk_region_get_clipbox (expose_region, &event.expose.area);
4709 (*_gdk_event_func) (&event, _gdk_event_data);
4711 g_object_unref (window);
4713 else if (private->bg_pixmap != GDK_NO_BG)
4715 /* No exposure mask set, so nothing will be drawn, the
4716 * app relies on the background being what it specified
4717 * for the window. So, we need to clear this manually.
4719 * We use begin/end_paint around the clear so that we can
4720 * piggyback on the implicit paint */
4722 gdk_window_begin_paint_region (window, expose_region);
4723 gdk_window_clear_region_internal (window, expose_region, FALSE);
4724 gdk_window_end_paint (window);
4730 gdk_window_process_updates_internal (GdkWindow *window)
4732 GdkWindowObject *private = (GdkWindowObject *)window;
4733 gboolean save_region = FALSE;
4734 GdkRectangle clip_box;
4736 /* If an update got queued during update processing, we can get a
4737 * window in the update queue that has an empty update_area.
4740 if (private->update_area)
4742 GdkRegion *update_area = private->update_area;
4743 private->update_area = NULL;
4745 if (_gdk_event_func && gdk_window_is_viewable (window) &&
4746 private->window_type != GDK_WINDOW_FOREIGN)
4748 GdkRectangle window_rect;
4749 GdkRegion *expose_region;
4750 GdkRegion *window_region;
4751 gboolean end_implicit;
4753 /* Clip to part visible in toplevel */
4754 gdk_region_intersect (update_area, private->clip_region);
4758 /* Make sure we see the red invalid area before redrawing. */
4759 gdk_display_sync (gdk_drawable_get_display (window));
4763 save_region = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->queue_antiexpose (window, update_area);
4765 expose_region = gdk_region_copy (update_area);
4767 expose_region = update_area;
4771 window_rect.width = private->width;
4772 window_rect.height = private->height;
4774 window_region = gdk_region_rectangle (&window_rect);
4775 gdk_region_intersect (expose_region,
4777 gdk_region_destroy (window_region);
4780 /* No need to do any moves that will end up over the update area */
4781 if (private->outstanding_moves)
4783 GdkWindowRegionMove *move;
4787 remove = gdk_region_copy (update_area);
4788 for (l = g_list_last (private->outstanding_moves); l != NULL; l = prev)
4792 /* Don't need this area */
4793 gdk_region_subtract (move->dest_region, remove);
4795 /* However if any of the destination we do need has a source
4796 in the updated region we do need that as a destination for
4797 the earlier moves */
4798 gdk_region_offset (move->dest_region, -move->dx, -move->dy);
4799 gdk_region_subtract (remove, move->dest_region);
4801 if (gdk_region_empty (move->dest_region))
4803 gdk_window_region_move_free (move);
4804 private->outstanding_moves =
4805 g_list_delete_link (private->outstanding_moves, l);
4808 gdk_region_offset (move->dest_region, move->dx, move->dy);
4810 gdk_region_destroy (remove);
4813 gdk_region_get_clipbox (expose_region, &clip_box);
4814 end_implicit = gdk_window_begin_implicit_paint (window, &clip_box);
4815 if (end_implicit) /* rendering is not double buffered, do moves now */
4816 gdk_window_flush_outstanding_moves (window);
4817 _gdk_windowing_window_process_updates_recurse (window, expose_region);
4820 /* Do moves right before exposes are rendered */
4821 gdk_window_flush_outstanding_moves (window);
4822 gdk_window_end_implicit_paint (window);
4825 if (expose_region != update_area)
4826 gdk_region_destroy (expose_region);
4829 gdk_region_destroy (update_area);
4832 if (private->outstanding_moves)
4834 /* Flush any outstanding moves, may happen if we moved a window but got
4835 no actual invalid area */
4836 gdk_window_flush_outstanding_moves (window);
4841 flush_all_displays (void)
4843 GSList *displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
4846 for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
4847 gdk_display_flush (tmp_list->data);
4849 g_slist_free (displays);
4852 /* Currently it is not possible to override
4853 * gdk_window_process_all_updates in the same manner as
4854 * gdk_window_process_updates and gdk_window_invalidate_maybe_recurse
4855 * by implementing the GdkPaintable interface. If in the future a
4856 * backend would need this, the right solution would be to add a
4857 * method to GdkDisplay that can be optionally
4858 * NULL. gdk_window_process_all_updates can then walk the list of open
4859 * displays and call the mehod.
4863 * gdk_window_process_all_updates:
4865 * Calls gdk_window_process_updates() for all windows (see #GdkWindow)
4866 * in the application.
4870 gdk_window_process_all_updates (void)
4872 GSList *old_update_windows = update_windows;
4873 GSList *tmp_list = update_windows;
4874 static gboolean in_process_all_updates = FALSE;
4876 if (in_process_all_updates)
4879 in_process_all_updates = TRUE;
4882 g_source_remove (update_idle);
4884 update_windows = NULL;
4887 _gdk_windowing_before_process_all_updates ();
4889 g_slist_foreach (old_update_windows, (GFunc)g_object_ref, NULL);
4893 GdkWindowObject *private = (GdkWindowObject *)tmp_list->data;
4895 if (!GDK_WINDOW_DESTROYED (tmp_list->data))
4897 if (private->update_freeze_count ||
4898 gdk_window_is_toplevel_frozen (tmp_list->data))
4899 gdk_window_add_update_window ((GdkWindow *) private);
4901 gdk_window_process_updates_internal (tmp_list->data);
4904 g_object_unref (tmp_list->data);
4905 tmp_list = tmp_list->next;
4908 g_slist_free (old_update_windows);
4910 flush_all_displays ();
4912 _gdk_windowing_after_process_all_updates ();
4914 in_process_all_updates = FALSE;
4918 * gdk_window_process_updates:
4919 * @window: a #GdkWindow
4920 * @update_children: whether to also process updates for child windows
4922 * Sends one or more expose events to @window. The areas in each
4923 * expose event will cover the entire update area for the window (see
4924 * gdk_window_invalidate_region() for details). Normally GDK calls
4925 * gdk_window_process_all_updates() on your behalf, so there's no
4926 * need to call this function unless you want to force expose events
4927 * to be delivered immediately and synchronously (vs. the usual
4928 * case, where GDK delivers them in an idle handler). Occasionally
4929 * this is useful to produce nicer scrolling behavior, for example.
4933 gdk_window_process_updates (GdkWindow *window,
4934 gboolean update_children)
4936 GdkWindowObject *private = (GdkWindowObject *)window;
4937 GdkWindowObject *impl_window;
4939 g_return_if_fail (GDK_IS_WINDOW (window));
4941 impl_window = gdk_window_get_impl_window (private);
4942 if ((impl_window->update_area ||
4943 impl_window->outstanding_moves) &&
4944 !impl_window->update_freeze_count &&
4945 !gdk_window_is_toplevel_frozen (window))
4947 gdk_window_process_updates_internal ((GdkWindow *)impl_window);
4948 gdk_window_remove_update_window ((GdkWindow *)impl_window);
4951 if (update_children)
4953 /* process updates in reverse stacking order so composition or
4954 * painting over achieves the desired effect for offscreen windows
4957 for (node = g_list_last (private->children); node; node = node->prev)
4958 gdk_window_process_updates (node->data, TRUE);
4963 * gdk_window_invalidate_rect:
4964 * @window: a #GdkWindow
4965 * @rect: rectangle to invalidate or %NULL to invalidate the whole
4967 * @invalidate_children: whether to also invalidate child windows
4969 * A convenience wrapper around gdk_window_invalidate_region() which
4970 * invalidates a rectangular region. See
4971 * gdk_window_invalidate_region() for details.
4974 gdk_window_invalidate_rect (GdkWindow *window,
4975 const GdkRectangle *rect,
4976 gboolean invalidate_children)
4978 GdkRectangle window_rect;
4980 GdkWindowObject *private = (GdkWindowObject *)window;
4982 g_return_if_fail (GDK_IS_WINDOW (window));
4984 if (GDK_WINDOW_DESTROYED (window))
4987 if (private->input_only || !private->viewable)
4994 gdk_drawable_get_size (GDK_DRAWABLE (window),
4996 &window_rect.height);
4997 rect = &window_rect;
5000 region = gdk_region_rectangle (rect);
5001 gdk_window_invalidate_region (window, region, invalidate_children);
5002 gdk_region_destroy (region);
5006 draw_ugly_color (GdkWindow *window,
5007 const GdkRegion *region)
5009 /* Draw ugly color all over the newly-invalid region */
5010 GdkColor ugly_color = { 0, 50000, 10000, 10000 };
5012 GdkRectangle clipbox;
5014 ugly_gc = gdk_gc_new (window);
5015 gdk_gc_set_rgb_fg_color (ugly_gc, &ugly_color);
5016 gdk_gc_set_clip_region (ugly_gc, region);
5018 gdk_region_get_clipbox (region, &clipbox);
5020 gdk_draw_rectangle (window,
5023 clipbox.x, clipbox.y,
5024 clipbox.width, clipbox.height);
5026 g_object_unref (ugly_gc);
5030 * gdk_window_invalidate_maybe_recurse:
5031 * @window: a #GdkWindow
5032 * @region: a #GdkRegion
5033 * @child_func: function to use to decide if to recurse to a child,
5034 * %NULL means never recurse.
5035 * @user_data: data passed to @child_func
5037 * Adds @region to the update area for @window. The update area is the
5038 * region that needs to be redrawn, or "dirty region." The call
5039 * gdk_window_process_updates() sends one or more expose events to the
5040 * window, which together cover the entire update area. An
5041 * application would normally redraw the contents of @window in
5042 * response to those expose events.
5044 * GDK will call gdk_window_process_all_updates() on your behalf
5045 * whenever your program returns to the main loop and becomes idle, so
5046 * normally there's no need to do that manually, you just need to
5047 * invalidate regions that you know should be redrawn.
5049 * The @child_func parameter controls whether the region of
5050 * each child window that intersects @region will also be invalidated.
5051 * Only children for which @child_func returns TRUE will have the area
5055 gdk_window_invalidate_maybe_recurse (GdkWindow *window,
5056 const GdkRegion *region,
5057 gboolean (*child_func) (GdkWindow *,
5061 GdkWindowObject *private = (GdkWindowObject *)window;
5062 GdkWindowObject *impl_window;
5063 GdkRegion *visible_region;
5066 g_return_if_fail (GDK_IS_WINDOW (window));
5068 if (GDK_WINDOW_DESTROYED (window))
5071 if (private->input_only ||
5072 !private->viewable ||
5073 gdk_region_empty (region))
5076 visible_region = gdk_drawable_get_visible_region (window);
5077 gdk_region_intersect (visible_region, region);
5079 tmp_list = private->children;
5082 GdkWindowObject *child = tmp_list->data;
5084 if (!child->input_only)
5086 GdkRegion *child_region;
5087 GdkRectangle child_rect;
5089 child_rect.x = child->x;
5090 child_rect.y = child->y;
5091 child_rect.width = child->width;
5092 child_rect.height = child->height;
5093 child_region = gdk_region_rectangle (&child_rect);
5095 /* remove child area from the invalid area of the parent */
5096 if (GDK_WINDOW_IS_MAPPED (child) && !child->shaped &&
5097 !child->composited &&
5098 !gdk_window_is_offscreen (child))
5099 gdk_region_subtract (visible_region, child_region);
5101 if (child_func && (*child_func) ((GdkWindow *)child, user_data))
5103 GdkRegion *tmp = gdk_region_copy (region);
5105 gdk_region_offset (tmp, - child_rect.x, - child_rect.y);
5106 gdk_region_offset (child_region, - child_rect.x, - child_rect.y);
5107 gdk_region_intersect (child_region, tmp);
5109 gdk_window_invalidate_maybe_recurse ((GdkWindow *)child,
5110 child_region, child_func, user_data);
5112 gdk_region_destroy (tmp);
5115 gdk_region_destroy (child_region);
5118 tmp_list = tmp_list->next;
5121 impl_window = gdk_window_get_impl_window (private);
5123 if (!gdk_region_empty (visible_region) ||
5124 /* Even if we're not exposing anything, make sure we process
5125 idles for windows with outstanding moves */
5126 (impl_window->outstanding_moves != NULL &&
5127 impl_window->update_area == NULL))
5130 draw_ugly_color (window, region);
5132 /* Convert to impl coords */
5133 gdk_region_offset (visible_region, private->abs_x, private->abs_y);
5134 if (impl_window->update_area)
5136 gdk_region_union (impl_window->update_area, visible_region);
5140 gdk_window_add_update_window ((GdkWindow *)impl_window);
5141 impl_window->update_area = gdk_region_copy (visible_region);
5143 gdk_window_schedule_update ((GdkWindow *)impl_window);
5147 gdk_region_destroy (visible_region);
5151 true_predicate (GdkWindow *window,
5158 * gdk_window_invalidate_region:
5159 * @window: a #GdkWindow
5160 * @region: a #GdkRegion
5161 * @invalidate_children: %TRUE to also invalidate child windows
5163 * Adds @region to the update area for @window. The update area is the
5164 * region that needs to be redrawn, or "dirty region." The call
5165 * gdk_window_process_updates() sends one or more expose events to the
5166 * window, which together cover the entire update area. An
5167 * application would normally redraw the contents of @window in
5168 * response to those expose events.
5170 * GDK will call gdk_window_process_all_updates() on your behalf
5171 * whenever your program returns to the main loop and becomes idle, so
5172 * normally there's no need to do that manually, you just need to
5173 * invalidate regions that you know should be redrawn.
5175 * The @invalidate_children parameter controls whether the region of
5176 * each child window that intersects @region will also be invalidated.
5177 * If %FALSE, then the update area for child windows will remain
5178 * unaffected. See gdk_window_invalidate_maybe_recurse if you need
5179 * fine grained control over which children are invalidated.
5182 gdk_window_invalidate_region (GdkWindow *window,
5183 const GdkRegion *region,
5184 gboolean invalidate_children)
5186 gdk_window_invalidate_maybe_recurse (window, region,
5187 invalidate_children ?
5188 true_predicate : (gboolean (*) (GdkWindow *, gpointer))NULL,
5193 * _gdk_window_invalidate_for_expose:
5194 * @window: a #GdkWindow
5195 * @region: a #GdkRegion
5197 * Adds @region to the update area for @window. The update area is the
5198 * region that needs to be redrawn, or "dirty region." The call
5199 * gdk_window_process_updates() sends one or more expose events to the
5200 * window, which together cover the entire update area. An
5201 * application would normally redraw the contents of @window in
5202 * response to those expose events.
5204 * GDK will call gdk_window_process_all_updates() on your behalf
5205 * whenever your program returns to the main loop and becomes idle, so
5206 * normally there's no need to do that manually, you just need to
5207 * invalidate regions that you know should be redrawn.
5209 * This version of invalidation is used when you recieve expose events
5210 * from the native window system. It exposes the native window, plus
5211 * any non-native child windows (but not native child windows, as those would
5212 * have gotten their own expose events).
5215 _gdk_window_invalidate_for_expose (GdkWindow *window,
5216 const GdkRegion *region)
5218 gdk_window_invalidate_maybe_recurse (window, region,
5219 (gboolean (*) (GdkWindow *, gpointer))gdk_window_has_no_impl,
5225 * gdk_window_get_update_area:
5226 * @window: a #GdkWindow
5228 * Transfers ownership of the update area from @window to the caller
5229 * of the function. That is, after calling this function, @window will
5230 * no longer have an invalid/dirty region; the update area is removed
5231 * from @window and handed to you. If a window has no update area,
5232 * gdk_window_get_update_area() returns %NULL. You are responsible for
5233 * calling gdk_region_destroy() on the returned region if it's non-%NULL.
5235 * Return value: the update area for @window
5238 gdk_window_get_update_area (GdkWindow *window)
5240 GdkWindowObject *private = (GdkWindowObject *)window;
5241 GdkWindowObject *impl_window;
5242 GdkRegion *tmp_region;
5244 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
5246 impl_window = gdk_window_get_impl_window (private);
5248 if (impl_window->update_area)
5250 tmp_region = gdk_region_copy (private->clip_region_with_children);
5251 /* Convert to impl coords */
5252 gdk_region_offset (tmp_region, private->abs_x, private->abs_y);
5253 gdk_region_intersect (tmp_region, impl_window->update_area);
5255 if (gdk_region_empty (tmp_region))
5257 gdk_region_destroy (tmp_region);
5262 gdk_region_subtract (impl_window->update_area, tmp_region);
5264 if (gdk_region_empty (impl_window->update_area) &&
5265 impl_window->outstanding_moves == NULL)
5267 gdk_region_destroy (impl_window->update_area);
5268 impl_window->update_area = NULL;
5270 gdk_window_remove_update_window ((GdkWindow *)impl_window);
5273 /* Convert from impl coords */
5274 gdk_region_offset (tmp_region, -private->abs_x, -private->abs_y);
5284 * _gdk_window_clear_update_area:
5285 * @window: a #GdkWindow.
5287 * Internal function to clear the update area for a window. This
5288 * is called when the window is hidden or destroyed.
5291 _gdk_window_clear_update_area (GdkWindow *window)
5293 GdkWindowObject *private = (GdkWindowObject *)window;
5295 g_return_if_fail (GDK_IS_WINDOW (window));
5297 if (private->update_area)
5299 gdk_window_remove_update_window (window);
5301 gdk_region_destroy (private->update_area);
5302 private->update_area = NULL;
5307 * gdk_window_freeze_updates:
5308 * @window: a #GdkWindow
5310 * Temporarily freezes a window such that it won't receive expose
5311 * events. The window will begin receiving expose events again when
5312 * gdk_window_thaw_updates() is called. If gdk_window_freeze_updates()
5313 * has been called more than once, gdk_window_thaw_updates() must be called
5314 * an equal number of times to begin processing exposes.
5317 gdk_window_freeze_updates (GdkWindow *window)
5319 GdkWindowObject *private = (GdkWindowObject *)window;
5320 GdkWindowObject *impl_window;
5322 g_return_if_fail (GDK_IS_WINDOW (window));
5324 impl_window = gdk_window_get_impl_window (private);
5325 impl_window->update_freeze_count++;
5329 * gdk_window_thaw_updates:
5330 * @window: a #GdkWindow
5332 * Thaws a window frozen with gdk_window_freeze_updates().
5335 gdk_window_thaw_updates (GdkWindow *window)
5337 GdkWindowObject *private = (GdkWindowObject *)window;
5338 GdkWindowObject *impl_window;
5340 g_return_if_fail (GDK_IS_WINDOW (window));
5342 impl_window = gdk_window_get_impl_window (private);
5344 g_return_if_fail (impl_window->update_freeze_count > 0);
5346 if (--impl_window->update_freeze_count == 0)
5347 gdk_window_schedule_update (GDK_WINDOW (impl_window));
5351 * gdk_window_freeze_toplevel_updates_libgtk_only:
5352 * @window: a #GdkWindow
5354 * Temporarily freezes a window and all its descendants such that it won't
5355 * receive expose events. The window will begin receiving expose events
5356 * again when gdk_window_thaw_toplevel_updates_libgtk_only() is called. If
5357 * gdk_window_freeze_toplevel_updates_libgtk_only()
5358 * has been called more than once,
5359 * gdk_window_thaw_toplevel_updates_libgtk_only() must be called
5360 * an equal number of times to begin processing exposes.
5362 * This function is not part of the GDK public API and is only
5366 gdk_window_freeze_toplevel_updates_libgtk_only (GdkWindow *window)
5368 GdkWindowObject *private = (GdkWindowObject *)window;
5370 g_return_if_fail (GDK_IS_WINDOW (window));
5371 g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
5373 private->update_and_descendants_freeze_count++;
5377 * gdk_window_thaw_toplevel_updates_libgtk_only:
5378 * @window: a #GdkWindow
5380 * Thaws a window frozen with
5381 * gdk_window_freeze_toplevel_updates_libgtk_only().
5383 * This function is not part of the GDK public API and is only
5387 gdk_window_thaw_toplevel_updates_libgtk_only (GdkWindow *window)
5389 GdkWindowObject *private = (GdkWindowObject *)window;
5391 g_return_if_fail (GDK_IS_WINDOW (window));
5392 g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
5393 g_return_if_fail (private->update_and_descendants_freeze_count > 0);
5395 private->update_and_descendants_freeze_count--;
5397 gdk_window_schedule_update (window);
5401 * gdk_window_set_debug_updates:
5402 * @setting: %TRUE to turn on update debugging
5404 * With update debugging enabled, calls to
5405 * gdk_window_invalidate_region() clear the invalidated region of the
5406 * screen to a noticeable color, and GDK pauses for a short time
5407 * before sending exposes to windows during
5408 * gdk_window_process_updates(). The net effect is that you can see
5409 * the invalid region for each window and watch redraws as they
5410 * occur. This allows you to diagnose inefficiencies in your application.
5412 * In essence, because the GDK rendering model prevents all flicker,
5413 * if you are redrawing the same region 400 times you may never
5414 * notice, aside from noticing a speed problem. Enabling update
5415 * debugging causes GTK to flicker slowly and noticeably, so you can
5416 * see exactly what's being redrawn when, in what order.
5418 * The --gtk-debug=updates command line option passed to GTK+ programs
5419 * enables this debug option at application startup time. That's
5420 * usually more useful than calling gdk_window_set_debug_updates()
5421 * yourself, though you might want to use this function to enable
5422 * updates sometime after application startup time.
5426 gdk_window_set_debug_updates (gboolean setting)
5428 debug_updates = setting;
5432 * gdk_window_constrain_size:
5433 * @geometry: a #GdkGeometry structure
5434 * @flags: a mask indicating what portions of @geometry are set
5435 * @width: desired width of window
5436 * @height: desired height of the window
5437 * @new_width: location to store resulting width
5438 * @new_height: location to store resulting height
5440 * Constrains a desired width and height according to a
5441 * set of geometry hints (such as minimum and maximum size).
5444 gdk_window_constrain_size (GdkGeometry *geometry,
5451 /* This routine is partially borrowed from fvwm.
5453 * Copyright 1993, Robert Nation
5454 * You may use this code for any purpose, as long as the original
5455 * copyright remains in the source code and all documentation
5457 * which in turn borrows parts of the algorithm from uwm
5460 gint min_height = 0;
5461 gint base_width = 0;
5462 gint base_height = 0;
5465 gint max_width = G_MAXINT;
5466 gint max_height = G_MAXINT;
5468 #define FLOOR(value, base) ( ((gint) ((value) / (base))) * (base) )
5470 if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
5472 base_width = geometry->base_width;
5473 base_height = geometry->base_height;
5474 min_width = geometry->min_width;
5475 min_height = geometry->min_height;
5477 else if (flags & GDK_HINT_BASE_SIZE)
5479 base_width = geometry->base_width;
5480 base_height = geometry->base_height;
5481 min_width = geometry->base_width;
5482 min_height = geometry->base_height;
5484 else if (flags & GDK_HINT_MIN_SIZE)
5486 base_width = geometry->min_width;
5487 base_height = geometry->min_height;
5488 min_width = geometry->min_width;
5489 min_height = geometry->min_height;
5492 if (flags & GDK_HINT_MAX_SIZE)
5494 max_width = geometry->max_width ;
5495 max_height = geometry->max_height;
5498 if (flags & GDK_HINT_RESIZE_INC)
5500 xinc = MAX (xinc, geometry->width_inc);
5501 yinc = MAX (yinc, geometry->height_inc);
5504 /* clamp width and height to min and max values
5506 width = CLAMP (width, min_width, max_width);
5507 height = CLAMP (height, min_height, max_height);
5509 /* shrink to base + N * inc
5511 width = base_width + FLOOR (width - base_width, xinc);
5512 height = base_height + FLOOR (height - base_height, yinc);
5514 /* constrain aspect ratio, according to:
5517 * min_aspect <= -------- <= max_aspect
5521 if (flags & GDK_HINT_ASPECT &&
5522 geometry->min_aspect > 0 &&
5523 geometry->max_aspect > 0)
5527 if (geometry->min_aspect * height > width)
5529 delta = FLOOR (height - width / geometry->min_aspect, yinc);
5530 if (height - delta >= min_height)
5534 delta = FLOOR (height * geometry->min_aspect - width, xinc);
5535 if (width + delta <= max_width)
5540 if (geometry->max_aspect * height < width)
5542 delta = FLOOR (width - height * geometry->max_aspect, xinc);
5543 if (width - delta >= min_width)
5547 delta = FLOOR (width / geometry->max_aspect - height, yinc);
5548 if (height + delta <= max_height)
5557 *new_height = height;
5561 * gdk_window_get_pointer:
5562 * @window: a #GdkWindow
5563 * @x: return location for X coordinate of pointer or %NULL to not
5564 * return the X coordinate
5565 * @y: return location for Y coordinate of pointer or %NULL to not
5566 * return the Y coordinate
5567 * @mask: return location for modifier mask or %NULL to not return the
5570 * Obtains the current pointer position and modifier state.
5571 * The position is given in coordinates relative to the upper left
5572 * corner of @window.
5574 * Return value: the window containing the pointer (as with
5575 * gdk_window_at_pointer()), or %NULL if the window containing the
5576 * pointer isn't known to GDK
5579 gdk_window_get_pointer (GdkWindow *window,
5582 GdkModifierType *mask)
5584 GdkDisplay *display;
5586 GdkModifierType tmp_mask;
5589 g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
5593 display = gdk_drawable_get_display (window);
5597 GdkScreen *screen = gdk_screen_get_default ();
5599 display = gdk_screen_get_display (screen);
5600 window = gdk_screen_get_root_window (screen);
5602 GDK_NOTE (MULTIHEAD,
5603 g_message ("Passing NULL for window to gdk_window_get_pointer()\n"
5604 "is not multihead safe"));
5607 child = display->pointer_hooks->window_get_pointer (display, window, &tmp_x, &tmp_y, &tmp_mask);
5616 _gdk_display_enable_motion_hints (display);
5622 * gdk_window_at_pointer:
5623 * @win_x: return location for origin of the window under the pointer
5624 * @win_y: return location for origin of the window under the pointer
5626 * Obtains the window underneath the mouse pointer, returning the
5627 * location of that window in @win_x, @win_y. Returns %NULL if the
5628 * window under the mouse pointer is not known to GDK (if the window
5629 * belongs to another application and a #GdkWindow hasn't been created
5630 * for it with gdk_window_foreign_new())
5632 * NOTE: For multihead-aware widgets or applications use
5633 * gdk_display_get_window_at_pointer() instead.
5635 * Return value: window under the mouse pointer
5638 gdk_window_at_pointer (gint *win_x,
5641 return gdk_display_get_window_at_pointer (gdk_display_get_default (), win_x, win_y);
5645 * gdk_get_default_root_window:
5647 * Obtains the root window (parent all other windows are inside)
5648 * for the default display and screen.
5650 * Return value: the default root window
5653 gdk_get_default_root_window (void)
5655 return gdk_screen_get_root_window (gdk_screen_get_default ());
5659 * gdk_window_foreign_new:
5660 * @anid: a native window handle.
5662 * Wraps a native window for the default display in a #GdkWindow.
5663 * This may fail if the window has been destroyed.
5665 * For example in the X backend, a native window handle is an Xlib
5668 * Return value: the newly-created #GdkWindow wrapper for the
5669 * native window or %NULL if the window has been destroyed.
5672 gdk_window_foreign_new (GdkNativeWindow anid)
5674 return gdk_window_foreign_new_for_display (gdk_display_get_default (), anid);
5678 get_all_native_children (GdkWindowObject *private,
5681 GdkWindowObject *child;
5684 for (l = private->children; l != NULL; l = l->next)
5688 if (gdk_window_has_impl (child))
5689 *native = g_list_prepend (*native, child);
5691 get_all_native_children (child, native);
5697 gdk_window_raise_internal (GdkWindow *window)
5699 GdkWindowObject *private = (GdkWindowObject *)window;
5700 GdkWindowObject *parent = private->parent;
5701 GdkWindowObject *above;
5702 GList *native_children;
5707 parent->children = g_list_remove (parent->children, window);
5708 parent->children = g_list_prepend (parent->children, window);
5711 /* Just do native raise for toplevels */
5712 if (private->parent == NULL ||
5713 private->parent->window_type == GDK_WINDOW_ROOT)
5715 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
5717 else if (gdk_window_has_impl (private))
5719 above = find_native_sibling_above (parent, private);
5722 listhead.data = window;
5723 listhead.next = NULL;
5724 listhead.prev = NULL;
5725 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
5729 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
5733 native_children = NULL;
5734 get_all_native_children (private, &native_children);
5735 if (native_children != NULL)
5737 above = find_native_sibling_above (parent, private);
5740 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
5744 /* Right order, since native_children is bottom-topmost first */
5745 for (l = native_children; l != NULL; l = l->next)
5746 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (l->data);
5749 g_list_free (native_children);
5755 /* Showing a non-native parent may cause children to become visible,
5756 we need to handle this by manually showing them then. To simplify
5757 things we hide them all when they are not visible. */
5759 show_all_visible_impls (GdkWindowObject *private, gboolean already_mapped)
5761 GdkWindowObject *child;
5764 for (l = private->children; l != NULL; l = l->next)
5768 /* For foreign windows, only show if if was
5769 explicitly hidden, otherwise we might cause
5770 suprising things to happen to the other client. */
5771 if (GDK_WINDOW_IS_MAPPED (child) &&
5772 child->window_type != GDK_WINDOW_FOREIGN)
5773 show_all_visible_impls (child, FALSE);
5776 if (gdk_window_has_impl (private))
5777 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show ((GdkWindow *)private, already_mapped);
5781 set_viewable (GdkWindowObject *w,
5784 GdkWindowObject *child;
5789 for (l = w->children; l != NULL; l = l->next)
5793 if (GDK_WINDOW_IS_MAPPED (child) &&
5794 child->window_type != GDK_WINDOW_FOREIGN)
5795 set_viewable (child, val);
5800 _gdk_window_update_viewable (GdkWindow *window)
5802 GdkWindowObject *priv = (GdkWindowObject *)window;
5805 if (priv->window_type == GDK_WINDOW_FOREIGN ||
5806 priv->window_type == GDK_WINDOW_ROOT)
5808 else if (priv->parent == NULL ||
5809 priv->parent->window_type == GDK_WINDOW_ROOT ||
5810 priv->parent->viewable)
5811 viewable = GDK_WINDOW_IS_MAPPED (priv);
5815 if (priv->viewable != viewable)
5816 set_viewable (priv, viewable);
5820 gdk_window_show_internal (GdkWindow *window, gboolean raise)
5822 GdkWindowObject *private;
5823 gboolean was_mapped;
5825 g_return_if_fail (GDK_IS_WINDOW (window));
5827 private = (GdkWindowObject *) window;
5828 if (private->destroyed)
5831 was_mapped = GDK_WINDOW_IS_MAPPED (window);
5834 /* Keep children in (reverse) stacking order */
5835 gdk_window_raise_internal (window);
5837 if (gdk_window_has_impl (private))
5840 gdk_synthesize_window_state (window,
5841 GDK_WINDOW_STATE_WITHDRAWN,
5849 _gdk_window_update_viewable (window);
5851 if (gdk_window_is_viewable (window))
5852 show_all_visible_impls (private, was_mapped);
5854 if (!was_mapped && !gdk_window_has_impl (private))
5856 if (private->event_mask & GDK_STRUCTURE_MASK)
5857 _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
5859 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
5860 _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
5863 if (!was_mapped || raise)
5865 recompute_visible_regions (private, TRUE, FALSE);
5867 /* If any decendants became visible we need to send visibility notify */
5868 gdk_window_update_visibility_recursively (private, NULL);
5870 if (gdk_window_is_viewable (window))
5872 _gdk_synthesize_crossing_events_for_geometry_change (window);
5873 gdk_window_invalidate_rect (window, NULL, TRUE);
5879 * gdk_window_show_unraised:
5880 * @window: a #GdkWindow
5882 * Shows a #GdkWindow onscreen, but does not modify its stacking
5883 * order. In contrast, gdk_window_show() will raise the window
5884 * to the top of the window stack.
5886 * On the X11 platform, in Xlib terms, this function calls
5887 * XMapWindow() (it also updates some internal GDK state, which means
5888 * that you can't really use XMapWindow() directly on a GDK window).
5891 gdk_window_show_unraised (GdkWindow *window)
5893 gdk_window_show_internal (window, FALSE);
5898 * @window: a #GdkWindow
5900 * Raises @window to the top of the Z-order (stacking order), so that
5901 * other windows with the same parent window appear below @window.
5902 * This is true whether or not the windows are visible.
5904 * If @window is a toplevel, the window manager may choose to deny the
5905 * request to move the window in the Z-order, gdk_window_raise() only
5906 * requests the restack, does not guarantee it.
5909 gdk_window_raise (GdkWindow *window)
5911 GdkWindowObject *private;
5913 g_return_if_fail (GDK_IS_WINDOW (window));
5915 private = (GdkWindowObject *) window;
5916 if (private->destroyed)
5919 /* Keep children in (reverse) stacking order */
5920 gdk_window_raise_internal (window);
5922 recompute_visible_regions (private, TRUE, FALSE);
5924 gdk_window_invalidate_rect (window, NULL, TRUE);
5928 gdk_window_lower_internal (GdkWindow *window)
5930 GdkWindowObject *private = (GdkWindowObject *)window;
5931 GdkWindowObject *parent = private->parent;
5932 GdkWindowObject *above;
5933 GList *native_children;
5938 parent->children = g_list_remove (parent->children, window);
5939 parent->children = g_list_append (parent->children, window);
5942 /* Just do native lower for toplevels */
5943 if (private->parent == NULL ||
5944 private->parent->window_type == GDK_WINDOW_ROOT)
5946 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->lower (window);
5948 else if (gdk_window_has_impl (private))
5950 above = find_native_sibling_above (parent, private);
5953 listhead.data = window;
5954 listhead.next = NULL;
5955 listhead.prev = NULL;
5956 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
5960 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
5964 native_children = NULL;
5965 get_all_native_children (private, &native_children);
5966 if (native_children != NULL)
5968 above = find_native_sibling_above (parent, private);
5971 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
5975 /* Right order, since native_children is bottom-topmost first */
5976 for (l = native_children; l != NULL; l = l->next)
5977 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (l->data);
5980 g_list_free (native_children);
5987 gdk_window_invalidate_in_parent (GdkWindowObject *private)
5989 GdkRectangle r, child;
5991 if (private->parent == NULL ||
5992 private->parent->window_type == GDK_WINDOW_ROOT)
5995 /* get the visible rectangle of the parent */
5997 r.width = private->parent->width;
5998 r.height = private->parent->height;
6000 child.x = private->x;
6001 child.y = private->y;
6002 child.width = private->width;
6003 child.height = private->height;
6004 gdk_rectangle_intersect (&r, &child, &r);
6006 gdk_window_invalidate_rect (GDK_WINDOW (private->parent), &r, TRUE);
6012 * @window: a #GdkWindow
6014 * Lowers @window to the bottom of the Z-order (stacking order), so that
6015 * other windows with the same parent window appear above @window.
6016 * This is true whether or not the other windows are visible.
6018 * If @window is a toplevel, the window manager may choose to deny the
6019 * request to move the window in the Z-order, gdk_window_lower() only
6020 * requests the restack, does not guarantee it.
6022 * Note that gdk_window_show() raises the window again, so don't call this
6023 * function before gdk_window_show(). (Try gdk_window_show_unraised().)
6026 gdk_window_lower (GdkWindow *window)
6028 GdkWindowObject *private;
6030 g_return_if_fail (GDK_IS_WINDOW (window));
6032 private = (GdkWindowObject *) window;
6033 if (private->destroyed)
6036 /* Keep children in (reverse) stacking order */
6037 gdk_window_lower_internal (window);
6039 recompute_visible_regions (private, TRUE, FALSE);
6041 _gdk_synthesize_crossing_events_for_geometry_change (window);
6042 gdk_window_invalidate_in_parent (private);
6047 * @window: a #GdkWindow
6049 * Like gdk_window_show_unraised(), but also raises the window to the
6050 * top of the window stack (moves the window to the front of the
6053 * This function maps a window so it's visible onscreen. Its opposite
6054 * is gdk_window_hide().
6056 * When implementing a #GtkWidget, you should call this function on the widget's
6057 * #GdkWindow as part of the "map" method.
6060 gdk_window_show (GdkWindow *window)
6062 gdk_window_show_internal (window, TRUE);
6065 /* Hiding a non-native parent may cause parents to become non-visible,
6066 even if their parent native window is visible. We need to handle this
6067 by manually hiding them then. To simplify things we hide them all
6068 when they are not visible. */
6070 hide_all_visible_impls (GdkWindowObject *private)
6072 GdkWindowObject *child;
6075 for (l = private->children; l != NULL; l = l->next)
6079 /* For foreign windows, only hide if if was
6080 explicitly hidden, otherwise we might cause
6081 suprising things to happen to the other client. */
6082 if (GDK_WINDOW_IS_MAPPED (child) &&
6083 child->window_type != GDK_WINDOW_FOREIGN)
6084 hide_all_visible_impls (child);
6087 if (gdk_window_has_impl (private))
6088 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->hide ((GdkWindow *)private);
6094 * @window: a #GdkWindow
6096 * For toplevel windows, withdraws them, so they will no longer be
6097 * known to the window manager; for all windows, unmaps them, so
6098 * they won't be displayed. Normally done automatically as
6099 * part of gtk_widget_hide().
6102 gdk_window_hide (GdkWindow *window)
6104 GdkWindowObject *private;
6105 gboolean was_mapped, was_viewable;
6107 g_return_if_fail (GDK_IS_WINDOW (window));
6109 private = (GdkWindowObject *) window;
6110 if (private->destroyed)
6113 was_mapped = GDK_WINDOW_IS_MAPPED (private);
6114 was_viewable = gdk_window_is_viewable (window);
6116 if (gdk_window_has_impl (private))
6119 if (GDK_WINDOW_IS_MAPPED (window))
6120 gdk_synthesize_window_state (window,
6122 GDK_WINDOW_STATE_WITHDRAWN);
6124 else if (was_mapped)
6126 GdkDisplay *display;
6128 /* May need to break grabs on children */
6129 display = gdk_drawable_get_display (window);
6131 if (_gdk_display_end_pointer_grab (display,
6132 _gdk_windowing_window_get_next_serial (display),
6135 gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
6137 if (display->keyboard_grab.window != NULL)
6139 if (is_parent_of (window, display->keyboard_grab.window))
6141 /* Call this ourselves, even though gdk_display_keyboard_ungrab
6142 does so too, since we want to pass implicit == TRUE so the
6143 broken grab event is generated */
6144 _gdk_display_unset_has_keyboard_grab (display,
6146 gdk_display_keyboard_ungrab (display, GDK_CURRENT_TIME);
6150 private->state = GDK_WINDOW_STATE_WITHDRAWN;
6153 _gdk_window_update_viewable (window);
6156 hide_all_visible_impls (private);
6158 recompute_visible_regions (private, TRUE, FALSE);
6160 /* all decendants became non-visible, we need to send visibility notify */
6161 gdk_window_update_visibility_recursively (private, NULL);
6163 if (was_mapped && !gdk_window_has_impl (private))
6165 if (private->event_mask & GDK_STRUCTURE_MASK)
6166 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6168 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
6169 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6171 _gdk_synthesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
6174 /* Invalidate the rect */
6175 gdk_window_invalidate_in_parent (private);
6179 * gdk_window_withdraw:
6180 * @window: a toplevel #GdkWindow
6182 * Withdraws a window (unmaps it and asks the window manager to forget about it).
6183 * This function is not really useful as gdk_window_hide() automatically
6184 * withdraws toplevel windows before hiding them.
6187 gdk_window_withdraw (GdkWindow *window)
6189 GdkWindowObject *private;
6190 gboolean was_mapped;
6192 g_return_if_fail (GDK_IS_WINDOW (window));
6194 private = (GdkWindowObject *) window;
6195 if (private->destroyed)
6198 was_mapped = GDK_WINDOW_IS_MAPPED (private);
6200 if (gdk_window_has_impl (private))
6202 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->withdraw (window);
6206 if (private->event_mask & GDK_STRUCTURE_MASK)
6207 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6209 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
6210 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6212 _gdk_synthesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
6215 recompute_visible_regions (private, TRUE, FALSE);
6220 * gdk_window_set_events:
6221 * @window: a #GdkWindow
6222 * @event_mask: event mask for @window
6224 * The event mask for a window determines which events will be reported
6225 * for that window. For example, an event mask including #GDK_BUTTON_PRESS_MASK
6226 * means the window should report button press events. The event mask
6227 * is the bitwise OR of values from the #GdkEventMask enumeration.
6230 gdk_window_set_events (GdkWindow *window,
6231 GdkEventMask event_mask)
6233 GdkWindowObject *private;
6234 GdkDisplay *display;
6237 g_return_if_fail (GDK_IS_WINDOW (window));
6239 private = (GdkWindowObject *) window;
6240 if (private->destroyed)
6243 /* If motion hint is disabled, enable motion events again */
6244 display = gdk_drawable_get_display (window);
6245 if ((private->event_mask & GDK_POINTER_MOTION_HINT_MASK) &&
6246 !(event_mask & GDK_POINTER_MOTION_HINT_MASK))
6247 _gdk_display_enable_motion_hints (display);
6249 private->event_mask = event_mask;
6251 if (gdk_window_has_impl (private))
6252 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_events (window,
6253 get_native_event_mask (private));
6258 * gdk_window_get_events:
6259 * @window: a #GdkWindow
6261 * Gets the event mask for @window. See gdk_window_set_events().
6263 * Return value: event mask for @window
6266 gdk_window_get_events (GdkWindow *window)
6268 GdkWindowObject *private;
6270 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
6272 private = (GdkWindowObject *) window;
6273 if (private->destroyed)
6276 return private->event_mask;
6280 gdk_window_move_resize_toplevel (GdkWindow *window,
6287 GdkWindowObject *private;
6288 GdkRegion *old_region, *new_region;
6289 GdkWindowObject *impl_window;
6291 int old_x, old_y, old_abs_x, old_abs_y;
6295 private = (GdkWindowObject *) window;
6300 impl_window = gdk_window_get_impl_window (private);
6305 is_resize = (width != -1) || (height != -1);
6307 if (gdk_window_is_viewable (window) &&
6308 !private->input_only)
6311 old_region = gdk_region_copy (private->clip_region);
6314 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, with_move, x, y, width, height);
6316 dx = private->x - old_x;
6317 dy = private->y - old_y;
6319 old_abs_x = private->abs_x;
6320 old_abs_y = private->abs_y;
6322 /* Avoid recomputing for pure toplevel moves, for performance reasons */
6324 recompute_visible_regions (private, TRUE, FALSE);
6328 new_region = gdk_region_copy (private->clip_region);
6330 /* This is the newly exposed area (due to any resize),
6331 * X will expose it, but lets do that without the
6334 gdk_region_subtract (new_region, old_region);
6335 gdk_window_invalidate_region (window, new_region, TRUE);
6337 gdk_region_destroy (old_region);
6338 gdk_region_destroy (new_region);
6341 _gdk_synthesize_crossing_events_for_geometry_change (window);
6346 move_native_children (GdkWindowObject *private)
6349 GdkWindowObject *child;
6351 for (l = private->children; l; l = l->next)
6355 if (child->impl != private->impl)
6356 GDK_WINDOW_IMPL_GET_IFACE (child->impl)->move_resize ((GdkWindow *)child, TRUE, child->x, child->y, child->width, child->height);
6358 move_native_children (child);
6363 collect_native_child_region_helper (GdkWindowObject *window,
6369 GdkWindowObject *child;
6373 for (l = window->children; l != NULL; l = l->next)
6377 if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only)
6380 if (child->impl != impl)
6382 tmp = gdk_region_copy (child->clip_region);
6383 gdk_region_offset (tmp,
6384 x_offset + child->x,
6385 y_offset + child->y);
6386 if (*region == NULL)
6390 gdk_region_union (*region, tmp);
6391 gdk_region_destroy (tmp);
6395 collect_native_child_region_helper (child, impl, region,
6396 x_offset + child->x,
6397 y_offset + child->y);
6404 collect_native_child_region (GdkWindowObject *window,
6405 gboolean include_this)
6409 if (include_this && gdk_window_has_impl (window) && window->viewable)
6410 return gdk_region_copy (window->clip_region);
6414 collect_native_child_region_helper (window, window->impl, ®ion, 0, 0);
6421 gdk_window_move_resize_internal (GdkWindow *window,
6428 GdkWindowObject *private;
6429 GdkRegion *old_region, *new_region, *copy_area;
6430 GdkRegion *old_native_child_region, *new_native_child_region;
6431 GdkWindowObject *impl_window;
6433 int old_x, old_y, old_abs_x, old_abs_y;
6436 g_return_if_fail (GDK_IS_WINDOW (window));
6438 private = (GdkWindowObject *) window;
6439 if (private->destroyed)
6442 if (private->parent == NULL ||
6443 private->parent->window_type == GDK_WINDOW_ROOT)
6445 gdk_window_move_resize_toplevel (window, with_move, x, y, width, height);
6449 /* Handle child windows */
6454 impl_window = gdk_window_get_impl_window (private);
6459 old_native_child_region = NULL;
6460 if (gdk_window_is_viewable (window) &&
6461 !private->input_only)
6465 old_region = gdk_region_copy (private->clip_region);
6466 /* Adjust region to parent window coords */
6467 gdk_region_offset (old_region, private->x, private->y);
6469 old_native_child_region = collect_native_child_region (private, TRUE);
6470 if (old_native_child_region)
6472 /* Adjust region to parent window coords */
6473 gdk_region_offset (old_native_child_region, private->x, private->y);
6475 /* Any native window move will immediately copy stuff to the destination, which may overwrite a
6476 * source or destination for a delayed GdkWindowRegionMove. So, we need
6477 * to flush those here for the parent window and all overlapped subwindows
6478 * of it. And we need to do this before setting the new clips as those will be
6481 gdk_window_flush_recursive (private->parent);
6485 /* Set the new position and size */
6491 if (!(width < 0 && height < 0))
6495 private->width = width;
6498 private->height = height;
6501 dx = private->x - old_x;
6502 dy = private->y - old_y;
6504 old_abs_x = private->abs_x;
6505 old_abs_y = private->abs_y;
6507 recompute_visible_regions (private, TRUE, FALSE);
6509 new_native_child_region = NULL;
6510 if (old_native_child_region)
6512 new_native_child_region = collect_native_child_region (private, TRUE);
6513 /* Adjust region to parent window coords */
6514 gdk_region_offset (new_native_child_region, private->x, private->y);
6517 if (gdk_window_has_impl (private))
6519 /* Do the actual move after recomputing things, as this will have set the shape to
6520 the now correct one, thus avoiding copying regions that should not be copied. */
6521 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, TRUE, private->x, private->y, private->width, private->height);
6523 else if (old_abs_x != private->abs_x ||
6524 old_abs_y != private->abs_y)
6525 move_native_children (private);
6529 new_region = gdk_region_copy (private->clip_region);
6530 /* Adjust region to parent window coords */
6531 gdk_region_offset (new_region, private->x, private->y);
6534 * Part of the data at the new location can be copied from the
6535 * old location, this area is the intersection of the old region
6536 * moved as the copy will move it and then intersected with
6540 * Everything in the old and new regions that is not copied must be
6541 * invalidated (including children) as this is newly exposed
6543 copy_area = gdk_region_copy (new_region);
6545 gdk_region_union (new_region, old_region);
6547 if (old_native_child_region)
6549 /* Don't copy from inside native children, as this is copied by
6550 * the native window move.
6552 gdk_region_subtract (old_region, old_native_child_region);
6554 gdk_region_offset (old_region, dx, dy);
6556 gdk_region_intersect (copy_area, old_region);
6558 if (new_native_child_region)
6560 /* Don't copy any bits that would cause a read from the moved
6561 native windows, as we can't read that data */
6562 gdk_region_offset (new_native_child_region, dx, dy);
6563 gdk_region_subtract (copy_area, new_native_child_region);
6566 gdk_region_subtract (new_region, copy_area);
6568 /* Convert old region to impl coords */
6569 gdk_region_offset (old_region, -dx + private->abs_x - private->x, -dy + private->abs_y - private->y);
6571 /* convert from parent coords to impl */
6572 gdk_region_offset (copy_area, private->abs_x - private->x, private->abs_y - private->y);
6574 move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
6576 /* Invalidate affected part in the parent window
6577 * (no higher window should be affected)
6578 * We also invalidate any children in that area, which could include
6579 * this window if it still overlaps that area.
6581 gdk_window_invalidate_region (GDK_WINDOW (private->parent), new_region, TRUE);
6583 gdk_region_destroy (old_region);
6584 gdk_region_destroy (new_region);
6587 if (old_native_child_region)
6589 gdk_region_destroy (old_native_child_region);
6590 gdk_region_destroy (new_native_child_region);
6593 _gdk_synthesize_crossing_events_for_geometry_change (window);
6600 * @window: a #GdkWindow
6601 * @x: X coordinate relative to window's parent
6602 * @y: Y coordinate relative to window's parent
6604 * Repositions a window relative to its parent window.
6605 * For toplevel windows, window managers may ignore or modify the move;
6606 * you should probably use gtk_window_move() on a #GtkWindow widget
6607 * anyway, instead of using GDK functions. For child windows,
6608 * the move will reliably succeed.
6610 * If you're also planning to resize the window, use gdk_window_move_resize()
6611 * to both move and resize simultaneously, for a nicer visual effect.
6614 gdk_window_move (GdkWindow *window,
6618 gdk_window_move_resize_internal (window, TRUE, x, y, -1, -1);
6622 * gdk_window_resize:
6623 * @window: a #GdkWindow
6624 * @width: new width of the window
6625 * @height: new height of the window
6627 * Resizes @window; for toplevel windows, asks the window manager to resize
6628 * the window. The window manager may not allow the resize. When using GTK+,
6629 * use gtk_window_resize() instead of this low-level GDK function.
6631 * Windows may not be resized below 1x1.
6633 * If you're also planning to move the window, use gdk_window_move_resize()
6634 * to both move and resize simultaneously, for a nicer visual effect.
6637 gdk_window_resize (GdkWindow *window,
6641 gdk_window_move_resize_internal (window, FALSE, 0, 0, width, height);
6646 * gdk_window_move_resize:
6647 * @window: a #GdkWindow
6648 * @x: new X position relative to window's parent
6649 * @y: new Y position relative to window's parent
6651 * @height: new height
6653 * Equivalent to calling gdk_window_move() and gdk_window_resize(),
6654 * except that both operations are performed at once, avoiding strange
6655 * visual effects. (i.e. the user may be able to see the window first
6656 * move, then resize, if you don't use gdk_window_move_resize().)
6659 gdk_window_move_resize (GdkWindow *window,
6665 gdk_window_move_resize_internal (window, TRUE, x, y, width, height);
6670 * gdk_window_scroll:
6671 * @window: a #GdkWindow
6672 * @dx: Amount to scroll in the X direction
6673 * @dy: Amount to scroll in the Y direction
6675 * Scroll the contents of @window, both pixels and children, by the
6676 * given amount. @window itself does not move. Portions of the window
6677 * that the scroll operation brings in from offscreen areas are
6678 * invalidated. The invalidated region may be bigger than what would
6679 * strictly be necessary.
6681 * For X11, a minimum area will be invalidated if the window has no
6682 * subwindows, or if the edges of the window's parent do not extend
6683 * beyond the edges of the window. In other cases, a multi-step process
6684 * is used to scroll the window which may produce temporary visual
6685 * artifacts and unnecessary invalidations.
6688 gdk_window_scroll (GdkWindow *window,
6692 GdkWindowObject *private = (GdkWindowObject *) window;
6693 GdkWindowObject *impl_window;
6694 GdkRegion *copy_area, *noncopy_area;
6695 GdkRegion *old_native_child_region, *new_native_child_region;
6698 g_return_if_fail (GDK_IS_WINDOW (window));
6700 if (dx == 0 && dy == 0)
6703 if (private->destroyed)
6706 old_native_child_region = collect_native_child_region (private, FALSE);
6707 if (old_native_child_region)
6709 /* Any native window move will immediately copy stuff to the destination, which may overwrite a
6710 * source or destination for a delayed GdkWindowRegionMove. So, we need
6711 * to flush those here for the window and all overlapped subwindows
6712 * of it. And we need to do this before setting the new clips as those will be
6715 gdk_window_flush_recursive (private);
6719 /* First move all child windows, without causing invalidation */
6721 tmp_list = private->children;
6724 GdkWindow *child = GDK_WINDOW (tmp_list->data);
6725 GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
6727 /* Just update the positions, the bits will move with the copy */
6731 tmp_list = tmp_list->next;
6734 recompute_visible_regions (private, FALSE, TRUE);
6736 new_native_child_region = NULL;
6737 if (old_native_child_region)
6738 new_native_child_region = collect_native_child_region (private, FALSE);
6740 move_native_children (private);
6742 /* Then copy the actual bits of the window w/ child windows */
6744 impl_window = gdk_window_get_impl_window (private);
6746 /* Calculate the area that can be gotten by copying the old area */
6747 copy_area = gdk_region_copy (private->clip_region);
6748 if (old_native_child_region)
6750 /* Don't copy from inside native children, as this is copied by
6751 * the native window move.
6753 gdk_region_subtract (copy_area, old_native_child_region);
6755 /* Don't copy any bits that would cause a read from the moved
6756 native windows, as we can't read that data */
6757 gdk_region_subtract (copy_area, new_native_child_region);
6759 gdk_region_offset (copy_area, dx, dy);
6760 gdk_region_intersect (copy_area, private->clip_region);
6762 /* And the rest need to be invalidated */
6763 noncopy_area = gdk_region_copy (private->clip_region);
6764 gdk_region_subtract (noncopy_area, copy_area);
6766 /* convert from window coords to impl */
6767 gdk_region_offset (copy_area, private->abs_x, private->abs_y);
6769 move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
6771 /* Invalidate not copied regions */
6772 gdk_window_invalidate_region (window, noncopy_area, TRUE);
6774 gdk_region_destroy (noncopy_area);
6776 if (old_native_child_region)
6778 gdk_region_destroy (old_native_child_region);
6779 gdk_region_destroy (new_native_child_region);
6782 _gdk_synthesize_crossing_events_for_geometry_change (window);
6786 * gdk_window_move_region:
6787 * @window: a #GdkWindow
6788 * @region: The #GdkRegion to move
6789 * @dx: Amount to move in the X direction
6790 * @dy: Amount to move in the Y direction
6792 * Move the part of @window indicated by @region by @dy pixels in the Y
6793 * direction and @dx pixels in the X direction. The portions of @region
6794 * that not covered by the new position of @region are invalidated.
6796 * Child windows are not moved.
6801 gdk_window_move_region (GdkWindow *window,
6802 const GdkRegion *region,
6806 GdkWindowObject *private = (GdkWindowObject *) window;
6807 GdkWindowObject *impl_window;
6808 GdkRegion *nocopy_area;
6809 GdkRegion *copy_area;
6811 g_return_if_fail (GDK_IS_WINDOW (window));
6812 g_return_if_fail (region != NULL);
6814 if (dx == 0 && dy == 0)
6817 if (private->destroyed)
6820 impl_window = gdk_window_get_impl_window (private);
6822 /* compute source regions */
6823 copy_area = gdk_region_copy (region);
6824 gdk_region_intersect (copy_area, private->clip_region_with_children);
6826 /* compute destination regions */
6827 gdk_region_offset (copy_area, dx, dy);
6828 gdk_region_intersect (copy_area, private->clip_region_with_children);
6830 /* invalidate parts of the region not covered by the copy */
6831 nocopy_area = gdk_region_copy (region);
6832 gdk_region_offset (nocopy_area, dx, dy);
6833 gdk_region_subtract (nocopy_area, copy_area);
6834 gdk_window_invalidate_region (window, nocopy_area, FALSE);
6835 gdk_region_destroy (nocopy_area);
6837 /* convert from window coords to impl */
6838 gdk_region_offset (copy_area, private->abs_x, private->abs_y);
6840 move_region_on_impl (impl_window, copy_area, dx, dy); /* Takes ownership of copy_area */
6844 * gdk_window_set_background:
6845 * @window: a #GdkWindow
6846 * @color: an allocated #GdkColor
6848 * Sets the background color of @window. (However, when using GTK+,
6849 * set the background of a widget with gtk_widget_modify_bg() - if
6850 * you're an application - or gtk_style_set_background() - if you're
6851 * implementing a custom widget.)
6853 * The @color must be allocated; gdk_rgb_find_color() is the best way
6854 * to allocate a color.
6856 * See also gdk_window_set_back_pixmap().
6859 gdk_window_set_background (GdkWindow *window,
6860 const GdkColor *color)
6862 GdkWindowObject *private;
6863 GdkColormap *colormap = gdk_drawable_get_colormap (window);
6865 g_return_if_fail (GDK_IS_WINDOW (window));
6867 private = (GdkWindowObject *) window;
6869 private->bg_color = *color;
6870 gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
6872 if (private->bg_pixmap &&
6873 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
6874 private->bg_pixmap != GDK_NO_BG)
6875 g_object_unref (private->bg_pixmap);
6877 private->bg_pixmap = NULL;
6879 if (!GDK_WINDOW_DESTROYED (window) &&
6880 gdk_window_has_impl (private) &&
6881 !private->input_only)
6882 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, &private->bg_color);
6886 * gdk_window_set_back_pixmap:
6887 * @window: a #GdkWindow
6888 * @pixmap: a #GdkPixmap, or %NULL
6889 * @parent_relative: whether the tiling origin is at the origin of
6892 * Sets the background pixmap of @window. May also be used to set a
6893 * background of "None" on @window, by setting a background pixmap
6896 * A background pixmap will be tiled, positioning the first tile at
6897 * the origin of @window, or if @parent_relative is %TRUE, the tiling
6898 * will be done based on the origin of the parent window (useful to
6899 * align tiles in a parent with tiles in a child).
6901 * A background pixmap of %NULL means that the window will have no
6902 * background. A window with no background will never have its
6903 * background filled by the windowing system, instead the window will
6904 * contain whatever pixels were already in the corresponding area of
6907 * The windowing system will normally fill a window with its background
6908 * when the window is obscured then exposed, and when you call
6909 * gdk_window_clear().
6912 gdk_window_set_back_pixmap (GdkWindow *window,
6914 gboolean parent_relative)
6916 GdkWindowObject *private;
6918 g_return_if_fail (GDK_IS_WINDOW (window));
6919 g_return_if_fail (pixmap == NULL || !parent_relative);
6920 g_return_if_fail (pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap));
6922 private = (GdkWindowObject *) window;
6924 if (pixmap && !gdk_drawable_get_colormap (pixmap))
6926 g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
6930 if (private->bg_pixmap &&
6931 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
6932 private->bg_pixmap != GDK_NO_BG)
6933 g_object_unref (private->bg_pixmap);
6935 if (parent_relative)
6936 private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
6938 private->bg_pixmap = g_object_ref (pixmap);
6940 private->bg_pixmap = GDK_NO_BG;
6942 if (!GDK_WINDOW_DESTROYED (window) &&
6943 gdk_window_has_impl (private) &&
6944 !private->input_only)
6945 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, private->bg_pixmap);
6949 * gdk_window_set_cursor:
6950 * @window: a #GdkWindow
6953 * Sets the mouse pointer for a #GdkWindow. Use gdk_cursor_new_for_display()
6954 * or gdk_cursor_new_from_pixmap() to create the cursor. To make the cursor
6955 * invisible, use %GDK_BLANK_CURSOR. Passing %NULL for the @cursor argument
6956 * to gdk_window_set_cursor() means that @window will use the cursor of its
6957 * parent window. Most windows should use this default.
6960 gdk_window_set_cursor (GdkWindow *window,
6963 GdkWindowObject *private;
6964 GdkDisplay *display;
6966 g_return_if_fail (GDK_IS_WINDOW (window));
6968 private = (GdkWindowObject *) window;
6969 display = gdk_drawable_get_display (window);
6971 if (private->cursor)
6973 gdk_cursor_unref (private->cursor);
6974 private->cursor = NULL;
6977 if (!GDK_WINDOW_DESTROYED (window))
6980 private->cursor = gdk_cursor_ref (cursor);
6982 if (_gdk_window_event_parent_of (window, display->pointer_info.window_under_pointer))
6983 update_cursor (display);
6988 * gdk_window_get_geometry:
6989 * @window: a #GdkWindow
6990 * @x: return location for X coordinate of window (relative to its parent)
6991 * @y: return location for Y coordinate of window (relative to its parent)
6992 * @width: return location for width of window
6993 * @height: return location for height of window
6994 * @depth: return location for bit depth of window
6996 * Any of the return location arguments to this function may be %NULL,
6997 * if you aren't interested in getting the value of that field.
6999 * The X and Y coordinates returned are relative to the parent window
7000 * of @window, which for toplevels usually means relative to the
7001 * window decorations (titlebar, etc.) rather than relative to the
7002 * root window (screen-size background window).
7004 * On the X11 platform, the geometry is obtained from the X server,
7005 * so reflects the latest position of @window; this may be out-of-sync
7006 * with the position of @window delivered in the most-recently-processed
7007 * #GdkEventConfigure. gdk_window_get_position() in contrast gets the
7008 * position from the most recent configure event.
7011 * If @window is not a toplevel, it is <emphasis>much</emphasis> better
7012 * to call gdk_window_get_position() and gdk_drawable_get_size() instead,
7013 * because it avoids the roundtrip to the X server and because
7014 * gdk_drawable_get_size() supports the full 32-bit coordinate space,
7015 * whereas gdk_window_get_geometry() is restricted to the 16-bit
7016 * coordinates of X11.
7020 gdk_window_get_geometry (GdkWindow *window,
7027 GdkWindowObject *private;
7031 GDK_NOTE (MULTIHEAD,
7032 g_message ("gdk_window_get_geometry(): Window needs "
7033 "to be non-NULL to be multi head safe"));
7034 window = gdk_screen_get_root_window ((gdk_screen_get_default ()));
7037 g_return_if_fail (GDK_IS_WINDOW (window));
7039 private = (GdkWindowObject *) window;
7041 if (!GDK_WINDOW_DESTROYED (window))
7043 if (gdk_window_has_impl (private))
7044 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_geometry (window, x, y,
7054 *width = private->width;
7056 *height = private->height;
7058 *depth = private->depth;
7064 * gdk_window_get_origin:
7065 * @window: a #GdkWindow
7066 * @x: return location for X coordinate
7067 * @y: return location for Y coordinate
7069 * Obtains the position of a window in root window coordinates.
7070 * (Compare with gdk_window_get_position() and
7071 * gdk_window_get_geometry() which return the position of a window
7072 * relative to its parent window.)
7074 * Return value: not meaningful, ignore
7077 gdk_window_get_origin (GdkWindow *window,
7081 GdkWindowObject *private;
7083 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
7085 if (GDK_WINDOW_DESTROYED (window))
7094 private = (GdkWindowObject *) window;
7096 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_root_coords (window,
7105 * gdk_window_get_root_coords:
7106 * @window: a #GdkWindow
7107 * @x: X coordinate in window
7108 * @y: Y coordinate in window
7109 * @root_x: return location for X coordinate
7110 * @root_y: return location for Y coordinate
7112 * Obtains the position of a window position in root
7113 * window coordinates. This is similar to
7114 * gdk_window_get_origin() but allows you go pass
7115 * in any position in the window, not just the origin.
7118 gdk_window_get_root_coords (GdkWindow *window,
7124 GdkWindowObject *private;
7126 g_return_if_fail (GDK_IS_WINDOW (window));
7128 private = (GdkWindowObject *) window;
7130 if (GDK_WINDOW_DESTROYED (window))
7139 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_root_coords (window,
7147 * gdk_window_get_deskrelative_origin:
7148 * @window: a toplevel #GdkWindow
7149 * @x: return location for X coordinate
7150 * @y: return location for Y coordinate
7152 * This gets the origin of a #GdkWindow relative to
7153 * an Enlightenment-window-manager desktop. As long as you don't
7154 * assume that the user's desktop/workspace covers the entire
7155 * root window (i.e. you don't assume that the desktop begins
7156 * at root window coordinate 0,0) this function is not necessary.
7157 * It's deprecated for that reason.
7159 * Return value: not meaningful
7162 gdk_window_get_deskrelative_origin (GdkWindow *window,
7166 GdkWindowObject *private;
7167 gboolean return_val = FALSE;
7171 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
7173 private = (GdkWindowObject *) window;
7175 if (!GDK_WINDOW_DESTROYED (window))
7177 return_val = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_deskrelative_origin (window, &tx, &ty);
7180 *x = tx + private->abs_x;
7182 *y = ty + private->abs_y;
7189 * gdk_window_shape_combine_mask:
7190 * @window: a #GdkWindow
7192 * @x: X position of shape mask with respect to @window
7193 * @y: Y position of shape mask with respect to @window
7195 * Applies a shape mask to @window. Pixels in @window corresponding to
7196 * set bits in the @mask will be visible; pixels in @window
7197 * corresponding to unset bits in the @mask will be transparent. This
7198 * gives a non-rectangular window.
7200 * If @mask is %NULL, the shape mask will be unset, and the @x/@y
7201 * parameters are not used.
7203 * On the X11 platform, this uses an X server extension which is
7204 * widely available on most common platforms, but not available on
7205 * very old X servers, and occasionally the implementation will be
7206 * buggy. On servers without the shape extension, this function
7209 * This function works on both toplevel and child windows.
7212 gdk_window_shape_combine_mask (GdkWindow *window,
7217 GdkWindowObject *private;
7220 g_return_if_fail (GDK_IS_WINDOW (window));
7222 private = (GdkWindowObject *) window;
7225 region = _gdk_windowing_get_shape_for_mask (mask);
7229 gdk_window_shape_combine_region (window,
7234 gdk_region_destroy (region);
7238 * gdk_window_shape_combine_region:
7239 * @window: a #GdkWindow
7240 * @shape_region: region of window to be non-transparent
7241 * @offset_x: X position of @shape_region in @window coordinates
7242 * @offset_y: Y position of @shape_region in @window coordinates
7244 * Makes pixels in @window outside @shape_region be transparent,
7245 * so that the window may be nonrectangular. See also
7246 * gdk_window_shape_combine_mask() to use a bitmap as the mask.
7248 * If @shape_region is %NULL, the shape will be unset, so the whole
7249 * window will be opaque again. @offset_x and @offset_y are ignored
7250 * if @shape_region is %NULL.
7252 * On the X11 platform, this uses an X server extension which is
7253 * widely available on most common platforms, but not available on
7254 * very old X servers, and occasionally the implementation will be
7255 * buggy. On servers without the shape extension, this function
7258 * This function works on both toplevel and child windows.
7261 gdk_window_shape_combine_region (GdkWindow *window,
7262 const GdkRegion *shape_region,
7266 GdkWindowObject *private;
7267 GdkRegion *old_region, *new_region, *diff;
7269 g_return_if_fail (GDK_IS_WINDOW (window));
7271 private = (GdkWindowObject *) window;
7273 if (GDK_WINDOW_DESTROYED (window))
7276 private->shaped = (shape_region != NULL);
7279 gdk_region_destroy (private->shape);
7282 if (private->viewable)
7283 old_region = gdk_region_copy (private->clip_region);
7287 private->shape = gdk_region_copy (shape_region);
7288 gdk_region_offset (private->shape, offset_x, offset_y);
7291 private->shape = NULL;
7293 recompute_visible_regions (private, TRUE, FALSE);
7297 new_region = gdk_region_copy (private->clip_region);
7299 /* New area in the window, needs invalidation */
7300 diff = gdk_region_copy (new_region);
7301 gdk_region_subtract (diff, old_region);
7303 gdk_window_invalidate_region (window, diff, TRUE);
7305 gdk_region_destroy (diff);
7307 if (private->parent != NULL &&
7308 private->parent->window_type != GDK_WINDOW_ROOT)
7310 /* New area in the non-root parent window, needs invalidation */
7311 diff = gdk_region_copy (old_region);
7312 gdk_region_subtract (diff, new_region);
7314 /* Adjust region to parent window coords */
7315 gdk_region_offset (diff, private->x, private->y);
7317 gdk_window_invalidate_region (GDK_WINDOW (private->parent), diff, TRUE);
7319 gdk_region_destroy (diff);
7322 gdk_region_destroy (new_region);
7323 gdk_region_destroy (old_region);
7328 do_child_shapes (GdkWindow *window,
7331 GdkWindowObject *private;
7335 private = (GdkWindowObject *) window;
7339 r.width = private->width;
7340 r.height = private->height;
7342 region = gdk_region_rectangle (&r);
7343 remove_child_area (private, NULL, FALSE, region);
7345 if (merge && private->shape)
7346 gdk_region_subtract (region, private->shape);
7348 gdk_window_shape_combine_region (window, region, 0, 0);
7352 * gdk_window_set_child_shapes:
7353 * @window: a #GdkWindow
7355 * Sets the shape mask of @window to the union of shape masks
7356 * for all children of @window, ignoring the shape mask of @window
7357 * itself. Contrast with gdk_window_merge_child_shapes() which includes
7358 * the shape mask of @window in the masks to be merged.
7361 gdk_window_set_child_shapes (GdkWindow *window)
7363 g_return_if_fail (GDK_IS_WINDOW (window));
7365 do_child_shapes (window, FALSE);
7369 * gdk_window_merge_child_shapes:
7370 * @window: a #GdkWindow
7372 * Merges the shape masks for any child windows into the
7373 * shape mask for @window. i.e. the union of all masks
7374 * for @window and its children will become the new mask
7375 * for @window. See gdk_window_shape_combine_mask().
7377 * This function is distinct from gdk_window_set_child_shapes()
7378 * because it includes @window's shape mask in the set of shapes to
7382 gdk_window_merge_child_shapes (GdkWindow *window)
7384 g_return_if_fail (GDK_IS_WINDOW (window));
7386 do_child_shapes (window, TRUE);
7390 * gdk_window_input_shape_combine_mask:
7391 * @window: a #GdkWindow
7393 * @x: X position of shape mask with respect to @window
7394 * @y: Y position of shape mask with respect to @window
7396 * Like gdk_window_shape_combine_mask(), but the shape applies
7397 * only to event handling. Mouse events which happen while
7398 * the pointer position corresponds to an unset bit in the
7399 * mask will be passed on the window below @window.
7401 * An input shape is typically used with RGBA windows.
7402 * The alpha channel of the window defines which pixels are
7403 * invisible and allows for nicely antialiased borders,
7404 * and the input shape controls where the window is
7407 * On the X11 platform, this requires version 1.1 of the
7410 * On the Win32 platform, this functionality is not present and the
7411 * function does nothing.
7416 gdk_window_input_shape_combine_mask (GdkWindow *window,
7421 GdkWindowObject *private;
7424 g_return_if_fail (GDK_IS_WINDOW (window));
7426 private = (GdkWindowObject *) window;
7429 region = _gdk_windowing_get_shape_for_mask (mask);
7433 gdk_window_input_shape_combine_region (window,
7437 gdk_region_destroy (region);
7441 * gdk_window_input_shape_combine_region:
7442 * @window: a #GdkWindow
7443 * @shape_region: region of window to be non-transparent
7444 * @offset_x: X position of @shape_region in @window coordinates
7445 * @offset_y: Y position of @shape_region in @window coordinates
7447 * Like gdk_window_shape_combine_region(), but the shape applies
7448 * only to event handling. Mouse events which happen while
7449 * the pointer position corresponds to an unset bit in the
7450 * mask will be passed on the window below @window.
7452 * An input shape is typically used with RGBA windows.
7453 * The alpha channel of the window defines which pixels are
7454 * invisible and allows for nicely antialiased borders,
7455 * and the input shape controls where the window is
7458 * On the X11 platform, this requires version 1.1 of the
7461 * On the Win32 platform, this functionality is not present and the
7462 * function does nothing.
7467 gdk_window_input_shape_combine_region (GdkWindow *window,
7468 const GdkRegion *shape_region,
7472 GdkWindowObject *private;
7474 g_return_if_fail (GDK_IS_WINDOW (window));
7476 private = (GdkWindowObject *) window;
7478 if (GDK_WINDOW_DESTROYED (window))
7481 if (private->input_shape)
7482 gdk_region_destroy (private->input_shape);
7486 private->input_shape = gdk_region_copy (shape_region);
7487 gdk_region_offset (private->input_shape, offset_x, offset_y);
7490 private->input_shape = NULL;
7492 if (gdk_window_has_impl (private))
7493 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_shape_combine_region ((GdkWindow *)private, private->input_shape, 0, 0);
7495 /* Pointer may have e.g. moved outside window due to the input mask change */
7496 _gdk_synthesize_crossing_events_for_geometry_change (window);
7500 do_child_input_shapes (GdkWindow *window,
7503 GdkWindowObject *private;
7507 private = (GdkWindowObject *) window;
7511 r.width = private->width;
7512 r.height = private->height;
7514 region = gdk_region_rectangle (&r);
7515 remove_child_area (private, NULL, TRUE, region);
7517 if (merge && private->shape)
7518 gdk_region_subtract (region, private->shape);
7519 if (merge && private->input_shape)
7520 gdk_region_subtract (region, private->input_shape);
7522 gdk_window_input_shape_combine_region (window, region, 0, 0);
7527 * gdk_window_set_child_input_shapes:
7528 * @window: a #GdkWindow
7530 * Sets the input shape mask of @window to the union of input shape masks
7531 * for all children of @window, ignoring the input shape mask of @window
7532 * itself. Contrast with gdk_window_merge_child_input_shapes() which includes
7533 * the input shape mask of @window in the masks to be merged.
7538 gdk_window_set_child_input_shapes (GdkWindow *window)
7540 g_return_if_fail (GDK_IS_WINDOW (window));
7542 do_child_input_shapes (window, FALSE);
7546 * gdk_window_merge_child_input_shapes:
7547 * @window: a #GdkWindow
7549 * Merges the input shape masks for any child windows into the
7550 * input shape mask for @window. i.e. the union of all input masks
7551 * for @window and its children will become the new input mask
7552 * for @window. See gdk_window_input_shape_combine_mask().
7554 * This function is distinct from gdk_window_set_child_input_shapes()
7555 * because it includes @window's input shape mask in the set of
7556 * shapes to be merged.
7561 gdk_window_merge_child_input_shapes (GdkWindow *window)
7563 g_return_if_fail (GDK_IS_WINDOW (window));
7565 do_child_input_shapes (window, TRUE);
7570 * gdk_window_set_static_gravities:
7571 * @window: a #GdkWindow
7572 * @use_static: %TRUE to turn on static gravity
7574 * Set the bit gravity of the given window to static, and flag it so
7575 * all children get static subwindow gravity. This is used if you are
7576 * implementing scary features that involve deep knowledge of the
7577 * windowing system. Don't worry about it unless you have to.
7579 * Return value: %TRUE if the server supports static gravity
7582 gdk_window_set_static_gravities (GdkWindow *window,
7583 gboolean use_static)
7585 GdkWindowObject *private;
7587 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
7589 private = (GdkWindowObject *) window;
7591 if (gdk_window_has_impl (private))
7592 return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_static_gravities (window, use_static);
7598 * gdk_window_set_composited:
7599 * @window: a #GdkWindow
7600 * @composited: %TRUE to set the window as composited
7602 * Sets a #GdkWindow as composited, or unsets it. Composited
7603 * windows do not automatically have their contents drawn to
7604 * the screen. Drawing is redirected to an offscreen buffer
7605 * and an expose event is emitted on the parent of the composited
7606 * window. It is the responsibility of the parent's expose handler
7607 * to manually merge the off-screen content onto the screen in
7608 * whatever way it sees fit. See <xref linkend="composited-window-example"/>
7611 * It only makes sense for child windows to be composited; see
7612 * gdk_window_set_opacity() if you need translucent toplevel
7615 * An additional effect of this call is that the area of this
7616 * window is no longer clipped from regions marked for
7617 * invalidation on its parent. Draws done on the parent
7618 * window are also no longer clipped by the child.
7620 * This call is only supported on some systems (currently,
7621 * only X11 with new enough Xcomposite and Xdamage extensions).
7622 * You must call gdk_display_supports_composite() to check if
7623 * setting a window as composited is supported before
7624 * attempting to do so.
7629 gdk_window_set_composited (GdkWindow *window,
7630 gboolean composited)
7632 GdkWindowObject *private = (GdkWindowObject *)window;
7633 GdkDisplay *display;
7635 g_return_if_fail (GDK_IS_WINDOW (window));
7637 composited = composited != FALSE;
7639 if (private->composited == composited)
7643 gdk_window_ensure_native (window);
7645 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
7647 if (!gdk_display_supports_composite (display) && composited)
7649 g_warning ("gdk_window_set_composited called but "
7650 "compositing is not supported");
7654 _gdk_windowing_window_set_composited (window, composited);
7656 recompute_visible_regions (private, TRUE, FALSE);
7658 if (GDK_WINDOW_IS_MAPPED (window))
7659 gdk_window_invalidate_in_parent (private);
7661 private->composited = composited;
7666 remove_redirect_from_children (GdkWindowObject *private,
7667 GdkWindowRedirect *redirect)
7670 GdkWindowObject *child;
7672 for (l = private->children; l != NULL; l = l->next)
7676 /* Don't redirect this child if it already has another redirect */
7677 if (child->redirect == redirect)
7679 child->redirect = NULL;
7680 remove_redirect_from_children (child, redirect);
7686 * gdk_window_remove_redirection:
7687 * @window: a #GdkWindow
7689 * Removes any active redirection started by
7690 * gdk_window_redirect_to_drawable().
7695 gdk_window_remove_redirection (GdkWindow *window)
7697 GdkWindowObject *private;
7699 g_return_if_fail (GDK_IS_WINDOW (window));
7701 private = (GdkWindowObject *) window;
7703 if (private->redirect &&
7704 private->redirect->redirected == private)
7706 remove_redirect_from_children (private, private->redirect);
7707 gdk_window_redirect_free (private->redirect);
7708 private->redirect = NULL;
7713 apply_redirect_to_children (GdkWindowObject *private,
7714 GdkWindowRedirect *redirect)
7717 GdkWindowObject *child;
7719 for (l = private->children; l != NULL; l = l->next)
7723 /* Don't redirect this child if it already has another redirect */
7724 if (!child->redirect)
7726 child->redirect = redirect;
7727 apply_redirect_to_children (child, redirect);
7733 * gdk_window_redirect_to_drawable:
7734 * @window: a #GdkWindow
7735 * @drawable: a #GdkDrawable
7736 * @src_x: x position in @window
7737 * @src_y: y position in @window
7738 * @dest_x: x position in @drawable
7739 * @dest_y: y position in @drawable
7740 * @width: width of redirection
7741 * @height: height of redirection
7743 * Redirects drawing into @window so that drawing to the
7744 * window in the rectangle specified by @src_x, @src_y,
7745 * @width and @height is also drawn into @drawable at
7748 * Only drawing between gdk_window_begin_paint_region() or
7749 * gdk_window_begin_paint_rect() and gdk_window_end_paint() is
7752 * Redirection is active until gdk_window_remove_redirection()
7758 gdk_window_redirect_to_drawable (GdkWindow *window,
7759 GdkDrawable *drawable,
7767 GdkWindowObject *private;
7769 g_return_if_fail (GDK_IS_WINDOW (window));
7770 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
7771 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
7773 private = (GdkWindowObject *) window;
7775 if (private->redirect)
7776 gdk_window_remove_redirection (window);
7778 if (width == -1 || height == -1)
7781 gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
7788 private->redirect = g_new0 (GdkWindowRedirect, 1);
7789 private->redirect->redirected = private;
7790 private->redirect->pixmap = g_object_ref (drawable);
7791 private->redirect->src_x = src_x;
7792 private->redirect->src_y = src_y;
7793 private->redirect->dest_x = dest_x;
7794 private->redirect->dest_y = dest_y;
7795 private->redirect->width = width;
7796 private->redirect->height = height;
7798 apply_redirect_to_children (private, private->redirect);
7802 window_get_size_rectangle (GdkWindow *window,
7805 GdkWindowObject *private = (GdkWindowObject *) window;
7807 rect->x = rect->y = 0;
7808 rect->width = private->width;
7809 rect->height = private->height;
7812 /* Calculates the real clipping region for a window, in window coordinates,
7813 * taking into account other windows, gc clip region and gc clip mask.
7816 _gdk_window_calculate_full_clip_region (GdkWindow *window,
7817 GdkWindow *base_window,
7818 gboolean do_children,
7819 gint *base_x_offset,
7820 gint *base_y_offset)
7822 GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
7823 GdkRectangle visible_rect;
7824 GdkRegion *real_clip_region, *tmpreg;
7825 gint x_offset, y_offset;
7826 GdkWindowObject *parentwin, *lastwin;
7833 if (!private->viewable || private->input_only)
7834 return gdk_region_new ();
7836 window_get_size_rectangle (window, &visible_rect);
7838 /* real_clip_region is in window coordinates */
7839 real_clip_region = gdk_region_rectangle (&visible_rect);
7841 x_offset = y_offset = 0;
7845 parentwin = lastwin;
7847 parentwin = lastwin->parent;
7849 /* Remove the areas of all overlapping windows above parentwin in the hiearachy */
7850 for (; parentwin != NULL &&
7851 (parentwin == private || lastwin != (GdkWindowObject*) base_window);
7852 lastwin = parentwin, parentwin = lastwin->parent)
7855 GdkRectangle real_clip_rect;
7856 gboolean is_offscreen;
7858 if (parentwin != private)
7860 x_offset += GDK_WINDOW_OBJECT (lastwin)->x;
7861 y_offset += GDK_WINDOW_OBJECT (lastwin)->y;
7864 is_offscreen = gdk_window_is_offscreen (parentwin);
7866 /* children is ordered in reverse stack order */
7867 for (cur = parentwin->children;
7868 cur && cur->data != lastwin;
7871 GdkWindow *child = cur->data;
7872 GdkWindowObject *child_private = (GdkWindowObject *)child;
7874 if (!GDK_WINDOW_IS_MAPPED (child) || child_private->input_only)
7877 /* Ignore offscreen children, as they don't draw in their parent and
7878 * don't take part in the clipping */
7879 if (gdk_window_is_offscreen (child_private))
7882 window_get_size_rectangle (child, &visible_rect);
7884 /* Convert rect to "window" coords */
7885 visible_rect.x += child_private->x - x_offset;
7886 visible_rect.y += child_private->y - y_offset;
7888 /* This shortcut is really necessary for performance when there are a lot of windows */
7889 gdk_region_get_clipbox (real_clip_region, &real_clip_rect);
7890 if (visible_rect.x >= real_clip_rect.x + real_clip_rect.width ||
7891 visible_rect.x + visible_rect.width <= real_clip_rect.x ||
7892 visible_rect.y >= real_clip_rect.y + real_clip_rect.height ||
7893 visible_rect.y + visible_rect.height <= real_clip_rect.y)
7896 tmpreg = gdk_region_rectangle (&visible_rect);
7897 gdk_region_subtract (real_clip_region, tmpreg);
7898 gdk_region_destroy (tmpreg);
7901 /* Clip to the parent */
7902 window_get_size_rectangle ((GdkWindow *)parentwin, &visible_rect);
7903 /* Convert rect to "window" coords */
7904 visible_rect.x += - x_offset;
7905 visible_rect.y += - y_offset;
7907 tmpreg = gdk_region_rectangle (&visible_rect);
7908 gdk_region_intersect (real_clip_region, tmpreg);
7909 gdk_region_destroy (tmpreg);
7913 *base_x_offset = x_offset;
7915 *base_y_offset = y_offset;
7917 return real_clip_region;
7921 _gdk_window_add_damage (GdkWindow *toplevel,
7922 GdkRegion *damaged_region)
7924 GdkDisplay *display;
7925 GdkEvent event = { 0, };
7926 event.expose.type = GDK_DAMAGE;
7927 event.expose.window = toplevel;
7928 event.expose.send_event = FALSE;
7929 event.expose.region = damaged_region;
7930 gdk_region_get_clipbox (event.expose.region, &event.expose.area);
7931 display = gdk_drawable_get_display (event.expose.window);
7932 _gdk_event_queue_append (display, gdk_event_copy (&event));
7936 gdk_window_redirect_free (GdkWindowRedirect *redirect)
7938 g_object_unref (redirect->pixmap);
7942 /* Gets the toplevel for a window as used for events,
7943 i.e. including offscreen parents */
7944 static GdkWindowObject *
7945 get_event_parent (GdkWindowObject *window)
7947 if (window->window_type == GDK_WINDOW_OFFSCREEN)
7948 return (GdkWindowObject *)gdk_offscreen_window_get_embedder ((GdkWindow *)window);
7950 return window->parent;
7953 /* Gets the toplevel for a window as used for events,
7954 i.e. including offscreen parents going up to the native
7957 get_event_toplevel (GdkWindow *w)
7959 GdkWindowObject *private = GDK_WINDOW_OBJECT (w);
7960 GdkWindowObject *parent;
7962 while ((parent = get_event_parent (private)) != NULL &&
7963 (parent->window_type != GDK_WINDOW_ROOT))
7966 return GDK_WINDOW (private);
7970 _gdk_window_event_parent_of (GdkWindow *parent,
7981 w = (GdkWindow *)get_event_parent ((GdkWindowObject *)w);
7988 update_cursor (GdkDisplay *display)
7990 GdkWindowObject *pointer_window, *cursor_window, *parent, *toplevel;
7991 GdkPointerGrabInfo *grab;
7993 pointer_window = (GdkWindowObject *)display->pointer_info.window_under_pointer;
7995 cursor_window = pointer_window;
7996 while (cursor_window->cursor == NULL &&
7997 (parent = get_event_parent (cursor_window)) != NULL &&
7998 parent->window_type != GDK_WINDOW_ROOT)
7999 cursor_window = parent;
8001 /* We ignore the serials here and just pick the last grab
8002 we've sent, as that would shortly be used anyway. */
8003 grab = _gdk_display_get_last_pointer_grab (display);
8005 !_gdk_window_event_parent_of (grab->window, (GdkWindow *)cursor_window))
8006 cursor_window = (GdkWindowObject *)grab->window;
8008 /* Set all cursors on toplevel, otherwise its tricky to keep track of
8009 * which native window has what cursor set. */
8010 toplevel = (GdkWindowObject *)get_event_toplevel ((GdkWindow *)pointer_window);
8011 GDK_WINDOW_IMPL_GET_IFACE (toplevel->impl)->set_cursor
8012 ((GdkWindow *)toplevel, cursor_window->cursor);
8016 from_embedder (GdkWindowObject *window,
8017 double embedder_x, double embedder_y,
8018 double *offscreen_x, double *offscreen_y)
8020 g_signal_emit (window,
8021 signals[FROM_EMBEDDER], 0,
8022 embedder_x, embedder_y,
8023 offscreen_x, offscreen_y,
8028 convert_coords_to_child (GdkWindowObject *child,
8030 double *child_x, double *child_y)
8032 if (gdk_window_is_offscreen (child))
8034 from_embedder (child, x, y,
8039 *child_x = x - child->x;
8040 *child_y = y - child->y;
8045 point_in_window (GdkWindowObject *window,
8049 x >= 0 && x < window->width &&
8050 y >= 0 && y < window->height &&
8051 (window->shape == NULL ||
8052 gdk_region_point_in (window->shape,
8054 (window->input_shape == NULL ||
8055 gdk_region_point_in (window->input_shape,
8060 convert_native_coords_to_toplevel (GdkWindow *window,
8061 double child_x, double child_y,
8062 double *toplevel_x, double *toplevel_y)
8064 GdkWindowObject *private = (GdkWindowObject *)window;
8070 while (private->parent != NULL &&
8071 (private->parent->window_type != GDK_WINDOW_ROOT))
8075 private = private->parent;
8081 return (GdkWindow *)private;
8085 convert_toplevel_coords_to_window (GdkWindow *window,
8091 GdkWindowObject *private;
8092 GdkWindowObject *parent;
8094 GList *children, *l;
8096 private = GDK_WINDOW_OBJECT (window);
8102 while ((parent = get_event_parent (private)) != NULL &&
8103 (parent->window_type != GDK_WINDOW_ROOT))
8105 children = g_list_prepend (children, private);
8109 for (l = children; l != NULL; l = l->next)
8110 convert_coords_to_child (l->data, x, y, &x, &y);
8112 g_list_free (children);
8118 static GdkWindowObject *
8119 pick_embedded_child (GdkWindowObject *window,
8122 GdkWindowObject *res;
8125 g_signal_emit (window,
8126 signals[PICK_EMBEDDED_CHILD], 0,
8133 _gdk_window_find_child_at (GdkWindow *window,
8136 GdkWindowObject *private, *sub;
8137 double child_x, child_y;
8140 private = (GdkWindowObject *)window;
8142 if (point_in_window (private, x, y))
8144 /* Children is ordered in reverse stack order, i.e. first is topmost */
8145 for (l = private->children; l != NULL; l = l->next)
8149 if (!GDK_WINDOW_IS_MAPPED (sub))
8152 convert_coords_to_child (sub,
8154 &child_x, &child_y);
8155 if (point_in_window (sub, child_x, child_y))
8156 return (GdkWindow *)sub;
8159 if (private->num_offscreen_children > 0)
8161 sub = pick_embedded_child (private,
8164 return (GdkWindow *)sub;
8172 _gdk_window_find_descendant_at (GdkWindow *toplevel,
8177 GdkWindowObject *private, *sub;
8178 double child_x, child_y;
8182 private = (GdkWindowObject *)toplevel;
8184 if (point_in_window (private, x, y))
8189 /* Children is ordered in reverse stack order, i.e. first is topmost */
8190 for (l = private->children; l != NULL; l = l->next)
8194 if (!GDK_WINDOW_IS_MAPPED (sub))
8197 convert_coords_to_child (sub,
8199 &child_x, &child_y);
8200 if (point_in_window (sub, child_x, child_y))
8210 private->num_offscreen_children > 0)
8212 sub = pick_embedded_child (private,
8218 from_embedder (sub, x, y, &x, &y);
8226 /* Not in window at all */
8235 return (GdkWindow *)private;
8240 * @window: a toplevel #GdkWindow
8242 * Emits a short beep associated to @window in the appropriate
8243 * display, if supported. Otherwise, emits a short beep on
8244 * the display just as gdk_display_beep().
8249 gdk_window_beep (GdkWindow *window)
8251 GdkDisplay *display;
8252 GdkWindow *toplevel;
8254 g_return_if_fail (GDK_IS_WINDOW (window));
8256 if (GDK_WINDOW_DESTROYED (window))
8259 toplevel = get_event_toplevel (window);
8260 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
8262 if (toplevel && gdk_window_is_offscreen ((GdkWindowObject *)toplevel))
8263 _gdk_windowing_window_beep (toplevel);
8265 gdk_display_beep (display);
8268 static const guint type_masks[] = {
8269 GDK_SUBSTRUCTURE_MASK, /* GDK_DELETE = 0 */
8270 GDK_STRUCTURE_MASK, /* GDK_DESTROY = 1 */
8271 GDK_EXPOSURE_MASK, /* GDK_EXPOSE = 2 */
8272 GDK_POINTER_MOTION_MASK, /* GDK_MOTION_NOTIFY = 3 */
8273 GDK_BUTTON_PRESS_MASK, /* GDK_BUTTON_PRESS = 4 */
8274 GDK_BUTTON_PRESS_MASK, /* GDK_2BUTTON_PRESS = 5 */
8275 GDK_BUTTON_PRESS_MASK, /* GDK_3BUTTON_PRESS = 6 */
8276 GDK_BUTTON_RELEASE_MASK, /* GDK_BUTTON_RELEASE = 7 */
8277 GDK_KEY_PRESS_MASK, /* GDK_KEY_PRESS = 8 */
8278 GDK_KEY_RELEASE_MASK, /* GDK_KEY_RELEASE = 9 */
8279 GDK_ENTER_NOTIFY_MASK, /* GDK_ENTER_NOTIFY = 10 */
8280 GDK_LEAVE_NOTIFY_MASK, /* GDK_LEAVE_NOTIFY = 11 */
8281 GDK_FOCUS_CHANGE_MASK, /* GDK_FOCUS_CHANGE = 12 */
8282 GDK_STRUCTURE_MASK, /* GDK_CONFIGURE = 13 */
8283 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_MAP = 14 */
8284 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_UNMAP = 15 */
8285 GDK_PROPERTY_CHANGE_MASK, /* GDK_PROPERTY_NOTIFY = 16 */
8286 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_CLEAR = 17 */
8287 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_REQUEST = 18 */
8288 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_NOTIFY = 19 */
8289 GDK_PROXIMITY_IN_MASK, /* GDK_PROXIMITY_IN = 20 */
8290 GDK_PROXIMITY_OUT_MASK, /* GDK_PROXIMITY_OUT = 21 */
8291 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_ENTER = 22 */
8292 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_LEAVE = 23 */
8293 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_MOTION = 24 */
8294 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_STATUS = 25 */
8295 GDK_ALL_EVENTS_MASK, /* GDK_DROP_START = 26 */
8296 GDK_ALL_EVENTS_MASK, /* GDK_DROP_FINISHED = 27 */
8297 GDK_ALL_EVENTS_MASK, /* GDK_CLIENT_EVENT = 28 */
8298 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_VISIBILITY_NOTIFY = 29 */
8299 GDK_EXPOSURE_MASK, /* GDK_NO_EXPOSE = 30 */
8300 GDK_SCROLL_MASK | GDK_BUTTON_PRESS_MASK,/* GDK_SCROLL= 31 */
8301 0, /* GDK_WINDOW_STATE = 32 */
8302 0, /* GDK_SETTING = 33 */
8303 0, /* GDK_OWNER_CHANGE = 34 */
8304 0, /* GDK_GRAB_BROKEN = 35 */
8305 0, /* GDK_DAMAGE = 36 */
8307 G_STATIC_ASSERT (G_N_ELEMENTS (type_masks) == GDK_EVENT_LAST);
8309 /* send motion events if the right buttons are down */
8311 update_evmask_for_button_motion (guint evmask,
8312 GdkModifierType mask)
8314 if (evmask & GDK_BUTTON_MOTION_MASK &&
8315 mask & (GDK_BUTTON1_MASK |
8320 evmask |= GDK_POINTER_MOTION_MASK;
8322 if ((evmask & GDK_BUTTON1_MOTION_MASK && mask & GDK_BUTTON1_MASK) ||
8323 (evmask & GDK_BUTTON2_MOTION_MASK && mask & GDK_BUTTON2_MASK) ||
8324 (evmask & GDK_BUTTON3_MOTION_MASK && mask & GDK_BUTTON3_MASK))
8325 evmask |= GDK_POINTER_MOTION_MASK;
8331 is_button_type (GdkEventType type)
8333 return type == GDK_BUTTON_PRESS ||
8334 type == GDK_2BUTTON_PRESS ||
8335 type == GDK_3BUTTON_PRESS ||
8336 type == GDK_BUTTON_RELEASE ||
8341 is_motion_type (GdkEventType type)
8343 return type == GDK_MOTION_NOTIFY ||
8344 type == GDK_ENTER_NOTIFY ||
8345 type == GDK_LEAVE_NOTIFY;
8348 static GdkWindowObject *
8349 find_common_ancestor (GdkWindowObject *win1,
8350 GdkWindowObject *win2)
8352 GdkWindowObject *tmp;
8353 GList *path1 = NULL, *path2 = NULL;
8354 GList *list1, *list2;
8357 while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
8359 path1 = g_list_prepend (path1, tmp);
8360 tmp = get_event_parent (tmp);
8364 while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
8366 path2 = g_list_prepend (path2, tmp);
8367 tmp = get_event_parent (tmp);
8373 while (list1 && list2 && (list1->data == list2->data))
8375 tmp = (GdkWindowObject *)list1->data;
8376 list1 = g_list_next (list1);
8377 list2 = g_list_next (list2);
8379 g_list_free (path1);
8380 g_list_free (path2);
8386 _gdk_make_event (GdkWindow *window,
8388 GdkEvent *event_in_queue,
8389 gboolean before_event)
8391 GdkEvent *event = gdk_event_new (type);
8393 GdkModifierType the_state;
8395 the_time = gdk_event_get_time (event_in_queue);
8396 gdk_event_get_state (event_in_queue, &the_state);
8398 event->any.window = g_object_ref (window);
8399 event->any.send_event = FALSE;
8403 case GDK_MOTION_NOTIFY:
8404 event->motion.time = the_time;
8405 event->motion.axes = NULL;
8406 event->motion.state = the_state;
8409 case GDK_BUTTON_PRESS:
8410 case GDK_2BUTTON_PRESS:
8411 case GDK_3BUTTON_PRESS:
8412 case GDK_BUTTON_RELEASE:
8413 event->button.time = the_time;
8414 event->button.axes = NULL;
8415 event->button.state = the_state;
8419 event->scroll.time = the_time;
8420 event->scroll.state = the_state;
8424 case GDK_KEY_RELEASE:
8425 event->key.time = the_time;
8426 event->key.state = the_state;
8429 case GDK_ENTER_NOTIFY:
8430 case GDK_LEAVE_NOTIFY:
8431 event->crossing.time = the_time;
8432 event->crossing.state = the_state;
8435 case GDK_PROPERTY_NOTIFY:
8436 event->property.time = the_time;
8437 event->property.state = the_state;
8440 case GDK_SELECTION_CLEAR:
8441 case GDK_SELECTION_REQUEST:
8442 case GDK_SELECTION_NOTIFY:
8443 event->selection.time = the_time;
8446 case GDK_PROXIMITY_IN:
8447 case GDK_PROXIMITY_OUT:
8448 event->proximity.time = the_time;
8451 case GDK_DRAG_ENTER:
8452 case GDK_DRAG_LEAVE:
8453 case GDK_DRAG_MOTION:
8454 case GDK_DRAG_STATUS:
8455 case GDK_DROP_START:
8456 case GDK_DROP_FINISHED:
8457 event->dnd.time = the_time;
8460 case GDK_FOCUS_CHANGE:
8464 case GDK_CLIENT_EVENT:
8465 case GDK_VISIBILITY_NOTIFY:
8477 _gdk_event_queue_insert_before (gdk_drawable_get_display (window), event_in_queue, event);
8479 _gdk_event_queue_insert_after (gdk_drawable_get_display (window), event_in_queue, event);
8482 _gdk_event_queue_append (gdk_drawable_get_display (window), event);
8488 send_crossing_event (GdkDisplay *display,
8489 GdkWindowObject *toplevel,
8490 GdkWindowObject *window,
8492 GdkCrossingMode mode,
8493 GdkNotifyType notify_type,
8494 GdkWindow *subwindow,
8497 GdkModifierType mask,
8499 GdkEvent *event_in_queue,
8504 GdkPointerGrabInfo *grab;
8506 grab = _gdk_display_has_pointer_grab (display, serial);
8509 !grab->owner_events &&
8510 (GdkWindow *)window != grab->window)
8513 if (type == GDK_LEAVE_NOTIFY)
8514 event_mask = GDK_LEAVE_NOTIFY_MASK;
8516 event_mask = GDK_ENTER_NOTIFY_MASK;
8518 if (window->extension_events != 0)
8519 GDK_WINDOW_IMPL_GET_IFACE (window->impl)->input_window_crossing ((GdkWindow *)window,
8520 type == GDK_ENTER_NOTIFY);
8522 if (window->event_mask & event_mask)
8524 event = _gdk_make_event ((GdkWindow *)window, type, event_in_queue, TRUE);
8525 event->crossing.time = time_;
8526 event->crossing.subwindow = subwindow;
8528 g_object_ref (subwindow);
8529 convert_toplevel_coords_to_window ((GdkWindow *)window,
8530 toplevel_x, toplevel_y,
8531 &event->crossing.x, &event->crossing.y);
8532 event->crossing.x_root = toplevel_x + toplevel->x;
8533 event->crossing.y_root = toplevel_y + toplevel->y;
8534 event->crossing.mode = mode;
8535 event->crossing.detail = notify_type;
8536 event->crossing.focus = FALSE;
8537 event->crossing.state = mask;
8542 /* The coordinates are in the toplevel window that src/dest are in.
8543 * src and dest are always (if != NULL) in the same toplevel, as
8544 * we get a leave-notify and set the window_under_pointer to null
8545 * before crossing to another toplevel.
8548 _gdk_synthesize_crossing_events (GdkDisplay *display,
8551 GdkCrossingMode mode,
8554 GdkModifierType mask,
8556 GdkEvent *event_in_queue,
8558 gboolean non_linear)
8561 GdkWindowObject *win, *last, *next;
8565 GdkWindowObject *toplevel;
8566 GdkNotifyType notify_type;
8568 /* TODO: Don't send events to toplevel, as we get those from the windowing system */
8570 a = (GdkWindowObject *)src;
8571 b = (GdkWindowObject *)dest;
8573 return; /* No crossings generated between src and dest */
8575 c = find_common_ancestor (a, b);
8577 non_linear |= (c != a) && (c != b);
8579 if (a) /* There might not be a source (i.e. if no previous pointer_in_window) */
8581 toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)a);
8583 /* Traverse up from a to (excluding) c sending leave events */
8585 notify_type = GDK_NOTIFY_NONLINEAR;
8587 notify_type = GDK_NOTIFY_INFERIOR;
8589 notify_type = GDK_NOTIFY_ANCESTOR;
8590 send_crossing_event (display, toplevel,
8591 a, GDK_LEAVE_NOTIFY,
8595 toplevel_x, toplevel_y,
8603 notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
8605 notify_type = GDK_NOTIFY_VIRTUAL;
8608 win = get_event_parent (a);
8609 while (win != c && win->window_type != GDK_WINDOW_ROOT)
8611 send_crossing_event (display, toplevel,
8612 win, GDK_LEAVE_NOTIFY,
8616 toplevel_x, toplevel_y,
8622 win = get_event_parent (win);
8627 if (b) /* Might not be a dest, e.g. if we're moving out of the window */
8629 toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)b);
8631 /* Traverse down from c to b */
8635 win = get_event_parent (b);
8636 while (win != c && win->window_type != GDK_WINDOW_ROOT)
8638 path = g_list_prepend (path, win);
8639 win = get_event_parent (win);
8643 notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
8645 notify_type = GDK_NOTIFY_VIRTUAL;
8650 win = (GdkWindowObject *)list->data;
8651 list = g_list_next (list);
8653 next = (GdkWindowObject *)list->data;
8657 send_crossing_event (display, toplevel,
8658 win, GDK_ENTER_NOTIFY,
8662 toplevel_x, toplevel_y,
8672 notify_type = GDK_NOTIFY_NONLINEAR;
8674 notify_type = GDK_NOTIFY_ANCESTOR;
8676 notify_type = GDK_NOTIFY_INFERIOR;
8678 send_crossing_event (display, toplevel,
8679 b, GDK_ENTER_NOTIFY,
8683 toplevel_x, toplevel_y,
8690 /* Returns the window inside the event window with the pointer in it
8691 * at the specified coordinates, or NULL if its not in any child of
8692 * the toplevel. It also takes into account !owner_events grabs.
8695 get_pointer_window (GdkDisplay *display,
8696 GdkWindow *event_window,
8701 GdkWindow *pointer_window;
8702 GdkPointerGrabInfo *grab;
8704 if (event_window == display->pointer_info.toplevel_under_pointer)
8706 _gdk_window_find_descendant_at (event_window,
8707 toplevel_x, toplevel_y,
8710 pointer_window = NULL;
8712 grab = _gdk_display_has_pointer_grab (display, serial);
8714 !grab->owner_events &&
8715 pointer_window != grab->window)
8716 pointer_window = NULL;
8718 return pointer_window;
8722 _gdk_display_set_window_under_pointer (GdkDisplay *display,
8725 GdkWindowObject *private;
8727 private = (GdkWindowObject *)window;
8729 if (display->pointer_info.window_under_pointer)
8730 g_object_unref (display->pointer_info.window_under_pointer);
8731 display->pointer_info.window_under_pointer = window;
8733 g_object_ref (window);
8736 update_cursor (display);
8738 _gdk_display_enable_motion_hints (display);
8742 *--------------------------------------------------------------
8745 * Grabs the pointer to a specific window
8748 * "window" is the window which will receive the grab
8749 * "owner_events" specifies whether events will be reported as is,
8750 * or relative to "window"
8751 * "event_mask" masks only interesting events
8752 * "confine_to" limits the cursor movement to the specified window
8753 * "cursor" changes the cursor for the duration of the grab
8754 * "time" specifies the time
8759 * requires a corresponding call to gdk_pointer_ungrab
8761 *--------------------------------------------------------------
8764 gdk_pointer_grab (GdkWindow * window,
8765 gboolean owner_events,
8766 GdkEventMask event_mask,
8767 GdkWindow * confine_to,
8772 GdkDisplay *display;
8776 g_return_val_if_fail (window != NULL, 0);
8777 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
8778 g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
8780 /* We need a native window for confine to to work, ensure we have one */
8783 if (!gdk_window_ensure_native (confine_to))
8785 g_warning ("Can't confine to grabbed window, not native");
8790 /* Non-viewable client side window => fail */
8791 if (!_gdk_window_has_impl (window) &&
8792 !gdk_window_is_viewable (window))
8793 return GDK_GRAB_NOT_VIEWABLE;
8795 native = gdk_window_get_toplevel (window);
8796 while (gdk_window_is_offscreen ((GdkWindowObject *)native))
8798 native = gdk_offscreen_window_get_embedder (native);
8800 if (native == NULL ||
8801 (!_gdk_window_has_impl (native) &&
8802 !gdk_window_is_viewable (native)))
8803 return GDK_GRAB_NOT_VIEWABLE;
8805 native = gdk_window_get_toplevel (native);
8808 display = gdk_drawable_get_display (window);
8810 serial = _gdk_windowing_window_get_next_serial (display);
8812 res = _gdk_windowing_pointer_grab (window,
8820 if (res == GDK_GRAB_SUCCESS)
8821 _gdk_display_add_pointer_grab (display,
8834 * gdk_window_geometry_changed:
8835 * @window: a #GdkWindow
8840 gdk_window_geometry_changed (GdkWindow *window)
8842 _gdk_synthesize_crossing_events_for_geometry_change (window);
8846 do_synthesize_crossing_event (gpointer data)
8848 GdkDisplay *display;
8849 GdkWindow *changed_toplevel;
8850 GdkWindowObject *changed_toplevel_priv;
8851 GdkWindow *new_window_under_pointer;
8854 changed_toplevel = data;
8855 changed_toplevel_priv = (GdkWindowObject *)changed_toplevel;
8857 changed_toplevel_priv->synthesize_crossing_event_queued = FALSE;
8859 if (GDK_WINDOW_DESTROYED (changed_toplevel))
8862 display = gdk_drawable_get_display (changed_toplevel);
8863 serial = _gdk_windowing_window_get_next_serial (display);
8865 if (changed_toplevel == display->pointer_info.toplevel_under_pointer)
8867 new_window_under_pointer =
8868 get_pointer_window (display, changed_toplevel,
8869 display->pointer_info.toplevel_x,
8870 display->pointer_info.toplevel_y,
8872 if (new_window_under_pointer !=
8873 display->pointer_info.window_under_pointer)
8875 _gdk_synthesize_crossing_events (display,
8876 display->pointer_info.window_under_pointer,
8877 new_window_under_pointer,
8878 GDK_CROSSING_NORMAL,
8879 display->pointer_info.toplevel_x,
8880 display->pointer_info.toplevel_y,
8881 display->pointer_info.state,
8886 _gdk_display_set_window_under_pointer (display, new_window_under_pointer);
8894 _gdk_synthesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
8896 GdkDisplay *display;
8897 GdkWindow *toplevel;
8898 GdkWindowObject *toplevel_priv;
8900 display = gdk_drawable_get_display (changed_window);
8902 toplevel = get_event_toplevel (changed_window);
8903 toplevel_priv = (GdkWindowObject *)toplevel;
8905 if (toplevel == display->pointer_info.toplevel_under_pointer &&
8906 !toplevel_priv->synthesize_crossing_event_queued)
8908 toplevel_priv->synthesize_crossing_event_queued = TRUE;
8909 g_idle_add_full (GDK_PRIORITY_EVENTS - 1,
8910 do_synthesize_crossing_event,
8911 g_object_ref (toplevel),
8916 /* Don't use for crossing events */
8918 get_event_window (GdkDisplay *display,
8919 GdkWindow *pointer_window,
8921 GdkModifierType mask,
8926 GdkWindow *grab_window;
8928 GdkPointerGrabInfo *grab;
8930 grab = _gdk_display_has_pointer_grab (display, serial);
8932 if (grab != NULL && !grab->owner_events)
8934 evmask = grab->event_mask;
8935 evmask = update_evmask_for_button_motion (evmask, mask);
8937 grab_window = grab->window;
8939 if (evmask & type_masks[type])
8942 *evmask_out = evmask;
8949 w = (GdkWindowObject *)pointer_window;
8952 evmask = w->event_mask;
8953 evmask = update_evmask_for_button_motion (evmask, mask);
8955 if (evmask & type_masks[type])
8958 *evmask_out = evmask;
8959 return (GdkWindow *)w;
8962 w = get_event_parent (w);
8968 evmask = grab->event_mask;
8969 evmask = update_evmask_for_button_motion (evmask, mask);
8971 if (evmask & type_masks[type])
8974 *evmask_out = evmask;
8975 return grab->window;
8985 proxy_pointer_event (GdkDisplay *display,
8986 GdkEvent *source_event,
8989 GdkWindow *toplevel_window, *event_window;
8990 GdkWindow *pointer_window;
8993 gdouble toplevel_x, toplevel_y;
8995 gboolean non_linear;
8997 event_window = source_event->any.window;
8998 gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
8999 gdk_event_get_state (source_event, &state);
9000 time_ = gdk_event_get_time (source_event);
9001 toplevel_window = convert_native_coords_to_toplevel (event_window,
9002 toplevel_x, toplevel_y,
9003 &toplevel_x, &toplevel_y);
9006 if ((source_event->type == GDK_LEAVE_NOTIFY ||
9007 source_event->type == GDK_ENTER_NOTIFY) &&
9008 (source_event->crossing.detail == GDK_NOTIFY_NONLINEAR ||
9009 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))
9012 /* If we get crossing events with subwindow unexpectedly being NULL
9013 that means there is a native subwindow that gdk doesn't know about.
9014 We track these and forward them, with the correct virtual window
9016 This is important to get right, as metacity uses gdk for the frame
9017 windows, but gdk doesn't know about the client windows reparented
9019 if (((source_event->type == GDK_LEAVE_NOTIFY &&
9020 source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
9021 (source_event->type == GDK_ENTER_NOTIFY &&
9022 (source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
9023 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
9024 source_event->crossing.subwindow == NULL)
9026 /* Left for an unknown (to gdk) subwindow */
9028 /* Send leave events from window under pointer to event window
9029 that will get the subwindow == NULL window */
9030 _gdk_synthesize_crossing_events (display,
9031 display->pointer_info.window_under_pointer,
9033 source_event->crossing.mode,
9034 toplevel_x, toplevel_y,
9040 /* Send subwindow == NULL event */
9041 send_crossing_event (display,
9042 (GdkWindowObject *)toplevel_window,
9043 (GdkWindowObject *)event_window,
9045 source_event->crossing.mode,
9046 source_event->crossing.detail,
9048 toplevel_x, toplevel_y,
9053 _gdk_display_set_window_under_pointer (display, NULL);
9057 pointer_window = get_pointer_window (display, toplevel_window,
9058 toplevel_x, toplevel_y, serial);
9060 if (((source_event->type == GDK_ENTER_NOTIFY &&
9061 source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
9062 (source_event->type == GDK_LEAVE_NOTIFY &&
9063 (source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
9064 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
9065 source_event->crossing.subwindow == NULL)
9067 /* Entered from an unknown (to gdk) subwindow */
9069 /* Send subwindow == NULL event */
9070 send_crossing_event (display,
9071 (GdkWindowObject *)toplevel_window,
9072 (GdkWindowObject *)event_window,
9074 source_event->crossing.mode,
9075 source_event->crossing.detail,
9077 toplevel_x, toplevel_y,
9082 /* Send enter events from event window to pointer_window */
9083 _gdk_synthesize_crossing_events (display,
9086 source_event->crossing.mode,
9087 toplevel_x, toplevel_y,
9090 serial, non_linear);
9091 _gdk_display_set_window_under_pointer (display, pointer_window);
9095 if (display->pointer_info.window_under_pointer != pointer_window)
9097 /* Either a toplevel crossing notify that ended up inside a child window,
9098 or a motion notify that got into another child window */
9100 /* Different than last time, send crossing events */
9101 _gdk_synthesize_crossing_events (display,
9102 display->pointer_info.window_under_pointer,
9104 GDK_CROSSING_NORMAL,
9105 toplevel_x, toplevel_y,
9108 serial, non_linear);
9109 _gdk_display_set_window_under_pointer (display, pointer_window);
9111 else if (source_event->type == GDK_MOTION_NOTIFY)
9113 GdkWindow *event_win;
9117 event_win = get_event_window (display,
9127 (evmask & GDK_POINTER_MOTION_HINT_MASK))
9129 if (display->pointer_info.motion_hint_serial != 0 &&
9130 serial < display->pointer_info.motion_hint_serial)
9131 event_win = NULL; /* Ignore event */
9135 display->pointer_info.motion_hint_serial = G_MAXULONG;
9139 if (event_win && !display->ignore_core_events)
9141 event = _gdk_make_event (event_win, GDK_MOTION_NOTIFY, source_event, FALSE);
9142 event->motion.time = time_;
9143 convert_toplevel_coords_to_window (event_win,
9144 toplevel_x, toplevel_y,
9145 &event->motion.x, &event->motion.y);
9146 event->motion.x_root = source_event->motion.x_root;
9147 event->motion.y_root = source_event->motion.y_root;;
9148 event->motion.state = state;
9149 event->motion.is_hint = is_hint;
9150 event->motion.device = NULL;
9151 event->motion.device = source_event->motion.device;
9155 /* unlink all move events from queue.
9156 We handle our own, including our emulated masks. */
9160 #define GDK_ANY_BUTTON_MASK (GDK_BUTTON1_MASK | \
9161 GDK_BUTTON2_MASK | \
9162 GDK_BUTTON3_MASK | \
9163 GDK_BUTTON4_MASK | \
9167 proxy_button_event (GdkEvent *source_event,
9170 GdkWindow *toplevel_window, *event_window;
9171 GdkWindow *event_win;
9172 GdkWindow *pointer_window;
9173 GdkWindowObject *parent;
9178 gdouble toplevel_x, toplevel_y;
9179 GdkDisplay *display;
9182 type = source_event->any.type;
9183 event_window = source_event->any.window;
9184 gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
9185 gdk_event_get_state (source_event, &state);
9186 time_ = gdk_event_get_time (source_event);
9187 display = gdk_drawable_get_display (source_event->any.window);
9188 toplevel_window = convert_native_coords_to_toplevel (event_window,
9189 toplevel_x, toplevel_y,
9190 &toplevel_x, &toplevel_y);
9192 if (type == GDK_BUTTON_PRESS &&
9193 _gdk_display_has_pointer_grab (display, serial) == NULL)
9196 _gdk_window_find_descendant_at (toplevel_window,
9197 toplevel_x, toplevel_y,
9200 /* Find the event window, that gets the grab */
9201 w = (GdkWindowObject *)pointer_window;
9203 (parent = get_event_parent (w)) != NULL &&
9204 parent->window_type != GDK_WINDOW_ROOT)
9206 if (w->event_mask & GDK_BUTTON_PRESS_MASK)
9210 pointer_window = (GdkWindow *)w;
9212 _gdk_display_add_pointer_grab (display,
9216 gdk_window_get_events (pointer_window),
9220 _gdk_display_pointer_grab_update (display, serial);
9223 pointer_window = get_pointer_window (display, toplevel_window,
9224 toplevel_x, toplevel_y,
9227 event_win = get_event_window (display,
9232 if (event_win == NULL || display->ignore_core_events)
9235 event = _gdk_make_event (event_win, type, source_event, FALSE);
9239 case GDK_BUTTON_PRESS:
9240 case GDK_BUTTON_RELEASE:
9241 event->button.button = source_event->button.button;
9242 convert_toplevel_coords_to_window (event_win,
9243 toplevel_x, toplevel_y,
9244 &event->button.x, &event->button.y);
9245 event->button.x_root = source_event->button.x_root;
9246 event->button.y_root = source_event->button.y_root;
9247 event->button.state = state;
9248 event->button.device = source_event->button.device;
9250 if (type == GDK_BUTTON_PRESS)
9251 _gdk_event_button_generate (display, event);
9255 event->scroll.direction = source_event->scroll.direction;
9256 convert_toplevel_coords_to_window (event_win,
9257 toplevel_x, toplevel_y,
9258 &event->scroll.x, &event->scroll.y);
9259 event->scroll.x_root = source_event->scroll.x_root;
9260 event->scroll.y_root = source_event->scroll.y_root;
9261 event->scroll.state = state;
9262 event->scroll.device = source_event->scroll.device;
9269 return TRUE; /* Always unlink original, we want to obey the emulated event mask */
9272 #ifdef DEBUG_WINDOW_PRINTING
9274 gdk_window_print (GdkWindowObject *window,
9279 g_print ("%*s%p: [%s] %d,%d %dx%d", indent, "", window,
9280 window->user_data ? g_type_name_from_instance (window->user_data) : "no widget",
9281 window->x, window->y,
9282 window->width, window->height
9285 if (gdk_window_has_impl (window))
9287 #ifdef GDK_WINDOWING_X11
9288 g_print (" impl(0x%lx)", gdk_x11_drawable_get_xid (GDK_DRAWABLE (window)));
9292 if (window->input_only)
9293 g_print (" input-only");
9295 if (!gdk_window_is_visible ((GdkWindow *)window))
9296 g_print (" hidden");
9298 g_print (" abs[%d,%d]",
9299 window->abs_x, window->abs_y);
9301 gdk_region_get_clipbox (window->clip_region, &r);
9302 if (gdk_region_empty (window->clip_region))
9303 g_print (" clipbox[empty]");
9305 g_print (" clipbox[%d,%d %dx%d]", r.x, r.y, r.width, r.height);
9312 gdk_window_print_tree (GdkWindow *window,
9314 gboolean include_input_only)
9316 GdkWindowObject *private;
9319 private = (GdkWindowObject *)window;
9321 if (private->input_only && !include_input_only)
9324 gdk_window_print (private, indent);
9326 for (l = private->children; l != NULL; l = l->next)
9327 gdk_window_print_tree (l->data, indent + 4, include_input_only);
9330 #endif /* DEBUG_WINDOW_PRINTING */
9333 is_input_event (GdkDisplay *display,
9336 GdkDevice *core_pointer;
9338 core_pointer = gdk_display_get_core_pointer (display);
9339 if ((event->type == GDK_MOTION_NOTIFY &&
9340 event->motion.device != core_pointer) ||
9341 ((event->type == GDK_BUTTON_PRESS ||
9342 event->type == GDK_BUTTON_RELEASE) &&
9343 event->button.device != core_pointer))
9349 _gdk_windowing_got_event (GdkDisplay *display,
9354 GdkWindow *event_window;
9355 GdkWindowObject *event_private;
9357 gboolean unlink_event;
9358 guint old_state, old_button;
9359 GdkPointerGrabInfo *button_release_grab;
9360 gboolean is_toplevel;
9362 if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
9363 display->last_event_time = gdk_event_get_time (event);
9365 _gdk_display_pointer_grab_update (display,
9368 event_window = event->any.window;
9372 event_private = GDK_WINDOW_OBJECT (event_window);
9374 #ifdef DEBUG_WINDOW_PRINTING
9375 if (event->type == GDK_KEY_PRESS &&
9376 (event->key.keyval == 0xa7 ||
9377 event->key.keyval == 0xbd))
9379 gdk_window_print_tree (event_window, 0,
9380 event->key.keyval == 0xbd);
9384 if (event->type == GDK_VISIBILITY_NOTIFY)
9386 event_private->native_visibility = event->visibility.state;
9387 gdk_window_update_visibility_recursively (event_private,
9392 if (is_input_event (display, event))
9395 if (!(is_button_type (event->type) ||
9396 is_motion_type (event->type)) ||
9397 event_private->window_type == GDK_WINDOW_ROOT)
9401 event_private->parent == NULL ||
9402 event_private->parent->window_type == GDK_WINDOW_ROOT;
9404 if ((event->type == GDK_ENTER_NOTIFY ||
9405 event->type == GDK_LEAVE_NOTIFY) &&
9406 (event->crossing.mode == GDK_CROSSING_GRAB ||
9407 event->crossing.mode == GDK_CROSSING_UNGRAB) &&
9408 (_gdk_display_has_pointer_grab (display, serial) ||
9409 event->crossing.detail == GDK_NOTIFY_INFERIOR))
9411 /* We synthesize all crossing events due to grabs ourselves,
9412 * so we ignore the native ones caused by our native pointer_grab
9413 * calls. Otherwise we would proxy these crossing event and cause
9414 * multiple copies of crossing events for grabs.
9416 * We do want to handle grabs from other clients though, as for
9417 * instance alt-tab in metacity causes grabs like these and
9418 * we want to handle those. Thus the has_pointer_grab check.
9420 * Implicit grabs on child windows create some grabbing events
9421 * that are sent before the button press. This means we can't
9422 * detect these with the has_pointer_grab check (as the implicit
9423 * grab is only noticed when we get button press event), so we
9424 * detect these events by checking for INFERIOR enter or leave
9425 * events. These should never be a problem to filter out.
9428 /* We ended up in this window after some (perhaps other clients)
9429 grab, so update the toplevel_under_window state */
9431 event->type == GDK_ENTER_NOTIFY &&
9432 event->crossing.mode == GDK_CROSSING_UNGRAB)
9434 if (display->pointer_info.toplevel_under_pointer)
9435 g_object_unref (display->pointer_info.toplevel_under_pointer);
9436 display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
9439 unlink_event = TRUE;
9443 /* Track toplevel_under_pointer */
9446 if (event->type == GDK_ENTER_NOTIFY &&
9447 event->crossing.detail != GDK_NOTIFY_INFERIOR)
9449 if (display->pointer_info.toplevel_under_pointer)
9450 g_object_unref (display->pointer_info.toplevel_under_pointer);
9451 display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
9453 else if (event->type == GDK_LEAVE_NOTIFY &&
9454 event->crossing.detail != GDK_NOTIFY_INFERIOR &&
9455 display->pointer_info.toplevel_under_pointer == event_window)
9457 if (display->pointer_info.toplevel_under_pointer)
9458 g_object_unref (display->pointer_info.toplevel_under_pointer);
9459 display->pointer_info.toplevel_under_pointer = NULL;
9463 /* Store last pointer window and position/state */
9464 old_state = display->pointer_info.state;
9465 old_button = display->pointer_info.button;
9467 gdk_event_get_coords (event, &x, &y);
9468 convert_native_coords_to_toplevel (event_window, x, y, &x, &y);
9469 display->pointer_info.toplevel_x = x;
9470 display->pointer_info.toplevel_y = y;
9471 gdk_event_get_state (event, &display->pointer_info.state);
9472 if (event->type == GDK_BUTTON_PRESS ||
9473 event->type == GDK_BUTTON_RELEASE)
9474 display->pointer_info.button = event->button.button;
9476 if (display->pointer_info.state != old_state ||
9477 display->pointer_info.button != old_button)
9478 _gdk_display_enable_motion_hints (display);
9480 unlink_event = FALSE;
9481 if (is_motion_type (event->type))
9482 unlink_event = proxy_pointer_event (display,
9485 else if (is_button_type (event->type))
9486 unlink_event = proxy_button_event (event,
9489 if (event->type == GDK_BUTTON_RELEASE)
9491 button_release_grab =
9492 _gdk_display_has_pointer_grab (display, serial);
9493 if (button_release_grab &&
9494 button_release_grab->implicit &&
9495 (event->button.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
9497 button_release_grab->serial_end = serial;
9498 button_release_grab->implicit_ungrab = TRUE;
9499 _gdk_display_pointer_grab_update (display, serial);
9506 _gdk_event_queue_remove_link (display, event_link);
9507 g_list_free_1 (event_link);
9508 gdk_event_free (event);
9514 get_extension_event_window (GdkDisplay *display,
9515 GdkWindow *pointer_window,
9520 GdkWindow *grab_window;
9522 GdkPointerGrabInfo *grab;
9524 grab = _gdk_display_has_pointer_grab (display, serial);
9526 if (grab != NULL && !grab->owner_events)
9528 evmask = grab->event_mask;
9530 grab_window = grab->window;
9532 if (evmask & type_masks[type])
9538 w = (GdkWindowObject *)pointer_window;
9541 evmask = w->extension_events;
9543 if (evmask & type_masks[type])
9544 return (GdkWindow *)w;
9546 w = get_event_parent (w);
9552 evmask = grab->event_mask;
9554 if (evmask & type_masks[type])
9555 return grab->window;
9565 _gdk_window_get_input_window_for_event (GdkWindow *native_window,
9566 GdkEventType event_type,
9570 GdkDisplay *display;
9571 GdkWindow *toplevel_window;
9572 GdkWindow *pointer_window;
9573 GdkWindow *event_win;
9574 gdouble toplevel_x, toplevel_y;
9579 display = gdk_drawable_get_display (native_window);
9580 toplevel_window = convert_native_coords_to_toplevel (native_window,
9581 toplevel_x, toplevel_y,
9582 &toplevel_x, &toplevel_y);
9583 pointer_window = get_pointer_window (display, toplevel_window,
9584 toplevel_x, toplevel_y, serial);
9585 event_win = get_extension_event_window (display,
9594 #define __GDK_WINDOW_C__
9595 #include "gdkaliasdef.c"