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 Library 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 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library 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-1999. 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"
32 #ifndef USE_BACKING_STORE
33 #ifndef GDK_WINDOWING_WIN32
34 #define USE_BACKING_STORE /* Doesn't work yet on Win32 */
38 typedef struct _GdkWindowPaint GdkWindowPaint;
40 struct _GdkWindowPaint
48 static void gdk_window_draw_destroy (GdkDrawable *drawable);
49 static GdkGC *gdk_window_draw_create_gc (GdkDrawable *drawable,
51 GdkGCValuesMask mask);
52 static void gdk_window_draw_rectangle (GdkDrawable *drawable,
59 static void gdk_window_draw_arc (GdkDrawable *drawable,
68 static void gdk_window_draw_polygon (GdkDrawable *drawable,
73 static void gdk_window_draw_text (GdkDrawable *drawable,
80 static void gdk_window_draw_text_wc (GdkDrawable *drawable,
87 static void gdk_window_draw_drawable (GdkDrawable *drawable,
96 static void gdk_window_draw_points (GdkDrawable *drawable,
100 static void gdk_window_draw_segments (GdkDrawable *drawable,
104 static void gdk_window_draw_lines (GdkDrawable *drawable,
110 /* All drawing operations on windows are forwarded through the following
111 * class to enable the automatic-backing-store feature.
113 GdkDrawableClass _gdk_window_class = {
114 gdk_window_draw_destroy,
115 gdk_window_draw_create_gc,
116 gdk_window_draw_rectangle,
118 gdk_window_draw_polygon,
119 gdk_window_draw_text,
120 gdk_window_draw_text_wc,
121 gdk_window_draw_drawable,
122 gdk_window_draw_points,
123 gdk_window_draw_segments,
124 gdk_window_draw_lines
128 _gdk_window_alloc (void)
130 GdkWindowPrivate *private = g_new (GdkWindowPrivate, 1);
131 GdkWindow *window = (GdkWindow*) private;
133 window->user_data = NULL;
135 private->drawable.ref_count = 1;
136 private->drawable.destroyed = FALSE;
137 private->drawable.klass = NULL;
138 private->drawable.klass_data = NULL;
139 private->drawable.window_type = GDK_WINDOW_CHILD;
141 private->drawable.width = 1;
142 private->drawable.height = 1;
144 private->drawable.colormap = NULL;
146 private->parent = NULL;
149 private->resize_count = 0;
151 private->mapped = FALSE;
152 private->guffaw_gravity = FALSE;
153 private->extension_events = FALSE;
155 private->filters = NULL;
156 private->children = NULL;
158 private->bg_color.pixel = 0;
159 private->bg_color.red = 0;
160 private->bg_color.green = 0;
161 private->bg_color.blue = 0;
163 private->bg_pixmap = NULL;
165 private->paint_stack = NULL;
167 private->update_area = NULL;
168 private->update_freeze_count = 0;
174 gdk_window_set_user_data (GdkWindow *window,
177 g_return_if_fail (window != NULL);
179 window->user_data = user_data;
183 gdk_window_get_user_data (GdkWindow *window,
186 g_return_if_fail (window != NULL);
188 *data = window->user_data;
192 gdk_window_get_position (GdkWindow *window,
196 GdkWindowPrivate *window_private;
198 g_return_if_fail (window != NULL);
199 g_return_if_fail (GDK_IS_WINDOW (window));
201 window_private = (GdkWindowPrivate*) window;
204 *x = window_private->x;
206 *y = window_private->y;
210 gdk_window_get_parent (GdkWindow *window)
212 g_return_val_if_fail (window != NULL, NULL);
213 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
215 return ((GdkWindowPrivate*) window)->parent;
219 gdk_window_get_toplevel (GdkWindow *window)
221 GdkWindowPrivate *private;
223 g_return_val_if_fail (window != NULL, NULL);
224 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
226 private = (GdkWindowPrivate *)window;
227 while (GDK_DRAWABLE_TYPE (private) == GDK_WINDOW_CHILD)
228 private = (GdkWindowPrivate *)private->parent;
230 return (GdkWindow *)window;
234 gdk_window_add_filter (GdkWindow *window,
235 GdkFilterFunc function,
238 GdkWindowPrivate *private;
240 GdkEventFilter *filter;
242 g_return_if_fail (window != NULL);
243 g_return_if_fail (GDK_IS_WINDOW (window));
245 private = (GdkWindowPrivate*) window;
246 if (private && GDK_DRAWABLE_DESTROYED (window))
250 tmp_list = private->filters;
252 tmp_list = gdk_default_filters;
256 filter = (GdkEventFilter *)tmp_list->data;
257 if ((filter->function == function) && (filter->data == data))
259 tmp_list = tmp_list->next;
262 filter = g_new (GdkEventFilter, 1);
263 filter->function = function;
267 private->filters = g_list_append (private->filters, filter);
269 gdk_default_filters = g_list_append (gdk_default_filters, filter);
273 gdk_window_remove_filter (GdkWindow *window,
274 GdkFilterFunc function,
277 GdkWindowPrivate *private;
278 GList *tmp_list, *node;
279 GdkEventFilter *filter;
281 g_return_if_fail (window != NULL);
282 g_return_if_fail (GDK_IS_WINDOW (window));
284 private = (GdkWindowPrivate*) window;
287 tmp_list = private->filters;
289 tmp_list = gdk_default_filters;
293 filter = (GdkEventFilter *)tmp_list->data;
295 tmp_list = tmp_list->next;
297 if ((filter->function == function) && (filter->data == data))
300 private->filters = g_list_remove_link (private->filters, node);
302 gdk_default_filters = g_list_remove_link (gdk_default_filters, node);
303 g_list_free_1 (node);
312 gdk_window_get_toplevels (void)
314 GList *new_list = NULL;
317 tmp_list = ((GdkWindowPrivate *)gdk_parent_root)->children;
320 new_list = g_list_prepend (new_list, tmp_list->data);
321 tmp_list = tmp_list->next;
327 /*************************************************************
328 * gdk_window_is_visible:
329 * Check if the given window is mapped.
333 * is the window mapped
334 *************************************************************/
337 gdk_window_is_visible (GdkWindow *window)
339 GdkWindowPrivate *private = (GdkWindowPrivate *)window;
341 g_return_val_if_fail (window != NULL, FALSE);
342 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
344 return private->mapped;
347 /*************************************************************
348 * gdk_window_is_viewable:
349 * Check if the window and all ancestors of the window
350 * are mapped. (This is not necessarily "viewable" in
351 * the X sense, since we only check as far as we have
352 * GDK window parents, not to the root window)
356 * is the window viewable
357 *************************************************************/
360 gdk_window_is_viewable (GdkWindow *window)
362 GdkWindowPrivate *private = (GdkWindowPrivate *)window;
364 g_return_val_if_fail (window != NULL, FALSE);
365 g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
368 (private != (GdkWindowPrivate *)gdk_parent_root) &&
369 (private->drawable.window_type != GDK_WINDOW_FOREIGN))
371 if (!private->mapped)
374 private = (GdkWindowPrivate *)private->parent;
381 gdk_window_begin_paint_rect (GdkWindow *window,
382 GdkRectangle *rectangle)
386 g_return_if_fail (window != NULL);
387 g_return_if_fail (GDK_IS_WINDOW (window));
389 region = gdk_region_rectangle (rectangle);
390 gdk_window_begin_paint_region (window, region);
391 gdk_region_destroy (region);
395 gdk_window_get_bg_gc (GdkWindow *window, GdkWindowPaint *paint)
397 GdkWindowPrivate *private = (GdkWindowPrivate *)window;
400 GdkGCValues gc_values;
402 if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
404 GdkWindowPaint tmp_paint = *paint;
405 tmp_paint.x_offset += private->x;
406 tmp_paint.y_offset += private->y;
408 return gdk_window_get_bg_gc (private->parent, &tmp_paint);
410 else if (private->bg_pixmap && private->bg_pixmap != GDK_PARENT_RELATIVE_BG && private->bg_pixmap != GDK_NO_BG)
412 gc_values.fill = GDK_TILED;
413 gc_values.tile = private->bg_pixmap;
414 gc_values.ts_x_origin = - paint->x_offset;
415 gc_values.ts_y_origin = - paint->y_offset;
417 gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN;
421 gc_values.foreground = private->bg_color;
422 gc_mask = GDK_GC_FOREGROUND;
425 return gdk_gc_new_with_values (paint->pixmap, &gc_values, gc_mask);
429 gdk_window_paint_init_bg (GdkWindow *window,
430 GdkWindowPaint *paint,
431 GdkRegion *init_region)
435 tmp_gc = gdk_window_get_bg_gc (window, paint);
436 gdk_draw_rectangle (paint->pixmap, tmp_gc, TRUE, 0, 0, -1, -1);
437 gdk_gc_unref (tmp_gc);
441 gdk_window_begin_paint_region (GdkWindow *window,
444 #ifdef USE_BACKING_STORE
445 GdkWindowPrivate *private = (GdkWindowPrivate *)window;
446 GdkRectangle clip_box;
447 GdkWindowPaint *paint;
448 GdkRegion *init_region;
451 g_return_if_fail (window != NULL);
452 g_return_if_fail (GDK_IS_WINDOW (window));
454 paint = g_new (GdkWindowPaint, 1);
456 paint->region = gdk_region_copy (region);
458 init_region = gdk_region_copy (region);
459 gdk_region_get_clipbox (paint->region, &clip_box);
461 if (private->paint_stack)
463 gint old_width, old_height;
464 GdkWindowPaint *tmp_paint = private->paint_stack->data;
465 GdkRectangle old_rect, new_rect;
468 gdk_drawable_get_size (tmp_paint->pixmap, &old_width, &old_height);
469 old_rect.x = tmp_paint->x_offset;
470 old_rect.y = tmp_paint->y_offset;
471 old_rect.width = old_width;
472 old_rect.height = old_height;
474 gdk_rectangle_union (&clip_box, &old_rect, &new_rect);
476 if (new_rect.width > old_rect.width || new_rect.height > old_rect.height)
478 paint->pixmap = gdk_pixmap_new (window, new_rect.width, new_rect.height, -1);
479 tmp_gc = gdk_gc_new (paint->pixmap);
480 gdk_draw_drawable (paint->pixmap, tmp_gc, tmp_paint->pixmap,
481 0, 0, old_rect.width, old_rect.height,
482 old_rect.x - new_rect.x, old_rect.y - new_rect.y);
483 gdk_gc_unref (tmp_gc);
484 gdk_drawable_unref (tmp_paint->pixmap);
486 paint->x_offset = new_rect.x;
487 paint->y_offset = new_rect.y;
489 tmp_list = private->paint_stack;
492 tmp_paint = private->paint_stack->data;
493 gdk_region_subtract (init_region, tmp_paint->region);
495 tmp_paint->pixmap = paint->pixmap;
496 tmp_paint->x_offset = paint->x_offset;
497 tmp_paint->y_offset = paint->x_offset;
499 tmp_list = tmp_list->next;
504 paint->x_offset = tmp_paint->x_offset;
505 paint->y_offset = tmp_paint->y_offset;
506 paint->pixmap = tmp_paint->pixmap;
508 tmp_list = private->paint_stack;
511 tmp_paint = private->paint_stack->data;
512 gdk_region_subtract (init_region, tmp_paint->region);
514 tmp_list = tmp_list->next;
520 paint->x_offset = clip_box.x;
521 paint->y_offset = clip_box.y;
522 paint->pixmap = gdk_pixmap_new (window, clip_box.width, clip_box.height, -1);
525 if (!gdk_region_empty (init_region))
526 gdk_window_paint_init_bg (window, paint, init_region);
527 gdk_region_destroy (init_region);
529 private->paint_stack = g_slist_prepend (private->paint_stack, paint);
530 #endif /* USE_BACKING_STORE */
534 gdk_window_end_paint (GdkWindow *window)
536 #ifdef USE_BACKING_STORE
537 GdkWindowPrivate *private = (GdkWindowPrivate *)window;
538 GdkWindowPaint *paint;
540 GdkRectangle clip_box;
541 gint x_offset, y_offset;
543 g_return_if_fail (window != NULL);
544 g_return_if_fail (GDK_IS_WINDOW (window));
545 g_return_if_fail (private->paint_stack != NULL);
547 paint = private->paint_stack->data;
548 private->paint_stack = g_slist_delete_link (private->paint_stack, private->paint_stack);
550 gdk_region_get_clipbox (paint->region, &clip_box);
552 tmp_gc = gdk_gc_new (window);
554 _gdk_windowing_window_get_offsets (window, &x_offset, &y_offset);
556 gdk_gc_set_clip_region (tmp_gc, paint->region);
557 gdk_gc_set_clip_origin (tmp_gc, -x_offset, -y_offset);
559 _gdk_windowing_window_class.draw_drawable (window, tmp_gc, paint->pixmap,
560 clip_box.x - paint->x_offset,
561 clip_box.y - paint->y_offset,
562 clip_box.x - x_offset, clip_box.y - y_offset,
563 clip_box.width, clip_box.height);
564 gdk_gc_unref (tmp_gc);
566 if (private->paint_stack)
568 GSList *tmp_list = private->paint_stack;
571 GdkWindowPaint *tmp_paint = tmp_list->data;
572 gdk_region_subtract (tmp_paint->region, paint->region);
574 tmp_list = tmp_list->next;
578 gdk_drawable_unref (paint->pixmap);
580 gdk_region_destroy (paint->region);
582 #endif /* USE_BACKING_STORE */
586 gdk_window_get_offsets (GdkWindow *window,
590 GdkWindowPrivate *private = (GdkWindowPrivate *)window;
592 if (private->paint_stack)
594 GdkWindowPaint *paint = private->paint_stack->data;
595 *x_offset = paint->x_offset;
596 *y_offset = paint->y_offset;
599 _gdk_windowing_window_get_offsets (window, x_offset, y_offset);
602 #define OFFSET_GC(gc) \
603 gint x_offset, y_offset; \
604 gint old_clip_x = ((GdkGCPrivate *)gc)->clip_x_origin; \
605 gint old_clip_y = ((GdkGCPrivate *)gc)->clip_y_origin; \
606 gint old_ts_x = ((GdkGCPrivate *)gc)->ts_x_origin; \
607 gint old_ts_y = ((GdkGCPrivate *)gc)->ts_y_origin; \
608 gdk_window_get_offsets (drawable, &x_offset, &y_offset); \
609 if (x_offset != 0 || y_offset != 0) \
611 gdk_gc_set_clip_origin (gc, old_clip_x - x_offset, \
612 old_clip_y - y_offset); \
613 gdk_gc_set_ts_origin (gc, old_ts_x - x_offset, \
614 old_ts_y - y_offset); \
617 #define RESTORE_GC(gc) \
618 if (x_offset != 0 || y_offset != 0) \
620 gdk_gc_set_clip_origin (gc, old_clip_x, old_clip_y); \
621 gdk_gc_set_ts_origin (gc, old_ts_x, old_ts_y); \
625 gdk_window_draw_destroy (GdkDrawable *drawable)
627 _gdk_windowing_window_class.destroy (drawable);
631 gdk_window_draw_create_gc (GdkDrawable *drawable,
633 GdkGCValuesMask mask)
635 return _gdk_windowing_window_class.create_gc (drawable, values, mask);
639 gdk_window_draw_rectangle (GdkDrawable *drawable,
647 GdkWindowPrivate *private = (GdkWindowPrivate *)drawable;
650 if (private->paint_stack)
652 GdkWindowPaint *paint = private->paint_stack->data;
653 gdk_draw_rectangle (paint->pixmap, gc, filled,
654 x - x_offset, y - y_offset, width, height);
657 _gdk_windowing_window_class.draw_rectangle (drawable, gc, filled,
658 x - x_offset, y - y_offset, width, height);
664 gdk_window_draw_arc (GdkDrawable *drawable,
674 GdkWindowPrivate *private = (GdkWindowPrivate *)drawable;
677 if (private->paint_stack)
679 GdkWindowPaint *paint = private->paint_stack->data;
680 gdk_draw_arc (paint->pixmap, gc, filled,
681 x - x_offset, y_offset,
682 width, height, angle1, angle2);
685 _gdk_windowing_window_class.draw_arc (drawable, gc, filled,
686 x - x_offset, y - y_offset,
687 width, height, angle1, angle2);
692 gdk_window_draw_polygon (GdkDrawable *drawable,
698 GdkWindowPrivate *private = (GdkWindowPrivate *)drawable;
699 GdkPoint *new_points;
703 if (x_offset != 0 || y_offset != 0)
707 new_points = g_new (GdkPoint, npoints);
708 for (i=0; i<npoints; i++)
710 new_points[i].x = points[i].x - x_offset;
711 new_points[i].y = points[i].y - y_offset;
717 if (private->paint_stack)
719 GdkWindowPaint *paint = private->paint_stack->data;
720 gdk_draw_polygon (paint->pixmap, gc, filled, new_points, npoints);
724 _gdk_windowing_window_class.draw_polygon (drawable, gc, filled, new_points, npoints);
726 if (new_points != points)
733 gdk_window_draw_text (GdkDrawable *drawable,
741 GdkWindowPrivate *private = (GdkWindowPrivate *)drawable;
744 if (private->paint_stack)
746 GdkWindowPaint *paint = private->paint_stack->data;
747 gdk_draw_text (paint->pixmap, font, gc,
748 x - x_offset, y - y_offset, text, text_length);
752 _gdk_windowing_window_class.draw_text (drawable, font, gc,
753 x - x_offset, y - y_offset, text, text_length);
759 gdk_window_draw_text_wc (GdkDrawable *drawable,
764 const GdkWChar *text,
767 GdkWindowPrivate *private = (GdkWindowPrivate *)drawable;
770 if (private->paint_stack)
772 GdkWindowPaint *paint = private->paint_stack->data;
773 gdk_draw_text_wc (paint->pixmap, font, gc,
774 x - x_offset, y - y_offset, text, text_length);
777 _gdk_windowing_window_class.draw_text_wc (drawable, font, gc,
778 x - x_offset, y - y_offset, text, text_length);
784 gdk_window_draw_drawable (GdkDrawable *drawable,
794 GdkWindowPrivate *private = (GdkWindowPrivate *)drawable;
797 if (private->paint_stack)
799 GdkWindowPaint *paint = private->paint_stack->data;
800 gdk_draw_drawable (paint->pixmap, gc, src, xsrc, ysrc,
801 xdest - x_offset, ydest - y_offset, width, height);
805 _gdk_windowing_window_class.draw_drawable (drawable, gc, src, xsrc, ysrc,
806 xdest - x_offset, ydest - y_offset,
812 gdk_window_draw_points (GdkDrawable *drawable,
817 GdkWindowPrivate *private = (GdkWindowPrivate *)drawable;
818 GdkPoint *new_points;
822 if (x_offset != 0 || y_offset != 0)
826 new_points = g_new (GdkPoint, npoints);
827 for (i=0; i<npoints; i++)
829 new_points[i].x = points[i].x - x_offset;
830 new_points[i].y = points[i].y - y_offset;
836 if (private->paint_stack)
838 GdkWindowPaint *paint = private->paint_stack->data;
839 gdk_draw_points (paint->pixmap, gc, new_points, npoints);
842 _gdk_windowing_window_class.draw_points (drawable, gc, points, npoints);
844 if (new_points != points)
851 gdk_window_draw_segments (GdkDrawable *drawable,
856 GdkWindowPrivate *private = (GdkWindowPrivate *)drawable;
857 GdkSegment *new_segs;
861 if (x_offset != 0 || y_offset != 0)
865 new_segs = g_new (GdkSegment, nsegs);
866 for (i=0; i<nsegs; i++)
868 new_segs[i].x1 = segs[i].x1 - x_offset;
869 new_segs[i].y1 = segs[i].y1 - y_offset;
870 new_segs[i].x2 = segs[i].x2 - x_offset;
871 new_segs[i].y2 = segs[i].y2 - y_offset;
877 if (private->paint_stack)
879 GdkWindowPaint *paint = private->paint_stack->data;
880 gdk_draw_segments (paint->pixmap, gc, new_segs, nsegs);
883 _gdk_windowing_window_class.draw_segments (drawable, gc, new_segs, nsegs);
885 if (new_segs != segs)
892 gdk_window_draw_lines (GdkDrawable *drawable,
897 GdkWindowPrivate *private = (GdkWindowPrivate *)drawable;
898 GdkPoint *new_points;
902 if (x_offset != 0 || y_offset != 0)
906 new_points = g_new (GdkPoint, npoints);
907 for (i=0; i<npoints; i++)
909 new_points[i].x = points[i].x - x_offset;
910 new_points[i].y = points[i].y - y_offset;
916 if (private->paint_stack)
918 GdkWindowPaint *paint = private->paint_stack->data;
919 gdk_draw_lines (paint->pixmap, gc, new_points, npoints);
922 _gdk_windowing_window_class.draw_lines (drawable, gc, new_points, npoints);
924 if (new_points != points)
930 /* Fixme - this is just like gdk_window_paint_init_bg */
932 gdk_window_clear_backing_rect (GdkWindow *window,
938 GdkWindowPrivate *private = (GdkWindowPrivate *)window;
939 GdkWindowPaint *paint = private->paint_stack->data;
942 tmp_gc = gdk_window_get_bg_gc (window, paint);
943 gdk_draw_rectangle (paint->pixmap, tmp_gc, TRUE,
944 x - paint->x_offset, y - paint->y_offset, width, height);
945 gdk_gc_unref (tmp_gc);
949 gdk_window_clear_area (GdkWindow *window,
955 GdkWindowPrivate *private = (GdkWindowPrivate *)window;
957 g_return_if_fail (window != NULL);
958 g_return_if_fail (GDK_IS_WINDOW (window));
960 if (private->paint_stack)
961 gdk_window_clear_backing_rect (window, x, y, width, height);
963 _gdk_windowing_window_clear_area (window, x, y, width, height);
967 gdk_window_clear_area_e (GdkWindow *window,
973 GdkWindowPrivate *private = (GdkWindowPrivate *)window;
975 g_return_if_fail (window != NULL);
976 g_return_if_fail (GDK_IS_WINDOW (window));
978 if (private->paint_stack)
979 gdk_window_clear_backing_rect (window, x, y, width, height);
981 _gdk_windowing_window_clear_area_e (window, x, y, width, height);
985 _gdk_window_draw_image (GdkDrawable *drawable,
995 GdkImagePrivate *image_private = (GdkImagePrivate*) image;
996 GdkWindowPrivate *private = (GdkWindowPrivate *)drawable;
1000 if (private->paint_stack)
1002 GdkWindowPaint *paint = private->paint_stack->data;
1003 image_private->klass->image_put (image, paint->pixmap, gc, xsrc, ysrc,
1004 xdest - x_offset, ydest - y_offset,
1009 image_private->klass->image_put (image, drawable, gc, xsrc, ysrc,
1010 xdest - x_offset, ydest - y_offset,
1016 /* Code for dirty-region queueing
1019 static GSList *update_windows = NULL;
1020 static guint update_idle = 0;
1022 #define GDK_PRIORITY_REDRAW (G_PRIORITY_HIGH_IDLE + 20)
1025 gdk_window_process_updates_internal (GdkWindow *window)
1027 GdkWindowPrivate *private = (GdkWindowPrivate *)window;
1028 gboolean save_region = FALSE;
1033 GdkRectangle window_rect;
1037 window_rect.width = private->drawable.width;
1038 window_rect.height = private->drawable.height;
1040 save_region = _gdk_windowing_window_queue_antiexpose (window, private->update_area);
1042 event.expose.type = GDK_EXPOSE;
1043 event.expose.window = gdk_window_ref ((GdkWindow *)private);
1044 event.expose.count = 0;
1046 gdk_region_get_clipbox (private->update_area, &event.expose.area);
1047 if (gdk_rectangle_intersect (&event.expose.area, &window_rect, &event.expose.area))
1049 (*gdk_event_func) (&event, gdk_event_data);
1054 gdk_region_destroy (private->update_area);
1055 private->update_area = NULL;
1059 gdk_window_process_all_updates (void)
1061 GSList *old_update_windows = update_windows;
1062 GSList *tmp_list = update_windows;
1065 g_source_remove (update_idle);
1067 update_windows = NULL;
1072 gdk_window_process_updates_internal (tmp_list->data);
1073 tmp_list = tmp_list->next;
1076 g_slist_free (old_update_windows);
1082 gdk_window_update_idle (gpointer data)
1084 gdk_window_process_all_updates ();
1090 gdk_window_process_updates (GdkWindow *window,
1091 gboolean update_children)
1093 GdkWindowPrivate *private = (GdkWindowPrivate *)window;
1095 g_return_if_fail (window != NULL);
1096 g_return_if_fail (GDK_IS_WINDOW (window));
1098 if (private->update_area)
1100 gdk_window_process_updates_internal (window);
1101 update_windows = g_slist_remove (update_windows, window);
1104 if (update_children)
1106 GList *tmp_list = private->children;
1109 gdk_window_process_updates (tmp_list->data, TRUE);
1110 tmp_list = tmp_list->next;
1116 gdk_window_invalidate_rect (GdkWindow *window,
1118 gboolean invalidate_children)
1120 GdkWindowPrivate *private = (GdkWindowPrivate *)window;
1122 g_return_if_fail (window != NULL);
1123 g_return_if_fail (GDK_IS_WINDOW (window));
1125 if (private->update_area)
1127 gdk_region_union_with_rect (private->update_area, rect);
1131 update_windows = g_slist_prepend (update_windows, window);
1132 private->update_area = gdk_region_rectangle (rect);
1134 if (!private->update_freeze_count && !update_idle)
1135 update_idle = g_idle_add_full (GDK_PRIORITY_REDRAW,
1136 gdk_window_update_idle, NULL, NULL);
1140 if (invalidate_children)
1143 GdkRectangle child_rect, new_rect;
1145 tmp_list = private->children;
1148 GdkWindowPrivate *child = tmp_list->data;
1149 tmp_list = tmp_list->next;
1151 /* FIXME: this is a HACK to figure out if the child is
1154 if (child->drawable.colormap)
1156 child_rect.x = child->x;
1157 child_rect.y = child->y;
1158 child_rect.width = child->drawable.width;
1159 child_rect.height = child->drawable.height;
1161 if (gdk_rectangle_intersect (rect, &child_rect, &new_rect))
1163 new_rect.x -= child_rect.x;
1164 new_rect.y -= child_rect.y;
1166 gdk_window_invalidate_rect ((GdkWindow *)child, &new_rect, TRUE);
1174 gdk_window_invalidate_region (GdkWindow *window,
1176 gboolean invalidate_children)
1178 GdkWindowPrivate *private = (GdkWindowPrivate *)window;
1180 g_return_if_fail (window != NULL);
1181 g_return_if_fail (GDK_IS_WINDOW (window));
1183 if (private->input_only)
1186 if (private->update_area)
1188 gdk_region_union (private->update_area, region);
1192 update_windows = g_slist_prepend (update_windows, window);
1193 private->update_area = gdk_region_copy (region);
1195 if (!private->update_freeze_count && !update_idle)
1196 update_idle = g_idle_add_full (GDK_PRIORITY_REDRAW,
1197 gdk_window_update_idle, NULL, NULL);
1200 if (invalidate_children)
1203 GdkRectangle child_rect;
1204 GdkRegion *child_region;
1206 tmp_list = private->children;
1209 GdkWindowPrivate *child = tmp_list->data;
1210 tmp_list = tmp_list->next;
1212 if (child->input_only)
1214 child_rect.x = child->x;
1215 child_rect.y = child->y;
1216 child_rect.width = child->drawable.width;
1217 child_rect.height = child->drawable.height;
1219 child_region = gdk_region_rectangle (&child_rect);
1220 gdk_region_intersect (child_region, region);
1222 if (!gdk_region_empty (child_region))
1224 gdk_region_offset (child_region, - child_rect.x, - child_rect.y);
1225 gdk_window_invalidate_region ((GdkWindow *)child, child_region, TRUE);
1228 gdk_region_destroy (child_region);
1235 gdk_window_get_update_area (GdkWindow *window)
1237 GdkWindowPrivate *private = (GdkWindowPrivate *)window;
1238 GdkRegion *tmp_region;
1240 g_return_val_if_fail (window != NULL, NULL);
1241 g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
1243 if (private->update_area)
1245 tmp_region = private->update_area;
1246 private->update_area = NULL;
1248 update_windows = g_slist_remove (update_windows, window);
1257 gdk_window_freeze_updates (GdkWindow *window)
1259 GdkWindowPrivate *private = (GdkWindowPrivate *)window;
1261 g_return_if_fail (window != NULL);
1262 g_return_if_fail (GDK_IS_WINDOW (window));
1264 private->update_freeze_count++;
1268 gdk_window_thaw_updates (GdkWindow *window)
1270 GdkWindowPrivate *private = (GdkWindowPrivate *)window;
1272 g_return_if_fail (window != NULL);
1273 g_return_if_fail (GDK_IS_WINDOW (window));
1274 g_return_if_fail (private->update_freeze_count > 0);
1276 private->update_freeze_count--;
1277 if (!private->update_freeze_count && private->update_area && !update_idle)
1278 update_idle = g_idle_add_full (GDK_PRIORITY_REDRAW,
1279 gdk_window_update_idle, NULL, NULL);