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"
36 #include "gdkscreen.h"
37 #include "gdkmarshalers.h"
40 #undef DEBUG_WINDOW_PRINTING
42 #ifdef GDK_WINDOWING_X11
43 #include "x11/gdkx.h" /* For workaround */
48 /* Historically a GdkWindow always matches a platform native window,
49 * be it a toplevel window or a child window. In this setup the
50 * GdkWindow (and other GdkDrawables) were platform independent classes,
51 * and the actual platform specific implementation was in a delegate
52 * object availible as "impl" in the window object.
54 * With the addition of client side windows and offscreen windows this
55 * changes a bit. The application-visible GdkWindow object behaves as
56 * it did before, but not all such windows now have a corresponding native
57 * window. Instead windows that are "client side" are emulated by the gdk
58 * code such that clipping, drawing, moving, events etc work as expected.
60 * For GdkWindows that have a native window the "impl" object is the
61 * same as before. However, for all client side windows the impl object
62 * is shared with its parent (i.e. all client windows descendants of one
63 * native window has the same impl.
65 * Additionally there is a new type of platform independent impl object,
66 * GdkOffscreenWindow. All windows of type GDK_WINDOW_OFFSCREEN get an impl
67 * of this type (while their children are generally GDK_WINDOW_CHILD virtual
68 * windows). Such windows work by allocating a GdkPixmap as the backing store
69 * for drawing operations, which is resized with the window.
71 * GdkWindows have a pointer to the "impl window" they are in, i.e.
72 * the topmost GdkWindow which have the same "impl" value. This is stored
73 * in impl_window, which is different from the window itself only for client
75 * All GdkWindows (native or not) track the position of the window in the parent
76 * (x, y), the size of the window (width, height), the position of the window
77 * with respect to the impl window (abs_x, abs_y). We also track the clip
78 * region of the window wrt parent windows and siblings, in window-relative
79 * coordinates with and without child windows included (clip_region,
80 * clip_region_with_children).
82 * All toplevel windows are native windows, but also child windows can be
83 * native (although not children of offscreens). We always listen to
84 * a basic set of events (see get_native_event_mask) for these windows
85 * so that we can emulate events for any client side children.
87 * For native windows we apply the calculated clip region as a window shape
88 * so that eg. client side siblings that overlap the native child properly
89 * draws over the native child window.
91 * In order to minimize flicker and for performance we use a couple of cacheing
92 * tricks. First of all, every time we do a window to window copy area, for instance
93 * when moving a client side window or when scrolling/moving a region in a window
94 * we store this in outstanding_moves instead of applying immediately. We then
95 * delay this move until we really need it (because something depends on being
96 * able to read it), or until we're handing a redraw from an expose/invalidation
97 * (actually we delay it past redraw, but before blitting the double buffer pixmap
98 * to the window). This gives us two advantages. First of all it minimizes the time
99 * from the window is moved to the exposes related to that move, secondly it allows
100 * us to be smart about how to do the copy. We combine multiple moves into one (when
101 * possible) and we don't actually do copies to anything that is or will be
102 * invalidated and exposed anyway.
104 * Secondly, we use something called a "implicit paint" during repaint handling.
105 * An implicit paint is similar to a regular paint for the paint stack, but it is
106 * not put on the stack. Instead, it is set on the impl window, and later when
107 * regular gdk_window_begin_paint_region() happen on a window of this impl window
108 * we reuse the pixmap from the implicit paint. During repaint we create and at the
109 * end flush an implicit paint, which means we can collect all the paints on
110 * multiple client side windows in the same backing store pixmap.
112 * All drawing to windows are wrapped with macros that set up the GC such that
113 * the offsets and clip region is right for drawing to the paint object or
114 * directly to the emulated window. It also automatically handles any flushing
115 * needed when drawing directly to a window. Adding window/paint clipping is
116 * done using _gdk_gc_add_drawable_clip which lets us efficiently add and then
117 * remove a custom clip region.
120 #define USE_BACKING_STORE /* Appears to work on Win32, too, now. */
122 /* This adds a local value to the GdkVisibilityState enum */
123 #define GDK_VISIBILITY_NOT_VIEWABLE 3
126 PICK_EMBEDDED_CHILD, /* only called if children are embedded */
137 struct _GdkWindowPaint
143 cairo_surface_t *surface;
144 guint uses_implicit : 1;
150 GdkRegion *dest_region; /* The destination region */
151 int dx, dy; /* The amount that the source was moved to reach dest_region */
152 } GdkWindowRegionMove;
157 static GdkGC *gdk_window_create_gc (GdkDrawable *drawable,
159 GdkGCValuesMask mask);
160 static void gdk_window_draw_rectangle (GdkDrawable *drawable,
167 static void gdk_window_draw_arc (GdkDrawable *drawable,
176 static void gdk_window_draw_polygon (GdkDrawable *drawable,
181 static void gdk_window_draw_text (GdkDrawable *drawable,
188 static void gdk_window_draw_text_wc (GdkDrawable *drawable,
193 const GdkWChar *text,
195 static void gdk_window_draw_drawable (GdkDrawable *drawable,
204 GdkDrawable *original_src);
205 static void gdk_window_draw_points (GdkDrawable *drawable,
209 static void gdk_window_draw_segments (GdkDrawable *drawable,
213 static void gdk_window_draw_lines (GdkDrawable *drawable,
218 static void gdk_window_draw_glyphs (GdkDrawable *drawable,
223 PangoGlyphString *glyphs);
224 static void gdk_window_draw_glyphs_transformed (GdkDrawable *drawable,
230 PangoGlyphString *glyphs);
232 static void gdk_window_draw_image (GdkDrawable *drawable,
242 static void gdk_window_draw_pixbuf (GdkDrawable *drawable,
255 static void gdk_window_draw_trapezoids (GdkDrawable *drawable,
257 GdkTrapezoid *trapezoids,
260 static GdkImage* gdk_window_copy_to_image (GdkDrawable *drawable,
269 static cairo_surface_t *gdk_window_ref_cairo_surface (GdkDrawable *drawable);
270 static cairo_surface_t *gdk_window_create_cairo_surface (GdkDrawable *drawable,
273 static void gdk_window_set_cairo_clip (GdkDrawable *drawable,
276 static void gdk_window_real_get_size (GdkDrawable *drawable,
280 static GdkVisual* gdk_window_real_get_visual (GdkDrawable *drawable);
281 static gint gdk_window_real_get_depth (GdkDrawable *drawable);
282 static GdkScreen* gdk_window_real_get_screen (GdkDrawable *drawable);
283 static void gdk_window_real_set_colormap (GdkDrawable *drawable,
285 static GdkColormap* gdk_window_real_get_colormap (GdkDrawable *drawable);
287 static GdkDrawable* gdk_window_get_source_drawable (GdkDrawable *drawable);
288 static GdkDrawable* gdk_window_get_composite_drawable (GdkDrawable *drawable,
293 gint *composite_x_offset,
294 gint *composite_y_offset);
295 static GdkRegion* gdk_window_get_clip_region (GdkDrawable *drawable);
296 static GdkRegion* gdk_window_get_visible_region (GdkDrawable *drawable);
298 static void gdk_window_free_paint_stack (GdkWindow *window);
300 static void gdk_window_init (GdkWindowObject *window);
301 static void gdk_window_class_init (GdkWindowObjectClass *klass);
302 static void gdk_window_finalize (GObject *object);
304 static void gdk_window_set_property (GObject *object,
308 static void gdk_window_get_property (GObject *object,
313 static void gdk_window_clear_backing_region (GdkWindow *window,
315 static void gdk_window_redirect_free (GdkWindowRedirect *redirect);
316 static void apply_redirect_to_children (GdkWindowObject *private,
317 GdkWindowRedirect *redirect);
318 static void remove_redirect_from_children (GdkWindowObject *private,
319 GdkWindowRedirect *redirect);
321 static void recompute_visible_regions (GdkWindowObject *private,
322 gboolean recalculate_siblings,
323 gboolean recalculate_children);
324 static void gdk_window_flush_outstanding_moves (GdkWindow *window);
325 static void gdk_window_flush_recursive (GdkWindowObject *window);
326 static void do_move_region_bits_on_impl (GdkWindowObject *private,
327 GdkRegion *region, /* In impl window coords */
329 static void gdk_window_invalidate_in_parent (GdkWindowObject *private);
330 static void move_native_children (GdkWindowObject *private);
331 static void update_cursor (GdkDisplay *display);
332 static void impl_window_add_update_area (GdkWindowObject *impl_window,
334 static void gdk_window_region_move_free (GdkWindowRegionMove *move);
336 static guint signals[LAST_SIGNAL] = { 0 };
338 static gpointer parent_class = NULL;
340 static const cairo_user_data_key_t gdk_window_cairo_key;
343 new_region_tag (void)
345 static guint32 tag = 0;
351 gdk_window_object_get_type (void)
353 static GType object_type = 0;
356 object_type = g_type_register_static_simple (GDK_TYPE_DRAWABLE,
358 sizeof (GdkWindowObjectClass),
359 (GClassInitFunc) gdk_window_class_init,
360 sizeof (GdkWindowObject),
361 (GInstanceInitFunc) gdk_window_init,
368 _gdk_paintable_get_type (void)
370 static GType paintable_type = 0;
374 const GTypeInfo paintable_info =
376 sizeof (GdkPaintableIface), /* class_size */
377 NULL, /* base_init */
378 NULL, /* base_finalize */
381 paintable_type = g_type_register_static (G_TYPE_INTERFACE,
382 g_intern_static_string ("GdkPaintable"),
385 g_type_interface_add_prerequisite (paintable_type, G_TYPE_OBJECT);
388 return paintable_type;
392 gdk_window_init (GdkWindowObject *window)
394 /* 0-initialization is good for all other fields. */
396 window->window_type = GDK_WINDOW_CHILD;
398 window->state = GDK_WINDOW_STATE_WITHDRAWN;
401 window->toplevel_window_type = -1;
403 window->effective_visibility = GDK_VISIBILITY_NOT_VIEWABLE;
404 window->visibility = GDK_VISIBILITY_FULLY_OBSCURED;
405 /* Default to unobscured since some backends don't send visibility events */
406 window->native_visibility = GDK_VISIBILITY_UNOBSCURED;
409 /* Stop and return on the first non-NULL parent */
411 accumulate_get_window (GSignalInvocationHint *ihint,
413 const GValue *handler_return,
416 g_value_copy (handler_return, return_accu);
417 /* Continue while returning NULL */
418 return g_value_get_object (handler_return) == NULL;
421 static GQuark quark_pointer_window = 0;
424 gdk_window_class_init (GdkWindowObjectClass *klass)
426 GObjectClass *object_class = G_OBJECT_CLASS (klass);
427 GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
429 parent_class = g_type_class_peek_parent (klass);
431 object_class->finalize = gdk_window_finalize;
432 object_class->set_property = gdk_window_set_property;
433 object_class->get_property = gdk_window_get_property;
435 drawable_class->create_gc = gdk_window_create_gc;
436 drawable_class->draw_rectangle = gdk_window_draw_rectangle;
437 drawable_class->draw_arc = gdk_window_draw_arc;
438 drawable_class->draw_polygon = gdk_window_draw_polygon;
439 drawable_class->draw_text = gdk_window_draw_text;
440 drawable_class->draw_text_wc = gdk_window_draw_text_wc;
441 drawable_class->draw_drawable_with_src = gdk_window_draw_drawable;
442 drawable_class->draw_points = gdk_window_draw_points;
443 drawable_class->draw_segments = gdk_window_draw_segments;
444 drawable_class->draw_lines = gdk_window_draw_lines;
445 drawable_class->draw_glyphs = gdk_window_draw_glyphs;
446 drawable_class->draw_glyphs_transformed = gdk_window_draw_glyphs_transformed;
447 drawable_class->draw_image = gdk_window_draw_image;
448 drawable_class->draw_pixbuf = gdk_window_draw_pixbuf;
449 drawable_class->draw_trapezoids = gdk_window_draw_trapezoids;
450 drawable_class->get_depth = gdk_window_real_get_depth;
451 drawable_class->get_screen = gdk_window_real_get_screen;
452 drawable_class->get_size = gdk_window_real_get_size;
453 drawable_class->set_colormap = gdk_window_real_set_colormap;
454 drawable_class->get_colormap = gdk_window_real_get_colormap;
455 drawable_class->get_visual = gdk_window_real_get_visual;
456 drawable_class->_copy_to_image = gdk_window_copy_to_image;
457 drawable_class->ref_cairo_surface = gdk_window_ref_cairo_surface;
458 drawable_class->create_cairo_surface = gdk_window_create_cairo_surface;
459 drawable_class->set_cairo_clip = gdk_window_set_cairo_clip;
460 drawable_class->get_clip_region = gdk_window_get_clip_region;
461 drawable_class->get_visible_region = gdk_window_get_visible_region;
462 drawable_class->get_composite_drawable = gdk_window_get_composite_drawable;
463 drawable_class->get_source_drawable = gdk_window_get_source_drawable;
465 quark_pointer_window = g_quark_from_static_string ("gtk-pointer-window");
469 g_object_class_install_property (object_class,
471 g_param_spec_boxed ("cursor",
478 * GdkWindow::pick-embedded-child:
479 * @window: the window on which the signal is emitted
480 * @x: x coordinate in the window
481 * @y: y coordinate in the window
483 * The ::pick-embedded-child signal is emitted to find an embedded
484 * child at the given position.
486 * Returns: the #GdkWindow of the embedded child at @x, @y, or %NULL
490 signals[PICK_EMBEDDED_CHILD] =
491 g_signal_new (g_intern_static_string ("pick-embedded-child"),
492 G_OBJECT_CLASS_TYPE (object_class),
495 accumulate_get_window, NULL,
496 _gdk_marshal_OBJECT__DOUBLE_DOUBLE,
503 * GdkWindow::to-embedder:
504 * @window: the offscreen window on which the signal is emitted
505 * @offscreen-x: x coordinate in the offscreen window
506 * @offscreen-y: y coordinate in the offscreen window
507 * @embedder-x: return location for the x coordinate in the embedder window
508 * @embedder-y: return location for the y coordinate in the embedder window
510 * The ::to-embedder signal is emitted to translate coordinates
511 * in an offscreen window to its embedder.
513 * See also #GtkWindow::from-embedder.
517 signals[TO_EMBEDDER] =
518 g_signal_new (g_intern_static_string ("to-embedder"),
519 G_OBJECT_CLASS_TYPE (object_class),
523 _gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
532 * GdkWindow::from-embedder:
533 * @window: the offscreen window on which the signal is emitted
534 * @embedder-x: x coordinate in the embedder window
535 * @embedder-y: y coordinate in the embedder window
536 * @offscreen-x: return location for the x coordinate in the offscreen window
537 * @offscreen-y: return location for the y coordinate in the offscreen window
539 * The ::from-embedder signal is emitted to translate coordinates
540 * in the embedder of an offscreen window to the offscreen window.
542 * See also #GtkWindow::to-embedder.
546 signals[FROM_EMBEDDER] =
547 g_signal_new (g_intern_static_string ("from-embedder"),
548 G_OBJECT_CLASS_TYPE (object_class),
552 _gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
562 gdk_window_finalize (GObject *object)
564 GdkWindow *window = GDK_WINDOW (object);
565 GdkWindowObject *obj = (GdkWindowObject *) object;
567 if (!GDK_WINDOW_DESTROYED (window))
569 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
571 g_warning ("losing last reference to undestroyed window\n");
572 _gdk_window_destroy (window, FALSE);
575 /* We use TRUE here, to keep us from actually calling
576 * XDestroyWindow() on the window
578 _gdk_window_destroy (window, TRUE);
583 g_object_unref (obj->impl);
587 if (obj->impl_window != obj)
589 g_object_unref (obj->impl_window);
590 obj->impl_window = NULL;
594 gdk_region_destroy (obj->shape);
596 if (obj->input_shape)
597 gdk_region_destroy (obj->input_shape);
600 gdk_cursor_unref (obj->cursor);
602 G_OBJECT_CLASS (parent_class)->finalize (object);
606 gdk_window_set_property (GObject *object,
611 GdkWindow *window = (GdkWindow *)object;
616 gdk_window_set_cursor (window, g_value_get_boxed (value));
620 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
626 gdk_window_get_property (GObject *object,
631 GdkWindow *window = (GdkWindow *) object;
636 g_value_set_boxed (value, gdk_window_get_cursor (window));
640 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
646 gdk_window_is_offscreen (GdkWindowObject *window)
648 return window->window_type == GDK_WINDOW_OFFSCREEN;
651 static GdkWindowObject *
652 gdk_window_get_impl_window (GdkWindowObject *window)
654 return window->impl_window;
658 _gdk_window_get_impl_window (GdkWindow *window)
660 return (GdkWindow *)gdk_window_get_impl_window ((GdkWindowObject *)window);
664 gdk_window_has_impl (GdkWindowObject *window)
666 return window->impl_window == window;
670 gdk_window_is_toplevel (GdkWindowObject *window)
673 window->parent == NULL ||
674 window->parent->window_type == GDK_WINDOW_ROOT;
678 _gdk_window_has_impl (GdkWindow *window)
680 return gdk_window_has_impl ((GdkWindowObject *)window);
684 gdk_window_has_no_impl (GdkWindowObject *window)
686 return window->impl_window != window;
690 remove_child_area (GdkWindowObject *private,
691 GdkWindowObject *until,
695 GdkWindowObject *child;
696 GdkRegion *child_region;
701 for (l = private->children; l; l = l->next)
708 /* If region is empty already, no need to do
709 anything potentially costly */
710 if (gdk_region_empty (region))
713 if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
716 /* Ignore offscreen children, as they don't draw in their parent and
717 * don't take part in the clipping */
718 if (gdk_window_is_offscreen (child))
723 r.width = child->width;
724 r.height = child->height;
726 /* Bail early if child totally outside region */
727 if (gdk_region_rect_in (region, &r) == GDK_OVERLAP_RECTANGLE_OUT)
730 child_region = gdk_region_rectangle (&r);
734 /* Adjust shape region to parent window coords */
735 gdk_region_offset (child->shape, child->x, child->y);
736 gdk_region_intersect (child_region, child->shape);
737 gdk_region_offset (child->shape, -child->x, -child->y);
739 else if (private->window_type == GDK_WINDOW_FOREIGN)
741 shape = _gdk_windowing_window_get_shape ((GdkWindow *)child);
744 gdk_region_intersect (child_region, shape);
745 gdk_region_destroy (shape);
751 if (child->input_shape)
752 gdk_region_intersect (child_region, child->input_shape);
753 else if (private->window_type == GDK_WINDOW_FOREIGN)
755 shape = _gdk_windowing_window_get_input_shape ((GdkWindow *)child);
758 gdk_region_intersect (child_region, shape);
759 gdk_region_destroy (shape);
764 gdk_region_subtract (region, child_region);
765 gdk_region_destroy (child_region);
770 static GdkVisibilityState
771 effective_visibility (GdkWindowObject *private)
773 GdkVisibilityState native;
775 if (!gdk_window_is_viewable ((GdkWindow *)private))
776 return GDK_VISIBILITY_NOT_VIEWABLE;
778 native = private->impl_window->native_visibility;
780 if (native == GDK_VISIBILITY_FULLY_OBSCURED ||
781 private->visibility == GDK_VISIBILITY_FULLY_OBSCURED)
782 return GDK_VISIBILITY_FULLY_OBSCURED;
783 else if (native == GDK_VISIBILITY_UNOBSCURED)
784 return private->visibility;
785 else /* native PARTIAL, private partial or unobscured */
786 return GDK_VISIBILITY_PARTIAL;
790 gdk_window_update_visibility (GdkWindowObject *private)
792 GdkVisibilityState new_visibility;
795 new_visibility = effective_visibility (private);
797 if (new_visibility != private->effective_visibility)
799 private->effective_visibility = new_visibility;
801 if (new_visibility != GDK_VISIBILITY_NOT_VIEWABLE &&
802 private->event_mask & GDK_VISIBILITY_NOTIFY)
804 event = _gdk_make_event ((GdkWindow *)private, GDK_VISIBILITY_NOTIFY,
806 event->visibility.state = new_visibility;
812 gdk_window_update_visibility_recursively (GdkWindowObject *private,
813 GdkWindowObject *only_for_impl)
815 GdkWindowObject *child;
818 gdk_window_update_visibility (private);
819 for (l = private->children; l != NULL; l = l->next)
822 if ((only_for_impl == NULL) ||
823 (only_for_impl == child->impl_window))
824 gdk_window_update_visibility_recursively (child, only_for_impl);
829 should_apply_clip_as_shape (GdkWindowObject *private)
832 gdk_window_has_impl (private) &&
833 /* Not for offscreens */
834 private->window_type != GDK_WINDOW_OFFSCREEN &&
835 /* or for toplevels */
836 !gdk_window_is_toplevel (private) &&
837 /* or for foreign windows */
838 private->window_type != GDK_WINDOW_FOREIGN &&
839 /* or for the root window */
840 private->window_type != GDK_WINDOW_ROOT;
844 apply_shape (GdkWindowObject *private,
847 GdkWindowImplIface *impl_iface;
849 /* We trash whether we applied a shape so that
850 we can avoid unsetting it many times, which
851 could happen in e.g. apply_clip_as_shape as
852 windows get resized */
853 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
855 impl_iface->shape_combine_region ((GdkWindow *)private,
857 else if (private->applied_shape)
858 impl_iface->shape_combine_region ((GdkWindow *)private,
861 private->applied_shape = region != NULL;
865 apply_clip_as_shape (GdkWindowObject *private)
870 r.width = private->width;
871 r.height = private->height;
873 /* We only apply the clip region if would differ
874 from the actual clip region implied by the size
875 of the window. This is to avoid unneccessarily
876 adding meaningless shapes to all native subwindows */
877 if (!gdk_region_rect_equal (private->clip_region, &r))
878 apply_shape (private, private->clip_region);
880 apply_shape (private, NULL);
884 recompute_visible_regions_internal (GdkWindowObject *private,
885 gboolean recalculate_clip,
886 gboolean recalculate_siblings,
887 gboolean recalculate_children)
891 GdkWindowObject *child;
892 GdkRegion *new_clip, *old_clip_region_with_children;
893 gboolean clip_region_changed;
894 gboolean abs_pos_changed;
895 int old_abs_x, old_abs_y;
897 old_abs_x = private->abs_x;
898 old_abs_y = private->abs_y;
900 /* Update absolute position */
901 if (gdk_window_has_impl (private))
903 /* Native window starts here */
909 private->abs_x = private->parent->abs_x + private->x;
910 private->abs_y = private->parent->abs_y + private->y;
914 private->abs_x != old_abs_x ||
915 private->abs_y != old_abs_y;
917 /* Update clip region based on:
920 * siblings in parents above window
922 clip_region_changed = FALSE;
923 if (recalculate_clip)
925 if (private->viewable)
927 /* Calculate visible region (sans children) in parent window coords */
930 r.width = private->width;
931 r.height = private->height;
932 new_clip = gdk_region_rectangle (&r);
934 if (!gdk_window_is_toplevel (private))
936 gdk_region_intersect (new_clip, private->parent->clip_region);
938 /* Remove all overlapping children from parent.
939 * Unless we're all native, because then we don't need to take
940 * siblings into account since X does that clipping for us.
941 * This makes things like SWT that modify the raw X stacking
942 * order without GDKs knowledge work.
944 if (!_gdk_native_windows)
945 remove_child_area (private->parent, private, FALSE, new_clip);
948 /* Convert from parent coords to window coords */
949 gdk_region_offset (new_clip, -private->x, -private->y);
952 gdk_region_intersect (new_clip, private->shape);
955 new_clip = gdk_region_new ();
957 if (private->clip_region == NULL ||
958 !gdk_region_equal (private->clip_region, new_clip))
959 clip_region_changed = TRUE;
961 if (private->clip_region)
962 gdk_region_destroy (private->clip_region);
963 private->clip_region = new_clip;
965 old_clip_region_with_children = private->clip_region_with_children;
966 private->clip_region_with_children = gdk_region_copy (private->clip_region);
967 if (private->window_type != GDK_WINDOW_ROOT)
968 remove_child_area (private, NULL, FALSE, private->clip_region_with_children);
970 if (clip_region_changed ||
971 !gdk_region_equal (private->clip_region_with_children, old_clip_region_with_children))
972 private->clip_tag = new_region_tag ();
974 if (old_clip_region_with_children)
975 gdk_region_destroy (old_clip_region_with_children);
978 if (clip_region_changed)
980 GdkVisibilityState visibility;
981 gboolean fully_visible;
983 if (gdk_region_empty (private->clip_region))
984 visibility = GDK_VISIBILITY_FULLY_OBSCURED;
989 fully_visible = gdk_region_equal (private->clip_region,
996 r.width = private->width;
997 r.height = private->height;
998 fully_visible = gdk_region_rect_equal (private->clip_region, &r);
1002 visibility = GDK_VISIBILITY_UNOBSCURED;
1004 visibility = GDK_VISIBILITY_PARTIAL;
1007 if (private->visibility != visibility)
1009 private->visibility = visibility;
1010 gdk_window_update_visibility (private);
1014 /* Update all children, recursively (except for root, where children are not exact). */
1015 if ((abs_pos_changed || clip_region_changed || recalculate_children) &&
1016 private->window_type != GDK_WINDOW_ROOT)
1018 for (l = private->children; l; l = l->next)
1021 /* Only recalculate clip if the the clip region changed, otherwise
1022 * there is no way the child clip region could change (its has not e.g. moved)
1023 * Except if recalculate_children is set to force child updates
1025 recompute_visible_regions_internal (child,
1026 recalculate_clip && (clip_region_changed || recalculate_children),
1031 if (clip_region_changed &&
1032 should_apply_clip_as_shape (private))
1033 apply_clip_as_shape (private);
1035 if (recalculate_siblings &&
1036 !gdk_window_is_toplevel (private))
1038 /* If we moved a child window in parent or changed the stacking order, then we
1039 * need to recompute the visible area of all the other children in the parent
1041 for (l = private->parent->children; l; l = l->next)
1045 if (child != private)
1046 recompute_visible_regions_internal (child, TRUE, FALSE, FALSE);
1049 /* We also need to recompute the _with_children clip for the parent */
1050 recompute_visible_regions_internal (private->parent, TRUE, FALSE, FALSE);
1053 if (private->cairo_surface)
1057 /* It would be nice if we had some cairo support here so we
1058 could set the clip rect on the cairo surface */
1059 width = private->abs_x + private->width;
1060 height = private->abs_y + private->height;
1062 _gdk_windowing_set_cairo_surface_size (private->cairo_surface,
1064 cairo_surface_set_device_offset (private->cairo_surface,
1070 /* Call this when private has changed in one or more of these ways:
1074 * stacking order of window changed
1077 * It will recalculate abs_x/y and the clip regions
1079 * Unless the window didn't change stacking order or size/pos, pass in TRUE
1080 * for recalculate_siblings. (Mostly used internally for the recursion)
1082 * If a child window was removed (and you can't use that child for
1083 * recompute_visible_regions), pass in TRUE for recalculate_children on the parent
1086 recompute_visible_regions (GdkWindowObject *private,
1087 gboolean recalculate_siblings,
1088 gboolean recalculate_children)
1090 recompute_visible_regions_internal (private,
1092 recalculate_siblings,
1093 recalculate_children);
1097 _gdk_window_update_size (GdkWindow *window)
1099 recompute_visible_regions ((GdkWindowObject *)window, TRUE, FALSE);
1102 /* Find the native window that would be just above "child"
1103 * in the native stacking order if "child" was a native window
1104 * (it doesn't have to be native). If there is no such native
1105 * window inside this native parent then NULL is returned.
1106 * If child is NULL, find lowest native window in parent.
1108 static GdkWindowObject *
1109 find_native_sibling_above_helper (GdkWindowObject *parent,
1110 GdkWindowObject *child)
1117 l = g_list_find (parent->children, child);
1118 g_assert (l != NULL); /* Better be a child of its parent... */
1119 l = l->prev; /* Start looking at the one above the child */
1122 l = g_list_last (parent->children);
1124 for (; l != NULL; l = l->prev)
1128 if (gdk_window_has_impl (w))
1131 g_assert (parent != w);
1132 w = find_native_sibling_above_helper (w, NULL);
1141 static GdkWindowObject *
1142 find_native_sibling_above (GdkWindowObject *parent,
1143 GdkWindowObject *child)
1147 w = find_native_sibling_above_helper (parent, child);
1151 if (gdk_window_has_impl (parent))
1154 return find_native_sibling_above (parent->parent, parent);
1158 get_native_event_mask (GdkWindowObject *private)
1160 if (_gdk_native_windows ||
1161 private->window_type == GDK_WINDOW_ROOT ||
1162 private->window_type == GDK_WINDOW_FOREIGN)
1163 return private->event_mask;
1168 /* Do whatever the app asks to, since the app
1169 * may be asking for weird things for native windows,
1170 * but filter out things that override the special
1171 * requests below. */
1172 mask = private->event_mask &
1173 ~(GDK_POINTER_MOTION_HINT_MASK |
1174 GDK_BUTTON_MOTION_MASK |
1175 GDK_BUTTON1_MOTION_MASK |
1176 GDK_BUTTON2_MOTION_MASK |
1177 GDK_BUTTON3_MOTION_MASK);
1179 /* We need thse for all native windows so we can
1180 emulate events on children: */
1183 GDK_VISIBILITY_NOTIFY_MASK |
1184 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK;
1186 /* Additionally we select for pointer and button events
1187 * for toplevels as we need to get these to emulate
1188 * them for non-native subwindows. Even though we don't
1189 * select on them for all native windows we will get them
1190 * as the events are propagated out to the first window
1191 * that select for them.
1192 * Not selecting for button press on all windows is an
1193 * important thing, because in X only one client can do
1194 * so, and we don't want to unexpectedly prevent another
1195 * client from doing it.
1197 if (gdk_window_is_toplevel (private))
1199 GDK_POINTER_MOTION_MASK |
1200 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
1208 get_native_grab_event_mask (GdkEventMask grab_mask)
1210 /* Similar to the above but for pointer events only */
1212 GDK_POINTER_MOTION_MASK |
1213 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
1214 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
1217 ~(GDK_POINTER_MOTION_HINT_MASK |
1218 GDK_BUTTON_MOTION_MASK |
1219 GDK_BUTTON1_MOTION_MASK |
1220 GDK_BUTTON2_MOTION_MASK |
1221 GDK_BUTTON3_MOTION_MASK));
1224 /* Puts the native window in the right order wrt the other native windows
1225 * in the hierarchy, given the position it has in the client side data.
1226 * This is useful if some operation changed the stacking order.
1227 * This calls assumes the native window is now topmost in its native parent.
1230 sync_native_window_stack_position (GdkWindow *window)
1232 GdkWindowObject *above;
1233 GdkWindowObject *private;
1234 GdkWindowImplIface *impl_iface;
1235 GList listhead = {0};
1237 private = (GdkWindowObject *) window;
1238 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
1240 above = find_native_sibling_above (private->parent, private);
1243 listhead.data = window;
1244 impl_iface->restack_under ((GdkWindow *)above,
1251 * @parent: a #GdkWindow, or %NULL to create the window as a child of
1252 * the default root window for the default display.
1253 * @attributes: attributes of the new window
1254 * @attributes_mask: mask indicating which fields in @attributes are valid
1256 * Creates a new #GdkWindow using the attributes from
1257 * @attributes. See #GdkWindowAttr and #GdkWindowAttributesType for
1258 * more details. Note: to use this on displays other than the default
1259 * display, @parent must be specified.
1261 * Return value: the new #GdkWindow
1264 gdk_window_new (GdkWindow *parent,
1265 GdkWindowAttr *attributes,
1266 gint attributes_mask)
1269 GdkWindowObject *private;
1274 GdkEventMask event_mask;
1275 GdkWindow *real_parent;
1277 g_return_val_if_fail (attributes != NULL, NULL);
1281 GDK_NOTE (MULTIHEAD,
1282 g_warning ("gdk_window_new(): no parent specified reverting to parent = default root window"));
1284 screen = gdk_screen_get_default ();
1285 parent = gdk_screen_get_root_window (screen);
1288 screen = gdk_drawable_get_screen (parent);
1290 g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
1292 if (GDK_WINDOW_DESTROYED (parent))
1294 g_warning ("gdk_window_new(): parent is destroyed\n");
1298 if (attributes->window_type == GDK_WINDOW_OFFSCREEN &&
1299 _gdk_native_windows)
1301 g_warning ("Offscreen windows not supported with native-windows gdk");
1305 window = g_object_new (GDK_TYPE_WINDOW, NULL);
1306 private = (GdkWindowObject *) window;
1308 /* Windows with a foreign parent are treated as if they are children
1309 * of the root window, except for actual creation.
1311 real_parent = parent;
1312 if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
1313 parent = gdk_screen_get_root_window (screen);
1315 private->parent = (GdkWindowObject *)parent;
1317 private->accept_focus = TRUE;
1318 private->focus_on_map = TRUE;
1320 if (attributes_mask & GDK_WA_X)
1325 if (attributes_mask & GDK_WA_Y)
1332 private->width = (attributes->width > 1) ? (attributes->width) : (1);
1333 private->height = (attributes->height > 1) ? (attributes->height) : (1);
1335 #ifdef GDK_WINDOWING_X11
1336 /* Work around a bug where Xorg refuses to map toplevel InputOnly windows
1337 * from an untrusted client: http://bugs.freedesktop.org/show_bug.cgi?id=6988
1339 if (attributes->wclass == GDK_INPUT_ONLY &&
1340 private->parent->window_type == GDK_WINDOW_ROOT &&
1341 !G_LIKELY (GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (parent))->trusted_client))
1343 g_warning ("Coercing GDK_INPUT_ONLY toplevel window to GDK_INPUT_OUTPUT to work around bug in Xorg server");
1344 attributes->wclass = GDK_INPUT_OUTPUT;
1348 if (attributes->wclass == GDK_INPUT_ONLY)
1350 /* Backwards compatiblity - we've always ignored
1351 * attributes->window_type for input-only windows
1354 if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
1355 private->window_type = GDK_WINDOW_TEMP;
1357 private->window_type = GDK_WINDOW_CHILD;
1360 private->window_type = attributes->window_type;
1363 switch (private->window_type)
1365 case GDK_WINDOW_TOPLEVEL:
1366 case GDK_WINDOW_DIALOG:
1367 case GDK_WINDOW_TEMP:
1368 case GDK_WINDOW_OFFSCREEN:
1369 if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
1370 g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
1371 "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
1372 case GDK_WINDOW_CHILD:
1376 g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
1380 if (attributes_mask & GDK_WA_VISUAL)
1381 visual = attributes->visual;
1383 visual = gdk_screen_get_system_visual (screen);
1385 private->event_mask = attributes->event_mask;
1387 if (attributes->wclass == GDK_INPUT_OUTPUT)
1389 private->input_only = FALSE;
1390 private->depth = visual->depth;
1392 private->bg_color.pixel = 0; /* TODO: BlackPixel (xdisplay, screen_x11->screen_num); */
1393 private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
1395 private->bg_pixmap = NULL;
1400 private->input_only = TRUE;
1403 if (private->parent)
1404 private->parent->children = g_list_prepend (private->parent->children, window);
1406 native = _gdk_native_windows; /* Default */
1407 if (private->parent->window_type == GDK_WINDOW_ROOT)
1408 native = TRUE; /* Always use native windows for toplevels */
1409 else if (!private->input_only &&
1410 ((attributes_mask & GDK_WA_COLORMAP &&
1411 attributes->colormap != gdk_drawable_get_colormap ((GdkDrawable *)private->parent)) ||
1412 (attributes_mask & GDK_WA_VISUAL &&
1413 attributes->visual != gdk_drawable_get_visual ((GdkDrawable *)private->parent))))
1414 native = TRUE; /* InputOutput window with different colormap or visual than parent, needs native window */
1416 if (private->window_type == GDK_WINDOW_OFFSCREEN)
1418 _gdk_offscreen_window_new (window, screen, visual, attributes, attributes_mask);
1419 private->impl_window = private;
1423 event_mask = get_native_event_mask (private);
1425 /* Create the impl */
1426 _gdk_window_impl_new (window, real_parent, screen, visual, event_mask, attributes, attributes_mask);
1427 private->impl_window = private;
1429 /* This will put the native window topmost in the native parent, which may
1430 * be wrong wrt other native windows in the non-native hierarchy, so restack */
1431 if (!_gdk_window_has_impl (real_parent))
1432 sync_native_window_stack_position (window);
1436 private->impl_window = g_object_ref (private->parent->impl_window);
1437 private->impl = g_object_ref (private->impl_window->impl);
1440 recompute_visible_regions (private, TRUE, FALSE);
1442 if (private->parent->window_type != GDK_WINDOW_ROOT)
1444 /* Inherit redirection from parent */
1445 private->redirect = private->parent->redirect;
1448 gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
1449 (attributes->cursor) :
1456 is_parent_of (GdkWindow *parent,
1467 w = gdk_window_get_parent (w);
1474 change_impl (GdkWindowObject *private,
1475 GdkWindowObject *impl_window,
1479 GdkWindowObject *child;
1480 GdkDrawable *old_impl;
1481 GdkWindowObject *old_impl_window;
1483 old_impl = private->impl;
1484 old_impl_window = private->impl_window;
1485 if (private != impl_window)
1486 private->impl_window = g_object_ref (impl_window);
1488 private->impl_window = private;
1489 private->impl = g_object_ref (new);
1490 if (old_impl_window != private)
1491 g_object_unref (old_impl_window);
1492 g_object_unref (old_impl);
1494 for (l = private->children; l != NULL; l = l->next)
1498 if (child->impl == old_impl)
1499 change_impl (child, impl_window, new);
1504 reparent_to_impl (GdkWindowObject *private)
1507 GdkWindowObject *child;
1509 GdkWindowImplIface *impl_iface;
1511 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
1513 /* Enumerate in reverse order so we get the right order for the native
1514 windows (first in childrens list is topmost, and reparent places on top) */
1515 for (l = g_list_last (private->children); l != NULL; l = l->prev)
1519 if (child->impl == private->impl)
1520 reparent_to_impl (child);
1523 show = impl_iface->reparent ((GdkWindow *)child,
1524 (GdkWindow *)private,
1525 child->x, child->y);
1527 gdk_window_show_unraised ((GdkWindow *)child);
1534 * gdk_window_reparent:
1535 * @window: a #GdkWindow
1536 * @new_parent: new parent to move @window into
1537 * @x: X location inside the new parent
1538 * @y: Y location inside the new parent
1540 * Reparents @window into the given @new_parent. The window being
1541 * reparented will be unmapped as a side effect.
1545 gdk_window_reparent (GdkWindow *window,
1546 GdkWindow *new_parent,
1550 GdkWindowObject *private;
1551 GdkWindowObject *new_parent_private;
1552 GdkWindowObject *old_parent;
1554 gboolean show, was_mapped, applied_clip_as_shape;
1555 gboolean do_reparent_to_impl;
1556 GdkEventMask old_native_event_mask;
1557 GdkWindowImplIface *impl_iface;
1559 g_return_if_fail (GDK_IS_WINDOW (window));
1560 g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
1561 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
1563 if (GDK_WINDOW_DESTROYED (window) ||
1564 (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
1567 screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
1569 new_parent = gdk_screen_get_root_window (screen);
1571 private = (GdkWindowObject *) window;
1572 new_parent_private = (GdkWindowObject *)new_parent;
1574 /* No input-output children of input-only windows */
1575 if (new_parent_private->input_only && !private->input_only)
1578 /* Don't create loops in hierarchy */
1579 if (is_parent_of (window, new_parent))
1582 if (private->cairo_surface)
1584 /* This might be wrong in the new parent, e.g. for non-native surfaces.
1585 To make sure we're ok, just wipe it. */
1586 cairo_surface_finish (private->cairo_surface);
1587 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
1591 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
1592 old_parent = private->parent;
1594 /* Break up redirection if inherited */
1595 if (private->redirect && private->redirect->redirected != private)
1597 remove_redirect_from_children (private, private->redirect);
1598 private->redirect = NULL;
1601 was_mapped = GDK_WINDOW_IS_MAPPED (window);
1604 /* Reparenting to toplevel. Ensure we have a native window so this can work */
1605 if (new_parent_private->window_type == GDK_WINDOW_ROOT ||
1606 new_parent_private->window_type == GDK_WINDOW_FOREIGN)
1607 gdk_window_ensure_native (window);
1609 applied_clip_as_shape = should_apply_clip_as_shape (private);
1611 old_native_event_mask = 0;
1612 do_reparent_to_impl = FALSE;
1613 if (gdk_window_has_impl (private))
1615 old_native_event_mask = get_native_event_mask (private);
1617 show = impl_iface->reparent (window, new_parent, x, y);
1621 /* This shouldn't happen, as we created a native in this case, check anyway to see if that ever fails */
1622 g_assert (new_parent_private->window_type != GDK_WINDOW_ROOT &&
1623 new_parent_private->window_type != GDK_WINDOW_FOREIGN);
1626 gdk_window_hide (window);
1628 do_reparent_to_impl = TRUE;
1629 change_impl (private,
1630 new_parent_private->impl_window,
1631 new_parent_private->impl);
1634 /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
1637 if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1639 new_parent = gdk_screen_get_root_window (screen);
1640 new_parent_private = (GdkWindowObject *)new_parent;
1644 old_parent->children = g_list_remove (old_parent->children, window);
1646 private->parent = new_parent_private;
1650 new_parent_private->children = g_list_prepend (new_parent_private->children, window);
1652 /* Switch the window type as appropriate */
1654 switch (GDK_WINDOW_TYPE (new_parent))
1656 case GDK_WINDOW_ROOT:
1657 case GDK_WINDOW_FOREIGN:
1658 if (private->toplevel_window_type != -1)
1659 GDK_WINDOW_TYPE (window) = private->toplevel_window_type;
1660 else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1661 GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
1663 case GDK_WINDOW_OFFSCREEN:
1664 case GDK_WINDOW_TOPLEVEL:
1665 case GDK_WINDOW_CHILD:
1666 case GDK_WINDOW_DIALOG:
1667 case GDK_WINDOW_TEMP:
1668 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
1669 GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
1671 /* Save the original window type so we can restore it if the
1672 * window is reparented back to be a toplevel
1674 private->toplevel_window_type = GDK_WINDOW_TYPE (window);
1675 GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
1679 /* We might have changed window type for a native windows, so we
1680 need to change the event mask too. */
1681 if (gdk_window_has_impl (private))
1683 GdkEventMask native_event_mask = get_native_event_mask (private);
1685 if (native_event_mask != old_native_event_mask)
1686 impl_iface->set_events (window, native_event_mask);
1689 /* Inherit parent redirect if we don't have our own */
1690 if (private->parent && private->redirect == NULL)
1692 private->redirect = private->parent->redirect;
1693 apply_redirect_to_children (private, private->redirect);
1696 _gdk_window_update_viewable (window);
1698 recompute_visible_regions (private, TRUE, FALSE);
1699 if (old_parent && GDK_WINDOW_TYPE (old_parent) != GDK_WINDOW_ROOT)
1700 recompute_visible_regions (old_parent, FALSE, TRUE);
1702 /* We used to apply the clip as the shape, but no more.
1703 Reset this to the real shape */
1704 if (gdk_window_has_impl (private) &&
1705 applied_clip_as_shape &&
1706 !should_apply_clip_as_shape (private))
1707 apply_shape (private, private->shape);
1709 if (do_reparent_to_impl)
1710 reparent_to_impl (private);
1713 /* The reparent will have put the native window topmost in the native parent,
1714 * which may be wrong wrt other native windows in the non-native hierarchy,
1716 if (!gdk_window_has_impl (new_parent_private))
1717 sync_native_window_stack_position (window);
1721 gdk_window_show_unraised (window);
1723 _gdk_synthesize_crossing_events_for_geometry_change (window);
1727 * gdk_window_ensure_native:
1728 * @window: a #GdkWindow
1730 * Tries to ensure that there is a window-system native window for this
1731 * GdkWindow. This may fail in some situations, returning %FALSE.
1733 * Offscreen window and children of them can never have native windows.
1735 * Some backends may not support native child windows.
1737 * Returns: %TRUE if the window has a native window, %FALSE otherwise
1742 gdk_window_ensure_native (GdkWindow *window)
1744 GdkWindowObject *private;
1745 GdkWindowObject *impl_window;
1746 GdkDrawable *new_impl, *old_impl;
1749 GdkWindowAttr attributes;
1750 GdkWindowObject *above;
1752 GdkWindowImplIface *impl_iface;
1754 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
1756 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT ||
1757 GDK_WINDOW_DESTROYED (window))
1760 private = (GdkWindowObject *) window;
1762 impl_window = gdk_window_get_impl_window (private);
1764 if (impl_window->window_type == GDK_WINDOW_OFFSCREEN)
1765 return FALSE; /* native in offscreens not supported */
1767 if (impl_window == private)
1768 /* Already has an impl, and its not offscreen . */
1771 /* Need to create a native window */
1773 screen = gdk_drawable_get_screen (window);
1774 visual = gdk_drawable_get_visual (window);
1776 attributes.colormap = gdk_drawable_get_colormap (window);
1778 old_impl = private->impl;
1779 _gdk_window_impl_new (window, (GdkWindow *)private->parent,
1781 get_native_event_mask (private),
1782 &attributes, GDK_WA_COLORMAP);
1783 new_impl = private->impl;
1785 private->impl = old_impl;
1786 change_impl (private, private, new_impl);
1788 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
1790 /* Native window creation will put the native window topmost in the
1791 * native parent, which may be wrong wrt the position of the previous
1792 * non-native window wrt to the other non-native children, so correct this.
1794 above = find_native_sibling_above (private->parent, private);
1797 listhead.data = window;
1798 listhead.prev = NULL;
1799 listhead.next = NULL;
1800 impl_iface->restack_under ((GdkWindow *)above, &listhead);
1803 recompute_visible_regions (private, FALSE, FALSE);
1805 /* The shape may not have been set, as the clip region doesn't actually
1806 change, so do it here manually */
1807 if (should_apply_clip_as_shape (private))
1808 apply_clip_as_shape (private);
1810 reparent_to_impl (private);
1812 if (!private->input_only)
1814 impl_iface->set_background (window, &private->bg_color);
1815 if (private->bg_pixmap != NULL)
1816 impl_iface->set_back_pixmap (window, private->bg_pixmap);
1819 impl_iface->input_shape_combine_region (window,
1820 private->input_shape,
1823 if (gdk_window_is_viewable (window))
1824 impl_iface->show (window, FALSE);
1830 window_remove_filters (GdkWindow *window)
1832 GdkWindowObject *obj = (GdkWindowObject*) window;
1838 for (tmp_list = obj->filters; tmp_list; tmp_list = tmp_list->next)
1839 g_free (tmp_list->data);
1841 g_list_free (obj->filters);
1842 obj->filters = NULL;
1847 * _gdk_window_destroy_hierarchy:
1848 * @window: a #GdkWindow
1849 * @recursing: If TRUE, then this is being called because a parent
1851 * @recursing_native: If TRUE, then this is being called because a native parent
1852 * was destroyed. This generally means that the call to the
1853 * windowing system to destroy the window can be omitted, since
1854 * it will be destroyed as a result of the parent being destroyed.
1855 * Unless @foreign_destroy.
1856 * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
1857 * external agency. The window has already been destroyed and no
1858 * windowing system calls should be made. (This may never happen
1859 * for some windowing systems.)
1861 * Internal function to destroy a window. Like gdk_window_destroy(),
1862 * but does not drop the reference count created by gdk_window_new().
1865 _gdk_window_destroy_hierarchy (GdkWindow *window,
1867 gboolean recursing_native,
1868 gboolean foreign_destroy)
1870 GdkWindowObject *private;
1871 GdkWindowObject *temp_private;
1872 GdkWindowImplIface *impl_iface;
1873 GdkWindow *temp_window;
1875 GdkDisplay *display;
1879 g_return_if_fail (GDK_IS_WINDOW (window));
1881 private = (GdkWindowObject*) window;
1883 if (GDK_WINDOW_DESTROYED (window))
1886 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
1887 screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
1888 temp_window = g_object_get_qdata (G_OBJECT (screen), quark_pointer_window);
1889 if (temp_window == window)
1890 g_object_set_qdata (G_OBJECT (screen), quark_pointer_window, NULL);
1893 switch (private->window_type)
1895 case GDK_WINDOW_ROOT:
1896 if (!screen->closed)
1898 g_error ("attempted to destroy root window");
1901 /* else fall thru */
1902 case GDK_WINDOW_TOPLEVEL:
1903 case GDK_WINDOW_CHILD:
1904 case GDK_WINDOW_DIALOG:
1905 case GDK_WINDOW_TEMP:
1906 case GDK_WINDOW_FOREIGN:
1907 case GDK_WINDOW_OFFSCREEN:
1908 if (private->window_type == GDK_WINDOW_FOREIGN && !foreign_destroy)
1910 /* Logically, it probably makes more sense to send
1911 * a "destroy yourself" message to the foreign window
1912 * whether or not it's in our hierarchy; but for historical
1913 * reasons, we only send "destroy yourself" messages to
1914 * foreign windows in our hierarchy.
1916 if (private->parent)
1917 _gdk_windowing_window_destroy_foreign (window);
1919 /* Also for historical reasons, we remove any filters
1920 * on a foreign window when it or a parent is destroyed;
1921 * this likely causes problems if two separate portions
1922 * of code are maintaining filter lists on a foreign window.
1924 window_remove_filters (window);
1928 if (private->parent)
1930 GdkWindowObject *parent_private = (GdkWindowObject *)private->parent;
1932 if (parent_private->children)
1933 parent_private->children = g_list_remove (parent_private->children, window);
1936 GDK_WINDOW_IS_MAPPED (window))
1938 recompute_visible_regions (private, TRUE, FALSE);
1939 gdk_window_invalidate_in_parent (private);
1943 gdk_window_free_paint_stack (window);
1945 if (private->bg_pixmap &&
1946 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
1947 private->bg_pixmap != GDK_NO_BG)
1949 g_object_unref (private->bg_pixmap);
1950 private->bg_pixmap = NULL;
1953 if (private->window_type == GDK_WINDOW_FOREIGN)
1954 g_assert (private->children == NULL);
1957 children = tmp = private->children;
1958 private->children = NULL;
1962 temp_window = tmp->data;
1965 temp_private = (GdkWindowObject*) temp_window;
1967 _gdk_window_destroy_hierarchy (temp_window,
1969 recursing_native || gdk_window_has_impl (private),
1973 g_list_free (children);
1976 _gdk_window_clear_update_area (window);
1978 if (private->cairo_surface)
1980 cairo_surface_finish (private->cairo_surface);
1981 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
1986 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
1988 if (private->extension_events)
1989 impl_iface->input_window_destroy (window);
1991 if (gdk_window_has_impl (private))
1992 impl_iface->destroy (window, recursing_native,
1996 /* hide to make sure we repaint and break grabs */
1997 gdk_window_hide (window);
2000 private->state |= GDK_WINDOW_STATE_WITHDRAWN;
2001 private->parent = NULL;
2002 private->destroyed = TRUE;
2004 window_remove_filters (window);
2006 gdk_drawable_set_colormap (GDK_DRAWABLE (window), NULL);
2008 /* If we own the redirect, free it */
2009 if (private->redirect && private->redirect->redirected == private)
2010 gdk_window_redirect_free (private->redirect);
2012 private->redirect = NULL;
2014 if (display->pointer_info.toplevel_under_pointer == window)
2016 g_object_unref (display->pointer_info.toplevel_under_pointer);
2017 display->pointer_info.toplevel_under_pointer = NULL;
2020 if (private->clip_region)
2022 gdk_region_destroy (private->clip_region);
2023 private->clip_region = NULL;
2026 if (private->clip_region_with_children)
2028 gdk_region_destroy (private->clip_region_with_children);
2029 private->clip_region_with_children = NULL;
2032 if (private->outstanding_moves)
2034 g_list_foreach (private->outstanding_moves, (GFunc)gdk_window_region_move_free, NULL);
2035 g_list_free (private->outstanding_moves);
2036 private->outstanding_moves = NULL;
2044 * _gdk_window_destroy:
2045 * @window: a #GdkWindow
2046 * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
2047 * external agency. The window has already been destroyed and no
2048 * windowing system calls should be made. (This may never happen
2049 * for some windowing systems.)
2051 * Internal function to destroy a window. Like gdk_window_destroy(),
2052 * but does not drop the reference count created by gdk_window_new().
2055 _gdk_window_destroy (GdkWindow *window,
2056 gboolean foreign_destroy)
2058 _gdk_window_destroy_hierarchy (window, FALSE, FALSE, foreign_destroy);
2062 * gdk_window_destroy:
2063 * @window: a #GdkWindow
2065 * Destroys the window system resources associated with @window and decrements @window's
2066 * reference count. The window system resources for all children of @window are also
2067 * destroyed, but the children's reference counts are not decremented.
2069 * Note that a window will not be destroyed automatically when its reference count
2070 * reaches zero. You must call this function yourself before that happens.
2074 gdk_window_destroy (GdkWindow *window)
2076 _gdk_window_destroy_hierarchy (window, FALSE, FALSE, FALSE);
2077 g_object_unref (window);
2081 * gdk_window_set_user_data:
2082 * @window: a #GdkWindow
2083 * @user_data: user data
2085 * For most purposes this function is deprecated in favor of
2086 * g_object_set_data(). However, for historical reasons GTK+ stores
2087 * the #GtkWidget that owns a #GdkWindow as user data on the
2088 * #GdkWindow. So, custom widget implementations should use
2089 * this function for that. If GTK+ receives an event for a #GdkWindow,
2090 * and the user data for the window is non-%NULL, GTK+ will assume the
2091 * user data is a #GtkWidget, and forward the event to that widget.
2095 gdk_window_set_user_data (GdkWindow *window,
2098 g_return_if_fail (GDK_IS_WINDOW (window));
2100 ((GdkWindowObject*)window)->user_data = user_data;
2104 * gdk_window_get_user_data:
2105 * @window: a #GdkWindow
2106 * @data: return location for user data
2108 * Retrieves the user data for @window, which is normally the widget
2109 * that @window belongs to. See gdk_window_set_user_data().
2113 gdk_window_get_user_data (GdkWindow *window,
2116 g_return_if_fail (GDK_IS_WINDOW (window));
2118 *data = ((GdkWindowObject*)window)->user_data;
2122 * gdk_window_get_window_type:
2123 * @window: a #GdkWindow
2125 * Gets the type of the window. See #GdkWindowType.
2127 * Return value: type of window
2130 gdk_window_get_window_type (GdkWindow *window)
2132 g_return_val_if_fail (GDK_IS_WINDOW (window), (GdkWindowType) -1);
2134 return GDK_WINDOW_TYPE (window);
2138 * gdk_window_is_destroyed:
2139 * @window: a #GdkWindow
2141 * Check to see if a window is destroyed..
2143 * Return value: %TRUE if the window is destroyed
2146 gdk_window_is_destroyed (GdkWindow *window)
2148 return GDK_WINDOW_DESTROYED (window);
2152 * gdk_window_get_position:
2153 * @window: a #GdkWindow
2154 * @x: X coordinate of window
2155 * @y: Y coordinate of window
2157 * Obtains the position of the window as reported in the
2158 * most-recently-processed #GdkEventConfigure. Contrast with
2159 * gdk_window_get_geometry() which queries the X server for the
2160 * current window position, regardless of which events have been
2161 * received or processed.
2163 * The position coordinates are relative to the window's parent window.
2167 gdk_window_get_position (GdkWindow *window,
2171 GdkWindowObject *obj;
2173 g_return_if_fail (GDK_IS_WINDOW (window));
2175 obj = (GdkWindowObject*) window;
2184 * gdk_window_get_parent:
2185 * @window: a #GdkWindow
2187 * Obtains the parent of @window, as known to GDK. Does not query the
2188 * X server; thus this returns the parent as passed to gdk_window_new(),
2189 * not the actual parent. This should never matter unless you're using
2190 * Xlib calls mixed with GDK calls on the X11 platform. It may also
2191 * matter for toplevel windows, because the window manager may choose
2194 * Return value: parent of @window
2197 gdk_window_get_parent (GdkWindow *window)
2199 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2201 return (GdkWindow*) ((GdkWindowObject*) window)->parent;
2205 * gdk_window_get_toplevel:
2206 * @window: a #GdkWindow
2208 * Gets the toplevel window that's an ancestor of @window.
2210 * Any window type but %GDK_WINDOW_CHILD is considered a
2211 * toplevel window, as is a %GDK_WINDOW_CHILD window that
2212 * has a root window as parent.
2214 * Return value: the toplevel window containing @window
2217 gdk_window_get_toplevel (GdkWindow *window)
2219 GdkWindowObject *obj;
2221 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2223 obj = (GdkWindowObject *)window;
2225 while (obj->window_type == GDK_WINDOW_CHILD)
2227 if (gdk_window_is_toplevel (obj))
2232 return GDK_WINDOW (obj);
2236 * gdk_window_get_children:
2237 * @window: a #GdkWindow
2239 * Gets the list of children of @window known to GDK.
2240 * This function only returns children created via GDK,
2241 * so for example it's useless when used with the root window;
2242 * it only returns windows an application created itself.
2244 * The returned list must be freed, but the elements in the
2247 * Return value: list of child windows inside @window
2250 gdk_window_get_children (GdkWindow *window)
2252 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2254 if (GDK_WINDOW_DESTROYED (window))
2257 return g_list_copy (GDK_WINDOW_OBJECT (window)->children);
2261 * gdk_window_peek_children:
2262 * @window: a #GdkWindow
2264 * Like gdk_window_get_children(), but does not copy the list of
2265 * children, so the list does not need to be freed.
2267 * Return value: a reference to the list of child windows in @window
2270 gdk_window_peek_children (GdkWindow *window)
2272 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2274 if (GDK_WINDOW_DESTROYED (window))
2277 return GDK_WINDOW_OBJECT (window)->children;
2281 * gdk_window_add_filter:
2282 * @window: a #GdkWindow
2283 * @function: filter callback
2284 * @data: data to pass to filter callback
2286 * Adds an event filter to @window, allowing you to intercept events
2287 * before they reach GDK. This is a low-level operation and makes it
2288 * easy to break GDK and/or GTK+, so you have to know what you're
2289 * doing. Pass %NULL for @window to get all events for all windows,
2290 * instead of events for a specific window.
2292 * See gdk_display_add_client_message_filter() if you are interested
2293 * in X ClientMessage events.
2296 gdk_window_add_filter (GdkWindow *window,
2297 GdkFilterFunc function,
2300 GdkWindowObject *private;
2302 GdkEventFilter *filter;
2304 g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
2306 private = (GdkWindowObject*) window;
2307 if (private && GDK_WINDOW_DESTROYED (window))
2310 /* Filters are for the native events on the native window, so
2311 ensure there is a native window. */
2313 gdk_window_ensure_native (window);
2316 tmp_list = private->filters;
2318 tmp_list = _gdk_default_filters;
2322 filter = (GdkEventFilter *)tmp_list->data;
2323 if ((filter->function == function) && (filter->data == data))
2325 tmp_list = tmp_list->next;
2328 filter = g_new (GdkEventFilter, 1);
2329 filter->function = function;
2330 filter->data = data;
2333 private->filters = g_list_append (private->filters, filter);
2335 _gdk_default_filters = g_list_append (_gdk_default_filters, filter);
2339 * gdk_window_remove_filter:
2340 * @window: a #GdkWindow
2341 * @function: previously-added filter function
2342 * @data: user data for previously-added filter function
2344 * Remove a filter previously added with gdk_window_add_filter().
2348 gdk_window_remove_filter (GdkWindow *window,
2349 GdkFilterFunc function,
2352 GdkWindowObject *private;
2353 GList *tmp_list, *node;
2354 GdkEventFilter *filter;
2356 g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
2358 private = (GdkWindowObject*) window;
2361 tmp_list = private->filters;
2363 tmp_list = _gdk_default_filters;
2367 filter = (GdkEventFilter *)tmp_list->data;
2369 tmp_list = tmp_list->next;
2371 if ((filter->function == function) && (filter->data == data))
2374 private->filters = g_list_remove_link (private->filters, node);
2376 _gdk_default_filters = g_list_remove_link (_gdk_default_filters, node);
2377 g_list_free_1 (node);
2386 * gdk_screen_get_toplevel_windows:
2387 * @screen: The #GdkScreen where the toplevels are located.
2389 * Obtains a list of all toplevel windows known to GDK on the screen @screen.
2390 * A toplevel window is a child of the root window (see
2391 * gdk_get_default_root_window()).
2393 * The returned list should be freed with g_list_free(), but
2394 * its elements need not be freed.
2396 * Return value: list of toplevel windows, free with g_list_free()
2401 gdk_screen_get_toplevel_windows (GdkScreen *screen)
2403 GdkWindow * root_window;
2404 GList *new_list = NULL;
2407 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
2409 root_window = gdk_screen_get_root_window (screen);
2411 tmp_list = ((GdkWindowObject *)root_window)->children;
2414 GdkWindowObject *w = tmp_list->data;
2416 if (w->window_type != GDK_WINDOW_FOREIGN)
2417 new_list = g_list_prepend (new_list, w);
2418 tmp_list = tmp_list->next;
2425 * gdk_window_get_toplevels:
2427 * Obtains a list of all toplevel windows known to GDK on the default
2428 * screen (see gdk_screen_get_toplevel_windows()).
2429 * A toplevel window is a child of the root window (see
2430 * gdk_get_default_root_window()).
2432 * The returned list should be freed with g_list_free(), but
2433 * its elements need not be freed.
2435 * Return value: list of toplevel windows, free with g_list_free()
2437 * Deprecated: 2.16: Use gdk_screen_get_toplevel_windows() instead.
2440 gdk_window_get_toplevels (void)
2442 return gdk_screen_get_toplevel_windows (gdk_screen_get_default ());
2446 * gdk_window_is_visible:
2447 * @window: a #GdkWindow
2449 * Checks whether the window has been mapped (with gdk_window_show() or
2450 * gdk_window_show_unraised()).
2452 * Return value: %TRUE if the window is mapped
2455 gdk_window_is_visible (GdkWindow *window)
2457 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2459 return GDK_WINDOW_IS_MAPPED (window);
2463 * gdk_window_is_viewable:
2464 * @window: a #GdkWindow
2466 * Check if the window and all ancestors of the window are
2467 * mapped. (This is not necessarily "viewable" in the X sense, since
2468 * we only check as far as we have GDK window parents, not to the root
2471 * Return value: %TRUE if the window is viewable
2474 gdk_window_is_viewable (GdkWindow *window)
2476 GdkWindowObject *private = (GdkWindowObject *)window;
2478 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2480 if (private->destroyed)
2483 return private->viewable;
2487 * gdk_window_get_state:
2488 * @window: a #GdkWindow
2490 * Gets the bitwise OR of the currently active window state flags,
2491 * from the #GdkWindowState enumeration.
2493 * Return value: window state bitfield
2496 gdk_window_get_state (GdkWindow *window)
2498 GdkWindowObject *private = (GdkWindowObject *)window;
2500 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2502 return private->state;
2506 /* This creates an empty "implicit" paint region for the impl window.
2507 * By itself this does nothing, but real paints to this window
2508 * or children of it can use this pixmap as backing to avoid allocating
2509 * multiple pixmaps for subwindow rendering. When doing so they
2510 * add to the region of the implicit paint region, which will be
2511 * pushed to the window when the implicit paint region is ended.
2512 * Such paints should not copy anything to the window on paint end, but
2513 * should rely on the implicit paint end.
2514 * The implicit paint will be automatically ended if someone draws
2515 * directly to the window or a child window.
2518 gdk_window_begin_implicit_paint (GdkWindow *window, GdkRectangle *rect)
2520 GdkWindowObject *private = (GdkWindowObject *)window;
2521 GdkWindowPaint *paint;
2523 g_assert (gdk_window_has_impl (private));
2525 if (_gdk_native_windows)
2526 return FALSE; /* No need for implicit paints since we can't merge draws anyway */
2528 if (GDK_IS_PAINTABLE (private->impl))
2529 return FALSE; /* Implementation does double buffering */
2531 if (private->paint_stack != NULL ||
2532 private->implicit_paint != NULL)
2533 return FALSE; /* Don't stack implicit paints */
2535 paint = g_new (GdkWindowPaint, 1);
2536 paint->region = gdk_region_new (); /* Empty */
2537 paint->x_offset = rect->x;
2538 paint->y_offset = rect->y;
2539 paint->uses_implicit = FALSE;
2540 paint->flushed = FALSE;
2541 paint->surface = NULL;
2543 gdk_pixmap_new (window,
2544 MAX (rect->width, 1), MAX (rect->height, 1), -1);
2546 private->implicit_paint = paint;
2551 /* Ensure that all content related to this (sub)window is pushed to the
2552 native region. If there is an active paint then that area is not
2553 pushed, in order to not show partially finished double buffers. */
2555 gdk_window_flush_implicit_paint (GdkWindow *window)
2557 GdkWindowObject *private = (GdkWindowObject *)window;
2558 GdkWindowObject *impl_window;
2559 GdkWindowPaint *paint;
2564 impl_window = gdk_window_get_impl_window (private);
2565 if (impl_window->implicit_paint == NULL)
2568 paint = impl_window->implicit_paint;
2569 paint->flushed = TRUE;
2570 region = gdk_region_copy (private->clip_region_with_children);
2572 /* Don't flush active double buffers, as that may show partially done
2574 for (list = private->paint_stack; list != NULL; list = list->next)
2576 GdkWindowPaint *tmp_paint = list->data;
2578 gdk_region_subtract (region, tmp_paint->region);
2581 gdk_region_offset (region, private->abs_x, private->abs_y);
2582 gdk_region_intersect (region, paint->region);
2584 if (!gdk_region_empty (region))
2586 /* Remove flushed region from the implicit paint */
2587 gdk_region_subtract (paint->region, region);
2589 /* Some regions are valid, push these to window now */
2590 tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
2591 _gdk_gc_set_clip_region_internal (tmp_gc, region, TRUE);
2592 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2593 0, 0, paint->x_offset, paint->y_offset, -1, -1);
2594 /* Reset clip region of the cached GdkGC */
2595 gdk_gc_set_clip_region (tmp_gc, NULL);
2598 gdk_region_destroy (region);
2601 /* Ends an implicit paint, paired with gdk_window_begin_implicit_paint returning TRUE */
2603 gdk_window_end_implicit_paint (GdkWindow *window)
2605 GdkWindowObject *private = (GdkWindowObject *)window;
2606 GdkWindowPaint *paint;
2609 g_assert (gdk_window_has_impl (private));
2611 g_assert (private->implicit_paint != NULL);
2613 paint = private->implicit_paint;
2615 private->implicit_paint = NULL;
2617 if (!gdk_region_empty (paint->region))
2619 /* Some regions are valid, push these to window now */
2620 tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
2621 _gdk_gc_set_clip_region_internal (tmp_gc, paint->region, TRUE);
2622 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2623 0, 0, paint->x_offset, paint->y_offset, -1, -1);
2624 /* Reset clip region of the cached GdkGC */
2625 gdk_gc_set_clip_region (tmp_gc, NULL);
2628 gdk_region_destroy (paint->region);
2630 g_object_unref (paint->pixmap);
2635 * gdk_window_begin_paint_rect:
2636 * @window: a #GdkWindow
2637 * @rectangle: rectangle you intend to draw to
2639 * A convenience wrapper around gdk_window_begin_paint_region() which
2640 * creates a rectangular region for you. See
2641 * gdk_window_begin_paint_region() for details.
2645 gdk_window_begin_paint_rect (GdkWindow *window,
2646 const GdkRectangle *rectangle)
2650 g_return_if_fail (GDK_IS_WINDOW (window));
2652 region = gdk_region_rectangle (rectangle);
2653 gdk_window_begin_paint_region (window, region);
2654 gdk_region_destroy (region);
2658 * gdk_window_begin_paint_region:
2659 * @window: a #GdkWindow
2660 * @region: region you intend to draw to
2662 * Indicates that you are beginning the process of redrawing @region.
2663 * A backing store (offscreen buffer) large enough to contain @region
2664 * will be created. The backing store will be initialized with the
2665 * background color or background pixmap for @window. Then, all
2666 * drawing operations performed on @window will be diverted to the
2667 * backing store. When you call gdk_window_end_paint(), the backing
2668 * store will be copied to @window, making it visible onscreen. Only
2669 * the part of @window contained in @region will be modified; that is,
2670 * drawing operations are clipped to @region.
2672 * The net result of all this is to remove flicker, because the user
2673 * sees the finished product appear all at once when you call
2674 * gdk_window_end_paint(). If you draw to @window directly without
2675 * calling gdk_window_begin_paint_region(), the user may see flicker
2676 * as individual drawing operations are performed in sequence. The
2677 * clipping and background-initializing features of
2678 * gdk_window_begin_paint_region() are conveniences for the
2679 * programmer, so you can avoid doing that work yourself.
2681 * When using GTK+, the widget system automatically places calls to
2682 * gdk_window_begin_paint_region() and gdk_window_end_paint() around
2683 * emissions of the expose_event signal. That is, if you're writing an
2684 * expose event handler, you can assume that the exposed area in
2685 * #GdkEventExpose has already been cleared to the window background,
2686 * is already set as the clip region, and already has a backing store.
2687 * Therefore in most cases, application code need not call
2688 * gdk_window_begin_paint_region(). (You can disable the automatic
2689 * calls around expose events on a widget-by-widget basis by calling
2690 * gtk_widget_set_double_buffered().)
2692 * If you call this function multiple times before calling the
2693 * matching gdk_window_end_paint(), the backing stores are pushed onto
2694 * a stack. gdk_window_end_paint() copies the topmost backing store
2695 * onscreen, subtracts the topmost region from all other regions in
2696 * the stack, and pops the stack. All drawing operations affect only
2697 * the topmost backing store in the stack. One matching call to
2698 * gdk_window_end_paint() is required for each call to
2699 * gdk_window_begin_paint_region().
2703 gdk_window_begin_paint_region (GdkWindow *window,
2704 const GdkRegion *region)
2706 #ifdef USE_BACKING_STORE
2707 GdkWindowObject *private = (GdkWindowObject *)window;
2708 GdkRectangle clip_box;
2709 GdkWindowPaint *paint, *implicit_paint;
2710 GdkWindowObject *impl_window;
2713 g_return_if_fail (GDK_IS_WINDOW (window));
2715 if (GDK_WINDOW_DESTROYED (window))
2718 if (GDK_IS_PAINTABLE (private->impl))
2720 GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
2722 if (iface->begin_paint_region)
2723 iface->begin_paint_region ((GdkPaintable*)private->impl, window, region);
2728 impl_window = gdk_window_get_impl_window (private);
2729 implicit_paint = impl_window->implicit_paint;
2731 paint = g_new (GdkWindowPaint, 1);
2732 paint->region = gdk_region_copy (region);
2733 paint->region_tag = new_region_tag ();
2735 gdk_region_intersect (paint->region, private->clip_region_with_children);
2736 gdk_region_get_clipbox (paint->region, &clip_box);
2738 /* Convert to impl coords */
2739 gdk_region_offset (paint->region, private->abs_x, private->abs_y);
2741 /* Mark the region as valid on the implicit paint */
2744 gdk_region_union (implicit_paint->region, paint->region);
2746 /* Convert back to normal coords */
2747 gdk_region_offset (paint->region, -private->abs_x, -private->abs_y);
2753 paint->uses_implicit = TRUE;
2754 paint->pixmap = g_object_ref (implicit_paint->pixmap);
2755 paint->x_offset = -private->abs_x + implicit_paint->x_offset;
2756 paint->y_offset = -private->abs_y + implicit_paint->y_offset;
2758 gdk_drawable_get_size (paint->pixmap, &width, &height);
2759 paint->surface = _gdk_drawable_create_cairo_surface (paint->pixmap, width, height);
2763 paint->uses_implicit = FALSE;
2764 paint->x_offset = clip_box.x;
2765 paint->y_offset = clip_box.y;
2767 gdk_pixmap_new (window,
2768 MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1);
2769 paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap);
2773 cairo_surface_set_device_offset (paint->surface,
2774 -paint->x_offset, -paint->y_offset);
2776 for (list = private->paint_stack; list != NULL; list = list->next)
2778 GdkWindowPaint *tmp_paint = list->data;
2780 gdk_region_subtract (tmp_paint->region, paint->region);
2783 private->paint_stack = g_slist_prepend (private->paint_stack, paint);
2785 if (!gdk_region_empty (paint->region))
2787 gdk_window_clear_backing_region (window,
2791 #endif /* USE_BACKING_STORE */
2795 setup_redirect_clip (GdkWindow *window,
2800 GdkWindowObject *private = (GdkWindowObject *)window;
2801 GdkRegion *visible_region;
2802 GdkRectangle dest_rect;
2804 GdkWindow *toplevel;
2805 int x_offset, y_offset;
2807 toplevel = GDK_WINDOW (private->redirect->redirected);
2809 /* Get the clip region for gc clip rect + window hierarchy in
2810 window relative coords */
2812 _gdk_window_calculate_full_clip_region (window, toplevel,
2817 /* Compensate for the source pos/size */
2818 x_offset -= private->redirect->src_x;
2819 y_offset -= private->redirect->src_y;
2820 dest_rect.x = -x_offset;
2821 dest_rect.y = -y_offset;
2822 dest_rect.width = private->redirect->width;
2823 dest_rect.height = private->redirect->height;
2824 tmpreg = gdk_region_rectangle (&dest_rect);
2825 gdk_region_intersect (visible_region, tmpreg);
2826 gdk_region_destroy (tmpreg);
2828 /* Compensate for the dest pos */
2829 x_offset += private->redirect->dest_x;
2830 y_offset += private->redirect->dest_y;
2832 gdk_gc_set_clip_region (gc, visible_region); /* This resets clip origin! */
2834 /* offset clip and tiles from window coords to pixmaps coords */
2835 gdk_gc_offset (gc, -x_offset, -y_offset);
2837 gdk_region_destroy (visible_region);
2839 *x_offset_out = x_offset;
2840 *y_offset_out = y_offset;
2844 * gdk_window_end_paint:
2845 * @window: a #GdkWindow
2847 * Indicates that the backing store created by the most recent call to
2848 * gdk_window_begin_paint_region() should be copied onscreen and
2849 * deleted, leaving the next-most-recent backing store or no backing
2850 * store at all as the active paint region. See
2851 * gdk_window_begin_paint_region() for full details. It is an error to
2852 * call this function without a matching
2853 * gdk_window_begin_paint_region() first.
2857 gdk_window_end_paint (GdkWindow *window)
2859 #ifdef USE_BACKING_STORE
2860 GdkWindowObject *private = (GdkWindowObject *)window;
2861 GdkWindowObject *composited;
2862 GdkWindowPaint *paint;
2864 GdkRectangle clip_box;
2865 gint x_offset, y_offset;
2866 GdkRegion *full_clip;
2868 g_return_if_fail (GDK_IS_WINDOW (window));
2870 if (GDK_WINDOW_DESTROYED (window))
2873 if (GDK_IS_PAINTABLE (private->impl))
2875 GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
2877 if (iface->end_paint)
2878 iface->end_paint ((GdkPaintable*)private->impl);
2882 if (private->paint_stack == NULL)
2884 g_warning (G_STRLOC": no preceding call to gdk_window_begin_paint_region(), see documentation");
2888 paint = private->paint_stack->data;
2890 private->paint_stack = g_slist_delete_link (private->paint_stack,
2891 private->paint_stack);
2893 gdk_region_get_clipbox (paint->region, &clip_box);
2895 tmp_gc = _gdk_drawable_get_scratch_gc (window, FALSE);
2897 x_offset = -private->abs_x;
2898 y_offset = -private->abs_y;
2900 if (!paint->uses_implicit)
2902 gdk_window_flush_outstanding_moves (window);
2904 full_clip = gdk_region_copy (private->clip_region_with_children);
2905 gdk_region_intersect (full_clip, paint->region);
2906 _gdk_gc_set_clip_region_internal (tmp_gc, full_clip, TRUE); /* Takes ownership of full_clip */
2907 gdk_gc_set_clip_origin (tmp_gc, - x_offset, - y_offset);
2908 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2909 clip_box.x - paint->x_offset,
2910 clip_box.y - paint->y_offset,
2911 clip_box.x - x_offset, clip_box.y - y_offset,
2912 clip_box.width, clip_box.height);
2915 if (private->redirect)
2917 int x_offset, y_offset;
2919 /* TODO: Should also use paint->region for clipping */
2920 setup_redirect_clip (window, tmp_gc, &x_offset, &y_offset);
2921 gdk_draw_drawable (private->redirect->pixmap, tmp_gc, paint->pixmap,
2922 clip_box.x - paint->x_offset,
2923 clip_box.y - paint->y_offset,
2924 clip_box.x + x_offset,
2925 clip_box.y + y_offset,
2926 clip_box.width, clip_box.height);
2929 /* Reset clip region of the cached GdkGC */
2930 gdk_gc_set_clip_region (tmp_gc, NULL);
2932 cairo_surface_destroy (paint->surface);
2933 g_object_unref (paint->pixmap);
2934 gdk_region_destroy (paint->region);
2937 /* find a composited window in our hierarchy to signal its
2938 * parent to redraw, calculating the clip box as we go...
2940 * stop if parent becomes NULL since then we'd have nowhere
2941 * to draw (ie: 'composited' will always be non-NULL here).
2943 for (composited = private;
2945 composited = composited->parent)
2949 gdk_drawable_get_size (GDK_DRAWABLE (composited->parent),
2952 clip_box.x += composited->x;
2953 clip_box.y += composited->y;
2954 clip_box.width = MIN (clip_box.width, width - clip_box.x);
2955 clip_box.height = MIN (clip_box.height, height - clip_box.y);
2957 if (composited->composited)
2959 gdk_window_invalidate_rect (GDK_WINDOW (composited->parent),
2964 #endif /* USE_BACKING_STORE */
2968 gdk_window_free_paint_stack (GdkWindow *window)
2970 GdkWindowObject *private = (GdkWindowObject *)window;
2972 if (private->paint_stack)
2974 GSList *tmp_list = private->paint_stack;
2978 GdkWindowPaint *paint = tmp_list->data;
2980 if (tmp_list == private->paint_stack)
2981 g_object_unref (paint->pixmap);
2983 gdk_region_destroy (paint->region);
2986 tmp_list = tmp_list->next;
2989 g_slist_free (private->paint_stack);
2990 private->paint_stack = NULL;
2995 do_move_region_bits_on_impl (GdkWindowObject *impl_window,
2996 GdkRegion *dest_region, /* In impl window coords */
3000 GdkRectangle copy_rect;
3001 GdkWindowObject *private;
3002 GdkWindowImplIface *impl_iface;
3004 /* We need to get data from subwindows here, because we might have
3005 * shaped a native window over the moving region (with bg none,
3006 * so the pixels are still there). In fact we might need to get data
3007 * from overlapping native window that are not children of this window,
3008 * so we copy from the toplevel with INCLUDE_INFERIORS.
3010 private = impl_window;
3011 while (!gdk_window_is_toplevel (private))
3013 dx -= private->parent->abs_x + private->x;
3014 dy -= private->parent->abs_y + private->y;
3015 private = gdk_window_get_impl_window (private->parent);
3017 tmp_gc = _gdk_drawable_get_subwindow_scratch_gc ((GdkWindow *)private);
3019 gdk_region_get_clipbox (dest_region, ©_rect);
3020 gdk_gc_set_clip_region (tmp_gc, dest_region);
3022 /* The region area is moved and we queue translations for all expose events
3023 to the source area that were sent prior to the copy */
3024 gdk_region_offset (dest_region, -dx, -dy); /* Move to source region */
3025 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
3027 impl_iface->queue_translation ((GdkWindow *)impl_window,
3029 dest_region, dx, dy);
3031 gdk_draw_drawable (impl_window->impl,
3034 copy_rect.x-dx, copy_rect.y-dy,
3035 copy_rect.x, copy_rect.y,
3036 copy_rect.width, copy_rect.height);
3037 gdk_gc_set_clip_region (tmp_gc, NULL);
3040 static GdkWindowRegionMove *
3041 gdk_window_region_move_new (GdkRegion *region,
3044 GdkWindowRegionMove *move;
3046 move = g_slice_new (GdkWindowRegionMove);
3047 move->dest_region = gdk_region_copy (region);
3055 gdk_window_region_move_free (GdkWindowRegionMove *move)
3057 gdk_region_destroy (move->dest_region);
3058 g_slice_free (GdkWindowRegionMove, move);
3062 append_move_region (GdkWindowObject *impl_window,
3063 GdkRegion *new_dest_region,
3066 GdkWindowRegionMove *move, *old_move;
3067 GdkRegion *new_total_region, *old_total_region;
3068 GdkRegion *source_overlaps_destination;
3069 GdkRegion *non_overwritten;
3070 gboolean added_move;
3073 if (gdk_region_empty (new_dest_region))
3076 /* In principle this could just append the move to the list of outstanding
3077 moves that will be replayed before drawing anything when we're handling
3078 exposes. However, we'd like to do a bit better since its commonly the case
3079 that we get multiple copies where A is copied to B and then B is copied
3080 to C, and we'd like to express this as a simple copy A to C operation. */
3082 /* We approach this by taking the new move and pushing it ahead of moves
3083 starting at the end of the list and stopping when its not safe to do so.
3084 It's not safe to push past a move if either the source of the new move
3085 is in the destination of the old move, or if the destination of the new
3086 move is in the source of the new move, or if the destination of the new
3087 move overlaps the destination of the old move. We simplify this by
3088 just comparing the total regions (src + dest) */
3089 new_total_region = gdk_region_copy (new_dest_region);
3090 gdk_region_offset (new_total_region, -dx, -dy);
3091 gdk_region_union (new_total_region, new_dest_region);
3094 for (l = g_list_last (impl_window->outstanding_moves); l != NULL; l = prev)
3099 old_total_region = gdk_region_copy (old_move->dest_region);
3100 gdk_region_offset (old_total_region, -old_move->dx, -old_move->dy);
3101 gdk_region_union (old_total_region, old_move->dest_region);
3103 gdk_region_intersect (old_total_region, new_total_region);
3104 /* If these regions intersect then its not safe to push the
3105 new region before the old one */
3106 if (!gdk_region_empty (old_total_region))
3108 /* The area where the new moves source overlaps the old ones
3110 source_overlaps_destination = gdk_region_copy (new_dest_region);
3111 gdk_region_offset (source_overlaps_destination, -dx, -dy);
3112 gdk_region_intersect (source_overlaps_destination, old_move->dest_region);
3113 gdk_region_offset (source_overlaps_destination, dx, dy);
3115 /* We can do all sort of optimizations here, but to do things safely it becomes
3116 quite complicated. However, a very common case is that you copy something first,
3117 then copy all that or a subset of it to a new location (i.e. if you scroll twice
3118 in the same direction). We'd like to detect this case and optimize it to one
3120 if (gdk_region_equal (source_overlaps_destination, new_dest_region))
3122 /* This means we might be able to replace the old move and the new one
3123 with the new one read from the old ones source, and a second copy of
3124 the non-overwritten parts of the old move. However, such a split
3125 is only valid if the source in the old move isn't overwritten
3126 by the destination of the new one */
3128 /* the new destination of old move if split is ok: */
3129 non_overwritten = gdk_region_copy (old_move->dest_region);
3130 gdk_region_subtract (non_overwritten, new_dest_region);
3131 /* move to source region */
3132 gdk_region_offset (non_overwritten, -old_move->dx, -old_move->dy);
3134 gdk_region_intersect (non_overwritten, new_dest_region);
3135 if (gdk_region_empty (non_overwritten))
3138 move = gdk_window_region_move_new (new_dest_region,
3142 impl_window->outstanding_moves =
3143 g_list_insert_before (impl_window->outstanding_moves,
3145 gdk_region_subtract (old_move->dest_region, new_dest_region);
3147 gdk_region_destroy (non_overwritten);
3150 gdk_region_destroy (source_overlaps_destination);
3151 gdk_region_destroy (old_total_region);
3154 gdk_region_destroy (old_total_region);
3157 gdk_region_destroy (new_total_region);
3161 move = gdk_window_region_move_new (new_dest_region, dx, dy);
3164 impl_window->outstanding_moves =
3165 g_list_prepend (impl_window->outstanding_moves,
3168 impl_window->outstanding_moves =
3169 g_list_insert_before (impl_window->outstanding_moves,
3174 /* Moves bits and update area by dx/dy in impl window.
3175 Takes ownership of region to avoid copy (because we may change it) */
3177 move_region_on_impl (GdkWindowObject *impl_window,
3178 GdkRegion *region, /* In impl window coords */
3181 if ((dx == 0 && dy == 0) ||
3182 gdk_region_empty (region))
3184 gdk_region_destroy (region);
3188 g_assert (impl_window == gdk_window_get_impl_window (impl_window));
3190 /* Move any old invalid regions in the copy source area by dx/dy */
3191 if (impl_window->update_area)
3193 GdkRegion *update_area;
3195 update_area = gdk_region_copy (region);
3197 /* Convert from target to source */
3198 gdk_region_offset (update_area, -dx, -dy);
3199 gdk_region_intersect (update_area, impl_window->update_area);
3200 /* We only copy the area, so keep the old update area invalid.
3201 It would be safe to remove it too, as code that uses
3202 move_region_on_impl generally also invalidate the source
3203 area. However, it would just use waste cycles. */
3206 gdk_region_offset (update_area, dx, dy);
3207 gdk_region_union (impl_window->update_area, update_area);
3209 /* This area of the destination is now invalid,
3210 so no need to copy to it. */
3211 gdk_region_subtract (region, update_area);
3213 gdk_region_destroy (update_area);
3216 /* If we're currently exposing this window, don't copy to this
3217 destination, as it will be overdrawn when the expose is done,
3218 instead invalidate it and repaint later. */
3219 if (impl_window->implicit_paint)
3221 GdkWindowPaint *implicit_paint = impl_window->implicit_paint;
3222 GdkRegion *exposing;
3224 exposing = gdk_region_copy (implicit_paint->region);
3225 gdk_region_intersect (exposing, region);
3226 gdk_region_subtract (region, exposing);
3228 impl_window_add_update_area (impl_window, exposing);
3229 gdk_region_destroy (exposing);
3232 if (1) /* Enable flicker free handling of moves. */
3233 append_move_region (impl_window, region, dx, dy);
3235 do_move_region_bits_on_impl (impl_window,
3238 gdk_region_destroy (region);
3241 /* Flushes all outstanding changes to the window, call this
3242 * before drawing directly to the window (i.e. outside a begin/end_paint pair).
3245 gdk_window_flush_outstanding_moves (GdkWindow *window)
3247 GdkWindowObject *private;
3248 GdkWindowObject *impl_window;
3250 GdkWindowRegionMove *move;
3252 private = (GdkWindowObject *) window;
3254 impl_window = gdk_window_get_impl_window (private);
3256 for (l = impl_window->outstanding_moves; l != NULL; l = l->next)
3260 do_move_region_bits_on_impl (impl_window,
3261 move->dest_region, move->dx, move->dy);
3263 gdk_window_region_move_free (move);
3266 g_list_free (impl_window->outstanding_moves);
3267 impl_window->outstanding_moves = NULL;
3272 * @window: a #GdkWindow
3274 * Flush all outstanding cached operations on a window, leaving the
3275 * window in a state which reflects all that has been drawn before.
3277 * Gdk uses multiple kinds of caching to get better performance and
3278 * nicer drawing. For instance, during exposes all paints to a window
3279 * using double buffered rendering are keep on a pixmap until the last
3280 * window has been exposed. It also delays window moves/scrolls until
3281 * as long as possible until next update to avoid tearing when moving
3284 * Normally this should be completely invisible to applications, as
3285 * we automatically flush the windows when required, but this might
3286 * be needed if you for instance mix direct native drawing with
3287 * gdk drawing. For Gtk widgets that don't use double buffering this
3288 * will be called automatically before sending the expose event.
3293 gdk_window_flush (GdkWindow *window)
3295 gdk_window_flush_outstanding_moves (window);
3296 gdk_window_flush_implicit_paint (window);
3299 /* If we're about to move/resize or otherwise change the
3300 * hierarchy of a client side window in an impl and we're
3301 * called from an expose event handler then we need to
3302 * flush any already painted parts of the implicit paint
3303 * that are not part of the current paint, as these may
3304 * be used when scrolling or may overdraw the changes
3305 * caused by the hierarchy change.
3308 gdk_window_flush_if_exposing (GdkWindow *window)
3310 GdkWindowObject *private;
3311 GdkWindowObject *impl_window;
3313 GdkWindowRegionMove *move;
3315 private = (GdkWindowObject *) window;
3316 impl_window = gdk_window_get_impl_window (private);
3318 /* If we're in an implicit paint (i.e. in an expose handler, flush
3319 all the already finished exposes to get things to an uptodate state. */
3320 if (impl_window->implicit_paint)
3321 gdk_window_flush (window);
3326 gdk_window_flush_recursive_helper (GdkWindowObject *window,
3329 GdkWindowObject *child;
3332 for (l = window->children; l != NULL; l = l->next)
3336 if (child->impl == impl)
3337 /* Same impl, ignore */
3338 gdk_window_flush_recursive_helper (child, impl);
3340 gdk_window_flush_recursive (child);
3345 gdk_window_flush_recursive (GdkWindowObject *window)
3347 gdk_window_flush ((GdkWindow *)window);
3348 gdk_window_flush_recursive_helper (window, window->impl);
3352 gdk_window_get_offsets (GdkWindow *window,
3356 GdkWindowObject *private = (GdkWindowObject *)window;
3358 if (private->paint_stack)
3360 GdkWindowPaint *paint = private->paint_stack->data;
3361 *x_offset = paint->x_offset;
3362 *y_offset = paint->y_offset;
3366 *x_offset = -private->abs_x;
3367 *y_offset = -private->abs_y;
3372 * gdk_window_get_internal_paint_info:
3373 * @window: a #GdkWindow
3374 * @real_drawable: location to store the drawable to which drawing should be
3376 * @x_offset: location to store the X offset between coordinates in @window,
3377 * and the underlying window system primitive coordinates for
3379 * @y_offset: location to store the Y offset between coordinates in @window,
3380 * and the underlying window system primitive coordinates for
3383 * If you bypass the GDK layer and use windowing system primitives to
3384 * draw directly onto a #GdkWindow, then you need to deal with two
3385 * details: there may be an offset between GDK coordinates and windowing
3386 * system coordinates, and GDK may have redirected drawing to a offscreen
3387 * pixmap as the result of a gdk_window_begin_paint_region() calls.
3388 * This function allows retrieving the information you need to compensate
3389 * for these effects.
3391 * This function exposes details of the GDK implementation, and is thus
3392 * likely to change in future releases of GDK.
3395 gdk_window_get_internal_paint_info (GdkWindow *window,
3396 GdkDrawable **real_drawable,
3402 GdkWindowObject *private;
3404 g_return_if_fail (GDK_IS_WINDOW (window));
3406 private = (GdkWindowObject *)window;
3410 if (private->paint_stack)
3412 GdkWindowPaint *paint = private->paint_stack->data;
3413 *real_drawable = paint->pixmap;
3417 /* This means you're probably gonna be doing some weird shit
3418 directly to the window, so we flush all outstanding stuff */
3419 gdk_window_flush (window);
3420 *real_drawable = window;
3424 gdk_window_get_offsets (window, &x_off, &y_off);
3432 static GdkDrawable *
3433 start_draw_helper (GdkDrawable *drawable,
3438 GdkWindowObject *private = (GdkWindowObject *)drawable;
3439 gint x_offset, y_offset;
3441 gint old_clip_x = gc->clip_x_origin;
3442 gint old_clip_y = gc->clip_y_origin;
3444 guint32 clip_region_tag;
3445 GdkWindowPaint *paint;
3448 if (private->paint_stack)
3449 paint = private->paint_stack->data;
3453 x_offset = paint->x_offset;
3454 y_offset = paint->y_offset;
3458 x_offset = -private->abs_x;
3459 y_offset = -private->abs_y;
3462 if (x_offset != 0 || y_offset != 0)
3464 gdk_gc_set_clip_origin (gc,
3465 old_clip_x - x_offset,
3466 old_clip_y - y_offset);
3467 gdk_gc_set_ts_origin (gc,
3468 gc->ts_x_origin - x_offset,
3469 gc->ts_y_origin - y_offset);
3472 *x_offset_out = x_offset;
3473 *y_offset_out = y_offset;
3475 /* Add client side window clip region to gc */
3479 /* Only need clipping if using implicit paint, otherwise
3480 the pixmap is clipped when copying to the window in end_paint */
3481 if (paint->uses_implicit)
3483 /* This includes the window clip */
3484 clip = paint->region;
3486 clip_region_tag = paint->region_tag;
3488 /* After having set up the drawable clip rect on a GC we need to make sure
3489 * that we draw to th the impl, otherwise the pixmap code will reset the
3491 impl = ((GdkPixmapObject *)(paint->pixmap))->impl;
3495 /* Drawing directly to the window, flush anything outstanding to
3496 guarantee ordering. */
3497 gdk_window_flush ((GdkWindow *)drawable);
3499 /* Don't clip when drawing to root or all native */
3500 if (!_gdk_native_windows && private->window_type != GDK_WINDOW_ROOT)
3502 if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
3503 clip = private->clip_region_with_children;
3505 clip = private->clip_region;
3507 clip_region_tag = private->clip_tag;
3508 impl = private->impl;
3512 _gdk_gc_add_drawable_clip (gc,
3513 clip_region_tag, clip,
3514 /* If there was a clip origin set appart from the
3515 * window offset, need to take that into
3517 -old_clip_x, -old_clip_y);
3522 #define BEGIN_DRAW \
3524 GdkDrawable *impl; \
3525 gint x_offset, y_offset; \
3526 gint old_clip_x = gc->clip_x_origin; \
3527 gint old_clip_y = gc->clip_y_origin; \
3528 gint old_ts_x = gc->ts_x_origin; \
3529 gint old_ts_y = gc->ts_y_origin; \
3530 impl = start_draw_helper (drawable, gc, \
3531 &x_offset, &y_offset);
3534 if (x_offset != 0 || y_offset != 0) \
3536 gdk_gc_set_clip_origin (gc, old_clip_x, old_clip_y); \
3537 gdk_gc_set_ts_origin (gc, old_ts_x, old_ts_y); \
3542 gdk_window_create_gc (GdkDrawable *drawable,
3543 GdkGCValues *values,
3544 GdkGCValuesMask mask)
3546 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
3548 if (GDK_WINDOW_DESTROYED (drawable))
3551 return gdk_gc_new_with_values (((GdkWindowObject *) drawable)->impl,
3556 gdk_window_draw_rectangle (GdkDrawable *drawable,
3564 if (GDK_WINDOW_DESTROYED (drawable))
3568 gdk_draw_rectangle (impl, gc, filled,
3569 x - x_offset, y - y_offset, width, height);
3574 gdk_window_draw_arc (GdkDrawable *drawable,
3584 if (GDK_WINDOW_DESTROYED (drawable))
3588 gdk_draw_arc (impl, gc, filled,
3589 x - x_offset, y - y_offset,
3590 width, height, angle1, angle2);
3595 gdk_window_draw_polygon (GdkDrawable *drawable,
3601 GdkPoint *new_points;
3603 if (GDK_WINDOW_DESTROYED (drawable))
3608 if (x_offset != 0 || y_offset != 0)
3612 new_points = g_new (GdkPoint, npoints);
3613 for (i=0; i<npoints; i++)
3615 new_points[i].x = points[i].x - x_offset;
3616 new_points[i].y = points[i].y - y_offset;
3620 new_points = points;
3622 gdk_draw_polygon (impl, gc, filled, new_points, npoints);
3624 if (new_points != points)
3625 g_free (new_points);
3631 gdk_window_draw_text (GdkDrawable *drawable,
3639 if (GDK_WINDOW_DESTROYED (drawable))
3643 gdk_draw_text (impl, font, gc,
3644 x - x_offset, y - y_offset, text, text_length);
3649 gdk_window_draw_text_wc (GdkDrawable *drawable,
3654 const GdkWChar *text,
3657 if (GDK_WINDOW_DESTROYED (drawable))
3661 gdk_draw_text_wc (impl, font, gc,
3662 x - x_offset, y - y_offset, text, text_length);
3666 static GdkDrawable *
3667 gdk_window_get_source_drawable (GdkDrawable *drawable)
3669 GdkWindow *window = GDK_WINDOW (drawable);
3670 GdkWindowObject *private;
3672 private = (GdkWindowObject *) window;
3673 if (GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable)
3674 return GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable (private->impl);
3679 static GdkDrawable *
3680 gdk_window_get_composite_drawable (GdkDrawable *drawable,
3685 gint *composite_x_offset,
3686 gint *composite_y_offset)
3688 GdkWindowObject *private = (GdkWindowObject *)drawable;
3690 GdkPixmap *tmp_pixmap;
3693 gboolean overlap_buffer;
3694 GdkDrawable *source;
3695 GdkWindowObject *impl_window;
3696 GdkWindowPaint *implicit_paint;
3698 *composite_x_offset = -private->abs_x;
3699 *composite_y_offset = -private->abs_y;
3701 if ((GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable)))
3702 return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
3704 /* See if any buffered part is overlapping the part we want
3710 rect.height = height;
3712 overlap_buffer = FALSE;
3714 for (list = private->paint_stack; list != NULL; list = list->next)
3716 GdkWindowPaint *paint = list->data;
3717 GdkOverlapType overlap;
3719 overlap = gdk_region_rect_in (paint->region, &rect);
3721 if (overlap == GDK_OVERLAP_RECTANGLE_IN)
3723 *composite_x_offset = paint->x_offset;
3724 *composite_y_offset = paint->y_offset;
3726 return g_object_ref (paint->pixmap);
3728 else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
3730 overlap_buffer = TRUE;
3735 impl_window = gdk_window_get_impl_window (private);
3736 implicit_paint = impl_window->implicit_paint;
3739 GdkOverlapType overlap;
3741 rect.x += private->abs_x;
3742 rect.y += private->abs_y;
3744 overlap = gdk_region_rect_in (implicit_paint->region, &rect);
3745 if (overlap == GDK_OVERLAP_RECTANGLE_IN)
3747 *composite_x_offset = -private->abs_x + implicit_paint->x_offset;
3748 *composite_y_offset = -private->abs_y + implicit_paint->y_offset;
3750 return g_object_ref (implicit_paint->pixmap);
3752 else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
3753 overlap_buffer = TRUE;
3756 if (!overlap_buffer)
3757 return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
3759 tmp_pixmap = gdk_pixmap_new (drawable, width, height, -1);
3760 tmp_gc = _gdk_drawable_get_scratch_gc (tmp_pixmap, FALSE);
3762 source = _gdk_drawable_get_source_drawable (drawable);
3764 /* Copy the current window contents */
3765 gdk_draw_drawable (tmp_pixmap,
3767 GDK_WINDOW_OBJECT (source)->impl,
3768 x - *composite_x_offset,
3769 y - *composite_y_offset,
3773 /* paint the backing stores */
3776 GdkWindowPaint *paint = list->data;
3778 gdk_gc_set_clip_region (tmp_gc, paint->region);
3779 gdk_gc_set_clip_origin (tmp_gc, -x - paint->x_offset, -y - paint->y_offset);
3781 gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
3782 x - paint->x_offset,
3783 y - paint->y_offset,
3784 0, 0, width, height);
3787 for (list = private->paint_stack; list != NULL; list = list->next)
3789 GdkWindowPaint *paint = list->data;
3791 if (paint->uses_implicit)
3792 continue; /* We already copied this above */
3794 gdk_gc_set_clip_region (tmp_gc, paint->region);
3795 gdk_gc_set_clip_origin (tmp_gc, -x, -y);
3797 gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
3798 x - paint->x_offset,
3799 y - paint->y_offset,
3800 0, 0, width, height);
3803 /* Reset clip region of the cached GdkGC */
3804 gdk_gc_set_clip_region (tmp_gc, NULL);
3806 /* Set these to location of tmp_pixmap within the window */
3807 *composite_x_offset = x;
3808 *composite_y_offset = y;
3814 gdk_window_get_clip_region (GdkDrawable *drawable)
3816 GdkWindowObject *private = (GdkWindowObject *)drawable;
3819 result = gdk_region_copy (private->clip_region);
3821 if (private->paint_stack)
3823 GdkRegion *paint_region = gdk_region_new ();
3824 GSList *tmp_list = private->paint_stack;
3828 GdkWindowPaint *paint = tmp_list->data;
3830 gdk_region_union (paint_region, paint->region);
3832 tmp_list = tmp_list->next;
3835 gdk_region_intersect (result, paint_region);
3836 gdk_region_destroy (paint_region);
3843 gdk_window_get_visible_region (GdkDrawable *drawable)
3845 GdkWindowObject *private = (GdkWindowObject*) drawable;
3847 return gdk_region_copy (private->clip_region);
3851 gdk_window_draw_drawable (GdkDrawable *drawable,
3860 GdkDrawable *original_src)
3862 GdkWindowObject *private = (GdkWindowObject *)drawable;
3864 if (GDK_WINDOW_DESTROYED (drawable))
3869 /* Call the method directly to avoid getting the composite drawable again */
3870 GDK_DRAWABLE_GET_CLASS (impl)->draw_drawable_with_src (impl, gc,
3878 if (!private->paint_stack)
3880 /* We might have drawn from an obscured part of a client
3881 side window, if so we need to send graphics exposures */
3882 if (_gdk_gc_get_exposures (gc) &&
3883 GDK_IS_WINDOW (original_src))
3885 GdkRegion *exposure_region;
3893 exposure_region = gdk_region_rectangle (&r);
3895 if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
3896 clip = private->clip_region_with_children;
3898 clip = private->clip_region;
3899 gdk_region_intersect (exposure_region, clip);
3901 _gdk_gc_remove_drawable_clip (gc);
3902 clip = _gdk_gc_get_clip_region (gc);
3905 gdk_region_offset (exposure_region,
3908 gdk_region_intersect (exposure_region, clip);
3909 gdk_region_offset (exposure_region,
3914 /* Note: We don't clip by the clip mask if set, so this
3915 may invalidate to much */
3917 /* Remove the area that is correctly copied from the src.
3918 * Note that xsrc/ysrc has been corrected for abs_x/y offsets already,
3919 * which need to be undone */
3920 clip = gdk_drawable_get_visible_region (original_src);
3921 gdk_region_offset (clip,
3922 xdest - (xsrc - GDK_WINDOW_OBJECT (original_src)->abs_x),
3923 ydest - (ysrc - GDK_WINDOW_OBJECT (original_src)->abs_y));
3924 gdk_region_subtract (exposure_region, clip);
3925 gdk_region_destroy (clip);
3927 gdk_window_invalidate_region (GDK_WINDOW (private),
3929 _gdk_gc_get_subwindow (gc) == GDK_INCLUDE_INFERIORS);
3931 gdk_region_destroy (exposure_region);
3939 gdk_window_draw_points (GdkDrawable *drawable,
3944 GdkPoint *new_points;
3946 if (GDK_WINDOW_DESTROYED (drawable))
3951 if (x_offset != 0 || y_offset != 0)
3955 new_points = g_new (GdkPoint, npoints);
3956 for (i=0; i<npoints; i++)
3958 new_points[i].x = points[i].x - x_offset;
3959 new_points[i].y = points[i].y - y_offset;
3963 new_points = points;
3965 gdk_draw_points (impl, gc, new_points, npoints);
3967 if (new_points != points)
3968 g_free (new_points);
3974 gdk_window_draw_segments (GdkDrawable *drawable,
3979 GdkSegment *new_segs;
3981 if (GDK_WINDOW_DESTROYED (drawable))
3986 if (x_offset != 0 || y_offset != 0)
3990 new_segs = g_new (GdkSegment, nsegs);
3991 for (i=0; i<nsegs; i++)
3993 new_segs[i].x1 = segs[i].x1 - x_offset;
3994 new_segs[i].y1 = segs[i].y1 - y_offset;
3995 new_segs[i].x2 = segs[i].x2 - x_offset;
3996 new_segs[i].y2 = segs[i].y2 - y_offset;
4002 gdk_draw_segments (impl, gc, new_segs, nsegs);
4004 if (new_segs != segs)
4011 gdk_window_draw_lines (GdkDrawable *drawable,
4016 GdkPoint *new_points;
4018 if (GDK_WINDOW_DESTROYED (drawable))
4023 if (x_offset != 0 || y_offset != 0)
4027 new_points = g_new (GdkPoint, npoints);
4028 for (i=0; i<npoints; i++)
4030 new_points[i].x = points[i].x - x_offset;
4031 new_points[i].y = points[i].y - y_offset;
4035 new_points = points;
4037 gdk_draw_lines (impl, gc, new_points, npoints);
4039 if (new_points != points)
4040 g_free (new_points);
4046 gdk_window_draw_glyphs (GdkDrawable *drawable,
4051 PangoGlyphString *glyphs)
4053 if (GDK_WINDOW_DESTROYED (drawable))
4057 gdk_draw_glyphs (impl, gc, font,
4058 x - x_offset, y - y_offset, glyphs);
4063 gdk_window_draw_glyphs_transformed (GdkDrawable *drawable,
4065 PangoMatrix *matrix,
4069 PangoGlyphString *glyphs)
4071 PangoMatrix tmp_matrix;
4073 if (GDK_WINDOW_DESTROYED (drawable))
4078 if (x_offset != 0 || y_offset != 0)
4082 tmp_matrix = *matrix;
4083 tmp_matrix.x0 -= x_offset;
4084 tmp_matrix.y0 -= y_offset;
4085 matrix = &tmp_matrix;
4087 else if (GDK_PANGO_UNITS_OVERFLOWS (x_offset, y_offset))
4089 PangoMatrix identity = PANGO_MATRIX_INIT;
4091 tmp_matrix = identity;
4092 tmp_matrix.x0 -= x_offset;
4093 tmp_matrix.y0 -= y_offset;
4094 matrix = &tmp_matrix;
4098 x -= x_offset * PANGO_SCALE;
4099 y -= y_offset * PANGO_SCALE;
4103 gdk_draw_glyphs_transformed (impl, gc, matrix, font, x, y, glyphs);
4109 cairo_t *cr; /* if non-null, it means use this cairo context */
4110 GdkGC *gc; /* if non-null, it means use this GC instead */
4111 } BackingRectMethod;
4114 setup_backing_rect_method (BackingRectMethod *method, GdkWindow *window, GdkWindowPaint *paint, int x_offset_cairo, int y_offset_cairo)
4116 GdkWindowObject *private = (GdkWindowObject *)window;
4118 if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
4120 GdkWindowPaint tmp_paint;
4123 tmp_paint.x_offset += private->x;
4124 tmp_paint.y_offset += private->y;
4126 x_offset_cairo += private->x;
4127 y_offset_cairo += private->y;
4129 setup_backing_rect_method (method, GDK_WINDOW (private->parent), &tmp_paint, x_offset_cairo, y_offset_cairo);
4131 else if (private->bg_pixmap &&
4132 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
4133 private->bg_pixmap != GDK_NO_BG)
4135 /* This is a workaround for https://bugs.freedesktop.org/show_bug.cgi?id=4320.
4136 * In it, using a pixmap as a repeating pattern in Cairo, and painting it to a
4137 * pixmap destination surface, can be very slow (on the order of seconds for a
4138 * whole-screen copy). The workaround is to use pretty much the same code that
4139 * we used in GTK+ 2.6 (pre-Cairo), which clears the double-buffer pixmap with
4140 * a tiled GC XFillRectangle().
4143 /* Actually computing this flag is left as an exercise for the reader */
4144 #if defined (G_OS_UNIX)
4145 # define GDK_CAIRO_REPEAT_IS_FAST 0
4147 # define GDK_CAIRO_REPEAT_IS_FAST 1
4150 #if GDK_CAIRO_REPEAT_IS_FAST
4151 cairo_surface_t *surface = _gdk_drawable_ref_cairo_surface (private->bg_pixmap);
4152 cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
4153 cairo_surface_destroy (surface);
4155 if (x_offset_cairo != 0 || y_offset_cairo != 0)
4157 cairo_matrix_t matrix;
4158 cairo_matrix_init_translate (&matrix, x_offset_cairo, y_offset_cairo);
4159 cairo_pattern_set_matrix (pattern, &matrix);
4162 cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
4164 method->cr = cairo_create (paint->surface);
4167 cairo_set_source (method->cr, pattern);
4168 cairo_pattern_destroy (pattern);
4171 GdkGCValues gc_values;
4173 gc_values.fill = GDK_TILED;
4174 gc_values.tile = private->bg_pixmap;
4175 gc_values.ts_x_origin = -x_offset_cairo;
4176 gc_values.ts_y_origin = -y_offset_cairo;
4178 gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN;
4180 method->gc = gdk_gc_new_with_values (paint->pixmap, &gc_values, gc_mask);
4185 method->cr = cairo_create (paint->surface);
4187 gdk_cairo_set_source_color (method->cr, &private->bg_color);
4192 gdk_window_clear_backing_region (GdkWindow *window,
4195 GdkWindowObject *private = (GdkWindowObject *)window;
4196 GdkWindowPaint *paint = private->paint_stack->data;
4197 BackingRectMethod method;
4199 GdkRectangle clipbox;
4205 if (GDK_WINDOW_DESTROYED (window))
4209 timer = g_timer_new ();
4214 setup_backing_rect_method (&method, window, paint, 0, 0);
4216 clip = gdk_region_copy (paint->region);
4217 gdk_region_intersect (clip, region);
4218 gdk_region_get_clipbox (clip, &clipbox);
4223 g_assert (method.gc == NULL);
4225 gdk_cairo_region (method.cr, clip);
4226 cairo_fill (method.cr);
4228 cairo_destroy (method.cr);
4230 elapsed = g_timer_elapsed (timer, NULL);
4231 g_print ("Draw the background with Cairo: %fs\n", elapsed);
4236 g_assert (method.gc != NULL);
4238 gdk_gc_set_clip_region (method.gc, clip);
4239 gdk_draw_rectangle (window, method.gc, TRUE,
4240 clipbox.x, clipbox.y,
4241 clipbox.width, clipbox.height);
4242 g_object_unref (method.gc);
4245 elapsed = g_timer_elapsed (timer, NULL);
4246 g_print ("Draw the background with GDK: %fs\n", elapsed);
4250 gdk_region_destroy (clip);
4253 g_timer_destroy (timer);
4258 gdk_window_clear_backing_region_redirect (GdkWindow *window,
4261 GdkWindowObject *private = (GdkWindowObject *)window;
4262 GdkWindowRedirect *redirect = private->redirect;
4263 GdkRegion *clip_region;
4264 GdkRectangle clipbox;
4265 gint x_offset, y_offset;
4266 BackingRectMethod method;
4267 GdkWindowPaint paint;
4269 if (GDK_WINDOW_DESTROYED (window))
4272 clip_region = _gdk_window_calculate_full_clip_region (window,
4273 GDK_WINDOW (redirect->redirected),
4275 &x_offset, &y_offset);
4276 gdk_region_intersect (clip_region, region);
4278 /* offset is from redirected window origin to window origin, convert to
4279 the offset from the redirected pixmap origin to the window origin */
4280 x_offset += redirect->dest_x - redirect->src_x;
4281 y_offset += redirect->dest_y - redirect->src_y;
4283 /* Convert region to pixmap coords */
4284 gdk_region_offset (clip_region, x_offset, y_offset);
4288 paint.pixmap = redirect->pixmap;
4289 paint.surface = _gdk_drawable_ref_cairo_surface (redirect->pixmap);
4293 setup_backing_rect_method (&method, window, &paint, -x_offset, -y_offset);
4297 g_assert (method.gc == NULL);
4299 gdk_cairo_region (method.cr, clip_region);
4300 cairo_fill (method.cr);
4302 cairo_destroy (method.cr);
4306 g_assert (method.gc != NULL);
4308 gdk_region_get_clipbox (clip_region, &clipbox);
4309 gdk_gc_set_clip_region (method.gc, clip_region);
4310 gdk_draw_rectangle (redirect->pixmap, method.gc, TRUE,
4311 clipbox.x, clipbox.y,
4312 clipbox.width, clipbox.height);
4313 g_object_unref (method.gc);
4317 gdk_region_destroy (clip_region);
4318 cairo_surface_destroy (paint.surface);
4322 gdk_window_clear_backing_region_direct (GdkWindow *window,
4325 GdkWindowObject *private = (GdkWindowObject *)window;
4326 BackingRectMethod method;
4327 GdkWindowPaint paint;
4329 GdkRectangle clipbox;
4331 if (GDK_WINDOW_DESTROYED (window))
4336 paint.pixmap = window;
4337 paint.surface = _gdk_drawable_ref_cairo_surface (window);
4341 setup_backing_rect_method (&method, window, &paint, 0, 0);
4343 clip = gdk_region_copy (private->clip_region_with_children);
4344 gdk_region_intersect (clip, region);
4345 gdk_region_get_clipbox (clip, &clipbox);
4349 g_assert (method.gc == NULL);
4351 gdk_cairo_region (method.cr, clip);
4352 cairo_fill (method.cr);
4354 cairo_destroy (method.cr);
4358 g_assert (method.gc != NULL);
4360 gdk_gc_set_clip_region (method.gc, clip);
4361 gdk_draw_rectangle (window, method.gc, TRUE,
4362 clipbox.x, clipbox.y,
4363 clipbox.width, clipbox.height);
4364 g_object_unref (method.gc);
4368 gdk_region_destroy (clip);
4369 cairo_surface_destroy (paint.surface);
4375 * @window: a #GdkWindow
4377 * Clears an entire @window to the background color or background pixmap.
4380 gdk_window_clear (GdkWindow *window)
4384 g_return_if_fail (GDK_IS_WINDOW (window));
4386 gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height);
4388 gdk_window_clear_area (window, 0, 0,
4393 clears_on_native (GdkWindowObject *private)
4395 GdkWindowObject *next;
4401 if (gdk_window_has_impl (private))
4403 next = private->parent;
4405 while (private->bg_pixmap == GDK_PARENT_RELATIVE_BG &&
4406 next && next->window_type != GDK_WINDOW_ROOT);
4411 gdk_window_clear_region_internal (GdkWindow *window,
4413 gboolean send_expose)
4415 GdkWindowObject *private = (GdkWindowObject *)window;
4416 GdkWindowImplIface *impl_iface;
4418 if (private->paint_stack)
4419 gdk_window_clear_backing_region (window, region);
4422 if (private->redirect)
4423 gdk_window_clear_backing_region_redirect (window, region);
4425 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
4427 if (impl_iface->clear_region && clears_on_native (private))
4430 copy = gdk_region_copy (region);
4431 gdk_region_intersect (copy,
4432 private->clip_region_with_children);
4434 impl_iface->clear_region (window, copy, send_expose);
4436 gdk_region_destroy (copy);
4440 gdk_window_clear_backing_region_direct (window, region);
4442 gdk_window_invalidate_region (window, region, FALSE);
4448 gdk_window_clear_area_internal (GdkWindow *window,
4453 gboolean send_expose)
4458 g_return_if_fail (GDK_IS_WINDOW (window));
4460 if (GDK_WINDOW_DESTROYED (window))
4463 /* Terminate early to avoid weird interpretation of
4464 zero width/height by XClearArea */
4465 if (width == 0 || height == 0)
4471 rect.height = height;
4473 region = gdk_region_rectangle (&rect);
4474 gdk_window_clear_region_internal (window,
4477 gdk_region_destroy (region);
4482 * gdk_window_clear_area:
4483 * @window: a #GdkWindow
4484 * @x: x coordinate of rectangle to clear
4485 * @y: y coordinate of rectangle to clear
4486 * @width: width of rectangle to clear
4487 * @height: height of rectangle to clear
4489 * Clears an area of @window to the background color or background pixmap.
4493 gdk_window_clear_area (GdkWindow *window,
4499 gdk_window_clear_area_internal (window,
4506 * gdk_window_clear_area_e:
4507 * @window: a #GdkWindow
4508 * @x: x coordinate of rectangle to clear
4509 * @y: y coordinate of rectangle to clear
4510 * @width: width of rectangle to clear
4511 * @height: height of rectangle to clear
4513 * Like gdk_window_clear_area(), but also generates an expose event for
4516 * This function has a stupid name because it dates back to the mists
4517 * time, pre-GDK-1.0.
4521 gdk_window_clear_area_e (GdkWindow *window,
4527 gdk_window_clear_area_internal (window,
4534 gdk_window_draw_image (GdkDrawable *drawable,
4544 if (GDK_WINDOW_DESTROYED (drawable))
4548 gdk_draw_image (impl, gc, image, xsrc, ysrc,
4549 xdest - x_offset, ydest - y_offset,
4555 gdk_window_draw_pixbuf (GdkDrawable *drawable,
4564 GdkRgbDither dither,
4568 GdkWindowObject *private = (GdkWindowObject *)drawable;
4569 GdkDrawableClass *klass;
4571 if (GDK_WINDOW_DESTROYED (drawable))
4574 /* If no gc => no user clipping, but we need clipping
4575 for window emulation, so use a scratch gc */
4577 gc = _gdk_drawable_get_scratch_gc (drawable, FALSE);
4581 klass = GDK_DRAWABLE_GET_CLASS (impl);
4583 if (private->paint_stack)
4584 klass->draw_pixbuf (impl, gc, pixbuf, src_x, src_y,
4585 dest_x - x_offset, dest_y - y_offset,
4587 dither, x_dither - x_offset, y_dither - y_offset);
4589 klass->draw_pixbuf (impl, gc, pixbuf, src_x, src_y,
4590 dest_x - x_offset, dest_y - y_offset,
4592 dither, x_dither, y_dither);
4597 gdk_window_draw_trapezoids (GdkDrawable *drawable,
4599 GdkTrapezoid *trapezoids,
4602 GdkTrapezoid *new_trapezoids = NULL;
4604 if (GDK_WINDOW_DESTROYED (drawable))
4609 if (x_offset != 0 || y_offset != 0)
4613 new_trapezoids = g_new (GdkTrapezoid, n_trapezoids);
4614 for (i=0; i < n_trapezoids; i++)
4616 new_trapezoids[i].y1 = trapezoids[i].y1 - y_offset;
4617 new_trapezoids[i].x11 = trapezoids[i].x11 - x_offset;
4618 new_trapezoids[i].x21 = trapezoids[i].x21 - x_offset;
4619 new_trapezoids[i].y2 = trapezoids[i].y2 - y_offset;
4620 new_trapezoids[i].x12 = trapezoids[i].x12 - x_offset;
4621 new_trapezoids[i].x22 = trapezoids[i].x22 - x_offset;
4624 trapezoids = new_trapezoids;
4627 gdk_draw_trapezoids (impl, gc, trapezoids, n_trapezoids);
4629 g_free (new_trapezoids);
4635 gdk_window_real_get_size (GdkDrawable *drawable,
4639 GdkWindowObject *private = (GdkWindowObject *)drawable;
4642 *width = private->width;
4644 *height = private->height;
4648 gdk_window_real_get_visual (GdkDrawable *drawable)
4650 GdkColormap *colormap;
4652 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4654 colormap = gdk_drawable_get_colormap (drawable);
4655 return colormap ? gdk_colormap_get_visual (colormap) : NULL;
4659 gdk_window_real_get_depth (GdkDrawable *drawable)
4661 g_return_val_if_fail (GDK_IS_WINDOW (drawable), 0);
4663 return ((GdkWindowObject *)GDK_WINDOW (drawable))->depth;
4667 gdk_window_real_get_screen (GdkDrawable *drawable)
4669 return gdk_drawable_get_screen (GDK_WINDOW_OBJECT (drawable)->impl);
4673 gdk_window_real_set_colormap (GdkDrawable *drawable,
4676 GdkWindowObject *private;
4678 g_return_if_fail (GDK_IS_WINDOW (drawable));
4680 if (GDK_WINDOW_DESTROYED (drawable))
4683 private = (GdkWindowObject *)drawable;
4685 /* different colormap than parent, requires native window */
4686 if (!private->input_only &&
4687 cmap != gdk_drawable_get_colormap ((GdkDrawable *)(private->parent)))
4688 gdk_window_ensure_native ((GdkWindow *)drawable);
4690 gdk_drawable_set_colormap (private->impl, cmap);
4694 gdk_window_real_get_colormap (GdkDrawable *drawable)
4696 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4698 if (GDK_WINDOW_DESTROYED (drawable))
4701 return gdk_drawable_get_colormap (((GdkWindowObject*)drawable)->impl);
4705 gdk_window_copy_to_image (GdkDrawable *drawable,
4714 GdkWindowObject *private = (GdkWindowObject *) drawable;
4715 gint x_offset, y_offset;
4717 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4719 if (GDK_WINDOW_DESTROYED (drawable))
4722 /* If we're here, a composite image was not necessary, so
4723 * we can ignore the paint stack.
4726 /* TODO: Is this right? */
4730 return gdk_drawable_copy_to_image (private->impl,
4739 gdk_window_cairo_surface_destroy (void *data)
4741 GdkWindowObject *private = (GdkWindowObject*) data;
4743 private->cairo_surface = NULL;
4746 static cairo_surface_t *
4747 gdk_window_create_cairo_surface (GdkDrawable *drawable,
4751 return _gdk_windowing_create_cairo_surface (GDK_WINDOW_OBJECT(drawable)->impl,
4756 static cairo_surface_t *
4757 gdk_window_ref_cairo_surface (GdkDrawable *drawable)
4759 GdkWindowObject *private = (GdkWindowObject*) drawable;
4760 cairo_surface_t *surface;
4762 if (private->paint_stack)
4764 GdkWindowPaint *paint = private->paint_stack->data;
4766 surface = paint->surface;
4767 cairo_surface_reference (surface);
4772 /* This will be drawing directly to the window, so flush implicit paint */
4773 gdk_window_flush ((GdkWindow *)drawable);
4775 if (!private->cairo_surface)
4778 GdkDrawable *source;
4780 /* It would be nice if we had some cairo support here so we
4781 could set the clip rect on the cairo surface */
4782 width = private->abs_x + private->width;
4783 height = private->abs_y + private->height;
4785 source = _gdk_drawable_get_source_drawable (drawable);
4787 /* TODO: Avoid the typecheck crap by adding virtual call */
4788 private->cairo_surface = _gdk_drawable_create_cairo_surface (source, width, height);
4790 if (private->cairo_surface)
4792 cairo_surface_set_device_offset (private->cairo_surface,
4796 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
4797 drawable, gdk_window_cairo_surface_destroy);
4801 cairo_surface_reference (private->cairo_surface);
4803 surface = private->cairo_surface;
4810 gdk_window_set_cairo_clip (GdkDrawable *drawable,
4813 GdkWindowObject *private = (GdkWindowObject*) drawable;
4815 if (!private->paint_stack)
4817 cairo_reset_clip (cr);
4820 cairo_identity_matrix (cr);
4822 cairo_new_path (cr);
4823 gdk_cairo_region (cr, private->clip_region_with_children);
4830 GdkWindowPaint *paint = private->paint_stack->data;
4832 /* Only needs to clip to region if piggybacking
4833 on an implicit paint pixmap */
4834 cairo_reset_clip (cr);
4835 if (paint->uses_implicit)
4838 cairo_identity_matrix (cr);
4840 cairo_new_path (cr);
4841 gdk_cairo_region (cr, paint->region);
4849 /* Code for dirty-region queueing
4851 static GSList *update_windows = NULL;
4852 static guint update_idle = 0;
4853 static gboolean debug_updates = FALSE;
4855 static inline gboolean
4856 gdk_window_is_ancestor (GdkWindow *window,
4857 GdkWindow *ancestor)
4861 GdkWindow *parent = (GdkWindow*) ((GdkWindowObject*) window)->parent;
4863 if (parent == ancestor)
4873 gdk_window_add_update_window (GdkWindow *window)
4876 GSList *prev = NULL;
4877 gboolean has_ancestor_in_list = FALSE;
4879 for (tmp = update_windows; tmp; tmp = tmp->next)
4881 GdkWindowObject *parent = GDK_WINDOW_OBJECT (window)->parent;
4883 /* check if tmp is an ancestor of "window"; if it is, set a
4884 * flag indicating that all following windows are either
4885 * children of "window" or from a differen hierarchy
4887 if (!has_ancestor_in_list && gdk_window_is_ancestor (window, tmp->data))
4888 has_ancestor_in_list = TRUE;
4890 /* insert in reverse stacking order when adding around siblings,
4891 * so processing updates properly paints over lower stacked windows
4893 if (parent == GDK_WINDOW_OBJECT (tmp->data)->parent)
4895 gint index = g_list_index (parent->children, window);
4896 for (; tmp && parent == GDK_WINDOW_OBJECT (tmp->data)->parent; tmp = tmp->next)
4898 gint sibling_index = g_list_index (parent->children, tmp->data);
4899 if (index > sibling_index)
4903 /* here, tmp got advanced past all lower stacked siblings */
4904 tmp = g_slist_prepend (tmp, window);
4908 update_windows = tmp;
4912 /* if "window" has an ancestor in the list and tmp is one of
4913 * "window's" children, insert "window" before tmp
4915 if (has_ancestor_in_list && gdk_window_is_ancestor (tmp->data, window))
4917 tmp = g_slist_prepend (tmp, window);
4922 update_windows = tmp;
4926 /* if we're at the end of the list and had an ancestor it it,
4927 * append to the list
4929 if (! tmp->next && has_ancestor_in_list)
4931 tmp = g_slist_append (tmp, window);
4938 /* if all above checks failed ("window" is from a different
4939 * hierarchy than what is already in the list) or the list is
4942 update_windows = g_slist_prepend (update_windows, window);
4946 gdk_window_remove_update_window (GdkWindow *window)
4948 update_windows = g_slist_remove (update_windows, window);
4952 gdk_window_update_idle (gpointer data)
4954 gdk_window_process_all_updates ();
4960 gdk_window_is_toplevel_frozen (GdkWindow *window)
4962 GdkWindowObject *toplevel;
4964 toplevel = (GdkWindowObject *)gdk_window_get_toplevel (window);
4966 return toplevel->update_and_descendants_freeze_count > 0;
4970 gdk_window_schedule_update (GdkWindow *window)
4973 (GDK_WINDOW_OBJECT (window)->update_freeze_count ||
4974 gdk_window_is_toplevel_frozen (window)))
4979 gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
4980 gdk_window_update_idle,
4985 _gdk_window_process_updates_recurse (GdkWindow *window,
4986 GdkRegion *expose_region)
4988 GdkWindowObject *private = (GdkWindowObject *)window;
4989 GdkWindowObject *child;
4990 GdkRegion *child_region;
4992 GList *l, *children;
4994 if (gdk_region_empty (expose_region))
4997 /* Make this reentrancy safe for expose handlers freeing windows */
4998 children = g_list_copy (private->children);
4999 g_list_foreach (children, (GFunc)g_object_ref, NULL);
5001 /* Iterate over children, starting at topmost */
5002 for (l = children; l != NULL; l = l->next)
5006 if (child->destroyed || !GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
5009 /* Ignore offscreen children, as they don't draw in their parent and
5010 * don't take part in the clipping */
5011 if (gdk_window_is_offscreen (child))
5016 r.width = child->width;
5017 r.height = child->height;
5019 child_region = gdk_region_rectangle (&r);
5022 /* Adjust shape region to parent window coords */
5023 gdk_region_offset (child->shape, child->x, child->y);
5024 gdk_region_intersect (child_region, child->shape);
5025 gdk_region_offset (child->shape, -child->x, -child->y);
5028 if (child->impl == private->impl)
5030 /* Client side child, expose */
5031 gdk_region_intersect (child_region, expose_region);
5032 gdk_region_subtract (expose_region, child_region);
5033 gdk_region_offset (child_region, -child->x, -child->y);
5034 _gdk_window_process_updates_recurse ((GdkWindow *)child, child_region);
5038 /* Native child, just remove area from expose region */
5039 gdk_region_subtract (expose_region, child_region);
5041 gdk_region_destroy (child_region);
5044 g_list_foreach (children, (GFunc)g_object_unref, NULL);
5045 g_list_free (children);
5047 if (!gdk_region_empty (expose_region) &&
5048 !private->destroyed)
5050 if (private->event_mask & GDK_EXPOSURE_MASK)
5054 event.expose.type = GDK_EXPOSE;
5055 event.expose.window = g_object_ref (window);
5056 event.expose.send_event = FALSE;
5057 event.expose.count = 0;
5058 event.expose.region = expose_region;
5059 gdk_region_get_clipbox (expose_region, &event.expose.area);
5061 (*_gdk_event_func) (&event, _gdk_event_data);
5063 g_object_unref (window);
5065 else if (private->bg_pixmap != GDK_NO_BG &&
5066 private->window_type != GDK_WINDOW_FOREIGN)
5068 /* No exposure mask set, so nothing will be drawn, the
5069 * app relies on the background being what it specified
5070 * for the window. So, we need to clear this manually.
5072 * For foreign windows if expose is not set that generally
5073 * means some other client paints them, so don't clear
5076 * We use begin/end_paint around the clear so that we can
5077 * piggyback on the implicit paint */
5079 gdk_window_begin_paint_region (window, expose_region);
5080 gdk_window_clear_region_internal (window, expose_region, FALSE);
5081 gdk_window_end_paint (window);
5086 /* Process and remove any invalid area on the native window by creating
5087 * expose events for the window and all non-native descendants.
5088 * Also processes any outstanding moves on the window before doing
5089 * any drawing. Note that its possible to have outstanding moves without
5090 * any invalid area as we use the update idle mechanism to coalesce
5091 * multiple moves as well as multiple invalidations.
5094 gdk_window_process_updates_internal (GdkWindow *window)
5096 GdkWindowObject *private = (GdkWindowObject *)window;
5097 GdkWindowImplIface *impl_iface;
5098 gboolean save_region = FALSE;
5099 GdkRectangle clip_box;
5101 /* Ensure the window lives while updating it */
5102 g_object_ref (window);
5104 /* If an update got queued during update processing, we can get a
5105 * window in the update queue that has an empty update_area.
5108 if (private->update_area)
5110 GdkRegion *update_area = private->update_area;
5111 private->update_area = NULL;
5113 if (_gdk_event_func && gdk_window_is_viewable (window))
5115 GdkRegion *expose_region;
5116 gboolean end_implicit;
5118 /* Clip to part visible in toplevel */
5119 gdk_region_intersect (update_area, private->clip_region);
5123 /* Make sure we see the red invalid area before redrawing. */
5124 gdk_display_sync (gdk_drawable_get_display (window));
5128 /* At this point we will be completely redrawing all of update_area.
5129 * If we have any outstanding moves that end up moving stuff inside
5130 * this area we don't actually need to move that as that part would
5131 * be overdrawn by the expose anyway. So, in order to copy less data
5132 * we remove these areas from the outstanding moves.
5134 if (private->outstanding_moves)
5136 GdkWindowRegionMove *move;
5140 remove = gdk_region_copy (update_area);
5141 /* We iterate backwards, starting from the state that would be
5142 if we had applied all the moves. */
5143 for (l = g_list_last (private->outstanding_moves); l != NULL; l = prev)
5148 /* Don't need this area */
5149 gdk_region_subtract (move->dest_region, remove);
5151 /* However if any of the destination we do need has a source
5152 in the updated region we do need that as a destination for
5153 the earlier moves */
5154 gdk_region_offset (move->dest_region, -move->dx, -move->dy);
5155 gdk_region_subtract (remove, move->dest_region);
5157 if (gdk_region_empty (move->dest_region))
5159 gdk_window_region_move_free (move);
5160 private->outstanding_moves =
5161 g_list_delete_link (private->outstanding_moves, l);
5163 else /* move back */
5164 gdk_region_offset (move->dest_region, move->dx, move->dy);
5166 gdk_region_destroy (remove);
5169 /* By now we a set of window moves that should be applied, and then
5170 * an update region that should be repainted. A trivial implementation
5171 * would just do that in order, however in order to get nicer drawing
5172 * we do some tricks:
5174 * First of all, each subwindow expose may be double buffered by
5175 * itself (depending on widget setting) via
5176 * gdk_window_begin/end_paint(). But we also do an "implicit" paint,
5177 * creating a single pixmap the size of the invalid area on the
5178 * native window which all the individual normal paints will draw
5179 * into. This way in the normal case there will be only one pixmap
5180 * allocated and only once pixmap draw done for all the windows
5181 * in this native window.
5182 * There are a couple of reasons this may fail, for instance, some
5183 * backends (like quartz) do its own double buffering, so we disable
5184 * gdk double buffering there. Secondly, some subwindow could be
5185 * non-double buffered and draw directly to the window outside a
5186 * begin/end_paint pair. That will be lead to a gdk_window_flush
5187 * which immediately executes all outstanding moves and paints+removes
5188 * the implicit paint (further paints will allocate their own pixmap).
5190 * Secondly, in the case of implicit double buffering we expose all
5191 * the child windows into the implicit pixmap before we execute
5192 * the outstanding moves. This way we minimize the time between
5193 * doing the moves and rendering the new update area, thus minimizing
5194 * flashing. Of course, if any subwindow is non-double buffered we
5195 * well flush earlier than that.
5197 * Thirdly, after having done the outstanding moves we queue an
5198 * "antiexpose" on the area that will be drawn by the expose, which
5199 * means that any invalid region on the native window side before
5200 * the first expose drawing operation will be discarded, as it
5201 * has by then been overdrawn with valid data. This means we can
5202 * avoid doing the unnecessary repaint any outstanding expose events.
5205 gdk_region_get_clipbox (update_area, &clip_box);
5206 end_implicit = gdk_window_begin_implicit_paint (window, &clip_box);
5207 expose_region = gdk_region_copy (update_area);
5210 /* Rendering is not double buffered by gdk, do outstanding
5211 * moves and queue antiexposure immediately. No need to do
5213 gdk_window_flush_outstanding_moves (window);
5214 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
5215 save_region = impl_iface->queue_antiexpose (window, update_area);
5218 /* Render the invalid areas to the implicit paint, by sending exposes.
5219 * May flush if non-double buffered widget draw. */
5220 _gdk_windowing_window_process_updates_recurse (window, expose_region);
5224 /* Do moves right before exposes are rendered to the window */
5225 gdk_window_flush_outstanding_moves (window);
5227 /* By this time we know that any outstanding expose for this
5228 * area is invalid and we can avoid it, so queue an antiexpose.
5229 * However, it may be that due to an non-double buffered expose
5230 * we have already started drawing to the window, so it would
5231 * be to late to anti-expose now. Since this is merely an
5232 * optimization we just avoid doing it at all in that case.
5234 if (private->implicit_paint != NULL &&
5235 !private->implicit_paint->flushed)
5237 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
5238 save_region = impl_iface->queue_antiexpose (window, update_area);
5241 gdk_window_end_implicit_paint (window);
5243 gdk_region_destroy (expose_region);
5246 gdk_region_destroy (update_area);
5249 if (private->outstanding_moves)
5251 /* Flush any outstanding moves, may happen if we moved a window but got
5252 no actual invalid area */
5253 gdk_window_flush_outstanding_moves (window);
5256 g_object_unref (window);
5260 flush_all_displays (void)
5262 GSList *displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
5265 for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
5266 gdk_display_flush (tmp_list->data);
5268 g_slist_free (displays);
5271 /* Currently it is not possible to override
5272 * gdk_window_process_all_updates in the same manner as
5273 * gdk_window_process_updates and gdk_window_invalidate_maybe_recurse
5274 * by implementing the GdkPaintable interface. If in the future a
5275 * backend would need this, the right solution would be to add a
5276 * method to GdkDisplay that can be optionally
5277 * NULL. gdk_window_process_all_updates can then walk the list of open
5278 * displays and call the mehod.
5282 * gdk_window_process_all_updates:
5284 * Calls gdk_window_process_updates() for all windows (see #GdkWindow)
5285 * in the application.
5289 gdk_window_process_all_updates (void)
5291 GSList *old_update_windows = update_windows;
5292 GSList *tmp_list = update_windows;
5293 static gboolean in_process_all_updates = FALSE;
5294 static gboolean got_recursive_update = FALSE;
5296 if (in_process_all_updates)
5298 /* We can't do this now since that would recurse, so
5299 delay it until after the recursion is done. */
5300 got_recursive_update = TRUE;
5305 in_process_all_updates = TRUE;
5306 got_recursive_update = FALSE;
5309 g_source_remove (update_idle);
5311 update_windows = NULL;
5314 _gdk_windowing_before_process_all_updates ();
5316 g_slist_foreach (old_update_windows, (GFunc)g_object_ref, NULL);
5320 GdkWindowObject *private = (GdkWindowObject *)tmp_list->data;
5322 if (!GDK_WINDOW_DESTROYED (tmp_list->data))
5324 if (private->update_freeze_count ||
5325 gdk_window_is_toplevel_frozen (tmp_list->data))
5326 gdk_window_add_update_window ((GdkWindow *) private);
5328 gdk_window_process_updates_internal (tmp_list->data);
5331 g_object_unref (tmp_list->data);
5332 tmp_list = tmp_list->next;
5335 g_slist_free (old_update_windows);
5337 flush_all_displays ();
5339 _gdk_windowing_after_process_all_updates ();
5341 in_process_all_updates = FALSE;
5343 /* If we ignored a recursive call, schedule a
5344 redraw now so that it eventually happens,
5345 otherwise we could miss an update if nothing
5346 else schedules an update. */
5347 if (got_recursive_update && !update_idle)
5349 gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
5350 gdk_window_update_idle,
5355 * gdk_window_process_updates:
5356 * @window: a #GdkWindow
5357 * @update_children: whether to also process updates for child windows
5359 * Sends one or more expose events to @window. The areas in each
5360 * expose event will cover the entire update area for the window (see
5361 * gdk_window_invalidate_region() for details). Normally GDK calls
5362 * gdk_window_process_all_updates() on your behalf, so there's no
5363 * need to call this function unless you want to force expose events
5364 * to be delivered immediately and synchronously (vs. the usual
5365 * case, where GDK delivers them in an idle handler). Occasionally
5366 * this is useful to produce nicer scrolling behavior, for example.
5370 gdk_window_process_updates (GdkWindow *window,
5371 gboolean update_children)
5373 GdkWindowObject *private = (GdkWindowObject *)window;
5374 GdkWindowObject *impl_window;
5376 g_return_if_fail (GDK_IS_WINDOW (window));
5378 if (GDK_WINDOW_DESTROYED (window))
5381 /* Make sure the window lives during the expose callouts */
5382 g_object_ref (window);
5384 impl_window = gdk_window_get_impl_window (private);
5385 if ((impl_window->update_area ||
5386 impl_window->outstanding_moves) &&
5387 !impl_window->update_freeze_count &&
5388 !gdk_window_is_toplevel_frozen (window) &&
5390 /* Don't recurse into process_updates_internal, we'll
5391 * do the update later when idle instead. */
5392 impl_window->implicit_paint == NULL)
5394 gdk_window_process_updates_internal ((GdkWindow *)impl_window);
5395 gdk_window_remove_update_window ((GdkWindow *)impl_window);
5398 if (update_children)
5400 /* process updates in reverse stacking order so composition or
5401 * painting over achieves the desired effect for offscreen windows
5403 GList *node, *children;
5405 children = g_list_copy (private->children);
5406 g_list_foreach (children, (GFunc)g_object_ref, NULL);
5408 for (node = g_list_last (children); node; node = node->prev)
5410 gdk_window_process_updates (node->data, TRUE);
5411 g_object_unref (node->data);
5414 g_list_free (children);
5417 g_object_unref (window);
5421 * gdk_window_invalidate_rect:
5422 * @window: a #GdkWindow
5423 * @rect: rectangle to invalidate or %NULL to invalidate the whole
5425 * @invalidate_children: whether to also invalidate child windows
5427 * A convenience wrapper around gdk_window_invalidate_region() which
5428 * invalidates a rectangular region. See
5429 * gdk_window_invalidate_region() for details.
5432 gdk_window_invalidate_rect (GdkWindow *window,
5433 const GdkRectangle *rect,
5434 gboolean invalidate_children)
5436 GdkRectangle window_rect;
5438 GdkWindowObject *private = (GdkWindowObject *)window;
5440 g_return_if_fail (GDK_IS_WINDOW (window));
5442 if (GDK_WINDOW_DESTROYED (window))
5445 if (private->input_only || !private->viewable)
5452 gdk_drawable_get_size (GDK_DRAWABLE (window),
5454 &window_rect.height);
5455 rect = &window_rect;
5458 region = gdk_region_rectangle (rect);
5459 gdk_window_invalidate_region (window, region, invalidate_children);
5460 gdk_region_destroy (region);
5464 draw_ugly_color (GdkWindow *window,
5465 const GdkRegion *region)
5467 /* Draw ugly color all over the newly-invalid region */
5468 GdkColor ugly_color = { 0, 50000, 10000, 10000 };
5470 GdkRectangle clipbox;
5472 ugly_gc = gdk_gc_new (window);
5473 gdk_gc_set_rgb_fg_color (ugly_gc, &ugly_color);
5474 gdk_gc_set_clip_region (ugly_gc, region);
5476 gdk_region_get_clipbox (region, &clipbox);
5478 gdk_draw_rectangle (window,
5481 clipbox.x, clipbox.y,
5482 clipbox.width, clipbox.height);
5484 g_object_unref (ugly_gc);
5488 impl_window_add_update_area (GdkWindowObject *impl_window,
5491 if (impl_window->update_area)
5492 gdk_region_union (impl_window->update_area, region);
5495 gdk_window_add_update_window ((GdkWindow *)impl_window);
5496 impl_window->update_area = gdk_region_copy (region);
5497 gdk_window_schedule_update ((GdkWindow *)impl_window);
5502 * gdk_window_invalidate_maybe_recurse:
5503 * @window: a #GdkWindow
5504 * @region: a #GdkRegion
5505 * @child_func: function to use to decide if to recurse to a child,
5506 * %NULL means never recurse.
5507 * @user_data: data passed to @child_func
5509 * Adds @region to the update area for @window. The update area is the
5510 * region that needs to be redrawn, or "dirty region." The call
5511 * gdk_window_process_updates() sends one or more expose events to the
5512 * window, which together cover the entire update area. An
5513 * application would normally redraw the contents of @window in
5514 * response to those expose events.
5516 * GDK will call gdk_window_process_all_updates() on your behalf
5517 * whenever your program returns to the main loop and becomes idle, so
5518 * normally there's no need to do that manually, you just need to
5519 * invalidate regions that you know should be redrawn.
5521 * The @child_func parameter controls whether the region of
5522 * each child window that intersects @region will also be invalidated.
5523 * Only children for which @child_func returns TRUE will have the area
5527 gdk_window_invalidate_maybe_recurse (GdkWindow *window,
5528 const GdkRegion *region,
5529 gboolean (*child_func) (GdkWindow *,
5533 GdkWindowObject *private = (GdkWindowObject *)window;
5534 GdkWindowObject *impl_window;
5535 GdkRegion *visible_region;
5538 g_return_if_fail (GDK_IS_WINDOW (window));
5540 if (GDK_WINDOW_DESTROYED (window))
5543 if (private->input_only ||
5544 !private->viewable ||
5545 gdk_region_empty (region) ||
5546 private->window_type == GDK_WINDOW_ROOT)
5549 visible_region = gdk_drawable_get_visible_region (window);
5550 gdk_region_intersect (visible_region, region);
5552 tmp_list = private->children;
5555 GdkWindowObject *child = tmp_list->data;
5557 if (!child->input_only)
5559 GdkRegion *child_region;
5560 GdkRectangle child_rect;
5562 child_rect.x = child->x;
5563 child_rect.y = child->y;
5564 child_rect.width = child->width;
5565 child_rect.height = child->height;
5566 child_region = gdk_region_rectangle (&child_rect);
5568 /* remove child area from the invalid area of the parent */
5569 if (GDK_WINDOW_IS_MAPPED (child) && !child->shaped &&
5570 !child->composited &&
5571 !gdk_window_is_offscreen (child))
5572 gdk_region_subtract (visible_region, child_region);
5574 if (child_func && (*child_func) ((GdkWindow *)child, user_data))
5576 GdkRegion *tmp = gdk_region_copy (region);
5578 gdk_region_offset (tmp, - child_rect.x, - child_rect.y);
5579 gdk_region_offset (child_region, - child_rect.x, - child_rect.y);
5580 gdk_region_intersect (child_region, tmp);
5582 gdk_window_invalidate_maybe_recurse ((GdkWindow *)child,
5583 child_region, child_func, user_data);
5585 gdk_region_destroy (tmp);
5588 gdk_region_destroy (child_region);
5591 tmp_list = tmp_list->next;
5594 impl_window = gdk_window_get_impl_window (private);
5596 if (!gdk_region_empty (visible_region) ||
5597 /* Even if we're not exposing anything, make sure we process
5598 idles for windows with outstanding moves */
5599 (impl_window->outstanding_moves != NULL &&
5600 impl_window->update_area == NULL))
5603 draw_ugly_color (window, region);
5605 /* Convert to impl coords */
5606 gdk_region_offset (visible_region, private->abs_x, private->abs_y);
5607 impl_window_add_update_area (impl_window, visible_region);
5610 gdk_region_destroy (visible_region);
5614 true_predicate (GdkWindow *window,
5621 * gdk_window_invalidate_region:
5622 * @window: a #GdkWindow
5623 * @region: a #GdkRegion
5624 * @invalidate_children: %TRUE to also invalidate child windows
5626 * Adds @region to the update area for @window. The update area is the
5627 * region that needs to be redrawn, or "dirty region." The call
5628 * gdk_window_process_updates() sends one or more expose events to the
5629 * window, which together cover the entire update area. An
5630 * application would normally redraw the contents of @window in
5631 * response to those expose events.
5633 * GDK will call gdk_window_process_all_updates() on your behalf
5634 * whenever your program returns to the main loop and becomes idle, so
5635 * normally there's no need to do that manually, you just need to
5636 * invalidate regions that you know should be redrawn.
5638 * The @invalidate_children parameter controls whether the region of
5639 * each child window that intersects @region will also be invalidated.
5640 * If %FALSE, then the update area for child windows will remain
5641 * unaffected. See gdk_window_invalidate_maybe_recurse if you need
5642 * fine grained control over which children are invalidated.
5645 gdk_window_invalidate_region (GdkWindow *window,
5646 const GdkRegion *region,
5647 gboolean invalidate_children)
5649 gdk_window_invalidate_maybe_recurse (window, region,
5650 invalidate_children ?
5651 true_predicate : (gboolean (*) (GdkWindow *, gpointer))NULL,
5656 * _gdk_window_invalidate_for_expose:
5657 * @window: a #GdkWindow
5658 * @region: a #GdkRegion
5660 * Adds @region to the update area for @window. The update area is the
5661 * region that needs to be redrawn, or "dirty region." The call
5662 * gdk_window_process_updates() sends one or more expose events to the
5663 * window, which together cover the entire update area. An
5664 * application would normally redraw the contents of @window in
5665 * response to those expose events.
5667 * GDK will call gdk_window_process_all_updates() on your behalf
5668 * whenever your program returns to the main loop and becomes idle, so
5669 * normally there's no need to do that manually, you just need to
5670 * invalidate regions that you know should be redrawn.
5672 * This version of invalidation is used when you recieve expose events
5673 * from the native window system. It exposes the native window, plus
5674 * any non-native child windows (but not native child windows, as those would
5675 * have gotten their own expose events).
5678 _gdk_window_invalidate_for_expose (GdkWindow *window,
5681 GdkWindowObject *private = (GdkWindowObject *) window;
5682 GdkWindowRegionMove *move;
5683 GdkRegion *move_region;
5686 /* Any invalidations comming from the windowing system will
5687 be in areas that may be moved by outstanding moves,
5688 so we need to modify the expose region correspondingly,
5689 otherwise we would expose in the wrong place, as the
5690 outstanding moves will be copied before we draw the
5692 for (l = private->outstanding_moves; l != NULL; l = l->next)
5696 /* covert to move source region */
5697 move_region = gdk_region_copy (move->dest_region);
5698 gdk_region_offset (move_region, -move->dx, -move->dy);
5700 /* Move area of region that intersects with move source
5701 by dx, dy of the move*/
5702 gdk_region_intersect (move_region, region);
5703 gdk_region_subtract (region, move_region);
5704 gdk_region_offset (move_region, move->dx, move->dy);
5705 gdk_region_union (region, move_region);
5707 gdk_region_destroy (move_region);
5710 gdk_window_invalidate_maybe_recurse (window, region,
5711 (gboolean (*) (GdkWindow *, gpointer))gdk_window_has_no_impl,
5717 * gdk_window_get_update_area:
5718 * @window: a #GdkWindow
5720 * Transfers ownership of the update area from @window to the caller
5721 * of the function. That is, after calling this function, @window will
5722 * no longer have an invalid/dirty region; the update area is removed
5723 * from @window and handed to you. If a window has no update area,
5724 * gdk_window_get_update_area() returns %NULL. You are responsible for
5725 * calling gdk_region_destroy() on the returned region if it's non-%NULL.
5727 * Return value: the update area for @window
5730 gdk_window_get_update_area (GdkWindow *window)
5732 GdkWindowObject *private = (GdkWindowObject *)window;
5733 GdkWindowObject *impl_window;
5734 GdkRegion *tmp_region;
5736 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
5738 impl_window = gdk_window_get_impl_window (private);
5740 if (impl_window->update_area)
5742 tmp_region = gdk_region_copy (private->clip_region_with_children);
5743 /* Convert to impl coords */
5744 gdk_region_offset (tmp_region, private->abs_x, private->abs_y);
5745 gdk_region_intersect (tmp_region, impl_window->update_area);
5747 if (gdk_region_empty (tmp_region))
5749 gdk_region_destroy (tmp_region);
5754 gdk_region_subtract (impl_window->update_area, tmp_region);
5756 if (gdk_region_empty (impl_window->update_area) &&
5757 impl_window->outstanding_moves == NULL)
5759 gdk_region_destroy (impl_window->update_area);
5760 impl_window->update_area = NULL;
5762 gdk_window_remove_update_window ((GdkWindow *)impl_window);
5765 /* Convert from impl coords */
5766 gdk_region_offset (tmp_region, -private->abs_x, -private->abs_y);
5776 * _gdk_window_clear_update_area:
5777 * @window: a #GdkWindow.
5779 * Internal function to clear the update area for a window. This
5780 * is called when the window is hidden or destroyed.
5783 _gdk_window_clear_update_area (GdkWindow *window)
5785 GdkWindowObject *private = (GdkWindowObject *)window;
5787 g_return_if_fail (GDK_IS_WINDOW (window));
5789 if (private->update_area)
5791 gdk_window_remove_update_window (window);
5793 gdk_region_destroy (private->update_area);
5794 private->update_area = NULL;
5799 * gdk_window_freeze_updates:
5800 * @window: a #GdkWindow
5802 * Temporarily freezes a window such that it won't receive expose
5803 * events. The window will begin receiving expose events again when
5804 * gdk_window_thaw_updates() is called. If gdk_window_freeze_updates()
5805 * has been called more than once, gdk_window_thaw_updates() must be called
5806 * an equal number of times to begin processing exposes.
5809 gdk_window_freeze_updates (GdkWindow *window)
5811 GdkWindowObject *private = (GdkWindowObject *)window;
5812 GdkWindowObject *impl_window;
5814 g_return_if_fail (GDK_IS_WINDOW (window));
5816 impl_window = gdk_window_get_impl_window (private);
5817 impl_window->update_freeze_count++;
5821 * gdk_window_thaw_updates:
5822 * @window: a #GdkWindow
5824 * Thaws a window frozen with gdk_window_freeze_updates().
5827 gdk_window_thaw_updates (GdkWindow *window)
5829 GdkWindowObject *private = (GdkWindowObject *)window;
5830 GdkWindowObject *impl_window;
5832 g_return_if_fail (GDK_IS_WINDOW (window));
5834 impl_window = gdk_window_get_impl_window (private);
5836 g_return_if_fail (impl_window->update_freeze_count > 0);
5838 if (--impl_window->update_freeze_count == 0)
5839 gdk_window_schedule_update (GDK_WINDOW (impl_window));
5843 * gdk_window_freeze_toplevel_updates_libgtk_only:
5844 * @window: a #GdkWindow
5846 * Temporarily freezes a window and all its descendants such that it won't
5847 * receive expose events. The window will begin receiving expose events
5848 * again when gdk_window_thaw_toplevel_updates_libgtk_only() is called. If
5849 * gdk_window_freeze_toplevel_updates_libgtk_only()
5850 * has been called more than once,
5851 * gdk_window_thaw_toplevel_updates_libgtk_only() must be called
5852 * an equal number of times to begin processing exposes.
5854 * This function is not part of the GDK public API and is only
5858 gdk_window_freeze_toplevel_updates_libgtk_only (GdkWindow *window)
5860 GdkWindowObject *private = (GdkWindowObject *)window;
5862 g_return_if_fail (GDK_IS_WINDOW (window));
5863 g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
5865 private->update_and_descendants_freeze_count++;
5869 * gdk_window_thaw_toplevel_updates_libgtk_only:
5870 * @window: a #GdkWindow
5872 * Thaws a window frozen with
5873 * gdk_window_freeze_toplevel_updates_libgtk_only().
5875 * This function is not part of the GDK public API and is only
5879 gdk_window_thaw_toplevel_updates_libgtk_only (GdkWindow *window)
5881 GdkWindowObject *private = (GdkWindowObject *)window;
5883 g_return_if_fail (GDK_IS_WINDOW (window));
5884 g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
5885 g_return_if_fail (private->update_and_descendants_freeze_count > 0);
5887 private->update_and_descendants_freeze_count--;
5889 gdk_window_schedule_update (window);
5893 * gdk_window_set_debug_updates:
5894 * @setting: %TRUE to turn on update debugging
5896 * With update debugging enabled, calls to
5897 * gdk_window_invalidate_region() clear the invalidated region of the
5898 * screen to a noticeable color, and GDK pauses for a short time
5899 * before sending exposes to windows during
5900 * gdk_window_process_updates(). The net effect is that you can see
5901 * the invalid region for each window and watch redraws as they
5902 * occur. This allows you to diagnose inefficiencies in your application.
5904 * In essence, because the GDK rendering model prevents all flicker,
5905 * if you are redrawing the same region 400 times you may never
5906 * notice, aside from noticing a speed problem. Enabling update
5907 * debugging causes GTK to flicker slowly and noticeably, so you can
5908 * see exactly what's being redrawn when, in what order.
5910 * The --gtk-debug=updates command line option passed to GTK+ programs
5911 * enables this debug option at application startup time. That's
5912 * usually more useful than calling gdk_window_set_debug_updates()
5913 * yourself, though you might want to use this function to enable
5914 * updates sometime after application startup time.
5918 gdk_window_set_debug_updates (gboolean setting)
5920 debug_updates = setting;
5924 * gdk_window_constrain_size:
5925 * @geometry: a #GdkGeometry structure
5926 * @flags: a mask indicating what portions of @geometry are set
5927 * @width: desired width of window
5928 * @height: desired height of the window
5929 * @new_width: location to store resulting width
5930 * @new_height: location to store resulting height
5932 * Constrains a desired width and height according to a
5933 * set of geometry hints (such as minimum and maximum size).
5936 gdk_window_constrain_size (GdkGeometry *geometry,
5943 /* This routine is partially borrowed from fvwm.
5945 * Copyright 1993, Robert Nation
5946 * You may use this code for any purpose, as long as the original
5947 * copyright remains in the source code and all documentation
5949 * which in turn borrows parts of the algorithm from uwm
5952 gint min_height = 0;
5953 gint base_width = 0;
5954 gint base_height = 0;
5957 gint max_width = G_MAXINT;
5958 gint max_height = G_MAXINT;
5960 #define FLOOR(value, base) ( ((gint) ((value) / (base))) * (base) )
5962 if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
5964 base_width = geometry->base_width;
5965 base_height = geometry->base_height;
5966 min_width = geometry->min_width;
5967 min_height = geometry->min_height;
5969 else if (flags & GDK_HINT_BASE_SIZE)
5971 base_width = geometry->base_width;
5972 base_height = geometry->base_height;
5973 min_width = geometry->base_width;
5974 min_height = geometry->base_height;
5976 else if (flags & GDK_HINT_MIN_SIZE)
5978 base_width = geometry->min_width;
5979 base_height = geometry->min_height;
5980 min_width = geometry->min_width;
5981 min_height = geometry->min_height;
5984 if (flags & GDK_HINT_MAX_SIZE)
5986 max_width = geometry->max_width ;
5987 max_height = geometry->max_height;
5990 if (flags & GDK_HINT_RESIZE_INC)
5992 xinc = MAX (xinc, geometry->width_inc);
5993 yinc = MAX (yinc, geometry->height_inc);
5996 /* clamp width and height to min and max values
5998 width = CLAMP (width, min_width, max_width);
5999 height = CLAMP (height, min_height, max_height);
6001 /* shrink to base + N * inc
6003 width = base_width + FLOOR (width - base_width, xinc);
6004 height = base_height + FLOOR (height - base_height, yinc);
6006 /* constrain aspect ratio, according to:
6009 * min_aspect <= -------- <= max_aspect
6013 if (flags & GDK_HINT_ASPECT &&
6014 geometry->min_aspect > 0 &&
6015 geometry->max_aspect > 0)
6019 if (geometry->min_aspect * height > width)
6021 delta = FLOOR (height - width / geometry->min_aspect, yinc);
6022 if (height - delta >= min_height)
6026 delta = FLOOR (height * geometry->min_aspect - width, xinc);
6027 if (width + delta <= max_width)
6032 if (geometry->max_aspect * height < width)
6034 delta = FLOOR (width - height * geometry->max_aspect, xinc);
6035 if (width - delta >= min_width)
6039 delta = FLOOR (width / geometry->max_aspect - height, yinc);
6040 if (height + delta <= max_height)
6049 *new_height = height;
6053 * gdk_window_get_pointer:
6054 * @window: a #GdkWindow
6055 * @x: return location for X coordinate of pointer or %NULL to not
6056 * return the X coordinate
6057 * @y: return location for Y coordinate of pointer or %NULL to not
6058 * return the Y coordinate
6059 * @mask: return location for modifier mask or %NULL to not return the
6062 * Obtains the current pointer position and modifier state.
6063 * The position is given in coordinates relative to the upper left
6064 * corner of @window.
6066 * Return value: the window containing the pointer (as with
6067 * gdk_window_at_pointer()), or %NULL if the window containing the
6068 * pointer isn't known to GDK
6071 gdk_window_get_pointer (GdkWindow *window,
6074 GdkModifierType *mask)
6076 GdkDisplay *display;
6078 GdkModifierType tmp_mask;
6081 g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
6085 display = gdk_drawable_get_display (window);
6089 GdkScreen *screen = gdk_screen_get_default ();
6091 display = gdk_screen_get_display (screen);
6092 window = gdk_screen_get_root_window (screen);
6094 GDK_NOTE (MULTIHEAD,
6095 g_message ("Passing NULL for window to gdk_window_get_pointer()\n"
6096 "is not multihead safe"));
6099 child = display->pointer_hooks->window_get_pointer (display, window, &tmp_x, &tmp_y, &tmp_mask);
6108 _gdk_display_enable_motion_hints (display);
6114 * gdk_window_at_pointer:
6115 * @win_x: return location for origin of the window under the pointer
6116 * @win_y: return location for origin of the window under the pointer
6118 * Obtains the window underneath the mouse pointer, returning the
6119 * location of that window in @win_x, @win_y. Returns %NULL if the
6120 * window under the mouse pointer is not known to GDK (if the window
6121 * belongs to another application and a #GdkWindow hasn't been created
6122 * for it with gdk_window_foreign_new())
6124 * NOTE: For multihead-aware widgets or applications use
6125 * gdk_display_get_window_at_pointer() instead.
6127 * Return value: window under the mouse pointer
6130 gdk_window_at_pointer (gint *win_x,
6133 return gdk_display_get_window_at_pointer (gdk_display_get_default (), win_x, win_y);
6137 * gdk_get_default_root_window:
6139 * Obtains the root window (parent all other windows are inside)
6140 * for the default display and screen.
6142 * Return value: the default root window
6145 gdk_get_default_root_window (void)
6147 return gdk_screen_get_root_window (gdk_screen_get_default ());
6151 * gdk_window_foreign_new:
6152 * @anid: a native window handle.
6154 * Wraps a native window for the default display in a #GdkWindow.
6155 * This may fail if the window has been destroyed.
6157 * For example in the X backend, a native window handle is an Xlib
6160 * Return value: the newly-created #GdkWindow wrapper for the
6161 * native window or %NULL if the window has been destroyed.
6164 gdk_window_foreign_new (GdkNativeWindow anid)
6166 return gdk_window_foreign_new_for_display (gdk_display_get_default (), anid);
6170 get_all_native_children (GdkWindowObject *private,
6173 GdkWindowObject *child;
6176 for (l = private->children; l != NULL; l = l->next)
6180 if (gdk_window_has_impl (child))
6181 *native = g_list_prepend (*native, child);
6183 get_all_native_children (child, native);
6189 gdk_window_raise_internal (GdkWindow *window)
6191 GdkWindowObject *private = (GdkWindowObject *)window;
6192 GdkWindowObject *parent = private->parent;
6193 GdkWindowObject *above;
6194 GList *native_children;
6196 GdkWindowImplIface *impl_iface;
6200 parent->children = g_list_remove (parent->children, window);
6201 parent->children = g_list_prepend (parent->children, window);
6204 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
6205 /* Just do native raise for toplevels */
6206 if (gdk_window_is_toplevel (private) ||
6207 /* The restack_under codepath should work correctly even if the parent
6208 is native, but it relies on the order of ->children to be correct,
6209 and some apps like SWT reorder the x windows without gdks knowledge,
6210 so we use raise directly in order to make these behave as before
6211 when using native windows */
6212 (gdk_window_has_impl (private) && gdk_window_has_impl (parent)))
6214 impl_iface->raise (window);
6216 else if (gdk_window_has_impl (private))
6218 above = find_native_sibling_above (parent, private);
6221 listhead.data = window;
6222 listhead.next = NULL;
6223 listhead.prev = NULL;
6224 impl_iface->restack_under ((GdkWindow *)above,
6228 impl_iface->raise (window);
6232 native_children = NULL;
6233 get_all_native_children (private, &native_children);
6234 if (native_children != NULL)
6236 above = find_native_sibling_above (parent, private);
6239 impl_iface->restack_under ((GdkWindow *)above,
6243 /* Right order, since native_children is bottom-topmost first */
6244 for (l = native_children; l != NULL; l = l->next)
6245 impl_iface->raise (l->data);
6248 g_list_free (native_children);
6254 /* Returns TRUE If the native window was mapped or unmapped */
6256 set_viewable (GdkWindowObject *w,
6259 GdkWindowObject *child;
6260 GdkWindowImplIface *impl_iface;
6263 if (w->viewable == val)
6269 recompute_visible_regions (w, FALSE, FALSE);
6271 for (l = w->children; l != NULL; l = l->next)
6275 if (GDK_WINDOW_IS_MAPPED (child) &&
6276 child->window_type != GDK_WINDOW_FOREIGN)
6277 set_viewable (child, val);
6280 if (!_gdk_native_windows &&
6281 gdk_window_has_impl (w) &&
6282 w->window_type != GDK_WINDOW_FOREIGN &&
6283 !gdk_window_is_toplevel (w))
6285 /* For most native windows we show/hide them not when they are
6286 * mapped/unmapped, because that may not produce the correct results.
6287 * For instance, if a native window have a non-native parent which is
6288 * hidden, but its native parent is viewable then showing the window
6289 * would make it viewable to X but its not viewable wrt the non-native
6290 * hierarchy. In order to handle this we track the gdk side viewability
6291 * and only map really viewable windows.
6293 * There are two exceptions though:
6295 * For foreign windows we don't want ever change the mapped state
6296 * except when explicitly done via gdk_window_show/hide, as this may
6297 * cause problems for client owning the foreign window when its window
6298 * is suddenly mapped or unmapped.
6300 * For toplevel windows embedded in a foreign window (e.g. a plug)
6301 * we sometimes synthesize a map of a window, but the native
6302 * window is really shown by the embedder, so we don't want to
6303 * do the show ourselves. We can't really tell this case from the normal
6304 * toplevel show as such toplevels are seen by gdk as parents of the
6305 * root window, so we make an exception for all toplevels.
6307 * Also, when in GDK_NATIVE_WINDOW mode we never need to play games
6308 * like this, so we just always show/hide directly.
6311 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (w->impl);
6313 impl_iface->show ((GdkWindow *)w, FALSE);
6315 impl_iface->hide ((GdkWindow *)w);
6323 /* Returns TRUE If the native window was mapped or unmapped */
6325 _gdk_window_update_viewable (GdkWindow *window)
6327 GdkWindowObject *priv = (GdkWindowObject *)window;
6330 if (priv->window_type == GDK_WINDOW_FOREIGN ||
6331 priv->window_type == GDK_WINDOW_ROOT)
6333 else if (gdk_window_is_toplevel (priv) ||
6334 priv->parent->viewable)
6335 viewable = GDK_WINDOW_IS_MAPPED (priv);
6339 return set_viewable (priv, viewable);
6343 gdk_window_show_internal (GdkWindow *window, gboolean raise)
6345 GdkWindowObject *private;
6346 GdkWindowImplIface *impl_iface;
6347 gboolean was_mapped, was_viewable;
6350 g_return_if_fail (GDK_IS_WINDOW (window));
6352 private = (GdkWindowObject *) window;
6353 if (private->destroyed)
6356 was_mapped = GDK_WINDOW_IS_MAPPED (window);
6357 was_viewable = private->viewable;
6360 /* Keep children in (reverse) stacking order */
6361 gdk_window_raise_internal (window);
6363 if (gdk_window_has_impl (private))
6366 gdk_synthesize_window_state (window,
6367 GDK_WINDOW_STATE_WITHDRAWN,
6375 did_show = _gdk_window_update_viewable (window);
6377 /* If it was already viewable the backend show op won't be called, call it
6378 again to ensure things happen right if the mapped tracking was not right
6379 for e.g. a foreign window.
6380 Dunno if this is strictly needed but its what happened pre-csw.
6381 Also show if not done by gdk_window_update_viewable. */
6382 if (gdk_window_has_impl (private) && (was_viewable || !did_show))
6384 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
6385 impl_iface->show ((GdkWindow *)private,
6386 !did_show ? was_mapped : TRUE);
6389 if (!was_mapped && !gdk_window_has_impl (private))
6391 if (private->event_mask & GDK_STRUCTURE_MASK)
6392 _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
6394 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
6395 _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
6398 if (!was_mapped || raise)
6400 recompute_visible_regions (private, TRUE, FALSE);
6402 /* If any decendants became visible we need to send visibility notify */
6403 gdk_window_update_visibility_recursively (private, NULL);
6405 if (gdk_window_is_viewable (window))
6407 _gdk_synthesize_crossing_events_for_geometry_change (window);
6408 gdk_window_invalidate_rect (window, NULL, TRUE);
6414 * gdk_window_show_unraised:
6415 * @window: a #GdkWindow
6417 * Shows a #GdkWindow onscreen, but does not modify its stacking
6418 * order. In contrast, gdk_window_show() will raise the window
6419 * to the top of the window stack.
6421 * On the X11 platform, in Xlib terms, this function calls
6422 * XMapWindow() (it also updates some internal GDK state, which means
6423 * that you can't really use XMapWindow() directly on a GDK window).
6426 gdk_window_show_unraised (GdkWindow *window)
6428 gdk_window_show_internal (window, FALSE);
6433 * @window: a #GdkWindow
6435 * Raises @window to the top of the Z-order (stacking order), so that
6436 * other windows with the same parent window appear below @window.
6437 * This is true whether or not the windows are visible.
6439 * If @window is a toplevel, the window manager may choose to deny the
6440 * request to move the window in the Z-order, gdk_window_raise() only
6441 * requests the restack, does not guarantee it.
6444 gdk_window_raise (GdkWindow *window)
6446 GdkWindowObject *private;
6447 GdkRegion *old_region, *new_region;
6449 g_return_if_fail (GDK_IS_WINDOW (window));
6451 private = (GdkWindowObject *) window;
6452 if (private->destroyed)
6455 gdk_window_flush_if_exposing (window);
6458 if (gdk_window_is_viewable (window) &&
6459 !private->input_only)
6460 old_region = gdk_region_copy (private->clip_region);
6462 /* Keep children in (reverse) stacking order */
6463 gdk_window_raise_internal (window);
6465 recompute_visible_regions (private, TRUE, FALSE);
6469 new_region = gdk_region_copy (private->clip_region);
6471 gdk_region_subtract (new_region, old_region);
6472 gdk_window_invalidate_region (window, new_region, TRUE);
6474 gdk_region_destroy (old_region);
6475 gdk_region_destroy (new_region);
6480 gdk_window_lower_internal (GdkWindow *window)
6482 GdkWindowObject *private = (GdkWindowObject *)window;
6483 GdkWindowObject *parent = private->parent;
6484 GdkWindowImplIface *impl_iface;
6485 GdkWindowObject *above;
6486 GList *native_children;
6491 parent->children = g_list_remove (parent->children, window);
6492 parent->children = g_list_append (parent->children, window);
6495 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
6496 /* Just do native lower for toplevels */
6497 if (gdk_window_is_toplevel (private) ||
6498 /* The restack_under codepath should work correctly even if the parent
6499 is native, but it relies on the order of ->children to be correct,
6500 and some apps like SWT reorder the x windows without gdks knowledge,
6501 so we use lower directly in order to make these behave as before
6502 when using native windows */
6503 (gdk_window_has_impl (private) && gdk_window_has_impl (parent)))
6505 impl_iface->lower (window);
6507 else if (gdk_window_has_impl (private))
6509 above = find_native_sibling_above (parent, private);
6512 listhead.data = window;
6513 listhead.next = NULL;
6514 listhead.prev = NULL;
6515 impl_iface->restack_under ((GdkWindow *)above, &listhead);
6518 impl_iface->raise (window);
6522 native_children = NULL;
6523 get_all_native_children (private, &native_children);
6524 if (native_children != NULL)
6526 above = find_native_sibling_above (parent, private);
6529 impl_iface->restack_under ((GdkWindow *)above,
6533 /* Right order, since native_children is bottom-topmost first */
6534 for (l = native_children; l != NULL; l = l->next)
6535 impl_iface->raise (l->data);
6538 g_list_free (native_children);
6545 gdk_window_invalidate_in_parent (GdkWindowObject *private)
6547 GdkRectangle r, child;
6549 if (gdk_window_is_toplevel (private))
6552 /* get the visible rectangle of the parent */
6554 r.width = private->parent->width;
6555 r.height = private->parent->height;
6557 child.x = private->x;
6558 child.y = private->y;
6559 child.width = private->width;
6560 child.height = private->height;
6561 gdk_rectangle_intersect (&r, &child, &r);
6563 gdk_window_invalidate_rect (GDK_WINDOW (private->parent), &r, TRUE);
6569 * @window: a #GdkWindow
6571 * Lowers @window to the bottom of the Z-order (stacking order), so that
6572 * other windows with the same parent window appear above @window.
6573 * This is true whether or not the other windows are visible.
6575 * If @window is a toplevel, the window manager may choose to deny the
6576 * request to move the window in the Z-order, gdk_window_lower() only
6577 * requests the restack, does not guarantee it.
6579 * Note that gdk_window_show() raises the window again, so don't call this
6580 * function before gdk_window_show(). (Try gdk_window_show_unraised().)
6583 gdk_window_lower (GdkWindow *window)
6585 GdkWindowObject *private;
6587 g_return_if_fail (GDK_IS_WINDOW (window));
6589 private = (GdkWindowObject *) window;
6590 if (private->destroyed)
6593 gdk_window_flush_if_exposing (window);
6595 /* Keep children in (reverse) stacking order */
6596 gdk_window_lower_internal (window);
6598 recompute_visible_regions (private, TRUE, FALSE);
6600 _gdk_synthesize_crossing_events_for_geometry_change (window);
6601 gdk_window_invalidate_in_parent (private);
6605 * gdk_window_restack:
6606 * @window: a #GdkWindow
6607 * @sibling: a #GdkWindow that is a sibling of @window, or %NULL
6610 * Changes the position of @window in the Z-order (stacking order), so that
6611 * it is above @sibling (if @above is %TRUE) or below @sibling (if @above is
6614 * If @sibling is %NULL, then this either raises (if @above is %TRUE) or
6615 * lowers the window.
6617 * If @window is a toplevel, the window manager may choose to deny the
6618 * request to move the window in the Z-order, gdk_window_restack() only
6619 * requests the restack, does not guarantee it.
6624 gdk_window_restack (GdkWindow *window,
6628 GdkWindowObject *private;
6629 GdkWindowImplIface *impl_iface;
6630 GdkWindowObject *parent;
6631 GdkWindowObject *above_native;
6632 GList *sibling_link;
6633 GList *native_children;
6636 g_return_if_fail (GDK_IS_WINDOW (window));
6637 g_return_if_fail (sibling == NULL || GDK_IS_WINDOW (sibling));
6639 private = (GdkWindowObject *) window;
6640 if (private->destroyed)
6643 if (sibling == NULL)
6646 gdk_window_raise (window);
6648 gdk_window_lower (window);
6652 gdk_window_flush_if_exposing (window);
6654 if (gdk_window_is_toplevel (private))
6656 g_return_if_fail (gdk_window_is_toplevel (GDK_WINDOW_OBJECT (sibling)));
6657 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
6658 impl_iface->restack_toplevel (window, sibling, above);
6662 parent = private->parent;
6665 sibling_link = g_list_find (parent->children, sibling);
6666 g_return_if_fail (sibling_link != NULL);
6667 if (sibling_link == NULL)
6670 parent->children = g_list_remove (parent->children, window);
6672 parent->children = g_list_insert_before (parent->children,
6676 parent->children = g_list_insert_before (parent->children,
6680 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
6681 if (gdk_window_has_impl (private))
6683 above_native = find_native_sibling_above (parent, private);
6686 listhead.data = window;
6687 listhead.next = NULL;
6688 listhead.prev = NULL;
6689 impl_iface->restack_under ((GdkWindow *)above_native, &listhead);
6692 impl_iface->raise (window);
6696 native_children = NULL;
6697 get_all_native_children (private, &native_children);
6698 if (native_children != NULL)
6700 above_native = find_native_sibling_above (parent, private);
6702 impl_iface->restack_under ((GdkWindow *)above_native,
6706 /* Right order, since native_children is bottom-topmost first */
6707 for (l = native_children; l != NULL; l = l->next)
6708 impl_iface->raise (l->data);
6711 g_list_free (native_children);
6716 recompute_visible_regions (private, TRUE, FALSE);
6718 _gdk_synthesize_crossing_events_for_geometry_change (window);
6719 gdk_window_invalidate_in_parent (private);
6725 * @window: a #GdkWindow
6727 * Like gdk_window_show_unraised(), but also raises the window to the
6728 * top of the window stack (moves the window to the front of the
6731 * This function maps a window so it's visible onscreen. Its opposite
6732 * is gdk_window_hide().
6734 * When implementing a #GtkWidget, you should call this function on the widget's
6735 * #GdkWindow as part of the "map" method.
6738 gdk_window_show (GdkWindow *window)
6740 gdk_window_show_internal (window, TRUE);
6745 * @window: a #GdkWindow
6747 * For toplevel windows, withdraws them, so they will no longer be
6748 * known to the window manager; for all windows, unmaps them, so
6749 * they won't be displayed. Normally done automatically as
6750 * part of gtk_widget_hide().
6753 gdk_window_hide (GdkWindow *window)
6755 GdkWindowObject *private;
6756 GdkWindowImplIface *impl_iface;
6757 gboolean was_mapped, did_hide;
6759 g_return_if_fail (GDK_IS_WINDOW (window));
6761 private = (GdkWindowObject *) window;
6762 if (private->destroyed)
6765 was_mapped = GDK_WINDOW_IS_MAPPED (private);
6767 if (gdk_window_has_impl (private))
6770 if (GDK_WINDOW_IS_MAPPED (window))
6771 gdk_synthesize_window_state (window,
6773 GDK_WINDOW_STATE_WITHDRAWN);
6775 else if (was_mapped)
6777 GdkDisplay *display;
6779 /* May need to break grabs on children */
6780 display = gdk_drawable_get_display (window);
6782 if (_gdk_display_end_pointer_grab (display,
6783 _gdk_windowing_window_get_next_serial (display),
6786 gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
6788 if (display->keyboard_grab.window != NULL)
6790 if (is_parent_of (window, display->keyboard_grab.window))
6792 /* Call this ourselves, even though gdk_display_keyboard_ungrab
6793 does so too, since we want to pass implicit == TRUE so the
6794 broken grab event is generated */
6795 _gdk_display_unset_has_keyboard_grab (display,
6797 gdk_display_keyboard_ungrab (display, GDK_CURRENT_TIME);
6801 private->state = GDK_WINDOW_STATE_WITHDRAWN;
6804 did_hide = _gdk_window_update_viewable (window);
6806 /* Hide foreign window as those are not handled by update_viewable. */
6807 if (gdk_window_has_impl (private) && (!did_hide))
6809 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
6810 impl_iface->hide (window);
6813 recompute_visible_regions (private, TRUE, FALSE);
6815 /* all decendants became non-visible, we need to send visibility notify */
6816 gdk_window_update_visibility_recursively (private, NULL);
6818 if (was_mapped && !gdk_window_has_impl (private))
6820 if (private->event_mask & GDK_STRUCTURE_MASK)
6821 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6823 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
6824 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6826 _gdk_synthesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
6829 /* Invalidate the rect */
6830 gdk_window_invalidate_in_parent (private);
6834 * gdk_window_withdraw:
6835 * @window: a toplevel #GdkWindow
6837 * Withdraws a window (unmaps it and asks the window manager to forget about it).
6838 * This function is not really useful as gdk_window_hide() automatically
6839 * withdraws toplevel windows before hiding them.
6842 gdk_window_withdraw (GdkWindow *window)
6844 GdkWindowObject *private;
6845 GdkWindowImplIface *impl_iface;
6846 gboolean was_mapped;
6848 g_return_if_fail (GDK_IS_WINDOW (window));
6850 private = (GdkWindowObject *) window;
6851 if (private->destroyed)
6854 was_mapped = GDK_WINDOW_IS_MAPPED (private);
6856 if (gdk_window_has_impl (private))
6858 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
6859 impl_iface->withdraw (window);
6863 if (private->event_mask & GDK_STRUCTURE_MASK)
6864 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6866 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
6867 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6869 _gdk_synthesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
6872 recompute_visible_regions (private, TRUE, FALSE);
6877 * gdk_window_set_events:
6878 * @window: a #GdkWindow
6879 * @event_mask: event mask for @window
6881 * The event mask for a window determines which events will be reported
6882 * for that window. For example, an event mask including #GDK_BUTTON_PRESS_MASK
6883 * means the window should report button press events. The event mask
6884 * is the bitwise OR of values from the #GdkEventMask enumeration.
6887 gdk_window_set_events (GdkWindow *window,
6888 GdkEventMask event_mask)
6890 GdkWindowObject *private;
6891 GdkWindowImplIface *impl_iface;
6892 GdkDisplay *display;
6894 g_return_if_fail (GDK_IS_WINDOW (window));
6896 private = (GdkWindowObject *) window;
6897 if (private->destroyed)
6900 /* If motion hint is disabled, enable motion events again */
6901 display = gdk_drawable_get_display (window);
6902 if ((private->event_mask & GDK_POINTER_MOTION_HINT_MASK) &&
6903 !(event_mask & GDK_POINTER_MOTION_HINT_MASK))
6904 _gdk_display_enable_motion_hints (display);
6906 private->event_mask = event_mask;
6908 if (gdk_window_has_impl (private))
6910 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
6911 impl_iface->set_events (window,
6912 get_native_event_mask (private));
6918 * gdk_window_get_events:
6919 * @window: a #GdkWindow
6921 * Gets the event mask for @window. See gdk_window_set_events().
6923 * Return value: event mask for @window
6926 gdk_window_get_events (GdkWindow *window)
6928 GdkWindowObject *private;
6930 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
6932 private = (GdkWindowObject *) window;
6933 if (private->destroyed)
6936 return private->event_mask;
6940 gdk_window_move_resize_toplevel (GdkWindow *window,
6947 GdkWindowObject *private;
6948 GdkRegion *old_region, *new_region;
6949 GdkWindowImplIface *impl_iface;
6951 int old_x, old_y, old_abs_x, old_abs_y;
6955 private = (GdkWindowObject *) window;
6963 is_resize = (width != -1) || (height != -1);
6965 if (gdk_window_is_viewable (window) &&
6966 !private->input_only)
6969 old_region = gdk_region_copy (private->clip_region);
6972 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
6973 impl_iface->move_resize (window, with_move, x, y, width, height);
6975 dx = private->x - old_x;
6976 dy = private->y - old_y;
6978 old_abs_x = private->abs_x;
6979 old_abs_y = private->abs_y;
6981 /* Avoid recomputing for pure toplevel moves, for performance reasons */
6983 recompute_visible_regions (private, TRUE, FALSE);
6987 new_region = gdk_region_copy (private->clip_region);
6989 /* This is the newly exposed area (due to any resize),
6990 * X will expose it, but lets do that without the
6993 gdk_region_subtract (new_region, old_region);
6994 gdk_window_invalidate_region (window, new_region, TRUE);
6996 gdk_region_destroy (old_region);
6997 gdk_region_destroy (new_region);
7000 _gdk_synthesize_crossing_events_for_geometry_change (window);
7005 move_native_children (GdkWindowObject *private)
7008 GdkWindowObject *child;
7009 GdkWindowImplIface *impl_iface;
7011 for (l = private->children; l; l = l->next)
7015 if (child->impl != private->impl)
7017 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (child->impl);
7018 impl_iface->move_resize ((GdkWindow *)child, TRUE,
7020 child->width, child->height);
7023 move_native_children (child);
7028 collect_native_child_region_helper (GdkWindowObject *window,
7034 GdkWindowObject *child;
7038 for (l = window->children; l != NULL; l = l->next)
7042 if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only)
7045 if (child->impl != impl)
7047 tmp = gdk_region_copy (child->clip_region);
7048 gdk_region_offset (tmp,
7049 x_offset + child->x,
7050 y_offset + child->y);
7051 if (*region == NULL)
7055 gdk_region_union (*region, tmp);
7056 gdk_region_destroy (tmp);
7060 collect_native_child_region_helper (child, impl, region,
7061 x_offset + child->x,
7062 y_offset + child->y);
7069 collect_native_child_region (GdkWindowObject *window,
7070 gboolean include_this)
7074 if (include_this && gdk_window_has_impl (window) && window->viewable)
7075 return gdk_region_copy (window->clip_region);
7079 collect_native_child_region_helper (window, window->impl, ®ion, 0, 0);
7086 gdk_window_move_resize_internal (GdkWindow *window,
7093 GdkWindowObject *private;
7094 GdkRegion *old_region, *new_region, *copy_area;
7095 GdkRegion *old_native_child_region, *new_native_child_region;
7096 GdkWindowObject *impl_window;
7097 GdkWindowImplIface *impl_iface;
7099 int old_x, old_y, old_abs_x, old_abs_y;
7102 g_return_if_fail (GDK_IS_WINDOW (window));
7104 private = (GdkWindowObject *) window;
7105 if (private->destroyed)
7108 if (gdk_window_is_toplevel (private))
7110 gdk_window_move_resize_toplevel (window, with_move, x, y, width, height);
7114 /* Bail early if no change */
7115 if (private->width == width &&
7116 private->height == height &&
7122 gdk_window_flush_if_exposing (window);
7124 /* Handle child windows */
7129 impl_window = gdk_window_get_impl_window (private);
7134 old_native_child_region = NULL;
7135 if (gdk_window_is_viewable (window) &&
7136 !private->input_only)
7140 old_region = gdk_region_copy (private->clip_region);
7141 /* Adjust region to parent window coords */
7142 gdk_region_offset (old_region, private->x, private->y);
7144 old_native_child_region = collect_native_child_region (private, TRUE);
7145 if (old_native_child_region)
7147 /* Adjust region to parent window coords */
7148 gdk_region_offset (old_native_child_region, private->x, private->y);
7150 /* Any native window move will immediately copy stuff to the destination, which may overwrite a
7151 * source or destination for a delayed GdkWindowRegionMove. So, we need
7152 * to flush those here for the parent window and all overlapped subwindows
7153 * of it. And we need to do this before setting the new clips as those will be
7156 gdk_window_flush_recursive (private->parent);
7160 /* Set the new position and size */
7166 if (!(width < 0 && height < 0))
7170 private->width = width;
7173 private->height = height;
7176 dx = private->x - old_x;
7177 dy = private->y - old_y;
7179 old_abs_x = private->abs_x;
7180 old_abs_y = private->abs_y;
7182 recompute_visible_regions (private, TRUE, FALSE);
7184 new_native_child_region = NULL;
7185 if (old_native_child_region)
7187 new_native_child_region = collect_native_child_region (private, TRUE);
7188 /* Adjust region to parent window coords */
7189 gdk_region_offset (new_native_child_region, private->x, private->y);
7192 if (gdk_window_has_impl (private))
7194 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
7196 /* Do the actual move after recomputing things, as this will have set the shape to
7197 the now correct one, thus avoiding copying regions that should not be copied. */
7198 impl_iface->move_resize (window, TRUE,
7199 private->x, private->y,
7200 private->width, private->height);
7202 else if (old_abs_x != private->abs_x ||
7203 old_abs_y != private->abs_y)
7204 move_native_children (private);
7208 new_region = gdk_region_copy (private->clip_region);
7209 /* Adjust region to parent window coords */
7210 gdk_region_offset (new_region, private->x, private->y);
7213 * Part of the data at the new location can be copied from the
7214 * old location, this area is the intersection of the old region
7215 * moved as the copy will move it and then intersected with
7219 * Everything in the old and new regions that is not copied must be
7220 * invalidated (including children) as this is newly exposed
7222 copy_area = gdk_region_copy (new_region);
7224 gdk_region_union (new_region, old_region);
7226 if (old_native_child_region)
7228 /* Don't copy from inside native children, as this is copied by
7229 * the native window move.
7231 gdk_region_subtract (old_region, old_native_child_region);
7233 gdk_region_offset (old_region, dx, dy);
7235 gdk_region_intersect (copy_area, old_region);
7237 if (new_native_child_region)
7239 /* Don't copy any bits that would cause a read from the moved
7240 native windows, as we can't read that data */
7241 gdk_region_offset (new_native_child_region, dx, dy);
7242 gdk_region_subtract (copy_area, new_native_child_region);
7245 gdk_region_subtract (new_region, copy_area);
7247 /* Convert old region to impl coords */
7248 gdk_region_offset (old_region, -dx + private->abs_x - private->x, -dy + private->abs_y - private->y);
7250 /* convert from parent coords to impl */
7251 gdk_region_offset (copy_area, private->abs_x - private->x, private->abs_y - private->y);
7253 move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
7255 /* Invalidate affected part in the parent window
7256 * (no higher window should be affected)
7257 * We also invalidate any children in that area, which could include
7258 * this window if it still overlaps that area.
7260 gdk_window_invalidate_region (GDK_WINDOW (private->parent), new_region, TRUE);
7262 gdk_region_destroy (old_region);
7263 gdk_region_destroy (new_region);
7266 if (old_native_child_region)
7268 gdk_region_destroy (old_native_child_region);
7269 gdk_region_destroy (new_native_child_region);
7272 _gdk_synthesize_crossing_events_for_geometry_change (window);
7279 * @window: a #GdkWindow
7280 * @x: X coordinate relative to window's parent
7281 * @y: Y coordinate relative to window's parent
7283 * Repositions a window relative to its parent window.
7284 * For toplevel windows, window managers may ignore or modify the move;
7285 * you should probably use gtk_window_move() on a #GtkWindow widget
7286 * anyway, instead of using GDK functions. For child windows,
7287 * the move will reliably succeed.
7289 * If you're also planning to resize the window, use gdk_window_move_resize()
7290 * to both move and resize simultaneously, for a nicer visual effect.
7293 gdk_window_move (GdkWindow *window,
7297 gdk_window_move_resize_internal (window, TRUE, x, y, -1, -1);
7301 * gdk_window_resize:
7302 * @window: a #GdkWindow
7303 * @width: new width of the window
7304 * @height: new height of the window
7306 * Resizes @window; for toplevel windows, asks the window manager to resize
7307 * the window. The window manager may not allow the resize. When using GTK+,
7308 * use gtk_window_resize() instead of this low-level GDK function.
7310 * Windows may not be resized below 1x1.
7312 * If you're also planning to move the window, use gdk_window_move_resize()
7313 * to both move and resize simultaneously, for a nicer visual effect.
7316 gdk_window_resize (GdkWindow *window,
7320 gdk_window_move_resize_internal (window, FALSE, 0, 0, width, height);
7325 * gdk_window_move_resize:
7326 * @window: a #GdkWindow
7327 * @x: new X position relative to window's parent
7328 * @y: new Y position relative to window's parent
7330 * @height: new height
7332 * Equivalent to calling gdk_window_move() and gdk_window_resize(),
7333 * except that both operations are performed at once, avoiding strange
7334 * visual effects. (i.e. the user may be able to see the window first
7335 * move, then resize, if you don't use gdk_window_move_resize().)
7338 gdk_window_move_resize (GdkWindow *window,
7344 gdk_window_move_resize_internal (window, TRUE, x, y, width, height);
7349 * gdk_window_scroll:
7350 * @window: a #GdkWindow
7351 * @dx: Amount to scroll in the X direction
7352 * @dy: Amount to scroll in the Y direction
7354 * Scroll the contents of @window, both pixels and children, by the
7355 * given amount. @window itself does not move. Portions of the window
7356 * that the scroll operation brings in from offscreen areas are
7357 * invalidated. The invalidated region may be bigger than what would
7358 * strictly be necessary.
7360 * For X11, a minimum area will be invalidated if the window has no
7361 * subwindows, or if the edges of the window's parent do not extend
7362 * beyond the edges of the window. In other cases, a multi-step process
7363 * is used to scroll the window which may produce temporary visual
7364 * artifacts and unnecessary invalidations.
7367 gdk_window_scroll (GdkWindow *window,
7371 GdkWindowObject *private = (GdkWindowObject *) window;
7372 GdkWindowObject *impl_window;
7373 GdkRegion *copy_area, *noncopy_area;
7374 GdkRegion *old_native_child_region, *new_native_child_region;
7377 g_return_if_fail (GDK_IS_WINDOW (window));
7379 if (dx == 0 && dy == 0)
7382 if (private->destroyed)
7385 gdk_window_flush_if_exposing (window);
7387 old_native_child_region = collect_native_child_region (private, FALSE);
7388 if (old_native_child_region)
7390 /* Any native window move will immediately copy stuff to the destination, which may overwrite a
7391 * source or destination for a delayed GdkWindowRegionMove. So, we need
7392 * to flush those here for the window and all overlapped subwindows
7393 * of it. And we need to do this before setting the new clips as those will be
7396 gdk_window_flush_recursive (private);
7400 /* First move all child windows, without causing invalidation */
7402 tmp_list = private->children;
7405 GdkWindow *child = GDK_WINDOW (tmp_list->data);
7406 GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
7408 /* Just update the positions, the bits will move with the copy */
7412 tmp_list = tmp_list->next;
7415 recompute_visible_regions (private, FALSE, TRUE);
7417 new_native_child_region = NULL;
7418 if (old_native_child_region)
7419 new_native_child_region = collect_native_child_region (private, FALSE);
7421 move_native_children (private);
7423 /* Then copy the actual bits of the window w/ child windows */
7425 impl_window = gdk_window_get_impl_window (private);
7427 /* Calculate the area that can be gotten by copying the old area */
7428 copy_area = gdk_region_copy (private->clip_region);
7429 if (old_native_child_region)
7431 /* Don't copy from inside native children, as this is copied by
7432 * the native window move.
7434 gdk_region_subtract (copy_area, old_native_child_region);
7436 /* Don't copy any bits that would cause a read from the moved
7437 native windows, as we can't read that data */
7438 gdk_region_subtract (copy_area, new_native_child_region);
7440 gdk_region_offset (copy_area, dx, dy);
7441 gdk_region_intersect (copy_area, private->clip_region);
7443 /* And the rest need to be invalidated */
7444 noncopy_area = gdk_region_copy (private->clip_region);
7445 gdk_region_subtract (noncopy_area, copy_area);
7447 /* convert from window coords to impl */
7448 gdk_region_offset (copy_area, private->abs_x, private->abs_y);
7450 move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
7452 /* Invalidate not copied regions */
7453 gdk_window_invalidate_region (window, noncopy_area, TRUE);
7455 gdk_region_destroy (noncopy_area);
7457 if (old_native_child_region)
7459 gdk_region_destroy (old_native_child_region);
7460 gdk_region_destroy (new_native_child_region);
7463 _gdk_synthesize_crossing_events_for_geometry_change (window);
7467 * gdk_window_move_region:
7468 * @window: a #GdkWindow
7469 * @region: The #GdkRegion to move
7470 * @dx: Amount to move in the X direction
7471 * @dy: Amount to move in the Y direction
7473 * Move the part of @window indicated by @region by @dy pixels in the Y
7474 * direction and @dx pixels in the X direction. The portions of @region
7475 * that not covered by the new position of @region are invalidated.
7477 * Child windows are not moved.
7482 gdk_window_move_region (GdkWindow *window,
7483 const GdkRegion *region,
7487 GdkWindowObject *private = (GdkWindowObject *) window;
7488 GdkWindowObject *impl_window;
7489 GdkRegion *nocopy_area;
7490 GdkRegion *copy_area;
7492 g_return_if_fail (GDK_IS_WINDOW (window));
7493 g_return_if_fail (region != NULL);
7495 if (dx == 0 && dy == 0)
7498 if (private->destroyed)
7501 impl_window = gdk_window_get_impl_window (private);
7503 /* compute source regions */
7504 copy_area = gdk_region_copy (region);
7505 gdk_region_intersect (copy_area, private->clip_region_with_children);
7507 /* compute destination regions */
7508 gdk_region_offset (copy_area, dx, dy);
7509 gdk_region_intersect (copy_area, private->clip_region_with_children);
7511 /* Invalidate parts of the region (source and dest) not covered
7513 nocopy_area = gdk_region_copy (region);
7514 gdk_region_offset (nocopy_area, dx, dy);
7515 gdk_region_union (nocopy_area, region);
7516 gdk_region_subtract (nocopy_area, copy_area);
7518 /* convert from window coords to impl */
7519 gdk_region_offset (copy_area, private->abs_x, private->abs_y);
7520 move_region_on_impl (impl_window, copy_area, dx, dy); /* Takes ownership of copy_area */
7522 gdk_window_invalidate_region (window, nocopy_area, FALSE);
7523 gdk_region_destroy (nocopy_area);
7527 * gdk_window_set_background:
7528 * @window: a #GdkWindow
7529 * @color: an allocated #GdkColor
7531 * Sets the background color of @window. (However, when using GTK+,
7532 * set the background of a widget with gtk_widget_modify_bg() - if
7533 * you're an application - or gtk_style_set_background() - if you're
7534 * implementing a custom widget.)
7536 * The @color must be allocated; gdk_rgb_find_color() is the best way
7537 * to allocate a color.
7539 * See also gdk_window_set_back_pixmap().
7542 gdk_window_set_background (GdkWindow *window,
7543 const GdkColor *color)
7545 GdkWindowObject *private;
7546 GdkColormap *colormap = gdk_drawable_get_colormap (window);
7547 GdkWindowImplIface *impl_iface;
7549 g_return_if_fail (GDK_IS_WINDOW (window));
7551 private = (GdkWindowObject *) window;
7553 private->bg_color = *color;
7554 gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
7556 if (private->bg_pixmap &&
7557 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
7558 private->bg_pixmap != GDK_NO_BG)
7559 g_object_unref (private->bg_pixmap);
7561 private->bg_pixmap = NULL;
7563 if (!GDK_WINDOW_DESTROYED (window) &&
7564 gdk_window_has_impl (private) &&
7565 !private->input_only)
7567 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
7568 impl_iface->set_background (window, &private->bg_color);
7573 * gdk_window_set_back_pixmap:
7574 * @window: a #GdkWindow
7575 * @pixmap: a #GdkPixmap, or %NULL
7576 * @parent_relative: whether the tiling origin is at the origin of
7579 * Sets the background pixmap of @window. May also be used to set a
7580 * background of "None" on @window, by setting a background pixmap
7583 * A background pixmap will be tiled, positioning the first tile at
7584 * the origin of @window, or if @parent_relative is %TRUE, the tiling
7585 * will be done based on the origin of the parent window (useful to
7586 * align tiles in a parent with tiles in a child).
7588 * A background pixmap of %NULL means that the window will have no
7589 * background. A window with no background will never have its
7590 * background filled by the windowing system, instead the window will
7591 * contain whatever pixels were already in the corresponding area of
7594 * The windowing system will normally fill a window with its background
7595 * when the window is obscured then exposed, and when you call
7596 * gdk_window_clear().
7599 gdk_window_set_back_pixmap (GdkWindow *window,
7601 gboolean parent_relative)
7603 GdkWindowObject *private;
7604 GdkWindowImplIface *impl_iface;
7606 g_return_if_fail (GDK_IS_WINDOW (window));
7607 g_return_if_fail (pixmap == NULL || !parent_relative);
7608 g_return_if_fail (pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap));
7610 private = (GdkWindowObject *) window;
7612 if (pixmap && !gdk_drawable_get_colormap (pixmap))
7614 g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
7618 if (private->bg_pixmap &&
7619 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
7620 private->bg_pixmap != GDK_NO_BG)
7621 g_object_unref (private->bg_pixmap);
7623 if (parent_relative)
7624 private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
7626 private->bg_pixmap = g_object_ref (pixmap);
7628 private->bg_pixmap = GDK_NO_BG;
7630 if (!GDK_WINDOW_DESTROYED (window) &&
7631 gdk_window_has_impl (private) &&
7632 !private->input_only)
7634 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
7635 impl_iface->set_back_pixmap (window, private->bg_pixmap);
7640 * gdk_window_get_cursor:
7641 * @window: a #GdkWindow
7643 * Retrieves a #GdkCursor pointer for the cursor currently set on the
7644 * specified #GdkWindow, or %NULL. If the return value is %NULL then
7645 * there is no custom cursor set on the specified window, and it is
7646 * using the cursor for its parent window.
7648 * Return value: a #GdkCursor, or %NULL. The returned object is owned
7649 * by the #GdkWindow and should not be unreferenced directly. Use
7650 * gdk_window_set_cursor() to unset the cursor of the window
7655 gdk_window_get_cursor (GdkWindow *window)
7657 GdkWindowObject *private;
7659 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
7661 private = (GdkWindowObject *) window;
7663 return private->cursor;
7667 * gdk_window_set_cursor:
7668 * @window: a #GdkWindow
7671 * Sets the mouse pointer for a #GdkWindow. Use gdk_cursor_new_for_display()
7672 * or gdk_cursor_new_from_pixmap() to create the cursor. To make the cursor
7673 * invisible, use %GDK_BLANK_CURSOR. Passing %NULL for the @cursor argument
7674 * to gdk_window_set_cursor() means that @window will use the cursor of its
7675 * parent window. Most windows should use this default.
7678 gdk_window_set_cursor (GdkWindow *window,
7681 GdkWindowObject *private;
7682 GdkWindowImplIface *impl_iface;
7683 GdkDisplay *display;
7685 g_return_if_fail (GDK_IS_WINDOW (window));
7687 private = (GdkWindowObject *) window;
7688 display = gdk_drawable_get_display (window);
7690 if (private->cursor)
7692 gdk_cursor_unref (private->cursor);
7693 private->cursor = NULL;
7696 if (!GDK_WINDOW_DESTROYED (window))
7699 private->cursor = gdk_cursor_ref (cursor);
7701 if (_gdk_native_windows ||
7702 private->window_type == GDK_WINDOW_ROOT ||
7703 private->window_type == GDK_WINDOW_FOREIGN)
7705 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
7706 impl_iface->set_cursor (window, cursor);
7708 else if (_gdk_window_event_parent_of (window, display->pointer_info.window_under_pointer))
7709 update_cursor (display);
7711 g_object_notify (G_OBJECT (window), "cursor");
7716 * gdk_window_get_geometry:
7717 * @window: a #GdkWindow
7718 * @x: return location for X coordinate of window (relative to its parent)
7719 * @y: return location for Y coordinate of window (relative to its parent)
7720 * @width: return location for width of window
7721 * @height: return location for height of window
7722 * @depth: return location for bit depth of window
7724 * Any of the return location arguments to this function may be %NULL,
7725 * if you aren't interested in getting the value of that field.
7727 * The X and Y coordinates returned are relative to the parent window
7728 * of @window, which for toplevels usually means relative to the
7729 * window decorations (titlebar, etc.) rather than relative to the
7730 * root window (screen-size background window).
7732 * On the X11 platform, the geometry is obtained from the X server,
7733 * so reflects the latest position of @window; this may be out-of-sync
7734 * with the position of @window delivered in the most-recently-processed
7735 * #GdkEventConfigure. gdk_window_get_position() in contrast gets the
7736 * position from the most recent configure event.
7739 * If @window is not a toplevel, it is <emphasis>much</emphasis> better
7740 * to call gdk_window_get_position() and gdk_drawable_get_size() instead,
7741 * because it avoids the roundtrip to the X server and because
7742 * gdk_drawable_get_size() supports the full 32-bit coordinate space,
7743 * whereas gdk_window_get_geometry() is restricted to the 16-bit
7744 * coordinates of X11.
7748 gdk_window_get_geometry (GdkWindow *window,
7755 GdkWindowObject *private, *parent;
7756 GdkWindowImplIface *impl_iface;
7760 GDK_NOTE (MULTIHEAD,
7761 g_message ("gdk_window_get_geometry(): Window needs "
7762 "to be non-NULL to be multi head safe"));
7763 window = gdk_screen_get_root_window ((gdk_screen_get_default ()));
7766 g_return_if_fail (GDK_IS_WINDOW (window));
7768 private = (GdkWindowObject *) window;
7770 if (!GDK_WINDOW_DESTROYED (window))
7772 if (gdk_window_has_impl (private))
7774 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
7775 impl_iface->get_geometry (window, x, y,
7778 /* This reports the position wrt to the native parent, we need to convert
7779 it to be relative to the client side parent */
7780 parent = private->parent;
7781 if (parent && !gdk_window_has_impl (parent))
7784 *x -= parent->abs_x;
7786 *y -= parent->abs_y;
7796 *width = private->width;
7798 *height = private->height;
7800 *depth = private->depth;
7806 * gdk_window_get_origin:
7807 * @window: a #GdkWindow
7808 * @x: return location for X coordinate
7809 * @y: return location for Y coordinate
7811 * Obtains the position of a window in root window coordinates.
7812 * (Compare with gdk_window_get_position() and
7813 * gdk_window_get_geometry() which return the position of a window
7814 * relative to its parent window.)
7816 * Return value: not meaningful, ignore
7819 gdk_window_get_origin (GdkWindow *window,
7823 GdkWindowObject *private;
7824 GdkWindowImplIface *impl_iface;
7826 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
7828 if (GDK_WINDOW_DESTROYED (window))
7837 private = (GdkWindowObject *) window;
7839 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
7840 impl_iface->get_root_coords (window,
7849 * gdk_window_get_root_coords:
7850 * @window: a #GdkWindow
7851 * @x: X coordinate in window
7852 * @y: Y coordinate in window
7853 * @root_x: return location for X coordinate
7854 * @root_y: return location for Y coordinate
7856 * Obtains the position of a window position in root
7857 * window coordinates. This is similar to
7858 * gdk_window_get_origin() but allows you go pass
7859 * in any position in the window, not just the origin.
7862 gdk_window_get_root_coords (GdkWindow *window,
7868 GdkWindowObject *private;
7869 GdkWindowImplIface *impl_iface;
7871 g_return_if_fail (GDK_IS_WINDOW (window));
7873 private = (GdkWindowObject *) window;
7875 if (GDK_WINDOW_DESTROYED (window))
7884 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
7885 impl_iface->get_root_coords (window,
7893 * gdk_window_get_deskrelative_origin:
7894 * @window: a toplevel #GdkWindow
7895 * @x: return location for X coordinate
7896 * @y: return location for Y coordinate
7898 * This gets the origin of a #GdkWindow relative to
7899 * an Enlightenment-window-manager desktop. As long as you don't
7900 * assume that the user's desktop/workspace covers the entire
7901 * root window (i.e. you don't assume that the desktop begins
7902 * at root window coordinate 0,0) this function is not necessary.
7903 * It's deprecated for that reason.
7905 * Return value: not meaningful
7908 gdk_window_get_deskrelative_origin (GdkWindow *window,
7912 GdkWindowObject *private;
7913 GdkWindowImplIface *impl_iface;
7914 gboolean return_val = FALSE;
7918 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
7920 private = (GdkWindowObject *) window;
7922 if (!GDK_WINDOW_DESTROYED (window))
7924 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
7925 return_val = impl_iface->get_deskrelative_origin (window, &tx, &ty);
7928 *x = tx + private->abs_x;
7930 *y = ty + private->abs_y;
7937 * gdk_window_shape_combine_mask:
7938 * @window: a #GdkWindow
7940 * @x: X position of shape mask with respect to @window
7941 * @y: Y position of shape mask with respect to @window
7943 * Applies a shape mask to @window. Pixels in @window corresponding to
7944 * set bits in the @mask will be visible; pixels in @window
7945 * corresponding to unset bits in the @mask will be transparent. This
7946 * gives a non-rectangular window.
7948 * If @mask is %NULL, the shape mask will be unset, and the @x/@y
7949 * parameters are not used.
7951 * On the X11 platform, this uses an X server extension which is
7952 * widely available on most common platforms, but not available on
7953 * very old X servers, and occasionally the implementation will be
7954 * buggy. On servers without the shape extension, this function
7957 * This function works on both toplevel and child windows.
7960 gdk_window_shape_combine_mask (GdkWindow *window,
7965 GdkWindowObject *private;
7968 g_return_if_fail (GDK_IS_WINDOW (window));
7970 private = (GdkWindowObject *) window;
7973 region = _gdk_windowing_get_shape_for_mask (mask);
7977 gdk_window_shape_combine_region (window,
7982 gdk_region_destroy (region);
7986 * gdk_window_shape_combine_region:
7987 * @window: a #GdkWindow
7988 * @shape_region: region of window to be non-transparent
7989 * @offset_x: X position of @shape_region in @window coordinates
7990 * @offset_y: Y position of @shape_region in @window coordinates
7992 * Makes pixels in @window outside @shape_region be transparent,
7993 * so that the window may be nonrectangular. See also
7994 * gdk_window_shape_combine_mask() to use a bitmap as the mask.
7996 * If @shape_region is %NULL, the shape will be unset, so the whole
7997 * window will be opaque again. @offset_x and @offset_y are ignored
7998 * if @shape_region is %NULL.
8000 * On the X11 platform, this uses an X server extension which is
8001 * widely available on most common platforms, but not available on
8002 * very old X servers, and occasionally the implementation will be
8003 * buggy. On servers without the shape extension, this function
8006 * This function works on both toplevel and child windows.
8009 gdk_window_shape_combine_region (GdkWindow *window,
8010 const GdkRegion *shape_region,
8014 GdkWindowObject *private;
8015 GdkRegion *old_region, *new_region, *diff;
8017 g_return_if_fail (GDK_IS_WINDOW (window));
8019 private = (GdkWindowObject *) window;
8021 if (GDK_WINDOW_DESTROYED (window))
8024 private->shaped = (shape_region != NULL);
8027 gdk_region_destroy (private->shape);
8030 if (GDK_WINDOW_IS_MAPPED (window))
8031 old_region = gdk_region_copy (private->clip_region);
8035 private->shape = gdk_region_copy (shape_region);
8036 gdk_region_offset (private->shape, offset_x, offset_y);
8039 private->shape = NULL;
8041 recompute_visible_regions (private, TRUE, FALSE);
8043 if (gdk_window_has_impl (private) &&
8044 !should_apply_clip_as_shape (private))
8045 apply_shape (private, private->shape);
8049 new_region = gdk_region_copy (private->clip_region);
8051 /* New area in the window, needs invalidation */
8052 diff = gdk_region_copy (new_region);
8053 gdk_region_subtract (diff, old_region);
8055 gdk_window_invalidate_region (window, diff, TRUE);
8057 gdk_region_destroy (diff);
8059 if (!gdk_window_is_toplevel (private))
8061 /* New area in the non-root parent window, needs invalidation */
8062 diff = gdk_region_copy (old_region);
8063 gdk_region_subtract (diff, new_region);
8065 /* Adjust region to parent window coords */
8066 gdk_region_offset (diff, private->x, private->y);
8068 gdk_window_invalidate_region (GDK_WINDOW (private->parent), diff, TRUE);
8070 gdk_region_destroy (diff);
8073 gdk_region_destroy (new_region);
8074 gdk_region_destroy (old_region);
8079 do_child_shapes (GdkWindow *window,
8082 GdkWindowObject *private;
8086 private = (GdkWindowObject *) window;
8090 r.width = private->width;
8091 r.height = private->height;
8093 region = gdk_region_rectangle (&r);
8094 remove_child_area (private, NULL, FALSE, region);
8096 if (merge && private->shape)
8097 gdk_region_subtract (region, private->shape);
8099 gdk_window_shape_combine_region (window, region, 0, 0);
8103 * gdk_window_set_child_shapes:
8104 * @window: a #GdkWindow
8106 * Sets the shape mask of @window to the union of shape masks
8107 * for all children of @window, ignoring the shape mask of @window
8108 * itself. Contrast with gdk_window_merge_child_shapes() which includes
8109 * the shape mask of @window in the masks to be merged.
8112 gdk_window_set_child_shapes (GdkWindow *window)
8114 g_return_if_fail (GDK_IS_WINDOW (window));
8116 do_child_shapes (window, FALSE);
8120 * gdk_window_merge_child_shapes:
8121 * @window: a #GdkWindow
8123 * Merges the shape masks for any child windows into the
8124 * shape mask for @window. i.e. the union of all masks
8125 * for @window and its children will become the new mask
8126 * for @window. See gdk_window_shape_combine_mask().
8128 * This function is distinct from gdk_window_set_child_shapes()
8129 * because it includes @window's shape mask in the set of shapes to
8133 gdk_window_merge_child_shapes (GdkWindow *window)
8135 g_return_if_fail (GDK_IS_WINDOW (window));
8137 do_child_shapes (window, TRUE);
8141 * gdk_window_input_shape_combine_mask:
8142 * @window: a #GdkWindow
8143 * @mask: shape mask, or %NULL
8144 * @x: X position of shape mask with respect to @window
8145 * @y: Y position of shape mask with respect to @window
8147 * Like gdk_window_shape_combine_mask(), but the shape applies
8148 * only to event handling. Mouse events which happen while
8149 * the pointer position corresponds to an unset bit in the
8150 * mask will be passed on the window below @window.
8152 * An input shape is typically used with RGBA windows.
8153 * The alpha channel of the window defines which pixels are
8154 * invisible and allows for nicely antialiased borders,
8155 * and the input shape controls where the window is
8158 * On the X11 platform, this requires version 1.1 of the
8161 * On the Win32 platform, this functionality is not present and the
8162 * function does nothing.
8167 gdk_window_input_shape_combine_mask (GdkWindow *window,
8172 GdkWindowObject *private;
8175 g_return_if_fail (GDK_IS_WINDOW (window));
8177 private = (GdkWindowObject *) window;
8180 region = _gdk_windowing_get_shape_for_mask (mask);
8184 gdk_window_input_shape_combine_region (window,
8189 gdk_region_destroy (region);
8193 * gdk_window_input_shape_combine_region:
8194 * @window: a #GdkWindow
8195 * @shape_region: region of window to be non-transparent
8196 * @offset_x: X position of @shape_region in @window coordinates
8197 * @offset_y: Y position of @shape_region in @window coordinates
8199 * Like gdk_window_shape_combine_region(), but the shape applies
8200 * only to event handling. Mouse events which happen while
8201 * the pointer position corresponds to an unset bit in the
8202 * mask will be passed on the window below @window.
8204 * An input shape is typically used with RGBA windows.
8205 * The alpha channel of the window defines which pixels are
8206 * invisible and allows for nicely antialiased borders,
8207 * and the input shape controls where the window is
8210 * On the X11 platform, this requires version 1.1 of the
8213 * On the Win32 platform, this functionality is not present and the
8214 * function does nothing.
8219 gdk_window_input_shape_combine_region (GdkWindow *window,
8220 const GdkRegion *shape_region,
8224 GdkWindowObject *private;
8225 GdkWindowImplIface *impl_iface;
8227 g_return_if_fail (GDK_IS_WINDOW (window));
8229 private = (GdkWindowObject *) window;
8231 if (GDK_WINDOW_DESTROYED (window))
8234 if (private->input_shape)
8235 gdk_region_destroy (private->input_shape);
8239 private->input_shape = gdk_region_copy (shape_region);
8240 gdk_region_offset (private->input_shape, offset_x, offset_y);
8243 private->input_shape = NULL;
8245 if (gdk_window_has_impl (private))
8247 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
8248 impl_iface->input_shape_combine_region (window, private->input_shape, 0, 0);
8251 /* Pointer may have e.g. moved outside window due to the input mask change */
8252 _gdk_synthesize_crossing_events_for_geometry_change (window);
8256 do_child_input_shapes (GdkWindow *window,
8259 GdkWindowObject *private;
8263 private = (GdkWindowObject *) window;
8267 r.width = private->width;
8268 r.height = private->height;
8270 region = gdk_region_rectangle (&r);
8271 remove_child_area (private, NULL, TRUE, region);
8273 if (merge && private->shape)
8274 gdk_region_subtract (region, private->shape);
8275 if (merge && private->input_shape)
8276 gdk_region_subtract (region, private->input_shape);
8278 gdk_window_input_shape_combine_region (window, region, 0, 0);
8283 * gdk_window_set_child_input_shapes:
8284 * @window: a #GdkWindow
8286 * Sets the input shape mask of @window to the union of input shape masks
8287 * for all children of @window, ignoring the input shape mask of @window
8288 * itself. Contrast with gdk_window_merge_child_input_shapes() which includes
8289 * the input shape mask of @window in the masks to be merged.
8294 gdk_window_set_child_input_shapes (GdkWindow *window)
8296 g_return_if_fail (GDK_IS_WINDOW (window));
8298 do_child_input_shapes (window, FALSE);
8302 * gdk_window_merge_child_input_shapes:
8303 * @window: a #GdkWindow
8305 * Merges the input shape masks for any child windows into the
8306 * input shape mask for @window. i.e. the union of all input masks
8307 * for @window and its children will become the new input mask
8308 * for @window. See gdk_window_input_shape_combine_mask().
8310 * This function is distinct from gdk_window_set_child_input_shapes()
8311 * because it includes @window's input shape mask in the set of
8312 * shapes to be merged.
8317 gdk_window_merge_child_input_shapes (GdkWindow *window)
8319 g_return_if_fail (GDK_IS_WINDOW (window));
8321 do_child_input_shapes (window, TRUE);
8326 * gdk_window_set_static_gravities:
8327 * @window: a #GdkWindow
8328 * @use_static: %TRUE to turn on static gravity
8330 * Set the bit gravity of the given window to static, and flag it so
8331 * all children get static subwindow gravity. This is used if you are
8332 * implementing scary features that involve deep knowledge of the
8333 * windowing system. Don't worry about it unless you have to.
8335 * Return value: %TRUE if the server supports static gravity
8338 gdk_window_set_static_gravities (GdkWindow *window,
8339 gboolean use_static)
8341 GdkWindowObject *private;
8342 GdkWindowImplIface *impl_iface;
8344 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
8346 private = (GdkWindowObject *) window;
8348 if (gdk_window_has_impl (private))
8350 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (private->impl);
8351 return impl_iface->set_static_gravities (window, use_static);
8358 * gdk_window_set_composited:
8359 * @window: a #GdkWindow
8360 * @composited: %TRUE to set the window as composited
8362 * Sets a #GdkWindow as composited, or unsets it. Composited
8363 * windows do not automatically have their contents drawn to
8364 * the screen. Drawing is redirected to an offscreen buffer
8365 * and an expose event is emitted on the parent of the composited
8366 * window. It is the responsibility of the parent's expose handler
8367 * to manually merge the off-screen content onto the screen in
8368 * whatever way it sees fit. See <xref linkend="composited-window-example"/>
8371 * It only makes sense for child windows to be composited; see
8372 * gdk_window_set_opacity() if you need translucent toplevel
8375 * An additional effect of this call is that the area of this
8376 * window is no longer clipped from regions marked for
8377 * invalidation on its parent. Draws done on the parent
8378 * window are also no longer clipped by the child.
8380 * This call is only supported on some systems (currently,
8381 * only X11 with new enough Xcomposite and Xdamage extensions).
8382 * You must call gdk_display_supports_composite() to check if
8383 * setting a window as composited is supported before
8384 * attempting to do so.
8389 gdk_window_set_composited (GdkWindow *window,
8390 gboolean composited)
8392 GdkWindowObject *private = (GdkWindowObject *)window;
8393 GdkDisplay *display;
8395 g_return_if_fail (GDK_IS_WINDOW (window));
8397 composited = composited != FALSE;
8399 if (private->composited == composited)
8403 gdk_window_ensure_native (window);
8405 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
8407 if (!gdk_display_supports_composite (display) && composited)
8409 g_warning ("gdk_window_set_composited called but "
8410 "compositing is not supported");
8414 _gdk_windowing_window_set_composited (window, composited);
8416 recompute_visible_regions (private, TRUE, FALSE);
8418 if (GDK_WINDOW_IS_MAPPED (window))
8419 gdk_window_invalidate_in_parent (private);
8421 private->composited = composited;
8426 remove_redirect_from_children (GdkWindowObject *private,
8427 GdkWindowRedirect *redirect)
8430 GdkWindowObject *child;
8432 for (l = private->children; l != NULL; l = l->next)
8436 /* Don't redirect this child if it already has another redirect */
8437 if (child->redirect == redirect)
8439 child->redirect = NULL;
8440 remove_redirect_from_children (child, redirect);
8446 * gdk_window_remove_redirection:
8447 * @window: a #GdkWindow
8449 * Removes any active redirection started by
8450 * gdk_window_redirect_to_drawable().
8455 gdk_window_remove_redirection (GdkWindow *window)
8457 GdkWindowObject *private;
8459 g_return_if_fail (GDK_IS_WINDOW (window));
8461 private = (GdkWindowObject *) window;
8463 if (private->redirect &&
8464 private->redirect->redirected == private)
8466 remove_redirect_from_children (private, private->redirect);
8467 gdk_window_redirect_free (private->redirect);
8468 private->redirect = NULL;
8473 apply_redirect_to_children (GdkWindowObject *private,
8474 GdkWindowRedirect *redirect)
8477 GdkWindowObject *child;
8479 for (l = private->children; l != NULL; l = l->next)
8483 /* Don't redirect this child if it already has another redirect */
8484 if (!child->redirect)
8486 child->redirect = redirect;
8487 apply_redirect_to_children (child, redirect);
8493 * gdk_window_redirect_to_drawable:
8494 * @window: a #GdkWindow
8495 * @drawable: a #GdkDrawable
8496 * @src_x: x position in @window
8497 * @src_y: y position in @window
8498 * @dest_x: x position in @drawable
8499 * @dest_y: y position in @drawable
8500 * @width: width of redirection, or -1 to use the width of @window
8501 * @height: height of redirection or -1 to use the height of @window
8503 * Redirects drawing into @window so that drawing to the
8504 * window in the rectangle specified by @src_x, @src_y,
8505 * @width and @height is also drawn into @drawable at
8508 * Only drawing between gdk_window_begin_paint_region() or
8509 * gdk_window_begin_paint_rect() and gdk_window_end_paint() is
8512 * Redirection is active until gdk_window_remove_redirection()
8518 gdk_window_redirect_to_drawable (GdkWindow *window,
8519 GdkDrawable *drawable,
8527 GdkWindowObject *private;
8529 g_return_if_fail (GDK_IS_WINDOW (window));
8530 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
8531 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
8533 private = (GdkWindowObject *) window;
8535 if (private->redirect)
8536 gdk_window_remove_redirection (window);
8538 if (width == -1 || height == -1)
8541 gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
8548 private->redirect = g_new0 (GdkWindowRedirect, 1);
8549 private->redirect->redirected = private;
8550 private->redirect->pixmap = g_object_ref (drawable);
8551 private->redirect->src_x = src_x;
8552 private->redirect->src_y = src_y;
8553 private->redirect->dest_x = dest_x;
8554 private->redirect->dest_y = dest_y;
8555 private->redirect->width = width;
8556 private->redirect->height = height;
8558 apply_redirect_to_children (private, private->redirect);
8562 window_get_size_rectangle (GdkWindow *window,
8565 GdkWindowObject *private = (GdkWindowObject *) window;
8567 rect->x = rect->y = 0;
8568 rect->width = private->width;
8569 rect->height = private->height;
8572 /* Calculates the real clipping region for a window, in window coordinates,
8573 * taking into account other windows, gc clip region and gc clip mask.
8576 _gdk_window_calculate_full_clip_region (GdkWindow *window,
8577 GdkWindow *base_window,
8578 gboolean do_children,
8579 gint *base_x_offset,
8580 gint *base_y_offset)
8582 GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
8583 GdkRectangle visible_rect;
8584 GdkRegion *real_clip_region, *tmpreg;
8585 gint x_offset, y_offset;
8586 GdkWindowObject *parentwin, *lastwin;
8593 if (!private->viewable || private->input_only)
8594 return gdk_region_new ();
8596 window_get_size_rectangle (window, &visible_rect);
8598 /* real_clip_region is in window coordinates */
8599 real_clip_region = gdk_region_rectangle (&visible_rect);
8601 x_offset = y_offset = 0;
8605 parentwin = lastwin;
8607 parentwin = lastwin->parent;
8609 /* Remove the areas of all overlapping windows above parentwin in the hiearachy */
8610 for (; parentwin != NULL &&
8611 (parentwin == private || lastwin != (GdkWindowObject*) base_window);
8612 lastwin = parentwin, parentwin = lastwin->parent)
8615 GdkRectangle real_clip_rect;
8617 if (parentwin != private)
8619 x_offset += GDK_WINDOW_OBJECT (lastwin)->x;
8620 y_offset += GDK_WINDOW_OBJECT (lastwin)->y;
8623 /* children is ordered in reverse stack order */
8624 for (cur = parentwin->children;
8625 cur && cur->data != lastwin;
8628 GdkWindow *child = cur->data;
8629 GdkWindowObject *child_private = (GdkWindowObject *)child;
8631 if (!GDK_WINDOW_IS_MAPPED (child) || child_private->input_only)
8634 /* Ignore offscreen children, as they don't draw in their parent and
8635 * don't take part in the clipping */
8636 if (gdk_window_is_offscreen (child_private))
8639 window_get_size_rectangle (child, &visible_rect);
8641 /* Convert rect to "window" coords */
8642 visible_rect.x += child_private->x - x_offset;
8643 visible_rect.y += child_private->y - y_offset;
8645 /* This shortcut is really necessary for performance when there are a lot of windows */
8646 gdk_region_get_clipbox (real_clip_region, &real_clip_rect);
8647 if (visible_rect.x >= real_clip_rect.x + real_clip_rect.width ||
8648 visible_rect.x + visible_rect.width <= real_clip_rect.x ||
8649 visible_rect.y >= real_clip_rect.y + real_clip_rect.height ||
8650 visible_rect.y + visible_rect.height <= real_clip_rect.y)
8653 tmpreg = gdk_region_rectangle (&visible_rect);
8654 gdk_region_subtract (real_clip_region, tmpreg);
8655 gdk_region_destroy (tmpreg);
8658 /* Clip to the parent */
8659 window_get_size_rectangle ((GdkWindow *)parentwin, &visible_rect);
8660 /* Convert rect to "window" coords */
8661 visible_rect.x += - x_offset;
8662 visible_rect.y += - y_offset;
8664 tmpreg = gdk_region_rectangle (&visible_rect);
8665 gdk_region_intersect (real_clip_region, tmpreg);
8666 gdk_region_destroy (tmpreg);
8670 *base_x_offset = x_offset;
8672 *base_y_offset = y_offset;
8674 return real_clip_region;
8678 _gdk_window_add_damage (GdkWindow *toplevel,
8679 GdkRegion *damaged_region)
8681 GdkDisplay *display;
8682 GdkEvent event = { 0, };
8683 event.expose.type = GDK_DAMAGE;
8684 event.expose.window = toplevel;
8685 event.expose.send_event = FALSE;
8686 event.expose.region = damaged_region;
8687 gdk_region_get_clipbox (event.expose.region, &event.expose.area);
8688 display = gdk_drawable_get_display (event.expose.window);
8689 _gdk_event_queue_append (display, gdk_event_copy (&event));
8693 gdk_window_redirect_free (GdkWindowRedirect *redirect)
8695 g_object_unref (redirect->pixmap);
8699 /* Gets the toplevel for a window as used for events,
8700 i.e. including offscreen parents */
8701 static GdkWindowObject *
8702 get_event_parent (GdkWindowObject *window)
8704 if (window->window_type == GDK_WINDOW_OFFSCREEN)
8705 return (GdkWindowObject *)gdk_offscreen_window_get_embedder ((GdkWindow *)window);
8707 return window->parent;
8710 /* Gets the toplevel for a window as used for events,
8711 i.e. including offscreen parents going up to the native
8714 get_event_toplevel (GdkWindow *w)
8716 GdkWindowObject *private = GDK_WINDOW_OBJECT (w);
8717 GdkWindowObject *parent;
8719 while ((parent = get_event_parent (private)) != NULL &&
8720 (parent->window_type != GDK_WINDOW_ROOT))
8723 return GDK_WINDOW (private);
8727 _gdk_window_event_parent_of (GdkWindow *parent,
8738 w = (GdkWindow *)get_event_parent ((GdkWindowObject *)w);
8745 update_cursor (GdkDisplay *display)
8747 GdkWindowObject *cursor_window, *parent, *toplevel;
8748 GdkWindow *pointer_window;
8749 GdkWindowImplIface *impl_iface;
8750 GdkPointerGrabInfo *grab;
8752 pointer_window = display->pointer_info.window_under_pointer;
8754 /* We ignore the serials here and just pick the last grab
8755 we've sent, as that would shortly be used anyway. */
8756 grab = _gdk_display_get_last_pointer_grab (display);
8759 /* the pointer is not in a descendant of the grab window */
8760 !_gdk_window_event_parent_of (grab->window, pointer_window))
8761 /* use the cursor from the grab window */
8762 cursor_window = (GdkWindowObject *)grab->window;
8764 /* otherwise use the cursor from the pointer window */
8765 cursor_window = (GdkWindowObject *)pointer_window;
8767 /* Find the first window with the cursor actually set, as
8768 the cursor is inherited from the parent */
8769 while (cursor_window->cursor == NULL &&
8770 (parent = get_event_parent (cursor_window)) != NULL &&
8771 parent->window_type != GDK_WINDOW_ROOT)
8772 cursor_window = parent;
8774 /* Set all cursors on toplevel, otherwise its tricky to keep track of
8775 * which native window has what cursor set. */
8776 toplevel = (GdkWindowObject *)get_event_toplevel (pointer_window);
8777 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (toplevel->impl);
8778 impl_iface->set_cursor ((GdkWindow *)toplevel, cursor_window->cursor);
8782 from_embedder (GdkWindowObject *window,
8785 gdouble *offscreen_x,
8786 gdouble *offscreen_y)
8788 g_signal_emit (window,
8789 signals[FROM_EMBEDDER], 0,
8790 embedder_x, embedder_y,
8791 offscreen_x, offscreen_y,
8796 convert_coords_to_child (GdkWindowObject *child,
8802 if (gdk_window_is_offscreen (child))
8804 from_embedder (child, x, y,
8809 *child_x = x - child->x;
8810 *child_y = y - child->y;
8815 point_in_window (GdkWindowObject *window,
8820 x >= 0 && x < window->width &&
8821 y >= 0 && y < window->height &&
8822 (window->shape == NULL ||
8823 gdk_region_point_in (window->shape,
8825 (window->input_shape == NULL ||
8826 gdk_region_point_in (window->input_shape,
8831 convert_native_coords_to_toplevel (GdkWindow *window,
8834 gdouble *toplevel_x,
8835 gdouble *toplevel_y)
8837 GdkWindowObject *private = (GdkWindowObject *)window;
8843 while (!gdk_window_is_toplevel (private))
8847 private = private->parent;
8853 return (GdkWindow *)private;
8857 convert_toplevel_coords_to_window (GdkWindow *window,
8863 GdkWindowObject *private;
8864 GdkWindowObject *parent;
8866 GList *children, *l;
8868 private = GDK_WINDOW_OBJECT (window);
8874 while ((parent = get_event_parent (private)) != NULL &&
8875 (parent->window_type != GDK_WINDOW_ROOT))
8877 children = g_list_prepend (children, private);
8881 for (l = children; l != NULL; l = l->next)
8882 convert_coords_to_child (l->data, x, y, &x, &y);
8884 g_list_free (children);
8890 static GdkWindowObject *
8891 pick_embedded_child (GdkWindowObject *window,
8895 GdkWindowObject *res;
8898 g_signal_emit (window,
8899 signals[PICK_EMBEDDED_CHILD], 0,
8906 _gdk_window_find_child_at (GdkWindow *window,
8910 GdkWindowObject *private, *sub;
8911 double child_x, child_y;
8914 private = (GdkWindowObject *)window;
8916 if (point_in_window (private, x, y))
8918 /* Children is ordered in reverse stack order, i.e. first is topmost */
8919 for (l = private->children; l != NULL; l = l->next)
8923 if (!GDK_WINDOW_IS_MAPPED (sub))
8926 convert_coords_to_child (sub,
8928 &child_x, &child_y);
8929 if (point_in_window (sub, child_x, child_y))
8930 return (GdkWindow *)sub;
8933 if (private->num_offscreen_children > 0)
8935 sub = pick_embedded_child (private,
8938 return (GdkWindow *)sub;
8946 _gdk_window_find_descendant_at (GdkWindow *toplevel,
8952 GdkWindowObject *private, *sub;
8953 gdouble child_x, child_y;
8957 private = (GdkWindowObject *)toplevel;
8959 if (point_in_window (private, x, y))
8964 /* Children is ordered in reverse stack order, i.e. first is topmost */
8965 for (l = private->children; l != NULL; l = l->next)
8969 if (!GDK_WINDOW_IS_MAPPED (sub))
8972 convert_coords_to_child (sub,
8974 &child_x, &child_y);
8975 if (point_in_window (sub, child_x, child_y))
8985 private->num_offscreen_children > 0)
8987 sub = pick_embedded_child (private,
8993 from_embedder (sub, x, y, &x, &y);
9001 /* Not in window at all */
9010 return (GdkWindow *)private;
9015 * @window: a toplevel #GdkWindow
9017 * Emits a short beep associated to @window in the appropriate
9018 * display, if supported. Otherwise, emits a short beep on
9019 * the display just as gdk_display_beep().
9024 gdk_window_beep (GdkWindow *window)
9026 GdkDisplay *display;
9027 GdkWindow *toplevel;
9029 g_return_if_fail (GDK_IS_WINDOW (window));
9031 if (GDK_WINDOW_DESTROYED (window))
9034 toplevel = get_event_toplevel (window);
9035 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
9037 if (toplevel && !gdk_window_is_offscreen ((GdkWindowObject *)toplevel))
9038 _gdk_windowing_window_beep (toplevel);
9040 gdk_display_beep (display);
9043 static const guint type_masks[] = {
9044 GDK_SUBSTRUCTURE_MASK, /* GDK_DELETE = 0 */
9045 GDK_STRUCTURE_MASK, /* GDK_DESTROY = 1 */
9046 GDK_EXPOSURE_MASK, /* GDK_EXPOSE = 2 */
9047 GDK_POINTER_MOTION_MASK, /* GDK_MOTION_NOTIFY = 3 */
9048 GDK_BUTTON_PRESS_MASK, /* GDK_BUTTON_PRESS = 4 */
9049 GDK_BUTTON_PRESS_MASK, /* GDK_2BUTTON_PRESS = 5 */
9050 GDK_BUTTON_PRESS_MASK, /* GDK_3BUTTON_PRESS = 6 */
9051 GDK_BUTTON_RELEASE_MASK, /* GDK_BUTTON_RELEASE = 7 */
9052 GDK_KEY_PRESS_MASK, /* GDK_KEY_PRESS = 8 */
9053 GDK_KEY_RELEASE_MASK, /* GDK_KEY_RELEASE = 9 */
9054 GDK_ENTER_NOTIFY_MASK, /* GDK_ENTER_NOTIFY = 10 */
9055 GDK_LEAVE_NOTIFY_MASK, /* GDK_LEAVE_NOTIFY = 11 */
9056 GDK_FOCUS_CHANGE_MASK, /* GDK_FOCUS_CHANGE = 12 */
9057 GDK_STRUCTURE_MASK, /* GDK_CONFIGURE = 13 */
9058 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_MAP = 14 */
9059 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_UNMAP = 15 */
9060 GDK_PROPERTY_CHANGE_MASK, /* GDK_PROPERTY_NOTIFY = 16 */
9061 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_CLEAR = 17 */
9062 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_REQUEST = 18 */
9063 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_NOTIFY = 19 */
9064 GDK_PROXIMITY_IN_MASK, /* GDK_PROXIMITY_IN = 20 */
9065 GDK_PROXIMITY_OUT_MASK, /* GDK_PROXIMITY_OUT = 21 */
9066 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_ENTER = 22 */
9067 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_LEAVE = 23 */
9068 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_MOTION = 24 */
9069 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_STATUS = 25 */
9070 GDK_ALL_EVENTS_MASK, /* GDK_DROP_START = 26 */
9071 GDK_ALL_EVENTS_MASK, /* GDK_DROP_FINISHED = 27 */
9072 GDK_ALL_EVENTS_MASK, /* GDK_CLIENT_EVENT = 28 */
9073 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_VISIBILITY_NOTIFY = 29 */
9074 GDK_EXPOSURE_MASK, /* GDK_NO_EXPOSE = 30 */
9075 GDK_SCROLL_MASK | GDK_BUTTON_PRESS_MASK,/* GDK_SCROLL= 31 */
9076 0, /* GDK_WINDOW_STATE = 32 */
9077 0, /* GDK_SETTING = 33 */
9078 0, /* GDK_OWNER_CHANGE = 34 */
9079 0, /* GDK_GRAB_BROKEN = 35 */
9080 0, /* GDK_DAMAGE = 36 */
9082 G_STATIC_ASSERT (G_N_ELEMENTS (type_masks) == GDK_EVENT_LAST);
9084 /* send motion events if the right buttons are down */
9086 update_evmask_for_button_motion (guint evmask,
9087 GdkModifierType mask)
9089 if (evmask & GDK_BUTTON_MOTION_MASK &&
9090 mask & (GDK_BUTTON1_MASK |
9095 evmask |= GDK_POINTER_MOTION_MASK;
9097 if ((evmask & GDK_BUTTON1_MOTION_MASK && mask & GDK_BUTTON1_MASK) ||
9098 (evmask & GDK_BUTTON2_MOTION_MASK && mask & GDK_BUTTON2_MASK) ||
9099 (evmask & GDK_BUTTON3_MOTION_MASK && mask & GDK_BUTTON3_MASK))
9100 evmask |= GDK_POINTER_MOTION_MASK;
9106 is_button_type (GdkEventType type)
9108 return type == GDK_BUTTON_PRESS ||
9109 type == GDK_2BUTTON_PRESS ||
9110 type == GDK_3BUTTON_PRESS ||
9111 type == GDK_BUTTON_RELEASE ||
9116 is_motion_type (GdkEventType type)
9118 return type == GDK_MOTION_NOTIFY ||
9119 type == GDK_ENTER_NOTIFY ||
9120 type == GDK_LEAVE_NOTIFY;
9123 static GdkWindowObject *
9124 find_common_ancestor (GdkWindowObject *win1,
9125 GdkWindowObject *win2)
9127 GdkWindowObject *tmp;
9128 GList *path1 = NULL, *path2 = NULL;
9129 GList *list1, *list2;
9132 while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
9134 path1 = g_list_prepend (path1, tmp);
9135 tmp = get_event_parent (tmp);
9139 while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
9141 path2 = g_list_prepend (path2, tmp);
9142 tmp = get_event_parent (tmp);
9148 while (list1 && list2 && (list1->data == list2->data))
9150 tmp = (GdkWindowObject *)list1->data;
9151 list1 = g_list_next (list1);
9152 list2 = g_list_next (list2);
9154 g_list_free (path1);
9155 g_list_free (path2);
9161 _gdk_make_event (GdkWindow *window,
9163 GdkEvent *event_in_queue,
9164 gboolean before_event)
9166 GdkEvent *event = gdk_event_new (type);
9168 GdkModifierType the_state;
9170 the_time = gdk_event_get_time (event_in_queue);
9171 gdk_event_get_state (event_in_queue, &the_state);
9173 event->any.window = g_object_ref (window);
9174 event->any.send_event = FALSE;
9175 if (event_in_queue && event_in_queue->any.send_event)
9176 event->any.send_event = TRUE;
9180 case GDK_MOTION_NOTIFY:
9181 event->motion.time = the_time;
9182 event->motion.axes = NULL;
9183 event->motion.state = the_state;
9186 case GDK_BUTTON_PRESS:
9187 case GDK_2BUTTON_PRESS:
9188 case GDK_3BUTTON_PRESS:
9189 case GDK_BUTTON_RELEASE:
9190 event->button.time = the_time;
9191 event->button.axes = NULL;
9192 event->button.state = the_state;
9196 event->scroll.time = the_time;
9197 event->scroll.state = the_state;
9201 case GDK_KEY_RELEASE:
9202 event->key.time = the_time;
9203 event->key.state = the_state;
9206 case GDK_ENTER_NOTIFY:
9207 case GDK_LEAVE_NOTIFY:
9208 event->crossing.time = the_time;
9209 event->crossing.state = the_state;
9212 case GDK_PROPERTY_NOTIFY:
9213 event->property.time = the_time;
9214 event->property.state = the_state;
9217 case GDK_SELECTION_CLEAR:
9218 case GDK_SELECTION_REQUEST:
9219 case GDK_SELECTION_NOTIFY:
9220 event->selection.time = the_time;
9223 case GDK_PROXIMITY_IN:
9224 case GDK_PROXIMITY_OUT:
9225 event->proximity.time = the_time;
9228 case GDK_DRAG_ENTER:
9229 case GDK_DRAG_LEAVE:
9230 case GDK_DRAG_MOTION:
9231 case GDK_DRAG_STATUS:
9232 case GDK_DROP_START:
9233 case GDK_DROP_FINISHED:
9234 event->dnd.time = the_time;
9237 case GDK_FOCUS_CHANGE:
9241 case GDK_CLIENT_EVENT:
9242 case GDK_VISIBILITY_NOTIFY:
9254 _gdk_event_queue_insert_before (gdk_drawable_get_display (window), event_in_queue, event);
9256 _gdk_event_queue_insert_after (gdk_drawable_get_display (window), event_in_queue, event);
9259 _gdk_event_queue_append (gdk_drawable_get_display (window), event);
9265 send_crossing_event (GdkDisplay *display,
9266 GdkWindowObject *toplevel,
9267 GdkWindowObject *window,
9269 GdkCrossingMode mode,
9270 GdkNotifyType notify_type,
9271 GdkWindow *subwindow,
9274 GdkModifierType mask,
9276 GdkEvent *event_in_queue,
9280 guint32 window_event_mask, type_event_mask;
9281 GdkPointerGrabInfo *grab;
9282 GdkWindowImplIface *impl_iface;
9284 grab = _gdk_display_has_pointer_grab (display, serial);
9287 !grab->owner_events)
9289 /* !owner_event => only report events wrt grab window, ignore rest */
9290 if ((GdkWindow *)window != grab->window)
9292 window_event_mask = grab->event_mask;
9295 window_event_mask = window->event_mask;
9297 if (type == GDK_LEAVE_NOTIFY)
9298 type_event_mask = GDK_LEAVE_NOTIFY_MASK;
9300 type_event_mask = GDK_ENTER_NOTIFY_MASK;
9302 if (window->extension_events != 0)
9304 impl_iface = GDK_WINDOW_IMPL_GET_IFACE (window->impl);
9305 impl_iface->input_window_crossing ((GdkWindow *)window,
9306 type == GDK_ENTER_NOTIFY);
9309 if (window_event_mask & type_event_mask)
9311 event = _gdk_make_event ((GdkWindow *)window, type, event_in_queue, TRUE);
9312 event->crossing.time = time_;
9313 event->crossing.subwindow = subwindow;
9315 g_object_ref (subwindow);
9316 convert_toplevel_coords_to_window ((GdkWindow *)window,
9317 toplevel_x, toplevel_y,
9318 &event->crossing.x, &event->crossing.y);
9319 event->crossing.x_root = toplevel_x + toplevel->x;
9320 event->crossing.y_root = toplevel_y + toplevel->y;
9321 event->crossing.mode = mode;
9322 event->crossing.detail = notify_type;
9323 event->crossing.focus = FALSE;
9324 event->crossing.state = mask;
9329 /* The coordinates are in the toplevel window that src/dest are in.
9330 * src and dest are always (if != NULL) in the same toplevel, as
9331 * we get a leave-notify and set the window_under_pointer to null
9332 * before crossing to another toplevel.
9335 _gdk_synthesize_crossing_events (GdkDisplay *display,
9338 GdkCrossingMode mode,
9341 GdkModifierType mask,
9343 GdkEvent *event_in_queue,
9345 gboolean non_linear)
9348 GdkWindowObject *win, *last, *next;
9352 GdkWindowObject *toplevel;
9353 GdkNotifyType notify_type;
9355 /* TODO: Don't send events to toplevel, as we get those from the windowing system */
9357 a = (GdkWindowObject *)src;
9358 b = (GdkWindowObject *)dest;
9360 return; /* No crossings generated between src and dest */
9362 c = find_common_ancestor (a, b);
9364 non_linear |= (c != a) && (c != b);
9366 if (a) /* There might not be a source (i.e. if no previous pointer_in_window) */
9368 toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)a);
9370 /* Traverse up from a to (excluding) c sending leave events */
9372 notify_type = GDK_NOTIFY_NONLINEAR;
9374 notify_type = GDK_NOTIFY_INFERIOR;
9376 notify_type = GDK_NOTIFY_ANCESTOR;
9377 send_crossing_event (display, toplevel,
9378 a, GDK_LEAVE_NOTIFY,
9382 toplevel_x, toplevel_y,
9390 notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
9392 notify_type = GDK_NOTIFY_VIRTUAL;
9395 win = get_event_parent (a);
9396 while (win != c && win->window_type != GDK_WINDOW_ROOT)
9398 send_crossing_event (display, toplevel,
9399 win, GDK_LEAVE_NOTIFY,
9403 toplevel_x, toplevel_y,
9409 win = get_event_parent (win);
9414 if (b) /* Might not be a dest, e.g. if we're moving out of the window */
9416 toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)b);
9418 /* Traverse down from c to b */
9422 win = get_event_parent (b);
9423 while (win != c && win->window_type != GDK_WINDOW_ROOT)
9425 path = g_list_prepend (path, win);
9426 win = get_event_parent (win);
9430 notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
9432 notify_type = GDK_NOTIFY_VIRTUAL;
9437 win = (GdkWindowObject *)list->data;
9438 list = g_list_next (list);
9440 next = (GdkWindowObject *)list->data;
9444 send_crossing_event (display, toplevel,
9445 win, GDK_ENTER_NOTIFY,
9449 toplevel_x, toplevel_y,
9459 notify_type = GDK_NOTIFY_NONLINEAR;
9461 notify_type = GDK_NOTIFY_ANCESTOR;
9463 notify_type = GDK_NOTIFY_INFERIOR;
9465 send_crossing_event (display, toplevel,
9466 b, GDK_ENTER_NOTIFY,
9470 toplevel_x, toplevel_y,
9477 /* Returns the window inside the event window with the pointer in it
9478 * at the specified coordinates, or NULL if its not in any child of
9479 * the toplevel. It also takes into account !owner_events grabs.
9482 get_pointer_window (GdkDisplay *display,
9483 GdkWindow *event_window,
9488 GdkWindow *pointer_window;
9489 GdkPointerGrabInfo *grab;
9491 if (event_window == display->pointer_info.toplevel_under_pointer)
9493 _gdk_window_find_descendant_at (event_window,
9494 toplevel_x, toplevel_y,
9497 pointer_window = NULL;
9499 grab = _gdk_display_has_pointer_grab (display, serial);
9501 !grab->owner_events &&
9502 pointer_window != grab->window)
9503 pointer_window = NULL;
9505 return pointer_window;
9509 _gdk_display_set_window_under_pointer (GdkDisplay *display,
9512 /* We don't track this if all native, and it can cause issues
9513 with the update_cursor call below */
9514 if (_gdk_native_windows)
9517 if (display->pointer_info.window_under_pointer)
9518 g_object_unref (display->pointer_info.window_under_pointer);
9519 display->pointer_info.window_under_pointer = window;
9521 g_object_ref (window);
9524 update_cursor (display);
9526 _gdk_display_enable_motion_hints (display);
9530 *--------------------------------------------------------------
9533 * Grabs the pointer to a specific window
9536 * "window" is the window which will receive the grab
9537 * "owner_events" specifies whether events will be reported as is,
9538 * or relative to "window"
9539 * "event_mask" masks only interesting events
9540 * "confine_to" limits the cursor movement to the specified window
9541 * "cursor" changes the cursor for the duration of the grab
9542 * "time" specifies the time
9547 * requires a corresponding call to gdk_pointer_ungrab
9549 *--------------------------------------------------------------
9552 gdk_pointer_grab (GdkWindow * window,
9553 gboolean owner_events,
9554 GdkEventMask event_mask,
9555 GdkWindow * confine_to,
9560 GdkDisplay *display;
9564 g_return_val_if_fail (window != NULL, 0);
9565 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
9566 g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
9568 /* We need a native window for confine to to work, ensure we have one */
9571 if (!gdk_window_ensure_native (confine_to))
9573 g_warning ("Can't confine to grabbed window, not native");
9578 /* Non-viewable client side window => fail */
9579 if (!_gdk_window_has_impl (window) &&
9580 !gdk_window_is_viewable (window))
9581 return GDK_GRAB_NOT_VIEWABLE;
9583 if (_gdk_native_windows)
9586 native = gdk_window_get_toplevel (window);
9587 while (gdk_window_is_offscreen ((GdkWindowObject *)native))
9589 native = gdk_offscreen_window_get_embedder (native);
9591 if (native == NULL ||
9592 (!_gdk_window_has_impl (native) &&
9593 !gdk_window_is_viewable (native)))
9594 return GDK_GRAB_NOT_VIEWABLE;
9596 native = gdk_window_get_toplevel (native);
9599 display = gdk_drawable_get_display (window);
9601 serial = _gdk_windowing_window_get_next_serial (display);
9603 res = _gdk_windowing_pointer_grab (window,
9606 get_native_grab_event_mask (event_mask),
9611 if (res == GDK_GRAB_SUCCESS)
9612 _gdk_display_add_pointer_grab (display,
9625 * gdk_window_geometry_changed:
9626 * @window: an embedded offscreen #GdkWindow
9628 * This function informs GDK that the geometry of an embedded
9629 * offscreen window has changed. This is necessary for GDK to keep
9630 * track of which offscreen window the pointer is in.
9635 gdk_window_geometry_changed (GdkWindow *window)
9637 _gdk_synthesize_crossing_events_for_geometry_change (window);
9641 do_synthesize_crossing_event (gpointer data)
9643 GdkDisplay *display;
9644 GdkWindow *changed_toplevel;
9645 GdkWindowObject *changed_toplevel_priv;
9646 GdkWindow *new_window_under_pointer;
9649 changed_toplevel = data;
9650 changed_toplevel_priv = (GdkWindowObject *)changed_toplevel;
9652 changed_toplevel_priv->synthesize_crossing_event_queued = FALSE;
9654 if (GDK_WINDOW_DESTROYED (changed_toplevel))
9657 display = gdk_drawable_get_display (changed_toplevel);
9658 serial = _gdk_windowing_window_get_next_serial (display);
9660 if (changed_toplevel == display->pointer_info.toplevel_under_pointer)
9662 new_window_under_pointer =
9663 get_pointer_window (display, changed_toplevel,
9664 display->pointer_info.toplevel_x,
9665 display->pointer_info.toplevel_y,
9667 if (new_window_under_pointer !=
9668 display->pointer_info.window_under_pointer)
9670 _gdk_synthesize_crossing_events (display,
9671 display->pointer_info.window_under_pointer,
9672 new_window_under_pointer,
9673 GDK_CROSSING_NORMAL,
9674 display->pointer_info.toplevel_x,
9675 display->pointer_info.toplevel_y,
9676 display->pointer_info.state,
9681 _gdk_display_set_window_under_pointer (display, new_window_under_pointer);
9689 _gdk_synthesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
9691 GdkDisplay *display;
9692 GdkWindow *toplevel;
9693 GdkWindowObject *toplevel_priv;
9695 if (_gdk_native_windows)
9696 return; /* We use the native crossing events if all native */
9698 display = gdk_drawable_get_display (changed_window);
9700 toplevel = get_event_toplevel (changed_window);
9701 toplevel_priv = (GdkWindowObject *)toplevel;
9703 if (toplevel == display->pointer_info.toplevel_under_pointer &&
9704 !toplevel_priv->synthesize_crossing_event_queued)
9706 toplevel_priv->synthesize_crossing_event_queued = TRUE;
9707 g_idle_add_full (GDK_PRIORITY_EVENTS - 1,
9708 do_synthesize_crossing_event,
9709 g_object_ref (toplevel),
9714 /* Don't use for crossing events */
9716 get_event_window (GdkDisplay *display,
9717 GdkWindow *pointer_window,
9719 GdkModifierType mask,
9724 GdkWindow *grab_window;
9726 GdkPointerGrabInfo *grab;
9728 grab = _gdk_display_has_pointer_grab (display, serial);
9730 if (grab != NULL && !grab->owner_events)
9732 evmask = grab->event_mask;
9733 evmask = update_evmask_for_button_motion (evmask, mask);
9735 grab_window = grab->window;
9737 if (evmask & type_masks[type])
9740 *evmask_out = evmask;
9747 w = (GdkWindowObject *)pointer_window;
9750 evmask = w->event_mask;
9751 evmask = update_evmask_for_button_motion (evmask, mask);
9753 if (evmask & type_masks[type])
9756 *evmask_out = evmask;
9757 return (GdkWindow *)w;
9760 w = get_event_parent (w);
9766 evmask = grab->event_mask;
9767 evmask = update_evmask_for_button_motion (evmask, mask);
9769 if (evmask & type_masks[type])
9772 *evmask_out = evmask;
9773 return grab->window;
9783 proxy_pointer_event (GdkDisplay *display,
9784 GdkEvent *source_event,
9787 GdkWindow *toplevel_window, *event_window;
9788 GdkWindow *pointer_window;
9791 gdouble toplevel_x, toplevel_y;
9793 gboolean non_linear;
9795 event_window = source_event->any.window;
9796 gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
9797 gdk_event_get_state (source_event, &state);
9798 time_ = gdk_event_get_time (source_event);
9799 toplevel_window = convert_native_coords_to_toplevel (event_window,
9800 toplevel_x, toplevel_y,
9801 &toplevel_x, &toplevel_y);
9804 if ((source_event->type == GDK_LEAVE_NOTIFY ||
9805 source_event->type == GDK_ENTER_NOTIFY) &&
9806 (source_event->crossing.detail == GDK_NOTIFY_NONLINEAR ||
9807 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))
9810 /* If we get crossing events with subwindow unexpectedly being NULL
9811 that means there is a native subwindow that gdk doesn't know about.
9812 We track these and forward them, with the correct virtual window
9814 This is important to get right, as metacity uses gdk for the frame
9815 windows, but gdk doesn't know about the client windows reparented
9817 if (((source_event->type == GDK_LEAVE_NOTIFY &&
9818 source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
9819 (source_event->type == GDK_ENTER_NOTIFY &&
9820 (source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
9821 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
9822 source_event->crossing.subwindow == NULL)
9824 /* Left for an unknown (to gdk) subwindow */
9826 /* Send leave events from window under pointer to event window
9827 that will get the subwindow == NULL window */
9828 _gdk_synthesize_crossing_events (display,
9829 display->pointer_info.window_under_pointer,
9831 source_event->crossing.mode,
9832 toplevel_x, toplevel_y,
9838 /* Send subwindow == NULL event */
9839 send_crossing_event (display,
9840 (GdkWindowObject *)toplevel_window,
9841 (GdkWindowObject *)event_window,
9843 source_event->crossing.mode,
9844 source_event->crossing.detail,
9846 toplevel_x, toplevel_y,
9851 _gdk_display_set_window_under_pointer (display, NULL);
9855 pointer_window = get_pointer_window (display, toplevel_window,
9856 toplevel_x, toplevel_y, serial);
9858 if (((source_event->type == GDK_ENTER_NOTIFY &&
9859 source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
9860 (source_event->type == GDK_LEAVE_NOTIFY &&
9861 (source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
9862 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
9863 source_event->crossing.subwindow == NULL)
9865 /* Entered from an unknown (to gdk) subwindow */
9867 /* Send subwindow == NULL event */
9868 send_crossing_event (display,
9869 (GdkWindowObject *)toplevel_window,
9870 (GdkWindowObject *)event_window,
9872 source_event->crossing.mode,
9873 source_event->crossing.detail,
9875 toplevel_x, toplevel_y,
9880 /* Send enter events from event window to pointer_window */
9881 _gdk_synthesize_crossing_events (display,
9884 source_event->crossing.mode,
9885 toplevel_x, toplevel_y,
9888 serial, non_linear);
9889 _gdk_display_set_window_under_pointer (display, pointer_window);
9893 if (display->pointer_info.window_under_pointer != pointer_window)
9895 /* Either a toplevel crossing notify that ended up inside a child window,
9896 or a motion notify that got into another child window */
9898 /* Different than last time, send crossing events */
9899 _gdk_synthesize_crossing_events (display,
9900 display->pointer_info.window_under_pointer,
9902 GDK_CROSSING_NORMAL,
9903 toplevel_x, toplevel_y,
9906 serial, non_linear);
9907 _gdk_display_set_window_under_pointer (display, pointer_window);
9909 else if (source_event->type == GDK_MOTION_NOTIFY)
9911 GdkWindow *event_win;
9915 event_win = get_event_window (display,
9925 (evmask & GDK_POINTER_MOTION_HINT_MASK))
9927 if (display->pointer_info.motion_hint_serial != 0 &&
9928 serial < display->pointer_info.motion_hint_serial)
9929 event_win = NULL; /* Ignore event */
9933 display->pointer_info.motion_hint_serial = G_MAXULONG;
9937 if (event_win && !display->ignore_core_events)
9939 event = _gdk_make_event (event_win, GDK_MOTION_NOTIFY, source_event, FALSE);
9940 event->motion.time = time_;
9941 convert_toplevel_coords_to_window (event_win,
9942 toplevel_x, toplevel_y,
9943 &event->motion.x, &event->motion.y);
9944 event->motion.x_root = source_event->motion.x_root;
9945 event->motion.y_root = source_event->motion.y_root;;
9946 event->motion.state = state;
9947 event->motion.is_hint = is_hint;
9948 event->motion.device = NULL;
9949 event->motion.device = source_event->motion.device;
9953 /* unlink all move events from queue.
9954 We handle our own, including our emulated masks. */
9958 #define GDK_ANY_BUTTON_MASK (GDK_BUTTON1_MASK | \
9959 GDK_BUTTON2_MASK | \
9960 GDK_BUTTON3_MASK | \
9961 GDK_BUTTON4_MASK | \
9965 proxy_button_event (GdkEvent *source_event,
9968 GdkWindow *toplevel_window, *event_window;
9969 GdkWindow *event_win;
9970 GdkWindow *pointer_window;
9971 GdkWindowObject *parent;
9976 gdouble toplevel_x, toplevel_y;
9977 GdkDisplay *display;
9980 type = source_event->any.type;
9981 event_window = source_event->any.window;
9982 gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
9983 gdk_event_get_state (source_event, &state);
9984 time_ = gdk_event_get_time (source_event);
9985 display = gdk_drawable_get_display (source_event->any.window);
9986 toplevel_window = convert_native_coords_to_toplevel (event_window,
9987 toplevel_x, toplevel_y,
9988 &toplevel_x, &toplevel_y);
9990 if (type == GDK_BUTTON_PRESS &&
9991 !source_event->any.send_event &&
9992 _gdk_display_has_pointer_grab (display, serial) == NULL)
9995 _gdk_window_find_descendant_at (toplevel_window,
9996 toplevel_x, toplevel_y,
9999 /* Find the event window, that gets the grab */
10000 w = (GdkWindowObject *)pointer_window;
10001 while (w != NULL &&
10002 (parent = get_event_parent (w)) != NULL &&
10003 parent->window_type != GDK_WINDOW_ROOT)
10005 if (w->event_mask & GDK_BUTTON_PRESS_MASK)
10009 pointer_window = (GdkWindow *)w;
10011 _gdk_display_add_pointer_grab (display,
10015 gdk_window_get_events (pointer_window),
10019 _gdk_display_pointer_grab_update (display, serial);
10022 pointer_window = get_pointer_window (display, toplevel_window,
10023 toplevel_x, toplevel_y,
10026 event_win = get_event_window (display,
10031 if (event_win == NULL || display->ignore_core_events)
10034 event = _gdk_make_event (event_win, type, source_event, FALSE);
10038 case GDK_BUTTON_PRESS:
10039 case GDK_BUTTON_RELEASE:
10040 event->button.button = source_event->button.button;
10041 convert_toplevel_coords_to_window (event_win,
10042 toplevel_x, toplevel_y,
10043 &event->button.x, &event->button.y);
10044 event->button.x_root = source_event->button.x_root;
10045 event->button.y_root = source_event->button.y_root;
10046 event->button.state = state;
10047 event->button.device = source_event->button.device;
10049 if (type == GDK_BUTTON_PRESS)
10050 _gdk_event_button_generate (display, event);
10054 event->scroll.direction = source_event->scroll.direction;
10055 convert_toplevel_coords_to_window (event_win,
10056 toplevel_x, toplevel_y,
10057 &event->scroll.x, &event->scroll.y);
10058 event->scroll.x_root = source_event->scroll.x_root;
10059 event->scroll.y_root = source_event->scroll.y_root;
10060 event->scroll.state = state;
10061 event->scroll.device = source_event->scroll.device;
10068 return TRUE; /* Always unlink original, we want to obey the emulated event mask */
10071 #ifdef DEBUG_WINDOW_PRINTING
10073 gdk_window_print (GdkWindowObject *window,
10077 const char *window_types[] = {
10087 g_print ("%*s%p: [%s] %d,%d %dx%d", indent, "", window,
10088 window->user_data ? g_type_name_from_instance (window->user_data) : "no widget",
10089 window->x, window->y,
10090 window->width, window->height
10093 if (gdk_window_has_impl (window))
10095 #ifdef GDK_WINDOWING_X11
10096 g_print (" impl(0x%lx)", gdk_x11_drawable_get_xid (GDK_DRAWABLE (window)));
10100 if (window->window_type != GDK_WINDOW_CHILD)
10101 g_print (" %s", window_types[window->window_type]);
10103 if (window->input_only)
10104 g_print (" input-only");
10106 if (window->shaped)
10107 g_print (" shaped");
10109 if (!gdk_window_is_visible ((GdkWindow *)window))
10110 g_print (" hidden");
10112 g_print (" abs[%d,%d]",
10113 window->abs_x, window->abs_y);
10115 gdk_region_get_clipbox (window->clip_region, &r);
10116 if (gdk_region_empty (window->clip_region))
10117 g_print (" clipbox[empty]");
10119 g_print (" clipbox[%d,%d %dx%d]", r.x, r.y, r.width, r.height);
10126 gdk_window_print_tree (GdkWindow *window,
10128 gboolean include_input_only)
10130 GdkWindowObject *private;
10133 private = (GdkWindowObject *)window;
10135 if (private->input_only && !include_input_only)
10138 gdk_window_print (private, indent);
10140 for (l = private->children; l != NULL; l = l->next)
10141 gdk_window_print_tree (l->data, indent + 4, include_input_only);
10144 #endif /* DEBUG_WINDOW_PRINTING */
10147 is_input_event (GdkDisplay *display,
10150 GdkDevice *core_pointer;
10152 core_pointer = gdk_display_get_core_pointer (display);
10153 if ((event->type == GDK_MOTION_NOTIFY &&
10154 event->motion.device != core_pointer) ||
10155 ((event->type == GDK_BUTTON_PRESS ||
10156 event->type == GDK_BUTTON_RELEASE) &&
10157 event->button.device != core_pointer))
10163 _gdk_windowing_got_event (GdkDisplay *display,
10168 GdkWindow *event_window;
10169 GdkWindowObject *event_private;
10171 gboolean unlink_event;
10172 guint old_state, old_button;
10173 GdkPointerGrabInfo *button_release_grab;
10174 gboolean is_toplevel;
10176 if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
10177 display->last_event_time = gdk_event_get_time (event);
10179 _gdk_display_pointer_grab_update (display,
10182 event_window = event->any.window;
10186 event_private = GDK_WINDOW_OBJECT (event_window);
10188 #ifdef DEBUG_WINDOW_PRINTING
10189 if (event->type == GDK_KEY_PRESS &&
10190 (event->key.keyval == 0xa7 ||
10191 event->key.keyval == 0xbd))
10193 gdk_window_print_tree (event_window, 0,
10194 event->key.keyval == 0xbd);
10198 if (_gdk_native_windows)
10200 if (event->type == GDK_BUTTON_PRESS &&
10201 !event->any.send_event &&
10202 _gdk_display_has_pointer_grab (display, serial) == NULL)
10204 _gdk_display_add_pointer_grab (display,
10208 gdk_window_get_events (event_window),
10210 gdk_event_get_time (event),
10212 _gdk_display_pointer_grab_update (display,
10215 if (event->type == GDK_BUTTON_RELEASE &&
10216 !event->any.send_event)
10218 button_release_grab =
10219 _gdk_display_has_pointer_grab (display, serial);
10220 if (button_release_grab &&
10221 button_release_grab->implicit &&
10222 (event->button.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
10224 button_release_grab->serial_end = serial;
10225 button_release_grab->implicit_ungrab = FALSE;
10226 _gdk_display_pointer_grab_update (display, serial);
10230 if (event->type == GDK_BUTTON_PRESS)
10231 _gdk_event_button_generate (display, event);
10236 if (event->type == GDK_VISIBILITY_NOTIFY)
10238 event_private->native_visibility = event->visibility.state;
10239 gdk_window_update_visibility_recursively (event_private,
10244 if (is_input_event (display, event))
10247 if (!(is_button_type (event->type) ||
10248 is_motion_type (event->type)) ||
10249 event_private->window_type == GDK_WINDOW_ROOT)
10252 is_toplevel = gdk_window_is_toplevel (event_private);
10254 if ((event->type == GDK_ENTER_NOTIFY ||
10255 event->type == GDK_LEAVE_NOTIFY) &&
10256 (event->crossing.mode == GDK_CROSSING_GRAB ||
10257 event->crossing.mode == GDK_CROSSING_UNGRAB) &&
10258 (_gdk_display_has_pointer_grab (display, serial) ||
10259 event->crossing.detail == GDK_NOTIFY_INFERIOR))
10261 /* We synthesize all crossing events due to grabs ourselves,
10262 * so we ignore the native ones caused by our native pointer_grab
10263 * calls. Otherwise we would proxy these crossing event and cause
10264 * multiple copies of crossing events for grabs.
10266 * We do want to handle grabs from other clients though, as for
10267 * instance alt-tab in metacity causes grabs like these and
10268 * we want to handle those. Thus the has_pointer_grab check.
10270 * Implicit grabs on child windows create some grabbing events
10271 * that are sent before the button press. This means we can't
10272 * detect these with the has_pointer_grab check (as the implicit
10273 * grab is only noticed when we get button press event), so we
10274 * detect these events by checking for INFERIOR enter or leave
10275 * events. These should never be a problem to filter out.
10278 /* We ended up in this window after some (perhaps other clients)
10279 grab, so update the toplevel_under_window state */
10281 event->type == GDK_ENTER_NOTIFY &&
10282 event->crossing.mode == GDK_CROSSING_UNGRAB)
10284 if (display->pointer_info.toplevel_under_pointer)
10285 g_object_unref (display->pointer_info.toplevel_under_pointer);
10286 display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
10289 unlink_event = TRUE;
10293 /* Track toplevel_under_pointer */
10296 if (event->type == GDK_ENTER_NOTIFY &&
10297 event->crossing.detail != GDK_NOTIFY_INFERIOR)
10299 if (display->pointer_info.toplevel_under_pointer)
10300 g_object_unref (display->pointer_info.toplevel_under_pointer);
10301 display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
10303 else if (event->type == GDK_LEAVE_NOTIFY &&
10304 event->crossing.detail != GDK_NOTIFY_INFERIOR &&
10305 display->pointer_info.toplevel_under_pointer == event_window)
10307 if (display->pointer_info.toplevel_under_pointer)
10308 g_object_unref (display->pointer_info.toplevel_under_pointer);
10309 display->pointer_info.toplevel_under_pointer = NULL;
10313 /* Store last pointer window and position/state */
10314 old_state = display->pointer_info.state;
10315 old_button = display->pointer_info.button;
10317 gdk_event_get_coords (event, &x, &y);
10318 convert_native_coords_to_toplevel (event_window, x, y, &x, &y);
10319 display->pointer_info.toplevel_x = x;
10320 display->pointer_info.toplevel_y = y;
10321 gdk_event_get_state (event, &display->pointer_info.state);
10322 if (event->type == GDK_BUTTON_PRESS ||
10323 event->type == GDK_BUTTON_RELEASE)
10324 display->pointer_info.button = event->button.button;
10326 if (display->pointer_info.state != old_state ||
10327 display->pointer_info.button != old_button)
10328 _gdk_display_enable_motion_hints (display);
10330 unlink_event = FALSE;
10331 if (is_motion_type (event->type))
10332 unlink_event = proxy_pointer_event (display,
10335 else if (is_button_type (event->type))
10336 unlink_event = proxy_button_event (event,
10339 if (event->type == GDK_BUTTON_RELEASE &&
10340 !event->any.send_event)
10342 button_release_grab =
10343 _gdk_display_has_pointer_grab (display, serial);
10344 if (button_release_grab &&
10345 button_release_grab->implicit &&
10346 (event->button.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
10348 button_release_grab->serial_end = serial;
10349 button_release_grab->implicit_ungrab = FALSE;
10350 _gdk_display_pointer_grab_update (display, serial);
10357 _gdk_event_queue_remove_link (display, event_link);
10358 g_list_free_1 (event_link);
10359 gdk_event_free (event);
10365 get_extension_event_window (GdkDisplay *display,
10366 GdkWindow *pointer_window,
10371 GdkWindow *grab_window;
10372 GdkWindowObject *w;
10373 GdkPointerGrabInfo *grab;
10375 grab = _gdk_display_has_pointer_grab (display, serial);
10377 if (grab != NULL && !grab->owner_events)
10379 evmask = grab->event_mask;
10381 grab_window = grab->window;
10383 if (evmask & type_masks[type])
10384 return grab_window;
10389 w = (GdkWindowObject *)pointer_window;
10392 evmask = w->extension_events;
10394 if (evmask & type_masks[type])
10395 return (GdkWindow *)w;
10397 w = get_event_parent (w);
10400 if (grab != NULL &&
10401 grab->owner_events)
10403 evmask = grab->event_mask;
10405 if (evmask & type_masks[type])
10406 return grab->window;
10416 _gdk_window_get_input_window_for_event (GdkWindow *native_window,
10417 GdkEventType event_type,
10421 GdkDisplay *display;
10422 GdkWindow *toplevel_window;
10423 GdkWindow *pointer_window;
10424 GdkWindow *event_win;
10425 gdouble toplevel_x, toplevel_y;
10430 display = gdk_drawable_get_display (native_window);
10431 toplevel_window = convert_native_coords_to_toplevel (native_window,
10432 toplevel_x, toplevel_y,
10433 &toplevel_x, &toplevel_y);
10434 pointer_window = get_pointer_window (display, toplevel_window,
10435 toplevel_x, toplevel_y, serial);
10436 event_win = get_extension_event_window (display,
10445 #define __GDK_WINDOW_C__
10446 #include "gdkaliasdef.c"