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;
149 GdkRegion *dest_region; /* The destination region */
150 int dx, dy; /* The amount that the source was moved to reach dest_region */
151 } GdkWindowRegionMove;
156 static GdkGC *gdk_window_create_gc (GdkDrawable *drawable,
158 GdkGCValuesMask mask);
159 static void gdk_window_draw_rectangle (GdkDrawable *drawable,
166 static void gdk_window_draw_arc (GdkDrawable *drawable,
175 static void gdk_window_draw_polygon (GdkDrawable *drawable,
180 static void gdk_window_draw_text (GdkDrawable *drawable,
187 static void gdk_window_draw_text_wc (GdkDrawable *drawable,
192 const GdkWChar *text,
194 static void gdk_window_draw_drawable (GdkDrawable *drawable,
203 GdkDrawable *original_src);
204 static void gdk_window_draw_points (GdkDrawable *drawable,
208 static void gdk_window_draw_segments (GdkDrawable *drawable,
212 static void gdk_window_draw_lines (GdkDrawable *drawable,
217 static void gdk_window_draw_glyphs (GdkDrawable *drawable,
222 PangoGlyphString *glyphs);
223 static void gdk_window_draw_glyphs_transformed (GdkDrawable *drawable,
229 PangoGlyphString *glyphs);
231 static void gdk_window_draw_image (GdkDrawable *drawable,
241 static void gdk_window_draw_pixbuf (GdkDrawable *drawable,
254 static void gdk_window_draw_trapezoids (GdkDrawable *drawable,
256 GdkTrapezoid *trapezoids,
259 static GdkImage* gdk_window_copy_to_image (GdkDrawable *drawable,
268 static cairo_surface_t *gdk_window_ref_cairo_surface (GdkDrawable *drawable);
269 static cairo_surface_t *gdk_window_create_cairo_surface (GdkDrawable *drawable,
272 static void gdk_window_set_cairo_clip (GdkDrawable *drawable,
275 static void gdk_window_real_get_size (GdkDrawable *drawable,
279 static GdkVisual* gdk_window_real_get_visual (GdkDrawable *drawable);
280 static gint gdk_window_real_get_depth (GdkDrawable *drawable);
281 static GdkScreen* gdk_window_real_get_screen (GdkDrawable *drawable);
282 static void gdk_window_real_set_colormap (GdkDrawable *drawable,
284 static GdkColormap* gdk_window_real_get_colormap (GdkDrawable *drawable);
286 static GdkDrawable* gdk_window_get_source_drawable (GdkDrawable *drawable);
287 static GdkDrawable* gdk_window_get_composite_drawable (GdkDrawable *drawable,
292 gint *composite_x_offset,
293 gint *composite_y_offset);
294 static GdkRegion* gdk_window_get_clip_region (GdkDrawable *drawable);
295 static GdkRegion* gdk_window_get_visible_region (GdkDrawable *drawable);
297 static void gdk_window_free_paint_stack (GdkWindow *window);
299 static void gdk_window_init (GdkWindowObject *window);
300 static void gdk_window_class_init (GdkWindowObjectClass *klass);
301 static void gdk_window_finalize (GObject *object);
303 static void gdk_window_set_property (GObject *object,
307 static void gdk_window_get_property (GObject *object,
312 static void gdk_window_clear_backing_region (GdkWindow *window,
314 static void gdk_window_redirect_free (GdkWindowRedirect *redirect);
315 static void apply_redirect_to_children (GdkWindowObject *private,
316 GdkWindowRedirect *redirect);
317 static void remove_redirect_from_children (GdkWindowObject *private,
318 GdkWindowRedirect *redirect);
320 static void recompute_visible_regions (GdkWindowObject *private,
321 gboolean recalculate_siblings,
322 gboolean recalculate_children);
323 static void gdk_window_flush_outstanding_moves (GdkWindow *window);
324 static void gdk_window_flush (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 gdk_window_region_move_free (GdkWindowRegionMove *move);
334 static guint signals[LAST_SIGNAL] = { 0 };
336 static gpointer parent_class = NULL;
338 static const cairo_user_data_key_t gdk_window_cairo_key;
341 new_region_tag (void)
343 static guint32 tag = 0;
349 gdk_window_object_get_type (void)
351 static GType object_type = 0;
354 object_type = g_type_register_static_simple (GDK_TYPE_DRAWABLE,
356 sizeof (GdkWindowObjectClass),
357 (GClassInitFunc) gdk_window_class_init,
358 sizeof (GdkWindowObject),
359 (GInstanceInitFunc) gdk_window_init,
366 _gdk_paintable_get_type (void)
368 static GType paintable_type = 0;
372 const GTypeInfo paintable_info =
374 sizeof (GdkPaintableIface), /* class_size */
375 NULL, /* base_init */
376 NULL, /* base_finalize */
379 paintable_type = g_type_register_static (G_TYPE_INTERFACE,
380 g_intern_static_string ("GdkPaintable"),
383 g_type_interface_add_prerequisite (paintable_type, G_TYPE_OBJECT);
386 return paintable_type;
390 gdk_window_init (GdkWindowObject *window)
392 /* 0-initialization is good for all other fields. */
394 window->window_type = GDK_WINDOW_CHILD;
396 window->state = GDK_WINDOW_STATE_WITHDRAWN;
399 window->toplevel_window_type = -1;
401 window->effective_visibility = GDK_VISIBILITY_NOT_VIEWABLE;
402 window->visibility = GDK_VISIBILITY_FULLY_OBSCURED;
403 /* Default to unobscured since some backends don't send visibility events */
404 window->native_visibility = GDK_VISIBILITY_UNOBSCURED;
407 /* Stop and return on the first non-NULL parent */
409 accumulate_get_window (GSignalInvocationHint *ihint,
411 const GValue *handler_return,
414 g_value_copy (handler_return, return_accu);
415 /* Continue while returning NULL */
416 return g_value_get_object (handler_return) == NULL;
419 static GQuark quark_pointer_window = 0;
422 gdk_window_class_init (GdkWindowObjectClass *klass)
424 GObjectClass *object_class = G_OBJECT_CLASS (klass);
425 GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
427 parent_class = g_type_class_peek_parent (klass);
429 object_class->finalize = gdk_window_finalize;
430 object_class->set_property = gdk_window_set_property;
431 object_class->get_property = gdk_window_get_property;
433 drawable_class->create_gc = gdk_window_create_gc;
434 drawable_class->draw_rectangle = gdk_window_draw_rectangle;
435 drawable_class->draw_arc = gdk_window_draw_arc;
436 drawable_class->draw_polygon = gdk_window_draw_polygon;
437 drawable_class->draw_text = gdk_window_draw_text;
438 drawable_class->draw_text_wc = gdk_window_draw_text_wc;
439 drawable_class->draw_drawable_with_src = gdk_window_draw_drawable;
440 drawable_class->draw_points = gdk_window_draw_points;
441 drawable_class->draw_segments = gdk_window_draw_segments;
442 drawable_class->draw_lines = gdk_window_draw_lines;
443 drawable_class->draw_glyphs = gdk_window_draw_glyphs;
444 drawable_class->draw_glyphs_transformed = gdk_window_draw_glyphs_transformed;
445 drawable_class->draw_image = gdk_window_draw_image;
446 drawable_class->draw_pixbuf = gdk_window_draw_pixbuf;
447 drawable_class->draw_trapezoids = gdk_window_draw_trapezoids;
448 drawable_class->get_depth = gdk_window_real_get_depth;
449 drawable_class->get_screen = gdk_window_real_get_screen;
450 drawable_class->get_size = gdk_window_real_get_size;
451 drawable_class->set_colormap = gdk_window_real_set_colormap;
452 drawable_class->get_colormap = gdk_window_real_get_colormap;
453 drawable_class->get_visual = gdk_window_real_get_visual;
454 drawable_class->_copy_to_image = gdk_window_copy_to_image;
455 drawable_class->ref_cairo_surface = gdk_window_ref_cairo_surface;
456 drawable_class->create_cairo_surface = gdk_window_create_cairo_surface;
457 drawable_class->set_cairo_clip = gdk_window_set_cairo_clip;
458 drawable_class->get_clip_region = gdk_window_get_clip_region;
459 drawable_class->get_visible_region = gdk_window_get_visible_region;
460 drawable_class->get_composite_drawable = gdk_window_get_composite_drawable;
461 drawable_class->get_source_drawable = gdk_window_get_source_drawable;
463 quark_pointer_window = g_quark_from_static_string ("gtk-pointer-window");
467 g_object_class_install_property (object_class,
469 g_param_spec_pointer ("cursor",
475 * GdkWindow::pick-embedded-child:
476 * @window: the window on which the signal is emitted
477 * @x: x coordinate in the window
478 * @y: y coordinate in the window
480 * The ::pick-embedded-child signal is emitted to find an embedded
481 * child at the given position.
483 * Returns: the #GdkWindow of the embedded child at @x, @y, or %NULL
487 signals[PICK_EMBEDDED_CHILD] =
488 g_signal_new (g_intern_static_string ("pick-embedded-child"),
489 G_OBJECT_CLASS_TYPE (object_class),
492 accumulate_get_window, NULL,
493 _gdk_marshal_OBJECT__DOUBLE_DOUBLE,
500 * GdkWindow::to-embedder:
501 * @window: the offscreen window on which the signal is emitted
502 * @offscreen-x: x coordinate in the offscreen window
503 * @offscreen-y: y coordinate in the offscreen window
504 * @embedder-x: return location for the x coordinate in the embedder window
505 * @embedder-y: return location for the y coordinate in the embedder window
507 * The ::to-embedder signal is emitted to translate coordinates
508 * in an offscreen window to its embedder.
510 * See also #GtkWindow::from-embedder.
514 signals[TO_EMBEDDER] =
515 g_signal_new (g_intern_static_string ("to-embedder"),
516 G_OBJECT_CLASS_TYPE (object_class),
520 _gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
529 * GdkWindow::from-embedder:
530 * @window: the offscreen window on which the signal is emitted
531 * @embedder-x: x coordinate in the embedder window
532 * @embedder-y: y coordinate in the embedder window
533 * @offscreen-x: return location for the x coordinate in the offscreen window
534 * @offscreen-y: return location for the y coordinate in the offscreen window
536 * The ::from-embedder signal is emitted to translate coordinates
537 * in the embedder of an offscreen window to the offscreen window.
539 * See also #GtkWindow::to-embedder.
543 signals[FROM_EMBEDDER] =
544 g_signal_new (g_intern_static_string ("from-embedder"),
545 G_OBJECT_CLASS_TYPE (object_class),
549 _gdk_marshal_VOID__DOUBLE_DOUBLE_POINTER_POINTER,
559 gdk_window_finalize (GObject *object)
561 GdkWindow *window = GDK_WINDOW (object);
562 GdkWindowObject *obj = (GdkWindowObject *) object;
564 if (!GDK_WINDOW_DESTROYED (window))
566 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
568 g_warning ("losing last reference to undestroyed window\n");
569 _gdk_window_destroy (window, FALSE);
572 /* We use TRUE here, to keep us from actually calling
573 * XDestroyWindow() on the window
575 _gdk_window_destroy (window, TRUE);
580 g_object_unref (obj->impl);
584 if (obj->impl_window != obj)
586 g_object_unref (obj->impl_window);
587 obj->impl_window = NULL;
591 gdk_region_destroy (obj->shape);
593 if (obj->input_shape)
594 gdk_region_destroy (obj->input_shape);
597 gdk_cursor_unref (obj->cursor);
599 G_OBJECT_CLASS (parent_class)->finalize (object);
603 gdk_window_set_property (GObject *object,
608 GdkWindow *window = (GdkWindow *)object;
613 gdk_window_set_cursor (window, g_value_get_pointer (value));
617 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
623 gdk_window_get_property (GObject *object,
628 GdkWindow *window = (GdkWindow *) object;
633 g_value_set_pointer (value, gdk_window_get_cursor (window));
637 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
643 gdk_window_is_offscreen (GdkWindowObject *window)
645 return window->window_type == GDK_WINDOW_OFFSCREEN;
648 static GdkWindowObject *
649 gdk_window_get_impl_window (GdkWindowObject *window)
651 return window->impl_window;
655 _gdk_window_get_impl_window (GdkWindow *window)
657 return (GdkWindow *)gdk_window_get_impl_window ((GdkWindowObject *)window);
661 gdk_window_has_impl (GdkWindowObject *window)
663 return window->impl_window == window;
667 _gdk_window_has_impl (GdkWindow *window)
669 return gdk_window_has_impl ((GdkWindowObject *)window);
673 gdk_window_has_no_impl (GdkWindowObject *window)
675 return window->impl_window != window;
679 remove_child_area (GdkWindowObject *private,
680 GdkWindowObject *until,
684 GdkWindowObject *child;
685 GdkRegion *child_region;
690 for (l = private->children; l; l = l->next)
697 /* If region is empty already, no need to do
698 anything potentially costly */
699 if (gdk_region_empty (region))
702 if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
705 /* Ignore offscreen children, as they don't draw in their parent and
706 * don't take part in the clipping */
707 if (gdk_window_is_offscreen (child))
712 r.width = child->width;
713 r.height = child->height;
715 /* Bail early if child totally outside region */
716 if (gdk_region_rect_in (region, &r) == GDK_OVERLAP_RECTANGLE_OUT)
719 child_region = gdk_region_rectangle (&r);
723 /* Adjust shape region to parent window coords */
724 gdk_region_offset (child->shape, child->x, child->y);
725 gdk_region_intersect (child_region, child->shape);
726 gdk_region_offset (child->shape, -child->x, -child->y);
728 else if (private->window_type == GDK_WINDOW_FOREIGN)
730 shape = _gdk_windowing_window_get_shape ((GdkWindow *)child);
733 gdk_region_intersect (child_region, shape);
734 gdk_region_destroy (shape);
740 if (child->input_shape)
741 gdk_region_intersect (child_region, child->input_shape);
742 else if (private->window_type == GDK_WINDOW_FOREIGN)
744 shape = _gdk_windowing_window_get_input_shape ((GdkWindow *)child);
747 gdk_region_intersect (child_region, shape);
748 gdk_region_destroy (shape);
753 gdk_region_subtract (region, child_region);
754 gdk_region_destroy (child_region);
759 static GdkVisibilityState
760 effective_visibility (GdkWindowObject *private)
762 GdkVisibilityState native;
764 if (!gdk_window_is_viewable ((GdkWindow *)private))
765 return GDK_VISIBILITY_NOT_VIEWABLE;
767 native = private->impl_window->native_visibility;
769 if (native == GDK_VISIBILITY_FULLY_OBSCURED ||
770 private->visibility == GDK_VISIBILITY_FULLY_OBSCURED)
771 return GDK_VISIBILITY_FULLY_OBSCURED;
772 else if (native == GDK_VISIBILITY_UNOBSCURED)
773 return private->visibility;
774 else /* native PARTIAL, private partial or unobscured */
775 return GDK_VISIBILITY_PARTIAL;
779 gdk_window_update_visibility (GdkWindowObject *private)
781 GdkVisibilityState new_visibility;
784 new_visibility = effective_visibility (private);
786 if (new_visibility != private->effective_visibility)
788 private->effective_visibility = new_visibility;
790 if (new_visibility != GDK_VISIBILITY_NOT_VIEWABLE &&
791 private->event_mask & GDK_VISIBILITY_NOTIFY)
793 event = _gdk_make_event ((GdkWindow *)private, GDK_VISIBILITY_NOTIFY,
795 event->visibility.state = new_visibility;
801 gdk_window_update_visibility_recursively (GdkWindowObject *private,
802 GdkWindowObject *only_for_impl)
804 GdkWindowObject *child;
807 gdk_window_update_visibility (private);
808 for (l = private->children; l != NULL; l = l->next)
811 if ((only_for_impl == NULL) ||
812 (only_for_impl == child->impl_window))
813 gdk_window_update_visibility_recursively (child, only_for_impl);
818 recompute_visible_regions_internal (GdkWindowObject *private,
819 gboolean recalculate_clip,
820 gboolean recalculate_siblings,
821 gboolean recalculate_children)
825 GdkWindowObject *child;
826 GdkRegion *new_clip, *old_clip_region_with_children;
827 gboolean clip_region_changed;
828 gboolean abs_pos_changed;
829 int old_abs_x, old_abs_y;
831 old_abs_x = private->abs_x;
832 old_abs_y = private->abs_y;
834 /* Update absolute position */
835 if (gdk_window_has_impl (private))
837 /* Native window starts here */
843 private->abs_x = private->parent->abs_x + private->x;
844 private->abs_y = private->parent->abs_y + private->y;
848 private->abs_x != old_abs_x ||
849 private->abs_y != old_abs_y;
851 /* Update clip region based on:
854 * siblings in parents above window
856 clip_region_changed = FALSE;
857 if (recalculate_clip)
859 if (private->viewable)
861 /* Calculate visible region (sans children) in parent window coords */
864 r.width = private->width;
865 r.height = private->height;
866 new_clip = gdk_region_rectangle (&r);
868 if (private->parent != NULL &&
869 private->parent->window_type != GDK_WINDOW_ROOT)
871 gdk_region_intersect (new_clip, private->parent->clip_region);
873 /* Remove all overlapping children from parent.
874 * Unless we're all native, because then we don't need to take
875 * siblings into account since X does that clipping for us.
876 * This makes things like SWT that modify the raw X stacking
877 * order without GDKs knowledge work.
879 if (!_gdk_native_windows)
880 remove_child_area (private->parent, private, FALSE, new_clip);
883 /* Convert from parent coords to window coords */
884 gdk_region_offset (new_clip, -private->x, -private->y);
887 gdk_region_intersect (new_clip, private->shape);
890 new_clip = gdk_region_new ();
892 if (private->clip_region == NULL ||
893 !gdk_region_equal (private->clip_region, new_clip))
894 clip_region_changed = TRUE;
896 if (private->clip_region)
897 gdk_region_destroy (private->clip_region);
898 private->clip_region = new_clip;
900 old_clip_region_with_children = private->clip_region_with_children;
901 private->clip_region_with_children = gdk_region_copy (private->clip_region);
902 if (private->window_type != GDK_WINDOW_ROOT)
903 remove_child_area (private, NULL, FALSE, private->clip_region_with_children);
905 if (clip_region_changed ||
906 !gdk_region_equal (private->clip_region_with_children, old_clip_region_with_children))
907 private->clip_tag = new_region_tag ();
909 if (old_clip_region_with_children)
910 gdk_region_destroy (old_clip_region_with_children);
913 if (clip_region_changed)
915 GdkVisibilityState visibility;
916 gboolean fully_visible;
918 if (gdk_region_empty (private->clip_region))
919 visibility = GDK_VISIBILITY_FULLY_OBSCURED;
924 fully_visible = gdk_region_equal (private->clip_region,
931 r.width = private->width;
932 r.height = private->height;
933 fully_visible = gdk_region_rect_equal (private->clip_region, &r);
937 visibility = GDK_VISIBILITY_UNOBSCURED;
939 visibility = GDK_VISIBILITY_PARTIAL;
942 if (private->visibility != visibility)
944 private->visibility = visibility;
945 gdk_window_update_visibility (private);
949 /* Update all children, recursively (except for root, where children are not exact). */
950 if ((abs_pos_changed || clip_region_changed || recalculate_children) &&
951 private->window_type != GDK_WINDOW_ROOT)
953 for (l = private->children; l; l = l->next)
956 /* Only recalculate clip if the the clip region changed, otherwise
957 * there is no way the child clip region could change (its has not e.g. moved)
958 * Except if recalculate_children is set to force child updates
960 recompute_visible_regions_internal (child,
961 recalculate_clip && (clip_region_changed || recalculate_children),
966 if (clip_region_changed &&
967 gdk_window_has_impl (private) &&
968 /* Not for offscreens */
969 private->window_type != GDK_WINDOW_OFFSCREEN &&
970 /* or for non-shaped toplevels */
972 (private->parent != NULL &&
973 private->parent->window_type != GDK_WINDOW_ROOT)) &&
974 /* or for foreign windows */
975 private->window_type != GDK_WINDOW_FOREIGN &&
976 /* or for the root window */
977 private->window_type != GDK_WINDOW_ROOT
980 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region ((GdkWindow *)private, private->clip_region, 0, 0);
983 if (recalculate_siblings &&
984 private->parent != NULL &&
985 private->parent->window_type != GDK_WINDOW_ROOT)
987 /* If we moved a child window in parent or changed the stacking order, then we
988 * need to recompute the visible area of all the other children in the parent
990 for (l = private->parent->children; l; l = l->next)
994 if (child != private)
995 recompute_visible_regions_internal (child, TRUE, FALSE, FALSE);
998 /* We also need to recompute the _with_children clip for the parent */
999 recompute_visible_regions_internal (private->parent, TRUE, FALSE, FALSE);
1002 if (private->cairo_surface)
1006 /* It would be nice if we had some cairo support here so we
1007 could set the clip rect on the cairo surface */
1008 width = private->abs_x + private->width;
1009 height = private->abs_y + private->height;
1011 _gdk_windowing_set_cairo_surface_size (private->cairo_surface,
1013 cairo_surface_set_device_offset (private->cairo_surface,
1019 /* Call this when private has changed in one or more of these ways:
1023 * stacking order of window changed
1026 * It will recalculate abs_x/y and the clip regions
1028 * Unless the window didn't change stacking order or size/pos, pass in TRUE
1029 * for recalculate_siblings. (Mostly used internally for the recursion)
1031 * If a child window was removed (and you can't use that child for
1032 * recompute_visible_regions), pass in TRUE for recalculate_children on the parent
1035 recompute_visible_regions (GdkWindowObject *private,
1036 gboolean recalculate_siblings,
1037 gboolean recalculate_children)
1039 recompute_visible_regions_internal (private,
1041 recalculate_siblings,
1042 recalculate_children);
1046 _gdk_window_update_size (GdkWindow *window)
1048 recompute_visible_regions ((GdkWindowObject *)window, TRUE, FALSE);
1051 /* Find the native window that would be just above "child"
1052 * in the native stacking order if "child" was a native window
1053 * (it doesn't have to be native). If there is no such native
1054 * window inside this native parent then NULL is returned.
1055 * If child is NULL, find lowest native window in parent.
1057 static GdkWindowObject *
1058 find_native_sibling_above_helper (GdkWindowObject *parent,
1059 GdkWindowObject *child)
1066 l = g_list_find (parent->children, child);
1067 g_assert (l != NULL); /* Better be a child of its parent... */
1068 l = l->prev; /* Start looking at the one above the child */
1071 l = g_list_last (parent->children);
1073 for (; l != NULL; l = l->prev)
1077 if (gdk_window_has_impl (w))
1080 g_assert (parent != w);
1081 w = find_native_sibling_above_helper (w, NULL);
1090 static GdkWindowObject *
1091 find_native_sibling_above (GdkWindowObject *parent,
1092 GdkWindowObject *child)
1096 w = find_native_sibling_above_helper (parent, child);
1100 if (gdk_window_has_impl (parent))
1103 return find_native_sibling_above (parent->parent, parent);
1107 get_native_event_mask (GdkWindowObject *private)
1109 if (_gdk_native_windows ||
1110 private->window_type == GDK_WINDOW_ROOT ||
1111 private->window_type == GDK_WINDOW_FOREIGN)
1112 return private->event_mask;
1116 /* We need thse for all native window so we can emulate
1117 events on children: */
1119 GDK_VISIBILITY_NOTIFY_MASK |
1120 GDK_POINTER_MOTION_MASK |
1121 GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
1122 GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
1124 /* Then do whatever the app asks to, since the app
1125 * may be asking for weird things for native windows,
1126 * but filter out things that override the above
1127 * requests somehow. */
1128 (private->event_mask &
1129 ~(GDK_POINTER_MOTION_HINT_MASK |
1130 GDK_BUTTON_MOTION_MASK |
1131 GDK_BUTTON1_MOTION_MASK |
1132 GDK_BUTTON2_MOTION_MASK |
1133 GDK_BUTTON3_MOTION_MASK));
1137 /* Puts the native window in the right order wrt the other native windows
1138 * in the hierarchy, given the position it has in the client side data.
1139 * This is useful if some operation changed the stacking order.
1140 * This calls assumes the native window is now topmost in its native parent.
1143 sync_native_window_stack_position (GdkWindow *window)
1145 GdkWindowObject *above;
1146 GdkWindowObject *private;
1147 GList listhead = {0};
1149 private = (GdkWindowObject *) window;
1151 above = find_native_sibling_above (private->parent, private);
1154 listhead.data = window;
1155 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
1162 * @parent: a #GdkWindow, or %NULL to create the window as a child of
1163 * the default root window for the default display.
1164 * @attributes: attributes of the new window
1165 * @attributes_mask: mask indicating which fields in @attributes are valid
1167 * Creates a new #GdkWindow using the attributes from
1168 * @attributes. See #GdkWindowAttr and #GdkWindowAttributesType for
1169 * more details. Note: to use this on displays other than the default
1170 * display, @parent must be specified.
1172 * Return value: the new #GdkWindow
1175 gdk_window_new (GdkWindow *parent,
1176 GdkWindowAttr *attributes,
1177 gint attributes_mask)
1180 GdkWindowObject *private;
1185 GdkEventMask event_mask;
1186 GdkWindow *real_parent;
1188 g_return_val_if_fail (attributes != NULL, NULL);
1192 GDK_NOTE (MULTIHEAD,
1193 g_warning ("gdk_window_new(): no parent specified reverting to parent = default root window"));
1195 screen = gdk_screen_get_default ();
1196 parent = gdk_screen_get_root_window (screen);
1199 screen = gdk_drawable_get_screen (parent);
1201 g_return_val_if_fail (GDK_IS_WINDOW (parent), NULL);
1203 if (GDK_WINDOW_DESTROYED (parent))
1205 g_warning ("gdk_window_new(): parent is destroyed\n");
1209 if (attributes->window_type == GDK_WINDOW_OFFSCREEN &&
1210 _gdk_native_windows)
1212 g_warning ("Offscreen windows not supported with native-windows gdk");
1216 window = g_object_new (GDK_TYPE_WINDOW, NULL);
1217 private = (GdkWindowObject *) window;
1219 /* Windows with a foreign parent are treated as if they are children
1220 * of the root window, except for actual creation.
1222 real_parent = parent;
1223 if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_FOREIGN)
1224 parent = gdk_screen_get_root_window (screen);
1226 private->parent = (GdkWindowObject *)parent;
1228 private->accept_focus = TRUE;
1229 private->focus_on_map = TRUE;
1231 if (attributes_mask & GDK_WA_X)
1236 if (attributes_mask & GDK_WA_Y)
1243 private->width = (attributes->width > 1) ? (attributes->width) : (1);
1244 private->height = (attributes->height > 1) ? (attributes->height) : (1);
1246 #ifdef GDK_WINDOWING_X11
1247 /* Work around a bug where Xorg refuses to map toplevel InputOnly windows
1248 * from an untrusted client: http://bugs.freedesktop.org/show_bug.cgi?id=6988
1250 if (attributes->wclass == GDK_INPUT_ONLY &&
1251 private->parent->window_type == GDK_WINDOW_ROOT &&
1252 !G_LIKELY (GDK_DISPLAY_X11 (GDK_WINDOW_DISPLAY (parent))->trusted_client))
1254 g_warning ("Coercing GDK_INPUT_ONLY toplevel window to GDK_INPUT_OUTPUT to work around bug in Xorg server");
1255 attributes->wclass = GDK_INPUT_OUTPUT;
1259 if (attributes->wclass == GDK_INPUT_ONLY)
1261 /* Backwards compatiblity - we've always ignored
1262 * attributes->window_type for input-only windows
1265 if (GDK_WINDOW_TYPE (parent) == GDK_WINDOW_ROOT)
1266 private->window_type = GDK_WINDOW_TEMP;
1268 private->window_type = GDK_WINDOW_CHILD;
1271 private->window_type = attributes->window_type;
1274 switch (private->window_type)
1276 case GDK_WINDOW_TOPLEVEL:
1277 case GDK_WINDOW_DIALOG:
1278 case GDK_WINDOW_TEMP:
1279 case GDK_WINDOW_OFFSCREEN:
1280 if (GDK_WINDOW_TYPE (parent) != GDK_WINDOW_ROOT)
1281 g_warning (G_STRLOC "Toplevel windows must be created as children of\n"
1282 "of a window of type GDK_WINDOW_ROOT or GDK_WINDOW_FOREIGN");
1283 case GDK_WINDOW_CHILD:
1287 g_warning (G_STRLOC "cannot make windows of type %d", private->window_type);
1291 if (attributes_mask & GDK_WA_VISUAL)
1292 visual = attributes->visual;
1294 visual = gdk_screen_get_system_visual (screen);
1296 private->event_mask = attributes->event_mask;
1298 if (attributes->wclass == GDK_INPUT_OUTPUT)
1300 private->input_only = FALSE;
1301 private->depth = visual->depth;
1303 private->bg_color.pixel = 0; /* TODO: BlackPixel (xdisplay, screen_x11->screen_num); */
1304 private->bg_color.red = private->bg_color.green = private->bg_color.blue = 0;
1306 private->bg_pixmap = NULL;
1311 private->input_only = TRUE;
1314 if (private->parent)
1315 private->parent->children = g_list_prepend (private->parent->children, window);
1317 native = _gdk_native_windows; /* Default */
1318 if (private->parent->window_type == GDK_WINDOW_ROOT)
1319 native = TRUE; /* Always use native windows for toplevels */
1320 else if (!private->input_only &&
1321 ((attributes_mask & GDK_WA_COLORMAP &&
1322 attributes->colormap != gdk_drawable_get_colormap ((GdkDrawable *)private->parent)) ||
1323 (attributes_mask & GDK_WA_VISUAL &&
1324 attributes->visual != gdk_drawable_get_visual ((GdkDrawable *)private->parent))))
1325 native = TRUE; /* InputOutput window with different colormap or visual than parent, needs native window */
1327 if (private->window_type == GDK_WINDOW_OFFSCREEN)
1329 _gdk_offscreen_window_new (window, screen, visual, attributes, attributes_mask);
1330 private->impl_window = private;
1334 event_mask = get_native_event_mask (private);
1336 /* Create the impl */
1337 _gdk_window_impl_new (window, real_parent, screen, visual, event_mask, attributes, attributes_mask);
1338 private->impl_window = private;
1340 /* This will put the native window topmost in the native parent, which may
1341 * be wrong wrt other native windows in the non-native hierarchy, so restack */
1342 if (!_gdk_window_has_impl (real_parent))
1343 sync_native_window_stack_position (window);
1347 private->impl_window = g_object_ref (private->parent->impl_window);
1348 private->impl = g_object_ref (private->impl_window->impl);
1351 recompute_visible_regions (private, TRUE, FALSE);
1353 if (private->parent->window_type != GDK_WINDOW_ROOT)
1355 /* Inherit redirection from parent */
1356 private->redirect = private->parent->redirect;
1359 gdk_window_set_cursor (window, ((attributes_mask & GDK_WA_CURSOR) ?
1360 (attributes->cursor) :
1367 is_parent_of (GdkWindow *parent,
1378 w = gdk_window_get_parent (w);
1385 change_impl (GdkWindowObject *private,
1386 GdkWindowObject *impl_window,
1390 GdkWindowObject *child;
1391 GdkDrawable *old_impl;
1392 GdkWindowObject *old_impl_window;
1394 old_impl = private->impl;
1395 old_impl_window = private->impl_window;
1396 if (private != impl_window)
1397 private->impl_window = g_object_ref (impl_window);
1399 private->impl_window = private;
1400 private->impl = g_object_ref (new);
1401 if (old_impl_window != private)
1402 g_object_unref (old_impl_window);
1403 g_object_unref (old_impl);
1405 for (l = private->children; l != NULL; l = l->next)
1409 if (child->impl == old_impl)
1410 change_impl (child, impl_window, new);
1415 reparent_to_impl (GdkWindowObject *private)
1418 GdkWindowObject *child;
1421 /* Enumerate in reverse order so we get the right order for the native
1422 windows (first in childrens list is topmost, and reparent places on top) */
1423 for (l = g_list_last (private->children); l != NULL; l = l->prev)
1427 if (child->impl == private->impl)
1428 reparent_to_impl (child);
1431 show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent ((GdkWindow *)child,
1432 (GdkWindow *)private,
1433 child->x, child->y);
1435 gdk_window_show_unraised ((GdkWindow *)child);
1442 * gdk_window_reparent:
1443 * @window: a #GdkWindow
1444 * @new_parent: new parent to move @window into
1445 * @x: X location inside the new parent
1446 * @y: Y location inside the new parent
1448 * Reparents @window into the given @new_parent. The window being
1449 * reparented will be unmapped as a side effect.
1453 gdk_window_reparent (GdkWindow *window,
1454 GdkWindow *new_parent,
1458 GdkWindowObject *private;
1459 GdkWindowObject *new_parent_private;
1460 GdkWindowObject *old_parent;
1462 gboolean show, was_mapped;
1463 gboolean do_reparent_to_impl;
1464 GdkEventMask old_native_event_mask;
1466 g_return_if_fail (GDK_IS_WINDOW (window));
1467 g_return_if_fail (new_parent == NULL || GDK_IS_WINDOW (new_parent));
1468 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
1470 if (GDK_WINDOW_DESTROYED (window) ||
1471 (new_parent && GDK_WINDOW_DESTROYED (new_parent)))
1474 screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
1476 new_parent = gdk_screen_get_root_window (screen);
1478 private = (GdkWindowObject *) window;
1479 new_parent_private = (GdkWindowObject *)new_parent;
1481 /* No input-output children of input-only windows */
1482 if (new_parent_private->input_only && !private->input_only)
1485 /* Don't create loops in hierarchy */
1486 if (is_parent_of (window, new_parent))
1489 if (private->cairo_surface)
1491 /* This might be wrong in the new parent, e.g. for non-native surfaces.
1492 To make sure we're ok, just wipe it. */
1493 cairo_surface_finish (private->cairo_surface);
1494 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
1498 old_parent = private->parent;
1500 /* Break up redirection if inherited */
1501 if (private->redirect && private->redirect->redirected != private)
1503 remove_redirect_from_children (private, private->redirect);
1504 private->redirect = NULL;
1507 was_mapped = GDK_WINDOW_IS_MAPPED (window);
1510 /* Reparenting to toplevel. Ensure we have a native window so this can work */
1511 if (new_parent_private->window_type == GDK_WINDOW_ROOT ||
1512 new_parent_private->window_type == GDK_WINDOW_FOREIGN)
1513 gdk_window_ensure_native (window);
1515 old_native_event_mask = 0;
1516 do_reparent_to_impl = FALSE;
1517 if (gdk_window_has_impl (private))
1519 old_native_event_mask = get_native_event_mask (private);
1521 show = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->reparent (window, new_parent, x, y);
1525 /* This shouldn't happen, as we created a native in this case, check anyway to see if that ever fails */
1526 g_assert (new_parent_private->window_type != GDK_WINDOW_ROOT &&
1527 new_parent_private->window_type != GDK_WINDOW_FOREIGN);
1530 gdk_window_hide (window);
1532 do_reparent_to_impl = TRUE;
1533 change_impl (private,
1534 new_parent_private->impl_window,
1535 new_parent_private->impl);
1538 /* From here on, we treat parents of type GDK_WINDOW_FOREIGN like
1541 if (GDK_WINDOW_TYPE (new_parent) == GDK_WINDOW_FOREIGN)
1543 new_parent = gdk_screen_get_root_window (screen);
1544 new_parent_private = (GdkWindowObject *)new_parent;
1548 old_parent->children = g_list_remove (old_parent->children, window);
1550 private->parent = new_parent_private;
1554 new_parent_private->children = g_list_prepend (new_parent_private->children, window);
1556 /* Switch the window type as appropriate */
1558 switch (GDK_WINDOW_TYPE (new_parent))
1560 case GDK_WINDOW_ROOT:
1561 case GDK_WINDOW_FOREIGN:
1562 if (private->toplevel_window_type != -1)
1563 GDK_WINDOW_TYPE (window) = private->toplevel_window_type;
1564 else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD)
1565 GDK_WINDOW_TYPE (window) = GDK_WINDOW_TOPLEVEL;
1567 case GDK_WINDOW_OFFSCREEN:
1568 case GDK_WINDOW_TOPLEVEL:
1569 case GDK_WINDOW_CHILD:
1570 case GDK_WINDOW_DIALOG:
1571 case GDK_WINDOW_TEMP:
1572 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && \
1573 GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
1575 /* Save the original window type so we can restore it if the
1576 * window is reparented back to be a toplevel
1578 private->toplevel_window_type = GDK_WINDOW_TYPE (window);
1579 GDK_WINDOW_TYPE (window) = GDK_WINDOW_CHILD;
1583 /* We might have changed window type for a native windows, so we
1584 need to change the event mask too. */
1585 if (gdk_window_has_impl (private))
1587 GdkEventMask native_event_mask = get_native_event_mask (private);
1589 if (native_event_mask != old_native_event_mask)
1590 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_events (window,
1594 /* Inherit parent redirect if we don't have our own */
1595 if (private->parent && private->redirect == NULL)
1597 private->redirect = private->parent->redirect;
1598 apply_redirect_to_children (private, private->redirect);
1601 _gdk_window_update_viewable (window);
1603 recompute_visible_regions (private, TRUE, FALSE);
1604 if (old_parent && GDK_WINDOW_TYPE (old_parent) != GDK_WINDOW_ROOT)
1605 recompute_visible_regions (old_parent, FALSE, TRUE);
1607 if (do_reparent_to_impl)
1608 reparent_to_impl (private);
1611 /* The reparent will have put the native window topmost in the native parent,
1612 * which may be wrong wrt other native windows in the non-native hierarchy,
1614 if (!gdk_window_has_impl (new_parent_private))
1615 sync_native_window_stack_position (window);
1619 gdk_window_show_unraised (window);
1621 _gdk_synthesize_crossing_events_for_geometry_change (window);
1625 * gdk_window_ensure_native:
1626 * @window: a #GdkWindow
1628 * Tries to ensure that there is a window-system native window for this
1629 * GdkWindow. This may fail in some situations, returning %FALSE.
1631 * Offscreen window and children of them can never have native windows.
1633 * Some backends may not support native child windows.
1635 * Returns: %TRUE if the window has a native window, %FALSE otherwise
1640 gdk_window_ensure_native (GdkWindow *window)
1642 GdkWindowObject *private;
1643 GdkWindowObject *impl_window;
1644 GdkDrawable *new_impl, *old_impl;
1647 GdkWindowAttr attributes;
1648 GdkWindowObject *above;
1651 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
1653 if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_ROOT ||
1654 GDK_WINDOW_DESTROYED (window))
1657 private = (GdkWindowObject *) window;
1659 impl_window = gdk_window_get_impl_window (private);
1661 if (impl_window->window_type == GDK_WINDOW_OFFSCREEN)
1662 return FALSE; /* native in offscreens not supported */
1664 if (impl_window == private)
1665 /* Already has an impl, and its not offscreen . */
1668 /* Need to create a native window */
1670 screen = gdk_drawable_get_screen (window);
1671 visual = gdk_drawable_get_visual (window);
1673 attributes.colormap = gdk_drawable_get_colormap (window);
1675 old_impl = private->impl;
1676 _gdk_window_impl_new (window, (GdkWindow *)private->parent, screen, visual,
1677 get_native_event_mask (private), &attributes, GDK_WA_COLORMAP);
1678 new_impl = private->impl;
1680 private->impl = old_impl;
1681 change_impl (private, private, new_impl);
1683 /* Native window creation will put the native window topmost in the
1684 * native parent, which may be wrong wrt the position of the previous
1685 * non-native window wrt to the other non-native children, so correct this.
1687 above = find_native_sibling_above (private->parent, private);
1690 listhead.data = window;
1691 listhead.prev = NULL;
1692 listhead.next = NULL;
1693 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
1697 recompute_visible_regions (private, FALSE, FALSE);
1699 /* The shape may not have been set, as the clip region doesn't actually
1700 change, so do it here manually */
1701 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->shape_combine_region ((GdkWindow *)private, private->clip_region, 0, 0);
1703 reparent_to_impl (private);
1705 if (!private->input_only)
1707 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, &private->bg_color);
1708 if (private->bg_pixmap != NULL)
1709 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, private->bg_pixmap);
1712 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_shape_combine_region ((GdkWindow *)private, private->input_shape, 0, 0);
1714 if (gdk_window_is_viewable (window))
1715 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show (window, FALSE);
1721 window_remove_filters (GdkWindow *window)
1723 GdkWindowObject *obj = (GdkWindowObject*) window;
1729 for (tmp_list = obj->filters; tmp_list; tmp_list = tmp_list->next)
1730 g_free (tmp_list->data);
1732 g_list_free (obj->filters);
1733 obj->filters = NULL;
1738 * _gdk_window_destroy_hierarchy:
1739 * @window: a #GdkWindow
1740 * @recursing: If TRUE, then this is being called because a parent
1742 * @recursing_native: If TRUE, then this is being called because a native parent
1743 * was destroyed. This generally means that the call to the
1744 * windowing system to destroy the window can be omitted, since
1745 * it will be destroyed as a result of the parent being destroyed.
1746 * Unless @foreign_destroy.
1747 * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
1748 * external agency. The window has already been destroyed and no
1749 * windowing system calls should be made. (This may never happen
1750 * for some windowing systems.)
1752 * Internal function to destroy a window. Like gdk_window_destroy(),
1753 * but does not drop the reference count created by gdk_window_new().
1756 _gdk_window_destroy_hierarchy (GdkWindow *window,
1758 gboolean recursing_native,
1759 gboolean foreign_destroy)
1761 GdkWindowObject *private;
1762 GdkWindowObject *temp_private;
1763 GdkWindow *temp_window;
1765 GdkDisplay *display;
1769 g_return_if_fail (GDK_IS_WINDOW (window));
1771 private = (GdkWindowObject*) window;
1773 if (GDK_WINDOW_DESTROYED (window))
1776 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
1777 screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
1778 temp_window = g_object_get_qdata (G_OBJECT (screen), quark_pointer_window);
1779 if (temp_window == window)
1780 g_object_set_qdata (G_OBJECT (screen), quark_pointer_window, NULL);
1783 switch (private->window_type)
1785 case GDK_WINDOW_ROOT:
1786 if (!screen->closed)
1788 g_error ("attempted to destroy root window");
1791 /* else fall thru */
1792 case GDK_WINDOW_TOPLEVEL:
1793 case GDK_WINDOW_CHILD:
1794 case GDK_WINDOW_DIALOG:
1795 case GDK_WINDOW_TEMP:
1796 case GDK_WINDOW_FOREIGN:
1797 case GDK_WINDOW_OFFSCREEN:
1798 if (private->window_type == GDK_WINDOW_FOREIGN && !foreign_destroy)
1800 /* Logically, it probably makes more sense to send
1801 * a "destroy yourself" message to the foreign window
1802 * whether or not it's in our hierarchy; but for historical
1803 * reasons, we only send "destroy yourself" messages to
1804 * foreign windows in our hierarchy.
1806 if (private->parent)
1807 _gdk_windowing_window_destroy_foreign (window);
1809 /* Also for historical reasons, we remove any filters
1810 * on a foreign window when it or a parent is destroyed;
1811 * this likely causes problems if two separate portions
1812 * of code are maintaining filter lists on a foreign window.
1814 window_remove_filters (window);
1818 if (private->parent)
1820 GdkWindowObject *parent_private = (GdkWindowObject *)private->parent;
1822 if (parent_private->children)
1823 parent_private->children = g_list_remove (parent_private->children, window);
1826 GDK_WINDOW_IS_MAPPED (window))
1828 recompute_visible_regions (private, TRUE, FALSE);
1829 gdk_window_invalidate_in_parent (private);
1833 gdk_window_free_paint_stack (window);
1835 if (private->bg_pixmap &&
1836 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
1837 private->bg_pixmap != GDK_NO_BG)
1839 g_object_unref (private->bg_pixmap);
1840 private->bg_pixmap = NULL;
1843 if (private->window_type == GDK_WINDOW_FOREIGN)
1844 g_assert (private->children == NULL);
1847 children = tmp = private->children;
1848 private->children = NULL;
1852 temp_window = tmp->data;
1855 temp_private = (GdkWindowObject*) temp_window;
1857 _gdk_window_destroy_hierarchy (temp_window,
1859 recursing_native || gdk_window_has_impl (private),
1863 g_list_free (children);
1866 _gdk_window_clear_update_area (window);
1868 if (private->cairo_surface)
1870 cairo_surface_finish (private->cairo_surface);
1871 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
1876 if (private->extension_events)
1877 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_window_destroy (window);
1879 if (gdk_window_has_impl (private))
1881 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->destroy (window, recursing_native, foreign_destroy);
1885 /* hide to make sure we repaint and break grabs */
1886 gdk_window_hide (window);
1889 private->state |= GDK_WINDOW_STATE_WITHDRAWN;
1890 private->parent = NULL;
1891 private->destroyed = TRUE;
1893 window_remove_filters (window);
1895 gdk_drawable_set_colormap (GDK_DRAWABLE (window), NULL);
1897 /* If we own the redirect, free it */
1898 if (private->redirect && private->redirect->redirected == private)
1899 gdk_window_redirect_free (private->redirect);
1901 private->redirect = NULL;
1903 if (display->pointer_info.toplevel_under_pointer == window)
1905 g_object_unref (display->pointer_info.toplevel_under_pointer);
1906 display->pointer_info.toplevel_under_pointer = NULL;
1909 if (private->clip_region)
1911 gdk_region_destroy (private->clip_region);
1912 private->clip_region = NULL;
1915 if (private->clip_region_with_children)
1917 gdk_region_destroy (private->clip_region_with_children);
1918 private->clip_region_with_children = NULL;
1921 if (private->outstanding_moves)
1923 g_list_foreach (private->outstanding_moves, (GFunc)gdk_window_region_move_free, NULL);
1924 g_list_free (private->outstanding_moves);
1925 private->outstanding_moves = NULL;
1933 * _gdk_window_destroy:
1934 * @window: a #GdkWindow
1935 * @foreign_destroy: If TRUE, the window or a parent was destroyed by some
1936 * external agency. The window has already been destroyed and no
1937 * windowing system calls should be made. (This may never happen
1938 * for some windowing systems.)
1940 * Internal function to destroy a window. Like gdk_window_destroy(),
1941 * but does not drop the reference count created by gdk_window_new().
1944 _gdk_window_destroy (GdkWindow *window,
1945 gboolean foreign_destroy)
1947 _gdk_window_destroy_hierarchy (window, FALSE, FALSE, foreign_destroy);
1951 * gdk_window_destroy:
1952 * @window: a #GdkWindow
1954 * Destroys the window system resources associated with @window and decrements @window's
1955 * reference count. The window system resources for all children of @window are also
1956 * destroyed, but the children's reference counts are not decremented.
1958 * Note that a window will not be destroyed automatically when its reference count
1959 * reaches zero. You must call this function yourself before that happens.
1963 gdk_window_destroy (GdkWindow *window)
1965 _gdk_window_destroy_hierarchy (window, FALSE, FALSE, FALSE);
1966 g_object_unref (window);
1970 * gdk_window_set_user_data:
1971 * @window: a #GdkWindow
1972 * @user_data: user data
1974 * For most purposes this function is deprecated in favor of
1975 * g_object_set_data(). However, for historical reasons GTK+ stores
1976 * the #GtkWidget that owns a #GdkWindow as user data on the
1977 * #GdkWindow. So, custom widget implementations should use
1978 * this function for that. If GTK+ receives an event for a #GdkWindow,
1979 * and the user data for the window is non-%NULL, GTK+ will assume the
1980 * user data is a #GtkWidget, and forward the event to that widget.
1984 gdk_window_set_user_data (GdkWindow *window,
1987 g_return_if_fail (GDK_IS_WINDOW (window));
1989 ((GdkWindowObject*)window)->user_data = user_data;
1993 * gdk_window_get_user_data:
1994 * @window: a #GdkWindow
1995 * @data: return location for user data
1997 * Retrieves the user data for @window, which is normally the widget
1998 * that @window belongs to. See gdk_window_set_user_data().
2002 gdk_window_get_user_data (GdkWindow *window,
2005 g_return_if_fail (GDK_IS_WINDOW (window));
2007 *data = ((GdkWindowObject*)window)->user_data;
2011 * gdk_window_get_window_type:
2012 * @window: a #GdkWindow
2014 * Gets the type of the window. See #GdkWindowType.
2016 * Return value: type of window
2019 gdk_window_get_window_type (GdkWindow *window)
2021 g_return_val_if_fail (GDK_IS_WINDOW (window), (GdkWindowType) -1);
2023 return GDK_WINDOW_TYPE (window);
2027 * gdk_window_get_position:
2028 * @window: a #GdkWindow
2029 * @x: X coordinate of window
2030 * @y: Y coordinate of window
2032 * Obtains the position of the window as reported in the
2033 * most-recently-processed #GdkEventConfigure. Contrast with
2034 * gdk_window_get_geometry() which queries the X server for the
2035 * current window position, regardless of which events have been
2036 * received or processed.
2038 * The position coordinates are relative to the window's parent window.
2042 gdk_window_get_position (GdkWindow *window,
2046 GdkWindowObject *obj;
2048 g_return_if_fail (GDK_IS_WINDOW (window));
2050 obj = (GdkWindowObject*) window;
2059 * gdk_window_get_parent:
2060 * @window: a #GdkWindow
2062 * Obtains the parent of @window, as known to GDK. Does not query the
2063 * X server; thus this returns the parent as passed to gdk_window_new(),
2064 * not the actual parent. This should never matter unless you're using
2065 * Xlib calls mixed with GDK calls on the X11 platform. It may also
2066 * matter for toplevel windows, because the window manager may choose
2069 * Return value: parent of @window
2072 gdk_window_get_parent (GdkWindow *window)
2074 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2076 return (GdkWindow*) ((GdkWindowObject*) window)->parent;
2080 * gdk_window_get_toplevel:
2081 * @window: a #GdkWindow
2083 * Gets the toplevel window that's an ancestor of @window.
2085 * Any window type but %GDK_WINDOW_CHILD is considered a
2086 * toplevel window, as is a %GDK_WINDOW_CHILD window that
2087 * has a root window as parent.
2089 * Return value: the toplevel window containing @window
2092 gdk_window_get_toplevel (GdkWindow *window)
2094 GdkWindowObject *obj;
2096 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2098 obj = (GdkWindowObject *)window;
2100 while (obj->window_type == GDK_WINDOW_CHILD)
2102 if (obj->parent == NULL ||
2103 obj->parent->window_type == GDK_WINDOW_ROOT)
2108 return GDK_WINDOW (obj);
2112 * gdk_window_get_children:
2113 * @window: a #GdkWindow
2115 * Gets the list of children of @window known to GDK.
2116 * This function only returns children created via GDK,
2117 * so for example it's useless when used with the root window;
2118 * it only returns windows an application created itself.
2120 * The returned list must be freed, but the elements in the
2123 * Return value: list of child windows inside @window
2126 gdk_window_get_children (GdkWindow *window)
2128 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2130 if (GDK_WINDOW_DESTROYED (window))
2133 return g_list_copy (GDK_WINDOW_OBJECT (window)->children);
2137 * gdk_window_peek_children:
2138 * @window: a #GdkWindow
2140 * Like gdk_window_get_children(), but does not copy the list of
2141 * children, so the list does not need to be freed.
2143 * Return value: a reference to the list of child windows in @window
2146 gdk_window_peek_children (GdkWindow *window)
2148 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
2150 if (GDK_WINDOW_DESTROYED (window))
2153 return GDK_WINDOW_OBJECT (window)->children;
2157 * gdk_window_add_filter:
2158 * @window: a #GdkWindow
2159 * @function: filter callback
2160 * @data: data to pass to filter callback
2162 * Adds an event filter to @window, allowing you to intercept events
2163 * before they reach GDK. This is a low-level operation and makes it
2164 * easy to break GDK and/or GTK+, so you have to know what you're
2165 * doing. Pass %NULL for @window to get all events for all windows,
2166 * instead of events for a specific window.
2168 * See gdk_display_add_client_message_filter() if you are interested
2169 * in X ClientMessage events.
2172 gdk_window_add_filter (GdkWindow *window,
2173 GdkFilterFunc function,
2176 GdkWindowObject *private;
2178 GdkEventFilter *filter;
2180 g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
2182 private = (GdkWindowObject*) window;
2183 if (private && GDK_WINDOW_DESTROYED (window))
2186 /* Filters are for the native events on the native window, so
2187 ensure there is a native window. */
2189 gdk_window_ensure_native (window);
2192 tmp_list = private->filters;
2194 tmp_list = _gdk_default_filters;
2198 filter = (GdkEventFilter *)tmp_list->data;
2199 if ((filter->function == function) && (filter->data == data))
2201 tmp_list = tmp_list->next;
2204 filter = g_new (GdkEventFilter, 1);
2205 filter->function = function;
2206 filter->data = data;
2209 private->filters = g_list_append (private->filters, filter);
2211 _gdk_default_filters = g_list_append (_gdk_default_filters, filter);
2215 * gdk_window_remove_filter:
2216 * @window: a #GdkWindow
2217 * @function: previously-added filter function
2218 * @data: user data for previously-added filter function
2220 * Remove a filter previously added with gdk_window_add_filter().
2224 gdk_window_remove_filter (GdkWindow *window,
2225 GdkFilterFunc function,
2228 GdkWindowObject *private;
2229 GList *tmp_list, *node;
2230 GdkEventFilter *filter;
2232 g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
2234 private = (GdkWindowObject*) window;
2237 tmp_list = private->filters;
2239 tmp_list = _gdk_default_filters;
2243 filter = (GdkEventFilter *)tmp_list->data;
2245 tmp_list = tmp_list->next;
2247 if ((filter->function == function) && (filter->data == data))
2250 private->filters = g_list_remove_link (private->filters, node);
2252 _gdk_default_filters = g_list_remove_link (_gdk_default_filters, node);
2253 g_list_free_1 (node);
2262 * gdk_screen_get_toplevel_windows:
2263 * @screen: The #GdkScreen where the toplevels are located.
2265 * Obtains a list of all toplevel windows known to GDK on the screen @screen.
2266 * A toplevel window is a child of the root window (see
2267 * gdk_get_default_root_window()).
2269 * The returned list should be freed with g_list_free(), but
2270 * its elements need not be freed.
2272 * Return value: list of toplevel windows, free with g_list_free()
2277 gdk_screen_get_toplevel_windows (GdkScreen *screen)
2279 GdkWindow * root_window;
2280 GList *new_list = NULL;
2283 g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL);
2285 root_window = gdk_screen_get_root_window (screen);
2287 tmp_list = ((GdkWindowObject *)root_window)->children;
2290 GdkWindowObject *w = tmp_list->data;
2292 if (w->window_type != GDK_WINDOW_FOREIGN)
2293 new_list = g_list_prepend (new_list, w);
2294 tmp_list = tmp_list->next;
2301 * gdk_window_get_toplevels:
2303 * Obtains a list of all toplevel windows known to GDK on the default
2304 * screen (see gdk_screen_get_toplevel_windows()).
2305 * A toplevel window is a child of the root window (see
2306 * gdk_get_default_root_window()).
2308 * The returned list should be freed with g_list_free(), but
2309 * its elements need not be freed.
2311 * Return value: list of toplevel windows, free with g_list_free()
2313 * Deprecated: 2.16: Use gdk_screen_get_toplevel_windows() instead.
2316 gdk_window_get_toplevels (void)
2318 return gdk_screen_get_toplevel_windows (gdk_screen_get_default ());
2322 * gdk_window_is_visible:
2323 * @window: a #GdkWindow
2325 * Checks whether the window has been mapped (with gdk_window_show() or
2326 * gdk_window_show_unraised()).
2328 * Return value: %TRUE if the window is mapped
2331 gdk_window_is_visible (GdkWindow *window)
2333 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2335 return GDK_WINDOW_IS_MAPPED (window);
2339 * gdk_window_is_viewable:
2340 * @window: a #GdkWindow
2342 * Check if the window and all ancestors of the window are
2343 * mapped. (This is not necessarily "viewable" in the X sense, since
2344 * we only check as far as we have GDK window parents, not to the root
2347 * Return value: %TRUE if the window is viewable
2350 gdk_window_is_viewable (GdkWindow *window)
2352 GdkWindowObject *private = (GdkWindowObject *)window;
2354 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2356 if (private->destroyed)
2359 return private->viewable;
2363 * gdk_window_get_state:
2364 * @window: a #GdkWindow
2366 * Gets the bitwise OR of the currently active window state flags,
2367 * from the #GdkWindowState enumeration.
2369 * Return value: window state bitfield
2372 gdk_window_get_state (GdkWindow *window)
2374 GdkWindowObject *private = (GdkWindowObject *)window;
2376 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
2378 return private->state;
2382 /* This creates an empty "implicit" paint region for the impl window.
2383 * By itself this does nothing, but real paints to this window
2384 * or children of it can use this pixmap as backing to avoid allocating
2385 * multiple pixmaps for subwindow rendering. When doing so they
2386 * add to the region of the implicit paint region, which will be
2387 * pushed to the window when the implicit paint region is ended.
2388 * Such paints should not copy anything to the window on paint end, but
2389 * should rely on the implicit paint end.
2390 * The implicit paint will be automatically ended if someone draws
2391 * directly to the window or a child window.
2394 gdk_window_begin_implicit_paint (GdkWindow *window, GdkRectangle *rect)
2396 GdkWindowObject *private = (GdkWindowObject *)window;
2397 GdkWindowPaint *paint;
2399 g_assert (gdk_window_has_impl (private));
2401 if (_gdk_native_windows)
2402 return FALSE; /* No need for implicit paints since we can't merge draws anyway */
2404 if (GDK_IS_PAINTABLE (private->impl))
2405 return FALSE; /* Implementation does double buffering */
2407 if (private->paint_stack != NULL ||
2408 private->implicit_paint != NULL)
2409 return FALSE; /* Don't stack implicit paints */
2411 paint = g_new (GdkWindowPaint, 1);
2412 paint->region = gdk_region_new (); /* Empty */
2413 paint->x_offset = rect->x;
2414 paint->y_offset = rect->y;
2415 paint->uses_implicit = FALSE;
2416 paint->surface = NULL;
2418 gdk_pixmap_new (window,
2419 MAX (rect->width, 1), MAX (rect->height, 1), -1);
2421 private->implicit_paint = paint;
2426 /* Ensure that all content related to this (sub)window is pushed to the
2427 native region. If there is an active paint then that area is not
2428 pushed, in order to not show partially finished double buffers. */
2430 gdk_window_flush_implicit_paint (GdkWindow *window)
2432 GdkWindowObject *private = (GdkWindowObject *)window;
2433 GdkWindowObject *impl_window;
2434 GdkWindowPaint *paint;
2439 impl_window = gdk_window_get_impl_window (private);
2440 if (impl_window->implicit_paint == NULL)
2443 paint = impl_window->implicit_paint;
2444 region = gdk_region_copy (private->clip_region_with_children);
2446 /* Don't flush active double buffers, as that may show partially done
2448 for (list = private->paint_stack; list != NULL; list = list->next)
2450 GdkWindowPaint *tmp_paint = list->data;
2452 gdk_region_subtract (region, tmp_paint->region);
2455 gdk_region_offset (region, private->abs_x, private->abs_y);
2456 gdk_region_intersect (region, paint->region);
2458 if (!gdk_region_empty (region))
2460 /* Some regions are valid, push these to window now */
2461 tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
2462 _gdk_gc_set_clip_region_internal (tmp_gc, region, TRUE);
2463 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2464 0, 0, paint->x_offset, paint->y_offset, -1, -1);
2465 /* Reset clip region of the cached GdkGC */
2466 gdk_gc_set_clip_region (tmp_gc, NULL);
2468 /* Remove flushed region from the implicit paint */
2469 gdk_region_subtract (paint->region, region);
2472 gdk_region_destroy (region);
2475 /* Ends an implicit paint, paired with gdk_window_begin_implicit_paint returning TRUE */
2477 gdk_window_end_implicit_paint (GdkWindow *window)
2479 GdkWindowObject *private = (GdkWindowObject *)window;
2480 GdkWindowPaint *paint;
2483 g_assert (gdk_window_has_impl (private));
2485 g_assert (private->implicit_paint != NULL);
2487 paint = private->implicit_paint;
2489 private->implicit_paint = NULL;
2491 if (!gdk_region_empty (paint->region))
2493 /* Some regions are valid, push these to window now */
2494 tmp_gc = _gdk_drawable_get_scratch_gc ((GdkDrawable *)window, FALSE);
2495 _gdk_gc_set_clip_region_internal (tmp_gc, paint->region, TRUE);
2496 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2497 0, 0, paint->x_offset, paint->y_offset, -1, -1);
2498 /* Reset clip region of the cached GdkGC */
2499 gdk_gc_set_clip_region (tmp_gc, NULL);
2502 g_object_unref (paint->pixmap);
2507 * gdk_window_begin_paint_rect:
2508 * @window: a #GdkWindow
2509 * @rectangle: rectangle you intend to draw to
2511 * A convenience wrapper around gdk_window_begin_paint_region() which
2512 * creates a rectangular region for you. See
2513 * gdk_window_begin_paint_region() for details.
2517 gdk_window_begin_paint_rect (GdkWindow *window,
2518 const GdkRectangle *rectangle)
2522 g_return_if_fail (GDK_IS_WINDOW (window));
2524 region = gdk_region_rectangle (rectangle);
2525 gdk_window_begin_paint_region (window, region);
2526 gdk_region_destroy (region);
2530 * gdk_window_begin_paint_region:
2531 * @window: a #GdkWindow
2532 * @region: region you intend to draw to
2534 * Indicates that you are beginning the process of redrawing @region.
2535 * A backing store (offscreen buffer) large enough to contain @region
2536 * will be created. The backing store will be initialized with the
2537 * background color or background pixmap for @window. Then, all
2538 * drawing operations performed on @window will be diverted to the
2539 * backing store. When you call gdk_window_end_paint(), the backing
2540 * store will be copied to @window, making it visible onscreen. Only
2541 * the part of @window contained in @region will be modified; that is,
2542 * drawing operations are clipped to @region.
2544 * The net result of all this is to remove flicker, because the user
2545 * sees the finished product appear all at once when you call
2546 * gdk_window_end_paint(). If you draw to @window directly without
2547 * calling gdk_window_begin_paint_region(), the user may see flicker
2548 * as individual drawing operations are performed in sequence. The
2549 * clipping and background-initializing features of
2550 * gdk_window_begin_paint_region() are conveniences for the
2551 * programmer, so you can avoid doing that work yourself.
2553 * When using GTK+, the widget system automatically places calls to
2554 * gdk_window_begin_paint_region() and gdk_window_end_paint() around
2555 * emissions of the expose_event signal. That is, if you're writing an
2556 * expose event handler, you can assume that the exposed area in
2557 * #GdkEventExpose has already been cleared to the window background,
2558 * is already set as the clip region, and already has a backing store.
2559 * Therefore in most cases, application code need not call
2560 * gdk_window_begin_paint_region(). (You can disable the automatic
2561 * calls around expose events on a widget-by-widget basis by calling
2562 * gtk_widget_set_double_buffered().)
2564 * If you call this function multiple times before calling the
2565 * matching gdk_window_end_paint(), the backing stores are pushed onto
2566 * a stack. gdk_window_end_paint() copies the topmost backing store
2567 * onscreen, subtracts the topmost region from all other regions in
2568 * the stack, and pops the stack. All drawing operations affect only
2569 * the topmost backing store in the stack. One matching call to
2570 * gdk_window_end_paint() is required for each call to
2571 * gdk_window_begin_paint_region().
2575 gdk_window_begin_paint_region (GdkWindow *window,
2576 const GdkRegion *region)
2578 #ifdef USE_BACKING_STORE
2579 GdkWindowObject *private = (GdkWindowObject *)window;
2580 GdkRectangle clip_box;
2581 GdkWindowPaint *paint, *implicit_paint;
2582 GdkWindowObject *impl_window;
2585 g_return_if_fail (GDK_IS_WINDOW (window));
2587 if (GDK_WINDOW_DESTROYED (window))
2590 if (GDK_IS_PAINTABLE (private->impl))
2592 GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
2594 if (iface->begin_paint_region)
2595 iface->begin_paint_region ((GdkPaintable*)private->impl, window, region);
2600 impl_window = gdk_window_get_impl_window (private);
2601 implicit_paint = impl_window->implicit_paint;
2603 paint = g_new (GdkWindowPaint, 1);
2604 paint->region = gdk_region_copy (region);
2605 paint->region_tag = new_region_tag ();
2607 gdk_region_intersect (paint->region, private->clip_region_with_children);
2608 gdk_region_get_clipbox (paint->region, &clip_box);
2610 /* Convert to impl coords */
2611 gdk_region_offset (paint->region, private->abs_x, private->abs_y);
2613 /* Mark the region as valid on the implicit paint */
2616 gdk_region_union (implicit_paint->region, paint->region);
2618 /* Convert back to normal coords */
2619 gdk_region_offset (paint->region, -private->abs_x, -private->abs_y);
2625 paint->uses_implicit = TRUE;
2626 paint->pixmap = g_object_ref (implicit_paint->pixmap);
2627 paint->x_offset = -private->abs_x + implicit_paint->x_offset;
2628 paint->y_offset = -private->abs_y + implicit_paint->y_offset;
2630 gdk_drawable_get_size (paint->pixmap, &width, &height);
2631 paint->surface = _gdk_drawable_create_cairo_surface (paint->pixmap, width, height);
2635 paint->uses_implicit = FALSE;
2636 paint->x_offset = clip_box.x;
2637 paint->y_offset = clip_box.y;
2639 gdk_pixmap_new (window,
2640 MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1);
2641 paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap);
2645 cairo_surface_set_device_offset (paint->surface,
2646 -paint->x_offset, -paint->y_offset);
2648 for (list = private->paint_stack; list != NULL; list = list->next)
2650 GdkWindowPaint *tmp_paint = list->data;
2652 gdk_region_subtract (tmp_paint->region, paint->region);
2655 private->paint_stack = g_slist_prepend (private->paint_stack, paint);
2657 if (!gdk_region_empty (paint->region))
2659 gdk_window_clear_backing_region (window,
2663 #endif /* USE_BACKING_STORE */
2667 setup_redirect_clip (GdkWindow *window,
2672 GdkWindowObject *private = (GdkWindowObject *)window;
2673 GdkRegion *visible_region;
2674 GdkRectangle dest_rect;
2676 GdkWindow *toplevel;
2677 int x_offset, y_offset;
2679 toplevel = GDK_WINDOW (private->redirect->redirected);
2681 /* Get the clip region for gc clip rect + window hierarchy in
2682 window relative coords */
2684 _gdk_window_calculate_full_clip_region (window, toplevel,
2689 /* Compensate for the source pos/size */
2690 x_offset -= private->redirect->src_x;
2691 y_offset -= private->redirect->src_y;
2692 dest_rect.x = -x_offset;
2693 dest_rect.y = -y_offset;
2694 dest_rect.width = private->redirect->width;
2695 dest_rect.height = private->redirect->height;
2696 tmpreg = gdk_region_rectangle (&dest_rect);
2697 gdk_region_intersect (visible_region, tmpreg);
2698 gdk_region_destroy (tmpreg);
2700 /* Compensate for the dest pos */
2701 x_offset += private->redirect->dest_x;
2702 y_offset += private->redirect->dest_y;
2704 gdk_gc_set_clip_region (gc, visible_region); /* This resets clip origin! */
2706 /* offset clip and tiles from window coords to pixmaps coords */
2707 gdk_gc_offset (gc, -x_offset, -y_offset);
2709 gdk_region_destroy (visible_region);
2711 *x_offset_out = x_offset;
2712 *y_offset_out = y_offset;
2716 * gdk_window_end_paint:
2717 * @window: a #GdkWindow
2719 * Indicates that the backing store created by the most recent call to
2720 * gdk_window_begin_paint_region() should be copied onscreen and
2721 * deleted, leaving the next-most-recent backing store or no backing
2722 * store at all as the active paint region. See
2723 * gdk_window_begin_paint_region() for full details. It is an error to
2724 * call this function without a matching
2725 * gdk_window_begin_paint_region() first.
2729 gdk_window_end_paint (GdkWindow *window)
2731 #ifdef USE_BACKING_STORE
2732 GdkWindowObject *private = (GdkWindowObject *)window;
2733 GdkWindowObject *composited;
2734 GdkWindowPaint *paint;
2736 GdkRectangle clip_box;
2737 gint x_offset, y_offset;
2738 GdkRegion *full_clip;
2740 g_return_if_fail (GDK_IS_WINDOW (window));
2742 if (GDK_WINDOW_DESTROYED (window))
2745 if (GDK_IS_PAINTABLE (private->impl))
2747 GdkPaintableIface *iface = GDK_PAINTABLE_GET_IFACE (private->impl);
2749 if (iface->end_paint)
2750 iface->end_paint ((GdkPaintable*)private->impl);
2754 if (private->paint_stack == NULL)
2756 g_warning (G_STRLOC": no preceding call to gdk_window_begin_paint_region(), see documentation");
2760 paint = private->paint_stack->data;
2762 private->paint_stack = g_slist_delete_link (private->paint_stack,
2763 private->paint_stack);
2765 gdk_region_get_clipbox (paint->region, &clip_box);
2767 tmp_gc = _gdk_drawable_get_scratch_gc (window, FALSE);
2769 x_offset = -private->abs_x;
2770 y_offset = -private->abs_y;
2772 if (!paint->uses_implicit)
2774 gdk_window_flush_outstanding_moves (window);
2776 full_clip = gdk_region_copy (private->clip_region_with_children);
2777 gdk_region_intersect (full_clip, paint->region);
2778 _gdk_gc_set_clip_region_internal (tmp_gc, full_clip, TRUE); /* Takes ownership of full_clip */
2779 gdk_gc_set_clip_origin (tmp_gc, - x_offset, - y_offset);
2780 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
2781 clip_box.x - paint->x_offset,
2782 clip_box.y - paint->y_offset,
2783 clip_box.x - x_offset, clip_box.y - y_offset,
2784 clip_box.width, clip_box.height);
2787 if (private->redirect)
2789 int x_offset, y_offset;
2791 /* TODO: Should also use paint->region for clipping */
2792 setup_redirect_clip (window, tmp_gc, &x_offset, &y_offset);
2793 gdk_draw_drawable (private->redirect->pixmap, tmp_gc, paint->pixmap,
2794 clip_box.x - paint->x_offset,
2795 clip_box.y - paint->y_offset,
2796 clip_box.x + x_offset,
2797 clip_box.y + y_offset,
2798 clip_box.width, clip_box.height);
2801 /* Reset clip region of the cached GdkGC */
2802 gdk_gc_set_clip_region (tmp_gc, NULL);
2804 cairo_surface_destroy (paint->surface);
2805 g_object_unref (paint->pixmap);
2806 gdk_region_destroy (paint->region);
2809 /* find a composited window in our hierarchy to signal its
2810 * parent to redraw, calculating the clip box as we go...
2812 * stop if parent becomes NULL since then we'd have nowhere
2813 * to draw (ie: 'composited' will always be non-NULL here).
2815 for (composited = private;
2817 composited = composited->parent)
2821 gdk_drawable_get_size (GDK_DRAWABLE (composited->parent),
2824 clip_box.x += composited->x;
2825 clip_box.y += composited->y;
2826 clip_box.width = MIN (clip_box.width, width - clip_box.x);
2827 clip_box.height = MIN (clip_box.height, height - clip_box.y);
2829 if (composited->composited)
2831 gdk_window_invalidate_rect (GDK_WINDOW (composited->parent),
2836 #endif /* USE_BACKING_STORE */
2840 gdk_window_free_paint_stack (GdkWindow *window)
2842 GdkWindowObject *private = (GdkWindowObject *)window;
2844 if (private->paint_stack)
2846 GSList *tmp_list = private->paint_stack;
2850 GdkWindowPaint *paint = tmp_list->data;
2852 if (tmp_list == private->paint_stack)
2853 g_object_unref (paint->pixmap);
2855 gdk_region_destroy (paint->region);
2858 tmp_list = tmp_list->next;
2861 g_slist_free (private->paint_stack);
2862 private->paint_stack = NULL;
2867 do_move_region_bits_on_impl (GdkWindowObject *impl_window,
2868 GdkRegion *dest_region, /* In impl window coords */
2872 GdkRectangle copy_rect;
2873 GdkWindowObject *private;
2875 /* We need to get data from subwindows here, because we might have
2876 * shaped a native window over the moving region (with bg none,
2877 * so the pixels are still there). In fact we might need to get data
2878 * from overlapping native window that are not children of this window,
2879 * so we copy from the toplevel with INCLUDE_INFERIORS.
2881 private = impl_window;
2882 while (private->parent != NULL &&
2883 private->parent->window_type != GDK_WINDOW_ROOT)
2885 dx -= private->parent->abs_x + private->x;
2886 dy -= private->parent->abs_y + private->y;
2887 private = gdk_window_get_impl_window (private->parent);
2889 tmp_gc = _gdk_drawable_get_subwindow_scratch_gc ((GdkWindow *)private);
2891 gdk_region_get_clipbox (dest_region, ©_rect);
2892 gdk_gc_set_clip_region (tmp_gc, dest_region);
2894 /* The region area is moved and we queue translations for all expose events
2895 to the source area that were sent prior to the copy */
2896 gdk_region_offset (dest_region, -dx, -dy); /* Move to source region */
2897 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->queue_translation ((GdkWindow *)impl_window,
2899 dest_region, dx, dy);
2901 gdk_draw_drawable (impl_window->impl,
2904 copy_rect.x-dx, copy_rect.y-dy,
2905 copy_rect.x, copy_rect.y,
2906 copy_rect.width, copy_rect.height);
2907 gdk_gc_set_clip_region (tmp_gc, NULL);
2910 static GdkWindowRegionMove *
2911 gdk_window_region_move_new (GdkRegion *region,
2914 GdkWindowRegionMove *move;
2916 move = g_slice_new (GdkWindowRegionMove);
2917 move->dest_region = gdk_region_copy (region);
2925 gdk_window_region_move_free (GdkWindowRegionMove *move)
2927 gdk_region_destroy (move->dest_region);
2928 g_slice_free (GdkWindowRegionMove, move);
2932 append_move_region (GdkWindowObject *impl_window,
2933 GdkRegion *new_dest_region,
2936 GdkWindowRegionMove *move, *old_move;
2937 GdkRegion *new_total_region, *old_total_region;
2938 GdkRegion *source_overlaps_destination;
2939 GdkRegion *non_overwritten;
2940 gboolean added_move;
2943 if (gdk_region_empty (new_dest_region))
2946 /* In principle this could just append the move to the list of outstanding
2947 moves that will be replayed before drawing anything when we're handling
2948 exposes. However, we'd like to do a bit better since its commonly the case
2949 that we get multiple copies where A is copied to B and then B is copied
2950 to C, and we'd like to express this as a simple copy A to C operation. */
2952 /* We approach this by taking the new move and pushing it ahead of moves
2953 starting at the end of the list and stopping when its not safe to do so.
2954 It's not safe to push past a move if either the source of the new move
2955 is in the destination of the old move, or if the destination of the new
2956 move is in the source of the new move, or if the destination of the new
2957 move overlaps the destination of the old move. We simplify this by
2958 just comparing the total regions (src + dest) */
2959 new_total_region = gdk_region_copy (new_dest_region);
2960 gdk_region_offset (new_total_region, -dx, -dy);
2961 gdk_region_union (new_total_region, new_dest_region);
2964 for (l = g_list_last (impl_window->outstanding_moves); l != NULL; l = prev)
2969 old_total_region = gdk_region_copy (old_move->dest_region);
2970 gdk_region_offset (old_total_region, -old_move->dx, -old_move->dy);
2971 gdk_region_union (old_total_region, old_move->dest_region);
2973 gdk_region_intersect (old_total_region, new_total_region);
2974 /* If these regions intersect then its not safe to push the
2975 new region before the old one */
2976 if (!gdk_region_empty (old_total_region))
2978 /* The area where the new moves source overlaps the old ones
2980 source_overlaps_destination = gdk_region_copy (new_dest_region);
2981 gdk_region_offset (source_overlaps_destination, -dx, -dy);
2982 gdk_region_intersect (source_overlaps_destination, old_move->dest_region);
2983 gdk_region_offset (source_overlaps_destination, dx, dy);
2985 /* We can do all sort of optimizations here, but to do things safely it becomes
2986 quite complicated. However, a very common case is that you copy something first,
2987 then copy all that or a subset of it to a new location (i.e. if you scroll twice
2988 in the same direction). We'd like to detect this case and optimize it to one
2990 if (gdk_region_equal (source_overlaps_destination, new_dest_region))
2992 /* This means we might be able to replace the old move and the new one
2993 with the new one read from the old ones source, and a second copy of
2994 the non-overwritten parts of the old move. However, such a split
2995 is only valid if the source in the old move isn't overwritten
2996 by the destination of the new one */
2998 /* the new destination of old move if split is ok: */
2999 non_overwritten = gdk_region_copy (old_move->dest_region);
3000 gdk_region_subtract (non_overwritten, new_dest_region);
3001 /* move to source region */
3002 gdk_region_offset (non_overwritten, -old_move->dx, -old_move->dy);
3004 gdk_region_intersect (non_overwritten, new_dest_region);
3005 if (gdk_region_empty (non_overwritten))
3008 move = gdk_window_region_move_new (new_dest_region,
3012 impl_window->outstanding_moves =
3013 g_list_insert_before (impl_window->outstanding_moves,
3015 gdk_region_subtract (old_move->dest_region, new_dest_region);
3017 gdk_region_destroy (non_overwritten);
3020 gdk_region_destroy (source_overlaps_destination);
3021 gdk_region_destroy (old_total_region);
3024 gdk_region_destroy (old_total_region);
3027 gdk_region_destroy (new_total_region);
3031 move = gdk_window_region_move_new (new_dest_region, dx, dy);
3034 impl_window->outstanding_moves =
3035 g_list_prepend (impl_window->outstanding_moves,
3038 impl_window->outstanding_moves =
3039 g_list_insert_before (impl_window->outstanding_moves,
3044 /* Moves bits and update area by dx/dy in impl window.
3045 Takes ownership of region to avoid copy (because we may change it) */
3047 move_region_on_impl (GdkWindowObject *private,
3048 GdkRegion *region, /* In impl window coords */
3051 GdkWindowObject *impl_window;
3053 if ((dx == 0 && dy == 0) ||
3054 gdk_region_empty (region))
3056 gdk_region_destroy (region);
3060 impl_window = gdk_window_get_impl_window (private);
3062 /* Move any old invalid regions in the copy source area by dx/dy */
3063 if (impl_window->update_area)
3065 GdkRegion *update_area;
3066 update_area = gdk_region_copy (region);
3068 /* Convert from target to source */
3069 gdk_region_offset (update_area, -dx, -dy);
3070 gdk_region_intersect (update_area, impl_window->update_area);
3071 /* We only copy the area, so keep the old update area invalid.
3072 It would be safe to remove it too, as code that uses
3073 move_region_on_impl generally also invalidate the source
3074 area. However, it would just use waste cycles. */
3077 gdk_region_offset (update_area, dx, dy);
3078 gdk_region_union (impl_window->update_area, update_area);
3080 /* This area of the destination is now invalid,
3081 so no need to copy to it. */
3082 gdk_region_subtract (region, update_area);
3084 gdk_region_destroy (update_area);
3087 if (1) /* Enable flicker free handling of moves. */
3088 append_move_region (impl_window, region, dx, dy);
3090 do_move_region_bits_on_impl (impl_window,
3093 gdk_region_destroy (region);
3096 /* Flushes all outstanding changes to the window, call this
3097 * before drawing directly to the window (i.e. outside a begin/end_paint pair).
3100 gdk_window_flush_outstanding_moves (GdkWindow *window)
3102 GdkWindowObject *private;
3103 GdkWindowObject *impl_window;
3105 GdkWindowRegionMove *move;
3107 private = (GdkWindowObject *) window;
3109 impl_window = gdk_window_get_impl_window (private);
3111 for (l = impl_window->outstanding_moves; l != NULL; l = l->next)
3115 do_move_region_bits_on_impl (impl_window,
3116 move->dest_region, move->dx, move->dy);
3118 gdk_window_region_move_free (move);
3121 g_list_free (impl_window->outstanding_moves);
3122 impl_window->outstanding_moves = NULL;
3126 gdk_window_flush (GdkWindow *window)
3128 gdk_window_flush_outstanding_moves (window);
3129 gdk_window_flush_implicit_paint (window);
3133 gdk_window_flush_recursive_helper (GdkWindowObject *window,
3136 GdkWindowObject *child;
3139 for (l = window->children; l != NULL; l = l->next)
3143 if (child->impl == impl)
3144 /* Same impl, ignore */
3145 gdk_window_flush_recursive_helper (child, impl);
3147 gdk_window_flush_recursive (child);
3152 gdk_window_flush_recursive (GdkWindowObject *window)
3154 gdk_window_flush ((GdkWindow *)window);
3155 gdk_window_flush_recursive_helper (window, window->impl);
3159 gdk_window_get_offsets (GdkWindow *window,
3163 GdkWindowObject *private = (GdkWindowObject *)window;
3165 if (private->paint_stack)
3167 GdkWindowPaint *paint = private->paint_stack->data;
3168 *x_offset = paint->x_offset;
3169 *y_offset = paint->y_offset;
3173 *x_offset = -private->abs_x;
3174 *y_offset = -private->abs_y;
3179 * gdk_window_get_internal_paint_info:
3180 * @window: a #GdkWindow
3181 * @real_drawable: location to store the drawable to which drawing should be
3183 * @x_offset: location to store the X offset between coordinates in @window,
3184 * and the underlying window system primitive coordinates for
3186 * @y_offset: location to store the Y offset between coordinates in @window,
3187 * and the underlying window system primitive coordinates for
3190 * If you bypass the GDK layer and use windowing system primitives to
3191 * draw directly onto a #GdkWindow, then you need to deal with two
3192 * details: there may be an offset between GDK coordinates and windowing
3193 * system coordinates, and GDK may have redirected drawing to a offscreen
3194 * pixmap as the result of a gdk_window_begin_paint_region() calls.
3195 * This function allows retrieving the information you need to compensate
3196 * for these effects.
3198 * This function exposes details of the GDK implementation, and is thus
3199 * likely to change in future releases of GDK.
3202 gdk_window_get_internal_paint_info (GdkWindow *window,
3203 GdkDrawable **real_drawable,
3209 GdkWindowObject *private;
3211 g_return_if_fail (GDK_IS_WINDOW (window));
3213 private = (GdkWindowObject *)window;
3217 if (private->paint_stack)
3219 GdkWindowPaint *paint = private->paint_stack->data;
3220 *real_drawable = paint->pixmap;
3224 /* This means you're probably gonna be doing some weird shit
3225 directly to the window, so we flush all outstanding stuff */
3226 gdk_window_flush (window);
3227 *real_drawable = window;
3231 gdk_window_get_offsets (window, &x_off, &y_off);
3239 static GdkDrawable *
3240 start_draw_helper (GdkDrawable *drawable,
3245 GdkWindowObject *private = (GdkWindowObject *)drawable;
3246 gint x_offset, y_offset;
3248 gint old_clip_x = gc->clip_x_origin;
3249 gint old_clip_y = gc->clip_y_origin;
3251 guint32 clip_region_tag;
3252 GdkWindowPaint *paint;
3255 if (private->paint_stack)
3256 paint = private->paint_stack->data;
3260 x_offset = paint->x_offset;
3261 y_offset = paint->y_offset;
3265 x_offset = -private->abs_x;
3266 y_offset = -private->abs_y;
3269 if (x_offset != 0 || y_offset != 0)
3271 gdk_gc_set_clip_origin (gc,
3272 old_clip_x - x_offset,
3273 old_clip_y - y_offset);
3274 gdk_gc_set_ts_origin (gc,
3275 gc->ts_x_origin - x_offset,
3276 gc->ts_y_origin - y_offset);
3279 *x_offset_out = x_offset;
3280 *y_offset_out = y_offset;
3282 /* Add client side window clip region to gc */
3286 /* Only need clipping if using implicit paint, otherwise
3287 the pixmap is clipped when copying to the window in end_paint */
3288 if (paint->uses_implicit)
3290 /* This includes the window clip */
3291 clip = paint->region;
3293 clip_region_tag = paint->region_tag;
3295 /* After having set up the drawable clip rect on a GC we need to make sure
3296 * that we draw to th the impl, otherwise the pixmap code will reset the
3298 impl = ((GdkPixmapObject *)(paint->pixmap))->impl;
3302 /* Drawing directly to the window, flush anything outstanding to
3303 guarantee ordering. */
3304 gdk_window_flush ((GdkWindow *)drawable);
3306 /* Don't clip when drawing to root or all native */
3307 if (!_gdk_native_windows && private->window_type != GDK_WINDOW_ROOT)
3309 if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
3310 clip = private->clip_region_with_children;
3312 clip = private->clip_region;
3314 clip_region_tag = private->clip_tag;
3315 impl = private->impl;
3319 _gdk_gc_add_drawable_clip (gc,
3320 clip_region_tag, clip,
3321 /* If there was a clip origin set appart from the
3322 * window offset, need to take that into
3324 -old_clip_x, -old_clip_y);
3329 #define BEGIN_DRAW \
3331 GdkDrawable *impl; \
3332 gint x_offset, y_offset; \
3333 gint old_clip_x = gc->clip_x_origin; \
3334 gint old_clip_y = gc->clip_y_origin; \
3335 gint old_ts_x = gc->ts_x_origin; \
3336 gint old_ts_y = gc->ts_y_origin; \
3337 impl = start_draw_helper (drawable, gc, \
3338 &x_offset, &y_offset);
3341 if (x_offset != 0 || y_offset != 0) \
3343 gdk_gc_set_clip_origin (gc, old_clip_x, old_clip_y); \
3344 gdk_gc_set_ts_origin (gc, old_ts_x, old_ts_y); \
3349 gdk_window_create_gc (GdkDrawable *drawable,
3350 GdkGCValues *values,
3351 GdkGCValuesMask mask)
3353 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
3355 if (GDK_WINDOW_DESTROYED (drawable))
3358 return gdk_gc_new_with_values (((GdkWindowObject *) drawable)->impl,
3363 gdk_window_draw_rectangle (GdkDrawable *drawable,
3371 if (GDK_WINDOW_DESTROYED (drawable))
3375 gdk_draw_rectangle (impl, gc, filled,
3376 x - x_offset, y - y_offset, width, height);
3381 gdk_window_draw_arc (GdkDrawable *drawable,
3391 if (GDK_WINDOW_DESTROYED (drawable))
3395 gdk_draw_arc (impl, gc, filled,
3396 x - x_offset, y - y_offset,
3397 width, height, angle1, angle2);
3402 gdk_window_draw_polygon (GdkDrawable *drawable,
3408 GdkPoint *new_points;
3410 if (GDK_WINDOW_DESTROYED (drawable))
3415 if (x_offset != 0 || y_offset != 0)
3419 new_points = g_new (GdkPoint, npoints);
3420 for (i=0; i<npoints; i++)
3422 new_points[i].x = points[i].x - x_offset;
3423 new_points[i].y = points[i].y - y_offset;
3427 new_points = points;
3429 gdk_draw_polygon (impl, gc, filled, new_points, npoints);
3431 if (new_points != points)
3432 g_free (new_points);
3438 gdk_window_draw_text (GdkDrawable *drawable,
3446 if (GDK_WINDOW_DESTROYED (drawable))
3450 gdk_draw_text (impl, font, gc,
3451 x - x_offset, y - y_offset, text, text_length);
3456 gdk_window_draw_text_wc (GdkDrawable *drawable,
3461 const GdkWChar *text,
3464 if (GDK_WINDOW_DESTROYED (drawable))
3468 gdk_draw_text_wc (impl, font, gc,
3469 x - x_offset, y - y_offset, text, text_length);
3473 static GdkDrawable *
3474 gdk_window_get_source_drawable (GdkDrawable *drawable)
3476 GdkWindow *window = GDK_WINDOW (drawable);
3477 GdkWindowObject *private;
3479 private = (GdkWindowObject *) window;
3480 if (GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable)
3481 return GDK_DRAWABLE_GET_CLASS (private->impl)->get_source_drawable (private->impl);
3486 static GdkDrawable *
3487 gdk_window_get_composite_drawable (GdkDrawable *drawable,
3492 gint *composite_x_offset,
3493 gint *composite_y_offset)
3495 GdkWindowObject *private = (GdkWindowObject *)drawable;
3497 GdkPixmap *tmp_pixmap;
3500 gboolean overlap_buffer;
3501 GdkDrawable *source;
3502 GdkWindowObject *impl_window;
3503 GdkWindowPaint *implicit_paint;
3505 *composite_x_offset = -private->abs_x;
3506 *composite_y_offset = -private->abs_y;
3508 if ((GDK_IS_WINDOW (drawable) && GDK_WINDOW_DESTROYED (drawable)))
3509 return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
3511 /* See if any buffered part is overlapping the part we want
3517 rect.height = height;
3519 overlap_buffer = FALSE;
3521 for (list = private->paint_stack; list != NULL; list = list->next)
3523 GdkWindowPaint *paint = list->data;
3524 GdkOverlapType overlap;
3526 overlap = gdk_region_rect_in (paint->region, &rect);
3528 if (overlap == GDK_OVERLAP_RECTANGLE_IN)
3530 *composite_x_offset = paint->x_offset;
3531 *composite_y_offset = paint->y_offset;
3533 return g_object_ref (paint->pixmap);
3535 else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
3537 overlap_buffer = TRUE;
3542 impl_window = gdk_window_get_impl_window (private);
3543 implicit_paint = impl_window->implicit_paint;
3546 GdkOverlapType overlap;
3548 rect.x += private->abs_x;
3549 rect.y += private->abs_y;
3551 overlap = gdk_region_rect_in (implicit_paint->region, &rect);
3552 if (overlap == GDK_OVERLAP_RECTANGLE_IN)
3554 *composite_x_offset = -private->abs_x + implicit_paint->x_offset;
3555 *composite_y_offset = -private->abs_y + implicit_paint->y_offset;
3557 return g_object_ref (implicit_paint->pixmap);
3559 else if (overlap == GDK_OVERLAP_RECTANGLE_PART)
3560 overlap_buffer = TRUE;
3563 if (!overlap_buffer)
3564 return g_object_ref (_gdk_drawable_get_source_drawable (drawable));
3566 tmp_pixmap = gdk_pixmap_new (drawable, width, height, -1);
3567 tmp_gc = _gdk_drawable_get_scratch_gc (tmp_pixmap, FALSE);
3569 source = _gdk_drawable_get_source_drawable (drawable);
3571 /* Copy the current window contents */
3572 gdk_draw_drawable (tmp_pixmap,
3574 GDK_WINDOW_OBJECT (source)->impl,
3575 x - *composite_x_offset,
3576 y - *composite_y_offset,
3580 /* paint the backing stores */
3583 GdkWindowPaint *paint = list->data;
3585 gdk_gc_set_clip_region (tmp_gc, paint->region);
3586 gdk_gc_set_clip_origin (tmp_gc, -x - paint->x_offset, -y - paint->y_offset);
3588 gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
3589 x - paint->x_offset,
3590 y - paint->y_offset,
3591 0, 0, width, height);
3594 for (list = private->paint_stack; list != NULL; list = list->next)
3596 GdkWindowPaint *paint = list->data;
3598 if (paint->uses_implicit)
3599 continue; /* We already copied this above */
3601 gdk_gc_set_clip_region (tmp_gc, paint->region);
3602 gdk_gc_set_clip_origin (tmp_gc, -x, -y);
3604 gdk_draw_drawable (tmp_pixmap, tmp_gc, paint->pixmap,
3605 x - paint->x_offset,
3606 y - paint->y_offset,
3607 0, 0, width, height);
3610 /* Reset clip region of the cached GdkGC */
3611 gdk_gc_set_clip_region (tmp_gc, NULL);
3613 /* Set these to location of tmp_pixmap within the window */
3614 *composite_x_offset = x;
3615 *composite_y_offset = y;
3621 gdk_window_get_clip_region (GdkDrawable *drawable)
3623 GdkWindowObject *private = (GdkWindowObject *)drawable;
3626 result = gdk_region_copy (private->clip_region);
3628 if (private->paint_stack)
3630 GdkRegion *paint_region = gdk_region_new ();
3631 GSList *tmp_list = private->paint_stack;
3635 GdkWindowPaint *paint = tmp_list->data;
3637 gdk_region_union (paint_region, paint->region);
3639 tmp_list = tmp_list->next;
3642 gdk_region_intersect (result, paint_region);
3643 gdk_region_destroy (paint_region);
3650 gdk_window_get_visible_region (GdkDrawable *drawable)
3652 GdkWindowObject *private = (GdkWindowObject*) drawable;
3654 return gdk_region_copy (private->clip_region);
3658 gdk_window_draw_drawable (GdkDrawable *drawable,
3667 GdkDrawable *original_src)
3669 GdkWindowObject *private = (GdkWindowObject *)drawable;
3671 if (GDK_WINDOW_DESTROYED (drawable))
3676 /* Call the method directly to avoid getting the composite drawable again */
3677 GDK_DRAWABLE_GET_CLASS (impl)->draw_drawable_with_src (impl, gc,
3685 if (!private->paint_stack)
3687 /* We might have drawn from an obscured part of a client
3688 side window, if so we need to send graphics exposures */
3689 if (_gdk_gc_get_exposures (gc) &&
3690 GDK_IS_WINDOW (original_src))
3692 GdkRegion *exposure_region;
3700 exposure_region = gdk_region_rectangle (&r);
3702 if (_gdk_gc_get_subwindow (gc) == GDK_CLIP_BY_CHILDREN)
3703 clip = private->clip_region_with_children;
3705 clip = private->clip_region;
3706 gdk_region_intersect (exposure_region, clip);
3708 clip = _gdk_gc_get_clip_region (gc);
3711 gdk_region_offset (exposure_region,
3714 gdk_region_intersect (exposure_region, clip);
3715 gdk_region_offset (exposure_region,
3720 /* Note: We don't clip by the clip mask if set, so this
3721 may invalidate to much */
3723 /* Remove the area that is correctly copied from the src.
3724 * Note that xsrc/ysrc has been corrected for abs_x/y offsets already,
3725 * which need to be undone */
3726 clip = gdk_drawable_get_visible_region (original_src);
3727 gdk_region_offset (clip,
3728 xdest - (xsrc - GDK_WINDOW_OBJECT (original_src)->abs_x),
3729 ydest - (ysrc - GDK_WINDOW_OBJECT (original_src)->abs_y));
3730 gdk_region_subtract (exposure_region, clip);
3731 gdk_region_destroy (clip);
3733 gdk_window_invalidate_region (GDK_WINDOW (private),
3735 _gdk_gc_get_subwindow (gc) == GDK_INCLUDE_INFERIORS);
3737 gdk_region_destroy (exposure_region);
3745 gdk_window_draw_points (GdkDrawable *drawable,
3750 GdkPoint *new_points;
3752 if (GDK_WINDOW_DESTROYED (drawable))
3757 if (x_offset != 0 || y_offset != 0)
3761 new_points = g_new (GdkPoint, npoints);
3762 for (i=0; i<npoints; i++)
3764 new_points[i].x = points[i].x - x_offset;
3765 new_points[i].y = points[i].y - y_offset;
3769 new_points = points;
3771 gdk_draw_points (impl, gc, new_points, npoints);
3773 if (new_points != points)
3774 g_free (new_points);
3780 gdk_window_draw_segments (GdkDrawable *drawable,
3785 GdkSegment *new_segs;
3787 if (GDK_WINDOW_DESTROYED (drawable))
3792 if (x_offset != 0 || y_offset != 0)
3796 new_segs = g_new (GdkSegment, nsegs);
3797 for (i=0; i<nsegs; i++)
3799 new_segs[i].x1 = segs[i].x1 - x_offset;
3800 new_segs[i].y1 = segs[i].y1 - y_offset;
3801 new_segs[i].x2 = segs[i].x2 - x_offset;
3802 new_segs[i].y2 = segs[i].y2 - y_offset;
3808 gdk_draw_segments (impl, gc, new_segs, nsegs);
3810 if (new_segs != segs)
3817 gdk_window_draw_lines (GdkDrawable *drawable,
3822 GdkPoint *new_points;
3824 if (GDK_WINDOW_DESTROYED (drawable))
3829 if (x_offset != 0 || y_offset != 0)
3833 new_points = g_new (GdkPoint, npoints);
3834 for (i=0; i<npoints; i++)
3836 new_points[i].x = points[i].x - x_offset;
3837 new_points[i].y = points[i].y - y_offset;
3841 new_points = points;
3843 gdk_draw_lines (impl, gc, new_points, npoints);
3845 if (new_points != points)
3846 g_free (new_points);
3852 gdk_window_draw_glyphs (GdkDrawable *drawable,
3857 PangoGlyphString *glyphs)
3859 if (GDK_WINDOW_DESTROYED (drawable))
3863 gdk_draw_glyphs (impl, gc, font,
3864 x - x_offset, y - y_offset, glyphs);
3869 gdk_window_draw_glyphs_transformed (GdkDrawable *drawable,
3871 PangoMatrix *matrix,
3875 PangoGlyphString *glyphs)
3877 PangoMatrix tmp_matrix;
3879 if (GDK_WINDOW_DESTROYED (drawable))
3884 if (x_offset != 0 || y_offset != 0)
3888 tmp_matrix = *matrix;
3889 tmp_matrix.x0 -= x_offset;
3890 tmp_matrix.y0 -= y_offset;
3891 matrix = &tmp_matrix;
3893 else if (GDK_PANGO_UNITS_OVERFLOWS (x_offset, y_offset))
3895 PangoMatrix identity = PANGO_MATRIX_INIT;
3897 tmp_matrix = identity;
3898 tmp_matrix.x0 -= x_offset;
3899 tmp_matrix.y0 -= y_offset;
3900 matrix = &tmp_matrix;
3904 x -= x_offset * PANGO_SCALE;
3905 y -= y_offset * PANGO_SCALE;
3909 gdk_draw_glyphs_transformed (impl, gc, matrix, font, x, y, glyphs);
3915 cairo_t *cr; /* if non-null, it means use this cairo context */
3916 GdkGC *gc; /* if non-null, it means use this GC instead */
3917 } BackingRectMethod;
3920 setup_backing_rect_method (BackingRectMethod *method, GdkWindow *window, GdkWindowPaint *paint, int x_offset_cairo, int y_offset_cairo)
3922 GdkWindowObject *private = (GdkWindowObject *)window;
3924 if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
3926 GdkWindowPaint tmp_paint;
3929 tmp_paint.x_offset += private->x;
3930 tmp_paint.y_offset += private->y;
3932 x_offset_cairo += private->x;
3933 y_offset_cairo += private->y;
3935 setup_backing_rect_method (method, GDK_WINDOW (private->parent), &tmp_paint, x_offset_cairo, y_offset_cairo);
3937 else if (private->bg_pixmap &&
3938 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
3939 private->bg_pixmap != GDK_NO_BG)
3941 /* This is a workaround for https://bugs.freedesktop.org/show_bug.cgi?id=4320.
3942 * In it, using a pixmap as a repeating pattern in Cairo, and painting it to a
3943 * pixmap destination surface, can be very slow (on the order of seconds for a
3944 * whole-screen copy). The workaround is to use pretty much the same code that
3945 * we used in GTK+ 2.6 (pre-Cairo), which clears the double-buffer pixmap with
3946 * a tiled GC XFillRectangle().
3949 /* Actually computing this flag is left as an exercise for the reader */
3950 #if defined (G_OS_UNIX)
3951 # define GDK_CAIRO_REPEAT_IS_FAST 0
3953 # define GDK_CAIRO_REPEAT_IS_FAST 1
3956 #if GDK_CAIRO_REPEAT_IS_FAST
3957 cairo_surface_t *surface = _gdk_drawable_ref_cairo_surface (private->bg_pixmap);
3958 cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
3959 cairo_surface_destroy (surface);
3961 if (x_offset_cairo != 0 || y_offset_cairo != 0)
3963 cairo_matrix_t matrix;
3964 cairo_matrix_init_translate (&matrix, x_offset_cairo, y_offset_cairo);
3965 cairo_pattern_set_matrix (pattern, &matrix);
3968 cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
3970 method->cr = cairo_create (paint->surface);
3973 cairo_set_source (method->cr, pattern);
3974 cairo_pattern_destroy (pattern);
3977 GdkGCValues gc_values;
3979 gc_values.fill = GDK_TILED;
3980 gc_values.tile = private->bg_pixmap;
3981 gc_values.ts_x_origin = -x_offset_cairo;
3982 gc_values.ts_y_origin = -y_offset_cairo;
3984 gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN;
3986 method->gc = gdk_gc_new_with_values (paint->pixmap, &gc_values, gc_mask);
3991 method->cr = cairo_create (paint->surface);
3993 gdk_cairo_set_source_color (method->cr, &private->bg_color);
3998 gdk_window_clear_backing_region (GdkWindow *window,
4001 GdkWindowObject *private = (GdkWindowObject *)window;
4002 GdkWindowPaint *paint = private->paint_stack->data;
4003 BackingRectMethod method;
4005 GdkRectangle clipbox;
4011 if (GDK_WINDOW_DESTROYED (window))
4015 timer = g_timer_new ();
4020 setup_backing_rect_method (&method, window, paint, 0, 0);
4022 clip = gdk_region_copy (paint->region);
4023 gdk_region_intersect (clip, region);
4024 gdk_region_get_clipbox (clip, &clipbox);
4029 g_assert (method.gc == NULL);
4031 gdk_cairo_region (method.cr, clip);
4032 cairo_fill (method.cr);
4034 cairo_destroy (method.cr);
4036 elapsed = g_timer_elapsed (timer, NULL);
4037 g_print ("Draw the background with Cairo: %fs\n", elapsed);
4042 g_assert (method.gc != NULL);
4044 gdk_gc_set_clip_region (method.gc, clip);
4045 gdk_draw_rectangle (window, method.gc, TRUE,
4046 clipbox.x, clipbox.y,
4047 clipbox.width, clipbox.height);
4048 g_object_unref (method.gc);
4051 elapsed = g_timer_elapsed (timer, NULL);
4052 g_print ("Draw the background with GDK: %fs\n", elapsed);
4056 gdk_region_destroy (clip);
4059 g_timer_destroy (timer);
4064 gdk_window_clear_backing_region_redirect (GdkWindow *window,
4067 GdkWindowObject *private = (GdkWindowObject *)window;
4068 GdkWindowRedirect *redirect = private->redirect;
4069 GdkRegion *clip_region;
4070 GdkRectangle clipbox;
4071 gint x_offset, y_offset;
4072 BackingRectMethod method;
4073 GdkWindowPaint paint;
4075 if (GDK_WINDOW_DESTROYED (window))
4078 clip_region = _gdk_window_calculate_full_clip_region (window,
4079 GDK_WINDOW (redirect->redirected),
4081 &x_offset, &y_offset);
4082 gdk_region_intersect (clip_region, region);
4084 /* offset is from redirected window origin to window origin, convert to
4085 the offset from the redirected pixmap origin to the window origin */
4086 x_offset += redirect->dest_x - redirect->src_x;
4087 y_offset += redirect->dest_y - redirect->src_y;
4089 /* Convert region to pixmap coords */
4090 gdk_region_offset (clip_region, x_offset, y_offset);
4094 paint.pixmap = redirect->pixmap;
4095 paint.surface = _gdk_drawable_ref_cairo_surface (redirect->pixmap);
4099 setup_backing_rect_method (&method, window, &paint, -x_offset, -y_offset);
4103 g_assert (method.gc == NULL);
4105 gdk_cairo_region (method.cr, clip_region);
4106 cairo_fill (method.cr);
4108 cairo_destroy (method.cr);
4112 g_assert (method.gc != NULL);
4114 gdk_region_get_clipbox (clip_region, &clipbox);
4115 gdk_gc_set_clip_region (method.gc, clip_region);
4116 gdk_draw_rectangle (redirect->pixmap, method.gc, TRUE,
4117 clipbox.x, clipbox.y,
4118 clipbox.width, clipbox.height);
4119 g_object_unref (method.gc);
4123 gdk_region_destroy (clip_region);
4124 cairo_surface_destroy (paint.surface);
4128 gdk_window_clear_backing_region_direct (GdkWindow *window,
4131 GdkWindowObject *private = (GdkWindowObject *)window;
4132 BackingRectMethod method;
4133 GdkWindowPaint paint;
4135 GdkRectangle clipbox;
4137 if (GDK_WINDOW_DESTROYED (window))
4142 paint.pixmap = window;
4143 paint.surface = _gdk_drawable_ref_cairo_surface (window);
4147 setup_backing_rect_method (&method, window, &paint, 0, 0);
4149 clip = gdk_region_copy (private->clip_region_with_children);
4150 gdk_region_intersect (clip, region);
4151 gdk_region_get_clipbox (clip, &clipbox);
4155 g_assert (method.gc == NULL);
4157 gdk_cairo_region (method.cr, clip);
4158 cairo_fill (method.cr);
4160 cairo_destroy (method.cr);
4164 g_assert (method.gc != NULL);
4166 gdk_gc_set_clip_region (method.gc, clip);
4167 gdk_draw_rectangle (window, method.gc, TRUE,
4168 clipbox.x, clipbox.y,
4169 clipbox.width, clipbox.height);
4170 g_object_unref (method.gc);
4174 gdk_region_destroy (clip);
4175 cairo_surface_destroy (paint.surface);
4181 * @window: a #GdkWindow
4183 * Clears an entire @window to the background color or background pixmap.
4186 gdk_window_clear (GdkWindow *window)
4190 g_return_if_fail (GDK_IS_WINDOW (window));
4192 gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height);
4194 gdk_window_clear_area (window, 0, 0,
4199 clears_on_native (GdkWindowObject *private)
4201 GdkWindowObject *next;
4207 if (gdk_window_has_impl (private))
4209 next = private->parent;
4211 while (private->bg_pixmap == GDK_PARENT_RELATIVE_BG &&
4212 next && next->window_type != GDK_WINDOW_ROOT);
4217 gdk_window_clear_region_internal (GdkWindow *window,
4219 gboolean send_expose)
4221 GdkWindowObject *private = (GdkWindowObject *)window;
4223 if (private->paint_stack)
4224 gdk_window_clear_backing_region (window, region);
4227 if (private->redirect)
4228 gdk_window_clear_backing_region_redirect (window, region);
4230 if (GDK_WINDOW_IMPL_GET_IFACE (private->impl)->clear_region &&
4231 clears_on_native (private))
4234 copy = gdk_region_copy (region);
4235 gdk_region_intersect (copy, private->clip_region_with_children);
4237 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->clear_region
4238 (window, copy, send_expose);
4240 gdk_region_destroy (copy);
4244 gdk_window_clear_backing_region_direct (window, region);
4246 gdk_window_invalidate_region (window, region, FALSE);
4252 gdk_window_clear_area_internal (GdkWindow *window,
4257 gboolean send_expose)
4259 GdkWindowObject *private = (GdkWindowObject *)window;
4263 g_return_if_fail (GDK_IS_WINDOW (window));
4265 if (GDK_WINDOW_DESTROYED (window))
4268 /* This is what XClearArea does, and e.g. GtkCList uses it,
4269 so we need to duplicate that */
4271 width = private->width - x;
4273 height = private->height - y;
4278 rect.height = height;
4280 region = gdk_region_rectangle (&rect);
4281 gdk_window_clear_region_internal (window,
4284 gdk_region_destroy (region);
4289 * gdk_window_clear_area:
4290 * @window: a #GdkWindow
4291 * @x: x coordinate of rectangle to clear
4292 * @y: y coordinate of rectangle to clear
4293 * @width: width of rectangle to clear
4294 * @height: height of rectangle to clear
4296 * Clears an area of @window to the background color or background pixmap.
4300 gdk_window_clear_area (GdkWindow *window,
4306 gdk_window_clear_area_internal (window,
4313 * gdk_window_clear_area_e:
4314 * @window: a #GdkWindow
4315 * @x: x coordinate of rectangle to clear
4316 * @y: y coordinate of rectangle to clear
4317 * @width: width of rectangle to clear
4318 * @height: height of rectangle to clear
4320 * Like gdk_window_clear_area(), but also generates an expose event for
4323 * This function has a stupid name because it dates back to the mists
4324 * time, pre-GDK-1.0.
4328 gdk_window_clear_area_e (GdkWindow *window,
4334 gdk_window_clear_area_internal (window,
4341 gdk_window_draw_image (GdkDrawable *drawable,
4351 if (GDK_WINDOW_DESTROYED (drawable))
4355 gdk_draw_image (impl, gc, image, xsrc, ysrc,
4356 xdest - x_offset, ydest - y_offset,
4362 gdk_window_draw_pixbuf (GdkDrawable *drawable,
4371 GdkRgbDither dither,
4375 GdkWindowObject *private = (GdkWindowObject *)drawable;
4376 GdkDrawableClass *klass;
4378 if (GDK_WINDOW_DESTROYED (drawable))
4381 /* If no gc => no user clipping, but we need clipping
4382 for window emulation, so use a scratch gc */
4384 gc = _gdk_drawable_get_scratch_gc (drawable, FALSE);
4388 klass = GDK_DRAWABLE_GET_CLASS (impl);
4390 if (private->paint_stack)
4391 klass->draw_pixbuf (impl, gc, pixbuf, src_x, src_y,
4392 dest_x - x_offset, dest_y - y_offset,
4394 dither, x_dither - x_offset, y_dither - y_offset);
4396 klass->draw_pixbuf (impl, gc, pixbuf, src_x, src_y,
4397 dest_x - x_offset, dest_y - y_offset,
4399 dither, x_dither, y_dither);
4404 gdk_window_draw_trapezoids (GdkDrawable *drawable,
4406 GdkTrapezoid *trapezoids,
4409 GdkTrapezoid *new_trapezoids = NULL;
4411 if (GDK_WINDOW_DESTROYED (drawable))
4416 if (x_offset != 0 || y_offset != 0)
4420 new_trapezoids = g_new (GdkTrapezoid, n_trapezoids);
4421 for (i=0; i < n_trapezoids; i++)
4423 new_trapezoids[i].y1 = trapezoids[i].y1 - y_offset;
4424 new_trapezoids[i].x11 = trapezoids[i].x11 - x_offset;
4425 new_trapezoids[i].x21 = trapezoids[i].x21 - x_offset;
4426 new_trapezoids[i].y2 = trapezoids[i].y2 - y_offset;
4427 new_trapezoids[i].x12 = trapezoids[i].x12 - x_offset;
4428 new_trapezoids[i].x22 = trapezoids[i].x22 - x_offset;
4431 trapezoids = new_trapezoids;
4434 gdk_draw_trapezoids (impl, gc, trapezoids, n_trapezoids);
4436 g_free (new_trapezoids);
4442 gdk_window_real_get_size (GdkDrawable *drawable,
4446 GdkWindowObject *private = (GdkWindowObject *)drawable;
4449 *width = private->width;
4451 *height = private->height;
4455 gdk_window_real_get_visual (GdkDrawable *drawable)
4457 GdkColormap *colormap;
4459 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4461 colormap = gdk_drawable_get_colormap (drawable);
4462 return colormap ? gdk_colormap_get_visual (colormap) : NULL;
4466 gdk_window_real_get_depth (GdkDrawable *drawable)
4468 g_return_val_if_fail (GDK_IS_WINDOW (drawable), 0);
4470 return ((GdkWindowObject *)GDK_WINDOW (drawable))->depth;
4474 gdk_window_real_get_screen (GdkDrawable *drawable)
4476 return gdk_drawable_get_screen (GDK_WINDOW_OBJECT (drawable)->impl);
4480 gdk_window_real_set_colormap (GdkDrawable *drawable,
4483 GdkWindowObject *private;
4485 g_return_if_fail (GDK_IS_WINDOW (drawable));
4487 if (GDK_WINDOW_DESTROYED (drawable))
4490 private = (GdkWindowObject *)drawable;
4492 /* different colormap than parent, requires native window */
4493 if (!private->input_only &&
4494 cmap != gdk_drawable_get_colormap ((GdkDrawable *)(private->parent)))
4495 gdk_window_ensure_native ((GdkWindow *)drawable);
4497 gdk_drawable_set_colormap (private->impl, cmap);
4501 gdk_window_real_get_colormap (GdkDrawable *drawable)
4503 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4505 if (GDK_WINDOW_DESTROYED (drawable))
4508 return gdk_drawable_get_colormap (((GdkWindowObject*)drawable)->impl);
4512 gdk_window_copy_to_image (GdkDrawable *drawable,
4521 GdkWindowObject *private = (GdkWindowObject *) drawable;
4522 gint x_offset, y_offset;
4524 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
4526 if (GDK_WINDOW_DESTROYED (drawable))
4529 /* If we're here, a composite image was not necessary, so
4530 * we can ignore the paint stack.
4533 /* TODO: Is this right? */
4537 return gdk_drawable_copy_to_image (private->impl,
4546 gdk_window_cairo_surface_destroy (void *data)
4548 GdkWindowObject *private = (GdkWindowObject*) data;
4550 private->cairo_surface = NULL;
4553 static cairo_surface_t *
4554 gdk_window_create_cairo_surface (GdkDrawable *drawable,
4558 return _gdk_windowing_create_cairo_surface (GDK_WINDOW_OBJECT(drawable)->impl,
4563 static cairo_surface_t *
4564 gdk_window_ref_cairo_surface (GdkDrawable *drawable)
4566 GdkWindowObject *private = (GdkWindowObject*) drawable;
4567 cairo_surface_t *surface;
4569 if (private->paint_stack)
4571 GdkWindowPaint *paint = private->paint_stack->data;
4573 surface = paint->surface;
4574 cairo_surface_reference (surface);
4579 /* This will be drawing directly to the window, so flush implicit paint */
4580 gdk_window_flush ((GdkWindow *)drawable);
4582 if (!private->cairo_surface)
4585 GdkDrawable *source;
4587 /* It would be nice if we had some cairo support here so we
4588 could set the clip rect on the cairo surface */
4589 width = private->abs_x + private->width;
4590 height = private->abs_y + private->height;
4592 source = _gdk_drawable_get_source_drawable (drawable);
4594 /* TODO: Avoid the typecheck crap by adding virtual call */
4595 private->cairo_surface = _gdk_drawable_create_cairo_surface (source, width, height);
4597 if (private->cairo_surface)
4599 cairo_surface_set_device_offset (private->cairo_surface,
4603 cairo_surface_set_user_data (private->cairo_surface, &gdk_window_cairo_key,
4604 drawable, gdk_window_cairo_surface_destroy);
4608 cairo_surface_reference (private->cairo_surface);
4610 surface = private->cairo_surface;
4617 gdk_window_set_cairo_clip (GdkDrawable *drawable,
4620 GdkWindowObject *private = (GdkWindowObject*) drawable;
4622 if (!private->paint_stack)
4624 cairo_reset_clip (cr);
4627 cairo_identity_matrix (cr);
4629 cairo_new_path (cr);
4630 gdk_cairo_region (cr, private->clip_region_with_children);
4637 GdkWindowPaint *paint = private->paint_stack->data;
4639 /* Only needs to clip to region if piggybacking
4640 on an implicit paint pixmap */
4641 cairo_reset_clip (cr);
4642 if (paint->uses_implicit)
4645 cairo_identity_matrix (cr);
4647 cairo_new_path (cr);
4648 gdk_cairo_region (cr, paint->region);
4656 /* Code for dirty-region queueing
4658 static GSList *update_windows = NULL;
4659 static guint update_idle = 0;
4660 static gboolean debug_updates = FALSE;
4662 static inline gboolean
4663 gdk_window_is_ancestor (GdkWindow *window,
4664 GdkWindow *ancestor)
4668 GdkWindow *parent = (GdkWindow*) ((GdkWindowObject*) window)->parent;
4670 if (parent == ancestor)
4680 gdk_window_add_update_window (GdkWindow *window)
4683 GSList *prev = NULL;
4684 gboolean has_ancestor_in_list = FALSE;
4686 for (tmp = update_windows; tmp; tmp = tmp->next)
4688 GdkWindowObject *parent = GDK_WINDOW_OBJECT (window)->parent;
4690 /* check if tmp is an ancestor of "window"; if it is, set a
4691 * flag indicating that all following windows are either
4692 * children of "window" or from a differen hierarchy
4694 if (!has_ancestor_in_list && gdk_window_is_ancestor (window, tmp->data))
4695 has_ancestor_in_list = TRUE;
4697 /* insert in reverse stacking order when adding around siblings,
4698 * so processing updates properly paints over lower stacked windows
4700 if (parent == GDK_WINDOW_OBJECT (tmp->data)->parent)
4702 gint index = g_list_index (parent->children, window);
4703 for (; tmp && parent == GDK_WINDOW_OBJECT (tmp->data)->parent; tmp = tmp->next)
4705 gint sibling_index = g_list_index (parent->children, tmp->data);
4706 if (index > sibling_index)
4710 /* here, tmp got advanced past all lower stacked siblings */
4711 tmp = g_slist_prepend (tmp, window);
4715 update_windows = tmp;
4719 /* if "window" has an ancestor in the list and tmp is one of
4720 * "window's" children, insert "window" before tmp
4722 if (has_ancestor_in_list && gdk_window_is_ancestor (tmp->data, window))
4724 tmp = g_slist_prepend (tmp, window);
4729 update_windows = tmp;
4733 /* if we're at the end of the list and had an ancestor it it,
4734 * append to the list
4736 if (! tmp->next && has_ancestor_in_list)
4738 tmp = g_slist_append (tmp, window);
4745 /* if all above checks failed ("window" is from a different
4746 * hierarchy than what is already in the list) or the list is
4749 update_windows = g_slist_prepend (update_windows, window);
4753 gdk_window_remove_update_window (GdkWindow *window)
4755 update_windows = g_slist_remove (update_windows, window);
4759 gdk_window_update_idle (gpointer data)
4761 gdk_window_process_all_updates ();
4767 gdk_window_is_toplevel_frozen (GdkWindow *window)
4769 GdkWindowObject *toplevel;
4771 toplevel = (GdkWindowObject *)gdk_window_get_toplevel (window);
4773 return toplevel->update_and_descendants_freeze_count > 0;
4777 gdk_window_schedule_update (GdkWindow *window)
4780 (GDK_WINDOW_OBJECT (window)->update_freeze_count ||
4781 gdk_window_is_toplevel_frozen (window)))
4786 update_idle = gdk_threads_add_idle_full (GDK_PRIORITY_REDRAW,
4787 gdk_window_update_idle, NULL, NULL);
4792 _gdk_window_process_updates_recurse (GdkWindow *window,
4793 GdkRegion *expose_region)
4795 GdkWindowObject *private = (GdkWindowObject *)window;
4796 GdkWindowObject *child;
4797 GdkRegion *child_region;
4799 GList *l, *children;
4801 if (gdk_region_empty (expose_region))
4804 /* Make this reentrancy safe for expose handlers freeing windows */
4805 children = g_list_copy (private->children);
4806 g_list_foreach (children, (GFunc)g_object_ref, NULL);
4808 /* Iterate over children, starting at topmost */
4809 for (l = children; l != NULL; l = l->next)
4813 if (child->destroyed || !GDK_WINDOW_IS_MAPPED (child) || child->input_only || child->composited)
4816 /* Ignore offscreen children, as they don't draw in their parent and
4817 * don't take part in the clipping */
4818 if (gdk_window_is_offscreen (child))
4823 r.width = child->width;
4824 r.height = child->height;
4826 child_region = gdk_region_rectangle (&r);
4829 /* Adjust shape region to parent window coords */
4830 gdk_region_offset (child->shape, child->x, child->y);
4831 gdk_region_intersect (child_region, child->shape);
4832 gdk_region_offset (child->shape, -child->x, -child->y);
4835 if (child->impl == private->impl)
4837 /* Client side child, expose */
4838 gdk_region_intersect (child_region, expose_region);
4839 gdk_region_subtract (expose_region, child_region);
4840 gdk_region_offset (child_region, -child->x, -child->y);
4841 _gdk_window_process_updates_recurse ((GdkWindow *)child, child_region);
4845 /* Native child, just remove area from expose region */
4846 gdk_region_subtract (expose_region, child_region);
4848 gdk_region_destroy (child_region);
4851 g_list_foreach (children, (GFunc)g_object_unref, NULL);
4852 g_list_free (children);
4854 if (!gdk_region_empty (expose_region) &&
4855 !private->destroyed)
4857 if (private->event_mask & GDK_EXPOSURE_MASK)
4861 event.expose.type = GDK_EXPOSE;
4862 event.expose.window = g_object_ref (window);
4863 event.expose.send_event = FALSE;
4864 event.expose.count = 0;
4865 event.expose.region = expose_region;
4866 gdk_region_get_clipbox (expose_region, &event.expose.area);
4868 (*_gdk_event_func) (&event, _gdk_event_data);
4870 g_object_unref (window);
4872 else if (private->bg_pixmap != GDK_NO_BG)
4874 /* No exposure mask set, so nothing will be drawn, the
4875 * app relies on the background being what it specified
4876 * for the window. So, we need to clear this manually.
4878 * We use begin/end_paint around the clear so that we can
4879 * piggyback on the implicit paint */
4881 gdk_window_begin_paint_region (window, expose_region);
4882 gdk_window_clear_region_internal (window, expose_region, FALSE);
4883 gdk_window_end_paint (window);
4888 /* Process and remove any invalid area on the native window by creating
4889 * expose events for the window and all non-native descendants.
4890 * Also processes any outstanding moves on the window before doing
4891 * any drawing. Note that its possible to have outstanding moves without
4892 * any invalid area as we use the update idle mechanism to coalesce
4893 * multiple moves as well as multiple invalidations.
4896 gdk_window_process_updates_internal (GdkWindow *window)
4898 GdkWindowObject *private = (GdkWindowObject *)window;
4899 gboolean save_region = FALSE;
4900 GdkRectangle clip_box;
4902 /* Ensure the window lives while updating it */
4903 g_object_ref (window);
4905 /* If an update got queued during update processing, we can get a
4906 * window in the update queue that has an empty update_area.
4909 if (private->update_area)
4911 GdkRegion *update_area = private->update_area;
4912 private->update_area = NULL;
4914 if (_gdk_event_func && gdk_window_is_viewable (window) &&
4915 private->window_type != GDK_WINDOW_FOREIGN)
4917 GdkRegion *expose_region;
4918 gboolean end_implicit;
4920 /* Clip to part visible in toplevel */
4921 gdk_region_intersect (update_area, private->clip_region);
4925 /* Make sure we see the red invalid area before redrawing. */
4926 gdk_display_sync (gdk_drawable_get_display (window));
4930 /* At this point we will be completely redrawing all of update_area.
4931 * If we have any outstanding moves that end up moving stuff inside
4932 * this area we don't actually need to move that as that part would
4933 * be overdrawn by the expose anyway. So, in order to copy less data
4934 * we remove these areas from the outstanding moves.
4936 if (private->outstanding_moves)
4938 GdkWindowRegionMove *move;
4942 remove = gdk_region_copy (update_area);
4943 /* We iterate backwards, starting from the state that would be
4944 if we had applied all the moves. */
4945 for (l = g_list_last (private->outstanding_moves); l != NULL; l = prev)
4950 /* Don't need this area */
4951 gdk_region_subtract (move->dest_region, remove);
4953 /* However if any of the destination we do need has a source
4954 in the updated region we do need that as a destination for
4955 the earlier moves */
4956 gdk_region_offset (move->dest_region, -move->dx, -move->dy);
4957 gdk_region_subtract (remove, move->dest_region);
4959 if (gdk_region_empty (move->dest_region))
4961 gdk_window_region_move_free (move);
4962 private->outstanding_moves =
4963 g_list_delete_link (private->outstanding_moves, l);
4965 else /* move back */
4966 gdk_region_offset (move->dest_region, move->dx, move->dy);
4968 gdk_region_destroy (remove);
4971 /* By now we a set of window moves that should be applied, and then
4972 * an update region that should be repainted. A trivial implementation
4973 * would just do that in order, however in order to get nicer drawing
4974 * we do some tricks:
4976 * First of all, each subwindow expose may be double buffered by
4977 * itself (depending on widget setting) via
4978 * gdk_window_begin/end_paint(). But we also do an "implicit" paint,
4979 * creating a single pixmap the size of the invalid area on the
4980 * native window which all the individual normal paints will draw
4981 * into. This way in the normal case there will be only one pixmap
4982 * allocated and only once pixmap draw done for all the windows
4983 * in this native window.
4984 * There are a couple of reasons this may fail, for instance, some
4985 * backends (like quartz) do its own double buffering, so we disable
4986 * gdk double buffering there. Secondly, some subwindow could be
4987 * non-double buffered and draw directly to the window outside a
4988 * begin/end_paint pair. That will be lead to a gdk_window_flush
4989 * which immediately executes all outstanding moves and paints+removes
4990 * the implicit paint (further paints will allocate their own pixmap).
4992 * Secondly, in the case of implicit double buffering we expose all
4993 * the child windows into the implicit pixmap before we execute
4994 * the outstanding moves. This way we minimize the time between
4995 * doing the moves and rendering the new update area, thus minimizing
4996 * flashing. Of course, if any subwindow is non-double buffered we
4997 * well flush earlier than that.
4999 * Thirdly, after having done the outstanding moves we queue an
5000 * "antiexpose" on the area that will be drawn by the expose, which
5001 * means that any invalid region on the native window side before
5002 * the first expose drawing operation will be discarded, as it
5003 * has by then been overdrawn with valid data. This means we can
5004 * avoid doing the unnecessary repaint any outstanding expose events.
5007 gdk_region_get_clipbox (update_area, &clip_box);
5008 end_implicit = gdk_window_begin_implicit_paint (window, &clip_box);
5009 expose_region = gdk_region_copy (update_area);
5012 /* Rendering is not double buffered by gdk, do outstanding
5013 * moves and queue antiexposure immediately. No need to do
5015 gdk_window_flush_outstanding_moves (window);
5016 save_region = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->queue_antiexpose (window, update_area);
5019 /* Render the invalid areas to the implicit paint, by sending exposes.
5020 * May flush if non-double buffered widget draw. */
5021 _gdk_windowing_window_process_updates_recurse (window, expose_region);
5025 /* Do moves right before exposes are rendered to the window */
5026 gdk_window_flush_outstanding_moves (window);
5028 /* By this time we know that any outstanding expose for this
5029 * area is invalid and we can avoid it, so queue an antiexpose.
5030 * However, it may be that due to an non-double buffered expose
5031 * we have already started drawing to the window, so it would
5032 * be to late to anti-expose now. Since this is merely an
5033 * optimization we just avoid doing it at all in that case.
5035 if (private->implicit_paint != NULL) /* didn't flush implicit paint */
5036 save_region = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->queue_antiexpose (window, update_area);
5038 gdk_window_end_implicit_paint (window);
5040 gdk_region_destroy (expose_region);
5043 gdk_region_destroy (update_area);
5046 if (private->outstanding_moves)
5048 /* Flush any outstanding moves, may happen if we moved a window but got
5049 no actual invalid area */
5050 gdk_window_flush_outstanding_moves (window);
5053 g_object_unref (window);
5057 flush_all_displays (void)
5059 GSList *displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
5062 for (tmp_list = displays; tmp_list; tmp_list = tmp_list->next)
5063 gdk_display_flush (tmp_list->data);
5065 g_slist_free (displays);
5068 /* Currently it is not possible to override
5069 * gdk_window_process_all_updates in the same manner as
5070 * gdk_window_process_updates and gdk_window_invalidate_maybe_recurse
5071 * by implementing the GdkPaintable interface. If in the future a
5072 * backend would need this, the right solution would be to add a
5073 * method to GdkDisplay that can be optionally
5074 * NULL. gdk_window_process_all_updates can then walk the list of open
5075 * displays and call the mehod.
5079 * gdk_window_process_all_updates:
5081 * Calls gdk_window_process_updates() for all windows (see #GdkWindow)
5082 * in the application.
5086 gdk_window_process_all_updates (void)
5088 GSList *old_update_windows = update_windows;
5089 GSList *tmp_list = update_windows;
5090 static gboolean in_process_all_updates = FALSE;
5092 if (in_process_all_updates)
5095 in_process_all_updates = TRUE;
5098 g_source_remove (update_idle);
5100 update_windows = NULL;
5103 _gdk_windowing_before_process_all_updates ();
5105 g_slist_foreach (old_update_windows, (GFunc)g_object_ref, NULL);
5109 GdkWindowObject *private = (GdkWindowObject *)tmp_list->data;
5111 if (!GDK_WINDOW_DESTROYED (tmp_list->data))
5113 if (private->update_freeze_count ||
5114 gdk_window_is_toplevel_frozen (tmp_list->data))
5115 gdk_window_add_update_window ((GdkWindow *) private);
5117 gdk_window_process_updates_internal (tmp_list->data);
5120 g_object_unref (tmp_list->data);
5121 tmp_list = tmp_list->next;
5124 g_slist_free (old_update_windows);
5126 flush_all_displays ();
5128 _gdk_windowing_after_process_all_updates ();
5130 in_process_all_updates = FALSE;
5134 * gdk_window_process_updates:
5135 * @window: a #GdkWindow
5136 * @update_children: whether to also process updates for child windows
5138 * Sends one or more expose events to @window. The areas in each
5139 * expose event will cover the entire update area for the window (see
5140 * gdk_window_invalidate_region() for details). Normally GDK calls
5141 * gdk_window_process_all_updates() on your behalf, so there's no
5142 * need to call this function unless you want to force expose events
5143 * to be delivered immediately and synchronously (vs. the usual
5144 * case, where GDK delivers them in an idle handler). Occasionally
5145 * this is useful to produce nicer scrolling behavior, for example.
5149 gdk_window_process_updates (GdkWindow *window,
5150 gboolean update_children)
5152 GdkWindowObject *private = (GdkWindowObject *)window;
5153 GdkWindowObject *impl_window;
5155 g_return_if_fail (GDK_IS_WINDOW (window));
5157 if (GDK_WINDOW_DESTROYED (window))
5160 /* Make sure the window lives during the expose callouts */
5161 g_object_ref (window);
5163 impl_window = gdk_window_get_impl_window (private);
5164 if ((impl_window->update_area ||
5165 impl_window->outstanding_moves) &&
5166 !impl_window->update_freeze_count &&
5167 !gdk_window_is_toplevel_frozen (window))
5169 gdk_window_process_updates_internal ((GdkWindow *)impl_window);
5170 gdk_window_remove_update_window ((GdkWindow *)impl_window);
5173 if (update_children)
5175 /* process updates in reverse stacking order so composition or
5176 * painting over achieves the desired effect for offscreen windows
5178 GList *node, *children;
5180 children = g_list_copy (private->children);
5181 g_list_foreach (children, (GFunc)g_object_ref, NULL);
5183 for (node = g_list_last (children); node; node = node->prev)
5185 gdk_window_process_updates (node->data, TRUE);
5186 g_object_unref (node->data);
5189 g_list_free (children);
5192 g_object_unref (window);
5196 * gdk_window_invalidate_rect:
5197 * @window: a #GdkWindow
5198 * @rect: rectangle to invalidate or %NULL to invalidate the whole
5200 * @invalidate_children: whether to also invalidate child windows
5202 * A convenience wrapper around gdk_window_invalidate_region() which
5203 * invalidates a rectangular region. See
5204 * gdk_window_invalidate_region() for details.
5207 gdk_window_invalidate_rect (GdkWindow *window,
5208 const GdkRectangle *rect,
5209 gboolean invalidate_children)
5211 GdkRectangle window_rect;
5213 GdkWindowObject *private = (GdkWindowObject *)window;
5215 g_return_if_fail (GDK_IS_WINDOW (window));
5217 if (GDK_WINDOW_DESTROYED (window))
5220 if (private->input_only || !private->viewable)
5227 gdk_drawable_get_size (GDK_DRAWABLE (window),
5229 &window_rect.height);
5230 rect = &window_rect;
5233 region = gdk_region_rectangle (rect);
5234 gdk_window_invalidate_region (window, region, invalidate_children);
5235 gdk_region_destroy (region);
5239 draw_ugly_color (GdkWindow *window,
5240 const GdkRegion *region)
5242 /* Draw ugly color all over the newly-invalid region */
5243 GdkColor ugly_color = { 0, 50000, 10000, 10000 };
5245 GdkRectangle clipbox;
5247 ugly_gc = gdk_gc_new (window);
5248 gdk_gc_set_rgb_fg_color (ugly_gc, &ugly_color);
5249 gdk_gc_set_clip_region (ugly_gc, region);
5251 gdk_region_get_clipbox (region, &clipbox);
5253 gdk_draw_rectangle (window,
5256 clipbox.x, clipbox.y,
5257 clipbox.width, clipbox.height);
5259 g_object_unref (ugly_gc);
5263 * gdk_window_invalidate_maybe_recurse:
5264 * @window: a #GdkWindow
5265 * @region: a #GdkRegion
5266 * @child_func: function to use to decide if to recurse to a child,
5267 * %NULL means never recurse.
5268 * @user_data: data passed to @child_func
5270 * Adds @region to the update area for @window. The update area is the
5271 * region that needs to be redrawn, or "dirty region." The call
5272 * gdk_window_process_updates() sends one or more expose events to the
5273 * window, which together cover the entire update area. An
5274 * application would normally redraw the contents of @window in
5275 * response to those expose events.
5277 * GDK will call gdk_window_process_all_updates() on your behalf
5278 * whenever your program returns to the main loop and becomes idle, so
5279 * normally there's no need to do that manually, you just need to
5280 * invalidate regions that you know should be redrawn.
5282 * The @child_func parameter controls whether the region of
5283 * each child window that intersects @region will also be invalidated.
5284 * Only children for which @child_func returns TRUE will have the area
5288 gdk_window_invalidate_maybe_recurse (GdkWindow *window,
5289 const GdkRegion *region,
5290 gboolean (*child_func) (GdkWindow *,
5294 GdkWindowObject *private = (GdkWindowObject *)window;
5295 GdkWindowObject *impl_window;
5296 GdkRegion *visible_region;
5299 g_return_if_fail (GDK_IS_WINDOW (window));
5301 if (GDK_WINDOW_DESTROYED (window))
5304 if (private->input_only ||
5305 !private->viewable ||
5306 gdk_region_empty (region) ||
5307 private->window_type == GDK_WINDOW_ROOT)
5310 visible_region = gdk_drawable_get_visible_region (window);
5311 gdk_region_intersect (visible_region, region);
5313 tmp_list = private->children;
5316 GdkWindowObject *child = tmp_list->data;
5318 if (!child->input_only)
5320 GdkRegion *child_region;
5321 GdkRectangle child_rect;
5323 child_rect.x = child->x;
5324 child_rect.y = child->y;
5325 child_rect.width = child->width;
5326 child_rect.height = child->height;
5327 child_region = gdk_region_rectangle (&child_rect);
5329 /* remove child area from the invalid area of the parent */
5330 if (GDK_WINDOW_IS_MAPPED (child) && !child->shaped &&
5331 !child->composited &&
5332 !gdk_window_is_offscreen (child))
5333 gdk_region_subtract (visible_region, child_region);
5335 if (child_func && (*child_func) ((GdkWindow *)child, user_data))
5337 GdkRegion *tmp = gdk_region_copy (region);
5339 gdk_region_offset (tmp, - child_rect.x, - child_rect.y);
5340 gdk_region_offset (child_region, - child_rect.x, - child_rect.y);
5341 gdk_region_intersect (child_region, tmp);
5343 gdk_window_invalidate_maybe_recurse ((GdkWindow *)child,
5344 child_region, child_func, user_data);
5346 gdk_region_destroy (tmp);
5349 gdk_region_destroy (child_region);
5352 tmp_list = tmp_list->next;
5355 impl_window = gdk_window_get_impl_window (private);
5357 if (!gdk_region_empty (visible_region) ||
5358 /* Even if we're not exposing anything, make sure we process
5359 idles for windows with outstanding moves */
5360 (impl_window->outstanding_moves != NULL &&
5361 impl_window->update_area == NULL))
5364 draw_ugly_color (window, region);
5366 /* Convert to impl coords */
5367 gdk_region_offset (visible_region, private->abs_x, private->abs_y);
5368 if (impl_window->update_area)
5370 gdk_region_union (impl_window->update_area, visible_region);
5374 gdk_window_add_update_window ((GdkWindow *)impl_window);
5375 impl_window->update_area = gdk_region_copy (visible_region);
5377 gdk_window_schedule_update ((GdkWindow *)impl_window);
5381 gdk_region_destroy (visible_region);
5385 true_predicate (GdkWindow *window,
5392 * gdk_window_invalidate_region:
5393 * @window: a #GdkWindow
5394 * @region: a #GdkRegion
5395 * @invalidate_children: %TRUE to also invalidate child windows
5397 * Adds @region to the update area for @window. The update area is the
5398 * region that needs to be redrawn, or "dirty region." The call
5399 * gdk_window_process_updates() sends one or more expose events to the
5400 * window, which together cover the entire update area. An
5401 * application would normally redraw the contents of @window in
5402 * response to those expose events.
5404 * GDK will call gdk_window_process_all_updates() on your behalf
5405 * whenever your program returns to the main loop and becomes idle, so
5406 * normally there's no need to do that manually, you just need to
5407 * invalidate regions that you know should be redrawn.
5409 * The @invalidate_children parameter controls whether the region of
5410 * each child window that intersects @region will also be invalidated.
5411 * If %FALSE, then the update area for child windows will remain
5412 * unaffected. See gdk_window_invalidate_maybe_recurse if you need
5413 * fine grained control over which children are invalidated.
5416 gdk_window_invalidate_region (GdkWindow *window,
5417 const GdkRegion *region,
5418 gboolean invalidate_children)
5420 gdk_window_invalidate_maybe_recurse (window, region,
5421 invalidate_children ?
5422 true_predicate : (gboolean (*) (GdkWindow *, gpointer))NULL,
5427 * _gdk_window_invalidate_for_expose:
5428 * @window: a #GdkWindow
5429 * @region: a #GdkRegion
5431 * Adds @region to the update area for @window. The update area is the
5432 * region that needs to be redrawn, or "dirty region." The call
5433 * gdk_window_process_updates() sends one or more expose events to the
5434 * window, which together cover the entire update area. An
5435 * application would normally redraw the contents of @window in
5436 * response to those expose events.
5438 * GDK will call gdk_window_process_all_updates() on your behalf
5439 * whenever your program returns to the main loop and becomes idle, so
5440 * normally there's no need to do that manually, you just need to
5441 * invalidate regions that you know should be redrawn.
5443 * This version of invalidation is used when you recieve expose events
5444 * from the native window system. It exposes the native window, plus
5445 * any non-native child windows (but not native child windows, as those would
5446 * have gotten their own expose events).
5449 _gdk_window_invalidate_for_expose (GdkWindow *window,
5452 GdkWindowObject *private = (GdkWindowObject *) window;
5453 GdkWindowRegionMove *move;
5454 GdkRegion *move_region;
5457 /* Any invalidations comming from the windowing system will
5458 be in areas that may be moved by outstanding moves,
5459 so we need to modify the expose region correspondingly,
5460 otherwise we would expose in the wrong place, as the
5461 outstanding moves will be copied before we draw the
5463 for (l = private->outstanding_moves; l != NULL; l = l->next)
5467 /* covert to move source region */
5468 move_region = gdk_region_copy (move->dest_region);
5469 gdk_region_offset (move_region, -move->dx, -move->dy);
5471 /* Move area of region that intersects with move source
5472 by dx, dy of the move*/
5473 gdk_region_intersect (move_region, region);
5474 gdk_region_subtract (region, move_region);
5475 gdk_region_offset (move_region, move->dx, move->dy);
5476 gdk_region_union (region, move_region);
5478 gdk_region_destroy (move_region);
5481 gdk_window_invalidate_maybe_recurse (window, region,
5482 (gboolean (*) (GdkWindow *, gpointer))gdk_window_has_no_impl,
5488 * gdk_window_get_update_area:
5489 * @window: a #GdkWindow
5491 * Transfers ownership of the update area from @window to the caller
5492 * of the function. That is, after calling this function, @window will
5493 * no longer have an invalid/dirty region; the update area is removed
5494 * from @window and handed to you. If a window has no update area,
5495 * gdk_window_get_update_area() returns %NULL. You are responsible for
5496 * calling gdk_region_destroy() on the returned region if it's non-%NULL.
5498 * Return value: the update area for @window
5501 gdk_window_get_update_area (GdkWindow *window)
5503 GdkWindowObject *private = (GdkWindowObject *)window;
5504 GdkWindowObject *impl_window;
5505 GdkRegion *tmp_region;
5507 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
5509 impl_window = gdk_window_get_impl_window (private);
5511 if (impl_window->update_area)
5513 tmp_region = gdk_region_copy (private->clip_region_with_children);
5514 /* Convert to impl coords */
5515 gdk_region_offset (tmp_region, private->abs_x, private->abs_y);
5516 gdk_region_intersect (tmp_region, impl_window->update_area);
5518 if (gdk_region_empty (tmp_region))
5520 gdk_region_destroy (tmp_region);
5525 gdk_region_subtract (impl_window->update_area, tmp_region);
5527 if (gdk_region_empty (impl_window->update_area) &&
5528 impl_window->outstanding_moves == NULL)
5530 gdk_region_destroy (impl_window->update_area);
5531 impl_window->update_area = NULL;
5533 gdk_window_remove_update_window ((GdkWindow *)impl_window);
5536 /* Convert from impl coords */
5537 gdk_region_offset (tmp_region, -private->abs_x, -private->abs_y);
5547 * _gdk_window_clear_update_area:
5548 * @window: a #GdkWindow.
5550 * Internal function to clear the update area for a window. This
5551 * is called when the window is hidden or destroyed.
5554 _gdk_window_clear_update_area (GdkWindow *window)
5556 GdkWindowObject *private = (GdkWindowObject *)window;
5558 g_return_if_fail (GDK_IS_WINDOW (window));
5560 if (private->update_area)
5562 gdk_window_remove_update_window (window);
5564 gdk_region_destroy (private->update_area);
5565 private->update_area = NULL;
5570 * gdk_window_freeze_updates:
5571 * @window: a #GdkWindow
5573 * Temporarily freezes a window such that it won't receive expose
5574 * events. The window will begin receiving expose events again when
5575 * gdk_window_thaw_updates() is called. If gdk_window_freeze_updates()
5576 * has been called more than once, gdk_window_thaw_updates() must be called
5577 * an equal number of times to begin processing exposes.
5580 gdk_window_freeze_updates (GdkWindow *window)
5582 GdkWindowObject *private = (GdkWindowObject *)window;
5583 GdkWindowObject *impl_window;
5585 g_return_if_fail (GDK_IS_WINDOW (window));
5587 impl_window = gdk_window_get_impl_window (private);
5588 impl_window->update_freeze_count++;
5592 * gdk_window_thaw_updates:
5593 * @window: a #GdkWindow
5595 * Thaws a window frozen with gdk_window_freeze_updates().
5598 gdk_window_thaw_updates (GdkWindow *window)
5600 GdkWindowObject *private = (GdkWindowObject *)window;
5601 GdkWindowObject *impl_window;
5603 g_return_if_fail (GDK_IS_WINDOW (window));
5605 impl_window = gdk_window_get_impl_window (private);
5607 g_return_if_fail (impl_window->update_freeze_count > 0);
5609 if (--impl_window->update_freeze_count == 0)
5610 gdk_window_schedule_update (GDK_WINDOW (impl_window));
5614 * gdk_window_freeze_toplevel_updates_libgtk_only:
5615 * @window: a #GdkWindow
5617 * Temporarily freezes a window and all its descendants such that it won't
5618 * receive expose events. The window will begin receiving expose events
5619 * again when gdk_window_thaw_toplevel_updates_libgtk_only() is called. If
5620 * gdk_window_freeze_toplevel_updates_libgtk_only()
5621 * has been called more than once,
5622 * gdk_window_thaw_toplevel_updates_libgtk_only() must be called
5623 * an equal number of times to begin processing exposes.
5625 * This function is not part of the GDK public API and is only
5629 gdk_window_freeze_toplevel_updates_libgtk_only (GdkWindow *window)
5631 GdkWindowObject *private = (GdkWindowObject *)window;
5633 g_return_if_fail (GDK_IS_WINDOW (window));
5634 g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
5636 private->update_and_descendants_freeze_count++;
5640 * gdk_window_thaw_toplevel_updates_libgtk_only:
5641 * @window: a #GdkWindow
5643 * Thaws a window frozen with
5644 * gdk_window_freeze_toplevel_updates_libgtk_only().
5646 * This function is not part of the GDK public API and is only
5650 gdk_window_thaw_toplevel_updates_libgtk_only (GdkWindow *window)
5652 GdkWindowObject *private = (GdkWindowObject *)window;
5654 g_return_if_fail (GDK_IS_WINDOW (window));
5655 g_return_if_fail (private->window_type != GDK_WINDOW_CHILD);
5656 g_return_if_fail (private->update_and_descendants_freeze_count > 0);
5658 private->update_and_descendants_freeze_count--;
5660 gdk_window_schedule_update (window);
5664 * gdk_window_set_debug_updates:
5665 * @setting: %TRUE to turn on update debugging
5667 * With update debugging enabled, calls to
5668 * gdk_window_invalidate_region() clear the invalidated region of the
5669 * screen to a noticeable color, and GDK pauses for a short time
5670 * before sending exposes to windows during
5671 * gdk_window_process_updates(). The net effect is that you can see
5672 * the invalid region for each window and watch redraws as they
5673 * occur. This allows you to diagnose inefficiencies in your application.
5675 * In essence, because the GDK rendering model prevents all flicker,
5676 * if you are redrawing the same region 400 times you may never
5677 * notice, aside from noticing a speed problem. Enabling update
5678 * debugging causes GTK to flicker slowly and noticeably, so you can
5679 * see exactly what's being redrawn when, in what order.
5681 * The --gtk-debug=updates command line option passed to GTK+ programs
5682 * enables this debug option at application startup time. That's
5683 * usually more useful than calling gdk_window_set_debug_updates()
5684 * yourself, though you might want to use this function to enable
5685 * updates sometime after application startup time.
5689 gdk_window_set_debug_updates (gboolean setting)
5691 debug_updates = setting;
5695 * gdk_window_constrain_size:
5696 * @geometry: a #GdkGeometry structure
5697 * @flags: a mask indicating what portions of @geometry are set
5698 * @width: desired width of window
5699 * @height: desired height of the window
5700 * @new_width: location to store resulting width
5701 * @new_height: location to store resulting height
5703 * Constrains a desired width and height according to a
5704 * set of geometry hints (such as minimum and maximum size).
5707 gdk_window_constrain_size (GdkGeometry *geometry,
5714 /* This routine is partially borrowed from fvwm.
5716 * Copyright 1993, Robert Nation
5717 * You may use this code for any purpose, as long as the original
5718 * copyright remains in the source code and all documentation
5720 * which in turn borrows parts of the algorithm from uwm
5723 gint min_height = 0;
5724 gint base_width = 0;
5725 gint base_height = 0;
5728 gint max_width = G_MAXINT;
5729 gint max_height = G_MAXINT;
5731 #define FLOOR(value, base) ( ((gint) ((value) / (base))) * (base) )
5733 if ((flags & GDK_HINT_BASE_SIZE) && (flags & GDK_HINT_MIN_SIZE))
5735 base_width = geometry->base_width;
5736 base_height = geometry->base_height;
5737 min_width = geometry->min_width;
5738 min_height = geometry->min_height;
5740 else if (flags & GDK_HINT_BASE_SIZE)
5742 base_width = geometry->base_width;
5743 base_height = geometry->base_height;
5744 min_width = geometry->base_width;
5745 min_height = geometry->base_height;
5747 else if (flags & GDK_HINT_MIN_SIZE)
5749 base_width = geometry->min_width;
5750 base_height = geometry->min_height;
5751 min_width = geometry->min_width;
5752 min_height = geometry->min_height;
5755 if (flags & GDK_HINT_MAX_SIZE)
5757 max_width = geometry->max_width ;
5758 max_height = geometry->max_height;
5761 if (flags & GDK_HINT_RESIZE_INC)
5763 xinc = MAX (xinc, geometry->width_inc);
5764 yinc = MAX (yinc, geometry->height_inc);
5767 /* clamp width and height to min and max values
5769 width = CLAMP (width, min_width, max_width);
5770 height = CLAMP (height, min_height, max_height);
5772 /* shrink to base + N * inc
5774 width = base_width + FLOOR (width - base_width, xinc);
5775 height = base_height + FLOOR (height - base_height, yinc);
5777 /* constrain aspect ratio, according to:
5780 * min_aspect <= -------- <= max_aspect
5784 if (flags & GDK_HINT_ASPECT &&
5785 geometry->min_aspect > 0 &&
5786 geometry->max_aspect > 0)
5790 if (geometry->min_aspect * height > width)
5792 delta = FLOOR (height - width / geometry->min_aspect, yinc);
5793 if (height - delta >= min_height)
5797 delta = FLOOR (height * geometry->min_aspect - width, xinc);
5798 if (width + delta <= max_width)
5803 if (geometry->max_aspect * height < width)
5805 delta = FLOOR (width - height * geometry->max_aspect, xinc);
5806 if (width - delta >= min_width)
5810 delta = FLOOR (width / geometry->max_aspect - height, yinc);
5811 if (height + delta <= max_height)
5820 *new_height = height;
5824 * gdk_window_get_pointer:
5825 * @window: a #GdkWindow
5826 * @x: return location for X coordinate of pointer or %NULL to not
5827 * return the X coordinate
5828 * @y: return location for Y coordinate of pointer or %NULL to not
5829 * return the Y coordinate
5830 * @mask: return location for modifier mask or %NULL to not return the
5833 * Obtains the current pointer position and modifier state.
5834 * The position is given in coordinates relative to the upper left
5835 * corner of @window.
5837 * Return value: the window containing the pointer (as with
5838 * gdk_window_at_pointer()), or %NULL if the window containing the
5839 * pointer isn't known to GDK
5842 gdk_window_get_pointer (GdkWindow *window,
5845 GdkModifierType *mask)
5847 GdkDisplay *display;
5849 GdkModifierType tmp_mask;
5852 g_return_val_if_fail (window == NULL || GDK_IS_WINDOW (window), NULL);
5856 display = gdk_drawable_get_display (window);
5860 GdkScreen *screen = gdk_screen_get_default ();
5862 display = gdk_screen_get_display (screen);
5863 window = gdk_screen_get_root_window (screen);
5865 GDK_NOTE (MULTIHEAD,
5866 g_message ("Passing NULL for window to gdk_window_get_pointer()\n"
5867 "is not multihead safe"));
5870 child = display->pointer_hooks->window_get_pointer (display, window, &tmp_x, &tmp_y, &tmp_mask);
5879 _gdk_display_enable_motion_hints (display);
5885 * gdk_window_at_pointer:
5886 * @win_x: return location for origin of the window under the pointer
5887 * @win_y: return location for origin of the window under the pointer
5889 * Obtains the window underneath the mouse pointer, returning the
5890 * location of that window in @win_x, @win_y. Returns %NULL if the
5891 * window under the mouse pointer is not known to GDK (if the window
5892 * belongs to another application and a #GdkWindow hasn't been created
5893 * for it with gdk_window_foreign_new())
5895 * NOTE: For multihead-aware widgets or applications use
5896 * gdk_display_get_window_at_pointer() instead.
5898 * Return value: window under the mouse pointer
5901 gdk_window_at_pointer (gint *win_x,
5904 return gdk_display_get_window_at_pointer (gdk_display_get_default (), win_x, win_y);
5908 * gdk_get_default_root_window:
5910 * Obtains the root window (parent all other windows are inside)
5911 * for the default display and screen.
5913 * Return value: the default root window
5916 gdk_get_default_root_window (void)
5918 return gdk_screen_get_root_window (gdk_screen_get_default ());
5922 * gdk_window_foreign_new:
5923 * @anid: a native window handle.
5925 * Wraps a native window for the default display in a #GdkWindow.
5926 * This may fail if the window has been destroyed.
5928 * For example in the X backend, a native window handle is an Xlib
5931 * Return value: the newly-created #GdkWindow wrapper for the
5932 * native window or %NULL if the window has been destroyed.
5935 gdk_window_foreign_new (GdkNativeWindow anid)
5937 return gdk_window_foreign_new_for_display (gdk_display_get_default (), anid);
5941 get_all_native_children (GdkWindowObject *private,
5944 GdkWindowObject *child;
5947 for (l = private->children; l != NULL; l = l->next)
5951 if (gdk_window_has_impl (child))
5952 *native = g_list_prepend (*native, child);
5954 get_all_native_children (child, native);
5960 gdk_window_raise_internal (GdkWindow *window)
5962 GdkWindowObject *private = (GdkWindowObject *)window;
5963 GdkWindowObject *parent = private->parent;
5964 GdkWindowObject *above;
5965 GList *native_children;
5970 parent->children = g_list_remove (parent->children, window);
5971 parent->children = g_list_prepend (parent->children, window);
5974 /* Just do native raise for toplevels */
5975 if (private->parent == NULL ||
5976 private->parent->window_type == GDK_WINDOW_ROOT ||
5977 /* The restack_under codepath should work correctly even if the parent
5978 is native, but it relies on the order of ->children to be correct,
5979 and some apps like SWT reorder the x windows without gdks knowledge,
5980 so we use raise directly in order to make these behave as before
5981 when using native windows */
5982 (gdk_window_has_impl (private) && gdk_window_has_impl (parent)))
5984 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
5986 else if (gdk_window_has_impl (private))
5988 above = find_native_sibling_above (parent, private);
5991 listhead.data = window;
5992 listhead.next = NULL;
5993 listhead.prev = NULL;
5994 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
5998 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
6002 native_children = NULL;
6003 get_all_native_children (private, &native_children);
6004 if (native_children != NULL)
6006 above = find_native_sibling_above (parent, private);
6009 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
6013 /* Right order, since native_children is bottom-topmost first */
6014 for (l = native_children; l != NULL; l = l->next)
6015 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (l->data);
6018 g_list_free (native_children);
6024 /* Returns TRUE If the native window was mapped or unmapped */
6026 set_viewable (GdkWindowObject *w,
6029 GdkWindowObject *child;
6032 if (w->viewable == val)
6038 recompute_visible_regions (w, FALSE, FALSE);
6040 for (l = w->children; l != NULL; l = l->next)
6044 if (GDK_WINDOW_IS_MAPPED (child) &&
6045 child->window_type != GDK_WINDOW_FOREIGN)
6046 set_viewable (child, val);
6049 if (gdk_window_has_impl (w) &&
6050 w->window_type != GDK_WINDOW_FOREIGN &&
6051 w->parent != NULL &&
6052 w->parent->window_type != GDK_WINDOW_ROOT)
6054 /* For most native windows we show/hide them not when they are
6055 * mapped/unmapped, because that may not produce the correct results.
6056 * For instance, if a native window have a non-native parent which is
6057 * hidden, but its native parent is viewable then showing the window
6058 * would make it viewable to X but its not viewable wrt the non-native
6059 * hierarchy. In order to handle this we track the gdk side viewability
6060 * and only map really viewable windows.
6062 * There are two exceptions though:
6064 * For foreign windows we don't want ever change the mapped state
6065 * except when explicitly done via gdk_window_show/hide, as this may
6066 * cause problems for client owning the foreign window when its window
6067 * is suddenly mapped or unmapped.
6069 * For toplevel windows embedded in a foreign window (e.g. a plug)
6070 * we sometimes synthesize a map of a window, but the native
6071 * window is really shown by the embedder, so we don't want to
6072 * do the show ourselves. We can't really tell this case from the normal
6073 * toplevel show as such toplevels are seen by gdk as parents of the
6074 * root window, so we make an exception for all toplevels.
6078 GDK_WINDOW_IMPL_GET_IFACE (w->impl)->show ((GdkWindow *)w, FALSE);
6080 GDK_WINDOW_IMPL_GET_IFACE (w->impl)->hide ((GdkWindow *)w);
6088 /* Returns TRUE If the native window was mapped or unmapped */
6090 _gdk_window_update_viewable (GdkWindow *window)
6092 GdkWindowObject *priv = (GdkWindowObject *)window;
6095 if (priv->window_type == GDK_WINDOW_FOREIGN ||
6096 priv->window_type == GDK_WINDOW_ROOT)
6098 else if (priv->parent == NULL ||
6099 priv->parent->window_type == GDK_WINDOW_ROOT ||
6100 priv->parent->viewable)
6101 viewable = GDK_WINDOW_IS_MAPPED (priv);
6105 return set_viewable (priv, viewable);
6109 gdk_window_show_internal (GdkWindow *window, gboolean raise)
6111 GdkWindowObject *private;
6112 gboolean was_mapped, was_viewable;
6115 g_return_if_fail (GDK_IS_WINDOW (window));
6117 private = (GdkWindowObject *) window;
6118 if (private->destroyed)
6121 was_mapped = GDK_WINDOW_IS_MAPPED (window);
6122 was_viewable = private->viewable;
6125 /* Keep children in (reverse) stacking order */
6126 gdk_window_raise_internal (window);
6128 if (gdk_window_has_impl (private))
6131 gdk_synthesize_window_state (window,
6132 GDK_WINDOW_STATE_WITHDRAWN,
6140 did_show = _gdk_window_update_viewable (window);
6142 /* If it was already viewable the backend show op won't be called, call it
6143 again to ensure things happen right if the mapped tracking was not right
6144 for e.g. a foreign window.
6145 Dunno if this is strictly needed but its what happened pre-csw.
6146 Also show if not done by gdk_window_update_viewable. */
6147 if (gdk_window_has_impl (private) && (was_viewable || !did_show))
6148 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->show ((GdkWindow *)private,
6152 if (!was_mapped && !gdk_window_has_impl (private))
6154 if (private->event_mask & GDK_STRUCTURE_MASK)
6155 _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
6157 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
6158 _gdk_make_event (GDK_WINDOW (private), GDK_MAP, NULL, FALSE);
6161 if (!was_mapped || raise)
6163 recompute_visible_regions (private, TRUE, FALSE);
6165 /* If any decendants became visible we need to send visibility notify */
6166 gdk_window_update_visibility_recursively (private, NULL);
6168 if (gdk_window_is_viewable (window))
6170 _gdk_synthesize_crossing_events_for_geometry_change (window);
6171 gdk_window_invalidate_rect (window, NULL, TRUE);
6177 * gdk_window_show_unraised:
6178 * @window: a #GdkWindow
6180 * Shows a #GdkWindow onscreen, but does not modify its stacking
6181 * order. In contrast, gdk_window_show() will raise the window
6182 * to the top of the window stack.
6184 * On the X11 platform, in Xlib terms, this function calls
6185 * XMapWindow() (it also updates some internal GDK state, which means
6186 * that you can't really use XMapWindow() directly on a GDK window).
6189 gdk_window_show_unraised (GdkWindow *window)
6191 gdk_window_show_internal (window, FALSE);
6196 * @window: a #GdkWindow
6198 * Raises @window to the top of the Z-order (stacking order), so that
6199 * other windows with the same parent window appear below @window.
6200 * This is true whether or not the windows are visible.
6202 * If @window is a toplevel, the window manager may choose to deny the
6203 * request to move the window in the Z-order, gdk_window_raise() only
6204 * requests the restack, does not guarantee it.
6207 gdk_window_raise (GdkWindow *window)
6209 GdkWindowObject *private;
6210 GdkRegion *old_region, *new_region;
6212 g_return_if_fail (GDK_IS_WINDOW (window));
6214 private = (GdkWindowObject *) window;
6215 if (private->destroyed)
6219 if (gdk_window_is_viewable (window) &&
6220 !private->input_only)
6221 old_region = gdk_region_copy (private->clip_region);
6223 /* Keep children in (reverse) stacking order */
6224 gdk_window_raise_internal (window);
6226 recompute_visible_regions (private, TRUE, FALSE);
6230 new_region = gdk_region_copy (private->clip_region);
6232 gdk_region_subtract (new_region, old_region);
6233 gdk_window_invalidate_region (window, new_region, TRUE);
6235 gdk_region_destroy (old_region);
6236 gdk_region_destroy (new_region);
6241 gdk_window_lower_internal (GdkWindow *window)
6243 GdkWindowObject *private = (GdkWindowObject *)window;
6244 GdkWindowObject *parent = private->parent;
6245 GdkWindowObject *above;
6246 GList *native_children;
6251 parent->children = g_list_remove (parent->children, window);
6252 parent->children = g_list_append (parent->children, window);
6255 /* Just do native lower for toplevels */
6256 if (private->parent == NULL ||
6257 private->parent->window_type == GDK_WINDOW_ROOT ||
6258 /* The restack_under codepath should work correctly even if the parent
6259 is native, but it relies on the order of ->children to be correct,
6260 and some apps like SWT reorder the x windows without gdks knowledge,
6261 so we use lower directly in order to make these behave as before
6262 when using native windows */
6263 (gdk_window_has_impl (private) && gdk_window_has_impl (parent)))
6265 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->lower (window);
6267 else if (gdk_window_has_impl (private))
6269 above = find_native_sibling_above (parent, private);
6272 listhead.data = window;
6273 listhead.next = NULL;
6274 listhead.prev = NULL;
6275 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
6279 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (window);
6283 native_children = NULL;
6284 get_all_native_children (private, &native_children);
6285 if (native_children != NULL)
6287 above = find_native_sibling_above (parent, private);
6290 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->restack_under ((GdkWindow *)above,
6294 /* Right order, since native_children is bottom-topmost first */
6295 for (l = native_children; l != NULL; l = l->next)
6296 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->raise (l->data);
6299 g_list_free (native_children);
6306 gdk_window_invalidate_in_parent (GdkWindowObject *private)
6308 GdkRectangle r, child;
6310 if (private->parent == NULL ||
6311 private->parent->window_type == GDK_WINDOW_ROOT)
6314 /* get the visible rectangle of the parent */
6316 r.width = private->parent->width;
6317 r.height = private->parent->height;
6319 child.x = private->x;
6320 child.y = private->y;
6321 child.width = private->width;
6322 child.height = private->height;
6323 gdk_rectangle_intersect (&r, &child, &r);
6325 gdk_window_invalidate_rect (GDK_WINDOW (private->parent), &r, TRUE);
6331 * @window: a #GdkWindow
6333 * Lowers @window to the bottom of the Z-order (stacking order), so that
6334 * other windows with the same parent window appear above @window.
6335 * This is true whether or not the other windows are visible.
6337 * If @window is a toplevel, the window manager may choose to deny the
6338 * request to move the window in the Z-order, gdk_window_lower() only
6339 * requests the restack, does not guarantee it.
6341 * Note that gdk_window_show() raises the window again, so don't call this
6342 * function before gdk_window_show(). (Try gdk_window_show_unraised().)
6345 gdk_window_lower (GdkWindow *window)
6347 GdkWindowObject *private;
6349 g_return_if_fail (GDK_IS_WINDOW (window));
6351 private = (GdkWindowObject *) window;
6352 if (private->destroyed)
6355 /* Keep children in (reverse) stacking order */
6356 gdk_window_lower_internal (window);
6358 recompute_visible_regions (private, TRUE, FALSE);
6360 _gdk_synthesize_crossing_events_for_geometry_change (window);
6361 gdk_window_invalidate_in_parent (private);
6366 * @window: a #GdkWindow
6368 * Like gdk_window_show_unraised(), but also raises the window to the
6369 * top of the window stack (moves the window to the front of the
6372 * This function maps a window so it's visible onscreen. Its opposite
6373 * is gdk_window_hide().
6375 * When implementing a #GtkWidget, you should call this function on the widget's
6376 * #GdkWindow as part of the "map" method.
6379 gdk_window_show (GdkWindow *window)
6381 gdk_window_show_internal (window, TRUE);
6386 * @window: a #GdkWindow
6388 * For toplevel windows, withdraws them, so they will no longer be
6389 * known to the window manager; for all windows, unmaps them, so
6390 * they won't be displayed. Normally done automatically as
6391 * part of gtk_widget_hide().
6394 gdk_window_hide (GdkWindow *window)
6396 GdkWindowObject *private;
6397 gboolean was_mapped, did_hide;
6399 g_return_if_fail (GDK_IS_WINDOW (window));
6401 private = (GdkWindowObject *) window;
6402 if (private->destroyed)
6405 was_mapped = GDK_WINDOW_IS_MAPPED (private);
6407 if (gdk_window_has_impl (private))
6410 if (GDK_WINDOW_IS_MAPPED (window))
6411 gdk_synthesize_window_state (window,
6413 GDK_WINDOW_STATE_WITHDRAWN);
6415 else if (was_mapped)
6417 GdkDisplay *display;
6419 /* May need to break grabs on children */
6420 display = gdk_drawable_get_display (window);
6422 if (_gdk_display_end_pointer_grab (display,
6423 _gdk_windowing_window_get_next_serial (display),
6426 gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
6428 if (display->keyboard_grab.window != NULL)
6430 if (is_parent_of (window, display->keyboard_grab.window))
6432 /* Call this ourselves, even though gdk_display_keyboard_ungrab
6433 does so too, since we want to pass implicit == TRUE so the
6434 broken grab event is generated */
6435 _gdk_display_unset_has_keyboard_grab (display,
6437 gdk_display_keyboard_ungrab (display, GDK_CURRENT_TIME);
6441 private->state = GDK_WINDOW_STATE_WITHDRAWN;
6444 did_hide = _gdk_window_update_viewable (window);
6446 /* Hide foreign window as those are not handled by update_viewable. */
6447 if (gdk_window_has_impl (private) && (!did_hide))
6448 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->hide ((GdkWindow *)private);
6450 recompute_visible_regions (private, TRUE, FALSE);
6452 /* all decendants became non-visible, we need to send visibility notify */
6453 gdk_window_update_visibility_recursively (private, NULL);
6455 if (was_mapped && !gdk_window_has_impl (private))
6457 if (private->event_mask & GDK_STRUCTURE_MASK)
6458 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6460 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
6461 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6463 _gdk_synthesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
6466 /* Invalidate the rect */
6467 gdk_window_invalidate_in_parent (private);
6471 * gdk_window_withdraw:
6472 * @window: a toplevel #GdkWindow
6474 * Withdraws a window (unmaps it and asks the window manager to forget about it).
6475 * This function is not really useful as gdk_window_hide() automatically
6476 * withdraws toplevel windows before hiding them.
6479 gdk_window_withdraw (GdkWindow *window)
6481 GdkWindowObject *private;
6482 gboolean was_mapped;
6484 g_return_if_fail (GDK_IS_WINDOW (window));
6486 private = (GdkWindowObject *) window;
6487 if (private->destroyed)
6490 was_mapped = GDK_WINDOW_IS_MAPPED (private);
6492 if (gdk_window_has_impl (private))
6494 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->withdraw (window);
6498 if (private->event_mask & GDK_STRUCTURE_MASK)
6499 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6501 if (private->parent && private->parent->event_mask & GDK_SUBSTRUCTURE_MASK)
6502 _gdk_make_event (GDK_WINDOW (private), GDK_UNMAP, NULL, FALSE);
6504 _gdk_synthesize_crossing_events_for_geometry_change (GDK_WINDOW (private->parent));
6507 recompute_visible_regions (private, TRUE, FALSE);
6512 * gdk_window_set_events:
6513 * @window: a #GdkWindow
6514 * @event_mask: event mask for @window
6516 * The event mask for a window determines which events will be reported
6517 * for that window. For example, an event mask including #GDK_BUTTON_PRESS_MASK
6518 * means the window should report button press events. The event mask
6519 * is the bitwise OR of values from the #GdkEventMask enumeration.
6522 gdk_window_set_events (GdkWindow *window,
6523 GdkEventMask event_mask)
6525 GdkWindowObject *private;
6526 GdkDisplay *display;
6529 g_return_if_fail (GDK_IS_WINDOW (window));
6531 private = (GdkWindowObject *) window;
6532 if (private->destroyed)
6535 /* If motion hint is disabled, enable motion events again */
6536 display = gdk_drawable_get_display (window);
6537 if ((private->event_mask & GDK_POINTER_MOTION_HINT_MASK) &&
6538 !(event_mask & GDK_POINTER_MOTION_HINT_MASK))
6539 _gdk_display_enable_motion_hints (display);
6541 private->event_mask = event_mask;
6543 if (gdk_window_has_impl (private))
6544 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_events (window,
6545 get_native_event_mask (private));
6550 * gdk_window_get_events:
6551 * @window: a #GdkWindow
6553 * Gets the event mask for @window. See gdk_window_set_events().
6555 * Return value: event mask for @window
6558 gdk_window_get_events (GdkWindow *window)
6560 GdkWindowObject *private;
6562 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
6564 private = (GdkWindowObject *) window;
6565 if (private->destroyed)
6568 return private->event_mask;
6572 gdk_window_move_resize_toplevel (GdkWindow *window,
6579 GdkWindowObject *private;
6580 GdkRegion *old_region, *new_region;
6581 GdkWindowObject *impl_window;
6583 int old_x, old_y, old_abs_x, old_abs_y;
6587 private = (GdkWindowObject *) window;
6592 impl_window = gdk_window_get_impl_window (private);
6597 is_resize = (width != -1) || (height != -1);
6599 if (gdk_window_is_viewable (window) &&
6600 !private->input_only)
6603 old_region = gdk_region_copy (private->clip_region);
6606 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, with_move, x, y, width, height);
6608 dx = private->x - old_x;
6609 dy = private->y - old_y;
6611 old_abs_x = private->abs_x;
6612 old_abs_y = private->abs_y;
6614 /* Avoid recomputing for pure toplevel moves, for performance reasons */
6616 recompute_visible_regions (private, TRUE, FALSE);
6620 new_region = gdk_region_copy (private->clip_region);
6622 /* This is the newly exposed area (due to any resize),
6623 * X will expose it, but lets do that without the
6626 gdk_region_subtract (new_region, old_region);
6627 gdk_window_invalidate_region (window, new_region, TRUE);
6629 gdk_region_destroy (old_region);
6630 gdk_region_destroy (new_region);
6633 _gdk_synthesize_crossing_events_for_geometry_change (window);
6638 move_native_children (GdkWindowObject *private)
6641 GdkWindowObject *child;
6643 for (l = private->children; l; l = l->next)
6647 if (child->impl != private->impl)
6648 GDK_WINDOW_IMPL_GET_IFACE (child->impl)->move_resize ((GdkWindow *)child, TRUE, child->x, child->y, child->width, child->height);
6650 move_native_children (child);
6655 collect_native_child_region_helper (GdkWindowObject *window,
6661 GdkWindowObject *child;
6665 for (l = window->children; l != NULL; l = l->next)
6669 if (!GDK_WINDOW_IS_MAPPED (child) || child->input_only)
6672 if (child->impl != impl)
6674 tmp = gdk_region_copy (child->clip_region);
6675 gdk_region_offset (tmp,
6676 x_offset + child->x,
6677 y_offset + child->y);
6678 if (*region == NULL)
6682 gdk_region_union (*region, tmp);
6683 gdk_region_destroy (tmp);
6687 collect_native_child_region_helper (child, impl, region,
6688 x_offset + child->x,
6689 y_offset + child->y);
6696 collect_native_child_region (GdkWindowObject *window,
6697 gboolean include_this)
6701 if (include_this && gdk_window_has_impl (window) && window->viewable)
6702 return gdk_region_copy (window->clip_region);
6706 collect_native_child_region_helper (window, window->impl, ®ion, 0, 0);
6713 gdk_window_move_resize_internal (GdkWindow *window,
6720 GdkWindowObject *private;
6721 GdkRegion *old_region, *new_region, *copy_area;
6722 GdkRegion *old_native_child_region, *new_native_child_region;
6723 GdkWindowObject *impl_window;
6725 int old_x, old_y, old_abs_x, old_abs_y;
6728 g_return_if_fail (GDK_IS_WINDOW (window));
6730 private = (GdkWindowObject *) window;
6731 if (private->destroyed)
6734 if (private->parent == NULL ||
6735 private->parent->window_type == GDK_WINDOW_ROOT)
6737 gdk_window_move_resize_toplevel (window, with_move, x, y, width, height);
6741 /* Handle child windows */
6746 impl_window = gdk_window_get_impl_window (private);
6751 old_native_child_region = NULL;
6752 if (gdk_window_is_viewable (window) &&
6753 !private->input_only)
6757 old_region = gdk_region_copy (private->clip_region);
6758 /* Adjust region to parent window coords */
6759 gdk_region_offset (old_region, private->x, private->y);
6761 old_native_child_region = collect_native_child_region (private, TRUE);
6762 if (old_native_child_region)
6764 /* Adjust region to parent window coords */
6765 gdk_region_offset (old_native_child_region, private->x, private->y);
6767 /* Any native window move will immediately copy stuff to the destination, which may overwrite a
6768 * source or destination for a delayed GdkWindowRegionMove. So, we need
6769 * to flush those here for the parent window and all overlapped subwindows
6770 * of it. And we need to do this before setting the new clips as those will be
6773 gdk_window_flush_recursive (private->parent);
6777 /* Set the new position and size */
6783 if (!(width < 0 && height < 0))
6787 private->width = width;
6790 private->height = height;
6793 dx = private->x - old_x;
6794 dy = private->y - old_y;
6796 old_abs_x = private->abs_x;
6797 old_abs_y = private->abs_y;
6799 recompute_visible_regions (private, TRUE, FALSE);
6801 new_native_child_region = NULL;
6802 if (old_native_child_region)
6804 new_native_child_region = collect_native_child_region (private, TRUE);
6805 /* Adjust region to parent window coords */
6806 gdk_region_offset (new_native_child_region, private->x, private->y);
6809 if (gdk_window_has_impl (private))
6811 /* Do the actual move after recomputing things, as this will have set the shape to
6812 the now correct one, thus avoiding copying regions that should not be copied. */
6813 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->move_resize (window, TRUE, private->x, private->y, private->width, private->height);
6815 else if (old_abs_x != private->abs_x ||
6816 old_abs_y != private->abs_y)
6817 move_native_children (private);
6821 new_region = gdk_region_copy (private->clip_region);
6822 /* Adjust region to parent window coords */
6823 gdk_region_offset (new_region, private->x, private->y);
6826 * Part of the data at the new location can be copied from the
6827 * old location, this area is the intersection of the old region
6828 * moved as the copy will move it and then intersected with
6832 * Everything in the old and new regions that is not copied must be
6833 * invalidated (including children) as this is newly exposed
6835 copy_area = gdk_region_copy (new_region);
6837 gdk_region_union (new_region, old_region);
6839 if (old_native_child_region)
6841 /* Don't copy from inside native children, as this is copied by
6842 * the native window move.
6844 gdk_region_subtract (old_region, old_native_child_region);
6846 gdk_region_offset (old_region, dx, dy);
6848 gdk_region_intersect (copy_area, old_region);
6850 if (new_native_child_region)
6852 /* Don't copy any bits that would cause a read from the moved
6853 native windows, as we can't read that data */
6854 gdk_region_offset (new_native_child_region, dx, dy);
6855 gdk_region_subtract (copy_area, new_native_child_region);
6858 gdk_region_subtract (new_region, copy_area);
6860 /* Convert old region to impl coords */
6861 gdk_region_offset (old_region, -dx + private->abs_x - private->x, -dy + private->abs_y - private->y);
6863 /* convert from parent coords to impl */
6864 gdk_region_offset (copy_area, private->abs_x - private->x, private->abs_y - private->y);
6866 move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
6868 /* Invalidate affected part in the parent window
6869 * (no higher window should be affected)
6870 * We also invalidate any children in that area, which could include
6871 * this window if it still overlaps that area.
6873 gdk_window_invalidate_region (GDK_WINDOW (private->parent), new_region, TRUE);
6875 gdk_region_destroy (old_region);
6876 gdk_region_destroy (new_region);
6879 if (old_native_child_region)
6881 gdk_region_destroy (old_native_child_region);
6882 gdk_region_destroy (new_native_child_region);
6885 _gdk_synthesize_crossing_events_for_geometry_change (window);
6892 * @window: a #GdkWindow
6893 * @x: X coordinate relative to window's parent
6894 * @y: Y coordinate relative to window's parent
6896 * Repositions a window relative to its parent window.
6897 * For toplevel windows, window managers may ignore or modify the move;
6898 * you should probably use gtk_window_move() on a #GtkWindow widget
6899 * anyway, instead of using GDK functions. For child windows,
6900 * the move will reliably succeed.
6902 * If you're also planning to resize the window, use gdk_window_move_resize()
6903 * to both move and resize simultaneously, for a nicer visual effect.
6906 gdk_window_move (GdkWindow *window,
6910 gdk_window_move_resize_internal (window, TRUE, x, y, -1, -1);
6914 * gdk_window_resize:
6915 * @window: a #GdkWindow
6916 * @width: new width of the window
6917 * @height: new height of the window
6919 * Resizes @window; for toplevel windows, asks the window manager to resize
6920 * the window. The window manager may not allow the resize. When using GTK+,
6921 * use gtk_window_resize() instead of this low-level GDK function.
6923 * Windows may not be resized below 1x1.
6925 * If you're also planning to move the window, use gdk_window_move_resize()
6926 * to both move and resize simultaneously, for a nicer visual effect.
6929 gdk_window_resize (GdkWindow *window,
6933 gdk_window_move_resize_internal (window, FALSE, 0, 0, width, height);
6938 * gdk_window_move_resize:
6939 * @window: a #GdkWindow
6940 * @x: new X position relative to window's parent
6941 * @y: new Y position relative to window's parent
6943 * @height: new height
6945 * Equivalent to calling gdk_window_move() and gdk_window_resize(),
6946 * except that both operations are performed at once, avoiding strange
6947 * visual effects. (i.e. the user may be able to see the window first
6948 * move, then resize, if you don't use gdk_window_move_resize().)
6951 gdk_window_move_resize (GdkWindow *window,
6957 gdk_window_move_resize_internal (window, TRUE, x, y, width, height);
6962 * gdk_window_scroll:
6963 * @window: a #GdkWindow
6964 * @dx: Amount to scroll in the X direction
6965 * @dy: Amount to scroll in the Y direction
6967 * Scroll the contents of @window, both pixels and children, by the
6968 * given amount. @window itself does not move. Portions of the window
6969 * that the scroll operation brings in from offscreen areas are
6970 * invalidated. The invalidated region may be bigger than what would
6971 * strictly be necessary.
6973 * For X11, a minimum area will be invalidated if the window has no
6974 * subwindows, or if the edges of the window's parent do not extend
6975 * beyond the edges of the window. In other cases, a multi-step process
6976 * is used to scroll the window which may produce temporary visual
6977 * artifacts and unnecessary invalidations.
6980 gdk_window_scroll (GdkWindow *window,
6984 GdkWindowObject *private = (GdkWindowObject *) window;
6985 GdkWindowObject *impl_window;
6986 GdkRegion *copy_area, *noncopy_area;
6987 GdkRegion *old_native_child_region, *new_native_child_region;
6990 g_return_if_fail (GDK_IS_WINDOW (window));
6992 if (dx == 0 && dy == 0)
6995 if (private->destroyed)
6998 old_native_child_region = collect_native_child_region (private, FALSE);
6999 if (old_native_child_region)
7001 /* Any native window move will immediately copy stuff to the destination, which may overwrite a
7002 * source or destination for a delayed GdkWindowRegionMove. So, we need
7003 * to flush those here for the window and all overlapped subwindows
7004 * of it. And we need to do this before setting the new clips as those will be
7007 gdk_window_flush_recursive (private);
7011 /* First move all child windows, without causing invalidation */
7013 tmp_list = private->children;
7016 GdkWindow *child = GDK_WINDOW (tmp_list->data);
7017 GdkWindowObject *child_obj = GDK_WINDOW_OBJECT (child);
7019 /* Just update the positions, the bits will move with the copy */
7023 tmp_list = tmp_list->next;
7026 recompute_visible_regions (private, FALSE, TRUE);
7028 new_native_child_region = NULL;
7029 if (old_native_child_region)
7030 new_native_child_region = collect_native_child_region (private, FALSE);
7032 move_native_children (private);
7034 /* Then copy the actual bits of the window w/ child windows */
7036 impl_window = gdk_window_get_impl_window (private);
7038 /* Calculate the area that can be gotten by copying the old area */
7039 copy_area = gdk_region_copy (private->clip_region);
7040 if (old_native_child_region)
7042 /* Don't copy from inside native children, as this is copied by
7043 * the native window move.
7045 gdk_region_subtract (copy_area, old_native_child_region);
7047 /* Don't copy any bits that would cause a read from the moved
7048 native windows, as we can't read that data */
7049 gdk_region_subtract (copy_area, new_native_child_region);
7051 gdk_region_offset (copy_area, dx, dy);
7052 gdk_region_intersect (copy_area, private->clip_region);
7054 /* And the rest need to be invalidated */
7055 noncopy_area = gdk_region_copy (private->clip_region);
7056 gdk_region_subtract (noncopy_area, copy_area);
7058 /* convert from window coords to impl */
7059 gdk_region_offset (copy_area, private->abs_x, private->abs_y);
7061 move_region_on_impl (impl_window, copy_area, dx, dy); /* takes ownership of copy_area */
7063 /* Invalidate not copied regions */
7064 gdk_window_invalidate_region (window, noncopy_area, TRUE);
7066 gdk_region_destroy (noncopy_area);
7068 if (old_native_child_region)
7070 gdk_region_destroy (old_native_child_region);
7071 gdk_region_destroy (new_native_child_region);
7074 _gdk_synthesize_crossing_events_for_geometry_change (window);
7078 * gdk_window_move_region:
7079 * @window: a #GdkWindow
7080 * @region: The #GdkRegion to move
7081 * @dx: Amount to move in the X direction
7082 * @dy: Amount to move in the Y direction
7084 * Move the part of @window indicated by @region by @dy pixels in the Y
7085 * direction and @dx pixels in the X direction. The portions of @region
7086 * that not covered by the new position of @region are invalidated.
7088 * Child windows are not moved.
7093 gdk_window_move_region (GdkWindow *window,
7094 const GdkRegion *region,
7098 GdkWindowObject *private = (GdkWindowObject *) window;
7099 GdkWindowObject *impl_window;
7100 GdkRegion *nocopy_area;
7101 GdkRegion *copy_area;
7103 g_return_if_fail (GDK_IS_WINDOW (window));
7104 g_return_if_fail (region != NULL);
7106 if (dx == 0 && dy == 0)
7109 if (private->destroyed)
7112 impl_window = gdk_window_get_impl_window (private);
7114 /* compute source regions */
7115 copy_area = gdk_region_copy (region);
7116 gdk_region_intersect (copy_area, private->clip_region_with_children);
7118 /* compute destination regions */
7119 gdk_region_offset (copy_area, dx, dy);
7120 gdk_region_intersect (copy_area, private->clip_region_with_children);
7122 /* Invalidate parts of the region (source and dest) not covered
7124 nocopy_area = gdk_region_copy (region);
7125 gdk_region_offset (nocopy_area, dx, dy);
7126 gdk_region_union (nocopy_area, region);
7127 gdk_region_subtract (nocopy_area, copy_area);
7129 /* convert from window coords to impl */
7130 gdk_region_offset (copy_area, private->abs_x, private->abs_y);
7131 move_region_on_impl (impl_window, copy_area, dx, dy); /* Takes ownership of copy_area */
7133 gdk_window_invalidate_region (window, nocopy_area, FALSE);
7134 gdk_region_destroy (nocopy_area);
7138 * gdk_window_set_background:
7139 * @window: a #GdkWindow
7140 * @color: an allocated #GdkColor
7142 * Sets the background color of @window. (However, when using GTK+,
7143 * set the background of a widget with gtk_widget_modify_bg() - if
7144 * you're an application - or gtk_style_set_background() - if you're
7145 * implementing a custom widget.)
7147 * The @color must be allocated; gdk_rgb_find_color() is the best way
7148 * to allocate a color.
7150 * See also gdk_window_set_back_pixmap().
7153 gdk_window_set_background (GdkWindow *window,
7154 const GdkColor *color)
7156 GdkWindowObject *private;
7157 GdkColormap *colormap = gdk_drawable_get_colormap (window);
7159 g_return_if_fail (GDK_IS_WINDOW (window));
7161 private = (GdkWindowObject *) window;
7163 private->bg_color = *color;
7164 gdk_colormap_query_color (colormap, private->bg_color.pixel, &private->bg_color);
7166 if (private->bg_pixmap &&
7167 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
7168 private->bg_pixmap != GDK_NO_BG)
7169 g_object_unref (private->bg_pixmap);
7171 private->bg_pixmap = NULL;
7173 if (!GDK_WINDOW_DESTROYED (window) &&
7174 gdk_window_has_impl (private) &&
7175 !private->input_only)
7176 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_background (window, &private->bg_color);
7180 * gdk_window_set_back_pixmap:
7181 * @window: a #GdkWindow
7182 * @pixmap: a #GdkPixmap, or %NULL
7183 * @parent_relative: whether the tiling origin is at the origin of
7186 * Sets the background pixmap of @window. May also be used to set a
7187 * background of "None" on @window, by setting a background pixmap
7190 * A background pixmap will be tiled, positioning the first tile at
7191 * the origin of @window, or if @parent_relative is %TRUE, the tiling
7192 * will be done based on the origin of the parent window (useful to
7193 * align tiles in a parent with tiles in a child).
7195 * A background pixmap of %NULL means that the window will have no
7196 * background. A window with no background will never have its
7197 * background filled by the windowing system, instead the window will
7198 * contain whatever pixels were already in the corresponding area of
7201 * The windowing system will normally fill a window with its background
7202 * when the window is obscured then exposed, and when you call
7203 * gdk_window_clear().
7206 gdk_window_set_back_pixmap (GdkWindow *window,
7208 gboolean parent_relative)
7210 GdkWindowObject *private;
7212 g_return_if_fail (GDK_IS_WINDOW (window));
7213 g_return_if_fail (pixmap == NULL || !parent_relative);
7214 g_return_if_fail (pixmap == NULL || gdk_drawable_get_depth (window) == gdk_drawable_get_depth (pixmap));
7216 private = (GdkWindowObject *) window;
7218 if (pixmap && !gdk_drawable_get_colormap (pixmap))
7220 g_warning ("gdk_window_set_back_pixmap(): pixmap must have a colormap");
7224 if (private->bg_pixmap &&
7225 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
7226 private->bg_pixmap != GDK_NO_BG)
7227 g_object_unref (private->bg_pixmap);
7229 if (parent_relative)
7230 private->bg_pixmap = GDK_PARENT_RELATIVE_BG;
7232 private->bg_pixmap = g_object_ref (pixmap);
7234 private->bg_pixmap = GDK_NO_BG;
7236 if (!GDK_WINDOW_DESTROYED (window) &&
7237 gdk_window_has_impl (private) &&
7238 !private->input_only)
7239 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_back_pixmap (window, private->bg_pixmap);
7243 * gdk_window_get_cursor:
7244 * @window: a #GdkWindow
7246 * Retrieves a #GdkCursor pointer for the cursor currently set on the
7247 * specified #GdkWindow, or %NULL. If the return value is %NULL then
7248 * there is no custom cursor set on the specified window, and it is
7249 * using the cursor for its parent window.
7251 * Return value: a #GdkCursor, or %NULL. The returned object is owned
7252 * by the #GdkWindow and should not be unreferenced directly. Use
7253 * gdk_window_set_cursor() to unset the cursor of the window
7258 gdk_window_get_cursor (GdkWindow *window)
7260 GdkWindowObject *private;
7262 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
7264 private = (GdkWindowObject *) window;
7266 return private->cursor;
7270 * gdk_window_set_cursor:
7271 * @window: a #GdkWindow
7274 * Sets the mouse pointer for a #GdkWindow. Use gdk_cursor_new_for_display()
7275 * or gdk_cursor_new_from_pixmap() to create the cursor. To make the cursor
7276 * invisible, use %GDK_BLANK_CURSOR. Passing %NULL for the @cursor argument
7277 * to gdk_window_set_cursor() means that @window will use the cursor of its
7278 * parent window. Most windows should use this default.
7281 gdk_window_set_cursor (GdkWindow *window,
7284 GdkWindowObject *private;
7285 GdkDisplay *display;
7287 g_return_if_fail (GDK_IS_WINDOW (window));
7289 private = (GdkWindowObject *) window;
7290 display = gdk_drawable_get_display (window);
7292 if (private->cursor)
7294 gdk_cursor_unref (private->cursor);
7295 private->cursor = NULL;
7298 if (!GDK_WINDOW_DESTROYED (window))
7301 private->cursor = gdk_cursor_ref (cursor);
7303 if (_gdk_native_windows ||
7304 private->window_type == GDK_WINDOW_ROOT ||
7305 private->window_type == GDK_WINDOW_FOREIGN)
7306 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_cursor (window, cursor);
7307 else if (_gdk_window_event_parent_of (window, display->pointer_info.window_under_pointer))
7308 update_cursor (display);
7310 g_object_notify (G_OBJECT (window), "cursor");
7315 * gdk_window_get_geometry:
7316 * @window: a #GdkWindow
7317 * @x: return location for X coordinate of window (relative to its parent)
7318 * @y: return location for Y coordinate of window (relative to its parent)
7319 * @width: return location for width of window
7320 * @height: return location for height of window
7321 * @depth: return location for bit depth of window
7323 * Any of the return location arguments to this function may be %NULL,
7324 * if you aren't interested in getting the value of that field.
7326 * The X and Y coordinates returned are relative to the parent window
7327 * of @window, which for toplevels usually means relative to the
7328 * window decorations (titlebar, etc.) rather than relative to the
7329 * root window (screen-size background window).
7331 * On the X11 platform, the geometry is obtained from the X server,
7332 * so reflects the latest position of @window; this may be out-of-sync
7333 * with the position of @window delivered in the most-recently-processed
7334 * #GdkEventConfigure. gdk_window_get_position() in contrast gets the
7335 * position from the most recent configure event.
7338 * If @window is not a toplevel, it is <emphasis>much</emphasis> better
7339 * to call gdk_window_get_position() and gdk_drawable_get_size() instead,
7340 * because it avoids the roundtrip to the X server and because
7341 * gdk_drawable_get_size() supports the full 32-bit coordinate space,
7342 * whereas gdk_window_get_geometry() is restricted to the 16-bit
7343 * coordinates of X11.
7347 gdk_window_get_geometry (GdkWindow *window,
7354 GdkWindowObject *private, *parent;
7358 GDK_NOTE (MULTIHEAD,
7359 g_message ("gdk_window_get_geometry(): Window needs "
7360 "to be non-NULL to be multi head safe"));
7361 window = gdk_screen_get_root_window ((gdk_screen_get_default ()));
7364 g_return_if_fail (GDK_IS_WINDOW (window));
7366 private = (GdkWindowObject *) window;
7368 if (!GDK_WINDOW_DESTROYED (window))
7370 if (gdk_window_has_impl (private))
7372 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_geometry (window, x, y,
7375 /* This reports the position wrt to the native parent, we need to convert
7376 it to be relative to the client side parent */
7377 parent = private->parent;
7378 if (parent && !gdk_window_has_impl (parent))
7381 *x -= parent->abs_x;
7383 *y -= parent->abs_y;
7393 *width = private->width;
7395 *height = private->height;
7397 *depth = private->depth;
7403 * gdk_window_get_origin:
7404 * @window: a #GdkWindow
7405 * @x: return location for X coordinate
7406 * @y: return location for Y coordinate
7408 * Obtains the position of a window in root window coordinates.
7409 * (Compare with gdk_window_get_position() and
7410 * gdk_window_get_geometry() which return the position of a window
7411 * relative to its parent window.)
7413 * Return value: not meaningful, ignore
7416 gdk_window_get_origin (GdkWindow *window,
7420 GdkWindowObject *private;
7422 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
7424 if (GDK_WINDOW_DESTROYED (window))
7433 private = (GdkWindowObject *) window;
7435 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_root_coords (window,
7444 * gdk_window_get_root_coords:
7445 * @window: a #GdkWindow
7446 * @x: X coordinate in window
7447 * @y: Y coordinate in window
7448 * @root_x: return location for X coordinate
7449 * @root_y: return location for Y coordinate
7451 * Obtains the position of a window position in root
7452 * window coordinates. This is similar to
7453 * gdk_window_get_origin() but allows you go pass
7454 * in any position in the window, not just the origin.
7457 gdk_window_get_root_coords (GdkWindow *window,
7463 GdkWindowObject *private;
7465 g_return_if_fail (GDK_IS_WINDOW (window));
7467 private = (GdkWindowObject *) window;
7469 if (GDK_WINDOW_DESTROYED (window))
7478 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_root_coords (window,
7486 * gdk_window_get_deskrelative_origin:
7487 * @window: a toplevel #GdkWindow
7488 * @x: return location for X coordinate
7489 * @y: return location for Y coordinate
7491 * This gets the origin of a #GdkWindow relative to
7492 * an Enlightenment-window-manager desktop. As long as you don't
7493 * assume that the user's desktop/workspace covers the entire
7494 * root window (i.e. you don't assume that the desktop begins
7495 * at root window coordinate 0,0) this function is not necessary.
7496 * It's deprecated for that reason.
7498 * Return value: not meaningful
7501 gdk_window_get_deskrelative_origin (GdkWindow *window,
7505 GdkWindowObject *private;
7506 gboolean return_val = FALSE;
7510 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
7512 private = (GdkWindowObject *) window;
7514 if (!GDK_WINDOW_DESTROYED (window))
7516 return_val = GDK_WINDOW_IMPL_GET_IFACE (private->impl)->get_deskrelative_origin (window, &tx, &ty);
7519 *x = tx + private->abs_x;
7521 *y = ty + private->abs_y;
7528 * gdk_window_shape_combine_mask:
7529 * @window: a #GdkWindow
7531 * @x: X position of shape mask with respect to @window
7532 * @y: Y position of shape mask with respect to @window
7534 * Applies a shape mask to @window. Pixels in @window corresponding to
7535 * set bits in the @mask will be visible; pixels in @window
7536 * corresponding to unset bits in the @mask will be transparent. This
7537 * gives a non-rectangular window.
7539 * If @mask is %NULL, the shape mask will be unset, and the @x/@y
7540 * parameters are not used.
7542 * On the X11 platform, this uses an X server extension which is
7543 * widely available on most common platforms, but not available on
7544 * very old X servers, and occasionally the implementation will be
7545 * buggy. On servers without the shape extension, this function
7548 * This function works on both toplevel and child windows.
7551 gdk_window_shape_combine_mask (GdkWindow *window,
7556 GdkWindowObject *private;
7559 g_return_if_fail (GDK_IS_WINDOW (window));
7561 private = (GdkWindowObject *) window;
7564 region = _gdk_windowing_get_shape_for_mask (mask);
7568 gdk_window_shape_combine_region (window,
7573 gdk_region_destroy (region);
7577 * gdk_window_shape_combine_region:
7578 * @window: a #GdkWindow
7579 * @shape_region: region of window to be non-transparent
7580 * @offset_x: X position of @shape_region in @window coordinates
7581 * @offset_y: Y position of @shape_region in @window coordinates
7583 * Makes pixels in @window outside @shape_region be transparent,
7584 * so that the window may be nonrectangular. See also
7585 * gdk_window_shape_combine_mask() to use a bitmap as the mask.
7587 * If @shape_region is %NULL, the shape will be unset, so the whole
7588 * window will be opaque again. @offset_x and @offset_y are ignored
7589 * if @shape_region is %NULL.
7591 * On the X11 platform, this uses an X server extension which is
7592 * widely available on most common platforms, but not available on
7593 * very old X servers, and occasionally the implementation will be
7594 * buggy. On servers without the shape extension, this function
7597 * This function works on both toplevel and child windows.
7600 gdk_window_shape_combine_region (GdkWindow *window,
7601 const GdkRegion *shape_region,
7605 GdkWindowObject *private;
7606 GdkRegion *old_region, *new_region, *diff;
7608 g_return_if_fail (GDK_IS_WINDOW (window));
7610 private = (GdkWindowObject *) window;
7612 if (GDK_WINDOW_DESTROYED (window))
7615 private->shaped = (shape_region != NULL);
7618 gdk_region_destroy (private->shape);
7621 if (GDK_WINDOW_IS_MAPPED (window))
7622 old_region = gdk_region_copy (private->clip_region);
7626 private->shape = gdk_region_copy (shape_region);
7627 gdk_region_offset (private->shape, offset_x, offset_y);
7630 private->shape = NULL;
7632 recompute_visible_regions (private, TRUE, FALSE);
7636 new_region = gdk_region_copy (private->clip_region);
7638 /* New area in the window, needs invalidation */
7639 diff = gdk_region_copy (new_region);
7640 gdk_region_subtract (diff, old_region);
7642 gdk_window_invalidate_region (window, diff, TRUE);
7644 gdk_region_destroy (diff);
7646 if (private->parent != NULL &&
7647 private->parent->window_type != GDK_WINDOW_ROOT)
7649 /* New area in the non-root parent window, needs invalidation */
7650 diff = gdk_region_copy (old_region);
7651 gdk_region_subtract (diff, new_region);
7653 /* Adjust region to parent window coords */
7654 gdk_region_offset (diff, private->x, private->y);
7656 gdk_window_invalidate_region (GDK_WINDOW (private->parent), diff, TRUE);
7658 gdk_region_destroy (diff);
7661 gdk_region_destroy (new_region);
7662 gdk_region_destroy (old_region);
7667 do_child_shapes (GdkWindow *window,
7670 GdkWindowObject *private;
7674 private = (GdkWindowObject *) window;
7678 r.width = private->width;
7679 r.height = private->height;
7681 region = gdk_region_rectangle (&r);
7682 remove_child_area (private, NULL, FALSE, region);
7684 if (merge && private->shape)
7685 gdk_region_subtract (region, private->shape);
7687 gdk_window_shape_combine_region (window, region, 0, 0);
7691 * gdk_window_set_child_shapes:
7692 * @window: a #GdkWindow
7694 * Sets the shape mask of @window to the union of shape masks
7695 * for all children of @window, ignoring the shape mask of @window
7696 * itself. Contrast with gdk_window_merge_child_shapes() which includes
7697 * the shape mask of @window in the masks to be merged.
7700 gdk_window_set_child_shapes (GdkWindow *window)
7702 g_return_if_fail (GDK_IS_WINDOW (window));
7704 do_child_shapes (window, FALSE);
7708 * gdk_window_merge_child_shapes:
7709 * @window: a #GdkWindow
7711 * Merges the shape masks for any child windows into the
7712 * shape mask for @window. i.e. the union of all masks
7713 * for @window and its children will become the new mask
7714 * for @window. See gdk_window_shape_combine_mask().
7716 * This function is distinct from gdk_window_set_child_shapes()
7717 * because it includes @window's shape mask in the set of shapes to
7721 gdk_window_merge_child_shapes (GdkWindow *window)
7723 g_return_if_fail (GDK_IS_WINDOW (window));
7725 do_child_shapes (window, TRUE);
7729 * gdk_window_input_shape_combine_mask:
7730 * @window: a #GdkWindow
7731 * @mask: shape mask, or %NULL
7732 * @x: X position of shape mask with respect to @window
7733 * @y: Y position of shape mask with respect to @window
7735 * Like gdk_window_shape_combine_mask(), but the shape applies
7736 * only to event handling. Mouse events which happen while
7737 * the pointer position corresponds to an unset bit in the
7738 * mask will be passed on the window below @window.
7740 * An input shape is typically used with RGBA windows.
7741 * The alpha channel of the window defines which pixels are
7742 * invisible and allows for nicely antialiased borders,
7743 * and the input shape controls where the window is
7746 * On the X11 platform, this requires version 1.1 of the
7749 * On the Win32 platform, this functionality is not present and the
7750 * function does nothing.
7755 gdk_window_input_shape_combine_mask (GdkWindow *window,
7760 GdkWindowObject *private;
7763 g_return_if_fail (GDK_IS_WINDOW (window));
7765 private = (GdkWindowObject *) window;
7768 region = _gdk_windowing_get_shape_for_mask (mask);
7772 gdk_window_input_shape_combine_region (window,
7777 gdk_region_destroy (region);
7781 * gdk_window_input_shape_combine_region:
7782 * @window: a #GdkWindow
7783 * @shape_region: region of window to be non-transparent
7784 * @offset_x: X position of @shape_region in @window coordinates
7785 * @offset_y: Y position of @shape_region in @window coordinates
7787 * Like gdk_window_shape_combine_region(), but the shape applies
7788 * only to event handling. Mouse events which happen while
7789 * the pointer position corresponds to an unset bit in the
7790 * mask will be passed on the window below @window.
7792 * An input shape is typically used with RGBA windows.
7793 * The alpha channel of the window defines which pixels are
7794 * invisible and allows for nicely antialiased borders,
7795 * and the input shape controls where the window is
7798 * On the X11 platform, this requires version 1.1 of the
7801 * On the Win32 platform, this functionality is not present and the
7802 * function does nothing.
7807 gdk_window_input_shape_combine_region (GdkWindow *window,
7808 const GdkRegion *shape_region,
7812 GdkWindowObject *private;
7814 g_return_if_fail (GDK_IS_WINDOW (window));
7816 private = (GdkWindowObject *) window;
7818 if (GDK_WINDOW_DESTROYED (window))
7821 if (private->input_shape)
7822 gdk_region_destroy (private->input_shape);
7826 private->input_shape = gdk_region_copy (shape_region);
7827 gdk_region_offset (private->input_shape, offset_x, offset_y);
7830 private->input_shape = NULL;
7832 if (gdk_window_has_impl (private))
7833 GDK_WINDOW_IMPL_GET_IFACE (private->impl)->input_shape_combine_region ((GdkWindow *)private, private->input_shape, 0, 0);
7835 /* Pointer may have e.g. moved outside window due to the input mask change */
7836 _gdk_synthesize_crossing_events_for_geometry_change (window);
7840 do_child_input_shapes (GdkWindow *window,
7843 GdkWindowObject *private;
7847 private = (GdkWindowObject *) window;
7851 r.width = private->width;
7852 r.height = private->height;
7854 region = gdk_region_rectangle (&r);
7855 remove_child_area (private, NULL, TRUE, region);
7857 if (merge && private->shape)
7858 gdk_region_subtract (region, private->shape);
7859 if (merge && private->input_shape)
7860 gdk_region_subtract (region, private->input_shape);
7862 gdk_window_input_shape_combine_region (window, region, 0, 0);
7867 * gdk_window_set_child_input_shapes:
7868 * @window: a #GdkWindow
7870 * Sets the input shape mask of @window to the union of input shape masks
7871 * for all children of @window, ignoring the input shape mask of @window
7872 * itself. Contrast with gdk_window_merge_child_input_shapes() which includes
7873 * the input shape mask of @window in the masks to be merged.
7878 gdk_window_set_child_input_shapes (GdkWindow *window)
7880 g_return_if_fail (GDK_IS_WINDOW (window));
7882 do_child_input_shapes (window, FALSE);
7886 * gdk_window_merge_child_input_shapes:
7887 * @window: a #GdkWindow
7889 * Merges the input shape masks for any child windows into the
7890 * input shape mask for @window. i.e. the union of all input masks
7891 * for @window and its children will become the new input mask
7892 * for @window. See gdk_window_input_shape_combine_mask().
7894 * This function is distinct from gdk_window_set_child_input_shapes()
7895 * because it includes @window's input shape mask in the set of
7896 * shapes to be merged.
7901 gdk_window_merge_child_input_shapes (GdkWindow *window)
7903 g_return_if_fail (GDK_IS_WINDOW (window));
7905 do_child_input_shapes (window, TRUE);
7910 * gdk_window_set_static_gravities:
7911 * @window: a #GdkWindow
7912 * @use_static: %TRUE to turn on static gravity
7914 * Set the bit gravity of the given window to static, and flag it so
7915 * all children get static subwindow gravity. This is used if you are
7916 * implementing scary features that involve deep knowledge of the
7917 * windowing system. Don't worry about it unless you have to.
7919 * Return value: %TRUE if the server supports static gravity
7922 gdk_window_set_static_gravities (GdkWindow *window,
7923 gboolean use_static)
7925 GdkWindowObject *private;
7927 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
7929 private = (GdkWindowObject *) window;
7931 if (gdk_window_has_impl (private))
7932 return GDK_WINDOW_IMPL_GET_IFACE (private->impl)->set_static_gravities (window, use_static);
7938 * gdk_window_set_composited:
7939 * @window: a #GdkWindow
7940 * @composited: %TRUE to set the window as composited
7942 * Sets a #GdkWindow as composited, or unsets it. Composited
7943 * windows do not automatically have their contents drawn to
7944 * the screen. Drawing is redirected to an offscreen buffer
7945 * and an expose event is emitted on the parent of the composited
7946 * window. It is the responsibility of the parent's expose handler
7947 * to manually merge the off-screen content onto the screen in
7948 * whatever way it sees fit. See <xref linkend="composited-window-example"/>
7951 * It only makes sense for child windows to be composited; see
7952 * gdk_window_set_opacity() if you need translucent toplevel
7955 * An additional effect of this call is that the area of this
7956 * window is no longer clipped from regions marked for
7957 * invalidation on its parent. Draws done on the parent
7958 * window are also no longer clipped by the child.
7960 * This call is only supported on some systems (currently,
7961 * only X11 with new enough Xcomposite and Xdamage extensions).
7962 * You must call gdk_display_supports_composite() to check if
7963 * setting a window as composited is supported before
7964 * attempting to do so.
7969 gdk_window_set_composited (GdkWindow *window,
7970 gboolean composited)
7972 GdkWindowObject *private = (GdkWindowObject *)window;
7973 GdkDisplay *display;
7975 g_return_if_fail (GDK_IS_WINDOW (window));
7977 composited = composited != FALSE;
7979 if (private->composited == composited)
7983 gdk_window_ensure_native (window);
7985 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
7987 if (!gdk_display_supports_composite (display) && composited)
7989 g_warning ("gdk_window_set_composited called but "
7990 "compositing is not supported");
7994 _gdk_windowing_window_set_composited (window, composited);
7996 recompute_visible_regions (private, TRUE, FALSE);
7998 if (GDK_WINDOW_IS_MAPPED (window))
7999 gdk_window_invalidate_in_parent (private);
8001 private->composited = composited;
8006 remove_redirect_from_children (GdkWindowObject *private,
8007 GdkWindowRedirect *redirect)
8010 GdkWindowObject *child;
8012 for (l = private->children; l != NULL; l = l->next)
8016 /* Don't redirect this child if it already has another redirect */
8017 if (child->redirect == redirect)
8019 child->redirect = NULL;
8020 remove_redirect_from_children (child, redirect);
8026 * gdk_window_remove_redirection:
8027 * @window: a #GdkWindow
8029 * Removes any active redirection started by
8030 * gdk_window_redirect_to_drawable().
8035 gdk_window_remove_redirection (GdkWindow *window)
8037 GdkWindowObject *private;
8039 g_return_if_fail (GDK_IS_WINDOW (window));
8041 private = (GdkWindowObject *) window;
8043 if (private->redirect &&
8044 private->redirect->redirected == private)
8046 remove_redirect_from_children (private, private->redirect);
8047 gdk_window_redirect_free (private->redirect);
8048 private->redirect = NULL;
8053 apply_redirect_to_children (GdkWindowObject *private,
8054 GdkWindowRedirect *redirect)
8057 GdkWindowObject *child;
8059 for (l = private->children; l != NULL; l = l->next)
8063 /* Don't redirect this child if it already has another redirect */
8064 if (!child->redirect)
8066 child->redirect = redirect;
8067 apply_redirect_to_children (child, redirect);
8073 * gdk_window_redirect_to_drawable:
8074 * @window: a #GdkWindow
8075 * @drawable: a #GdkDrawable
8076 * @src_x: x position in @window
8077 * @src_y: y position in @window
8078 * @dest_x: x position in @drawable
8079 * @dest_y: y position in @drawable
8080 * @width: width of redirection, or -1 to use the width of @window
8081 * @height: height of redirection or -1 to use the height of @window
8083 * Redirects drawing into @window so that drawing to the
8084 * window in the rectangle specified by @src_x, @src_y,
8085 * @width and @height is also drawn into @drawable at
8088 * Only drawing between gdk_window_begin_paint_region() or
8089 * gdk_window_begin_paint_rect() and gdk_window_end_paint() is
8092 * Redirection is active until gdk_window_remove_redirection()
8098 gdk_window_redirect_to_drawable (GdkWindow *window,
8099 GdkDrawable *drawable,
8107 GdkWindowObject *private;
8109 g_return_if_fail (GDK_IS_WINDOW (window));
8110 g_return_if_fail (GDK_IS_DRAWABLE (drawable));
8111 g_return_if_fail (GDK_WINDOW_TYPE (window) != GDK_WINDOW_ROOT);
8113 private = (GdkWindowObject *) window;
8115 if (private->redirect)
8116 gdk_window_remove_redirection (window);
8118 if (width == -1 || height == -1)
8121 gdk_drawable_get_size (GDK_DRAWABLE (window), &w, &h);
8128 private->redirect = g_new0 (GdkWindowRedirect, 1);
8129 private->redirect->redirected = private;
8130 private->redirect->pixmap = g_object_ref (drawable);
8131 private->redirect->src_x = src_x;
8132 private->redirect->src_y = src_y;
8133 private->redirect->dest_x = dest_x;
8134 private->redirect->dest_y = dest_y;
8135 private->redirect->width = width;
8136 private->redirect->height = height;
8138 apply_redirect_to_children (private, private->redirect);
8142 window_get_size_rectangle (GdkWindow *window,
8145 GdkWindowObject *private = (GdkWindowObject *) window;
8147 rect->x = rect->y = 0;
8148 rect->width = private->width;
8149 rect->height = private->height;
8152 /* Calculates the real clipping region for a window, in window coordinates,
8153 * taking into account other windows, gc clip region and gc clip mask.
8156 _gdk_window_calculate_full_clip_region (GdkWindow *window,
8157 GdkWindow *base_window,
8158 gboolean do_children,
8159 gint *base_x_offset,
8160 gint *base_y_offset)
8162 GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
8163 GdkRectangle visible_rect;
8164 GdkRegion *real_clip_region, *tmpreg;
8165 gint x_offset, y_offset;
8166 GdkWindowObject *parentwin, *lastwin;
8173 if (!private->viewable || private->input_only)
8174 return gdk_region_new ();
8176 window_get_size_rectangle (window, &visible_rect);
8178 /* real_clip_region is in window coordinates */
8179 real_clip_region = gdk_region_rectangle (&visible_rect);
8181 x_offset = y_offset = 0;
8185 parentwin = lastwin;
8187 parentwin = lastwin->parent;
8189 /* Remove the areas of all overlapping windows above parentwin in the hiearachy */
8190 for (; parentwin != NULL &&
8191 (parentwin == private || lastwin != (GdkWindowObject*) base_window);
8192 lastwin = parentwin, parentwin = lastwin->parent)
8195 GdkRectangle real_clip_rect;
8196 gboolean is_offscreen;
8198 if (parentwin != private)
8200 x_offset += GDK_WINDOW_OBJECT (lastwin)->x;
8201 y_offset += GDK_WINDOW_OBJECT (lastwin)->y;
8204 is_offscreen = gdk_window_is_offscreen (parentwin);
8206 /* children is ordered in reverse stack order */
8207 for (cur = parentwin->children;
8208 cur && cur->data != lastwin;
8211 GdkWindow *child = cur->data;
8212 GdkWindowObject *child_private = (GdkWindowObject *)child;
8214 if (!GDK_WINDOW_IS_MAPPED (child) || child_private->input_only)
8217 /* Ignore offscreen children, as they don't draw in their parent and
8218 * don't take part in the clipping */
8219 if (gdk_window_is_offscreen (child_private))
8222 window_get_size_rectangle (child, &visible_rect);
8224 /* Convert rect to "window" coords */
8225 visible_rect.x += child_private->x - x_offset;
8226 visible_rect.y += child_private->y - y_offset;
8228 /* This shortcut is really necessary for performance when there are a lot of windows */
8229 gdk_region_get_clipbox (real_clip_region, &real_clip_rect);
8230 if (visible_rect.x >= real_clip_rect.x + real_clip_rect.width ||
8231 visible_rect.x + visible_rect.width <= real_clip_rect.x ||
8232 visible_rect.y >= real_clip_rect.y + real_clip_rect.height ||
8233 visible_rect.y + visible_rect.height <= real_clip_rect.y)
8236 tmpreg = gdk_region_rectangle (&visible_rect);
8237 gdk_region_subtract (real_clip_region, tmpreg);
8238 gdk_region_destroy (tmpreg);
8241 /* Clip to the parent */
8242 window_get_size_rectangle ((GdkWindow *)parentwin, &visible_rect);
8243 /* Convert rect to "window" coords */
8244 visible_rect.x += - x_offset;
8245 visible_rect.y += - y_offset;
8247 tmpreg = gdk_region_rectangle (&visible_rect);
8248 gdk_region_intersect (real_clip_region, tmpreg);
8249 gdk_region_destroy (tmpreg);
8253 *base_x_offset = x_offset;
8255 *base_y_offset = y_offset;
8257 return real_clip_region;
8261 _gdk_window_add_damage (GdkWindow *toplevel,
8262 GdkRegion *damaged_region)
8264 GdkDisplay *display;
8265 GdkEvent event = { 0, };
8266 event.expose.type = GDK_DAMAGE;
8267 event.expose.window = toplevel;
8268 event.expose.send_event = FALSE;
8269 event.expose.region = damaged_region;
8270 gdk_region_get_clipbox (event.expose.region, &event.expose.area);
8271 display = gdk_drawable_get_display (event.expose.window);
8272 _gdk_event_queue_append (display, gdk_event_copy (&event));
8276 gdk_window_redirect_free (GdkWindowRedirect *redirect)
8278 g_object_unref (redirect->pixmap);
8282 /* Gets the toplevel for a window as used for events,
8283 i.e. including offscreen parents */
8284 static GdkWindowObject *
8285 get_event_parent (GdkWindowObject *window)
8287 if (window->window_type == GDK_WINDOW_OFFSCREEN)
8288 return (GdkWindowObject *)gdk_offscreen_window_get_embedder ((GdkWindow *)window);
8290 return window->parent;
8293 /* Gets the toplevel for a window as used for events,
8294 i.e. including offscreen parents going up to the native
8297 get_event_toplevel (GdkWindow *w)
8299 GdkWindowObject *private = GDK_WINDOW_OBJECT (w);
8300 GdkWindowObject *parent;
8302 while ((parent = get_event_parent (private)) != NULL &&
8303 (parent->window_type != GDK_WINDOW_ROOT))
8306 return GDK_WINDOW (private);
8310 _gdk_window_event_parent_of (GdkWindow *parent,
8321 w = (GdkWindow *)get_event_parent ((GdkWindowObject *)w);
8328 update_cursor (GdkDisplay *display)
8330 GdkWindowObject *pointer_window, *cursor_window, *parent, *toplevel;
8331 GdkPointerGrabInfo *grab;
8333 pointer_window = (GdkWindowObject *)display->pointer_info.window_under_pointer;
8335 cursor_window = pointer_window;
8336 while (cursor_window->cursor == NULL &&
8337 (parent = get_event_parent (cursor_window)) != NULL &&
8338 parent->window_type != GDK_WINDOW_ROOT)
8339 cursor_window = parent;
8341 /* We ignore the serials here and just pick the last grab
8342 we've sent, as that would shortly be used anyway. */
8343 grab = _gdk_display_get_last_pointer_grab (display);
8345 !_gdk_window_event_parent_of (grab->window, (GdkWindow *)cursor_window))
8346 cursor_window = (GdkWindowObject *)grab->window;
8348 /* Set all cursors on toplevel, otherwise its tricky to keep track of
8349 * which native window has what cursor set. */
8350 toplevel = (GdkWindowObject *)get_event_toplevel ((GdkWindow *)pointer_window);
8351 GDK_WINDOW_IMPL_GET_IFACE (toplevel->impl)->set_cursor
8352 ((GdkWindow *)toplevel, cursor_window->cursor);
8356 from_embedder (GdkWindowObject *window,
8359 gdouble *offscreen_x,
8360 gdouble *offscreen_y)
8362 g_signal_emit (window,
8363 signals[FROM_EMBEDDER], 0,
8364 embedder_x, embedder_y,
8365 offscreen_x, offscreen_y,
8370 convert_coords_to_child (GdkWindowObject *child,
8376 if (gdk_window_is_offscreen (child))
8378 from_embedder (child, x, y,
8383 *child_x = x - child->x;
8384 *child_y = y - child->y;
8389 point_in_window (GdkWindowObject *window,
8394 x >= 0 && x < window->width &&
8395 y >= 0 && y < window->height &&
8396 (window->shape == NULL ||
8397 gdk_region_point_in (window->shape,
8399 (window->input_shape == NULL ||
8400 gdk_region_point_in (window->input_shape,
8405 convert_native_coords_to_toplevel (GdkWindow *window,
8408 gdouble *toplevel_x,
8409 gdouble *toplevel_y)
8411 GdkWindowObject *private = (GdkWindowObject *)window;
8417 while (private->parent != NULL &&
8418 (private->parent->window_type != GDK_WINDOW_ROOT))
8422 private = private->parent;
8428 return (GdkWindow *)private;
8432 convert_toplevel_coords_to_window (GdkWindow *window,
8438 GdkWindowObject *private;
8439 GdkWindowObject *parent;
8441 GList *children, *l;
8443 private = GDK_WINDOW_OBJECT (window);
8449 while ((parent = get_event_parent (private)) != NULL &&
8450 (parent->window_type != GDK_WINDOW_ROOT))
8452 children = g_list_prepend (children, private);
8456 for (l = children; l != NULL; l = l->next)
8457 convert_coords_to_child (l->data, x, y, &x, &y);
8459 g_list_free (children);
8465 static GdkWindowObject *
8466 pick_embedded_child (GdkWindowObject *window,
8470 GdkWindowObject *res;
8473 g_signal_emit (window,
8474 signals[PICK_EMBEDDED_CHILD], 0,
8481 _gdk_window_find_child_at (GdkWindow *window,
8485 GdkWindowObject *private, *sub;
8486 double child_x, child_y;
8489 private = (GdkWindowObject *)window;
8491 if (point_in_window (private, x, y))
8493 /* Children is ordered in reverse stack order, i.e. first is topmost */
8494 for (l = private->children; l != NULL; l = l->next)
8498 if (!GDK_WINDOW_IS_MAPPED (sub))
8501 convert_coords_to_child (sub,
8503 &child_x, &child_y);
8504 if (point_in_window (sub, child_x, child_y))
8505 return (GdkWindow *)sub;
8508 if (private->num_offscreen_children > 0)
8510 sub = pick_embedded_child (private,
8513 return (GdkWindow *)sub;
8521 _gdk_window_find_descendant_at (GdkWindow *toplevel,
8527 GdkWindowObject *private, *sub;
8528 gdouble child_x, child_y;
8532 private = (GdkWindowObject *)toplevel;
8534 if (point_in_window (private, x, y))
8539 /* Children is ordered in reverse stack order, i.e. first is topmost */
8540 for (l = private->children; l != NULL; l = l->next)
8544 if (!GDK_WINDOW_IS_MAPPED (sub))
8547 convert_coords_to_child (sub,
8549 &child_x, &child_y);
8550 if (point_in_window (sub, child_x, child_y))
8560 private->num_offscreen_children > 0)
8562 sub = pick_embedded_child (private,
8568 from_embedder (sub, x, y, &x, &y);
8576 /* Not in window at all */
8585 return (GdkWindow *)private;
8590 * @window: a toplevel #GdkWindow
8592 * Emits a short beep associated to @window in the appropriate
8593 * display, if supported. Otherwise, emits a short beep on
8594 * the display just as gdk_display_beep().
8599 gdk_window_beep (GdkWindow *window)
8601 GdkDisplay *display;
8602 GdkWindow *toplevel;
8604 g_return_if_fail (GDK_IS_WINDOW (window));
8606 if (GDK_WINDOW_DESTROYED (window))
8609 toplevel = get_event_toplevel (window);
8610 display = gdk_drawable_get_display (GDK_DRAWABLE (window));
8612 if (toplevel && !gdk_window_is_offscreen ((GdkWindowObject *)toplevel))
8613 _gdk_windowing_window_beep (toplevel);
8615 gdk_display_beep (display);
8618 static const guint type_masks[] = {
8619 GDK_SUBSTRUCTURE_MASK, /* GDK_DELETE = 0 */
8620 GDK_STRUCTURE_MASK, /* GDK_DESTROY = 1 */
8621 GDK_EXPOSURE_MASK, /* GDK_EXPOSE = 2 */
8622 GDK_POINTER_MOTION_MASK, /* GDK_MOTION_NOTIFY = 3 */
8623 GDK_BUTTON_PRESS_MASK, /* GDK_BUTTON_PRESS = 4 */
8624 GDK_BUTTON_PRESS_MASK, /* GDK_2BUTTON_PRESS = 5 */
8625 GDK_BUTTON_PRESS_MASK, /* GDK_3BUTTON_PRESS = 6 */
8626 GDK_BUTTON_RELEASE_MASK, /* GDK_BUTTON_RELEASE = 7 */
8627 GDK_KEY_PRESS_MASK, /* GDK_KEY_PRESS = 8 */
8628 GDK_KEY_RELEASE_MASK, /* GDK_KEY_RELEASE = 9 */
8629 GDK_ENTER_NOTIFY_MASK, /* GDK_ENTER_NOTIFY = 10 */
8630 GDK_LEAVE_NOTIFY_MASK, /* GDK_LEAVE_NOTIFY = 11 */
8631 GDK_FOCUS_CHANGE_MASK, /* GDK_FOCUS_CHANGE = 12 */
8632 GDK_STRUCTURE_MASK, /* GDK_CONFIGURE = 13 */
8633 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_MAP = 14 */
8634 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_UNMAP = 15 */
8635 GDK_PROPERTY_CHANGE_MASK, /* GDK_PROPERTY_NOTIFY = 16 */
8636 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_CLEAR = 17 */
8637 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_REQUEST = 18 */
8638 GDK_PROPERTY_CHANGE_MASK, /* GDK_SELECTION_NOTIFY = 19 */
8639 GDK_PROXIMITY_IN_MASK, /* GDK_PROXIMITY_IN = 20 */
8640 GDK_PROXIMITY_OUT_MASK, /* GDK_PROXIMITY_OUT = 21 */
8641 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_ENTER = 22 */
8642 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_LEAVE = 23 */
8643 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_MOTION = 24 */
8644 GDK_ALL_EVENTS_MASK, /* GDK_DRAG_STATUS = 25 */
8645 GDK_ALL_EVENTS_MASK, /* GDK_DROP_START = 26 */
8646 GDK_ALL_EVENTS_MASK, /* GDK_DROP_FINISHED = 27 */
8647 GDK_ALL_EVENTS_MASK, /* GDK_CLIENT_EVENT = 28 */
8648 GDK_VISIBILITY_NOTIFY_MASK, /* GDK_VISIBILITY_NOTIFY = 29 */
8649 GDK_EXPOSURE_MASK, /* GDK_NO_EXPOSE = 30 */
8650 GDK_SCROLL_MASK | GDK_BUTTON_PRESS_MASK,/* GDK_SCROLL= 31 */
8651 0, /* GDK_WINDOW_STATE = 32 */
8652 0, /* GDK_SETTING = 33 */
8653 0, /* GDK_OWNER_CHANGE = 34 */
8654 0, /* GDK_GRAB_BROKEN = 35 */
8655 0, /* GDK_DAMAGE = 36 */
8657 G_STATIC_ASSERT (G_N_ELEMENTS (type_masks) == GDK_EVENT_LAST);
8659 /* send motion events if the right buttons are down */
8661 update_evmask_for_button_motion (guint evmask,
8662 GdkModifierType mask)
8664 if (evmask & GDK_BUTTON_MOTION_MASK &&
8665 mask & (GDK_BUTTON1_MASK |
8670 evmask |= GDK_POINTER_MOTION_MASK;
8672 if ((evmask & GDK_BUTTON1_MOTION_MASK && mask & GDK_BUTTON1_MASK) ||
8673 (evmask & GDK_BUTTON2_MOTION_MASK && mask & GDK_BUTTON2_MASK) ||
8674 (evmask & GDK_BUTTON3_MOTION_MASK && mask & GDK_BUTTON3_MASK))
8675 evmask |= GDK_POINTER_MOTION_MASK;
8681 is_button_type (GdkEventType type)
8683 return type == GDK_BUTTON_PRESS ||
8684 type == GDK_2BUTTON_PRESS ||
8685 type == GDK_3BUTTON_PRESS ||
8686 type == GDK_BUTTON_RELEASE ||
8691 is_motion_type (GdkEventType type)
8693 return type == GDK_MOTION_NOTIFY ||
8694 type == GDK_ENTER_NOTIFY ||
8695 type == GDK_LEAVE_NOTIFY;
8698 static GdkWindowObject *
8699 find_common_ancestor (GdkWindowObject *win1,
8700 GdkWindowObject *win2)
8702 GdkWindowObject *tmp;
8703 GList *path1 = NULL, *path2 = NULL;
8704 GList *list1, *list2;
8707 while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
8709 path1 = g_list_prepend (path1, tmp);
8710 tmp = get_event_parent (tmp);
8714 while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT)
8716 path2 = g_list_prepend (path2, tmp);
8717 tmp = get_event_parent (tmp);
8723 while (list1 && list2 && (list1->data == list2->data))
8725 tmp = (GdkWindowObject *)list1->data;
8726 list1 = g_list_next (list1);
8727 list2 = g_list_next (list2);
8729 g_list_free (path1);
8730 g_list_free (path2);
8736 _gdk_make_event (GdkWindow *window,
8738 GdkEvent *event_in_queue,
8739 gboolean before_event)
8741 GdkEvent *event = gdk_event_new (type);
8743 GdkModifierType the_state;
8745 the_time = gdk_event_get_time (event_in_queue);
8746 gdk_event_get_state (event_in_queue, &the_state);
8748 event->any.window = g_object_ref (window);
8749 event->any.send_event = FALSE;
8750 if (event_in_queue && event_in_queue->any.send_event)
8751 event->any.send_event = TRUE;
8755 case GDK_MOTION_NOTIFY:
8756 event->motion.time = the_time;
8757 event->motion.axes = NULL;
8758 event->motion.state = the_state;
8761 case GDK_BUTTON_PRESS:
8762 case GDK_2BUTTON_PRESS:
8763 case GDK_3BUTTON_PRESS:
8764 case GDK_BUTTON_RELEASE:
8765 event->button.time = the_time;
8766 event->button.axes = NULL;
8767 event->button.state = the_state;
8771 event->scroll.time = the_time;
8772 event->scroll.state = the_state;
8776 case GDK_KEY_RELEASE:
8777 event->key.time = the_time;
8778 event->key.state = the_state;
8781 case GDK_ENTER_NOTIFY:
8782 case GDK_LEAVE_NOTIFY:
8783 event->crossing.time = the_time;
8784 event->crossing.state = the_state;
8787 case GDK_PROPERTY_NOTIFY:
8788 event->property.time = the_time;
8789 event->property.state = the_state;
8792 case GDK_SELECTION_CLEAR:
8793 case GDK_SELECTION_REQUEST:
8794 case GDK_SELECTION_NOTIFY:
8795 event->selection.time = the_time;
8798 case GDK_PROXIMITY_IN:
8799 case GDK_PROXIMITY_OUT:
8800 event->proximity.time = the_time;
8803 case GDK_DRAG_ENTER:
8804 case GDK_DRAG_LEAVE:
8805 case GDK_DRAG_MOTION:
8806 case GDK_DRAG_STATUS:
8807 case GDK_DROP_START:
8808 case GDK_DROP_FINISHED:
8809 event->dnd.time = the_time;
8812 case GDK_FOCUS_CHANGE:
8816 case GDK_CLIENT_EVENT:
8817 case GDK_VISIBILITY_NOTIFY:
8829 _gdk_event_queue_insert_before (gdk_drawable_get_display (window), event_in_queue, event);
8831 _gdk_event_queue_insert_after (gdk_drawable_get_display (window), event_in_queue, event);
8834 _gdk_event_queue_append (gdk_drawable_get_display (window), event);
8840 send_crossing_event (GdkDisplay *display,
8841 GdkWindowObject *toplevel,
8842 GdkWindowObject *window,
8844 GdkCrossingMode mode,
8845 GdkNotifyType notify_type,
8846 GdkWindow *subwindow,
8849 GdkModifierType mask,
8851 GdkEvent *event_in_queue,
8856 GdkPointerGrabInfo *grab;
8858 grab = _gdk_display_has_pointer_grab (display, serial);
8861 !grab->owner_events &&
8862 (GdkWindow *)window != grab->window)
8865 if (type == GDK_LEAVE_NOTIFY)
8866 event_mask = GDK_LEAVE_NOTIFY_MASK;
8868 event_mask = GDK_ENTER_NOTIFY_MASK;
8870 if (window->extension_events != 0)
8871 GDK_WINDOW_IMPL_GET_IFACE (window->impl)->input_window_crossing ((GdkWindow *)window,
8872 type == GDK_ENTER_NOTIFY);
8874 if (window->event_mask & event_mask)
8876 event = _gdk_make_event ((GdkWindow *)window, type, event_in_queue, TRUE);
8877 event->crossing.time = time_;
8878 event->crossing.subwindow = subwindow;
8880 g_object_ref (subwindow);
8881 convert_toplevel_coords_to_window ((GdkWindow *)window,
8882 toplevel_x, toplevel_y,
8883 &event->crossing.x, &event->crossing.y);
8884 event->crossing.x_root = toplevel_x + toplevel->x;
8885 event->crossing.y_root = toplevel_y + toplevel->y;
8886 event->crossing.mode = mode;
8887 event->crossing.detail = notify_type;
8888 event->crossing.focus = FALSE;
8889 event->crossing.state = mask;
8894 /* The coordinates are in the toplevel window that src/dest are in.
8895 * src and dest are always (if != NULL) in the same toplevel, as
8896 * we get a leave-notify and set the window_under_pointer to null
8897 * before crossing to another toplevel.
8900 _gdk_synthesize_crossing_events (GdkDisplay *display,
8903 GdkCrossingMode mode,
8906 GdkModifierType mask,
8908 GdkEvent *event_in_queue,
8910 gboolean non_linear)
8913 GdkWindowObject *win, *last, *next;
8917 GdkWindowObject *toplevel;
8918 GdkNotifyType notify_type;
8920 /* TODO: Don't send events to toplevel, as we get those from the windowing system */
8922 a = (GdkWindowObject *)src;
8923 b = (GdkWindowObject *)dest;
8925 return; /* No crossings generated between src and dest */
8927 c = find_common_ancestor (a, b);
8929 non_linear |= (c != a) && (c != b);
8931 if (a) /* There might not be a source (i.e. if no previous pointer_in_window) */
8933 toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)a);
8935 /* Traverse up from a to (excluding) c sending leave events */
8937 notify_type = GDK_NOTIFY_NONLINEAR;
8939 notify_type = GDK_NOTIFY_INFERIOR;
8941 notify_type = GDK_NOTIFY_ANCESTOR;
8942 send_crossing_event (display, toplevel,
8943 a, GDK_LEAVE_NOTIFY,
8947 toplevel_x, toplevel_y,
8955 notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
8957 notify_type = GDK_NOTIFY_VIRTUAL;
8960 win = get_event_parent (a);
8961 while (win != c && win->window_type != GDK_WINDOW_ROOT)
8963 send_crossing_event (display, toplevel,
8964 win, GDK_LEAVE_NOTIFY,
8968 toplevel_x, toplevel_y,
8974 win = get_event_parent (win);
8979 if (b) /* Might not be a dest, e.g. if we're moving out of the window */
8981 toplevel = (GdkWindowObject *)gdk_window_get_toplevel ((GdkWindow *)b);
8983 /* Traverse down from c to b */
8987 win = get_event_parent (b);
8988 while (win != c && win->window_type != GDK_WINDOW_ROOT)
8990 path = g_list_prepend (path, win);
8991 win = get_event_parent (win);
8995 notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL;
8997 notify_type = GDK_NOTIFY_VIRTUAL;
9002 win = (GdkWindowObject *)list->data;
9003 list = g_list_next (list);
9005 next = (GdkWindowObject *)list->data;
9009 send_crossing_event (display, toplevel,
9010 win, GDK_ENTER_NOTIFY,
9014 toplevel_x, toplevel_y,
9024 notify_type = GDK_NOTIFY_NONLINEAR;
9026 notify_type = GDK_NOTIFY_ANCESTOR;
9028 notify_type = GDK_NOTIFY_INFERIOR;
9030 send_crossing_event (display, toplevel,
9031 b, GDK_ENTER_NOTIFY,
9035 toplevel_x, toplevel_y,
9042 /* Returns the window inside the event window with the pointer in it
9043 * at the specified coordinates, or NULL if its not in any child of
9044 * the toplevel. It also takes into account !owner_events grabs.
9047 get_pointer_window (GdkDisplay *display,
9048 GdkWindow *event_window,
9053 GdkWindow *pointer_window;
9054 GdkPointerGrabInfo *grab;
9056 if (event_window == display->pointer_info.toplevel_under_pointer)
9058 _gdk_window_find_descendant_at (event_window,
9059 toplevel_x, toplevel_y,
9062 pointer_window = NULL;
9064 grab = _gdk_display_has_pointer_grab (display, serial);
9066 !grab->owner_events &&
9067 pointer_window != grab->window)
9068 pointer_window = NULL;
9070 return pointer_window;
9074 _gdk_display_set_window_under_pointer (GdkDisplay *display,
9077 GdkWindowObject *private;
9079 /* We don't track this if all native, and it can cause issues
9080 with the update_cursor call below */
9081 if (_gdk_native_windows)
9084 private = (GdkWindowObject *)window;
9086 if (display->pointer_info.window_under_pointer)
9087 g_object_unref (display->pointer_info.window_under_pointer);
9088 display->pointer_info.window_under_pointer = window;
9090 g_object_ref (window);
9093 update_cursor (display);
9095 _gdk_display_enable_motion_hints (display);
9099 *--------------------------------------------------------------
9102 * Grabs the pointer to a specific window
9105 * "window" is the window which will receive the grab
9106 * "owner_events" specifies whether events will be reported as is,
9107 * or relative to "window"
9108 * "event_mask" masks only interesting events
9109 * "confine_to" limits the cursor movement to the specified window
9110 * "cursor" changes the cursor for the duration of the grab
9111 * "time" specifies the time
9116 * requires a corresponding call to gdk_pointer_ungrab
9118 *--------------------------------------------------------------
9121 gdk_pointer_grab (GdkWindow * window,
9122 gboolean owner_events,
9123 GdkEventMask event_mask,
9124 GdkWindow * confine_to,
9129 GdkDisplay *display;
9133 g_return_val_if_fail (window != NULL, 0);
9134 g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
9135 g_return_val_if_fail (confine_to == NULL || GDK_IS_WINDOW (confine_to), 0);
9137 /* We need a native window for confine to to work, ensure we have one */
9140 if (!gdk_window_ensure_native (confine_to))
9142 g_warning ("Can't confine to grabbed window, not native");
9147 /* Non-viewable client side window => fail */
9148 if (!_gdk_window_has_impl (window) &&
9149 !gdk_window_is_viewable (window))
9150 return GDK_GRAB_NOT_VIEWABLE;
9152 if (_gdk_native_windows)
9155 native = gdk_window_get_toplevel (window);
9156 while (gdk_window_is_offscreen ((GdkWindowObject *)native))
9158 native = gdk_offscreen_window_get_embedder (native);
9160 if (native == NULL ||
9161 (!_gdk_window_has_impl (native) &&
9162 !gdk_window_is_viewable (native)))
9163 return GDK_GRAB_NOT_VIEWABLE;
9165 native = gdk_window_get_toplevel (native);
9168 display = gdk_drawable_get_display (window);
9170 serial = _gdk_windowing_window_get_next_serial (display);
9172 res = _gdk_windowing_pointer_grab (window,
9180 if (res == GDK_GRAB_SUCCESS)
9181 _gdk_display_add_pointer_grab (display,
9194 * gdk_window_geometry_changed:
9195 * @window: a #GdkWindow
9200 gdk_window_geometry_changed (GdkWindow *window)
9202 _gdk_synthesize_crossing_events_for_geometry_change (window);
9206 do_synthesize_crossing_event (gpointer data)
9208 GdkDisplay *display;
9209 GdkWindow *changed_toplevel;
9210 GdkWindowObject *changed_toplevel_priv;
9211 GdkWindow *new_window_under_pointer;
9214 changed_toplevel = data;
9215 changed_toplevel_priv = (GdkWindowObject *)changed_toplevel;
9217 changed_toplevel_priv->synthesize_crossing_event_queued = FALSE;
9219 if (GDK_WINDOW_DESTROYED (changed_toplevel))
9222 display = gdk_drawable_get_display (changed_toplevel);
9223 serial = _gdk_windowing_window_get_next_serial (display);
9225 if (changed_toplevel == display->pointer_info.toplevel_under_pointer)
9227 new_window_under_pointer =
9228 get_pointer_window (display, changed_toplevel,
9229 display->pointer_info.toplevel_x,
9230 display->pointer_info.toplevel_y,
9232 if (new_window_under_pointer !=
9233 display->pointer_info.window_under_pointer)
9235 _gdk_synthesize_crossing_events (display,
9236 display->pointer_info.window_under_pointer,
9237 new_window_under_pointer,
9238 GDK_CROSSING_NORMAL,
9239 display->pointer_info.toplevel_x,
9240 display->pointer_info.toplevel_y,
9241 display->pointer_info.state,
9246 _gdk_display_set_window_under_pointer (display, new_window_under_pointer);
9254 _gdk_synthesize_crossing_events_for_geometry_change (GdkWindow *changed_window)
9256 GdkDisplay *display;
9257 GdkWindow *toplevel;
9258 GdkWindowObject *toplevel_priv;
9260 if (_gdk_native_windows)
9261 return; /* We use the native crossing events if all native */
9263 display = gdk_drawable_get_display (changed_window);
9265 toplevel = get_event_toplevel (changed_window);
9266 toplevel_priv = (GdkWindowObject *)toplevel;
9268 if (toplevel == display->pointer_info.toplevel_under_pointer &&
9269 !toplevel_priv->synthesize_crossing_event_queued)
9271 toplevel_priv->synthesize_crossing_event_queued = TRUE;
9272 g_idle_add_full (GDK_PRIORITY_EVENTS - 1,
9273 do_synthesize_crossing_event,
9274 g_object_ref (toplevel),
9279 /* Don't use for crossing events */
9281 get_event_window (GdkDisplay *display,
9282 GdkWindow *pointer_window,
9284 GdkModifierType mask,
9289 GdkWindow *grab_window;
9291 GdkPointerGrabInfo *grab;
9293 grab = _gdk_display_has_pointer_grab (display, serial);
9295 if (grab != NULL && !grab->owner_events)
9297 evmask = grab->event_mask;
9298 evmask = update_evmask_for_button_motion (evmask, mask);
9300 grab_window = grab->window;
9302 if (evmask & type_masks[type])
9305 *evmask_out = evmask;
9312 w = (GdkWindowObject *)pointer_window;
9315 evmask = w->event_mask;
9316 evmask = update_evmask_for_button_motion (evmask, mask);
9318 if (evmask & type_masks[type])
9321 *evmask_out = evmask;
9322 return (GdkWindow *)w;
9325 w = get_event_parent (w);
9331 evmask = grab->event_mask;
9332 evmask = update_evmask_for_button_motion (evmask, mask);
9334 if (evmask & type_masks[type])
9337 *evmask_out = evmask;
9338 return grab->window;
9348 proxy_pointer_event (GdkDisplay *display,
9349 GdkEvent *source_event,
9352 GdkWindow *toplevel_window, *event_window;
9353 GdkWindow *pointer_window;
9356 gdouble toplevel_x, toplevel_y;
9358 gboolean non_linear;
9360 event_window = source_event->any.window;
9361 gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
9362 gdk_event_get_state (source_event, &state);
9363 time_ = gdk_event_get_time (source_event);
9364 toplevel_window = convert_native_coords_to_toplevel (event_window,
9365 toplevel_x, toplevel_y,
9366 &toplevel_x, &toplevel_y);
9369 if ((source_event->type == GDK_LEAVE_NOTIFY ||
9370 source_event->type == GDK_ENTER_NOTIFY) &&
9371 (source_event->crossing.detail == GDK_NOTIFY_NONLINEAR ||
9372 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))
9375 /* If we get crossing events with subwindow unexpectedly being NULL
9376 that means there is a native subwindow that gdk doesn't know about.
9377 We track these and forward them, with the correct virtual window
9379 This is important to get right, as metacity uses gdk for the frame
9380 windows, but gdk doesn't know about the client windows reparented
9382 if (((source_event->type == GDK_LEAVE_NOTIFY &&
9383 source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
9384 (source_event->type == GDK_ENTER_NOTIFY &&
9385 (source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
9386 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
9387 source_event->crossing.subwindow == NULL)
9389 /* Left for an unknown (to gdk) subwindow */
9391 /* Send leave events from window under pointer to event window
9392 that will get the subwindow == NULL window */
9393 _gdk_synthesize_crossing_events (display,
9394 display->pointer_info.window_under_pointer,
9396 source_event->crossing.mode,
9397 toplevel_x, toplevel_y,
9403 /* Send subwindow == NULL event */
9404 send_crossing_event (display,
9405 (GdkWindowObject *)toplevel_window,
9406 (GdkWindowObject *)event_window,
9408 source_event->crossing.mode,
9409 source_event->crossing.detail,
9411 toplevel_x, toplevel_y,
9416 _gdk_display_set_window_under_pointer (display, NULL);
9420 pointer_window = get_pointer_window (display, toplevel_window,
9421 toplevel_x, toplevel_y, serial);
9423 if (((source_event->type == GDK_ENTER_NOTIFY &&
9424 source_event->crossing.detail == GDK_NOTIFY_INFERIOR) ||
9425 (source_event->type == GDK_LEAVE_NOTIFY &&
9426 (source_event->crossing.detail == GDK_NOTIFY_VIRTUAL ||
9427 source_event->crossing.detail == GDK_NOTIFY_NONLINEAR_VIRTUAL))) &&
9428 source_event->crossing.subwindow == NULL)
9430 /* Entered from an unknown (to gdk) subwindow */
9432 /* Send subwindow == NULL event */
9433 send_crossing_event (display,
9434 (GdkWindowObject *)toplevel_window,
9435 (GdkWindowObject *)event_window,
9437 source_event->crossing.mode,
9438 source_event->crossing.detail,
9440 toplevel_x, toplevel_y,
9445 /* Send enter events from event window to pointer_window */
9446 _gdk_synthesize_crossing_events (display,
9449 source_event->crossing.mode,
9450 toplevel_x, toplevel_y,
9453 serial, non_linear);
9454 _gdk_display_set_window_under_pointer (display, pointer_window);
9458 if (display->pointer_info.window_under_pointer != pointer_window)
9460 /* Either a toplevel crossing notify that ended up inside a child window,
9461 or a motion notify that got into another child window */
9463 /* Different than last time, send crossing events */
9464 _gdk_synthesize_crossing_events (display,
9465 display->pointer_info.window_under_pointer,
9467 GDK_CROSSING_NORMAL,
9468 toplevel_x, toplevel_y,
9471 serial, non_linear);
9472 _gdk_display_set_window_under_pointer (display, pointer_window);
9474 else if (source_event->type == GDK_MOTION_NOTIFY)
9476 GdkWindow *event_win;
9480 event_win = get_event_window (display,
9490 (evmask & GDK_POINTER_MOTION_HINT_MASK))
9492 if (display->pointer_info.motion_hint_serial != 0 &&
9493 serial < display->pointer_info.motion_hint_serial)
9494 event_win = NULL; /* Ignore event */
9498 display->pointer_info.motion_hint_serial = G_MAXULONG;
9502 if (event_win && !display->ignore_core_events)
9504 event = _gdk_make_event (event_win, GDK_MOTION_NOTIFY, source_event, FALSE);
9505 event->motion.time = time_;
9506 convert_toplevel_coords_to_window (event_win,
9507 toplevel_x, toplevel_y,
9508 &event->motion.x, &event->motion.y);
9509 event->motion.x_root = source_event->motion.x_root;
9510 event->motion.y_root = source_event->motion.y_root;;
9511 event->motion.state = state;
9512 event->motion.is_hint = is_hint;
9513 event->motion.device = NULL;
9514 event->motion.device = source_event->motion.device;
9518 /* unlink all move events from queue.
9519 We handle our own, including our emulated masks. */
9523 #define GDK_ANY_BUTTON_MASK (GDK_BUTTON1_MASK | \
9524 GDK_BUTTON2_MASK | \
9525 GDK_BUTTON3_MASK | \
9526 GDK_BUTTON4_MASK | \
9530 proxy_button_event (GdkEvent *source_event,
9533 GdkWindow *toplevel_window, *event_window;
9534 GdkWindow *event_win;
9535 GdkWindow *pointer_window;
9536 GdkWindowObject *parent;
9541 gdouble toplevel_x, toplevel_y;
9542 GdkDisplay *display;
9545 type = source_event->any.type;
9546 event_window = source_event->any.window;
9547 gdk_event_get_coords (source_event, &toplevel_x, &toplevel_y);
9548 gdk_event_get_state (source_event, &state);
9549 time_ = gdk_event_get_time (source_event);
9550 display = gdk_drawable_get_display (source_event->any.window);
9551 toplevel_window = convert_native_coords_to_toplevel (event_window,
9552 toplevel_x, toplevel_y,
9553 &toplevel_x, &toplevel_y);
9555 if (type == GDK_BUTTON_PRESS &&
9556 _gdk_display_has_pointer_grab (display, serial) == NULL)
9559 _gdk_window_find_descendant_at (toplevel_window,
9560 toplevel_x, toplevel_y,
9563 /* Find the event window, that gets the grab */
9564 w = (GdkWindowObject *)pointer_window;
9566 (parent = get_event_parent (w)) != NULL &&
9567 parent->window_type != GDK_WINDOW_ROOT)
9569 if (w->event_mask & GDK_BUTTON_PRESS_MASK)
9573 pointer_window = (GdkWindow *)w;
9575 _gdk_display_add_pointer_grab (display,
9579 gdk_window_get_events (pointer_window),
9583 _gdk_display_pointer_grab_update (display, serial);
9586 pointer_window = get_pointer_window (display, toplevel_window,
9587 toplevel_x, toplevel_y,
9590 event_win = get_event_window (display,
9595 if (event_win == NULL || display->ignore_core_events)
9598 event = _gdk_make_event (event_win, type, source_event, FALSE);
9602 case GDK_BUTTON_PRESS:
9603 case GDK_BUTTON_RELEASE:
9604 event->button.button = source_event->button.button;
9605 convert_toplevel_coords_to_window (event_win,
9606 toplevel_x, toplevel_y,
9607 &event->button.x, &event->button.y);
9608 event->button.x_root = source_event->button.x_root;
9609 event->button.y_root = source_event->button.y_root;
9610 event->button.state = state;
9611 event->button.device = source_event->button.device;
9613 if (type == GDK_BUTTON_PRESS)
9614 _gdk_event_button_generate (display, event);
9618 event->scroll.direction = source_event->scroll.direction;
9619 convert_toplevel_coords_to_window (event_win,
9620 toplevel_x, toplevel_y,
9621 &event->scroll.x, &event->scroll.y);
9622 event->scroll.x_root = source_event->scroll.x_root;
9623 event->scroll.y_root = source_event->scroll.y_root;
9624 event->scroll.state = state;
9625 event->scroll.device = source_event->scroll.device;
9632 return TRUE; /* Always unlink original, we want to obey the emulated event mask */
9635 #ifdef DEBUG_WINDOW_PRINTING
9637 gdk_window_print (GdkWindowObject *window,
9641 const char *window_types[] = {
9651 g_print ("%*s%p: [%s] %d,%d %dx%d", indent, "", window,
9652 window->user_data ? g_type_name_from_instance (window->user_data) : "no widget",
9653 window->x, window->y,
9654 window->width, window->height
9657 if (gdk_window_has_impl (window))
9659 #ifdef GDK_WINDOWING_X11
9660 g_print (" impl(0x%lx)", gdk_x11_drawable_get_xid (GDK_DRAWABLE (window)));
9664 if (window->window_type != GDK_WINDOW_CHILD)
9665 g_print (" %s", window_types[window->window_type]);
9667 if (window->input_only)
9668 g_print (" input-only");
9671 g_print (" shaped");
9673 if (!gdk_window_is_visible ((GdkWindow *)window))
9674 g_print (" hidden");
9676 g_print (" abs[%d,%d]",
9677 window->abs_x, window->abs_y);
9679 gdk_region_get_clipbox (window->clip_region, &r);
9680 if (gdk_region_empty (window->clip_region))
9681 g_print (" clipbox[empty]");
9683 g_print (" clipbox[%d,%d %dx%d]", r.x, r.y, r.width, r.height);
9690 gdk_window_print_tree (GdkWindow *window,
9692 gboolean include_input_only)
9694 GdkWindowObject *private;
9697 private = (GdkWindowObject *)window;
9699 if (private->input_only && !include_input_only)
9702 gdk_window_print (private, indent);
9704 for (l = private->children; l != NULL; l = l->next)
9705 gdk_window_print_tree (l->data, indent + 4, include_input_only);
9708 #endif /* DEBUG_WINDOW_PRINTING */
9711 is_input_event (GdkDisplay *display,
9714 GdkDevice *core_pointer;
9716 core_pointer = gdk_display_get_core_pointer (display);
9717 if ((event->type == GDK_MOTION_NOTIFY &&
9718 event->motion.device != core_pointer) ||
9719 ((event->type == GDK_BUTTON_PRESS ||
9720 event->type == GDK_BUTTON_RELEASE) &&
9721 event->button.device != core_pointer))
9727 _gdk_windowing_got_event (GdkDisplay *display,
9732 GdkWindow *event_window;
9733 GdkWindowObject *event_private;
9735 gboolean unlink_event;
9736 guint old_state, old_button;
9737 GdkPointerGrabInfo *button_release_grab;
9738 gboolean is_toplevel;
9740 if (gdk_event_get_time (event) != GDK_CURRENT_TIME)
9741 display->last_event_time = gdk_event_get_time (event);
9743 _gdk_display_pointer_grab_update (display,
9746 event_window = event->any.window;
9750 event_private = GDK_WINDOW_OBJECT (event_window);
9752 #ifdef DEBUG_WINDOW_PRINTING
9753 if (event->type == GDK_KEY_PRESS &&
9754 (event->key.keyval == 0xa7 ||
9755 event->key.keyval == 0xbd))
9757 gdk_window_print_tree (event_window, 0,
9758 event->key.keyval == 0xbd);
9762 if (_gdk_native_windows)
9764 if (event->type == GDK_BUTTON_PRESS &&
9765 _gdk_display_has_pointer_grab (display, serial) == NULL)
9767 _gdk_display_add_pointer_grab (display,
9771 gdk_window_get_events (event_window),
9773 gdk_event_get_time (event),
9775 _gdk_display_pointer_grab_update (display,
9778 if (event->type == GDK_BUTTON_RELEASE)
9780 button_release_grab =
9781 _gdk_display_has_pointer_grab (display, serial);
9782 if (button_release_grab &&
9783 button_release_grab->implicit &&
9784 (event->button.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
9786 button_release_grab->serial_end = serial;
9787 button_release_grab->implicit_ungrab = TRUE;
9788 _gdk_display_pointer_grab_update (display, serial);
9792 if (event->type == GDK_BUTTON_PRESS)
9793 _gdk_event_button_generate (display, event);
9798 if (event->type == GDK_VISIBILITY_NOTIFY)
9800 event_private->native_visibility = event->visibility.state;
9801 gdk_window_update_visibility_recursively (event_private,
9806 if (is_input_event (display, event))
9809 if (!(is_button_type (event->type) ||
9810 is_motion_type (event->type)) ||
9811 event_private->window_type == GDK_WINDOW_ROOT)
9815 event_private->parent == NULL ||
9816 event_private->parent->window_type == GDK_WINDOW_ROOT;
9818 if ((event->type == GDK_ENTER_NOTIFY ||
9819 event->type == GDK_LEAVE_NOTIFY) &&
9820 (event->crossing.mode == GDK_CROSSING_GRAB ||
9821 event->crossing.mode == GDK_CROSSING_UNGRAB) &&
9822 (_gdk_display_has_pointer_grab (display, serial) ||
9823 event->crossing.detail == GDK_NOTIFY_INFERIOR))
9825 /* We synthesize all crossing events due to grabs ourselves,
9826 * so we ignore the native ones caused by our native pointer_grab
9827 * calls. Otherwise we would proxy these crossing event and cause
9828 * multiple copies of crossing events for grabs.
9830 * We do want to handle grabs from other clients though, as for
9831 * instance alt-tab in metacity causes grabs like these and
9832 * we want to handle those. Thus the has_pointer_grab check.
9834 * Implicit grabs on child windows create some grabbing events
9835 * that are sent before the button press. This means we can't
9836 * detect these with the has_pointer_grab check (as the implicit
9837 * grab is only noticed when we get button press event), so we
9838 * detect these events by checking for INFERIOR enter or leave
9839 * events. These should never be a problem to filter out.
9842 /* We ended up in this window after some (perhaps other clients)
9843 grab, so update the toplevel_under_window state */
9845 event->type == GDK_ENTER_NOTIFY &&
9846 event->crossing.mode == GDK_CROSSING_UNGRAB)
9848 if (display->pointer_info.toplevel_under_pointer)
9849 g_object_unref (display->pointer_info.toplevel_under_pointer);
9850 display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
9853 unlink_event = TRUE;
9857 /* Track toplevel_under_pointer */
9860 if (event->type == GDK_ENTER_NOTIFY &&
9861 event->crossing.detail != GDK_NOTIFY_INFERIOR)
9863 if (display->pointer_info.toplevel_under_pointer)
9864 g_object_unref (display->pointer_info.toplevel_under_pointer);
9865 display->pointer_info.toplevel_under_pointer = g_object_ref (event_window);
9867 else if (event->type == GDK_LEAVE_NOTIFY &&
9868 event->crossing.detail != GDK_NOTIFY_INFERIOR &&
9869 display->pointer_info.toplevel_under_pointer == event_window)
9871 if (display->pointer_info.toplevel_under_pointer)
9872 g_object_unref (display->pointer_info.toplevel_under_pointer);
9873 display->pointer_info.toplevel_under_pointer = NULL;
9877 /* Store last pointer window and position/state */
9878 old_state = display->pointer_info.state;
9879 old_button = display->pointer_info.button;
9881 gdk_event_get_coords (event, &x, &y);
9882 convert_native_coords_to_toplevel (event_window, x, y, &x, &y);
9883 display->pointer_info.toplevel_x = x;
9884 display->pointer_info.toplevel_y = y;
9885 gdk_event_get_state (event, &display->pointer_info.state);
9886 if (event->type == GDK_BUTTON_PRESS ||
9887 event->type == GDK_BUTTON_RELEASE)
9888 display->pointer_info.button = event->button.button;
9890 if (display->pointer_info.state != old_state ||
9891 display->pointer_info.button != old_button)
9892 _gdk_display_enable_motion_hints (display);
9894 unlink_event = FALSE;
9895 if (is_motion_type (event->type))
9896 unlink_event = proxy_pointer_event (display,
9899 else if (is_button_type (event->type))
9900 unlink_event = proxy_button_event (event,
9903 if (event->type == GDK_BUTTON_RELEASE)
9905 button_release_grab =
9906 _gdk_display_has_pointer_grab (display, serial);
9907 if (button_release_grab &&
9908 button_release_grab->implicit &&
9909 (event->button.state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (event->button.button - 1))) == 0)
9911 button_release_grab->serial_end = serial;
9912 button_release_grab->implicit_ungrab = TRUE;
9913 _gdk_display_pointer_grab_update (display, serial);
9920 _gdk_event_queue_remove_link (display, event_link);
9921 g_list_free_1 (event_link);
9922 gdk_event_free (event);
9928 get_extension_event_window (GdkDisplay *display,
9929 GdkWindow *pointer_window,
9934 GdkWindow *grab_window;
9936 GdkPointerGrabInfo *grab;
9938 grab = _gdk_display_has_pointer_grab (display, serial);
9940 if (grab != NULL && !grab->owner_events)
9942 evmask = grab->event_mask;
9944 grab_window = grab->window;
9946 if (evmask & type_masks[type])
9952 w = (GdkWindowObject *)pointer_window;
9955 evmask = w->extension_events;
9957 if (evmask & type_masks[type])
9958 return (GdkWindow *)w;
9960 w = get_event_parent (w);
9966 evmask = grab->event_mask;
9968 if (evmask & type_masks[type])
9969 return grab->window;
9979 _gdk_window_get_input_window_for_event (GdkWindow *native_window,
9980 GdkEventType event_type,
9984 GdkDisplay *display;
9985 GdkWindow *toplevel_window;
9986 GdkWindow *pointer_window;
9987 GdkWindow *event_win;
9988 gdouble toplevel_x, toplevel_y;
9993 display = gdk_drawable_get_display (native_window);
9994 toplevel_window = convert_native_coords_to_toplevel (native_window,
9995 toplevel_x, toplevel_y,
9996 &toplevel_x, &toplevel_y);
9997 pointer_window = get_pointer_window (display, toplevel_window,
9998 toplevel_x, toplevel_y, serial);
9999 event_win = get_extension_event_window (display,
10008 #define __GDK_WINDOW_C__
10009 #include "gdkaliasdef.c"