From 8970b174dc274104ff86733a48b0e05e33791431 Mon Sep 17 00:00:00 2001 From: Kristian Rietveld Date: Mon, 4 Oct 2010 11:43:16 +0200 Subject: [PATCH] quartz: Emulate root window as 1x1 bitmap We subclass GdkWindowImplQuartz into a new GdkRootWindowImplQuartz, and override the get_context method in order to do this cleanly. Also made release_context a virtual method, since the root window has to release its CGContextRef differently compared to normal windows. --- gdk/quartz/gdkdrawable-quartz.c | 34 +++++------- gdk/quartz/gdkdrawable-quartz.h | 2 + gdk/quartz/gdkwindow-quartz.c | 96 ++++++++++++++++++++++++++++++++- gdk/quartz/gdkwindow-quartz.h | 27 ++++++++++ 4 files changed, 138 insertions(+), 21 deletions(-) diff --git a/gdk/quartz/gdkdrawable-quartz.c b/gdk/quartz/gdkdrawable-quartz.c index 8c6a141fa2..b19913675b 100644 --- a/gdk/quartz/gdkdrawable-quartz.c +++ b/gdk/quartz/gdkdrawable-quartz.c @@ -167,6 +167,20 @@ gdk_quartz_drawable_get_context (GdkDrawable *drawable, return GDK_DRAWABLE_IMPL_QUARTZ_GET_CLASS (drawable)->get_context (drawable, antialias); } +void +gdk_quartz_drawable_release_context (GdkDrawable *drawable, + CGContextRef cg_context) +{ + if (!GDK_DRAWABLE_IMPL_QUARTZ_GET_CLASS (drawable)->release_context) + { + g_warning ("%s doesn't implement GdkDrawableImplQuartzClass::release_context()", + G_OBJECT_TYPE_NAME (drawable)); + return; + } + + GDK_DRAWABLE_IMPL_QUARTZ_GET_CLASS (drawable)->release_context (drawable, cg_context); +} + /* Help preventing "beam sync penalty" where CG makes all graphics code * block until the next vsync if we try to flush (including call display on * a view) too often. We do this by limiting the manual flushing done @@ -212,26 +226,6 @@ _gdk_quartz_drawable_flush (GdkDrawable *drawable) prev_tv = tv; } -void -gdk_quartz_drawable_release_context (GdkDrawable *drawable, - CGContextRef cg_context) -{ - if (GDK_IS_WINDOW_IMPL_QUARTZ (drawable)) - { - GdkWindowImplQuartz *window_impl = GDK_WINDOW_IMPL_QUARTZ (drawable); - - CGContextRestoreGState (cg_context); - CGContextSetAllowsAntialiasing (cg_context, TRUE); - - /* See comment in gdk_quartz_drawable_get_context(). */ - if (window_impl->in_paint_rect_count == 0) - { - _gdk_quartz_drawable_flush (drawable); - [window_impl->view unlockFocus]; - } - } -} - void _gdk_quartz_drawable_finish (GdkDrawable *drawable) { diff --git a/gdk/quartz/gdkdrawable-quartz.h b/gdk/quartz/gdkdrawable-quartz.h index 52a9bef5d5..24d17d83ea 100644 --- a/gdk/quartz/gdkdrawable-quartz.h +++ b/gdk/quartz/gdkdrawable-quartz.h @@ -56,6 +56,8 @@ struct _GdkDrawableImplQuartzClass /* vtable */ CGContextRef (*get_context) (GdkDrawable* drawable, gboolean antialias); + void (*release_context) (GdkDrawable *drawable, + CGContextRef cg_context); }; GType gdk_drawable_impl_quartz_get_type (void); diff --git a/gdk/quartz/gdkwindow-quartz.c b/gdk/quartz/gdkwindow-quartz.c index ffdc83bc07..6a58347667 100644 --- a/gdk/quartz/gdkwindow-quartz.c +++ b/gdk/quartz/gdkwindow-quartz.c @@ -30,6 +30,7 @@ #include "gdkinputprivate.h" static gpointer parent_class; +static gpointer root_window_parent_class; static GSList *update_nswindows; static gboolean in_process_all_updates = FALSE; @@ -141,6 +142,23 @@ gdk_window_impl_quartz_get_context (GdkDrawable *drawable, return cg_context; } +static void +gdk_window_impl_quartz_release_context (GdkDrawable *drawable, + CGContextRef cg_context) +{ + GdkWindowImplQuartz *window_impl = GDK_WINDOW_IMPL_QUARTZ (drawable); + + CGContextRestoreGState (cg_context); + CGContextSetAllowsAntialiasing (cg_context, TRUE); + + /* See comment in gdk_quartz_drawable_get_context(). */ + if (window_impl->in_paint_rect_count == 0) + { + _gdk_quartz_drawable_flush (drawable); + [window_impl->view unlockFocus]; + } +} + static void check_grab_unmap (GdkWindow *window) { @@ -214,6 +232,7 @@ gdk_window_impl_quartz_class_init (GdkWindowImplQuartzClass *klass) object_class->finalize = gdk_window_impl_quartz_finalize; drawable_quartz_class->get_context = gdk_window_impl_quartz_get_context; + drawable_quartz_class->release_context = gdk_window_impl_quartz_release_context; } static void @@ -1009,7 +1028,7 @@ _gdk_windowing_window_init (void) _gdk_root = g_object_new (GDK_TYPE_WINDOW, NULL); private = (GdkWindowObject *)_gdk_root; - private->impl = g_object_new (_gdk_window_impl_get_type (), NULL); + private->impl = g_object_new (_gdk_root_window_impl_quartz_get_type (), NULL); private->impl_window = private; private->visual = gdk_screen_get_system_visual (_gdk_screen); @@ -2968,3 +2987,78 @@ gdk_window_impl_iface_init (GdkWindowImplIface *iface) iface->translate = _gdk_quartz_window_translate; iface->destroy = _gdk_quartz_window_destroy; } + + +static CGContextRef +gdk_root_window_impl_quartz_get_context (GdkDrawable *drawable, + gboolean antialias) +{ + GdkDrawableImplQuartz *drawable_impl = GDK_DRAWABLE_IMPL_QUARTZ (drawable); + CGColorSpaceRef colorspace; + CGContextRef cg_context; + + if (GDK_WINDOW_DESTROYED (drawable_impl->wrapper)) + return NULL; + + /* We do not have the notion of a root window on OS X. We fake this + * by creating a 1x1 bitmap and return a context to that. + */ + colorspace = CGColorSpaceCreateWithName (kCGColorSpaceGenericRGB); + cg_context = CGBitmapContextCreate (NULL, + 1, 1, 8, 4, colorspace, + kCGImageAlphaPremultipliedLast); + CGColorSpaceRelease (colorspace); + + return cg_context; +} + +static void +gdk_root_window_impl_quartz_release_context (GdkDrawable *drawable, + CGContextRef cg_context) +{ + CGContextRelease (cg_context); +} + +static void +gdk_root_window_impl_quartz_class_init (GdkRootWindowImplQuartzClass *klass) +{ + GdkDrawableImplQuartzClass *drawable_quartz_class = GDK_DRAWABLE_IMPL_QUARTZ_CLASS (klass); + + root_window_parent_class = g_type_class_peek_parent (klass); + + drawable_quartz_class->get_context = gdk_root_window_impl_quartz_get_context; + drawable_quartz_class->release_context = gdk_root_window_impl_quartz_release_context; +} + +static void +gdk_root_window_impl_quartz_init (GdkRootWindowImplQuartz *impl) +{ +} + +GType +_gdk_root_window_impl_quartz_get_type (void) +{ + static GType object_type = 0; + + if (!object_type) + { + const GTypeInfo object_info = + { + sizeof (GdkRootWindowImplQuartzClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gdk_root_window_impl_quartz_class_init, + NULL, /* class_finalize */ + NULL, /* class_data */ + sizeof (GdkRootWindowImplQuartz), + 0, /* n_preallocs */ + (GInstanceInitFunc) gdk_root_window_impl_quartz_init, + }; + + object_type = g_type_register_static (GDK_TYPE_WINDOW_IMPL_QUARTZ, + "GdkRootWindowQuartz", + &object_info, 0); + } + + return object_type; +} diff --git a/gdk/quartz/gdkwindow-quartz.h b/gdk/quartz/gdkwindow-quartz.h index c022b991ce..b591eebc81 100644 --- a/gdk/quartz/gdkwindow-quartz.h +++ b/gdk/quartz/gdkwindow-quartz.h @@ -69,6 +69,33 @@ struct _GdkWindowImplQuartzClass GType _gdk_window_impl_quartz_get_type (void); + +/* Root window implementation for Quartz + */ + +typedef struct _GdkRootWindowImplQuartz GdkRootWindowImplQuartz; +typedef struct _GdkRootWindowImplQuartzClass GdkRootWindowImplQuartzClass; + +#define GDK_TYPE_ROOT_WINDOW_IMPL_QUARTZ (_gdk_root_window_impl_quartz_get_type ()) +#define GDK_ROOT_WINDOW_IMPL_QUARTZ(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_ROOT_WINDOW_IMPL_QUARTZ, GdkRootWindowImplQuartz)) +#define GDK_ROOT_WINDOW_IMPL_QUARTZ_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_ROOT_WINDOW_IMPL_QUARTZ, GdkRootWindowImplQuartzClass)) +#define GDK_IS_ROOT_WINDOW_IMPL_QUARTZ(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_ROOT_WINDOW_IMPL_QUARTZ)) +#define GDK_IS_ROOT_WINDOW_IMPL_QUARTZ_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_ROOT_WINDOW_IMPL_QUARTZ)) +#define GDK_ROOT_WINDOW_IMPL_QUARTZ_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_ROOT_WINDOW_IMPL_QUARTZ, GdkRootWindowImplQuartzClass)) + +struct _GdkRootWindowImplQuartz +{ + GdkWindowImplQuartz parent_instance; +}; + +struct _GdkRootWindowImplQuartzClass +{ + GdkWindowImplQuartzClass parent_class; +}; + +GType _gdk_root_window_impl_quartz_get_type (void); + + G_END_DECLS #endif /* __GDK_WINDOW_QUARTZ_H__ */