/* 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
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)
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;
}
-}
+}
/* 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
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
{
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,
* 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))
{
}
x += width;
}
-
- g_object_unref (G_OBJECT (gc));
+
+ g_object_unref (gc);
}
-
+
g_free (rects);
}
{
GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (paintable);
- impl->begin_paint_count --;
+ impl->begin_paint_count--;
if (impl->begin_paint_count == 0)
{
g_slist_foreach (old_update_windows, (GFunc) g_object_ref, NULL);
+ GDK_QUARTZ_ALLOC_POOL;
+
while (tmp_list)
{
GdkWindowObject *private = tmp_list->data;
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);
}
tmp_list = tmp_list->next;
}
+ GDK_QUARTZ_RELEASE_POOL;
+
g_slist_free (old_update_windows);
}
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",
GDK_TYPE_PAINTABLE,
&paintable_info);
}
-
+
return object_type;
}
GDK_QUARTZ_ALLOC_POOL;
+ _gdk_quartz_drawable_finish (GDK_DRAWABLE (impl));
+
if (impl->toplevel)
[impl->toplevel close];
else if (impl->view)
{
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];
}
}