Update for the new quartz cairo surface API (#410442). Don't lock focus
authorRichard Hult <richard@imendio.com>
Sat, 10 Mar 2007 21:58:49 +0000 (21:58 +0000)
committerRichard Hult <rhult@src.gnome.org>
Sat, 10 Mar 2007 21:58:49 +0000 (21:58 +0000)
2007-03-10  Richard Hult  <richard@imendio.com>

* gdk/quartz/gdkdrawable-quartz.c:
(gdk_quartz_drawable_get_context): Update for the new quartz cairo
surface API (#410442). Don't lock focus unless called outside of an
expose event.
(gdk_quartz_drawable_release_context): Only flush the CG context and
unlock focus if called outside of expose.
(gdk_quartz_ref_cairo_surface): Reuse the surface during its lifetime.
(_gdk_quartz_drawable_finish): New function, used to free the cached
cairo surface.

* gdk/quartz/gdkwindow-quartz.c:
(gdk_window_impl_quartz_begin_paint_region): A few small style changes.
(gdk_window_quartz_process_all_updates): Move the autorelease pool
allocation and freeing outside the loop.
(_gdk_windowing_window_destroy): Finish the drawable.
(move_resize_window_internal): Small cleanup and remove comment.
(_gdk_window_impl_quartz_get_type): No need to make the type info
static.

* gdk/quartz/gdkpixmap-quartz.c: Finish the drawable.

svn path=/trunk/; revision=17463

ChangeLog
gdk/quartz/gdkdrawable-quartz.c
gdk/quartz/gdkdrawable-quartz.h
gdk/quartz/gdkpixmap-quartz.c
gdk/quartz/gdkprivate-quartz.h
gdk/quartz/gdkwindow-quartz.c

index 73590f45a12fd9ccfaba23c97d8a3ac2ad3f0019..4aa766515edcc4cd35f3291f707f719dfd8e1651 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,26 @@
+2007-03-10  Richard Hult  <richard@imendio.com>
+
+       * gdk/quartz/gdkdrawable-quartz.c:
+       (gdk_quartz_ref_cairo_surface): Reuse the surface during its lifetime.
+       (gdk_quartz_drawable_get_context): Update for the new quartz cairo 
+       surface API (#410442). Don't lock focus unless called outside of an 
+       expose event.
+       (gdk_quartz_drawable_release_context): Only flush the CG context and 
+       unlock focus if called outside of expose.
+       (_gdk_quartz_drawable_finish): New function, used to free the cached
+       cairo surface.
+
+       * gdk/quartz/gdkwindow-quartz.c:
+       (gdk_window_impl_quartz_begin_paint_region): A few small style changes.
+       (_gdk_window_impl_quartz_get_type): No need to make the type info
+       static.
+       (gdk_window_quartz_process_all_updates): Move the autorelease pool
+       allocation and freeing outside the loop.
+       (_gdk_windowing_window_destroy): Finish the drawable.
+       (move_resize_window_internal): Small cleanup and remove comment.
+
+       * gdk/quartz/gdkpixmap-quartz.c: Finish the drawable.
+
 2007-03-10  Richard Hult  <richard@imendio.com>
 
        * gdk/quartz/gdkprivate-quartz.h: Add missing function signature to fix
index 030f68362e186e33edab456bb8e3eb10c7190ec5..5b2a4da1959820d9b288ed48be63a9a2511cf623 100644 (file)
@@ -1,6 +1,6 @@
 /* gdkdrawable-quartz.c
  *
- * Copyright (C) 2005, 2006 Imendio AB
+ * Copyright (C) 2005-2007 Imendio AB
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
  */
 
 #include <config.h>
-
 #include <cairo-quartz.h>
 #include "gdkprivate-quartz.h"
 
 static gpointer parent_class;
 
-typedef struct {
-  GdkDrawable *drawable;
-  CGContextRef context;
-} SurfaceInfo;
+static cairo_user_data_key_t gdk_quartz_cairo_key;
 
-static cairo_user_data_key_t surface_info_key;
+typedef struct {
+  GdkDrawable  *drawable;
+  CGContextRef  cg_context;
+} GdkQuartzCairoSurfaceData;
 
 static void
-surface_info_destroy (void *data)
+gdk_quartz_cairo_surface_destroy (void *data)
 {
-  SurfaceInfo *info = data;
+  GdkQuartzCairoSurfaceData *surface_data = data;
+  GdkDrawableImplQuartz *impl = GDK_DRAWABLE_IMPL_QUARTZ (surface_data->drawable);
 
-  gdk_quartz_drawable_release_context (info->drawable, info->context);
+  gdk_quartz_drawable_release_context (surface_data->drawable, 
+                                      surface_data->cg_context);
 
-  g_free (info);
+  impl->cairo_surface = NULL;
+
+  g_free (surface_data);
 }
 
 static cairo_surface_t *
 gdk_quartz_ref_cairo_surface (GdkDrawable *drawable)
 {
   GdkDrawableImplQuartz *impl = GDK_DRAWABLE_IMPL_QUARTZ (drawable);
-  CGContextRef context;
-  int width, height;
-  cairo_surface_t *surface;
-  SurfaceInfo *info;
 
   if (GDK_IS_WINDOW_IMPL_QUARTZ (drawable) &&
       GDK_WINDOW_DESTROYED (impl->wrapper))
     return NULL;
 
-  context = gdk_quartz_drawable_get_context (drawable, TRUE);
-  if (!context)
-    return NULL;
+  if (!impl->cairo_surface)
+    {
+      CGContextRef cg_context;
+      int width, height;
+      GdkQuartzCairoSurfaceData *surface_data;
+
+      cg_context = gdk_quartz_drawable_get_context (drawable, TRUE);
+      if (!cg_context)
+       return NULL;
+
+      gdk_drawable_get_size (drawable, &width, &height);
 
-  gdk_drawable_get_size (drawable, &width, &height);
+      impl->cairo_surface = cairo_quartz_surface_create_for_cg_context (cg_context, width, height);
 
-  surface = cairo_quartz_surface_create (context, width, height, TRUE);
+      surface_data = g_new (GdkQuartzCairoSurfaceData, 1);
+      surface_data->drawable = drawable;
+      surface_data->cg_context = cg_context;
 
-  info = g_new (SurfaceInfo, 1);
-  info->drawable = drawable;
-  info->context = context;
+      cairo_surface_set_user_data (impl->cairo_surface, &gdk_quartz_cairo_key,
+                                  surface_data, gdk_quartz_cairo_surface_destroy);
+    }
+  else
+    cairo_surface_reference (impl->cairo_surface);
 
-  cairo_surface_set_user_data (surface, &surface_info_key,
-                              info, surface_info_destroy);
-  return surface;
+  return impl->cairo_surface;
 }
 
 static void
@@ -588,33 +597,47 @@ CGContextRef
 gdk_quartz_drawable_get_context (GdkDrawable *drawable,
                                 gboolean     antialias)
 {
-  if (GDK_IS_WINDOW_IMPL_QUARTZ (drawable))
-    {
-      GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (drawable);
-      CGContextRef context;
+  GdkDrawableImplQuartz *drawable_impl = GDK_DRAWABLE_IMPL_QUARTZ (drawable);
 
-      impl->pool = [[NSAutoreleasePool alloc] init];
+  if (GDK_IS_WINDOW_IMPL_QUARTZ (drawable) &&
+      GDK_WINDOW_DESTROYED (drawable_impl->wrapper))
+    return NULL;
 
-      if (![impl->view lockFocusIfCanDraw])
+  CGContextRef cg_context;
+  
+  if (GDK_IS_WINDOW_IMPL_QUARTZ (drawable))
+    {
+      GdkWindowImplQuartz *window_impl = GDK_WINDOW_IMPL_QUARTZ (drawable);
+         
+      /* Lock focus when not called as part of begin/end paint cycle. 
+       * This is needed to allow broken apps that draw outside of expose
+       * to still work (somewhat). 
+       */
+      if (window_impl->begin_paint_count == 0)
        {
-         [impl->pool release];
-         return NULL;
-       }
-
-      context = [[NSGraphicsContext currentContext] graphicsPort];
+         window_impl->pool = [[NSAutoreleasePool alloc] init];
+         if (![window_impl->view lockFocusIfCanDraw])
+           {
+             [window_impl->pool release];
+             window_impl->pool = NULL;
 
-      CGContextSaveGState (context);
-      CGContextSetAllowsAntialiasing (context, antialias);
+             return NULL;
+           }
+       }
 
+      cg_context = [[NSGraphicsContext currentContext] graphicsPort];
+      CGContextSaveGState (cg_context);
+      CGContextSetAllowsAntialiasing (cg_context, antialias);
+         
       /* We'll emulate the clipping caused by double buffering here */
-      if (impl->begin_paint_count != 0)
+      if (window_impl->begin_paint_count != 0)
        {
          CGRect rect;
          CGRect *cg_rects;
          GdkRectangle *rects;
          gint n_rects, i;
          
-         gdk_region_get_rectangles (impl->paint_clip_region,
+         gdk_region_get_rectangles (window_impl->paint_clip_region,
                                     &rects, &n_rects);
          
          if (n_rects == 1)
@@ -630,60 +653,75 @@ gdk_quartz_drawable_get_context (GdkDrawable *drawable,
              cg_rects[i].size.height = rects[i].height;
            }
          
-         CGContextClipToRects (context, cg_rects, n_rects);
+         CGContextClipToRects (cg_context, cg_rects, n_rects);
          
          g_free (rects);
          if (cg_rects != &rect)
            g_free (cg_rects);
        }
-      
-      return context;
     }
   else if (GDK_IS_PIXMAP_IMPL_QUARTZ (drawable))
     {
       GdkPixmapImplQuartz *impl = GDK_PIXMAP_IMPL_QUARTZ (drawable);
-      CGContextRef context;
-
-      context = CGBitmapContextCreate (impl->data,
-                                      CGImageGetWidth (impl->image),
-                                      CGImageGetHeight (impl->image),
-                                      CGImageGetBitsPerComponent (impl->image),
-                                      CGImageGetBytesPerRow (impl->image),
-                                      CGImageGetColorSpace (impl->image),
-                                      CGImageGetBitmapInfo (impl->image));
-      CGContextSetAllowsAntialiasing (context, antialias);
       
-      return context;
+      cg_context = CGBitmapContextCreate (impl->data,
+                                         CGImageGetWidth (impl->image),
+                                         CGImageGetHeight (impl->image),
+                                         CGImageGetBitsPerComponent (impl->image),
+                                         CGImageGetBytesPerRow (impl->image),
+                                         CGImageGetColorSpace (impl->image),
+                                         CGImageGetBitmapInfo (impl->image));
+      CGContextSetAllowsAntialiasing (cg_context, antialias);
+    }
+  else 
+    {
+      g_warning ("Tried to create CGContext for something not a quartz window or pixmap");
+      cg_context = NULL;
     }
 
-  g_assert_not_reached ();
-
-  return NULL;
+  return cg_context;
 }
 
 void
-gdk_quartz_drawable_release_context (GdkDrawable  *drawable,
-                                    CGContextRef  context)
+gdk_quartz_drawable_release_context (GdkDrawable  *drawable, 
+                                    CGContextRef  cg_context)
 {
-  if (!context)
-    return;
-
   if (GDK_IS_WINDOW_IMPL_QUARTZ (drawable))
     {
-      GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (drawable);
+      GdkWindowImplQuartz *window_impl = GDK_WINDOW_IMPL_QUARTZ (drawable);
 
-      CGContextRestoreGState (context);
-      CGContextSetAllowsAntialiasing (context, TRUE);
+      CGContextRestoreGState (cg_context);
+      CGContextSetAllowsAntialiasing (cg_context, TRUE);
 
-      if (impl->in_paint_rect_count == 0 &&
-         impl->begin_paint_count == 0)
-       CGContextFlush (context);
+      /* Only flush and unlock if called outside the expose, since it's
+       * already handled for otherwise.
+       */
+      if (window_impl->in_paint_rect_count == 0 && window_impl->begin_paint_count == 0)
+       {
+         CGContextFlush (cg_context);
+         [window_impl->view unlockFocus];
+       }
 
-      [impl->view unlockFocus];
-      [impl->pool release];
+      if (window_impl->pool)
+       {
+         [window_impl->pool release];
+         window_impl->pool = NULL;
+       }
     }
   else if (GDK_IS_PIXMAP_IMPL_QUARTZ (drawable))
+    CGContextRelease (cg_context);
+}
+
+void
+_gdk_quartz_drawable_finish (GdkDrawable *drawable)
+{
+  GdkDrawableImplQuartz *impl = GDK_DRAWABLE_IMPL_QUARTZ (drawable);
+
+  if (impl->cairo_surface)
     {
-      CGContextRelease (context);
+      cairo_surface_finish (impl->cairo_surface);
+      cairo_surface_set_user_data (impl->cairo_surface, &gdk_quartz_cairo_key,
+                                  NULL, NULL);
+      impl->cairo_surface = NULL;
     }
-}
+}  
index 2f2f533d1a2287a5816e5ccd11bfed9820e06998..f10441ff8e56e5695976632c33dd055640ed0a19 100644 (file)
@@ -40,11 +40,13 @@ typedef struct _GdkDrawableImplQuartzClass GdkDrawableImplQuartzClass;
 
 struct _GdkDrawableImplQuartz
 {
-  GdkDrawable parent_instance;
+  GdkDrawable      parent_instance;
 
-  GdkDrawable *wrapper;
+  GdkDrawable     *wrapper;
 
-  GdkColormap *colormap;
+  GdkColormap     *colormap;
+
+  cairo_surface_t *cairo_surface;
 };
  
 struct _GdkDrawableImplQuartzClass 
@@ -52,10 +54,11 @@ struct _GdkDrawableImplQuartzClass
   GdkDrawableClass parent_class;
 };
 
-GType gdk_drawable_impl_quartz_get_type (void);
-
-CGContextRef gdk_quartz_drawable_get_context (GdkDrawable *drawable, gboolean antialias);
-void gdk_quartz_drawable_release_context (GdkDrawable *drawable, CGContextRef context);
+GType        gdk_drawable_impl_quartz_get_type   (void);
+CGContextRef gdk_quartz_drawable_get_context     (GdkDrawable  *drawable, 
+                                                 gboolean      antialias);
+void         gdk_quartz_drawable_release_context (GdkDrawable  *drawable, 
+                                                 CGContextRef  context);
 
 G_END_DECLS
 
index 8176e75d15e1ded5c6202786505fbf9083393905..740321dca6213f082bef12bf6489b28db9c65f21 100644 (file)
@@ -48,6 +48,8 @@ gdk_pixmap_impl_quartz_finalize (GObject *object)
 
   CGImageRelease (impl->image);
 
+  _gdk_quartz_drawable_finish (GDK_DRAWABLE (impl));
+
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
index 0b4c3ebee3d2a712c8de52b12044c47caa09284c..4263563db59a24c7d493371d8555d956b9238d45 100644 (file)
@@ -168,4 +168,6 @@ void     _gdk_quartz_event_loop_init            (void);
 NSEvent *_gdk_quartz_event_loop_get_current     (void);
 void     _gdk_quartz_event_loop_release_current (void);
 
+void     _gdk_quartz_drawable_finish (GdkDrawable *drawable);
+
 #endif /* __GDK_PRIVATE_QUARTZ_H__ */
index 0789d0c94b258f6e06e8215805059cef960fda5b..7e8c31957aeaccaad903fd89216b67cc952a359c 100644 (file)
@@ -1,7 +1,7 @@
 /* gdkwindow-quartz.c
  *
  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- * Copyright (C) 2005 Imendio AB
+ * Copyright (C) 2005-2007 Imendio AB
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -145,45 +145,47 @@ gdk_window_impl_quartz_begin_paint_region (GdkPaintable *paintable,
                                           GdkRegion    *region)
 {
   GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (paintable);
+  GdkDrawableImplQuartz *drawable_impl;
   int n_rects;
   GdkRectangle *rects;
   GdkPixmap *bg_pixmap;
   GdkWindow *window;
-  
-  bg_pixmap = GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_QUARTZ (impl)->wrapper)->bg_pixmap;
+
+  drawable_impl = GDK_DRAWABLE_IMPL_QUARTZ (impl);
+  bg_pixmap = GDK_WINDOW_OBJECT (drawable_impl->wrapper)->bg_pixmap;
 
   if (impl->begin_paint_count == 0)
     impl->paint_clip_region = gdk_region_copy (region);
   else
     gdk_region_union (impl->paint_clip_region, region);
 
-  impl->begin_paint_count ++;
+  impl->begin_paint_count++;
 
   if (bg_pixmap == GDK_NO_BG)
     return;
-       
+
   gdk_region_get_rectangles (region, &rects, &n_rects);
-  
+
   if (bg_pixmap == NULL)
     {
-      CGContextRef context = gdk_quartz_drawable_get_context (GDK_DRAWABLE (impl), FALSE);
+      CGContextRef cg_context;
+      gfloat r, g, b, a;
       gint i;
-    
+
+      cg_context = gdk_quartz_drawable_get_context (GDK_DRAWABLE (impl), FALSE);
+      gdk_quartz_get_rgba_from_pixel (gdk_drawable_get_colormap (drawable_impl->wrapper),
+                                     GDK_WINDOW_OBJECT (drawable_impl->wrapper)->bg_color.pixel,
+                                     &r, &g, &b, &a);
       for (i = 0; i < n_rects; i++) 
         {
-         gfloat r, g, b, a;
-
-         gdk_quartz_get_rgba_from_pixel (gdk_drawable_get_colormap (GDK_DRAWABLE_IMPL_QUARTZ (impl)->wrapper),
-                                         GDK_WINDOW_OBJECT (GDK_DRAWABLE_IMPL_QUARTZ (impl)->wrapper)->bg_color.pixel,
-                                         &r, &g, &b, &a);
-
-         CGContextSetRGBFillColor (context, r, g, b, a);
-          CGContextFillRect (context,
+         CGContextSetRGBFillColor (cg_context, r, g, b, a);
+          CGContextFillRect (cg_context,
                             CGRectMake (rects[i].x, rects[i].y,
                                         rects[i].width, rects[i].height));
         }
-      
-      gdk_quartz_drawable_release_context (GDK_DRAWABLE (impl), context);
+
+      gdk_quartz_drawable_release_context (GDK_DRAWABLE (impl), cg_context);
     }
   else
     {
@@ -191,10 +193,10 @@ gdk_window_impl_quartz_begin_paint_region (GdkPaintable *paintable,
       int x_offset, y_offset;
       int width, height;
       GdkGC *gc;
-      
+
       x_offset = y_offset = 0;
-      
-      window = GDK_WINDOW (GDK_DRAWABLE_IMPL_QUARTZ (impl)->wrapper);
+
+      window = GDK_WINDOW (drawable_impl->wrapper);
       while (window && ((GdkWindowObject *) window)->bg_pixmap == GDK_PARENT_RELATIVE_BG)
         {
           /* If this window should have the same background as the parent,
@@ -210,9 +212,9 @@ gdk_window_impl_quartz_begin_paint_region (GdkPaintable *paintable,
        * want to look into that for this. 
        */
       gc = gdk_gc_new (GDK_DRAWABLE (impl));
-      
+
       gdk_drawable_get_size (GDK_DRAWABLE (bg_pixmap), &width, &height);
-      
+
       x = -x_offset;
       while (x < (rects[0].x + rects[0].width))
         {
@@ -229,10 +231,10 @@ gdk_window_impl_quartz_begin_paint_region (GdkPaintable *paintable,
             }
           x += width;
         }
-      
-      g_object_unref (G_OBJECT (gc));
+
+      g_object_unref (gc);
     }
-  
+
   g_free (rects);
 }
 
@@ -241,7 +243,7 @@ gdk_window_impl_quartz_end_paint (GdkPaintable *paintable)
 {
   GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (paintable);
 
-  impl->begin_paint_count --;
+  impl->begin_paint_count--;
 
   if (impl->begin_paint_count == 0)
     {
@@ -261,6 +263,8 @@ gdk_window_quartz_process_all_updates (void)
 
   g_slist_foreach (old_update_windows, (GFunc) g_object_ref, NULL);
   
+  GDK_QUARTZ_ALLOC_POOL;
+
   while (tmp_list)
     {
       GdkWindowObject *private = tmp_list->data;
@@ -275,18 +279,14 @@ gdk_window_quartz_process_all_updates (void)
          gdk_region_destroy (private->update_area);
          private->update_area = NULL;
          
-          GDK_QUARTZ_ALLOC_POOL;
-
          for (i = 0; i < n_rects; i++) 
            {
              [impl->view setNeedsDisplayInRect:NSMakeRect (rects[i].x, rects[i].y,
-                                                           rects[i].width, rects[i].height)];
+                                                           rects[i].width, rects[i].height)];
            }
          
          [impl->view displayIfNeeded];
 
-          GDK_QUARTZ_RELEASE_POOL;
-
          g_free (rects);
        }
 
@@ -294,6 +294,8 @@ gdk_window_quartz_process_all_updates (void)
       tmp_list = tmp_list->next;
     }
 
+  GDK_QUARTZ_RELEASE_POOL;
+
   g_slist_free (old_update_windows);
 }
 
@@ -373,25 +375,25 @@ _gdk_window_impl_quartz_get_type (void)
 
   if (!object_type)
     {
-      static const GTypeInfo object_info =
-      {
-        sizeof (GdkWindowImplQuartzClass),
-        (GBaseInitFunc) NULL,
-        (GBaseFinalizeFunc) NULL,
-        (GClassInitFunc) gdk_window_impl_quartz_class_init,
-        NULL,           /* class_finalize */
-        NULL,           /* class_data */
-        sizeof (GdkWindowImplQuartz),
-        0,              /* n_preallocs */
-        (GInstanceInitFunc) gdk_window_impl_quartz_init,
-      };
-      
-      static const GInterfaceInfo paintable_info = 
-      {
-       (GInterfaceInitFunc) gdk_window_impl_quartz_paintable_init,
-       NULL,
-       NULL
-      };
+      const GTypeInfo object_info =
+       {
+         sizeof (GdkWindowImplQuartzClass),
+         (GBaseInitFunc) NULL,
+         (GBaseFinalizeFunc) NULL,
+         (GClassInitFunc) gdk_window_impl_quartz_class_init,
+         NULL,           /* class_finalize */
+         NULL,           /* class_data */
+         sizeof (GdkWindowImplQuartz),
+         0,              /* n_preallocs */
+         (GInstanceInitFunc) gdk_window_impl_quartz_init,
+       };
+
+      const GInterfaceInfo paintable_info = 
+       {
+         (GInterfaceInitFunc) gdk_window_impl_quartz_paintable_init,
+         NULL,
+         NULL
+       };
 
       object_type = g_type_register_static (GDK_TYPE_DRAWABLE_IMPL_QUARTZ,
                                             "GdkWindowImplQuartz",
@@ -400,7 +402,7 @@ _gdk_window_impl_quartz_get_type (void)
                                   GDK_TYPE_PAINTABLE,
                                   &paintable_info);
     }
-  
+
   return object_type;
 }
 
@@ -737,6 +739,8 @@ _gdk_windowing_window_destroy (GdkWindow *window,
 
       GDK_QUARTZ_ALLOC_POOL;
 
+      _gdk_quartz_drawable_finish (GDK_DRAWABLE (impl));
+
       if (impl->toplevel)
        [impl->toplevel close];
       else if (impl->view)
@@ -908,10 +912,10 @@ move_resize_window_internal (GdkWindow *window,
     {
       if (!private->input_only)
        {
-         [impl->view setFrame:NSMakeRect (private->x, private->y, 
-                                          impl->width, impl->height)];
+         NSRect nsrect;
 
-         /* FIXME: Maybe we should use setNeedsDisplayInRect instead */
+         nsrect = NSMakeRect (private->x, private->y, impl->width, impl->height);
+         [impl->view setFrame: nsrect];
          [impl->view setNeedsDisplay:YES];
        }
     }