OSX: add multistage support

Bug #911 - OSX: add multistage support

	* clutter/osx/clutter-backend-osx.{c,h}
	(clutter_backend_osx_init_stage, clutter_backend_osx_get_stage,
	clutter_backend_osx_redraw, clutter_backend_osx_create_stage,
	clutter_backend_osx_ensure_context, clutter_backend_osx_class_init,
	clutter_backend_osx_dispose, ClutterGLView:drawRect:):
	* clutter/osx/clutter-stage-osx.{c,h} (clutter_stage_osx_realize,
	ClutterGLWindow:setFrameSize:):
	Adapt to new multistage backend API. Don't keep a pointer to
	default stage. Derive from ClutterActor instead of ClutterStage.
	Implement ClutterStageWindow interface. Paint, resize and
	otherwise manipulate the wrapper rather than self when necessary.

	(clutter_backend_post_parse): Create our singleton GL context
	here. We could probably create the context when the default
	stage is created, but I think this is more clean.

	* clutter/osx/clutter-event-osx.c (clutter_event_osx_translate)
	* clutter/osx/clutter-stage-osx.c (clutter_stage_osx_state_update,
	ClutterGLWindow:windowShouldClose:):
	* clutter/osx/clutter-stage-osx.h: Export ClutterGLWindow interface
	for clutter-event-osx.c to easily get the stage for NSWindow.
	Fill in ClutterEventAny::stage on our events.

	Consistently use 'stage_osx' and 'wrapper' as variable names
	when referring to ClutterStageOSX and ClutterStage objects
	respectively.
This commit is contained in:
Tommi Komulainen 2008-06-05 21:27:58 +00:00
parent cba23c0b26
commit b8e8a80a40
6 changed files with 196 additions and 132 deletions

View File

@ -1,3 +1,30 @@
2008-06-05 Tommi Komulainen <tommi.komulainen@iki.fi>
Bug #911 - OSX: add multistage support
* clutter/osx/clutter-backend-osx.{c,h}
(clutter_backend_osx_init_stage, clutter_backend_osx_get_stage,
clutter_backend_osx_redraw, clutter_backend_osx_create_stage,
clutter_backend_osx_ensure_context, clutter_backend_osx_class_init,
clutter_backend_osx_dispose, ClutterGLView:drawRect:):
* clutter/osx/clutter-stage-osx.{c,h} (clutter_stage_osx_realize,
ClutterGLWindow:setFrameSize:):
Adapt to new multistage backend API. Don't keep a pointer to
default stage. Derive from ClutterActor instead of ClutterStage.
Implement ClutterStageWindow interface. Paint, resize and
otherwise manipulate the wrapper rather than self when necessary.
(clutter_backend_post_parse): Create our singleton GL context
here. We could probably create the context when the default
stage is created, but I think this is more clean.
* clutter/osx/clutter-event-osx.c (clutter_event_osx_translate)
* clutter/osx/clutter-stage-osx.c (clutter_stage_osx_state_update,
ClutterGLWindow:windowShouldClose:):
* clutter/osx/clutter-stage-osx.h: Export ClutterGLWindow interface
for clutter-event-osx.c to easily get the stage for NSWindow.
Fill in ClutterEventAny::stage on our events.
2008-06-05 Tommi Komulainen <tommi.komulainen@iki.fi> 2008-06-05 Tommi Komulainen <tommi.komulainen@iki.fi>
Bug #910 - OSX: missing memory pool Bug #910 - OSX: missing memory pool

View File

@ -1,7 +1,7 @@
/* Clutter - An OpenGL based 'interactive canvas' library. /* Clutter - An OpenGL based 'interactive canvas' library.
* OSX backend - initial entry point * OSX backend - initial entry point
* *
* Copyright (C) 2007 Tommi Komulainen <tommi.komulainen@iki.fi> * Copyright (C) 2007-2008 Tommi Komulainen <tommi.komulainen@iki.fi>
* Copyright (C) 2007 OpenedHand Ltd. * Copyright (C) 2007 OpenedHand Ltd.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
@ -36,6 +36,8 @@ static gboolean
clutter_backend_osx_post_parse (ClutterBackend *backend, clutter_backend_osx_post_parse (ClutterBackend *backend,
GError **error) GError **error)
{ {
ClutterBackendOSX *self = CLUTTER_BACKEND_OSX (backend);
CLUTTER_NOTE (BACKEND, "post_parse"); CLUTTER_NOTE (BACKEND, "post_parse");
CLUTTER_OSX_POOL_ALLOC(); CLUTTER_OSX_POOL_ALLOC();
@ -53,40 +55,8 @@ clutter_backend_osx_post_parse (ClutterBackend *backend,
[NSApplication sharedApplication]; [NSApplication sharedApplication];
/* Initialize(?) OpenGL -- without this glGetString crashes /* Allocate ourselves a GL context. Since we're supposed to have only one per
* * backend we can just as well create it now.
* Program received signal EXC_BAD_ACCESS, Could not access memory.
* Reason: KERN_PROTECTION_FAILURE at address: 0x00000ac0
* 0x92b22b2f in glGetString ()
*/
[NSOpenGLView defaultPixelFormat];
CLUTTER_OSX_POOL_RELEASE();
return TRUE;
}
static ClutterFeatureFlags
clutter_backend_osx_get_features (ClutterBackend *backend)
{
return CLUTTER_FEATURE_STAGE_USER_RESIZE;
}
static gboolean
clutter_backend_osx_init_stage (ClutterBackend *backend,
GError **error)
{
ClutterBackendOSX *self = CLUTTER_BACKEND_OSX (backend);
ClutterActor *stage;
CLUTTER_NOTE (BACKEND, "init_stage");
CLUTTER_OSX_POOL_ALLOC();
g_assert (self->stage == NULL);
/* Allocate ourselves a GL context. We need one this early for clutter to
* manage textures.
*/ */
NSOpenGLPixelFormatAttribute attrs[] = { NSOpenGLPixelFormatAttribute attrs[] = {
NSOpenGLPFADoubleBuffer, NSOpenGLPFADoubleBuffer,
@ -96,16 +66,42 @@ clutter_backend_osx_init_stage (ClutterBackend *backend,
self->context = [[NSOpenGLContext alloc] self->context = [[NSOpenGLContext alloc]
initWithFormat: self->pixel_format initWithFormat: self->pixel_format
shareContext: nil]; shareContext: nil];
[self->context makeCurrentContext];
stage = clutter_stage_osx_new (backend); /* Enable vblank sync - http://developer.apple.com/qa/qa2007/qa1521.html*/
self->stage = g_object_ref_sink (stage); const long sw = 1;
[self->context setValues:&sw forParameter: NSOpenGLCPSwapInterval];
CLUTTER_OSX_POOL_RELEASE(); CLUTTER_OSX_POOL_RELEASE();
return TRUE; return TRUE;
} }
static ClutterFeatureFlags
clutter_backend_osx_get_features (ClutterBackend *backend)
{
return CLUTTER_FEATURE_STAGE_MULTIPLE|CLUTTER_FEATURE_STAGE_USER_RESIZE;
}
static ClutterActor*
clutter_backend_osx_create_stage (ClutterBackend *backend,
ClutterStage *wrapper,
GError **error)
{
ClutterActor *impl;
CLUTTER_NOTE (BACKEND, "create_stage: wrapper=%p", wrapper);
CLUTTER_OSX_POOL_ALLOC();
impl = clutter_stage_osx_new (backend, wrapper);
CLUTTER_NOTE (BACKEND, "create_stage: impl=%p", impl);
CLUTTER_OSX_POOL_RELEASE();
return impl;
}
static void static void
clutter_backend_osx_init_events (ClutterBackend *backend) clutter_backend_osx_init_events (ClutterBackend *backend)
{ {
@ -114,21 +110,41 @@ clutter_backend_osx_init_events (ClutterBackend *backend)
_clutter_events_osx_init (); _clutter_events_osx_init ();
} }
static ClutterActor * static void
clutter_backend_osx_get_stage (ClutterBackend *backend) clutter_backend_osx_ensure_context (ClutterBackend *backend,
ClutterStage *wrapper)
{ {
ClutterBackendOSX *self = CLUTTER_BACKEND_OSX (backend); ClutterBackendOSX *backend_osx = CLUTTER_BACKEND_OSX (backend);
return self->stage; CLUTTER_NOTE (BACKEND, "ensure_context: wrapper=%p", wrapper);
CLUTTER_OSX_POOL_ALLOC();
if (wrapper)
{
ClutterStageWindow *impl = _clutter_stage_get_window (wrapper);
ClutterStageOSX *stage_osx;
g_assert (CLUTTER_IS_STAGE_OSX (impl));
stage_osx = CLUTTER_STAGE_OSX (impl);
[backend_osx->context setView:stage_osx->view];
[backend_osx->context makeCurrentContext];
}
else
{
[backend_osx->context clearDrawable];
[NSOpenGLContext clearCurrentContext];
}
CLUTTER_OSX_POOL_RELEASE();
} }
static void static void
clutter_backend_osx_redraw (ClutterBackend *backend) clutter_backend_osx_redraw (ClutterBackend *backend, ClutterStage *wrapper)
{ {
ClutterBackendOSX *self = CLUTTER_BACKEND_OSX (backend); ClutterStageWindow *impl = _clutter_stage_get_window (wrapper);
ClutterStageOSX *stage_osx; ClutterStageOSX *stage_osx = CLUTTER_STAGE_OSX (impl);
stage_osx = CLUTTER_STAGE_OSX (self->stage);
CLUTTER_OSX_POOL_ALLOC(); CLUTTER_OSX_POOL_ALLOC();
@ -149,12 +165,7 @@ clutter_backend_osx_dispose (GObject *object)
{ {
ClutterBackendOSX *self = CLUTTER_BACKEND_OSX (object); ClutterBackendOSX *self = CLUTTER_BACKEND_OSX (object);
if (self->stage) _clutter_shader_release_all ();
{
CLUTTER_UNSET_PRIVATE_FLAGS (self->stage, CLUTTER_ACTOR_IS_TOPLEVEL);
clutter_actor_destroy (self->stage);
self->stage = NULL;
}
[self->context release]; [self->context release];
self->context = NULL; self->context = NULL;
@ -162,7 +173,6 @@ clutter_backend_osx_dispose (GObject *object)
[self->pixel_format release]; [self->pixel_format release];
self->pixel_format = NULL; self->pixel_format = NULL;
G_OBJECT_CLASS (clutter_backend_osx_parent_class)->dispose (object); G_OBJECT_CLASS (clutter_backend_osx_parent_class)->dispose (object);
} }
@ -176,9 +186,9 @@ clutter_backend_osx_class_init (ClutterBackendOSXClass *klass)
backend_class->post_parse = clutter_backend_osx_post_parse; backend_class->post_parse = clutter_backend_osx_post_parse;
backend_class->get_features = clutter_backend_osx_get_features; backend_class->get_features = clutter_backend_osx_get_features;
backend_class->init_stage = clutter_backend_osx_init_stage; backend_class->create_stage = clutter_backend_osx_create_stage;
backend_class->ensure_context = clutter_backend_osx_ensure_context;
backend_class->init_events = clutter_backend_osx_init_events; backend_class->init_events = clutter_backend_osx_init_events;
backend_class->get_stage = clutter_backend_osx_get_stage;
backend_class->redraw = clutter_backend_osx_redraw; backend_class->redraw = clutter_backend_osx_redraw;
} }

View File

@ -44,8 +44,6 @@ struct _ClutterBackendOSX
NSOpenGLPixelFormat *pixel_format; NSOpenGLPixelFormat *pixel_format;
NSOpenGLContext *context; NSOpenGLContext *context;
ClutterActor *stage;
}; };
struct _ClutterBackendOSXClass struct _ClutterBackendOSXClass

View File

@ -1,7 +1,7 @@
/* Clutter - An OpenGL based 'interactive canvas' library. /* Clutter - An OpenGL based 'interactive canvas' library.
* OSX backend - event loops integration * OSX backend - event loops integration
* *
* Copyright (C) 2007 Tommi Komulainen <tommi.komulainen@iki.fi> * Copyright (C) 2007-2008 Tommi Komulainen <tommi.komulainen@iki.fi>
* Copyright (C) 2007 OpenedHand Ltd. * Copyright (C) 2007 OpenedHand Ltd.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
@ -22,6 +22,7 @@
#include "config.h" #include "config.h"
#include "clutter-osx.h" #include "clutter-osx.h"
#include "clutter-stage-osx.h"
#import <AppKit/AppKit.h> #import <AppKit/AppKit.h>
#include <glib/gmain.h> #include <glib/gmain.h>
@ -37,6 +38,7 @@ static GPollFunc old_poll_func = NULL;
/*************************************************************************/ /*************************************************************************/
@interface NSEvent (Clutter) @interface NSEvent (Clutter)
- (ClutterStage*)clutterStage;
- (gint)clutterTime; - (gint)clutterTime;
- (gint)clutterButton; - (gint)clutterButton;
- (void)clutterX:(gint*)ptrX y:(gint*)ptrY; - (void)clutterX:(gint*)ptrX y:(gint*)ptrY;
@ -45,6 +47,16 @@ static GPollFunc old_poll_func = NULL;
@end @end
@implementation NSEvent (Clutter) @implementation NSEvent (Clutter)
- (ClutterStage*)clutterStage
{
ClutterGLWindow *w = (ClutterGLWindow*)[self window];
if (![w isKindOfClass:[ClutterGLWindow class]])
return NULL;
ClutterStageOSX *stage_osx = w->stage_osx;
return stage_osx->wrapper;
}
- (gint)clutterTime - (gint)clutterTime
{ {
return [self timestamp] * 1000; return [self timestamp] * 1000;
@ -160,6 +172,7 @@ static GPollFunc old_poll_func = NULL;
static gboolean static gboolean
clutter_event_osx_translate (NSEvent *nsevent, ClutterEvent *event) clutter_event_osx_translate (NSEvent *nsevent, ClutterEvent *event)
{ {
event->any.stage = [nsevent clutterStage];
event->any.time = [nsevent clutterTime]; event->any.time = [nsevent clutterTime];
switch ([nsevent type]) switch ([nsevent type])

View File

@ -1,7 +1,7 @@
/* Clutter - An OpenGL based 'interactive canvas' library. /* Clutter - An OpenGL based 'interactive canvas' library.
* OSX backend - integration with NSWindow and NSView * OSX backend - integration with NSWindow and NSView
* *
* Copyright (C) 2007 Tommi Komulainen <tommi.komulainen@iki.fi> * Copyright (C) 2007-2008 Tommi Komulainen <tommi.komulainen@iki.fi>
* Copyright (C) 2007 OpenedHand Ltd. * Copyright (C) 2007 OpenedHand Ltd.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
@ -29,7 +29,11 @@
#include <clutter/clutter-debug.h> #include <clutter/clutter-debug.h>
#include <clutter/clutter-private.h> #include <clutter/clutter-private.h>
G_DEFINE_TYPE (ClutterStageOSX, clutter_stage_osx, CLUTTER_TYPE_STAGE) static void clutter_stage_window_iface_init (ClutterStageWindowIface *iface);
G_DEFINE_TYPE_WITH_CODE (ClutterStageOSX, clutter_stage_osx, CLUTTER_TYPE_ACTOR,
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW,
clutter_stage_window_iface_init))
/* FIXME: this should be in clutter-stage.c */ /* FIXME: this should be in clutter-stage.c */
static void static void
@ -40,12 +44,6 @@ clutter_stage_osx_state_update (ClutterStageOSX *self,
#define CLUTTER_OSX_FULLSCREEN_WINDOW_LEVEL (NSMainMenuWindowLevel + 1) #define CLUTTER_OSX_FULLSCREEN_WINDOW_LEVEL (NSMainMenuWindowLevel + 1)
/*************************************************************************/ /*************************************************************************/
@interface ClutterGLWindow : NSWindow
{
ClutterStageOSX *stage;
}
@end
@implementation ClutterGLWindow @implementation ClutterGLWindow
- (id)initWithView:(NSView *)aView UTF8Title:(const char *)aTitle stage:(ClutterStageOSX *)aStage - (id)initWithView:(NSView *)aView UTF8Title:(const char *)aTitle stage:(ClutterStageOSX *)aStage
{ {
@ -58,17 +56,18 @@ clutter_stage_osx_state_update (ClutterStageOSX *self,
[self useOptimizedDrawing: YES]; [self useOptimizedDrawing: YES];
[self setContentView: aView]; [self setContentView: aView];
[self setTitle:[NSString stringWithUTF8String: aTitle ? aTitle : ""]]; [self setTitle:[NSString stringWithUTF8String: aTitle ? aTitle : ""]];
stage = aStage; self->stage_osx = aStage;
} }
return self; return self;
} }
- (BOOL) windowShouldClose: (id) sender - (BOOL) windowShouldClose: (id) sender
{ {
CLUTTER_NOTE (BACKEND, "windowShouldClose"); CLUTTER_NOTE (BACKEND, "[%p] windowShouldClose", self->stage_osx);
ClutterEvent event; ClutterEvent event;
event.type = CLUTTER_DELETE; event.type = CLUTTER_DELETE;
event.any.stage = CLUTTER_STAGE (self->stage_osx->wrapper);
clutter_event_put (&event); clutter_event_put (&event);
return NO; return NO;
@ -85,55 +84,50 @@ clutter_stage_osx_state_update (ClutterStageOSX *self,
- (void) windowDidBecomeKey:(NSNotification*)aNotification - (void) windowDidBecomeKey:(NSNotification*)aNotification
{ {
CLUTTER_NOTE (BACKEND, "windowDidBecomeKey"); CLUTTER_NOTE (BACKEND, "[%p] windowDidBecomeKey", self->stage_osx);
if (stage->stage_state & CLUTTER_STAGE_STATE_FULLSCREEN) if (self->stage_osx->stage_state & CLUTTER_STAGE_STATE_FULLSCREEN)
[self setLevel: CLUTTER_OSX_FULLSCREEN_WINDOW_LEVEL]; [self setLevel: CLUTTER_OSX_FULLSCREEN_WINDOW_LEVEL];
clutter_stage_osx_state_update (stage, 0, CLUTTER_STAGE_STATE_ACTIVATED); clutter_stage_osx_state_update (self->stage_osx, 0, CLUTTER_STAGE_STATE_ACTIVATED);
} }
- (void) windowDidResignKey:(NSNotification*)aNotification - (void) windowDidResignKey:(NSNotification*)aNotification
{ {
CLUTTER_NOTE (BACKEND, "windowDidResignKey"); CLUTTER_NOTE (BACKEND, "[%p] windowDidResignKey", self->stage_osx);
if (stage->stage_state & CLUTTER_STAGE_STATE_FULLSCREEN) if (self->stage_osx->stage_state & CLUTTER_STAGE_STATE_FULLSCREEN)
{ {
[self setLevel: NSNormalWindowLevel]; [self setLevel: NSNormalWindowLevel];
[self orderBack: nil]; [self orderBack: nil];
} }
clutter_stage_osx_state_update (stage, CLUTTER_STAGE_STATE_ACTIVATED, 0); clutter_stage_osx_state_update (self->stage_osx, CLUTTER_STAGE_STATE_ACTIVATED, 0);
} }
@end @end
/*************************************************************************/ /*************************************************************************/
@interface ClutterGLView : NSOpenGLView @interface ClutterGLView : NSOpenGLView
{ {
ClutterActor *stage; ClutterStageOSX *stage_osx;
} }
- (void) drawRect: (NSRect) bounds; - (void) drawRect: (NSRect) bounds;
@end @end
@implementation ClutterGLView @implementation ClutterGLView
- (id) initWithFrame: (NSRect)aFrame pixelFormat:(NSOpenGLPixelFormat*)aFormat stage:(ClutterActor*)aStage - (id) initWithFrame: (NSRect)aFrame pixelFormat:(NSOpenGLPixelFormat*)aFormat stage:(ClutterStageOSX*)aStage
{ {
long sw = 1;
if ((self = [super initWithFrame:aFrame pixelFormat:aFormat]) != nil) if ((self = [super initWithFrame:aFrame pixelFormat:aFormat]) != nil)
{ {
self->stage = aStage; self->stage_osx = aStage;
} }
/* Enable vblank sync - http://developer.apple.com/qa/qa2007/qa1521.html*/
[[self openGLContext] setValues:&sw forParameter: NSOpenGLCPSwapInterval];
return self; return self;
} }
- (void) drawRect: (NSRect) bounds - (void) drawRect: (NSRect) bounds
{ {
clutter_actor_paint (self->stage); clutter_actor_paint (CLUTTER_ACTOR (self->stage_osx->wrapper));
[[self openGLContext] flushBuffer]; [[self openGLContext] flushBuffer];
} }
@ -151,14 +145,15 @@ clutter_stage_osx_state_update (ClutterStageOSX *self,
- (void) setFrameSize: (NSSize) aSize - (void) setFrameSize: (NSSize) aSize
{ {
CLUTTER_NOTE (BACKEND, "setFrameSize: %dx%d", CLUTTER_NOTE (BACKEND, "[%p] setFrameSize: %dx%d", self->stage_osx,
(int)aSize.width, (int)aSize.height); (int)aSize.width, (int)aSize.height);
[super setFrameSize: aSize]; [super setFrameSize: aSize];
clutter_actor_set_size (self->stage, (int)aSize.width, (int)aSize.height); clutter_actor_set_size (CLUTTER_ACTOR (self->stage_osx->wrapper),
(int)aSize.width, (int)aSize.height);
CLUTTER_SET_PRIVATE_FLAGS(self->stage, CLUTTER_ACTOR_SYNC_MATRICES); CLUTTER_SET_PRIVATE_FLAGS(self->stage_osx->wrapper, CLUTTER_ACTOR_SYNC_MATRICES);
} }
/* Simply forward all events that reach our view to clutter. */ /* Simply forward all events that reach our view to clutter. */
@ -209,6 +204,7 @@ clutter_stage_osx_state_update (ClutterStageOSX *self,
self->stage_state = event.new_state; self->stage_state = event.new_state;
event.type = CLUTTER_STAGE_STATE; event.type = CLUTTER_STAGE_STATE;
event.stage = CLUTTER_STAGE (self->wrapper);
clutter_event_put ((ClutterEvent*)&event); clutter_event_put ((ClutterEvent*)&event);
} }
@ -263,11 +259,14 @@ clutter_stage_osx_realize (ClutterActor *actor)
ClutterBackendOSX *backend_osx; ClutterBackendOSX *backend_osx;
gboolean offscreen; gboolean offscreen;
CLUTTER_NOTE (BACKEND, "realize"); CLUTTER_NOTE (BACKEND, "[%p] realize", self);
/* ensure we get realize+unrealize properly paired */
g_return_if_fail (self->view == NULL && self->window == NULL);
CLUTTER_OSX_POOL_ALLOC(); CLUTTER_OSX_POOL_ALLOC();
g_object_get (actor, "offscreen", &offscreen, NULL); g_object_get (self->wrapper, "offscreen", &offscreen, NULL);
if (offscreen) if (offscreen)
{ {
@ -276,9 +275,6 @@ clutter_stage_osx_realize (ClutterActor *actor)
return; return;
} }
if (CLUTTER_ACTOR_CLASS (clutter_stage_osx_parent_class)->realize)
CLUTTER_ACTOR_CLASS (clutter_stage_osx_parent_class)->realize (actor);
backend_osx = CLUTTER_BACKEND_OSX (self->backend); backend_osx = CLUTTER_BACKEND_OSX (self->backend);
NSRect rect = NSMakeRect(0, 0, self->requisition_width, self->requisition_height); NSRect rect = NSMakeRect(0, 0, self->requisition_width, self->requisition_height);
@ -286,28 +282,23 @@ clutter_stage_osx_realize (ClutterActor *actor)
self->view = [[ClutterGLView alloc] self->view = [[ClutterGLView alloc]
initWithFrame: rect initWithFrame: rect
pixelFormat: backend_osx->pixel_format pixelFormat: backend_osx->pixel_format
stage: actor]; stage: self];
[self->view setOpenGLContext:backend_osx->context];
self->window = [[ClutterGLWindow alloc] self->window = [[ClutterGLWindow alloc]
initWithView: self->view initWithView: self->view
UTF8Title: clutter_stage_get_title (CLUTTER_STAGE (self)) UTF8Title: clutter_stage_get_title (CLUTTER_STAGE (self->wrapper))
stage: self]; stage: self];
/* looks better than positioning to 0,0 (bottom right) */ /* looks better than positioning to 0,0 (bottom right) */
[self->window center]; [self->window center];
/* To not miss all textures created with the context created in the backend
* make sure we share the context. (By default NSOpenGLView creates its own
* context.)
*/
NSOpenGLContext *context = backend_osx->context;
[self->view setOpenGLContext: context];
[context setView: self->view];
CLUTTER_OSX_POOL_RELEASE(); CLUTTER_OSX_POOL_RELEASE();
/* FIXME: ClutterStage:realize is using the class pointer directly rather
* than clutter_actor_realize which would set the REALIZED flag for us.
*/
CLUTTER_ACTOR_SET_FLAGS(self, CLUTTER_ACTOR_REALIZED);
CLUTTER_SET_PRIVATE_FLAGS(self, CLUTTER_ACTOR_SYNC_MATRICES); CLUTTER_SET_PRIVATE_FLAGS(self, CLUTTER_ACTOR_SYNC_MATRICES);
} }
@ -316,7 +307,10 @@ clutter_stage_osx_unrealize (ClutterActor *actor)
{ {
ClutterStageOSX *self = CLUTTER_STAGE_OSX (actor); ClutterStageOSX *self = CLUTTER_STAGE_OSX (actor);
CLUTTER_NOTE (BACKEND, "unrealize"); CLUTTER_NOTE (BACKEND, "[%p] unrealize", self);
/* ensure we get realize+unrealize properly paired */
g_return_if_fail (self->view != NULL && self->window != NULL);
CLUTTER_OSX_POOL_ALLOC(); CLUTTER_OSX_POOL_ALLOC();
@ -328,8 +322,7 @@ clutter_stage_osx_unrealize (ClutterActor *actor)
CLUTTER_OSX_POOL_RELEASE(); CLUTTER_OSX_POOL_RELEASE();
if (CLUTTER_ACTOR_CLASS (clutter_stage_osx_parent_class)->unrealize) CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
CLUTTER_ACTOR_CLASS (clutter_stage_osx_parent_class)->unrealize (actor);
} }
static void static void
@ -337,13 +330,13 @@ clutter_stage_osx_show (ClutterActor *actor)
{ {
ClutterStageOSX *self = CLUTTER_STAGE_OSX (actor); ClutterStageOSX *self = CLUTTER_STAGE_OSX (actor);
CLUTTER_NOTE (BACKEND, "show"); CLUTTER_NOTE (BACKEND, "[%p] show", self);
CLUTTER_ACTOR_SET_FLAGS (actor, CLUTTER_ACTOR_MAPPED);
if (CLUTTER_ACTOR_CLASS (clutter_stage_osx_parent_class)->show) if (CLUTTER_ACTOR_CLASS (clutter_stage_osx_parent_class)->show)
CLUTTER_ACTOR_CLASS (clutter_stage_osx_parent_class)->show (actor); CLUTTER_ACTOR_CLASS (clutter_stage_osx_parent_class)->show (actor);
CLUTTER_ACTOR_SET_FLAGS (actor, CLUTTER_ACTOR_MAPPED);
CLUTTER_OSX_POOL_ALLOC(); CLUTTER_OSX_POOL_ALLOC();
clutter_stage_osx_set_frame (self); clutter_stage_osx_set_frame (self);
@ -358,7 +351,7 @@ clutter_stage_osx_hide (ClutterActor *actor)
{ {
ClutterStageOSX *self = CLUTTER_STAGE_OSX (actor); ClutterStageOSX *self = CLUTTER_STAGE_OSX (actor);
CLUTTER_NOTE (BACKEND, "hide"); CLUTTER_NOTE (BACKEND, "[%p] hide", self);
CLUTTER_OSX_POOL_ALLOC(); CLUTTER_OSX_POOL_ALLOC();
@ -394,7 +387,7 @@ clutter_stage_osx_request_coords (ClutterActor *actor,
{ {
ClutterStageOSX *self = CLUTTER_STAGE_OSX (actor); ClutterStageOSX *self = CLUTTER_STAGE_OSX (actor);
CLUTTER_NOTE (BACKEND, "request_coords: %d,%d %dx%d", CLUTTER_NOTE (BACKEND, "[%p], request_coords: %d,%d %dx%d", self,
CLUTTER_UNITS_TO_INT (box->x1), CLUTTER_UNITS_TO_INT (box->x1),
CLUTTER_UNITS_TO_INT (box->y1), CLUTTER_UNITS_TO_INT (box->y1),
CLUTTER_UNITS_TO_INT (box->x2 - box->x1), CLUTTER_UNITS_TO_INT (box->x2 - box->x1),
@ -416,29 +409,37 @@ clutter_stage_osx_request_coords (ClutterActor *actor,
} }
/*************************************************************************/ /*************************************************************************/
static void static ClutterActor *
clutter_stage_osx_set_title (ClutterStage *stage, clutter_stage_osx_get_wrapper (ClutterStageWindow *stage_window)
const char *title)
{ {
ClutterStageOSX *self = CLUTTER_STAGE_OSX (stage); ClutterStageOSX *self = CLUTTER_STAGE_OSX (stage_window);
CLUTTER_NOTE (BACKEND, "set_title: %s", title); return CLUTTER_ACTOR (self->wrapper);
}
static void
clutter_stage_osx_set_title (ClutterStageWindow *stage_window,
const char *title)
{
ClutterStageOSX *self = CLUTTER_STAGE_OSX (stage_window);
CLUTTER_NOTE (BACKEND, "[%p] set_title: %s", self, title);
CLUTTER_OSX_POOL_ALLOC(); CLUTTER_OSX_POOL_ALLOC();
if (CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (stage))) if (CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (self)))
[self->window setTitle:[NSString stringWithUTF8String: title ? title : ""]]; [self->window setTitle:[NSString stringWithUTF8String: title ? title : ""]];
CLUTTER_OSX_POOL_RELEASE(); CLUTTER_OSX_POOL_RELEASE();
} }
static void static void
clutter_stage_osx_set_fullscreen (ClutterStage *stage, clutter_stage_osx_set_fullscreen (ClutterStageWindow *stage_window,
gboolean fullscreen) gboolean fullscreen)
{ {
ClutterStageOSX *self = CLUTTER_STAGE_OSX (stage); ClutterStageOSX *self = CLUTTER_STAGE_OSX (stage_window);
CLUTTER_NOTE (BACKEND, "set_fullscreen: %u", fullscreen); CLUTTER_NOTE (BACKEND, "[%p] set_fullscreen: %u", self, fullscreen);
CLUTTER_OSX_POOL_ALLOC(); CLUTTER_OSX_POOL_ALLOC();
@ -476,14 +477,24 @@ clutter_stage_osx_set_fullscreen (ClutterStage *stage,
CLUTTER_OSX_POOL_RELEASE(); CLUTTER_OSX_POOL_RELEASE();
} }
static void
clutter_stage_window_iface_init (ClutterStageWindowIface *iface)
{
iface->get_wrapper = clutter_stage_osx_get_wrapper;
iface->set_title = clutter_stage_osx_set_title;
iface->set_fullscreen = clutter_stage_osx_set_fullscreen;
}
/*************************************************************************/ /*************************************************************************/
ClutterActor * ClutterActor *
clutter_stage_osx_new (ClutterBackend *backend) clutter_stage_osx_new (ClutterBackend *backend,
ClutterStage *wrapper)
{ {
ClutterStageOSX *self; ClutterStageOSX *self;
self = g_object_new (CLUTTER_TYPE_STAGE_OSX, NULL); self = g_object_new (CLUTTER_TYPE_STAGE_OSX, NULL);
self->backend = backend; self->backend = backend;
self->wrapper = wrapper;
return CLUTTER_ACTOR(self); return CLUTTER_ACTOR(self);
} }
@ -495,14 +506,13 @@ clutter_stage_osx_init (ClutterStageOSX *self)
self->requisition_width = 640; self->requisition_width = 640;
self->requisition_height = 480; self->requisition_height = 480;
CLUTTER_SET_PRIVATE_FLAGS(self, CLUTTER_ACTOR_SYNC_MATRICES); CLUTTER_SET_PRIVATE_FLAGS(self, CLUTTER_ACTOR_IS_TOPLEVEL);
} }
static void static void
clutter_stage_osx_class_init (ClutterStageOSXClass *klass) clutter_stage_osx_class_init (ClutterStageOSXClass *klass)
{ {
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
ClutterStageClass *stage_class = CLUTTER_STAGE_CLASS (klass);
actor_class->realize = clutter_stage_osx_realize; actor_class->realize = clutter_stage_osx_realize;
actor_class->unrealize = clutter_stage_osx_unrealize; actor_class->unrealize = clutter_stage_osx_unrealize;
@ -511,7 +521,4 @@ clutter_stage_osx_class_init (ClutterStageOSXClass *klass)
actor_class->query_coords = clutter_stage_osx_query_coords; actor_class->query_coords = clutter_stage_osx_query_coords;
actor_class->request_coords = clutter_stage_osx_request_coords; actor_class->request_coords = clutter_stage_osx_request_coords;
stage_class->set_title = clutter_stage_osx_set_title;
stage_class->set_fullscreen = clutter_stage_osx_set_fullscreen;
} }

View File

@ -26,7 +26,7 @@
#include <clutter/clutter-backend.h> #include <clutter/clutter-backend.h>
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
@class NSOpenGLView, NSWindow; #import <AppKit/AppKit.h>
G_BEGIN_DECLS G_BEGIN_DECLS
@ -41,11 +41,19 @@ G_BEGIN_DECLS
typedef struct _ClutterStageOSX ClutterStageOSX; typedef struct _ClutterStageOSX ClutterStageOSX;
typedef struct _ClutterStageOSXClass ClutterStageOSXClass; typedef struct _ClutterStageOSXClass ClutterStageOSXClass;
@interface ClutterGLWindow : NSWindow
{
@public
ClutterStageOSX *stage_osx;
}
@end
struct _ClutterStageOSX struct _ClutterStageOSX
{ {
ClutterStage parent; ClutterActor parent;
ClutterBackend *backend; ClutterBackend *backend;
ClutterStage *wrapper;
NSWindow *window; NSWindow *window;
NSOpenGLView *view; NSOpenGLView *view;
@ -61,12 +69,13 @@ struct _ClutterStageOSX
struct _ClutterStageOSXClass struct _ClutterStageOSXClass
{ {
ClutterStageClass parent_class; ClutterActorClass parent_class;
}; };
GType clutter_stage_osx_get_type (void) G_GNUC_CONST; GType clutter_stage_osx_get_type (void) G_GNUC_CONST;
ClutterActor* clutter_stage_osx_new (ClutterBackend *backend); ClutterActor* clutter_stage_osx_new (ClutterBackend *backend,
ClutterStage *wrapper);
G_END_DECLS G_END_DECLS