1 /* GDK - The GIMP Drawing Kit
2 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
21 * Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
22 * file for a list of people on the GTK+ Team. See the ChangeLog
23 * files for a list of changes. These files are distributed with
24 * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
27 #include "gdkwindow.h"
28 #include "gdkinternals.h"
29 #include "gdk.h" /* For gdk_rectangle_union() */
30 #include "gdkpixmap.h"
31 #include "gdkdrawable.h"
32 #include "gdkpixmap.h"
34 #define USE_BACKING_STORE /* Appears to work on Win32, too, now. */
36 typedef struct _GdkWindowPaint GdkWindowPaint;
38 struct _GdkWindowPaint
45 static GdkGC *gdk_window_create_gc (GdkDrawable *drawable,
47 GdkGCValuesMask mask);
48 static void gdk_window_draw_rectangle (GdkDrawable *drawable,
55 static void gdk_window_draw_arc (GdkDrawable *drawable,
64 static void gdk_window_draw_polygon (GdkDrawable *drawable,
69 static void gdk_window_draw_text (GdkDrawable *drawable,
76 static void gdk_window_draw_text_wc (GdkDrawable *drawable,
83 static void gdk_window_draw_drawable (GdkDrawable *drawable,
92 static void gdk_window_draw_points (GdkDrawable *drawable,
96 static void gdk_window_draw_segments (GdkDrawable *drawable,
100 static void gdk_window_draw_lines (GdkDrawable *drawable,
104 static void gdk_window_draw_glyphs (GdkDrawable *drawable,
109 PangoGlyphString *glyphs);
111 static void gdk_window_draw_image (GdkDrawable *drawable,
121 static GdkImage* gdk_window_get_image (GdkDrawable *drawable,
128 static void gdk_window_real_get_size (GdkDrawable *drawable,
132 static GdkVisual* gdk_window_real_get_visual (GdkDrawable *drawable);
133 static gint gdk_window_real_get_depth (GdkDrawable *drawable);
134 static void gdk_window_real_set_colormap (GdkDrawable *drawable,
136 static GdkColormap* gdk_window_real_get_colormap (GdkDrawable *drawable);
138 static GdkDrawable* gdk_window_get_composite_drawable (GdkDrawable *drawable,
143 gint *composite_x_offset,
144 gint *composite_y_offset);
145 static GdkRegion* gdk_window_get_clip_region (GdkDrawable *drawable);
146 static GdkRegion* gdk_window_get_visible_region (GdkDrawable *drawable);
148 static void gdk_window_free_paint_stack (GdkWindow *window);
150 static void gdk_window_init (GdkWindowObject *window);
151 static void gdk_window_class_init (GdkWindowObjectClass *klass);
152 static void gdk_window_finalize (GObject *object);
154 static gpointer parent_class = NULL;
157 gdk_window_object_get_type (void)
159 static GType object_type = 0;
163 static const GTypeInfo object_info =
165 sizeof (GdkWindowObjectClass),
166 (GBaseInitFunc) NULL,
167 (GBaseFinalizeFunc) NULL,
168 (GClassInitFunc) gdk_window_class_init,
169 NULL, /* class_finalize */
170 NULL, /* class_data */
171 sizeof (GdkWindowObject),
173 (GInstanceInitFunc) gdk_window_init,
176 object_type = g_type_register_static (GDK_TYPE_DRAWABLE,
185 gdk_window_init (GdkWindowObject *window)
187 /* 0-initialization is good for all other fields. */
189 window->window_type = GDK_WINDOW_CHILD;
191 window->impl = g_object_new (_gdk_window_impl_get_type (), NULL);
195 gdk_window_class_init (GdkWindowObjectClass *klass)
197 GObjectClass *object_class = G_OBJECT_CLASS (klass);
198 GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
200 parent_class = g_type_class_peek_parent (klass);
202 object_class->finalize = gdk_window_finalize;
204 drawable_class->create_gc = gdk_window_create_gc;
205 drawable_class->draw_rectangle = gdk_window_draw_rectangle;
206 drawable_class->draw_arc = gdk_window_draw_arc;
207 drawable_class->draw_polygon = gdk_window_draw_polygon;
208 drawable_class->draw_text = gdk_window_draw_text;
209 drawable_class->draw_text_wc = gdk_window_draw_text_wc;
210 drawable_class->draw_drawable = gdk_window_draw_drawable;
211 drawable_class->draw_points = gdk_window_draw_points;
212 drawable_class->draw_segments = gdk_window_draw_segments;
213 drawable_class->draw_lines = gdk_window_draw_lines;
214 drawable_class->draw_glyphs = gdk_window_draw_glyphs;
215 drawable_class->draw_image = gdk_window_draw_image;
216 drawable_class->get_depth = gdk_window_real_get_depth;
217 drawable_class->get_size = gdk_window_real_get_size;
218 drawable_class->set_colormap = gdk_window_real_set_colormap;
219 drawable_class->get_colormap = gdk_window_real_get_colormap;
220 drawable_class->get_visual = gdk_window_real_get_visual;
221 drawable_class->get_image = gdk_window_get_image;
222 drawable_class->get_clip_region = gdk_window_get_clip_region;
223 drawable_class->get_visible_region = gdk_window_get_visible_region;
224 drawable_class->get_composite_drawable = gdk_window_get_composite_drawable;
228 gdk_window_finalize (GObject *object)
230 GdkWindow *window = GDK_WINDOW (object);
231 GdkWindowObject *obj = (GdkWindowObject *) object;
233 if (!GDK_WINDOW_DESTROYED (window))
235 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
237 g_warning ("losing last reference to undestroyed window\n");
238 _gdk_window_destroy (window, FALSE);
241 /* We use TRUE here, to keep us from actually calling
242 * XDestroyWindow() on the window
244 _gdk_window_destroy (window, TRUE);
247 g_object_unref (G_OBJECT (obj->impl));
250 G_OBJECT_CLASS (parent_class)->finalize (object);
254 * _gdk_window_destroy_hierarchy:
255 * @window: a #GdkWindow
256 * @recursing: If TRUE, then this is being called because a parent
257 * was destroyed. This generally means that the call to the windowing system
258 * to destroy the window can be omitted, since it will be destroyed as a result
259 * of the parent being destroyed. Unless @foreign_destroy
261 * foreign_destroy: If TRUE, the window or a parent was destroyed by some external
262 * agency. The window has already been destroyed and no windowing
263 * system calls should be made. (This may never happen for some
264 * windowing systems.)
266 * Internal function to destroy a window. Like gdk_window_destroy(), but does not
267 * drop the reference count created by gdk_window_new().
270 _gdk_window_destroy_hierarchy (GdkWindow *window,
272 gboolean foreign_destroy)
274 GdkWindowObject *private;
275 GdkWindowObject *temp_private;
276 GdkWindow *temp_window;
280 g_return_if_fail (window != NULL);
282 private = (GdkWindowObject*) window;
284 switch (GDK_WINDOW_TYPE (window))
286 case GDK_WINDOW_TOPLEVEL:
287 case GDK_WINDOW_CHILD:
288 case GDK_WINDOW_DIALOG:
289 case GDK_WINDOW_TEMP:
290 case GDK_WINDOW_FOREIGN:
291 if (!GDK_WINDOW_DESTROYED (window))
293 private->mapped = FALSE;
294 private->destroyed = TRUE;
296 _gdk_windowing_window_destroy (window, recursing, foreign_destroy);
300 GdkWindowObject *parent_private = (GdkWindowObject *)private->parent;
301 if (parent_private->children)
302 parent_private->children = g_list_remove (parent_private->children, window);
305 _gdk_window_clear_update_area (window);
306 gdk_window_free_paint_stack (window);
308 if (private->bg_pixmap &&
309 private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
310 private->bg_pixmap != GDK_NO_BG)
312 gdk_pixmap_unref (private->bg_pixmap);
313 private->bg_pixmap = NULL;
316 if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_FOREIGN)
318 children = tmp = private->children;
319 private->children = NULL;
323 temp_window = tmp->data;
326 temp_private = (GdkWindowObject*) temp_window;
328 _gdk_window_destroy_hierarchy (temp_window, TRUE, foreign_destroy);
331 g_list_free (children);
334 if (private->filters)
336 tmp = private->filters;
344 g_list_free (private->filters);
345 private->filters = NULL;
348 gdk_drawable_set_colormap (GDK_DRAWABLE (window), NULL);
352 case GDK_WINDOW_ROOT:
353 g_error ("attempted to destroy root window");
359 * _gdk_window_destroy:
360 * @window: a #GdkWindow
361 * foreign_destroy: If TRUE, the window or a parent was destroyed by some external
362 * agency. The window has already been destroyed and no windowing
363 * system calls should be made. (This may never happen for some
364 * windowing systems.)
366 * Internal function to destroy a window. Like gdk_window_destroy(), but does not
367 * drop the reference count created by gdk_window_new().
370 _gdk_window_destroy (GdkWindow *window,
371 gboolean foreign_destroy)
373 _gdk_window_destroy_hierarchy (window, FALSE, foreign_destroy);
377 gdk_window_destroy (GdkWindow *window)
379 _gdk_window_destroy_hierarchy (window, FALSE, FALSE);
380 gdk_drawable_unref (window);
384 gdk_window_set_user_data (GdkWindow *window,
387 g_return_if_fail (window != NULL);
389 ((GdkWindowObject*)window)->user_data = user_data;
393 gdk_window_get_user_data (GdkWindow *window,
396 g_return_if_fail (window != NULL);
398 *data = ((GdkWindowObject*)window)->user_data;
402 gdk_window_get_window_type (GdkWindow *window)
404 g_return_val_if_fail (GDK_IS_WINDOW (window), (GdkWindowType) -1);
406 return GDK_WINDOW_TYPE (window);
410 gdk_window_get_position (GdkWindow *window,
414 GdkWindowObject *obj;
416 g_return_if_fail (GDK_IS_WINDOW (window));
418 obj = (GdkWindowObject*) window;
427 gdk_window_get_parent (GdkWindow *window)
429 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
431 return (GdkWindow*) ((GdkWindowObject*) window)->parent;
435 gdk_window_get_toplevel (GdkWindow *window)
437 GdkWindowObject *obj;
439 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
441 obj = (GdkWindowObject *)window;
442 while (GDK_WINDOW_TYPE (obj) == GDK_WINDOW_CHILD)
443 obj = (GdkWindowObject *)obj->parent;
445 return GDK_WINDOW (obj);
449 gdk_window_get_children (GdkWindow *window)
451 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
453 if (GDK_WINDOW_DESTROYED (window))
456 return g_list_copy (GDK_WINDOW_OBJECT (window)->children);
460 gdk_window_peek_children (GdkWindow *window)
462 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
464 if (GDK_WINDOW_DESTROYED (window))
467 return GDK_WINDOW_OBJECT (window)->children;
471 gdk_window_add_filter (GdkWindow *window,
472 GdkFilterFunc function,
475 GdkWindowObject *private;
477 GdkEventFilter *filter;
479 g_return_if_fail (window != NULL);
480 g_return_if_fail (GDK_IS_WINDOW (window));
482 private = (GdkWindowObject*) window;
483 if (private && GDK_WINDOW_DESTROYED (window))
487 tmp_list = private->filters;
489 tmp_list = gdk_default_filters;
493 filter = (GdkEventFilter *)tmp_list->data;
494 if ((filter->function == function) && (filter->data == data))
496 tmp_list = tmp_list->next;
499 filter = g_new (GdkEventFilter, 1);
500 filter->function = function;
504 private->filters = g_list_append (private->filters, filter);
506 gdk_default_filters = g_list_append (gdk_default_filters, filter);
510 gdk_window_remove_filter (GdkWindow *window,
511 GdkFilterFunc function,
514 GdkWindowObject *private;
515 GList *tmp_list, *node;
516 GdkEventFilter *filter;
518 g_return_if_fail (window != NULL);
519 g_return_if_fail (GDK_IS_WINDOW (window));
521 private = (GdkWindowObject*) window;
524 tmp_list = private->filters;
526 tmp_list = gdk_default_filters;
530 filter = (GdkEventFilter *)tmp_list->data;
532 tmp_list = tmp_list->next;
534 if ((filter->function == function) && (filter->data == data))
537 private->filters = g_list_remove_link (private->filters, node);
539 gdk_default_filters = g_list_remove_link (gdk_default_filters, node);
540 g_list_free_1 (node);
549 gdk_window_get_toplevels (void)
551 GList *new_list = NULL;
554 tmp_list = ((GdkWindowObject *)gdk_parent_root)->children;
557 new_list = g_list_prepend (new_list, tmp_list->data);
558 tmp_list = tmp_list->next;
564 /*************************************************************
565 * gdk_window_is_visible:
566 * Check if the given window is mapped.
570 * is the window mapped
571 *************************************************************/
574 gdk_window_is_visible (GdkWindow *window)
576 GdkWindowObject *private = (GdkWindowObject *)window;
578 g_return_val_if_fail (window != NULL, FALSE);
579 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
581 return private->mapped;
584 /*************************************************************
585 * gdk_window_is_viewable:
586 * Check if the window and all ancestors of the window
587 * are mapped. (This is not necessarily "viewable" in
588 * the X sense, since we only check as far as we have
589 * GDK window parents, not to the root window)
593 * is the window viewable
594 *************************************************************/
597 gdk_window_is_viewable (GdkWindow *window)
599 GdkWindowObject *private = (GdkWindowObject *)window;
601 g_return_val_if_fail (window != NULL, FALSE);
602 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
605 (private != (GdkWindowObject *)gdk_parent_root) &&
606 (GDK_WINDOW_TYPE (private) != GDK_WINDOW_FOREIGN))
608 if (!private->mapped)
611 private = (GdkWindowObject *)private->parent;
618 gdk_window_begin_paint_rect (GdkWindow *window,
619 GdkRectangle *rectangle)
623 g_return_if_fail (window != NULL);
624 g_return_if_fail (GDK_IS_WINDOW (window));
626 region = gdk_region_rectangle (rectangle);
627 gdk_window_begin_paint_region (window, region);
628 gdk_region_destroy (region);
632 gdk_window_get_bg_gc (GdkWindow *window, GdkWindowPaint *paint)
634 GdkWindowObject *private = (GdkWindowObject *)window;
637 GdkGCValues gc_values;
639 if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
641 GdkWindowPaint tmp_paint = *paint;
642 tmp_paint.x_offset += private->x;
643 tmp_paint.y_offset += private->y;
645 return gdk_window_get_bg_gc (GDK_WINDOW (private->parent), &tmp_paint);
647 else if (private->bg_pixmap && private->bg_pixmap != GDK_PARENT_RELATIVE_BG && private->bg_pixmap != GDK_NO_BG)
649 gc_values.fill = GDK_TILED;
650 gc_values.tile = private->bg_pixmap;
651 gc_values.ts_x_origin = - paint->x_offset;
652 gc_values.ts_y_origin = - paint->y_offset;
654 gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN;
658 gc_values.foreground = private->bg_color;
659 gc_mask = GDK_GC_FOREGROUND;
662 return gdk_gc_new_with_values (paint->pixmap, &gc_values, gc_mask);
666 gdk_window_paint_init_bg (GdkWindow *window,
667 GdkWindowPaint *paint,
668 GdkRegion *init_region)
672 tmp_gc = gdk_window_get_bg_gc (window, paint);
674 gdk_region_offset (init_region,
677 gdk_gc_set_clip_region (tmp_gc, init_region);
679 gdk_draw_rectangle (paint->pixmap, tmp_gc, TRUE, 0, 0, -1, -1);
680 gdk_gc_unref (tmp_gc);
683 #ifdef GDK_WINDOWING_X11
684 #include "x11/gdkx.h"
688 gdk_window_begin_paint_region (GdkWindow *window,
691 #ifdef USE_BACKING_STORE
692 GdkWindowObject *private = (GdkWindowObject *)window;
693 GdkRectangle clip_box;
694 GdkWindowPaint *paint;
695 GdkRegion *init_region;
698 g_return_if_fail (window != NULL);
699 g_return_if_fail (GDK_IS_WINDOW (window));
701 if (GDK_WINDOW_DESTROYED (window))
704 paint = g_new (GdkWindowPaint, 1);
706 paint->region = gdk_region_copy (region);
708 init_region = gdk_region_copy (region);
709 gdk_region_get_clipbox (paint->region, &clip_box);
711 if (private->paint_stack)
713 gint old_width, old_height;
714 GdkWindowPaint *tmp_paint = private->paint_stack->data;
715 GdkRectangle old_rect, new_rect;
718 gdk_drawable_get_size (tmp_paint->pixmap, &old_width, &old_height);
719 old_rect.x = tmp_paint->x_offset;
720 old_rect.y = tmp_paint->y_offset;
721 old_rect.width = old_width;
722 old_rect.height = old_height;
724 gdk_rectangle_union (&clip_box, &old_rect, &new_rect);
726 if (new_rect.width > old_rect.width || new_rect.height > old_rect.height)
728 paint->pixmap = gdk_pixmap_new (window,
729 new_rect.width, new_rect.height, -1);
730 tmp_gc = gdk_gc_new (paint->pixmap);
731 gdk_draw_drawable (paint->pixmap, tmp_gc, tmp_paint->pixmap,
733 old_rect.x - new_rect.x, old_rect.y - new_rect.y,
734 old_rect.width, old_rect.height);
735 gdk_gc_unref (tmp_gc);
736 gdk_drawable_unref (tmp_paint->pixmap);
738 paint->x_offset = new_rect.x;
739 paint->y_offset = new_rect.y;
741 tmp_list = private->paint_stack;
744 tmp_paint = tmp_list->data;
745 gdk_region_subtract (init_region, tmp_paint->region);
747 tmp_paint->pixmap = paint->pixmap;
748 tmp_paint->x_offset = paint->x_offset;
749 tmp_paint->y_offset = paint->y_offset;
751 tmp_list = tmp_list->next;
756 paint->x_offset = tmp_paint->x_offset;
757 paint->y_offset = tmp_paint->y_offset;
758 paint->pixmap = tmp_paint->pixmap;
760 tmp_list = private->paint_stack;
763 tmp_paint = tmp_list->data;
764 gdk_region_subtract (init_region, tmp_paint->region);
766 tmp_list = tmp_list->next;
772 paint->x_offset = clip_box.x;
773 paint->y_offset = clip_box.y;
774 paint->pixmap = gdk_pixmap_new (window, clip_box.width, clip_box.height, -1);
777 if (!gdk_region_empty (init_region))
778 gdk_window_paint_init_bg (window, paint, init_region);
780 gdk_region_destroy (init_region);
782 private->paint_stack = g_slist_prepend (private->paint_stack, paint);
783 #endif /* USE_BACKING_STORE */
787 gdk_window_end_paint (GdkWindow *window)
789 #ifdef USE_BACKING_STORE
790 GdkWindowObject *private = (GdkWindowObject *)window;
791 GdkWindowPaint *paint;
793 GdkRectangle clip_box;
794 gint x_offset, y_offset;
796 g_return_if_fail (window != NULL);
797 g_return_if_fail (GDK_IS_WINDOW (window));
799 if (GDK_WINDOW_DESTROYED (window))
802 g_return_if_fail (private->paint_stack != NULL);
804 paint = private->paint_stack->data;
805 private->paint_stack = g_slist_delete_link (private->paint_stack, private->paint_stack);
807 gdk_region_get_clipbox (paint->region, &clip_box);
809 tmp_gc = gdk_gc_new (window);
811 _gdk_windowing_window_get_offsets (window, &x_offset, &y_offset);
813 gdk_gc_set_clip_region (tmp_gc, paint->region);
814 gdk_gc_set_clip_origin (tmp_gc, -x_offset, -y_offset);
816 gdk_draw_drawable (private->impl, tmp_gc, paint->pixmap,
817 clip_box.x - paint->x_offset,
818 clip_box.y - paint->y_offset,
819 clip_box.x - x_offset, clip_box.y - y_offset,
820 clip_box.width, clip_box.height);
821 gdk_gc_unref (tmp_gc);
823 if (private->paint_stack)
825 GSList *tmp_list = private->paint_stack;
828 GdkWindowPaint *tmp_paint = tmp_list->data;
829 gdk_region_subtract (tmp_paint->region, paint->region);
831 tmp_list = tmp_list->next;
835 gdk_drawable_unref (paint->pixmap);
837 gdk_region_destroy (paint->region);
839 #endif /* USE_BACKING_STORE */
843 gdk_window_free_paint_stack (GdkWindow *window)
845 GdkWindowObject *private = (GdkWindowObject *)window;
847 if (private->paint_stack)
849 GSList *tmp_list = private->paint_stack;
853 GdkWindowPaint *paint = tmp_list->data;
855 if (tmp_list == private->paint_stack)
856 gdk_drawable_unref (paint->pixmap);
858 gdk_region_destroy (paint->region);
861 tmp_list = tmp_list->next;
864 g_slist_free (private->paint_stack);
865 private->paint_stack = NULL;
870 gdk_window_get_offsets (GdkWindow *window,
874 GdkWindowObject *private = (GdkWindowObject *)window;
876 if (private->paint_stack)
878 GdkWindowPaint *paint = private->paint_stack->data;
879 *x_offset = paint->x_offset;
880 *y_offset = paint->y_offset;
883 _gdk_windowing_window_get_offsets (window, x_offset, y_offset);
886 #define OFFSET_GC(gc) \
887 gint x_offset, y_offset; \
888 gint old_clip_x = gc->clip_x_origin; \
889 gint old_clip_y = gc->clip_y_origin; \
890 gint old_ts_x = gc->ts_x_origin; \
891 gint old_ts_y = gc->ts_y_origin; \
892 gdk_window_get_offsets (drawable, &x_offset, &y_offset); \
893 if (x_offset != 0 || y_offset != 0) \
895 gdk_gc_set_clip_origin (gc, old_clip_x - x_offset, \
896 old_clip_y - y_offset); \
897 gdk_gc_set_ts_origin (gc, old_ts_x - x_offset, \
898 old_ts_y - y_offset); \
901 #define RESTORE_GC(gc) \
902 if (x_offset != 0 || y_offset != 0) \
904 gdk_gc_set_clip_origin (gc, old_clip_x, old_clip_y); \
905 gdk_gc_set_ts_origin (gc, old_ts_x, old_ts_y); \
909 gdk_window_create_gc (GdkDrawable *drawable,
911 GdkGCValuesMask mask)
913 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
915 if (GDK_WINDOW_DESTROYED (drawable))
918 return gdk_gc_new_with_values (((GdkWindowObject *) drawable)->impl,
923 gdk_window_draw_rectangle (GdkDrawable *drawable,
931 GdkWindowObject *private = (GdkWindowObject *)drawable;
934 if (GDK_WINDOW_DESTROYED (drawable))
937 if (private->paint_stack)
939 GdkWindowPaint *paint = private->paint_stack->data;
940 gdk_draw_rectangle (paint->pixmap, gc, filled,
941 x - x_offset, y - y_offset, width, height);
944 gdk_draw_rectangle (private->impl, gc, filled,
945 x - x_offset, y - y_offset, width, height);
951 gdk_window_draw_arc (GdkDrawable *drawable,
961 GdkWindowObject *private = (GdkWindowObject *)drawable;
964 if (GDK_WINDOW_DESTROYED (drawable))
967 if (private->paint_stack)
969 GdkWindowPaint *paint = private->paint_stack->data;
970 gdk_draw_arc (paint->pixmap, gc, filled,
971 x - x_offset, y - y_offset,
972 width, height, angle1, angle2);
975 gdk_draw_arc (private->impl, gc, filled,
976 x - x_offset, y - y_offset,
977 width, height, angle1, angle2);
982 gdk_window_draw_polygon (GdkDrawable *drawable,
988 GdkWindowObject *private = (GdkWindowObject *)drawable;
989 GdkPoint *new_points;
993 if (GDK_WINDOW_DESTROYED (drawable))
996 if (x_offset != 0 || y_offset != 0)
1000 new_points = g_new (GdkPoint, npoints);
1001 for (i=0; i<npoints; i++)
1003 new_points[i].x = points[i].x - x_offset;
1004 new_points[i].y = points[i].y - y_offset;
1008 new_points = points;
1010 if (private->paint_stack)
1012 GdkWindowPaint *paint = private->paint_stack->data;
1013 gdk_draw_polygon (paint->pixmap, gc, filled, new_points, npoints);
1017 gdk_draw_polygon (private->impl, gc, filled, new_points, npoints);
1019 if (new_points != points)
1020 g_free (new_points);
1026 gdk_window_draw_text (GdkDrawable *drawable,
1034 GdkWindowObject *private = (GdkWindowObject *)drawable;
1037 if (GDK_WINDOW_DESTROYED (drawable))
1040 if (private->paint_stack)
1042 GdkWindowPaint *paint = private->paint_stack->data;
1043 gdk_draw_text (paint->pixmap, font, gc,
1044 x - x_offset, y - y_offset, text, text_length);
1048 gdk_draw_text (private->impl, font, gc,
1049 x - x_offset, y - y_offset, text, text_length);
1055 gdk_window_draw_text_wc (GdkDrawable *drawable,
1060 const GdkWChar *text,
1063 GdkWindowObject *private = (GdkWindowObject *)drawable;
1066 if (GDK_WINDOW_DESTROYED (drawable))
1069 if (private->paint_stack)
1071 GdkWindowPaint *paint = private->paint_stack->data;
1072 gdk_draw_text_wc (paint->pixmap, font, gc,
1073 x - x_offset, y - y_offset, text, text_length);
1076 gdk_draw_text_wc (private->impl, font, gc,
1077 x - x_offset, y - y_offset, text, text_length);
1083 gdk_window_get_composite_drawable (GdkDrawable *window,
1088 gint *composite_x_offset,
1089 gint *composite_y_offset)
1091 GdkWindowObject *private = (GdkWindowObject *)window;
1092 GdkWindowPaint *paint;
1093 GdkRegion *buffered_region;
1096 GdkPixmap *tmp_pixmap;
1098 GdkRegion *rect_region;
1100 gint windowing_x_offset, windowing_y_offset;
1101 gint buffer_x_offset, buffer_y_offset;
1103 if (GDK_WINDOW_DESTROYED (window) || private->paint_stack == NULL)
1105 /* No backing store */
1106 _gdk_windowing_window_get_offsets (window,
1108 composite_y_offset);
1110 return GDK_DRAWABLE (g_object_ref (G_OBJECT (window)));
1113 buffered_region = NULL;
1116 /* All GtkWindowPaint structs have the same pixmap and offsets, just
1117 * get the first one. (should probably be cleaned up so that the
1118 * pixmap is stored in the window)
1120 paint = private->paint_stack->data;
1121 buffer = paint->pixmap;
1122 buffer_x_offset = paint->x_offset;
1123 buffer_y_offset = paint->y_offset;
1125 tmp_list = private->paint_stack;
1126 while (tmp_list != NULL)
1128 paint = tmp_list->data;
1130 if (buffered_region == NULL)
1131 buffered_region = gdk_region_copy (paint->region);
1133 gdk_region_union (buffered_region, paint->region);
1135 tmp_list = g_slist_next (tmp_list);
1138 /* See if the buffered part is overlapping the part we want
1144 rect.height = height;
1146 rect_region = gdk_region_rectangle (&rect);
1148 gdk_region_intersect (buffered_region, rect_region);
1150 gdk_region_destroy (rect_region);
1152 if (gdk_region_empty (buffered_region))
1154 gdk_region_destroy (buffered_region);
1156 _gdk_windowing_window_get_offsets (window,
1158 composite_y_offset);
1160 return GDK_DRAWABLE (g_object_ref (G_OBJECT (window)));
1163 tmp_pixmap = gdk_pixmap_new (window,
1167 tmp_gc = gdk_gc_new (tmp_pixmap);
1169 _gdk_windowing_window_get_offsets (window,
1170 &windowing_x_offset,
1171 &windowing_y_offset);
1173 /* Copy the current window contents */
1174 gdk_draw_drawable (tmp_pixmap,
1177 x - windowing_x_offset,
1178 y - windowing_y_offset,
1182 /* Make buffered_region relative to the tmp_pixmap */
1183 gdk_region_offset (buffered_region,
1187 /* Set the clip mask to avoid drawing over non-buffered areas of
1191 gdk_gc_set_clip_region (tmp_gc, buffered_region);
1192 gdk_region_destroy (buffered_region);
1194 /* Draw backing pixmap onto the tmp_pixmap, offsetting
1197 gdk_draw_drawable (tmp_pixmap,
1200 x - buffer_x_offset,
1201 y - buffer_y_offset,
1205 /* Set these to location of tmp_pixmap within the window */
1206 *composite_x_offset = x;
1207 *composite_y_offset = y;
1209 g_object_unref (G_OBJECT (tmp_gc));
1215 gdk_window_get_clip_region (GdkDrawable *drawable)
1217 GdkWindowObject *private = (GdkWindowObject *)drawable;
1220 result = gdk_drawable_get_clip_region (private->impl);
1222 if (private->paint_stack)
1224 GdkRegion *paint_region = gdk_region_new ();
1225 GSList *tmp_list = private->paint_stack;
1229 GdkWindowPaint *paint = tmp_list->data;
1231 gdk_region_union (paint_region, paint->region);
1234 gdk_region_intersect (result, paint_region);
1235 gdk_region_destroy (paint_region);
1242 gdk_window_get_visible_region (GdkDrawable *drawable)
1244 GdkWindowObject *private = (GdkWindowObject*) drawable;
1246 return gdk_drawable_get_visible_region (private->impl);
1250 gdk_window_draw_drawable (GdkDrawable *drawable,
1260 GdkWindowObject *private = (GdkWindowObject *)drawable;
1263 if (GDK_WINDOW_DESTROYED (drawable))
1266 /* If we have a backing pixmap draw to that */
1267 if (private->paint_stack)
1269 GdkWindowPaint *paint = private->paint_stack->data;
1270 gdk_draw_drawable (paint->pixmap, gc,
1272 xdest - x_offset, ydest - y_offset, width, height);
1276 gdk_draw_drawable (private->impl, gc,
1278 xdest - x_offset, ydest - y_offset,
1285 gdk_window_draw_points (GdkDrawable *drawable,
1290 GdkWindowObject *private = (GdkWindowObject *)drawable;
1291 GdkPoint *new_points;
1295 if (GDK_WINDOW_DESTROYED (drawable))
1298 if (x_offset != 0 || y_offset != 0)
1302 new_points = g_new (GdkPoint, npoints);
1303 for (i=0; i<npoints; i++)
1305 new_points[i].x = points[i].x - x_offset;
1306 new_points[i].y = points[i].y - y_offset;
1310 new_points = points;
1312 if (private->paint_stack)
1314 GdkWindowPaint *paint = private->paint_stack->data;
1315 gdk_draw_points (paint->pixmap, gc, new_points, npoints);
1318 gdk_draw_points (private->impl, gc, points, npoints);
1320 if (new_points != points)
1321 g_free (new_points);
1327 gdk_window_draw_segments (GdkDrawable *drawable,
1332 GdkWindowObject *private = (GdkWindowObject *)drawable;
1333 GdkSegment *new_segs;
1337 if (GDK_WINDOW_DESTROYED (drawable))
1340 if (x_offset != 0 || y_offset != 0)
1344 new_segs = g_new (GdkSegment, nsegs);
1345 for (i=0; i<nsegs; i++)
1347 new_segs[i].x1 = segs[i].x1 - x_offset;
1348 new_segs[i].y1 = segs[i].y1 - y_offset;
1349 new_segs[i].x2 = segs[i].x2 - x_offset;
1350 new_segs[i].y2 = segs[i].y2 - y_offset;
1356 if (private->paint_stack)
1358 GdkWindowPaint *paint = private->paint_stack->data;
1359 gdk_draw_segments (paint->pixmap, gc, new_segs, nsegs);
1362 gdk_draw_segments (private->impl, gc, new_segs, nsegs);
1364 if (new_segs != segs)
1371 gdk_window_draw_lines (GdkDrawable *drawable,
1376 GdkWindowObject *private = (GdkWindowObject *)drawable;
1377 GdkPoint *new_points;
1381 if (GDK_WINDOW_DESTROYED (drawable))
1384 if (x_offset != 0 || y_offset != 0)
1388 new_points = g_new (GdkPoint, npoints);
1389 for (i=0; i<npoints; i++)
1391 new_points[i].x = points[i].x - x_offset;
1392 new_points[i].y = points[i].y - y_offset;
1396 new_points = points;
1398 if (private->paint_stack)
1400 GdkWindowPaint *paint = private->paint_stack->data;
1401 gdk_draw_lines (paint->pixmap, gc, new_points, npoints);
1404 gdk_draw_lines (private->impl, gc, new_points, npoints);
1406 if (new_points != points)
1407 g_free (new_points);
1413 gdk_window_draw_glyphs (GdkDrawable *drawable,
1418 PangoGlyphString *glyphs)
1420 GdkWindowObject *private = (GdkWindowObject *)drawable;
1424 if (GDK_WINDOW_DESTROYED (drawable))
1427 if (private->paint_stack)
1429 GdkWindowPaint *paint = private->paint_stack->data;
1431 gdk_draw_glyphs (paint->pixmap, gc, font, x - x_offset, y - y_offset, glyphs);
1434 gdk_draw_glyphs (private->impl, gc, font,
1435 x - x_offset, y - y_offset, glyphs);
1440 /* Fixme - this is just like gdk_window_paint_init_bg */
1442 gdk_window_clear_backing_rect (GdkWindow *window,
1448 GdkWindowObject *private = (GdkWindowObject *)window;
1449 GdkWindowPaint *paint = private->paint_stack->data;
1452 if (GDK_WINDOW_DESTROYED (window))
1455 tmp_gc = gdk_window_get_bg_gc (window, paint);
1456 gdk_draw_rectangle (paint->pixmap, tmp_gc, TRUE,
1457 x - paint->x_offset, y - paint->y_offset, width, height);
1458 gdk_gc_unref (tmp_gc);
1462 gdk_window_clear (GdkWindow *window)
1466 g_return_if_fail (window != NULL);
1467 g_return_if_fail (GDK_IS_WINDOW (window));
1469 gdk_drawable_get_size (GDK_DRAWABLE (window), &width, &height);
1471 gdk_window_clear_area (window, 0, 0,
1476 gdk_window_clear_area (GdkWindow *window,
1482 GdkWindowObject *private = (GdkWindowObject *)window;
1484 g_return_if_fail (window != NULL);
1485 g_return_if_fail (GDK_IS_WINDOW (window));
1487 if (private->paint_stack)
1488 gdk_window_clear_backing_rect (window, x, y, width, height);
1490 _gdk_windowing_window_clear_area (window, x, y, width, height);
1494 gdk_window_clear_area_e (GdkWindow *window,
1500 GdkWindowObject *private = (GdkWindowObject *)window;
1502 g_return_if_fail (window != NULL);
1503 g_return_if_fail (GDK_IS_WINDOW (window));
1505 if (private->paint_stack)
1506 gdk_window_clear_backing_rect (window, x, y, width, height);
1508 _gdk_windowing_window_clear_area_e (window, x, y, width, height);
1512 gdk_window_draw_image (GdkDrawable *drawable,
1522 GdkWindowObject *private = (GdkWindowObject *)drawable;
1526 if (GDK_WINDOW_DESTROYED (drawable))
1529 if (private->paint_stack)
1531 GdkWindowPaint *paint = private->paint_stack->data;
1532 gdk_draw_image (paint->pixmap, gc, image, xsrc, ysrc,
1533 xdest - x_offset, ydest - y_offset,
1538 gdk_draw_image (private->impl, gc, image, xsrc, ysrc,
1539 xdest - x_offset, ydest - y_offset,
1547 gdk_window_real_get_size (GdkDrawable *drawable,
1551 g_return_if_fail (GDK_IS_WINDOW (drawable));
1553 gdk_drawable_get_size (GDK_WINDOW_OBJECT (drawable)->impl,
1558 gdk_window_real_get_visual (GdkDrawable *drawable)
1560 GdkColormap *colormap;
1562 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
1564 colormap = gdk_drawable_get_colormap (drawable);
1565 return colormap ? gdk_colormap_get_visual (colormap) : NULL;
1569 gdk_window_real_get_depth (GdkDrawable *drawable)
1573 g_return_val_if_fail (GDK_IS_WINDOW (drawable), 0);
1575 depth = ((GdkWindowObject *)GDK_WINDOW (drawable))->depth;
1579 g_print ("0 depth for type %s\n", g_type_name (G_OBJECT_TYPE (drawable)));
1587 gdk_window_real_set_colormap (GdkDrawable *drawable,
1590 g_return_if_fail (GDK_IS_WINDOW (drawable));
1592 if (GDK_WINDOW_DESTROYED (drawable))
1595 gdk_drawable_set_colormap (((GdkWindowObject*)drawable)->impl, cmap);
1599 gdk_window_real_get_colormap (GdkDrawable *drawable)
1601 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
1603 if (GDK_WINDOW_DESTROYED (drawable))
1606 return gdk_drawable_get_colormap (((GdkWindowObject*)drawable)->impl);
1610 gdk_window_get_image (GdkDrawable *drawable,
1616 gint x_offset, y_offset;
1618 g_return_val_if_fail (GDK_IS_WINDOW (drawable), NULL);
1620 if (GDK_WINDOW_DESTROYED (drawable))
1623 /* If we're here, a composite image was not necessary, so
1624 * we can ignore the paint stack.
1627 _gdk_windowing_window_get_offsets (drawable, &x_offset, &y_offset);
1629 return gdk_drawable_get_image (((GdkWindowObject*)drawable)->impl,
1635 /* Code for dirty-region queueing
1638 static GSList *update_windows = NULL;
1639 static guint update_idle = 0;
1642 gdk_window_process_updates_internal (GdkWindow *window)
1644 GdkWindowObject *private = (GdkWindowObject *)window;
1645 gboolean save_region = FALSE;
1647 /* If an update got queued during update processing, we can get a
1648 * window in the update queue that has an empty update_area.
1651 if (private->update_area)
1653 GdkRegion *update_area = private->update_area;
1654 private->update_area = NULL;
1656 if (gdk_event_func && gdk_window_is_viewable (window))
1659 GdkRectangle window_rect;
1662 gdk_drawable_get_size (GDK_DRAWABLE (private), &width, &height);
1666 window_rect.width = width;
1667 window_rect.height = height;
1669 save_region = _gdk_windowing_window_queue_antiexpose (window, update_area);
1671 event.expose.type = GDK_EXPOSE;
1672 event.expose.window = gdk_window_ref (window);
1673 event.expose.count = 0;
1675 gdk_region_get_clipbox (update_area, &event.expose.area);
1676 if (gdk_rectangle_intersect (&event.expose.area, &window_rect, &event.expose.area))
1678 (*gdk_event_func) (&event, gdk_event_data);
1681 gdk_window_unref (window);
1685 gdk_region_destroy (update_area);
1690 gdk_window_process_all_updates (void)
1692 GSList *old_update_windows = update_windows;
1693 GSList *tmp_list = update_windows;
1696 g_source_remove (update_idle);
1698 update_windows = NULL;
1703 gdk_window_process_updates_internal (tmp_list->data);
1704 tmp_list = tmp_list->next;
1707 g_slist_free (old_update_windows);
1713 gdk_window_update_idle (gpointer data)
1715 gdk_window_process_all_updates ();
1721 gdk_window_process_updates (GdkWindow *window,
1722 gboolean update_children)
1724 GdkWindowObject *private = (GdkWindowObject *)window;
1726 g_return_if_fail (window != NULL);
1727 g_return_if_fail (GDK_IS_WINDOW (window));
1729 if (private->update_area)
1731 gdk_window_process_updates_internal (window);
1732 update_windows = g_slist_remove (update_windows, window);
1735 if (update_children)
1737 GList *tmp_list = private->children;
1740 gdk_window_process_updates (tmp_list->data, TRUE);
1741 tmp_list = tmp_list->next;
1747 gdk_window_invalidate_rect (GdkWindow *window,
1749 gboolean invalidate_children)
1751 GdkRectangle window_rect;
1753 GdkWindowObject *private = (GdkWindowObject *)window;
1755 g_return_if_fail (window != NULL);
1756 g_return_if_fail (GDK_IS_WINDOW (window));
1758 if (GDK_WINDOW_DESTROYED (window))
1761 if (private->input_only || !private->mapped)
1768 gdk_drawable_get_size (GDK_DRAWABLE (window),
1770 &window_rect.height);
1771 rect = &window_rect;
1774 region = gdk_region_rectangle (rect);
1775 gdk_window_invalidate_region (window, region, invalidate_children);
1776 gdk_region_destroy (region);
1780 gdk_window_invalidate_region (GdkWindow *window,
1782 gboolean invalidate_children)
1784 GdkWindowObject *private = (GdkWindowObject *)window;
1785 GdkRegion *visible_region;
1787 g_return_if_fail (window != NULL);
1788 g_return_if_fail (GDK_IS_WINDOW (window));
1790 if (GDK_WINDOW_DESTROYED (window))
1793 if (private->input_only || !private->mapped)
1796 visible_region = gdk_drawable_get_visible_region (window);
1797 gdk_region_intersect (visible_region, region);
1799 if (!gdk_region_empty (visible_region))
1801 if (private->update_area)
1803 gdk_region_union (private->update_area, visible_region);
1807 update_windows = g_slist_prepend (update_windows, window);
1808 private->update_area = gdk_region_copy (visible_region);
1810 if (!private->update_freeze_count && !update_idle)
1811 update_idle = g_idle_add_full (GDK_PRIORITY_REDRAW,
1812 gdk_window_update_idle, NULL, NULL);
1815 if (invalidate_children)
1819 tmp_list = private->children;
1822 GdkWindowObject *child = tmp_list->data;
1823 tmp_list = tmp_list->next;
1825 if (!child->input_only)
1827 GdkRegion *child_region;
1830 gdk_window_get_position ((GdkWindow *)child, &x, &y);
1832 /* This copy could be saved with a little more complexity */
1833 child_region = gdk_region_copy (visible_region);
1834 gdk_region_offset (child_region, -x, -y);
1836 gdk_window_invalidate_region ((GdkWindow *)child, child_region, TRUE);
1838 gdk_region_destroy (child_region);
1844 gdk_region_destroy (visible_region);
1848 gdk_window_get_update_area (GdkWindow *window)
1850 GdkWindowObject *private = (GdkWindowObject *)window;
1851 GdkRegion *tmp_region;
1853 g_return_val_if_fail (window != NULL, NULL);
1854 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1856 if (private->update_area)
1858 tmp_region = private->update_area;
1859 private->update_area = NULL;
1861 update_windows = g_slist_remove (update_windows, window);
1870 * _gdk_window_clear_update_area:
1871 * @window: a #GdkWindow.
1873 * Internal function to clear the update area for a window. This
1874 * is called when the window is hidden or destroyed.
1877 _gdk_window_clear_update_area (GdkWindow *window)
1879 GdkWindowObject *private = (GdkWindowObject *)window;
1881 g_return_if_fail (window != NULL);
1882 g_return_if_fail (GDK_IS_WINDOW (window));
1884 if (private->update_area)
1886 update_windows = g_slist_remove (update_windows, window);
1888 gdk_region_destroy (private->update_area);
1889 private->update_area = NULL;
1894 gdk_window_freeze_updates (GdkWindow *window)
1896 GdkWindowObject *private = (GdkWindowObject *)window;
1898 g_return_if_fail (window != NULL);
1899 g_return_if_fail (GDK_IS_WINDOW (window));
1901 private->update_freeze_count++;
1905 gdk_window_thaw_updates (GdkWindow *window)
1907 GdkWindowObject *private = (GdkWindowObject *)window;
1909 g_return_if_fail (window != NULL);
1910 g_return_if_fail (GDK_IS_WINDOW (window));
1911 g_return_if_fail (private->update_freeze_count > 0);
1913 private->update_freeze_count--;
1914 if (!private->update_freeze_count && private->update_area && !update_idle)
1915 update_idle = g_idle_add_full (GDK_PRIORITY_REDRAW,
1916 gdk_window_update_idle, NULL, NULL);