From 5ca4d3718d61805b1e4ee52758801d824e8517fa Mon Sep 17 00:00:00 2001 From: Matthew Allum Date: Wed, 15 Nov 2006 21:19:01 +0000 Subject: [PATCH] 2006-11-15 Matthew Allum * clutter/clutter-actor.h: * clutter/clutter-actor.c: Add new API clutter_actor_move_by(), clutter_actor_get_size() * clutter/clutter-alpha.c: * clutter/clutter-alpha.h: Add clutter alpha sine func * clutter/clutter-behaviours.h: * clutter/clutter-behaviours.c: Add a basic scale behaviour (needs work) * examples/behave.c: (main): More playing with new behaviour functionality * clutter/clutter-feature.c: * clutter/clutter-feature.h: * clutter/clutter-main.c: Add new experimental sync to vblank code Set env CLUTTER_VBLANK=none to disable. --- clutter/clutter-actor.c | 53 ++++++++ clutter/clutter-actor.h | 10 ++ clutter/clutter-alpha.c | 21 ++++ clutter/clutter-alpha.h | 4 + clutter/clutter-behaviours.c | 166 ++++++++++++++++++++++++- clutter/clutter-behaviours.h | 63 +++++++++- clutter/clutter-feature.c | 229 +++++++++++++++++++++++++++++++++-- clutter/clutter-feature.h | 4 +- clutter/clutter-main.c | 9 +- 9 files changed, 535 insertions(+), 24 deletions(-) diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c index e47028630..70aeaa75e 100644 --- a/clutter/clutter-actor.c +++ b/clutter/clutter-actor.c @@ -874,6 +874,36 @@ clutter_actor_set_position (ClutterActor *self, clutter_actor_request_coords (self, &box); } +/** + * clutter_actor_move_by + * @self: A #ClutterActor + * @dx: Distance to move Actor on X axis. + * @dy: Distance to move Actor on Y axis. + * + * Moves an actor by specified distance relative to + * current position. + * + * Since: 0.2 + */ +void +clutter_actor_move_by (ClutterActor *self, + gint dx, + gint dy) +{ + ClutterActorBox box; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + clutter_actor_allocate_coords (self, &box); + + box.x2 += dx; + box.y2 += dy; + box.x1 += dx; + box.y1 += dy; + + clutter_actor_request_coords (self, &box); +} + /** * clutter_actor_set_size * @self: A #ClutterActor @@ -900,6 +930,29 @@ clutter_actor_set_size (ClutterActor *self, clutter_actor_request_coords (self, &box); } +/* + * clutter_actor_get_size + * @self: A #ClutterActor + * @x: Location to store width if non NULL. + * @y: Location to store height if non NULL. + * + * Gets the size of an actor ignoring any scaling factors + * + * Since: 0.2 + */ +void +clutter_actor_get_size (ClutterActor *self, + guint *width, + guint *height) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + if (width) + *width = clutter_actor_get_width(self); + if (height) + *height = clutter_actor_get_height(self); +} + /** * clutter_actor_get_abs_position * @self: A #ClutterActor diff --git a/clutter/clutter-actor.h b/clutter/clutter-actor.h index d4c307074..8ef61b508 100644 --- a/clutter/clutter-actor.h +++ b/clutter/clutter-actor.h @@ -237,6 +237,16 @@ clutter_actor_get_abs_size (ClutterActor *self, guint *width, guint *height); +void +clutter_actor_get_size (ClutterActor *self, + guint *width, + guint *height); + +void +clutter_actor_move_by (ClutterActor *self, + gint dx, + gint dy); + G_END_DECLS #endif diff --git a/clutter/clutter-alpha.c b/clutter/clutter-alpha.c index 61ebbbe1d..e3723eb78 100644 --- a/clutter/clutter-alpha.c +++ b/clutter/clutter-alpha.c @@ -37,6 +37,7 @@ #include "clutter-alpha.h" #include "clutter-main.h" #include "clutter-marshal.h" +#include G_DEFINE_TYPE (ClutterAlpha, clutter_alpha, G_TYPE_OBJECT); @@ -105,6 +106,26 @@ clutter_alpha_ramp_func (ClutterAlpha *alpha) } } +guint32 +clutter_alpha_sine_func (ClutterAlpha *alpha) +{ + int current_frame_num, nframes; + double x; + + current_frame_num = + clutter_timeline_get_current_frame (alpha->priv->timeline); + nframes = + clutter_timeline_get_n_frames (alpha->priv->timeline); + + /* FIXME: fixed point, and fixed point sine() */ + + x = (double)(current_frame_num * 2.0f * M_PI) / nframes ; + + printf("%2f\n", ((sin(x-(M_PI/2.0f)) + 1.0f ) * 0.5f )); + + return (guint32) (((sin(x-(M_PI/2.0f)) + 1.0f ) * 0.5f ) * (double)CLUTTER_ALPHA_MAX_ALPHA); +} + /* Object */ static void diff --git a/clutter/clutter-alpha.h b/clutter/clutter-alpha.h index 6db4ff371..5761440d4 100644 --- a/clutter/clutter-alpha.h +++ b/clutter/clutter-alpha.h @@ -112,9 +112,13 @@ clutter_alpha_ramp_dec_func (ClutterAlpha *alpha); guint32 clutter_alpha_ramp_func (ClutterAlpha *alpha); +guint32 +clutter_alpha_sine_func (ClutterAlpha *alpha); + #define CLUTTER_ALPHA_RAMP_INC clutter_alpha_ramp_inc_func #define CLUTTER_ALPHA_RAMP_DEC clutter_alpha_ramp_dec_func #define CLUTTER_ALPHA_RAMP clutter_alpha_ramp_func +#define CLUTTER_ALPHA_SINE clutter_alpha_sine_func G_END_DECLS diff --git a/clutter/clutter-behaviours.c b/clutter/clutter-behaviours.c index be82cbf06..e70587b8b 100644 --- a/clutter/clutter-behaviours.c +++ b/clutter/clutter-behaviours.c @@ -25,10 +25,16 @@ /** * SECTION:clutter-behaviour - * @short_description: Class for providing behaviours to actors + * @short_description: Class for providing common behaviours to actors * */ +/* TODO: + * o Document + * o Add props + * o Optimise + */ + #include "config.h" #include "clutter-actor.h" @@ -341,6 +347,7 @@ clutter_path_behavior_get_knot (ClutterBehaviourPath *behave, guint index) { /* FIXME: implement */ + return NULL; } void @@ -397,7 +404,7 @@ clutter_behaviour_opacity_frame_foreach (ClutterActor *actor, } static void -clutter_behaviour_alpha_notify (ClutterBehaviour *behave) +clutter_behaviour_opacity_alpha_notify (ClutterBehaviour *behave) { clutter_behaviour_actors_foreach (behave, @@ -439,7 +446,7 @@ clutter_behaviour_opacity_class_init (ClutterBehaviourOpacityClass *klass) behave_class = (ClutterBehaviourClass*) klass; - behave_class->alpha_notify = clutter_behaviour_alpha_notify; + behave_class->alpha_notify = clutter_behaviour_opacity_alpha_notify; g_type_class_add_private (object_class, sizeof (ClutterBehaviourOpacityPrivate)); } @@ -469,3 +476,156 @@ clutter_behaviour_opacity_new (ClutterAlpha *alpha, return CLUTTER_BEHAVIOUR(behave); } +/* + * ====================== Scale ============================ + */ + +G_DEFINE_TYPE (ClutterBehaviourScale, \ + clutter_behaviour_scale, \ + CLUTTER_TYPE_BEHAVIOUR); + +struct ClutterBehaviourScalePrivate +{ + ClutterFixed scale_begin; + ClutterFixed scale_end; + ClutterGravity gravity; +}; + +#define CLUTTER_BEHAVIOUR_SCALE_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \ + CLUTTER_TYPE_BEHAVIOUR_SCALE, \ + ClutterBehaviourScalePrivate)) + +static void +clutter_behaviour_scale_frame_foreach (ClutterActor *actor, + ClutterBehaviourScale *behave) +{ + ClutterFixed scale, factor; + guint32 alpha; + ClutterBehaviourScalePrivate *priv; + ClutterBehaviour *_behave; + gint sw, sh, w, h; + + priv = CLUTTER_BEHAVIOUR_SCALE_GET_PRIVATE (behave); + _behave = CLUTTER_BEHAVIOUR (behave); + + alpha = clutter_alpha_get_alpha (clutter_behaviour_get_alpha (_behave)); + + /* FIXME: use all fixed if possible + factor = CLUTTER_FIXED_DIV(CLUTTER_INT_TO_FIXED(alpha/2), + CLUTTER_INT_TO_FIXED(CLUTTER_ALPHA_MAX_ALPHA/2)); + */ + + factor = CLUTTER_FLOAT_TO_FIXED((double) alpha / CLUTTER_ALPHA_MAX_ALPHA); + + scale = CLUTTER_FIXED_MUL(factor, (priv->scale_end - priv->scale_begin)); + + scale += priv->scale_begin; + + clutter_actor_set_scalex (actor, scale, scale); + + if (priv->gravity == CLUTTER_GRAVITY_NONE + || priv->gravity == CLUTTER_GRAVITY_NORTH_WEST) + return; + + clutter_actor_get_abs_size (actor, (guint*)&sw, (guint*)&sh); + clutter_actor_get_size (actor, (guint*)&w, (guint*)&h); + + switch (priv->gravity) + { + case CLUTTER_GRAVITY_NORTH: + break; + case CLUTTER_GRAVITY_NORTH_EAST: + break; + case CLUTTER_GRAVITY_EAST: + break; + case CLUTTER_GRAVITY_SOUTH_EAST: + break; + case CLUTTER_GRAVITY_SOUTH: + break; + case CLUTTER_GRAVITY_SOUTH_WEST: + break; + case CLUTTER_GRAVITY_WEST: + break; + case CLUTTER_GRAVITY_CENTER: + printf("%i vs %i\n", sw, w); + clutter_actor_move_by (actor, sw - w, sh - h); + default: + break; + } +} + +static void +clutter_behaviour_scale_alpha_notify (ClutterBehaviour *behave) +{ + clutter_behaviour_actors_foreach + (behave, + (GFunc)clutter_behaviour_scale_frame_foreach, + CLUTTER_BEHAVIOUR_SCALE(behave)); +} + +static void +clutter_behaviour_scale_dispose (GObject *object) +{ + G_OBJECT_CLASS (clutter_behaviour_scale_parent_class)->dispose (object); +} + +static void +clutter_behaviour_scale_finalize (GObject *object) +{ + ClutterBehaviourScale *self = CLUTTER_BEHAVIOUR_SCALE(object); + + if (self->priv) + { + g_free(self->priv); + self->priv = NULL; + } + + G_OBJECT_CLASS (clutter_behaviour_scale_parent_class)->finalize (object); +} + + +static void +clutter_behaviour_scale_class_init (ClutterBehaviourScaleClass *klass) +{ + GObjectClass *object_class; + ClutterBehaviourClass *behave_class; + + object_class = (GObjectClass*) klass; + + object_class->finalize = clutter_behaviour_scale_finalize; + object_class->dispose = clutter_behaviour_scale_dispose; + + behave_class = (ClutterBehaviourClass*) klass; + + behave_class->alpha_notify = clutter_behaviour_scale_alpha_notify; + + g_type_class_add_private (object_class, sizeof (ClutterBehaviourScalePrivate)); +} + +static void +clutter_behaviour_scale_init (ClutterBehaviourScale *self) +{ + ClutterBehaviourScalePrivate *priv; + + self->priv = priv = CLUTTER_BEHAVIOUR_SCALE_GET_PRIVATE (self); +} + +ClutterBehaviour* +clutter_behaviour_scale_new (ClutterAlpha *alpha, + double scale_begin, + double scale_end, + ClutterGravity gravity) +{ + ClutterBehaviourScale *behave; + + behave = g_object_new (CLUTTER_TYPE_BEHAVIOUR_SCALE, + "alpha", alpha, + NULL); + + behave->priv->scale_begin = CLUTTER_FLOAT_TO_FIXED (scale_begin); + behave->priv->scale_end = CLUTTER_FLOAT_TO_FIXED (scale_end); + behave->priv->gravity = gravity; + + return CLUTTER_BEHAVIOUR(behave); +} diff --git a/clutter/clutter-behaviours.h b/clutter/clutter-behaviours.h index f7d28570d..347be137e 100644 --- a/clutter/clutter-behaviours.h +++ b/clutter/clutter-behaviours.h @@ -80,7 +80,7 @@ clutter_path_behavior_append_knots (ClutterBehaviourPath *pathb, const ClutterKnot *first_knot, ...); -/* opacity */ +/* ============================ opacity ======================== */ #define CLUTTER_TYPE_BEHAVIOUR_OPACITY clutter_behaviour_opacity_get_type() @@ -126,6 +126,67 @@ clutter_behaviour_opacity_new (ClutterAlpha *alpha, guint8 opacity_start, guint8 opacity_end); +/* ============================ scale ======================== */ + +#define CLUTTER_TYPE_BEHAVIOUR_SCALE clutter_behaviour_scale_get_type() + +#define CLUTTER_BEHAVIOUR_SCALE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + CLUTTER_TYPE_BEHAVIOUR_SCALE, ClutterBehaviourScale)) + +#define CLUTTER_BEHAVIOUR_SCALE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + CLUTTER_TYPE_BEHAVIOUR_SCALE, ClutterBehaviourScaleClass)) + +#define CLUTTER_IS_BEHAVIOUR_SCALE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + CLUTTER_TYPE_BEHAVIOUR_SCALE)) + +#define CLUTTER_IS_BEHAVIOUR_SCALE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + CLUTTER_TYPE_BEHAVIOUR_SCALE)) + +#define CLUTTER_BEHAVIOUR_SCALE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + CLUTTER_TYPE_BEHAVIOUR_SCALE, ClutterBehaviourScaleClass)) + +typedef struct _ClutterBehaviourScale ClutterBehaviourScale; +typedef struct ClutterBehaviourScalePrivate ClutterBehaviourScalePrivate; +typedef struct _ClutterBehaviourScaleClass ClutterBehaviourScaleClass; + +struct _ClutterBehaviourScale +{ + ClutterBehaviour parent; + ClutterBehaviourScalePrivate *priv; +}; + +struct _ClutterBehaviourScaleClass +{ + ClutterBehaviourClass parent_class; +}; + +typedef enum { + CLUTTER_GRAVITY_NONE = 0, + CLUTTER_GRAVITY_NORTH, + CLUTTER_GRAVITY_NORTH_EAST, + CLUTTER_GRAVITY_EAST, + CLUTTER_GRAVITY_SOUTH_EAST, + CLUTTER_GRAVITY_SOUTH, + CLUTTER_GRAVITY_SOUTH_WEST, + CLUTTER_GRAVITY_WEST, + CLUTTER_GRAVITY_NORTH_WEST, + CLUTTER_GRAVITY_CENTER +} ClutterGravity; + +GType clutter_behaviour_scale_get_type (void); + +ClutterBehaviour* +clutter_behaviour_scale_new (ClutterAlpha *alpha, + double scale_begin, + double scale_end, + ClutterGravity gravity); + + G_END_DECLS #endif diff --git a/clutter/clutter-feature.c b/clutter/clutter-feature.c index 4ff4c04bc..fe395edf4 100644 --- a/clutter/clutter-feature.c +++ b/clutter/clutter-feature.c @@ -31,21 +31,102 @@ */ #include "config.h" +#include "clutter-main.h" #include "clutter-feature.h" -#include "string.h" -static ClutterFeatureFlags __features = -1; +#include +#include +#include +#include +#include +#include +#include + + #include + +typedef void (*FuncPtr) (void); +typedef int (*GLXGetVideoSyncProc) (unsigned int *count); +typedef int (*GLXWaitVideoSyncProc) (int divisor, + int remainder, + unsigned int *count); +typedef FuncPtr (*GLXGetProcAddressProc) (const guint8 *procName); + +typedef struct ClutterFeatureFuncs +{ + GLXGetVideoSyncProc get_video_sync; + GLXWaitVideoSyncProc wait_video_sync; + +} ClutterFeatureFuncs; + +typedef enum ClutterVBlankType +{ + CLUTTER_VBLANK_NONE = 0, + CLUTTER_VBLANK_GLX, + CLUTTER_VBLANK_DRI + +} ClutterVBlankType; + +typedef struct ClutterFeatures +{ + ClutterFeatureFlags flags; + ClutterFeatureFuncs funcs; + gint dri_fd; + ClutterVBlankType vblank_type; + +} ClutterFeatures; + +static ClutterFeatures* __features = NULL; + +/* #ifdef linux */ +#define DRM_VBLANK_RELATIVE 0x1; + +struct drm_wait_vblank_request { + int type; + unsigned int sequence; + unsigned long signal; +}; + +struct drm_wait_vblank_reply { + int type; + unsigned int sequence; + long tval_sec; + long tval_usec; +}; + +typedef union drm_wait_vblank { + struct drm_wait_vblank_request request; + struct drm_wait_vblank_reply reply; +} drm_wait_vblank_t; + +#define DRM_IOCTL_BASE 'd' +#define DRM_IOWR(nr,type) _IOWR(DRM_IOCTL_BASE,nr,type) +#define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, drm_wait_vblank_t) + +static int drm_wait_vblank(int fd, drm_wait_vblank_t *vbl) +{ + int ret, rc; + + do + { + ret = ioctl(fd, DRM_IOCTL_WAIT_VBLANK, vbl); + vbl->request.type &= ~DRM_VBLANK_RELATIVE; + rc = errno; + } + while (ret && rc == EINTR); + + return rc; +} + +/* #endif */ + /* Note must be called after context created */ static gboolean -check_gl_extension (const gchar *name) +check_gl_extension (const gchar *name, const gchar *ext) { - const gchar *ext; gchar *end; gint name_len, n; - ext = (const gchar*)glGetString(GL_EXTENSIONS); - if (name == NULL || ext == NULL) return FALSE; @@ -65,20 +146,117 @@ check_gl_extension (const gchar *name) return FALSE; } +static FuncPtr +get_proc_address (const gchar *name) +{ + static GLXGetProcAddressProc get_proc_func = NULL; + static void *dlhand = NULL; + + if (get_proc_func == NULL && dlhand == NULL) + { + dlhand = dlopen (NULL, RTLD_LAZY); + + if (dlhand) + { + dlerror (); + get_proc_func + = (GLXGetProcAddressProc) dlsym (dlhand, "glXGetProcAddress"); + if (dlerror () != NULL) + get_proc_func + = (GLXGetProcAddressProc) dlsym (dlhand, "glXGetProcAddressARB"); + if (dlerror () != NULL) + { + get_proc_func = NULL; + g_warning + ("failed to bind GLXGetProcAddress or GLXGetProcAddressARB"); + } + } + } + + if (get_proc_func) + return get_proc_func ((unsigned char*)name); + + return NULL; +} + + +static gboolean +check_vblank_env (const char *name) +{ + const char *val; + + val = getenv("CLUTTER_VBLANK"); + + if (val && !strcasecmp(val, name)) + return TRUE; + + return FALSE; +} + void clutter_feature_init (void) { - if (__features != -1) + const gchar *gl_extensions, *glx_extensions; + + if (__features != NULL) { g_warning ("You should never call clutter_feature_init() " "more than once."); return; } - __features = 0; + __features = g_new0 (ClutterFeatures, 1); + memset(&__features->funcs, 0, sizeof(ClutterFeatureFuncs)); - if (check_gl_extension ("GL_ARB_texture_rectangle")) - __features |= CLUTTER_FEATURE_TEXTURE_RECTANGLE; + gl_extensions = (const gchar*)glGetString(GL_EXTENSIONS); + glx_extensions = glXQueryExtensionsString (clutter_xdisplay(), + clutter_xscreen()); + + if (check_gl_extension ("GL_ARB_texture_rectangle", gl_extensions)) + __features->flags |= CLUTTER_FEATURE_TEXTURE_RECTANGLE; + + /* vblank */ + + __features->vblank_type = CLUTTER_VBLANK_NONE; + + if (getenv("__GL_SYNC_TO_VBLANK") || check_vblank_env("none")) + { + CLUTTER_DBG("vblank sync: disabled at user request"); + } + else + { + if (!check_vblank_env("dri") + && check_gl_extension ("GLX_SGI_video_sync", glx_extensions)) + { + __features->funcs.get_video_sync = + (GLXGetVideoSyncProc) get_proc_address ("glXGetVideoSyncSGI"); + + __features->funcs.wait_video_sync = + (GLXWaitVideoSyncProc) get_proc_address ("glXWaitVideoSyncSGI"); + + if (__features->funcs.get_video_sync != NULL + && __features->funcs.wait_video_sync != NULL) + { + CLUTTER_DBG("vblank sync: using glx"); + __features->vblank_type = CLUTTER_VBLANK_GLX; + __features->flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK; + } + } + + if (!(__features->flags & CLUTTER_FEATURE_SYNC_TO_VBLANK)) + { + __features->dri_fd = open("/dev/dri/card0", O_RDWR); + if (__features->dri_fd >= 0) + { + CLUTTER_DBG("vblank sync: using dri"); + __features->vblank_type = CLUTTER_VBLANK_DRI; + __features->flags |= CLUTTER_FEATURE_SYNC_TO_VBLANK; + } + } + + if (!(__features->flags & CLUTTER_FEATURE_SYNC_TO_VBLANK)) + CLUTTER_DBG("vblank sync: no use-able mechanism found"); + } } /** @@ -95,7 +273,7 @@ clutter_feature_init (void) gboolean clutter_feature_available (ClutterFeatureFlags feature) { - return (__features & feature); + return (__features->flags & feature); } /** @@ -110,5 +288,32 @@ clutter_feature_available (ClutterFeatureFlags feature) ClutterFeatureFlags clutter_feature_all (void) { - return __features; + return __features->flags; +} + +void +clutter_feature_wait_for_vblank (void) +{ + switch (__features->vblank_type) + { + case CLUTTER_VBLANK_GLX: + { + unsigned int retraceCount; + __features->funcs.get_video_sync(&retraceCount); + __features->funcs.wait_video_sync(2, + (retraceCount+1)%2, &retraceCount); + } + break; + case CLUTTER_VBLANK_DRI: + { + drm_wait_vblank_t blank; + blank.request.type = DRM_VBLANK_RELATIVE; + blank.request.sequence = 1; + drm_wait_vblank (__features->dri_fd, &blank); + } + break; + case CLUTTER_VBLANK_NONE: + default: + break; + } } diff --git a/clutter/clutter-feature.h b/clutter/clutter-feature.h index d934bef23..faf632280 100644 --- a/clutter/clutter-feature.h +++ b/clutter/clutter-feature.h @@ -41,11 +41,13 @@ G_END_DECLS typedef enum { - CLUTTER_FEATURE_TEXTURE_RECTANGLE = (1 << 1) + CLUTTER_FEATURE_TEXTURE_RECTANGLE = (1 << 1), + CLUTTER_FEATURE_SYNC_TO_VBLANK = (1 << 2) } ClutterFeatureFlags; gboolean clutter_feature_available (ClutterFeatureFlags flags); ClutterFeatureFlags clutter_feature_get_all (void); +void clutter_feature_wait_for_vblank (); G_END_DECLS diff --git a/clutter/clutter-main.c b/clutter/clutter-main.c index 933397d7a..7db74a77d 100644 --- a/clutter/clutter-main.c +++ b/clutter/clutter-main.c @@ -289,13 +289,7 @@ clutter_redraw (void) if (clutter_stage_get_xwindow (stage)) { -#if 0 - unsigned int retraceCount; - /* Wait for vertical retrace */ - /* glXGetVideoSyncSGI(&retraceCount); */ - /* glXWaitVideoSyncSGI(2, (retraceCount+1)%2, &retraceCount); */ - glXWaitVideoSyncSGI(1, 0, &retraceCount); -#endif + clutter_feature_wait_for_vblank (); glXSwapBuffers(ctx->xdpy, clutter_stage_get_xwindow (stage)); } else @@ -584,6 +578,7 @@ clutter_init (int *argc, char ***argv) events_init (); + context->is_initialized = TRUE; return 1;