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 #ifdef GDK_WINDOWING_X11
39 #include "x11/gdkx.h" /* For workaround */
44 /* Not all GdkWindows have a corresponding native window.
45 * Instead some draw into the nearest parent that has whatss
46 * called an "impl", i.e. the implementation window.
47 * For toplevel window system windows the impl is always native
48 * window, but child windows can also have native windows as
49 * this is sometimes necessary. Furthermore, offscreen windows
50 * (type GDK_WINDOW_OFFSCREEN) have an impl of type
51 * GdkOffscreenWindow rather than a backend implementation native
52 * window. Such windows draw into an offscreen pixmap instead
53 * of a window and collect damage that lets you paint it where
56 * All GdkWindow track their position, size, clip region and
57 * absolute position in the impl window. For child window with
58 * native windows the clip region is set on the native window
59 * as a window shape to make it clip against other non-native windows.
62 #define USE_BACKING_STORE /* Appears to work on Win32, too, now. */
64 struct _GdkWindowPaint
70 cairo_surface_t *surface;
71 guint uses_implicit : 1;
76 GdkRegion *region; /* The destination region */
78 } GdkWindowRegionMove;
83 static GdkGC *gdk_window_create_gc (GdkDrawable *drawable,
85 GdkGCValuesMask mask);
86 static void gdk_window_draw_rectangle (GdkDrawable *drawable,
93 static void gdk_window_draw_arc (GdkDrawable *drawable,
102 static void gdk_window_draw_polygon (GdkDrawable *drawable,
107 static void gdk_window_draw_text (GdkDrawable *drawable,
114 static void gdk_window_draw_text_wc (GdkDrawable *drawable,
119 const GdkWChar *text,
121 static void gdk_window_draw_drawable (GdkDrawable *drawable,
130 static void gdk_window_draw_points (GdkDrawable *drawable,
134 static void gdk_window_draw_segments (GdkDrawable *drawable,
138 static void gdk_window_draw_lines (GdkDrawable *drawable,
143 static void gdk_window_draw_glyphs (GdkDrawable *drawable,
148 PangoGlyphString *glyphs);
149 static void gdk_window_draw_glyphs_transformed (GdkDrawable *drawable,
155 PangoGlyphString *glyphs);
157 static void gdk_window_draw_image (GdkDrawable *drawable,
167 static void gdk_window_draw_pixbuf (GdkDrawable *drawable,
180 static void gdk_window_draw_trapezoids (GdkDrawable *drawable,
182 GdkTrapezoid *trapezoids,
185 static GdkImage* gdk_window_copy_to_image (GdkDrawable *drawable,
194 static cairo_surface_t *gdk_window_ref_cairo_surface (GdkDrawable *drawable);
195 static void gdk_window_set_cairo_clip (GdkDrawable *drawable,
198 static void gdk_window_real_get_size (GdkDrawable *drawable,
202 static GdkVisual* gdk_window_real_get_visual (GdkDrawable *drawable);
203 static gint gdk_window_real_get_depth (GdkDrawable *drawable);
204 static GdkScreen* gdk_window_real_get_screen (GdkDrawable *drawable);
205 static void gdk_window_real_set_colormap (GdkDrawable *drawable,
207 static GdkColormap* gdk_window_real_get_colormap (GdkDrawable *drawable);
209 static GdkDrawable* gdk_window_get_source_drawable (GdkDrawable *drawable);
210 static GdkDrawable* gdk_window_get_composite_drawable (GdkDrawable *drawable,
215 gint *composite_x_offset,
216 gint *composite_y_offset);
217 static GdkRegion* gdk_window_get_clip_region (GdkDrawable *drawable);
218 static GdkRegion* gdk_window_get_visible_region (GdkDrawable *drawable);
220 static void gdk_window_free_paint_stack (GdkWindow *window);
222 static void gdk_window_init (GdkWindowObject *window);
223 static void gdk_window_class_init (GdkWindowObjectClass *klass);
224 static void gdk_window_finalize (GObject *object);
225 static void gdk_window_clear_backing_rect (GdkWindow *window,
230 static void gdk_window_redirect_free (GdkWindowRedirect *redirect);
231 static void apply_redirect_to_children (GdkWindowObject *private,
232 GdkWindowRedirect *redirect);
233 static void remove_redirect_from_children (GdkWindowObject *private,
234 GdkWindowRedirect *redirect);
236 static void recompute_visible_regions (GdkWindowObject *private,
237 gboolean recalculate_siblings,
238 gboolean recalculate_children);
239 static void gdk_window_flush (GdkWindow *window);
240 static void do_move_region_bits_on_impl (GdkWindowObject *private,
242 int dest_off_x, int dest_off_y,
243 GdkRegion *region, /* In impl window coords */
246 static gpointer parent_class = NULL;
248 static const cairo_user_data_key_t gdk_window_cairo_key;
251 new_region_tag (void)
253 static guint32 tag = 0;
259 gdk_window_object_get_type (void)
261 static GType object_type = 0;
264 object_type = g_type_register_static_simple (GDK_TYPE_DRAWABLE,
266 sizeof (GdkWindowObjectClass),
267 (GClassInitFunc) gdk_window_class_init,
268 sizeof (GdkWindowObject),
269 (GInstanceInitFunc) gdk_window_init,
276 _gdk_paintable_get_type (void)
278 static GType paintable_type = 0;
282 const GTypeInfo paintable_info =
284 sizeof (GdkPaintableIface), /* class_size */
285 NULL, /* base_init */
286 NULL, /* base_finalize */
289 paintable_type = g_type_register_static (G_TYPE_INTERFACE,
290 g_intern_static_string ("GdkPaintable"),
293 g_type_interface_add_prerequisite (paintable_type, G_TYPE_OBJECT);
296 return paintable_type;
300 gdk_window_init (GdkWindowObject *window)
302 /* 0-initialization is good for all other fields. */
304 window->window_type = GDK_WINDOW_CHILD;
306 window->state = GDK_WINDOW_STATE_WITHDRAWN;
309 window->toplevel_window_type = -1;
312 static GQuark quark_pointer_window = 0;
315 gdk_window_class_init (GdkWindowObjectClass *klass)
317 GObjectClass *object_class = G_OBJECT_CLASS (klass);
318 GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
320 parent_class = g_type_class_peek_parent (klass);
322 object_class->finalize = gdk_window_finalize;
324 drawable_class->create_gc = gdk_window_create_gc;
325 drawable_class->draw_rectangle = gdk_window_draw_rectangle;
326 drawable_class->draw_arc = gdk_window_draw_arc;
327 drawable_class->draw_polygon = gdk_window_draw_polygon;
328 drawable_class->draw_text = gdk_window_draw_text;
329 drawable_class->draw_text_wc = gdk_window_draw_text_wc;
330 drawable_class->draw_drawable = gdk_window_draw_drawable;
331 drawable_class->draw_points = gdk_window_draw_points;
332 drawable_class->draw_segments = gdk_window_draw_segments;
333 drawable_class->draw_lines = gdk_window_draw_lines;
334 drawable_class->draw_glyphs = gdk_window_draw_glyphs;
335 drawable_class->draw_glyphs_transformed = gdk_window_draw_glyphs_transformed;
336 drawable_class->draw_image = gdk_window_draw_image;
337 drawable_class->draw_pixbuf = gdk_window_draw_pixbuf;
338 drawable_class->draw_trapezoids = gdk_window_draw_trapezoids;
339 drawable_class->get_depth = gdk_window_real_get_depth;
340 drawable_class->get_screen = gdk_window_real_get_screen;
341 drawable_class->get_size = gdk_window_real_get_size;
342 drawable_class->set_colormap = gdk_window_real_set_colormap;
343 drawable_class->get_colormap = gdk_window_real_get_colormap;
344 drawable_class->get_visual = gdk_window_real_get_visual;
345 drawable_class->_copy_to_image = gdk_window_copy_to_image;
346 drawable_class->ref_cairo_surface = gdk_window_ref_cairo_surface;
347 drawable_class->set_cairo_clip = gdk_window_set_cairo_clip;
348 drawable_class->get_clip_region = gdk_window_get_clip_region;
349 drawable_class->get_visible_region = gdk_window_get_visible_region;
350 drawable_class->get_composite_drawable = gdk_window_get_composite_drawable;
351 drawable_class->get_source_drawable = gdk_window_get_source_drawable;
353 quark_pointer_window = g_quark_from_static_string ("gtk-pointer-window");
357 gdk_window_finalize (GObject *object)
359 GdkWindow *window = GDK_WINDOW (object);
360 GdkWindowObject *obj = (GdkWindowObject *) object;
362 if (!GDK_WINDOW_DESTROYED (window))
364 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
366 g_warning ("losing last reference to undestroyed window\n");
367 _gdk_window_destroy (window, FALSE);
370 /* We use TRUE here, to keep us from actually calling
371 * XDestroyWindow() on the window
373 _gdk_window_destroy (window, TRUE);
378 g_object_unref (obj->impl);
383 gdk_cursor_unref (obj->cursor);
385 G_OBJECT_CLASS (parent_class)->finalize (object);
389 gdk_window_is_offscreen (GdkWindowObject *window)
391 return GDK_WINDOW_TYPE (window) == GDK_WINDOW_OFFSCREEN;
394 static GdkWindowObject *
395 gdk_window_get_impl_window (GdkWindowObject *window)
397 while (window->parent != NULL && window->parent->impl == window->impl)
398 window = window->parent;
404 _gdk_window_get_impl_window (GdkWindow *window)
406 return (GdkWindow *)gdk_window_get_impl_window ((GdkWindowObject *)window);
410 gdk_window_has_impl (GdkWindowObject *window)
412 return window->parent == NULL || window->parent->impl != window->impl;
416 _gdk_window_has_impl (GdkWindow *window)
418 return gdk_window_has_impl ((GdkWindowObject *)window);
422 gdk_window_has_no_impl (GdkWindowObject *window)
424 return window->parent->impl == window->impl;
428 remove_child_area (GdkWindowObject *private,
429 GdkWindowObject *until,
432 GdkWindowObject *child;
433 GdkRegion *child_region;
437 for (l = private->children; l; l = l->next)
444 if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
447 /* Ignore offscreen children, as they don't draw in their parent and
448 * don't take part in the clipping */
449 if (gdk_window_is_offscreen (child))
454 r.width = child->width;
455 r.height = child->height;
457 child_region = gdk_region_rectangle (&r);
458 gdk_region_subtract (region, child_region);
459 gdk_region_destroy (child_region);
464 recompute_visible_regions_internal (GdkWindowObject *private,
465 gboolean recalculate_clip,
466 gboolean recalculate_siblings,
467 gboolean recalculate_children)
471 GdkWindowObject *child;
472 GdkRegion *new_clip, *old_clip_region_with_children;
473 gboolean clip_region_changed;
474 gboolean abs_pos_changed;
475 int old_abs_x, old_abs_y;
477 old_abs_x = private->abs_x;
478 old_abs_y = private->abs_y;
480 /* Update absolute position */
481 if (gdk_window_has_impl (private))
483 /* Native window starts here */
489 private->abs_x = private->parent->abs_x + private->x;
490 private->abs_y = private->parent->abs_y + private->y;
494 private->abs_x != old_abs_x ||
495 private->abs_y != old_abs_y;
497 /* Update clip region based on:
500 * siblings in parents above window
502 clip_region_changed = FALSE;
503 if (recalculate_clip)
505 /* Calculate visible region (sans children) in parent window coords */
508 r.width = private->width;
509 r.height = private->height;
510 new_clip = gdk_region_rectangle (&r);
512 if (private->parent != NULL && GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
514 gdk_region_intersect (new_clip, private->parent->clip_region);
516 /* Remove all overlapping children from parent */
517 remove_child_area (private->parent, private, new_clip);
520 /* Convert from parent coords to window coords */
521 gdk_region_offset (new_clip, -private->x, -private->y);
523 if (private->clip_region == NULL ||
524 !gdk_region_equal (private->clip_region, new_clip))
525 clip_region_changed = TRUE;
527 if (private->clip_region)
528 gdk_region_destroy (private->clip_region);
529 private->clip_region = new_clip;
531 old_clip_region_with_children = private->clip_region_with_children;
532 private->clip_region_with_children = gdk_region_copy (private->clip_region);
533 remove_child_area (private, NULL, private->clip_region_with_children);
535 if (clip_region_changed ||
536 !gdk_region_equal (private->clip_region_with_children, old_clip_region_with_children))
537 private->clip_tag = new_region_tag ();
539 if (old_clip_region_with_children)
540 gdk_region_destroy (old_clip_region_with_children);
543 /* Update all children, recursively. */
544 if (abs_pos_changed || clip_region_changed || recalculate_children)
546 for (l = private->children; l; l = l->next)
549 /* Only recalculate clip if the the clip region changed, otherwise
550 * there is no way the child clip region could change (its has not e.g. moved)
551 * Except if recalculate_children is set to force child updates
553 recompute_visible_regions_internal (child, recalculate_clip && (clip_region_changed || recalculate_children), FALSE, FALSE);
557 if (clip_region_changed &&
558 gdk_window_has_impl (private) &&
559 /* Not for offscreens */
560 private->window_type != GDK_WINDOW_OFFSCREEN &&
561 /* or for toplevels */
562 private->parent != NULL &&
563 GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT &&
564 /* or for foreign windows */
565 GDK_WINDOW_TYPE (private) != GDK_WINDOW_FOREIGN
568 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region ((GdkWindow *)private, private->clip_region, 0, 0);
572 if (recalculate_siblings &&
573 private->parent != NULL &&
574 GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
576 /* If we moved a child window in parent or changed the stacking order, then we
577 * need to recompute the visible area of all the other children in the parent
579 for (l = private->parent->children; l; l = l->next)
583 if (child != private)
584 recompute_visible_regions_internal (child, TRUE, FALSE, FALSE);
587 /* We also need to recompute the _with_children clip for the parent */
588 recompute_visible_regions_internal (private->parent, TRUE, FALSE, FALSE);
591 if (private->cairo_surface)
595 /* It would be nice if we had some cairo support here so we
596 could set the clip rect on the cairo surface */
597 width = private->abs_x + private->width;
598 height = private->abs_y + private->height;
600 _gdk_windowing_set_cairo_surface_size (private->cairo_surface,
602 cairo_surface_set_device_offset (private->cairo_surface,
608 /* Call this when private has changed in one or more of these ways:
612 * stacking order of window changed
615 * It will recalculate abs_x/y and the clip regions
617 * Unless the window didn't change stacking order or size/pos, pass in TRUE
618 * for recalculate_siblings. (Mostly used internally for the recursion)
620 * If a child window was removed (and you can't use that child for
621 * recompute_visible_regions), pass in TRUE for recalculate_children on the parent
624 recompute_visible_regions (GdkWindowObject *private,
625 gboolean recalculate_siblings,
626 gboolean recalculate_children)
628 recompute_visible_regions_internal (private,
630 recalculate_siblings,
631 recalculate_children);
635 _gdk_window_update_size (GdkWindow *window)
637 recompute_visible_regions ((GdkWindowObject *)window, TRUE, FALSE);
641 get_native_event_mask (GdkWindowObject *private)
643 if (GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
646 GDK_POINTER_MOTION_MASK |
647 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
648 GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK |
649 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
650 GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK | GDK_PROPERTY_CHANGE_MASK |
651 GDK_PROXIMITY_IN_MASK | GDK_PROXIMITY_OUT_MASK | GDK_SCROLL_MASK;
653 return GDK_EXPOSURE_MASK;
659 * @parent: a #GdkWindow, or %NULL to create the window as a child of
660 * the default root window for the default display.
661 * @attributes: attributes of the new window
662 * @attributes_mask: mask indicating which fields in @attributes are valid
664 * Creates a new #GdkWindow using the attributes from
665 * @attributes. See #GdkWindowAttr and #GdkWindowAttributesType for
666 * more details. Note: to use this on displays other than the default
667 * display, @parent must be specified.
669 * Return value: the new #GdkWindow
672 gdk_window_new (GdkWindow *parent,
673 GdkWindowAttr *attributes,
674 gint attributes_mask)
677 GdkWindowObject *private;
682 GdkEventMask event_mask;
683 GdkWindow *real_parent;
685 g_return_val_if_fail (attributes != NULL, NULL);
690 g_warning ("gdk_window_new(): no parent specified reverting to parent = default root window"));
692 screen = gdk_screen_get_default ();
693 parent = gdk_screen_get_root_window (screen);
696 screen = gdk_drawable_get_screen (parent);
698 g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
700 if (GDK_WINDOW_DESTROYED (parent))
703 window = g_object_new (GDK_TYPE_WINDOW, NULL);
704 private = (GdkWindowObject *) window;
706 /* Windows with a foreign parent are treated as if they are children
707 * of the root window, except for actual creation.
709 real_parent = parent;
710 if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
711 parent = gdk_screen_get_root_window (screen);
713 private->parent = (GdkWindowObject *)parent;
715 private->accept_focus = TRUE;
716 private->focus_on_map = TRUE;
718 if (attributes_mask & GDK_WA_X)
723 if (attributes_mask & GDK_WA_Y)
730 private->width = (attributes->width > 1) ? (attributes->width) : (1);
731 private->height = (attributes->height > 1) ? (attributes->height) : (1);
733 #ifdef GDK_WINDOWING_X11
734 /* Work around a bug where Xorg refuses to map toplevel InputOnly windows
735 * from an untrusted client: http://bugs.freedesktop.org/show_bug.cgi?id=6988
737 if (attributes->wclass == GDK_INPUT_ONLY &&
738 GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT &&
739 !G_LIKELY (GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (parent))->trusted_client))
741 g_warning ("Coercing GDK_INPUT_ONLY toplevel window to GDK_INPUT_OUTPUT to work around bug in Xorg server");
742 attributes->wclass = GDK_INPUT_OUTPUT;
746 if (attributes->wclass == GDK_INPUT_ONLY)
748 /* Backwards compatiblity - we've always ignored
749 * attributes->window_type for input-only windows
752 if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
753 private->window_type = GDK_WINDOW_TEMP;
755 private->window_type = GDK_WINDOW_CHILD;
758 private->window_type = attributes->window_type;
761 switch (private->window_type)
763 case GDK_WINDOW_TOPLEVEL:
764 case GDK_WINDOW_DIALOG:
765 case GDK_WINDOW_TEMP:
766 if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
767 g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
768 "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
769 case GDK_WINDOW_CHILD:
770 case GDK_WINDOW_OFFSCREEN:
773 g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
777 if (attributes_mask & GDK_WA_VISUAL)
778 visual = attributes->visual;
780 visual = gdk_screen_get_system_visual (screen);
782 private->event_mask = attributes->event_mask;
784 if (attributes->wclass == GDK_INPUT_OUTPUT)
786 private->input_only = FALSE;
787 private->depth = visual->depth;
789 private->bg_color.pixel = 0; // TODO: BlackPixel (xdisplay, screen_x11->screen_num);
790 private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
792 private->bg_pixmap = NULL;
797 private->input_only = TRUE;
801 private->parent->children = g_list_prepend (private->parent->children, window);
803 native = FALSE; /* Default */
804 if (GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
805 native = TRUE; /* Always use native windows for toplevels */
806 else if (!private->input_only &&
807 ((attributes_mask & GDK_WA_COLORMAP &&
808 attributes->colormap != gdk_drawable_get_colormap ((GdkDrawable *)private->parent)) ||
809 (attributes_mask & GDK_WA_VISUAL &&
810 attributes->visual != gdk_drawable_get_visual ((GdkDrawable *)private->parent))))
811 native = TRUE; /* InputOutput window with different colormap or visual than parent, needs native window */
813 if (private->window_type == GDK_WINDOW_OFFSCREEN)
815 _gdk_offscreen_window_new (window, screen, visual, attributes, attributes_mask);
819 event_mask = get_native_event_mask (private);
821 /* Create the impl */
822 _gdk_window_impl_new (window, real_parent, screen, visual, event_mask, attributes, attributes_mask);
826 private->impl = private->parent->impl;
829 recompute_visible_regions (private, TRUE, FALSE);
831 if (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
833 /* Inherit redirection from parent */
834 private->redirect = private->parent->redirect;
841 is_parent_of (GdkWindow *parent,
852 w = gdk_window_get_parent (w);
859 change_impl (GdkWindowObject *private,
863 GdkWindowObject *child;
865 GdkDrawable *old_impl;
867 old_impl = private->impl;
870 for (l = private->children; l != NULL; l = l->next)
874 if (child->impl == old_impl)
875 change_impl (child, new);
878 show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent ((GdkWindow *)child,
879 (GdkWindow *)private,
882 gdk_window_show_unraised ((GdkWindow *)child);
889 * gdk_window_reparent:
890 * @window: a #GdkWindow
891 * @new_parent: new parent to move @window into
892 * @x: X location inside the new parent
893 * @y: Y location inside the new parent
895 * Reparents @window into the given @new_parent. The window being
896 * reparented will be unmapped as a side effect.
900 gdk_window_reparent (GdkWindow *window,
901 GdkWindow *new_parent,
905 GdkWindowObject *private;
906 GdkWindowObject *new_parent_private;
907 GdkWindowObject *old_parent;
908 gboolean show, was_toplevel, was_mapped;
910 g_return_if_fail (GDK_IS_WINDOW (window));
911 g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
912 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
914 if (GDK_WINDOW_DESTROYED (window) ||
915 (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
919 new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
921 private = (GdkWindowObject *) window;
922 new_parent_private = (GdkWindowObject *)new_parent;
924 /* No input-output children of input-only windows */
925 if (new_parent_private->input_only && !private->input_only)
928 /* Don't create loops in hierarchy */
929 if (is_parent_of (window, new_parent))
932 if (private->cairo_surface)
934 /* This might be wrong in the new parent, e.g. for non-native surfaces.
935 To make sure we're ok, just wipe it. */
936 cairo_surface_finish (private->cairo_surface);
937 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
941 old_parent = private->parent;
943 /* Break up redirection if inherited */
944 if (private->redirect && private->redirect->redirected != private)
946 remove_redirect_from_children (private, private->redirect);
947 private->redirect = NULL;
950 was_toplevel = private->parent == NULL;
951 was_mapped = GDK_WINDOW_IS_MAPPED (window);
954 /* Reparenting to toplevel. Ensure we have a native window so this can work */
955 if (new_parent_private->window_type == GDK_WINDOW_ROOT ||
956 new_parent_private->window_type == GDK_WINDOW_FOREIGN)
957 gdk_window_set_has_native (window, TRUE);
959 if (gdk_window_has_impl (private))
962 show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent (window, new_parent, x, y);
966 /* This shouldn't happen, as we created a native in this case, check anyway to see if that ever fails */
967 g_assert (new_parent_private->window_type != GDK_WINDOW_ROOT &&
968 new_parent_private->window_type != GDK_WINDOW_FOREIGN);
971 gdk_window_hide (window);
973 change_impl (private, new_parent_private->impl);
976 /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
979 if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
981 new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
982 new_parent_private = (GdkWindowObject *)new_parent;
986 private->parent->children = g_list_remove (private->parent->children, window);
988 private->parent = new_parent_private;
992 new_parent_private->children = g_list_prepend (new_parent_private->children, window);
994 /* Switch the window type as appropriate */
996 switch (GDK_WINDOW_TYPE (new_parent))
998 case GDK_WINDOW_ROOT:
999 case GDK_WINDOW_FOREIGN:
1000 if (private->toplevel_window_type != -1)
1001 GDK_WINDOW_TYPE (window) = private->toplevel_window_type;
1002 else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1003 GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
1005 case GDK_WINDOW_OFFSCREEN:
1006 case GDK_WINDOW_TOPLEVEL:
1007 case GDK_WINDOW_CHILD:
1008 case GDK_WINDOW_DIALOG:
1009 case GDK_WINDOW_TEMP:
1010 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
1011 GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
1013 /* Save the original window type so we can restore it if the
1014 * window is reparented back to be a toplevel
1016 private->toplevel_window_type = GDK_WINDOW_TYPE (window);
1017 GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
1021 /* We might have changed window type for a native windows, so we
1022 need to change the event mask too. */
1023 if (gdk_window_has_impl (private))
1024 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_events (window, get_native_event_mask (private));
1026 /* Inherit parent redirect if we don't have our own */
1027 if (private->parent && private->redirect == NULL)
1029 private->redirect = private->parent->redirect;
1030 apply_redirect_to_children (private, private->redirect);
1033 recompute_visible_regions (private, TRUE, FALSE);
1034 if (old_parent && GDK_WINDOW_TYPE (old_parent) != GDK_WINDOW_ROOT)
1035 recompute_visible_regions (old_parent, FALSE, TRUE);
1038 gdk_window_show_unraised (window);
1040 _gdk_syntesize_crossing_events_for_geometry_change (window);
1044 * gdk_window_set_has_native:
1045 * @window: a #GdkWindow
1046 * @has_native: whethe the window should have a native window
1048 * Tries to create or remove a window-system native window for this
1049 * GdkWindow. This may fail in some situations. For instance:
1051 * Toplevel and foreign windows must have a native window.
1052 * Offscreen window and children of them can never have native windows.
1053 * Some backends may not support native child windows.
1057 gdk_window_set_has_native (GdkWindow *window, gboolean has_native)
1059 GdkWindowObject *private;
1060 GdkWindowObject *impl_window;
1061 GdkDrawable *new_impl, *old_impl;
1064 GdkWindowAttr attributes;
1066 g_return_if_fail (GDK_IS_WINDOW (window));
1068 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT ||
1069 GDK_WINDOW_DESTROYED (window))
1072 private = (GdkWindowObject *) window;
1076 /* Create native window */
1078 if (gdk_window_has_impl (private))
1079 /* Already has an impl, either native (ok) or
1080 offscreen (not supported). Bail. */
1083 impl_window = gdk_window_get_impl_window (private);
1084 if (impl_window->window_type == GDK_WINDOW_OFFSCREEN)
1085 return; /* native in offscreens not supported */
1087 screen = gdk_drawable_get_screen (window);
1088 visual = gdk_drawable_get_visual (window);
1090 attributes.colormap = gdk_drawable_get_colormap (window);
1092 old_impl = private->impl;
1093 _gdk_window_impl_new (window, (GdkWindow *)private->parent, screen, visual,
1094 get_native_event_mask (private), &attributes, GDK_WA_COLORMAP);
1095 new_impl = private->impl;
1097 private->impl = old_impl;
1098 change_impl (private, new_impl);
1102 /* Remove native window */
1104 if (!gdk_window_has_impl (private))
1105 return; /* Not native, can't remove */
1107 if (private->window_type == GDK_WINDOW_OFFSCREEN)
1108 return; /* Not native, can't remove */
1110 if (private->parent == NULL ||
1111 GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
1112 return; /* toplevel, must be native */
1114 g_warning ("Tried to turn native window to client side window, this is not supported yet.");
1116 /* TODO: remove native */
1121 window_remove_filters (GdkWindow *window)
1123 GdkWindowObject *obj = (GdkWindowObject*) window;
1129 for (tmp_list = obj->filters; tmp_list; tmp_list = tmp_list->next)
1130 g_free (tmp_list->data);
1132 g_list_free (obj->filters);
1133 obj->filters = NULL;
1138 * _gdk_window_destroy_hierarchy:
1139 * @window: a #GdkWindow
1140 * @recursing: If TRUE, then this is being called because a parent
1141 * was destroyed. This generally means that the call to the
1142 * windowing system to destroy the window can be omitted, since
1143 * it will be destroyed as a result of the parent being destroyed.
1144 * Unless @foreign_destroy.
1145 * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
1146 * external agency. The window has already been destroyed and no
1147 * windowing system calls should be made. (This may never happen
1148 * for some windowing systems.)
1150 * Internal function to destroy a window. Like gdk_window_destroy(),
1151 * but does not drop the reference count created by gdk_window_new().
1154 _gdk_window_destroy_hierarchy (GdkWindow *window,
1156 gboolean foreign_destroy)
1158 GdkWindowObject *private;
1159 GdkWindowObject *temp_private;
1160 GdkWindow *temp_window;
1162 GdkDisplay *display;
1166 g_return_if_fail (GDK_IS_WINDOW (window));
1168 private = (GdkWindowObject*) window;
1170 if (GDK_WINDOW_DESTROYED (window))
1173 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
1174 screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
1175 temp_window = g_object_get_qdata (G_OBJECT (screen), quark_pointer_window);
1176 if (temp_window == window)
1177 g_object_set_qdata (G_OBJECT (screen), quark_pointer_window, NULL);
1180 switch (GDK_WINDOW_TYPE (window))
1182 case GDK_WINDOW_ROOT:
1183 if (!screen->closed)
1185 g_error ("attempted to destroy root window");
1188 /* else fall thru */
1189 case GDK_WINDOW_TOPLEVEL:
1190 case GDK_WINDOW_CHILD:
1191 case GDK_WINDOW_DIALOG:
1192 case GDK_WINDOW_TEMP:
1193 case GDK_WINDOW_FOREIGN:
1194 case GDK_WINDOW_OFFSCREEN:
1195 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN && !foreign_destroy)
1197 /* Logically, it probably makes more sense to send
1198 * a "destroy yourself" message to the foreign window
1199 * whether or not it's in our hierarchy; but for historical
1200 * reasons, we only send "destroy yourself" messages to
1201 * foreign windows in our hierarchy.
1203 if (private->parent)
1204 _gdk_windowing_window_destroy_foreign (window);
1206 /* Also for historical reasons, we remove any filters
1207 * on a foreign window when it or a parent is destroyed;
1208 * this likely causes problems if two separate portions
1209 * of code are maintaining filter lists on a foreign window.
1211 window_remove_filters (window);
1215 if (private->parent)
1217 GdkWindowObject *parent_private = (GdkWindowObject *)private->parent;
1218 if (parent_private->children)
1219 parent_private->children = g_list_remove (parent_private->children, window);
1222 gdk_window_free_paint_stack (window);
1224 if (private->bg_pixmap &&
1225 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
1226 private->bg_pixmap != GDK_NO_BG)
1228 g_object_unref (private->bg_pixmap);
1229 private->bg_pixmap = NULL;
1232 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN)
1233 g_assert (private->children == NULL);
1236 children = tmp = private->children;
1237 private->children = NULL;
1241 temp_window = tmp->data;
1244 temp_private = (GdkWindowObject*) temp_window;
1246 _gdk_window_destroy_hierarchy (temp_window,
1247 TRUE, foreign_destroy);
1250 g_list_free (children);
1253 _gdk_window_clear_update_area (window);
1255 if (private->cairo_surface)
1257 cairo_surface_finish (private->cairo_surface);
1258 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
1262 if (gdk_window_has_impl (private))
1264 if (gdk_window_is_offscreen (private))
1265 _gdk_offscreen_window_destroy (window, recursing);
1267 _gdk_windowing_window_destroy (window, recursing, foreign_destroy);
1271 /* hide to make sure we repaint and break grabs */
1272 gdk_window_hide (window);
1273 /* NULL out impl so we don't double free it on finalize */
1274 private->impl = NULL;
1277 private->state |= GDK_WINDOW_STATE_WITHDRAWN;
1278 private->parent = NULL;
1279 private->destroyed = TRUE;
1281 window_remove_filters (window);
1283 gdk_drawable_set_colormap (GDK_DRAWABLE (window), NULL);
1285 /* If we own the redirect, free it */
1286 if (private->redirect && private->redirect->redirected == private)
1287 gdk_window_redirect_free (private->redirect);
1289 private->redirect = NULL;
1291 if (display->pointer_info.toplevel_under_pointer == window)
1293 g_object_unref (display->pointer_info.toplevel_under_pointer);
1294 display->pointer_info.toplevel_under_pointer = NULL;
1302 * _gdk_window_destroy:
1303 * @window: a #GdkWindow
1304 * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
1305 * external agency. The window has already been destroyed and no
1306 * windowing system calls should be made. (This may never happen
1307 * for some windowing systems.)
1309 * Internal function to destroy a window. Like gdk_window_destroy(),
1310 * but does not drop the reference count created by gdk_window_new().
1313 _gdk_window_destroy (GdkWindow *window,
1314 gboolean foreign_destroy)
1316 _gdk_window_destroy_hierarchy (window, FALSE, foreign_destroy);
1320 * gdk_window_destroy:
1321 * @window: a #GdkWindow
1323 * Destroys the window system resources associated with @window and decrements @window's
1324 * reference count. The window system resources for all children of @window are also
1325 * destroyed, but the children's reference counts are not decremented.
1327 * Note that a window will not be destroyed automatically when its reference count
1328 * reaches zero. You must call this function yourself before that happens.
1332 gdk_window_destroy (GdkWindow *window)
1334 _gdk_window_destroy_hierarchy (window, FALSE, FALSE);
1335 g_object_unref (window);
1339 * gdk_window_set_user_data:
1340 * @window: a #GdkWindow
1341 * @user_data: user data
1343 * For most purposes this function is deprecated in favor of
1344 * g_object_set_data(). However, for historical reasons GTK+ stores
1345 * the #GtkWidget that owns a #GdkWindow as user data on the
1346 * #GdkWindow. So, custom widget implementations should use
1347 * this function for that. If GTK+ receives an event for a #GdkWindow,
1348 * and the user data for the window is non-%NULL, GTK+ will assume the
1349 * user data is a #GtkWidget, and forward the event to that widget.
1353 gdk_window_set_user_data (GdkWindow *window,
1356 g_return_if_fail (GDK_IS_WINDOW (window));
1358 ((GdkWindowObject*)window)->user_data = user_data;
1362 * gdk_window_get_user_data:
1363 * @window: a #GdkWindow
1364 * @data: return location for user data
1366 * Retrieves the user data for @window, which is normally the widget
1367 * that @window belongs to. See gdk_window_set_user_data().
1371 gdk_window_get_user_data (GdkWindow *window,
1374 g_return_if_fail (GDK_IS_WINDOW (window));
1376 *data = ((GdkWindowObject*)window)->user_data;
1380 * gdk_window_get_window_type:
1381 * @window: a #GdkWindow
1383 * Gets the type of the window. See #GdkWindowType.
1385 * Return value: type of window
1388 gdk_window_get_window_type (GdkWindow *window)
1390 g_return_val_if_fail (GDK_IS_WINDOW (window), (GdkWindowType) -1);
1392 return GDK_WINDOW_TYPE (window);
1396 * gdk_window_get_position:
1397 * @window: a #GdkWindow
1398 * @x: X coordinate of window
1399 * @y: Y coordinate of window
1401 * Obtains the position of the window as reported in the
1402 * most-recently-processed #GdkEventConfigure. Contrast with
1403 * gdk_window_get_geometry() which queries the X server for the
1404 * current window position, regardless of which events have been
1405 * received or processed.
1407 * The position coordinates are relative to the window's parent window.
1411 gdk_window_get_position (GdkWindow *window,
1415 GdkWindowObject *obj;
1417 g_return_if_fail (GDK_IS_WINDOW (window));
1419 obj = (GdkWindowObject*) window;
1428 * gdk_window_get_parent:
1429 * @window: a #GdkWindow
1431 * Obtains the parent of @window, as known to GDK. Does not query the
1432 * X server; thus this returns the parent as passed to gdk_window_new(),
1433 * not the actual parent. This should never matter unless you're using
1434 * Xlib calls mixed with GDK calls on the X11 platform. It may also
1435 * matter for toplevel windows, because the window manager may choose
1438 * Return value: parent of @window
1441 gdk_window_get_parent (GdkWindow *window)
1443 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1445 return (GdkWindow*) ((GdkWindowObject*) window)->parent;
1449 * gdk_window_get_toplevel:
1450 * @window: a #GdkWindow
1452 * Gets the toplevel window that's an ancestor of @window.
1454 * Return value: the toplevel window containing @window
1457 gdk_window_get_toplevel (GdkWindow *window)
1459 GdkWindowObject *obj;
1461 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1463 obj = (GdkWindowObject *)window;
1464 while (GDK_WINDOW_TYPE (obj) == GDK_WINDOW_CHILD)
1465 obj = (GdkWindowObject *)obj->parent;
1467 return GDK_WINDOW (obj);
1471 * gdk_window_get_children:
1472 * @window: a #GdkWindow
1474 * Gets the list of children of @window known to GDK.
1475 * This function only returns children created via GDK,
1476 * so for example it's useless when used with the root window;
1477 * it only returns windows an application created itself.
1479 * The returned list must be freed, but the elements in the
1482 * Return value: list of child windows inside @window
1485 gdk_window_get_children (GdkWindow *window)
1487 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1489 if (GDK_WINDOW_DESTROYED (window))
1492 return g_list_copy (GDK_WINDOW_OBJECT (window)->children);
1496 * gdk_window_peek_children:
1497 * @window: a #GdkWindow
1499 * Like gdk_window_get_children(), but does not copy the list of
1500 * children, so the list does not need to be freed.
1502 * Return value: a reference to the list of child windows in @window
1505 gdk_window_peek_children (GdkWindow *window)
1507 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1509 if (GDK_WINDOW_DESTROYED (window))
1512 return GDK_WINDOW_OBJECT (window)->children;
1516 * gdk_window_add_filter:
1517 * @window: a #GdkWindow
1518 * @function: filter callback
1519 * @data: data to pass to filter callback
1521 * Adds an event filter to @window, allowing you to intercept events
1522 * before they reach GDK. This is a low-level operation and makes it
1523 * easy to break GDK and/or GTK+, so you have to know what you're
1524 * doing. Pass %NULL for @window to get all events for all windows,
1525 * instead of events for a specific window.
1527 * See gdk_display_add_client_message_filter() if you are interested
1528 * in X ClientMessage events.
1531 gdk_window_add_filter (GdkWindow *window,
1532 GdkFilterFunc function,
1535 GdkWindowObject *private;
1537 GdkEventFilter *filter;
1539 g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
1541 private = (GdkWindowObject*) window;
1542 if (private && GDK_WINDOW_DESTROYED (window))
1545 /* Filters are for the native events on the native window, so
1546 ensure there is a native window. */
1548 gdk_window_set_has_native (window, TRUE);
1551 tmp_list = private->filters;
1553 tmp_list = _gdk_default_filters;
1557 filter = (GdkEventFilter *)tmp_list->data;
1558 if ((filter->function == function) && (filter->data == data))
1560 tmp_list = tmp_list->next;
1563 filter = g_new (GdkEventFilter, 1);
1564 filter->function = function;
1565 filter->data = data;
1568 private->filters = g_list_append (private->filters, filter);
1570 _gdk_default_filters = g_list_append (_gdk_default_filters, filter);
1574 * gdk_window_remove_filter:
1575 * @window: a #GdkWindow
1576 * @function: previously-added filter function
1577 * @data: user data for previously-added filter function
1579 * Remove a filter previously added with gdk_window_add_filter().
1583 gdk_window_remove_filter (GdkWindow *window,
1584 GdkFilterFunc function,
1587 GdkWindowObject *private;
1588 GList *tmp_list, *node;
1589 GdkEventFilter *filter;
1591 g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
1593 private = (GdkWindowObject*) window;
1596 tmp_list = private->filters;
1598 tmp_list = _gdk_default_filters;
1602 filter = (GdkEventFilter *)tmp_list->data;
1604 tmp_list = tmp_list->next;
1606 if ((filter->function == function) && (filter->data == data))
1609 private->filters = g_list_remove_link (private->filters, node);
1611 _gdk_default_filters = g_list_remove_link (_gdk_default_filters, node);
1612 g_list_free_1 (node);
1621 * gdk_screen_get_toplevel_windows:
1622 * @screen: The #GdkScreen where the toplevels are located.
1624 * Obtains a list of all toplevel windows known to GDK on the screen @screen.
1625 * A toplevel window is a child of the root window (see
1626 * gdk_get_default_root_window()).
1628 * The returned list should be freed with g_list_free(), but
1629 * its elements need not be freed.
1631 * Return value: list of toplevel windows, free with g_list_free()
1636 gdk_screen_get_toplevel_windows (GdkScreen *screen)
1638 GdkWindow * root_window;
1639 GList *new_list = NULL;
1642 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
1644 root_window = gdk_screen_get_root_window (screen);
1646 tmp_list = ((GdkWindowObject *)root_window)->children;
1649 if (GDK_WINDOW_TYPE (tmp_list->data) != GDK_WINDOW_FOREIGN)
1650 new_list = g_list_prepend (new_list, tmp_list->data);
1651 tmp_list = tmp_list->next;
1658 * gdk_window_get_toplevels:
1660 * Obtains a list of all toplevel windows known to GDK on the default
1661 * screen (see gdk_screen_get_toplevel_windows()).
1662 * A toplevel window is a child of the root window (see
1663 * gdk_get_default_root_window()).
1665 * The returned list should be freed with g_list_free(), but
1666 * its elements need not be freed.
1668 * Return value: list of toplevel windows, free with g_list_free()
1670 * Deprecated: 2.16: Use gdk_screen_get_toplevel_windows() instead.
1673 gdk_window_get_toplevels (void)
1675 return gdk_screen_get_toplevel_windows (gdk_screen_get_default ());
1679 * gdk_window_is_visible:
1680 * @window: a #GdkWindow
1682 * Checks whether the window has been mapped (with gdk_window_show() or
1683 * gdk_window_show_unraised()).
1685 * Return value: %TRUE if the window is mapped
1688 gdk_window_is_visible (GdkWindow *window)
1690 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
1692 return GDK_WINDOW_IS_MAPPED (window);
1696 * gdk_window_is_viewable:
1697 * @window: a #GdkWindow
1699 * Check if the window and all ancestors of the window are
1700 * mapped. (This is not necessarily "viewable" in the X sense, since
1701 * we only check as far as we have GDK window parents, not to the root
1704 * Return value: %TRUE if the window is viewable
1707 gdk_window_is_viewable (GdkWindow *window)
1709 GdkWindowObject *private = (GdkWindowObject *)window;
1711 GdkWindow *root_window;
1713 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
1715 screen = gdk_drawable_get_screen (window);
1716 root_window = gdk_screen_get_root_window (screen);
1719 (private != (GdkWindowObject *)root_window) &&
1720 (GDK_WINDOW_TYPE (private) != GDK_WINDOW_FOREIGN))
1722 if (GDK_WINDOW_DESTROYED (private) || !GDK_WINDOW_IS_MAPPED (private))
1725 private = (GdkWindowObject *)private->parent;
1732 * gdk_window_get_state:
1733 * @window: a #GdkWindow
1735 * Gets the bitwise OR of the currently active window state flags,
1736 * from the #GdkWindowState enumeration.
1738 * Return value: window state bitfield
1741 gdk_window_get_state (GdkWindow *window)
1743 GdkWindowObject *private = (GdkWindowObject *)window;
1745 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
1747 return private->state;
1751 /* This creates an empty "implicit" paint region for the impl window.
1752 * By itself this does nothing, but real paints to this window
1753 * or children of it can use this pixmap as backing to avoid allocating
1754 * multiple pixmaps for subwindow rendering. When doing so they
1755 * add to the region of the implicit paint region, which will be
1756 * pushed to the window when the implicit paint region is ended.
1757 * Such paints should not copy anything to the window on paint end, but
1758 * should rely on the implicit paint end.
1759 * The implicit paint will be automatically ended if someone draws
1760 * directly to the window or a child window.
1763 gdk_window_begin_implicit_paint (GdkWindow *window, GdkRectangle *rect)
1765 GdkWindowObject *private = (GdkWindowObject *)window;
1766 GdkWindowPaint *paint;
1767 GdkRectangle r, clipbox;
1769 GdkWindowRegionMove *move;
1771 g_assert (gdk_window_has_impl (private));
1773 if (GDK_IS_PAINTABLE (private->impl))
1774 return FALSE; /* Implementation does double buffering */
1776 if (private->paint_stack != NULL ||
1777 private->implicit_paint != NULL)
1778 return FALSE; /* Don't stack implicit paints */
1781 for (l = private->outstanding_moves; l != NULL; l = l->next)
1785 gdk_region_get_clipbox (move->region, &clipbox);
1786 gdk_rectangle_union (&r, &clipbox, &r);
1789 paint = g_new (GdkWindowPaint, 1);
1790 paint->region = gdk_region_new (); /* Empty */
1791 paint->x_offset = r.x;
1792 paint->y_offset = r.y;
1793 paint->uses_implicit = FALSE;
1794 paint->surface = NULL;
1796 gdk_pixmap_new (window,
1797 MAX (r.width, 1), MAX (r.height, 1), -1);
1799 _gdk_pixmap_set_as_backing (paint->pixmap,
1802 for (l = private->outstanding_moves; l != NULL; l = l->next)
1806 gdk_region_union (paint->region, move->region);
1807 g_object_ref (paint->pixmap);
1808 do_move_region_bits_on_impl (private,
1810 paint->x_offset, paint->y_offset,
1811 move->region, /* In impl window coords */
1812 move->dx, move->dy);
1813 gdk_region_destroy (move->region);
1814 g_slice_free (GdkWindowRegionMove, move);
1816 private->outstanding_moves = NULL;
1818 private->implicit_paint = paint;
1823 /* Ensure that all content related to this (sub)window is pushed to the
1826 gdk_window_flush_implicit_paint (GdkWindow *window)
1828 GdkWindowObject *private = (GdkWindowObject *)window;
1829 GdkWindowObject *impl_window;
1830 GdkWindowPaint *paint;
1834 /* Ensure that there is no explicit paint region. */
1835 g_assert (private->paint_stack == NULL);
1837 impl_window = gdk_window_get_impl_window (private);
1838 if (impl_window->implicit_paint == NULL)
1841 paint = impl_window->implicit_paint;
1842 region = gdk_region_copy (private->clip_region_with_children);
1843 gdk_region_offset (region, private->abs_x, private->abs_y);
1844 gdk_region_intersect (region, paint->region);
1846 if (!gdk_region_empty (region))
1848 /* Some regions are valid, push these to window now */
1849 tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
1850 _gdk_gc_set_clip_region_internal (tmp_gc, region, TRUE);
1851 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
1852 0, 0, paint->x_offset, paint->y_offset, -1, -1);
1853 /* Reset clip region of the cached GdkGC */
1854 gdk_gc_set_clip_region (tmp_gc, NULL);
1856 /* Remove flushed region from the implicit paint */
1857 gdk_region_subtract (paint->region, region);
1860 gdk_region_destroy (region);
1863 /* Ends an implicit paint, paired with gdk_window_begin_implicit_paint returning TRUE */
1865 gdk_window_end_implicit_paint (GdkWindow *window)
1867 GdkWindowObject *private = (GdkWindowObject *)window;
1868 GdkWindowPaint *paint;
1871 g_assert (gdk_window_has_impl (private));
1873 g_assert (private->implicit_paint != NULL);
1875 paint = private->implicit_paint;
1877 private->implicit_paint = NULL;
1879 if (!gdk_region_empty (paint->region))
1881 /* Some regions are valid, push these to window now */
1882 tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
1883 _gdk_gc_set_clip_region_internal (tmp_gc, paint->region, TRUE);
1884 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
1885 0, 0, paint->x_offset, paint->y_offset, -1, -1);
1886 /* Reset clip region of the cached GdkGC */
1887 gdk_gc_set_clip_region (tmp_gc, NULL);
1890 g_object_unref (paint->pixmap);
1895 * gdk_window_begin_paint_rect:
1896 * @window: a #GdkWindow
1897 * @rectangle: rectangle you intend to draw to
1899 * A convenience wrapper around gdk_window_begin_paint_region() which
1900 * creates a rectangular region for you. See
1901 * gdk_window_begin_paint_region() for details.
1905 gdk_window_begin_paint_rect (GdkWindow *window,
1906 const GdkRectangle *rectangle)
1910 g_return_if_fail (GDK_IS_WINDOW (window));
1912 region = gdk_region_rectangle (rectangle);
1913 gdk_window_begin_paint_region (window, region);
1914 gdk_region_destroy (region);
1917 #ifdef GDK_WINDOWING_X11
1918 #include "x11/gdkx.h"
1922 * gdk_window_begin_paint_region:
1923 * @window: a #GdkWindow
1924 * @region: region you intend to draw to
1926 * Indicates that you are beginning the process of redrawing @region.
1927 * A backing store (offscreen buffer) large enough to contain @region
1928 * will be created. The backing store will be initialized with the
1929 * background color or background pixmap for @window. Then, all
1930 * drawing operations performed on @window will be diverted to the
1931 * backing store. When you call gdk_window_end_paint(), the backing
1932 * store will be copied to @window, making it visible onscreen. Only
1933 * the part of @window contained in @region will be modified; that is,
1934 * drawing operations are clipped to @region.
1936 * The net result of all this is to remove flicker, because the user
1937 * sees the finished product appear all at once when you call
1938 * gdk_window_end_paint(). If you draw to @window directly without
1939 * calling gdk_window_begin_paint_region(), the user may see flicker
1940 * as individual drawing operations are performed in sequence. The
1941 * clipping and background-initializing features of
1942 * gdk_window_begin_paint_region() are conveniences for the
1943 * programmer, so you can avoid doing that work yourself.
1945 * When using GTK+, the widget system automatically places calls to
1946 * gdk_window_begin_paint_region() and gdk_window_end_paint() around
1947 * emissions of the expose_event signal. That is, if you're writing an
1948 * expose event handler, you can assume that the exposed area in
1949 * #GdkEventExpose has already been cleared to the window background,
1950 * is already set as the clip region, and already has a backing store.
1951 * Therefore in most cases, application code need not call
1952 * gdk_window_begin_paint_region(). (You can disable the automatic
1953 * calls around expose events on a widget-by-widget basis by calling
1954 * gtk_widget_set_double_buffered().)
1956 * If you call this function multiple times before calling the
1957 * matching gdk_window_end_paint(), the backing stores are pushed onto
1958 * a stack. gdk_window_end_paint() copies the topmost backing store
1959 * onscreen, subtracts the topmost region from all other regions in
1960 * the stack, and pops the stack. All drawing operations affect only
1961 * the topmost backing store in the stack. One matching call to
1962 * gdk_window_end_paint() is required for each call to
1963 * gdk_window_begin_paint_region().
1967 gdk_window_begin_paint_region (GdkWindow *window,
1968 const GdkRegion *region)
1970 #ifdef USE_BACKING_STORE
1971 GdkWindowObject *private = (GdkWindowObject *)window;
1972 GdkRectangle clip_box;
1973 GdkWindowPaint *paint, *implicit_paint;
1974 GdkWindowObject *impl_window;
1977 g_return_if_fail (GDK_IS_WINDOW (window));
1979 if (GDK_WINDOW_DESTROYED (window))
1982 if (GDK_IS_PAINTABLE (private->impl))
1984 GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
1986 if (iface->begin_paint_region)
1987 iface->begin_paint_region ((GdkPaintable*)private->impl, region);
1992 gdk_region_get_clipbox (region, &clip_box);
1994 impl_window = gdk_window_get_impl_window (private);
1995 implicit_paint = impl_window->implicit_paint;
1997 paint = g_new (GdkWindowPaint, 1);
1998 paint->region = gdk_region_copy (region);
1999 paint->region_tag = new_region_tag ();
2005 paint->uses_implicit = TRUE;
2006 paint->pixmap = g_object_ref (implicit_paint->pixmap);
2007 paint->x_offset = -private->abs_x + implicit_paint->x_offset;
2008 paint->y_offset = -private->abs_y + implicit_paint->y_offset;
2009 gdk_region_intersect (paint->region, private->clip_region_with_children);
2011 /* It would be nice if we had some cairo support here so we
2012 could set the clip rect on the cairo surface */
2013 width = private->abs_x + private->width;
2014 height = private->abs_y + private->height;
2016 paint->surface = _gdk_windowing_create_cairo_surface (((GdkPixmapObject *)paint->pixmap)->impl,
2019 /* Mark the region as valid on the implicit paint */
2020 gdk_region_offset (paint->region, private->abs_x, private->abs_y);
2021 gdk_region_union (implicit_paint->region, paint->region);
2022 gdk_region_offset (paint->region, -private->abs_x, -private->abs_y);
2026 paint->uses_implicit = FALSE;
2027 paint->x_offset = clip_box.x;
2028 paint->y_offset = clip_box.y;
2030 gdk_pixmap_new (window,
2031 MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1);
2032 paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap);
2036 cairo_surface_set_device_offset (paint->surface,
2037 -paint->x_offset, -paint->y_offset);
2039 for (list = private->paint_stack; list != NULL; list = list->next)
2041 GdkWindowPaint *tmp_paint = list->data;
2043 gdk_region_subtract (tmp_paint->region, paint->region);
2046 private->paint_stack = g_slist_prepend (private->paint_stack, paint);
2048 if (!gdk_region_empty (paint->region))
2050 gdk_window_clear_backing_rect (window,
2051 clip_box.x, clip_box.y,
2052 clip_box.width, clip_box.height);
2055 #endif /* USE_BACKING_STORE */
2059 setup_redirect_clip (GdkWindow *window,
2064 GdkWindowObject *private = (GdkWindowObject *)window;
2065 GdkRegion *visible_region;
2066 GdkRectangle dest_rect;
2068 GdkWindow *toplevel;
2069 int x_offset, y_offset;
2071 toplevel = GDK_WINDOW (private->redirect->redirected);
2073 /* Get the clip region for gc clip rect + window hierarchy in
2074 window relative coords */
2076 _gdk_window_calculate_full_clip_region (window, toplevel,
2081 /* Compensate for the source pos/size */
2082 x_offset -= private->redirect->src_x;
2083 y_offset -= private->redirect->src_y;
2084 dest_rect.x = -x_offset;
2085 dest_rect.y = -y_offset;
2086 dest_rect.width = private->redirect->width;
2087 dest_rect.height = private->redirect->height;
2088 tmpreg = gdk_region_rectangle (&dest_rect);
2089 gdk_region_intersect (visible_region, tmpreg);
2090 gdk_region_destroy (tmpreg);
2092 /* Compensate for the dest pos */
2093 x_offset += private->redirect->dest_x;
2094 y_offset += private->redirect->dest_y;
2096 gdk_gc_set_clip_region (gc, visible_region); /* This resets clip origin! */
2098 /* offset clip and tiles from window coords to pixmaps coords */
2099 gdk_gc_offset (gc, -x_offset, -y_offset);
2101 gdk_region_destroy (visible_region);
2103 *x_offset_out = x_offset;
2104 *y_offset_out = y_offset;
2108 * gdk_window_end_paint:
2109 * @window: a #GdkWindow
2111 * Indicates that the backing store created by the most recent call to
2112 * gdk_window_begin_paint_region() should be copied onscreen and
2113 * deleted, leaving the next-most-recent backing store or no backing
2114 * store at all as the active paint region. See
2115 * gdk_window_begin_paint_region() for full details. It is an error to
2116 * call this function without a matching
2117 * gdk_window_begin_paint_region() first.
2121 gdk_window_end_paint (GdkWindow *window)
2123 #ifdef USE_BACKING_STORE
2124 GdkWindowObject *private = (GdkWindowObject *)window;
2125 GdkWindowObject *composited;
2126 GdkWindowPaint *paint;
2128 GdkRectangle clip_box;
2129 gint x_offset, y_offset;
2130 GdkRegion *full_clip;
2132 g_return_if_fail (GDK_IS_WINDOW (window));
2134 if (GDK_WINDOW_DESTROYED (window))
2137 if (GDK_IS_PAINTABLE (private->impl))
2139 GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
2141 if (iface->end_paint)
2142 iface->end_paint ((GdkPaintable*)private->impl);
2146 if (private->paint_stack == NULL)
2148 g_warning (G_STRLOC": no preceding call to gdk_window_begin_paint_region(), see documentation");
2152 paint = private->paint_stack->data;
2154 private->paint_stack = g_slist_delete_link (private->paint_stack,
2155 private->paint_stack);
2157 gdk_region_get_clipbox (paint->region, &clip_box);
2159 tmp_gc = _gdk_drawable_get_scratch_gc (window, FALSE);
2161 x_offset = -private->abs_x;
2162 y_offset = -private->abs_y;
2164 if (!paint->uses_implicit)
2166 full_clip = gdk_region_copy (private->clip_region_with_children);
2167 gdk_region_intersect (full_clip, paint->region);
2168 _gdk_gc_set_clip_region_internal (tmp_gc, full_clip, TRUE); /* Takes ownership of full_clip */
2169 gdk_gc_set_clip_origin (tmp_gc, - x_offset, - y_offset);
2170 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2171 clip_box.x - paint->x_offset,
2172 clip_box.y - paint->y_offset,
2173 clip_box.x - x_offset, clip_box.y - y_offset,
2174 clip_box.width, clip_box.height);
2177 if (private->redirect)
2179 int x_offset, y_offset;
2181 /* TODO: Should also use paint->region for clipping */
2182 setup_redirect_clip (window, tmp_gc, &x_offset, &y_offset);
2183 gdk_draw_drawable (private->redirect->pixmap, tmp_gc, paint->pixmap,
2184 clip_box.x - paint->x_offset,
2185 clip_box.y - paint->y_offset,
2186 clip_box.x + x_offset,
2187 clip_box.y + y_offset,
2188 clip_box.width, clip_box.height);
2191 /* Reset clip region of the cached GdkGC */
2192 gdk_gc_set_clip_region (tmp_gc, NULL);
2194 cairo_surface_destroy (paint->surface);
2195 g_object_unref (paint->pixmap);
2196 gdk_region_destroy (paint->region);
2199 /* find a composited window in our hierarchy to signal its
2200 * parent to redraw, calculating the clip box as we go...
2202 * stop if parent becomes NULL since then we'd have nowhere
2203 * to draw (ie: 'composited' will always be non-NULL here).
2205 for (composited = private;
2207 composited = composited->parent)
2211 gdk_drawable_get_size (GDK_DRAWABLE (composited->parent),
2214 clip_box.x += composited->x;
2215 clip_box.y += composited->y;
2216 clip_box.width = MIN (clip_box.width, width - clip_box.x);
2217 clip_box.height = MIN (clip_box.height, height - clip_box.y);
2219 if (composited->composited)
2221 gdk_window_invalidate_rect (GDK_WINDOW (composited->parent),
2226 #endif /* USE_BACKING_STORE */
2230 gdk_window_free_paint_stack (GdkWindow *window)
2232 GdkWindowObject *private = (GdkWindowObject *)window;
2234 if (private->paint_stack)
2236 GSList *tmp_list = private->paint_stack;
2240 GdkWindowPaint *paint = tmp_list->data;
2242 if (tmp_list == private->paint_stack)
2243 g_object_unref (paint->pixmap);
2245 gdk_region_destroy (paint->region);
2248 tmp_list = tmp_list->next;
2251 g_slist_free (private->paint_stack);
2252 private->paint_stack = NULL;
2257 do_move_region_bits_on_impl (GdkWindowObject *private,
2259 int dest_off_x, int dest_off_y,
2260 GdkRegion *region, /* In impl window coords */
2264 GdkRectangle copy_rect;
2266 gdk_region_get_clipbox (region, ©_rect);
2267 gdk_region_offset (region, -dest_off_x, -dest_off_y);
2268 tmp_gc = _gdk_drawable_get_scratch_gc ((GdkWindow *)private, TRUE);
2269 gdk_gc_set_clip_region (tmp_gc, region);
2270 gdk_draw_drawable (dest,
2273 copy_rect.x-dx, copy_rect.y-dy,
2274 copy_rect.x - dest_off_x, copy_rect.y - dest_off_y,
2275 copy_rect.width, copy_rect.height);
2276 gdk_gc_set_clip_region (tmp_gc, NULL);
2280 append_move_region (GdkWindowObject *impl_window,
2284 GList *moves_to_add, *l, *s;
2285 GdkRegion *intersection;
2286 GdkWindowRegionMove *move, *new_move, *existing_move;
2288 move = g_slice_new (GdkWindowRegionMove);
2289 move->region = region;
2293 moves_to_add = g_list_prepend (NULL, move);
2295 for (l = impl_window->outstanding_moves; l != NULL; l = l->next)
2297 existing_move = l->data;
2299 for (s = moves_to_add; s != NULL; s = s->next)
2303 intersection = gdk_region_copy (move->region);
2304 gdk_region_offset (intersection, -move->dx, -move->dy);
2305 gdk_region_intersect (intersection, existing_move->region);
2306 gdk_region_offset (intersection, move->dx, move->dy);
2308 if (!gdk_region_empty (intersection))
2311 new_move = g_slice_new (GdkWindowRegionMove);
2312 new_move->region = intersection;
2313 new_move->dx = move->dx + existing_move->dx;
2314 new_move->dy = move->dy + existing_move->dy;
2315 moves_to_add = g_list_prepend (moves_to_add, new_move);
2317 gdk_region_subtract (move->region, intersection);
2318 gdk_region_subtract (existing_move->region, intersection);
2321 gdk_region_destroy (intersection);
2325 impl_window->outstanding_moves = g_list_concat (impl_window->outstanding_moves,
2330 /* Moves bits and update area by dx/dy in impl window
2331 * Takes ownership of region.
2334 move_region_on_impl (GdkWindowObject *private,
2335 GdkRegion *region, /* In impl window coords */
2338 GdkWindowObject *impl_window;
2339 gboolean free_region;
2342 impl_window = gdk_window_get_impl_window (private);
2344 if (1) /* Enable flicker free handling of moves. */
2346 free_region = FALSE;
2348 append_move_region (impl_window, region, dx, dy);
2351 do_move_region_bits_on_impl (private,
2355 /* Move any old invalid regions in the copy source area by dx/dy */
2356 if (impl_window->update_area)
2358 GdkRegion *update_area;
2360 update_area = gdk_region_copy (region);
2361 /* Convert from target to source */
2362 gdk_region_offset (update_area, -dx, -dy);
2363 gdk_region_intersect (update_area, impl_window->update_area);
2364 gdk_region_subtract (impl_window->update_area, update_area);
2366 gdk_region_offset (update_area, dx, dy);
2367 gdk_region_union (impl_window->update_area, update_area);
2368 gdk_region_destroy (update_area);
2372 gdk_region_destroy (region);
2375 /* Flushes all outstanding changes to the window, call this
2376 * before drawing directly to the window (i.e. outside a begin/end_paint pair).
2379 gdk_window_flush (GdkWindow *window)
2381 GdkWindowObject *private;
2382 GdkWindowObject *impl_window;
2384 GdkWindowRegionMove *move;
2386 private = (GdkWindowObject *) window;
2388 impl_window = gdk_window_get_impl_window (private);
2390 for (l = impl_window->outstanding_moves; l != NULL; l = l->next)
2394 do_move_region_bits_on_impl (private,
2395 private->impl, 0, 0,
2396 move->region, move->dx, move->dy);
2398 gdk_region_destroy (move->region);
2399 g_slice_free (GdkWindowRegionMove, move);
2402 g_list_free (impl_window->outstanding_moves);
2403 impl_window->outstanding_moves = NULL;
2405 gdk_window_flush_implicit_paint (window);
2409 gdk_window_get_offsets (GdkWindow *window,
2413 GdkWindowObject *private = (GdkWindowObject *)window;
2415 if (private->paint_stack)
2417 GdkWindowPaint *paint = private->paint_stack->data;
2418 *x_offset = paint->x_offset;
2419 *y_offset = paint->y_offset;
2423 *x_offset = -private->abs_x;
2424 *y_offset = -private->abs_y;
2429 * gdk_window_get_internal_paint_info:
2430 * @window: a #GdkWindow
2431 * @real_drawable: location to store the drawable to which drawing should be
2433 * @x_offset: location to store the X offset between coordinates in @window,
2434 * and the underlying window system primitive coordinates for
2436 * @y_offset: location to store the Y offset between coordinates in @window,
2437 * and the underlying window system primitive coordinates for
2440 * If you bypass the GDK layer and use windowing system primitives to
2441 * draw directly onto a #GdkWindow, then you need to deal with two
2442 * details: there may be an offset between GDK coordinates and windowing
2443 * system coordinates, and GDK may have redirected drawing to a offscreen
2444 * pixmap as the result of a gdk_window_begin_paint_region() calls.
2445 * This function allows retrieving the information you need to compensate
2446 * for these effects.
2448 * This function exposes details of the GDK implementation, and is thus
2449 * likely to change in future releases of GDK.
2452 gdk_window_get_internal_paint_info (GdkWindow *window,
2453 GdkDrawable **real_drawable,
2459 GdkWindowObject *private;
2461 g_return_if_fail (GDK_IS_WINDOW (window));
2463 private = (GdkWindowObject *)window;
2467 if (private->paint_stack)
2469 GdkWindowPaint *paint = private->paint_stack->data;
2470 *real_drawable = paint->pixmap;
2473 *real_drawable = window;
2476 gdk_window_get_offsets (window, &x_off, &y_off);
2485 setup_clip_for_draw (GdkDrawable *drawable,
2487 int old_clip_x, int old_clip_y)
2489 GdkWindowObject *private = (GdkWindowObject *)drawable;
2492 if (private->window_type == GDK_WINDOW_ROOT)
2495 if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
2496 clip = private->clip_region_with_children;
2498 clip = private->clip_region;
2500 _gdk_gc_add_drawable_clip (gc,
2503 /* If there was a clip origin set appart from the
2504 * window offset, need to take that into consideration */
2505 -old_clip_x, -old_clip_y);
2509 setup_clip_for_paint (GdkDrawable *drawable,
2510 GdkWindowPaint *paint,
2512 int old_clip_x, int old_clip_y)
2514 _gdk_gc_add_drawable_clip (gc,
2516 /* This includes the window clip */
2518 /* If there was a clip origin set appart from the
2519 * window offset, need to take that into consideration */
2520 -old_clip_x, -old_clip_y);
2524 #define OFFSET_GC(gc) \
2525 gint x_offset, y_offset; \
2526 gint old_clip_x = gc->clip_x_origin; \
2527 gint old_clip_y = gc->clip_y_origin; \
2528 gint old_ts_x = gc->ts_x_origin; \
2529 gint old_ts_y = gc->ts_y_origin; \
2530 gdk_window_get_offsets (drawable, &x_offset, &y_offset); \
2531 if (x_offset != 0 || y_offset != 0) \
2533 gdk_gc_set_clip_origin (gc, old_clip_x - x_offset, \
2534 old_clip_y - y_offset); \
2535 gdk_gc_set_ts_origin (gc, old_ts_x - x_offset, \
2536 old_ts_y - y_offset); \
2539 #define RESTORE_GC(gc) \
2540 if (x_offset != 0 || y_offset != 0) \
2542 gdk_gc_set_clip_origin (gc, old_clip_x, old_clip_y); \
2543 gdk_gc_set_ts_origin (gc, old_ts_x, old_ts_y); \
2546 #define SETUP_PAINT_GC_CLIP(gc) \
2547 if (paint->uses_implicit) \
2548 setup_clip_for_paint (drawable, paint, gc, old_clip_x, \
2551 #define RESTORE_PAINT_GC_CLIP(gc)
2554 #define SETUP_DIRECT_GC_CLIP(gc) \
2555 gdk_window_flush ((GdkWindow *)drawable);\
2556 setup_clip_for_draw (drawable, gc, old_clip_x, old_clip_y);
2558 #define RESTORE_DIRECT_GC_CLIP(gc)
2561 gdk_window_create_gc (GdkDrawable *drawable,
2562 GdkGCValues *values,
2563 GdkGCValuesMask mask)
2565 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
2567 if (GDK_WINDOW_DESTROYED (drawable))
2570 return gdk_gc_new_with_values (((GdkWindowObject *) drawable)->impl,
2574 /* After having set up the drawable clip rect on a GC we need
2575 * to make sure that if we draw to a pixmap we draw to the impl,
2576 * otherwise the pixmap code will reset the drawable clip.
2578 static GdkDrawable *
2579 pixmap_impl (GdkPixmap *pixmap)
2581 return ((GdkPixmapObject *)pixmap)->impl;
2585 gdk_window_draw_rectangle (GdkDrawable *drawable,
2593 GdkWindowObject *private = (GdkWindowObject *)drawable;
2596 if (GDK_WINDOW_DESTROYED (drawable))
2599 if (private->paint_stack)
2601 GdkWindowPaint *paint = private->paint_stack->data;
2602 SETUP_PAINT_GC_CLIP (gc);
2603 gdk_draw_rectangle (pixmap_impl (paint->pixmap), gc, filled,
2604 x - x_offset, y - y_offset, width, height);
2605 RESTORE_PAINT_GC_CLIP (gc);
2609 SETUP_DIRECT_GC_CLIP(gc);
2610 gdk_draw_rectangle (private->impl, gc, filled,
2611 x - x_offset, y - y_offset, width, height);
2612 RESTORE_DIRECT_GC_CLIP(gc);
2619 gdk_window_draw_arc (GdkDrawable *drawable,
2629 GdkWindowObject *private = (GdkWindowObject *)drawable;
2632 if (GDK_WINDOW_DESTROYED (drawable))
2635 if (private->paint_stack)
2637 GdkWindowPaint *paint = private->paint_stack->data;
2638 SETUP_PAINT_GC_CLIP (gc);
2639 gdk_draw_arc (pixmap_impl (paint->pixmap), gc, filled,
2640 x - x_offset, y - y_offset,
2641 width, height, angle1, angle2);
2642 RESTORE_PAINT_GC_CLIP (gc);
2646 SETUP_DIRECT_GC_CLIP(gc);
2647 gdk_draw_arc (private->impl, gc, filled,
2648 x - x_offset, y - y_offset,
2649 width, height, angle1, angle2);
2650 RESTORE_DIRECT_GC_CLIP(gc);
2656 gdk_window_draw_polygon (GdkDrawable *drawable,
2662 GdkWindowObject *private = (GdkWindowObject *)drawable;
2663 GdkPoint *new_points;
2667 if (GDK_WINDOW_DESTROYED (drawable))
2670 if (x_offset != 0 || y_offset != 0)
2674 new_points = g_new (GdkPoint, npoints);
2675 for (i=0; i<npoints; i++)
2677 new_points[i].x = points[i].x - x_offset;
2678 new_points[i].y = points[i].y - y_offset;
2682 new_points = points;
2684 if (private->paint_stack)
2686 GdkWindowPaint *paint = private->paint_stack->data;
2687 SETUP_PAINT_GC_CLIP (gc);
2688 gdk_draw_polygon (pixmap_impl (paint->pixmap), gc, filled, new_points, npoints);
2689 RESTORE_PAINT_GC_CLIP (gc);
2693 SETUP_DIRECT_GC_CLIP(gc);
2694 gdk_draw_polygon (private->impl, gc, filled, new_points, npoints);
2695 RESTORE_DIRECT_GC_CLIP(gc);
2698 if (new_points != points)
2699 g_free (new_points);
2705 gdk_window_draw_text (GdkDrawable *drawable,
2713 GdkWindowObject *private = (GdkWindowObject *)drawable;
2716 if (GDK_WINDOW_DESTROYED (drawable))
2719 if (private->paint_stack)
2721 GdkWindowPaint *paint = private->paint_stack->data;
2722 SETUP_PAINT_GC_CLIP (gc);
2723 gdk_draw_text (pixmap_impl (paint->pixmap), font, gc,
2724 x - x_offset, y - y_offset, text, text_length);
2726 RESTORE_PAINT_GC_CLIP (gc);
2730 SETUP_DIRECT_GC_CLIP(gc);
2731 gdk_draw_text (private->impl, font, gc,
2732 x - x_offset, y - y_offset, text, text_length);
2733 RESTORE_DIRECT_GC_CLIP(gc);
2740 gdk_window_draw_text_wc (GdkDrawable *drawable,
2745 const GdkWChar *text,
2748 GdkWindowObject *private = (GdkWindowObject *)drawable;
2751 if (GDK_WINDOW_DESTROYED (drawable))
2754 if (private->paint_stack)
2756 GdkWindowPaint *paint = private->paint_stack->data;
2757 SETUP_PAINT_GC_CLIP (gc);
2758 gdk_draw_text_wc (pixmap_impl (paint->pixmap), font, gc,
2759 x - x_offset, y - y_offset, text, text_length);
2760 RESTORE_PAINT_GC_CLIP (gc);
2764 SETUP_DIRECT_GC_CLIP(gc);
2765 gdk_draw_text_wc (private->impl, font, gc,
2766 x - x_offset, y - y_offset, text, text_length);
2767 RESTORE_DIRECT_GC_CLIP(gc);
2773 static GdkDrawable *
2774 gdk_window_get_source_drawable (GdkDrawable *drawable)
2776 GdkWindow *window = GDK_WINDOW (drawable);
2777 GdkWindowObject *private;
2779 private = (GdkWindowObject *) window;
2780 if (GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable)
2781 return GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable (private->impl);
2786 static GdkDrawable *
2787 gdk_window_get_composite_drawable (GdkDrawable *drawable,
2792 gint *composite_x_offset,
2793 gint *composite_y_offset)
2795 GdkWindowObject *private = (GdkWindowObject *)drawable;
2797 GdkPixmap *tmp_pixmap;
2800 gboolean overlap_buffer;
2801 GdkDrawable *source;
2802 GdkWindowObject *impl_window;
2803 GdkWindowPaint *implicit_paint;
2805 *composite_x_offset = -private->abs_x;
2806 *composite_y_offset = -private->abs_y;
2808 if ((GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable)))
2809 return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
2811 /* See if any buffered part is overlapping the part we want
2817 rect.height = height;
2819 overlap_buffer = FALSE;
2821 for (list = private->paint_stack; list != NULL; list = list->next)
2823 GdkWindowPaint *paint = list->data;
2824 GdkOverlapType overlap;
2826 overlap = gdk_region_rect_in (paint->region, &rect);
2828 if (overlap == GDK_OVERLAP_RECTANGLE_IN)
2830 *composite_x_offset = paint->x_offset;
2831 *composite_y_offset = paint->y_offset;
2833 return g_object_ref (paint->pixmap);
2835 else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
2837 overlap_buffer = TRUE;
2842 impl_window = gdk_window_get_impl_window (private);
2843 implicit_paint = impl_window->implicit_paint;
2846 GdkOverlapType overlap;
2848 rect.x += private->abs_x;
2849 rect.y += private->abs_y;
2851 overlap = gdk_region_rect_in (implicit_paint->region, &rect);
2852 if (overlap == GDK_OVERLAP_RECTANGLE_IN)
2854 *composite_x_offset = -private->abs_x + implicit_paint->x_offset;
2855 *composite_y_offset = -private->abs_y + implicit_paint->y_offset;
2857 return g_object_ref (implicit_paint->pixmap);
2859 else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
2860 overlap_buffer = TRUE;
2863 if (!overlap_buffer)
2864 return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
2866 tmp_pixmap = gdk_pixmap_new (drawable, width, height, -1);
2867 tmp_gc = _gdk_drawable_get_scratch_gc (tmp_pixmap, FALSE);
2869 source = _gdk_drawable_get_source_drawable (drawable);
2871 /* Copy the current window contents */
2872 gdk_draw_drawable (tmp_pixmap,
2874 GDK_WINDOW_OBJECT (source)->impl,
2875 x - *composite_x_offset,
2876 y - *composite_y_offset,
2880 /* paint the backing stores */
2883 GdkWindowPaint *paint = list->data;
2885 gdk_gc_set_clip_region (tmp_gc, paint->region);
2886 gdk_gc_set_clip_origin (tmp_gc, -x - paint->x_offset, -y - paint->y_offset);
2888 gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
2889 x - paint->x_offset,
2890 y - paint->y_offset,
2891 0, 0, width, height);
2894 for (list = private->paint_stack; list != NULL; list = list->next)
2896 GdkWindowPaint *paint = list->data;
2898 if (paint->uses_implicit)
2899 continue; /* We already copied this above */
2901 gdk_gc_set_clip_region (tmp_gc, paint->region);
2902 gdk_gc_set_clip_origin (tmp_gc, -x, -y);
2904 gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
2905 x - paint->x_offset,
2906 y - paint->y_offset,
2907 0, 0, width, height);
2910 /* Reset clip region of the cached GdkGC */
2911 gdk_gc_set_clip_region (tmp_gc, NULL);
2913 /* Set these to location of tmp_pixmap within the window */
2914 *composite_x_offset = x;
2915 *composite_y_offset = y;
2921 gdk_window_get_clip_region (GdkDrawable *drawable)
2923 GdkWindowObject *private = (GdkWindowObject *)drawable;
2926 result = gdk_region_copy (private->clip_region);
2928 if (private->paint_stack)
2930 GdkRegion *paint_region = gdk_region_new ();
2931 GSList *tmp_list = private->paint_stack;
2935 GdkWindowPaint *paint = tmp_list->data;
2937 gdk_region_union (paint_region, paint->region);
2939 tmp_list = tmp_list->next;
2942 gdk_region_intersect (result, paint_region);
2943 gdk_region_destroy (paint_region);
2950 gdk_window_get_visible_region (GdkDrawable *drawable)
2952 GdkWindowObject *private = (GdkWindowObject*) drawable;
2954 return gdk_region_copy (private->clip_region);
2958 gdk_window_draw_drawable (GdkDrawable *drawable,
2968 GdkWindowObject *private = (GdkWindowObject *)drawable;
2971 if (GDK_WINDOW_DESTROYED (drawable))
2974 /* If we have a backing pixmap draw to that */
2975 if (private->paint_stack)
2977 GdkWindowPaint *paint = private->paint_stack->data;
2978 SETUP_PAINT_GC_CLIP (gc);
2979 gdk_draw_drawable (pixmap_impl (paint->pixmap), gc,
2981 xdest - x_offset, ydest - y_offset, width, height);
2983 RESTORE_PAINT_GC_CLIP (gc);
2987 SETUP_DIRECT_GC_CLIP(gc);
2988 gdk_draw_drawable (private->impl, gc,
2990 xdest - x_offset, ydest - y_offset,
2992 RESTORE_DIRECT_GC_CLIP(gc);
2999 gdk_window_draw_points (GdkDrawable *drawable,
3004 GdkWindowObject *private = (GdkWindowObject *)drawable;
3005 GdkPoint *new_points;
3009 if (GDK_WINDOW_DESTROYED (drawable))
3012 if (x_offset != 0 || y_offset != 0)
3016 new_points = g_new (GdkPoint, npoints);
3017 for (i=0; i<npoints; i++)
3019 new_points[i].x = points[i].x - x_offset;
3020 new_points[i].y = points[i].y - y_offset;
3024 new_points = points;
3026 if (private->paint_stack)
3028 GdkWindowPaint *paint = private->paint_stack->data;
3029 SETUP_PAINT_GC_CLIP (gc);
3030 gdk_draw_points (pixmap_impl (paint->pixmap), gc, new_points, npoints);
3031 RESTORE_PAINT_GC_CLIP (gc);
3035 SETUP_DIRECT_GC_CLIP(gc);
3036 gdk_draw_points (private->impl, gc, new_points, npoints);
3037 RESTORE_DIRECT_GC_CLIP(gc);
3040 if (new_points != points)
3041 g_free (new_points);
3047 gdk_window_draw_segments (GdkDrawable *drawable,
3052 GdkWindowObject *private = (GdkWindowObject *)drawable;
3053 GdkSegment *new_segs;
3057 if (GDK_WINDOW_DESTROYED (drawable))
3060 if (x_offset != 0 || y_offset != 0)
3064 new_segs = g_new (GdkSegment, nsegs);
3065 for (i=0; i<nsegs; i++)
3067 new_segs[i].x1 = segs[i].x1 - x_offset;
3068 new_segs[i].y1 = segs[i].y1 - y_offset;
3069 new_segs[i].x2 = segs[i].x2 - x_offset;
3070 new_segs[i].y2 = segs[i].y2 - y_offset;
3076 if (private->paint_stack)
3078 GdkWindowPaint *paint = private->paint_stack->data;
3079 SETUP_PAINT_GC_CLIP (gc);
3080 gdk_draw_segments (pixmap_impl (paint->pixmap), gc, new_segs, nsegs);
3081 RESTORE_PAINT_GC_CLIP (gc);
3085 SETUP_DIRECT_GC_CLIP(gc);
3086 gdk_draw_segments (private->impl, gc, new_segs, nsegs);
3087 RESTORE_DIRECT_GC_CLIP(gc);
3090 if (new_segs != segs)
3097 gdk_window_draw_lines (GdkDrawable *drawable,
3102 GdkWindowObject *private = (GdkWindowObject *)drawable;
3103 GdkPoint *new_points;
3107 if (GDK_WINDOW_DESTROYED (drawable))
3110 if (x_offset != 0 || y_offset != 0)
3114 new_points = g_new (GdkPoint, npoints);
3115 for (i=0; i<npoints; i++)
3117 new_points[i].x = points[i].x - x_offset;
3118 new_points[i].y = points[i].y - y_offset;
3122 new_points = points;
3124 if (private->paint_stack)
3126 GdkWindowPaint *paint = private->paint_stack->data;
3127 SETUP_PAINT_GC_CLIP (gc);
3128 gdk_draw_lines (pixmap_impl (paint->pixmap), gc, new_points, npoints);
3129 RESTORE_PAINT_GC_CLIP (gc);
3133 SETUP_DIRECT_GC_CLIP(gc);
3134 gdk_draw_lines (private->impl, gc, new_points, npoints);
3135 RESTORE_DIRECT_GC_CLIP(gc);
3138 if (new_points != points)
3139 g_free (new_points);
3145 gdk_window_draw_glyphs (GdkDrawable *drawable,
3150 PangoGlyphString *glyphs)
3152 GdkWindowObject *private = (GdkWindowObject *)drawable;
3156 if (GDK_WINDOW_DESTROYED (drawable))
3159 if (private->paint_stack)
3161 GdkWindowPaint *paint = private->paint_stack->data;
3163 SETUP_PAINT_GC_CLIP (gc);
3164 gdk_draw_glyphs (pixmap_impl (paint->pixmap), gc, font, x - x_offset, y - y_offset, glyphs);
3165 RESTORE_PAINT_GC_CLIP (gc);
3169 SETUP_DIRECT_GC_CLIP(gc);
3170 gdk_draw_glyphs (private->impl, gc, font,
3171 x - x_offset, y - y_offset, glyphs);
3172 RESTORE_DIRECT_GC_CLIP(gc);
3179 gdk_window_draw_glyphs_transformed (GdkDrawable *drawable,
3181 PangoMatrix *matrix,
3185 PangoGlyphString *glyphs)
3187 GdkWindowObject *private = (GdkWindowObject *)drawable;
3188 PangoMatrix tmp_matrix;
3192 if (GDK_WINDOW_DESTROYED (drawable))
3195 if (x_offset != 0 || y_offset != 0)
3199 tmp_matrix = *matrix;
3200 tmp_matrix.x0 -= x_offset;
3201 tmp_matrix.y0 -= y_offset;
3202 matrix = &tmp_matrix;
3204 else if (GDK_PANGO_UNITS_OVERFLOWS (x_offset, y_offset))
3206 PangoMatrix identity = PANGO_MATRIX_INIT;
3208 tmp_matrix = identity;
3209 tmp_matrix.x0 -= x_offset;
3210 tmp_matrix.y0 -= y_offset;
3211 matrix = &tmp_matrix;
3215 x -= x_offset * PANGO_SCALE;
3216 y -= y_offset * PANGO_SCALE;
3220 if (private->paint_stack)
3222 GdkWindowPaint *paint = private->paint_stack->data;
3224 SETUP_PAINT_GC_CLIP (gc);
3225 gdk_draw_glyphs_transformed (pixmap_impl (paint->pixmap), gc, matrix, font, x, y, glyphs);
3226 RESTORE_PAINT_GC_CLIP (gc);
3230 SETUP_DIRECT_GC_CLIP(gc);
3231 gdk_draw_glyphs_transformed (private->impl, gc, matrix, font, x, y, glyphs);
3232 RESTORE_DIRECT_GC_CLIP(gc);
3239 cairo_t *cr; /* if non-null, it means use this cairo context */
3240 GdkGC *gc; /* if non-null, it means use this GC instead */
3241 } BackingRectMethod;
3244 setup_backing_rect_method (BackingRectMethod *method, GdkWindow *window, GdkWindowPaint *paint, int x_offset_cairo, int y_offset_cairo)
3246 GdkWindowObject *private = (GdkWindowObject *)window;
3248 if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
3250 GdkWindowPaint tmp_paint;
3253 tmp_paint.x_offset += private->x;
3254 tmp_paint.y_offset += private->y;
3256 x_offset_cairo += private->x;
3257 y_offset_cairo += private->y;
3259 setup_backing_rect_method (method, GDK_WINDOW (private->parent), &tmp_paint, x_offset_cairo, y_offset_cairo);
3261 else if (private->bg_pixmap &&
3262 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
3263 private->bg_pixmap != GDK_NO_BG)
3265 /* This is a workaround for https://bugs.freedesktop.org/show_bug.cgi?id=4320.
3266 * In it, using a pixmap as a repeating pattern in Cairo, and painting it to a
3267 * pixmap destination surface, can be very slow (on the order of seconds for a
3268 * whole-screen copy). The workaround is to use pretty much the same code that
3269 * we used in GTK+ 2.6 (pre-Cairo), which clears the double-buffer pixmap with
3270 * a tiled GC XFillRectangle().
3273 /* Actually computing this flag is left as an exercise for the reader */
3274 #if defined (G_OS_UNIX)
3275 # define GDK_CAIRO_REPEAT_IS_FAST 0
3277 # define GDK_CAIRO_REPEAT_IS_FAST 1
3280 #if GDK_CAIRO_REPEAT_IS_FAST
3281 cairo_surface_t *surface = _gdk_drawable_ref_cairo_surface (private->bg_pixmap);
3282 cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
3283 cairo_surface_destroy (surface);
3285 if (x_offset_cairo != 0 || y_offset_cairo != 0)
3287 cairo_matrix_t matrix;
3288 cairo_matrix_init_translate (&matrix, x_offset_cairo, y_offset_cairo);
3289 cairo_pattern_set_matrix (pattern, &matrix);
3292 cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
3294 method->cr = cairo_create (paint->surface);
3297 cairo_set_source (method->cr, pattern);
3298 cairo_pattern_destroy (pattern);
3301 GdkGCValues gc_values;
3303 gc_values.fill = GDK_TILED;
3304 gc_values.tile = private->bg_pixmap;
3305 gc_values.ts_x_origin = -x_offset_cairo;
3306 gc_values.ts_y_origin = -y_offset_cairo;
3308 gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN;
3310 method->gc = gdk_gc_new_with_values (paint->pixmap, &gc_values, gc_mask);
3315 method->cr = cairo_create (paint->surface);
3317 gdk_cairo_set_source_color (method->cr, &private->bg_color);
3322 gdk_window_clear_backing_rect (GdkWindow *window,
3328 GdkWindowObject *private = (GdkWindowObject *)window;
3329 GdkWindowPaint *paint = private->paint_stack->data;
3330 BackingRectMethod method;
3336 if (GDK_WINDOW_DESTROYED (window))
3340 timer = g_timer_new ();
3345 setup_backing_rect_method (&method, window, paint, 0, 0);
3349 g_assert (method.gc == NULL);
3351 cairo_rectangle (method.cr, x, y, width, height);
3352 cairo_clip (method.cr);
3354 gdk_cairo_region (method.cr, paint->region);
3355 cairo_fill (method.cr);
3357 cairo_destroy (method.cr);
3359 elapsed = g_timer_elapsed (timer, NULL);
3360 g_print ("Draw the background with Cairo: %fs\n", elapsed);
3365 g_assert (method.gc != NULL);
3367 gdk_gc_set_clip_region (method.gc, paint->region);
3368 gdk_draw_rectangle (window, method.gc, TRUE, x, y, width, height);
3369 g_object_unref (method.gc);
3372 elapsed = g_timer_elapsed (timer, NULL);
3373 g_print ("Draw the background with GDK: %fs\n", elapsed);
3378 g_timer_destroy (timer);
3383 gdk_window_clear_backing_rect_redirect (GdkWindow *window,
3389 GdkWindowObject *private = (GdkWindowObject *)window;
3390 GdkWindowRedirect *redirect = private->redirect;
3391 GdkRegion *clip_region;
3392 gint x_offset, y_offset;
3393 BackingRectMethod method;
3394 GdkWindowPaint paint;
3396 if (GDK_WINDOW_DESTROYED (window))
3399 clip_region = _gdk_window_calculate_full_clip_region (window,
3400 GDK_WINDOW (redirect->redirected),
3402 &x_offset, &y_offset);
3404 paint.x_offset = x_offset;
3405 paint.y_offset = y_offset;
3406 paint.pixmap = redirect->pixmap;
3407 paint.surface = _gdk_drawable_ref_cairo_surface (redirect->pixmap);
3411 setup_backing_rect_method (&method, window, &paint, 0, 0);
3415 g_assert (method.gc == NULL);
3417 cairo_rectangle (method.cr, x, y, width, height);
3418 cairo_clip (method.cr);
3420 gdk_cairo_region (method.cr, clip_region);
3421 cairo_fill (method.cr);
3423 cairo_destroy (method.cr);
3427 g_assert (method.gc != NULL);
3429 gdk_gc_set_clip_region (method.gc, clip_region);
3430 gdk_draw_rectangle (window, method.gc, TRUE, x, y, width, height);
3431 g_object_unref (method.gc);
3435 gdk_region_destroy (clip_region);
3436 cairo_surface_destroy (paint.surface);
3440 gdk_window_clear_backing_rect_direct (GdkWindow *window,
3446 GdkWindowObject *private = (GdkWindowObject *)window;
3447 BackingRectMethod method;
3448 GdkWindowPaint paint;
3450 if (GDK_WINDOW_DESTROYED (window))
3455 paint.pixmap = window;
3456 paint.surface = _gdk_drawable_ref_cairo_surface (window);
3460 setup_backing_rect_method (&method, window, &paint, 0, 0);
3464 g_assert (method.gc == NULL);
3466 gdk_cairo_region (method.cr, private->clip_region_with_children);
3467 cairo_clip (method.cr);
3469 cairo_rectangle (method.cr, x, y, width, height);
3470 cairo_fill (method.cr);
3472 cairo_destroy (method.cr);
3476 g_assert (method.gc != NULL);
3478 gdk_gc_set_clip_region (method.gc, private->clip_region_with_children);
3479 gdk_draw_rectangle (window, method.gc, TRUE, x, y, width, height);
3480 g_object_unref (method.gc);
3484 cairo_surface_destroy (paint.surface);
3490 * @window: a #GdkWindow
3492 * Clears an entire @window to the background color or background pixmap.
3495 gdk_window_clear (GdkWindow *window)
3499 g_return_if_fail (GDK_IS_WINDOW (window));
3501 gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height);
3503 gdk_window_clear_area (window, 0, 0,
3508 gdk_window_clear_area_internal (GdkWindow *window,
3513 gboolean send_expose)
3515 GdkWindowObject *private = (GdkWindowObject *)window;
3517 g_return_if_fail (GDK_IS_WINDOW (window));
3519 /* This is what XClearArea does, and e.g. GtkCList uses it,
3520 so we need to duplicate that */
3522 width = private->width - x;
3524 height = private->height - y;
3526 if (private->paint_stack)
3527 gdk_window_clear_backing_rect (window, x, y, width, height);
3530 if (private->redirect)
3531 gdk_window_clear_backing_rect_redirect (window, x, y, width, height);
3535 gdk_window_clear_backing_rect_direct (window, x, y, width, height);
3543 rect.height = height;
3545 gdk_window_invalidate_rect (window, &rect, FALSE);
3552 * gdk_window_clear_area:
3553 * @window: a #GdkWindow
3554 * @x: x coordinate of rectangle to clear
3555 * @y: y coordinate of rectangle to clear
3556 * @width: width of rectangle to clear
3557 * @height: height of rectangle to clear
3559 * Clears an area of @window to the background color or background pixmap.
3563 gdk_window_clear_area (GdkWindow *window,
3569 gdk_window_clear_area_internal (window,
3576 * gdk_window_clear_area_e:
3577 * @window: a #GdkWindow
3578 * @x: x coordinate of rectangle to clear
3579 * @y: y coordinate of rectangle to clear
3580 * @width: width of rectangle to clear
3581 * @height: height of rectangle to clear
3583 * Like gdk_window_clear_area(), but also generates an expose event for
3586 * This function has a stupid name because it dates back to the mists
3587 * time, pre-GDK-1.0.
3591 gdk_window_clear_area_e (GdkWindow *window,
3597 gdk_window_clear_area_internal (window,
3604 gdk_window_draw_image (GdkDrawable *drawable,
3614 GdkWindowObject *private = (GdkWindowObject *)drawable;
3618 if (GDK_WINDOW_DESTROYED (drawable))
3621 if (private->paint_stack)
3623 GdkWindowPaint *paint = private->paint_stack->data;
3624 SETUP_PAINT_GC_CLIP (gc);
3625 gdk_draw_image (pixmap_impl (paint->pixmap), gc, image, xsrc, ysrc,
3626 xdest - x_offset, ydest - y_offset,
3629 RESTORE_PAINT_GC_CLIP (gc);
3633 SETUP_DIRECT_GC_CLIP(gc);
3634 gdk_draw_image (private->impl, gc, image, xsrc, ysrc,
3635 xdest - x_offset, ydest - y_offset,
3637 RESTORE_DIRECT_GC_CLIP(gc);
3644 gdk_window_draw_pixbuf (GdkDrawable *drawable,
3653 GdkRgbDither dither,
3657 GdkWindowObject *private = (GdkWindowObject *)drawable;
3659 if (GDK_WINDOW_DESTROYED (drawable))
3666 if (private->paint_stack)
3668 GdkWindowPaint *paint = private->paint_stack->data;
3669 SETUP_PAINT_GC_CLIP (gc);
3670 gdk_draw_pixbuf (pixmap_impl (paint->pixmap), gc, pixbuf, src_x, src_y,
3671 dest_x - x_offset, dest_y - y_offset,
3673 dither, x_dither - x_offset, y_dither - y_offset);
3674 RESTORE_PAINT_GC_CLIP (gc);
3678 SETUP_DIRECT_GC_CLIP(gc);
3679 gdk_draw_pixbuf (private->impl, gc, pixbuf, src_x, src_y,
3680 dest_x - x_offset, dest_y - y_offset,
3682 dither, x_dither, y_dither);
3683 RESTORE_DIRECT_GC_CLIP(gc);
3690 gint x_offset, y_offset;
3691 gdk_window_get_offsets (drawable, &x_offset, &y_offset);
3693 if (private->paint_stack)
3695 GdkWindowPaint *paint = private->paint_stack->data;
3696 /* TODO: Do paint clipping here... */
3697 gdk_draw_pixbuf (paint->pixmap, gc, pixbuf, src_x, src_y,
3698 dest_x - x_offset, dest_y - y_offset,
3700 dither, x_dither - x_offset, y_dither - y_offset);
3704 /* TODO: No GC passed in, but still want clipping here... */
3705 gdk_draw_pixbuf (private->impl, gc, pixbuf, src_x, src_y,
3706 dest_x - x_offset, dest_y - y_offset,
3708 dither, x_dither, y_dither);
3714 gdk_window_draw_trapezoids (GdkDrawable *drawable,
3716 GdkTrapezoid *trapezoids,
3719 GdkWindowObject *private = (GdkWindowObject *)drawable;
3720 GdkTrapezoid *new_trapezoids = NULL;
3724 if (GDK_WINDOW_DESTROYED (drawable))
3727 if (x_offset != 0 || y_offset != 0)
3731 new_trapezoids = g_new (GdkTrapezoid, n_trapezoids);
3732 for (i=0; i < n_trapezoids; i++)
3734 new_trapezoids[i].y1 = trapezoids[i].y1 - y_offset;
3735 new_trapezoids[i].x11 = trapezoids[i].x11 - x_offset;
3736 new_trapezoids[i].x21 = trapezoids[i].x21 - x_offset;
3737 new_trapezoids[i].y2 = trapezoids[i].y2 - y_offset;
3738 new_trapezoids[i].x12 = trapezoids[i].x12 - x_offset;
3739 new_trapezoids[i].x22 = trapezoids[i].x22 - x_offset;
3742 trapezoids = new_trapezoids;
3745 if (private->paint_stack)
3747 GdkWindowPaint *paint = private->paint_stack->data;
3748 SETUP_PAINT_GC_CLIP (gc);
3749 gdk_draw_trapezoids (pixmap_impl (paint->pixmap), gc, trapezoids, n_trapezoids);
3750 RESTORE_PAINT_GC_CLIP (gc);
3754 SETUP_DIRECT_GC_CLIP(gc);
3755 gdk_draw_trapezoids (private->impl, gc, trapezoids, n_trapezoids);
3756 RESTORE_DIRECT_GC_CLIP(gc);
3759 g_free (new_trapezoids);
3765 gdk_window_real_get_size (GdkDrawable *drawable,
3769 GdkWindowObject *private = (GdkWindowObject *)drawable;
3772 *width = private->width;
3774 *height = private->height;
3778 gdk_window_real_get_visual (GdkDrawable *drawable)
3780 GdkColormap *colormap;
3782 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
3784 colormap = gdk_drawable_get_colormap (drawable);
3785 return colormap ? gdk_colormap_get_visual (colormap) : NULL;
3789 gdk_window_real_get_depth (GdkDrawable *drawable)
3791 g_return_val_if_fail (GDK_IS_WINDOW (drawable), 0);
3793 return ((GdkWindowObject *)GDK_WINDOW (drawable))->depth;
3797 gdk_window_real_get_screen (GdkDrawable *drawable)
3799 return gdk_drawable_get_screen (GDK_WINDOW_OBJECT (drawable)->impl);
3803 gdk_window_real_set_colormap (GdkDrawable *drawable,
3806 GdkWindowObject *private;
3808 g_return_if_fail (GDK_IS_WINDOW (drawable));
3810 if (GDK_WINDOW_DESTROYED (drawable))
3813 private = (GdkWindowObject *)drawable;
3815 /* different colormap than parent, requires native window */
3816 if (!private->input_only &&
3817 cmap != gdk_drawable_get_colormap ((GdkDrawable *)(private->parent)))
3818 gdk_window_set_has_native ((GdkWindow *)drawable, TRUE);
3820 gdk_drawable_set_colormap (private->impl, cmap);
3824 gdk_window_real_get_colormap (GdkDrawable *drawable)
3826 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
3828 if (GDK_WINDOW_DESTROYED (drawable))
3831 return gdk_drawable_get_colormap (((GdkWindowObject*)drawable)->impl);
3835 gdk_window_copy_to_image (GdkDrawable *drawable,
3844 GdkWindowObject *private = (GdkWindowObject *) drawable;
3845 gint x_offset, y_offset;
3847 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
3849 if (GDK_WINDOW_DESTROYED (drawable))
3852 /* If we're here, a composite image was not necessary, so
3853 * we can ignore the paint stack.
3856 /* TODO: Is this right? */
3860 return gdk_drawable_copy_to_image (private->impl,
3869 gdk_window_cairo_surface_destroy (void *data)
3871 GdkWindowObject *private = (GdkWindowObject*) data;
3873 private->cairo_surface = NULL;
3876 static cairo_surface_t *
3877 gdk_window_ref_cairo_surface (GdkDrawable *drawable)
3879 GdkWindowObject *private = (GdkWindowObject*) drawable;
3880 cairo_surface_t *surface;
3882 if (private->paint_stack)
3884 GdkWindowPaint *paint = private->paint_stack->data;
3886 surface = paint->surface;
3887 cairo_surface_reference (surface);
3892 /* This will be drawing directly to the window, so flush implicit paint */
3893 gdk_window_flush ((GdkWindow *)drawable);
3895 if (!private->cairo_surface)
3898 GdkDrawable *source;
3900 /* It would be nice if we had some cairo support here so we
3901 could set the clip rect on the cairo surface */
3902 width = private->abs_x + private->width;
3903 height = private->abs_y + private->height;
3905 source = _gdk_drawable_get_source_drawable (drawable);
3907 /* TODO: Avoid the typecheck crap by adding virtual call */
3908 private->cairo_surface = _gdk_windowing_create_cairo_surface (GDK_IS_PIXMAP (source) ? GDK_PIXMAP_OBJECT(source)->impl : GDK_WINDOW_OBJECT(source)->impl,
3911 if (private->cairo_surface)
3913 cairo_surface_set_device_offset (private->cairo_surface,
3917 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
3918 drawable, gdk_window_cairo_surface_destroy);
3922 cairo_surface_reference (private->cairo_surface);
3924 surface = private->cairo_surface;
3931 gdk_window_set_cairo_clip (GdkDrawable *drawable,
3934 GdkWindowObject *private = (GdkWindowObject*) drawable;
3936 if (!private->paint_stack)
3939 cairo_identity_matrix (cr);
3941 cairo_new_path (cr);
3942 gdk_cairo_region (cr, private->clip_region);
3949 GdkWindowPaint *paint = private->paint_stack->data;
3951 /* Only needs to clip to region if piggybacking
3952 on an implicit paint pixmap */
3953 if (paint->uses_implicit)
3956 cairo_identity_matrix (cr);
3958 cairo_new_path (cr);
3959 gdk_cairo_region (cr, paint->region);
3967 /* Code for dirty-region queueing
3969 static GSList *update_windows = NULL;
3970 static guint update_idle = 0;
3971 static gboolean debug_updates = FALSE;
3973 static inline gboolean
3974 gdk_window_is_ancestor (GdkWindow *window,
3975 GdkWindow *ancestor)
3979 GdkWindow *parent = (GdkWindow*) ((GdkWindowObject*) window)->parent;
3981 if (parent == ancestor)
3991 gdk_window_add_update_window (GdkWindow *window)
3994 GSList *prev = NULL;
3995 gboolean has_ancestor_in_list = FALSE;
3997 for (tmp = update_windows; tmp; tmp = tmp->next)
3999 GdkWindowObject *parent = GDK_WINDOW_OBJECT (window)->parent;
4001 /* check if tmp is an ancestor of "window"; if it is, set a
4002 * flag indicating that all following windows are either
4003 * children of "window" or from a differen hierarchy
4005 if (!has_ancestor_in_list && gdk_window_is_ancestor (window, tmp->data))
4006 has_ancestor_in_list = TRUE;
4008 /* insert in reverse stacking order when adding around siblings,
4009 * so processing updates properly paints over lower stacked windows
4011 if (parent == GDK_WINDOW_OBJECT (tmp->data)->parent)
4013 gint index = g_list_index (parent->children, window);
4014 for (; tmp && parent == GDK_WINDOW_OBJECT (tmp->data)->parent; tmp = tmp->next)
4016 gint sibling_index = g_list_index (parent->children, tmp->data);
4017 if (index > sibling_index)
4021 /* here, tmp got advanced past all lower stacked siblings */
4022 tmp = g_slist_prepend (tmp, window);
4026 update_windows = tmp;
4030 /* if "window" has an ancestor in the list and tmp is one of
4031 * "window's" children, insert "window" before tmp
4033 if (has_ancestor_in_list && gdk_window_is_ancestor (tmp->data, window))
4035 tmp = g_slist_prepend (tmp, window);
4040 update_windows = tmp;
4044 /* if we're at the end of the list and had an ancestor it it,
4045 * append to the list
4047 if (! tmp->next && has_ancestor_in_list)
4049 tmp = g_slist_append (tmp, window);
4056 /* if all above checks failed ("window" is from a different
4057 * hierarchy than what is already in the list) or the list is
4060 update_windows = g_slist_prepend (update_windows, window);
4064 gdk_window_remove_update_window (GdkWindow *window)
4066 update_windows = g_slist_remove (update_windows, window);
4070 gdk_window_update_idle (gpointer data)
4072 gdk_window_process_all_updates ();
4078 gdk_window_is_toplevel_frozen (GdkWindow *window)
4080 GdkWindowObject *toplevel;
4082 toplevel = (GdkWindowObject *)gdk_window_get_toplevel (window);
4084 return toplevel->update_and_descendants_freeze_count > 0;
4088 gdk_window_schedule_update (GdkWindow *window)
4091 (GDK_WINDOW_OBJECT (window)->update_freeze_count ||
4092 gdk_window_is_toplevel_frozen (window)))
4097 update_idle = gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
4098 gdk_window_update_idle, NULL, NULL);
4103 gdk_window_process_updates_recurse (GdkWindow *window,
4104 GdkRegion *expose_region)
4106 GdkWindowObject *private = (GdkWindowObject *)window;
4107 GdkWindowObject *child;
4108 GdkRegion *child_region;
4112 if (gdk_region_empty (expose_region))
4115 /* Iterate over children, starting at topmost */
4116 for (l = private->children; l != NULL; l = l->next)
4120 if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only)
4123 /* Ignore offscreen children, as they don't draw in their parent and
4124 * don't take part in the clipping */
4125 if (gdk_window_is_offscreen (child))
4130 r.width = child->width;
4131 r.height = child->height;
4133 child_region = gdk_region_rectangle (&r);
4135 if (child->impl == private->impl)
4137 /* Client side child, expose */
4138 gdk_region_intersect (child_region, expose_region);
4139 gdk_region_subtract (expose_region, child_region);
4140 gdk_region_offset (child_region, -child->x, -child->y);
4141 gdk_window_process_updates_recurse ((GdkWindow *)child, child_region);
4145 /* Native child, just remove area from expose region */
4146 gdk_region_subtract (expose_region, child_region);
4148 gdk_region_destroy (child_region);
4151 if (private->event_mask & GDK_EXPOSURE_MASK)
4155 event.expose.type = GDK_EXPOSE;
4156 event.expose.window = g_object_ref (window);
4157 event.expose.send_event = FALSE;
4158 event.expose.count = 0;
4159 event.expose.region = expose_region;
4160 gdk_region_get_clipbox (expose_region, &event.expose.area);
4162 (*_gdk_event_func) (&event, _gdk_event_data);
4164 g_object_unref (window);
4169 gdk_window_process_updates_internal (GdkWindow *window)
4171 GdkWindowObject *private = (GdkWindowObject *)window;
4172 gboolean save_region = FALSE;
4173 GdkRectangle clip_box;
4175 /* If an update got queued during update processing, we can get a
4176 * window in the update queue that has an empty update_area.
4179 if (private->update_area)
4181 GdkRegion *update_area = private->update_area;
4182 private->update_area = NULL;
4184 if (_gdk_event_func && gdk_window_is_viewable (window))
4186 GdkRectangle window_rect;
4187 GdkRegion *expose_region;
4188 GdkRegion *window_region;
4189 gboolean end_implicit;
4193 /* Make sure we see the red invalid area before redrawing. */
4194 gdk_display_sync (gdk_drawable_get_display (window));
4198 save_region = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->queue_antiexpose (window, update_area);
4200 expose_region = gdk_region_copy (update_area);
4202 expose_region = update_area;
4206 window_rect.width = private->width;
4207 window_rect.height = private->height;
4209 window_region = gdk_region_rectangle (&window_rect);
4210 gdk_region_intersect (expose_region,
4212 gdk_region_destroy (window_region);
4214 gdk_region_get_clipbox (expose_region, &clip_box);
4215 end_implicit = gdk_window_begin_implicit_paint (window, &clip_box);
4216 gdk_window_process_updates_recurse (window, expose_region);
4218 gdk_window_end_implicit_paint (window);
4220 if (expose_region != update_area)
4221 gdk_region_destroy (expose_region);
4224 gdk_region_destroy (update_area);
4229 flush_all_displays (void)
4231 GSList *displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
4234 for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
4235 gdk_display_flush (tmp_list->data);
4237 g_slist_free (displays);
4240 /* Currently it is not possible to override
4241 * gdk_window_process_all_updates in the same manner as
4242 * gdk_window_process_updates and gdk_window_invalidate_maybe_recurse
4243 * by implementing the GdkPaintable interface. If in the future a
4244 * backend would need this, the right solution would be to add a
4245 * method to GdkDisplay that can be optionally
4246 * NULL. gdk_window_process_all_updates can then walk the list of open
4247 * displays and call the mehod.
4251 * gdk_window_process_all_updates:
4253 * Calls gdk_window_process_updates() for all windows (see #GdkWindow)
4254 * in the application.
4258 gdk_window_process_all_updates (void)
4260 GSList *old_update_windows = update_windows;
4261 GSList *tmp_list = update_windows;
4264 g_source_remove (update_idle);
4266 update_windows = NULL;
4269 g_slist_foreach (old_update_windows, (GFunc)g_object_ref, NULL);
4273 GdkWindowObject *private = (GdkWindowObject *)tmp_list->data;
4275 if (!GDK_WINDOW_DESTROYED (tmp_list->data))
4277 if (private->update_freeze_count ||
4278 gdk_window_is_toplevel_frozen (tmp_list->data))
4279 gdk_window_add_update_window ((GdkWindow *) private);
4281 gdk_window_process_updates_internal (tmp_list->data);
4284 g_object_unref (tmp_list->data);
4285 tmp_list = tmp_list->next;
4288 g_slist_free (old_update_windows);
4290 flush_all_displays ();
4294 * gdk_window_process_updates:
4295 * @window: a #GdkWindow
4296 * @update_children: whether to also process updates for child windows
4298 * Sends one or more expose events to @window. The areas in each
4299 * expose event will cover the entire update area for the window (see
4300 * gdk_window_invalidate_region() for details). Normally GDK calls
4301 * gdk_window_process_all_updates() on your behalf, so there's no
4302 * need to call this function unless you want to force expose events
4303 * to be delivered immediately and synchronously (vs. the usual
4304 * case, where GDK delivers them in an idle handler). Occasionally
4305 * this is useful to produce nicer scrolling behavior, for example.
4309 gdk_window_process_updates (GdkWindow *window,
4310 gboolean update_children)
4312 GdkWindowObject *private = (GdkWindowObject *)window;
4313 GdkWindowObject *impl_window;
4315 g_return_if_fail (GDK_IS_WINDOW (window));
4317 if (GDK_IS_PAINTABLE (private->impl))
4319 GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
4321 if (iface->process_updates)
4322 iface->process_updates ((GdkPaintable*)private->impl, update_children);
4327 impl_window = gdk_window_get_impl_window (private);
4328 if (impl_window->update_area &&
4329 !impl_window->update_freeze_count &&
4330 !gdk_window_is_toplevel_frozen (window))
4332 gdk_window_process_updates_internal ((GdkWindow *)impl_window);
4333 gdk_window_remove_update_window ((GdkWindow *)impl_window);
4336 if (update_children)
4338 /* process updates in reverse stacking order so composition or
4339 * painting over achieves the desired effect for offscreen windows
4342 for (node = g_list_last (private->children); node; node = node->prev)
4343 gdk_window_process_updates (node->data, TRUE);
4348 * gdk_window_invalidate_rect:
4349 * @window: a #GdkWindow
4350 * @rect: rectangle to invalidate or %NULL to invalidate the whole
4352 * @invalidate_children: whether to also invalidate child windows
4354 * A convenience wrapper around gdk_window_invalidate_region() which
4355 * invalidates a rectangular region. See
4356 * gdk_window_invalidate_region() for details.
4359 gdk_window_invalidate_rect (GdkWindow *window,
4360 const GdkRectangle *rect,
4361 gboolean invalidate_children)
4363 GdkRectangle window_rect;
4365 GdkWindowObject *private = (GdkWindowObject *)window;
4367 g_return_if_fail (GDK_IS_WINDOW (window));
4369 if (GDK_WINDOW_DESTROYED (window))
4372 if (private->input_only || !GDK_WINDOW_IS_MAPPED (window))
4379 gdk_drawable_get_size (GDK_DRAWABLE (window),
4381 &window_rect.height);
4382 rect = &window_rect;
4385 region = gdk_region_rectangle (rect);
4386 gdk_window_invalidate_region (window, region, invalidate_children);
4387 gdk_region_destroy (region);
4391 draw_ugly_color (GdkWindow *window,
4392 const GdkRegion *region)
4394 /* Draw ugly color all over the newly-invalid region */
4395 GdkColor ugly_color = { 0, 50000, 10000, 10000 };
4397 GdkRectangle clipbox;
4399 ugly_gc = gdk_gc_new (window);
4400 gdk_gc_set_rgb_fg_color (ugly_gc, &ugly_color);
4401 gdk_gc_set_clip_region (ugly_gc, region);
4403 gdk_region_get_clipbox (region, &clipbox);
4405 gdk_draw_rectangle (window,
4408 clipbox.x, clipbox.y,
4409 clipbox.width, clipbox.height);
4411 g_object_unref (ugly_gc);
4415 * gdk_window_invalidate_maybe_recurse:
4416 * @window: a #GdkWindow
4417 * @region: a #GdkRegion
4418 * @child_func: function to use to decide if to recurse to a child,
4419 * %NULL means never recurse.
4420 * @user_data: data passed to @child_func
4422 * Adds @region to the update area for @window. The update area is the
4423 * region that needs to be redrawn, or "dirty region." The call
4424 * gdk_window_process_updates() sends one or more expose events to the
4425 * window, which together cover the entire update area. An
4426 * application would normally redraw the contents of @window in
4427 * response to those expose events.
4429 * GDK will call gdk_window_process_all_updates() on your behalf
4430 * whenever your program returns to the main loop and becomes idle, so
4431 * normally there's no need to do that manually, you just need to
4432 * invalidate regions that you know should be redrawn.
4434 * The @child_func parameter controls whether the region of
4435 * each child window that intersects @region will also be invalidated.
4436 * Only children for which @child_func returns TRUE will have the area
4440 gdk_window_invalidate_maybe_recurse (GdkWindow *window,
4441 const GdkRegion *region,
4442 gboolean (*child_func) (GdkWindow *,
4446 GdkWindowObject *private = (GdkWindowObject *)window;
4447 GdkWindowObject *impl_window;
4448 GdkRegion *visible_region;
4451 g_return_if_fail (GDK_IS_WINDOW (window));
4453 if (GDK_WINDOW_DESTROYED (window))
4456 if (private->input_only || !GDK_WINDOW_IS_MAPPED (window))
4459 if (GDK_IS_PAINTABLE (private->impl))
4461 GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
4463 if (iface->invalidate_maybe_recurse)
4464 iface->invalidate_maybe_recurse ((GdkPaintable*)private->impl,
4465 region, child_func, user_data);
4469 visible_region = gdk_drawable_get_visible_region (window);
4470 gdk_region_intersect (visible_region, region);
4472 tmp_list = private->children;
4475 GdkWindowObject *child = tmp_list->data;
4477 if (!child->input_only)
4479 GdkRegion *child_region;
4480 GdkRectangle child_rect;
4482 child_rect.x = child->x;
4483 child_rect.y = child->y;
4484 child_rect.width = child->width;
4485 child_rect.height = child->height;
4486 child_region = gdk_region_rectangle (&child_rect);
4488 /* remove child area from the invalid area of the parent */
4489 if (GDK_WINDOW_IS_MAPPED (child) && !child->shaped &&
4490 !child->composited &&
4491 !gdk_window_is_offscreen (child))
4492 gdk_region_subtract (visible_region, child_region);
4494 if (child_func && (*child_func) ((GdkWindow *)child, user_data))
4496 GdkRegion *tmp = gdk_region_copy (region);
4498 gdk_region_offset (tmp, - child_rect.x, - child_rect.y);
4499 gdk_region_offset (child_region, - child_rect.x, - child_rect.y);
4500 gdk_region_intersect (child_region, tmp);
4502 gdk_window_invalidate_maybe_recurse ((GdkWindow *)child,
4503 child_region, child_func, user_data);
4505 gdk_region_destroy (tmp);
4508 gdk_region_destroy (child_region);
4511 tmp_list = tmp_list->next;
4514 if (!gdk_region_empty (visible_region))
4517 draw_ugly_color (window, region);
4519 /* Convert to impl coords */
4520 impl_window = gdk_window_get_impl_window (private);
4521 gdk_region_offset (visible_region, private->abs_x, private->abs_y);
4522 if (impl_window->update_area)
4524 gdk_region_union (impl_window->update_area, visible_region);
4528 gdk_window_add_update_window ((GdkWindow *)impl_window);
4529 impl_window->update_area = gdk_region_copy (visible_region);
4531 gdk_window_schedule_update ((GdkWindow *)impl_window);
4535 gdk_region_destroy (visible_region);
4539 true_predicate (GdkWindow *window,
4546 * gdk_window_invalidate_region:
4547 * @window: a #GdkWindow
4548 * @region: a #GdkRegion
4549 * @invalidate_children: %TRUE to also invalidate child windows
4551 * Adds @region to the update area for @window. The update area is the
4552 * region that needs to be redrawn, or "dirty region." The call
4553 * gdk_window_process_updates() sends one or more expose events to the
4554 * window, which together cover the entire update area. An
4555 * application would normally redraw the contents of @window in
4556 * response to those expose events.
4558 * GDK will call gdk_window_process_all_updates() on your behalf
4559 * whenever your program returns to the main loop and becomes idle, so
4560 * normally there's no need to do that manually, you just need to
4561 * invalidate regions that you know should be redrawn.
4563 * The @invalidate_children parameter controls whether the region of
4564 * each child window that intersects @region will also be invalidated.
4565 * If %FALSE, then the update area for child windows will remain
4566 * unaffected. See gdk_window_invalidate_maybe_recurse if you need
4567 * fine grained control over which children are invalidated.
4570 gdk_window_invalidate_region (GdkWindow *window,
4571 const GdkRegion *region,
4572 gboolean invalidate_children)
4574 gdk_window_invalidate_maybe_recurse (window, region,
4575 invalidate_children ?
4576 true_predicate : (gboolean (*) (GdkWindow *, gpointer))NULL,
4581 * _gdk_window_invalidate_for_expose:
4582 * @window: a #GdkWindow
4583 * @region: a #GdkRegion
4585 * Adds @region to the update area for @window. The update area is the
4586 * region that needs to be redrawn, or "dirty region." The call
4587 * gdk_window_process_updates() sends one or more expose events to the
4588 * window, which together cover the entire update area. An
4589 * application would normally redraw the contents of @window in
4590 * response to those expose events.
4592 * GDK will call gdk_window_process_all_updates() on your behalf
4593 * whenever your program returns to the main loop and becomes idle, so
4594 * normally there's no need to do that manually, you just need to
4595 * invalidate regions that you know should be redrawn.
4597 * This version of invalidation is used when you recieve expose events
4598 * from the native window system. It exposes the native window, plus
4599 * any non-native child windows (but not native child windows, as those would
4600 * have gotten their own expose events).
4603 _gdk_window_invalidate_for_expose (GdkWindow *window,
4604 const GdkRegion *region)
4606 gdk_window_invalidate_maybe_recurse (window, region,
4607 (gboolean (*) (GdkWindow *, gpointer))gdk_window_has_no_impl,
4613 * gdk_window_get_update_area:
4614 * @window: a #GdkWindow
4616 * Transfers ownership of the update area from @window to the caller
4617 * of the function. That is, after calling this function, @window will
4618 * no longer have an invalid/dirty region; the update area is removed
4619 * from @window and handed to you. If a window has no update area,
4620 * gdk_window_get_update_area() returns %NULL. You are responsible for
4621 * calling gdk_region_destroy() on the returned region if it's non-%NULL.
4623 * Return value: the update area for @window
4626 gdk_window_get_update_area (GdkWindow *window)
4628 GdkWindowObject *private = (GdkWindowObject *)window;
4629 GdkWindowObject *impl_window;
4630 GdkRegion *tmp_region;
4632 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
4634 impl_window = gdk_window_get_impl_window (private);
4636 if (impl_window->update_area)
4638 tmp_region = gdk_region_copy (private->clip_region_with_children);
4639 /* Convert to impl coords */
4640 gdk_region_offset (tmp_region, private->abs_x, private->abs_y);
4641 gdk_region_intersect (tmp_region, impl_window->update_area);
4643 if (gdk_region_empty (tmp_region))
4645 gdk_region_destroy (tmp_region);
4650 gdk_region_subtract (impl_window->update_area, tmp_region);
4652 if (gdk_region_empty (impl_window->update_area))
4654 gdk_region_destroy (impl_window->update_area);
4655 impl_window->update_area = NULL;
4657 gdk_window_remove_update_window ((GdkWindow *)impl_window);
4660 /* Convert from impl coords */
4661 gdk_region_offset (tmp_region, -private->abs_x, -private->abs_y);
4671 * _gdk_window_clear_update_area:
4672 * @window: a #GdkWindow.
4674 * Internal function to clear the update area for a window. This
4675 * is called when the window is hidden or destroyed.
4678 _gdk_window_clear_update_area (GdkWindow *window)
4680 GdkWindowObject *private = (GdkWindowObject *)window;
4682 g_return_if_fail (GDK_IS_WINDOW (window));
4684 if (private->update_area)
4686 gdk_window_remove_update_window (window);
4688 gdk_region_destroy (private->update_area);
4689 private->update_area = NULL;
4694 * gdk_window_freeze_updates:
4695 * @window: a #GdkWindow
4697 * Temporarily freezes a window such that it won't receive expose
4698 * events. The window will begin receiving expose events again when
4699 * gdk_window_thaw_updates() is called. If gdk_window_freeze_updates()
4700 * has been called more than once, gdk_window_thaw_updates() must be called
4701 * an equal number of times to begin processing exposes.
4704 gdk_window_freeze_updates (GdkWindow *window)
4706 GdkWindowObject *private = (GdkWindowObject *)window;
4707 GdkWindowObject *impl_window;
4709 g_return_if_fail (GDK_IS_WINDOW (window));
4711 impl_window = gdk_window_get_impl_window (private);
4712 impl_window->update_freeze_count++;
4716 * gdk_window_thaw_updates:
4717 * @window: a #GdkWindow
4719 * Thaws a window frozen with gdk_window_freeze_updates().
4722 gdk_window_thaw_updates (GdkWindow *window)
4724 GdkWindowObject *private = (GdkWindowObject *)window;
4725 GdkWindowObject *impl_window;
4727 g_return_if_fail (GDK_IS_WINDOW (window));
4728 g_return_if_fail (private->update_freeze_count > 0);
4730 impl_window = gdk_window_get_impl_window (private);
4732 if (--impl_window->update_freeze_count == 0)
4733 gdk_window_schedule_update (GDK_WINDOW (impl_window));
4737 * gdk_window_freeze_toplevel_updates_libgtk_only:
4738 * @window: a #GdkWindow
4740 * Temporarily freezes a window and all its descendants such that it won't
4741 * receive expose events. The window will begin receiving expose events
4742 * again when gdk_window_thaw_toplevel_updates_libgtk_only() is called. If
4743 * gdk_window_freeze_toplevel_updates_libgtk_only()
4744 * has been called more than once,
4745 * gdk_window_thaw_toplevel_updates_libgtk_only() must be called
4746 * an equal number of times to begin processing exposes.
4748 * This function is not part of the GDK public API and is only
4752 gdk_window_freeze_toplevel_updates_libgtk_only (GdkWindow *window)
4754 GdkWindowObject *private = (GdkWindowObject *)window;
4756 g_return_if_fail (GDK_IS_WINDOW (window));
4757 g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
4759 private->update_and_descendants_freeze_count++;
4763 * gdk_window_thaw_toplevel_updates_libgtk_only:
4764 * @window: a #GdkWindow
4766 * Thaws a window frozen with
4767 * gdk_window_freeze_toplevel_updates_libgtk_only().
4769 * This function is not part of the GDK public API and is only
4773 gdk_window_thaw_toplevel_updates_libgtk_only (GdkWindow *window)
4775 GdkWindowObject *private = (GdkWindowObject *)window;
4777 g_return_if_fail (GDK_IS_WINDOW (window));
4778 g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
4779 g_return_if_fail (private->update_and_descendants_freeze_count > 0);
4781 private->update_and_descendants_freeze_count--;
4783 gdk_window_schedule_update (window);
4787 * gdk_window_set_debug_updates:
4788 * @setting: %TRUE to turn on update debugging
4790 * With update debugging enabled, calls to
4791 * gdk_window_invalidate_region() clear the invalidated region of the
4792 * screen to a noticeable color, and GDK pauses for a short time
4793 * before sending exposes to windows during
4794 * gdk_window_process_updates(). The net effect is that you can see
4795 * the invalid region for each window and watch redraws as they
4796 * occur. This allows you to diagnose inefficiencies in your application.
4798 * In essence, because the GDK rendering model prevents all flicker,
4799 * if you are redrawing the same region 400 times you may never
4800 * notice, aside from noticing a speed problem. Enabling update
4801 * debugging causes GTK to flicker slowly and noticeably, so you can
4802 * see exactly what's being redrawn when, in what order.
4804 * The --gtk-debug=updates command line option passed to GTK+ programs
4805 * enables this debug option at application startup time. That's
4806 * usually more useful than calling gdk_window_set_debug_updates()
4807 * yourself, though you might want to use this function to enable
4808 * updates sometime after application startup time.
4812 gdk_window_set_debug_updates (gboolean setting)
4814 debug_updates = setting;
4818 * gdk_window_constrain_size:
4819 * @geometry: a #GdkGeometry structure
4820 * @flags: a mask indicating what portions of @geometry are set
4821 * @width: desired width of window
4822 * @height: desired height of the window
4823 * @new_width: location to store resulting width
4824 * @new_height: location to store resulting height
4826 * Constrains a desired width and height according to a
4827 * set of geometry hints (such as minimum and maximum size).
4830 gdk_window_constrain_size (GdkGeometry *geometry,
4837 /* This routine is partially borrowed from fvwm.
4839 * Copyright 1993, Robert Nation
4840 * You may use this code for any purpose, as long as the original
4841 * copyright remains in the source code and all documentation
4843 * which in turn borrows parts of the algorithm from uwm
4846 gint min_height = 0;
4847 gint base_width = 0;
4848 gint base_height = 0;
4851 gint max_width = G_MAXINT;
4852 gint max_height = G_MAXINT;
4854 #define FLOOR(value, base) ( ((gint) ((value) / (base))) * (base) )
4856 if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
4858 base_width = geometry->base_width;
4859 base_height = geometry->base_height;
4860 min_width = geometry->min_width;
4861 min_height = geometry->min_height;
4863 else if (flags & GDK_HINT_BASE_SIZE)
4865 base_width = geometry->base_width;
4866 base_height = geometry->base_height;
4867 min_width = geometry->base_width;
4868 min_height = geometry->base_height;
4870 else if (flags & GDK_HINT_MIN_SIZE)
4872 base_width = geometry->min_width;
4873 base_height = geometry->min_height;
4874 min_width = geometry->min_width;
4875 min_height = geometry->min_height;
4878 if (flags & GDK_HINT_MAX_SIZE)
4880 max_width = geometry->max_width ;
4881 max_height = geometry->max_height;
4884 if (flags & GDK_HINT_RESIZE_INC)
4886 xinc = MAX (xinc, geometry->width_inc);
4887 yinc = MAX (yinc, geometry->height_inc);
4890 /* clamp width and height to min and max values
4892 width = CLAMP (width, min_width, max_width);
4893 height = CLAMP (height, min_height, max_height);
4895 /* shrink to base + N * inc
4897 width = base_width + FLOOR (width - base_width, xinc);
4898 height = base_height + FLOOR (height - base_height, yinc);
4900 /* constrain aspect ratio, according to:
4903 * min_aspect <= -------- <= max_aspect
4907 if (flags & GDK_HINT_ASPECT &&
4908 geometry->min_aspect > 0 &&
4909 geometry->max_aspect > 0)
4913 if (geometry->min_aspect * height > width)
4915 delta = FLOOR (height - width / geometry->min_aspect, yinc);
4916 if (height - delta >= min_height)
4920 delta = FLOOR (height * geometry->min_aspect - width, xinc);
4921 if (width + delta <= max_width)
4926 if (geometry->max_aspect * height < width)
4928 delta = FLOOR (width - height * geometry->max_aspect, xinc);
4929 if (width - delta >= min_width)
4933 delta = FLOOR (width / geometry->max_aspect - height, yinc);
4934 if (height + delta <= max_height)
4943 *new_height = height;
4947 * gdk_window_get_pointer:
4948 * @window: a #GdkWindow
4949 * @x: return location for X coordinate of pointer or %NULL to not
4950 * return the X coordinate
4951 * @y: return location for Y coordinate of pointer or %NULL to not
4952 * return the Y coordinate
4953 * @mask: return location for modifier mask or %NULL to not return the
4956 * Obtains the current pointer position and modifier state.
4957 * The position is given in coordinates relative to the upper left
4958 * corner of @window.
4960 * Return value: the window containing the pointer (as with
4961 * gdk_window_at_pointer()), or %NULL if the window containing the
4962 * pointer isn't known to GDK
4965 gdk_window_get_pointer (GdkWindow *window,
4968 GdkModifierType *mask)
4970 GdkDisplay *display;
4972 GdkModifierType tmp_mask;
4975 g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
4979 display = gdk_drawable_get_display (window);
4983 GdkScreen *screen = gdk_screen_get_default ();
4985 display = gdk_screen_get_display (screen);
4986 window = gdk_screen_get_root_window (screen);
4988 GDK_NOTE (MULTIHEAD,
4989 g_message ("Passing NULL for window to gdk_window_get_pointer()\n"
4990 "is not multihead safe"));
4993 child = display->pointer_hooks->window_get_pointer (display, window, &tmp_x, &tmp_y, &tmp_mask);
5006 * gdk_window_at_pointer:
5007 * @win_x: return location for origin of the window under the pointer
5008 * @win_y: return location for origin of the window under the pointer
5010 * Obtains the window underneath the mouse pointer, returning the
5011 * location of that window in @win_x, @win_y. Returns %NULL if the
5012 * window under the mouse pointer is not known to GDK (if the window
5013 * belongs to another application and a #GdkWindow hasn't been created
5014 * for it with gdk_window_foreign_new())
5016 * NOTE: For multihead-aware widgets or applications use
5017 * gdk_display_get_window_at_pointer() instead.
5019 * Return value: window under the mouse pointer
5022 gdk_window_at_pointer (gint *win_x,
5025 return gdk_display_get_window_at_pointer (gdk_display_get_default (), win_x, win_y);
5029 * gdk_get_default_root_window:
5031 * Obtains the root window (parent all other windows are inside)
5032 * for the default display and screen.
5034 * Return value: the default root window
5037 gdk_get_default_root_window (void)
5039 return gdk_screen_get_root_window (gdk_screen_get_default ());
5043 * gdk_window_foreign_new:
5044 * @anid: a native window handle.
5046 * Wraps a native window for the default display in a #GdkWindow.
5047 * This may fail if the window has been destroyed.
5049 * For example in the X backend, a native window handle is an Xlib
5052 * Return value: the newly-created #GdkWindow wrapper for the
5053 * native window or %NULL if the window has been destroyed.
5056 gdk_window_foreign_new (GdkNativeWindow anid)
5058 return gdk_window_foreign_new_for_display (gdk_display_get_default (), anid);
5062 gdk_window_raise_internal (GdkWindow *window)
5064 GdkWindowObject *private = (GdkWindowObject *)window;
5065 GdkWindowObject *parent = private->parent;
5069 parent->children = g_list_remove (parent->children, window);
5070 parent->children = g_list_prepend (parent->children, window);
5075 gdk_window_show_internal (GdkWindow *window, gboolean raise)
5077 GdkWindowObject *private;
5078 gboolean was_mapped;
5080 g_return_if_fail (GDK_IS_WINDOW (window));
5082 private = (GdkWindowObject *) window;
5083 if (private->destroyed)
5086 was_mapped = GDK_WINDOW_IS_MAPPED (window);
5090 /* Keep children in (reverse) stacking order */
5091 gdk_window_raise_internal (window);
5094 if (gdk_window_has_impl (private))
5095 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show (window, raise);
5098 if (GDK_WINDOW_IS_MAPPED (window))
5100 /* If we're raising, need to invalidate even if we're already shown */
5101 if (raise && gdk_window_is_viewable (window) && !private->input_only)
5102 gdk_window_invalidate_rect (window, NULL, TRUE);
5106 /* Wasn't visible already */
5113 if (private->event_mask & GDK_STRUCTURE_MASK)
5114 _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
5116 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
5117 _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
5120 if (!was_mapped || raise)
5122 if (gdk_window_is_viewable (window))
5123 _gdk_syntesize_crossing_events_for_geometry_change (window);
5125 recompute_visible_regions (private, TRUE, FALSE);
5128 if (!was_mapped && gdk_window_is_viewable (window))
5129 gdk_window_invalidate_rect (window, NULL, TRUE);
5133 * gdk_window_show_unraised:
5134 * @window: a #GdkWindow
5136 * Shows a #GdkWindow onscreen, but does not modify its stacking
5137 * order. In contrast, gdk_window_show() will raise the window
5138 * to the top of the window stack.
5140 * On the X11 platform, in Xlib terms, this function calls
5141 * XMapWindow() (it also updates some internal GDK state, which means
5142 * that you can't really use XMapWindow() directly on a GDK window).
5145 gdk_window_show_unraised (GdkWindow *window)
5147 gdk_window_show_internal (window, FALSE);
5152 * @window: a #GdkWindow
5154 * Raises @window to the top of the Z-order (stacking order), so that
5155 * other windows with the same parent window appear below @window.
5156 * This is true whether or not the windows are visible.
5158 * If @window is a toplevel, the window manager may choose to deny the
5159 * request to move the window in the Z-order, gdk_window_raise() only
5160 * requests the restack, does not guarantee it.
5163 gdk_window_raise (GdkWindow *window)
5165 GdkWindowObject *private;
5167 g_return_if_fail (GDK_IS_WINDOW (window));
5169 private = (GdkWindowObject *) window;
5170 if (private->destroyed)
5173 /* Keep children in (reverse) stacking order */
5174 gdk_window_raise_internal (window);
5176 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
5178 recompute_visible_regions (private, TRUE, FALSE);
5182 gdk_window_lower_internal (GdkWindow *window)
5184 GdkWindowObject *private = (GdkWindowObject *)window;
5185 GdkWindowObject *parent = private->parent;
5189 parent->children = g_list_remove (parent->children, window);
5190 parent->children = g_list_append (parent->children, window);
5195 gdk_window_invalidate_in_parent (GdkWindowObject *private)
5197 GdkRectangle r, child;
5199 if (private->parent == NULL ||
5200 GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
5203 /* get the visible rectangle of the parent */
5205 r.width = private->parent->width;
5206 r.height = private->parent->height;
5208 child.x = private->x;
5209 child.y = private->y;
5210 child.width = private->width;
5211 child.height = private->height;
5212 gdk_rectangle_intersect (&r, &child, &r);
5214 gdk_window_invalidate_rect (GDK_WINDOW (private->parent), &r, TRUE);
5220 * @window: a #GdkWindow
5222 * Lowers @window to the bottom of the Z-order (stacking order), so that
5223 * other windows with the same parent window appear above @window.
5224 * This is true whether or not the other windows are visible.
5226 * If @window is a toplevel, the window manager may choose to deny the
5227 * request to move the window in the Z-order, gdk_window_lower() only
5228 * requests the restack, does not guarantee it.
5230 * Note that gdk_window_show() raises the window again, so don't call this
5231 * function before gdk_window_show(). (Try gdk_window_show_unraised().)
5234 gdk_window_lower (GdkWindow *window)
5236 GdkWindowObject *private;
5238 g_return_if_fail (GDK_IS_WINDOW (window));
5240 private = (GdkWindowObject *) window;
5241 if (private->destroyed)
5244 /* Keep children in (reverse) stacking order */
5245 gdk_window_lower_internal (window);
5247 if (gdk_window_has_impl (private))
5248 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->lower (window);
5251 gdk_window_invalidate_in_parent (private);
5252 _gdk_syntesize_crossing_events_for_geometry_change (window);
5255 recompute_visible_regions (private, TRUE, FALSE);
5260 * @window: a #GdkWindow
5262 * Like gdk_window_show_unraised(), but also raises the window to the
5263 * top of the window stack (moves the window to the front of the
5266 * This function maps a window so it's visible onscreen. Its opposite
5267 * is gdk_window_hide().
5269 * When implementing a #GtkWidget, you should call this function on the widget's
5270 * #GdkWindow as part of the "map" method.
5273 gdk_window_show (GdkWindow *window)
5275 gdk_window_show_internal (window, TRUE);
5280 * @window: a #GdkWindow
5282 * For toplevel windows, withdraws them, so they will no longer be
5283 * known to the window manager; for all windows, unmaps them, so
5284 * they won't be displayed. Normally done automatically as
5285 * part of gtk_widget_hide().
5288 gdk_window_hide (GdkWindow *window)
5290 GdkWindowObject *private;
5291 gboolean was_mapped;
5293 g_return_if_fail (GDK_IS_WINDOW (window));
5295 private = (GdkWindowObject *) window;
5296 if (private->destroyed)
5299 was_mapped = GDK_WINDOW_IS_MAPPED (private);
5301 if (gdk_window_has_impl (private))
5302 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->hide (window);
5303 else if (was_mapped)
5305 GdkDisplay *display;
5307 /* May need to break grabs on children */
5308 display = gdk_drawable_get_display (window);
5310 if (display->pointer_grab.window != NULL)
5312 if (is_parent_of (window, display->pointer_grab.window))
5314 /* Call this ourselves, even though gdk_display_pointer_ungrab
5315 does so too, since we want to pass implicit == TRUE so the
5316 broken grab event is generated */
5317 _gdk_display_unset_has_pointer_grab (display,
5321 gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
5325 private->state = GDK_WINDOW_STATE_WITHDRAWN;
5327 /* Invalidate the rect */
5328 gdk_window_invalidate_in_parent (private);
5333 if (private->event_mask & GDK_STRUCTURE_MASK)
5334 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
5336 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
5337 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
5339 _gdk_syntesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
5342 recompute_visible_regions (private, TRUE, FALSE);
5346 * gdk_window_withdraw:
5347 * @window: a toplevel #GdkWindow
5349 * Withdraws a window (unmaps it and asks the window manager to forget about it).
5350 * This function is not really useful as gdk_window_hide() automatically
5351 * withdraws toplevel windows before hiding them.
5354 gdk_window_withdraw (GdkWindow *window)
5356 GdkWindowObject *private;
5357 gboolean was_mapped;
5359 g_return_if_fail (GDK_IS_WINDOW (window));
5361 private = (GdkWindowObject *) window;
5362 if (private->destroyed)
5365 was_mapped = GDK_WINDOW_IS_MAPPED (private);
5367 if (gdk_window_has_impl (private))
5369 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->withdraw (window);
5373 if (private->event_mask & GDK_STRUCTURE_MASK)
5374 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
5376 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
5377 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
5379 _gdk_syntesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
5382 recompute_visible_regions (private, TRUE, FALSE);
5387 * gdk_window_set_events:
5388 * @window: a #GdkWindow
5389 * @event_mask: event mask for @window
5391 * The event mask for a window determines which events will be reported
5392 * for that window. For example, an event mask including #GDK_BUTTON_PRESS_MASK
5393 * means the window should report button press events. The event mask
5394 * is the bitwise OR of values from the #GdkEventMask enumeration.
5397 gdk_window_set_events (GdkWindow *window,
5398 GdkEventMask event_mask)
5400 GdkWindowObject *private;
5402 g_return_if_fail (GDK_IS_WINDOW (window));
5404 private = (GdkWindowObject *) window;
5405 if (private->destroyed)
5408 private->event_mask = event_mask;
5412 * gdk_window_get_events:
5413 * @window: a #GdkWindow
5415 * Gets the event mask for @window. See gdk_window_set_events().
5417 * Return value: event mask for @window
5420 gdk_window_get_events (GdkWindow *window)
5422 GdkWindowObject *private;
5424 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
5426 private = (GdkWindowObject *) window;
5427 if (private->destroyed)
5430 return private->event_mask;
5434 move_native_children (GdkWindowObject *private)
5437 GdkWindowObject *child;
5439 for (l = private->children; l; l = l->next)
5443 if (child->impl != private->impl)
5444 GDK_WINDOW_IMPL_GET_IFACE (child->impl)->move_resize ((GdkWindow *)child, TRUE, child->x, child->y, child->width, child->height);
5446 move_native_children (child);
5451 gdk_window_move_resize_internal (GdkWindow *window,
5458 GdkWindowObject *private;
5459 GdkRegion *old_region, *new_region, *copy_area;
5460 GdkWindowObject *impl_window;
5462 int old_x, old_y, old_abs_x, old_abs_y;
5464 gboolean do_move_native_children;
5466 g_return_if_fail (GDK_IS_WINDOW (window));
5468 private = (GdkWindowObject *) window;
5469 if (private->destroyed)
5472 do_move_native_children = FALSE;
5476 impl_window = gdk_window_get_impl_window (private);
5481 if (gdk_window_has_impl (private))
5483 if (GDK_WINDOW_IS_MAPPED (window))
5485 expose = !private->input_only;
5486 old_region = gdk_region_copy (private->clip_region);
5487 /* Adjust region to parent window coords */
5488 gdk_region_offset (old_region, private->x, private->y);
5491 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, with_move, x, y, width, height);
5495 if (GDK_WINDOW_IS_MAPPED (window))
5497 expose = !private->input_only;
5498 old_region = gdk_region_copy (private->clip_region);
5499 /* Adjust region to parent window coords */
5500 gdk_region_offset (old_region, private->x, private->y);
5508 if (!(width < 0 && height < 0))
5512 private->width = width;
5515 private->height = height;
5518 do_move_native_children = TRUE;
5521 dx = private->x - old_x;
5522 dy = private->y - old_y;
5524 old_abs_x = private->abs_x;
5525 old_abs_y = private->abs_y;
5527 recompute_visible_regions (private, TRUE, FALSE);
5529 if (do_move_native_children &&
5530 (old_abs_x != private->abs_x ||
5531 old_abs_y != private->abs_y))
5532 move_native_children (private);
5536 new_region = gdk_region_copy (private->clip_region);
5537 /* Adjust region to parent window coords */
5538 gdk_region_offset (new_region, private->x, private->y);
5541 * Part of the data at the new location can be copied from the
5542 * old location, this area is the intersection of the old region
5543 * moved as the copy will move it and then intersected with
5547 * Everything in the old and new regions that is not copied must be
5548 * invalidated (including children) as this is newly exposed
5550 copy_area = gdk_region_copy (new_region);
5552 gdk_region_union (new_region, old_region);
5554 gdk_region_offset (old_region, dx, dy);
5555 gdk_region_intersect (copy_area, old_region);
5557 gdk_region_subtract (new_region, copy_area);
5559 /* Convert old region to impl coords */
5560 gdk_region_offset (old_region, -dx + private->abs_x - private->x, -dy + private->abs_y - private->y);
5562 /* The old_region area is moved and we queue translations for all expose events
5563 to it that will be sent before the copy operation */
5564 /* TODO: Make queue_translation a vtable call instead of hardcoding this crap */
5565 if (!gdk_window_is_offscreen (impl_window))
5566 _gdk_windowing_window_queue_translation ((GdkWindow *)impl_window, old_region, dx, dy);
5568 /* convert from parent coords to impl */
5569 gdk_region_offset (copy_area, private->abs_x - private->x, private->abs_y - private->y);
5571 move_region_on_impl (private, copy_area, dx, dy); /* Takes ownership of copy_area */
5573 /* Invalidate affected part in the parent window
5574 * (no higher window should be affected)
5575 * We also invalidate any children in that area, which could include
5576 * this window if it still overlaps that area.
5578 gdk_window_invalidate_region (GDK_WINDOW (private->parent), new_region, TRUE);
5580 gdk_region_destroy (old_region);
5581 gdk_region_destroy (new_region);
5584 _gdk_syntesize_crossing_events_for_geometry_change (window);
5591 * @window: a #GdkWindow
5592 * @x: X coordinate relative to window's parent
5593 * @y: Y coordinate relative to window's parent
5595 * Repositions a window relative to its parent window.
5596 * For toplevel windows, window managers may ignore or modify the move;
5597 * you should probably use gtk_window_move() on a #GtkWindow widget
5598 * anyway, instead of using GDK functions. For child windows,
5599 * the move will reliably succeed.
5601 * If you're also planning to resize the window, use gdk_window_move_resize()
5602 * to both move and resize simultaneously, for a nicer visual effect.
5605 gdk_window_move (GdkWindow *window,
5609 gdk_window_move_resize_internal (window, TRUE, x, y, -1, -1);
5613 * gdk_window_resize:
5614 * @window: a #GdkWindow
5615 * @width: new width of the window
5616 * @height: new height of the window
5618 * Resizes @window; for toplevel windows, asks the window manager to resize
5619 * the window. The window manager may not allow the resize. When using GTK+,
5620 * use gtk_window_resize() instead of this low-level GDK function.
5622 * Windows may not be resized below 1x1.
5624 * If you're also planning to move the window, use gdk_window_move_resize()
5625 * to both move and resize simultaneously, for a nicer visual effect.
5628 gdk_window_resize (GdkWindow *window,
5632 gdk_window_move_resize_internal (window, FALSE, 0, 0, width, height);
5637 * gdk_window_move_resize:
5638 * @window: a #GdkWindow
5639 * @x: new X position relative to window's parent
5640 * @y: new Y position relative to window's parent
5642 * @height: new height
5644 * Equivalent to calling gdk_window_move() and gdk_window_resize(),
5645 * except that both operations are performed at once, avoiding strange
5646 * visual effects. (i.e. the user may be able to see the window first
5647 * move, then resize, if you don't use gdk_window_move_resize().)
5650 gdk_window_move_resize (GdkWindow *window,
5656 gdk_window_move_resize_internal (window, TRUE, x, y, width, height);
5661 * gdk_window_scroll:
5662 * @window: a #GdkWindow
5663 * @dx: Amount to scroll in the X direction
5664 * @dy: Amount to scroll in the Y direction
5666 * Scroll the contents of @window, both pixels and children, by the
5667 * given amount. @window itself does not move. Portions of the window
5668 * that the scroll operation brings in from offscreen areas are
5669 * invalidated. The invalidated region may be bigger than what would
5670 * strictly be necessary.
5672 * For X11, a minimum area will be invalidated if the window has no
5673 * subwindows, or if the edges of the window's parent do not extend
5674 * beyond the edges of the window. In other cases, a multi-step process
5675 * is used to scroll the window which may produce temporary visual
5676 * artifacts and unnecessary invalidations.
5679 gdk_window_scroll (GdkWindow *window,
5683 GdkWindowObject *private = (GdkWindowObject *) window;
5684 GdkWindowObject *impl_window;
5685 GdkRegion *source_area, *copy_area, *noncopy_area;
5688 g_return_if_fail (GDK_IS_WINDOW (window));
5690 if (dx == 0 && dy == 0)
5693 if (private->destroyed)
5696 /* First move all child windows, without causing invalidation */
5698 tmp_list = private->children;
5701 GdkWindow *child = GDK_WINDOW (tmp_list->data);
5702 GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
5704 if (child_obj->impl == private->impl)
5706 /* Just update the positions, the bits will move with the copy */
5712 /* Native window, need to move it */
5713 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, TRUE, child_obj->x + dx, child_obj->y + dy, -1, -1);
5716 tmp_list = tmp_list->next;
5719 recompute_visible_regions (private, FALSE, TRUE);
5721 /* Then copy the actual bits of the window w/ child windows */
5723 impl_window = gdk_window_get_impl_window (private);
5725 /* Calculate the area that can be gotten by copying the old area */
5726 copy_area = gdk_region_copy (private->clip_region);
5727 gdk_region_offset (copy_area, dx, dy);
5728 gdk_region_intersect (copy_area, private->clip_region);
5730 /* And the rest need to be invalidated */
5731 noncopy_area = gdk_region_copy (private->clip_region);
5732 gdk_region_subtract (noncopy_area, copy_area);
5734 /* Get window clip and convert to real window coords, this
5735 area is moved and we queue translations for all expose events
5736 to it that will be sent before the copy operation */
5737 /* TODO: Make queue_translation a vtable call instead of hardcoding this crap */
5738 if (!gdk_window_is_offscreen (impl_window))
5740 source_area = gdk_region_copy (private->clip_region);
5741 /* convert from window coords to real parent */
5742 gdk_region_offset (source_area, private->abs_x, private->abs_y);
5743 _gdk_windowing_window_queue_translation ((GdkWindow *)impl_window, source_area, dx, dy);
5744 gdk_region_destroy (source_area);
5747 /* convert from window coords to impl */
5748 gdk_region_offset (copy_area, private->abs_x, private->abs_y);
5750 move_region_on_impl (private, copy_area, dx, dy); /* Takes ownership of copy_area */
5752 /* Invalidate not copied regions */
5753 gdk_window_invalidate_region (window, noncopy_area, TRUE);
5755 gdk_region_destroy (noncopy_area);
5757 _gdk_syntesize_crossing_events_for_geometry_change (window);
5761 * gdk_window_move_region:
5762 * @window: a #GdkWindow
5763 * @region: The #GdkRegion to move
5764 * @dx: Amount to move in the X direction
5765 * @dy: Amount to move in the Y direction
5767 * Move the part of @window indicated by @region by @dy pixels in the Y
5768 * direction and @dx pixels in the X direction. The portions of @region
5769 * that not covered by the new position of @region are invalidated.
5771 * Child windows are not moved.
5776 gdk_window_move_region (GdkWindow *window,
5777 const GdkRegion *region,
5781 GdkWindowObject *private = (GdkWindowObject *) window;
5782 GdkWindowObject *impl_window;
5783 GdkRegion *source_area;
5784 GdkRegion *nocopy_area;
5785 GdkRegion *copy_area;
5787 g_return_if_fail (GDK_IS_WINDOW (window));
5788 g_return_if_fail (region != NULL);
5790 if (dx == 0 && dy == 0)
5793 if (private->destroyed)
5796 impl_window = gdk_window_get_impl_window (private);
5798 /* compute source regions */
5799 source_area = gdk_region_copy (region);
5800 gdk_region_intersect (source_area, private->clip_region_with_children);
5802 /* compute destination regions */
5803 copy_area = gdk_region_copy (source_area);
5804 gdk_region_offset (copy_area, dx, dy);
5805 gdk_region_intersect (copy_area, private->clip_region_with_children);
5807 /* invalidate parts of the region not covered by the copy */
5808 nocopy_area = gdk_region_copy (region);
5809 gdk_region_offset (nocopy_area, dx, dy);
5810 gdk_region_subtract (nocopy_area, copy_area);
5811 gdk_window_invalidate_region (window, nocopy_area, FALSE);
5812 gdk_region_destroy (nocopy_area);
5814 /* TODO: Make queue_translation a vtable call instead of hardcoding this crap */
5815 if (!gdk_window_is_offscreen (impl_window))
5817 gdk_region_offset (source_area, private->abs_x, private->abs_y);
5818 _gdk_windowing_window_queue_translation ((GdkWindow *)impl_window, source_area, dx, dy);
5821 /* convert from window coords to impl */
5822 gdk_region_offset (copy_area, private->abs_x, private->abs_y);
5824 move_region_on_impl (private, copy_area, dx, dy); /* Takes ownership of copy_area */
5826 gdk_region_destroy (source_area);
5830 * gdk_window_set_background:
5831 * @window: a #GdkWindow
5832 * @color: an allocated #GdkColor
5834 * Sets the background color of @window. (However, when using GTK+,
5835 * set the background of a widget with gtk_widget_modify_bg() - if
5836 * you're an application - or gtk_style_set_background() - if you're
5837 * implementing a custom widget.)
5839 * The @color must be allocated; gdk_rgb_find_color() is the best way
5840 * to allocate a color.
5842 * See also gdk_window_set_back_pixmap().
5845 gdk_window_set_background (GdkWindow *window,
5846 const GdkColor *color)
5848 GdkWindowObject *private;
5849 GdkColormap *colormap = gdk_drawable_get_colormap (window);
5851 g_return_if_fail (GDK_IS_WINDOW (window));
5853 private = (GdkWindowObject *) window;
5855 private->bg_color = *color;
5856 gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
5858 if (private->bg_pixmap &&
5859 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
5860 private->bg_pixmap != GDK_NO_BG)
5861 g_object_unref (private->bg_pixmap);
5863 private->bg_pixmap = NULL;
5865 if (!GDK_WINDOW_DESTROYED (window) && gdk_window_has_impl (private))
5866 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, &private->bg_color);
5870 * gdk_window_set_back_pixmap:
5871 * @window: a #GdkWindow
5872 * @pixmap: a #GdkPixmap, or %NULL
5873 * @parent_relative: whether the tiling origin is at the origin of
5876 * Sets the background pixmap of @window. May also be used to set a
5877 * background of "None" on @window, by setting a background pixmap
5880 * A background pixmap will be tiled, positioning the first tile at
5881 * the origin of @window, or if @parent_relative is %TRUE, the tiling
5882 * will be done based on the origin of the parent window (useful to
5883 * align tiles in a parent with tiles in a child).
5885 * A background pixmap of %NULL means that the window will have no
5886 * background. A window with no background will never have its
5887 * background filled by the windowing system, instead the window will
5888 * contain whatever pixels were already in the corresponding area of
5891 * The windowing system will normally fill a window with its background
5892 * when the window is obscured then exposed, and when you call
5893 * gdk_window_clear().
5896 gdk_window_set_back_pixmap (GdkWindow *window,
5898 gboolean parent_relative)
5900 GdkWindowObject *private;
5902 g_return_if_fail (GDK_IS_WINDOW (window));
5903 g_return_if_fail (pixmap == NULL || !parent_relative);
5904 g_return_if_fail (pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap));
5906 private = (GdkWindowObject *) window;
5908 if (pixmap && !gdk_drawable_get_colormap (pixmap))
5910 g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
5914 if (private->bg_pixmap &&
5915 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
5916 private->bg_pixmap != GDK_NO_BG)
5917 g_object_unref (private->bg_pixmap);
5919 if (parent_relative)
5920 private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
5922 private->bg_pixmap = g_object_ref (pixmap);
5924 private->bg_pixmap = GDK_NO_BG;
5926 if (!GDK_WINDOW_DESTROYED (window) && gdk_window_has_impl (private))
5927 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, private->bg_pixmap);
5931 update_cursor (GdkDisplay *display)
5933 GdkWindowObject *pointer_window, *cursor_window;
5935 pointer_window = (GdkWindowObject *)display->pointer_info.window_under_pointer;
5937 cursor_window = pointer_window;
5938 while (cursor_window->cursor == NULL &&
5939 cursor_window->parent != NULL &&
5940 cursor_window->parent->window_type != GDK_WINDOW_ROOT)
5941 cursor_window = cursor_window->parent;
5943 if (display->pointer_grab.window != NULL &&
5944 !is_parent_of (display->pointer_grab.window, (GdkWindow *)cursor_window))
5945 cursor_window = (GdkWindowObject *)display->pointer_grab.window;
5947 GDK_WINDOW_IMPL_GET_IFACE (pointer_window->impl)->set_cursor (pointer_window,
5948 cursor_window->cursor);
5952 * gdk_window_set_cursor:
5953 * @window: a #GdkWindow
5956 * Sets the mouse pointer for a #GdkWindow. Use gdk_cursor_new_for_display()
5957 * or gdk_cursor_new_from_pixmap() to create the cursor. To make the cursor
5958 * invisible, use %GDK_BLANK_CURSOR. Passing %NULL for the @cursor argument
5959 * to gdk_window_set_cursor() means that @window will use the cursor of its
5960 * parent window. Most windows should use this default.
5963 gdk_window_set_cursor (GdkWindow *window,
5966 GdkWindowObject *private;
5967 GdkDisplay *display;
5969 g_return_if_fail (GDK_IS_WINDOW (window));
5971 private = (GdkWindowObject *) window;
5972 display = gdk_drawable_get_display (window);
5974 if (private->cursor)
5976 gdk_cursor_unref (private->cursor);
5977 private->cursor = NULL;
5980 if (!GDK_WINDOW_DESTROYED (window))
5983 private->cursor = gdk_cursor_ref (cursor);
5985 if (is_parent_of (window, display->pointer_info.window_under_pointer))
5986 update_cursor (display);
5991 * gdk_window_get_geometry:
5992 * @window: a #GdkWindow
5993 * @x: return location for X coordinate of window (relative to its parent)
5994 * @y: return location for Y coordinate of window (relative to its parent)
5995 * @width: return location for width of window
5996 * @height: return location for height of window
5997 * @depth: return location for bit depth of window
5999 * Any of the return location arguments to this function may be %NULL,
6000 * if you aren't interested in getting the value of that field.
6002 * The X and Y coordinates returned are relative to the parent window
6003 * of @window, which for toplevels usually means relative to the
6004 * window decorations (titlebar, etc.) rather than relative to the
6005 * root window (screen-size background window).
6007 * On the X11 platform, the geometry is obtained from the X server,
6008 * so reflects the latest position of @window; this may be out-of-sync
6009 * with the position of @window delivered in the most-recently-processed
6010 * #GdkEventConfigure. gdk_window_get_position() in contrast gets the
6011 * position from the most recent configure event.
6014 * If @window is not a toplevel, it is <emphasis>much</emphasis> better
6015 * to call gdk_window_get_position() and gdk_drawable_get_size() instead,
6016 * because it avoids the roundtrip to the X server and because
6017 * gdk_drawable_get_size() supports the full 32-bit coordinate space,
6018 * whereas gdk_window_get_geometry() is restricted to the 16-bit
6019 * coordinates of X11.
6023 gdk_window_get_geometry (GdkWindow *window,
6030 GdkWindowObject *private;
6034 GDK_NOTE (MULTIHEAD,
6035 g_message ("gdk_window_get_geometry(): Window needs "
6036 "to be non-NULL to be multi head safe"));
6037 window = gdk_screen_get_root_window ((gdk_screen_get_default ()));
6040 g_return_if_fail (GDK_IS_WINDOW (window));
6042 private = (GdkWindowObject *) window;
6044 if (!GDK_WINDOW_DESTROYED (window))
6046 if (gdk_window_has_impl (private))
6047 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_geometry (window, x, y,
6057 *width = private->width;
6059 *height = private->height;
6061 *depth = private->depth;
6067 * gdk_window_get_origin:
6068 * @window: a #GdkWindow
6069 * @x: return location for X coordinate
6070 * @y: return location for Y coordinate
6072 * Obtains the position of a window in root window coordinates.
6073 * (Compare with gdk_window_get_position() and
6074 * gdk_window_get_geometry() which return the position of a window
6075 * relative to its parent window.)
6077 * Return value: not meaningful, ignore
6080 gdk_window_get_origin (GdkWindow *window,
6084 GdkWindowObject *private;
6086 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
6088 private = (GdkWindowObject *) window;
6090 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_origin (window, x, y);
6093 *x += private->abs_x;
6095 *y += private->abs_y;
6102 * gdk_window_get_deskrelative_origin:
6103 * @window: a toplevel #GdkWindow
6104 * @x: return location for X coordinate
6105 * @y: return location for Y coordinate
6107 * This gets the origin of a #GdkWindow relative to
6108 * an Enlightenment-window-manager desktop. As long as you don't
6109 * assume that the user's desktop/workspace covers the entire
6110 * root window (i.e. you don't assume that the desktop begins
6111 * at root window coordinate 0,0) this function is not necessary.
6112 * It's deprecated for that reason.
6114 * Return value: not meaningful
6117 gdk_window_get_deskrelative_origin (GdkWindow *window,
6121 GdkWindowObject *private;
6122 gboolean return_val = FALSE;
6126 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
6128 private = (GdkWindowObject *) window;
6130 if (!GDK_WINDOW_DESTROYED (window))
6132 return_val = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_deskrelative_origin (window, &tx, &ty);
6135 *x = tx + private->abs_x;
6137 *y = ty + private->abs_y;
6144 * gdk_window_shape_combine_mask:
6145 * @window: a #GdkWindow
6147 * @x: X position of shape mask with respect to @window
6148 * @y: Y position of shape mask with respect to @window
6150 * Applies a shape mask to @window. Pixels in @window corresponding to
6151 * set bits in the @mask will be visible; pixels in @window
6152 * corresponding to unset bits in the @mask will be transparent. This
6153 * gives a non-rectangular window.
6155 * If @mask is %NULL, the shape mask will be unset, and the @x/@y
6156 * parameters are not used.
6158 * On the X11 platform, this uses an X server extension which is
6159 * widely available on most common platforms, but not available on
6160 * very old X servers, and occasionally the implementation will be
6161 * buggy. On servers without the shape extension, this function
6164 * This function works on both toplevel and child windows.
6167 gdk_window_shape_combine_mask (GdkWindow *window,
6172 GdkWindowObject *private;
6174 g_return_if_fail (GDK_IS_WINDOW (window));
6176 private = (GdkWindowObject *) window;
6178 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_mask (window, mask, x, y);
6182 * gdk_window_shape_combine_region:
6183 * @window: a #GdkWindow
6184 * @shape_region: region of window to be non-transparent
6185 * @offset_x: X position of @shape_region in @window coordinates
6186 * @offset_y: Y position of @shape_region in @window coordinates
6188 * Makes pixels in @window outside @shape_region be transparent,
6189 * so that the window may be nonrectangular. See also
6190 * gdk_window_shape_combine_mask() to use a bitmap as the mask.
6192 * If @shape_region is %NULL, the shape will be unset, so the whole
6193 * window will be opaque again. @offset_x and @offset_y are ignored
6194 * if @shape_region is %NULL.
6196 * On the X11 platform, this uses an X server extension which is
6197 * widely available on most common platforms, but not available on
6198 * very old X servers, and occasionally the implementation will be
6199 * buggy. On servers without the shape extension, this function
6202 * This function works on both toplevel and child windows.
6205 gdk_window_shape_combine_region (GdkWindow *window,
6206 const GdkRegion *shape_region,
6210 GdkWindowObject *private;
6212 g_return_if_fail (GDK_IS_WINDOW (window));
6214 private = (GdkWindowObject *) window;
6216 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region (window, shape_region, offset_x, offset_y);
6220 * gdk_window_set_child_shapes:
6221 * @window: a #GdkWindow
6223 * Sets the shape mask of @window to the union of shape masks
6224 * for all children of @window, ignoring the shape mask of @window
6225 * itself. Contrast with gdk_window_merge_child_shapes() which includes
6226 * the shape mask of @window in the masks to be merged.
6229 gdk_window_set_child_shapes (GdkWindow *window)
6231 GdkWindowObject *private;
6233 g_return_if_fail (GDK_IS_WINDOW (window));
6235 private = (GdkWindowObject *) window;
6237 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_child_shapes (window);
6241 * gdk_window_merge_child_shapes:
6242 * @window: a #GdkWindow
6244 * Merges the shape masks for any child windows into the
6245 * shape mask for @window. i.e. the union of all masks
6246 * for @window and its children will become the new mask
6247 * for @window. See gdk_window_shape_combine_mask().
6249 * This function is distinct from gdk_window_set_child_shapes()
6250 * because it includes @window's shape mask in the set of shapes to
6254 gdk_window_merge_child_shapes (GdkWindow *window)
6256 GdkWindowObject *private;
6258 g_return_if_fail (GDK_IS_WINDOW (window));
6260 private = (GdkWindowObject *) window;
6262 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->merge_child_shapes (window);
6267 * gdk_window_set_static_gravities:
6268 * @window: a #GdkWindow
6269 * @use_static: %TRUE to turn on static gravity
6271 * Set the bit gravity of the given window to static, and flag it so
6272 * all children get static subwindow gravity. This is used if you are
6273 * implementing scary features that involve deep knowledge of the
6274 * windowing system. Don't worry about it unless you have to.
6276 * Return value: %TRUE if the server supports static gravity
6279 gdk_window_set_static_gravities (GdkWindow *window,
6280 gboolean use_static)
6282 GdkWindowObject *private;
6284 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
6286 private = (GdkWindowObject *) window;
6288 if (gdk_window_has_impl (private))
6289 return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_static_gravities (window, use_static);
6295 * gdk_window_set_composited:
6296 * @window: a #GdkWindow
6297 * @composited: %TRUE to set the window as composited
6299 * Sets a #GdkWindow as composited, or unsets it. Composited
6300 * windows do not automatically have their contents drawn to
6301 * the screen. Drawing is redirected to an offscreen buffer
6302 * and an expose event is emitted on the parent of the composited
6303 * window. It is the responsibility of the parent's expose handler
6304 * to manually merge the off-screen content onto the screen in
6305 * whatever way it sees fit. See <xref linkend="composited-window-example"/>
6308 * It only makes sense for child windows to be composited; see
6309 * gdk_window_set_opacity() if you need translucent toplevel
6312 * An additional effect of this call is that the area of this
6313 * window is no longer clipped from regions marked for
6314 * invalidation on its parent. Draws done on the parent
6315 * window are also no longer clipped by the child.
6317 * This call is only supported on some systems (currently,
6318 * only X11 with new enough Xcomposite and Xdamage extensions).
6319 * You must call gdk_display_supports_composite() to check if
6320 * setting a window as composited is supported before
6321 * attempting to do so.
6326 gdk_window_set_composited (GdkWindow *window,
6327 gboolean composited)
6329 GdkWindowObject *private = (GdkWindowObject *)window;
6330 GdkDisplay *display;
6332 g_return_if_fail (GDK_IS_WINDOW (window));
6334 composited = composited != FALSE;
6336 if (private->composited == composited)
6340 gdk_window_set_has_native (window, TRUE);
6342 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
6344 if (!gdk_display_supports_composite (display) && composited)
6346 g_warning ("gdk_window_set_composited called but "
6347 "compositing is not supported");
6351 _gdk_windowing_window_set_composited (window, composited);
6353 recompute_visible_regions (private, TRUE, FALSE);
6355 private->composited = composited;
6360 remove_redirect_from_children (GdkWindowObject *private,
6361 GdkWindowRedirect *redirect)
6364 GdkWindowObject *child;
6366 for (l = private->children; l != NULL; l = l->next)
6370 /* Don't redirect this child if it already has another redirect */
6371 if (child->redirect == redirect)
6373 child->redirect = NULL;
6374 remove_redirect_from_children (child, redirect);
6380 * gdk_window_remove_redirection:
6381 * @window: a #GdkWindow
6383 * Removes any active redirection started by
6384 * gdk_window_redirect_to_drawable().
6389 gdk_window_remove_redirection (GdkWindow *window)
6391 GdkWindowObject *private;
6393 g_return_if_fail (GDK_IS_WINDOW (window));
6395 private = (GdkWindowObject *) window;
6397 if (private->redirect &&
6398 private->redirect->redirected == private)
6400 remove_redirect_from_children (private, private->redirect);
6401 gdk_window_redirect_free (private->redirect);
6402 private->redirect = NULL;
6407 apply_redirect_to_children (GdkWindowObject *private,
6408 GdkWindowRedirect *redirect)
6411 GdkWindowObject *child;
6413 for (l = private->children; l != NULL; l = l->next)
6417 /* Don't redirect this child if it already has another redirect */
6418 if (!child->redirect)
6420 child->redirect = redirect;
6421 apply_redirect_to_children (child, redirect);
6427 * gdk_window_redirect_to_drawable:
6428 * @window: a #GdkWindow
6429 * @drawable: a #GdkDrawable
6430 * @src_x: x position in @window
6431 * @src_y: y position in @window
6432 * @dest_x: x position in @drawable
6433 * @dest_y: y position in @drawable
6434 * @width: width of redirection
6435 * @height: height of redirection
6437 * Redirects drawing into @window so that drawing to the
6438 * window in the rectangle specified by @src_x, @src_y,
6439 * @width and @height is also drawn into @drawable at
6442 * Only drawing between gdk_window_begin_paint_region() or
6443 * gdk_window_begin_paint_rect() and gdk_window_end_paint() is
6446 * Redirection is active until gdk_window_remove_redirection()
6452 gdk_window_redirect_to_drawable (GdkWindow *window,
6453 GdkDrawable *drawable,
6461 GdkWindowObject *private;
6463 g_return_if_fail (GDK_IS_WINDOW (window));
6464 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
6465 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
6467 private = (GdkWindowObject *) window;
6469 if (private->redirect)
6470 gdk_window_remove_redirection (window);
6472 if (width == -1 || height == -1)
6475 gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
6482 private->redirect = g_new0 (GdkWindowRedirect, 1);
6483 private->redirect->redirected = private;
6484 private->redirect->pixmap = g_object_ref (drawable);
6485 private->redirect->src_x = src_x;
6486 private->redirect->src_y = src_y;
6487 private->redirect->dest_x = dest_x;
6488 private->redirect->dest_y = dest_y;
6489 private->redirect->width = width;
6490 private->redirect->height = height;
6492 apply_redirect_to_children (private, private->redirect);
6496 window_get_size_rectangle (GdkWindow *window,
6499 GdkWindowObject *private = (GdkWindowObject *) window;
6501 rect->x = rect->y = 0;
6502 rect->width = private->width;
6503 rect->height = private->height;
6506 /* Calculates the real clipping region for a window, in window coordinates,
6507 * taking into account other windows, gc clip region and gc clip mask.
6510 _gdk_window_calculate_full_clip_region (GdkWindow *window,
6511 GdkWindow *base_window,
6512 gboolean do_children,
6513 gint *base_x_offset,
6514 gint *base_y_offset)
6516 GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
6517 GdkRectangle visible_rect;
6518 GdkRegion *real_clip_region, *tmpreg;
6519 gint x_offset, y_offset;
6520 GdkWindowObject *parentwin, *lastwin;
6527 if (!GDK_WINDOW_IS_MAPPED (window) || private->input_only)
6528 return gdk_region_new ();
6530 window_get_size_rectangle (window, &visible_rect);
6532 /* real_clip_region is in window coordinates */
6533 real_clip_region = gdk_region_rectangle (&visible_rect);
6535 x_offset = y_offset = 0;
6539 parentwin = lastwin;
6541 parentwin = lastwin->parent;
6543 /* Remove the areas of all overlapping windows above parentwin in the hiearachy */
6544 for (; parentwin != NULL &&
6545 (parentwin == private || lastwin != (GdkWindowObject*) base_window);
6546 lastwin = parentwin, parentwin = lastwin->parent)
6549 GdkRectangle real_clip_rect;
6550 gboolean is_offscreen;
6552 if (parentwin != private)
6554 x_offset += GDK_WINDOW_OBJECT (lastwin)->x;
6555 y_offset += GDK_WINDOW_OBJECT (lastwin)->y;
6558 is_offscreen = gdk_window_is_offscreen (parentwin);
6560 /* children is ordered in reverse stack order */
6561 for (cur = parentwin->children;
6562 cur && cur->data != lastwin;
6565 GdkWindow *child = cur->data;
6566 GdkWindowObject *child_private = (GdkWindowObject *)child;
6568 if (!GDK_WINDOW_IS_MAPPED (child) || child_private->input_only)
6571 /* Ignore offscreen children, as they don't draw in their parent and
6572 * don't take part in the clipping */
6573 if (gdk_window_is_offscreen (child_private))
6576 window_get_size_rectangle (child, &visible_rect);
6578 /* Convert rect to "window" coords */
6579 visible_rect.x += child_private->x - x_offset;
6580 visible_rect.y += child_private->y - y_offset;
6582 /* This shortcut is really necessary for performance when there are a lot of windows */
6583 gdk_region_get_clipbox (real_clip_region, &real_clip_rect);
6584 if (visible_rect.x >= real_clip_rect.x + real_clip_rect.width ||
6585 visible_rect.x + visible_rect.width <= real_clip_rect.x ||
6586 visible_rect.y >= real_clip_rect.y + real_clip_rect.height ||
6587 visible_rect.y + visible_rect.height <= real_clip_rect.y)
6590 tmpreg = gdk_region_rectangle (&visible_rect);
6591 gdk_region_subtract (real_clip_region, tmpreg);
6592 gdk_region_destroy (tmpreg);
6595 /* Clip to the parent */
6596 window_get_size_rectangle ((GdkWindow *)parentwin, &visible_rect);
6597 /* Convert rect to "window" coords */
6598 visible_rect.x += - x_offset;
6599 visible_rect.y += - y_offset;
6601 tmpreg = gdk_region_rectangle (&visible_rect);
6602 gdk_region_intersect (real_clip_region, tmpreg);
6603 gdk_region_destroy (tmpreg);
6607 *base_x_offset = x_offset;
6609 *base_y_offset = y_offset;
6611 return real_clip_region;
6615 _gdk_window_add_damage (GdkWindow *toplevel,
6616 GdkRegion *damaged_region)
6618 GdkDisplay *display;
6619 GdkEvent event = { 0, };
6620 event.expose.type = GDK_DAMAGE;
6621 event.expose.window = toplevel;
6622 event.expose.send_event = FALSE;
6623 event.expose.region = damaged_region;
6624 gdk_region_get_clipbox (event.expose.region, &event.expose.area);
6625 display = gdk_drawable_get_display (event.expose.window);
6626 _gdk_event_queue_append (display, gdk_event_copy (&event));
6630 gdk_window_redirect_free (GdkWindowRedirect *redirect)
6632 g_object_unref (redirect->pixmap);
6637 convert_coords_to_child (GdkWindowObject *child,
6639 double *child_x, double *child_y)
6641 *child_x = x - child->x;
6642 *child_y = y - child->y;
6644 if (child->offscreen_hooks)
6645 child->offscreen_hooks->from_parent ((GdkWindow *)child, x, y, child_x, child_y);
6649 point_in_window (GdkWindowObject *window,
6653 x >= 0 && x < window->width &&
6654 y >= 0 && y < window->height;
6658 convert_toplevel_coords_to_window (GdkWindow *window,
6664 GdkWindowObject *private;
6666 GList *children, *l;
6668 private = GDK_WINDOW_OBJECT (window);
6674 while (private->parent != NULL &&
6675 (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT))
6677 children = g_list_prepend (children, private);
6678 private = private->parent;
6681 for (l = children; l != NULL; l = l->next)
6682 convert_coords_to_child (l->data, x, y, &x, &y);
6684 g_list_free (children);
6691 _gdk_window_find_descendant_at (GdkWindow *toplevel,
6696 GdkWindowObject *private, *sub;
6697 double child_x, child_y;
6700 private = (GdkWindowObject *)toplevel;
6702 if (point_in_window (private, x, y))
6706 /* Children is ordered in reverse stack order, i.e. first is topmost */
6707 for (l = private->children; l != NULL; l = l->next)
6711 if (!GDK_WINDOW_IS_MAPPED (sub))
6714 convert_coords_to_child (sub,
6716 &child_x, &child_y);
6717 if (point_in_window (sub, child_x, child_y))
6730 /* Not in window at all */
6739 return (GdkWindow *)private;
6742 static const guint type_masks[] = {
6743 GDK_SUBSTRUCTURE_MASK, /* GDK_DELETE = 0 */
6744 GDK_STRUCTURE_MASK, /* GDK_DESTROY = 1 */
6745 GDK_EXPOSURE_MASK, /* GDK_EXPOSE = 2 */
6746 GDK_POINTER_MOTION_MASK, /* GDK_MOTION_NOTIFY = 3 */
6747 GDK_BUTTON_PRESS_MASK, /* GDK_BUTTON_PRESS = 4 */
6748 GDK_BUTTON_PRESS_MASK, /* GDK_2BUTTON_PRESS = 5 */
6749 GDK_BUTTON_PRESS_MASK, /* GDK_3BUTTON_PRESS = 6 */
6750 GDK_BUTTON_RELEASE_MASK, /* GDK_BUTTON_RELEASE = 7 */
6751 GDK_KEY_PRESS_MASK, /* GDK_KEY_PRESS = 8 */
6752 GDK_KEY_RELEASE_MASK, /* GDK_KEY_RELEASE = 9 */
6753 GDK_ENTER_NOTIFY_MASK, /* GDK_ENTER_NOTIFY = 10 */
6754 GDK_LEAVE_NOTIFY_MASK, /* GDK_LEAVE_NOTIFY = 11 */
6755 GDK_FOCUS_CHANGE_MASK, /* GDK_FOCUS_CHANGE = 12 */
6756 GDK_STRUCTURE_MASK, /* GDK_CONFIGURE = 13 */
6757 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_MAP = 14 */
6758 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_UNMAP = 15 */
6759 GDK_PROPERTY_CHANGE_MASK, /* GDK_PROPERTY_NOTIFY = 16 */
6760 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_CLEAR = 17 */
6761 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_REQUEST = 18 */
6762 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_NOTIFY = 19 */
6763 GDK_PROXIMITY_IN_MASK, /* GDK_PROXIMITY_IN = 20 */
6764 GDK_PROXIMITY_OUT_MASK, /* GDK_PROXIMITY_OUT = 21 */
6765 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_ENTER = 22 */
6766 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_LEAVE = 23 */
6767 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_MOTION = 24 */
6768 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_STATUS = 25 */
6769 GDK_ALL_EVENTS_MASK, /* GDK_DROP_START = 26 */
6770 GDK_ALL_EVENTS_MASK, /* GDK_DROP_FINISHED = 27 */
6771 GDK_ALL_EVENTS_MASK, /* GDK_CLIENT_EVENT = 28 */
6772 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_VISIBILITY_NOTIFY = 29 */
6773 GDK_EXPOSURE_MASK, /* GDK_NO_EXPOSE = 30 */
6774 GDK_SCROLL_MASK | GDK_BUTTON_PRESS_MASK,/* GDK_SCROLL= 31 */
6775 0, /* GDK_WINDOW_STATE = 32 */
6776 0, /* GDK_SETTING = 33 */
6777 0, /* GDK_OWNER_CHANGE = 34 */
6778 0, /* GDK_GRAB_BROKEN = 35 */
6779 0, /* GDK_DAMAGE = 36 */
6781 G_STATIC_ASSERT (G_N_ELEMENTS (type_masks) == GDK_EVENT_LAST);
6783 /* send motion events if the right buttons are down */
6785 update_evmask_for_button_motion (guint evmask,
6786 GdkModifierType mask)
6788 if (evmask & GDK_BUTTON_MOTION_MASK &&
6789 mask & (GDK_BUTTON1_MASK |
6794 evmask |= GDK_POINTER_MOTION_MASK;
6796 if ((evmask & GDK_BUTTON1_MOTION_MASK && mask & GDK_BUTTON1_MASK) ||
6797 (evmask & GDK_BUTTON2_MOTION_MASK && mask & GDK_BUTTON2_MASK) ||
6798 (evmask & GDK_BUTTON3_MOTION_MASK && mask & GDK_BUTTON3_MASK))
6799 evmask |= GDK_POINTER_MOTION_MASK;
6805 is_button_type (GdkEventType type)
6807 return type == GDK_BUTTON_PRESS ||
6808 type == GDK_2BUTTON_PRESS ||
6809 type == GDK_3BUTTON_PRESS ||
6810 type == GDK_BUTTON_RELEASE ||
6815 is_motion_type (GdkEventType type)
6817 return type == GDK_MOTION_NOTIFY ||
6818 type == GDK_ENTER_NOTIFY ||
6819 type == GDK_LEAVE_NOTIFY;
6822 static GdkWindowObject *
6823 find_common_ancestor (GdkWindowObject *win1,
6824 GdkWindowObject *win2)
6826 GdkWindowObject *tmp;
6827 GList *path1 = NULL, *path2 = NULL;
6828 GList *list1, *list2;
6831 while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
6833 path1 = g_list_prepend (path1, tmp);
6838 while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
6840 path2 = g_list_prepend (path2, tmp);
6847 while (list1 && list2 && (list1->data == list2->data))
6849 tmp = (GdkWindowObject *)list1->data;
6850 list1 = g_list_next (list1);
6851 list2 = g_list_next (list2);
6853 g_list_free (path1);
6854 g_list_free (path2);
6860 _gdk_make_event (GdkWindow *window,
6862 GdkEvent *event_in_queue,
6863 gboolean before_event)
6865 GdkEvent *event = gdk_event_new (type);
6867 GdkModifierType the_state;
6869 the_time = gdk_event_get_time (event_in_queue);
6870 gdk_event_get_state (event_in_queue, &the_state);
6872 event->any.window = g_object_ref (window);
6873 event->any.send_event = FALSE;
6877 case GDK_MOTION_NOTIFY:
6878 event->motion.time = the_time;
6879 event->motion.axes = NULL;
6880 event->motion.state = the_state;
6883 case GDK_BUTTON_PRESS:
6884 case GDK_2BUTTON_PRESS:
6885 case GDK_3BUTTON_PRESS:
6886 case GDK_BUTTON_RELEASE:
6887 event->button.time = the_time;
6888 event->button.axes = NULL;
6889 event->button.state = the_state;
6893 event->scroll.time = the_time;
6894 event->scroll.state = the_state;
6898 case GDK_KEY_RELEASE:
6899 event->key.time = the_time;
6900 event->key.state = the_state;
6903 case GDK_ENTER_NOTIFY:
6904 case GDK_LEAVE_NOTIFY:
6905 event->crossing.time = the_time;
6906 event->crossing.state = the_state;
6909 case GDK_PROPERTY_NOTIFY:
6910 event->property.time = the_time;
6911 event->property.state = the_state;
6914 case GDK_SELECTION_CLEAR:
6915 case GDK_SELECTION_REQUEST:
6916 case GDK_SELECTION_NOTIFY:
6917 event->selection.time = the_time;
6920 case GDK_PROXIMITY_IN:
6921 case GDK_PROXIMITY_OUT:
6922 event->proximity.time = the_time;
6925 case GDK_DRAG_ENTER:
6926 case GDK_DRAG_LEAVE:
6927 case GDK_DRAG_MOTION:
6928 case GDK_DRAG_STATUS:
6929 case GDK_DROP_START:
6930 case GDK_DROP_FINISHED:
6931 event->dnd.time = the_time;
6934 case GDK_FOCUS_CHANGE:
6938 case GDK_CLIENT_EVENT:
6939 case GDK_VISIBILITY_NOTIFY:
6951 _gdk_event_queue_insert_before (gdk_drawable_get_display (window), event_in_queue, event);
6953 _gdk_event_queue_insert_after (gdk_drawable_get_display (window), event_in_queue, event);
6956 _gdk_event_queue_append (gdk_drawable_get_display (window), event);
6962 send_crossing_event (GdkDisplay *display,
6963 GdkWindowObject *toplevel,
6964 GdkWindowObject *window,
6966 GdkCrossingMode mode,
6967 GdkNotifyType notify_type,
6968 GdkWindow *subwindow,
6971 GdkModifierType mask,
6973 GdkEvent *event_in_queue)
6978 if (display->pointer_grab.window != NULL &&
6979 !display->pointer_grab.owner_events &&
6980 (GdkWindow *)window != display->pointer_grab.window)
6983 if (type == GDK_LEAVE_NOTIFY)
6984 event_mask = GDK_LEAVE_NOTIFY_MASK;
6986 event_mask = GDK_ENTER_NOTIFY_MASK;
6988 if (window->event_mask & event_mask)
6990 event = _gdk_make_event ((GdkWindow *)window, type, event_in_queue, TRUE);
6991 event->crossing.time = time_;
6992 event->crossing.subwindow = subwindow;
6994 g_object_ref (subwindow);
6995 convert_toplevel_coords_to_window ((GdkWindow *)window,
6996 toplevel_x, toplevel_y,
6997 &event->crossing.x, &event->crossing.y);
6998 event->crossing.x_root = toplevel_x + toplevel->x;
6999 event->crossing.y_root = toplevel_y + toplevel->y;
7000 event->crossing.mode = mode;
7001 event->crossing.detail = notify_type;
7002 event->crossing.focus = FALSE;
7003 event->crossing.state = mask;
7008 /* The coordinates are in the toplevel window that src/dest are in.
7009 * src and dest are always (if != NULL) in the same toplevel, as
7010 * we get a leave-notify and set the window_under_pointer to null
7011 * before crossing to another toplevel.
7014 _gdk_syntesize_crossing_events (GdkDisplay *display,
7017 GdkCrossingMode mode,
7020 GdkModifierType mask,
7022 GdkEvent *event_in_queue)
7025 GdkWindowObject *win, *last, *next;
7027 gboolean non_linear;
7030 GdkWindowObject *toplevel;
7031 GdkNotifyType notify_type;
7033 /* TODO: Don't send events to toplevel, as we get those from the windowing system */
7035 a = (GdkWindowObject *)src;
7036 b = (GdkWindowObject *)dest;
7038 return; /* No crossings generated between src and dest */
7040 c = find_common_ancestor (a, b);
7042 non_linear = (c != a) && (c != b);
7044 if (a) /* There might not be a source (i.e. if no previous pointer_in_window) */
7046 toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)a);
7048 /* Traverse up from a to (excluding) c sending leave events */
7050 notify_type = GDK_NOTIFY_NONLINEAR;
7052 notify_type = GDK_NOTIFY_INFERIOR;
7054 notify_type = GDK_NOTIFY_ANCESTOR;
7055 send_crossing_event (display, toplevel,
7056 a, GDK_LEAVE_NOTIFY,
7060 toplevel_x, toplevel_y,
7067 notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
7069 notify_type = GDK_NOTIFY_VIRTUAL;
7073 while (win != c && GDK_WINDOW_TYPE (win) != GDK_WINDOW_ROOT)
7075 send_crossing_event (display, toplevel,
7076 win, GDK_LEAVE_NOTIFY,
7080 toplevel_x, toplevel_y,
7090 if (b) /* Might not be a dest, e.g. if we're moving out of the window */
7092 toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)b);
7094 /* Traverse down from c to b */
7099 while (win != c && GDK_WINDOW_TYPE (win) != GDK_WINDOW_ROOT)
7101 path = g_list_prepend (path, win);
7106 notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
7108 notify_type = GDK_NOTIFY_VIRTUAL;
7113 win = (GdkWindowObject *)list->data;
7114 list = g_list_next (list);
7116 next = (GdkWindowObject *)list->data;
7120 send_crossing_event (display, toplevel,
7121 win, GDK_ENTER_NOTIFY,
7125 toplevel_x, toplevel_y,
7134 notify_type = GDK_NOTIFY_NONLINEAR;
7136 notify_type = GDK_NOTIFY_ANCESTOR;
7138 notify_type = GDK_NOTIFY_INFERIOR;
7140 send_crossing_event (display, toplevel,
7141 b, GDK_ENTER_NOTIFY,
7145 toplevel_x, toplevel_y,
7152 get_toplevel (GdkWindow *w)
7154 GdkWindowObject *private = GDK_WINDOW_OBJECT (w);
7156 while (private->parent != NULL &&
7157 (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT))
7158 private = private->parent;
7160 return GDK_WINDOW (private);
7163 /* Returns the window inside the event window with the pointer in it
7164 * at the specified coordinates, or NULL if its not in any child of
7165 * the toplevel. It also takes into account !owner_events grabs.
7168 get_pointer_window (GdkDisplay *display,
7169 GdkWindow *event_window,
7173 GdkWindow *pointer_window;
7175 if (event_window == display->pointer_info.toplevel_under_pointer)
7177 _gdk_window_find_descendant_at (event_window,
7178 toplevel_x, toplevel_y,
7181 pointer_window = NULL;
7183 if (display->pointer_grab.window != NULL &&
7184 !display->pointer_grab.owner_events &&
7185 pointer_window != display->pointer_grab.window)
7186 pointer_window = NULL;
7188 return pointer_window;
7192 _gdk_display_set_window_under_pointer (GdkDisplay *display,
7195 GdkWindowObject *private;
7197 private = (GdkWindowObject *)window;
7199 if (display->pointer_info.window_under_pointer)
7200 g_object_unref (display->pointer_info.window_under_pointer);
7201 display->pointer_info.window_under_pointer = window;
7203 g_object_ref (window);
7206 update_cursor (display);
7210 _gdk_syntesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
7212 GdkDisplay *display;
7213 GdkWindow *changed_toplevel;
7214 GdkWindow *new_window_under_pointer;
7216 changed_toplevel = get_toplevel (changed_window);
7218 display = gdk_drawable_get_display (changed_window);
7219 if (changed_toplevel == display->pointer_info.toplevel_under_pointer)
7221 new_window_under_pointer =
7222 get_pointer_window (display, changed_toplevel,
7223 display->pointer_info.toplevel_x,
7224 display->pointer_info.toplevel_y);
7225 if (new_window_under_pointer !=
7226 display->pointer_info.window_under_pointer)
7228 _gdk_syntesize_crossing_events (display,
7229 display->pointer_info.window_under_pointer,
7230 new_window_under_pointer,
7231 GDK_CROSSING_NORMAL,
7232 display->pointer_info.toplevel_x,
7233 display->pointer_info.toplevel_y,
7234 display->pointer_info.state,
7237 _gdk_display_set_window_under_pointer (display, new_window_under_pointer);
7242 /* Don't use for crossing events */
7244 get_event_window (GdkDisplay *display,
7245 GdkWindow *pointer_window,
7247 GdkModifierType mask)
7250 GdkWindow *grab_window;
7253 if ((display->pointer_grab.window != NULL && !display->pointer_grab.owner_events) ||
7254 (type == GDK_BUTTON_RELEASE && display->pointer_grab.grab_one_pointer_release_event))
7256 evmask = display->pointer_grab.event_mask;
7257 evmask = update_evmask_for_button_motion (evmask, mask);
7259 if (type == GDK_BUTTON_RELEASE &&
7260 display->pointer_grab.grab_one_pointer_release_event)
7262 grab_window = display->pointer_grab.grab_one_pointer_release_event;
7263 display->pointer_grab.grab_one_pointer_release_event = NULL;
7266 grab_window = display->pointer_grab.window;
7268 if (evmask & type_masks[type])
7274 w = (GdkWindowObject *)pointer_window;
7277 evmask = w->event_mask;
7278 evmask = update_evmask_for_button_motion (evmask, mask);
7280 if (evmask & type_masks[type])
7281 return (GdkWindow *)w;
7286 if (display->pointer_grab.window != NULL &&
7287 display->pointer_grab.owner_events)
7289 evmask = display->pointer_grab.event_mask;
7290 evmask = update_evmask_for_button_motion (evmask, mask);
7292 if (evmask & type_masks[type])
7293 return display->pointer_grab.window;
7302 proxy_pointer_event (GdkDisplay *display,
7303 GdkEvent *source_event)
7305 GdkWindow *toplevel_window;
7306 GdkWindow *pointer_window;
7307 GdkWindow *cursor_window;
7308 gboolean sent_motion;
7311 gdouble toplevel_x, toplevel_y;
7314 toplevel_window = source_event->any.window;
7315 gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
7316 gdk_event_get_state (source_event, &state);
7317 time_ = gdk_event_get_time (source_event);
7319 pointer_window = get_pointer_window (display, toplevel_window, toplevel_x, toplevel_y);
7320 if (display->pointer_info.window_under_pointer != pointer_window)
7322 /* Either a toplevel crossing notify that ended up inside a child window,
7323 or a motion notify that got into another child window */
7324 /* Different than last time, send crossing events */
7326 _gdk_syntesize_crossing_events (display,
7327 display->pointer_info.window_under_pointer,
7329 GDK_CROSSING_NORMAL,
7330 toplevel_x, toplevel_y,
7334 _gdk_display_set_window_under_pointer (display, pointer_window);
7336 else if (source_event->type == GDK_MOTION_NOTIFY)
7338 GdkWindow *event_win;
7340 event_win = get_event_window (display,
7348 event = _gdk_make_event (event_win, GDK_MOTION_NOTIFY, source_event, FALSE);
7349 event->motion.time = time_;
7350 convert_toplevel_coords_to_window (event_win,
7351 toplevel_x, toplevel_y,
7352 &event->motion.x, &event->motion.y);
7353 event->motion.x_root = source_event->motion.x_root;
7354 event->motion.y_root = source_event->motion.y_root;;
7355 event->motion.state = state;
7356 event->motion.is_hint = FALSE;
7357 event->motion.device = NULL;
7358 if (source_event && source_event->type == GDK_MOTION_NOTIFY)
7359 event->motion.device = source_event->motion.device;
7363 /* TODO: set cursor from cursor_window, or grab cursor */
7364 cursor_window = pointer_window;
7365 if (display->pointer_grab.window &&
7366 (pointer_window == NULL ||
7367 !is_parent_of (display->pointer_grab.window, pointer_window)))
7368 cursor_window = display->pointer_grab.window;
7369 /* Actually, this should probably happen in synthesize crossing so it works with geometry changes */
7372 /* unlink all move events from queue.
7373 We handle our own, including our emulated masks. */
7378 proxy_button_event (GdkEvent *source_event)
7380 GdkWindow *toplevel_window;
7381 GdkWindow *event_win;
7382 GdkWindow *pointer_window;
7387 gdouble toplevel_x, toplevel_y;
7388 GdkDisplay *display;
7391 type = source_event->any.type;
7392 toplevel_window = source_event->any.window;
7393 gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
7394 gdk_event_get_state (source_event, &state);
7395 time_ = gdk_event_get_time (source_event);
7396 display = gdk_drawable_get_display (source_event->any.window);
7398 if ((type == GDK_BUTTON_PRESS || type == GDK_SCROLL) &&
7399 display->pointer_grab.window == source_event->any.window &&
7400 display->pointer_grab.implicit &&
7401 !display->pointer_grab.converted_implicit)
7404 _gdk_window_find_descendant_at (toplevel_window,
7405 toplevel_x, toplevel_y,
7408 /* Find the actual event window, its what gets the grab */
7409 w = (GdkWindowObject *)pointer_window;
7410 while (w != NULL && w->parent->window_type != GDK_WINDOW_ROOT)
7412 if (w->event_mask & GDK_BUTTON_PRESS_MASK)
7419 if (pointer_window != NULL &&
7420 pointer_window != source_event->any.window)
7421 _gdk_display_set_has_pointer_grab (display,
7423 display->pointer_grab.native_window,
7424 display->pointer_grab.owner_events,
7425 gdk_window_get_events (pointer_window),
7426 display->pointer_grab.serial,
7427 display->pointer_grab.time,
7428 display->pointer_grab.implicit);
7429 display->pointer_grab.converted_implicit = TRUE;
7432 pointer_window = get_pointer_window (display, toplevel_window, toplevel_x, toplevel_y);
7434 event_win = get_event_window (display,
7439 if (event_win == NULL)
7442 event = _gdk_make_event (event_win, type, source_event, FALSE);
7446 case GDK_BUTTON_PRESS:
7447 case GDK_BUTTON_RELEASE:
7448 event->button.button = source_event->button.button;
7449 convert_toplevel_coords_to_window (event_win,
7450 toplevel_x, toplevel_y,
7451 &event->button.x, &event->button.y);
7452 event->button.x_root = source_event->button.x_root;
7453 event->button.y_root = source_event->button.y_root;
7454 event->button.state = state;
7455 event->button.device = source_event->button.device;
7457 if (type == GDK_BUTTON_PRESS)
7458 _gdk_event_button_generate (display, event);
7462 event->scroll.direction = source_event->scroll.direction;
7463 convert_toplevel_coords_to_window (event_win,
7464 toplevel_x, toplevel_y,
7465 &event->scroll.x, &event->scroll.y);
7466 event->scroll.x_root = source_event->scroll.x_root;
7467 event->scroll.y_root = source_event->scroll.y_root;
7468 event->scroll.state = state;
7469 event->scroll.device = source_event->scroll.device;
7476 return TRUE; /* Always unlink original, we want to obey the emulated event mask */
7480 _gdk_windowing_got_event (GdkDisplay *display,
7484 GdkWindow *event_window;
7485 GdkWindowObject *event_private;
7487 gboolean unlink_event;
7489 event_window = event->any.window;
7493 event_private = GDK_WINDOW_OBJECT (event_window);
7495 if (!(is_button_type (event->type) ||
7496 is_motion_type (event->type)))
7499 if (GDK_WINDOW_TYPE (event_private->parent) != GDK_WINDOW_ROOT)
7501 GEnumValue *event_type_value, *window_type_value;
7503 event_type_value = g_enum_get_value ((GEnumClass *) g_type_class_ref (GDK_TYPE_EVENT_TYPE),
7505 window_type_value = g_enum_get_value ((GEnumClass *) g_type_class_ref (GDK_TYPE_WINDOW_TYPE),
7506 event_private->window_type);
7508 /* We should only get these events on toplevel windows */
7509 g_warning ("got unexpected event of type %s on non-toplevel window (gtype %s, type %d)",
7510 event_type_value->value_name,
7511 window_type_value->value_name,
7512 GDK_WINDOW_TYPE (event_window));
7516 if ((event->type == GDK_ENTER_NOTIFY ||
7517 event->type == GDK_LEAVE_NOTIFY) &&
7518 (event->crossing.mode == GDK_CROSSING_GRAB ||
7519 event->crossing.mode == GDK_CROSSING_UNGRAB))
7521 /* We synthesize all crossing events due to grabs are synthesized,
7522 * so we ignore the native ones. This is partly to get easier non-X
7523 * portability, and because of problems with race conditions due to
7524 * the cached state in the client and the real state in the xserver
7528 /* We ended up in this window after some (perhaps other clients)
7529 grab, so update the toplevel_under_window state */
7530 if (event->type == GDK_ENTER_NOTIFY &&
7531 event->crossing.mode == GDK_CROSSING_UNGRAB)
7533 if (display->pointer_info.toplevel_under_pointer)
7534 g_object_unref (display->pointer_info.toplevel_under_pointer);
7535 display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
7538 unlink_event = TRUE;
7542 /* Store last pointer window and position/state */
7543 if (event->type == GDK_ENTER_NOTIFY &&
7544 event->crossing.detail != GDK_NOTIFY_INFERIOR)
7546 if (display->pointer_info.toplevel_under_pointer)
7547 g_object_unref (display->pointer_info.toplevel_under_pointer);
7548 display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
7550 else if (event->type == GDK_LEAVE_NOTIFY &&
7551 event->crossing.detail != GDK_NOTIFY_INFERIOR &&
7552 display->pointer_info.toplevel_under_pointer == event_window)
7554 if (display->pointer_info.toplevel_under_pointer)
7555 g_object_unref (display->pointer_info.toplevel_under_pointer);
7556 display->pointer_info.toplevel_under_pointer = NULL;
7559 gdk_event_get_coords (event, &x, &y);
7560 display->pointer_info.toplevel_x = x;
7561 display->pointer_info.toplevel_y = y;
7562 gdk_event_get_state (event, &display->pointer_info.state);
7565 unlink_event = FALSE;
7566 if (is_motion_type (event->type))
7567 unlink_event = proxy_pointer_event (display,
7569 else if (is_button_type (event->type))
7570 unlink_event = proxy_button_event (event);
7575 _gdk_event_queue_remove_link (display, event_link);
7576 g_list_free_1 (event_link);
7577 gdk_event_free (event);
7581 #define __GDK_WINDOW_C__
7582 #include "gdkaliasdef.c"