2007-10-26 Matthew Allum <mallum@openedhand.com>

* clutter/clutter-texture.c:
        * clutter/cogl/cogl.h:
        * clutter/cogl/gl/cogl-defines.h:
        * clutter/cogl/gles/cogl-defines.h:
        * clutter/cogl/gl/cogl.c:
        * clutter/cogl/gles/cogl.c:
        Switch from use of guint to COGLuint. Avoids problems when
        guint != GLuint on some platforms, i.e OSX.
        (Tommi Komulainen, #526)

        * clutter/Makefile.am:
        * clutter/osx/Makefile.am:
        * clutter/osx/clutter-backend-osx.c:
        * clutter/osx/clutter-backend-osx.h:
        * clutter/osx/clutter-event-osx.c:
        * clutter/osx/clutter-osx.h:
        * clutter/osx/clutter-stage-osx.c:
        * clutter/osx/clutter-stage-osx.h:
        * configure.ac:
        Add initial Cocoa/OSX Backend (by Tommi Komulainen, see #526)
This commit is contained in:
Matthew Allum 2007-10-26 22:06:45 +00:00
parent b7b7c60e5f
commit 737ac37f27
16 changed files with 1345 additions and 32 deletions

View File

@ -1,3 +1,26 @@
2007-10-26 Matthew Allum <mallum@openedhand.com>
* clutter/clutter-texture.c:
* clutter/cogl/cogl.h:
* clutter/cogl/gl/cogl-defines.h:
* clutter/cogl/gles/cogl-defines.h:
* clutter/cogl/gl/cogl.c:
* clutter/cogl/gles/cogl.c:
Switch from use of guint to COGLuint. Avoids problems when
guint != GLuint on some platforms, i.e OSX.
(Tommi Komulainen, #526)
* clutter/Makefile.am:
* clutter/osx/Makefile.am:
* clutter/osx/clutter-backend-osx.c:
* clutter/osx/clutter-backend-osx.h:
* clutter/osx/clutter-event-osx.c:
* clutter/osx/clutter-osx.h:
* clutter/osx/clutter-stage-osx.c:
* clutter/osx/clutter-stage-osx.h:
* configure.ac:
Add initial Cocoa/OSX Backend (by Tommi Komulainen, see #526)
2007-10-26 Emmanuele Bassi <ebassi@openedhand.com> 2007-10-26 Emmanuele Bassi <ebassi@openedhand.com>
* clutter/clutter-entry.c: Add a :x-align property for aligning * clutter/clutter-entry.c: Add a :x-align property for aligning

View File

@ -2,7 +2,7 @@ NULL =
SUBDIRS = cogl pango json $(clutterbackend) SUBDIRS = cogl pango json $(clutterbackend)
DIST_SUBDIRS = pango glx eglx eglnative cogl sdl json DIST_SUBDIRS = pango glx eglx eglnative cogl sdl json osx
target = $(clutterbackend) target = $(clutterbackend)

View File

@ -90,7 +90,7 @@ struct _ClutterTexturePrivate
ClutterTextureTileDimension *y_tiles; ClutterTextureTileDimension *y_tiles;
gint n_x_tiles; gint n_x_tiles;
gint n_y_tiles; gint n_y_tiles;
guint *tiles; COGLuint *tiles;
}; };
enum enum
@ -440,7 +440,7 @@ texture_upload_data (ClutterTexture *texture,
/* Single Texture */ /* Single Texture */
if (!priv->tiles) if (!priv->tiles)
{ {
priv->tiles = g_new (guint, 1); priv->tiles = g_new (COGLuint, 1);
glGenTextures (1, priv->tiles); glGenTextures (1, priv->tiles);
create_textures = TRUE; create_textures = TRUE;
} }
@ -511,7 +511,7 @@ texture_upload_data (ClutterTexture *texture,
if (priv->tiles == NULL) if (priv->tiles == NULL)
{ {
priv->tiles = g_new (guint, priv->n_x_tiles * priv->n_y_tiles); priv->tiles = g_new (COGLuint, priv->n_x_tiles * priv->n_y_tiles);
glGenTextures (priv->n_x_tiles * priv->n_y_tiles, priv->tiles); glGenTextures (priv->n_x_tiles * priv->n_y_tiles, priv->tiles);
create_textures = TRUE; create_textures = TRUE;
} }
@ -1423,7 +1423,7 @@ clutter_texture_set_from_yuv_data (ClutterTexture *texture,
if (!priv->tiles) if (!priv->tiles)
{ {
priv->tiles = g_new (guint, 1); priv->tiles = g_new (COGLuint, 1);
glGenTextures (1, priv->tiles); glGenTextures (1, priv->tiles);
} }

View File

@ -43,10 +43,7 @@
#define __COGL_H__ #define __COGL_H__
#include <glib.h> #include <glib.h>
#include <clutter/clutter-color.h> #include <clutter/clutter.h>
#include <clutter/clutter-feature.h>
#include <clutter/clutter-fixed.h>
#include <clutter/clutter-types.h>
#include "cogl-defines.h" #include "cogl-defines.h"
@ -133,13 +130,13 @@ cogl_texture_quad (gint x1,
ClutterFixed ty2); ClutterFixed ty2);
void void
cogl_textures_create (guint num, guint *textures); cogl_textures_create (guint num, COGLuint *textures);
void void
cogl_textures_destroy (guint num, const guint *textures); cogl_textures_destroy (guint num, const COGLuint *textures);
void void
cogl_texture_bind (COGLenum target, guint texture); cogl_texture_bind (COGLenum target, COGLuint texture);
void void
cogl_texture_set_alignment (COGLenum target, cogl_texture_set_alignment (COGLenum target,

View File

@ -27,16 +27,25 @@
#define __COGL_DEFINES_H__ #define __COGL_DEFINES_H__
#ifdef WIN32 #ifdef WIN32
#include <windows.h> #include <windows.h>
#include <GL/Glee.h> #include <GL/Glee.h>
#else #else
#if defined(HAVE_GL_GL_H)
#include <GL/gl.h> #include <GL/gl.h>
#elif defined(HAVE_OPENGL_GL_H)
#include <OpenGL/gl.h>
#endif #endif
#endif /* WIN32 */
G_BEGIN_DECLS G_BEGIN_DECLS
typedef GLenum COGLenum; typedef GLenum COGLenum;
typedef GLint COGLint; typedef GLint COGLint;
typedef GLuint COGLuint;
/* FIXME + DOCUMENT */ /* FIXME + DOCUMENT */

View File

@ -29,12 +29,6 @@
#include "cogl.h" #include "cogl.h"
#ifdef WIN32
#include <windows.h>
#include <GL/Glee.h>
#else
#include <GL/gl.h>
#endif
#include <string.h> #include <string.h>
#ifdef HAVE_CLUTTER_GLX #ifdef HAVE_CLUTTER_GLX
@ -333,7 +327,7 @@ cogl_texture_can_size (COGLenum target,
#ifdef GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB #ifdef GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB
if (target == CGL_TEXTURE_RECTANGLE_ARB) if (target == CGL_TEXTURE_RECTANGLE_ARB)
{ {
gint max_size = 0; GLint max_size = 0;
GE( glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &max_size) ); GE( glGetIntegerv(GL_MAX_RECTANGLE_TEXTURE_SIZE_ARB, &max_size) );
@ -381,19 +375,19 @@ cogl_texture_quad (gint x1,
} }
void void
cogl_textures_create (guint num, guint *textures) cogl_textures_create (guint num, COGLuint *textures)
{ {
GE( glGenTextures (num, textures) ); GE( glGenTextures (num, textures) );
} }
void void
cogl_textures_destroy (guint num, const guint *textures) cogl_textures_destroy (guint num, const COGLuint *textures)
{ {
GE( glDeleteTextures (num, textures) ); GE( glDeleteTextures (num, textures) );
} }
void void
cogl_texture_bind (COGLenum target, guint texture) cogl_texture_bind (COGLenum target, COGLuint texture)
{ {
GE( glBindTexture (target, texture) ); GE( glBindTexture (target, texture) );
} }
@ -696,12 +690,25 @@ cogl_get_viewport (ClutterFixed v[4])
void void
cogl_get_bitmasks (gint *red, gint *green, gint *blue, gint *alpha) cogl_get_bitmasks (gint *red, gint *green, gint *blue, gint *alpha)
{ {
GLint value;
if (red) if (red)
GE( glGetIntegerv(GL_RED_BITS, red) ); {
GE( glGetIntegerv(GL_RED_BITS, &value) );
*red = value;
}
if (green) if (green)
GE( glGetIntegerv(GL_GREEN_BITS, green) ); {
GE( glGetIntegerv(GL_GREEN_BITS, &value) );
*green = value;
}
if (blue) if (blue)
GE( glGetIntegerv(GL_BLUE_BITS, blue) ); {
GE( glGetIntegerv(GL_BLUE_BITS, &value) );
*blue = value;
}
if (alpha) if (alpha)
GE( glGetIntegerv(GL_ALPHA_BITS, alpha ) ); {
GE( glGetIntegerv(GL_ALPHA_BITS, &value ) );
*alpha = value;
}
} }

View File

@ -439,6 +439,7 @@ G_BEGIN_DECLS
typedef GLenum COGLenum; typedef GLenum COGLenum;
typedef GLint COGLint; typedef GLint COGLint;
typedef GLuint COGLuint;
/* extras */ /* extras */

View File

@ -323,19 +323,19 @@ cogl_texture_quad (gint x1,
} }
void void
cogl_textures_create (guint num, guint *textures) cogl_textures_create (guint num, COGLuint *textures)
{ {
GE( glGenTextures (num, textures) ); GE( glGenTextures (num, textures) );
} }
void void
cogl_textures_destroy (guint num, const guint *textures) cogl_textures_destroy (guint num, const COGLuint *textures)
{ {
GE( glDeleteTextures (num, textures) ); GE( glDeleteTextures (num, textures) );
} }
void void
cogl_texture_bind (COGLenum target, guint texture) cogl_texture_bind (COGLenum target, COGLuint texture)
{ {
GE( glBindTexture (target, texture) ); GE( glBindTexture (target, texture) );
} }

24
clutter/osx/Makefile.am Normal file
View File

@ -0,0 +1,24 @@
libclutterincludedir = $(includedir)/clutter-@CLUTTER_API_VERSION@/clutter
libclutterinclude_HEADERS = clutter-osx.h
INCLUDES = \
-DG_LOG_DOMAIN=\"ClutterOSX\" \
-I$(top_srcdir) \
-I$(top_srcdir)/clutter/cogl \
-I$(top_srcdir)/clutter/cogl/@CLUTTER_COGL@ \
$(CLUTTER_CFLAGS) \
$(CLUTTER_DEBUG_CFLAGS) \
$(GCC_FLAGS) \
-xobjective-c
LDADD = $(CLUTTER_LIBS)
noinst_LTLIBRARIES = libclutter-osx.la
libclutter_osx_la_SOURCES = \
clutter-backend-osx.h \
clutter-backend-osx.c \
clutter-event-osx.c \
clutter-stage-osx.h \
clutter-stage-osx.c \
clutter-osx.h

View File

@ -0,0 +1,182 @@
/* Clutter - An OpenGL based 'interactive canvas' library.
* OSX backend - initial entry point
*
* Copyright (C) 2007 Tommi Komulainen <tommi.komulainen@iki.fi>
* Copyright (C) 2007 OpenedHand Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include "clutter-osx.h"
#include "clutter-backend-osx.h"
#include "clutter-stage-osx.h"
#include <clutter/clutter-debug.h>
#import <AppKit/AppKit.h>
G_DEFINE_TYPE (ClutterBackendOSX, clutter_backend_osx, CLUTTER_TYPE_BACKEND)
/*************************************************************************/
static gboolean
clutter_backend_osx_post_parse (ClutterBackend *backend,
GError **error)
{
CLUTTER_NOTE (BACKEND, "post_parse");
CLUTTER_OSX_POOL_ALLOC();
/* Bring our app to foreground, background apps don't appear in dock or
* accept keyboard focus.
*/
const ProcessSerialNumber psn = { 0, kCurrentProcess };
TransformProcessType (&psn, kProcessTransformToForegroundApplication);
/* Also raise our app to front, otherwise our window will remain under the
* terminal.
*/
SetFrontProcess (&psn);
[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.
*/
NSOpenGLPixelFormatAttribute attrs[] = {
NSOpenGLPFADoubleBuffer,
0
};
self->pixel_format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];
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);
CLUTTER_OSX_POOL_RELEASE();
return TRUE;
}
static void
clutter_backend_osx_init_events (ClutterBackend *backend)
{
CLUTTER_NOTE (BACKEND, "init_events");
_clutter_events_osx_init ();
}
static ClutterActor *
clutter_backend_osx_get_stage (ClutterBackend *backend)
{
ClutterBackendOSX *self = CLUTTER_BACKEND_OSX (backend);
return self->stage;
}
static void
clutter_backend_osx_redraw (ClutterBackend *backend)
{
ClutterBackendOSX *self = CLUTTER_BACKEND_OSX (backend);
ClutterStageOSX *stage_osx;
stage_osx = CLUTTER_STAGE_OSX (self->stage);
[stage_osx->view setNeedsDisplay: YES];
}
/*************************************************************************/
static void
clutter_backend_osx_init (ClutterBackendOSX *self)
{
}
static void
clutter_backend_osx_dispose (GObject *object)
{
ClutterBackendOSX *self = CLUTTER_BACKEND_OSX (object);
if (self->stage)
{
clutter_actor_destroy (self->stage);
self->stage = NULL;
}
[self->context release];
self->context = NULL;
[self->pixel_format release];
self->pixel_format = NULL;
G_OBJECT_CLASS (clutter_backend_osx_parent_class)->dispose (object);
}
static void
clutter_backend_osx_class_init (ClutterBackendOSXClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass);
object_class->dispose = clutter_backend_osx_dispose;
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->init_events = clutter_backend_osx_init_events;
backend_class->get_stage = clutter_backend_osx_get_stage;
backend_class->redraw = clutter_backend_osx_redraw;
}
GType
_clutter_backend_impl_get_type (void)
{
return clutter_backend_osx_get_type ();
}

View File

@ -0,0 +1,60 @@
/* Clutter - An OpenGL based 'interactive canvas' library.
* OSX backend - initial entry point
*
* Copyright (C) 2007 Tommi Komulainen <tommi.komulainen@iki.fi>
* Copyright (C) 2007 OpenedHand Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __CLUTTER_BACKEND_OSX_H__
#define __CLUTTER_BACKEND_OSX_H__
#include <clutter/clutter-backend.h>
@class NSOpenGLPixelFormat, NSOpenGLContext;
G_BEGIN_DECLS
#define CLUTTER_TYPE_BACKEND_OSX (clutter_backend_osx_get_type())
#define CLUTTER_BACKEND_OSX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),CLUTTER_TYPE_BACKEND_OSX,ClutterBackendOSX))
#define CLUTTER_BACKEND_OSX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),CLUTTER_TYPE_BACKEND_OSX,ClutterBackend))
#define CLUTTER_IS_BACKEND_OSX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),CLUTTER_TYPE_BACKEND_OSX))
#define CLUTTER_IS_BACKEND_OSX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),CLUTTER_TYPE_BACKEND_OSX))
#define CLUTTER_BACKEND_OSX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),CLUTTER_TYPE_BACKEND_OSX,ClutterBackendOSXClass))
typedef struct _ClutterBackendOSX ClutterBackendOSX;
typedef struct _ClutterBackendOSXClass ClutterBackendOSXClass;
struct _ClutterBackendOSX
{
ClutterBackend parent;
NSOpenGLPixelFormat *pixel_format;
NSOpenGLContext *context;
ClutterActor *stage;
};
struct _ClutterBackendOSXClass
{
ClutterBackendClass parent_class;
};
GType clutter_backend_osx_get_type (void) G_GNUC_CONST;
G_END_DECLS
#endif /* __CLUTTER_BACKEND_OSX_H__ */

View File

@ -0,0 +1,387 @@
/* Clutter - An OpenGL based 'interactive canvas' library.
* OSX backend - event loops integration
*
* Copyright (C) 2007 Tommi Komulainen <tommi.komulainen@iki.fi>
* Copyright (C) 2007 OpenedHand Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include "clutter-osx.h"
#import <AppKit/AppKit.h>
#include <glib/gmain.h>
#include <clutter/clutter-debug.h>
#include <clutter/clutter-private.h>
#include <clutter/clutter-keysyms.h>
/* Overriding the poll function because the events are not delivered over file
* descriptors and setting up a GSource would just introduce polling.
*/
static GPollFunc old_poll_func = NULL;
/*************************************************************************/
@interface NSEvent (Clutter)
- (gint)clutterTime;
- (gint)clutterButton;
- (void)clutterX:(gint*)ptrX y:(gint*)ptrY;
- (gint)clutterModifierState;
- (guint)clutterKeyVal;
@end
@implementation NSEvent (Clutter)
- (gint)clutterTime
{
return [self timestamp] * 1000;
}
- (gint)clutterButton
{
switch ([self buttonNumber])
{
case 0: return 1; /* left */
case 1: return 3; /* right */
case 2: return 2; /* middle */
default: return 1 + [self buttonNumber];
}
}
- (void)clutterX:(gint*)ptrX y:(gint*)ptrY
{
NSView *view = [[self window] contentView];
NSPoint pt = [view convertPoint:[self locationInWindow] fromView:nil];
*ptrX = (gint)pt.x;
*ptrY = (gint)pt.y;
}
- (gint)clutterModifierState
{
guint mods = [self modifierFlags];
gint rv = 0;
if (mods & NSAlphaShiftKeyMask)
rv |= CLUTTER_LOCK_MASK;
if (mods & NSShiftKeyMask)
rv |= CLUTTER_SHIFT_MASK;
if (mods & NSControlKeyMask)
rv |= CLUTTER_CONTROL_MASK;
if (mods & NSAlternateKeyMask)
rv |= CLUTTER_MOD1_MASK;
if (mods & NSCommandKeyMask)
rv |= CLUTTER_MOD2_MASK;
return rv;
}
- (guint)clutterKeyVal
{
/* FIXME: doing this right is a lot of work, see gdkkeys-quartz.c in gtk+
* For now handle some common/simple keys only. Might not work with other
* hardware than mine (MacBook Pro, finnish layout). Sorry.
*/
unichar c = [[self characters] characterAtIndex:0];
/* Latin-1 characters, 1:1 mapping - this ought to be reliable */
if ((c >= 0x0020 && c <= 0x007e) ||
(c >= 0x00a0 && c <= 0x00ff))
return c;
switch (c)
{
/* these should be fairly standard */
/* (maybe add 0x0008 (Ctrl+H) for backspace too) */
case 0x000d: return CLUTTER_Return;
case 0x001b: return CLUTTER_Escape;
case 0x007f: return CLUTTER_BackSpace;
/* Defined in NSEvent.h */
case NSUpArrowFunctionKey: return CLUTTER_Up;
case NSDownArrowFunctionKey: return CLUTTER_Down;
case NSLeftArrowFunctionKey: return CLUTTER_Left;
case NSRightArrowFunctionKey: return CLUTTER_Right;
case NSF1FunctionKey: return CLUTTER_F1;
case NSF2FunctionKey: return CLUTTER_F2;
case NSF3FunctionKey: return CLUTTER_F3;
case NSF4FunctionKey: return CLUTTER_F4;
case NSF5FunctionKey: return CLUTTER_F5;
case NSF6FunctionKey: return CLUTTER_F6;
case NSF7FunctionKey: return CLUTTER_F7;
case NSF8FunctionKey: return CLUTTER_F8;
case NSF9FunctionKey: return CLUTTER_F9;
case NSF10FunctionKey: return CLUTTER_F10;
case NSF11FunctionKey: return CLUTTER_F11;
case NSF12FunctionKey: return CLUTTER_F12;
case NSInsertFunctionKey: return CLUTTER_Insert;
case NSDeleteFunctionKey: return CLUTTER_Delete;
case NSHomeFunctionKey: return CLUTTER_Home;
case NSEndFunctionKey: return CLUTTER_End;
case NSPageUpFunctionKey: return CLUTTER_Page_Up;
case NSPageDownFunctionKey: return CLUTTER_Page_Down;
}
CLUTTER_NOTE (BACKEND, "unhandled unicode key 0x%x (%d)", c, c);
/* hardware dependent, worksforme(tm) Redundant due to above, left around as
* example.
*/
switch ([self keyCode])
{
case 115: return CLUTTER_Home;
case 116: return CLUTTER_Page_Up;
case 117: return CLUTTER_Delete;
case 119: return CLUTTER_End;
case 121: return CLUTTER_Page_Down;
case 123: return CLUTTER_Left;
case 124: return CLUTTER_Right;
case 125: return CLUTTER_Down;
case 126: return CLUTTER_Up;
}
return 0;
}
@end
/*************************************************************************/
static gboolean
clutter_event_osx_translate (NSEvent *nsevent, ClutterEvent *event)
{
event->any.time = [nsevent clutterTime];
switch ([nsevent type])
{
case NSLeftMouseDown:
case NSRightMouseDown:
case NSOtherMouseDown:
event->type = CLUTTER_BUTTON_PRESS;
/* fall through */
case NSLeftMouseUp:
case NSRightMouseUp:
case NSOtherMouseUp:
if (event->type != CLUTTER_BUTTON_PRESS)
event->type = CLUTTER_BUTTON_RELEASE;
event->button.button = [nsevent clutterButton];
event->button.click_count = [nsevent clickCount];
event->motion.modifier_state = [nsevent clutterModifierState];
[nsevent clutterX:&(event->button.x) y:&(event->button.y)];
CLUTTER_NOTE (EVENT, "button %d %s at %d,%d clicks=%d",
[nsevent buttonNumber],
event->type == CLUTTER_BUTTON_PRESS ? "press" : "release",
event->button.x, event->button.y,
event->button.click_count);
return TRUE;
case NSMouseMoved:
case NSLeftMouseDragged:
case NSRightMouseDragged:
case NSOtherMouseDragged:
event->type = CLUTTER_MOTION;
[nsevent clutterX:(&event->motion.x) y:&(event->motion.y)];
event->motion.modifier_state = [nsevent clutterModifierState];
CLUTTER_NOTE (EVENT, "motion %d at %d,%d",
[nsevent buttonNumber],
event->button.x, event->button.y);
return TRUE;
case NSKeyDown:
event->type = CLUTTER_KEY_PRESS;
/* fall through */
case NSKeyUp:
if (event->type != CLUTTER_KEY_PRESS)
event->type = CLUTTER_KEY_RELEASE;
event->key.hardware_keycode = [nsevent keyCode];
event->key.modifier_state = [nsevent clutterModifierState];
event->key.keyval = [nsevent clutterKeyVal];
CLUTTER_NOTE (EVENT, "key %d (%s) (%s) %s, keyval %d",
[nsevent keyCode],
[[nsevent characters] UTF8String],
[[nsevent charactersIgnoringModifiers] UTF8String],
event->type == CLUTTER_KEY_PRESS ? "press" : "release",
event->key.keyval);
return TRUE;
default:
CLUTTER_NOTE (EVENT, "unhandled event %d", [nsevent type]);
break;
}
return FALSE;
}
void
_clutter_event_osx_put (NSEvent *nsevent)
{
ClutterEvent event;
event.type = CLUTTER_NOTHING;
if (clutter_event_osx_translate (nsevent, &event))
{
g_assert (event.type != CLUTTER_NOTHING);
clutter_event_put (&event);
}
}
typedef struct {
CFSocketRef sock;
CFRunLoopSourceRef source;
gushort revents;
} SocketInfo;
static void
socket_activity_cb (CFSocketRef sock,
CFSocketCallBackType cbtype,
CFDataRef address,
const void *data,
void *info)
{
SocketInfo *si = info;
if (cbtype & kCFSocketReadCallBack)
si->revents |= G_IO_IN;
if (cbtype & kCFSocketWriteCallBack)
si->revents |= G_IO_OUT;
}
static gint
clutter_event_osx_poll_func (GPollFD *ufds, guint nfds, gint timeout)
{
NSDate *until_date;
NSEvent *nsevent;
SocketInfo *sockets = NULL;
gint n_active = 0;
CLUTTER_OSX_POOL_ALLOC();
if (timeout == -1)
until_date = [NSDate distantFuture];
else if (timeout == 0)
until_date = [NSDate distantPast];
else
until_date = [NSDate dateWithTimeIntervalSinceNow:timeout/1000.0];
/* File descriptors appear to be similar enough to sockets so that they can
* be used in CFRunLoopSource.
*
* We could also launch a thread to call old_poll_func and signal the main
* thread. No idea which way is better.
*/
if (nfds > 0)
{
CFRunLoopRef run_loop;
run_loop = [[NSRunLoop currentRunLoop] getCFRunLoop];
sockets = g_new (SocketInfo, nfds);
int i;
for (i = 0; i < nfds; i++)
{
SocketInfo *si = &sockets[i];
CFSocketCallBackType cbtype;
cbtype = 0;
if (ufds[i].events & G_IO_IN)
cbtype |= kCFSocketReadCallBack;
if (ufds[i].events & G_IO_OUT)
cbtype |= kCFSocketWriteCallBack;
/* FIXME: how to handle G_IO_HUP and G_IO_ERR? */
const CFSocketContext ctxt = {
0, si, NULL, NULL, NULL
};
si->sock = CFSocketCreateWithNative (NULL, ufds[i].fd, cbtype, socket_activity_cb, &ctxt);
si->source = CFSocketCreateRunLoopSource (NULL, si->sock, 0);
si->revents = 0;
CFRunLoopAddSource (run_loop, si->source, kCFRunLoopCommonModes);
}
}
nsevent = [NSApp nextEventMatchingMask: NSAnyEventMask
untilDate: until_date
inMode: NSDefaultRunLoopMode
dequeue: YES];
/* Push the events to NSApplication which will do some magic(?) and forward
* interesting events to our view. While we could do event translation here
* we'd also need to filter out clicks on titlebar, and perhaps do special
* handling for the first click (couldn't figure it out - always ended up
* missing a screen refresh) and maybe other things.
*/
[NSApp sendEvent:nsevent];
if (nfds > 0)
{
int i;
for (i = 0; i < nfds; i++)
{
SocketInfo *si = &sockets[i];
if ((ufds[i].revents = si->revents) != 0)
n_active++;
/* Invalidating the source also removes it from run loop and
* guarantees the callback is never called again.
* CFRunLoopRemoveSource removes the source from the loop, but might
* still call the callback which would be badly timed.
*/
CFRunLoopSourceInvalidate (si->source);
CFRelease (si->source);
CFRelease (si->sock);
}
g_free (sockets);
}
/* FIXME this could result in infinite loop */
ClutterEvent *event = clutter_event_get ();
while (event)
{
clutter_do_event (event);
clutter_event_free (event);
event = clutter_event_get ();
}
CLUTTER_OSX_POOL_RELEASE();
return n_active;
}
void
_clutter_events_osx_init (void)
{
g_assert (old_poll_func == NULL);
old_poll_func = g_main_context_get_poll_func (NULL);
g_main_context_set_poll_func (NULL, clutter_event_osx_poll_func);
}
void
_clutter_events_osx_uninit (void)
{
if (old_poll_func)
{
g_main_context_set_poll_func (NULL, old_poll_func);
old_poll_func = NULL;
}
}

41
clutter/osx/clutter-osx.h Normal file
View File

@ -0,0 +1,41 @@
/* Clutter - An OpenGL based 'interactive canvas' library.
* OSX backend
*
* Copyright (C) 2007 Tommi Komulainen <tommi.komulainen@iki.fi>
* Copyright (C) 2007 OpenedHand Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __CLUTTER_OSX_H__
#define __CLUTTER_OSX_H__
#include <clutter/clutter-stage.h>
@class NSEvent;
G_BEGIN_DECLS
#define CLUTTER_OSX_POOL_ALLOC() NSAutoreleasePool *autorelease_pool = [[NSAutoreleasePool alloc] init]
#define CLUTTER_OSX_POOL_RELEASE() [autorelease_pool release];
void _clutter_events_osx_init (void);
void _clutter_events_osx_uninit (void);
void _clutter_event_osx_put (NSEvent *nsevent);
G_END_DECLS
#endif /* __CLUTTER_OSX_H__ */

View File

@ -0,0 +1,496 @@
/* Clutter - An OpenGL based 'interactive canvas' library.
* OSX backend - integration with NSWindow and NSView
*
* Copyright (C) 2007 Tommi Komulainen <tommi.komulainen@iki.fi>
* Copyright (C) 2007 OpenedHand Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include "clutter-osx.h"
#include "clutter-stage-osx.h"
#include "clutter-backend-osx.h"
#import <AppKit/AppKit.h>
#include <clutter/clutter-debug.h>
#include <clutter/clutter-private.h>
G_DEFINE_TYPE (ClutterStageOSX, clutter_stage_osx, CLUTTER_TYPE_STAGE)
/* FIXME: this should be in clutter-stage.c */
static void
clutter_stage_osx_state_update (ClutterStageOSX *self,
ClutterStageState unset_flags,
ClutterStageState set_flags);
#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
{
if ((self = [super initWithContentRect: [aView frame]
styleMask: NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask
backing: NSBackingStoreBuffered
defer: NO]) != nil)
{
[self setDelegate: self];
[self useOptimizedDrawing: YES];
[self setContentView: aView];
[self setTitle:[NSString stringWithUTF8String: aTitle]];
stage = aStage;
}
return self;
}
- (BOOL) windowShouldClose: (id) sender
{
CLUTTER_NOTE (BACKEND, "windowShouldClose");
ClutterEvent event;
event.type = CLUTTER_DELETE;
clutter_event_put (&event);
return NO;
}
- (NSRect) constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen*)aScreen
{
/* in fullscreen mode we don't want to be constrained by menubar or dock
* FIXME: calculate proper constraints depending on fullscreen mode
*/
return frameRect;
}
- (void) windowDidBecomeKey:(NSNotification*)aNotification
{
CLUTTER_NOTE (BACKEND, "windowDidBecomeKey");
if (stage->stage_state & CLUTTER_STAGE_STATE_FULLSCREEN)
[self setLevel: CLUTTER_OSX_FULLSCREEN_WINDOW_LEVEL];
clutter_stage_osx_state_update (stage, 0, CLUTTER_STAGE_STATE_ACTIVATED);
}
- (void) windowDidResignKey:(NSNotification*)aNotification
{
CLUTTER_NOTE (BACKEND, "windowDidResignKey");
if (stage->stage_state & CLUTTER_STAGE_STATE_FULLSCREEN)
{
[self setLevel: NSNormalWindowLevel];
[self orderBack: nil];
}
clutter_stage_osx_state_update (stage, CLUTTER_STAGE_STATE_ACTIVATED, 0);
}
@end
/*************************************************************************/
@interface ClutterGLView : NSOpenGLView
{
ClutterActor *stage;
}
- (void) drawRect: (NSRect) bounds;
@end
@implementation ClutterGLView
- (id) initWithFrame: (NSRect)aFrame pixelFormat:(NSOpenGLPixelFormat*)aFormat stage:(ClutterActor*)aStage
{
if ((self = [super initWithFrame:aFrame pixelFormat:aFormat]) != nil)
{
self->stage = aStage;
}
return self;
}
- (void) drawRect: (NSRect) bounds
{
clutter_actor_paint (self->stage);
[[self openGLContext] flushBuffer];
}
/* In order to receive key events */
- (BOOL) acceptsFirstResponder
{
return YES;
}
/* We want 0,0 top left */
- (BOOL) isFlipped
{
return YES;
}
- (void) setFrameSize: (NSSize) aSize
{
CLUTTER_NOTE (BACKEND, "setFrameSize: %dx%d",
(int)aSize.width, (int)aSize.height);
[super setFrameSize: aSize];
clutter_actor_set_size (self->stage, (int)aSize.width, (int)aSize.height);
CLUTTER_SET_PRIVATE_FLAGS(self->stage, CLUTTER_ACTOR_SYNC_MATRICES);
}
/* Simply forward all events that reach our view to clutter. */
#define EVENT_HANDLER(event) -(void)event:(NSEvent *)theEvent { \
_clutter_event_osx_put (theEvent); \
}
EVENT_HANDLER(mouseDown)
EVENT_HANDLER(mouseDragged)
EVENT_HANDLER(mouseUp)
EVENT_HANDLER(mouseMoved)
EVENT_HANDLER(mouseEntered)
EVENT_HANDLER(mouseExited)
EVENT_HANDLER(rightMouseDown)
EVENT_HANDLER(rightMouseDragged)
EVENT_HANDLER(rightMouseUp)
EVENT_HANDLER(otherMouseDown)
EVENT_HANDLER(otherMouseDragged)
EVENT_HANDLER(otherMouseUp)
EVENT_HANDLER(scrollWheel)
EVENT_HANDLER(keyDown)
EVENT_HANDLER(keyUp)
EVENT_HANDLER(flagsChanged)
EVENT_HANDLER(helpRequested)
EVENT_HANDLER(tabletPoint)
EVENT_HANDLER(tabletProximity)
#undef EVENT_HANDLER
@end
/*************************************************************************/
static void
clutter_stage_osx_state_update (ClutterStageOSX *self,
ClutterStageState unset_flags,
ClutterStageState set_flags)
{
ClutterStageStateEvent event;
event.new_state = self->stage_state;
event.new_state |= set_flags;
event.new_state &= ~unset_flags;
if (event.new_state == self->stage_state)
return;
event.changed_mask = event.new_state ^ self->stage_state;
self->stage_state = event.new_state;
event.type = CLUTTER_STAGE_STATE;
clutter_event_put ((ClutterEvent*)&event);
}
static void
clutter_stage_osx_save_frame (ClutterStageOSX *self)
{
if (CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (self)))
{
g_assert (self->window != NULL);
self->normalFrame = [self->window frame];
self->haveNormalFrame = TRUE;
}
}
static void
clutter_stage_osx_set_frame (ClutterStageOSX *self)
{
g_assert (CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (self)));
g_assert (self->window != NULL);
if (self->stage_state & CLUTTER_STAGE_STATE_FULLSCREEN)
{
/* Raise above the menubar (and dock) covering the whole screen.
*
* NOTE: This effectively breaks Option-Tabbing as our window covers
* all other applications completely. However we deal with the situation
* by lowering the window to the bottom of the normal level stack on
* windowDidResignKey notification.
*/
[self->window setLevel: CLUTTER_OSX_FULLSCREEN_WINDOW_LEVEL];
[self->window setFrame: [self->window frameRectForContentRect: [[self->window screen] frame]] display: NO];
}
else
{
[self->window setLevel: NSNormalWindowLevel];
if (self->haveNormalFrame)
[self->window setFrame: self->normalFrame display: NO];
else
/* looks better than positioning to 0,0 (bottom right) */
[self->window center];
}
}
/*************************************************************************/
static void
clutter_stage_osx_realize (ClutterActor *actor)
{
ClutterStageOSX *self = CLUTTER_STAGE_OSX (actor);
ClutterBackendOSX *backend_osx;
CLUTTER_NOTE (BACKEND, "realize");
CLUTTER_OSX_POOL_ALLOC();
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);
self->view = [[ClutterGLView alloc]
initWithFrame: rect
pixelFormat: backend_osx->pixel_format
stage: actor];
self->window = [[ClutterGLWindow alloc]
initWithView: self->view
UTF8Title: clutter_stage_get_title (CLUTTER_STAGE (self))
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();
CLUTTER_SET_PRIVATE_FLAGS(self, CLUTTER_ACTOR_SYNC_MATRICES);
}
static void
clutter_stage_osx_unrealize (ClutterActor *actor)
{
ClutterStageOSX *self = CLUTTER_STAGE_OSX (actor);
CLUTTER_NOTE (BACKEND, "unrealize");
CLUTTER_OSX_POOL_ALLOC();
[self->view release];
[self->window close];
self->view = NULL;
self->window = NULL;
CLUTTER_OSX_POOL_RELEASE();
if (CLUTTER_ACTOR_CLASS (clutter_stage_osx_parent_class)->unrealize)
CLUTTER_ACTOR_CLASS (clutter_stage_osx_parent_class)->unrealize (actor);
}
static void
clutter_stage_osx_show (ClutterActor *actor)
{
ClutterStageOSX *self = CLUTTER_STAGE_OSX (actor);
CLUTTER_NOTE (BACKEND, "show");
if (CLUTTER_ACTOR_CLASS (clutter_stage_osx_parent_class)->show)
CLUTTER_ACTOR_CLASS (clutter_stage_osx_parent_class)->show (actor);
CLUTTER_OSX_POOL_ALLOC();
clutter_stage_osx_set_frame (self);
[self->window makeKeyAndOrderFront: nil];
CLUTTER_OSX_POOL_RELEASE();
}
static void
clutter_stage_osx_hide (ClutterActor *actor)
{
ClutterStageOSX *self = CLUTTER_STAGE_OSX (actor);
CLUTTER_NOTE (BACKEND, "hide");
CLUTTER_OSX_POOL_ALLOC();
[self->window orderOut: nil];
CLUTTER_OSX_POOL_RELEASE();
if (CLUTTER_ACTOR_CLASS (clutter_stage_osx_parent_class)->hide)
CLUTTER_ACTOR_CLASS (clutter_stage_osx_parent_class)->hide (actor);
}
static void
clutter_stage_osx_query_coords (ClutterActor *actor,
ClutterActorBox *box)
{
ClutterStageOSX *self = CLUTTER_STAGE_OSX (actor);
CLUTTER_OSX_POOL_ALLOC();
box->x1 = 0;
box->y1 = 0;
box->x2 = box->x1 + CLUTTER_UNITS_FROM_FLOAT (self->requisition_width);
box->y2 = box->y1 + CLUTTER_UNITS_FROM_FLOAT (self->requisition_height);
CLUTTER_OSX_POOL_RELEASE();
}
static void
clutter_stage_osx_request_coords (ClutterActor *actor,
ClutterActorBox *box)
{
ClutterStageOSX *self = CLUTTER_STAGE_OSX (actor);
CLUTTER_NOTE (BACKEND, "request_coords: %d,%d %dx%d",
CLUTTER_UNITS_TO_INT (box->x1),
CLUTTER_UNITS_TO_INT (box->y1),
CLUTTER_UNITS_TO_INT (box->x2 - box->x1),
CLUTTER_UNITS_TO_INT (box->y2 - box->y1));
self->requisition_width = CLUTTER_UNITS_TO_INT (box->x2 - box->x1);
self->requisition_height = CLUTTER_UNITS_TO_INT (box->y2 - box->y1);
if (CLUTTER_ACTOR_IS_REALIZED (actor))
{
CLUTTER_OSX_POOL_ALLOC();
NSSize size = NSMakeSize(self->requisition_width,
self->requisition_height);
[self->window setContentSize: size];
CLUTTER_OSX_POOL_RELEASE();
}
}
/*************************************************************************/
static void
clutter_stage_osx_set_title (ClutterStage *stage,
const char *title)
{
ClutterStageOSX *self = CLUTTER_STAGE_OSX (stage);
CLUTTER_NOTE (BACKEND, "set_title: %s", title);
CLUTTER_OSX_POOL_ALLOC();
if (CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (stage)))
[self->window setTitle:[NSString stringWithUTF8String:title]];
CLUTTER_OSX_POOL_RELEASE();
}
static void
clutter_stage_osx_set_fullscreen (ClutterStage *stage,
gboolean fullscreen)
{
ClutterStageOSX *self = CLUTTER_STAGE_OSX (stage);
CLUTTER_NOTE (BACKEND, "set_fullscreen: %u", fullscreen);
CLUTTER_OSX_POOL_ALLOC();
/* Make sure to update the state before clutter_stage_osx_set_frame.
*
* Toggling fullscreen isn't atomic, there's two "events" involved:
* - stage state change (via state_update)
* - stage size change (via set_frame -> setFrameSize / set_size)
*
* We do state change first. Not sure there's any difference.
*/
if (fullscreen)
clutter_stage_osx_state_update (self, 0, CLUTTER_STAGE_STATE_FULLSCREEN);
else
clutter_stage_osx_state_update (self, CLUTTER_STAGE_STATE_FULLSCREEN, 0);
if (CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (self)))
{
if (fullscreen)
clutter_stage_osx_save_frame (self);
clutter_stage_osx_set_frame (self);
}
else if (fullscreen)
{
/* FIXME: if you go fullscreen before realize we throw away the normal
* stage size and can't return. Need to maintain them separately.
*/
NSSize size = [[NSScreen mainScreen] frame].size;
clutter_actor_set_size (CLUTTER_ACTOR (self),
(int)size.width, (int)size.height);
}
CLUTTER_OSX_POOL_RELEASE();
}
/*************************************************************************/
ClutterActor *
clutter_stage_osx_new (ClutterBackend *backend)
{
ClutterStageOSX *self;
self = g_object_new (CLUTTER_TYPE_STAGE_OSX, NULL);
self->backend = backend;
return CLUTTER_ACTOR(self);
}
/*************************************************************************/
static void
clutter_stage_osx_init (ClutterStageOSX *self)
{
self->requisition_width = 640;
self->requisition_height = 480;
CLUTTER_SET_PRIVATE_FLAGS(self, CLUTTER_ACTOR_SYNC_MATRICES);
}
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;
actor_class->show = clutter_stage_osx_show;
actor_class->hide = clutter_stage_osx_hide;
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;
}

View File

@ -0,0 +1,73 @@
/* Clutter - An OpenGL based 'interactive canvas' library.
* OSX backend - integration with NSWindow and NSView
*
* Copyright (C) 2007 Tommi Komulainen <tommi.komulainen@iki.fi>
* Copyright (C) 2007 OpenedHand Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __CLUTTER_STAGE_OSX_H__
#define __CLUTTER_STAGE_OSX_H__
#include <clutter/clutter-stage.h>
#include <clutter/clutter-backend.h>
#import <Foundation/Foundation.h>
@class NSOpenGLView, NSWindow;
G_BEGIN_DECLS
/* convenience macros */
#define CLUTTER_TYPE_STAGE_OSX (clutter_stage_osx_get_type())
#define CLUTTER_STAGE_OSX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),CLUTTER_TYPE_STAGE_OSX,ClutterStageOSX))
#define CLUTTER_STAGE_OSX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),CLUTTER_TYPE_STAGE_OSX,ClutterStage))
#define CLUTTER_IS_STAGE_OSX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),CLUTTER_TYPE_STAGE_OSX))
#define CLUTTER_IS_STAGE_OSX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),CLUTTER_TYPE_STAGE_OSX))
#define CLUTTER_STAGE_OSX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),CLUTTER_TYPE_STAGE_OSX,ClutterStageOSXClass))
typedef struct _ClutterStageOSX ClutterStageOSX;
typedef struct _ClutterStageOSXClass ClutterStageOSXClass;
struct _ClutterStageOSX
{
ClutterStage parent;
ClutterBackend *backend;
NSWindow *window;
NSOpenGLView *view;
gboolean haveNormalFrame;
NSRect normalFrame;
gint requisition_width;
gint requisition_height;
ClutterStageState stage_state;
};
struct _ClutterStageOSXClass
{
ClutterStageClass parent_class;
};
GType clutter_stage_osx_get_type (void) G_GNUC_CONST;
ClutterActor* clutter_stage_osx_new (ClutterBackend *backend);
G_END_DECLS
#endif /* __CLUTTER_STAGE_OSX_H__ */

View File

@ -258,8 +258,20 @@ case $clutterbackend in
EGL_CFLAGS="$TSLIB_CFLAGS" EGL_CFLAGS="$TSLIB_CFLAGS"
;; ;;
osx)
*) AC_MSG_ERROR([Invalid backend for Clutter: use glx,sdl, eglx or eglnative]) CLUTTER_FLAVOUR="osx"
AC_DEFINE([HAVE_CLUTTER_OSX], [1], [Have the OSX backend])
CLUTTER_COGL="gl"
AC_DEFINE([HAVE_COGL_GL], [1], [Have GL for rendering])
OSX_LIBS="-framework Cocoa -framework OpenGL"
AC_CHECK_HEADERS([OpenGL/gl.h],,
[AC_MSG_ERROR([Unable to locate required GL headers])])
;;
*) AC_MSG_ERROR([Invalid backend for Clutter: use glx,sdl,osx,eglx or eglnative])
;; ;;
esac esac
@ -351,8 +363,8 @@ dnl ========================================================================
AC_SUBST(GCC_FLAGS) AC_SUBST(GCC_FLAGS)
CLUTTER_CFLAGS="$SDL_CFLAGS $EGL_CFLAGS $GLX_CFLAGS $CLUTTER_DEPS_CFLAGS " CLUTTER_CFLAGS="$SDL_CFLAGS $EGL_CFLAGS $GLX_CFLAGS $OSX_CFLAGS $CLUTTER_DEPS_CFLAGS "
CLUTTER_LIBS="$SDL_LIBS $EGL_LIBS $GLX_LIBS $CLUTTER_DEPS_LIBS" CLUTTER_LIBS="$SDL_LIBS $EGL_LIBS $GLX_LIBS $OSX_LIBS $CLUTTER_DEPS_LIBS"
AC_SUBST(CLUTTER_CFLAGS) AC_SUBST(CLUTTER_CFLAGS)
AC_SUBST(CLUTTER_LIBS) AC_SUBST(CLUTTER_LIBS)
@ -364,6 +376,7 @@ AC_CONFIG_FILES([
clutter/glx/Makefile clutter/glx/Makefile
clutter/eglx/Makefile clutter/eglx/Makefile
clutter/eglnative/Makefile clutter/eglnative/Makefile
clutter/osx/Makefile
clutter/sdl/Makefile clutter/sdl/Makefile
clutter/cogl/Makefile clutter/cogl/Makefile
clutter/cogl/gl/Makefile clutter/cogl/gl/Makefile