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"
38 #undef DEBUG_WINDOW_PRINTING
40 #ifdef GDK_WINDOWING_X11
41 #include "x11/gdkx.h" /* For workaround */
46 /* Not all GdkWindows have a corresponding native window.
47 * Instead some draw into the nearest parent that has whatss
48 * called an "impl", i.e. the implementation window.
49 * For toplevel window system windows the impl is always native
50 * window, but child windows can also have native windows as
51 * this is sometimes necessary. Furthermore, offscreen windows
52 * (type GDK_WINDOW_OFFSCREEN) have an impl of type
53 * GdkOffscreenWindow rather than a backend implementation native
54 * window. Such windows draw into an offscreen pixmap instead
55 * of a window and collect damage that lets you paint it where
58 * All GdkWindow track their position, size, clip region and
59 * absolute position in the impl window. For child window with
60 * native windows the clip region is set on the native window
61 * as a window shape to make it clip against other non-native windows.
64 #define USE_BACKING_STORE /* Appears to work on Win32, too, now. */
66 struct _GdkWindowPaint
72 cairo_surface_t *surface;
73 guint uses_implicit : 1;
78 GdkRegion *region; /* The destination region */
80 } GdkWindowRegionMove;
85 static GdkGC *gdk_window_create_gc (GdkDrawable *drawable,
87 GdkGCValuesMask mask);
88 static void gdk_window_draw_rectangle (GdkDrawable *drawable,
95 static void gdk_window_draw_arc (GdkDrawable *drawable,
104 static void gdk_window_draw_polygon (GdkDrawable *drawable,
109 static void gdk_window_draw_text (GdkDrawable *drawable,
116 static void gdk_window_draw_text_wc (GdkDrawable *drawable,
121 const GdkWChar *text,
123 static void gdk_window_draw_drawable (GdkDrawable *drawable,
132 static void gdk_window_draw_points (GdkDrawable *drawable,
136 static void gdk_window_draw_segments (GdkDrawable *drawable,
140 static void gdk_window_draw_lines (GdkDrawable *drawable,
145 static void gdk_window_draw_glyphs (GdkDrawable *drawable,
150 PangoGlyphString *glyphs);
151 static void gdk_window_draw_glyphs_transformed (GdkDrawable *drawable,
157 PangoGlyphString *glyphs);
159 static void gdk_window_draw_image (GdkDrawable *drawable,
169 static void gdk_window_draw_pixbuf (GdkDrawable *drawable,
182 static void gdk_window_draw_trapezoids (GdkDrawable *drawable,
184 GdkTrapezoid *trapezoids,
187 static GdkImage* gdk_window_copy_to_image (GdkDrawable *drawable,
196 static cairo_surface_t *gdk_window_ref_cairo_surface (GdkDrawable *drawable);
197 static cairo_surface_t *gdk_window_create_cairo_surface (GdkDrawable *drawable,
200 static void gdk_window_set_cairo_clip (GdkDrawable *drawable,
203 static void gdk_window_real_get_size (GdkDrawable *drawable,
207 static GdkVisual* gdk_window_real_get_visual (GdkDrawable *drawable);
208 static gint gdk_window_real_get_depth (GdkDrawable *drawable);
209 static GdkScreen* gdk_window_real_get_screen (GdkDrawable *drawable);
210 static void gdk_window_real_set_colormap (GdkDrawable *drawable,
212 static GdkColormap* gdk_window_real_get_colormap (GdkDrawable *drawable);
214 static GdkDrawable* gdk_window_get_source_drawable (GdkDrawable *drawable);
215 static GdkDrawable* gdk_window_get_composite_drawable (GdkDrawable *drawable,
220 gint *composite_x_offset,
221 gint *composite_y_offset);
222 static GdkRegion* gdk_window_get_clip_region (GdkDrawable *drawable);
223 static GdkRegion* gdk_window_get_visible_region (GdkDrawable *drawable);
225 static void gdk_window_free_paint_stack (GdkWindow *window);
227 static void gdk_window_init (GdkWindowObject *window);
228 static void gdk_window_class_init (GdkWindowObjectClass *klass);
229 static void gdk_window_finalize (GObject *object);
230 static void gdk_window_clear_backing_rect (GdkWindow *window,
235 static void gdk_window_redirect_free (GdkWindowRedirect *redirect);
236 static void apply_redirect_to_children (GdkWindowObject *private,
237 GdkWindowRedirect *redirect);
238 static void remove_redirect_from_children (GdkWindowObject *private,
239 GdkWindowRedirect *redirect);
241 static void recompute_visible_regions (GdkWindowObject *private,
242 gboolean recalculate_siblings,
243 gboolean recalculate_children);
244 static void gdk_window_flush_outstanding_moves (GdkWindow *window);
245 static void gdk_window_flush (GdkWindow *window);
246 static void gdk_window_flush_recursive (GdkWindowObject *window);
247 static void do_move_region_bits_on_impl (GdkWindowObject *private,
249 int dest_off_x, int dest_off_y,
250 GdkRegion *region, /* In impl window coords */
252 static void gdk_window_invalidate_in_parent (GdkWindowObject *private);
253 static void move_native_children (GdkWindowObject *private);
255 static gpointer parent_class = NULL;
257 static const cairo_user_data_key_t gdk_window_cairo_key;
260 new_region_tag (void)
262 static guint32 tag = 0;
268 gdk_window_object_get_type (void)
270 static GType object_type = 0;
273 object_type = g_type_register_static_simple (GDK_TYPE_DRAWABLE,
275 sizeof (GdkWindowObjectClass),
276 (GClassInitFunc) gdk_window_class_init,
277 sizeof (GdkWindowObject),
278 (GInstanceInitFunc) gdk_window_init,
285 _gdk_paintable_get_type (void)
287 static GType paintable_type = 0;
291 const GTypeInfo paintable_info =
293 sizeof (GdkPaintableIface), /* class_size */
294 NULL, /* base_init */
295 NULL, /* base_finalize */
298 paintable_type = g_type_register_static (G_TYPE_INTERFACE,
299 g_intern_static_string ("GdkPaintable"),
302 g_type_interface_add_prerequisite (paintable_type, G_TYPE_OBJECT);
305 return paintable_type;
309 gdk_window_init (GdkWindowObject *window)
311 /* 0-initialization is good for all other fields. */
313 window->window_type = GDK_WINDOW_CHILD;
315 window->state = GDK_WINDOW_STATE_WITHDRAWN;
318 window->toplevel_window_type = -1;
321 static GQuark quark_pointer_window = 0;
324 gdk_window_class_init (GdkWindowObjectClass *klass)
326 GObjectClass *object_class = G_OBJECT_CLASS (klass);
327 GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
329 parent_class = g_type_class_peek_parent (klass);
331 object_class->finalize = gdk_window_finalize;
333 drawable_class->create_gc = gdk_window_create_gc;
334 drawable_class->draw_rectangle = gdk_window_draw_rectangle;
335 drawable_class->draw_arc = gdk_window_draw_arc;
336 drawable_class->draw_polygon = gdk_window_draw_polygon;
337 drawable_class->draw_text = gdk_window_draw_text;
338 drawable_class->draw_text_wc = gdk_window_draw_text_wc;
339 drawable_class->draw_drawable = gdk_window_draw_drawable;
340 drawable_class->draw_points = gdk_window_draw_points;
341 drawable_class->draw_segments = gdk_window_draw_segments;
342 drawable_class->draw_lines = gdk_window_draw_lines;
343 drawable_class->draw_glyphs = gdk_window_draw_glyphs;
344 drawable_class->draw_glyphs_transformed = gdk_window_draw_glyphs_transformed;
345 drawable_class->draw_image = gdk_window_draw_image;
346 drawable_class->draw_pixbuf = gdk_window_draw_pixbuf;
347 drawable_class->draw_trapezoids = gdk_window_draw_trapezoids;
348 drawable_class->get_depth = gdk_window_real_get_depth;
349 drawable_class->get_screen = gdk_window_real_get_screen;
350 drawable_class->get_size = gdk_window_real_get_size;
351 drawable_class->set_colormap = gdk_window_real_set_colormap;
352 drawable_class->get_colormap = gdk_window_real_get_colormap;
353 drawable_class->get_visual = gdk_window_real_get_visual;
354 drawable_class->_copy_to_image = gdk_window_copy_to_image;
355 drawable_class->ref_cairo_surface = gdk_window_ref_cairo_surface;
356 drawable_class->create_cairo_surface = gdk_window_create_cairo_surface;
357 drawable_class->set_cairo_clip = gdk_window_set_cairo_clip;
358 drawable_class->get_clip_region = gdk_window_get_clip_region;
359 drawable_class->get_visible_region = gdk_window_get_visible_region;
360 drawable_class->get_composite_drawable = gdk_window_get_composite_drawable;
361 drawable_class->get_source_drawable = gdk_window_get_source_drawable;
363 quark_pointer_window = g_quark_from_static_string ("gtk-pointer-window");
367 gdk_window_finalize (GObject *object)
369 GdkWindow *window = GDK_WINDOW (object);
370 GdkWindowObject *obj = (GdkWindowObject *) object;
372 if (!GDK_WINDOW_DESTROYED (window))
374 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
376 g_warning ("losing last reference to undestroyed window\n");
377 _gdk_window_destroy (window, FALSE);
380 /* We use TRUE here, to keep us from actually calling
381 * XDestroyWindow() on the window
383 _gdk_window_destroy (window, TRUE);
388 g_object_unref (obj->impl);
393 gdk_region_destroy (obj->shape);
395 if (obj->input_shape)
396 gdk_region_destroy (obj->input_shape);
399 gdk_cursor_unref (obj->cursor);
401 G_OBJECT_CLASS (parent_class)->finalize (object);
405 gdk_window_is_offscreen (GdkWindowObject *window)
407 return GDK_WINDOW_TYPE (window) == GDK_WINDOW_OFFSCREEN;
410 static GdkWindowObject *
411 gdk_window_get_impl_window (GdkWindowObject *window)
413 while (window->parent != NULL && window->parent->impl == window->impl)
414 window = window->parent;
420 _gdk_window_get_impl_window (GdkWindow *window)
422 return (GdkWindow *)gdk_window_get_impl_window ((GdkWindowObject *)window);
426 gdk_window_has_impl (GdkWindowObject *window)
428 return window->parent == NULL || window->parent->impl != window->impl;
432 _gdk_window_has_impl (GdkWindow *window)
434 return gdk_window_has_impl ((GdkWindowObject *)window);
438 gdk_window_has_no_impl (GdkWindowObject *window)
440 return window->parent->impl == window->impl;
444 remove_child_area (GdkWindowObject *private,
445 GdkWindowObject *until,
449 GdkWindowObject *child;
450 GdkRegion *child_region;
455 for (l = private->children; l; l = l->next)
462 if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
465 /* Ignore offscreen children, as they don't draw in their parent and
466 * don't take part in the clipping */
467 if (gdk_window_is_offscreen (child))
472 r.width = child->width;
473 r.height = child->height;
475 child_region = gdk_region_rectangle (&r);
478 gdk_region_intersect (child_region, child->shape);
479 else if (private->window_type == GDK_WINDOW_FOREIGN)
481 shape = _gdk_windowing_window_get_shape ((GdkWindow *)child);
484 gdk_region_intersect (child_region, shape);
485 gdk_region_destroy (shape);
491 if (child->input_shape)
492 gdk_region_intersect (child_region, child->input_shape);
493 else if (private->window_type == GDK_WINDOW_FOREIGN)
495 shape = _gdk_windowing_window_get_input_shape ((GdkWindow *)child);
498 gdk_region_intersect (child_region, shape);
499 gdk_region_destroy (shape);
504 gdk_region_subtract (region, child_region);
505 gdk_region_destroy (child_region);
511 recompute_visible_regions_internal (GdkWindowObject *private,
512 gboolean recalculate_clip,
513 gboolean recalculate_siblings,
514 gboolean recalculate_children)
518 GdkWindowObject *child;
519 GdkRegion *new_clip, *old_clip_region_with_children;
520 gboolean clip_region_changed;
521 gboolean abs_pos_changed;
522 int old_abs_x, old_abs_y;
524 old_abs_x = private->abs_x;
525 old_abs_y = private->abs_y;
527 /* Update absolute position */
528 if (gdk_window_has_impl (private))
530 /* Native window starts here */
536 private->abs_x = private->parent->abs_x + private->x;
537 private->abs_y = private->parent->abs_y + private->y;
541 private->abs_x != old_abs_x ||
542 private->abs_y != old_abs_y;
544 /* Update clip region based on:
547 * siblings in parents above window
549 clip_region_changed = FALSE;
550 if (recalculate_clip)
552 /* Calculate visible region (sans children) in parent window coords */
555 r.width = private->width;
556 r.height = private->height;
557 new_clip = gdk_region_rectangle (&r);
559 if (private->parent != NULL && GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
561 gdk_region_intersect (new_clip, private->parent->clip_region);
563 /* Remove all overlapping children from parent */
564 remove_child_area (private->parent, private, FALSE, new_clip);
567 /* Convert from parent coords to window coords */
568 gdk_region_offset (new_clip, -private->x, -private->y);
571 gdk_region_intersect (new_clip, private->shape);
573 if (private->clip_region == NULL ||
574 !gdk_region_equal (private->clip_region, new_clip))
575 clip_region_changed = TRUE;
577 if (private->clip_region)
578 gdk_region_destroy (private->clip_region);
579 private->clip_region = new_clip;
581 old_clip_region_with_children = private->clip_region_with_children;
582 private->clip_region_with_children = gdk_region_copy (private->clip_region);
583 remove_child_area (private, NULL, FALSE, private->clip_region_with_children);
585 if (clip_region_changed ||
586 !gdk_region_equal (private->clip_region_with_children, old_clip_region_with_children))
587 private->clip_tag = new_region_tag ();
589 if (old_clip_region_with_children)
590 gdk_region_destroy (old_clip_region_with_children);
593 /* Update all children, recursively. */
594 if (abs_pos_changed || clip_region_changed || recalculate_children)
596 for (l = private->children; l; l = l->next)
599 /* Only recalculate clip if the the clip region changed, otherwise
600 * there is no way the child clip region could change (its has not e.g. moved)
601 * Except if recalculate_children is set to force child updates
603 recompute_visible_regions_internal (child, recalculate_clip && (clip_region_changed || recalculate_children), FALSE, FALSE);
607 if (clip_region_changed &&
608 gdk_window_has_impl (private) &&
609 /* Not for offscreens */
610 private->window_type != GDK_WINDOW_OFFSCREEN &&
611 /* or for non-shaped toplevels */
613 (private->parent != NULL &&
614 GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)) &&
615 /* or for foreign windows */
616 GDK_WINDOW_TYPE (private) != GDK_WINDOW_FOREIGN
619 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region ((GdkWindow *)private, private->clip_region, 0, 0);
622 if (recalculate_siblings &&
623 private->parent != NULL &&
624 GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
626 /* If we moved a child window in parent or changed the stacking order, then we
627 * need to recompute the visible area of all the other children in the parent
629 for (l = private->parent->children; l; l = l->next)
633 if (child != private)
634 recompute_visible_regions_internal (child, TRUE, FALSE, FALSE);
637 /* We also need to recompute the _with_children clip for the parent */
638 recompute_visible_regions_internal (private->parent, TRUE, FALSE, FALSE);
641 if (private->cairo_surface)
645 /* It would be nice if we had some cairo support here so we
646 could set the clip rect on the cairo surface */
647 width = private->abs_x + private->width;
648 height = private->abs_y + private->height;
650 _gdk_windowing_set_cairo_surface_size (private->cairo_surface,
652 cairo_surface_set_device_offset (private->cairo_surface,
658 /* Call this when private has changed in one or more of these ways:
662 * stacking order of window changed
665 * It will recalculate abs_x/y and the clip regions
667 * Unless the window didn't change stacking order or size/pos, pass in TRUE
668 * for recalculate_siblings. (Mostly used internally for the recursion)
670 * If a child window was removed (and you can't use that child for
671 * recompute_visible_regions), pass in TRUE for recalculate_children on the parent
674 recompute_visible_regions (GdkWindowObject *private,
675 gboolean recalculate_siblings,
676 gboolean recalculate_children)
678 recompute_visible_regions_internal (private,
680 recalculate_siblings,
681 recalculate_children);
685 _gdk_window_update_size (GdkWindow *window)
687 recompute_visible_regions ((GdkWindowObject *)window, TRUE, FALSE);
690 /* Find the native window that would be just above "child"
691 * in the native stacking order if "child" was a native window
692 * (it doesn't have to be native). If there is no such native
693 * window inside this native parent then NULL is returned.
694 * If child is NULL, find lowest native window in parent.
696 static GdkWindowObject *
697 find_native_sibling_above_helper (GdkWindowObject *parent,
698 GdkWindowObject *child)
705 l = g_list_find (parent->children, child);
706 g_assert (l != NULL); /* Better be a child of its parent... */
707 l = l->prev; /* Start looking at the one above the child */
710 l = g_list_last (parent->children);
712 for (; l != NULL; l = l->prev)
716 if (gdk_window_has_impl (w))
719 g_assert (parent != w);
720 w = find_native_sibling_above_helper (w, NULL);
729 static GdkWindowObject *
730 find_native_sibling_above (GdkWindowObject *parent,
731 GdkWindowObject *child)
735 w = find_native_sibling_above_helper (parent, child);
739 if (gdk_window_has_impl (parent))
742 return find_native_sibling_above (parent->parent, parent);
746 get_native_event_mask (GdkWindowObject *private)
748 if (GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
751 GDK_POINTER_MOTION_MASK |
752 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
753 GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK |
754 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
755 GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK |
756 GDK_PROXIMITY_IN_MASK | GDK_PROXIMITY_OUT_MASK | GDK_SCROLL_MASK;
758 return GDK_EXPOSURE_MASK;
763 * @parent: a #GdkWindow, or %NULL to create the window as a child of
764 * the default root window for the default display.
765 * @attributes: attributes of the new window
766 * @attributes_mask: mask indicating which fields in @attributes are valid
768 * Creates a new #GdkWindow using the attributes from
769 * @attributes. See #GdkWindowAttr and #GdkWindowAttributesType for
770 * more details. Note: to use this on displays other than the default
771 * display, @parent must be specified.
773 * Return value: the new #GdkWindow
776 gdk_window_new (GdkWindow *parent,
777 GdkWindowAttr *attributes,
778 gint attributes_mask)
781 GdkWindowObject *private;
786 GdkEventMask event_mask;
787 GdkWindow *real_parent;
789 g_return_val_if_fail (attributes != NULL, NULL);
794 g_warning ("gdk_window_new(): no parent specified reverting to parent = default root window"));
796 screen = gdk_screen_get_default ();
797 parent = gdk_screen_get_root_window (screen);
800 screen = gdk_drawable_get_screen (parent);
802 g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
804 if (GDK_WINDOW_DESTROYED (parent))
807 window = g_object_new (GDK_TYPE_WINDOW, NULL);
808 private = (GdkWindowObject *) window;
810 /* Windows with a foreign parent are treated as if they are children
811 * of the root window, except for actual creation.
813 real_parent = parent;
814 if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
815 parent = gdk_screen_get_root_window (screen);
817 private->parent = (GdkWindowObject *)parent;
819 private->accept_focus = TRUE;
820 private->focus_on_map = TRUE;
822 if (attributes_mask & GDK_WA_X)
827 if (attributes_mask & GDK_WA_Y)
834 private->width = (attributes->width > 1) ? (attributes->width) : (1);
835 private->height = (attributes->height > 1) ? (attributes->height) : (1);
837 #ifdef GDK_WINDOWING_X11
838 /* Work around a bug where Xorg refuses to map toplevel InputOnly windows
839 * from an untrusted client: http://bugs.freedesktop.org/show_bug.cgi?id=6988
841 if (attributes->wclass == GDK_INPUT_ONLY &&
842 GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT &&
843 !G_LIKELY (GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (parent))->trusted_client))
845 g_warning ("Coercing GDK_INPUT_ONLY toplevel window to GDK_INPUT_OUTPUT to work around bug in Xorg server");
846 attributes->wclass = GDK_INPUT_OUTPUT;
850 if (attributes->wclass == GDK_INPUT_ONLY)
852 /* Backwards compatiblity - we've always ignored
853 * attributes->window_type for input-only windows
856 if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
857 private->window_type = GDK_WINDOW_TEMP;
859 private->window_type = GDK_WINDOW_CHILD;
862 private->window_type = attributes->window_type;
865 switch (private->window_type)
867 case GDK_WINDOW_TOPLEVEL:
868 case GDK_WINDOW_DIALOG:
869 case GDK_WINDOW_TEMP:
870 if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
871 g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
872 "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
873 case GDK_WINDOW_CHILD:
874 case GDK_WINDOW_OFFSCREEN:
877 g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
881 if (attributes_mask & GDK_WA_VISUAL)
882 visual = attributes->visual;
884 visual = gdk_screen_get_system_visual (screen);
886 private->event_mask = attributes->event_mask;
888 if (attributes->wclass == GDK_INPUT_OUTPUT)
890 private->input_only = FALSE;
891 private->depth = visual->depth;
893 private->bg_color.pixel = 0; // TODO: BlackPixel (xdisplay, screen_x11->screen_num);
894 private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
896 private->bg_pixmap = NULL;
901 private->input_only = TRUE;
905 private->parent->children = g_list_prepend (private->parent->children, window);
907 native = FALSE; /* Default */
908 if (GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
909 native = TRUE; /* Always use native windows for toplevels */
910 else if (!private->input_only &&
911 ((attributes_mask & GDK_WA_COLORMAP &&
912 attributes->colormap != gdk_drawable_get_colormap ((GdkDrawable *)private->parent)) ||
913 (attributes_mask & GDK_WA_VISUAL &&
914 attributes->visual != gdk_drawable_get_visual ((GdkDrawable *)private->parent))))
915 native = TRUE; /* InputOutput window with different colormap or visual than parent, needs native window */
917 if (private->window_type == GDK_WINDOW_OFFSCREEN)
919 _gdk_offscreen_window_new (window, screen, visual, attributes, attributes_mask);
923 GdkWindowObject *above;
924 GList listhead = {0};
926 event_mask = get_native_event_mask (private);
928 /* Create the impl */
929 _gdk_window_impl_new (window, real_parent, screen, visual, event_mask, attributes, attributes_mask);
931 /* This will put the native window topmost in the native parent, which may
932 * be wrong wrt other native windows in the non-native hierarchy, so restack */
933 above = find_native_sibling_above (private->parent, private);
936 listhead.data = window;
937 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
944 private->impl = g_object_ref (private->parent->impl);
947 recompute_visible_regions (private, TRUE, FALSE);
949 if (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
951 /* Inherit redirection from parent */
952 private->redirect = private->parent->redirect;
955 gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
956 (attributes->cursor) :
963 is_parent_of (GdkWindow *parent,
974 w = gdk_window_get_parent (w);
981 change_impl (GdkWindowObject *private,
985 GdkWindowObject *child;
986 GdkDrawable *old_impl;
988 old_impl = private->impl;
989 private->impl = g_object_ref (new);
990 g_object_unref (old_impl);
992 for (l = private->children; l != NULL; l = l->next)
996 if (child->impl == old_impl)
997 change_impl (child, new);
1002 reparent_to_impl (GdkWindowObject *private)
1005 GdkWindowObject *child;
1008 /* Enumerate in reverse order so we get the right order for the native
1009 windows (first in childrens list is topmost, and reparent places on top) */
1010 for (l = g_list_last (private->children); l != NULL; l = l->prev)
1014 if (child->impl == private->impl)
1015 reparent_to_impl (child);
1018 show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent ((GdkWindow *)child,
1019 (GdkWindow *)private,
1020 child->x, child->y);
1022 gdk_window_show_unraised ((GdkWindow *)child);
1029 * gdk_window_reparent:
1030 * @window: a #GdkWindow
1031 * @new_parent: new parent to move @window into
1032 * @x: X location inside the new parent
1033 * @y: Y location inside the new parent
1035 * Reparents @window into the given @new_parent. The window being
1036 * reparented will be unmapped as a side effect.
1040 gdk_window_reparent (GdkWindow *window,
1041 GdkWindow *new_parent,
1045 GdkWindowObject *private;
1046 GdkWindowObject *new_parent_private;
1047 GdkWindowObject *old_parent;
1048 gboolean show, was_toplevel, was_mapped;
1049 gboolean do_reparent_to_impl;
1051 g_return_if_fail (GDK_IS_WINDOW (window));
1052 g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
1053 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
1055 if (GDK_WINDOW_DESTROYED (window) ||
1056 (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
1060 new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
1062 private = (GdkWindowObject *) window;
1063 new_parent_private = (GdkWindowObject *)new_parent;
1065 /* No input-output children of input-only windows */
1066 if (new_parent_private->input_only && !private->input_only)
1069 /* Don't create loops in hierarchy */
1070 if (is_parent_of (window, new_parent))
1073 if (private->cairo_surface)
1075 /* This might be wrong in the new parent, e.g. for non-native surfaces.
1076 To make sure we're ok, just wipe it. */
1077 cairo_surface_finish (private->cairo_surface);
1078 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
1082 old_parent = private->parent;
1084 /* Break up redirection if inherited */
1085 if (private->redirect && private->redirect->redirected != private)
1087 remove_redirect_from_children (private, private->redirect);
1088 private->redirect = NULL;
1091 was_toplevel = private->parent == NULL;
1092 was_mapped = GDK_WINDOW_IS_MAPPED (window);
1095 /* Reparenting to toplevel. Ensure we have a native window so this can work */
1096 if (new_parent_private->window_type == GDK_WINDOW_ROOT ||
1097 new_parent_private->window_type == GDK_WINDOW_FOREIGN)
1098 gdk_window_set_has_native (window, TRUE);
1100 do_reparent_to_impl = FALSE;
1101 if (gdk_window_has_impl (private))
1104 show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent (window, new_parent, x, y);
1108 /* This shouldn't happen, as we created a native in this case, check anyway to see if that ever fails */
1109 g_assert (new_parent_private->window_type != GDK_WINDOW_ROOT &&
1110 new_parent_private->window_type != GDK_WINDOW_FOREIGN);
1113 gdk_window_hide (window);
1115 do_reparent_to_impl = TRUE;
1116 change_impl (private, new_parent_private->impl);
1119 /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
1122 if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1124 new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
1125 new_parent_private = (GdkWindowObject *)new_parent;
1128 if (private->parent)
1129 private->parent->children = g_list_remove (private->parent->children, window);
1131 private->parent = new_parent_private;
1135 new_parent_private->children = g_list_prepend (new_parent_private->children, window);
1137 /* Switch the window type as appropriate */
1139 switch (GDK_WINDOW_TYPE (new_parent))
1141 case GDK_WINDOW_ROOT:
1142 case GDK_WINDOW_FOREIGN:
1143 if (private->toplevel_window_type != -1)
1144 GDK_WINDOW_TYPE (window) = private->toplevel_window_type;
1145 else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1146 GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
1148 case GDK_WINDOW_OFFSCREEN:
1149 case GDK_WINDOW_TOPLEVEL:
1150 case GDK_WINDOW_CHILD:
1151 case GDK_WINDOW_DIALOG:
1152 case GDK_WINDOW_TEMP:
1153 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
1154 GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
1156 /* Save the original window type so we can restore it if the
1157 * window is reparented back to be a toplevel
1159 private->toplevel_window_type = GDK_WINDOW_TYPE (window);
1160 GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
1164 /* We might have changed window type for a native windows, so we
1165 need to change the event mask too. */
1166 if (gdk_window_has_impl (private))
1167 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_events (window, get_native_event_mask (private));
1169 /* Inherit parent redirect if we don't have our own */
1170 if (private->parent && private->redirect == NULL)
1172 private->redirect = private->parent->redirect;
1173 apply_redirect_to_children (private, private->redirect);
1176 recompute_visible_regions (private, TRUE, FALSE);
1177 if (old_parent && GDK_WINDOW_TYPE (old_parent) != GDK_WINDOW_ROOT)
1178 recompute_visible_regions (old_parent, FALSE, TRUE);
1180 if (do_reparent_to_impl)
1181 reparent_to_impl (private);
1184 GdkWindowObject *above;
1185 GList listhead = {0};
1187 /* The reparent will have put the native window topmost in the native parent,
1188 * which may be wrong wrt other native windows in the non-native hierarchy,
1190 above = find_native_sibling_above (private->parent, private);
1193 listhead.data = window;
1194 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
1200 gdk_window_show_unraised (window);
1202 _gdk_syntesize_crossing_events_for_geometry_change (window);
1206 * gdk_window_set_has_native:
1207 * @window: a #GdkWindow
1208 * @has_native: whethe the window should have a native window
1210 * Tries to create or remove a window-system native window for this
1211 * GdkWindow. This may fail in some situations. For instance:
1213 * Toplevel and foreign windows must have a native window.
1214 * Offscreen window and children of them can never have native windows.
1215 * Some backends may not support native child windows.
1219 gdk_window_set_has_native (GdkWindow *window, gboolean has_native)
1221 GdkWindowObject *private;
1222 GdkWindowObject *impl_window;
1223 GdkDrawable *new_impl, *old_impl;
1226 GdkWindowAttr attributes;
1227 GdkWindowObject *above;
1230 g_return_if_fail (GDK_IS_WINDOW (window));
1232 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT ||
1233 GDK_WINDOW_DESTROYED (window))
1236 private = (GdkWindowObject *) window;
1240 /* Create native window */
1242 if (gdk_window_has_impl (private))
1243 /* Already has an impl, either native (ok) or
1244 offscreen (not supported). Bail. */
1247 impl_window = gdk_window_get_impl_window (private);
1248 if (impl_window->window_type == GDK_WINDOW_OFFSCREEN)
1249 return; /* native in offscreens not supported */
1251 screen = gdk_drawable_get_screen (window);
1252 visual = gdk_drawable_get_visual (window);
1254 attributes.colormap = gdk_drawable_get_colormap (window);
1256 old_impl = private->impl;
1257 _gdk_window_impl_new (window, (GdkWindow *)private->parent, screen, visual,
1258 get_native_event_mask (private), &attributes, GDK_WA_COLORMAP);
1259 new_impl = private->impl;
1261 private->impl = old_impl;
1262 change_impl (private, new_impl);
1264 /* Native window creation will put the native window topmost in the
1265 * native parent, which may be wrong wrt other native windows in the
1266 * non-native hierarchy, so restack */
1267 above = find_native_sibling_above (private->parent, private);
1270 listhead.data = window;
1271 listhead.prev = NULL;
1272 listhead.next = NULL;
1273 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
1277 recompute_visible_regions (private, FALSE, FALSE);
1279 /* The shape may not have been set, as the clip region doesn't actually
1280 change, so do it here manually */
1281 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region ((GdkWindow *)private, private->clip_region, 0, 0);
1283 reparent_to_impl (private);
1285 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, &private->bg_color);
1286 if (private->bg_pixmap != NULL)
1287 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, private->bg_pixmap);
1289 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_shape_combine_region ((GdkWindow *)private, private->input_shape, 0, 0);
1291 if (gdk_window_is_viewable (window))
1292 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show (window);
1296 /* Remove native window */
1298 if (!gdk_window_has_impl (private))
1299 return; /* Not native, can't remove */
1301 if (private->window_type == GDK_WINDOW_OFFSCREEN)
1302 return; /* Not native, can't remove */
1304 if (private->parent == NULL ||
1305 GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
1306 return; /* toplevel, must be native */
1308 g_warning ("Tried to turn native window to client side window, this is not supported yet.");
1310 /* TODO: remove native */
1315 window_remove_filters (GdkWindow *window)
1317 GdkWindowObject *obj = (GdkWindowObject*) window;
1323 for (tmp_list = obj->filters; tmp_list; tmp_list = tmp_list->next)
1324 g_free (tmp_list->data);
1326 g_list_free (obj->filters);
1327 obj->filters = NULL;
1332 * _gdk_window_destroy_hierarchy:
1333 * @window: a #GdkWindow
1334 * @recursing: If TRUE, then this is being called because a parent
1335 * was destroyed. This generally means that the call to the
1336 * windowing system to destroy the window can be omitted, since
1337 * it will be destroyed as a result of the parent being destroyed.
1338 * Unless @foreign_destroy.
1339 * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
1340 * external agency. The window has already been destroyed and no
1341 * windowing system calls should be made. (This may never happen
1342 * for some windowing systems.)
1344 * Internal function to destroy a window. Like gdk_window_destroy(),
1345 * but does not drop the reference count created by gdk_window_new().
1348 _gdk_window_destroy_hierarchy (GdkWindow *window,
1350 gboolean foreign_destroy)
1352 GdkWindowObject *private;
1353 GdkWindowObject *temp_private;
1354 GdkWindow *temp_window;
1356 GdkDisplay *display;
1360 g_return_if_fail (GDK_IS_WINDOW (window));
1362 private = (GdkWindowObject*) window;
1364 if (GDK_WINDOW_DESTROYED (window))
1367 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
1368 screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
1369 temp_window = g_object_get_qdata (G_OBJECT (screen), quark_pointer_window);
1370 if (temp_window == window)
1371 g_object_set_qdata (G_OBJECT (screen), quark_pointer_window, NULL);
1374 switch (GDK_WINDOW_TYPE (window))
1376 case GDK_WINDOW_ROOT:
1377 if (!screen->closed)
1379 g_error ("attempted to destroy root window");
1382 /* else fall thru */
1383 case GDK_WINDOW_TOPLEVEL:
1384 case GDK_WINDOW_CHILD:
1385 case GDK_WINDOW_DIALOG:
1386 case GDK_WINDOW_TEMP:
1387 case GDK_WINDOW_FOREIGN:
1388 case GDK_WINDOW_OFFSCREEN:
1389 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN && !foreign_destroy)
1391 /* Logically, it probably makes more sense to send
1392 * a "destroy yourself" message to the foreign window
1393 * whether or not it's in our hierarchy; but for historical
1394 * reasons, we only send "destroy yourself" messages to
1395 * foreign windows in our hierarchy.
1397 if (private->parent)
1398 _gdk_windowing_window_destroy_foreign (window);
1400 /* Also for historical reasons, we remove any filters
1401 * on a foreign window when it or a parent is destroyed;
1402 * this likely causes problems if two separate portions
1403 * of code are maintaining filter lists on a foreign window.
1405 window_remove_filters (window);
1409 if (private->parent)
1411 GdkWindowObject *parent_private = (GdkWindowObject *)private->parent;
1413 if (parent_private->children)
1414 parent_private->children = g_list_remove (parent_private->children, window);
1417 GDK_WINDOW_IS_MAPPED (window))
1419 recompute_visible_regions (private, TRUE, FALSE);
1420 gdk_window_invalidate_in_parent (private);
1424 gdk_window_free_paint_stack (window);
1426 if (private->bg_pixmap &&
1427 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
1428 private->bg_pixmap != GDK_NO_BG)
1430 g_object_unref (private->bg_pixmap);
1431 private->bg_pixmap = NULL;
1434 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN)
1435 g_assert (private->children == NULL);
1438 children = tmp = private->children;
1439 private->children = NULL;
1443 temp_window = tmp->data;
1446 temp_private = (GdkWindowObject*) temp_window;
1448 _gdk_window_destroy_hierarchy (temp_window,
1449 TRUE, foreign_destroy);
1452 g_list_free (children);
1455 _gdk_window_clear_update_area (window);
1457 if (private->cairo_surface)
1459 cairo_surface_finish (private->cairo_surface);
1460 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
1464 if (gdk_window_has_impl (private))
1466 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->destroy (window, recursing, foreign_destroy);
1470 /* hide to make sure we repaint and break grabs */
1471 gdk_window_hide (window);
1474 private->state |= GDK_WINDOW_STATE_WITHDRAWN;
1475 private->parent = NULL;
1476 private->destroyed = TRUE;
1478 window_remove_filters (window);
1480 gdk_drawable_set_colormap (GDK_DRAWABLE (window), NULL);
1482 /* If we own the redirect, free it */
1483 if (private->redirect && private->redirect->redirected == private)
1484 gdk_window_redirect_free (private->redirect);
1486 private->redirect = NULL;
1488 if (display->pointer_info.toplevel_under_pointer == window)
1490 g_object_unref (display->pointer_info.toplevel_under_pointer);
1491 display->pointer_info.toplevel_under_pointer = NULL;
1499 * _gdk_window_destroy:
1500 * @window: a #GdkWindow
1501 * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
1502 * external agency. The window has already been destroyed and no
1503 * windowing system calls should be made. (This may never happen
1504 * for some windowing systems.)
1506 * Internal function to destroy a window. Like gdk_window_destroy(),
1507 * but does not drop the reference count created by gdk_window_new().
1510 _gdk_window_destroy (GdkWindow *window,
1511 gboolean foreign_destroy)
1513 _gdk_window_destroy_hierarchy (window, FALSE, foreign_destroy);
1517 * gdk_window_destroy:
1518 * @window: a #GdkWindow
1520 * Destroys the window system resources associated with @window and decrements @window's
1521 * reference count. The window system resources for all children of @window are also
1522 * destroyed, but the children's reference counts are not decremented.
1524 * Note that a window will not be destroyed automatically when its reference count
1525 * reaches zero. You must call this function yourself before that happens.
1529 gdk_window_destroy (GdkWindow *window)
1531 _gdk_window_destroy_hierarchy (window, FALSE, FALSE);
1532 g_object_unref (window);
1536 * gdk_window_set_user_data:
1537 * @window: a #GdkWindow
1538 * @user_data: user data
1540 * For most purposes this function is deprecated in favor of
1541 * g_object_set_data(). However, for historical reasons GTK+ stores
1542 * the #GtkWidget that owns a #GdkWindow as user data on the
1543 * #GdkWindow. So, custom widget implementations should use
1544 * this function for that. If GTK+ receives an event for a #GdkWindow,
1545 * and the user data for the window is non-%NULL, GTK+ will assume the
1546 * user data is a #GtkWidget, and forward the event to that widget.
1550 gdk_window_set_user_data (GdkWindow *window,
1553 g_return_if_fail (GDK_IS_WINDOW (window));
1555 ((GdkWindowObject*)window)->user_data = user_data;
1559 * gdk_window_get_user_data:
1560 * @window: a #GdkWindow
1561 * @data: return location for user data
1563 * Retrieves the user data for @window, which is normally the widget
1564 * that @window belongs to. See gdk_window_set_user_data().
1568 gdk_window_get_user_data (GdkWindow *window,
1571 g_return_if_fail (GDK_IS_WINDOW (window));
1573 *data = ((GdkWindowObject*)window)->user_data;
1577 * gdk_window_get_window_type:
1578 * @window: a #GdkWindow
1580 * Gets the type of the window. See #GdkWindowType.
1582 * Return value: type of window
1585 gdk_window_get_window_type (GdkWindow *window)
1587 g_return_val_if_fail (GDK_IS_WINDOW (window), (GdkWindowType) -1);
1589 return GDK_WINDOW_TYPE (window);
1593 * gdk_window_get_position:
1594 * @window: a #GdkWindow
1595 * @x: X coordinate of window
1596 * @y: Y coordinate of window
1598 * Obtains the position of the window as reported in the
1599 * most-recently-processed #GdkEventConfigure. Contrast with
1600 * gdk_window_get_geometry() which queries the X server for the
1601 * current window position, regardless of which events have been
1602 * received or processed.
1604 * The position coordinates are relative to the window's parent window.
1608 gdk_window_get_position (GdkWindow *window,
1612 GdkWindowObject *obj;
1614 g_return_if_fail (GDK_IS_WINDOW (window));
1616 obj = (GdkWindowObject*) window;
1625 * gdk_window_get_parent:
1626 * @window: a #GdkWindow
1628 * Obtains the parent of @window, as known to GDK. Does not query the
1629 * X server; thus this returns the parent as passed to gdk_window_new(),
1630 * not the actual parent. This should never matter unless you're using
1631 * Xlib calls mixed with GDK calls on the X11 platform. It may also
1632 * matter for toplevel windows, because the window manager may choose
1635 * Return value: parent of @window
1638 gdk_window_get_parent (GdkWindow *window)
1640 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1642 return (GdkWindow*) ((GdkWindowObject*) window)->parent;
1646 * gdk_window_get_toplevel:
1647 * @window: a #GdkWindow
1649 * Gets the toplevel window that's an ancestor of @window.
1651 * Return value: the toplevel window containing @window
1654 gdk_window_get_toplevel (GdkWindow *window)
1656 GdkWindowObject *obj;
1658 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1660 obj = (GdkWindowObject *)window;
1661 while (GDK_WINDOW_TYPE (obj) == GDK_WINDOW_CHILD)
1662 obj = (GdkWindowObject *)obj->parent;
1664 return GDK_WINDOW (obj);
1668 * gdk_window_get_children:
1669 * @window: a #GdkWindow
1671 * Gets the list of children of @window known to GDK.
1672 * This function only returns children created via GDK,
1673 * so for example it's useless when used with the root window;
1674 * it only returns windows an application created itself.
1676 * The returned list must be freed, but the elements in the
1679 * Return value: list of child windows inside @window
1682 gdk_window_get_children (GdkWindow *window)
1684 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1686 if (GDK_WINDOW_DESTROYED (window))
1689 return g_list_copy (GDK_WINDOW_OBJECT (window)->children);
1693 * gdk_window_peek_children:
1694 * @window: a #GdkWindow
1696 * Like gdk_window_get_children(), but does not copy the list of
1697 * children, so the list does not need to be freed.
1699 * Return value: a reference to the list of child windows in @window
1702 gdk_window_peek_children (GdkWindow *window)
1704 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1706 if (GDK_WINDOW_DESTROYED (window))
1709 return GDK_WINDOW_OBJECT (window)->children;
1713 * gdk_window_add_filter:
1714 * @window: a #GdkWindow
1715 * @function: filter callback
1716 * @data: data to pass to filter callback
1718 * Adds an event filter to @window, allowing you to intercept events
1719 * before they reach GDK. This is a low-level operation and makes it
1720 * easy to break GDK and/or GTK+, so you have to know what you're
1721 * doing. Pass %NULL for @window to get all events for all windows,
1722 * instead of events for a specific window.
1724 * See gdk_display_add_client_message_filter() if you are interested
1725 * in X ClientMessage events.
1728 gdk_window_add_filter (GdkWindow *window,
1729 GdkFilterFunc function,
1732 GdkWindowObject *private;
1734 GdkEventFilter *filter;
1736 g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
1738 private = (GdkWindowObject*) window;
1739 if (private && GDK_WINDOW_DESTROYED (window))
1742 /* Filters are for the native events on the native window, so
1743 ensure there is a native window. */
1745 gdk_window_set_has_native (window, TRUE);
1748 tmp_list = private->filters;
1750 tmp_list = _gdk_default_filters;
1754 filter = (GdkEventFilter *)tmp_list->data;
1755 if ((filter->function == function) && (filter->data == data))
1757 tmp_list = tmp_list->next;
1760 filter = g_new (GdkEventFilter, 1);
1761 filter->function = function;
1762 filter->data = data;
1765 private->filters = g_list_append (private->filters, filter);
1767 _gdk_default_filters = g_list_append (_gdk_default_filters, filter);
1771 * gdk_window_remove_filter:
1772 * @window: a #GdkWindow
1773 * @function: previously-added filter function
1774 * @data: user data for previously-added filter function
1776 * Remove a filter previously added with gdk_window_add_filter().
1780 gdk_window_remove_filter (GdkWindow *window,
1781 GdkFilterFunc function,
1784 GdkWindowObject *private;
1785 GList *tmp_list, *node;
1786 GdkEventFilter *filter;
1788 g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
1790 private = (GdkWindowObject*) window;
1793 tmp_list = private->filters;
1795 tmp_list = _gdk_default_filters;
1799 filter = (GdkEventFilter *)tmp_list->data;
1801 tmp_list = tmp_list->next;
1803 if ((filter->function == function) && (filter->data == data))
1806 private->filters = g_list_remove_link (private->filters, node);
1808 _gdk_default_filters = g_list_remove_link (_gdk_default_filters, node);
1809 g_list_free_1 (node);
1818 * gdk_screen_get_toplevel_windows:
1819 * @screen: The #GdkScreen where the toplevels are located.
1821 * Obtains a list of all toplevel windows known to GDK on the screen @screen.
1822 * A toplevel window is a child of the root window (see
1823 * gdk_get_default_root_window()).
1825 * The returned list should be freed with g_list_free(), but
1826 * its elements need not be freed.
1828 * Return value: list of toplevel windows, free with g_list_free()
1833 gdk_screen_get_toplevel_windows (GdkScreen *screen)
1835 GdkWindow * root_window;
1836 GList *new_list = NULL;
1839 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
1841 root_window = gdk_screen_get_root_window (screen);
1843 tmp_list = ((GdkWindowObject *)root_window)->children;
1846 if (GDK_WINDOW_TYPE (tmp_list->data) != GDK_WINDOW_FOREIGN)
1847 new_list = g_list_prepend (new_list, tmp_list->data);
1848 tmp_list = tmp_list->next;
1855 * gdk_window_get_toplevels:
1857 * Obtains a list of all toplevel windows known to GDK on the default
1858 * screen (see gdk_screen_get_toplevel_windows()).
1859 * A toplevel window is a child of the root window (see
1860 * gdk_get_default_root_window()).
1862 * The returned list should be freed with g_list_free(), but
1863 * its elements need not be freed.
1865 * Return value: list of toplevel windows, free with g_list_free()
1867 * Deprecated: 2.16: Use gdk_screen_get_toplevel_windows() instead.
1870 gdk_window_get_toplevels (void)
1872 return gdk_screen_get_toplevel_windows (gdk_screen_get_default ());
1876 * gdk_window_is_visible:
1877 * @window: a #GdkWindow
1879 * Checks whether the window has been mapped (with gdk_window_show() or
1880 * gdk_window_show_unraised()).
1882 * Return value: %TRUE if the window is mapped
1885 gdk_window_is_visible (GdkWindow *window)
1887 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
1889 return GDK_WINDOW_IS_MAPPED (window);
1893 * gdk_window_is_viewable:
1894 * @window: a #GdkWindow
1896 * Check if the window and all ancestors of the window are
1897 * mapped. (This is not necessarily "viewable" in the X sense, since
1898 * we only check as far as we have GDK window parents, not to the root
1901 * Return value: %TRUE if the window is viewable
1904 gdk_window_is_viewable (GdkWindow *window)
1906 GdkWindowObject *private = (GdkWindowObject *)window;
1908 GdkWindow *root_window;
1910 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
1912 screen = gdk_drawable_get_screen (window);
1913 root_window = gdk_screen_get_root_window (screen);
1916 (private != (GdkWindowObject *)root_window) &&
1917 (GDK_WINDOW_TYPE (private) != GDK_WINDOW_FOREIGN))
1919 if (GDK_WINDOW_DESTROYED (private) || !GDK_WINDOW_IS_MAPPED (private))
1922 private = (GdkWindowObject *)private->parent;
1929 * gdk_window_get_state:
1930 * @window: a #GdkWindow
1932 * Gets the bitwise OR of the currently active window state flags,
1933 * from the #GdkWindowState enumeration.
1935 * Return value: window state bitfield
1938 gdk_window_get_state (GdkWindow *window)
1940 GdkWindowObject *private = (GdkWindowObject *)window;
1942 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
1944 return private->state;
1948 /* This creates an empty "implicit" paint region for the impl window.
1949 * By itself this does nothing, but real paints to this window
1950 * or children of it can use this pixmap as backing to avoid allocating
1951 * multiple pixmaps for subwindow rendering. When doing so they
1952 * add to the region of the implicit paint region, which will be
1953 * pushed to the window when the implicit paint region is ended.
1954 * Such paints should not copy anything to the window on paint end, but
1955 * should rely on the implicit paint end.
1956 * The implicit paint will be automatically ended if someone draws
1957 * directly to the window or a child window.
1960 gdk_window_begin_implicit_paint (GdkWindow *window, GdkRectangle *rect)
1962 GdkWindowObject *private = (GdkWindowObject *)window;
1963 GdkWindowPaint *paint;
1964 GdkRectangle r, clipbox;
1966 GdkWindowRegionMove *move;
1968 g_assert (gdk_window_has_impl (private));
1970 if (GDK_IS_PAINTABLE (private->impl))
1971 return FALSE; /* Implementation does double buffering */
1973 if (private->paint_stack != NULL ||
1974 private->implicit_paint != NULL)
1975 return FALSE; /* Don't stack implicit paints */
1978 for (l = private->outstanding_moves; l != NULL; l = l->next)
1982 if (!gdk_region_empty (move->region))
1984 gdk_region_get_clipbox (move->region, &clipbox);
1985 gdk_rectangle_union (&r, &clipbox, &r);
1989 paint = g_new (GdkWindowPaint, 1);
1990 paint->region = gdk_region_new (); /* Empty */
1991 paint->x_offset = r.x;
1992 paint->y_offset = r.y;
1993 paint->uses_implicit = FALSE;
1994 paint->surface = NULL;
1996 gdk_pixmap_new (window,
1997 MAX (r.width, 1), MAX (r.height, 1), -1);
1999 _gdk_pixmap_set_as_backing (paint->pixmap,
2002 for (l = private->outstanding_moves; l != NULL; l = l->next)
2006 gdk_region_union (paint->region, move->region);
2007 g_object_ref (paint->pixmap);
2008 do_move_region_bits_on_impl (private,
2010 paint->x_offset, paint->y_offset,
2011 move->region, /* In impl window coords */
2012 move->dx, move->dy);
2013 gdk_region_destroy (move->region);
2014 g_slice_free (GdkWindowRegionMove, move);
2016 private->outstanding_moves = NULL;
2018 private->implicit_paint = paint;
2023 /* Ensure that all content related to this (sub)window is pushed to the
2026 gdk_window_flush_implicit_paint (GdkWindow *window)
2028 GdkWindowObject *private = (GdkWindowObject *)window;
2029 GdkWindowObject *impl_window;
2030 GdkWindowPaint *paint;
2034 /* Ensure that there is no explicit paint region. */
2035 g_assert (private->paint_stack == NULL);
2037 impl_window = gdk_window_get_impl_window (private);
2038 if (impl_window->implicit_paint == NULL)
2041 paint = impl_window->implicit_paint;
2042 region = gdk_region_copy (private->clip_region_with_children);
2043 gdk_region_offset (region, private->abs_x, private->abs_y);
2044 gdk_region_intersect (region, paint->region);
2046 if (!gdk_region_empty (region))
2048 /* Some regions are valid, push these to window now */
2049 tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
2050 _gdk_gc_set_clip_region_internal (tmp_gc, region, TRUE);
2051 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2052 0, 0, paint->x_offset, paint->y_offset, -1, -1);
2053 /* Reset clip region of the cached GdkGC */
2054 gdk_gc_set_clip_region (tmp_gc, NULL);
2056 /* Remove flushed region from the implicit paint */
2057 gdk_region_subtract (paint->region, region);
2060 gdk_region_destroy (region);
2063 /* Ends an implicit paint, paired with gdk_window_begin_implicit_paint returning TRUE */
2065 gdk_window_end_implicit_paint (GdkWindow *window)
2067 GdkWindowObject *private = (GdkWindowObject *)window;
2068 GdkWindowPaint *paint;
2071 g_assert (gdk_window_has_impl (private));
2073 g_assert (private->implicit_paint != NULL);
2075 paint = private->implicit_paint;
2077 private->implicit_paint = NULL;
2079 if (!gdk_region_empty (paint->region))
2081 /* Some regions are valid, push these to window now */
2082 tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
2083 _gdk_gc_set_clip_region_internal (tmp_gc, paint->region, TRUE);
2084 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2085 0, 0, paint->x_offset, paint->y_offset, -1, -1);
2086 /* Reset clip region of the cached GdkGC */
2087 gdk_gc_set_clip_region (tmp_gc, NULL);
2090 g_object_unref (paint->pixmap);
2095 * gdk_window_begin_paint_rect:
2096 * @window: a #GdkWindow
2097 * @rectangle: rectangle you intend to draw to
2099 * A convenience wrapper around gdk_window_begin_paint_region() which
2100 * creates a rectangular region for you. See
2101 * gdk_window_begin_paint_region() for details.
2105 gdk_window_begin_paint_rect (GdkWindow *window,
2106 const GdkRectangle *rectangle)
2110 g_return_if_fail (GDK_IS_WINDOW (window));
2112 region = gdk_region_rectangle (rectangle);
2113 gdk_window_begin_paint_region (window, region);
2114 gdk_region_destroy (region);
2117 #ifdef GDK_WINDOWING_X11
2118 #include "x11/gdkx.h"
2122 * gdk_window_begin_paint_region:
2123 * @window: a #GdkWindow
2124 * @region: region you intend to draw to
2126 * Indicates that you are beginning the process of redrawing @region.
2127 * A backing store (offscreen buffer) large enough to contain @region
2128 * will be created. The backing store will be initialized with the
2129 * background color or background pixmap for @window. Then, all
2130 * drawing operations performed on @window will be diverted to the
2131 * backing store. When you call gdk_window_end_paint(), the backing
2132 * store will be copied to @window, making it visible onscreen. Only
2133 * the part of @window contained in @region will be modified; that is,
2134 * drawing operations are clipped to @region.
2136 * The net result of all this is to remove flicker, because the user
2137 * sees the finished product appear all at once when you call
2138 * gdk_window_end_paint(). If you draw to @window directly without
2139 * calling gdk_window_begin_paint_region(), the user may see flicker
2140 * as individual drawing operations are performed in sequence. The
2141 * clipping and background-initializing features of
2142 * gdk_window_begin_paint_region() are conveniences for the
2143 * programmer, so you can avoid doing that work yourself.
2145 * When using GTK+, the widget system automatically places calls to
2146 * gdk_window_begin_paint_region() and gdk_window_end_paint() around
2147 * emissions of the expose_event signal. That is, if you're writing an
2148 * expose event handler, you can assume that the exposed area in
2149 * #GdkEventExpose has already been cleared to the window background,
2150 * is already set as the clip region, and already has a backing store.
2151 * Therefore in most cases, application code need not call
2152 * gdk_window_begin_paint_region(). (You can disable the automatic
2153 * calls around expose events on a widget-by-widget basis by calling
2154 * gtk_widget_set_double_buffered().)
2156 * If you call this function multiple times before calling the
2157 * matching gdk_window_end_paint(), the backing stores are pushed onto
2158 * a stack. gdk_window_end_paint() copies the topmost backing store
2159 * onscreen, subtracts the topmost region from all other regions in
2160 * the stack, and pops the stack. All drawing operations affect only
2161 * the topmost backing store in the stack. One matching call to
2162 * gdk_window_end_paint() is required for each call to
2163 * gdk_window_begin_paint_region().
2167 gdk_window_begin_paint_region (GdkWindow *window,
2168 const GdkRegion *region)
2170 #ifdef USE_BACKING_STORE
2171 GdkWindowObject *private = (GdkWindowObject *)window;
2172 GdkRectangle clip_box;
2173 GdkWindowPaint *paint, *implicit_paint;
2174 GdkWindowObject *impl_window;
2177 g_return_if_fail (GDK_IS_WINDOW (window));
2179 if (GDK_WINDOW_DESTROYED (window))
2182 if (GDK_IS_PAINTABLE (private->impl))
2184 GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
2186 if (iface->begin_paint_region)
2187 iface->begin_paint_region ((GdkPaintable*)private->impl, region);
2192 gdk_region_get_clipbox (region, &clip_box);
2194 impl_window = gdk_window_get_impl_window (private);
2195 implicit_paint = impl_window->implicit_paint;
2197 paint = g_new (GdkWindowPaint, 1);
2198 paint->region = gdk_region_copy (region);
2199 paint->region_tag = new_region_tag ();
2205 paint->uses_implicit = TRUE;
2206 paint->pixmap = g_object_ref (implicit_paint->pixmap);
2207 paint->x_offset = -private->abs_x + implicit_paint->x_offset;
2208 paint->y_offset = -private->abs_y + implicit_paint->y_offset;
2209 gdk_region_intersect (paint->region, private->clip_region_with_children);
2211 /* It would be nice if we had some cairo support here so we
2212 could set the clip rect on the cairo surface */
2213 width = private->abs_x + private->width;
2214 height = private->abs_y + private->height;
2216 paint->surface = _gdk_drawable_create_cairo_surface (paint->pixmap, width, height);
2218 /* Mark the region as valid on the implicit paint */
2219 gdk_region_offset (paint->region, private->abs_x, private->abs_y);
2220 gdk_region_union (implicit_paint->region, paint->region);
2221 gdk_region_offset (paint->region, -private->abs_x, -private->abs_y);
2225 paint->uses_implicit = FALSE;
2226 paint->x_offset = clip_box.x;
2227 paint->y_offset = clip_box.y;
2229 gdk_pixmap_new (window,
2230 MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1);
2231 paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap);
2235 cairo_surface_set_device_offset (paint->surface,
2236 -paint->x_offset, -paint->y_offset);
2238 for (list = private->paint_stack; list != NULL; list = list->next)
2240 GdkWindowPaint *tmp_paint = list->data;
2242 gdk_region_subtract (tmp_paint->region, paint->region);
2245 private->paint_stack = g_slist_prepend (private->paint_stack, paint);
2247 if (!gdk_region_empty (paint->region))
2249 gdk_window_clear_backing_rect (window,
2250 clip_box.x, clip_box.y,
2251 clip_box.width, clip_box.height);
2254 #endif /* USE_BACKING_STORE */
2258 setup_redirect_clip (GdkWindow *window,
2263 GdkWindowObject *private = (GdkWindowObject *)window;
2264 GdkRegion *visible_region;
2265 GdkRectangle dest_rect;
2267 GdkWindow *toplevel;
2268 int x_offset, y_offset;
2270 toplevel = GDK_WINDOW (private->redirect->redirected);
2272 /* Get the clip region for gc clip rect + window hierarchy in
2273 window relative coords */
2275 _gdk_window_calculate_full_clip_region (window, toplevel,
2280 /* Compensate for the source pos/size */
2281 x_offset -= private->redirect->src_x;
2282 y_offset -= private->redirect->src_y;
2283 dest_rect.x = -x_offset;
2284 dest_rect.y = -y_offset;
2285 dest_rect.width = private->redirect->width;
2286 dest_rect.height = private->redirect->height;
2287 tmpreg = gdk_region_rectangle (&dest_rect);
2288 gdk_region_intersect (visible_region, tmpreg);
2289 gdk_region_destroy (tmpreg);
2291 /* Compensate for the dest pos */
2292 x_offset += private->redirect->dest_x;
2293 y_offset += private->redirect->dest_y;
2295 gdk_gc_set_clip_region (gc, visible_region); /* This resets clip origin! */
2297 /* offset clip and tiles from window coords to pixmaps coords */
2298 gdk_gc_offset (gc, -x_offset, -y_offset);
2300 gdk_region_destroy (visible_region);
2302 *x_offset_out = x_offset;
2303 *y_offset_out = y_offset;
2307 * gdk_window_end_paint:
2308 * @window: a #GdkWindow
2310 * Indicates that the backing store created by the most recent call to
2311 * gdk_window_begin_paint_region() should be copied onscreen and
2312 * deleted, leaving the next-most-recent backing store or no backing
2313 * store at all as the active paint region. See
2314 * gdk_window_begin_paint_region() for full details. It is an error to
2315 * call this function without a matching
2316 * gdk_window_begin_paint_region() first.
2320 gdk_window_end_paint (GdkWindow *window)
2322 #ifdef USE_BACKING_STORE
2323 GdkWindowObject *private = (GdkWindowObject *)window;
2324 GdkWindowObject *composited;
2325 GdkWindowPaint *paint;
2327 GdkRectangle clip_box;
2328 gint x_offset, y_offset;
2329 GdkRegion *full_clip;
2331 g_return_if_fail (GDK_IS_WINDOW (window));
2333 if (GDK_WINDOW_DESTROYED (window))
2336 if (GDK_IS_PAINTABLE (private->impl))
2338 GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
2340 if (iface->end_paint)
2341 iface->end_paint ((GdkPaintable*)private->impl);
2345 if (private->paint_stack == NULL)
2347 g_warning (G_STRLOC": no preceding call to gdk_window_begin_paint_region(), see documentation");
2351 paint = private->paint_stack->data;
2353 private->paint_stack = g_slist_delete_link (private->paint_stack,
2354 private->paint_stack);
2356 gdk_region_get_clipbox (paint->region, &clip_box);
2358 tmp_gc = _gdk_drawable_get_scratch_gc (window, FALSE);
2360 x_offset = -private->abs_x;
2361 y_offset = -private->abs_y;
2363 if (!paint->uses_implicit)
2365 full_clip = gdk_region_copy (private->clip_region_with_children);
2366 gdk_region_intersect (full_clip, paint->region);
2367 _gdk_gc_set_clip_region_internal (tmp_gc, full_clip, TRUE); /* Takes ownership of full_clip */
2368 gdk_gc_set_clip_origin (tmp_gc, - x_offset, - y_offset);
2369 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2370 clip_box.x - paint->x_offset,
2371 clip_box.y - paint->y_offset,
2372 clip_box.x - x_offset, clip_box.y - y_offset,
2373 clip_box.width, clip_box.height);
2376 if (private->redirect)
2378 int x_offset, y_offset;
2380 /* TODO: Should also use paint->region for clipping */
2381 setup_redirect_clip (window, tmp_gc, &x_offset, &y_offset);
2382 gdk_draw_drawable (private->redirect->pixmap, tmp_gc, paint->pixmap,
2383 clip_box.x - paint->x_offset,
2384 clip_box.y - paint->y_offset,
2385 clip_box.x + x_offset,
2386 clip_box.y + y_offset,
2387 clip_box.width, clip_box.height);
2390 /* Reset clip region of the cached GdkGC */
2391 gdk_gc_set_clip_region (tmp_gc, NULL);
2393 cairo_surface_destroy (paint->surface);
2394 g_object_unref (paint->pixmap);
2395 gdk_region_destroy (paint->region);
2398 /* find a composited window in our hierarchy to signal its
2399 * parent to redraw, calculating the clip box as we go...
2401 * stop if parent becomes NULL since then we'd have nowhere
2402 * to draw (ie: 'composited' will always be non-NULL here).
2404 for (composited = private;
2406 composited = composited->parent)
2410 gdk_drawable_get_size (GDK_DRAWABLE (composited->parent),
2413 clip_box.x += composited->x;
2414 clip_box.y += composited->y;
2415 clip_box.width = MIN (clip_box.width, width - clip_box.x);
2416 clip_box.height = MIN (clip_box.height, height - clip_box.y);
2418 if (composited->composited)
2420 gdk_window_invalidate_rect (GDK_WINDOW (composited->parent),
2425 #endif /* USE_BACKING_STORE */
2429 gdk_window_free_paint_stack (GdkWindow *window)
2431 GdkWindowObject *private = (GdkWindowObject *)window;
2433 if (private->paint_stack)
2435 GSList *tmp_list = private->paint_stack;
2439 GdkWindowPaint *paint = tmp_list->data;
2441 if (tmp_list == private->paint_stack)
2442 g_object_unref (paint->pixmap);
2444 gdk_region_destroy (paint->region);
2447 tmp_list = tmp_list->next;
2450 g_slist_free (private->paint_stack);
2451 private->paint_stack = NULL;
2456 do_move_region_bits_on_impl (GdkWindowObject *private,
2458 int dest_off_x, int dest_off_y,
2459 GdkRegion *region, /* In impl window coords */
2463 GdkRectangle copy_rect;
2465 gdk_region_get_clipbox (region, ©_rect);
2466 gdk_region_offset (region, -dest_off_x, -dest_off_y);
2468 /* We need to get data from subwindows here, because we might have
2469 * shaped a native window over the moving region (with bg none,
2470 * so the pixels are still there). In fact we might need to get data
2471 * from overlapping native window that are not children of this window,
2472 * so we copy from the toplevel with INCLUDE_INFERIORS.
2474 private = gdk_window_get_impl_window (private);
2475 while (private->parent != NULL &&
2476 GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
2478 dx -= private->parent->abs_x + private->x;
2479 dy -= private->parent->abs_y + private->y;
2480 private = gdk_window_get_impl_window (private->parent);
2482 tmp_gc = _gdk_drawable_get_subwindow_scratch_gc ((GdkWindow *)private);
2483 gdk_gc_set_clip_region (tmp_gc, region);
2484 gdk_draw_drawable (dest,
2487 copy_rect.x-dx, copy_rect.y-dy,
2488 copy_rect.x - dest_off_x, copy_rect.y - dest_off_y,
2489 copy_rect.width, copy_rect.height);
2490 gdk_gc_set_clip_region (tmp_gc, NULL);
2494 append_move_region (GdkWindowObject *impl_window,
2498 GList *moves_to_add, *l, *s;
2499 GdkRegion *intersection;
2500 GdkWindowRegionMove *move, *new_move, *existing_move;
2502 move = g_slice_new (GdkWindowRegionMove);
2503 move->region = region;
2507 moves_to_add = g_list_prepend (NULL, move);
2509 for (l = impl_window->outstanding_moves; l != NULL; l = l->next)
2511 existing_move = l->data;
2513 for (s = moves_to_add; s != NULL; s = s->next)
2517 intersection = gdk_region_copy (move->region);
2518 gdk_region_offset (intersection, -move->dx, -move->dy);
2519 gdk_region_intersect (intersection, existing_move->region);
2520 gdk_region_offset (intersection, move->dx, move->dy);
2522 if (!gdk_region_empty (intersection))
2525 new_move = g_slice_new (GdkWindowRegionMove);
2526 new_move->region = intersection;
2527 new_move->dx = move->dx + existing_move->dx;
2528 new_move->dy = move->dy + existing_move->dy;
2529 moves_to_add = g_list_prepend (moves_to_add, new_move);
2531 gdk_region_subtract (move->region, intersection);
2532 gdk_region_subtract (existing_move->region, intersection);
2535 gdk_region_destroy (intersection);
2539 impl_window->outstanding_moves = g_list_concat (impl_window->outstanding_moves,
2544 /* Moves bits and update area by dx/dy in impl window
2545 * Takes ownership of region.
2548 move_region_on_impl (GdkWindowObject *private,
2549 GdkRegion *region, /* In impl window coords */
2552 GdkWindowObject *impl_window;
2553 gboolean free_region;
2555 if ((dx == 0 && dy == 0) ||
2556 gdk_region_empty (region))
2558 gdk_region_destroy (region);
2563 impl_window = gdk_window_get_impl_window (private);
2565 if (1) /* Enable flicker free handling of moves. */
2567 free_region = FALSE;
2569 append_move_region (impl_window, region, dx, dy);
2572 do_move_region_bits_on_impl (private,
2576 /* Move any old invalid regions in the copy source area by dx/dy */
2577 if (impl_window->update_area)
2579 GdkRegion *update_area;
2581 update_area = gdk_region_copy (region);
2582 /* Convert from target to source */
2583 gdk_region_offset (update_area, -dx, -dy);
2584 gdk_region_intersect (update_area, impl_window->update_area);
2585 gdk_region_subtract (impl_window->update_area, update_area);
2587 gdk_region_offset (update_area, dx, dy);
2588 gdk_region_union (impl_window->update_area, update_area);
2589 gdk_region_destroy (update_area);
2593 gdk_region_destroy (region);
2596 /* Flushes all outstanding changes to the window, call this
2597 * before drawing directly to the window (i.e. outside a begin/end_paint pair).
2600 gdk_window_flush_outstanding_moves (GdkWindow *window)
2602 GdkWindowObject *private;
2603 GdkWindowObject *impl_window;
2605 GdkWindowRegionMove *move;
2607 private = (GdkWindowObject *) window;
2609 impl_window = gdk_window_get_impl_window (private);
2611 for (l = impl_window->outstanding_moves; l != NULL; l = l->next)
2615 do_move_region_bits_on_impl (private,
2616 private->impl, 0, 0,
2617 move->region, move->dx, move->dy);
2619 gdk_region_destroy (move->region);
2620 g_slice_free (GdkWindowRegionMove, move);
2623 g_list_free (impl_window->outstanding_moves);
2624 impl_window->outstanding_moves = NULL;
2628 gdk_window_flush (GdkWindow *window)
2630 gdk_window_flush_outstanding_moves (window);
2631 gdk_window_flush_implicit_paint (window);
2635 gdk_window_flush_recursive_helper (GdkWindowObject *window,
2638 GdkWindowObject *child;
2641 for (l = window->children; l != NULL; l = l->next)
2645 if (child->impl == impl)
2646 /* Same impl, ignore */
2647 gdk_window_flush_recursive_helper (child, impl);
2649 gdk_window_flush_recursive (child);
2654 gdk_window_flush_recursive (GdkWindowObject *window)
2656 gdk_window_flush ((GdkWindow *)window);
2657 gdk_window_flush_recursive_helper (window, window->impl);
2661 gdk_window_get_offsets (GdkWindow *window,
2665 GdkWindowObject *private = (GdkWindowObject *)window;
2667 if (private->paint_stack)
2669 GdkWindowPaint *paint = private->paint_stack->data;
2670 *x_offset = paint->x_offset;
2671 *y_offset = paint->y_offset;
2675 *x_offset = -private->abs_x;
2676 *y_offset = -private->abs_y;
2681 * gdk_window_get_internal_paint_info:
2682 * @window: a #GdkWindow
2683 * @real_drawable: location to store the drawable to which drawing should be
2685 * @x_offset: location to store the X offset between coordinates in @window,
2686 * and the underlying window system primitive coordinates for
2688 * @y_offset: location to store the Y offset between coordinates in @window,
2689 * and the underlying window system primitive coordinates for
2692 * If you bypass the GDK layer and use windowing system primitives to
2693 * draw directly onto a #GdkWindow, then you need to deal with two
2694 * details: there may be an offset between GDK coordinates and windowing
2695 * system coordinates, and GDK may have redirected drawing to a offscreen
2696 * pixmap as the result of a gdk_window_begin_paint_region() calls.
2697 * This function allows retrieving the information you need to compensate
2698 * for these effects.
2700 * This function exposes details of the GDK implementation, and is thus
2701 * likely to change in future releases of GDK.
2704 gdk_window_get_internal_paint_info (GdkWindow *window,
2705 GdkDrawable **real_drawable,
2711 GdkWindowObject *private;
2713 g_return_if_fail (GDK_IS_WINDOW (window));
2715 private = (GdkWindowObject *)window;
2719 if (private->paint_stack)
2721 GdkWindowPaint *paint = private->paint_stack->data;
2722 *real_drawable = paint->pixmap;
2726 /* This means you're probably gonna be doing some weird shit
2727 directly to the window, so we flush all outstanding stuff */
2728 gdk_window_flush (window);
2729 *real_drawable = window;
2733 gdk_window_get_offsets (window, &x_off, &y_off);
2742 setup_clip_for_draw (GdkDrawable *drawable,
2744 int old_clip_x, int old_clip_y)
2746 GdkWindowObject *private = (GdkWindowObject *)drawable;
2749 if (private->window_type == GDK_WINDOW_ROOT)
2752 if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
2753 clip = private->clip_region_with_children;
2755 clip = private->clip_region;
2757 _gdk_gc_add_drawable_clip (gc,
2760 /* If there was a clip origin set appart from the
2761 * window offset, need to take that into consideration */
2762 -old_clip_x, -old_clip_y);
2766 setup_clip_for_paint (GdkDrawable *drawable,
2767 GdkWindowPaint *paint,
2769 int old_clip_x, int old_clip_y)
2771 _gdk_gc_add_drawable_clip (gc,
2773 /* This includes the window clip */
2775 /* If there was a clip origin set appart from the
2776 * window offset, need to take that into consideration */
2777 -old_clip_x, -old_clip_y);
2781 #define OFFSET_GC(gc) \
2782 gint x_offset, y_offset; \
2783 gint old_clip_x = gc->clip_x_origin; \
2784 gint old_clip_y = gc->clip_y_origin; \
2785 gint old_ts_x = gc->ts_x_origin; \
2786 gint old_ts_y = gc->ts_y_origin; \
2787 gdk_window_get_offsets (drawable, &x_offset, &y_offset); \
2788 if (x_offset != 0 || y_offset != 0) \
2790 gdk_gc_set_clip_origin (gc, old_clip_x - x_offset, \
2791 old_clip_y - y_offset); \
2792 gdk_gc_set_ts_origin (gc, old_ts_x - x_offset, \
2793 old_ts_y - y_offset); \
2796 #define RESTORE_GC(gc) \
2797 if (x_offset != 0 || y_offset != 0) \
2799 gdk_gc_set_clip_origin (gc, old_clip_x, old_clip_y); \
2800 gdk_gc_set_ts_origin (gc, old_ts_x, old_ts_y); \
2803 #define SETUP_PAINT_GC_CLIP(gc) \
2804 if (paint->uses_implicit) \
2805 setup_clip_for_paint (drawable, paint, gc, old_clip_x, \
2808 #define RESTORE_PAINT_GC_CLIP(gc)
2811 #define SETUP_DIRECT_GC_CLIP(gc) \
2812 gdk_window_flush ((GdkWindow *)drawable);\
2813 setup_clip_for_draw (drawable, gc, old_clip_x, old_clip_y);
2815 #define RESTORE_DIRECT_GC_CLIP(gc)
2818 gdk_window_create_gc (GdkDrawable *drawable,
2819 GdkGCValues *values,
2820 GdkGCValuesMask mask)
2822 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
2824 if (GDK_WINDOW_DESTROYED (drawable))
2827 return gdk_gc_new_with_values (((GdkWindowObject *) drawable)->impl,
2831 /* After having set up the drawable clip rect on a GC we need
2832 * to make sure that if we draw to a pixmap we draw to the impl,
2833 * otherwise the pixmap code will reset the drawable clip.
2835 static GdkDrawable *
2836 pixmap_impl (GdkPixmap *pixmap)
2838 return ((GdkPixmapObject *)pixmap)->impl;
2842 gdk_window_draw_rectangle (GdkDrawable *drawable,
2850 GdkWindowObject *private = (GdkWindowObject *)drawable;
2853 if (GDK_WINDOW_DESTROYED (drawable))
2856 if (private->paint_stack)
2858 GdkWindowPaint *paint = private->paint_stack->data;
2859 SETUP_PAINT_GC_CLIP (gc);
2860 gdk_draw_rectangle (pixmap_impl (paint->pixmap), gc, filled,
2861 x - x_offset, y - y_offset, width, height);
2862 RESTORE_PAINT_GC_CLIP (gc);
2866 SETUP_DIRECT_GC_CLIP(gc);
2867 gdk_draw_rectangle (private->impl, gc, filled,
2868 x - x_offset, y - y_offset, width, height);
2869 RESTORE_DIRECT_GC_CLIP(gc);
2876 gdk_window_draw_arc (GdkDrawable *drawable,
2886 GdkWindowObject *private = (GdkWindowObject *)drawable;
2889 if (GDK_WINDOW_DESTROYED (drawable))
2892 if (private->paint_stack)
2894 GdkWindowPaint *paint = private->paint_stack->data;
2895 SETUP_PAINT_GC_CLIP (gc);
2896 gdk_draw_arc (pixmap_impl (paint->pixmap), gc, filled,
2897 x - x_offset, y - y_offset,
2898 width, height, angle1, angle2);
2899 RESTORE_PAINT_GC_CLIP (gc);
2903 SETUP_DIRECT_GC_CLIP(gc);
2904 gdk_draw_arc (private->impl, gc, filled,
2905 x - x_offset, y - y_offset,
2906 width, height, angle1, angle2);
2907 RESTORE_DIRECT_GC_CLIP(gc);
2913 gdk_window_draw_polygon (GdkDrawable *drawable,
2919 GdkWindowObject *private = (GdkWindowObject *)drawable;
2920 GdkPoint *new_points;
2924 if (GDK_WINDOW_DESTROYED (drawable))
2927 if (x_offset != 0 || y_offset != 0)
2931 new_points = g_new (GdkPoint, npoints);
2932 for (i=0; i<npoints; i++)
2934 new_points[i].x = points[i].x - x_offset;
2935 new_points[i].y = points[i].y - y_offset;
2939 new_points = points;
2941 if (private->paint_stack)
2943 GdkWindowPaint *paint = private->paint_stack->data;
2944 SETUP_PAINT_GC_CLIP (gc);
2945 gdk_draw_polygon (pixmap_impl (paint->pixmap), gc, filled, new_points, npoints);
2946 RESTORE_PAINT_GC_CLIP (gc);
2950 SETUP_DIRECT_GC_CLIP(gc);
2951 gdk_draw_polygon (private->impl, gc, filled, new_points, npoints);
2952 RESTORE_DIRECT_GC_CLIP(gc);
2955 if (new_points != points)
2956 g_free (new_points);
2962 gdk_window_draw_text (GdkDrawable *drawable,
2970 GdkWindowObject *private = (GdkWindowObject *)drawable;
2973 if (GDK_WINDOW_DESTROYED (drawable))
2976 if (private->paint_stack)
2978 GdkWindowPaint *paint = private->paint_stack->data;
2979 SETUP_PAINT_GC_CLIP (gc);
2980 gdk_draw_text (pixmap_impl (paint->pixmap), font, gc,
2981 x - x_offset, y - y_offset, text, text_length);
2983 RESTORE_PAINT_GC_CLIP (gc);
2987 SETUP_DIRECT_GC_CLIP(gc);
2988 gdk_draw_text (private->impl, font, gc,
2989 x - x_offset, y - y_offset, text, text_length);
2990 RESTORE_DIRECT_GC_CLIP(gc);
2997 gdk_window_draw_text_wc (GdkDrawable *drawable,
3002 const GdkWChar *text,
3005 GdkWindowObject *private = (GdkWindowObject *)drawable;
3008 if (GDK_WINDOW_DESTROYED (drawable))
3011 if (private->paint_stack)
3013 GdkWindowPaint *paint = private->paint_stack->data;
3014 SETUP_PAINT_GC_CLIP (gc);
3015 gdk_draw_text_wc (pixmap_impl (paint->pixmap), font, gc,
3016 x - x_offset, y - y_offset, text, text_length);
3017 RESTORE_PAINT_GC_CLIP (gc);
3021 SETUP_DIRECT_GC_CLIP(gc);
3022 gdk_draw_text_wc (private->impl, font, gc,
3023 x - x_offset, y - y_offset, text, text_length);
3024 RESTORE_DIRECT_GC_CLIP(gc);
3030 static GdkDrawable *
3031 gdk_window_get_source_drawable (GdkDrawable *drawable)
3033 GdkWindow *window = GDK_WINDOW (drawable);
3034 GdkWindowObject *private;
3036 private = (GdkWindowObject *) window;
3037 if (GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable)
3038 return GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable (private->impl);
3043 static GdkDrawable *
3044 gdk_window_get_composite_drawable (GdkDrawable *drawable,
3049 gint *composite_x_offset,
3050 gint *composite_y_offset)
3052 GdkWindowObject *private = (GdkWindowObject *)drawable;
3054 GdkPixmap *tmp_pixmap;
3057 gboolean overlap_buffer;
3058 GdkDrawable *source;
3059 GdkWindowObject *impl_window;
3060 GdkWindowPaint *implicit_paint;
3062 *composite_x_offset = -private->abs_x;
3063 *composite_y_offset = -private->abs_y;
3065 if ((GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable)))
3066 return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
3068 /* See if any buffered part is overlapping the part we want
3074 rect.height = height;
3076 overlap_buffer = FALSE;
3078 for (list = private->paint_stack; list != NULL; list = list->next)
3080 GdkWindowPaint *paint = list->data;
3081 GdkOverlapType overlap;
3083 overlap = gdk_region_rect_in (paint->region, &rect);
3085 if (overlap == GDK_OVERLAP_RECTANGLE_IN)
3087 *composite_x_offset = paint->x_offset;
3088 *composite_y_offset = paint->y_offset;
3090 return g_object_ref (paint->pixmap);
3092 else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
3094 overlap_buffer = TRUE;
3099 impl_window = gdk_window_get_impl_window (private);
3100 implicit_paint = impl_window->implicit_paint;
3103 GdkOverlapType overlap;
3105 rect.x += private->abs_x;
3106 rect.y += private->abs_y;
3108 overlap = gdk_region_rect_in (implicit_paint->region, &rect);
3109 if (overlap == GDK_OVERLAP_RECTANGLE_IN)
3111 *composite_x_offset = -private->abs_x + implicit_paint->x_offset;
3112 *composite_y_offset = -private->abs_y + implicit_paint->y_offset;
3114 return g_object_ref (implicit_paint->pixmap);
3116 else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
3117 overlap_buffer = TRUE;
3120 if (!overlap_buffer)
3121 return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
3123 tmp_pixmap = gdk_pixmap_new (drawable, width, height, -1);
3124 tmp_gc = _gdk_drawable_get_scratch_gc (tmp_pixmap, FALSE);
3126 source = _gdk_drawable_get_source_drawable (drawable);
3128 /* Copy the current window contents */
3129 gdk_draw_drawable (tmp_pixmap,
3131 GDK_WINDOW_OBJECT (source)->impl,
3132 x - *composite_x_offset,
3133 y - *composite_y_offset,
3137 /* paint the backing stores */
3140 GdkWindowPaint *paint = list->data;
3142 gdk_gc_set_clip_region (tmp_gc, paint->region);
3143 gdk_gc_set_clip_origin (tmp_gc, -x - paint->x_offset, -y - paint->y_offset);
3145 gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
3146 x - paint->x_offset,
3147 y - paint->y_offset,
3148 0, 0, width, height);
3151 for (list = private->paint_stack; list != NULL; list = list->next)
3153 GdkWindowPaint *paint = list->data;
3155 if (paint->uses_implicit)
3156 continue; /* We already copied this above */
3158 gdk_gc_set_clip_region (tmp_gc, paint->region);
3159 gdk_gc_set_clip_origin (tmp_gc, -x, -y);
3161 gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
3162 x - paint->x_offset,
3163 y - paint->y_offset,
3164 0, 0, width, height);
3167 /* Reset clip region of the cached GdkGC */
3168 gdk_gc_set_clip_region (tmp_gc, NULL);
3170 /* Set these to location of tmp_pixmap within the window */
3171 *composite_x_offset = x;
3172 *composite_y_offset = y;
3178 gdk_window_get_clip_region (GdkDrawable *drawable)
3180 GdkWindowObject *private = (GdkWindowObject *)drawable;
3183 result = gdk_region_copy (private->clip_region);
3185 if (private->paint_stack)
3187 GdkRegion *paint_region = gdk_region_new ();
3188 GSList *tmp_list = private->paint_stack;
3192 GdkWindowPaint *paint = tmp_list->data;
3194 gdk_region_union (paint_region, paint->region);
3196 tmp_list = tmp_list->next;
3199 gdk_region_intersect (result, paint_region);
3200 gdk_region_destroy (paint_region);
3207 gdk_window_get_visible_region (GdkDrawable *drawable)
3209 GdkWindowObject *private = (GdkWindowObject*) drawable;
3211 return gdk_region_copy (private->clip_region);
3215 gdk_window_draw_drawable (GdkDrawable *drawable,
3225 GdkWindowObject *private = (GdkWindowObject *)drawable;
3228 if (GDK_WINDOW_DESTROYED (drawable))
3231 /* If we have a backing pixmap draw to that */
3232 if (private->paint_stack)
3234 GdkWindowPaint *paint = private->paint_stack->data;
3235 SETUP_PAINT_GC_CLIP (gc);
3236 gdk_draw_drawable (pixmap_impl (paint->pixmap), gc,
3238 xdest - x_offset, ydest - y_offset, width, height);
3240 RESTORE_PAINT_GC_CLIP (gc);
3244 SETUP_DIRECT_GC_CLIP(gc);
3245 gdk_draw_drawable (private->impl, gc,
3247 xdest - x_offset, ydest - y_offset,
3249 RESTORE_DIRECT_GC_CLIP(gc);
3256 gdk_window_draw_points (GdkDrawable *drawable,
3261 GdkWindowObject *private = (GdkWindowObject *)drawable;
3262 GdkPoint *new_points;
3266 if (GDK_WINDOW_DESTROYED (drawable))
3269 if (x_offset != 0 || y_offset != 0)
3273 new_points = g_new (GdkPoint, npoints);
3274 for (i=0; i<npoints; i++)
3276 new_points[i].x = points[i].x - x_offset;
3277 new_points[i].y = points[i].y - y_offset;
3281 new_points = points;
3283 if (private->paint_stack)
3285 GdkWindowPaint *paint = private->paint_stack->data;
3286 SETUP_PAINT_GC_CLIP (gc);
3287 gdk_draw_points (pixmap_impl (paint->pixmap), gc, new_points, npoints);
3288 RESTORE_PAINT_GC_CLIP (gc);
3292 SETUP_DIRECT_GC_CLIP(gc);
3293 gdk_draw_points (private->impl, gc, new_points, npoints);
3294 RESTORE_DIRECT_GC_CLIP(gc);
3297 if (new_points != points)
3298 g_free (new_points);
3304 gdk_window_draw_segments (GdkDrawable *drawable,
3309 GdkWindowObject *private = (GdkWindowObject *)drawable;
3310 GdkSegment *new_segs;
3314 if (GDK_WINDOW_DESTROYED (drawable))
3317 if (x_offset != 0 || y_offset != 0)
3321 new_segs = g_new (GdkSegment, nsegs);
3322 for (i=0; i<nsegs; i++)
3324 new_segs[i].x1 = segs[i].x1 - x_offset;
3325 new_segs[i].y1 = segs[i].y1 - y_offset;
3326 new_segs[i].x2 = segs[i].x2 - x_offset;
3327 new_segs[i].y2 = segs[i].y2 - y_offset;
3333 if (private->paint_stack)
3335 GdkWindowPaint *paint = private->paint_stack->data;
3336 SETUP_PAINT_GC_CLIP (gc);
3337 gdk_draw_segments (pixmap_impl (paint->pixmap), gc, new_segs, nsegs);
3338 RESTORE_PAINT_GC_CLIP (gc);
3342 SETUP_DIRECT_GC_CLIP(gc);
3343 gdk_draw_segments (private->impl, gc, new_segs, nsegs);
3344 RESTORE_DIRECT_GC_CLIP(gc);
3347 if (new_segs != segs)
3354 gdk_window_draw_lines (GdkDrawable *drawable,
3359 GdkWindowObject *private = (GdkWindowObject *)drawable;
3360 GdkPoint *new_points;
3364 if (GDK_WINDOW_DESTROYED (drawable))
3367 if (x_offset != 0 || y_offset != 0)
3371 new_points = g_new (GdkPoint, npoints);
3372 for (i=0; i<npoints; i++)
3374 new_points[i].x = points[i].x - x_offset;
3375 new_points[i].y = points[i].y - y_offset;
3379 new_points = points;
3381 if (private->paint_stack)
3383 GdkWindowPaint *paint = private->paint_stack->data;
3384 SETUP_PAINT_GC_CLIP (gc);
3385 gdk_draw_lines (pixmap_impl (paint->pixmap), gc, new_points, npoints);
3386 RESTORE_PAINT_GC_CLIP (gc);
3390 SETUP_DIRECT_GC_CLIP(gc);
3391 gdk_draw_lines (private->impl, gc, new_points, npoints);
3392 RESTORE_DIRECT_GC_CLIP(gc);
3395 if (new_points != points)
3396 g_free (new_points);
3402 gdk_window_draw_glyphs (GdkDrawable *drawable,
3407 PangoGlyphString *glyphs)
3409 GdkWindowObject *private = (GdkWindowObject *)drawable;
3413 if (GDK_WINDOW_DESTROYED (drawable))
3416 if (private->paint_stack)
3418 GdkWindowPaint *paint = private->paint_stack->data;
3420 SETUP_PAINT_GC_CLIP (gc);
3421 gdk_draw_glyphs (pixmap_impl (paint->pixmap), gc, font, x - x_offset, y - y_offset, glyphs);
3422 RESTORE_PAINT_GC_CLIP (gc);
3426 SETUP_DIRECT_GC_CLIP(gc);
3427 gdk_draw_glyphs (private->impl, gc, font,
3428 x - x_offset, y - y_offset, glyphs);
3429 RESTORE_DIRECT_GC_CLIP(gc);
3436 gdk_window_draw_glyphs_transformed (GdkDrawable *drawable,
3438 PangoMatrix *matrix,
3442 PangoGlyphString *glyphs)
3444 GdkWindowObject *private = (GdkWindowObject *)drawable;
3445 PangoMatrix tmp_matrix;
3449 if (GDK_WINDOW_DESTROYED (drawable))
3452 if (x_offset != 0 || y_offset != 0)
3456 tmp_matrix = *matrix;
3457 tmp_matrix.x0 -= x_offset;
3458 tmp_matrix.y0 -= y_offset;
3459 matrix = &tmp_matrix;
3461 else if (GDK_PANGO_UNITS_OVERFLOWS (x_offset, y_offset))
3463 PangoMatrix identity = PANGO_MATRIX_INIT;
3465 tmp_matrix = identity;
3466 tmp_matrix.x0 -= x_offset;
3467 tmp_matrix.y0 -= y_offset;
3468 matrix = &tmp_matrix;
3472 x -= x_offset * PANGO_SCALE;
3473 y -= y_offset * PANGO_SCALE;
3477 if (private->paint_stack)
3479 GdkWindowPaint *paint = private->paint_stack->data;
3481 SETUP_PAINT_GC_CLIP (gc);
3482 gdk_draw_glyphs_transformed (pixmap_impl (paint->pixmap), gc, matrix, font, x, y, glyphs);
3483 RESTORE_PAINT_GC_CLIP (gc);
3487 SETUP_DIRECT_GC_CLIP(gc);
3488 gdk_draw_glyphs_transformed (private->impl, gc, matrix, font, x, y, glyphs);
3489 RESTORE_DIRECT_GC_CLIP(gc);
3496 cairo_t *cr; /* if non-null, it means use this cairo context */
3497 GdkGC *gc; /* if non-null, it means use this GC instead */
3498 } BackingRectMethod;
3501 setup_backing_rect_method (BackingRectMethod *method, GdkWindow *window, GdkWindowPaint *paint, int x_offset_cairo, int y_offset_cairo)
3503 GdkWindowObject *private = (GdkWindowObject *)window;
3505 if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
3507 GdkWindowPaint tmp_paint;
3510 tmp_paint.x_offset += private->x;
3511 tmp_paint.y_offset += private->y;
3513 x_offset_cairo += private->x;
3514 y_offset_cairo += private->y;
3516 setup_backing_rect_method (method, GDK_WINDOW (private->parent), &tmp_paint, x_offset_cairo, y_offset_cairo);
3518 else if (private->bg_pixmap &&
3519 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
3520 private->bg_pixmap != GDK_NO_BG)
3522 /* This is a workaround for https://bugs.freedesktop.org/show_bug.cgi?id=4320.
3523 * In it, using a pixmap as a repeating pattern in Cairo, and painting it to a
3524 * pixmap destination surface, can be very slow (on the order of seconds for a
3525 * whole-screen copy). The workaround is to use pretty much the same code that
3526 * we used in GTK+ 2.6 (pre-Cairo), which clears the double-buffer pixmap with
3527 * a tiled GC XFillRectangle().
3530 /* Actually computing this flag is left as an exercise for the reader */
3531 #if defined (G_OS_UNIX)
3532 # define GDK_CAIRO_REPEAT_IS_FAST 0
3534 # define GDK_CAIRO_REPEAT_IS_FAST 1
3537 #if GDK_CAIRO_REPEAT_IS_FAST
3538 cairo_surface_t *surface = _gdk_drawable_ref_cairo_surface (private->bg_pixmap);
3539 cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
3540 cairo_surface_destroy (surface);
3542 if (x_offset_cairo != 0 || y_offset_cairo != 0)
3544 cairo_matrix_t matrix;
3545 cairo_matrix_init_translate (&matrix, x_offset_cairo, y_offset_cairo);
3546 cairo_pattern_set_matrix (pattern, &matrix);
3549 cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
3551 method->cr = cairo_create (paint->surface);
3554 cairo_set_source (method->cr, pattern);
3555 cairo_pattern_destroy (pattern);
3558 GdkGCValues gc_values;
3560 gc_values.fill = GDK_TILED;
3561 gc_values.tile = private->bg_pixmap;
3562 gc_values.ts_x_origin = -x_offset_cairo;
3563 gc_values.ts_y_origin = -y_offset_cairo;
3565 gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN;
3567 method->gc = gdk_gc_new_with_values (paint->pixmap, &gc_values, gc_mask);
3572 method->cr = cairo_create (paint->surface);
3574 gdk_cairo_set_source_color (method->cr, &private->bg_color);
3579 gdk_window_clear_backing_rect (GdkWindow *window,
3585 GdkWindowObject *private = (GdkWindowObject *)window;
3586 GdkWindowPaint *paint = private->paint_stack->data;
3587 BackingRectMethod method;
3593 if (GDK_WINDOW_DESTROYED (window))
3597 timer = g_timer_new ();
3602 setup_backing_rect_method (&method, window, paint, 0, 0);
3606 g_assert (method.gc == NULL);
3608 cairo_rectangle (method.cr, x, y, width, height);
3609 cairo_clip (method.cr);
3611 gdk_cairo_region (method.cr, paint->region);
3612 cairo_fill (method.cr);
3614 cairo_destroy (method.cr);
3616 elapsed = g_timer_elapsed (timer, NULL);
3617 g_print ("Draw the background with Cairo: %fs\n", elapsed);
3622 g_assert (method.gc != NULL);
3624 gdk_gc_set_clip_region (method.gc, paint->region);
3625 gdk_draw_rectangle (window, method.gc, TRUE, x, y, width, height);
3626 g_object_unref (method.gc);
3629 elapsed = g_timer_elapsed (timer, NULL);
3630 g_print ("Draw the background with GDK: %fs\n", elapsed);
3635 g_timer_destroy (timer);
3640 gdk_window_clear_backing_rect_redirect (GdkWindow *window,
3646 GdkWindowObject *private = (GdkWindowObject *)window;
3647 GdkWindowRedirect *redirect = private->redirect;
3648 GdkRegion *clip_region;
3649 gint x_offset, y_offset;
3650 BackingRectMethod method;
3651 GdkWindowPaint paint;
3653 if (GDK_WINDOW_DESTROYED (window))
3656 clip_region = _gdk_window_calculate_full_clip_region (window,
3657 GDK_WINDOW (redirect->redirected),
3659 &x_offset, &y_offset);
3661 paint.x_offset = x_offset;
3662 paint.y_offset = y_offset;
3663 paint.pixmap = redirect->pixmap;
3664 paint.surface = _gdk_drawable_ref_cairo_surface (redirect->pixmap);
3668 setup_backing_rect_method (&method, window, &paint, 0, 0);
3672 g_assert (method.gc == NULL);
3674 cairo_rectangle (method.cr, x, y, width, height);
3675 cairo_clip (method.cr);
3677 gdk_cairo_region (method.cr, clip_region);
3678 cairo_fill (method.cr);
3680 cairo_destroy (method.cr);
3684 g_assert (method.gc != NULL);
3686 gdk_gc_set_clip_region (method.gc, clip_region);
3687 gdk_draw_rectangle (window, method.gc, TRUE, x, y, width, height);
3688 g_object_unref (method.gc);
3692 gdk_region_destroy (clip_region);
3693 cairo_surface_destroy (paint.surface);
3697 gdk_window_clear_backing_rect_direct (GdkWindow *window,
3703 GdkWindowObject *private = (GdkWindowObject *)window;
3704 BackingRectMethod method;
3705 GdkWindowPaint paint;
3707 if (GDK_WINDOW_DESTROYED (window))
3712 paint.pixmap = window;
3713 paint.surface = _gdk_drawable_ref_cairo_surface (window);
3717 setup_backing_rect_method (&method, window, &paint, 0, 0);
3721 g_assert (method.gc == NULL);
3723 gdk_cairo_region (method.cr, private->clip_region_with_children);
3724 cairo_clip (method.cr);
3726 cairo_rectangle (method.cr, x, y, width, height);
3727 cairo_fill (method.cr);
3729 cairo_destroy (method.cr);
3733 g_assert (method.gc != NULL);
3735 gdk_gc_set_clip_region (method.gc, private->clip_region_with_children);
3736 gdk_draw_rectangle (window, method.gc, TRUE, x, y, width, height);
3737 g_object_unref (method.gc);
3741 cairo_surface_destroy (paint.surface);
3747 * @window: a #GdkWindow
3749 * Clears an entire @window to the background color or background pixmap.
3752 gdk_window_clear (GdkWindow *window)
3756 g_return_if_fail (GDK_IS_WINDOW (window));
3758 gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height);
3760 gdk_window_clear_area (window, 0, 0,
3765 gdk_window_clear_area_internal (GdkWindow *window,
3770 gboolean send_expose)
3772 GdkWindowObject *private = (GdkWindowObject *)window;
3774 g_return_if_fail (GDK_IS_WINDOW (window));
3776 /* This is what XClearArea does, and e.g. GtkCList uses it,
3777 so we need to duplicate that */
3779 width = private->width - x;
3781 height = private->height - y;
3783 if (private->paint_stack)
3784 gdk_window_clear_backing_rect (window, x, y, width, height);
3787 if (private->redirect)
3788 gdk_window_clear_backing_rect_redirect (window, x, y, width, height);
3790 gdk_window_clear_backing_rect_direct (window, x, y, width, height);
3798 rect.height = height;
3800 gdk_window_invalidate_rect (window, &rect, FALSE);
3807 * gdk_window_clear_area:
3808 * @window: a #GdkWindow
3809 * @x: x coordinate of rectangle to clear
3810 * @y: y coordinate of rectangle to clear
3811 * @width: width of rectangle to clear
3812 * @height: height of rectangle to clear
3814 * Clears an area of @window to the background color or background pixmap.
3818 gdk_window_clear_area (GdkWindow *window,
3824 gdk_window_clear_area_internal (window,
3831 * gdk_window_clear_area_e:
3832 * @window: a #GdkWindow
3833 * @x: x coordinate of rectangle to clear
3834 * @y: y coordinate of rectangle to clear
3835 * @width: width of rectangle to clear
3836 * @height: height of rectangle to clear
3838 * Like gdk_window_clear_area(), but also generates an expose event for
3841 * This function has a stupid name because it dates back to the mists
3842 * time, pre-GDK-1.0.
3846 gdk_window_clear_area_e (GdkWindow *window,
3852 gdk_window_clear_area_internal (window,
3859 gdk_window_draw_image (GdkDrawable *drawable,
3869 GdkWindowObject *private = (GdkWindowObject *)drawable;
3873 if (GDK_WINDOW_DESTROYED (drawable))
3876 if (private->paint_stack)
3878 GdkWindowPaint *paint = private->paint_stack->data;
3879 SETUP_PAINT_GC_CLIP (gc);
3880 gdk_draw_image (pixmap_impl (paint->pixmap), gc, image, xsrc, ysrc,
3881 xdest - x_offset, ydest - y_offset,
3884 RESTORE_PAINT_GC_CLIP (gc);
3888 SETUP_DIRECT_GC_CLIP(gc);
3889 gdk_draw_image (private->impl, gc, image, xsrc, ysrc,
3890 xdest - x_offset, ydest - y_offset,
3892 RESTORE_DIRECT_GC_CLIP(gc);
3899 gdk_window_draw_pixbuf (GdkDrawable *drawable,
3908 GdkRgbDither dither,
3912 GdkWindowObject *private = (GdkWindowObject *)drawable;
3914 if (GDK_WINDOW_DESTROYED (drawable))
3917 /* If no gc => no user clipping, but we need clipping
3918 for window emulation, so use a scratch gc */
3920 gc = _gdk_drawable_get_scratch_gc (drawable, FALSE);
3922 /* Need block to make OFFSET_GC macro to work */
3926 if (private->paint_stack)
3928 GdkWindowPaint *paint = private->paint_stack->data;
3929 SETUP_PAINT_GC_CLIP (gc);
3930 gdk_draw_pixbuf (pixmap_impl (paint->pixmap), gc, pixbuf, src_x, src_y,
3931 dest_x - x_offset, dest_y - y_offset,
3933 dither, x_dither - x_offset, y_dither - y_offset);
3934 RESTORE_PAINT_GC_CLIP (gc);
3938 SETUP_DIRECT_GC_CLIP(gc);
3939 gdk_draw_pixbuf (private->impl, gc, pixbuf, src_x, src_y,
3940 dest_x - x_offset, dest_y - y_offset,
3942 dither, x_dither, y_dither);
3943 RESTORE_DIRECT_GC_CLIP(gc);
3951 gdk_window_draw_trapezoids (GdkDrawable *drawable,
3953 GdkTrapezoid *trapezoids,
3956 GdkWindowObject *private = (GdkWindowObject *)drawable;
3957 GdkTrapezoid *new_trapezoids = NULL;
3961 if (GDK_WINDOW_DESTROYED (drawable))
3964 if (x_offset != 0 || y_offset != 0)
3968 new_trapezoids = g_new (GdkTrapezoid, n_trapezoids);
3969 for (i=0; i < n_trapezoids; i++)
3971 new_trapezoids[i].y1 = trapezoids[i].y1 - y_offset;
3972 new_trapezoids[i].x11 = trapezoids[i].x11 - x_offset;
3973 new_trapezoids[i].x21 = trapezoids[i].x21 - x_offset;
3974 new_trapezoids[i].y2 = trapezoids[i].y2 - y_offset;
3975 new_trapezoids[i].x12 = trapezoids[i].x12 - x_offset;
3976 new_trapezoids[i].x22 = trapezoids[i].x22 - x_offset;
3979 trapezoids = new_trapezoids;
3982 if (private->paint_stack)
3984 GdkWindowPaint *paint = private->paint_stack->data;
3985 SETUP_PAINT_GC_CLIP (gc);
3986 gdk_draw_trapezoids (pixmap_impl (paint->pixmap), gc, trapezoids, n_trapezoids);
3987 RESTORE_PAINT_GC_CLIP (gc);
3991 SETUP_DIRECT_GC_CLIP(gc);
3992 gdk_draw_trapezoids (private->impl, gc, trapezoids, n_trapezoids);
3993 RESTORE_DIRECT_GC_CLIP(gc);
3996 g_free (new_trapezoids);
4002 gdk_window_real_get_size (GdkDrawable *drawable,
4006 GdkWindowObject *private = (GdkWindowObject *)drawable;
4009 *width = private->width;
4011 *height = private->height;
4015 gdk_window_real_get_visual (GdkDrawable *drawable)
4017 GdkColormap *colormap;
4019 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4021 colormap = gdk_drawable_get_colormap (drawable);
4022 return colormap ? gdk_colormap_get_visual (colormap) : NULL;
4026 gdk_window_real_get_depth (GdkDrawable *drawable)
4028 g_return_val_if_fail (GDK_IS_WINDOW (drawable), 0);
4030 return ((GdkWindowObject *)GDK_WINDOW (drawable))->depth;
4034 gdk_window_real_get_screen (GdkDrawable *drawable)
4036 return gdk_drawable_get_screen (GDK_WINDOW_OBJECT (drawable)->impl);
4040 gdk_window_real_set_colormap (GdkDrawable *drawable,
4043 GdkWindowObject *private;
4045 g_return_if_fail (GDK_IS_WINDOW (drawable));
4047 if (GDK_WINDOW_DESTROYED (drawable))
4050 private = (GdkWindowObject *)drawable;
4052 /* different colormap than parent, requires native window */
4053 if (!private->input_only &&
4054 cmap != gdk_drawable_get_colormap ((GdkDrawable *)(private->parent)))
4055 gdk_window_set_has_native ((GdkWindow *)drawable, TRUE);
4057 gdk_drawable_set_colormap (private->impl, cmap);
4061 gdk_window_real_get_colormap (GdkDrawable *drawable)
4063 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4065 if (GDK_WINDOW_DESTROYED (drawable))
4068 return gdk_drawable_get_colormap (((GdkWindowObject*)drawable)->impl);
4072 gdk_window_copy_to_image (GdkDrawable *drawable,
4081 GdkWindowObject *private = (GdkWindowObject *) drawable;
4082 gint x_offset, y_offset;
4084 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4086 if (GDK_WINDOW_DESTROYED (drawable))
4089 /* If we're here, a composite image was not necessary, so
4090 * we can ignore the paint stack.
4093 /* TODO: Is this right? */
4097 return gdk_drawable_copy_to_image (private->impl,
4106 gdk_window_cairo_surface_destroy (void *data)
4108 GdkWindowObject *private = (GdkWindowObject*) data;
4110 private->cairo_surface = NULL;
4113 static cairo_surface_t *
4114 gdk_window_create_cairo_surface (GdkDrawable *drawable,
4118 return _gdk_windowing_create_cairo_surface (GDK_WINDOW_OBJECT(drawable)->impl,
4123 static cairo_surface_t *
4124 gdk_window_ref_cairo_surface (GdkDrawable *drawable)
4126 GdkWindowObject *private = (GdkWindowObject*) drawable;
4127 cairo_surface_t *surface;
4129 if (private->paint_stack)
4131 GdkWindowPaint *paint = private->paint_stack->data;
4133 surface = paint->surface;
4134 cairo_surface_reference (surface);
4139 /* This will be drawing directly to the window, so flush implicit paint */
4140 gdk_window_flush ((GdkWindow *)drawable);
4142 if (!private->cairo_surface)
4145 GdkDrawable *source;
4147 /* It would be nice if we had some cairo support here so we
4148 could set the clip rect on the cairo surface */
4149 width = private->abs_x + private->width;
4150 height = private->abs_y + private->height;
4152 source = _gdk_drawable_get_source_drawable (drawable);
4154 /* TODO: Avoid the typecheck crap by adding virtual call */
4155 private->cairo_surface = _gdk_drawable_create_cairo_surface (source, width, height);
4157 if (private->cairo_surface)
4159 cairo_surface_set_device_offset (private->cairo_surface,
4163 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
4164 drawable, gdk_window_cairo_surface_destroy);
4168 cairo_surface_reference (private->cairo_surface);
4170 surface = private->cairo_surface;
4177 gdk_window_set_cairo_clip (GdkDrawable *drawable,
4180 GdkWindowObject *private = (GdkWindowObject*) drawable;
4182 if (!private->paint_stack)
4185 cairo_identity_matrix (cr);
4187 cairo_reset_clip (cr);
4189 cairo_new_path (cr);
4190 gdk_cairo_region (cr, private->clip_region);
4197 GdkWindowPaint *paint = private->paint_stack->data;
4199 /* Only needs to clip to region if piggybacking
4200 on an implicit paint pixmap */
4201 if (paint->uses_implicit)
4204 cairo_identity_matrix (cr);
4206 cairo_reset_clip (cr);
4208 cairo_new_path (cr);
4209 gdk_cairo_region (cr, paint->region);
4217 /* Code for dirty-region queueing
4219 static GSList *update_windows = NULL;
4220 static guint update_idle = 0;
4221 static gboolean debug_updates = FALSE;
4223 static inline gboolean
4224 gdk_window_is_ancestor (GdkWindow *window,
4225 GdkWindow *ancestor)
4229 GdkWindow *parent = (GdkWindow*) ((GdkWindowObject*) window)->parent;
4231 if (parent == ancestor)
4241 gdk_window_add_update_window (GdkWindow *window)
4244 GSList *prev = NULL;
4245 gboolean has_ancestor_in_list = FALSE;
4247 for (tmp = update_windows; tmp; tmp = tmp->next)
4249 GdkWindowObject *parent = GDK_WINDOW_OBJECT (window)->parent;
4251 /* check if tmp is an ancestor of "window"; if it is, set a
4252 * flag indicating that all following windows are either
4253 * children of "window" or from a differen hierarchy
4255 if (!has_ancestor_in_list && gdk_window_is_ancestor (window, tmp->data))
4256 has_ancestor_in_list = TRUE;
4258 /* insert in reverse stacking order when adding around siblings,
4259 * so processing updates properly paints over lower stacked windows
4261 if (parent == GDK_WINDOW_OBJECT (tmp->data)->parent)
4263 gint index = g_list_index (parent->children, window);
4264 for (; tmp && parent == GDK_WINDOW_OBJECT (tmp->data)->parent; tmp = tmp->next)
4266 gint sibling_index = g_list_index (parent->children, tmp->data);
4267 if (index > sibling_index)
4271 /* here, tmp got advanced past all lower stacked siblings */
4272 tmp = g_slist_prepend (tmp, window);
4276 update_windows = tmp;
4280 /* if "window" has an ancestor in the list and tmp is one of
4281 * "window's" children, insert "window" before tmp
4283 if (has_ancestor_in_list && gdk_window_is_ancestor (tmp->data, window))
4285 tmp = g_slist_prepend (tmp, window);
4290 update_windows = tmp;
4294 /* if we're at the end of the list and had an ancestor it it,
4295 * append to the list
4297 if (! tmp->next && has_ancestor_in_list)
4299 tmp = g_slist_append (tmp, window);
4306 /* if all above checks failed ("window" is from a different
4307 * hierarchy than what is already in the list) or the list is
4310 update_windows = g_slist_prepend (update_windows, window);
4314 gdk_window_remove_update_window (GdkWindow *window)
4316 update_windows = g_slist_remove (update_windows, window);
4320 gdk_window_update_idle (gpointer data)
4322 gdk_window_process_all_updates ();
4328 gdk_window_is_toplevel_frozen (GdkWindow *window)
4330 GdkWindowObject *toplevel;
4332 toplevel = (GdkWindowObject *)gdk_window_get_toplevel (window);
4334 return toplevel->update_and_descendants_freeze_count > 0;
4338 gdk_window_schedule_update (GdkWindow *window)
4341 (GDK_WINDOW_OBJECT (window)->update_freeze_count ||
4342 gdk_window_is_toplevel_frozen (window)))
4347 update_idle = gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
4348 gdk_window_update_idle, NULL, NULL);
4353 gdk_window_process_updates_recurse (GdkWindow *window,
4354 GdkRegion *expose_region)
4356 GdkWindowObject *private = (GdkWindowObject *)window;
4357 GdkWindowObject *child;
4358 GdkRegion *child_region;
4362 if (gdk_region_empty (expose_region))
4365 /* Iterate over children, starting at topmost */
4366 for (l = private->children; l != NULL; l = l->next)
4370 if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
4373 /* Ignore offscreen children, as they don't draw in their parent and
4374 * don't take part in the clipping */
4375 if (gdk_window_is_offscreen (child))
4380 r.width = child->width;
4381 r.height = child->height;
4383 child_region = gdk_region_rectangle (&r);
4385 gdk_region_intersect (child_region, child->shape);
4387 if (child->impl == private->impl)
4389 /* Client side child, expose */
4390 gdk_region_intersect (child_region, expose_region);
4391 gdk_region_subtract (expose_region, child_region);
4392 gdk_region_offset (child_region, -child->x, -child->y);
4393 gdk_window_process_updates_recurse ((GdkWindow *)child, child_region);
4397 /* Native child, just remove area from expose region */
4398 gdk_region_subtract (expose_region, child_region);
4400 gdk_region_destroy (child_region);
4403 if (private->event_mask & GDK_EXPOSURE_MASK &&
4404 !gdk_region_empty (expose_region))
4408 event.expose.type = GDK_EXPOSE;
4409 event.expose.window = g_object_ref (window);
4410 event.expose.send_event = FALSE;
4411 event.expose.count = 0;
4412 event.expose.region = expose_region;
4413 gdk_region_get_clipbox (expose_region, &event.expose.area);
4415 (*_gdk_event_func) (&event, _gdk_event_data);
4417 g_object_unref (window);
4422 gdk_window_process_updates_internal (GdkWindow *window)
4424 GdkWindowObject *private = (GdkWindowObject *)window;
4425 gboolean save_region = FALSE;
4426 GdkRectangle clip_box;
4428 /* If an update got queued during update processing, we can get a
4429 * window in the update queue that has an empty update_area.
4432 if (private->update_area)
4434 GdkRegion *update_area = private->update_area;
4435 private->update_area = NULL;
4437 if (_gdk_event_func && gdk_window_is_viewable (window))
4439 GdkRectangle window_rect;
4440 GdkRegion *expose_region;
4441 GdkRegion *window_region;
4442 gboolean end_implicit;
4444 /* Clip to part visible in toplevel */
4445 gdk_region_intersect (update_area, private->clip_region);
4449 /* Make sure we see the red invalid area before redrawing. */
4450 gdk_display_sync (gdk_drawable_get_display (window));
4454 save_region = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->queue_antiexpose (window, update_area);
4456 expose_region = gdk_region_copy (update_area);
4458 expose_region = update_area;
4462 window_rect.width = private->width;
4463 window_rect.height = private->height;
4465 window_region = gdk_region_rectangle (&window_rect);
4466 gdk_region_intersect (expose_region,
4468 gdk_region_destroy (window_region);
4470 gdk_region_get_clipbox (expose_region, &clip_box);
4471 end_implicit = gdk_window_begin_implicit_paint (window, &clip_box);
4472 gdk_window_process_updates_recurse (window, expose_region);
4474 gdk_window_end_implicit_paint (window);
4476 if (expose_region != update_area)
4477 gdk_region_destroy (expose_region);
4480 gdk_region_destroy (update_area);
4483 if (private->outstanding_moves)
4485 /* Flush any outstanding moves, may happen if we moved a window but got
4486 no actual invalid area */
4487 gdk_window_flush (window);
4492 flush_all_displays (void)
4494 GSList *displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
4497 for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
4498 gdk_display_flush (tmp_list->data);
4500 g_slist_free (displays);
4503 /* Currently it is not possible to override
4504 * gdk_window_process_all_updates in the same manner as
4505 * gdk_window_process_updates and gdk_window_invalidate_maybe_recurse
4506 * by implementing the GdkPaintable interface. If in the future a
4507 * backend would need this, the right solution would be to add a
4508 * method to GdkDisplay that can be optionally
4509 * NULL. gdk_window_process_all_updates can then walk the list of open
4510 * displays and call the mehod.
4514 * gdk_window_process_all_updates:
4516 * Calls gdk_window_process_updates() for all windows (see #GdkWindow)
4517 * in the application.
4521 gdk_window_process_all_updates (void)
4523 GSList *old_update_windows = update_windows;
4524 GSList *tmp_list = update_windows;
4527 g_source_remove (update_idle);
4529 update_windows = NULL;
4532 g_slist_foreach (old_update_windows, (GFunc)g_object_ref, NULL);
4536 GdkWindowObject *private = (GdkWindowObject *)tmp_list->data;
4538 if (!GDK_WINDOW_DESTROYED (tmp_list->data))
4540 if (private->update_freeze_count ||
4541 gdk_window_is_toplevel_frozen (tmp_list->data))
4542 gdk_window_add_update_window ((GdkWindow *) private);
4544 gdk_window_process_updates_internal (tmp_list->data);
4547 g_object_unref (tmp_list->data);
4548 tmp_list = tmp_list->next;
4551 g_slist_free (old_update_windows);
4553 flush_all_displays ();
4557 * gdk_window_process_updates:
4558 * @window: a #GdkWindow
4559 * @update_children: whether to also process updates for child windows
4561 * Sends one or more expose events to @window. The areas in each
4562 * expose event will cover the entire update area for the window (see
4563 * gdk_window_invalidate_region() for details). Normally GDK calls
4564 * gdk_window_process_all_updates() on your behalf, so there's no
4565 * need to call this function unless you want to force expose events
4566 * to be delivered immediately and synchronously (vs. the usual
4567 * case, where GDK delivers them in an idle handler). Occasionally
4568 * this is useful to produce nicer scrolling behavior, for example.
4572 gdk_window_process_updates (GdkWindow *window,
4573 gboolean update_children)
4575 GdkWindowObject *private = (GdkWindowObject *)window;
4576 GdkWindowObject *impl_window;
4578 g_return_if_fail (GDK_IS_WINDOW (window));
4580 if (GDK_IS_PAINTABLE (private->impl))
4582 GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
4584 if (iface->process_updates)
4585 iface->process_updates ((GdkPaintable*)private->impl, update_children);
4590 impl_window = gdk_window_get_impl_window (private);
4591 if ((impl_window->update_area ||
4592 impl_window->outstanding_moves) &&
4593 !impl_window->update_freeze_count &&
4594 !gdk_window_is_toplevel_frozen (window))
4596 gdk_window_process_updates_internal ((GdkWindow *)impl_window);
4597 gdk_window_remove_update_window ((GdkWindow *)impl_window);
4600 if (update_children)
4602 /* process updates in reverse stacking order so composition or
4603 * painting over achieves the desired effect for offscreen windows
4606 for (node = g_list_last (private->children); node; node = node->prev)
4607 gdk_window_process_updates (node->data, TRUE);
4612 * gdk_window_invalidate_rect:
4613 * @window: a #GdkWindow
4614 * @rect: rectangle to invalidate or %NULL to invalidate the whole
4616 * @invalidate_children: whether to also invalidate child windows
4618 * A convenience wrapper around gdk_window_invalidate_region() which
4619 * invalidates a rectangular region. See
4620 * gdk_window_invalidate_region() for details.
4623 gdk_window_invalidate_rect (GdkWindow *window,
4624 const GdkRectangle *rect,
4625 gboolean invalidate_children)
4627 GdkRectangle window_rect;
4629 GdkWindowObject *private = (GdkWindowObject *)window;
4631 g_return_if_fail (GDK_IS_WINDOW (window));
4633 if (GDK_WINDOW_DESTROYED (window))
4636 if (private->input_only || !GDK_WINDOW_IS_MAPPED (window))
4643 gdk_drawable_get_size (GDK_DRAWABLE (window),
4645 &window_rect.height);
4646 rect = &window_rect;
4649 region = gdk_region_rectangle (rect);
4650 gdk_window_invalidate_region (window, region, invalidate_children);
4651 gdk_region_destroy (region);
4655 draw_ugly_color (GdkWindow *window,
4656 const GdkRegion *region)
4658 /* Draw ugly color all over the newly-invalid region */
4659 GdkColor ugly_color = { 0, 50000, 10000, 10000 };
4661 GdkRectangle clipbox;
4663 ugly_gc = gdk_gc_new (window);
4664 gdk_gc_set_rgb_fg_color (ugly_gc, &ugly_color);
4665 gdk_gc_set_clip_region (ugly_gc, region);
4667 gdk_region_get_clipbox (region, &clipbox);
4669 gdk_draw_rectangle (window,
4672 clipbox.x, clipbox.y,
4673 clipbox.width, clipbox.height);
4675 g_object_unref (ugly_gc);
4679 * gdk_window_invalidate_maybe_recurse:
4680 * @window: a #GdkWindow
4681 * @region: a #GdkRegion
4682 * @child_func: function to use to decide if to recurse to a child,
4683 * %NULL means never recurse.
4684 * @user_data: data passed to @child_func
4686 * Adds @region to the update area for @window. The update area is the
4687 * region that needs to be redrawn, or "dirty region." The call
4688 * gdk_window_process_updates() sends one or more expose events to the
4689 * window, which together cover the entire update area. An
4690 * application would normally redraw the contents of @window in
4691 * response to those expose events.
4693 * GDK will call gdk_window_process_all_updates() on your behalf
4694 * whenever your program returns to the main loop and becomes idle, so
4695 * normally there's no need to do that manually, you just need to
4696 * invalidate regions that you know should be redrawn.
4698 * The @child_func parameter controls whether the region of
4699 * each child window that intersects @region will also be invalidated.
4700 * Only children for which @child_func returns TRUE will have the area
4704 gdk_window_invalidate_maybe_recurse (GdkWindow *window,
4705 const GdkRegion *region,
4706 gboolean (*child_func) (GdkWindow *,
4710 GdkWindowObject *private = (GdkWindowObject *)window;
4711 GdkWindowObject *impl_window;
4712 GdkRegion *visible_region;
4715 g_return_if_fail (GDK_IS_WINDOW (window));
4717 if (GDK_WINDOW_DESTROYED (window))
4720 if (private->input_only || !GDK_WINDOW_IS_MAPPED (window))
4723 if (GDK_IS_PAINTABLE (private->impl))
4725 GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
4727 if (iface->invalidate_maybe_recurse)
4728 iface->invalidate_maybe_recurse ((GdkPaintable*)private->impl,
4729 region, child_func, user_data);
4733 visible_region = gdk_drawable_get_visible_region (window);
4734 gdk_region_intersect (visible_region, region);
4736 tmp_list = private->children;
4739 GdkWindowObject *child = tmp_list->data;
4741 if (!child->input_only)
4743 GdkRegion *child_region;
4744 GdkRectangle child_rect;
4746 child_rect.x = child->x;
4747 child_rect.y = child->y;
4748 child_rect.width = child->width;
4749 child_rect.height = child->height;
4750 child_region = gdk_region_rectangle (&child_rect);
4752 /* remove child area from the invalid area of the parent */
4753 if (GDK_WINDOW_IS_MAPPED (child) && !child->shaped &&
4754 !child->composited &&
4755 !gdk_window_is_offscreen (child))
4756 gdk_region_subtract (visible_region, child_region);
4758 if (child_func && (*child_func) ((GdkWindow *)child, user_data))
4760 GdkRegion *tmp = gdk_region_copy (region);
4762 gdk_region_offset (tmp, - child_rect.x, - child_rect.y);
4763 gdk_region_offset (child_region, - child_rect.x, - child_rect.y);
4764 gdk_region_intersect (child_region, tmp);
4766 gdk_window_invalidate_maybe_recurse ((GdkWindow *)child,
4767 child_region, child_func, user_data);
4769 gdk_region_destroy (tmp);
4772 gdk_region_destroy (child_region);
4775 tmp_list = tmp_list->next;
4778 impl_window = gdk_window_get_impl_window (private);
4780 if (!gdk_region_empty (visible_region) ||
4781 /* Even if we're not exposing anything, make sure we process
4782 idles for windows with outstanding moves */
4783 (impl_window->outstanding_moves != NULL &&
4784 impl_window->update_area == NULL))
4787 draw_ugly_color (window, region);
4789 /* Convert to impl coords */
4790 gdk_region_offset (visible_region, private->abs_x, private->abs_y);
4791 if (impl_window->update_area)
4793 gdk_region_union (impl_window->update_area, visible_region);
4797 gdk_window_add_update_window ((GdkWindow *)impl_window);
4798 impl_window->update_area = gdk_region_copy (visible_region);
4800 gdk_window_schedule_update ((GdkWindow *)impl_window);
4804 gdk_region_destroy (visible_region);
4808 true_predicate (GdkWindow *window,
4815 * gdk_window_invalidate_region:
4816 * @window: a #GdkWindow
4817 * @region: a #GdkRegion
4818 * @invalidate_children: %TRUE to also invalidate child windows
4820 * Adds @region to the update area for @window. The update area is the
4821 * region that needs to be redrawn, or "dirty region." The call
4822 * gdk_window_process_updates() sends one or more expose events to the
4823 * window, which together cover the entire update area. An
4824 * application would normally redraw the contents of @window in
4825 * response to those expose events.
4827 * GDK will call gdk_window_process_all_updates() on your behalf
4828 * whenever your program returns to the main loop and becomes idle, so
4829 * normally there's no need to do that manually, you just need to
4830 * invalidate regions that you know should be redrawn.
4832 * The @invalidate_children parameter controls whether the region of
4833 * each child window that intersects @region will also be invalidated.
4834 * If %FALSE, then the update area for child windows will remain
4835 * unaffected. See gdk_window_invalidate_maybe_recurse if you need
4836 * fine grained control over which children are invalidated.
4839 gdk_window_invalidate_region (GdkWindow *window,
4840 const GdkRegion *region,
4841 gboolean invalidate_children)
4843 gdk_window_invalidate_maybe_recurse (window, region,
4844 invalidate_children ?
4845 true_predicate : (gboolean (*) (GdkWindow *, gpointer))NULL,
4850 * _gdk_window_invalidate_for_expose:
4851 * @window: a #GdkWindow
4852 * @region: a #GdkRegion
4854 * Adds @region to the update area for @window. The update area is the
4855 * region that needs to be redrawn, or "dirty region." The call
4856 * gdk_window_process_updates() sends one or more expose events to the
4857 * window, which together cover the entire update area. An
4858 * application would normally redraw the contents of @window in
4859 * response to those expose events.
4861 * GDK will call gdk_window_process_all_updates() on your behalf
4862 * whenever your program returns to the main loop and becomes idle, so
4863 * normally there's no need to do that manually, you just need to
4864 * invalidate regions that you know should be redrawn.
4866 * This version of invalidation is used when you recieve expose events
4867 * from the native window system. It exposes the native window, plus
4868 * any non-native child windows (but not native child windows, as those would
4869 * have gotten their own expose events).
4872 _gdk_window_invalidate_for_expose (GdkWindow *window,
4873 const GdkRegion *region)
4875 gdk_window_invalidate_maybe_recurse (window, region,
4876 (gboolean (*) (GdkWindow *, gpointer))gdk_window_has_no_impl,
4882 * gdk_window_get_update_area:
4883 * @window: a #GdkWindow
4885 * Transfers ownership of the update area from @window to the caller
4886 * of the function. That is, after calling this function, @window will
4887 * no longer have an invalid/dirty region; the update area is removed
4888 * from @window and handed to you. If a window has no update area,
4889 * gdk_window_get_update_area() returns %NULL. You are responsible for
4890 * calling gdk_region_destroy() on the returned region if it's non-%NULL.
4892 * Return value: the update area for @window
4895 gdk_window_get_update_area (GdkWindow *window)
4897 GdkWindowObject *private = (GdkWindowObject *)window;
4898 GdkWindowObject *impl_window;
4899 GdkRegion *tmp_region;
4901 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
4903 impl_window = gdk_window_get_impl_window (private);
4905 if (impl_window->update_area)
4907 tmp_region = gdk_region_copy (private->clip_region_with_children);
4908 /* Convert to impl coords */
4909 gdk_region_offset (tmp_region, private->abs_x, private->abs_y);
4910 gdk_region_intersect (tmp_region, impl_window->update_area);
4912 if (gdk_region_empty (tmp_region))
4914 gdk_region_destroy (tmp_region);
4919 gdk_region_subtract (impl_window->update_area, tmp_region);
4921 if (gdk_region_empty (impl_window->update_area) &&
4922 impl_window->outstanding_moves == NULL)
4924 gdk_region_destroy (impl_window->update_area);
4925 impl_window->update_area = NULL;
4927 gdk_window_remove_update_window ((GdkWindow *)impl_window);
4930 /* Convert from impl coords */
4931 gdk_region_offset (tmp_region, -private->abs_x, -private->abs_y);
4941 * _gdk_window_clear_update_area:
4942 * @window: a #GdkWindow.
4944 * Internal function to clear the update area for a window. This
4945 * is called when the window is hidden or destroyed.
4948 _gdk_window_clear_update_area (GdkWindow *window)
4950 GdkWindowObject *private = (GdkWindowObject *)window;
4952 g_return_if_fail (GDK_IS_WINDOW (window));
4954 if (private->update_area)
4956 gdk_window_remove_update_window (window);
4958 gdk_region_destroy (private->update_area);
4959 private->update_area = NULL;
4964 * gdk_window_freeze_updates:
4965 * @window: a #GdkWindow
4967 * Temporarily freezes a window such that it won't receive expose
4968 * events. The window will begin receiving expose events again when
4969 * gdk_window_thaw_updates() is called. If gdk_window_freeze_updates()
4970 * has been called more than once, gdk_window_thaw_updates() must be called
4971 * an equal number of times to begin processing exposes.
4974 gdk_window_freeze_updates (GdkWindow *window)
4976 GdkWindowObject *private = (GdkWindowObject *)window;
4977 GdkWindowObject *impl_window;
4979 g_return_if_fail (GDK_IS_WINDOW (window));
4981 impl_window = gdk_window_get_impl_window (private);
4982 impl_window->update_freeze_count++;
4986 * gdk_window_thaw_updates:
4987 * @window: a #GdkWindow
4989 * Thaws a window frozen with gdk_window_freeze_updates().
4992 gdk_window_thaw_updates (GdkWindow *window)
4994 GdkWindowObject *private = (GdkWindowObject *)window;
4995 GdkWindowObject *impl_window;
4997 g_return_if_fail (GDK_IS_WINDOW (window));
4998 g_return_if_fail (private->update_freeze_count > 0);
5000 impl_window = gdk_window_get_impl_window (private);
5002 if (--impl_window->update_freeze_count == 0)
5003 gdk_window_schedule_update (GDK_WINDOW (impl_window));
5007 * gdk_window_freeze_toplevel_updates_libgtk_only:
5008 * @window: a #GdkWindow
5010 * Temporarily freezes a window and all its descendants such that it won't
5011 * receive expose events. The window will begin receiving expose events
5012 * again when gdk_window_thaw_toplevel_updates_libgtk_only() is called. If
5013 * gdk_window_freeze_toplevel_updates_libgtk_only()
5014 * has been called more than once,
5015 * gdk_window_thaw_toplevel_updates_libgtk_only() must be called
5016 * an equal number of times to begin processing exposes.
5018 * This function is not part of the GDK public API and is only
5022 gdk_window_freeze_toplevel_updates_libgtk_only (GdkWindow *window)
5024 GdkWindowObject *private = (GdkWindowObject *)window;
5026 g_return_if_fail (GDK_IS_WINDOW (window));
5027 g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
5029 private->update_and_descendants_freeze_count++;
5033 * gdk_window_thaw_toplevel_updates_libgtk_only:
5034 * @window: a #GdkWindow
5036 * Thaws a window frozen with
5037 * gdk_window_freeze_toplevel_updates_libgtk_only().
5039 * This function is not part of the GDK public API and is only
5043 gdk_window_thaw_toplevel_updates_libgtk_only (GdkWindow *window)
5045 GdkWindowObject *private = (GdkWindowObject *)window;
5047 g_return_if_fail (GDK_IS_WINDOW (window));
5048 g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
5049 g_return_if_fail (private->update_and_descendants_freeze_count > 0);
5051 private->update_and_descendants_freeze_count--;
5053 gdk_window_schedule_update (window);
5057 * gdk_window_set_debug_updates:
5058 * @setting: %TRUE to turn on update debugging
5060 * With update debugging enabled, calls to
5061 * gdk_window_invalidate_region() clear the invalidated region of the
5062 * screen to a noticeable color, and GDK pauses for a short time
5063 * before sending exposes to windows during
5064 * gdk_window_process_updates(). The net effect is that you can see
5065 * the invalid region for each window and watch redraws as they
5066 * occur. This allows you to diagnose inefficiencies in your application.
5068 * In essence, because the GDK rendering model prevents all flicker,
5069 * if you are redrawing the same region 400 times you may never
5070 * notice, aside from noticing a speed problem. Enabling update
5071 * debugging causes GTK to flicker slowly and noticeably, so you can
5072 * see exactly what's being redrawn when, in what order.
5074 * The --gtk-debug=updates command line option passed to GTK+ programs
5075 * enables this debug option at application startup time. That's
5076 * usually more useful than calling gdk_window_set_debug_updates()
5077 * yourself, though you might want to use this function to enable
5078 * updates sometime after application startup time.
5082 gdk_window_set_debug_updates (gboolean setting)
5084 debug_updates = setting;
5088 * gdk_window_constrain_size:
5089 * @geometry: a #GdkGeometry structure
5090 * @flags: a mask indicating what portions of @geometry are set
5091 * @width: desired width of window
5092 * @height: desired height of the window
5093 * @new_width: location to store resulting width
5094 * @new_height: location to store resulting height
5096 * Constrains a desired width and height according to a
5097 * set of geometry hints (such as minimum and maximum size).
5100 gdk_window_constrain_size (GdkGeometry *geometry,
5107 /* This routine is partially borrowed from fvwm.
5109 * Copyright 1993, Robert Nation
5110 * You may use this code for any purpose, as long as the original
5111 * copyright remains in the source code and all documentation
5113 * which in turn borrows parts of the algorithm from uwm
5116 gint min_height = 0;
5117 gint base_width = 0;
5118 gint base_height = 0;
5121 gint max_width = G_MAXINT;
5122 gint max_height = G_MAXINT;
5124 #define FLOOR(value, base) ( ((gint) ((value) / (base))) * (base) )
5126 if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
5128 base_width = geometry->base_width;
5129 base_height = geometry->base_height;
5130 min_width = geometry->min_width;
5131 min_height = geometry->min_height;
5133 else if (flags & GDK_HINT_BASE_SIZE)
5135 base_width = geometry->base_width;
5136 base_height = geometry->base_height;
5137 min_width = geometry->base_width;
5138 min_height = geometry->base_height;
5140 else if (flags & GDK_HINT_MIN_SIZE)
5142 base_width = geometry->min_width;
5143 base_height = geometry->min_height;
5144 min_width = geometry->min_width;
5145 min_height = geometry->min_height;
5148 if (flags & GDK_HINT_MAX_SIZE)
5150 max_width = geometry->max_width ;
5151 max_height = geometry->max_height;
5154 if (flags & GDK_HINT_RESIZE_INC)
5156 xinc = MAX (xinc, geometry->width_inc);
5157 yinc = MAX (yinc, geometry->height_inc);
5160 /* clamp width and height to min and max values
5162 width = CLAMP (width, min_width, max_width);
5163 height = CLAMP (height, min_height, max_height);
5165 /* shrink to base + N * inc
5167 width = base_width + FLOOR (width - base_width, xinc);
5168 height = base_height + FLOOR (height - base_height, yinc);
5170 /* constrain aspect ratio, according to:
5173 * min_aspect <= -------- <= max_aspect
5177 if (flags & GDK_HINT_ASPECT &&
5178 geometry->min_aspect > 0 &&
5179 geometry->max_aspect > 0)
5183 if (geometry->min_aspect * height > width)
5185 delta = FLOOR (height - width / geometry->min_aspect, yinc);
5186 if (height - delta >= min_height)
5190 delta = FLOOR (height * geometry->min_aspect - width, xinc);
5191 if (width + delta <= max_width)
5196 if (geometry->max_aspect * height < width)
5198 delta = FLOOR (width - height * geometry->max_aspect, xinc);
5199 if (width - delta >= min_width)
5203 delta = FLOOR (width / geometry->max_aspect - height, yinc);
5204 if (height + delta <= max_height)
5213 *new_height = height;
5217 * gdk_window_get_pointer:
5218 * @window: a #GdkWindow
5219 * @x: return location for X coordinate of pointer or %NULL to not
5220 * return the X coordinate
5221 * @y: return location for Y coordinate of pointer or %NULL to not
5222 * return the Y coordinate
5223 * @mask: return location for modifier mask or %NULL to not return the
5226 * Obtains the current pointer position and modifier state.
5227 * The position is given in coordinates relative to the upper left
5228 * corner of @window.
5230 * Return value: the window containing the pointer (as with
5231 * gdk_window_at_pointer()), or %NULL if the window containing the
5232 * pointer isn't known to GDK
5235 gdk_window_get_pointer (GdkWindow *window,
5238 GdkModifierType *mask)
5240 GdkDisplay *display;
5242 GdkModifierType tmp_mask;
5245 g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
5249 display = gdk_drawable_get_display (window);
5253 GdkScreen *screen = gdk_screen_get_default ();
5255 display = gdk_screen_get_display (screen);
5256 window = gdk_screen_get_root_window (screen);
5258 GDK_NOTE (MULTIHEAD,
5259 g_message ("Passing NULL for window to gdk_window_get_pointer()\n"
5260 "is not multihead safe"));
5263 child = display->pointer_hooks->window_get_pointer (display, window, &tmp_x, &tmp_y, &tmp_mask);
5276 * gdk_window_at_pointer:
5277 * @win_x: return location for origin of the window under the pointer
5278 * @win_y: return location for origin of the window under the pointer
5280 * Obtains the window underneath the mouse pointer, returning the
5281 * location of that window in @win_x, @win_y. Returns %NULL if the
5282 * window under the mouse pointer is not known to GDK (if the window
5283 * belongs to another application and a #GdkWindow hasn't been created
5284 * for it with gdk_window_foreign_new())
5286 * NOTE: For multihead-aware widgets or applications use
5287 * gdk_display_get_window_at_pointer() instead.
5289 * Return value: window under the mouse pointer
5292 gdk_window_at_pointer (gint *win_x,
5295 return gdk_display_get_window_at_pointer (gdk_display_get_default (), win_x, win_y);
5299 * gdk_get_default_root_window:
5301 * Obtains the root window (parent all other windows are inside)
5302 * for the default display and screen.
5304 * Return value: the default root window
5307 gdk_get_default_root_window (void)
5309 return gdk_screen_get_root_window (gdk_screen_get_default ());
5313 * gdk_window_foreign_new:
5314 * @anid: a native window handle.
5316 * Wraps a native window for the default display in a #GdkWindow.
5317 * This may fail if the window has been destroyed.
5319 * For example in the X backend, a native window handle is an Xlib
5322 * Return value: the newly-created #GdkWindow wrapper for the
5323 * native window or %NULL if the window has been destroyed.
5326 gdk_window_foreign_new (GdkNativeWindow anid)
5328 return gdk_window_foreign_new_for_display (gdk_display_get_default (), anid);
5332 get_all_native_children (GdkWindowObject *private,
5335 GdkWindowObject *child;
5338 for (l = private->children; l != NULL; l = l->next)
5342 if (gdk_window_has_impl (child))
5343 *native = g_list_prepend (*native, child);
5345 get_all_native_children (child, native);
5351 gdk_window_raise_internal (GdkWindow *window)
5353 GdkWindowObject *private = (GdkWindowObject *)window;
5354 GdkWindowObject *parent = private->parent;
5355 GdkWindowObject *above;
5356 GList *native_children;
5361 parent->children = g_list_remove (parent->children, window);
5362 parent->children = g_list_prepend (parent->children, window);
5365 /* Just do native raise for toplevels */
5366 if (private->parent == NULL ||
5367 GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
5369 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
5371 else if (gdk_window_has_impl (private))
5373 above = find_native_sibling_above (parent, private);
5376 listhead.data = window;
5377 listhead.next = NULL;
5378 listhead.prev = NULL;
5379 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
5383 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
5387 native_children = NULL;
5388 get_all_native_children (private, &native_children);
5389 if (native_children != NULL)
5391 above = find_native_sibling_above (parent, private);
5394 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
5398 /* Right order, since native_chilren is bottom-opmost first */
5399 for (l = native_children; l != NULL; l = l->next)
5400 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (l->data);
5403 g_list_free (native_children);
5410 show_all_visible_impls (GdkWindowObject *private)
5412 GdkWindowObject *child;
5415 for (l = private->children; l != NULL; l = l->next)
5418 if (GDK_WINDOW_IS_MAPPED (child))
5419 show_all_visible_impls (child);
5422 if (gdk_window_has_impl (private))
5423 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show ((GdkWindow *)private);
5427 gdk_window_show_internal (GdkWindow *window, gboolean raise)
5429 GdkWindowObject *private;
5430 gboolean was_mapped;
5432 g_return_if_fail (GDK_IS_WINDOW (window));
5434 private = (GdkWindowObject *) window;
5435 if (private->destroyed)
5438 was_mapped = GDK_WINDOW_IS_MAPPED (window);
5441 /* Keep children in (reverse) stacking order */
5442 gdk_window_raise_internal (window);
5444 if (gdk_window_has_impl (private))
5447 gdk_synthesize_window_state (window,
5448 GDK_WINDOW_STATE_WITHDRAWN,
5456 if (!was_mapped && gdk_window_is_viewable (window))
5457 show_all_visible_impls (private);
5461 if (private->event_mask & GDK_STRUCTURE_MASK)
5462 _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
5464 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
5465 _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
5468 if (!was_mapped || raise)
5470 recompute_visible_regions (private, TRUE, FALSE);
5472 if (gdk_window_is_viewable (window))
5474 _gdk_syntesize_crossing_events_for_geometry_change (window);
5475 gdk_window_invalidate_rect (window, NULL, TRUE);
5481 * gdk_window_show_unraised:
5482 * @window: a #GdkWindow
5484 * Shows a #GdkWindow onscreen, but does not modify its stacking
5485 * order. In contrast, gdk_window_show() will raise the window
5486 * to the top of the window stack.
5488 * On the X11 platform, in Xlib terms, this function calls
5489 * XMapWindow() (it also updates some internal GDK state, which means
5490 * that you can't really use XMapWindow() directly on a GDK window).
5493 gdk_window_show_unraised (GdkWindow *window)
5495 gdk_window_show_internal (window, FALSE);
5500 * @window: a #GdkWindow
5502 * Raises @window to the top of the Z-order (stacking order), so that
5503 * other windows with the same parent window appear below @window.
5504 * This is true whether or not the windows are visible.
5506 * If @window is a toplevel, the window manager may choose to deny the
5507 * request to move the window in the Z-order, gdk_window_raise() only
5508 * requests the restack, does not guarantee it.
5511 gdk_window_raise (GdkWindow *window)
5513 GdkWindowObject *private;
5515 g_return_if_fail (GDK_IS_WINDOW (window));
5517 private = (GdkWindowObject *) window;
5518 if (private->destroyed)
5521 /* Keep children in (reverse) stacking order */
5522 gdk_window_raise_internal (window);
5524 recompute_visible_regions (private, TRUE, FALSE);
5526 gdk_window_invalidate_rect (window, NULL, TRUE);
5530 gdk_window_lower_internal (GdkWindow *window)
5532 GdkWindowObject *private = (GdkWindowObject *)window;
5533 GdkWindowObject *parent = private->parent;
5534 GdkWindowObject *above;
5535 GList *native_children;
5540 parent->children = g_list_remove (parent->children, window);
5541 parent->children = g_list_append (parent->children, window);
5544 /* Just do native lower for toplevels */
5545 if (private->parent == NULL ||
5546 GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
5548 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->lower (window);
5550 else if (gdk_window_has_impl (private))
5552 above = find_native_sibling_above (parent, private);
5555 listhead.data = window;
5556 listhead.next = NULL;
5557 listhead.prev = NULL;
5558 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
5562 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
5566 native_children = NULL;
5567 get_all_native_children (private, &native_children);
5568 if (native_children != NULL)
5570 above = find_native_sibling_above (parent, private);
5573 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
5577 /* Right order, since native_chilren is bottom-opmost first */
5578 for (l = native_children; l != NULL; l = l->next)
5579 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (l->data);
5582 g_list_free (native_children);
5589 gdk_window_invalidate_in_parent (GdkWindowObject *private)
5591 GdkRectangle r, child;
5593 if (private->parent == NULL ||
5594 GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
5597 /* get the visible rectangle of the parent */
5599 r.width = private->parent->width;
5600 r.height = private->parent->height;
5602 child.x = private->x;
5603 child.y = private->y;
5604 child.width = private->width;
5605 child.height = private->height;
5606 gdk_rectangle_intersect (&r, &child, &r);
5608 gdk_window_invalidate_rect (GDK_WINDOW (private->parent), &r, TRUE);
5614 * @window: a #GdkWindow
5616 * Lowers @window to the bottom of the Z-order (stacking order), so that
5617 * other windows with the same parent window appear above @window.
5618 * This is true whether or not the other windows are visible.
5620 * If @window is a toplevel, the window manager may choose to deny the
5621 * request to move the window in the Z-order, gdk_window_lower() only
5622 * requests the restack, does not guarantee it.
5624 * Note that gdk_window_show() raises the window again, so don't call this
5625 * function before gdk_window_show(). (Try gdk_window_show_unraised().)
5628 gdk_window_lower (GdkWindow *window)
5630 GdkWindowObject *private;
5632 g_return_if_fail (GDK_IS_WINDOW (window));
5634 private = (GdkWindowObject *) window;
5635 if (private->destroyed)
5638 /* Keep children in (reverse) stacking order */
5639 gdk_window_lower_internal (window);
5641 recompute_visible_regions (private, TRUE, FALSE);
5643 _gdk_syntesize_crossing_events_for_geometry_change (window);
5644 gdk_window_invalidate_in_parent (private);
5649 * @window: a #GdkWindow
5651 * Like gdk_window_show_unraised(), but also raises the window to the
5652 * top of the window stack (moves the window to the front of the
5655 * This function maps a window so it's visible onscreen. Its opposite
5656 * is gdk_window_hide().
5658 * When implementing a #GtkWidget, you should call this function on the widget's
5659 * #GdkWindow as part of the "map" method.
5662 gdk_window_show (GdkWindow *window)
5664 gdk_window_show_internal (window, TRUE);
5668 hide_all_visible_impls (GdkWindowObject *private)
5670 GdkWindowObject *child;
5673 for (l = private->children; l != NULL; l = l->next)
5677 if (GDK_WINDOW_IS_MAPPED (child))
5678 hide_all_visible_impls (child);
5681 if (gdk_window_has_impl (private))
5682 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->hide ((GdkWindow *)private);
5688 * @window: a #GdkWindow
5690 * For toplevel windows, withdraws them, so they will no longer be
5691 * known to the window manager; for all windows, unmaps them, so
5692 * they won't be displayed. Normally done automatically as
5693 * part of gtk_widget_hide().
5696 gdk_window_hide (GdkWindow *window)
5698 GdkWindowObject *private;
5699 gboolean was_mapped, was_viewable;
5701 g_return_if_fail (GDK_IS_WINDOW (window));
5703 private = (GdkWindowObject *) window;
5704 if (private->destroyed)
5707 was_mapped = GDK_WINDOW_IS_MAPPED (private);
5708 was_viewable = gdk_window_is_viewable (window);
5710 if (gdk_window_has_impl (private))
5713 if (GDK_WINDOW_IS_MAPPED (window))
5714 gdk_synthesize_window_state (window,
5716 GDK_WINDOW_STATE_WITHDRAWN);
5718 else if (was_mapped)
5720 GdkDisplay *display;
5722 /* May need to break grabs on children */
5723 display = gdk_drawable_get_display (window);
5725 if (display->pointer_grab.window != NULL)
5727 if (is_parent_of (window, display->pointer_grab.window))
5729 /* Call this ourselves, even though gdk_display_pointer_ungrab
5730 does so too, since we want to pass implicit == TRUE so the
5731 broken grab event is generated */
5732 _gdk_display_unset_has_pointer_grab (display,
5736 gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
5740 private->state = GDK_WINDOW_STATE_WITHDRAWN;
5744 hide_all_visible_impls (private);
5746 recompute_visible_regions (private, TRUE, FALSE);
5750 if (private->event_mask & GDK_STRUCTURE_MASK)
5751 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
5753 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
5754 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
5756 _gdk_syntesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
5759 /* Invalidate the rect */
5760 gdk_window_invalidate_in_parent (private);
5764 * gdk_window_withdraw:
5765 * @window: a toplevel #GdkWindow
5767 * Withdraws a window (unmaps it and asks the window manager to forget about it).
5768 * This function is not really useful as gdk_window_hide() automatically
5769 * withdraws toplevel windows before hiding them.
5772 gdk_window_withdraw (GdkWindow *window)
5774 GdkWindowObject *private;
5775 gboolean was_mapped;
5777 g_return_if_fail (GDK_IS_WINDOW (window));
5779 private = (GdkWindowObject *) window;
5780 if (private->destroyed)
5783 was_mapped = GDK_WINDOW_IS_MAPPED (private);
5785 if (gdk_window_has_impl (private))
5787 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->withdraw (window);
5791 if (private->event_mask & GDK_STRUCTURE_MASK)
5792 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
5794 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
5795 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
5797 _gdk_syntesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
5800 recompute_visible_regions (private, TRUE, FALSE);
5805 * gdk_window_set_events:
5806 * @window: a #GdkWindow
5807 * @event_mask: event mask for @window
5809 * The event mask for a window determines which events will be reported
5810 * for that window. For example, an event mask including #GDK_BUTTON_PRESS_MASK
5811 * means the window should report button press events. The event mask
5812 * is the bitwise OR of values from the #GdkEventMask enumeration.
5815 gdk_window_set_events (GdkWindow *window,
5816 GdkEventMask event_mask)
5818 GdkWindowObject *private;
5820 g_return_if_fail (GDK_IS_WINDOW (window));
5822 private = (GdkWindowObject *) window;
5823 if (private->destroyed)
5826 private->event_mask = event_mask;
5830 * gdk_window_get_events:
5831 * @window: a #GdkWindow
5833 * Gets the event mask for @window. See gdk_window_set_events().
5835 * Return value: event mask for @window
5838 gdk_window_get_events (GdkWindow *window)
5840 GdkWindowObject *private;
5842 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
5844 private = (GdkWindowObject *) window;
5845 if (private->destroyed)
5848 return private->event_mask;
5852 gdk_window_move_resize_toplevel (GdkWindow *window,
5859 GdkWindowObject *private;
5860 GdkRegion *old_region, *new_region;
5861 GdkWindowObject *impl_window;
5863 int old_x, old_y, old_abs_x, old_abs_y;
5867 private = (GdkWindowObject *) window;
5872 impl_window = gdk_window_get_impl_window (private);
5877 is_resize = (width != -1) || (height != -1);
5879 if (GDK_WINDOW_IS_MAPPED (window) &&
5880 !private->input_only)
5883 old_region = gdk_region_copy (private->clip_region);
5886 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, with_move, x, y, width, height);
5888 dx = private->x - old_x;
5889 dy = private->y - old_y;
5891 old_abs_x = private->abs_x;
5892 old_abs_y = private->abs_y;
5894 /* Avoid recomputing for pure toplevel moves, for performance reasons */
5896 recompute_visible_regions (private, TRUE, FALSE);
5900 new_region = gdk_region_copy (private->clip_region);
5902 /* This is the newly exposed area (due to any resize),
5903 * X will expose it, but lets do that without the
5906 gdk_region_subtract (new_region, old_region);
5907 gdk_window_invalidate_region (window, new_region, TRUE);
5909 gdk_region_destroy (old_region);
5910 gdk_region_destroy (new_region);
5913 _gdk_syntesize_crossing_events_for_geometry_change (window);
5918 move_native_children (GdkWindowObject *private)
5921 GdkWindowObject *child;
5923 for (l = private->children; l; l = l->next)
5927 if (child->impl != private->impl)
5928 GDK_WINDOW_IMPL_GET_IFACE (child->impl)->move_resize ((GdkWindow *)child, TRUE, child->x, child->y, child->width, child->height);
5930 move_native_children (child);
5935 collect_native_child_region_helper (GdkWindowObject *window,
5941 GdkWindowObject *child;
5945 for (l = window->children; l != NULL; l = l->next)
5949 if (child->impl != impl)
5951 tmp = gdk_region_copy (child->clip_region);
5952 gdk_region_offset (tmp,
5953 x_offset + child->x,
5954 y_offset + child->y);
5955 if (*region == NULL)
5959 gdk_region_union (*region, tmp);
5960 gdk_region_destroy (tmp);
5964 collect_native_child_region_helper (child, impl, region,
5965 x_offset + child->x,
5966 y_offset + child->y);
5973 collect_native_child_region (GdkWindowObject *window,
5974 gboolean include_this)
5978 if (include_this && gdk_window_has_impl (window))
5979 return gdk_region_copy (window->clip_region);
5983 collect_native_child_region_helper (window, window->impl, ®ion, 0, 0);
5990 gdk_window_move_resize_internal (GdkWindow *window,
5997 GdkWindowObject *private;
5998 GdkRegion *old_region, *new_region, *copy_area;
5999 GdkRegion *old_native_child_region, *new_native_child_region;
6000 GdkWindowObject *impl_window;
6002 int old_x, old_y, old_abs_x, old_abs_y;
6005 g_return_if_fail (GDK_IS_WINDOW (window));
6007 private = (GdkWindowObject *) window;
6008 if (private->destroyed)
6011 if (private->parent == NULL ||
6012 GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
6014 gdk_window_move_resize_toplevel (window, with_move, x, y, width, height);
6018 /* Handle child windows */
6023 impl_window = gdk_window_get_impl_window (private);
6028 if (GDK_WINDOW_IS_MAPPED (window) &&
6029 !private->input_only)
6033 old_region = gdk_region_copy (private->clip_region);
6034 /* Adjust region to parent window coords */
6035 gdk_region_offset (old_region, private->x, private->y);
6038 old_native_child_region = collect_native_child_region (private, TRUE);
6039 if (old_native_child_region)
6041 /* Adjust region to parent window coords */
6042 gdk_region_offset (old_native_child_region, private->x, private->y);
6044 /* Any native window move will immediately copy stuff to the destination, which may overwrite a
6045 * source or destination for a delayed GdkWindowRegionMove. So, we need
6046 * to flush those here for the parent window and all overlapped subwindows
6047 * of it. And we need to do this before setting the new clips as those will be
6050 gdk_window_flush_recursive (private->parent);
6053 /* Set the new position and size */
6059 if (!(width < 0 && height < 0))
6063 private->width = width;
6066 private->height = height;
6069 dx = private->x - old_x;
6070 dy = private->y - old_y;
6072 old_abs_x = private->abs_x;
6073 old_abs_y = private->abs_y;
6075 recompute_visible_regions (private, TRUE, FALSE);
6077 new_native_child_region = NULL;
6078 if (old_native_child_region)
6080 new_native_child_region = collect_native_child_region (private, TRUE);
6081 /* Adjust region to parent window coords */
6082 gdk_region_offset (new_native_child_region, private->x, private->y);
6085 if (gdk_window_has_impl (private))
6087 /* Do the actual move after recomputing things, as this will have set the shape to
6088 the now correct one, thus avoiding copying regions that should not be copied. */
6089 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, TRUE, private->x, private->y, private->width, private->height);
6091 else if (old_abs_x != private->abs_x ||
6092 old_abs_y != private->abs_y)
6093 move_native_children (private);
6097 new_region = gdk_region_copy (private->clip_region);
6098 /* Adjust region to parent window coords */
6099 gdk_region_offset (new_region, private->x, private->y);
6102 * Part of the data at the new location can be copied from the
6103 * old location, this area is the intersection of the old region
6104 * moved as the copy will move it and then intersected with
6108 * Everything in the old and new regions that is not copied must be
6109 * invalidated (including children) as this is newly exposed
6111 copy_area = gdk_region_copy (new_region);
6113 gdk_region_union (new_region, old_region);
6115 if (old_native_child_region)
6117 /* Don't copy from inside native children, as this is copied by
6118 * the native window move.
6120 gdk_region_subtract (old_region, old_native_child_region);
6122 gdk_region_offset (old_region, dx, dy);
6124 gdk_region_intersect (copy_area, old_region);
6126 if (new_native_child_region)
6128 /* Don't copy any bits that would cause a read from the moved
6129 native windows, as we can't read that data */
6130 gdk_region_offset (new_native_child_region, dx, dy);
6131 gdk_region_subtract (copy_area, new_native_child_region);
6134 gdk_region_subtract (new_region, copy_area);
6136 /* Convert old region to impl coords */
6137 gdk_region_offset (old_region, -dx + private->abs_x - private->x, -dy + private->abs_y - private->y);
6139 /* The old_region area is moved and we queue translations for all expose events
6140 to it that will be sent before the copy operation */
6141 GDK_WINDOW_IMPL_GET_IFACE (impl_window->impl)->queue_translation ((GdkWindow *)impl_window,
6142 old_region, dx, dy);
6144 /* convert from parent coords to impl */
6145 gdk_region_offset (copy_area, private->abs_x - private->x, private->abs_y - private->y);
6147 move_region_on_impl (private, copy_area, dx, dy); /* Takes ownership of copy_area */
6149 /* Invalidate affected part in the parent window
6150 * (no higher window should be affected)
6151 * We also invalidate any children in that area, which could include
6152 * this window if it still overlaps that area.
6154 gdk_window_invalidate_region (GDK_WINDOW (private->parent), new_region, TRUE);
6156 gdk_region_destroy (old_region);
6157 gdk_region_destroy (new_region);
6160 if (old_native_child_region)
6162 gdk_region_destroy (old_native_child_region);
6163 gdk_region_destroy (new_native_child_region);
6166 _gdk_syntesize_crossing_events_for_geometry_change (window);
6173 * @window: a #GdkWindow
6174 * @x: X coordinate relative to window's parent
6175 * @y: Y coordinate relative to window's parent
6177 * Repositions a window relative to its parent window.
6178 * For toplevel windows, window managers may ignore or modify the move;
6179 * you should probably use gtk_window_move() on a #GtkWindow widget
6180 * anyway, instead of using GDK functions. For child windows,
6181 * the move will reliably succeed.
6183 * If you're also planning to resize the window, use gdk_window_move_resize()
6184 * to both move and resize simultaneously, for a nicer visual effect.
6187 gdk_window_move (GdkWindow *window,
6191 gdk_window_move_resize_internal (window, TRUE, x, y, -1, -1);
6195 * gdk_window_resize:
6196 * @window: a #GdkWindow
6197 * @width: new width of the window
6198 * @height: new height of the window
6200 * Resizes @window; for toplevel windows, asks the window manager to resize
6201 * the window. The window manager may not allow the resize. When using GTK+,
6202 * use gtk_window_resize() instead of this low-level GDK function.
6204 * Windows may not be resized below 1x1.
6206 * If you're also planning to move the window, use gdk_window_move_resize()
6207 * to both move and resize simultaneously, for a nicer visual effect.
6210 gdk_window_resize (GdkWindow *window,
6214 gdk_window_move_resize_internal (window, FALSE, 0, 0, width, height);
6219 * gdk_window_move_resize:
6220 * @window: a #GdkWindow
6221 * @x: new X position relative to window's parent
6222 * @y: new Y position relative to window's parent
6224 * @height: new height
6226 * Equivalent to calling gdk_window_move() and gdk_window_resize(),
6227 * except that both operations are performed at once, avoiding strange
6228 * visual effects. (i.e. the user may be able to see the window first
6229 * move, then resize, if you don't use gdk_window_move_resize().)
6232 gdk_window_move_resize (GdkWindow *window,
6238 gdk_window_move_resize_internal (window, TRUE, x, y, width, height);
6243 * gdk_window_scroll:
6244 * @window: a #GdkWindow
6245 * @dx: Amount to scroll in the X direction
6246 * @dy: Amount to scroll in the Y direction
6248 * Scroll the contents of @window, both pixels and children, by the
6249 * given amount. @window itself does not move. Portions of the window
6250 * that the scroll operation brings in from offscreen areas are
6251 * invalidated. The invalidated region may be bigger than what would
6252 * strictly be necessary.
6254 * For X11, a minimum area will be invalidated if the window has no
6255 * subwindows, or if the edges of the window's parent do not extend
6256 * beyond the edges of the window. In other cases, a multi-step process
6257 * is used to scroll the window which may produce temporary visual
6258 * artifacts and unnecessary invalidations.
6261 gdk_window_scroll (GdkWindow *window,
6265 GdkWindowObject *private = (GdkWindowObject *) window;
6266 GdkWindowObject *impl_window;
6267 GdkRegion *source_area, *copy_area, *noncopy_area;
6268 GdkRegion *old_native_child_region, *new_native_child_region;
6271 g_return_if_fail (GDK_IS_WINDOW (window));
6273 if (dx == 0 && dy == 0)
6276 if (private->destroyed)
6279 old_native_child_region = collect_native_child_region (private, FALSE);
6280 if (old_native_child_region)
6282 /* Any native window move will immediately copy stuff to the destination, which may overwrite a
6283 * source or destination for a delayed GdkWindowRegionMove. So, we need
6284 * to flush those here for the window and all overlapped subwindows
6285 * of it. And we need to do this before setting the new clips as those will be
6288 gdk_window_flush_recursive (private);
6292 /* First move all child windows, without causing invalidation */
6294 tmp_list = private->children;
6297 GdkWindow *child = GDK_WINDOW (tmp_list->data);
6298 GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
6300 /* Just update the positions, the bits will move with the copy */
6304 tmp_list = tmp_list->next;
6307 recompute_visible_regions (private, FALSE, TRUE);
6309 new_native_child_region = NULL;
6310 if (old_native_child_region)
6311 new_native_child_region = collect_native_child_region (private, FALSE);
6313 move_native_children (private);
6315 /* Then copy the actual bits of the window w/ child windows */
6317 impl_window = gdk_window_get_impl_window (private);
6319 /* Calculate the area that can be gotten by copying the old area */
6320 copy_area = gdk_region_copy (private->clip_region);
6321 if (old_native_child_region)
6323 /* Don't copy from inside native children, as this is copied by
6324 * the native window move.
6326 gdk_region_subtract (copy_area, old_native_child_region);
6328 /* Don't copy any bits that would cause a read from the moved
6329 native windows, as we can't read that data */
6330 gdk_region_subtract (copy_area, new_native_child_region);
6332 gdk_region_offset (copy_area, dx, dy);
6333 gdk_region_intersect (copy_area, private->clip_region);
6335 /* And the rest need to be invalidated */
6336 noncopy_area = gdk_region_copy (private->clip_region);
6337 gdk_region_subtract (noncopy_area, copy_area);
6339 /* Get window clip and convert to real window coords, this
6340 area is moved and we queue translations for all expose events
6341 to it that will be sent before the copy operation */
6343 source_area = gdk_region_copy (private->clip_region);
6344 /* convert from window coords to real parent */
6345 gdk_region_offset (source_area, private->abs_x, private->abs_y);
6346 GDK_WINDOW_IMPL_GET_IFACE (impl_window->impl)->queue_translation ((GdkWindow *)impl_window,
6347 source_area, dx, dy);
6348 gdk_region_destroy (source_area);
6350 /* convert from window coords to impl */
6351 gdk_region_offset (copy_area, private->abs_x, private->abs_y);
6353 move_region_on_impl (private, copy_area, dx, dy); /* Takes ownership of copy_area */
6355 /* Invalidate not copied regions */
6356 gdk_window_invalidate_region (window, noncopy_area, TRUE);
6358 gdk_region_destroy (noncopy_area);
6360 if (old_native_child_region)
6362 gdk_region_destroy (old_native_child_region);
6363 gdk_region_destroy (new_native_child_region);
6366 _gdk_syntesize_crossing_events_for_geometry_change (window);
6370 * gdk_window_move_region:
6371 * @window: a #GdkWindow
6372 * @region: The #GdkRegion to move
6373 * @dx: Amount to move in the X direction
6374 * @dy: Amount to move in the Y direction
6376 * Move the part of @window indicated by @region by @dy pixels in the Y
6377 * direction and @dx pixels in the X direction. The portions of @region
6378 * that not covered by the new position of @region are invalidated.
6380 * Child windows are not moved.
6385 gdk_window_move_region (GdkWindow *window,
6386 const GdkRegion *region,
6390 GdkWindowObject *private = (GdkWindowObject *) window;
6391 GdkWindowObject *impl_window;
6392 GdkRegion *source_area;
6393 GdkRegion *nocopy_area;
6394 GdkRegion *copy_area;
6396 g_return_if_fail (GDK_IS_WINDOW (window));
6397 g_return_if_fail (region != NULL);
6399 if (dx == 0 && dy == 0)
6402 if (private->destroyed)
6405 impl_window = gdk_window_get_impl_window (private);
6407 /* compute source regions */
6408 source_area = gdk_region_copy (region);
6409 gdk_region_intersect (source_area, private->clip_region_with_children);
6411 /* compute destination regions */
6412 copy_area = gdk_region_copy (source_area);
6413 gdk_region_offset (copy_area, dx, dy);
6414 gdk_region_intersect (copy_area, private->clip_region_with_children);
6416 /* invalidate parts of the region not covered by the copy */
6417 nocopy_area = gdk_region_copy (region);
6418 gdk_region_offset (nocopy_area, dx, dy);
6419 gdk_region_subtract (nocopy_area, copy_area);
6420 gdk_window_invalidate_region (window, nocopy_area, FALSE);
6421 gdk_region_destroy (nocopy_area);
6423 gdk_region_offset (source_area, private->abs_x, private->abs_y);
6424 GDK_WINDOW_IMPL_GET_IFACE (impl_window->impl)->queue_translation ((GdkWindow *)impl_window,
6425 source_area, dx, dy);
6427 /* convert from window coords to impl */
6428 gdk_region_offset (copy_area, private->abs_x, private->abs_y);
6430 move_region_on_impl (private, copy_area, dx, dy); /* Takes ownership of copy_area */
6432 gdk_region_destroy (source_area);
6436 * gdk_window_set_background:
6437 * @window: a #GdkWindow
6438 * @color: an allocated #GdkColor
6440 * Sets the background color of @window. (However, when using GTK+,
6441 * set the background of a widget with gtk_widget_modify_bg() - if
6442 * you're an application - or gtk_style_set_background() - if you're
6443 * implementing a custom widget.)
6445 * The @color must be allocated; gdk_rgb_find_color() is the best way
6446 * to allocate a color.
6448 * See also gdk_window_set_back_pixmap().
6451 gdk_window_set_background (GdkWindow *window,
6452 const GdkColor *color)
6454 GdkWindowObject *private;
6455 GdkColormap *colormap = gdk_drawable_get_colormap (window);
6457 g_return_if_fail (GDK_IS_WINDOW (window));
6459 private = (GdkWindowObject *) window;
6461 private->bg_color = *color;
6462 gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
6464 if (private->bg_pixmap &&
6465 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
6466 private->bg_pixmap != GDK_NO_BG)
6467 g_object_unref (private->bg_pixmap);
6469 private->bg_pixmap = NULL;
6471 if (!GDK_WINDOW_DESTROYED (window) && gdk_window_has_impl (private))
6472 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, &private->bg_color);
6476 * gdk_window_set_back_pixmap:
6477 * @window: a #GdkWindow
6478 * @pixmap: a #GdkPixmap, or %NULL
6479 * @parent_relative: whether the tiling origin is at the origin of
6482 * Sets the background pixmap of @window. May also be used to set a
6483 * background of "None" on @window, by setting a background pixmap
6486 * A background pixmap will be tiled, positioning the first tile at
6487 * the origin of @window, or if @parent_relative is %TRUE, the tiling
6488 * will be done based on the origin of the parent window (useful to
6489 * align tiles in a parent with tiles in a child).
6491 * A background pixmap of %NULL means that the window will have no
6492 * background. A window with no background will never have its
6493 * background filled by the windowing system, instead the window will
6494 * contain whatever pixels were already in the corresponding area of
6497 * The windowing system will normally fill a window with its background
6498 * when the window is obscured then exposed, and when you call
6499 * gdk_window_clear().
6502 gdk_window_set_back_pixmap (GdkWindow *window,
6504 gboolean parent_relative)
6506 GdkWindowObject *private;
6508 g_return_if_fail (GDK_IS_WINDOW (window));
6509 g_return_if_fail (pixmap == NULL || !parent_relative);
6510 g_return_if_fail (pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap));
6512 private = (GdkWindowObject *) window;
6514 if (pixmap && !gdk_drawable_get_colormap (pixmap))
6516 g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
6520 if (private->bg_pixmap &&
6521 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
6522 private->bg_pixmap != GDK_NO_BG)
6523 g_object_unref (private->bg_pixmap);
6525 if (parent_relative)
6526 private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
6528 private->bg_pixmap = g_object_ref (pixmap);
6530 private->bg_pixmap = GDK_NO_BG;
6532 if (!GDK_WINDOW_DESTROYED (window) && gdk_window_has_impl (private))
6533 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, private->bg_pixmap);
6537 update_cursor (GdkDisplay *display)
6539 GdkWindowObject *pointer_window, *cursor_window;
6541 pointer_window = (GdkWindowObject *)display->pointer_info.window_under_pointer;
6543 cursor_window = pointer_window;
6544 while (cursor_window->cursor == NULL &&
6545 cursor_window->parent != NULL &&
6546 cursor_window->parent->window_type != GDK_WINDOW_ROOT)
6547 cursor_window = cursor_window->parent;
6549 if (display->pointer_grab.window != NULL &&
6550 !is_parent_of (display->pointer_grab.window, (GdkWindow *)cursor_window))
6551 cursor_window = (GdkWindowObject *)display->pointer_grab.window;
6553 GDK_WINDOW_IMPL_GET_IFACE (pointer_window->impl)->set_cursor ((GdkWindow *)pointer_window,
6554 cursor_window->cursor);
6558 * gdk_window_set_cursor:
6559 * @window: a #GdkWindow
6562 * Sets the mouse pointer for a #GdkWindow. Use gdk_cursor_new_for_display()
6563 * or gdk_cursor_new_from_pixmap() to create the cursor. To make the cursor
6564 * invisible, use %GDK_BLANK_CURSOR. Passing %NULL for the @cursor argument
6565 * to gdk_window_set_cursor() means that @window will use the cursor of its
6566 * parent window. Most windows should use this default.
6569 gdk_window_set_cursor (GdkWindow *window,
6572 GdkWindowObject *private;
6573 GdkDisplay *display;
6575 g_return_if_fail (GDK_IS_WINDOW (window));
6577 private = (GdkWindowObject *) window;
6578 display = gdk_drawable_get_display (window);
6580 if (private->cursor)
6582 gdk_cursor_unref (private->cursor);
6583 private->cursor = NULL;
6586 if (!GDK_WINDOW_DESTROYED (window))
6589 private->cursor = gdk_cursor_ref (cursor);
6591 if (is_parent_of (window, display->pointer_info.window_under_pointer))
6592 update_cursor (display);
6597 * gdk_window_get_geometry:
6598 * @window: a #GdkWindow
6599 * @x: return location for X coordinate of window (relative to its parent)
6600 * @y: return location for Y coordinate of window (relative to its parent)
6601 * @width: return location for width of window
6602 * @height: return location for height of window
6603 * @depth: return location for bit depth of window
6605 * Any of the return location arguments to this function may be %NULL,
6606 * if you aren't interested in getting the value of that field.
6608 * The X and Y coordinates returned are relative to the parent window
6609 * of @window, which for toplevels usually means relative to the
6610 * window decorations (titlebar, etc.) rather than relative to the
6611 * root window (screen-size background window).
6613 * On the X11 platform, the geometry is obtained from the X server,
6614 * so reflects the latest position of @window; this may be out-of-sync
6615 * with the position of @window delivered in the most-recently-processed
6616 * #GdkEventConfigure. gdk_window_get_position() in contrast gets the
6617 * position from the most recent configure event.
6620 * If @window is not a toplevel, it is <emphasis>much</emphasis> better
6621 * to call gdk_window_get_position() and gdk_drawable_get_size() instead,
6622 * because it avoids the roundtrip to the X server and because
6623 * gdk_drawable_get_size() supports the full 32-bit coordinate space,
6624 * whereas gdk_window_get_geometry() is restricted to the 16-bit
6625 * coordinates of X11.
6629 gdk_window_get_geometry (GdkWindow *window,
6636 GdkWindowObject *private;
6640 GDK_NOTE (MULTIHEAD,
6641 g_message ("gdk_window_get_geometry(): Window needs "
6642 "to be non-NULL to be multi head safe"));
6643 window = gdk_screen_get_root_window ((gdk_screen_get_default ()));
6646 g_return_if_fail (GDK_IS_WINDOW (window));
6648 private = (GdkWindowObject *) window;
6650 if (!GDK_WINDOW_DESTROYED (window))
6652 if (gdk_window_has_impl (private))
6653 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_geometry (window, x, y,
6663 *width = private->width;
6665 *height = private->height;
6667 *depth = private->depth;
6673 * gdk_window_get_origin:
6674 * @window: a #GdkWindow
6675 * @x: return location for X coordinate
6676 * @y: return location for Y coordinate
6678 * Obtains the position of a window in root window coordinates.
6679 * (Compare with gdk_window_get_position() and
6680 * gdk_window_get_geometry() which return the position of a window
6681 * relative to its parent window.)
6683 * Return value: not meaningful, ignore
6686 gdk_window_get_origin (GdkWindow *window,
6690 GdkWindowObject *private;
6692 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
6694 private = (GdkWindowObject *) window;
6696 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_origin (window, x, y);
6699 *x += private->abs_x;
6701 *y += private->abs_y;
6708 * gdk_window_get_deskrelative_origin:
6709 * @window: a toplevel #GdkWindow
6710 * @x: return location for X coordinate
6711 * @y: return location for Y coordinate
6713 * This gets the origin of a #GdkWindow relative to
6714 * an Enlightenment-window-manager desktop. As long as you don't
6715 * assume that the user's desktop/workspace covers the entire
6716 * root window (i.e. you don't assume that the desktop begins
6717 * at root window coordinate 0,0) this function is not necessary.
6718 * It's deprecated for that reason.
6720 * Return value: not meaningful
6723 gdk_window_get_deskrelative_origin (GdkWindow *window,
6727 GdkWindowObject *private;
6728 gboolean return_val = FALSE;
6732 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
6734 private = (GdkWindowObject *) window;
6736 if (!GDK_WINDOW_DESTROYED (window))
6738 return_val = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_deskrelative_origin (window, &tx, &ty);
6741 *x = tx + private->abs_x;
6743 *y = ty + private->abs_y;
6750 * gdk_window_shape_combine_mask:
6751 * @window: a #GdkWindow
6753 * @x: X position of shape mask with respect to @window
6754 * @y: Y position of shape mask with respect to @window
6756 * Applies a shape mask to @window. Pixels in @window corresponding to
6757 * set bits in the @mask will be visible; pixels in @window
6758 * corresponding to unset bits in the @mask will be transparent. This
6759 * gives a non-rectangular window.
6761 * If @mask is %NULL, the shape mask will be unset, and the @x/@y
6762 * parameters are not used.
6764 * On the X11 platform, this uses an X server extension which is
6765 * widely available on most common platforms, but not available on
6766 * very old X servers, and occasionally the implementation will be
6767 * buggy. On servers without the shape extension, this function
6770 * This function works on both toplevel and child windows.
6773 gdk_window_shape_combine_mask (GdkWindow *window,
6778 GdkWindowObject *private;
6781 g_return_if_fail (GDK_IS_WINDOW (window));
6783 private = (GdkWindowObject *) window;
6786 region = _gdk_windowing_get_shape_for_mask (mask);
6790 gdk_window_shape_combine_region (window,
6795 gdk_region_destroy (region);
6799 * gdk_window_shape_combine_region:
6800 * @window: a #GdkWindow
6801 * @shape_region: region of window to be non-transparent
6802 * @offset_x: X position of @shape_region in @window coordinates
6803 * @offset_y: Y position of @shape_region in @window coordinates
6805 * Makes pixels in @window outside @shape_region be transparent,
6806 * so that the window may be nonrectangular. See also
6807 * gdk_window_shape_combine_mask() to use a bitmap as the mask.
6809 * If @shape_region is %NULL, the shape will be unset, so the whole
6810 * window will be opaque again. @offset_x and @offset_y are ignored
6811 * if @shape_region is %NULL.
6813 * On the X11 platform, this uses an X server extension which is
6814 * widely available on most common platforms, but not available on
6815 * very old X servers, and occasionally the implementation will be
6816 * buggy. On servers without the shape extension, this function
6819 * This function works on both toplevel and child windows.
6822 gdk_window_shape_combine_region (GdkWindow *window,
6823 const GdkRegion *shape_region,
6827 GdkWindowObject *private;
6828 GdkRegion *old_region, *new_region, *diff;
6830 g_return_if_fail (GDK_IS_WINDOW (window));
6832 private = (GdkWindowObject *) window;
6834 if (GDK_WINDOW_DESTROYED (window))
6837 private->shaped = (shape_region != NULL);
6840 gdk_region_destroy (private->shape);
6843 if (GDK_WINDOW_IS_MAPPED (window))
6844 old_region = gdk_region_copy (private->clip_region);
6848 private->shape = gdk_region_copy (shape_region);
6849 gdk_region_offset (private->shape, offset_x, offset_y);
6852 private->shape = NULL;
6854 recompute_visible_regions (private, TRUE, FALSE);
6858 new_region = gdk_region_copy (private->clip_region);
6860 /* New area in the window, needs invalidation */
6861 diff = gdk_region_copy (new_region);
6862 gdk_region_subtract (diff, old_region);
6864 gdk_window_invalidate_region (window, diff, TRUE);
6866 gdk_region_destroy (diff);
6868 if (private->parent != NULL &&
6869 GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
6871 /* New area in the non-root parent window, needs invalidation */
6872 diff = gdk_region_copy (old_region);
6873 gdk_region_subtract (diff, new_region);
6875 /* Adjust region to parent window coords */
6876 gdk_region_offset (diff, private->x, private->y);
6878 gdk_window_invalidate_region (GDK_WINDOW (private->parent), diff, TRUE);
6880 gdk_region_destroy (diff);
6883 gdk_region_destroy (new_region);
6884 gdk_region_destroy (old_region);
6889 do_child_shapes (GdkWindow *window,
6892 GdkWindowObject *private;
6896 private = (GdkWindowObject *) window;
6900 r.width = private->width;
6901 r.height = private->height;
6903 region = gdk_region_rectangle (&r);
6904 remove_child_area (private, NULL, FALSE, region);
6906 if (merge && private->shape)
6907 gdk_region_subtract (region, private->shape);
6909 gdk_window_shape_combine_region (window, region, 0, 0);
6913 * gdk_window_set_child_shapes:
6914 * @window: a #GdkWindow
6916 * Sets the shape mask of @window to the union of shape masks
6917 * for all children of @window, ignoring the shape mask of @window
6918 * itself. Contrast with gdk_window_merge_child_shapes() which includes
6919 * the shape mask of @window in the masks to be merged.
6922 gdk_window_set_child_shapes (GdkWindow *window)
6924 g_return_if_fail (GDK_IS_WINDOW (window));
6926 do_child_shapes (window, FALSE);
6930 * gdk_window_merge_child_shapes:
6931 * @window: a #GdkWindow
6933 * Merges the shape masks for any child windows into the
6934 * shape mask for @window. i.e. the union of all masks
6935 * for @window and its children will become the new mask
6936 * for @window. See gdk_window_shape_combine_mask().
6938 * This function is distinct from gdk_window_set_child_shapes()
6939 * because it includes @window's shape mask in the set of shapes to
6943 gdk_window_merge_child_shapes (GdkWindow *window)
6945 g_return_if_fail (GDK_IS_WINDOW (window));
6947 do_child_shapes (window, TRUE);
6951 * gdk_window_input_shape_combine_mask:
6952 * @window: a #GdkWindow
6954 * @x: X position of shape mask with respect to @window
6955 * @y: Y position of shape mask with respect to @window
6957 * Like gdk_window_shape_combine_mask(), but the shape applies
6958 * only to event handling. Mouse events which happen while
6959 * the pointer position corresponds to an unset bit in the
6960 * mask will be passed on the window below @window.
6962 * An input shape is typically used with RGBA windows.
6963 * The alpha channel of the window defines which pixels are
6964 * invisible and allows for nicely antialiased borders,
6965 * and the input shape controls where the window is
6968 * On the X11 platform, this requires version 1.1 of the
6971 * On the Win32 platform, this functionality is not present and the
6972 * function does nothing.
6977 gdk_window_input_shape_combine_mask (GdkWindow *window,
6982 GdkWindowObject *private;
6985 g_return_if_fail (GDK_IS_WINDOW (window));
6987 private = (GdkWindowObject *) window;
6990 region = _gdk_windowing_get_shape_for_mask (mask);
6994 gdk_window_input_shape_combine_region (window,
6998 gdk_region_destroy (region);
7002 * gdk_window_input_shape_combine_region:
7003 * @window: a #GdkWindow
7004 * @shape_region: region of window to be non-transparent
7005 * @offset_x: X position of @shape_region in @window coordinates
7006 * @offset_y: Y position of @shape_region in @window coordinates
7008 * Like gdk_window_shape_combine_region(), but the shape applies
7009 * only to event handling. Mouse events which happen while
7010 * the pointer position corresponds to an unset bit in the
7011 * mask will be passed on the window below @window.
7013 * An input shape is typically used with RGBA windows.
7014 * The alpha channel of the window defines which pixels are
7015 * invisible and allows for nicely antialiased borders,
7016 * and the input shape controls where the window is
7019 * On the X11 platform, this requires version 1.1 of the
7022 * On the Win32 platform, this functionality is not present and the
7023 * function does nothing.
7028 gdk_window_input_shape_combine_region (GdkWindow *window,
7029 const GdkRegion *shape_region,
7033 GdkWindowObject *private;
7035 g_return_if_fail (GDK_IS_WINDOW (window));
7037 private = (GdkWindowObject *) window;
7039 if (GDK_WINDOW_DESTROYED (window))
7042 if (private->input_shape)
7043 gdk_region_destroy (private->input_shape);
7047 private->input_shape = gdk_region_copy (shape_region);
7048 gdk_region_offset (private->shape, offset_x, offset_y);
7051 private->input_shape = NULL;
7053 if (gdk_window_has_impl (private))
7054 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_shape_combine_region ((GdkWindow *)private, private->input_shape, 0, 0);
7056 /* Pointer may have e.g. moved outside window due to the input mask change */
7057 _gdk_syntesize_crossing_events_for_geometry_change (window);
7061 do_child_input_shapes (GdkWindow *window,
7064 GdkWindowObject *private;
7068 private = (GdkWindowObject *) window;
7072 r.width = private->width;
7073 r.height = private->height;
7075 region = gdk_region_rectangle (&r);
7076 remove_child_area (private, NULL, TRUE, region);
7078 if (merge && private->shape)
7079 gdk_region_subtract (region, private->shape);
7080 if (merge && private->input_shape)
7081 gdk_region_subtract (region, private->input_shape);
7083 gdk_window_input_shape_combine_region (window, region, 0, 0);
7088 * gdk_window_set_child_input_shapes:
7089 * @window: a #GdkWindow
7091 * Sets the input shape mask of @window to the union of input shape masks
7092 * for all children of @window, ignoring the input shape mask of @window
7093 * itself. Contrast with gdk_window_merge_child_input_shapes() which includes
7094 * the input shape mask of @window in the masks to be merged.
7099 gdk_window_set_child_input_shapes (GdkWindow *window)
7101 g_return_if_fail (GDK_IS_WINDOW (window));
7103 do_child_input_shapes (window, FALSE);
7107 * gdk_window_merge_child_input_shapes:
7108 * @window: a #GdkWindow
7110 * Merges the input shape masks for any child windows into the
7111 * input shape mask for @window. i.e. the union of all input masks
7112 * for @window and its children will become the new input mask
7113 * for @window. See gdk_window_input_shape_combine_mask().
7115 * This function is distinct from gdk_window_set_child_input_shapes()
7116 * because it includes @window's input shape mask in the set of
7117 * shapes to be merged.
7122 gdk_window_merge_child_input_shapes (GdkWindow *window)
7124 g_return_if_fail (GDK_IS_WINDOW (window));
7126 do_child_input_shapes (window, TRUE);
7131 * gdk_window_set_static_gravities:
7132 * @window: a #GdkWindow
7133 * @use_static: %TRUE to turn on static gravity
7135 * Set the bit gravity of the given window to static, and flag it so
7136 * all children get static subwindow gravity. This is used if you are
7137 * implementing scary features that involve deep knowledge of the
7138 * windowing system. Don't worry about it unless you have to.
7140 * Return value: %TRUE if the server supports static gravity
7143 gdk_window_set_static_gravities (GdkWindow *window,
7144 gboolean use_static)
7146 GdkWindowObject *private;
7148 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
7150 private = (GdkWindowObject *) window;
7152 if (gdk_window_has_impl (private))
7153 return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_static_gravities (window, use_static);
7159 * gdk_window_set_composited:
7160 * @window: a #GdkWindow
7161 * @composited: %TRUE to set the window as composited
7163 * Sets a #GdkWindow as composited, or unsets it. Composited
7164 * windows do not automatically have their contents drawn to
7165 * the screen. Drawing is redirected to an offscreen buffer
7166 * and an expose event is emitted on the parent of the composited
7167 * window. It is the responsibility of the parent's expose handler
7168 * to manually merge the off-screen content onto the screen in
7169 * whatever way it sees fit. See <xref linkend="composited-window-example"/>
7172 * It only makes sense for child windows to be composited; see
7173 * gdk_window_set_opacity() if you need translucent toplevel
7176 * An additional effect of this call is that the area of this
7177 * window is no longer clipped from regions marked for
7178 * invalidation on its parent. Draws done on the parent
7179 * window are also no longer clipped by the child.
7181 * This call is only supported on some systems (currently,
7182 * only X11 with new enough Xcomposite and Xdamage extensions).
7183 * You must call gdk_display_supports_composite() to check if
7184 * setting a window as composited is supported before
7185 * attempting to do so.
7190 gdk_window_set_composited (GdkWindow *window,
7191 gboolean composited)
7193 GdkWindowObject *private = (GdkWindowObject *)window;
7194 GdkDisplay *display;
7196 g_return_if_fail (GDK_IS_WINDOW (window));
7198 composited = composited != FALSE;
7200 if (private->composited == composited)
7204 gdk_window_set_has_native (window, TRUE);
7206 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
7208 if (!gdk_display_supports_composite (display) && composited)
7210 g_warning ("gdk_window_set_composited called but "
7211 "compositing is not supported");
7215 _gdk_windowing_window_set_composited (window, composited);
7217 recompute_visible_regions (private, TRUE, FALSE);
7219 if (GDK_WINDOW_IS_MAPPED (window))
7220 gdk_window_invalidate_in_parent (private);
7222 private->composited = composited;
7227 remove_redirect_from_children (GdkWindowObject *private,
7228 GdkWindowRedirect *redirect)
7231 GdkWindowObject *child;
7233 for (l = private->children; l != NULL; l = l->next)
7237 /* Don't redirect this child if it already has another redirect */
7238 if (child->redirect == redirect)
7240 child->redirect = NULL;
7241 remove_redirect_from_children (child, redirect);
7247 * gdk_window_remove_redirection:
7248 * @window: a #GdkWindow
7250 * Removes any active redirection started by
7251 * gdk_window_redirect_to_drawable().
7256 gdk_window_remove_redirection (GdkWindow *window)
7258 GdkWindowObject *private;
7260 g_return_if_fail (GDK_IS_WINDOW (window));
7262 private = (GdkWindowObject *) window;
7264 if (private->redirect &&
7265 private->redirect->redirected == private)
7267 remove_redirect_from_children (private, private->redirect);
7268 gdk_window_redirect_free (private->redirect);
7269 private->redirect = NULL;
7274 apply_redirect_to_children (GdkWindowObject *private,
7275 GdkWindowRedirect *redirect)
7278 GdkWindowObject *child;
7280 for (l = private->children; l != NULL; l = l->next)
7284 /* Don't redirect this child if it already has another redirect */
7285 if (!child->redirect)
7287 child->redirect = redirect;
7288 apply_redirect_to_children (child, redirect);
7294 * gdk_window_redirect_to_drawable:
7295 * @window: a #GdkWindow
7296 * @drawable: a #GdkDrawable
7297 * @src_x: x position in @window
7298 * @src_y: y position in @window
7299 * @dest_x: x position in @drawable
7300 * @dest_y: y position in @drawable
7301 * @width: width of redirection
7302 * @height: height of redirection
7304 * Redirects drawing into @window so that drawing to the
7305 * window in the rectangle specified by @src_x, @src_y,
7306 * @width and @height is also drawn into @drawable at
7309 * Only drawing between gdk_window_begin_paint_region() or
7310 * gdk_window_begin_paint_rect() and gdk_window_end_paint() is
7313 * Redirection is active until gdk_window_remove_redirection()
7319 gdk_window_redirect_to_drawable (GdkWindow *window,
7320 GdkDrawable *drawable,
7328 GdkWindowObject *private;
7330 g_return_if_fail (GDK_IS_WINDOW (window));
7331 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
7332 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
7334 private = (GdkWindowObject *) window;
7336 if (private->redirect)
7337 gdk_window_remove_redirection (window);
7339 if (width == -1 || height == -1)
7342 gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
7349 private->redirect = g_new0 (GdkWindowRedirect, 1);
7350 private->redirect->redirected = private;
7351 private->redirect->pixmap = g_object_ref (drawable);
7352 private->redirect->src_x = src_x;
7353 private->redirect->src_y = src_y;
7354 private->redirect->dest_x = dest_x;
7355 private->redirect->dest_y = dest_y;
7356 private->redirect->width = width;
7357 private->redirect->height = height;
7359 apply_redirect_to_children (private, private->redirect);
7363 window_get_size_rectangle (GdkWindow *window,
7366 GdkWindowObject *private = (GdkWindowObject *) window;
7368 rect->x = rect->y = 0;
7369 rect->width = private->width;
7370 rect->height = private->height;
7373 /* Calculates the real clipping region for a window, in window coordinates,
7374 * taking into account other windows, gc clip region and gc clip mask.
7377 _gdk_window_calculate_full_clip_region (GdkWindow *window,
7378 GdkWindow *base_window,
7379 gboolean do_children,
7380 gint *base_x_offset,
7381 gint *base_y_offset)
7383 GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
7384 GdkRectangle visible_rect;
7385 GdkRegion *real_clip_region, *tmpreg;
7386 gint x_offset, y_offset;
7387 GdkWindowObject *parentwin, *lastwin;
7394 if (!GDK_WINDOW_IS_MAPPED (window) || private->input_only)
7395 return gdk_region_new ();
7397 window_get_size_rectangle (window, &visible_rect);
7399 /* real_clip_region is in window coordinates */
7400 real_clip_region = gdk_region_rectangle (&visible_rect);
7402 x_offset = y_offset = 0;
7406 parentwin = lastwin;
7408 parentwin = lastwin->parent;
7410 /* Remove the areas of all overlapping windows above parentwin in the hiearachy */
7411 for (; parentwin != NULL &&
7412 (parentwin == private || lastwin != (GdkWindowObject*) base_window);
7413 lastwin = parentwin, parentwin = lastwin->parent)
7416 GdkRectangle real_clip_rect;
7417 gboolean is_offscreen;
7419 if (parentwin != private)
7421 x_offset += GDK_WINDOW_OBJECT (lastwin)->x;
7422 y_offset += GDK_WINDOW_OBJECT (lastwin)->y;
7425 is_offscreen = gdk_window_is_offscreen (parentwin);
7427 /* children is ordered in reverse stack order */
7428 for (cur = parentwin->children;
7429 cur && cur->data != lastwin;
7432 GdkWindow *child = cur->data;
7433 GdkWindowObject *child_private = (GdkWindowObject *)child;
7435 if (!GDK_WINDOW_IS_MAPPED (child) || child_private->input_only)
7438 /* Ignore offscreen children, as they don't draw in their parent and
7439 * don't take part in the clipping */
7440 if (gdk_window_is_offscreen (child_private))
7443 window_get_size_rectangle (child, &visible_rect);
7445 /* Convert rect to "window" coords */
7446 visible_rect.x += child_private->x - x_offset;
7447 visible_rect.y += child_private->y - y_offset;
7449 /* This shortcut is really necessary for performance when there are a lot of windows */
7450 gdk_region_get_clipbox (real_clip_region, &real_clip_rect);
7451 if (visible_rect.x >= real_clip_rect.x + real_clip_rect.width ||
7452 visible_rect.x + visible_rect.width <= real_clip_rect.x ||
7453 visible_rect.y >= real_clip_rect.y + real_clip_rect.height ||
7454 visible_rect.y + visible_rect.height <= real_clip_rect.y)
7457 tmpreg = gdk_region_rectangle (&visible_rect);
7458 gdk_region_subtract (real_clip_region, tmpreg);
7459 gdk_region_destroy (tmpreg);
7462 /* Clip to the parent */
7463 window_get_size_rectangle ((GdkWindow *)parentwin, &visible_rect);
7464 /* Convert rect to "window" coords */
7465 visible_rect.x += - x_offset;
7466 visible_rect.y += - y_offset;
7468 tmpreg = gdk_region_rectangle (&visible_rect);
7469 gdk_region_intersect (real_clip_region, tmpreg);
7470 gdk_region_destroy (tmpreg);
7474 *base_x_offset = x_offset;
7476 *base_y_offset = y_offset;
7478 return real_clip_region;
7482 _gdk_window_add_damage (GdkWindow *toplevel,
7483 GdkRegion *damaged_region)
7485 GdkDisplay *display;
7486 GdkEvent event = { 0, };
7487 event.expose.type = GDK_DAMAGE;
7488 event.expose.window = toplevel;
7489 event.expose.send_event = FALSE;
7490 event.expose.region = damaged_region;
7491 gdk_region_get_clipbox (event.expose.region, &event.expose.area);
7492 display = gdk_drawable_get_display (event.expose.window);
7493 _gdk_event_queue_append (display, gdk_event_copy (&event));
7497 gdk_window_redirect_free (GdkWindowRedirect *redirect)
7499 g_object_unref (redirect->pixmap);
7504 convert_coords_to_child (GdkWindowObject *child,
7506 double *child_x, double *child_y)
7508 *child_x = x - child->x;
7509 *child_y = y - child->y;
7511 if (child->offscreen_hooks)
7512 child->offscreen_hooks->from_parent ((GdkWindow *)child, x, y, child_x, child_y);
7516 point_in_window (GdkWindowObject *window,
7520 x >= 0 && x < window->width &&
7521 y >= 0 && y < window->height &&
7522 (window->shape == NULL ||
7523 gdk_region_point_in (window->shape,
7525 (window->input_shape == NULL ||
7526 gdk_region_point_in (window->input_shape,
7531 convert_toplevel_coords_to_window (GdkWindow *window,
7537 GdkWindowObject *private;
7539 GList *children, *l;
7541 private = GDK_WINDOW_OBJECT (window);
7547 while (private->parent != NULL &&
7548 (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT))
7550 children = g_list_prepend (children, private);
7551 private = private->parent;
7554 for (l = children; l != NULL; l = l->next)
7555 convert_coords_to_child (l->data, x, y, &x, &y);
7557 g_list_free (children);
7564 _gdk_window_find_descendant_at (GdkWindow *toplevel,
7569 GdkWindowObject *private, *sub;
7570 double child_x, child_y;
7573 private = (GdkWindowObject *)toplevel;
7575 if (point_in_window (private, x, y))
7579 /* Children is ordered in reverse stack order, i.e. first is topmost */
7580 for (l = private->children; l != NULL; l = l->next)
7584 if (!GDK_WINDOW_IS_MAPPED (sub))
7587 convert_coords_to_child (sub,
7589 &child_x, &child_y);
7590 if (point_in_window (sub, child_x, child_y))
7603 /* Not in window at all */
7612 return (GdkWindow *)private;
7615 static const guint type_masks[] = {
7616 GDK_SUBSTRUCTURE_MASK, /* GDK_DELETE = 0 */
7617 GDK_STRUCTURE_MASK, /* GDK_DESTROY = 1 */
7618 GDK_EXPOSURE_MASK, /* GDK_EXPOSE = 2 */
7619 GDK_POINTER_MOTION_MASK, /* GDK_MOTION_NOTIFY = 3 */
7620 GDK_BUTTON_PRESS_MASK, /* GDK_BUTTON_PRESS = 4 */
7621 GDK_BUTTON_PRESS_MASK, /* GDK_2BUTTON_PRESS = 5 */
7622 GDK_BUTTON_PRESS_MASK, /* GDK_3BUTTON_PRESS = 6 */
7623 GDK_BUTTON_RELEASE_MASK, /* GDK_BUTTON_RELEASE = 7 */
7624 GDK_KEY_PRESS_MASK, /* GDK_KEY_PRESS = 8 */
7625 GDK_KEY_RELEASE_MASK, /* GDK_KEY_RELEASE = 9 */
7626 GDK_ENTER_NOTIFY_MASK, /* GDK_ENTER_NOTIFY = 10 */
7627 GDK_LEAVE_NOTIFY_MASK, /* GDK_LEAVE_NOTIFY = 11 */
7628 GDK_FOCUS_CHANGE_MASK, /* GDK_FOCUS_CHANGE = 12 */
7629 GDK_STRUCTURE_MASK, /* GDK_CONFIGURE = 13 */
7630 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_MAP = 14 */
7631 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_UNMAP = 15 */
7632 GDK_PROPERTY_CHANGE_MASK, /* GDK_PROPERTY_NOTIFY = 16 */
7633 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_CLEAR = 17 */
7634 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_REQUEST = 18 */
7635 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_NOTIFY = 19 */
7636 GDK_PROXIMITY_IN_MASK, /* GDK_PROXIMITY_IN = 20 */
7637 GDK_PROXIMITY_OUT_MASK, /* GDK_PROXIMITY_OUT = 21 */
7638 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_ENTER = 22 */
7639 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_LEAVE = 23 */
7640 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_MOTION = 24 */
7641 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_STATUS = 25 */
7642 GDK_ALL_EVENTS_MASK, /* GDK_DROP_START = 26 */
7643 GDK_ALL_EVENTS_MASK, /* GDK_DROP_FINISHED = 27 */
7644 GDK_ALL_EVENTS_MASK, /* GDK_CLIENT_EVENT = 28 */
7645 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_VISIBILITY_NOTIFY = 29 */
7646 GDK_EXPOSURE_MASK, /* GDK_NO_EXPOSE = 30 */
7647 GDK_SCROLL_MASK | GDK_BUTTON_PRESS_MASK,/* GDK_SCROLL= 31 */
7648 0, /* GDK_WINDOW_STATE = 32 */
7649 0, /* GDK_SETTING = 33 */
7650 0, /* GDK_OWNER_CHANGE = 34 */
7651 0, /* GDK_GRAB_BROKEN = 35 */
7652 0, /* GDK_DAMAGE = 36 */
7654 G_STATIC_ASSERT (G_N_ELEMENTS (type_masks) == GDK_EVENT_LAST);
7656 /* send motion events if the right buttons are down */
7658 update_evmask_for_button_motion (guint evmask,
7659 GdkModifierType mask)
7661 if (evmask & GDK_BUTTON_MOTION_MASK &&
7662 mask & (GDK_BUTTON1_MASK |
7667 evmask |= GDK_POINTER_MOTION_MASK;
7669 if ((evmask & GDK_BUTTON1_MOTION_MASK && mask & GDK_BUTTON1_MASK) ||
7670 (evmask & GDK_BUTTON2_MOTION_MASK && mask & GDK_BUTTON2_MASK) ||
7671 (evmask & GDK_BUTTON3_MOTION_MASK && mask & GDK_BUTTON3_MASK))
7672 evmask |= GDK_POINTER_MOTION_MASK;
7678 is_button_type (GdkEventType type)
7680 return type == GDK_BUTTON_PRESS ||
7681 type == GDK_2BUTTON_PRESS ||
7682 type == GDK_3BUTTON_PRESS ||
7683 type == GDK_BUTTON_RELEASE ||
7688 is_motion_type (GdkEventType type)
7690 return type == GDK_MOTION_NOTIFY ||
7691 type == GDK_ENTER_NOTIFY ||
7692 type == GDK_LEAVE_NOTIFY;
7695 static GdkWindowObject *
7696 find_common_ancestor (GdkWindowObject *win1,
7697 GdkWindowObject *win2)
7699 GdkWindowObject *tmp;
7700 GList *path1 = NULL, *path2 = NULL;
7701 GList *list1, *list2;
7704 while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
7706 path1 = g_list_prepend (path1, tmp);
7711 while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
7713 path2 = g_list_prepend (path2, tmp);
7720 while (list1 && list2 && (list1->data == list2->data))
7722 tmp = (GdkWindowObject *)list1->data;
7723 list1 = g_list_next (list1);
7724 list2 = g_list_next (list2);
7726 g_list_free (path1);
7727 g_list_free (path2);
7733 _gdk_make_event (GdkWindow *window,
7735 GdkEvent *event_in_queue,
7736 gboolean before_event)
7738 GdkEvent *event = gdk_event_new (type);
7740 GdkModifierType the_state;
7742 the_time = gdk_event_get_time (event_in_queue);
7743 gdk_event_get_state (event_in_queue, &the_state);
7745 event->any.window = g_object_ref (window);
7746 event->any.send_event = FALSE;
7750 case GDK_MOTION_NOTIFY:
7751 event->motion.time = the_time;
7752 event->motion.axes = NULL;
7753 event->motion.state = the_state;
7756 case GDK_BUTTON_PRESS:
7757 case GDK_2BUTTON_PRESS:
7758 case GDK_3BUTTON_PRESS:
7759 case GDK_BUTTON_RELEASE:
7760 event->button.time = the_time;
7761 event->button.axes = NULL;
7762 event->button.state = the_state;
7766 event->scroll.time = the_time;
7767 event->scroll.state = the_state;
7771 case GDK_KEY_RELEASE:
7772 event->key.time = the_time;
7773 event->key.state = the_state;
7776 case GDK_ENTER_NOTIFY:
7777 case GDK_LEAVE_NOTIFY:
7778 event->crossing.time = the_time;
7779 event->crossing.state = the_state;
7782 case GDK_PROPERTY_NOTIFY:
7783 event->property.time = the_time;
7784 event->property.state = the_state;
7787 case GDK_SELECTION_CLEAR:
7788 case GDK_SELECTION_REQUEST:
7789 case GDK_SELECTION_NOTIFY:
7790 event->selection.time = the_time;
7793 case GDK_PROXIMITY_IN:
7794 case GDK_PROXIMITY_OUT:
7795 event->proximity.time = the_time;
7798 case GDK_DRAG_ENTER:
7799 case GDK_DRAG_LEAVE:
7800 case GDK_DRAG_MOTION:
7801 case GDK_DRAG_STATUS:
7802 case GDK_DROP_START:
7803 case GDK_DROP_FINISHED:
7804 event->dnd.time = the_time;
7807 case GDK_FOCUS_CHANGE:
7811 case GDK_CLIENT_EVENT:
7812 case GDK_VISIBILITY_NOTIFY:
7824 _gdk_event_queue_insert_before (gdk_drawable_get_display (window), event_in_queue, event);
7826 _gdk_event_queue_insert_after (gdk_drawable_get_display (window), event_in_queue, event);
7829 _gdk_event_queue_append (gdk_drawable_get_display (window), event);
7835 send_crossing_event (GdkDisplay *display,
7836 GdkWindowObject *toplevel,
7837 GdkWindowObject *window,
7839 GdkCrossingMode mode,
7840 GdkNotifyType notify_type,
7841 GdkWindow *subwindow,
7844 GdkModifierType mask,
7846 GdkEvent *event_in_queue)
7851 if (display->pointer_grab.window != NULL &&
7852 !display->pointer_grab.owner_events &&
7853 (GdkWindow *)window != display->pointer_grab.window)
7856 if (type == GDK_LEAVE_NOTIFY)
7857 event_mask = GDK_LEAVE_NOTIFY_MASK;
7859 event_mask = GDK_ENTER_NOTIFY_MASK;
7861 if (window->event_mask & event_mask)
7863 event = _gdk_make_event ((GdkWindow *)window, type, event_in_queue, TRUE);
7864 event->crossing.time = time_;
7865 event->crossing.subwindow = subwindow;
7867 g_object_ref (subwindow);
7868 convert_toplevel_coords_to_window ((GdkWindow *)window,
7869 toplevel_x, toplevel_y,
7870 &event->crossing.x, &event->crossing.y);
7871 event->crossing.x_root = toplevel_x + toplevel->x;
7872 event->crossing.y_root = toplevel_y + toplevel->y;
7873 event->crossing.mode = mode;
7874 event->crossing.detail = notify_type;
7875 event->crossing.focus = FALSE;
7876 event->crossing.state = mask;
7881 /* The coordinates are in the toplevel window that src/dest are in.
7882 * src and dest are always (if != NULL) in the same toplevel, as
7883 * we get a leave-notify and set the window_under_pointer to null
7884 * before crossing to another toplevel.
7887 _gdk_syntesize_crossing_events (GdkDisplay *display,
7890 GdkCrossingMode mode,
7893 GdkModifierType mask,
7895 GdkEvent *event_in_queue)
7898 GdkWindowObject *win, *last, *next;
7900 gboolean non_linear;
7903 GdkWindowObject *toplevel;
7904 GdkNotifyType notify_type;
7906 /* TODO: Don't send events to toplevel, as we get those from the windowing system */
7908 a = (GdkWindowObject *)src;
7909 b = (GdkWindowObject *)dest;
7911 return; /* No crossings generated between src and dest */
7913 c = find_common_ancestor (a, b);
7915 non_linear = (c != a) && (c != b);
7917 if (a) /* There might not be a source (i.e. if no previous pointer_in_window) */
7919 toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)a);
7921 /* Traverse up from a to (excluding) c sending leave events */
7923 notify_type = GDK_NOTIFY_NONLINEAR;
7925 notify_type = GDK_NOTIFY_INFERIOR;
7927 notify_type = GDK_NOTIFY_ANCESTOR;
7928 send_crossing_event (display, toplevel,
7929 a, GDK_LEAVE_NOTIFY,
7933 toplevel_x, toplevel_y,
7940 notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
7942 notify_type = GDK_NOTIFY_VIRTUAL;
7946 while (win != c && GDK_WINDOW_TYPE (win) != GDK_WINDOW_ROOT)
7948 send_crossing_event (display, toplevel,
7949 win, GDK_LEAVE_NOTIFY,
7953 toplevel_x, toplevel_y,
7963 if (b) /* Might not be a dest, e.g. if we're moving out of the window */
7965 toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)b);
7967 /* Traverse down from c to b */
7972 while (win != c && GDK_WINDOW_TYPE (win) != GDK_WINDOW_ROOT)
7974 path = g_list_prepend (path, win);
7979 notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
7981 notify_type = GDK_NOTIFY_VIRTUAL;
7986 win = (GdkWindowObject *)list->data;
7987 list = g_list_next (list);
7989 next = (GdkWindowObject *)list->data;
7993 send_crossing_event (display, toplevel,
7994 win, GDK_ENTER_NOTIFY,
7998 toplevel_x, toplevel_y,
8007 notify_type = GDK_NOTIFY_NONLINEAR;
8009 notify_type = GDK_NOTIFY_ANCESTOR;
8011 notify_type = GDK_NOTIFY_INFERIOR;
8013 send_crossing_event (display, toplevel,
8014 b, GDK_ENTER_NOTIFY,
8018 toplevel_x, toplevel_y,
8025 get_toplevel (GdkWindow *w)
8027 GdkWindowObject *private = GDK_WINDOW_OBJECT (w);
8029 while (private->parent != NULL &&
8030 (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT))
8031 private = private->parent;
8033 return GDK_WINDOW (private);
8036 /* Returns the window inside the event window with the pointer in it
8037 * at the specified coordinates, or NULL if its not in any child of
8038 * the toplevel. It also takes into account !owner_events grabs.
8041 get_pointer_window (GdkDisplay *display,
8042 GdkWindow *event_window,
8046 GdkWindow *pointer_window;
8048 if (event_window == display->pointer_info.toplevel_under_pointer)
8050 _gdk_window_find_descendant_at (event_window,
8051 toplevel_x, toplevel_y,
8054 pointer_window = NULL;
8056 if (display->pointer_grab.window != NULL &&
8057 !display->pointer_grab.owner_events &&
8058 pointer_window != display->pointer_grab.window)
8059 pointer_window = NULL;
8061 return pointer_window;
8065 _gdk_display_set_window_under_pointer (GdkDisplay *display,
8068 GdkWindowObject *private;
8070 private = (GdkWindowObject *)window;
8072 if (display->pointer_info.window_under_pointer)
8073 g_object_unref (display->pointer_info.window_under_pointer);
8074 display->pointer_info.window_under_pointer = window;
8076 g_object_ref (window);
8079 update_cursor (display);
8083 _gdk_syntesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
8085 GdkDisplay *display;
8086 GdkWindow *changed_toplevel;
8087 GdkWindow *new_window_under_pointer;
8089 changed_toplevel = get_toplevel (changed_window);
8091 display = gdk_drawable_get_display (changed_window);
8092 if (changed_toplevel == display->pointer_info.toplevel_under_pointer)
8094 new_window_under_pointer =
8095 get_pointer_window (display, changed_toplevel,
8096 display->pointer_info.toplevel_x,
8097 display->pointer_info.toplevel_y);
8098 if (new_window_under_pointer !=
8099 display->pointer_info.window_under_pointer)
8101 _gdk_syntesize_crossing_events (display,
8102 display->pointer_info.window_under_pointer,
8103 new_window_under_pointer,
8104 GDK_CROSSING_NORMAL,
8105 display->pointer_info.toplevel_x,
8106 display->pointer_info.toplevel_y,
8107 display->pointer_info.state,
8110 _gdk_display_set_window_under_pointer (display, new_window_under_pointer);
8115 /* Don't use for crossing events */
8117 get_event_window (GdkDisplay *display,
8118 GdkWindow *pointer_window,
8120 GdkModifierType mask)
8123 GdkWindow *grab_window;
8126 if ((display->pointer_grab.window != NULL && !display->pointer_grab.owner_events) ||
8127 (type == GDK_BUTTON_RELEASE && display->pointer_grab.grab_one_pointer_release_event))
8129 evmask = display->pointer_grab.event_mask;
8130 evmask = update_evmask_for_button_motion (evmask, mask);
8132 if (type == GDK_BUTTON_RELEASE &&
8133 display->pointer_grab.grab_one_pointer_release_event)
8135 grab_window = display->pointer_grab.grab_one_pointer_release_event;
8136 display->pointer_grab.grab_one_pointer_release_event = NULL;
8139 grab_window = display->pointer_grab.window;
8141 if (evmask & type_masks[type])
8147 w = (GdkWindowObject *)pointer_window;
8150 evmask = w->event_mask;
8151 evmask = update_evmask_for_button_motion (evmask, mask);
8153 if (evmask & type_masks[type])
8154 return (GdkWindow *)w;
8159 if (display->pointer_grab.window != NULL &&
8160 display->pointer_grab.owner_events)
8162 evmask = display->pointer_grab.event_mask;
8163 evmask = update_evmask_for_button_motion (evmask, mask);
8165 if (evmask & type_masks[type])
8166 return display->pointer_grab.window;
8175 proxy_pointer_event (GdkDisplay *display,
8176 GdkEvent *source_event)
8178 GdkWindow *toplevel_window;
8179 GdkWindow *pointer_window;
8180 GdkWindow *cursor_window;
8181 gboolean sent_motion;
8184 gdouble toplevel_x, toplevel_y;
8187 toplevel_window = source_event->any.window;
8188 gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
8189 gdk_event_get_state (source_event, &state);
8190 time_ = gdk_event_get_time (source_event);
8192 pointer_window = get_pointer_window (display, toplevel_window, toplevel_x, toplevel_y);
8193 if (display->pointer_info.window_under_pointer != pointer_window)
8195 /* Either a toplevel crossing notify that ended up inside a child window,
8196 or a motion notify that got into another child window */
8197 /* Different than last time, send crossing events */
8199 _gdk_syntesize_crossing_events (display,
8200 display->pointer_info.window_under_pointer,
8202 GDK_CROSSING_NORMAL,
8203 toplevel_x, toplevel_y,
8207 _gdk_display_set_window_under_pointer (display, pointer_window);
8209 else if (source_event->type == GDK_MOTION_NOTIFY)
8211 GdkWindow *event_win;
8213 event_win = get_event_window (display,
8221 event = _gdk_make_event (event_win, GDK_MOTION_NOTIFY, source_event, FALSE);
8222 event->motion.time = time_;
8223 convert_toplevel_coords_to_window (event_win,
8224 toplevel_x, toplevel_y,
8225 &event->motion.x, &event->motion.y);
8226 event->motion.x_root = source_event->motion.x_root;
8227 event->motion.y_root = source_event->motion.y_root;;
8228 event->motion.state = state;
8229 event->motion.is_hint = FALSE;
8230 event->motion.device = NULL;
8231 if (source_event && source_event->type == GDK_MOTION_NOTIFY)
8232 event->motion.device = source_event->motion.device;
8236 /* TODO: set cursor from cursor_window, or grab cursor */
8237 cursor_window = pointer_window;
8238 if (display->pointer_grab.window &&
8239 (pointer_window == NULL ||
8240 !is_parent_of (display->pointer_grab.window, pointer_window)))
8241 cursor_window = display->pointer_grab.window;
8242 /* Actually, this should probably happen in synthesize crossing so it works with geometry changes */
8245 /* unlink all move events from queue.
8246 We handle our own, including our emulated masks. */
8251 proxy_button_event (GdkEvent *source_event)
8253 GdkWindow *toplevel_window;
8254 GdkWindow *event_win;
8255 GdkWindow *pointer_window;
8260 gdouble toplevel_x, toplevel_y;
8261 GdkDisplay *display;
8264 type = source_event->any.type;
8265 toplevel_window = source_event->any.window;
8266 gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
8267 gdk_event_get_state (source_event, &state);
8268 time_ = gdk_event_get_time (source_event);
8269 display = gdk_drawable_get_display (source_event->any.window);
8271 if ((type == GDK_BUTTON_PRESS || type == GDK_SCROLL) &&
8272 display->pointer_grab.window == source_event->any.window &&
8273 display->pointer_grab.implicit &&
8274 !display->pointer_grab.converted_implicit)
8277 _gdk_window_find_descendant_at (toplevel_window,
8278 toplevel_x, toplevel_y,
8281 /* Find the actual event window, its what gets the grab */
8282 w = (GdkWindowObject *)pointer_window;
8283 while (w != NULL && w->parent->window_type != GDK_WINDOW_ROOT)
8285 if (w->event_mask & GDK_BUTTON_PRESS_MASK)
8289 pointer_window = (GdkWindow *)w;
8291 if (pointer_window != NULL &&
8292 pointer_window != source_event->any.window)
8293 _gdk_display_set_has_pointer_grab (display,
8295 display->pointer_grab.native_window,
8296 display->pointer_grab.owner_events,
8297 gdk_window_get_events (pointer_window),
8298 display->pointer_grab.serial,
8299 display->pointer_grab.time,
8300 display->pointer_grab.implicit);
8301 display->pointer_grab.converted_implicit = TRUE;
8304 pointer_window = get_pointer_window (display, toplevel_window, toplevel_x, toplevel_y);
8306 event_win = get_event_window (display,
8311 if (event_win == NULL)
8314 event = _gdk_make_event (event_win, type, source_event, FALSE);
8318 case GDK_BUTTON_PRESS:
8319 case GDK_BUTTON_RELEASE:
8320 event->button.button = source_event->button.button;
8321 convert_toplevel_coords_to_window (event_win,
8322 toplevel_x, toplevel_y,
8323 &event->button.x, &event->button.y);
8324 event->button.x_root = source_event->button.x_root;
8325 event->button.y_root = source_event->button.y_root;
8326 event->button.state = state;
8327 event->button.device = source_event->button.device;
8329 if (type == GDK_BUTTON_PRESS)
8330 _gdk_event_button_generate (display, event);
8334 event->scroll.direction = source_event->scroll.direction;
8335 convert_toplevel_coords_to_window (event_win,
8336 toplevel_x, toplevel_y,
8337 &event->scroll.x, &event->scroll.y);
8338 event->scroll.x_root = source_event->scroll.x_root;
8339 event->scroll.y_root = source_event->scroll.y_root;
8340 event->scroll.state = state;
8341 event->scroll.device = source_event->scroll.device;
8348 return TRUE; /* Always unlink original, we want to obey the emulated event mask */
8351 #ifdef DEBUG_WINDOW_PRINTING
8353 gdk_window_print (GdkWindowObject *window,
8358 g_print ("%*s%p: [%s] %d,%d %dx%d", indent, "", window,
8359 window->user_data ? g_type_name_from_instance (window->user_data) : "no widget",
8360 window->x, window->y,
8361 window->width, window->height
8364 if (gdk_window_has_impl (window))
8366 #ifdef GDK_WINDOWING_X11
8367 g_print (" impl(0x%lx)", gdk_x11_drawable_get_xid (GDK_DRAWABLE (window)));
8371 if (window->input_only)
8372 g_print (" input-only");
8374 if (!gdk_window_is_visible ((GdkWindow *)window))
8375 g_print (" hidden");
8377 g_print (" abs[%d,%d]",
8378 window->abs_x, window->abs_y);
8380 gdk_region_get_clipbox (window->clip_region, &r);
8381 if (gdk_region_empty (window->clip_region))
8382 g_print (" clipbox[empty]");
8384 g_print (" clipbox[%d,%d %dx%d]", r.x, r.y, r.width, r.height);
8391 gdk_window_print_tree (GdkWindow *window,
8393 gboolean include_input_only)
8395 GdkWindowObject *private;
8398 private = (GdkWindowObject *)window;
8400 if (private->input_only && !include_input_only)
8403 gdk_window_print (private, indent);
8405 for (l = private->children; l != NULL; l = l->next)
8406 gdk_window_print_tree (l->data, indent + 4, include_input_only);
8409 #endif /* DEBUG_WINDOW_PRINTING */
8412 _gdk_windowing_got_event (GdkDisplay *display,
8416 GdkWindow *event_window;
8417 GdkWindowObject *event_private;
8419 gboolean unlink_event;
8421 event_window = event->any.window;
8425 event_private = GDK_WINDOW_OBJECT (event_window);
8427 #ifdef DEBUG_WINDOW_PRINTING
8428 if (event->type == GDK_KEY_PRESS &&
8429 (event->key.keyval == 0xa7 ||
8430 event->key.keyval == 0xbd))
8432 gdk_window_print_tree (event_window, 0,
8433 event->key.keyval == 0xbd);
8437 if (!(is_button_type (event->type) ||
8438 is_motion_type (event->type)))
8441 if (GDK_WINDOW_TYPE (event_private->parent) != GDK_WINDOW_ROOT)
8443 GEnumValue *event_type_value, *window_type_value;
8445 event_type_value = g_enum_get_value ((GEnumClass *) g_type_class_ref (GDK_TYPE_EVENT_TYPE),
8447 window_type_value = g_enum_get_value ((GEnumClass *) g_type_class_ref (GDK_TYPE_WINDOW_TYPE),
8448 event_private->window_type);
8450 /* We should only get these events on toplevel windows */
8451 g_warning ("got unexpected event of type %s on non-toplevel window (gtype %s, type %d)",
8452 event_type_value->value_name,
8453 window_type_value->value_name,
8454 GDK_WINDOW_TYPE (event_window));
8458 if ((event->type == GDK_ENTER_NOTIFY ||
8459 event->type == GDK_LEAVE_NOTIFY) &&
8460 (event->crossing.mode == GDK_CROSSING_GRAB ||
8461 event->crossing.mode == GDK_CROSSING_UNGRAB))
8463 /* We synthesize all crossing events due to grabs are synthesized,
8464 * so we ignore the native ones. This is partly to get easier non-X
8465 * portability, and because of problems with race conditions due to
8466 * the cached state in the client and the real state in the xserver
8470 /* We ended up in this window after some (perhaps other clients)
8471 grab, so update the toplevel_under_window state */
8472 if (event->type == GDK_ENTER_NOTIFY &&
8473 event->crossing.mode == GDK_CROSSING_UNGRAB)
8475 if (display->pointer_info.toplevel_under_pointer)
8476 g_object_unref (display->pointer_info.toplevel_under_pointer);
8477 display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
8480 unlink_event = TRUE;
8484 /* Store last pointer window and position/state */
8485 if (event->type == GDK_ENTER_NOTIFY &&
8486 event->crossing.detail != GDK_NOTIFY_INFERIOR)
8488 if (display->pointer_info.toplevel_under_pointer)
8489 g_object_unref (display->pointer_info.toplevel_under_pointer);
8490 display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
8492 else if (event->type == GDK_LEAVE_NOTIFY &&
8493 event->crossing.detail != GDK_NOTIFY_INFERIOR &&
8494 display->pointer_info.toplevel_under_pointer == event_window)
8496 if (display->pointer_info.toplevel_under_pointer)
8497 g_object_unref (display->pointer_info.toplevel_under_pointer);
8498 display->pointer_info.toplevel_under_pointer = NULL;
8501 gdk_event_get_coords (event, &x, &y);
8502 display->pointer_info.toplevel_x = x;
8503 display->pointer_info.toplevel_y = y;
8504 gdk_event_get_state (event, &display->pointer_info.state);
8507 unlink_event = FALSE;
8508 if (is_motion_type (event->type))
8509 unlink_event = proxy_pointer_event (display,
8511 else if (is_button_type (event->type))
8512 unlink_event = proxy_button_event (event);
8517 _gdk_event_queue_remove_link (display, event_link);
8518 g_list_free_1 (event_link);
8519 gdk_event_free (event);
8523 #define __GDK_WINDOW_C__
8524 #include "gdkaliasdef.c"