* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
+#include <config.h>
#include "gdkwindow.h"
#include "gdkinternals.h"
#include "gdk.h" /* For gdk_rectangle_union() */
#include "gdkdrawable.h"
#include "gdkpixmap.h"
#include "gdkscreen.h"
+#include "gdkalias.h"
#define USE_BACKING_STORE /* Appears to work on Win32, too, now. */
GdkPixmap *pixmap;
gint x_offset;
gint y_offset;
+ cairo_surface_t *surface;
};
static GdkGC *gdk_window_create_gc (GdkDrawable *drawable,
GdkGC *gc,
GdkPoint *points,
gint npoints);
-static void gdk_window_draw_glyphs (GdkDrawable *drawable,
- GdkGC *gc,
- PangoFont *font,
- gint x,
- gint y,
- PangoGlyphString *glyphs);
+
+static void gdk_window_draw_glyphs (GdkDrawable *drawable,
+ GdkGC *gc,
+ PangoFont *font,
+ gint x,
+ gint y,
+ PangoGlyphString *glyphs);
+static void gdk_window_draw_glyphs_transformed (GdkDrawable *drawable,
+ GdkGC *gc,
+ PangoMatrix *matrix,
+ PangoFont *font,
+ gint x,
+ gint y,
+ PangoGlyphString *glyphs);
static void gdk_window_draw_image (GdkDrawable *drawable,
GdkGC *gc,
gint x_dither,
gint y_dither);
+static void gdk_window_draw_trapezoids (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkTrapezoid *trapezoids,
+ gint n_trapezoids);
+
static GdkImage* gdk_window_copy_to_image (GdkDrawable *drawable,
GdkImage *image,
gint src_x,
gint width,
gint height);
+static cairo_surface_t *gdk_window_ref_cairo_surface (GdkDrawable *drawable);
+
static void gdk_window_real_get_size (GdkDrawable *drawable,
gint *width,
gint *height);
static GType object_type = 0;
if (!object_type)
+ object_type = g_type_register_static_simple (GDK_TYPE_DRAWABLE,
+ "GdkWindow",
+ sizeof (GdkWindowObjectClass),
+ (GClassInitFunc) gdk_window_class_init,
+ sizeof (GdkWindowObject),
+ (GInstanceInitFunc) gdk_window_init,
+ 0);
+
+ return object_type;
+}
+
+GType
+_gdk_paintable_get_type (void)
+{
+ static GType paintable_type = 0;
+
+ if (!paintable_type)
{
- static const GTypeInfo object_info =
+ static const GTypeInfo paintable_info =
{
- sizeof (GdkWindowObjectClass),
- (GBaseInitFunc) NULL,
- (GBaseFinalizeFunc) NULL,
- (GClassInitFunc) gdk_window_class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
- sizeof (GdkWindowObject),
- 0, /* n_preallocs */
- (GInstanceInitFunc) gdk_window_init,
+ sizeof (GdkPaintableIface), /* class_size */
+ NULL, /* base_init */
+ NULL, /* base_finalize */
};
-
- object_type = g_type_register_static (GDK_TYPE_DRAWABLE,
- "GdkWindow",
- &object_info, 0);
+
+ paintable_type = g_type_register_static (G_TYPE_INTERFACE,
+ g_intern_static_string ("GdkPaintable"),
+ &paintable_info, 0);
+
+ g_type_interface_add_prerequisite (paintable_type, G_TYPE_OBJECT);
}
-
- return object_type;
+
+ return paintable_type;
}
static void
drawable_class->draw_segments = gdk_window_draw_segments;
drawable_class->draw_lines = gdk_window_draw_lines;
drawable_class->draw_glyphs = gdk_window_draw_glyphs;
+ drawable_class->draw_glyphs_transformed = gdk_window_draw_glyphs_transformed;
drawable_class->draw_image = gdk_window_draw_image;
drawable_class->draw_pixbuf = gdk_window_draw_pixbuf;
+ drawable_class->draw_trapezoids = gdk_window_draw_trapezoids;
drawable_class->get_depth = gdk_window_real_get_depth;
drawable_class->get_screen = gdk_window_real_get_screen;
drawable_class->get_size = gdk_window_real_get_size;
drawable_class->get_colormap = gdk_window_real_get_colormap;
drawable_class->get_visual = gdk_window_real_get_visual;
drawable_class->_copy_to_image = gdk_window_copy_to_image;
+ drawable_class->ref_cairo_surface = gdk_window_ref_cairo_surface;
drawable_class->get_clip_region = gdk_window_get_clip_region;
drawable_class->get_visible_region = gdk_window_get_visible_region;
drawable_class->get_composite_drawable = gdk_window_get_composite_drawable;
G_OBJECT_CLASS (parent_class)->finalize (object);
}
+static void
+window_remove_filters (GdkWindow *window)
+{
+ GdkWindowObject *obj = (GdkWindowObject*) window;
+
+ if (obj->filters)
+ {
+ GList *tmp_list;
+
+ for (tmp_list = obj->filters; tmp_list; tmp_list = tmp_list->next)
+ g_free (tmp_list->data);
+
+ g_list_free (obj->filters);
+ obj->filters = NULL;
+ }
+}
+
/**
* _gdk_window_destroy_hierarchy:
* @window: a #GdkWindow
GdkWindowObject *private;
GdkWindowObject *temp_private;
GdkWindow *temp_window;
+ GdkScreen *screen;
GList *children;
GList *tmp;
private = (GdkWindowObject*) window;
+ if (GDK_WINDOW_DESTROYED (window))
+ return;
+
switch (GDK_WINDOW_TYPE (window))
{
+ case GDK_WINDOW_ROOT:
+ screen = gdk_drawable_get_screen (GDK_DRAWABLE (window));
+ if (!screen->closed)
+ {
+ g_error ("attempted to destroy root window");
+ break;
+ }
+ /* else fall thru */
case GDK_WINDOW_TOPLEVEL:
case GDK_WINDOW_CHILD:
case GDK_WINDOW_DIALOG:
case GDK_WINDOW_TEMP:
case GDK_WINDOW_FOREIGN:
- if (!GDK_WINDOW_DESTROYED (window))
+ if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_FOREIGN && !foreign_destroy)
+ {
+ /* Logically, it probably makes more sense to send
+ * a "destroy yourself" message to the foreign window
+ * whether or not it's in our heirarchy; but for historical
+ * reasons, we only send "destroy yourself" messages to
+ * foreign windows in our heirarchy.
+ */
+ if (private->parent)
+ _gdk_windowing_window_destroy_foreign (window);
+
+ /* Also for historical reasons, we remove any filters
+ * on a foreign window when it or a parent is destroyed;
+ * this likely causes problems if two separate portions
+ * of code are maintaining filter lists on a foreign window.
+ */
+ window_remove_filters (window);
+ }
+ else
{
private->state |= GDK_WINDOW_STATE_WITHDRAWN;
private->parent = NULL;
private->destroyed = TRUE;
- if (private->filters)
- {
- tmp = private->filters;
-
- while (tmp)
- {
- g_free (tmp->data);
- tmp = tmp->next;
- }
-
- g_list_free (private->filters);
- private->filters = NULL;
- }
+ window_remove_filters (window);
gdk_drawable_set_colormap (GDK_DRAWABLE (window), NULL);
}
break;
-
- case GDK_WINDOW_ROOT:
- g_error ("attempted to destroy root window");
- break;
}
}
* gdk_window_get_toplevels:
*
* Obtains a list of all toplevel windows known to GDK on the default
- * screen (see gdk_window_get_toplevels_for_screen()).
+ * screen (see gdk_screen_get_toplevel_windows()).
* A toplevel window is a child of the root window (see
* gdk_get_default_root_window()).
*
(private != (GdkWindowObject *)root_window) &&
(GDK_WINDOW_TYPE (private) != GDK_WINDOW_FOREIGN))
{
- if (GDK_WINDOW_DESTROYED (window) || !GDK_WINDOW_IS_MAPPED (window))
+ if (GDK_WINDOW_DESTROYED (private) || !GDK_WINDOW_IS_MAPPED (private))
return FALSE;
private = (GdkWindowObject *)private->parent;
gdk_region_destroy (region);
}
-static GdkGC *
-gdk_window_get_bg_gc (GdkWindow *window,
- GdkWindowPaint *paint)
-{
- GdkWindowObject *private = (GdkWindowObject *)window;
-
- guint gc_mask = 0;
- GdkGCValues gc_values;
-
- if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
- {
- GdkWindowPaint tmp_paint = *paint;
- tmp_paint.x_offset += private->x;
- tmp_paint.y_offset += private->y;
-
- return gdk_window_get_bg_gc (GDK_WINDOW (private->parent), &tmp_paint);
- }
- else if (private->bg_pixmap &&
- private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
- private->bg_pixmap != GDK_NO_BG)
- {
- gc_values.fill = GDK_TILED;
- gc_values.tile = private->bg_pixmap;
-
- gc_mask = GDK_GC_FILL | GDK_GC_TILE;
- }
- else
- {
- gc_values.foreground = private->bg_color;
- gc_mask = GDK_GC_FOREGROUND;
- }
-
- return gdk_gc_new_with_values (paint->pixmap, &gc_values, gc_mask);
-}
-
#ifdef GDK_WINDOWING_X11
#include "x11/gdkx.h"
#endif
if (GDK_WINDOW_DESTROYED (window))
return;
+ if (GDK_IS_PAINTABLE (private->impl) &&
+ GDK_PAINTABLE_GET_IFACE (private->impl)->begin_paint_region)
+ {
+ GDK_PAINTABLE_GET_IFACE (private->impl)->begin_paint_region (GDK_PAINTABLE (private->impl), region);
+ return;
+ }
+
gdk_region_get_clipbox (region, &clip_box);
paint = g_new (GdkWindowPaint, 1);
gdk_pixmap_new (window,
MAX (clip_box.width, 1), MAX (clip_box.height, 1), -1);
+ paint->surface = _gdk_drawable_ref_cairo_surface (paint->pixmap);
+ cairo_surface_set_device_offset (paint->surface,
+ - paint->x_offset, - paint->y_offset);
+
for (list = private->paint_stack; list != NULL; list = list->next)
{
GdkWindowPaint *tmp_paint = list->data;
if (GDK_WINDOW_DESTROYED (window))
return;
+ if (GDK_IS_PAINTABLE (private->impl) &&
+ GDK_PAINTABLE_GET_IFACE (private->impl)->end_paint)
+ {
+ GDK_PAINTABLE_GET_IFACE (private->impl)->end_paint (GDK_PAINTABLE (private->impl));
+ return;
+ }
+
if (private->paint_stack == NULL)
{
g_warning (G_STRLOC": no preceding call to gdk_window_begin_paint_region(), see documentation");
/* Reset clip region of the cached GdkGC */
gdk_gc_set_clip_region (tmp_gc, NULL);
-
+
+ cairo_surface_destroy (paint->surface);
g_object_unref (paint->pixmap);
gdk_region_destroy (paint->region);
g_free (paint);
RESTORE_GC (gc);
}
+static void
+gdk_window_draw_glyphs_transformed (GdkDrawable *drawable,
+ GdkGC *gc,
+ PangoMatrix *matrix,
+ PangoFont *font,
+ gint x,
+ gint y,
+ PangoGlyphString *glyphs)
+{
+ GdkWindowObject *private = (GdkWindowObject *)drawable;
+ PangoMatrix tmp_matrix;
+
+ OFFSET_GC (gc);
+
+ if (GDK_WINDOW_DESTROYED (drawable))
+ return;
+
+ if (x_offset != 0 || y_offset != 0)
+ {
+ if (matrix)
+ {
+ tmp_matrix = *matrix;
+ tmp_matrix.x0 -= x_offset;
+ tmp_matrix.y0 -= y_offset;
+ matrix = &tmp_matrix;
+ }
+ else
+ {
+ x -= x_offset * PANGO_SCALE;
+ y -= y_offset * PANGO_SCALE;
+ }
+ }
+
+ if (private->paint_stack)
+ {
+ GdkWindowPaint *paint = private->paint_stack->data;
+
+ gdk_draw_glyphs_transformed (paint->pixmap, gc, matrix, font, x, y, glyphs);
+ }
+ else
+ gdk_draw_glyphs_transformed (private->impl, gc, matrix, font, x, y, glyphs);
+
+ RESTORE_GC (gc);
+}
+
+typedef struct {
+ cairo_t *cr; /* if non-null, it means use this cairo context */
+ GdkGC *gc; /* if non-null, it means use this GC instead */
+} BackingRectMethod;
+
+static void
+setup_backing_rect_method (BackingRectMethod *method, GdkWindow *window, GdkWindowPaint *paint, int x_offset_cairo, int y_offset_cairo)
+{
+ GdkWindowObject *private = (GdkWindowObject *)window;
+
+ if (private->bg_pixmap == GDK_PARENT_RELATIVE_BG && private->parent)
+ {
+ GdkWindowPaint tmp_paint;
+
+ tmp_paint = *paint;
+ tmp_paint.x_offset += private->x;
+ tmp_paint.y_offset += private->y;
+
+ x_offset_cairo += private->x;
+ y_offset_cairo += private->y;
+
+ setup_backing_rect_method (method, GDK_WINDOW (private->parent), &tmp_paint, x_offset_cairo, y_offset_cairo);
+ }
+ else if (private->bg_pixmap &&
+ private->bg_pixmap != GDK_PARENT_RELATIVE_BG &&
+ private->bg_pixmap != GDK_NO_BG)
+ {
+/* This is a workaround for https://bugs.freedesktop.org/show_bug.cgi?id=4320.
+ * In it, using a pixmap as a repeating pattern in Cairo, and painting it to a
+ * pixmap destination surface, can be very slow (on the order of seconds for a
+ * whole-screen copy). The workaround is to use pretty much the same code that
+ * we used in GTK+ 2.6 (pre-Cairo), which clears the double-buffer pixmap with
+ * a tiled GC XFillRectangle().
+ */
+
+/* Actually computing this flag is left as an exercise for the reader */
+#if defined (G_OS_UNIX)
+# define GDK_CAIRO_REPEAT_IS_FAST 0
+#else
+# define GDK_CAIRO_REPEAT_IS_FAST 1
+#endif
+
+#if GDK_CAIRO_REPEAT_IS_FAST
+ cairo_surface_t *surface = _gdk_drawable_ref_cairo_surface (private->bg_pixmap);
+ cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
+ cairo_surface_destroy (surface);
+
+ if (x_offset_cairo != 0 || y_offset_cairo != 0)
+ {
+ cairo_matrix_t matrix;
+ cairo_matrix_init_translate (&matrix, x_offset_cairo, y_offset_cairo);
+ cairo_pattern_set_matrix (pattern, &matrix);
+ }
+
+ cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
+
+ method->cr = cairo_create (paint->surface);
+ method->gc = NULL;
+
+ cairo_set_source (method->cr, pattern);
+ cairo_pattern_destroy (pattern);
+#else
+ guint gc_mask;
+ GdkGCValues gc_values;
+
+ gc_values.fill = GDK_TILED;
+ gc_values.tile = private->bg_pixmap;
+ gc_values.ts_x_origin = -x_offset_cairo;
+ gc_values.ts_y_origin = -y_offset_cairo;
+
+ gc_mask = GDK_GC_FILL | GDK_GC_TILE | GDK_GC_TS_X_ORIGIN | GDK_GC_TS_Y_ORIGIN;
+
+ method->gc = gdk_gc_new_with_values (paint->pixmap, &gc_values, gc_mask);
+#endif
+ }
+ else
+ {
+ method->cr = cairo_create (paint->surface);
+
+ gdk_cairo_set_source_color (method->cr, &private->bg_color);
+ }
+}
+
static void
gdk_window_clear_backing_rect (GdkWindow *window,
gint x,
{
GdkWindowObject *private = (GdkWindowObject *)window;
GdkWindowPaint *paint = private->paint_stack->data;
- GdkGC *tmp_gc;
+ BackingRectMethod method;
+#if 0
+ GTimer *timer;
+ double elapsed;
+#endif
if (GDK_WINDOW_DESTROYED (window))
return;
- tmp_gc = gdk_window_get_bg_gc (window, paint);
- gdk_gc_set_clip_region (tmp_gc, paint->region);
-
- gdk_draw_rectangle (window, tmp_gc, TRUE,
- x, y, width, height);
+#if 0
+ timer = g_timer_new ();
+#endif
- g_object_unref (tmp_gc);
+ method.cr = NULL;
+ method.gc = NULL;
+ setup_backing_rect_method (&method, window, paint, 0, 0);
+
+ if (method.cr)
+ {
+ g_assert (method.gc == NULL);
+
+ cairo_rectangle (method.cr, x, y, width, height);
+ cairo_clip (method.cr);
+
+ gdk_cairo_region (method.cr, paint->region);
+ cairo_fill (method.cr);
+
+ cairo_destroy (method.cr);
+#if 0
+ elapsed = g_timer_elapsed (timer, NULL);
+ g_print ("Draw the background with Cairo: %fs\n", elapsed);
+#endif
+ }
+ else
+ {
+ g_assert (method.gc != NULL);
+
+ gdk_gc_set_clip_region (method.gc, paint->region);
+ gdk_draw_rectangle (window, method.gc, TRUE, x, y, width, height);
+ g_object_unref (method.gc);
+
+#if 0
+ elapsed = g_timer_elapsed (timer, NULL);
+ g_print ("Draw the background with GDK: %fs\n", elapsed);
+#endif
+ }
+
+#if 0
+ g_timer_destroy (timer);
+#endif
}
/**
}
}
+static void
+gdk_window_draw_trapezoids (GdkDrawable *drawable,
+ GdkGC *gc,
+ GdkTrapezoid *trapezoids,
+ gint n_trapezoids)
+{
+ GdkWindowObject *private = (GdkWindowObject *)drawable;
+ GdkTrapezoid *new_trapezoids = NULL;
+
+ OFFSET_GC (gc);
+
+ if (GDK_WINDOW_DESTROYED (drawable))
+ return;
+
+ if (x_offset != 0 || y_offset != 0)
+ {
+ gint i;
+
+ new_trapezoids = g_new (GdkTrapezoid, n_trapezoids);
+ for (i=0; i < n_trapezoids; i++)
+ {
+ new_trapezoids[i].y1 = trapezoids[i].y1 - y_offset;
+ new_trapezoids[i].x11 = trapezoids[i].x11 - x_offset;
+ new_trapezoids[i].x21 = trapezoids[i].x21 - x_offset;
+ new_trapezoids[i].y2 = trapezoids[i].y2 - y_offset;
+ new_trapezoids[i].x12 = trapezoids[i].x12 - x_offset;
+ new_trapezoids[i].x22 = trapezoids[i].x22 - x_offset;
+ }
+
+ trapezoids = new_trapezoids;
+ }
+
+ if (private->paint_stack)
+ {
+ GdkWindowPaint *paint = private->paint_stack->data;
+ gdk_draw_trapezoids (paint->pixmap, gc, trapezoids, n_trapezoids);
+ }
+ else
+ gdk_draw_trapezoids (private->impl, gc, trapezoids, n_trapezoids);
+
+ if (new_trapezoids)
+ g_free (new_trapezoids);
+
+ RESTORE_GC (gc);
+}
+
static void
gdk_window_real_get_size (GdkDrawable *drawable,
gint *width,
width, height);
}
+static cairo_surface_t *
+gdk_window_ref_cairo_surface (GdkDrawable *drawable)
+{
+ GdkWindowObject *private = (GdkWindowObject*) drawable;
+ cairo_surface_t *surface;
+
+ if (private->paint_stack)
+ {
+ GdkWindowPaint *paint = private->paint_stack->data;
+
+ surface = paint->surface;
+ cairo_surface_reference (surface);
+ }
+ else
+ surface = _gdk_drawable_ref_cairo_surface (private->impl);
+
+ return surface;
+}
+
/* Code for dirty-region queueing
*/
-
static GSList *update_windows = NULL;
static guint update_idle = 0;
static gboolean debug_updates = FALSE;
+static gboolean
+gdk_window_update_idle (gpointer data)
+{
+ GDK_THREADS_ENTER ();
+ gdk_window_process_all_updates ();
+ GDK_THREADS_LEAVE ();
+
+ return FALSE;
+}
+
+static void
+gdk_window_schedule_update (GdkWindow *window)
+{
+ if (window && GDK_WINDOW_OBJECT (window)->update_freeze_count)
+ return;
+
+ if (!update_idle)
+ {
+ update_idle = g_idle_add_full (GDK_PRIORITY_REDRAW,
+ gdk_window_update_idle, NULL, NULL);
+ }
+}
+
static void
gdk_window_process_updates_internal (GdkWindow *window)
{
GdkRegion *update_area = private->update_area;
private->update_area = NULL;
- if (_gdk_event_func && gdk_window_is_viewable (window) &&
- (private->event_mask & GDK_EXPOSURE_MASK))
+ if (_gdk_event_func && gdk_window_is_viewable (window))
{
- GdkEvent event;
GdkRectangle window_rect;
GdkRegion *expose_region;
GdkRegion *window_region;
g_usleep (70000);
}
- gdk_drawable_get_size (GDK_DRAWABLE (private), &width, &height);
-
- window_rect.x = 0;
- window_rect.y = 0;
- window_rect.width = width;
- window_rect.height = height;
-
save_region = _gdk_windowing_window_queue_antiexpose (window, update_area);
-
- event.expose.type = GDK_EXPOSE;
- event.expose.window = g_object_ref (window);
- event.expose.count = 0;
if (save_region)
expose_region = gdk_region_copy (update_area);
else
expose_region = update_area;
+
+ gdk_drawable_get_size (GDK_DRAWABLE (private), &width, &height);
+
+ window_rect.x = 0;
+ window_rect.y = 0;
+ window_rect.width = width;
+ window_rect.height = height;
+
window_region = gdk_region_rectangle (&window_rect);
gdk_region_intersect (expose_region,
window_region);
gdk_region_destroy (window_region);
- event.expose.region = expose_region;
- gdk_region_get_clipbox (expose_region, &event.expose.area);
-
- if (!gdk_region_empty (expose_region))
+ if (!gdk_region_empty (expose_region) &&
+ (private->event_mask & GDK_EXPOSURE_MASK))
{
+ GdkEvent event;
+
+ event.expose.type = GDK_EXPOSE;
+ event.expose.window = g_object_ref (window);
+ event.expose.send_event = FALSE;
+ event.expose.count = 0;
+ event.expose.region = expose_region;
+ gdk_region_get_clipbox (expose_region, &event.expose.area);
+
(*_gdk_event_func) (&event, _gdk_event_data);
+
+ g_object_unref (window);
}
if (expose_region != update_area)
gdk_region_destroy (expose_region);
- g_object_unref (window);
}
if (!save_region)
gdk_region_destroy (update_area);
g_slist_free (displays);
}
+/* Currently it is not possible to override
+ * gdk_window_process_all_updates in the same manner as
+ * gdk_window_process_updates and gdk_window_invalidate_maybe_recurse
+ * by implementing the GdkPaintable interface. If in the future a
+ * backend would need this, the right solution would be to add a
+ * method to GdkDisplay that can be optionally
+ * NULL. gdk_window_process_all_updates can then walk the list of open
+ * displays and call the mehod.
+ */
+
/**
* gdk_window_process_all_updates:
*
while (tmp_list)
{
- gdk_window_process_updates_internal (tmp_list->data);
+ GdkWindowObject *private = (GdkWindowObject *)tmp_list->data;
+
+ if (private->update_freeze_count)
+ update_windows = g_slist_prepend (update_windows, private);
+ else
+ gdk_window_process_updates_internal (tmp_list->data);
+
g_object_unref (tmp_list->data);
tmp_list = tmp_list->next;
}
flush_all_displays ();
}
-static gboolean
-gdk_window_update_idle (gpointer data)
-{
- GDK_THREADS_ENTER ();
- gdk_window_process_all_updates ();
- GDK_THREADS_LEAVE ();
-
- return FALSE;
-}
-
/**
* gdk_window_process_updates:
* @window: a #GdkWindow
g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
- if (private->update_area)
+ if (GDK_IS_PAINTABLE (private->impl) &&
+ GDK_PAINTABLE_GET_IFACE (private->impl)->process_updates)
+ {
+ GDK_PAINTABLE_GET_IFACE (private->impl)->process_updates (GDK_PAINTABLE (private->impl), update_children);
+ return;
+ }
+
+ if (private->update_area && !private->update_freeze_count)
{
gdk_window_process_updates_internal (window);
update_windows = g_slist_remove (update_windows, window);
{
GdkWindowObject *private = (GdkWindowObject *)window;
GdkRegion *visible_region;
+ GList *tmp_list;
g_return_if_fail (window != NULL);
g_return_if_fail (GDK_IS_WINDOW (window));
if (private->input_only || !GDK_WINDOW_IS_MAPPED (window))
return;
+ if (GDK_IS_PAINTABLE (private->impl) &&
+ GDK_PAINTABLE_GET_IFACE (private->impl)->invalidate_maybe_recurse)
+ {
+ GDK_PAINTABLE_GET_IFACE (private->impl)->invalidate_maybe_recurse (GDK_PAINTABLE (private->impl), region,
+ child_func, user_data);
+ return;
+ }
+
visible_region = gdk_drawable_get_visible_region (window);
gdk_region_intersect (visible_region, region);
+ tmp_list = private->children;
+ while (tmp_list)
+ {
+ GdkWindowObject *child = tmp_list->data;
+
+ if (!child->input_only)
+ {
+ GdkRegion *child_region;
+ GdkRectangle child_rect;
+
+ gdk_window_get_position ((GdkWindow *)child,
+ &child_rect.x, &child_rect.y);
+ gdk_drawable_get_size ((GdkDrawable *)child,
+ &child_rect.width, &child_rect.height);
+
+ child_region = gdk_region_rectangle (&child_rect);
+
+ /* remove child area from the invalid area of the parent */
+ if (GDK_WINDOW_IS_MAPPED (child) && !child->shaped)
+ gdk_region_subtract (visible_region, child_region);
+
+ if (child_func && (*child_func) ((GdkWindow *)child, user_data))
+ {
+ gdk_region_offset (region, - child_rect.x, - child_rect.y);
+ gdk_region_offset (child_region, - child_rect.x, - child_rect.y);
+ gdk_region_intersect (child_region, region);
+
+ gdk_window_invalidate_maybe_recurse ((GdkWindow *)child,
+ child_region, child_func, user_data);
+
+ gdk_region_offset (region, child_rect.x, child_rect.y);
+ }
+
+ gdk_region_destroy (child_region);
+ }
+
+ tmp_list = tmp_list->next;
+ }
+
if (!gdk_region_empty (visible_region))
{
if (debug_updates)
update_windows = g_slist_prepend (update_windows, window);
private->update_area = gdk_region_copy (visible_region);
- if (!private->update_freeze_count && !update_idle)
- update_idle = g_idle_add_full (GDK_PRIORITY_REDRAW,
- gdk_window_update_idle, NULL, NULL);
- }
-
- if (child_func)
- {
- GList *tmp_list;
-
- tmp_list = private->children;
- while (tmp_list)
- {
- GdkWindowObject *child = tmp_list->data;
- tmp_list = tmp_list->next;
-
- if (!child->input_only && (*child_func) ((GdkWindow *)child, user_data))
- {
- GdkRegion *child_region;
- gint x, y;
-
- gdk_window_get_position ((GdkWindow *)child, &x, &y);
-
- /* This copy could be saved with a little more complexity */
- child_region = gdk_region_copy (visible_region);
- gdk_region_offset (child_region, - x, - y);
-
- gdk_window_invalidate_maybe_recurse ((GdkWindow *)child, child_region, child_func, user_data);
-
- gdk_region_destroy (child_region);
- }
- }
+ gdk_window_schedule_update (window);
}
}
g_return_if_fail (GDK_IS_WINDOW (window));
g_return_if_fail (private->update_freeze_count > 0);
- private->update_freeze_count--;
- if (!private->update_freeze_count && private->update_area && !update_idle)
- update_idle = g_idle_add_full (GDK_PRIORITY_REDRAW,
- gdk_window_update_idle, NULL, NULL);
+ if (--private->update_freeze_count == 0)
+ gdk_window_schedule_update (window);
}
/**
* @mask: return location for modifier mask
*
* Obtains the current pointer position and modifier state.
- * The position is given in coordinates relative to @window.
+ * The position is given in coordinates relative to the upper left
+ * corner of @window.
*
* Return value: the window containing the pointer (as with
* gdk_window_at_pointer()), or %NULL if the window containing the
return gdk_window_foreign_new_for_display (gdk_display_get_default (), anid);
}
+#define __GDK_WINDOW_C__
+#include "gdkaliasdef.c"