]> Pileus Git - ~andy/gtk/commitdiff
[broadway] Ensure gdk_ref_cairo_surface object can be destroyed
authorAlexander Larsson <alexl@redhat.com>
Tue, 16 Nov 2010 19:28:54 +0000 (20:28 +0100)
committerAlexander Larsson <alexl@redhat.com>
Thu, 25 Nov 2010 21:09:29 +0000 (22:09 +0100)
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.

gdk/broadway/gdkdrawable-broadway.c
gdk/broadway/gdkdrawable-broadway.h
gdk/broadway/gdkwindow-broadway.c

index 8978adfa10475dfd48284b0463f42ca5b61ecf6a..195d9e68bbbc0fa1a9c47a58f6ca4a0486bd4925 100644 (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;
 }
index 505a530e67bf5a6c0365589eed28252f6bb35c87..2a5b2798794eda6d0d57f2a164d6670631059c81 100644 (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
index 909ad5baacf8c837de11089f22dbf2c290575b6d..bd0f74ffb7169079976e6b76830c13e3029beecc 100644 (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);