summaryrefslogtreecommitdiff
path: root/gdk
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2010-11-16 20:28:54 +0100
committerAlexander Larsson <alexl@redhat.com>2010-11-25 22:09:29 +0100
commitdb288f32339a0a09effceb8b84662da335871b70 (patch)
treec813c4db11b9ae4111c3277896e1077d6c3efb5c /gdk
parentf02b7c9ed209aa680f5735cc814790ec5437fd45 (diff)
downloadgtk+-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.c45
-rw-r--r--gdk/broadway/gdkdrawable-broadway.h1
-rw-r--r--gdk/broadway/gdkwindow-broadway.c6
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);