[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.
This commit is contained in:
Alexander Larsson 2010-11-16 20:28:54 +01:00
parent f02b7c9ed2
commit db288f3233
3 changed files with 42 additions and 10 deletions

View File

@ -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;
}

View File

@ -53,6 +53,7 @@ struct _GdkDrawableImplBroadway
GdkScreen *screen;
cairo_surface_t *surface;
cairo_surface_t *last_surface;
cairo_surface_t *ref_surface;
};
struct _GdkDrawableImplBroadwayClass

View File

@ -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);