Add gdk_window_set_update_handler

This lets you register callbacks for when child widgets invalidate
areas of the window read it and/or change it.

For instance, this lets you do rendering effects and keeping offscreen
caches uptodate.
This commit is contained in:
Alexander Larsson
2013-04-21 01:27:07 +02:00
parent b8d3b98416
commit 8251523e1d
3 changed files with 43 additions and 16 deletions

View File

@@ -266,6 +266,7 @@ struct _GdkWindow
guint num_offscreen_children; guint num_offscreen_children;
GdkFrameClock *frame_clock; /* NULL to use from parent or default */ GdkFrameClock *frame_clock; /* NULL to use from parent or default */
GdkWindowUpdateHandlerFunc update_handler;
}; };
#define GDK_WINDOW_TYPE(d) (((GDK_WINDOW (d)))->window_type) #define GDK_WINDOW_TYPE(d) (((GDK_WINDOW (d)))->window_type)

View File

@@ -3662,6 +3662,13 @@ gdk_window_invalidate_rect (GdkWindow *window,
gdk_window_invalidate_rect_full (window, rect, invalidate_children); gdk_window_invalidate_rect_full (window, rect, invalidate_children);
} }
void
gdk_window_set_update_handler (GdkWindow *window,
GdkWindowUpdateHandlerFunc handler)
{
window->update_handler = handler;
}
static void static void
draw_ugly_color (GdkWindow *window, draw_ugly_color (GdkWindow *window,
const cairo_region_t *region) const cairo_region_t *region)
@@ -3749,8 +3756,8 @@ gdk_window_invalidate_maybe_recurse_full (GdkWindow *window,
GdkWindowChildFunc child_func, GdkWindowChildFunc child_func,
gpointer user_data) gpointer user_data)
{ {
GdkWindow *impl_window;
cairo_region_t *visible_region; cairo_region_t *visible_region;
cairo_rectangle_int_t r;
g_return_if_fail (GDK_IS_WINDOW (window)); g_return_if_fail (GDK_IS_WINDOW (window));
@@ -3763,26 +3770,41 @@ gdk_window_invalidate_maybe_recurse_full (GdkWindow *window,
window->window_type == GDK_WINDOW_ROOT) window->window_type == GDK_WINDOW_ROOT)
return; return;
visible_region = gdk_window_get_visible_region (window); r.x = 0;
cairo_region_intersect (visible_region, region); r.y = 0;
r.width = window->width;
r.height = window->height;
visible_region = cairo_region_copy (region);
cairo_region_intersect_rectangle (visible_region, &r);
invalidate_impl_subwindows (window, region, child_func, user_data, 0, 0); invalidate_impl_subwindows (window, region, child_func, user_data, 0, 0);
impl_window = gdk_window_get_impl_window (window); if (debug_updates)
draw_ugly_color (window, visible_region);
if (!cairo_region_is_empty (visible_region)) while (window != NULL &&
!cairo_region_is_empty (visible_region))
{ {
if (debug_updates) if (gdk_window_has_impl (window))
draw_ugly_color (window, visible_region); {
impl_window_add_update_area (window, visible_region);
/* Convert to impl coords */ break;
cairo_region_translate (visible_region, window->abs_x, window->abs_y); }
else
/* Only invalidate area if app requested expose events or if {
we need to clear the area (by request or to emulate background if (window->update_handler)
clearing for non-native windows or native windows with no support {
for window backgrounds */ if (!window->update_handler (window, visible_region))
impl_window_add_update_area (impl_window, visible_region); break;
}
cairo_region_translate (visible_region,
window->x, window->y);
window = window->parent;
r.width = window->width;
r.height = window->height;
cairo_region_intersect_rectangle (visible_region, &r);
}
} }
cairo_region_destroy (visible_region); cairo_region_destroy (visible_region);

View File

@@ -633,6 +633,10 @@ gboolean gdk_window_set_static_gravities (GdkWindow *window,
gboolean use_static); gboolean use_static);
/* GdkWindow */ /* GdkWindow */
typedef gboolean (*GdkWindowUpdateHandlerFunc) (GdkWindow *window,
cairo_region_t *region);
void gdk_window_set_update_handler (GdkWindow *window,
GdkWindowUpdateHandlerFunc handler);
gboolean gdk_window_has_native (GdkWindow *window); gboolean gdk_window_has_native (GdkWindow *window);
void gdk_window_set_type_hint (GdkWindow *window, void gdk_window_set_type_hint (GdkWindow *window,