diff options
author | Alexander Larsson <alexl@redhat.com> | 2010-11-16 20:28:54 +0100 |
---|---|---|
committer | Alexander Larsson <alexl@redhat.com> | 2010-11-25 22:09:29 +0100 |
commit | db288f32339a0a09effceb8b84662da335871b70 (patch) | |
tree | c813c4db11b9ae4111c3277896e1077d6c3efb5c /gdk | |
parent | f02b7c9ed209aa680f5735cc814790ec5437fd45 (diff) | |
download | gtk+-db288f32339a0a09effceb8b84662da335871b70.tar.gz |
[broadway] Ensure gdk_ref_cairo_surface object can be destroyed
If we return a direct ref that is not possible, since we own a ref to it.
This is problematic as the gdkwindow.c code uses destruction to track
outstanding surfaces.
We fix this by returning a subsurface.
Diffstat (limited to 'gdk')
-rw-r--r-- | gdk/broadway/gdkdrawable-broadway.c | 45 | ||||
-rw-r--r-- | gdk/broadway/gdkdrawable-broadway.h | 1 | ||||
-rw-r--r-- | gdk/broadway/gdkwindow-broadway.c | 6 |
3 files changed, 42 insertions, 10 deletions
diff --git a/gdk/broadway/gdkdrawable-broadway.c b/gdk/broadway/gdkdrawable-broadway.c index 8978adfa10..195d9e68bb 100644 --- a/gdk/broadway/gdkdrawable-broadway.c +++ b/gdk/broadway/gdkdrawable-broadway.c @@ -67,11 +67,18 @@ _gdk_broadway_drawable_finish (GdkDrawable *drawable) { GdkDrawableImplBroadway *impl = GDK_DRAWABLE_IMPL_BROADWAY (drawable); + if (impl->ref_surface) + { + cairo_surface_finish (impl->ref_surface); + cairo_surface_set_user_data (impl->ref_surface, &gdk_broadway_cairo_key, + NULL, NULL); + } + if (impl->surface) { - cairo_surface_finish (impl->surface); + cairo_surface_destroy (impl->surface); impl->surface = NULL; - cairo_surface_finish (impl->last_surface); + cairo_surface_destroy (impl->last_surface); impl->last_surface = NULL; } } @@ -103,8 +110,8 @@ _gdk_broadway_drawable_update_size (GdkDrawable *drawable) /* TODO: copy old contents */ - cairo_surface_finish (old); - cairo_surface_finish (last_old); + cairo_surface_destroy (old); + cairo_surface_destroy (last_old); } } @@ -112,6 +119,14 @@ _gdk_broadway_drawable_update_size (GdkDrawable *drawable) * Broadway specific implementations of generic functions * *****************************************************/ +static void +gdk_broadway_cairo_surface_destroy (void *data) +{ + GdkDrawableImplBroadway *impl = data; + + impl->ref_surface = NULL; +} + static cairo_surface_t * gdk_broadway_ref_cairo_surface (GdkDrawable *drawable) { @@ -123,10 +138,12 @@ gdk_broadway_ref_cairo_surface (GdkDrawable *drawable) GDK_WINDOW_DESTROYED (impl->wrapper)) return NULL; + w = gdk_window_get_width (impl->wrapper); + h = gdk_window_get_height (impl->wrapper); + + /* Create actual backing store if missing */ if (!impl->surface) { - w = gdk_window_get_width (impl->wrapper); - h = gdk_window_get_height (impl->wrapper); impl->surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, w, h); impl->last_surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, w, h); @@ -143,5 +160,19 @@ gdk_broadway_ref_cairo_surface (GdkDrawable *drawable) cairo_destroy (cr); } - return cairo_surface_reference (impl->surface); + /* Create a destroyable surface referencing the real one */ + if (!impl->ref_surface) + { + impl->ref_surface = + cairo_surface_create_for_rectangle (impl->surface, + 0, 0, + w, h); + if (impl->ref_surface) + cairo_surface_set_user_data (impl->ref_surface, &gdk_broadway_cairo_key, + drawable, gdk_broadway_cairo_surface_destroy); + } + else + cairo_surface_reference (impl->ref_surface); + + return impl->ref_surface; } diff --git a/gdk/broadway/gdkdrawable-broadway.h b/gdk/broadway/gdkdrawable-broadway.h index 505a530e67..2a5b279879 100644 --- a/gdk/broadway/gdkdrawable-broadway.h +++ b/gdk/broadway/gdkdrawable-broadway.h @@ -53,6 +53,7 @@ struct _GdkDrawableImplBroadway GdkScreen *screen; cairo_surface_t *surface; cairo_surface_t *last_surface; + cairo_surface_t *ref_surface; }; struct _GdkDrawableImplBroadwayClass diff --git a/gdk/broadway/gdkwindow-broadway.c b/gdk/broadway/gdkwindow-broadway.c index 909ad5baac..bd0f74ffb7 100644 --- a/gdk/broadway/gdkwindow-broadway.c +++ b/gdk/broadway/gdkwindow-broadway.c @@ -230,9 +230,9 @@ _gdk_broadway_window_destroy (GdkWindow *window, static cairo_surface_t * gdk_window_broadway_resize_cairo_surface (GdkWindow *window, - cairo_surface_t *surface, - gint width, - gint height) + cairo_surface_t *surface, + gint width, + gint height) { /* Image surfaces cannot be resized */ cairo_surface_destroy (surface); |