From b788fb784c069dc4bdb3a1d40cb507dec9dc4f9d Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Sun, 21 Apr 2013 01:27:07 +0200 Subject: [PATCH] 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. --- gdk/gdkinternals.h | 1 + gdk/gdkwindow.c | 54 ++++++++++++++++++++++++++++++++-------------- gdk/gdkwindow.h | 4 ++++ 3 files changed, 43 insertions(+), 16 deletions(-) diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h index d512220ed8..604a601d71 100644 --- a/gdk/gdkinternals.h +++ b/gdk/gdkinternals.h @@ -266,6 +266,7 @@ struct _GdkWindow guint num_offscreen_children; GdkFrameClock *frame_clock; /* NULL to use from parent or default */ + GdkWindowUpdateHandlerFunc update_handler; }; #define GDK_WINDOW_TYPE(d) (((GDK_WINDOW (d)))->window_type) diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index 3086bb322f..313abc098e 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -3662,6 +3662,13 @@ gdk_window_invalidate_rect (GdkWindow *window, 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 draw_ugly_color (GdkWindow *window, const cairo_region_t *region) @@ -3749,8 +3756,8 @@ gdk_window_invalidate_maybe_recurse_full (GdkWindow *window, GdkWindowChildFunc child_func, gpointer user_data) { - GdkWindow *impl_window; cairo_region_t *visible_region; + cairo_rectangle_int_t r; 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) return; - visible_region = gdk_window_get_visible_region (window); - cairo_region_intersect (visible_region, region); + r.x = 0; + 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); - 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) - draw_ugly_color (window, visible_region); - - /* Convert to impl coords */ - cairo_region_translate (visible_region, window->abs_x, window->abs_y); - - /* Only invalidate area if app requested expose events or if - we need to clear the area (by request or to emulate background - clearing for non-native windows or native windows with no support - for window backgrounds */ - impl_window_add_update_area (impl_window, visible_region); + if (gdk_window_has_impl (window)) + { + impl_window_add_update_area (window, visible_region); + break; + } + else + { + if (window->update_handler) + { + if (!window->update_handler (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); diff --git a/gdk/gdkwindow.h b/gdk/gdkwindow.h index d2ee972cbb..81d325a7c1 100644 --- a/gdk/gdkwindow.h +++ b/gdk/gdkwindow.h @@ -633,6 +633,10 @@ gboolean gdk_window_set_static_gravities (GdkWindow *window, gboolean use_static); /* 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); void gdk_window_set_type_hint (GdkWindow *window,