1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-2007 Peter Mattis, Spencer Kimball,
3 * Josh MacDonald, Ryan Lortie
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
22 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
23 * file for a list of people on the GTK+ Team. See the ChangeLog
24 * files for a list of changes. These files are distributed with
25 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
29 #include "gdkwindow.h"
30 #include "gdkwindowimpl.h"
31 #include "gdkinternals.h"
32 #include "gdk.h" /* For gdk_rectangle_union() */
33 #include "gdkpixmap.h"
34 #include "gdkdrawable.h"
35 #include "gdkscreen.h"
38 #undef DEBUG_WINDOW_PRINTING
40 #ifdef GDK_WINDOWING_X11
41 #include "x11/gdkx.h" /* For workaround */
46 /* Not all GdkWindows have a corresponding native window.
47 * Instead some draw into the nearest parent that has whatss
48 * called an "impl", i.e. the implementation window.
49 * For toplevel window system windows the impl is always native
50 * window, but child windows can also have native windows as
51 * this is sometimes necessary. Furthermore, offscreen windows
52 * (type GDK_WINDOW_OFFSCREEN) have an impl of type
53 * GdkOffscreenWindow rather than a backend implementation native
54 * window. Such windows draw into an offscreen pixmap instead
55 * of a window and collect damage that lets you paint it where
58 * All GdkWindow track their position, size, clip region and
59 * absolute position in the impl window. For child window with
60 * native windows the clip region is set on the native window
61 * as a window shape to make it clip against other non-native windows.
64 #define USE_BACKING_STORE /* Appears to work on Win32, too, now. */
66 struct _GdkWindowPaint
72 cairo_surface_t *surface;
73 guint uses_implicit : 1;
78 GdkRegion *dest_region; /* The destination region */
79 int dx, dy; /* The amount that the source was moved to reach dest_region */
80 } GdkWindowRegionMove;
85 static GdkGC *gdk_window_create_gc (GdkDrawable *drawable,
87 GdkGCValuesMask mask);
88 static void gdk_window_draw_rectangle (GdkDrawable *drawable,
95 static void gdk_window_draw_arc (GdkDrawable *drawable,
104 static void gdk_window_draw_polygon (GdkDrawable *drawable,
109 static void gdk_window_draw_text (GdkDrawable *drawable,
116 static void gdk_window_draw_text_wc (GdkDrawable *drawable,
121 const GdkWChar *text,
123 static void gdk_window_draw_drawable (GdkDrawable *drawable,
132 static void gdk_window_draw_points (GdkDrawable *drawable,
136 static void gdk_window_draw_segments (GdkDrawable *drawable,
140 static void gdk_window_draw_lines (GdkDrawable *drawable,
145 static void gdk_window_draw_glyphs (GdkDrawable *drawable,
150 PangoGlyphString *glyphs);
151 static void gdk_window_draw_glyphs_transformed (GdkDrawable *drawable,
157 PangoGlyphString *glyphs);
159 static void gdk_window_draw_image (GdkDrawable *drawable,
169 static void gdk_window_draw_pixbuf (GdkDrawable *drawable,
182 static void gdk_window_draw_trapezoids (GdkDrawable *drawable,
184 GdkTrapezoid *trapezoids,
187 static GdkImage* gdk_window_copy_to_image (GdkDrawable *drawable,
196 static cairo_surface_t *gdk_window_ref_cairo_surface (GdkDrawable *drawable);
197 static cairo_surface_t *gdk_window_create_cairo_surface (GdkDrawable *drawable,
200 static void gdk_window_set_cairo_clip (GdkDrawable *drawable,
203 static void gdk_window_real_get_size (GdkDrawable *drawable,
207 static GdkVisual* gdk_window_real_get_visual (GdkDrawable *drawable);
208 static gint gdk_window_real_get_depth (GdkDrawable *drawable);
209 static GdkScreen* gdk_window_real_get_screen (GdkDrawable *drawable);
210 static void gdk_window_real_set_colormap (GdkDrawable *drawable,
212 static GdkColormap* gdk_window_real_get_colormap (GdkDrawable *drawable);
214 static GdkDrawable* gdk_window_get_source_drawable (GdkDrawable *drawable);
215 static GdkDrawable* gdk_window_get_composite_drawable (GdkDrawable *drawable,
220 gint *composite_x_offset,
221 gint *composite_y_offset);
222 static GdkRegion* gdk_window_get_clip_region (GdkDrawable *drawable);
223 static GdkRegion* gdk_window_get_visible_region (GdkDrawable *drawable);
225 static void gdk_window_free_paint_stack (GdkWindow *window);
227 static void gdk_window_init (GdkWindowObject *window);
228 static void gdk_window_class_init (GdkWindowObjectClass *klass);
229 static void gdk_window_finalize (GObject *object);
230 static void gdk_window_clear_backing_region (GdkWindow *window,
232 static void gdk_window_redirect_free (GdkWindowRedirect *redirect);
233 static void apply_redirect_to_children (GdkWindowObject *private,
234 GdkWindowRedirect *redirect);
235 static void remove_redirect_from_children (GdkWindowObject *private,
236 GdkWindowRedirect *redirect);
238 static void recompute_visible_regions (GdkWindowObject *private,
239 gboolean recalculate_siblings,
240 gboolean recalculate_children);
241 static void gdk_window_flush_outstanding_moves (GdkWindow *window);
242 static void gdk_window_flush (GdkWindow *window);
243 static void gdk_window_flush_recursive (GdkWindowObject *window);
244 static void do_move_region_bits_on_impl (GdkWindowObject *private,
245 GdkRegion *region, /* In impl window coords */
247 static void gdk_window_invalidate_in_parent (GdkWindowObject *private);
248 static void move_native_children (GdkWindowObject *private);
250 static gpointer parent_class = NULL;
252 static const cairo_user_data_key_t gdk_window_cairo_key;
255 new_region_tag (void)
257 static guint32 tag = 0;
263 gdk_window_object_get_type (void)
265 static GType object_type = 0;
268 object_type = g_type_register_static_simple (GDK_TYPE_DRAWABLE,
270 sizeof (GdkWindowObjectClass),
271 (GClassInitFunc) gdk_window_class_init,
272 sizeof (GdkWindowObject),
273 (GInstanceInitFunc) gdk_window_init,
280 _gdk_paintable_get_type (void)
282 static GType paintable_type = 0;
286 const GTypeInfo paintable_info =
288 sizeof (GdkPaintableIface), /* class_size */
289 NULL, /* base_init */
290 NULL, /* base_finalize */
293 paintable_type = g_type_register_static (G_TYPE_INTERFACE,
294 g_intern_static_string ("GdkPaintable"),
297 g_type_interface_add_prerequisite (paintable_type, G_TYPE_OBJECT);
300 return paintable_type;
304 gdk_window_init (GdkWindowObject *window)
306 /* 0-initialization is good for all other fields. */
308 window->window_type = GDK_WINDOW_CHILD;
310 window->state = GDK_WINDOW_STATE_WITHDRAWN;
313 window->toplevel_window_type = -1;
316 static GQuark quark_pointer_window = 0;
319 gdk_window_class_init (GdkWindowObjectClass *klass)
321 GObjectClass *object_class = G_OBJECT_CLASS (klass);
322 GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
324 parent_class = g_type_class_peek_parent (klass);
326 object_class->finalize = gdk_window_finalize;
328 drawable_class->create_gc = gdk_window_create_gc;
329 drawable_class->draw_rectangle = gdk_window_draw_rectangle;
330 drawable_class->draw_arc = gdk_window_draw_arc;
331 drawable_class->draw_polygon = gdk_window_draw_polygon;
332 drawable_class->draw_text = gdk_window_draw_text;
333 drawable_class->draw_text_wc = gdk_window_draw_text_wc;
334 drawable_class->draw_drawable = gdk_window_draw_drawable;
335 drawable_class->draw_points = gdk_window_draw_points;
336 drawable_class->draw_segments = gdk_window_draw_segments;
337 drawable_class->draw_lines = gdk_window_draw_lines;
338 drawable_class->draw_glyphs = gdk_window_draw_glyphs;
339 drawable_class->draw_glyphs_transformed = gdk_window_draw_glyphs_transformed;
340 drawable_class->draw_image = gdk_window_draw_image;
341 drawable_class->draw_pixbuf = gdk_window_draw_pixbuf;
342 drawable_class->draw_trapezoids = gdk_window_draw_trapezoids;
343 drawable_class->get_depth = gdk_window_real_get_depth;
344 drawable_class->get_screen = gdk_window_real_get_screen;
345 drawable_class->get_size = gdk_window_real_get_size;
346 drawable_class->set_colormap = gdk_window_real_set_colormap;
347 drawable_class->get_colormap = gdk_window_real_get_colormap;
348 drawable_class->get_visual = gdk_window_real_get_visual;
349 drawable_class->_copy_to_image = gdk_window_copy_to_image;
350 drawable_class->ref_cairo_surface = gdk_window_ref_cairo_surface;
351 drawable_class->create_cairo_surface = gdk_window_create_cairo_surface;
352 drawable_class->set_cairo_clip = gdk_window_set_cairo_clip;
353 drawable_class->get_clip_region = gdk_window_get_clip_region;
354 drawable_class->get_visible_region = gdk_window_get_visible_region;
355 drawable_class->get_composite_drawable = gdk_window_get_composite_drawable;
356 drawable_class->get_source_drawable = gdk_window_get_source_drawable;
358 quark_pointer_window = g_quark_from_static_string ("gtk-pointer-window");
362 gdk_window_finalize (GObject *object)
364 GdkWindow *window = GDK_WINDOW (object);
365 GdkWindowObject *obj = (GdkWindowObject *) object;
367 if (!GDK_WINDOW_DESTROYED (window))
369 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
371 g_warning ("losing last reference to undestroyed window\n");
372 _gdk_window_destroy (window, FALSE);
375 /* We use TRUE here, to keep us from actually calling
376 * XDestroyWindow() on the window
378 _gdk_window_destroy (window, TRUE);
383 g_object_unref (obj->impl);
387 if (obj->impl_window != obj)
389 g_object_unref (obj->impl_window);
390 obj->impl_window = NULL;
394 gdk_region_destroy (obj->shape);
396 if (obj->input_shape)
397 gdk_region_destroy (obj->input_shape);
400 gdk_cursor_unref (obj->cursor);
402 G_OBJECT_CLASS (parent_class)->finalize (object);
406 gdk_window_is_offscreen (GdkWindowObject *window)
408 return GDK_WINDOW_TYPE (window) == GDK_WINDOW_OFFSCREEN;
411 static GdkWindowObject *
412 gdk_window_get_impl_window (GdkWindowObject *window)
414 return window->impl_window;
418 _gdk_window_get_impl_window (GdkWindow *window)
420 return (GdkWindow *)gdk_window_get_impl_window ((GdkWindowObject *)window);
424 gdk_window_has_impl (GdkWindowObject *window)
426 return window->impl_window == window;
430 _gdk_window_has_impl (GdkWindow *window)
432 return gdk_window_has_impl ((GdkWindowObject *)window);
436 gdk_window_has_no_impl (GdkWindowObject *window)
438 return window->impl_window != window;
442 remove_child_area (GdkWindowObject *private,
443 GdkWindowObject *until,
447 GdkWindowObject *child;
448 GdkRegion *child_region;
453 for (l = private->children; l; l = l->next)
460 if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
463 /* Ignore offscreen children, as they don't draw in their parent and
464 * don't take part in the clipping */
465 if (gdk_window_is_offscreen (child))
470 r.width = child->width;
471 r.height = child->height;
473 child_region = gdk_region_rectangle (&r);
476 gdk_region_intersect (child_region, child->shape);
477 else if (private->window_type == GDK_WINDOW_FOREIGN)
479 shape = _gdk_windowing_window_get_shape ((GdkWindow *)child);
482 gdk_region_intersect (child_region, shape);
483 gdk_region_destroy (shape);
489 if (child->input_shape)
490 gdk_region_intersect (child_region, child->input_shape);
491 else if (private->window_type == GDK_WINDOW_FOREIGN)
493 shape = _gdk_windowing_window_get_input_shape ((GdkWindow *)child);
496 gdk_region_intersect (child_region, shape);
497 gdk_region_destroy (shape);
502 gdk_region_subtract (region, child_region);
503 gdk_region_destroy (child_region);
509 recompute_visible_regions_internal (GdkWindowObject *private,
510 gboolean recalculate_clip,
511 gboolean recalculate_siblings,
512 gboolean recalculate_children)
516 GdkWindowObject *child;
517 GdkRegion *new_clip, *old_clip_region_with_children;
518 gboolean clip_region_changed;
519 gboolean abs_pos_changed;
520 int old_abs_x, old_abs_y;
522 old_abs_x = private->abs_x;
523 old_abs_y = private->abs_y;
525 /* Update absolute position */
526 if (gdk_window_has_impl (private))
528 /* Native window starts here */
534 private->abs_x = private->parent->abs_x + private->x;
535 private->abs_y = private->parent->abs_y + private->y;
539 private->abs_x != old_abs_x ||
540 private->abs_y != old_abs_y;
542 /* Update clip region based on:
545 * siblings in parents above window
547 clip_region_changed = FALSE;
548 if (recalculate_clip)
550 /* Calculate visible region (sans children) in parent window coords */
553 r.width = private->width;
554 r.height = private->height;
555 new_clip = gdk_region_rectangle (&r);
557 if (private->parent != NULL && GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
559 gdk_region_intersect (new_clip, private->parent->clip_region);
561 /* Remove all overlapping children from parent */
562 remove_child_area (private->parent, private, FALSE, new_clip);
565 /* Convert from parent coords to window coords */
566 gdk_region_offset (new_clip, -private->x, -private->y);
569 gdk_region_intersect (new_clip, private->shape);
571 if (private->clip_region == NULL ||
572 !gdk_region_equal (private->clip_region, new_clip))
573 clip_region_changed = TRUE;
575 if (private->clip_region)
576 gdk_region_destroy (private->clip_region);
577 private->clip_region = new_clip;
579 old_clip_region_with_children = private->clip_region_with_children;
580 private->clip_region_with_children = gdk_region_copy (private->clip_region);
581 remove_child_area (private, NULL, FALSE, private->clip_region_with_children);
583 if (clip_region_changed ||
584 !gdk_region_equal (private->clip_region_with_children, old_clip_region_with_children))
585 private->clip_tag = new_region_tag ();
587 if (old_clip_region_with_children)
588 gdk_region_destroy (old_clip_region_with_children);
591 /* Update all children, recursively. */
592 if (abs_pos_changed || clip_region_changed || recalculate_children)
594 for (l = private->children; l; l = l->next)
597 /* Only recalculate clip if the the clip region changed, otherwise
598 * there is no way the child clip region could change (its has not e.g. moved)
599 * Except if recalculate_children is set to force child updates
601 recompute_visible_regions_internal (child, recalculate_clip && (clip_region_changed || recalculate_children), FALSE, FALSE);
605 if (clip_region_changed &&
606 gdk_window_has_impl (private) &&
607 /* Not for offscreens */
608 private->window_type != GDK_WINDOW_OFFSCREEN &&
609 /* or for non-shaped toplevels */
611 (private->parent != NULL &&
612 GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)) &&
613 /* or for foreign windows */
614 GDK_WINDOW_TYPE (private) != GDK_WINDOW_FOREIGN
617 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region ((GdkWindow *)private, private->clip_region, 0, 0);
620 if (recalculate_siblings &&
621 private->parent != NULL &&
622 GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
624 /* If we moved a child window in parent or changed the stacking order, then we
625 * need to recompute the visible area of all the other children in the parent
627 for (l = private->parent->children; l; l = l->next)
631 if (child != private)
632 recompute_visible_regions_internal (child, TRUE, FALSE, FALSE);
635 /* We also need to recompute the _with_children clip for the parent */
636 recompute_visible_regions_internal (private->parent, TRUE, FALSE, FALSE);
639 if (private->cairo_surface)
643 /* It would be nice if we had some cairo support here so we
644 could set the clip rect on the cairo surface */
645 width = private->abs_x + private->width;
646 height = private->abs_y + private->height;
648 _gdk_windowing_set_cairo_surface_size (private->cairo_surface,
650 cairo_surface_set_device_offset (private->cairo_surface,
656 /* Call this when private has changed in one or more of these ways:
660 * stacking order of window changed
663 * It will recalculate abs_x/y and the clip regions
665 * Unless the window didn't change stacking order or size/pos, pass in TRUE
666 * for recalculate_siblings. (Mostly used internally for the recursion)
668 * If a child window was removed (and you can't use that child for
669 * recompute_visible_regions), pass in TRUE for recalculate_children on the parent
672 recompute_visible_regions (GdkWindowObject *private,
673 gboolean recalculate_siblings,
674 gboolean recalculate_children)
676 recompute_visible_regions_internal (private,
678 recalculate_siblings,
679 recalculate_children);
683 _gdk_window_update_size (GdkWindow *window)
685 recompute_visible_regions ((GdkWindowObject *)window, TRUE, FALSE);
688 /* Find the native window that would be just above "child"
689 * in the native stacking order if "child" was a native window
690 * (it doesn't have to be native). If there is no such native
691 * window inside this native parent then NULL is returned.
692 * If child is NULL, find lowest native window in parent.
694 static GdkWindowObject *
695 find_native_sibling_above_helper (GdkWindowObject *parent,
696 GdkWindowObject *child)
703 l = g_list_find (parent->children, child);
704 g_assert (l != NULL); /* Better be a child of its parent... */
705 l = l->prev; /* Start looking at the one above the child */
708 l = g_list_last (parent->children);
710 for (; l != NULL; l = l->prev)
714 if (gdk_window_has_impl (w))
717 g_assert (parent != w);
718 w = find_native_sibling_above_helper (w, NULL);
727 static GdkWindowObject *
728 find_native_sibling_above (GdkWindowObject *parent,
729 GdkWindowObject *child)
733 w = find_native_sibling_above_helper (parent, child);
737 if (gdk_window_has_impl (parent))
740 return find_native_sibling_above (parent->parent, parent);
744 get_native_event_mask (GdkWindowObject *private)
746 if (private->window_type != GDK_WINDOW_ROOT &&
747 private->window_type != GDK_WINDOW_FOREIGN)
750 /* We need thse for all native window so we can emulate
751 events on children: */
753 GDK_POINTER_MOTION_MASK |
754 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
755 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
757 /* Then do whatever the app asks to, since the app
758 * may be asking for weird things for native windows,
759 * but filter out things that override the above
760 * requests somehow. */
761 (private->event_mask &
762 ~(GDK_POINTER_MOTION_HINT_MASK |
763 GDK_BUTTON_MOTION_MASK |
764 GDK_BUTTON1_MOTION_MASK |
765 GDK_BUTTON2_MOTION_MASK |
766 GDK_BUTTON3_MOTION_MASK));
769 return private->event_mask;
774 * @parent: a #GdkWindow, or %NULL to create the window as a child of
775 * the default root window for the default display.
776 * @attributes: attributes of the new window
777 * @attributes_mask: mask indicating which fields in @attributes are valid
779 * Creates a new #GdkWindow using the attributes from
780 * @attributes. See #GdkWindowAttr and #GdkWindowAttributesType for
781 * more details. Note: to use this on displays other than the default
782 * display, @parent must be specified.
784 * Return value: the new #GdkWindow
787 gdk_window_new (GdkWindow *parent,
788 GdkWindowAttr *attributes,
789 gint attributes_mask)
792 GdkWindowObject *private;
797 GdkEventMask event_mask;
798 GdkWindow *real_parent;
800 g_return_val_if_fail (attributes != NULL, NULL);
805 g_warning ("gdk_window_new(): no parent specified reverting to parent = default root window"));
807 screen = gdk_screen_get_default ();
808 parent = gdk_screen_get_root_window (screen);
811 screen = gdk_drawable_get_screen (parent);
813 g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
815 if (GDK_WINDOW_DESTROYED (parent))
818 window = g_object_new (GDK_TYPE_WINDOW, NULL);
819 private = (GdkWindowObject *) window;
821 /* Windows with a foreign parent are treated as if they are children
822 * of the root window, except for actual creation.
824 real_parent = parent;
825 if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
826 parent = gdk_screen_get_root_window (screen);
828 private->parent = (GdkWindowObject *)parent;
830 private->accept_focus = TRUE;
831 private->focus_on_map = TRUE;
833 if (attributes_mask & GDK_WA_X)
838 if (attributes_mask & GDK_WA_Y)
845 private->width = (attributes->width > 1) ? (attributes->width) : (1);
846 private->height = (attributes->height > 1) ? (attributes->height) : (1);
848 #ifdef GDK_WINDOWING_X11
849 /* Work around a bug where Xorg refuses to map toplevel InputOnly windows
850 * from an untrusted client: http://bugs.freedesktop.org/show_bug.cgi?id=6988
852 if (attributes->wclass == GDK_INPUT_ONLY &&
853 GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT &&
854 !G_LIKELY (GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (parent))->trusted_client))
856 g_warning ("Coercing GDK_INPUT_ONLY toplevel window to GDK_INPUT_OUTPUT to work around bug in Xorg server");
857 attributes->wclass = GDK_INPUT_OUTPUT;
861 if (attributes->wclass == GDK_INPUT_ONLY)
863 /* Backwards compatiblity - we've always ignored
864 * attributes->window_type for input-only windows
867 if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
868 private->window_type = GDK_WINDOW_TEMP;
870 private->window_type = GDK_WINDOW_CHILD;
873 private->window_type = attributes->window_type;
876 switch (private->window_type)
878 case GDK_WINDOW_TOPLEVEL:
879 case GDK_WINDOW_DIALOG:
880 case GDK_WINDOW_TEMP:
881 case GDK_WINDOW_OFFSCREEN:
882 if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
883 g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
884 "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
885 case GDK_WINDOW_CHILD:
889 g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
893 if (attributes_mask & GDK_WA_VISUAL)
894 visual = attributes->visual;
896 visual = gdk_screen_get_system_visual (screen);
898 private->event_mask = attributes->event_mask;
900 if (attributes->wclass == GDK_INPUT_OUTPUT)
902 private->input_only = FALSE;
903 private->depth = visual->depth;
905 private->bg_color.pixel = 0; // TODO: BlackPixel (xdisplay, screen_x11->screen_num);
906 private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
908 private->bg_pixmap = NULL;
913 private->input_only = TRUE;
917 private->parent->children = g_list_prepend (private->parent->children, window);
919 native = FALSE; /* Default */
920 if (GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
921 native = TRUE; /* Always use native windows for toplevels */
922 else if (!private->input_only &&
923 ((attributes_mask & GDK_WA_COLORMAP &&
924 attributes->colormap != gdk_drawable_get_colormap ((GdkDrawable *)private->parent)) ||
925 (attributes_mask & GDK_WA_VISUAL &&
926 attributes->visual != gdk_drawable_get_visual ((GdkDrawable *)private->parent))))
927 native = TRUE; /* InputOutput window with different colormap or visual than parent, needs native window */
929 if (private->window_type == GDK_WINDOW_OFFSCREEN)
931 _gdk_offscreen_window_new (window, screen, visual, attributes, attributes_mask);
932 private->impl_window = private;
936 GdkWindowObject *above;
937 GList listhead = {0};
939 event_mask = get_native_event_mask (private);
941 /* Create the impl */
942 _gdk_window_impl_new (window, real_parent, screen, visual, event_mask, attributes, attributes_mask);
943 private->impl_window = private;
945 /* This will put the native window topmost in the native parent, which may
946 * be wrong wrt other native windows in the non-native hierarchy, so restack */
947 above = find_native_sibling_above (private->parent, private);
950 listhead.data = window;
951 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
958 private->impl_window = g_object_ref (private->parent->impl_window);
959 private->impl = g_object_ref (private->impl_window->impl);
962 recompute_visible_regions (private, TRUE, FALSE);
964 if (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
966 /* Inherit redirection from parent */
967 private->redirect = private->parent->redirect;
970 gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
971 (attributes->cursor) :
978 is_parent_of (GdkWindow *parent,
989 w = gdk_window_get_parent (w);
996 change_impl (GdkWindowObject *private,
997 GdkWindowObject *impl_window,
1001 GdkWindowObject *child;
1002 GdkDrawable *old_impl;
1003 GdkWindowObject *old_impl_window;
1005 old_impl = private->impl;
1006 old_impl_window = private->impl_window;
1007 if (private != impl_window)
1008 private->impl_window = g_object_ref (impl_window);
1010 private->impl_window = private;
1011 private->impl = g_object_ref (new);
1012 if (old_impl_window != private)
1013 g_object_unref (old_impl_window);
1014 g_object_unref (old_impl);
1016 for (l = private->children; l != NULL; l = l->next)
1020 if (child->impl == old_impl)
1021 change_impl (child, impl_window, new);
1026 reparent_to_impl (GdkWindowObject *private)
1029 GdkWindowObject *child;
1032 /* Enumerate in reverse order so we get the right order for the native
1033 windows (first in childrens list is topmost, and reparent places on top) */
1034 for (l = g_list_last (private->children); l != NULL; l = l->prev)
1038 if (child->impl == private->impl)
1039 reparent_to_impl (child);
1042 show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent ((GdkWindow *)child,
1043 (GdkWindow *)private,
1044 child->x, child->y);
1046 gdk_window_show_unraised ((GdkWindow *)child);
1053 * gdk_window_reparent:
1054 * @window: a #GdkWindow
1055 * @new_parent: new parent to move @window into
1056 * @x: X location inside the new parent
1057 * @y: Y location inside the new parent
1059 * Reparents @window into the given @new_parent. The window being
1060 * reparented will be unmapped as a side effect.
1064 gdk_window_reparent (GdkWindow *window,
1065 GdkWindow *new_parent,
1069 GdkWindowObject *private;
1070 GdkWindowObject *new_parent_private;
1071 GdkWindowObject *old_parent;
1072 gboolean show, was_toplevel, was_mapped;
1073 gboolean do_reparent_to_impl;
1075 g_return_if_fail (GDK_IS_WINDOW (window));
1076 g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
1077 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
1079 if (GDK_WINDOW_DESTROYED (window) ||
1080 (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
1084 new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
1086 private = (GdkWindowObject *) window;
1087 new_parent_private = (GdkWindowObject *)new_parent;
1089 /* No input-output children of input-only windows */
1090 if (new_parent_private->input_only && !private->input_only)
1093 /* Don't create loops in hierarchy */
1094 if (is_parent_of (window, new_parent))
1097 if (private->cairo_surface)
1099 /* This might be wrong in the new parent, e.g. for non-native surfaces.
1100 To make sure we're ok, just wipe it. */
1101 cairo_surface_finish (private->cairo_surface);
1102 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
1106 old_parent = private->parent;
1108 /* Break up redirection if inherited */
1109 if (private->redirect && private->redirect->redirected != private)
1111 remove_redirect_from_children (private, private->redirect);
1112 private->redirect = NULL;
1115 was_toplevel = private->parent == NULL;
1116 was_mapped = GDK_WINDOW_IS_MAPPED (window);
1119 /* Reparenting to toplevel. Ensure we have a native window so this can work */
1120 if (new_parent_private->window_type == GDK_WINDOW_ROOT ||
1121 new_parent_private->window_type == GDK_WINDOW_FOREIGN)
1122 gdk_window_set_has_native (window, TRUE);
1124 do_reparent_to_impl = FALSE;
1125 if (gdk_window_has_impl (private))
1128 show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent (window, new_parent, x, y);
1132 /* This shouldn't happen, as we created a native in this case, check anyway to see if that ever fails */
1133 g_assert (new_parent_private->window_type != GDK_WINDOW_ROOT &&
1134 new_parent_private->window_type != GDK_WINDOW_FOREIGN);
1137 gdk_window_hide (window);
1139 do_reparent_to_impl = TRUE;
1140 change_impl (private,
1141 new_parent_private->impl_window,
1142 new_parent_private->impl);
1145 /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
1148 if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1150 new_parent = gdk_screen_get_root_window (GDK_WINDOW_SCREEN (window));
1151 new_parent_private = (GdkWindowObject *)new_parent;
1155 old_parent->children = g_list_remove (old_parent->children, window);
1157 private->parent = new_parent_private;
1161 new_parent_private->children = g_list_prepend (new_parent_private->children, window);
1163 /* Switch the window type as appropriate */
1165 switch (GDK_WINDOW_TYPE (new_parent))
1167 case GDK_WINDOW_ROOT:
1168 case GDK_WINDOW_FOREIGN:
1169 if (private->toplevel_window_type != -1)
1170 GDK_WINDOW_TYPE (window) = private->toplevel_window_type;
1171 else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1172 GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
1174 case GDK_WINDOW_OFFSCREEN:
1175 case GDK_WINDOW_TOPLEVEL:
1176 case GDK_WINDOW_CHILD:
1177 case GDK_WINDOW_DIALOG:
1178 case GDK_WINDOW_TEMP:
1179 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
1180 GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
1182 /* Save the original window type so we can restore it if the
1183 * window is reparented back to be a toplevel
1185 private->toplevel_window_type = GDK_WINDOW_TYPE (window);
1186 GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
1190 /* We might have changed window type for a native windows, so we
1191 need to change the event mask too. */
1192 if (gdk_window_has_impl (private))
1193 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_events (window, get_native_event_mask (private));
1195 /* Inherit parent redirect if we don't have our own */
1196 if (private->parent && private->redirect == NULL)
1198 private->redirect = private->parent->redirect;
1199 apply_redirect_to_children (private, private->redirect);
1202 recompute_visible_regions (private, TRUE, FALSE);
1203 if (old_parent && GDK_WINDOW_TYPE (old_parent) != GDK_WINDOW_ROOT)
1204 recompute_visible_regions (old_parent, FALSE, TRUE);
1206 if (do_reparent_to_impl)
1207 reparent_to_impl (private);
1210 GdkWindowObject *above;
1211 GList listhead = {0};
1213 /* The reparent will have put the native window topmost in the native parent,
1214 * which may be wrong wrt other native windows in the non-native hierarchy,
1216 above = find_native_sibling_above (private->parent, private);
1219 listhead.data = window;
1220 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
1226 gdk_window_show_unraised (window);
1228 _gdk_syntesize_crossing_events_for_geometry_change (window);
1232 * gdk_window_set_has_native:
1233 * @window: a #GdkWindow
1234 * @has_native: whethe the window should have a native window
1236 * Tries to create or remove a window-system native window for this
1237 * GdkWindow. This may fail in some situations. For instance:
1239 * Toplevel and foreign windows must have a native window.
1240 * Offscreen window and children of them can never have native windows.
1241 * Some backends may not support native child windows.
1245 gdk_window_set_has_native (GdkWindow *window, gboolean has_native)
1247 GdkWindowObject *private;
1248 GdkWindowObject *impl_window;
1249 GdkDrawable *new_impl, *old_impl;
1252 GdkWindowAttr attributes;
1253 GdkWindowObject *above;
1256 g_return_if_fail (GDK_IS_WINDOW (window));
1258 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT ||
1259 GDK_WINDOW_DESTROYED (window))
1262 private = (GdkWindowObject *) window;
1266 /* Create native window */
1268 if (gdk_window_has_impl (private))
1269 /* Already has an impl, either native (ok) or
1270 offscreen (not supported). Bail. */
1273 impl_window = gdk_window_get_impl_window (private);
1274 if (impl_window->window_type == GDK_WINDOW_OFFSCREEN)
1275 return; /* native in offscreens not supported */
1277 screen = gdk_drawable_get_screen (window);
1278 visual = gdk_drawable_get_visual (window);
1280 attributes.colormap = gdk_drawable_get_colormap (window);
1282 old_impl = private->impl;
1283 _gdk_window_impl_new (window, (GdkWindow *)private->parent, screen, visual,
1284 get_native_event_mask (private), &attributes, GDK_WA_COLORMAP);
1285 new_impl = private->impl;
1287 private->impl = old_impl;
1288 change_impl (private, private, new_impl);
1290 /* Native window creation will put the native window topmost in the
1291 * native parent, which may be wrong wrt other native windows in the
1292 * non-native hierarchy, so restack */
1293 above = find_native_sibling_above (private->parent, private);
1296 listhead.data = window;
1297 listhead.prev = NULL;
1298 listhead.next = NULL;
1299 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
1303 recompute_visible_regions (private, FALSE, FALSE);
1305 /* The shape may not have been set, as the clip region doesn't actually
1306 change, so do it here manually */
1307 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region ((GdkWindow *)private, private->clip_region, 0, 0);
1309 reparent_to_impl (private);
1311 if (!private->input_only)
1313 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, &private->bg_color);
1314 if (private->bg_pixmap != NULL)
1315 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, private->bg_pixmap);
1318 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_shape_combine_region ((GdkWindow *)private, private->input_shape, 0, 0);
1320 if (gdk_window_is_viewable (window))
1321 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show (window);
1325 /* Remove native window */
1327 if (!gdk_window_has_impl (private))
1328 return; /* Not native, can't remove */
1330 if (private->window_type == GDK_WINDOW_OFFSCREEN)
1331 return; /* Not native, can't remove */
1333 if (private->parent == NULL ||
1334 GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
1335 return; /* toplevel, must be native */
1337 g_warning ("Tried to turn native window to client side window, this is not supported yet.");
1339 /* TODO: remove native */
1344 window_remove_filters (GdkWindow *window)
1346 GdkWindowObject *obj = (GdkWindowObject*) window;
1352 for (tmp_list = obj->filters; tmp_list; tmp_list = tmp_list->next)
1353 g_free (tmp_list->data);
1355 g_list_free (obj->filters);
1356 obj->filters = NULL;
1361 * _gdk_window_destroy_hierarchy:
1362 * @window: a #GdkWindow
1363 * @recursing: If TRUE, then this is being called because a parent
1365 * @recursing_native: If TRUE, then this is being called because a native parent
1366 * was destroyed. This generally means that the call to the
1367 * windowing system to destroy the window can be omitted, since
1368 * it will be destroyed as a result of the parent being destroyed.
1369 * Unless @foreign_destroy.
1370 * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
1371 * external agency. The window has already been destroyed and no
1372 * windowing system calls should be made. (This may never happen
1373 * for some windowing systems.)
1375 * Internal function to destroy a window. Like gdk_window_destroy(),
1376 * but does not drop the reference count created by gdk_window_new().
1379 _gdk_window_destroy_hierarchy (GdkWindow *window,
1381 gboolean recursing_native,
1382 gboolean foreign_destroy)
1384 GdkWindowObject *private;
1385 GdkWindowObject *temp_private;
1386 GdkWindow *temp_window;
1388 GdkDisplay *display;
1392 g_return_if_fail (GDK_IS_WINDOW (window));
1394 private = (GdkWindowObject*) window;
1396 if (GDK_WINDOW_DESTROYED (window))
1399 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
1400 screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
1401 temp_window = g_object_get_qdata (G_OBJECT (screen), quark_pointer_window);
1402 if (temp_window == window)
1403 g_object_set_qdata (G_OBJECT (screen), quark_pointer_window, NULL);
1406 switch (GDK_WINDOW_TYPE (window))
1408 case GDK_WINDOW_ROOT:
1409 if (!screen->closed)
1411 g_error ("attempted to destroy root window");
1414 /* else fall thru */
1415 case GDK_WINDOW_TOPLEVEL:
1416 case GDK_WINDOW_CHILD:
1417 case GDK_WINDOW_DIALOG:
1418 case GDK_WINDOW_TEMP:
1419 case GDK_WINDOW_FOREIGN:
1420 case GDK_WINDOW_OFFSCREEN:
1421 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN && !foreign_destroy)
1423 /* Logically, it probably makes more sense to send
1424 * a "destroy yourself" message to the foreign window
1425 * whether or not it's in our hierarchy; but for historical
1426 * reasons, we only send "destroy yourself" messages to
1427 * foreign windows in our hierarchy.
1429 if (private->parent)
1430 _gdk_windowing_window_destroy_foreign (window);
1432 /* Also for historical reasons, we remove any filters
1433 * on a foreign window when it or a parent is destroyed;
1434 * this likely causes problems if two separate portions
1435 * of code are maintaining filter lists on a foreign window.
1437 window_remove_filters (window);
1441 if (private->parent)
1443 GdkWindowObject *parent_private = (GdkWindowObject *)private->parent;
1445 if (parent_private->children)
1446 parent_private->children = g_list_remove (parent_private->children, window);
1449 GDK_WINDOW_IS_MAPPED (window))
1451 recompute_visible_regions (private, TRUE, FALSE);
1452 gdk_window_invalidate_in_parent (private);
1456 gdk_window_free_paint_stack (window);
1458 if (private->bg_pixmap &&
1459 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
1460 private->bg_pixmap != GDK_NO_BG)
1462 g_object_unref (private->bg_pixmap);
1463 private->bg_pixmap = NULL;
1466 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN)
1467 g_assert (private->children == NULL);
1470 children = tmp = private->children;
1471 private->children = NULL;
1475 temp_window = tmp->data;
1478 temp_private = (GdkWindowObject*) temp_window;
1480 _gdk_window_destroy_hierarchy (temp_window,
1482 recursing_native || gdk_window_has_impl (private),
1486 g_list_free (children);
1489 _gdk_window_clear_update_area (window);
1491 if (private->cairo_surface)
1493 cairo_surface_finish (private->cairo_surface);
1494 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
1498 if (gdk_window_has_impl (private))
1500 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->destroy (window, recursing_native, foreign_destroy);
1504 /* hide to make sure we repaint and break grabs */
1505 gdk_window_hide (window);
1508 private->state |= GDK_WINDOW_STATE_WITHDRAWN;
1509 private->parent = NULL;
1510 private->destroyed = TRUE;
1512 window_remove_filters (window);
1514 gdk_drawable_set_colormap (GDK_DRAWABLE (window), NULL);
1516 /* If we own the redirect, free it */
1517 if (private->redirect && private->redirect->redirected == private)
1518 gdk_window_redirect_free (private->redirect);
1520 private->redirect = NULL;
1522 if (display->pointer_info.toplevel_under_pointer == window)
1524 g_object_unref (display->pointer_info.toplevel_under_pointer);
1525 display->pointer_info.toplevel_under_pointer = NULL;
1533 * _gdk_window_destroy:
1534 * @window: a #GdkWindow
1535 * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
1536 * external agency. The window has already been destroyed and no
1537 * windowing system calls should be made. (This may never happen
1538 * for some windowing systems.)
1540 * Internal function to destroy a window. Like gdk_window_destroy(),
1541 * but does not drop the reference count created by gdk_window_new().
1544 _gdk_window_destroy (GdkWindow *window,
1545 gboolean foreign_destroy)
1547 _gdk_window_destroy_hierarchy (window, FALSE, FALSE, foreign_destroy);
1551 * gdk_window_destroy:
1552 * @window: a #GdkWindow
1554 * Destroys the window system resources associated with @window and decrements @window's
1555 * reference count. The window system resources for all children of @window are also
1556 * destroyed, but the children's reference counts are not decremented.
1558 * Note that a window will not be destroyed automatically when its reference count
1559 * reaches zero. You must call this function yourself before that happens.
1563 gdk_window_destroy (GdkWindow *window)
1565 _gdk_window_destroy_hierarchy (window, FALSE, FALSE, FALSE);
1566 g_object_unref (window);
1570 * gdk_window_set_user_data:
1571 * @window: a #GdkWindow
1572 * @user_data: user data
1574 * For most purposes this function is deprecated in favor of
1575 * g_object_set_data(). However, for historical reasons GTK+ stores
1576 * the #GtkWidget that owns a #GdkWindow as user data on the
1577 * #GdkWindow. So, custom widget implementations should use
1578 * this function for that. If GTK+ receives an event for a #GdkWindow,
1579 * and the user data for the window is non-%NULL, GTK+ will assume the
1580 * user data is a #GtkWidget, and forward the event to that widget.
1584 gdk_window_set_user_data (GdkWindow *window,
1587 g_return_if_fail (GDK_IS_WINDOW (window));
1589 ((GdkWindowObject*)window)->user_data = user_data;
1593 * gdk_window_get_user_data:
1594 * @window: a #GdkWindow
1595 * @data: return location for user data
1597 * Retrieves the user data for @window, which is normally the widget
1598 * that @window belongs to. See gdk_window_set_user_data().
1602 gdk_window_get_user_data (GdkWindow *window,
1605 g_return_if_fail (GDK_IS_WINDOW (window));
1607 *data = ((GdkWindowObject*)window)->user_data;
1611 * gdk_window_get_window_type:
1612 * @window: a #GdkWindow
1614 * Gets the type of the window. See #GdkWindowType.
1616 * Return value: type of window
1619 gdk_window_get_window_type (GdkWindow *window)
1621 g_return_val_if_fail (GDK_IS_WINDOW (window), (GdkWindowType) -1);
1623 return GDK_WINDOW_TYPE (window);
1627 * gdk_window_get_position:
1628 * @window: a #GdkWindow
1629 * @x: X coordinate of window
1630 * @y: Y coordinate of window
1632 * Obtains the position of the window as reported in the
1633 * most-recently-processed #GdkEventConfigure. Contrast with
1634 * gdk_window_get_geometry() which queries the X server for the
1635 * current window position, regardless of which events have been
1636 * received or processed.
1638 * The position coordinates are relative to the window's parent window.
1642 gdk_window_get_position (GdkWindow *window,
1646 GdkWindowObject *obj;
1648 g_return_if_fail (GDK_IS_WINDOW (window));
1650 obj = (GdkWindowObject*) window;
1659 * gdk_window_get_parent:
1660 * @window: a #GdkWindow
1662 * Obtains the parent of @window, as known to GDK. Does not query the
1663 * X server; thus this returns the parent as passed to gdk_window_new(),
1664 * not the actual parent. This should never matter unless you're using
1665 * Xlib calls mixed with GDK calls on the X11 platform. It may also
1666 * matter for toplevel windows, because the window manager may choose
1669 * Return value: parent of @window
1672 gdk_window_get_parent (GdkWindow *window)
1674 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1676 return (GdkWindow*) ((GdkWindowObject*) window)->parent;
1680 * gdk_window_get_toplevel:
1681 * @window: a #GdkWindow
1683 * Gets the toplevel window that's an ancestor of @window.
1685 * Any window type but %GDK_WINDOW_CHILD is considered a
1686 * toplevel window, as is a %GDK_WINDOW_CHILD window that
1687 * has a root window as parent.
1689 * Return value: the toplevel window containing @window
1692 gdk_window_get_toplevel (GdkWindow *window)
1694 GdkWindowObject *obj;
1696 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1698 obj = (GdkWindowObject *)window;
1700 while (GDK_WINDOW_TYPE (obj) == GDK_WINDOW_CHILD)
1702 if (obj->parent == NULL ||
1703 GDK_WINDOW_TYPE (obj->parent) == GDK_WINDOW_ROOT)
1708 return GDK_WINDOW (obj);
1712 * gdk_window_get_children:
1713 * @window: a #GdkWindow
1715 * Gets the list of children of @window known to GDK.
1716 * This function only returns children created via GDK,
1717 * so for example it's useless when used with the root window;
1718 * it only returns windows an application created itself.
1720 * The returned list must be freed, but the elements in the
1723 * Return value: list of child windows inside @window
1726 gdk_window_get_children (GdkWindow *window)
1728 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1730 if (GDK_WINDOW_DESTROYED (window))
1733 return g_list_copy (GDK_WINDOW_OBJECT (window)->children);
1737 * gdk_window_peek_children:
1738 * @window: a #GdkWindow
1740 * Like gdk_window_get_children(), but does not copy the list of
1741 * children, so the list does not need to be freed.
1743 * Return value: a reference to the list of child windows in @window
1746 gdk_window_peek_children (GdkWindow *window)
1748 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1750 if (GDK_WINDOW_DESTROYED (window))
1753 return GDK_WINDOW_OBJECT (window)->children;
1757 * gdk_window_add_filter:
1758 * @window: a #GdkWindow
1759 * @function: filter callback
1760 * @data: data to pass to filter callback
1762 * Adds an event filter to @window, allowing you to intercept events
1763 * before they reach GDK. This is a low-level operation and makes it
1764 * easy to break GDK and/or GTK+, so you have to know what you're
1765 * doing. Pass %NULL for @window to get all events for all windows,
1766 * instead of events for a specific window.
1768 * See gdk_display_add_client_message_filter() if you are interested
1769 * in X ClientMessage events.
1772 gdk_window_add_filter (GdkWindow *window,
1773 GdkFilterFunc function,
1776 GdkWindowObject *private;
1778 GdkEventFilter *filter;
1780 g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
1782 private = (GdkWindowObject*) window;
1783 if (private && GDK_WINDOW_DESTROYED (window))
1786 /* Filters are for the native events on the native window, so
1787 ensure there is a native window. */
1789 gdk_window_set_has_native (window, TRUE);
1792 tmp_list = private->filters;
1794 tmp_list = _gdk_default_filters;
1798 filter = (GdkEventFilter *)tmp_list->data;
1799 if ((filter->function == function) && (filter->data == data))
1801 tmp_list = tmp_list->next;
1804 filter = g_new (GdkEventFilter, 1);
1805 filter->function = function;
1806 filter->data = data;
1809 private->filters = g_list_append (private->filters, filter);
1811 _gdk_default_filters = g_list_append (_gdk_default_filters, filter);
1815 * gdk_window_remove_filter:
1816 * @window: a #GdkWindow
1817 * @function: previously-added filter function
1818 * @data: user data for previously-added filter function
1820 * Remove a filter previously added with gdk_window_add_filter().
1824 gdk_window_remove_filter (GdkWindow *window,
1825 GdkFilterFunc function,
1828 GdkWindowObject *private;
1829 GList *tmp_list, *node;
1830 GdkEventFilter *filter;
1832 g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
1834 private = (GdkWindowObject*) window;
1837 tmp_list = private->filters;
1839 tmp_list = _gdk_default_filters;
1843 filter = (GdkEventFilter *)tmp_list->data;
1845 tmp_list = tmp_list->next;
1847 if ((filter->function == function) && (filter->data == data))
1850 private->filters = g_list_remove_link (private->filters, node);
1852 _gdk_default_filters = g_list_remove_link (_gdk_default_filters, node);
1853 g_list_free_1 (node);
1862 * gdk_screen_get_toplevel_windows:
1863 * @screen: The #GdkScreen where the toplevels are located.
1865 * Obtains a list of all toplevel windows known to GDK on the screen @screen.
1866 * A toplevel window is a child of the root window (see
1867 * gdk_get_default_root_window()).
1869 * The returned list should be freed with g_list_free(), but
1870 * its elements need not be freed.
1872 * Return value: list of toplevel windows, free with g_list_free()
1877 gdk_screen_get_toplevel_windows (GdkScreen *screen)
1879 GdkWindow * root_window;
1880 GList *new_list = NULL;
1883 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
1885 root_window = gdk_screen_get_root_window (screen);
1887 tmp_list = ((GdkWindowObject *)root_window)->children;
1890 if (GDK_WINDOW_TYPE (tmp_list->data) != GDK_WINDOW_FOREIGN)
1891 new_list = g_list_prepend (new_list, tmp_list->data);
1892 tmp_list = tmp_list->next;
1899 * gdk_window_get_toplevels:
1901 * Obtains a list of all toplevel windows known to GDK on the default
1902 * screen (see gdk_screen_get_toplevel_windows()).
1903 * A toplevel window is a child of the root window (see
1904 * gdk_get_default_root_window()).
1906 * The returned list should be freed with g_list_free(), but
1907 * its elements need not be freed.
1909 * Return value: list of toplevel windows, free with g_list_free()
1911 * Deprecated: 2.16: Use gdk_screen_get_toplevel_windows() instead.
1914 gdk_window_get_toplevels (void)
1916 return gdk_screen_get_toplevel_windows (gdk_screen_get_default ());
1920 * gdk_window_is_visible:
1921 * @window: a #GdkWindow
1923 * Checks whether the window has been mapped (with gdk_window_show() or
1924 * gdk_window_show_unraised()).
1926 * Return value: %TRUE if the window is mapped
1929 gdk_window_is_visible (GdkWindow *window)
1931 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
1933 return GDK_WINDOW_IS_MAPPED (window);
1937 * gdk_window_is_viewable:
1938 * @window: a #GdkWindow
1940 * Check if the window and all ancestors of the window are
1941 * mapped. (This is not necessarily "viewable" in the X sense, since
1942 * we only check as far as we have GDK window parents, not to the root
1945 * Return value: %TRUE if the window is viewable
1948 gdk_window_is_viewable (GdkWindow *window)
1950 GdkWindowObject *private = (GdkWindowObject *)window;
1952 GdkWindow *root_window;
1954 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
1956 screen = gdk_drawable_get_screen (window);
1957 root_window = gdk_screen_get_root_window (screen);
1960 (private != (GdkWindowObject *)root_window) &&
1961 (GDK_WINDOW_TYPE (private) != GDK_WINDOW_FOREIGN))
1963 if (GDK_WINDOW_DESTROYED (private) || !GDK_WINDOW_IS_MAPPED (private))
1966 private = (GdkWindowObject *)private->parent;
1973 * gdk_window_get_state:
1974 * @window: a #GdkWindow
1976 * Gets the bitwise OR of the currently active window state flags,
1977 * from the #GdkWindowState enumeration.
1979 * Return value: window state bitfield
1982 gdk_window_get_state (GdkWindow *window)
1984 GdkWindowObject *private = (GdkWindowObject *)window;
1986 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
1988 return private->state;
1992 /* This creates an empty "implicit" paint region for the impl window.
1993 * By itself this does nothing, but real paints to this window
1994 * or children of it can use this pixmap as backing to avoid allocating
1995 * multiple pixmaps for subwindow rendering. When doing so they
1996 * add to the region of the implicit paint region, which will be
1997 * pushed to the window when the implicit paint region is ended.
1998 * Such paints should not copy anything to the window on paint end, but
1999 * should rely on the implicit paint end.
2000 * The implicit paint will be automatically ended if someone draws
2001 * directly to the window or a child window.
2004 gdk_window_begin_implicit_paint (GdkWindow *window, GdkRectangle *rect)
2006 GdkWindowObject *private = (GdkWindowObject *)window;
2007 GdkWindowPaint *paint;
2009 g_assert (gdk_window_has_impl (private));
2011 if (GDK_IS_PAINTABLE (private->impl))
2012 return FALSE; /* Implementation does double buffering */
2014 if (private->paint_stack != NULL ||
2015 private->implicit_paint != NULL)
2016 return FALSE; /* Don't stack implicit paints */
2018 paint = g_new (GdkWindowPaint, 1);
2019 paint->region = gdk_region_new (); /* Empty */
2020 paint->x_offset = rect->x;
2021 paint->y_offset = rect->y;
2022 paint->uses_implicit = FALSE;
2023 paint->surface = NULL;
2025 gdk_pixmap_new (window,
2026 MAX (rect->width, 1), MAX (rect->height, 1), -1);
2028 private->implicit_paint = paint;
2033 /* Ensure that all content related to this (sub)window is pushed to the
2036 gdk_window_flush_implicit_paint (GdkWindow *window)
2038 GdkWindowObject *private = (GdkWindowObject *)window;
2039 GdkWindowObject *impl_window;
2040 GdkWindowPaint *paint;
2044 /* Ensure that there is no explicit paint region. */
2045 g_assert (private->paint_stack == NULL);
2047 impl_window = gdk_window_get_impl_window (private);
2048 if (impl_window->implicit_paint == NULL)
2051 paint = impl_window->implicit_paint;
2052 region = gdk_region_copy (private->clip_region_with_children);
2053 gdk_region_offset (region, private->abs_x, private->abs_y);
2054 gdk_region_intersect (region, paint->region);
2056 if (!gdk_region_empty (region))
2058 /* Some regions are valid, push these to window now */
2059 tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
2060 _gdk_gc_set_clip_region_internal (tmp_gc, region, TRUE);
2061 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2062 0, 0, paint->x_offset, paint->y_offset, -1, -1);
2063 /* Reset clip region of the cached GdkGC */
2064 gdk_gc_set_clip_region (tmp_gc, NULL);
2066 /* Remove flushed region from the implicit paint */
2067 gdk_region_subtract (paint->region, region);
2070 gdk_region_destroy (region);
2073 /* Ends an implicit paint, paired with gdk_window_begin_implicit_paint returning TRUE */
2075 gdk_window_end_implicit_paint (GdkWindow *window)
2077 GdkWindowObject *private = (GdkWindowObject *)window;
2078 GdkWindowPaint *paint;
2081 g_assert (gdk_window_has_impl (private));
2083 g_assert (private->implicit_paint != NULL);
2085 paint = private->implicit_paint;
2087 private->implicit_paint = NULL;
2089 if (!gdk_region_empty (paint->region))
2091 /* Some regions are valid, push these to window now */
2092 tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
2093 _gdk_gc_set_clip_region_internal (tmp_gc, paint->region, TRUE);
2094 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2095 0, 0, paint->x_offset, paint->y_offset, -1, -1);
2096 /* Reset clip region of the cached GdkGC */
2097 gdk_gc_set_clip_region (tmp_gc, NULL);
2100 g_object_unref (paint->pixmap);
2105 * gdk_window_begin_paint_rect:
2106 * @window: a #GdkWindow
2107 * @rectangle: rectangle you intend to draw to
2109 * A convenience wrapper around gdk_window_begin_paint_region() which
2110 * creates a rectangular region for you. See
2111 * gdk_window_begin_paint_region() for details.
2115 gdk_window_begin_paint_rect (GdkWindow *window,
2116 const GdkRectangle *rectangle)
2120 g_return_if_fail (GDK_IS_WINDOW (window));
2122 region = gdk_region_rectangle (rectangle);
2123 gdk_window_begin_paint_region (window, region);
2124 gdk_region_destroy (region);
2127 #ifdef GDK_WINDOWING_X11
2128 #include "x11/gdkx.h"
2132 * gdk_window_begin_paint_region:
2133 * @window: a #GdkWindow
2134 * @region: region you intend to draw to
2136 * Indicates that you are beginning the process of redrawing @region.
2137 * A backing store (offscreen buffer) large enough to contain @region
2138 * will be created. The backing store will be initialized with the
2139 * background color or background pixmap for @window. Then, all
2140 * drawing operations performed on @window will be diverted to the
2141 * backing store. When you call gdk_window_end_paint(), the backing
2142 * store will be copied to @window, making it visible onscreen. Only
2143 * the part of @window contained in @region will be modified; that is,
2144 * drawing operations are clipped to @region.
2146 * The net result of all this is to remove flicker, because the user
2147 * sees the finished product appear all at once when you call
2148 * gdk_window_end_paint(). If you draw to @window directly without
2149 * calling gdk_window_begin_paint_region(), the user may see flicker
2150 * as individual drawing operations are performed in sequence. The
2151 * clipping and background-initializing features of
2152 * gdk_window_begin_paint_region() are conveniences for the
2153 * programmer, so you can avoid doing that work yourself.
2155 * When using GTK+, the widget system automatically places calls to
2156 * gdk_window_begin_paint_region() and gdk_window_end_paint() around
2157 * emissions of the expose_event signal. That is, if you're writing an
2158 * expose event handler, you can assume that the exposed area in
2159 * #GdkEventExpose has already been cleared to the window background,
2160 * is already set as the clip region, and already has a backing store.
2161 * Therefore in most cases, application code need not call
2162 * gdk_window_begin_paint_region(). (You can disable the automatic
2163 * calls around expose events on a widget-by-widget basis by calling
2164 * gtk_widget_set_double_buffered().)
2166 * If you call this function multiple times before calling the
2167 * matching gdk_window_end_paint(), the backing stores are pushed onto
2168 * a stack. gdk_window_end_paint() copies the topmost backing store
2169 * onscreen, subtracts the topmost region from all other regions in
2170 * the stack, and pops the stack. All drawing operations affect only
2171 * the topmost backing store in the stack. One matching call to
2172 * gdk_window_end_paint() is required for each call to
2173 * gdk_window_begin_paint_region().
2177 gdk_window_begin_paint_region (GdkWindow *window,
2178 const GdkRegion *region)
2180 #ifdef USE_BACKING_STORE
2181 GdkWindowObject *private = (GdkWindowObject *)window;
2182 GdkRectangle clip_box;
2183 GdkWindowPaint *paint, *implicit_paint;
2184 GdkWindowObject *impl_window;
2187 g_return_if_fail (GDK_IS_WINDOW (window));
2189 if (GDK_WINDOW_DESTROYED (window))
2192 if (GDK_IS_PAINTABLE (private->impl))
2194 GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
2196 if (iface->begin_paint_region)
2197 iface->begin_paint_region ((GdkPaintable*)private->impl, window, region);
2202 impl_window = gdk_window_get_impl_window (private);
2203 implicit_paint = impl_window->implicit_paint;
2205 paint = g_new (GdkWindowPaint, 1);
2206 paint->region = gdk_region_copy (region);
2207 paint->region_tag = new_region_tag ();
2209 gdk_region_intersect (paint->region, private->clip_region_with_children);
2210 gdk_region_get_clipbox (paint->region, &clip_box);
2212 /* Convert to impl coords */
2213 gdk_region_offset (paint->region, private->abs_x, private->abs_y);
2215 /* Mark the region as valid on the implicit paint */
2218 gdk_region_union (implicit_paint->region, paint->region);
2220 /* Convert back to normal coords */
2221 gdk_region_offset (paint->region, -private->abs_x, -private->abs_y);
2227 paint->uses_implicit = TRUE;
2228 paint->pixmap = g_object_ref (implicit_paint->pixmap);
2229 paint->x_offset = -private->abs_x + implicit_paint->x_offset;
2230 paint->y_offset = -private->abs_y + implicit_paint->y_offset;
2232 /* It would be nice if we had some cairo support here so we
2233 could set the clip rect on the cairo surface */
2234 width = private->abs_x + private->width;
2235 height = private->abs_y + private->height;
2237 paint->surface = _gdk_drawable_create_cairo_surface (paint->pixmap, width, height);
2242 paint->uses_implicit = FALSE;
2243 paint->x_offset = clip_box.x;
2244 paint->y_offset = clip_box.y;
2246 gdk_pixmap_new (window,
2247 MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1);
2248 paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap);
2252 cairo_surface_set_device_offset (paint->surface,
2253 -paint->x_offset, -paint->y_offset);
2255 for (list = private->paint_stack; list != NULL; list = list->next)
2257 GdkWindowPaint *tmp_paint = list->data;
2259 gdk_region_subtract (tmp_paint->region, paint->region);
2262 private->paint_stack = g_slist_prepend (private->paint_stack, paint);
2264 if (!gdk_region_empty (paint->region))
2266 gdk_window_clear_backing_region (window,
2270 #endif /* USE_BACKING_STORE */
2274 setup_redirect_clip (GdkWindow *window,
2279 GdkWindowObject *private = (GdkWindowObject *)window;
2280 GdkRegion *visible_region;
2281 GdkRectangle dest_rect;
2283 GdkWindow *toplevel;
2284 int x_offset, y_offset;
2286 toplevel = GDK_WINDOW (private->redirect->redirected);
2288 /* Get the clip region for gc clip rect + window hierarchy in
2289 window relative coords */
2291 _gdk_window_calculate_full_clip_region (window, toplevel,
2296 /* Compensate for the source pos/size */
2297 x_offset -= private->redirect->src_x;
2298 y_offset -= private->redirect->src_y;
2299 dest_rect.x = -x_offset;
2300 dest_rect.y = -y_offset;
2301 dest_rect.width = private->redirect->width;
2302 dest_rect.height = private->redirect->height;
2303 tmpreg = gdk_region_rectangle (&dest_rect);
2304 gdk_region_intersect (visible_region, tmpreg);
2305 gdk_region_destroy (tmpreg);
2307 /* Compensate for the dest pos */
2308 x_offset += private->redirect->dest_x;
2309 y_offset += private->redirect->dest_y;
2311 gdk_gc_set_clip_region (gc, visible_region); /* This resets clip origin! */
2313 /* offset clip and tiles from window coords to pixmaps coords */
2314 gdk_gc_offset (gc, -x_offset, -y_offset);
2316 gdk_region_destroy (visible_region);
2318 *x_offset_out = x_offset;
2319 *y_offset_out = y_offset;
2323 * gdk_window_end_paint:
2324 * @window: a #GdkWindow
2326 * Indicates that the backing store created by the most recent call to
2327 * gdk_window_begin_paint_region() should be copied onscreen and
2328 * deleted, leaving the next-most-recent backing store or no backing
2329 * store at all as the active paint region. See
2330 * gdk_window_begin_paint_region() for full details. It is an error to
2331 * call this function without a matching
2332 * gdk_window_begin_paint_region() first.
2336 gdk_window_end_paint (GdkWindow *window)
2338 #ifdef USE_BACKING_STORE
2339 GdkWindowObject *private = (GdkWindowObject *)window;
2340 GdkWindowObject *composited;
2341 GdkWindowPaint *paint;
2343 GdkRectangle clip_box;
2344 gint x_offset, y_offset;
2345 GdkRegion *full_clip;
2347 g_return_if_fail (GDK_IS_WINDOW (window));
2349 if (GDK_WINDOW_DESTROYED (window))
2352 if (GDK_IS_PAINTABLE (private->impl))
2354 GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
2356 if (iface->end_paint)
2357 iface->end_paint ((GdkPaintable*)private->impl);
2361 if (private->paint_stack == NULL)
2363 g_warning (G_STRLOC": no preceding call to gdk_window_begin_paint_region(), see documentation");
2367 paint = private->paint_stack->data;
2369 private->paint_stack = g_slist_delete_link (private->paint_stack,
2370 private->paint_stack);
2372 gdk_region_get_clipbox (paint->region, &clip_box);
2374 tmp_gc = _gdk_drawable_get_scratch_gc (window, FALSE);
2376 x_offset = -private->abs_x;
2377 y_offset = -private->abs_y;
2379 if (!paint->uses_implicit)
2381 gdk_window_flush_outstanding_moves (window);
2383 full_clip = gdk_region_copy (private->clip_region_with_children);
2384 gdk_region_intersect (full_clip, paint->region);
2385 _gdk_gc_set_clip_region_internal (tmp_gc, full_clip, TRUE); /* Takes ownership of full_clip */
2386 gdk_gc_set_clip_origin (tmp_gc, - x_offset, - y_offset);
2387 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2388 clip_box.x - paint->x_offset,
2389 clip_box.y - paint->y_offset,
2390 clip_box.x - x_offset, clip_box.y - y_offset,
2391 clip_box.width, clip_box.height);
2394 if (private->redirect)
2396 int x_offset, y_offset;
2398 /* TODO: Should also use paint->region for clipping */
2399 setup_redirect_clip (window, tmp_gc, &x_offset, &y_offset);
2400 gdk_draw_drawable (private->redirect->pixmap, tmp_gc, paint->pixmap,
2401 clip_box.x - paint->x_offset,
2402 clip_box.y - paint->y_offset,
2403 clip_box.x + x_offset,
2404 clip_box.y + y_offset,
2405 clip_box.width, clip_box.height);
2408 /* Reset clip region of the cached GdkGC */
2409 gdk_gc_set_clip_region (tmp_gc, NULL);
2411 cairo_surface_destroy (paint->surface);
2412 g_object_unref (paint->pixmap);
2413 gdk_region_destroy (paint->region);
2416 /* find a composited window in our hierarchy to signal its
2417 * parent to redraw, calculating the clip box as we go...
2419 * stop if parent becomes NULL since then we'd have nowhere
2420 * to draw (ie: 'composited' will always be non-NULL here).
2422 for (composited = private;
2424 composited = composited->parent)
2428 gdk_drawable_get_size (GDK_DRAWABLE (composited->parent),
2431 clip_box.x += composited->x;
2432 clip_box.y += composited->y;
2433 clip_box.width = MIN (clip_box.width, width - clip_box.x);
2434 clip_box.height = MIN (clip_box.height, height - clip_box.y);
2436 if (composited->composited)
2438 gdk_window_invalidate_rect (GDK_WINDOW (composited->parent),
2443 #endif /* USE_BACKING_STORE */
2447 gdk_window_free_paint_stack (GdkWindow *window)
2449 GdkWindowObject *private = (GdkWindowObject *)window;
2451 if (private->paint_stack)
2453 GSList *tmp_list = private->paint_stack;
2457 GdkWindowPaint *paint = tmp_list->data;
2459 if (tmp_list == private->paint_stack)
2460 g_object_unref (paint->pixmap);
2462 gdk_region_destroy (paint->region);
2465 tmp_list = tmp_list->next;
2468 g_slist_free (private->paint_stack);
2469 private->paint_stack = NULL;
2474 do_move_region_bits_on_impl (GdkWindowObject *impl_window,
2475 GdkRegion *dest_region, /* In impl window coords */
2479 GdkRectangle copy_rect;
2480 GdkWindowObject *private;
2482 /* We need to get data from subwindows here, because we might have
2483 * shaped a native window over the moving region (with bg none,
2484 * so the pixels are still there). In fact we might need to get data
2485 * from overlapping native window that are not children of this window,
2486 * so we copy from the toplevel with INCLUDE_INFERIORS.
2488 private = impl_window;
2489 while (private->parent != NULL &&
2490 GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
2492 dx -= private->parent->abs_x + private->x;
2493 dy -= private->parent->abs_y + private->y;
2494 private = gdk_window_get_impl_window (private->parent);
2496 tmp_gc = _gdk_drawable_get_subwindow_scratch_gc ((GdkWindow *)private);
2498 /* The region area is moved and we queue translations for all expose events
2499 to the source area that were sent prior to the copy */
2500 gdk_region_offset (dest_region, -dx, -dy); /* Temporarily move to source area */
2501 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->queue_translation ((GdkWindow *)impl_window,
2502 dest_region, dx, dy);
2503 gdk_region_offset (dest_region, dx, dy); /* back to dest area */
2505 gdk_region_get_clipbox (dest_region, ©_rect);
2507 gdk_gc_set_clip_region (tmp_gc, dest_region);
2508 gdk_draw_drawable (impl_window->impl,
2511 copy_rect.x-dx, copy_rect.y-dy,
2512 copy_rect.x, copy_rect.y,
2513 copy_rect.width, copy_rect.height);
2514 gdk_gc_set_clip_region (tmp_gc, NULL);
2517 static GdkWindowRegionMove *
2518 gdk_window_region_move_new (GdkRegion *region,
2521 GdkWindowRegionMove *move;
2523 move = g_slice_new (GdkWindowRegionMove);
2524 move->dest_region = gdk_region_copy (region);
2532 gdk_window_region_move_free (GdkWindowRegionMove *move)
2534 gdk_region_destroy (move->dest_region);
2535 g_slice_free (GdkWindowRegionMove, move);
2539 append_move_region (GdkWindowObject *impl_window,
2540 GdkRegion *new_dest_region,
2543 GdkWindowRegionMove *move, *old_move;
2544 GdkRegion *new_total_region, *old_total_region;
2545 GdkRegion *source_overlaps_destination;
2546 GdkRegion *non_overwritten;
2547 gboolean added_move;
2550 if (gdk_region_empty (new_dest_region))
2553 /* In principle this could just append the move to the list of outstanding
2554 moves that will be replayed before drawing anything when we're handling
2555 exposes. However, we'd like to do a bit better since its commonly the case
2556 that we get multiple copies where A is copied to B and then B is copied
2557 to C, and we'd like to express this as a simple copy A to C operation. */
2559 /* We approach this by taking the new move and pushing it ahead of moves
2560 starting at the end of the list and stopping when its not safe to do so.
2561 Its not safe to push past a move is either the source of the new move
2562 is in the destination of the old move, or if the destination of the new
2563 move is in the source of the new move, or if the destination of the new
2564 move overlaps the destination of the old move. We simplify this by
2565 just comparing the total regions (src + dest) */
2566 new_total_region = gdk_region_copy (new_dest_region);
2567 gdk_region_offset (new_total_region, -dx, -dy);
2568 gdk_region_union (new_total_region, new_dest_region);
2571 for (l = g_list_last (impl_window->outstanding_moves); l != NULL; l = prev)
2576 old_total_region = gdk_region_copy (old_move->dest_region);
2577 gdk_region_offset (old_total_region, -old_move->dx, -old_move->dy);
2578 gdk_region_union (old_total_region, old_move->dest_region);
2580 gdk_region_intersect (old_total_region, new_total_region);
2581 /* If these regions intersect then its not safe to push the
2582 new region before the old one */
2583 if (!gdk_region_empty (old_total_region))
2585 /* The area where the new moves source overlaps the old ones
2587 source_overlaps_destination = gdk_region_copy (new_dest_region);
2588 gdk_region_offset (source_overlaps_destination, -dx, -dy);
2589 gdk_region_intersect (source_overlaps_destination, old_move->dest_region);
2590 gdk_region_offset (source_overlaps_destination, dx, dy);
2592 /* We can do all sort of optimizations here, but to do things safely it becomes
2593 quite complicated. However, a very common case is that you copy something first,
2594 then copy all that or a subset of it to a new location (i.e. if you scroll twice
2595 in the same direction). We'd like to detect this case and optimize it to one
2597 if (gdk_region_equal (source_overlaps_destination, new_dest_region))
2599 /* This means we might be able to replace the old move and the new one
2600 with the new one read from the old ones source, and a second copy of
2601 the non-overwritten parts of the old move. However, such a split
2602 is only valid if the source in the old move isn't overwritten
2603 by the destination of the new one */
2605 /* the new destination of old move if split is ok: */
2606 non_overwritten = gdk_region_copy (old_move->dest_region);
2607 gdk_region_subtract (non_overwritten, new_dest_region);
2608 /* move to source region */
2609 gdk_region_offset (non_overwritten, -old_move->dx, -old_move->dy);
2611 gdk_region_intersect (non_overwritten, new_dest_region);
2612 if (gdk_region_empty (non_overwritten))
2615 move = gdk_window_region_move_new (new_dest_region,
2619 impl_window->outstanding_moves =
2620 g_list_insert_before (impl_window->outstanding_moves,
2622 gdk_region_subtract (old_move->dest_region, new_dest_region);
2624 gdk_region_destroy (non_overwritten);
2627 gdk_region_destroy (source_overlaps_destination);
2628 gdk_region_destroy (old_total_region);
2631 gdk_region_destroy (old_total_region);
2634 gdk_region_destroy (new_total_region);
2638 move = gdk_window_region_move_new (new_dest_region, dx, dy);
2641 impl_window->outstanding_moves =
2642 g_list_prepend (impl_window->outstanding_moves,
2645 impl_window->outstanding_moves =
2646 g_list_insert_before (impl_window->outstanding_moves,
2651 /* Moves bits and update area by dx/dy in impl window,
2652 takes ownership of region */
2654 move_region_on_impl (GdkWindowObject *private,
2655 GdkRegion *region, /* In impl window coords */
2658 GdkWindowObject *impl_window;
2660 if ((dx == 0 && dy == 0) ||
2661 gdk_region_empty (region))
2663 gdk_region_destroy (region);
2667 impl_window = gdk_window_get_impl_window (private);
2669 /* Move any old invalid regions in the copy source area by dx/dy */
2670 if (impl_window->update_area)
2672 GdkRegion *update_area;
2673 update_area = gdk_region_copy (region);
2675 /* Convert from target to source */
2676 gdk_region_offset (update_area, -dx, -dy);
2677 gdk_region_intersect (update_area, impl_window->update_area);
2678 gdk_region_subtract (impl_window->update_area, update_area);
2681 gdk_region_offset (update_area, dx, dy);
2682 gdk_region_union (impl_window->update_area, update_area);
2684 /* This area of the destination is now invalid,
2685 so no need to copy to it. */
2686 gdk_region_subtract (region, update_area);
2688 gdk_region_destroy (update_area);
2691 if (1) /* Enable flicker free handling of moves. */
2692 append_move_region (impl_window, region, dx, dy);
2694 do_move_region_bits_on_impl (impl_window,
2697 gdk_region_destroy (region);
2700 /* Flushes all outstanding changes to the window, call this
2701 * before drawing directly to the window (i.e. outside a begin/end_paint pair).
2704 gdk_window_flush_outstanding_moves (GdkWindow *window)
2706 GdkWindowObject *private;
2707 GdkWindowObject *impl_window;
2709 GdkWindowRegionMove *move;
2711 private = (GdkWindowObject *) window;
2713 impl_window = gdk_window_get_impl_window (private);
2715 for (l = impl_window->outstanding_moves; l != NULL; l = l->next)
2719 do_move_region_bits_on_impl (impl_window,
2720 move->dest_region, move->dx, move->dy);
2722 gdk_window_region_move_free (move);
2725 g_list_free (impl_window->outstanding_moves);
2726 impl_window->outstanding_moves = NULL;
2730 gdk_window_flush (GdkWindow *window)
2732 gdk_window_flush_outstanding_moves (window);
2733 gdk_window_flush_implicit_paint (window);
2737 gdk_window_flush_recursive_helper (GdkWindowObject *window,
2740 GdkWindowObject *child;
2743 for (l = window->children; l != NULL; l = l->next)
2747 if (child->impl == impl)
2748 /* Same impl, ignore */
2749 gdk_window_flush_recursive_helper (child, impl);
2751 gdk_window_flush_recursive (child);
2756 gdk_window_flush_recursive (GdkWindowObject *window)
2758 gdk_window_flush ((GdkWindow *)window);
2759 gdk_window_flush_recursive_helper (window, window->impl);
2763 gdk_window_get_offsets (GdkWindow *window,
2767 GdkWindowObject *private = (GdkWindowObject *)window;
2769 if (private->paint_stack)
2771 GdkWindowPaint *paint = private->paint_stack->data;
2772 *x_offset = paint->x_offset;
2773 *y_offset = paint->y_offset;
2777 *x_offset = -private->abs_x;
2778 *y_offset = -private->abs_y;
2783 * gdk_window_get_internal_paint_info:
2784 * @window: a #GdkWindow
2785 * @real_drawable: location to store the drawable to which drawing should be
2787 * @x_offset: location to store the X offset between coordinates in @window,
2788 * and the underlying window system primitive coordinates for
2790 * @y_offset: location to store the Y offset between coordinates in @window,
2791 * and the underlying window system primitive coordinates for
2794 * If you bypass the GDK layer and use windowing system primitives to
2795 * draw directly onto a #GdkWindow, then you need to deal with two
2796 * details: there may be an offset between GDK coordinates and windowing
2797 * system coordinates, and GDK may have redirected drawing to a offscreen
2798 * pixmap as the result of a gdk_window_begin_paint_region() calls.
2799 * This function allows retrieving the information you need to compensate
2800 * for these effects.
2802 * This function exposes details of the GDK implementation, and is thus
2803 * likely to change in future releases of GDK.
2806 gdk_window_get_internal_paint_info (GdkWindow *window,
2807 GdkDrawable **real_drawable,
2813 GdkWindowObject *private;
2815 g_return_if_fail (GDK_IS_WINDOW (window));
2817 private = (GdkWindowObject *)window;
2821 if (private->paint_stack)
2823 GdkWindowPaint *paint = private->paint_stack->data;
2824 *real_drawable = paint->pixmap;
2828 /* This means you're probably gonna be doing some weird shit
2829 directly to the window, so we flush all outstanding stuff */
2830 gdk_window_flush (window);
2831 *real_drawable = window;
2835 gdk_window_get_offsets (window, &x_off, &y_off);
2844 setup_clip_for_draw (GdkDrawable *drawable,
2846 int old_clip_x, int old_clip_y)
2848 GdkWindowObject *private = (GdkWindowObject *)drawable;
2851 if (private->window_type == GDK_WINDOW_ROOT)
2854 if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
2855 clip = private->clip_region_with_children;
2857 clip = private->clip_region;
2859 _gdk_gc_add_drawable_clip (gc,
2862 /* If there was a clip origin set appart from the
2863 * window offset, need to take that into consideration */
2864 -old_clip_x, -old_clip_y);
2868 setup_clip_for_paint (GdkDrawable *drawable,
2869 GdkWindowPaint *paint,
2871 int old_clip_x, int old_clip_y)
2873 _gdk_gc_add_drawable_clip (gc,
2875 /* This includes the window clip */
2877 /* If there was a clip origin set appart from the
2878 * window offset, need to take that into consideration */
2879 -old_clip_x, -old_clip_y);
2883 #define OFFSET_GC(gc) \
2884 gint x_offset, y_offset; \
2885 gint old_clip_x = gc->clip_x_origin; \
2886 gint old_clip_y = gc->clip_y_origin; \
2887 gint old_ts_x = gc->ts_x_origin; \
2888 gint old_ts_y = gc->ts_y_origin; \
2889 gdk_window_get_offsets (drawable, &x_offset, &y_offset); \
2890 if (x_offset != 0 || y_offset != 0) \
2892 gdk_gc_set_clip_origin (gc, old_clip_x - x_offset, \
2893 old_clip_y - y_offset); \
2894 gdk_gc_set_ts_origin (gc, old_ts_x - x_offset, \
2895 old_ts_y - y_offset); \
2898 #define RESTORE_GC(gc) \
2899 if (x_offset != 0 || y_offset != 0) \
2901 gdk_gc_set_clip_origin (gc, old_clip_x, old_clip_y); \
2902 gdk_gc_set_ts_origin (gc, old_ts_x, old_ts_y); \
2905 #define SETUP_PAINT_GC_CLIP(gc) \
2906 if (paint->uses_implicit) \
2907 setup_clip_for_paint (drawable, paint, gc, old_clip_x, \
2910 #define RESTORE_PAINT_GC_CLIP(gc)
2913 #define SETUP_DIRECT_GC_CLIP(gc) \
2914 gdk_window_flush ((GdkWindow *)drawable);\
2915 setup_clip_for_draw (drawable, gc, old_clip_x, old_clip_y);
2917 #define RESTORE_DIRECT_GC_CLIP(gc)
2920 gdk_window_create_gc (GdkDrawable *drawable,
2921 GdkGCValues *values,
2922 GdkGCValuesMask mask)
2924 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
2926 if (GDK_WINDOW_DESTROYED (drawable))
2929 return gdk_gc_new_with_values (((GdkWindowObject *) drawable)->impl,
2933 /* After having set up the drawable clip rect on a GC we need
2934 * to make sure that if we draw to a pixmap we draw to the impl,
2935 * otherwise the pixmap code will reset the drawable clip.
2937 static GdkDrawable *
2938 pixmap_impl (GdkPixmap *pixmap)
2940 return ((GdkPixmapObject *)pixmap)->impl;
2944 gdk_window_draw_rectangle (GdkDrawable *drawable,
2952 GdkWindowObject *private = (GdkWindowObject *)drawable;
2955 if (GDK_WINDOW_DESTROYED (drawable))
2958 if (private->paint_stack)
2960 GdkWindowPaint *paint = private->paint_stack->data;
2961 SETUP_PAINT_GC_CLIP (gc);
2962 gdk_draw_rectangle (pixmap_impl (paint->pixmap), gc, filled,
2963 x - x_offset, y - y_offset, width, height);
2964 RESTORE_PAINT_GC_CLIP (gc);
2968 SETUP_DIRECT_GC_CLIP(gc);
2969 gdk_draw_rectangle (private->impl, gc, filled,
2970 x - x_offset, y - y_offset, width, height);
2971 RESTORE_DIRECT_GC_CLIP(gc);
2978 gdk_window_draw_arc (GdkDrawable *drawable,
2988 GdkWindowObject *private = (GdkWindowObject *)drawable;
2991 if (GDK_WINDOW_DESTROYED (drawable))
2994 if (private->paint_stack)
2996 GdkWindowPaint *paint = private->paint_stack->data;
2997 SETUP_PAINT_GC_CLIP (gc);
2998 gdk_draw_arc (pixmap_impl (paint->pixmap), gc, filled,
2999 x - x_offset, y - y_offset,
3000 width, height, angle1, angle2);
3001 RESTORE_PAINT_GC_CLIP (gc);
3005 SETUP_DIRECT_GC_CLIP(gc);
3006 gdk_draw_arc (private->impl, gc, filled,
3007 x - x_offset, y - y_offset,
3008 width, height, angle1, angle2);
3009 RESTORE_DIRECT_GC_CLIP(gc);
3015 gdk_window_draw_polygon (GdkDrawable *drawable,
3021 GdkWindowObject *private = (GdkWindowObject *)drawable;
3022 GdkPoint *new_points;
3026 if (GDK_WINDOW_DESTROYED (drawable))
3029 if (x_offset != 0 || y_offset != 0)
3033 new_points = g_new (GdkPoint, npoints);
3034 for (i=0; i<npoints; i++)
3036 new_points[i].x = points[i].x - x_offset;
3037 new_points[i].y = points[i].y - y_offset;
3041 new_points = points;
3043 if (private->paint_stack)
3045 GdkWindowPaint *paint = private->paint_stack->data;
3046 SETUP_PAINT_GC_CLIP (gc);
3047 gdk_draw_polygon (pixmap_impl (paint->pixmap), gc, filled, new_points, npoints);
3048 RESTORE_PAINT_GC_CLIP (gc);
3052 SETUP_DIRECT_GC_CLIP(gc);
3053 gdk_draw_polygon (private->impl, gc, filled, new_points, npoints);
3054 RESTORE_DIRECT_GC_CLIP(gc);
3057 if (new_points != points)
3058 g_free (new_points);
3064 gdk_window_draw_text (GdkDrawable *drawable,
3072 GdkWindowObject *private = (GdkWindowObject *)drawable;
3075 if (GDK_WINDOW_DESTROYED (drawable))
3078 if (private->paint_stack)
3080 GdkWindowPaint *paint = private->paint_stack->data;
3081 SETUP_PAINT_GC_CLIP (gc);
3082 gdk_draw_text (pixmap_impl (paint->pixmap), font, gc,
3083 x - x_offset, y - y_offset, text, text_length);
3085 RESTORE_PAINT_GC_CLIP (gc);
3089 SETUP_DIRECT_GC_CLIP(gc);
3090 gdk_draw_text (private->impl, font, gc,
3091 x - x_offset, y - y_offset, text, text_length);
3092 RESTORE_DIRECT_GC_CLIP(gc);
3099 gdk_window_draw_text_wc (GdkDrawable *drawable,
3104 const GdkWChar *text,
3107 GdkWindowObject *private = (GdkWindowObject *)drawable;
3110 if (GDK_WINDOW_DESTROYED (drawable))
3113 if (private->paint_stack)
3115 GdkWindowPaint *paint = private->paint_stack->data;
3116 SETUP_PAINT_GC_CLIP (gc);
3117 gdk_draw_text_wc (pixmap_impl (paint->pixmap), font, gc,
3118 x - x_offset, y - y_offset, text, text_length);
3119 RESTORE_PAINT_GC_CLIP (gc);
3123 SETUP_DIRECT_GC_CLIP(gc);
3124 gdk_draw_text_wc (private->impl, font, gc,
3125 x - x_offset, y - y_offset, text, text_length);
3126 RESTORE_DIRECT_GC_CLIP(gc);
3132 static GdkDrawable *
3133 gdk_window_get_source_drawable (GdkDrawable *drawable)
3135 GdkWindow *window = GDK_WINDOW (drawable);
3136 GdkWindowObject *private;
3138 private = (GdkWindowObject *) window;
3139 if (GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable)
3140 return GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable (private->impl);
3145 static GdkDrawable *
3146 gdk_window_get_composite_drawable (GdkDrawable *drawable,
3151 gint *composite_x_offset,
3152 gint *composite_y_offset)
3154 GdkWindowObject *private = (GdkWindowObject *)drawable;
3156 GdkPixmap *tmp_pixmap;
3159 gboolean overlap_buffer;
3160 GdkDrawable *source;
3161 GdkWindowObject *impl_window;
3162 GdkWindowPaint *implicit_paint;
3164 *composite_x_offset = -private->abs_x;
3165 *composite_y_offset = -private->abs_y;
3167 if ((GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable)))
3168 return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
3170 /* See if any buffered part is overlapping the part we want
3176 rect.height = height;
3178 overlap_buffer = FALSE;
3180 for (list = private->paint_stack; list != NULL; list = list->next)
3182 GdkWindowPaint *paint = list->data;
3183 GdkOverlapType overlap;
3185 overlap = gdk_region_rect_in (paint->region, &rect);
3187 if (overlap == GDK_OVERLAP_RECTANGLE_IN)
3189 *composite_x_offset = paint->x_offset;
3190 *composite_y_offset = paint->y_offset;
3192 return g_object_ref (paint->pixmap);
3194 else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
3196 overlap_buffer = TRUE;
3201 impl_window = gdk_window_get_impl_window (private);
3202 implicit_paint = impl_window->implicit_paint;
3205 GdkOverlapType overlap;
3207 rect.x += private->abs_x;
3208 rect.y += private->abs_y;
3210 overlap = gdk_region_rect_in (implicit_paint->region, &rect);
3211 if (overlap == GDK_OVERLAP_RECTANGLE_IN)
3213 *composite_x_offset = -private->abs_x + implicit_paint->x_offset;
3214 *composite_y_offset = -private->abs_y + implicit_paint->y_offset;
3216 return g_object_ref (implicit_paint->pixmap);
3218 else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
3219 overlap_buffer = TRUE;
3222 if (!overlap_buffer)
3223 return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
3225 tmp_pixmap = gdk_pixmap_new (drawable, width, height, -1);
3226 tmp_gc = _gdk_drawable_get_scratch_gc (tmp_pixmap, FALSE);
3228 source = _gdk_drawable_get_source_drawable (drawable);
3230 /* Copy the current window contents */
3231 gdk_draw_drawable (tmp_pixmap,
3233 GDK_WINDOW_OBJECT (source)->impl,
3234 x - *composite_x_offset,
3235 y - *composite_y_offset,
3239 /* paint the backing stores */
3242 GdkWindowPaint *paint = list->data;
3244 gdk_gc_set_clip_region (tmp_gc, paint->region);
3245 gdk_gc_set_clip_origin (tmp_gc, -x - paint->x_offset, -y - paint->y_offset);
3247 gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
3248 x - paint->x_offset,
3249 y - paint->y_offset,
3250 0, 0, width, height);
3253 for (list = private->paint_stack; list != NULL; list = list->next)
3255 GdkWindowPaint *paint = list->data;
3257 if (paint->uses_implicit)
3258 continue; /* We already copied this above */
3260 gdk_gc_set_clip_region (tmp_gc, paint->region);
3261 gdk_gc_set_clip_origin (tmp_gc, -x, -y);
3263 gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
3264 x - paint->x_offset,
3265 y - paint->y_offset,
3266 0, 0, width, height);
3269 /* Reset clip region of the cached GdkGC */
3270 gdk_gc_set_clip_region (tmp_gc, NULL);
3272 /* Set these to location of tmp_pixmap within the window */
3273 *composite_x_offset = x;
3274 *composite_y_offset = y;
3280 gdk_window_get_clip_region (GdkDrawable *drawable)
3282 GdkWindowObject *private = (GdkWindowObject *)drawable;
3285 result = gdk_region_copy (private->clip_region);
3287 if (private->paint_stack)
3289 GdkRegion *paint_region = gdk_region_new ();
3290 GSList *tmp_list = private->paint_stack;
3294 GdkWindowPaint *paint = tmp_list->data;
3296 gdk_region_union (paint_region, paint->region);
3298 tmp_list = tmp_list->next;
3301 gdk_region_intersect (result, paint_region);
3302 gdk_region_destroy (paint_region);
3309 gdk_window_get_visible_region (GdkDrawable *drawable)
3311 GdkWindowObject *private = (GdkWindowObject*) drawable;
3313 return gdk_region_copy (private->clip_region);
3317 gdk_window_draw_drawable (GdkDrawable *drawable,
3327 GdkWindowObject *private = (GdkWindowObject *)drawable;
3330 if (GDK_WINDOW_DESTROYED (drawable))
3333 /* If we have a backing pixmap draw to that */
3334 if (private->paint_stack)
3336 GdkWindowPaint *paint = private->paint_stack->data;
3337 SETUP_PAINT_GC_CLIP (gc);
3338 gdk_draw_drawable (pixmap_impl (paint->pixmap), gc,
3340 xdest - x_offset, ydest - y_offset, width, height);
3342 RESTORE_PAINT_GC_CLIP (gc);
3346 SETUP_DIRECT_GC_CLIP(gc);
3347 gdk_draw_drawable (private->impl, gc,
3349 xdest - x_offset, ydest - y_offset,
3351 RESTORE_DIRECT_GC_CLIP(gc);
3358 gdk_window_draw_points (GdkDrawable *drawable,
3363 GdkWindowObject *private = (GdkWindowObject *)drawable;
3364 GdkPoint *new_points;
3368 if (GDK_WINDOW_DESTROYED (drawable))
3371 if (x_offset != 0 || y_offset != 0)
3375 new_points = g_new (GdkPoint, npoints);
3376 for (i=0; i<npoints; i++)
3378 new_points[i].x = points[i].x - x_offset;
3379 new_points[i].y = points[i].y - y_offset;
3383 new_points = points;
3385 if (private->paint_stack)
3387 GdkWindowPaint *paint = private->paint_stack->data;
3388 SETUP_PAINT_GC_CLIP (gc);
3389 gdk_draw_points (pixmap_impl (paint->pixmap), gc, new_points, npoints);
3390 RESTORE_PAINT_GC_CLIP (gc);
3394 SETUP_DIRECT_GC_CLIP(gc);
3395 gdk_draw_points (private->impl, gc, new_points, npoints);
3396 RESTORE_DIRECT_GC_CLIP(gc);
3399 if (new_points != points)
3400 g_free (new_points);
3406 gdk_window_draw_segments (GdkDrawable *drawable,
3411 GdkWindowObject *private = (GdkWindowObject *)drawable;
3412 GdkSegment *new_segs;
3416 if (GDK_WINDOW_DESTROYED (drawable))
3419 if (x_offset != 0 || y_offset != 0)
3423 new_segs = g_new (GdkSegment, nsegs);
3424 for (i=0; i<nsegs; i++)
3426 new_segs[i].x1 = segs[i].x1 - x_offset;
3427 new_segs[i].y1 = segs[i].y1 - y_offset;
3428 new_segs[i].x2 = segs[i].x2 - x_offset;
3429 new_segs[i].y2 = segs[i].y2 - y_offset;
3435 if (private->paint_stack)
3437 GdkWindowPaint *paint = private->paint_stack->data;
3438 SETUP_PAINT_GC_CLIP (gc);
3439 gdk_draw_segments (pixmap_impl (paint->pixmap), gc, new_segs, nsegs);
3440 RESTORE_PAINT_GC_CLIP (gc);
3444 SETUP_DIRECT_GC_CLIP(gc);
3445 gdk_draw_segments (private->impl, gc, new_segs, nsegs);
3446 RESTORE_DIRECT_GC_CLIP(gc);
3449 if (new_segs != segs)
3456 gdk_window_draw_lines (GdkDrawable *drawable,
3461 GdkWindowObject *private = (GdkWindowObject *)drawable;
3462 GdkPoint *new_points;
3466 if (GDK_WINDOW_DESTROYED (drawable))
3469 if (x_offset != 0 || y_offset != 0)
3473 new_points = g_new (GdkPoint, npoints);
3474 for (i=0; i<npoints; i++)
3476 new_points[i].x = points[i].x - x_offset;
3477 new_points[i].y = points[i].y - y_offset;
3481 new_points = points;
3483 if (private->paint_stack)
3485 GdkWindowPaint *paint = private->paint_stack->data;
3486 SETUP_PAINT_GC_CLIP (gc);
3487 gdk_draw_lines (pixmap_impl (paint->pixmap), gc, new_points, npoints);
3488 RESTORE_PAINT_GC_CLIP (gc);
3492 SETUP_DIRECT_GC_CLIP(gc);
3493 gdk_draw_lines (private->impl, gc, new_points, npoints);
3494 RESTORE_DIRECT_GC_CLIP(gc);
3497 if (new_points != points)
3498 g_free (new_points);
3504 gdk_window_draw_glyphs (GdkDrawable *drawable,
3509 PangoGlyphString *glyphs)
3511 GdkWindowObject *private = (GdkWindowObject *)drawable;
3515 if (GDK_WINDOW_DESTROYED (drawable))
3518 if (private->paint_stack)
3520 GdkWindowPaint *paint = private->paint_stack->data;
3522 SETUP_PAINT_GC_CLIP (gc);
3523 gdk_draw_glyphs (pixmap_impl (paint->pixmap), gc, font, x - x_offset, y - y_offset, glyphs);
3524 RESTORE_PAINT_GC_CLIP (gc);
3528 SETUP_DIRECT_GC_CLIP(gc);
3529 gdk_draw_glyphs (private->impl, gc, font,
3530 x - x_offset, y - y_offset, glyphs);
3531 RESTORE_DIRECT_GC_CLIP(gc);
3538 gdk_window_draw_glyphs_transformed (GdkDrawable *drawable,
3540 PangoMatrix *matrix,
3544 PangoGlyphString *glyphs)
3546 GdkWindowObject *private = (GdkWindowObject *)drawable;
3547 PangoMatrix tmp_matrix;
3551 if (GDK_WINDOW_DESTROYED (drawable))
3554 if (x_offset != 0 || y_offset != 0)
3558 tmp_matrix = *matrix;
3559 tmp_matrix.x0 -= x_offset;
3560 tmp_matrix.y0 -= y_offset;
3561 matrix = &tmp_matrix;
3563 else if (GDK_PANGO_UNITS_OVERFLOWS (x_offset, y_offset))
3565 PangoMatrix identity = PANGO_MATRIX_INIT;
3567 tmp_matrix = identity;
3568 tmp_matrix.x0 -= x_offset;
3569 tmp_matrix.y0 -= y_offset;
3570 matrix = &tmp_matrix;
3574 x -= x_offset * PANGO_SCALE;
3575 y -= y_offset * PANGO_SCALE;
3579 if (private->paint_stack)
3581 GdkWindowPaint *paint = private->paint_stack->data;
3583 SETUP_PAINT_GC_CLIP (gc);
3584 gdk_draw_glyphs_transformed (pixmap_impl (paint->pixmap), gc, matrix, font, x, y, glyphs);
3585 RESTORE_PAINT_GC_CLIP (gc);
3589 SETUP_DIRECT_GC_CLIP(gc);
3590 gdk_draw_glyphs_transformed (private->impl, gc, matrix, font, x, y, glyphs);
3591 RESTORE_DIRECT_GC_CLIP(gc);
3598 cairo_t *cr; /* if non-null, it means use this cairo context */
3599 GdkGC *gc; /* if non-null, it means use this GC instead */
3600 } BackingRectMethod;
3603 setup_backing_rect_method (BackingRectMethod *method, GdkWindow *window, GdkWindowPaint *paint, int x_offset_cairo, int y_offset_cairo)
3605 GdkWindowObject *private = (GdkWindowObject *)window;
3607 if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
3609 GdkWindowPaint tmp_paint;
3612 tmp_paint.x_offset += private->x;
3613 tmp_paint.y_offset += private->y;
3615 x_offset_cairo += private->x;
3616 y_offset_cairo += private->y;
3618 setup_backing_rect_method (method, GDK_WINDOW (private->parent), &tmp_paint, x_offset_cairo, y_offset_cairo);
3620 else if (private->bg_pixmap &&
3621 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
3622 private->bg_pixmap != GDK_NO_BG)
3624 /* This is a workaround for https://bugs.freedesktop.org/show_bug.cgi?id=4320.
3625 * In it, using a pixmap as a repeating pattern in Cairo, and painting it to a
3626 * pixmap destination surface, can be very slow (on the order of seconds for a
3627 * whole-screen copy). The workaround is to use pretty much the same code that
3628 * we used in GTK+ 2.6 (pre-Cairo), which clears the double-buffer pixmap with
3629 * a tiled GC XFillRectangle().
3632 /* Actually computing this flag is left as an exercise for the reader */
3633 #if defined (G_OS_UNIX)
3634 # define GDK_CAIRO_REPEAT_IS_FAST 0
3636 # define GDK_CAIRO_REPEAT_IS_FAST 1
3639 #if GDK_CAIRO_REPEAT_IS_FAST
3640 cairo_surface_t *surface = _gdk_drawable_ref_cairo_surface (private->bg_pixmap);
3641 cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
3642 cairo_surface_destroy (surface);
3644 if (x_offset_cairo != 0 || y_offset_cairo != 0)
3646 cairo_matrix_t matrix;
3647 cairo_matrix_init_translate (&matrix, x_offset_cairo, y_offset_cairo);
3648 cairo_pattern_set_matrix (pattern, &matrix);
3651 cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
3653 method->cr = cairo_create (paint->surface);
3656 cairo_set_source (method->cr, pattern);
3657 cairo_pattern_destroy (pattern);
3660 GdkGCValues gc_values;
3662 gc_values.fill = GDK_TILED;
3663 gc_values.tile = private->bg_pixmap;
3664 gc_values.ts_x_origin = -x_offset_cairo;
3665 gc_values.ts_y_origin = -y_offset_cairo;
3667 gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN;
3669 method->gc = gdk_gc_new_with_values (paint->pixmap, &gc_values, gc_mask);
3674 method->cr = cairo_create (paint->surface);
3676 gdk_cairo_set_source_color (method->cr, &private->bg_color);
3681 gdk_window_clear_backing_region (GdkWindow *window,
3684 GdkWindowObject *private = (GdkWindowObject *)window;
3685 GdkWindowPaint *paint = private->paint_stack->data;
3686 BackingRectMethod method;
3688 GdkRectangle clipbox;
3694 if (GDK_WINDOW_DESTROYED (window))
3698 timer = g_timer_new ();
3703 setup_backing_rect_method (&method, window, paint, 0, 0);
3705 clip = gdk_region_copy (paint->region);
3706 gdk_region_intersect (clip, region);
3707 gdk_region_get_clipbox (clip, &clipbox);
3712 g_assert (method.gc == NULL);
3714 gdk_cairo_region (method.cr, clip);
3715 cairo_fill (method.cr);
3717 cairo_destroy (method.cr);
3719 elapsed = g_timer_elapsed (timer, NULL);
3720 g_print ("Draw the background with Cairo: %fs\n", elapsed);
3725 g_assert (method.gc != NULL);
3727 gdk_gc_set_clip_region (method.gc, clip);
3728 gdk_draw_rectangle (window, method.gc, TRUE,
3729 clipbox.x, clipbox.y,
3730 clipbox.width, clipbox.height);
3731 g_object_unref (method.gc);
3734 elapsed = g_timer_elapsed (timer, NULL);
3735 g_print ("Draw the background with GDK: %fs\n", elapsed);
3739 gdk_region_destroy (clip);
3742 g_timer_destroy (timer);
3747 gdk_window_clear_backing_region_redirect (GdkWindow *window,
3750 GdkWindowObject *private = (GdkWindowObject *)window;
3751 GdkWindowRedirect *redirect = private->redirect;
3752 GdkRegion *clip_region;
3753 GdkRectangle clipbox;
3754 gint x_offset, y_offset;
3755 BackingRectMethod method;
3756 GdkWindowPaint paint;
3758 if (GDK_WINDOW_DESTROYED (window))
3761 clip_region = _gdk_window_calculate_full_clip_region (window,
3762 GDK_WINDOW (redirect->redirected),
3764 &x_offset, &y_offset);
3765 gdk_region_intersect (clip_region, region);
3767 paint.x_offset = x_offset;
3768 paint.y_offset = y_offset;
3769 paint.pixmap = redirect->pixmap;
3770 paint.surface = _gdk_drawable_ref_cairo_surface (redirect->pixmap);
3774 setup_backing_rect_method (&method, window, &paint, 0, 0);
3778 g_assert (method.gc == NULL);
3780 gdk_cairo_region (method.cr, clip_region);
3781 cairo_fill (method.cr);
3783 cairo_destroy (method.cr);
3787 g_assert (method.gc != NULL);
3789 gdk_region_get_clipbox (clip_region, &clipbox);
3790 gdk_gc_set_clip_region (method.gc, clip_region);
3791 gdk_draw_rectangle (window, method.gc, TRUE,
3792 clipbox.x, clipbox.y,
3793 clipbox.width, clipbox.height);
3794 g_object_unref (method.gc);
3798 gdk_region_destroy (clip_region);
3799 cairo_surface_destroy (paint.surface);
3803 gdk_window_clear_backing_region_direct (GdkWindow *window,
3806 GdkWindowObject *private = (GdkWindowObject *)window;
3807 BackingRectMethod method;
3808 GdkWindowPaint paint;
3810 GdkRectangle clipbox;
3812 if (GDK_WINDOW_DESTROYED (window))
3817 paint.pixmap = window;
3818 paint.surface = _gdk_drawable_ref_cairo_surface (window);
3822 setup_backing_rect_method (&method, window, &paint, 0, 0);
3824 clip = gdk_region_copy (private->clip_region_with_children);
3825 gdk_region_intersect (clip, region);
3826 gdk_region_get_clipbox (clip, &clipbox);
3830 g_assert (method.gc == NULL);
3832 gdk_cairo_region (method.cr, clip);
3833 cairo_fill (method.cr);
3835 cairo_destroy (method.cr);
3839 g_assert (method.gc != NULL);
3841 gdk_gc_set_clip_region (method.gc, clip);
3842 gdk_draw_rectangle (window, method.gc, TRUE,
3843 clipbox.x, clipbox.y,
3844 clipbox.width, clipbox.height);
3845 g_object_unref (method.gc);
3849 gdk_region_destroy (clip);
3850 cairo_surface_destroy (paint.surface);
3856 * @window: a #GdkWindow
3858 * Clears an entire @window to the background color or background pixmap.
3861 gdk_window_clear (GdkWindow *window)
3865 g_return_if_fail (GDK_IS_WINDOW (window));
3867 gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height);
3869 gdk_window_clear_area (window, 0, 0,
3874 gdk_window_clear_region_internal (GdkWindow *window,
3876 gboolean send_expose)
3878 GdkWindowObject *private = (GdkWindowObject *)window;
3880 if (private->paint_stack)
3881 gdk_window_clear_backing_region (window, region);
3884 if (private->redirect)
3885 gdk_window_clear_backing_region_redirect (window, region);
3887 gdk_window_clear_backing_region_direct (window, region);
3889 gdk_window_invalidate_region (window, region, FALSE);
3894 gdk_window_clear_area_internal (GdkWindow *window,
3899 gboolean send_expose)
3901 GdkWindowObject *private = (GdkWindowObject *)window;
3905 g_return_if_fail (GDK_IS_WINDOW (window));
3907 /* This is what XClearArea does, and e.g. GtkCList uses it,
3908 so we need to duplicate that */
3910 width = private->width - x;
3912 height = private->height - y;
3917 rect.height = height;
3919 region = gdk_region_rectangle (&rect);
3920 gdk_window_clear_region_internal (window,
3923 gdk_region_destroy (region);
3928 * gdk_window_clear_area:
3929 * @window: a #GdkWindow
3930 * @x: x coordinate of rectangle to clear
3931 * @y: y coordinate of rectangle to clear
3932 * @width: width of rectangle to clear
3933 * @height: height of rectangle to clear
3935 * Clears an area of @window to the background color or background pixmap.
3939 gdk_window_clear_area (GdkWindow *window,
3945 gdk_window_clear_area_internal (window,
3952 * gdk_window_clear_area_e:
3953 * @window: a #GdkWindow
3954 * @x: x coordinate of rectangle to clear
3955 * @y: y coordinate of rectangle to clear
3956 * @width: width of rectangle to clear
3957 * @height: height of rectangle to clear
3959 * Like gdk_window_clear_area(), but also generates an expose event for
3962 * This function has a stupid name because it dates back to the mists
3963 * time, pre-GDK-1.0.
3967 gdk_window_clear_area_e (GdkWindow *window,
3973 gdk_window_clear_area_internal (window,
3980 gdk_window_draw_image (GdkDrawable *drawable,
3990 GdkWindowObject *private = (GdkWindowObject *)drawable;
3994 if (GDK_WINDOW_DESTROYED (drawable))
3997 if (private->paint_stack)
3999 GdkWindowPaint *paint = private->paint_stack->data;
4000 SETUP_PAINT_GC_CLIP (gc);
4001 gdk_draw_image (pixmap_impl (paint->pixmap), gc, image, xsrc, ysrc,
4002 xdest - x_offset, ydest - y_offset,
4005 RESTORE_PAINT_GC_CLIP (gc);
4009 SETUP_DIRECT_GC_CLIP(gc);
4010 gdk_draw_image (private->impl, gc, image, xsrc, ysrc,
4011 xdest - x_offset, ydest - y_offset,
4013 RESTORE_DIRECT_GC_CLIP(gc);
4020 gdk_window_draw_pixbuf (GdkDrawable *drawable,
4029 GdkRgbDither dither,
4033 GdkWindowObject *private = (GdkWindowObject *)drawable;
4035 if (GDK_WINDOW_DESTROYED (drawable))
4038 /* If no gc => no user clipping, but we need clipping
4039 for window emulation, so use a scratch gc */
4041 gc = _gdk_drawable_get_scratch_gc (drawable, FALSE);
4043 /* Need block to make OFFSET_GC macro to work */
4047 if (private->paint_stack)
4049 GdkWindowPaint *paint = private->paint_stack->data;
4050 SETUP_PAINT_GC_CLIP (gc);
4051 gdk_draw_pixbuf (pixmap_impl (paint->pixmap), gc, pixbuf, src_x, src_y,
4052 dest_x - x_offset, dest_y - y_offset,
4054 dither, x_dither - x_offset, y_dither - y_offset);
4055 RESTORE_PAINT_GC_CLIP (gc);
4059 SETUP_DIRECT_GC_CLIP(gc);
4060 gdk_draw_pixbuf (private->impl, gc, pixbuf, src_x, src_y,
4061 dest_x - x_offset, dest_y - y_offset,
4063 dither, x_dither, y_dither);
4064 RESTORE_DIRECT_GC_CLIP(gc);
4072 gdk_window_draw_trapezoids (GdkDrawable *drawable,
4074 GdkTrapezoid *trapezoids,
4077 GdkWindowObject *private = (GdkWindowObject *)drawable;
4078 GdkTrapezoid *new_trapezoids = NULL;
4082 if (GDK_WINDOW_DESTROYED (drawable))
4085 if (x_offset != 0 || y_offset != 0)
4089 new_trapezoids = g_new (GdkTrapezoid, n_trapezoids);
4090 for (i=0; i < n_trapezoids; i++)
4092 new_trapezoids[i].y1 = trapezoids[i].y1 - y_offset;
4093 new_trapezoids[i].x11 = trapezoids[i].x11 - x_offset;
4094 new_trapezoids[i].x21 = trapezoids[i].x21 - x_offset;
4095 new_trapezoids[i].y2 = trapezoids[i].y2 - y_offset;
4096 new_trapezoids[i].x12 = trapezoids[i].x12 - x_offset;
4097 new_trapezoids[i].x22 = trapezoids[i].x22 - x_offset;
4100 trapezoids = new_trapezoids;
4103 if (private->paint_stack)
4105 GdkWindowPaint *paint = private->paint_stack->data;
4106 SETUP_PAINT_GC_CLIP (gc);
4107 gdk_draw_trapezoids (pixmap_impl (paint->pixmap), gc, trapezoids, n_trapezoids);
4108 RESTORE_PAINT_GC_CLIP (gc);
4112 SETUP_DIRECT_GC_CLIP(gc);
4113 gdk_draw_trapezoids (private->impl, gc, trapezoids, n_trapezoids);
4114 RESTORE_DIRECT_GC_CLIP(gc);
4117 g_free (new_trapezoids);
4123 gdk_window_real_get_size (GdkDrawable *drawable,
4127 GdkWindowObject *private = (GdkWindowObject *)drawable;
4130 *width = private->width;
4132 *height = private->height;
4136 gdk_window_real_get_visual (GdkDrawable *drawable)
4138 GdkColormap *colormap;
4140 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4142 colormap = gdk_drawable_get_colormap (drawable);
4143 return colormap ? gdk_colormap_get_visual (colormap) : NULL;
4147 gdk_window_real_get_depth (GdkDrawable *drawable)
4149 g_return_val_if_fail (GDK_IS_WINDOW (drawable), 0);
4151 return ((GdkWindowObject *)GDK_WINDOW (drawable))->depth;
4155 gdk_window_real_get_screen (GdkDrawable *drawable)
4157 return gdk_drawable_get_screen (GDK_WINDOW_OBJECT (drawable)->impl);
4161 gdk_window_real_set_colormap (GdkDrawable *drawable,
4164 GdkWindowObject *private;
4166 g_return_if_fail (GDK_IS_WINDOW (drawable));
4168 if (GDK_WINDOW_DESTROYED (drawable))
4171 private = (GdkWindowObject *)drawable;
4173 /* different colormap than parent, requires native window */
4174 if (!private->input_only &&
4175 cmap != gdk_drawable_get_colormap ((GdkDrawable *)(private->parent)))
4176 gdk_window_set_has_native ((GdkWindow *)drawable, TRUE);
4178 gdk_drawable_set_colormap (private->impl, cmap);
4182 gdk_window_real_get_colormap (GdkDrawable *drawable)
4184 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4186 if (GDK_WINDOW_DESTROYED (drawable))
4189 return gdk_drawable_get_colormap (((GdkWindowObject*)drawable)->impl);
4193 gdk_window_copy_to_image (GdkDrawable *drawable,
4202 GdkWindowObject *private = (GdkWindowObject *) drawable;
4203 gint x_offset, y_offset;
4205 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4207 if (GDK_WINDOW_DESTROYED (drawable))
4210 /* If we're here, a composite image was not necessary, so
4211 * we can ignore the paint stack.
4214 /* TODO: Is this right? */
4218 return gdk_drawable_copy_to_image (private->impl,
4227 gdk_window_cairo_surface_destroy (void *data)
4229 GdkWindowObject *private = (GdkWindowObject*) data;
4231 private->cairo_surface = NULL;
4234 static cairo_surface_t *
4235 gdk_window_create_cairo_surface (GdkDrawable *drawable,
4239 return _gdk_windowing_create_cairo_surface (GDK_WINDOW_OBJECT(drawable)->impl,
4244 static cairo_surface_t *
4245 gdk_window_ref_cairo_surface (GdkDrawable *drawable)
4247 GdkWindowObject *private = (GdkWindowObject*) drawable;
4248 cairo_surface_t *surface;
4250 if (private->paint_stack)
4252 GdkWindowPaint *paint = private->paint_stack->data;
4254 surface = paint->surface;
4255 cairo_surface_reference (surface);
4260 /* This will be drawing directly to the window, so flush implicit paint */
4261 gdk_window_flush ((GdkWindow *)drawable);
4263 if (!private->cairo_surface)
4266 GdkDrawable *source;
4268 /* It would be nice if we had some cairo support here so we
4269 could set the clip rect on the cairo surface */
4270 width = private->abs_x + private->width;
4271 height = private->abs_y + private->height;
4273 source = _gdk_drawable_get_source_drawable (drawable);
4275 /* TODO: Avoid the typecheck crap by adding virtual call */
4276 private->cairo_surface = _gdk_drawable_create_cairo_surface (source, width, height);
4278 if (private->cairo_surface)
4280 cairo_surface_set_device_offset (private->cairo_surface,
4284 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
4285 drawable, gdk_window_cairo_surface_destroy);
4289 cairo_surface_reference (private->cairo_surface);
4291 surface = private->cairo_surface;
4298 gdk_window_set_cairo_clip (GdkDrawable *drawable,
4301 GdkWindowObject *private = (GdkWindowObject*) drawable;
4303 if (!private->paint_stack)
4306 cairo_identity_matrix (cr);
4308 cairo_reset_clip (cr);
4310 cairo_new_path (cr);
4311 gdk_cairo_region (cr, private->clip_region);
4318 GdkWindowPaint *paint = private->paint_stack->data;
4320 /* Only needs to clip to region if piggybacking
4321 on an implicit paint pixmap */
4322 if (paint->uses_implicit)
4325 cairo_identity_matrix (cr);
4327 cairo_reset_clip (cr);
4329 cairo_new_path (cr);
4330 gdk_cairo_region (cr, paint->region);
4338 /* Code for dirty-region queueing
4340 static GSList *update_windows = NULL;
4341 static guint update_idle = 0;
4342 static gboolean debug_updates = FALSE;
4344 static inline gboolean
4345 gdk_window_is_ancestor (GdkWindow *window,
4346 GdkWindow *ancestor)
4350 GdkWindow *parent = (GdkWindow*) ((GdkWindowObject*) window)->parent;
4352 if (parent == ancestor)
4362 gdk_window_add_update_window (GdkWindow *window)
4365 GSList *prev = NULL;
4366 gboolean has_ancestor_in_list = FALSE;
4368 for (tmp = update_windows; tmp; tmp = tmp->next)
4370 GdkWindowObject *parent = GDK_WINDOW_OBJECT (window)->parent;
4372 /* check if tmp is an ancestor of "window"; if it is, set a
4373 * flag indicating that all following windows are either
4374 * children of "window" or from a differen hierarchy
4376 if (!has_ancestor_in_list && gdk_window_is_ancestor (window, tmp->data))
4377 has_ancestor_in_list = TRUE;
4379 /* insert in reverse stacking order when adding around siblings,
4380 * so processing updates properly paints over lower stacked windows
4382 if (parent == GDK_WINDOW_OBJECT (tmp->data)->parent)
4384 gint index = g_list_index (parent->children, window);
4385 for (; tmp && parent == GDK_WINDOW_OBJECT (tmp->data)->parent; tmp = tmp->next)
4387 gint sibling_index = g_list_index (parent->children, tmp->data);
4388 if (index > sibling_index)
4392 /* here, tmp got advanced past all lower stacked siblings */
4393 tmp = g_slist_prepend (tmp, window);
4397 update_windows = tmp;
4401 /* if "window" has an ancestor in the list and tmp is one of
4402 * "window's" children, insert "window" before tmp
4404 if (has_ancestor_in_list && gdk_window_is_ancestor (tmp->data, window))
4406 tmp = g_slist_prepend (tmp, window);
4411 update_windows = tmp;
4415 /* if we're at the end of the list and had an ancestor it it,
4416 * append to the list
4418 if (! tmp->next && has_ancestor_in_list)
4420 tmp = g_slist_append (tmp, window);
4427 /* if all above checks failed ("window" is from a different
4428 * hierarchy than what is already in the list) or the list is
4431 update_windows = g_slist_prepend (update_windows, window);
4435 gdk_window_remove_update_window (GdkWindow *window)
4437 update_windows = g_slist_remove (update_windows, window);
4441 gdk_window_update_idle (gpointer data)
4443 gdk_window_process_all_updates ();
4449 gdk_window_is_toplevel_frozen (GdkWindow *window)
4451 GdkWindowObject *toplevel;
4453 toplevel = (GdkWindowObject *)gdk_window_get_toplevel (window);
4455 return toplevel->update_and_descendants_freeze_count > 0;
4459 gdk_window_schedule_update (GdkWindow *window)
4462 (GDK_WINDOW_OBJECT (window)->update_freeze_count ||
4463 gdk_window_is_toplevel_frozen (window)))
4468 update_idle = gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
4469 gdk_window_update_idle, NULL, NULL);
4474 _gdk_window_process_updates_recurse (GdkWindow *window,
4475 GdkRegion *expose_region)
4477 GdkWindowObject *private = (GdkWindowObject *)window;
4478 GdkWindowObject *child;
4479 GdkRegion *child_region;
4483 if (gdk_region_empty (expose_region))
4486 /* Iterate over children, starting at topmost */
4487 for (l = private->children; l != NULL; l = l->next)
4491 if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
4494 /* Ignore offscreen children, as they don't draw in their parent and
4495 * don't take part in the clipping */
4496 if (gdk_window_is_offscreen (child))
4501 r.width = child->width;
4502 r.height = child->height;
4504 child_region = gdk_region_rectangle (&r);
4506 gdk_region_intersect (child_region, child->shape);
4508 if (child->impl == private->impl)
4510 /* Client side child, expose */
4511 gdk_region_intersect (child_region, expose_region);
4512 gdk_region_subtract (expose_region, child_region);
4513 gdk_region_offset (child_region, -child->x, -child->y);
4514 _gdk_window_process_updates_recurse ((GdkWindow *)child, child_region);
4518 /* Native child, just remove area from expose region */
4519 gdk_region_subtract (expose_region, child_region);
4521 gdk_region_destroy (child_region);
4524 if (!gdk_region_empty (expose_region))
4526 if (private->event_mask & GDK_EXPOSURE_MASK)
4530 event.expose.type = GDK_EXPOSE;
4531 event.expose.window = g_object_ref (window);
4532 event.expose.send_event = FALSE;
4533 event.expose.count = 0;
4534 event.expose.region = expose_region;
4535 gdk_region_get_clipbox (expose_region, &event.expose.area);
4537 (*_gdk_event_func) (&event, _gdk_event_data);
4539 g_object_unref (window);
4541 else if (private->bg_pixmap != GDK_NO_BG)
4543 /* No exposure mask set, so nothing will be drawn, the
4544 * app relies on the background being what it specified
4545 * for the window. So, we need to clear this manually.
4547 * We use begin/end_paint around the clear so that we can
4548 * piggyback on the implicit paint */
4550 gdk_window_begin_paint_region (window, expose_region);
4551 gdk_window_clear_region_internal (window, expose_region, FALSE);
4552 gdk_window_end_paint (window);
4558 gdk_window_process_updates_internal (GdkWindow *window)
4560 GdkWindowObject *private = (GdkWindowObject *)window;
4561 gboolean save_region = FALSE;
4562 GdkRectangle clip_box;
4564 /* If an update got queued during update processing, we can get a
4565 * window in the update queue that has an empty update_area.
4568 if (private->update_area)
4570 GdkRegion *update_area = private->update_area;
4571 private->update_area = NULL;
4573 if (_gdk_event_func && gdk_window_is_viewable (window) &&
4574 private->window_type != GDK_WINDOW_FOREIGN)
4576 GdkRectangle window_rect;
4577 GdkRegion *expose_region;
4578 GdkRegion *window_region;
4579 gboolean end_implicit;
4581 /* Clip to part visible in toplevel */
4582 gdk_region_intersect (update_area, private->clip_region);
4586 /* Make sure we see the red invalid area before redrawing. */
4587 gdk_display_sync (gdk_drawable_get_display (window));
4591 save_region = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->queue_antiexpose (window, update_area);
4593 expose_region = gdk_region_copy (update_area);
4595 expose_region = update_area;
4599 window_rect.width = private->width;
4600 window_rect.height = private->height;
4602 window_region = gdk_region_rectangle (&window_rect);
4603 gdk_region_intersect (expose_region,
4605 gdk_region_destroy (window_region);
4608 /* No need to do any moves that will end up over the update area */
4609 if (private->outstanding_moves)
4611 GdkWindowRegionMove *move;
4615 remove = gdk_region_copy (update_area);
4616 for (l = g_list_last (private->outstanding_moves); l != NULL; l = prev)
4620 /* Don't need this area */
4621 gdk_region_subtract (move->dest_region, remove);
4623 /* However if any of the destination we do need has a source
4624 in the updated region we do need that as a destination for
4625 the earlier moves */
4626 gdk_region_offset (move->dest_region, -move->dx, -move->dy);
4627 gdk_region_subtract (remove, move->dest_region);
4629 if (gdk_region_empty (move->dest_region))
4631 gdk_window_region_move_free (move);
4632 private->outstanding_moves =
4633 g_list_delete_link (private->outstanding_moves, l);
4636 gdk_region_offset (move->dest_region, move->dx, move->dy);
4638 gdk_region_destroy (remove);
4641 gdk_region_get_clipbox (expose_region, &clip_box);
4642 end_implicit = gdk_window_begin_implicit_paint (window, &clip_box);
4643 if (end_implicit) /* rendering is not double buffered, do moves now */
4644 gdk_window_flush_outstanding_moves (window);
4645 _gdk_windowing_window_process_updates_recurse (window, expose_region);
4648 /* Do moves right before exposes are rendered */
4649 gdk_window_flush_outstanding_moves (window);
4650 gdk_window_end_implicit_paint (window);
4653 if (expose_region != update_area)
4654 gdk_region_destroy (expose_region);
4657 gdk_region_destroy (update_area);
4660 if (private->outstanding_moves)
4662 /* Flush any outstanding moves, may happen if we moved a window but got
4663 no actual invalid area */
4664 gdk_window_flush_outstanding_moves (window);
4669 flush_all_displays (void)
4671 GSList *displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
4674 for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
4675 gdk_display_flush (tmp_list->data);
4677 g_slist_free (displays);
4680 /* Currently it is not possible to override
4681 * gdk_window_process_all_updates in the same manner as
4682 * gdk_window_process_updates and gdk_window_invalidate_maybe_recurse
4683 * by implementing the GdkPaintable interface. If in the future a
4684 * backend would need this, the right solution would be to add a
4685 * method to GdkDisplay that can be optionally
4686 * NULL. gdk_window_process_all_updates can then walk the list of open
4687 * displays and call the mehod.
4691 * gdk_window_process_all_updates:
4693 * Calls gdk_window_process_updates() for all windows (see #GdkWindow)
4694 * in the application.
4698 gdk_window_process_all_updates (void)
4700 GSList *old_update_windows = update_windows;
4701 GSList *tmp_list = update_windows;
4702 static gboolean in_process_all_updates = FALSE;
4704 if (in_process_all_updates)
4707 in_process_all_updates = TRUE;
4710 g_source_remove (update_idle);
4712 update_windows = NULL;
4715 _gdk_windowing_before_process_all_updates ();
4717 g_slist_foreach (old_update_windows, (GFunc)g_object_ref, NULL);
4721 GdkWindowObject *private = (GdkWindowObject *)tmp_list->data;
4723 if (!GDK_WINDOW_DESTROYED (tmp_list->data))
4725 if (private->update_freeze_count ||
4726 gdk_window_is_toplevel_frozen (tmp_list->data))
4727 gdk_window_add_update_window ((GdkWindow *) private);
4729 gdk_window_process_updates_internal (tmp_list->data);
4732 g_object_unref (tmp_list->data);
4733 tmp_list = tmp_list->next;
4736 g_slist_free (old_update_windows);
4738 flush_all_displays ();
4740 _gdk_windowing_after_process_all_updates ();
4742 in_process_all_updates = FALSE;
4746 * gdk_window_process_updates:
4747 * @window: a #GdkWindow
4748 * @update_children: whether to also process updates for child windows
4750 * Sends one or more expose events to @window. The areas in each
4751 * expose event will cover the entire update area for the window (see
4752 * gdk_window_invalidate_region() for details). Normally GDK calls
4753 * gdk_window_process_all_updates() on your behalf, so there's no
4754 * need to call this function unless you want to force expose events
4755 * to be delivered immediately and synchronously (vs. the usual
4756 * case, where GDK delivers them in an idle handler). Occasionally
4757 * this is useful to produce nicer scrolling behavior, for example.
4761 gdk_window_process_updates (GdkWindow *window,
4762 gboolean update_children)
4764 GdkWindowObject *private = (GdkWindowObject *)window;
4765 GdkWindowObject *impl_window;
4767 g_return_if_fail (GDK_IS_WINDOW (window));
4769 impl_window = gdk_window_get_impl_window (private);
4770 if ((impl_window->update_area ||
4771 impl_window->outstanding_moves) &&
4772 !impl_window->update_freeze_count &&
4773 !gdk_window_is_toplevel_frozen (window))
4775 gdk_window_process_updates_internal ((GdkWindow *)impl_window);
4776 gdk_window_remove_update_window ((GdkWindow *)impl_window);
4779 if (update_children)
4781 /* process updates in reverse stacking order so composition or
4782 * painting over achieves the desired effect for offscreen windows
4785 for (node = g_list_last (private->children); node; node = node->prev)
4786 gdk_window_process_updates (node->data, TRUE);
4791 * gdk_window_invalidate_rect:
4792 * @window: a #GdkWindow
4793 * @rect: rectangle to invalidate or %NULL to invalidate the whole
4795 * @invalidate_children: whether to also invalidate child windows
4797 * A convenience wrapper around gdk_window_invalidate_region() which
4798 * invalidates a rectangular region. See
4799 * gdk_window_invalidate_region() for details.
4802 gdk_window_invalidate_rect (GdkWindow *window,
4803 const GdkRectangle *rect,
4804 gboolean invalidate_children)
4806 GdkRectangle window_rect;
4808 GdkWindowObject *private = (GdkWindowObject *)window;
4810 g_return_if_fail (GDK_IS_WINDOW (window));
4812 if (GDK_WINDOW_DESTROYED (window))
4815 if (private->input_only || !GDK_WINDOW_IS_MAPPED (window))
4822 gdk_drawable_get_size (GDK_DRAWABLE (window),
4824 &window_rect.height);
4825 rect = &window_rect;
4828 region = gdk_region_rectangle (rect);
4829 gdk_window_invalidate_region (window, region, invalidate_children);
4830 gdk_region_destroy (region);
4834 draw_ugly_color (GdkWindow *window,
4835 const GdkRegion *region)
4837 /* Draw ugly color all over the newly-invalid region */
4838 GdkColor ugly_color = { 0, 50000, 10000, 10000 };
4840 GdkRectangle clipbox;
4842 ugly_gc = gdk_gc_new (window);
4843 gdk_gc_set_rgb_fg_color (ugly_gc, &ugly_color);
4844 gdk_gc_set_clip_region (ugly_gc, region);
4846 gdk_region_get_clipbox (region, &clipbox);
4848 gdk_draw_rectangle (window,
4851 clipbox.x, clipbox.y,
4852 clipbox.width, clipbox.height);
4854 g_object_unref (ugly_gc);
4858 * gdk_window_invalidate_maybe_recurse:
4859 * @window: a #GdkWindow
4860 * @region: a #GdkRegion
4861 * @child_func: function to use to decide if to recurse to a child,
4862 * %NULL means never recurse.
4863 * @user_data: data passed to @child_func
4865 * Adds @region to the update area for @window. The update area is the
4866 * region that needs to be redrawn, or "dirty region." The call
4867 * gdk_window_process_updates() sends one or more expose events to the
4868 * window, which together cover the entire update area. An
4869 * application would normally redraw the contents of @window in
4870 * response to those expose events.
4872 * GDK will call gdk_window_process_all_updates() on your behalf
4873 * whenever your program returns to the main loop and becomes idle, so
4874 * normally there's no need to do that manually, you just need to
4875 * invalidate regions that you know should be redrawn.
4877 * The @child_func parameter controls whether the region of
4878 * each child window that intersects @region will also be invalidated.
4879 * Only children for which @child_func returns TRUE will have the area
4883 gdk_window_invalidate_maybe_recurse (GdkWindow *window,
4884 const GdkRegion *region,
4885 gboolean (*child_func) (GdkWindow *,
4889 GdkWindowObject *private = (GdkWindowObject *)window;
4890 GdkWindowObject *impl_window;
4891 GdkRegion *visible_region;
4894 g_return_if_fail (GDK_IS_WINDOW (window));
4896 if (GDK_WINDOW_DESTROYED (window))
4899 if (private->input_only || !GDK_WINDOW_IS_MAPPED (window))
4902 visible_region = gdk_drawable_get_visible_region (window);
4903 gdk_region_intersect (visible_region, region);
4905 tmp_list = private->children;
4908 GdkWindowObject *child = tmp_list->data;
4910 if (!child->input_only)
4912 GdkRegion *child_region;
4913 GdkRectangle child_rect;
4915 child_rect.x = child->x;
4916 child_rect.y = child->y;
4917 child_rect.width = child->width;
4918 child_rect.height = child->height;
4919 child_region = gdk_region_rectangle (&child_rect);
4921 /* remove child area from the invalid area of the parent */
4922 if (GDK_WINDOW_IS_MAPPED (child) && !child->shaped &&
4923 !child->composited &&
4924 !gdk_window_is_offscreen (child))
4925 gdk_region_subtract (visible_region, child_region);
4927 if (child_func && (*child_func) ((GdkWindow *)child, user_data))
4929 GdkRegion *tmp = gdk_region_copy (region);
4931 gdk_region_offset (tmp, - child_rect.x, - child_rect.y);
4932 gdk_region_offset (child_region, - child_rect.x, - child_rect.y);
4933 gdk_region_intersect (child_region, tmp);
4935 gdk_window_invalidate_maybe_recurse ((GdkWindow *)child,
4936 child_region, child_func, user_data);
4938 gdk_region_destroy (tmp);
4941 gdk_region_destroy (child_region);
4944 tmp_list = tmp_list->next;
4947 impl_window = gdk_window_get_impl_window (private);
4949 if (!gdk_region_empty (visible_region) ||
4950 /* Even if we're not exposing anything, make sure we process
4951 idles for windows with outstanding moves */
4952 (impl_window->outstanding_moves != NULL &&
4953 impl_window->update_area == NULL))
4956 draw_ugly_color (window, region);
4958 /* Convert to impl coords */
4959 gdk_region_offset (visible_region, private->abs_x, private->abs_y);
4960 if (impl_window->update_area)
4962 gdk_region_union (impl_window->update_area, visible_region);
4966 gdk_window_add_update_window ((GdkWindow *)impl_window);
4967 impl_window->update_area = gdk_region_copy (visible_region);
4969 gdk_window_schedule_update ((GdkWindow *)impl_window);
4973 gdk_region_destroy (visible_region);
4977 true_predicate (GdkWindow *window,
4984 * gdk_window_invalidate_region:
4985 * @window: a #GdkWindow
4986 * @region: a #GdkRegion
4987 * @invalidate_children: %TRUE to also invalidate child windows
4989 * Adds @region to the update area for @window. The update area is the
4990 * region that needs to be redrawn, or "dirty region." The call
4991 * gdk_window_process_updates() sends one or more expose events to the
4992 * window, which together cover the entire update area. An
4993 * application would normally redraw the contents of @window in
4994 * response to those expose events.
4996 * GDK will call gdk_window_process_all_updates() on your behalf
4997 * whenever your program returns to the main loop and becomes idle, so
4998 * normally there's no need to do that manually, you just need to
4999 * invalidate regions that you know should be redrawn.
5001 * The @invalidate_children parameter controls whether the region of
5002 * each child window that intersects @region will also be invalidated.
5003 * If %FALSE, then the update area for child windows will remain
5004 * unaffected. See gdk_window_invalidate_maybe_recurse if you need
5005 * fine grained control over which children are invalidated.
5008 gdk_window_invalidate_region (GdkWindow *window,
5009 const GdkRegion *region,
5010 gboolean invalidate_children)
5012 gdk_window_invalidate_maybe_recurse (window, region,
5013 invalidate_children ?
5014 true_predicate : (gboolean (*) (GdkWindow *, gpointer))NULL,
5019 * _gdk_window_invalidate_for_expose:
5020 * @window: a #GdkWindow
5021 * @region: a #GdkRegion
5023 * Adds @region to the update area for @window. The update area is the
5024 * region that needs to be redrawn, or "dirty region." The call
5025 * gdk_window_process_updates() sends one or more expose events to the
5026 * window, which together cover the entire update area. An
5027 * application would normally redraw the contents of @window in
5028 * response to those expose events.
5030 * GDK will call gdk_window_process_all_updates() on your behalf
5031 * whenever your program returns to the main loop and becomes idle, so
5032 * normally there's no need to do that manually, you just need to
5033 * invalidate regions that you know should be redrawn.
5035 * This version of invalidation is used when you recieve expose events
5036 * from the native window system. It exposes the native window, plus
5037 * any non-native child windows (but not native child windows, as those would
5038 * have gotten their own expose events).
5041 _gdk_window_invalidate_for_expose (GdkWindow *window,
5042 const GdkRegion *region)
5044 gdk_window_invalidate_maybe_recurse (window, region,
5045 (gboolean (*) (GdkWindow *, gpointer))gdk_window_has_no_impl,
5051 * gdk_window_get_update_area:
5052 * @window: a #GdkWindow
5054 * Transfers ownership of the update area from @window to the caller
5055 * of the function. That is, after calling this function, @window will
5056 * no longer have an invalid/dirty region; the update area is removed
5057 * from @window and handed to you. If a window has no update area,
5058 * gdk_window_get_update_area() returns %NULL. You are responsible for
5059 * calling gdk_region_destroy() on the returned region if it's non-%NULL.
5061 * Return value: the update area for @window
5064 gdk_window_get_update_area (GdkWindow *window)
5066 GdkWindowObject *private = (GdkWindowObject *)window;
5067 GdkWindowObject *impl_window;
5068 GdkRegion *tmp_region;
5070 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
5072 impl_window = gdk_window_get_impl_window (private);
5074 if (impl_window->update_area)
5076 tmp_region = gdk_region_copy (private->clip_region_with_children);
5077 /* Convert to impl coords */
5078 gdk_region_offset (tmp_region, private->abs_x, private->abs_y);
5079 gdk_region_intersect (tmp_region, impl_window->update_area);
5081 if (gdk_region_empty (tmp_region))
5083 gdk_region_destroy (tmp_region);
5088 gdk_region_subtract (impl_window->update_area, tmp_region);
5090 if (gdk_region_empty (impl_window->update_area) &&
5091 impl_window->outstanding_moves == NULL)
5093 gdk_region_destroy (impl_window->update_area);
5094 impl_window->update_area = NULL;
5096 gdk_window_remove_update_window ((GdkWindow *)impl_window);
5099 /* Convert from impl coords */
5100 gdk_region_offset (tmp_region, -private->abs_x, -private->abs_y);
5110 * _gdk_window_clear_update_area:
5111 * @window: a #GdkWindow.
5113 * Internal function to clear the update area for a window. This
5114 * is called when the window is hidden or destroyed.
5117 _gdk_window_clear_update_area (GdkWindow *window)
5119 GdkWindowObject *private = (GdkWindowObject *)window;
5121 g_return_if_fail (GDK_IS_WINDOW (window));
5123 if (private->update_area)
5125 gdk_window_remove_update_window (window);
5127 gdk_region_destroy (private->update_area);
5128 private->update_area = NULL;
5133 * gdk_window_freeze_updates:
5134 * @window: a #GdkWindow
5136 * Temporarily freezes a window such that it won't receive expose
5137 * events. The window will begin receiving expose events again when
5138 * gdk_window_thaw_updates() is called. If gdk_window_freeze_updates()
5139 * has been called more than once, gdk_window_thaw_updates() must be called
5140 * an equal number of times to begin processing exposes.
5143 gdk_window_freeze_updates (GdkWindow *window)
5145 GdkWindowObject *private = (GdkWindowObject *)window;
5146 GdkWindowObject *impl_window;
5148 g_return_if_fail (GDK_IS_WINDOW (window));
5150 impl_window = gdk_window_get_impl_window (private);
5151 impl_window->update_freeze_count++;
5155 * gdk_window_thaw_updates:
5156 * @window: a #GdkWindow
5158 * Thaws a window frozen with gdk_window_freeze_updates().
5161 gdk_window_thaw_updates (GdkWindow *window)
5163 GdkWindowObject *private = (GdkWindowObject *)window;
5164 GdkWindowObject *impl_window;
5166 g_return_if_fail (GDK_IS_WINDOW (window));
5168 impl_window = gdk_window_get_impl_window (private);
5170 g_return_if_fail (impl_window->update_freeze_count > 0);
5172 if (--impl_window->update_freeze_count == 0)
5173 gdk_window_schedule_update (GDK_WINDOW (impl_window));
5177 * gdk_window_freeze_toplevel_updates_libgtk_only:
5178 * @window: a #GdkWindow
5180 * Temporarily freezes a window and all its descendants such that it won't
5181 * receive expose events. The window will begin receiving expose events
5182 * again when gdk_window_thaw_toplevel_updates_libgtk_only() is called. If
5183 * gdk_window_freeze_toplevel_updates_libgtk_only()
5184 * has been called more than once,
5185 * gdk_window_thaw_toplevel_updates_libgtk_only() must be called
5186 * an equal number of times to begin processing exposes.
5188 * This function is not part of the GDK public API and is only
5192 gdk_window_freeze_toplevel_updates_libgtk_only (GdkWindow *window)
5194 GdkWindowObject *private = (GdkWindowObject *)window;
5196 g_return_if_fail (GDK_IS_WINDOW (window));
5197 g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
5199 private->update_and_descendants_freeze_count++;
5203 * gdk_window_thaw_toplevel_updates_libgtk_only:
5204 * @window: a #GdkWindow
5206 * Thaws a window frozen with
5207 * gdk_window_freeze_toplevel_updates_libgtk_only().
5209 * This function is not part of the GDK public API and is only
5213 gdk_window_thaw_toplevel_updates_libgtk_only (GdkWindow *window)
5215 GdkWindowObject *private = (GdkWindowObject *)window;
5217 g_return_if_fail (GDK_IS_WINDOW (window));
5218 g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
5219 g_return_if_fail (private->update_and_descendants_freeze_count > 0);
5221 private->update_and_descendants_freeze_count--;
5223 gdk_window_schedule_update (window);
5227 * gdk_window_set_debug_updates:
5228 * @setting: %TRUE to turn on update debugging
5230 * With update debugging enabled, calls to
5231 * gdk_window_invalidate_region() clear the invalidated region of the
5232 * screen to a noticeable color, and GDK pauses for a short time
5233 * before sending exposes to windows during
5234 * gdk_window_process_updates(). The net effect is that you can see
5235 * the invalid region for each window and watch redraws as they
5236 * occur. This allows you to diagnose inefficiencies in your application.
5238 * In essence, because the GDK rendering model prevents all flicker,
5239 * if you are redrawing the same region 400 times you may never
5240 * notice, aside from noticing a speed problem. Enabling update
5241 * debugging causes GTK to flicker slowly and noticeably, so you can
5242 * see exactly what's being redrawn when, in what order.
5244 * The --gtk-debug=updates command line option passed to GTK+ programs
5245 * enables this debug option at application startup time. That's
5246 * usually more useful than calling gdk_window_set_debug_updates()
5247 * yourself, though you might want to use this function to enable
5248 * updates sometime after application startup time.
5252 gdk_window_set_debug_updates (gboolean setting)
5254 debug_updates = setting;
5258 * gdk_window_constrain_size:
5259 * @geometry: a #GdkGeometry structure
5260 * @flags: a mask indicating what portions of @geometry are set
5261 * @width: desired width of window
5262 * @height: desired height of the window
5263 * @new_width: location to store resulting width
5264 * @new_height: location to store resulting height
5266 * Constrains a desired width and height according to a
5267 * set of geometry hints (such as minimum and maximum size).
5270 gdk_window_constrain_size (GdkGeometry *geometry,
5277 /* This routine is partially borrowed from fvwm.
5279 * Copyright 1993, Robert Nation
5280 * You may use this code for any purpose, as long as the original
5281 * copyright remains in the source code and all documentation
5283 * which in turn borrows parts of the algorithm from uwm
5286 gint min_height = 0;
5287 gint base_width = 0;
5288 gint base_height = 0;
5291 gint max_width = G_MAXINT;
5292 gint max_height = G_MAXINT;
5294 #define FLOOR(value, base) ( ((gint) ((value) / (base))) * (base) )
5296 if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
5298 base_width = geometry->base_width;
5299 base_height = geometry->base_height;
5300 min_width = geometry->min_width;
5301 min_height = geometry->min_height;
5303 else if (flags & GDK_HINT_BASE_SIZE)
5305 base_width = geometry->base_width;
5306 base_height = geometry->base_height;
5307 min_width = geometry->base_width;
5308 min_height = geometry->base_height;
5310 else if (flags & GDK_HINT_MIN_SIZE)
5312 base_width = geometry->min_width;
5313 base_height = geometry->min_height;
5314 min_width = geometry->min_width;
5315 min_height = geometry->min_height;
5318 if (flags & GDK_HINT_MAX_SIZE)
5320 max_width = geometry->max_width ;
5321 max_height = geometry->max_height;
5324 if (flags & GDK_HINT_RESIZE_INC)
5326 xinc = MAX (xinc, geometry->width_inc);
5327 yinc = MAX (yinc, geometry->height_inc);
5330 /* clamp width and height to min and max values
5332 width = CLAMP (width, min_width, max_width);
5333 height = CLAMP (height, min_height, max_height);
5335 /* shrink to base + N * inc
5337 width = base_width + FLOOR (width - base_width, xinc);
5338 height = base_height + FLOOR (height - base_height, yinc);
5340 /* constrain aspect ratio, according to:
5343 * min_aspect <= -------- <= max_aspect
5347 if (flags & GDK_HINT_ASPECT &&
5348 geometry->min_aspect > 0 &&
5349 geometry->max_aspect > 0)
5353 if (geometry->min_aspect * height > width)
5355 delta = FLOOR (height - width / geometry->min_aspect, yinc);
5356 if (height - delta >= min_height)
5360 delta = FLOOR (height * geometry->min_aspect - width, xinc);
5361 if (width + delta <= max_width)
5366 if (geometry->max_aspect * height < width)
5368 delta = FLOOR (width - height * geometry->max_aspect, xinc);
5369 if (width - delta >= min_width)
5373 delta = FLOOR (width / geometry->max_aspect - height, yinc);
5374 if (height + delta <= max_height)
5383 *new_height = height;
5387 * gdk_window_get_pointer:
5388 * @window: a #GdkWindow
5389 * @x: return location for X coordinate of pointer or %NULL to not
5390 * return the X coordinate
5391 * @y: return location for Y coordinate of pointer or %NULL to not
5392 * return the Y coordinate
5393 * @mask: return location for modifier mask or %NULL to not return the
5396 * Obtains the current pointer position and modifier state.
5397 * The position is given in coordinates relative to the upper left
5398 * corner of @window.
5400 * Return value: the window containing the pointer (as with
5401 * gdk_window_at_pointer()), or %NULL if the window containing the
5402 * pointer isn't known to GDK
5405 gdk_window_get_pointer (GdkWindow *window,
5408 GdkModifierType *mask)
5410 GdkDisplay *display;
5412 GdkModifierType tmp_mask;
5415 g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
5419 display = gdk_drawable_get_display (window);
5423 GdkScreen *screen = gdk_screen_get_default ();
5425 display = gdk_screen_get_display (screen);
5426 window = gdk_screen_get_root_window (screen);
5428 GDK_NOTE (MULTIHEAD,
5429 g_message ("Passing NULL for window to gdk_window_get_pointer()\n"
5430 "is not multihead safe"));
5433 child = display->pointer_hooks->window_get_pointer (display, window, &tmp_x, &tmp_y, &tmp_mask);
5442 _gdk_display_enable_motion_hints (display);
5448 * gdk_window_at_pointer:
5449 * @win_x: return location for origin of the window under the pointer
5450 * @win_y: return location for origin of the window under the pointer
5452 * Obtains the window underneath the mouse pointer, returning the
5453 * location of that window in @win_x, @win_y. Returns %NULL if the
5454 * window under the mouse pointer is not known to GDK (if the window
5455 * belongs to another application and a #GdkWindow hasn't been created
5456 * for it with gdk_window_foreign_new())
5458 * NOTE: For multihead-aware widgets or applications use
5459 * gdk_display_get_window_at_pointer() instead.
5461 * Return value: window under the mouse pointer
5464 gdk_window_at_pointer (gint *win_x,
5467 return gdk_display_get_window_at_pointer (gdk_display_get_default (), win_x, win_y);
5471 * gdk_get_default_root_window:
5473 * Obtains the root window (parent all other windows are inside)
5474 * for the default display and screen.
5476 * Return value: the default root window
5479 gdk_get_default_root_window (void)
5481 return gdk_screen_get_root_window (gdk_screen_get_default ());
5485 * gdk_window_foreign_new:
5486 * @anid: a native window handle.
5488 * Wraps a native window for the default display in a #GdkWindow.
5489 * This may fail if the window has been destroyed.
5491 * For example in the X backend, a native window handle is an Xlib
5494 * Return value: the newly-created #GdkWindow wrapper for the
5495 * native window or %NULL if the window has been destroyed.
5498 gdk_window_foreign_new (GdkNativeWindow anid)
5500 return gdk_window_foreign_new_for_display (gdk_display_get_default (), anid);
5504 get_all_native_children (GdkWindowObject *private,
5507 GdkWindowObject *child;
5510 for (l = private->children; l != NULL; l = l->next)
5514 if (gdk_window_has_impl (child))
5515 *native = g_list_prepend (*native, child);
5517 get_all_native_children (child, native);
5523 gdk_window_raise_internal (GdkWindow *window)
5525 GdkWindowObject *private = (GdkWindowObject *)window;
5526 GdkWindowObject *parent = private->parent;
5527 GdkWindowObject *above;
5528 GList *native_children;
5533 parent->children = g_list_remove (parent->children, window);
5534 parent->children = g_list_prepend (parent->children, window);
5537 /* Just do native raise for toplevels */
5538 if (private->parent == NULL ||
5539 GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
5541 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
5543 else if (gdk_window_has_impl (private))
5545 above = find_native_sibling_above (parent, private);
5548 listhead.data = window;
5549 listhead.next = NULL;
5550 listhead.prev = NULL;
5551 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
5555 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
5559 native_children = NULL;
5560 get_all_native_children (private, &native_children);
5561 if (native_children != NULL)
5563 above = find_native_sibling_above (parent, private);
5566 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
5570 /* Right order, since native_chilren is bottom-opmost first */
5571 for (l = native_children; l != NULL; l = l->next)
5572 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (l->data);
5575 g_list_free (native_children);
5582 show_all_visible_impls (GdkWindowObject *private)
5584 GdkWindowObject *child;
5587 for (l = private->children; l != NULL; l = l->next)
5590 if (GDK_WINDOW_IS_MAPPED (child))
5591 show_all_visible_impls (child);
5594 if (gdk_window_has_impl (private))
5595 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show ((GdkWindow *)private);
5599 gdk_window_show_internal (GdkWindow *window, gboolean raise)
5601 GdkWindowObject *private;
5602 gboolean was_mapped;
5604 g_return_if_fail (GDK_IS_WINDOW (window));
5606 private = (GdkWindowObject *) window;
5607 if (private->destroyed)
5610 was_mapped = GDK_WINDOW_IS_MAPPED (window);
5613 /* Keep children in (reverse) stacking order */
5614 gdk_window_raise_internal (window);
5616 if (gdk_window_has_impl (private))
5619 gdk_synthesize_window_state (window,
5620 GDK_WINDOW_STATE_WITHDRAWN,
5628 if (gdk_window_is_viewable (window))
5629 show_all_visible_impls (private);
5633 if (private->event_mask & GDK_STRUCTURE_MASK)
5634 _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
5636 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
5637 _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
5640 if (!was_mapped || raise)
5642 recompute_visible_regions (private, TRUE, FALSE);
5644 if (gdk_window_is_viewable (window))
5646 _gdk_syntesize_crossing_events_for_geometry_change (window);
5647 gdk_window_invalidate_rect (window, NULL, TRUE);
5653 * gdk_window_show_unraised:
5654 * @window: a #GdkWindow
5656 * Shows a #GdkWindow onscreen, but does not modify its stacking
5657 * order. In contrast, gdk_window_show() will raise the window
5658 * to the top of the window stack.
5660 * On the X11 platform, in Xlib terms, this function calls
5661 * XMapWindow() (it also updates some internal GDK state, which means
5662 * that you can't really use XMapWindow() directly on a GDK window).
5665 gdk_window_show_unraised (GdkWindow *window)
5667 gdk_window_show_internal (window, FALSE);
5672 * @window: a #GdkWindow
5674 * Raises @window to the top of the Z-order (stacking order), so that
5675 * other windows with the same parent window appear below @window.
5676 * This is true whether or not the windows are visible.
5678 * If @window is a toplevel, the window manager may choose to deny the
5679 * request to move the window in the Z-order, gdk_window_raise() only
5680 * requests the restack, does not guarantee it.
5683 gdk_window_raise (GdkWindow *window)
5685 GdkWindowObject *private;
5687 g_return_if_fail (GDK_IS_WINDOW (window));
5689 private = (GdkWindowObject *) window;
5690 if (private->destroyed)
5693 /* Keep children in (reverse) stacking order */
5694 gdk_window_raise_internal (window);
5696 recompute_visible_regions (private, TRUE, FALSE);
5698 gdk_window_invalidate_rect (window, NULL, TRUE);
5702 gdk_window_lower_internal (GdkWindow *window)
5704 GdkWindowObject *private = (GdkWindowObject *)window;
5705 GdkWindowObject *parent = private->parent;
5706 GdkWindowObject *above;
5707 GList *native_children;
5712 parent->children = g_list_remove (parent->children, window);
5713 parent->children = g_list_append (parent->children, window);
5716 /* Just do native lower for toplevels */
5717 if (private->parent == NULL ||
5718 GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
5720 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->lower (window);
5722 else if (gdk_window_has_impl (private))
5724 above = find_native_sibling_above (parent, private);
5727 listhead.data = window;
5728 listhead.next = NULL;
5729 listhead.prev = NULL;
5730 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
5734 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
5738 native_children = NULL;
5739 get_all_native_children (private, &native_children);
5740 if (native_children != NULL)
5742 above = find_native_sibling_above (parent, private);
5745 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
5749 /* Right order, since native_chilren is bottom-opmost first */
5750 for (l = native_children; l != NULL; l = l->next)
5751 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (l->data);
5754 g_list_free (native_children);
5761 gdk_window_invalidate_in_parent (GdkWindowObject *private)
5763 GdkRectangle r, child;
5765 if (private->parent == NULL ||
5766 GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
5769 /* get the visible rectangle of the parent */
5771 r.width = private->parent->width;
5772 r.height = private->parent->height;
5774 child.x = private->x;
5775 child.y = private->y;
5776 child.width = private->width;
5777 child.height = private->height;
5778 gdk_rectangle_intersect (&r, &child, &r);
5780 gdk_window_invalidate_rect (GDK_WINDOW (private->parent), &r, TRUE);
5786 * @window: a #GdkWindow
5788 * Lowers @window to the bottom of the Z-order (stacking order), so that
5789 * other windows with the same parent window appear above @window.
5790 * This is true whether or not the other windows are visible.
5792 * If @window is a toplevel, the window manager may choose to deny the
5793 * request to move the window in the Z-order, gdk_window_lower() only
5794 * requests the restack, does not guarantee it.
5796 * Note that gdk_window_show() raises the window again, so don't call this
5797 * function before gdk_window_show(). (Try gdk_window_show_unraised().)
5800 gdk_window_lower (GdkWindow *window)
5802 GdkWindowObject *private;
5804 g_return_if_fail (GDK_IS_WINDOW (window));
5806 private = (GdkWindowObject *) window;
5807 if (private->destroyed)
5810 /* Keep children in (reverse) stacking order */
5811 gdk_window_lower_internal (window);
5813 recompute_visible_regions (private, TRUE, FALSE);
5815 _gdk_syntesize_crossing_events_for_geometry_change (window);
5816 gdk_window_invalidate_in_parent (private);
5821 * @window: a #GdkWindow
5823 * Like gdk_window_show_unraised(), but also raises the window to the
5824 * top of the window stack (moves the window to the front of the
5827 * This function maps a window so it's visible onscreen. Its opposite
5828 * is gdk_window_hide().
5830 * When implementing a #GtkWidget, you should call this function on the widget's
5831 * #GdkWindow as part of the "map" method.
5834 gdk_window_show (GdkWindow *window)
5836 gdk_window_show_internal (window, TRUE);
5840 hide_all_visible_impls (GdkWindowObject *private)
5842 GdkWindowObject *child;
5845 for (l = private->children; l != NULL; l = l->next)
5849 if (GDK_WINDOW_IS_MAPPED (child))
5850 hide_all_visible_impls (child);
5853 if (gdk_window_has_impl (private))
5854 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->hide ((GdkWindow *)private);
5860 * @window: a #GdkWindow
5862 * For toplevel windows, withdraws them, so they will no longer be
5863 * known to the window manager; for all windows, unmaps them, so
5864 * they won't be displayed. Normally done automatically as
5865 * part of gtk_widget_hide().
5868 gdk_window_hide (GdkWindow *window)
5870 GdkWindowObject *private;
5871 gboolean was_mapped, was_viewable;
5873 g_return_if_fail (GDK_IS_WINDOW (window));
5875 private = (GdkWindowObject *) window;
5876 if (private->destroyed)
5879 was_mapped = GDK_WINDOW_IS_MAPPED (private);
5880 was_viewable = gdk_window_is_viewable (window);
5882 if (gdk_window_has_impl (private))
5885 if (GDK_WINDOW_IS_MAPPED (window))
5886 gdk_synthesize_window_state (window,
5888 GDK_WINDOW_STATE_WITHDRAWN);
5890 else if (was_mapped)
5892 GdkDisplay *display;
5894 /* May need to break grabs on children */
5895 display = gdk_drawable_get_display (window);
5897 if (_gdk_display_end_pointer_grab (display,
5898 _gdk_windowing_window_get_next_serial (display),
5901 gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
5903 if (display->keyboard_grab.window != NULL)
5905 if (is_parent_of (window, display->keyboard_grab.window))
5907 /* Call this ourselves, even though gdk_display_keyboard_ungrab
5908 does so too, since we want to pass implicit == TRUE so the
5909 broken grab event is generated */
5910 _gdk_display_unset_has_keyboard_grab (display,
5912 gdk_display_keyboard_ungrab (display, GDK_CURRENT_TIME);
5916 private->state = GDK_WINDOW_STATE_WITHDRAWN;
5920 hide_all_visible_impls (private);
5922 recompute_visible_regions (private, TRUE, FALSE);
5926 if (private->event_mask & GDK_STRUCTURE_MASK)
5927 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
5929 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
5930 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
5932 _gdk_syntesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
5935 /* Invalidate the rect */
5936 gdk_window_invalidate_in_parent (private);
5940 * gdk_window_withdraw:
5941 * @window: a toplevel #GdkWindow
5943 * Withdraws a window (unmaps it and asks the window manager to forget about it).
5944 * This function is not really useful as gdk_window_hide() automatically
5945 * withdraws toplevel windows before hiding them.
5948 gdk_window_withdraw (GdkWindow *window)
5950 GdkWindowObject *private;
5951 gboolean was_mapped;
5953 g_return_if_fail (GDK_IS_WINDOW (window));
5955 private = (GdkWindowObject *) window;
5956 if (private->destroyed)
5959 was_mapped = GDK_WINDOW_IS_MAPPED (private);
5961 if (gdk_window_has_impl (private))
5963 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->withdraw (window);
5967 if (private->event_mask & GDK_STRUCTURE_MASK)
5968 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
5970 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
5971 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
5973 _gdk_syntesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
5976 recompute_visible_regions (private, TRUE, FALSE);
5981 * gdk_window_set_events:
5982 * @window: a #GdkWindow
5983 * @event_mask: event mask for @window
5985 * The event mask for a window determines which events will be reported
5986 * for that window. For example, an event mask including #GDK_BUTTON_PRESS_MASK
5987 * means the window should report button press events. The event mask
5988 * is the bitwise OR of values from the #GdkEventMask enumeration.
5991 gdk_window_set_events (GdkWindow *window,
5992 GdkEventMask event_mask)
5994 GdkWindowObject *private;
5995 GdkDisplay *display;
5998 g_return_if_fail (GDK_IS_WINDOW (window));
6000 private = (GdkWindowObject *) window;
6001 if (private->destroyed)
6004 /* If motion hint is disabled, enable motion events again */
6005 display = gdk_drawable_get_display (window);
6006 if ((private->event_mask & GDK_POINTER_MOTION_HINT_MASK) &&
6007 !(event_mask & GDK_POINTER_MOTION_HINT_MASK))
6008 _gdk_display_enable_motion_hints (display);
6010 private->event_mask = event_mask;
6012 if (gdk_window_has_impl (private))
6013 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_events (window,
6014 get_native_event_mask (private));
6019 * gdk_window_get_events:
6020 * @window: a #GdkWindow
6022 * Gets the event mask for @window. See gdk_window_set_events().
6024 * Return value: event mask for @window
6027 gdk_window_get_events (GdkWindow *window)
6029 GdkWindowObject *private;
6031 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
6033 private = (GdkWindowObject *) window;
6034 if (private->destroyed)
6037 return private->event_mask;
6041 gdk_window_move_resize_toplevel (GdkWindow *window,
6048 GdkWindowObject *private;
6049 GdkRegion *old_region, *new_region;
6050 GdkWindowObject *impl_window;
6052 int old_x, old_y, old_abs_x, old_abs_y;
6056 private = (GdkWindowObject *) window;
6061 impl_window = gdk_window_get_impl_window (private);
6066 is_resize = (width != -1) || (height != -1);
6068 if (GDK_WINDOW_IS_MAPPED (window) &&
6069 !private->input_only)
6072 old_region = gdk_region_copy (private->clip_region);
6075 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, with_move, x, y, width, height);
6077 dx = private->x - old_x;
6078 dy = private->y - old_y;
6080 old_abs_x = private->abs_x;
6081 old_abs_y = private->abs_y;
6083 /* Avoid recomputing for pure toplevel moves, for performance reasons */
6085 recompute_visible_regions (private, TRUE, FALSE);
6089 new_region = gdk_region_copy (private->clip_region);
6091 /* This is the newly exposed area (due to any resize),
6092 * X will expose it, but lets do that without the
6095 gdk_region_subtract (new_region, old_region);
6096 gdk_window_invalidate_region (window, new_region, TRUE);
6098 gdk_region_destroy (old_region);
6099 gdk_region_destroy (new_region);
6102 _gdk_syntesize_crossing_events_for_geometry_change (window);
6107 move_native_children (GdkWindowObject *private)
6110 GdkWindowObject *child;
6112 for (l = private->children; l; l = l->next)
6116 if (child->impl != private->impl)
6117 GDK_WINDOW_IMPL_GET_IFACE (child->impl)->move_resize ((GdkWindow *)child, TRUE, child->x, child->y, child->width, child->height);
6119 move_native_children (child);
6124 collect_native_child_region_helper (GdkWindowObject *window,
6130 GdkWindowObject *child;
6134 for (l = window->children; l != NULL; l = l->next)
6138 if (child->impl != impl)
6140 tmp = gdk_region_copy (child->clip_region);
6141 gdk_region_offset (tmp,
6142 x_offset + child->x,
6143 y_offset + child->y);
6144 if (*region == NULL)
6148 gdk_region_union (*region, tmp);
6149 gdk_region_destroy (tmp);
6153 collect_native_child_region_helper (child, impl, region,
6154 x_offset + child->x,
6155 y_offset + child->y);
6162 collect_native_child_region (GdkWindowObject *window,
6163 gboolean include_this)
6167 if (include_this && gdk_window_has_impl (window))
6168 return gdk_region_copy (window->clip_region);
6172 collect_native_child_region_helper (window, window->impl, ®ion, 0, 0);
6179 gdk_window_move_resize_internal (GdkWindow *window,
6186 GdkWindowObject *private;
6187 GdkRegion *old_region, *new_region, *copy_area;
6188 GdkRegion *old_native_child_region, *new_native_child_region;
6189 GdkWindowObject *impl_window;
6191 int old_x, old_y, old_abs_x, old_abs_y;
6194 g_return_if_fail (GDK_IS_WINDOW (window));
6196 private = (GdkWindowObject *) window;
6197 if (private->destroyed)
6200 if (private->parent == NULL ||
6201 GDK_WINDOW_TYPE (private->parent) == GDK_WINDOW_ROOT)
6203 gdk_window_move_resize_toplevel (window, with_move, x, y, width, height);
6207 /* Handle child windows */
6212 impl_window = gdk_window_get_impl_window (private);
6217 if (GDK_WINDOW_IS_MAPPED (window) &&
6218 !private->input_only)
6222 old_region = gdk_region_copy (private->clip_region);
6223 /* Adjust region to parent window coords */
6224 gdk_region_offset (old_region, private->x, private->y);
6227 old_native_child_region = collect_native_child_region (private, TRUE);
6228 if (old_native_child_region)
6230 /* Adjust region to parent window coords */
6231 gdk_region_offset (old_native_child_region, private->x, private->y);
6233 /* Any native window move will immediately copy stuff to the destination, which may overwrite a
6234 * source or destination for a delayed GdkWindowRegionMove. So, we need
6235 * to flush those here for the parent window and all overlapped subwindows
6236 * of it. And we need to do this before setting the new clips as those will be
6239 gdk_window_flush_recursive (private->parent);
6242 /* Set the new position and size */
6248 if (!(width < 0 && height < 0))
6252 private->width = width;
6255 private->height = height;
6258 dx = private->x - old_x;
6259 dy = private->y - old_y;
6261 old_abs_x = private->abs_x;
6262 old_abs_y = private->abs_y;
6264 recompute_visible_regions (private, TRUE, FALSE);
6266 new_native_child_region = NULL;
6267 if (old_native_child_region)
6269 new_native_child_region = collect_native_child_region (private, TRUE);
6270 /* Adjust region to parent window coords */
6271 gdk_region_offset (new_native_child_region, private->x, private->y);
6274 if (gdk_window_has_impl (private))
6276 /* Do the actual move after recomputing things, as this will have set the shape to
6277 the now correct one, thus avoiding copying regions that should not be copied. */
6278 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, TRUE, private->x, private->y, private->width, private->height);
6280 else if (old_abs_x != private->abs_x ||
6281 old_abs_y != private->abs_y)
6282 move_native_children (private);
6286 new_region = gdk_region_copy (private->clip_region);
6287 /* Adjust region to parent window coords */
6288 gdk_region_offset (new_region, private->x, private->y);
6291 * Part of the data at the new location can be copied from the
6292 * old location, this area is the intersection of the old region
6293 * moved as the copy will move it and then intersected with
6297 * Everything in the old and new regions that is not copied must be
6298 * invalidated (including children) as this is newly exposed
6300 copy_area = gdk_region_copy (new_region);
6302 gdk_region_union (new_region, old_region);
6304 if (old_native_child_region)
6306 /* Don't copy from inside native children, as this is copied by
6307 * the native window move.
6309 gdk_region_subtract (old_region, old_native_child_region);
6311 gdk_region_offset (old_region, dx, dy);
6313 gdk_region_intersect (copy_area, old_region);
6315 if (new_native_child_region)
6317 /* Don't copy any bits that would cause a read from the moved
6318 native windows, as we can't read that data */
6319 gdk_region_offset (new_native_child_region, dx, dy);
6320 gdk_region_subtract (copy_area, new_native_child_region);
6323 gdk_region_subtract (new_region, copy_area);
6325 /* Convert old region to impl coords */
6326 gdk_region_offset (old_region, -dx + private->abs_x - private->x, -dy + private->abs_y - private->y);
6328 /* convert from parent coords to impl */
6329 gdk_region_offset (copy_area, private->abs_x - private->x, private->abs_y - private->y);
6331 move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
6333 /* Invalidate affected part in the parent window
6334 * (no higher window should be affected)
6335 * We also invalidate any children in that area, which could include
6336 * this window if it still overlaps that area.
6338 gdk_window_invalidate_region (GDK_WINDOW (private->parent), new_region, TRUE);
6340 gdk_region_destroy (old_region);
6341 gdk_region_destroy (new_region);
6344 if (old_native_child_region)
6346 gdk_region_destroy (old_native_child_region);
6347 gdk_region_destroy (new_native_child_region);
6350 _gdk_syntesize_crossing_events_for_geometry_change (window);
6357 * @window: a #GdkWindow
6358 * @x: X coordinate relative to window's parent
6359 * @y: Y coordinate relative to window's parent
6361 * Repositions a window relative to its parent window.
6362 * For toplevel windows, window managers may ignore or modify the move;
6363 * you should probably use gtk_window_move() on a #GtkWindow widget
6364 * anyway, instead of using GDK functions. For child windows,
6365 * the move will reliably succeed.
6367 * If you're also planning to resize the window, use gdk_window_move_resize()
6368 * to both move and resize simultaneously, for a nicer visual effect.
6371 gdk_window_move (GdkWindow *window,
6375 gdk_window_move_resize_internal (window, TRUE, x, y, -1, -1);
6379 * gdk_window_resize:
6380 * @window: a #GdkWindow
6381 * @width: new width of the window
6382 * @height: new height of the window
6384 * Resizes @window; for toplevel windows, asks the window manager to resize
6385 * the window. The window manager may not allow the resize. When using GTK+,
6386 * use gtk_window_resize() instead of this low-level GDK function.
6388 * Windows may not be resized below 1x1.
6390 * If you're also planning to move the window, use gdk_window_move_resize()
6391 * to both move and resize simultaneously, for a nicer visual effect.
6394 gdk_window_resize (GdkWindow *window,
6398 gdk_window_move_resize_internal (window, FALSE, 0, 0, width, height);
6403 * gdk_window_move_resize:
6404 * @window: a #GdkWindow
6405 * @x: new X position relative to window's parent
6406 * @y: new Y position relative to window's parent
6408 * @height: new height
6410 * Equivalent to calling gdk_window_move() and gdk_window_resize(),
6411 * except that both operations are performed at once, avoiding strange
6412 * visual effects. (i.e. the user may be able to see the window first
6413 * move, then resize, if you don't use gdk_window_move_resize().)
6416 gdk_window_move_resize (GdkWindow *window,
6422 gdk_window_move_resize_internal (window, TRUE, x, y, width, height);
6427 * gdk_window_scroll:
6428 * @window: a #GdkWindow
6429 * @dx: Amount to scroll in the X direction
6430 * @dy: Amount to scroll in the Y direction
6432 * Scroll the contents of @window, both pixels and children, by the
6433 * given amount. @window itself does not move. Portions of the window
6434 * that the scroll operation brings in from offscreen areas are
6435 * invalidated. The invalidated region may be bigger than what would
6436 * strictly be necessary.
6438 * For X11, a minimum area will be invalidated if the window has no
6439 * subwindows, or if the edges of the window's parent do not extend
6440 * beyond the edges of the window. In other cases, a multi-step process
6441 * is used to scroll the window which may produce temporary visual
6442 * artifacts and unnecessary invalidations.
6445 gdk_window_scroll (GdkWindow *window,
6449 GdkWindowObject *private = (GdkWindowObject *) window;
6450 GdkWindowObject *impl_window;
6451 GdkRegion *copy_area, *noncopy_area;
6452 GdkRegion *old_native_child_region, *new_native_child_region;
6455 g_return_if_fail (GDK_IS_WINDOW (window));
6457 if (dx == 0 && dy == 0)
6460 if (private->destroyed)
6463 old_native_child_region = collect_native_child_region (private, FALSE);
6464 if (old_native_child_region)
6466 /* Any native window move will immediately copy stuff to the destination, which may overwrite a
6467 * source or destination for a delayed GdkWindowRegionMove. So, we need
6468 * to flush those here for the window and all overlapped subwindows
6469 * of it. And we need to do this before setting the new clips as those will be
6472 gdk_window_flush_recursive (private);
6476 /* First move all child windows, without causing invalidation */
6478 tmp_list = private->children;
6481 GdkWindow *child = GDK_WINDOW (tmp_list->data);
6482 GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
6484 /* Just update the positions, the bits will move with the copy */
6488 tmp_list = tmp_list->next;
6491 recompute_visible_regions (private, FALSE, TRUE);
6493 new_native_child_region = NULL;
6494 if (old_native_child_region)
6495 new_native_child_region = collect_native_child_region (private, FALSE);
6497 move_native_children (private);
6499 /* Then copy the actual bits of the window w/ child windows */
6501 impl_window = gdk_window_get_impl_window (private);
6503 /* Calculate the area that can be gotten by copying the old area */
6504 copy_area = gdk_region_copy (private->clip_region);
6505 if (old_native_child_region)
6507 /* Don't copy from inside native children, as this is copied by
6508 * the native window move.
6510 gdk_region_subtract (copy_area, old_native_child_region);
6512 /* Don't copy any bits that would cause a read from the moved
6513 native windows, as we can't read that data */
6514 gdk_region_subtract (copy_area, new_native_child_region);
6516 gdk_region_offset (copy_area, dx, dy);
6517 gdk_region_intersect (copy_area, private->clip_region);
6519 /* And the rest need to be invalidated */
6520 noncopy_area = gdk_region_copy (private->clip_region);
6521 gdk_region_subtract (noncopy_area, copy_area);
6523 /* convert from window coords to impl */
6524 gdk_region_offset (copy_area, private->abs_x, private->abs_y);
6526 move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
6528 /* Invalidate not copied regions */
6529 gdk_window_invalidate_region (window, noncopy_area, TRUE);
6531 gdk_region_destroy (noncopy_area);
6533 if (old_native_child_region)
6535 gdk_region_destroy (old_native_child_region);
6536 gdk_region_destroy (new_native_child_region);
6539 _gdk_syntesize_crossing_events_for_geometry_change (window);
6543 * gdk_window_move_region:
6544 * @window: a #GdkWindow
6545 * @region: The #GdkRegion to move
6546 * @dx: Amount to move in the X direction
6547 * @dy: Amount to move in the Y direction
6549 * Move the part of @window indicated by @region by @dy pixels in the Y
6550 * direction and @dx pixels in the X direction. The portions of @region
6551 * that not covered by the new position of @region are invalidated.
6553 * Child windows are not moved.
6558 gdk_window_move_region (GdkWindow *window,
6559 const GdkRegion *region,
6563 GdkWindowObject *private = (GdkWindowObject *) window;
6564 GdkWindowObject *impl_window;
6565 GdkRegion *nocopy_area;
6566 GdkRegion *copy_area;
6568 g_return_if_fail (GDK_IS_WINDOW (window));
6569 g_return_if_fail (region != NULL);
6571 if (dx == 0 && dy == 0)
6574 if (private->destroyed)
6577 impl_window = gdk_window_get_impl_window (private);
6579 /* compute source regions */
6580 copy_area = gdk_region_copy (region);
6581 gdk_region_intersect (copy_area, private->clip_region_with_children);
6583 /* compute destination regions */
6584 gdk_region_offset (copy_area, dx, dy);
6585 gdk_region_intersect (copy_area, private->clip_region_with_children);
6587 /* invalidate parts of the region not covered by the copy */
6588 nocopy_area = gdk_region_copy (region);
6589 gdk_region_offset (nocopy_area, dx, dy);
6590 gdk_region_subtract (nocopy_area, copy_area);
6591 gdk_window_invalidate_region (window, nocopy_area, FALSE);
6592 gdk_region_destroy (nocopy_area);
6594 /* convert from window coords to impl */
6595 gdk_region_offset (copy_area, private->abs_x, private->abs_y);
6597 move_region_on_impl (impl_window, copy_area, dx, dy); /* Takes ownership of copy_area */
6601 * gdk_window_set_background:
6602 * @window: a #GdkWindow
6603 * @color: an allocated #GdkColor
6605 * Sets the background color of @window. (However, when using GTK+,
6606 * set the background of a widget with gtk_widget_modify_bg() - if
6607 * you're an application - or gtk_style_set_background() - if you're
6608 * implementing a custom widget.)
6610 * The @color must be allocated; gdk_rgb_find_color() is the best way
6611 * to allocate a color.
6613 * See also gdk_window_set_back_pixmap().
6616 gdk_window_set_background (GdkWindow *window,
6617 const GdkColor *color)
6619 GdkWindowObject *private;
6620 GdkColormap *colormap = gdk_drawable_get_colormap (window);
6622 g_return_if_fail (GDK_IS_WINDOW (window));
6624 private = (GdkWindowObject *) window;
6626 private->bg_color = *color;
6627 gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
6629 if (private->bg_pixmap &&
6630 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
6631 private->bg_pixmap != GDK_NO_BG)
6632 g_object_unref (private->bg_pixmap);
6634 private->bg_pixmap = NULL;
6636 if (!GDK_WINDOW_DESTROYED (window) &&
6637 gdk_window_has_impl (private) &&
6638 !private->input_only)
6639 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, &private->bg_color);
6643 * gdk_window_set_back_pixmap:
6644 * @window: a #GdkWindow
6645 * @pixmap: a #GdkPixmap, or %NULL
6646 * @parent_relative: whether the tiling origin is at the origin of
6649 * Sets the background pixmap of @window. May also be used to set a
6650 * background of "None" on @window, by setting a background pixmap
6653 * A background pixmap will be tiled, positioning the first tile at
6654 * the origin of @window, or if @parent_relative is %TRUE, the tiling
6655 * will be done based on the origin of the parent window (useful to
6656 * align tiles in a parent with tiles in a child).
6658 * A background pixmap of %NULL means that the window will have no
6659 * background. A window with no background will never have its
6660 * background filled by the windowing system, instead the window will
6661 * contain whatever pixels were already in the corresponding area of
6664 * The windowing system will normally fill a window with its background
6665 * when the window is obscured then exposed, and when you call
6666 * gdk_window_clear().
6669 gdk_window_set_back_pixmap (GdkWindow *window,
6671 gboolean parent_relative)
6673 GdkWindowObject *private;
6675 g_return_if_fail (GDK_IS_WINDOW (window));
6676 g_return_if_fail (pixmap == NULL || !parent_relative);
6677 g_return_if_fail (pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap));
6679 private = (GdkWindowObject *) window;
6681 if (pixmap && !gdk_drawable_get_colormap (pixmap))
6683 g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
6687 if (private->bg_pixmap &&
6688 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
6689 private->bg_pixmap != GDK_NO_BG)
6690 g_object_unref (private->bg_pixmap);
6692 if (parent_relative)
6693 private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
6695 private->bg_pixmap = g_object_ref (pixmap);
6697 private->bg_pixmap = GDK_NO_BG;
6699 if (!GDK_WINDOW_DESTROYED (window) &&
6700 gdk_window_has_impl (private) &&
6701 !private->input_only)
6702 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, private->bg_pixmap);
6706 update_cursor (GdkDisplay *display)
6708 GdkWindowObject *pointer_window, *cursor_window;
6709 GdkPointerGrabInfo *grab;
6711 pointer_window = (GdkWindowObject *)display->pointer_info.window_under_pointer;
6713 cursor_window = pointer_window;
6714 while (cursor_window->cursor == NULL &&
6715 cursor_window->parent != NULL &&
6716 cursor_window->parent->window_type != GDK_WINDOW_ROOT)
6717 cursor_window = cursor_window->parent;
6719 /* We ignore the serials here and just pick the last grab
6720 we've sent, as that would shortly be used anyway. */
6721 grab = _gdk_display_get_last_pointer_grab (display);
6723 !is_parent_of (grab->window, (GdkWindow *)cursor_window))
6724 cursor_window = (GdkWindowObject *)grab->window;
6726 /* Set all cursors on toplevel, otherwise its tricky to keep track of
6727 * which native window has what cursor set. */
6728 GDK_WINDOW_IMPL_GET_IFACE (pointer_window->impl)->set_cursor
6729 (gdk_window_get_toplevel ((GdkWindow *)pointer_window),
6730 cursor_window->cursor);
6734 * gdk_window_set_cursor:
6735 * @window: a #GdkWindow
6738 * Sets the mouse pointer for a #GdkWindow. Use gdk_cursor_new_for_display()
6739 * or gdk_cursor_new_from_pixmap() to create the cursor. To make the cursor
6740 * invisible, use %GDK_BLANK_CURSOR. Passing %NULL for the @cursor argument
6741 * to gdk_window_set_cursor() means that @window will use the cursor of its
6742 * parent window. Most windows should use this default.
6745 gdk_window_set_cursor (GdkWindow *window,
6748 GdkWindowObject *private;
6749 GdkDisplay *display;
6751 g_return_if_fail (GDK_IS_WINDOW (window));
6753 private = (GdkWindowObject *) window;
6754 display = gdk_drawable_get_display (window);
6756 if (private->cursor)
6758 gdk_cursor_unref (private->cursor);
6759 private->cursor = NULL;
6762 if (!GDK_WINDOW_DESTROYED (window))
6765 private->cursor = gdk_cursor_ref (cursor);
6767 if (is_parent_of (window, display->pointer_info.window_under_pointer))
6768 update_cursor (display);
6773 * gdk_window_get_geometry:
6774 * @window: a #GdkWindow
6775 * @x: return location for X coordinate of window (relative to its parent)
6776 * @y: return location for Y coordinate of window (relative to its parent)
6777 * @width: return location for width of window
6778 * @height: return location for height of window
6779 * @depth: return location for bit depth of window
6781 * Any of the return location arguments to this function may be %NULL,
6782 * if you aren't interested in getting the value of that field.
6784 * The X and Y coordinates returned are relative to the parent window
6785 * of @window, which for toplevels usually means relative to the
6786 * window decorations (titlebar, etc.) rather than relative to the
6787 * root window (screen-size background window).
6789 * On the X11 platform, the geometry is obtained from the X server,
6790 * so reflects the latest position of @window; this may be out-of-sync
6791 * with the position of @window delivered in the most-recently-processed
6792 * #GdkEventConfigure. gdk_window_get_position() in contrast gets the
6793 * position from the most recent configure event.
6796 * If @window is not a toplevel, it is <emphasis>much</emphasis> better
6797 * to call gdk_window_get_position() and gdk_drawable_get_size() instead,
6798 * because it avoids the roundtrip to the X server and because
6799 * gdk_drawable_get_size() supports the full 32-bit coordinate space,
6800 * whereas gdk_window_get_geometry() is restricted to the 16-bit
6801 * coordinates of X11.
6805 gdk_window_get_geometry (GdkWindow *window,
6812 GdkWindowObject *private;
6816 GDK_NOTE (MULTIHEAD,
6817 g_message ("gdk_window_get_geometry(): Window needs "
6818 "to be non-NULL to be multi head safe"));
6819 window = gdk_screen_get_root_window ((gdk_screen_get_default ()));
6822 g_return_if_fail (GDK_IS_WINDOW (window));
6824 private = (GdkWindowObject *) window;
6826 if (!GDK_WINDOW_DESTROYED (window))
6828 if (gdk_window_has_impl (private))
6829 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_geometry (window, x, y,
6839 *width = private->width;
6841 *height = private->height;
6843 *depth = private->depth;
6849 * gdk_window_get_origin:
6850 * @window: a #GdkWindow
6851 * @x: return location for X coordinate
6852 * @y: return location for Y coordinate
6854 * Obtains the position of a window in root window coordinates.
6855 * (Compare with gdk_window_get_position() and
6856 * gdk_window_get_geometry() which return the position of a window
6857 * relative to its parent window.)
6859 * Return value: not meaningful, ignore
6862 gdk_window_get_origin (GdkWindow *window,
6866 GdkWindowObject *private;
6868 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
6870 private = (GdkWindowObject *) window;
6872 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_origin (window, x, y);
6875 *x += private->abs_x;
6877 *y += private->abs_y;
6884 * gdk_window_get_deskrelative_origin:
6885 * @window: a toplevel #GdkWindow
6886 * @x: return location for X coordinate
6887 * @y: return location for Y coordinate
6889 * This gets the origin of a #GdkWindow relative to
6890 * an Enlightenment-window-manager desktop. As long as you don't
6891 * assume that the user's desktop/workspace covers the entire
6892 * root window (i.e. you don't assume that the desktop begins
6893 * at root window coordinate 0,0) this function is not necessary.
6894 * It's deprecated for that reason.
6896 * Return value: not meaningful
6899 gdk_window_get_deskrelative_origin (GdkWindow *window,
6903 GdkWindowObject *private;
6904 gboolean return_val = FALSE;
6908 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
6910 private = (GdkWindowObject *) window;
6912 if (!GDK_WINDOW_DESTROYED (window))
6914 return_val = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_deskrelative_origin (window, &tx, &ty);
6917 *x = tx + private->abs_x;
6919 *y = ty + private->abs_y;
6926 * gdk_window_shape_combine_mask:
6927 * @window: a #GdkWindow
6929 * @x: X position of shape mask with respect to @window
6930 * @y: Y position of shape mask with respect to @window
6932 * Applies a shape mask to @window. Pixels in @window corresponding to
6933 * set bits in the @mask will be visible; pixels in @window
6934 * corresponding to unset bits in the @mask will be transparent. This
6935 * gives a non-rectangular window.
6937 * If @mask is %NULL, the shape mask will be unset, and the @x/@y
6938 * parameters are not used.
6940 * On the X11 platform, this uses an X server extension which is
6941 * widely available on most common platforms, but not available on
6942 * very old X servers, and occasionally the implementation will be
6943 * buggy. On servers without the shape extension, this function
6946 * This function works on both toplevel and child windows.
6949 gdk_window_shape_combine_mask (GdkWindow *window,
6954 GdkWindowObject *private;
6957 g_return_if_fail (GDK_IS_WINDOW (window));
6959 private = (GdkWindowObject *) window;
6962 region = _gdk_windowing_get_shape_for_mask (mask);
6966 gdk_window_shape_combine_region (window,
6971 gdk_region_destroy (region);
6975 * gdk_window_shape_combine_region:
6976 * @window: a #GdkWindow
6977 * @shape_region: region of window to be non-transparent
6978 * @offset_x: X position of @shape_region in @window coordinates
6979 * @offset_y: Y position of @shape_region in @window coordinates
6981 * Makes pixels in @window outside @shape_region be transparent,
6982 * so that the window may be nonrectangular. See also
6983 * gdk_window_shape_combine_mask() to use a bitmap as the mask.
6985 * If @shape_region is %NULL, the shape will be unset, so the whole
6986 * window will be opaque again. @offset_x and @offset_y are ignored
6987 * if @shape_region is %NULL.
6989 * On the X11 platform, this uses an X server extension which is
6990 * widely available on most common platforms, but not available on
6991 * very old X servers, and occasionally the implementation will be
6992 * buggy. On servers without the shape extension, this function
6995 * This function works on both toplevel and child windows.
6998 gdk_window_shape_combine_region (GdkWindow *window,
6999 const GdkRegion *shape_region,
7003 GdkWindowObject *private;
7004 GdkRegion *old_region, *new_region, *diff;
7006 g_return_if_fail (GDK_IS_WINDOW (window));
7008 private = (GdkWindowObject *) window;
7010 if (GDK_WINDOW_DESTROYED (window))
7013 private->shaped = (shape_region != NULL);
7016 gdk_region_destroy (private->shape);
7019 if (GDK_WINDOW_IS_MAPPED (window))
7020 old_region = gdk_region_copy (private->clip_region);
7024 private->shape = gdk_region_copy (shape_region);
7025 gdk_region_offset (private->shape, offset_x, offset_y);
7028 private->shape = NULL;
7030 recompute_visible_regions (private, TRUE, FALSE);
7034 new_region = gdk_region_copy (private->clip_region);
7036 /* New area in the window, needs invalidation */
7037 diff = gdk_region_copy (new_region);
7038 gdk_region_subtract (diff, old_region);
7040 gdk_window_invalidate_region (window, diff, TRUE);
7042 gdk_region_destroy (diff);
7044 if (private->parent != NULL &&
7045 GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT)
7047 /* New area in the non-root parent window, needs invalidation */
7048 diff = gdk_region_copy (old_region);
7049 gdk_region_subtract (diff, new_region);
7051 /* Adjust region to parent window coords */
7052 gdk_region_offset (diff, private->x, private->y);
7054 gdk_window_invalidate_region (GDK_WINDOW (private->parent), diff, TRUE);
7056 gdk_region_destroy (diff);
7059 gdk_region_destroy (new_region);
7060 gdk_region_destroy (old_region);
7065 do_child_shapes (GdkWindow *window,
7068 GdkWindowObject *private;
7072 private = (GdkWindowObject *) window;
7076 r.width = private->width;
7077 r.height = private->height;
7079 region = gdk_region_rectangle (&r);
7080 remove_child_area (private, NULL, FALSE, region);
7082 if (merge && private->shape)
7083 gdk_region_subtract (region, private->shape);
7085 gdk_window_shape_combine_region (window, region, 0, 0);
7089 * gdk_window_set_child_shapes:
7090 * @window: a #GdkWindow
7092 * Sets the shape mask of @window to the union of shape masks
7093 * for all children of @window, ignoring the shape mask of @window
7094 * itself. Contrast with gdk_window_merge_child_shapes() which includes
7095 * the shape mask of @window in the masks to be merged.
7098 gdk_window_set_child_shapes (GdkWindow *window)
7100 g_return_if_fail (GDK_IS_WINDOW (window));
7102 do_child_shapes (window, FALSE);
7106 * gdk_window_merge_child_shapes:
7107 * @window: a #GdkWindow
7109 * Merges the shape masks for any child windows into the
7110 * shape mask for @window. i.e. the union of all masks
7111 * for @window and its children will become the new mask
7112 * for @window. See gdk_window_shape_combine_mask().
7114 * This function is distinct from gdk_window_set_child_shapes()
7115 * because it includes @window's shape mask in the set of shapes to
7119 gdk_window_merge_child_shapes (GdkWindow *window)
7121 g_return_if_fail (GDK_IS_WINDOW (window));
7123 do_child_shapes (window, TRUE);
7127 * gdk_window_input_shape_combine_mask:
7128 * @window: a #GdkWindow
7130 * @x: X position of shape mask with respect to @window
7131 * @y: Y position of shape mask with respect to @window
7133 * Like gdk_window_shape_combine_mask(), but the shape applies
7134 * only to event handling. Mouse events which happen while
7135 * the pointer position corresponds to an unset bit in the
7136 * mask will be passed on the window below @window.
7138 * An input shape is typically used with RGBA windows.
7139 * The alpha channel of the window defines which pixels are
7140 * invisible and allows for nicely antialiased borders,
7141 * and the input shape controls where the window is
7144 * On the X11 platform, this requires version 1.1 of the
7147 * On the Win32 platform, this functionality is not present and the
7148 * function does nothing.
7153 gdk_window_input_shape_combine_mask (GdkWindow *window,
7158 GdkWindowObject *private;
7161 g_return_if_fail (GDK_IS_WINDOW (window));
7163 private = (GdkWindowObject *) window;
7166 region = _gdk_windowing_get_shape_for_mask (mask);
7170 gdk_window_input_shape_combine_region (window,
7174 gdk_region_destroy (region);
7178 * gdk_window_input_shape_combine_region:
7179 * @window: a #GdkWindow
7180 * @shape_region: region of window to be non-transparent
7181 * @offset_x: X position of @shape_region in @window coordinates
7182 * @offset_y: Y position of @shape_region in @window coordinates
7184 * Like gdk_window_shape_combine_region(), but the shape applies
7185 * only to event handling. Mouse events which happen while
7186 * the pointer position corresponds to an unset bit in the
7187 * mask will be passed on the window below @window.
7189 * An input shape is typically used with RGBA windows.
7190 * The alpha channel of the window defines which pixels are
7191 * invisible and allows for nicely antialiased borders,
7192 * and the input shape controls where the window is
7195 * On the X11 platform, this requires version 1.1 of the
7198 * On the Win32 platform, this functionality is not present and the
7199 * function does nothing.
7204 gdk_window_input_shape_combine_region (GdkWindow *window,
7205 const GdkRegion *shape_region,
7209 GdkWindowObject *private;
7211 g_return_if_fail (GDK_IS_WINDOW (window));
7213 private = (GdkWindowObject *) window;
7215 if (GDK_WINDOW_DESTROYED (window))
7218 if (private->input_shape)
7219 gdk_region_destroy (private->input_shape);
7223 private->input_shape = gdk_region_copy (shape_region);
7224 gdk_region_offset (private->input_shape, offset_x, offset_y);
7227 private->input_shape = NULL;
7229 if (gdk_window_has_impl (private))
7230 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_shape_combine_region ((GdkWindow *)private, private->input_shape, 0, 0);
7232 /* Pointer may have e.g. moved outside window due to the input mask change */
7233 _gdk_syntesize_crossing_events_for_geometry_change (window);
7237 do_child_input_shapes (GdkWindow *window,
7240 GdkWindowObject *private;
7244 private = (GdkWindowObject *) window;
7248 r.width = private->width;
7249 r.height = private->height;
7251 region = gdk_region_rectangle (&r);
7252 remove_child_area (private, NULL, TRUE, region);
7254 if (merge && private->shape)
7255 gdk_region_subtract (region, private->shape);
7256 if (merge && private->input_shape)
7257 gdk_region_subtract (region, private->input_shape);
7259 gdk_window_input_shape_combine_region (window, region, 0, 0);
7264 * gdk_window_set_child_input_shapes:
7265 * @window: a #GdkWindow
7267 * Sets the input shape mask of @window to the union of input shape masks
7268 * for all children of @window, ignoring the input shape mask of @window
7269 * itself. Contrast with gdk_window_merge_child_input_shapes() which includes
7270 * the input shape mask of @window in the masks to be merged.
7275 gdk_window_set_child_input_shapes (GdkWindow *window)
7277 g_return_if_fail (GDK_IS_WINDOW (window));
7279 do_child_input_shapes (window, FALSE);
7283 * gdk_window_merge_child_input_shapes:
7284 * @window: a #GdkWindow
7286 * Merges the input shape masks for any child windows into the
7287 * input shape mask for @window. i.e. the union of all input masks
7288 * for @window and its children will become the new input mask
7289 * for @window. See gdk_window_input_shape_combine_mask().
7291 * This function is distinct from gdk_window_set_child_input_shapes()
7292 * because it includes @window's input shape mask in the set of
7293 * shapes to be merged.
7298 gdk_window_merge_child_input_shapes (GdkWindow *window)
7300 g_return_if_fail (GDK_IS_WINDOW (window));
7302 do_child_input_shapes (window, TRUE);
7307 * gdk_window_set_static_gravities:
7308 * @window: a #GdkWindow
7309 * @use_static: %TRUE to turn on static gravity
7311 * Set the bit gravity of the given window to static, and flag it so
7312 * all children get static subwindow gravity. This is used if you are
7313 * implementing scary features that involve deep knowledge of the
7314 * windowing system. Don't worry about it unless you have to.
7316 * Return value: %TRUE if the server supports static gravity
7319 gdk_window_set_static_gravities (GdkWindow *window,
7320 gboolean use_static)
7322 GdkWindowObject *private;
7324 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
7326 private = (GdkWindowObject *) window;
7328 if (gdk_window_has_impl (private))
7329 return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_static_gravities (window, use_static);
7335 * gdk_window_set_composited:
7336 * @window: a #GdkWindow
7337 * @composited: %TRUE to set the window as composited
7339 * Sets a #GdkWindow as composited, or unsets it. Composited
7340 * windows do not automatically have their contents drawn to
7341 * the screen. Drawing is redirected to an offscreen buffer
7342 * and an expose event is emitted on the parent of the composited
7343 * window. It is the responsibility of the parent's expose handler
7344 * to manually merge the off-screen content onto the screen in
7345 * whatever way it sees fit. See <xref linkend="composited-window-example"/>
7348 * It only makes sense for child windows to be composited; see
7349 * gdk_window_set_opacity() if you need translucent toplevel
7352 * An additional effect of this call is that the area of this
7353 * window is no longer clipped from regions marked for
7354 * invalidation on its parent. Draws done on the parent
7355 * window are also no longer clipped by the child.
7357 * This call is only supported on some systems (currently,
7358 * only X11 with new enough Xcomposite and Xdamage extensions).
7359 * You must call gdk_display_supports_composite() to check if
7360 * setting a window as composited is supported before
7361 * attempting to do so.
7366 gdk_window_set_composited (GdkWindow *window,
7367 gboolean composited)
7369 GdkWindowObject *private = (GdkWindowObject *)window;
7370 GdkDisplay *display;
7372 g_return_if_fail (GDK_IS_WINDOW (window));
7374 composited = composited != FALSE;
7376 if (private->composited == composited)
7380 gdk_window_set_has_native (window, TRUE);
7382 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
7384 if (!gdk_display_supports_composite (display) && composited)
7386 g_warning ("gdk_window_set_composited called but "
7387 "compositing is not supported");
7391 _gdk_windowing_window_set_composited (window, composited);
7393 recompute_visible_regions (private, TRUE, FALSE);
7395 if (GDK_WINDOW_IS_MAPPED (window))
7396 gdk_window_invalidate_in_parent (private);
7398 private->composited = composited;
7403 remove_redirect_from_children (GdkWindowObject *private,
7404 GdkWindowRedirect *redirect)
7407 GdkWindowObject *child;
7409 for (l = private->children; l != NULL; l = l->next)
7413 /* Don't redirect this child if it already has another redirect */
7414 if (child->redirect == redirect)
7416 child->redirect = NULL;
7417 remove_redirect_from_children (child, redirect);
7423 * gdk_window_remove_redirection:
7424 * @window: a #GdkWindow
7426 * Removes any active redirection started by
7427 * gdk_window_redirect_to_drawable().
7432 gdk_window_remove_redirection (GdkWindow *window)
7434 GdkWindowObject *private;
7436 g_return_if_fail (GDK_IS_WINDOW (window));
7438 private = (GdkWindowObject *) window;
7440 if (private->redirect &&
7441 private->redirect->redirected == private)
7443 remove_redirect_from_children (private, private->redirect);
7444 gdk_window_redirect_free (private->redirect);
7445 private->redirect = NULL;
7450 apply_redirect_to_children (GdkWindowObject *private,
7451 GdkWindowRedirect *redirect)
7454 GdkWindowObject *child;
7456 for (l = private->children; l != NULL; l = l->next)
7460 /* Don't redirect this child if it already has another redirect */
7461 if (!child->redirect)
7463 child->redirect = redirect;
7464 apply_redirect_to_children (child, redirect);
7470 * gdk_window_redirect_to_drawable:
7471 * @window: a #GdkWindow
7472 * @drawable: a #GdkDrawable
7473 * @src_x: x position in @window
7474 * @src_y: y position in @window
7475 * @dest_x: x position in @drawable
7476 * @dest_y: y position in @drawable
7477 * @width: width of redirection
7478 * @height: height of redirection
7480 * Redirects drawing into @window so that drawing to the
7481 * window in the rectangle specified by @src_x, @src_y,
7482 * @width and @height is also drawn into @drawable at
7485 * Only drawing between gdk_window_begin_paint_region() or
7486 * gdk_window_begin_paint_rect() and gdk_window_end_paint() is
7489 * Redirection is active until gdk_window_remove_redirection()
7495 gdk_window_redirect_to_drawable (GdkWindow *window,
7496 GdkDrawable *drawable,
7504 GdkWindowObject *private;
7506 g_return_if_fail (GDK_IS_WINDOW (window));
7507 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
7508 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
7510 private = (GdkWindowObject *) window;
7512 if (private->redirect)
7513 gdk_window_remove_redirection (window);
7515 if (width == -1 || height == -1)
7518 gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
7525 private->redirect = g_new0 (GdkWindowRedirect, 1);
7526 private->redirect->redirected = private;
7527 private->redirect->pixmap = g_object_ref (drawable);
7528 private->redirect->src_x = src_x;
7529 private->redirect->src_y = src_y;
7530 private->redirect->dest_x = dest_x;
7531 private->redirect->dest_y = dest_y;
7532 private->redirect->width = width;
7533 private->redirect->height = height;
7535 apply_redirect_to_children (private, private->redirect);
7539 window_get_size_rectangle (GdkWindow *window,
7542 GdkWindowObject *private = (GdkWindowObject *) window;
7544 rect->x = rect->y = 0;
7545 rect->width = private->width;
7546 rect->height = private->height;
7549 /* Calculates the real clipping region for a window, in window coordinates,
7550 * taking into account other windows, gc clip region and gc clip mask.
7553 _gdk_window_calculate_full_clip_region (GdkWindow *window,
7554 GdkWindow *base_window,
7555 gboolean do_children,
7556 gint *base_x_offset,
7557 gint *base_y_offset)
7559 GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
7560 GdkRectangle visible_rect;
7561 GdkRegion *real_clip_region, *tmpreg;
7562 gint x_offset, y_offset;
7563 GdkWindowObject *parentwin, *lastwin;
7570 if (!GDK_WINDOW_IS_MAPPED (window) || private->input_only)
7571 return gdk_region_new ();
7573 window_get_size_rectangle (window, &visible_rect);
7575 /* real_clip_region is in window coordinates */
7576 real_clip_region = gdk_region_rectangle (&visible_rect);
7578 x_offset = y_offset = 0;
7582 parentwin = lastwin;
7584 parentwin = lastwin->parent;
7586 /* Remove the areas of all overlapping windows above parentwin in the hiearachy */
7587 for (; parentwin != NULL &&
7588 (parentwin == private || lastwin != (GdkWindowObject*) base_window);
7589 lastwin = parentwin, parentwin = lastwin->parent)
7592 GdkRectangle real_clip_rect;
7593 gboolean is_offscreen;
7595 if (parentwin != private)
7597 x_offset += GDK_WINDOW_OBJECT (lastwin)->x;
7598 y_offset += GDK_WINDOW_OBJECT (lastwin)->y;
7601 is_offscreen = gdk_window_is_offscreen (parentwin);
7603 /* children is ordered in reverse stack order */
7604 for (cur = parentwin->children;
7605 cur && cur->data != lastwin;
7608 GdkWindow *child = cur->data;
7609 GdkWindowObject *child_private = (GdkWindowObject *)child;
7611 if (!GDK_WINDOW_IS_MAPPED (child) || child_private->input_only)
7614 /* Ignore offscreen children, as they don't draw in their parent and
7615 * don't take part in the clipping */
7616 if (gdk_window_is_offscreen (child_private))
7619 window_get_size_rectangle (child, &visible_rect);
7621 /* Convert rect to "window" coords */
7622 visible_rect.x += child_private->x - x_offset;
7623 visible_rect.y += child_private->y - y_offset;
7625 /* This shortcut is really necessary for performance when there are a lot of windows */
7626 gdk_region_get_clipbox (real_clip_region, &real_clip_rect);
7627 if (visible_rect.x >= real_clip_rect.x + real_clip_rect.width ||
7628 visible_rect.x + visible_rect.width <= real_clip_rect.x ||
7629 visible_rect.y >= real_clip_rect.y + real_clip_rect.height ||
7630 visible_rect.y + visible_rect.height <= real_clip_rect.y)
7633 tmpreg = gdk_region_rectangle (&visible_rect);
7634 gdk_region_subtract (real_clip_region, tmpreg);
7635 gdk_region_destroy (tmpreg);
7638 /* Clip to the parent */
7639 window_get_size_rectangle ((GdkWindow *)parentwin, &visible_rect);
7640 /* Convert rect to "window" coords */
7641 visible_rect.x += - x_offset;
7642 visible_rect.y += - y_offset;
7644 tmpreg = gdk_region_rectangle (&visible_rect);
7645 gdk_region_intersect (real_clip_region, tmpreg);
7646 gdk_region_destroy (tmpreg);
7650 *base_x_offset = x_offset;
7652 *base_y_offset = y_offset;
7654 return real_clip_region;
7658 _gdk_window_add_damage (GdkWindow *toplevel,
7659 GdkRegion *damaged_region)
7661 GdkDisplay *display;
7662 GdkEvent event = { 0, };
7663 event.expose.type = GDK_DAMAGE;
7664 event.expose.window = toplevel;
7665 event.expose.send_event = FALSE;
7666 event.expose.region = damaged_region;
7667 gdk_region_get_clipbox (event.expose.region, &event.expose.area);
7668 display = gdk_drawable_get_display (event.expose.window);
7669 _gdk_event_queue_append (display, gdk_event_copy (&event));
7673 gdk_window_redirect_free (GdkWindowRedirect *redirect)
7675 g_object_unref (redirect->pixmap);
7680 convert_coords_to_child (GdkWindowObject *child,
7682 double *child_x, double *child_y)
7684 *child_x = x - child->x;
7685 *child_y = y - child->y;
7689 point_in_window (GdkWindowObject *window,
7693 x >= 0 && x < window->width &&
7694 y >= 0 && y < window->height &&
7695 (window->shape == NULL ||
7696 gdk_region_point_in (window->shape,
7698 (window->input_shape == NULL ||
7699 gdk_region_point_in (window->input_shape,
7704 convert_coords_to_toplevel (GdkWindow *window,
7705 double child_x, double child_y,
7706 double *toplevel_x, double *toplevel_y)
7708 GdkWindowObject *private = (GdkWindowObject *)window;
7714 while (private->parent != NULL &&
7715 (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT))
7719 private = private->parent;
7725 return (GdkWindow *)private;
7730 convert_toplevel_coords_to_window (GdkWindow *window,
7736 GdkWindowObject *private;
7738 GList *children, *l;
7740 private = GDK_WINDOW_OBJECT (window);
7746 while (private->parent != NULL &&
7747 (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT))
7749 children = g_list_prepend (children, private);
7750 private = private->parent;
7753 for (l = children; l != NULL; l = l->next)
7754 convert_coords_to_child (l->data, x, y, &x, &y);
7756 g_list_free (children);
7763 _gdk_window_find_descendant_at (GdkWindow *toplevel,
7768 GdkWindowObject *private, *sub;
7769 double child_x, child_y;
7772 private = (GdkWindowObject *)toplevel;
7774 if (point_in_window (private, x, y))
7778 /* Children is ordered in reverse stack order, i.e. first is topmost */
7779 for (l = private->children; l != NULL; l = l->next)
7783 if (!GDK_WINDOW_IS_MAPPED (sub))
7786 convert_coords_to_child (sub,
7788 &child_x, &child_y);
7789 if (point_in_window (sub, child_x, child_y))
7802 /* Not in window at all */
7811 return (GdkWindow *)private;
7814 static const guint type_masks[] = {
7815 GDK_SUBSTRUCTURE_MASK, /* GDK_DELETE = 0 */
7816 GDK_STRUCTURE_MASK, /* GDK_DESTROY = 1 */
7817 GDK_EXPOSURE_MASK, /* GDK_EXPOSE = 2 */
7818 GDK_POINTER_MOTION_MASK, /* GDK_MOTION_NOTIFY = 3 */
7819 GDK_BUTTON_PRESS_MASK, /* GDK_BUTTON_PRESS = 4 */
7820 GDK_BUTTON_PRESS_MASK, /* GDK_2BUTTON_PRESS = 5 */
7821 GDK_BUTTON_PRESS_MASK, /* GDK_3BUTTON_PRESS = 6 */
7822 GDK_BUTTON_RELEASE_MASK, /* GDK_BUTTON_RELEASE = 7 */
7823 GDK_KEY_PRESS_MASK, /* GDK_KEY_PRESS = 8 */
7824 GDK_KEY_RELEASE_MASK, /* GDK_KEY_RELEASE = 9 */
7825 GDK_ENTER_NOTIFY_MASK, /* GDK_ENTER_NOTIFY = 10 */
7826 GDK_LEAVE_NOTIFY_MASK, /* GDK_LEAVE_NOTIFY = 11 */
7827 GDK_FOCUS_CHANGE_MASK, /* GDK_FOCUS_CHANGE = 12 */
7828 GDK_STRUCTURE_MASK, /* GDK_CONFIGURE = 13 */
7829 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_MAP = 14 */
7830 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_UNMAP = 15 */
7831 GDK_PROPERTY_CHANGE_MASK, /* GDK_PROPERTY_NOTIFY = 16 */
7832 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_CLEAR = 17 */
7833 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_REQUEST = 18 */
7834 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_NOTIFY = 19 */
7835 GDK_PROXIMITY_IN_MASK, /* GDK_PROXIMITY_IN = 20 */
7836 GDK_PROXIMITY_OUT_MASK, /* GDK_PROXIMITY_OUT = 21 */
7837 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_ENTER = 22 */
7838 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_LEAVE = 23 */
7839 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_MOTION = 24 */
7840 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_STATUS = 25 */
7841 GDK_ALL_EVENTS_MASK, /* GDK_DROP_START = 26 */
7842 GDK_ALL_EVENTS_MASK, /* GDK_DROP_FINISHED = 27 */
7843 GDK_ALL_EVENTS_MASK, /* GDK_CLIENT_EVENT = 28 */
7844 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_VISIBILITY_NOTIFY = 29 */
7845 GDK_EXPOSURE_MASK, /* GDK_NO_EXPOSE = 30 */
7846 GDK_SCROLL_MASK | GDK_BUTTON_PRESS_MASK,/* GDK_SCROLL= 31 */
7847 0, /* GDK_WINDOW_STATE = 32 */
7848 0, /* GDK_SETTING = 33 */
7849 0, /* GDK_OWNER_CHANGE = 34 */
7850 0, /* GDK_GRAB_BROKEN = 35 */
7851 0, /* GDK_DAMAGE = 36 */
7853 G_STATIC_ASSERT (G_N_ELEMENTS (type_masks) == GDK_EVENT_LAST);
7855 /* send motion events if the right buttons are down */
7857 update_evmask_for_button_motion (guint evmask,
7858 GdkModifierType mask)
7860 if (evmask & GDK_BUTTON_MOTION_MASK &&
7861 mask & (GDK_BUTTON1_MASK |
7866 evmask |= GDK_POINTER_MOTION_MASK;
7868 if ((evmask & GDK_BUTTON1_MOTION_MASK && mask & GDK_BUTTON1_MASK) ||
7869 (evmask & GDK_BUTTON2_MOTION_MASK && mask & GDK_BUTTON2_MASK) ||
7870 (evmask & GDK_BUTTON3_MOTION_MASK && mask & GDK_BUTTON3_MASK))
7871 evmask |= GDK_POINTER_MOTION_MASK;
7877 is_button_type (GdkEventType type)
7879 return type == GDK_BUTTON_PRESS ||
7880 type == GDK_2BUTTON_PRESS ||
7881 type == GDK_3BUTTON_PRESS ||
7882 type == GDK_BUTTON_RELEASE ||
7887 is_motion_type (GdkEventType type)
7889 return type == GDK_MOTION_NOTIFY ||
7890 type == GDK_ENTER_NOTIFY ||
7891 type == GDK_LEAVE_NOTIFY;
7894 static GdkWindowObject *
7895 find_common_ancestor (GdkWindowObject *win1,
7896 GdkWindowObject *win2)
7898 GdkWindowObject *tmp;
7899 GList *path1 = NULL, *path2 = NULL;
7900 GList *list1, *list2;
7903 while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
7905 path1 = g_list_prepend (path1, tmp);
7910 while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
7912 path2 = g_list_prepend (path2, tmp);
7919 while (list1 && list2 && (list1->data == list2->data))
7921 tmp = (GdkWindowObject *)list1->data;
7922 list1 = g_list_next (list1);
7923 list2 = g_list_next (list2);
7925 g_list_free (path1);
7926 g_list_free (path2);
7932 _gdk_make_event (GdkWindow *window,
7934 GdkEvent *event_in_queue,
7935 gboolean before_event)
7937 GdkEvent *event = gdk_event_new (type);
7939 GdkModifierType the_state;
7941 the_time = gdk_event_get_time (event_in_queue);
7942 gdk_event_get_state (event_in_queue, &the_state);
7944 event->any.window = g_object_ref (window);
7945 event->any.send_event = FALSE;
7949 case GDK_MOTION_NOTIFY:
7950 event->motion.time = the_time;
7951 event->motion.axes = NULL;
7952 event->motion.state = the_state;
7955 case GDK_BUTTON_PRESS:
7956 case GDK_2BUTTON_PRESS:
7957 case GDK_3BUTTON_PRESS:
7958 case GDK_BUTTON_RELEASE:
7959 event->button.time = the_time;
7960 event->button.axes = NULL;
7961 event->button.state = the_state;
7965 event->scroll.time = the_time;
7966 event->scroll.state = the_state;
7970 case GDK_KEY_RELEASE:
7971 event->key.time = the_time;
7972 event->key.state = the_state;
7975 case GDK_ENTER_NOTIFY:
7976 case GDK_LEAVE_NOTIFY:
7977 event->crossing.time = the_time;
7978 event->crossing.state = the_state;
7981 case GDK_PROPERTY_NOTIFY:
7982 event->property.time = the_time;
7983 event->property.state = the_state;
7986 case GDK_SELECTION_CLEAR:
7987 case GDK_SELECTION_REQUEST:
7988 case GDK_SELECTION_NOTIFY:
7989 event->selection.time = the_time;
7992 case GDK_PROXIMITY_IN:
7993 case GDK_PROXIMITY_OUT:
7994 event->proximity.time = the_time;
7997 case GDK_DRAG_ENTER:
7998 case GDK_DRAG_LEAVE:
7999 case GDK_DRAG_MOTION:
8000 case GDK_DRAG_STATUS:
8001 case GDK_DROP_START:
8002 case GDK_DROP_FINISHED:
8003 event->dnd.time = the_time;
8006 case GDK_FOCUS_CHANGE:
8010 case GDK_CLIENT_EVENT:
8011 case GDK_VISIBILITY_NOTIFY:
8023 _gdk_event_queue_insert_before (gdk_drawable_get_display (window), event_in_queue, event);
8025 _gdk_event_queue_insert_after (gdk_drawable_get_display (window), event_in_queue, event);
8028 _gdk_event_queue_append (gdk_drawable_get_display (window), event);
8034 send_crossing_event (GdkDisplay *display,
8035 GdkWindowObject *toplevel,
8036 GdkWindowObject *window,
8038 GdkCrossingMode mode,
8039 GdkNotifyType notify_type,
8040 GdkWindow *subwindow,
8043 GdkModifierType mask,
8045 GdkEvent *event_in_queue,
8050 GdkPointerGrabInfo *grab;
8052 grab = _gdk_display_has_pointer_grab (display, serial);
8055 !grab->owner_events &&
8056 (GdkWindow *)window != grab->window)
8059 if (type == GDK_LEAVE_NOTIFY)
8060 event_mask = GDK_LEAVE_NOTIFY_MASK;
8062 event_mask = GDK_ENTER_NOTIFY_MASK;
8064 if (window->event_mask & event_mask)
8066 event = _gdk_make_event ((GdkWindow *)window, type, event_in_queue, TRUE);
8067 event->crossing.time = time_;
8068 event->crossing.subwindow = subwindow;
8070 g_object_ref (subwindow);
8071 convert_toplevel_coords_to_window ((GdkWindow *)window,
8072 toplevel_x, toplevel_y,
8073 &event->crossing.x, &event->crossing.y);
8074 event->crossing.x_root = toplevel_x + toplevel->x;
8075 event->crossing.y_root = toplevel_y + toplevel->y;
8076 event->crossing.mode = mode;
8077 event->crossing.detail = notify_type;
8078 event->crossing.focus = FALSE;
8079 event->crossing.state = mask;
8084 /* The coordinates are in the toplevel window that src/dest are in.
8085 * src and dest are always (if != NULL) in the same toplevel, as
8086 * we get a leave-notify and set the window_under_pointer to null
8087 * before crossing to another toplevel.
8090 _gdk_syntesize_crossing_events (GdkDisplay *display,
8093 GdkCrossingMode mode,
8096 GdkModifierType mask,
8098 GdkEvent *event_in_queue,
8102 GdkWindowObject *win, *last, *next;
8104 gboolean non_linear;
8107 GdkWindowObject *toplevel;
8108 GdkNotifyType notify_type;
8110 /* TODO: Don't send events to toplevel, as we get those from the windowing system */
8112 a = (GdkWindowObject *)src;
8113 b = (GdkWindowObject *)dest;
8115 return; /* No crossings generated between src and dest */
8117 c = find_common_ancestor (a, b);
8119 non_linear = (c != a) && (c != b);
8121 if (a) /* There might not be a source (i.e. if no previous pointer_in_window) */
8123 toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)a);
8125 /* Traverse up from a to (excluding) c sending leave events */
8127 notify_type = GDK_NOTIFY_NONLINEAR;
8129 notify_type = GDK_NOTIFY_INFERIOR;
8131 notify_type = GDK_NOTIFY_ANCESTOR;
8132 send_crossing_event (display, toplevel,
8133 a, GDK_LEAVE_NOTIFY,
8137 toplevel_x, toplevel_y,
8145 notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
8147 notify_type = GDK_NOTIFY_VIRTUAL;
8151 while (win != c && GDK_WINDOW_TYPE (win) != GDK_WINDOW_ROOT)
8153 send_crossing_event (display, toplevel,
8154 win, GDK_LEAVE_NOTIFY,
8158 toplevel_x, toplevel_y,
8169 if (b) /* Might not be a dest, e.g. if we're moving out of the window */
8171 toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)b);
8173 /* Traverse down from c to b */
8178 while (win != c && GDK_WINDOW_TYPE (win) != GDK_WINDOW_ROOT)
8180 path = g_list_prepend (path, win);
8185 notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
8187 notify_type = GDK_NOTIFY_VIRTUAL;
8192 win = (GdkWindowObject *)list->data;
8193 list = g_list_next (list);
8195 next = (GdkWindowObject *)list->data;
8199 send_crossing_event (display, toplevel,
8200 win, GDK_ENTER_NOTIFY,
8204 toplevel_x, toplevel_y,
8214 notify_type = GDK_NOTIFY_NONLINEAR;
8216 notify_type = GDK_NOTIFY_ANCESTOR;
8218 notify_type = GDK_NOTIFY_INFERIOR;
8220 send_crossing_event (display, toplevel,
8221 b, GDK_ENTER_NOTIFY,
8225 toplevel_x, toplevel_y,
8233 get_toplevel (GdkWindow *w)
8235 GdkWindowObject *private = GDK_WINDOW_OBJECT (w);
8237 while (private->parent != NULL &&
8238 (GDK_WINDOW_TYPE (private->parent) != GDK_WINDOW_ROOT))
8239 private = private->parent;
8241 return GDK_WINDOW (private);
8244 /* Returns the window inside the event window with the pointer in it
8245 * at the specified coordinates, or NULL if its not in any child of
8246 * the toplevel. It also takes into account !owner_events grabs.
8249 get_pointer_window (GdkDisplay *display,
8250 GdkWindow *event_window,
8255 GdkWindow *pointer_window;
8256 GdkPointerGrabInfo *grab;
8258 if (event_window == display->pointer_info.toplevel_under_pointer)
8260 _gdk_window_find_descendant_at (event_window,
8261 toplevel_x, toplevel_y,
8264 pointer_window = NULL;
8266 grab = _gdk_display_has_pointer_grab (display, serial);
8268 !grab->owner_events &&
8269 pointer_window != grab->window)
8270 pointer_window = NULL;
8272 return pointer_window;
8276 _gdk_display_set_window_under_pointer (GdkDisplay *display,
8279 GdkWindowObject *private;
8281 private = (GdkWindowObject *)window;
8283 if (display->pointer_info.window_under_pointer)
8284 g_object_unref (display->pointer_info.window_under_pointer);
8285 display->pointer_info.window_under_pointer = window;
8287 g_object_ref (window);
8290 update_cursor (display);
8292 _gdk_display_enable_motion_hints (display);
8296 _gdk_syntesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
8298 GdkDisplay *display;
8299 GdkWindow *changed_toplevel;
8300 GdkWindow *new_window_under_pointer;
8303 display = gdk_drawable_get_display (changed_window);
8305 serial = _gdk_windowing_window_get_next_serial (display);
8306 changed_toplevel = get_toplevel (changed_window);
8308 if (changed_toplevel == display->pointer_info.toplevel_under_pointer)
8310 new_window_under_pointer =
8311 get_pointer_window (display, changed_toplevel,
8312 display->pointer_info.toplevel_x,
8313 display->pointer_info.toplevel_y,
8315 if (new_window_under_pointer !=
8316 display->pointer_info.window_under_pointer)
8318 _gdk_syntesize_crossing_events (display,
8319 display->pointer_info.window_under_pointer,
8320 new_window_under_pointer,
8321 GDK_CROSSING_NORMAL,
8322 display->pointer_info.toplevel_x,
8323 display->pointer_info.toplevel_y,
8324 display->pointer_info.state,
8328 _gdk_display_set_window_under_pointer (display, new_window_under_pointer);
8333 /* Don't use for crossing events */
8335 get_event_window (GdkDisplay *display,
8336 GdkWindow *pointer_window,
8338 GdkModifierType mask,
8343 GdkWindow *grab_window;
8345 GdkPointerGrabInfo *grab;
8347 grab = _gdk_display_has_pointer_grab (display, serial);
8349 if (grab != NULL && !grab->owner_events)
8351 evmask = grab->event_mask;
8352 evmask = update_evmask_for_button_motion (evmask, mask);
8354 grab_window = grab->window;
8356 if (evmask & type_masks[type])
8359 *evmask_out = evmask;
8366 w = (GdkWindowObject *)pointer_window;
8369 evmask = w->event_mask;
8370 evmask = update_evmask_for_button_motion (evmask, mask);
8372 if (evmask & type_masks[type])
8375 *evmask_out = evmask;
8376 return (GdkWindow *)w;
8385 evmask = grab->event_mask;
8386 evmask = update_evmask_for_button_motion (evmask, mask);
8388 if (evmask & type_masks[type])
8391 *evmask_out = evmask;
8392 return grab->window;
8402 proxy_pointer_event (GdkDisplay *display,
8403 GdkEvent *source_event,
8406 GdkWindow *toplevel_window, *event_window;
8407 GdkWindow *pointer_window;
8410 gdouble toplevel_x, toplevel_y;
8413 event_window = source_event->any.window;
8414 gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
8415 gdk_event_get_state (source_event, &state);
8416 time_ = gdk_event_get_time (source_event);
8417 toplevel_window = convert_coords_to_toplevel (event_window,
8418 toplevel_x, toplevel_y,
8419 &toplevel_x, &toplevel_y);
8422 /* If we get crossing events with subwindow unexpectedly being NULL
8423 that means there is a native subwindow that gdk doesn't know about.
8424 We track these and forward them, with the correct virtual window
8426 This is important to get right, as metacity uses gdk for the frame
8427 windows, but gdk doesn't know about the client windows reparented
8429 if (((source_event->type == GDK_LEAVE_NOTIFY &&
8430 source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
8431 (source_event->type == GDK_ENTER_NOTIFY &&
8432 (source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
8433 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
8434 source_event->crossing.subwindow == NULL)
8436 /* Left for an unknown (to gdk) subwindow */
8438 /* Send leave events from window under pointer to event window
8439 that will get the subwindow == NULL window */
8440 _gdk_syntesize_crossing_events (display,
8441 display->pointer_info.window_under_pointer,
8443 source_event->crossing.mode,
8444 toplevel_x, toplevel_y,
8449 /* Send subwindow == NULL event */
8450 send_crossing_event (display,
8451 (GdkWindowObject *)toplevel_window,
8452 (GdkWindowObject *)event_window,
8454 source_event->crossing.mode,
8455 source_event->crossing.detail,
8457 toplevel_x, toplevel_y,
8462 _gdk_display_set_window_under_pointer (display, NULL);
8466 pointer_window = get_pointer_window (display, toplevel_window,
8467 toplevel_x, toplevel_y, serial);
8469 if (((source_event->type == GDK_ENTER_NOTIFY &&
8470 source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
8471 (source_event->type == GDK_LEAVE_NOTIFY &&
8472 (source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
8473 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
8474 source_event->crossing.subwindow == NULL)
8476 /* Entered from an unknown (to gdk) subwindow */
8478 /* Send subwindow == NULL event */
8479 send_crossing_event (display,
8480 (GdkWindowObject *)toplevel_window,
8481 (GdkWindowObject *)event_window,
8483 source_event->crossing.mode,
8484 source_event->crossing.detail,
8486 toplevel_x, toplevel_y,
8491 /* Send enter events from event window to pointer_window */
8492 _gdk_syntesize_crossing_events (display,
8495 source_event->crossing.mode,
8496 toplevel_x, toplevel_y,
8500 _gdk_display_set_window_under_pointer (display, pointer_window);
8504 if (display->pointer_info.window_under_pointer != pointer_window)
8506 /* Either a toplevel crossing notify that ended up inside a child window,
8507 or a motion notify that got into another child window */
8509 /* Different than last time, send crossing events */
8510 _gdk_syntesize_crossing_events (display,
8511 display->pointer_info.window_under_pointer,
8513 GDK_CROSSING_NORMAL,
8514 toplevel_x, toplevel_y,
8518 _gdk_display_set_window_under_pointer (display, pointer_window);
8520 else if (source_event->type == GDK_MOTION_NOTIFY)
8522 GdkWindow *event_win;
8526 event_win = get_event_window (display,
8536 (evmask & GDK_POINTER_MOTION_HINT_MASK))
8538 if (display->pointer_info.motion_hint_serial != 0 &&
8539 serial < display->pointer_info.motion_hint_serial)
8540 event_win = NULL; /* Ignore event */
8544 display->pointer_info.motion_hint_serial = G_MAXULONG;
8550 event = _gdk_make_event (event_win, GDK_MOTION_NOTIFY, source_event, FALSE);
8551 event->motion.time = time_;
8552 convert_toplevel_coords_to_window (event_win,
8553 toplevel_x, toplevel_y,
8554 &event->motion.x, &event->motion.y);
8555 event->motion.x_root = source_event->motion.x_root;
8556 event->motion.y_root = source_event->motion.y_root;;
8557 event->motion.state = state;
8558 event->motion.is_hint = is_hint;
8559 event->motion.device = NULL;
8560 event->motion.device = source_event->motion.device;
8564 /* unlink all move events from queue.
8565 We handle our own, including our emulated masks. */
8569 #define GDK_ANY_BUTTON_MASK (GDK_BUTTON1_MASK | \
8570 GDK_BUTTON2_MASK | \
8571 GDK_BUTTON3_MASK | \
8572 GDK_BUTTON4_MASK | \
8576 proxy_button_event (GdkEvent *source_event,
8579 GdkWindow *toplevel_window, *event_window;
8580 GdkWindow *event_win;
8581 GdkWindow *pointer_window;
8586 gdouble toplevel_x, toplevel_y;
8587 GdkDisplay *display;
8590 type = source_event->any.type;
8591 event_window = source_event->any.window;
8592 gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
8593 gdk_event_get_state (source_event, &state);
8594 time_ = gdk_event_get_time (source_event);
8595 display = gdk_drawable_get_display (source_event->any.window);
8596 toplevel_window = convert_coords_to_toplevel (event_window,
8597 toplevel_x, toplevel_y,
8598 &toplevel_x, &toplevel_y);
8600 if (type == GDK_BUTTON_PRESS &&
8601 _gdk_display_has_pointer_grab (display, serial) == NULL)
8604 _gdk_window_find_descendant_at (toplevel_window,
8605 toplevel_x, toplevel_y,
8608 /* Find the event window, that gets the grab */
8609 w = (GdkWindowObject *)pointer_window;
8610 while (w != NULL && w->parent->window_type != GDK_WINDOW_ROOT)
8612 if (w->event_mask & GDK_BUTTON_PRESS_MASK)
8616 pointer_window = (GdkWindow *)w;
8618 _gdk_display_add_pointer_grab (display,
8622 gdk_window_get_events (pointer_window),
8626 _gdk_display_pointer_grab_update (display, serial);
8629 pointer_window = get_pointer_window (display, toplevel_window,
8630 toplevel_x, toplevel_y,
8633 event_win = get_event_window (display,
8638 if (event_win == NULL)
8641 event = _gdk_make_event (event_win, type, source_event, FALSE);
8645 case GDK_BUTTON_PRESS:
8646 case GDK_BUTTON_RELEASE:
8647 event->button.button = source_event->button.button;
8648 convert_toplevel_coords_to_window (event_win,
8649 toplevel_x, toplevel_y,
8650 &event->button.x, &event->button.y);
8651 event->button.x_root = source_event->button.x_root;
8652 event->button.y_root = source_event->button.y_root;
8653 event->button.state = state;
8654 event->button.device = source_event->button.device;
8656 if (type == GDK_BUTTON_PRESS)
8657 _gdk_event_button_generate (display, event);
8661 event->scroll.direction = source_event->scroll.direction;
8662 convert_toplevel_coords_to_window (event_win,
8663 toplevel_x, toplevel_y,
8664 &event->scroll.x, &event->scroll.y);
8665 event->scroll.x_root = source_event->scroll.x_root;
8666 event->scroll.y_root = source_event->scroll.y_root;
8667 event->scroll.state = state;
8668 event->scroll.device = source_event->scroll.device;
8675 return TRUE; /* Always unlink original, we want to obey the emulated event mask */
8678 #ifdef DEBUG_WINDOW_PRINTING
8680 gdk_window_print (GdkWindowObject *window,
8685 g_print ("%*s%p: [%s] %d,%d %dx%d", indent, "", window,
8686 window->user_data ? g_type_name_from_instance (window->user_data) : "no widget",
8687 window->x, window->y,
8688 window->width, window->height
8691 if (gdk_window_has_impl (window))
8693 #ifdef GDK_WINDOWING_X11
8694 g_print (" impl(0x%lx)", gdk_x11_drawable_get_xid (GDK_DRAWABLE (window)));
8698 if (window->input_only)
8699 g_print (" input-only");
8701 if (!gdk_window_is_visible ((GdkWindow *)window))
8702 g_print (" hidden");
8704 g_print (" abs[%d,%d]",
8705 window->abs_x, window->abs_y);
8707 gdk_region_get_clipbox (window->clip_region, &r);
8708 if (gdk_region_empty (window->clip_region))
8709 g_print (" clipbox[empty]");
8711 g_print (" clipbox[%d,%d %dx%d]", r.x, r.y, r.width, r.height);
8718 gdk_window_print_tree (GdkWindow *window,
8720 gboolean include_input_only)
8722 GdkWindowObject *private;
8725 private = (GdkWindowObject *)window;
8727 if (private->input_only && !include_input_only)
8730 gdk_window_print (private, indent);
8732 for (l = private->children; l != NULL; l = l->next)
8733 gdk_window_print_tree (l->data, indent + 4, include_input_only);
8736 #endif /* DEBUG_WINDOW_PRINTING */
8739 _gdk_windowing_got_event (GdkDisplay *display,
8744 GdkWindow *event_window;
8745 GdkWindowObject *event_private;
8747 gboolean unlink_event;
8748 guint old_state, old_button;
8749 GdkPointerGrabInfo *button_release_grab;
8750 gboolean is_toplevel;
8752 if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
8753 display->last_event_time = gdk_event_get_time (event);
8755 _gdk_display_pointer_grab_update (display,
8758 event_window = event->any.window;
8762 event_private = GDK_WINDOW_OBJECT (event_window);
8764 #ifdef DEBUG_WINDOW_PRINTING
8765 if (event->type == GDK_KEY_PRESS &&
8766 (event->key.keyval == 0xa7 ||
8767 event->key.keyval == 0xbd))
8769 gdk_window_print_tree (event_window, 0,
8770 event->key.keyval == 0xbd);
8774 if (!(is_button_type (event->type) ||
8775 is_motion_type (event->type)) ||
8776 GDK_WINDOW_TYPE (event_private) == GDK_WINDOW_ROOT)
8780 event_private->parent == NULL ||
8781 GDK_WINDOW_TYPE (event_private->parent) == GDK_WINDOW_ROOT;
8783 if ((event->type == GDK_ENTER_NOTIFY ||
8784 event->type == GDK_LEAVE_NOTIFY) &&
8785 (event->crossing.mode == GDK_CROSSING_GRAB ||
8786 event->crossing.mode == GDK_CROSSING_UNGRAB) &&
8787 (_gdk_display_has_pointer_grab (display, serial) ||
8788 event->crossing.detail == GDK_NOTIFY_INFERIOR))
8790 /* We synthesize all crossing events due to grabs outselves,
8791 * so we ignore the native ones caused by our native pointer_grab
8792 * calls. Otherwise we would proxy these crossing event and cause
8793 * multiple copies of crossing events for grabs.
8795 * We do want to handle grabs from other clients though, as for
8796 * instance alt-tab in metacity causes grabs like these and
8797 * we want to handle those. Thus the has_pointer_grab check.
8799 * Implicit grabs on child windows create some grabbing events
8800 * that are sent before the button press. This means we can't
8801 * detect these with the has_pointer_grab check (as the implicit
8802 * grab is only noticed when we get button press event), so we
8803 * detect these events by checking for INFERIOR enter or leave
8804 * events. These should never be a problem to filter out.
8807 /* We ended up in this window after some (perhaps other clients)
8808 grab, so update the toplevel_under_window state */
8810 event->type == GDK_ENTER_NOTIFY &&
8811 event->crossing.mode == GDK_CROSSING_UNGRAB)
8813 if (display->pointer_info.toplevel_under_pointer)
8814 g_object_unref (display->pointer_info.toplevel_under_pointer);
8815 display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
8818 unlink_event = TRUE;
8822 /* Track toplevel_under_pointer */
8825 if (event->type == GDK_ENTER_NOTIFY &&
8826 event->crossing.detail != GDK_NOTIFY_INFERIOR)
8828 if (display->pointer_info.toplevel_under_pointer)
8829 g_object_unref (display->pointer_info.toplevel_under_pointer);
8830 display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
8832 else if (event->type == GDK_LEAVE_NOTIFY &&
8833 event->crossing.detail != GDK_NOTIFY_INFERIOR &&
8834 display->pointer_info.toplevel_under_pointer == event_window)
8836 if (display->pointer_info.toplevel_under_pointer)
8837 g_object_unref (display->pointer_info.toplevel_under_pointer);
8838 display->pointer_info.toplevel_under_pointer = NULL;
8842 /* Store last pointer window and position/state */
8843 old_state = display->pointer_info.state;
8844 old_button = display->pointer_info.button;
8846 gdk_event_get_coords (event, &x, &y);
8847 convert_coords_to_toplevel (event_window, x, y, &x, &y);
8848 display->pointer_info.toplevel_x = x;
8849 display->pointer_info.toplevel_y = y;
8850 gdk_event_get_state (event, &display->pointer_info.state);
8851 if (event->type == GDK_BUTTON_PRESS ||
8852 event->type == GDK_BUTTON_RELEASE)
8853 display->pointer_info.button = event->button.button;
8855 if (display->pointer_info.state != old_state ||
8856 display->pointer_info.button != old_button)
8857 _gdk_display_enable_motion_hints (display);
8859 unlink_event = FALSE;
8860 if (is_motion_type (event->type))
8861 unlink_event = proxy_pointer_event (display,
8864 else if (is_button_type (event->type))
8865 unlink_event = proxy_button_event (event,
8868 if (event->type == GDK_BUTTON_RELEASE)
8870 button_release_grab =
8871 _gdk_display_has_pointer_grab (display, serial);
8872 if (button_release_grab &&
8873 button_release_grab->implicit &&
8874 (event->button.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
8876 button_release_grab->serial_end = serial;
8877 button_release_grab->implicit_ungrab = TRUE;
8878 _gdk_display_pointer_grab_update (display, serial);
8885 _gdk_event_queue_remove_link (display, event_link);
8886 g_list_free_1 (event_link);
8887 gdk_event_free (event);
8891 #define __GDK_WINDOW_C__
8892 #include "gdkaliasdef.c"