From b8e8a80a4033f2937b7a743df39283d1e9715c9c Mon Sep 17 00:00:00 2001 From: Tommi Komulainen Date: Thu, 5 Jun 2008 21:27:58 +0000 Subject: [PATCH] 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. --- ChangeLog | 27 ++++++ clutter/osx/clutter-backend-osx.c | 122 +++++++++++++------------ clutter/osx/clutter-backend-osx.h | 2 - clutter/osx/clutter-event-osx.c | 15 +++- clutter/osx/clutter-stage-osx.c | 145 ++++++++++++++++-------------- clutter/osx/clutter-stage-osx.h | 17 +++- 6 files changed, 196 insertions(+), 132 deletions(-) diff --git a/ChangeLog b/ChangeLog index 548392710..78def1967 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,30 @@ +2008-06-05 Tommi Komulainen + + 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 Bug #910 - OSX: missing memory pool diff --git a/clutter/osx/clutter-backend-osx.c b/clutter/osx/clutter-backend-osx.c index cc5554c46..492ef6e3f 100644 --- a/clutter/osx/clutter-backend-osx.c +++ b/clutter/osx/clutter-backend-osx.c @@ -1,7 +1,7 @@ /* Clutter - An OpenGL based 'interactive canvas' library. * OSX backend - initial entry point * - * Copyright (C) 2007 Tommi Komulainen + * Copyright (C) 2007-2008 Tommi Komulainen * Copyright (C) 2007 OpenedHand Ltd. * * This library is free software; you can redistribute it and/or @@ -36,6 +36,8 @@ static gboolean clutter_backend_osx_post_parse (ClutterBackend *backend, GError **error) { + ClutterBackendOSX *self = CLUTTER_BACKEND_OSX (backend); + CLUTTER_NOTE (BACKEND, "post_parse"); CLUTTER_OSX_POOL_ALLOC(); @@ -53,40 +55,8 @@ clutter_backend_osx_post_parse (ClutterBackend *backend, [NSApplication sharedApplication]; - /* Initialize(?) OpenGL -- without this glGetString crashes - * - * 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. + /* Allocate ourselves a GL context. Since we're supposed to have only one per + * backend we can just as well create it now. */ NSOpenGLPixelFormatAttribute attrs[] = { NSOpenGLPFADoubleBuffer, @@ -96,16 +66,42 @@ clutter_backend_osx_init_stage (ClutterBackend *backend, self->context = [[NSOpenGLContext alloc] initWithFormat: self->pixel_format shareContext: nil]; - [self->context makeCurrentContext]; - stage = clutter_stage_osx_new (backend); - self->stage = g_object_ref_sink (stage); + /* Enable vblank sync - http://developer.apple.com/qa/qa2007/qa1521.html*/ + const long sw = 1; + [self->context setValues:&sw forParameter: NSOpenGLCPSwapInterval]; CLUTTER_OSX_POOL_RELEASE(); 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 clutter_backend_osx_init_events (ClutterBackend *backend) { @@ -114,21 +110,41 @@ clutter_backend_osx_init_events (ClutterBackend *backend) _clutter_events_osx_init (); } -static ClutterActor * -clutter_backend_osx_get_stage (ClutterBackend *backend) +static void +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 -clutter_backend_osx_redraw (ClutterBackend *backend) +clutter_backend_osx_redraw (ClutterBackend *backend, ClutterStage *wrapper) { - ClutterBackendOSX *self = CLUTTER_BACKEND_OSX (backend); - ClutterStageOSX *stage_osx; - - stage_osx = CLUTTER_STAGE_OSX (self->stage); + ClutterStageWindow *impl = _clutter_stage_get_window (wrapper); + ClutterStageOSX *stage_osx = CLUTTER_STAGE_OSX (impl); CLUTTER_OSX_POOL_ALLOC(); @@ -149,12 +165,7 @@ clutter_backend_osx_dispose (GObject *object) { ClutterBackendOSX *self = CLUTTER_BACKEND_OSX (object); - if (self->stage) - { - CLUTTER_UNSET_PRIVATE_FLAGS (self->stage, CLUTTER_ACTOR_IS_TOPLEVEL); - clutter_actor_destroy (self->stage); - self->stage = NULL; - } + _clutter_shader_release_all (); [self->context release]; self->context = NULL; @@ -162,7 +173,6 @@ clutter_backend_osx_dispose (GObject *object) [self->pixel_format release]; self->pixel_format = NULL; - 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->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->get_stage = clutter_backend_osx_get_stage; backend_class->redraw = clutter_backend_osx_redraw; } diff --git a/clutter/osx/clutter-backend-osx.h b/clutter/osx/clutter-backend-osx.h index c4036575c..b47b88917 100644 --- a/clutter/osx/clutter-backend-osx.h +++ b/clutter/osx/clutter-backend-osx.h @@ -44,8 +44,6 @@ struct _ClutterBackendOSX NSOpenGLPixelFormat *pixel_format; NSOpenGLContext *context; - - ClutterActor *stage; }; struct _ClutterBackendOSXClass diff --git a/clutter/osx/clutter-event-osx.c b/clutter/osx/clutter-event-osx.c index ec08e48d0..2e5f5c3f3 100644 --- a/clutter/osx/clutter-event-osx.c +++ b/clutter/osx/clutter-event-osx.c @@ -1,7 +1,7 @@ /* Clutter - An OpenGL based 'interactive canvas' library. * OSX backend - event loops integration * - * Copyright (C) 2007 Tommi Komulainen + * Copyright (C) 2007-2008 Tommi Komulainen * Copyright (C) 2007 OpenedHand Ltd. * * This library is free software; you can redistribute it and/or @@ -22,6 +22,7 @@ #include "config.h" #include "clutter-osx.h" +#include "clutter-stage-osx.h" #import #include @@ -37,6 +38,7 @@ static GPollFunc old_poll_func = NULL; /*************************************************************************/ @interface NSEvent (Clutter) +- (ClutterStage*)clutterStage; - (gint)clutterTime; - (gint)clutterButton; - (void)clutterX:(gint*)ptrX y:(gint*)ptrY; @@ -45,6 +47,16 @@ static GPollFunc old_poll_func = NULL; @end @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 { return [self timestamp] * 1000; @@ -160,6 +172,7 @@ static GPollFunc old_poll_func = NULL; static gboolean clutter_event_osx_translate (NSEvent *nsevent, ClutterEvent *event) { + event->any.stage = [nsevent clutterStage]; event->any.time = [nsevent clutterTime]; switch ([nsevent type]) diff --git a/clutter/osx/clutter-stage-osx.c b/clutter/osx/clutter-stage-osx.c index d1a7bd8db..19d198a75 100644 --- a/clutter/osx/clutter-stage-osx.c +++ b/clutter/osx/clutter-stage-osx.c @@ -1,7 +1,7 @@ /* Clutter - An OpenGL based 'interactive canvas' library. * OSX backend - integration with NSWindow and NSView * - * Copyright (C) 2007 Tommi Komulainen + * Copyright (C) 2007-2008 Tommi Komulainen * Copyright (C) 2007 OpenedHand Ltd. * * This library is free software; you can redistribute it and/or @@ -29,7 +29,11 @@ #include #include -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 */ static void @@ -40,12 +44,6 @@ clutter_stage_osx_state_update (ClutterStageOSX *self, #define CLUTTER_OSX_FULLSCREEN_WINDOW_LEVEL (NSMainMenuWindowLevel + 1) /*************************************************************************/ -@interface ClutterGLWindow : NSWindow -{ - ClutterStageOSX *stage; -} -@end - @implementation ClutterGLWindow - (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 setContentView: aView]; [self setTitle:[NSString stringWithUTF8String: aTitle ? aTitle : ""]]; - stage = aStage; + self->stage_osx = aStage; } return self; } - (BOOL) windowShouldClose: (id) sender { - CLUTTER_NOTE (BACKEND, "windowShouldClose"); + CLUTTER_NOTE (BACKEND, "[%p] windowShouldClose", self->stage_osx); ClutterEvent event; event.type = CLUTTER_DELETE; + event.any.stage = CLUTTER_STAGE (self->stage_osx->wrapper); clutter_event_put (&event); return NO; @@ -85,55 +84,50 @@ clutter_stage_osx_state_update (ClutterStageOSX *self, - (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]; - 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 { - 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 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 /*************************************************************************/ @interface ClutterGLView : NSOpenGLView { - ClutterActor *stage; + ClutterStageOSX *stage_osx; } - (void) drawRect: (NSRect) bounds; @end @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) { - 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; } - (void) drawRect: (NSRect) bounds { - clutter_actor_paint (self->stage); + clutter_actor_paint (CLUTTER_ACTOR (self->stage_osx->wrapper)); [[self openGLContext] flushBuffer]; } @@ -151,14 +145,15 @@ clutter_stage_osx_state_update (ClutterStageOSX *self, - (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); [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. */ @@ -209,6 +204,7 @@ clutter_stage_osx_state_update (ClutterStageOSX *self, self->stage_state = event.new_state; event.type = CLUTTER_STAGE_STATE; + event.stage = CLUTTER_STAGE (self->wrapper); clutter_event_put ((ClutterEvent*)&event); } @@ -263,11 +259,14 @@ clutter_stage_osx_realize (ClutterActor *actor) ClutterBackendOSX *backend_osx; 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(); - g_object_get (actor, "offscreen", &offscreen, NULL); + g_object_get (self->wrapper, "offscreen", &offscreen, NULL); if (offscreen) { @@ -276,9 +275,6 @@ clutter_stage_osx_realize (ClutterActor *actor) 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); 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] initWithFrame: rect pixelFormat: backend_osx->pixel_format - stage: actor]; + stage: self]; + [self->view setOpenGLContext:backend_osx->context]; self->window = [[ClutterGLWindow alloc] initWithView: self->view - UTF8Title: clutter_stage_get_title (CLUTTER_STAGE (self)) + UTF8Title: clutter_stage_get_title (CLUTTER_STAGE (self->wrapper)) stage: self]; /* looks better than positioning to 0,0 (bottom right) */ [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(); + /* 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); } @@ -316,7 +307,10 @@ clutter_stage_osx_unrealize (ClutterActor *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(); @@ -328,8 +322,7 @@ clutter_stage_osx_unrealize (ClutterActor *actor) CLUTTER_OSX_POOL_RELEASE(); - if (CLUTTER_ACTOR_CLASS (clutter_stage_osx_parent_class)->unrealize) - CLUTTER_ACTOR_CLASS (clutter_stage_osx_parent_class)->unrealize (actor); + CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED); } static void @@ -337,13 +330,13 @@ clutter_stage_osx_show (ClutterActor *actor) { ClutterStageOSX *self = CLUTTER_STAGE_OSX (actor); - CLUTTER_NOTE (BACKEND, "show"); - - CLUTTER_ACTOR_SET_FLAGS (actor, CLUTTER_ACTOR_MAPPED); + CLUTTER_NOTE (BACKEND, "[%p] show", self); if (CLUTTER_ACTOR_CLASS (clutter_stage_osx_parent_class)->show) CLUTTER_ACTOR_CLASS (clutter_stage_osx_parent_class)->show (actor); + CLUTTER_ACTOR_SET_FLAGS (actor, CLUTTER_ACTOR_MAPPED); + CLUTTER_OSX_POOL_ALLOC(); clutter_stage_osx_set_frame (self); @@ -358,7 +351,7 @@ clutter_stage_osx_hide (ClutterActor *actor) { ClutterStageOSX *self = CLUTTER_STAGE_OSX (actor); - CLUTTER_NOTE (BACKEND, "hide"); + CLUTTER_NOTE (BACKEND, "[%p] hide", self); CLUTTER_OSX_POOL_ALLOC(); @@ -394,7 +387,7 @@ clutter_stage_osx_request_coords (ClutterActor *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->y1), CLUTTER_UNITS_TO_INT (box->x2 - box->x1), @@ -416,29 +409,37 @@ clutter_stage_osx_request_coords (ClutterActor *actor, } /*************************************************************************/ -static void -clutter_stage_osx_set_title (ClutterStage *stage, - const char *title) +static ClutterActor * +clutter_stage_osx_get_wrapper (ClutterStageWindow *stage_window) { - 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(); - if (CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (stage))) + if (CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (self))) [self->window setTitle:[NSString stringWithUTF8String: title ? title : ""]]; CLUTTER_OSX_POOL_RELEASE(); } static void -clutter_stage_osx_set_fullscreen (ClutterStage *stage, - gboolean fullscreen) +clutter_stage_osx_set_fullscreen (ClutterStageWindow *stage_window, + 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(); @@ -476,14 +477,24 @@ clutter_stage_osx_set_fullscreen (ClutterStage *stage, 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 * -clutter_stage_osx_new (ClutterBackend *backend) +clutter_stage_osx_new (ClutterBackend *backend, + ClutterStage *wrapper) { ClutterStageOSX *self; self = g_object_new (CLUTTER_TYPE_STAGE_OSX, NULL); self->backend = backend; + self->wrapper = wrapper; return CLUTTER_ACTOR(self); } @@ -495,14 +506,13 @@ clutter_stage_osx_init (ClutterStageOSX *self) self->requisition_width = 640; self->requisition_height = 480; - CLUTTER_SET_PRIVATE_FLAGS(self, CLUTTER_ACTOR_SYNC_MATRICES); + CLUTTER_SET_PRIVATE_FLAGS(self, CLUTTER_ACTOR_IS_TOPLEVEL); } static void clutter_stage_osx_class_init (ClutterStageOSXClass *klass) { ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass); - ClutterStageClass *stage_class = CLUTTER_STAGE_CLASS (klass); actor_class->realize = clutter_stage_osx_realize; 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->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; } diff --git a/clutter/osx/clutter-stage-osx.h b/clutter/osx/clutter-stage-osx.h index 0e5d29d57..e24acfad2 100644 --- a/clutter/osx/clutter-stage-osx.h +++ b/clutter/osx/clutter-stage-osx.h @@ -26,7 +26,7 @@ #include #import -@class NSOpenGLView, NSWindow; +#import G_BEGIN_DECLS @@ -41,11 +41,19 @@ G_BEGIN_DECLS typedef struct _ClutterStageOSX ClutterStageOSX; typedef struct _ClutterStageOSXClass ClutterStageOSXClass; +@interface ClutterGLWindow : NSWindow +{ +@public + ClutterStageOSX *stage_osx; +} +@end + struct _ClutterStageOSX { - ClutterStage parent; + ClutterActor parent; ClutterBackend *backend; + ClutterStage *wrapper; NSWindow *window; NSOpenGLView *view; @@ -61,12 +69,13 @@ struct _ClutterStageOSX struct _ClutterStageOSXClass { - ClutterStageClass parent_class; + ClutterActorClass parent_class; }; 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