mirror of
https://github.com/brl/mutter.git
synced 2024-11-22 16:10:41 -05:00
2008-03-28 Matthew Allum <mallum@openedhand.com>
* clutter/Makefile.am: * clutter/clutter-actor.c: * clutter/clutter-actor.h: * clutter/clutter-backend.c: * clutter/clutter-backend.h: * clutter/clutter-debug.h: * clutter/clutter-event.c: * clutter/clutter-event.h: * clutter/clutter-feature.h: * clutter/clutter-group.h: * clutter/clutter-main.c: * clutter/clutter-main.h: * clutter/clutter-private.h: * clutter/clutter-stage.c: * clutter/clutter-stage.h: * clutter/clutter-stage-manager.c * clutter/clutter-stage-manager.h * clutter/clutter-types.h: * clutter/glx/clutter-backend-glx.c: * clutter/glx/clutter-backend-glx.h: * clutter/glx/clutter-stage-glx.c: * clutter/glx/clutter-stage-glx.h: * clutter/x11/clutter-backend-x11.c: * clutter/x11/clutter-backend-x11.h: * clutter/x11/clutter-event-x11.c: * clutter/x11/clutter-stage-x11.c: * clutter/x11/clutter-x11.h: * tests/Makefile.am: * tests/test-multistage.c: Initial commit of multi stage support (mostly a merge from the clutter-multistage branch). Note, this commit will break all backends except glx.
This commit is contained in:
parent
dd7ff3e829
commit
8847bcd195
35
ChangeLog
35
ChangeLog
@ -1,3 +1,38 @@
|
||||
2008-03-28 Matthew Allum <mallum@openedhand.com>
|
||||
|
||||
* clutter/Makefile.am:
|
||||
* clutter/clutter-actor.c:
|
||||
* clutter/clutter-actor.h:
|
||||
* clutter/clutter-backend.c:
|
||||
* clutter/clutter-backend.h:
|
||||
* clutter/clutter-debug.h:
|
||||
* clutter/clutter-event.c:
|
||||
* clutter/clutter-event.h:
|
||||
* clutter/clutter-feature.h:
|
||||
* clutter/clutter-group.h:
|
||||
* clutter/clutter-main.c:
|
||||
* clutter/clutter-main.h:
|
||||
* clutter/clutter-private.h:
|
||||
* clutter/clutter-stage.c:
|
||||
* clutter/clutter-stage.h:
|
||||
* clutter/clutter-stage-manager.c
|
||||
* clutter/clutter-stage-manager.h
|
||||
* clutter/clutter-types.h:
|
||||
* clutter/glx/clutter-backend-glx.c:
|
||||
* clutter/glx/clutter-backend-glx.h:
|
||||
* clutter/glx/clutter-stage-glx.c:
|
||||
* clutter/glx/clutter-stage-glx.h:
|
||||
* clutter/x11/clutter-backend-x11.c:
|
||||
* clutter/x11/clutter-backend-x11.h:
|
||||
* clutter/x11/clutter-event-x11.c:
|
||||
* clutter/x11/clutter-stage-x11.c:
|
||||
* clutter/x11/clutter-x11.h:
|
||||
* tests/Makefile.am:
|
||||
* tests/test-multistage.c:
|
||||
Initial commit of multi stage support (mostly a merge from the
|
||||
clutter-multistage branch).
|
||||
Note, this commit will break all backends except glx.
|
||||
|
||||
2008-03-26 Neil Roberts <neil@o-hand.com>
|
||||
|
||||
* clutter/win32/clutter-win32.h: Added gtk-doc documentation for
|
||||
|
@ -72,6 +72,7 @@ source_h = \
|
||||
$(srcdir)/clutter-scriptable.h \
|
||||
$(srcdir)/clutter-shader.h \
|
||||
$(srcdir)/clutter-stage.h \
|
||||
$(srcdir)/clutter-stage-manager.h \
|
||||
$(srcdir)/clutter-texture.h \
|
||||
$(srcdir)/clutter-timeline.h \
|
||||
$(srcdir)/clutter-timeout-pool.h \
|
||||
@ -159,6 +160,7 @@ source_c = \
|
||||
clutter-scriptable.c \
|
||||
clutter-shader.c \
|
||||
clutter-stage.c \
|
||||
clutter-stage-manager.c \
|
||||
clutter-texture.c \
|
||||
clutter-timeline.c \
|
||||
clutter-timeout-pool.c \
|
||||
|
@ -198,6 +198,8 @@ struct _ClutterActorPrivate
|
||||
ClutterFixed scale_y;
|
||||
|
||||
ShaderData *shader_data;
|
||||
|
||||
ClutterStage *stage;
|
||||
};
|
||||
|
||||
enum
|
||||
@ -278,21 +280,6 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (ClutterActor,
|
||||
|
||||
|
||||
|
||||
static gboolean
|
||||
redraw_update_idle (gpointer data)
|
||||
{
|
||||
ClutterMainContext *ctx = CLUTTER_CONTEXT();
|
||||
|
||||
if (ctx->update_idle)
|
||||
{
|
||||
g_source_remove (ctx->update_idle);
|
||||
ctx->update_idle = 0;
|
||||
}
|
||||
|
||||
clutter_redraw ();
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_actor_real_show (ClutterActor *self)
|
||||
@ -423,7 +410,7 @@ clutter_actor_hide_all (ClutterActor *self)
|
||||
void
|
||||
clutter_actor_realize (ClutterActor *self)
|
||||
{
|
||||
ClutterActorClass *klass;
|
||||
ClutterActorClass *klass;
|
||||
|
||||
if (CLUTTER_ACTOR_IS_REALIZED (self))
|
||||
return;
|
||||
@ -447,6 +434,9 @@ void
|
||||
clutter_actor_unrealize (ClutterActor *self)
|
||||
{
|
||||
ClutterActorClass *klass;
|
||||
ClutterActorPrivate *priv;
|
||||
|
||||
priv = self->priv;
|
||||
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (self))
|
||||
return;
|
||||
@ -457,6 +447,8 @@ clutter_actor_unrealize (ClutterActor *self)
|
||||
|
||||
if (klass->unrealize)
|
||||
(klass->unrealize) (self);
|
||||
|
||||
priv->stage = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -910,7 +902,15 @@ clutter_actor_get_relative_vertices (ClutterActor *self,
|
||||
* Simply duping code for now in wait for Cogl cleanup that can hopefully
|
||||
* address this in a nicer way.
|
||||
*/
|
||||
stage = clutter_stage_get_default ();
|
||||
stage = clutter_actor_get_stage (self);
|
||||
|
||||
/* FIXME: if were not yet added to a stage, its probably unsafe to
|
||||
* return default - idealy the func should fail.
|
||||
*/
|
||||
if (stage == NULL)
|
||||
stage = clutter_stage_get_default ();
|
||||
|
||||
clutter_stage_ensure_current (CLUTTER_STAGE(stage));
|
||||
|
||||
if (CLUTTER_PRIVATE_FLAGS (stage) & CLUTTER_ACTOR_SYNC_MATRICES)
|
||||
{
|
||||
@ -991,7 +991,15 @@ clutter_actor_get_vertices (ClutterActor *self,
|
||||
* Simply duping code for now in wait for Cogl cleanup that can hopefully
|
||||
* address this in a nicer way.
|
||||
*/
|
||||
stage = clutter_stage_get_default ();
|
||||
stage = clutter_actor_get_stage (self);
|
||||
|
||||
/* FIXME: if were not yet added to a stage, its probably unsafe to
|
||||
* return default - idealy the func should fail.
|
||||
*/
|
||||
if (stage == NULL)
|
||||
stage = clutter_stage_get_default ();
|
||||
|
||||
clutter_stage_ensure_current (CLUTTER_STAGE(stage));
|
||||
|
||||
if (CLUTTER_PRIVATE_FLAGS (stage) & CLUTTER_ACTOR_SYNC_MATRICES)
|
||||
{
|
||||
@ -1146,7 +1154,7 @@ static void
|
||||
_clutter_actor_apply_modelview_transform_recursive (ClutterActor *self,
|
||||
ClutterActor *ancestor)
|
||||
{
|
||||
ClutterActor * parent;
|
||||
ClutterActor *parent, *stage;
|
||||
|
||||
parent = clutter_actor_get_parent (self);
|
||||
|
||||
@ -1158,10 +1166,18 @@ _clutter_actor_apply_modelview_transform_recursive (ClutterActor *self,
|
||||
if (self == ancestor)
|
||||
return;
|
||||
|
||||
stage = clutter_actor_get_stage (self);
|
||||
|
||||
/* FIXME: if were not yet added to a stage, its probably unsafe to
|
||||
* return default - idealy the func should fail.
|
||||
*/
|
||||
if (stage == NULL)
|
||||
stage = clutter_stage_get_default ();
|
||||
|
||||
if (parent)
|
||||
_clutter_actor_apply_modelview_transform_recursive (parent, ancestor);
|
||||
else if (self != clutter_stage_get_default ())
|
||||
_clutter_actor_apply_modelview_transform (clutter_stage_get_default());
|
||||
else if (self != stage)
|
||||
_clutter_actor_apply_modelview_transform (stage);
|
||||
|
||||
_clutter_actor_apply_modelview_transform (self);
|
||||
}
|
||||
@ -2352,14 +2368,6 @@ clutter_actor_destroy (ClutterActor *self)
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
||||
|
||||
if (CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_ACTOR_IS_TOPLEVEL)
|
||||
{
|
||||
g_warning ("Calling clutter_actor_destroy() on an actor of type `%s' "
|
||||
"is not possible. This is usually an application bug.",
|
||||
g_type_name (G_OBJECT_TYPE (self)));
|
||||
return;
|
||||
}
|
||||
|
||||
priv = self->priv;
|
||||
|
||||
if (priv->parent_actor)
|
||||
@ -2395,17 +2403,13 @@ clutter_actor_destroy (ClutterActor *self)
|
||||
void
|
||||
clutter_actor_queue_redraw (ClutterActor *self)
|
||||
{
|
||||
ClutterMainContext *ctx = CLUTTER_CONTEXT();
|
||||
ClutterActor *stage;
|
||||
|
||||
if (!ctx->update_idle)
|
||||
{
|
||||
CLUTTER_TIMESTAMP (SCHEDULER, "Adding idle source for actor: %p", self);
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
||||
|
||||
ctx->update_idle =
|
||||
clutter_threads_add_idle_full (G_PRIORITY_DEFAULT + 10,
|
||||
redraw_update_idle,
|
||||
NULL, NULL);
|
||||
}
|
||||
/* FIXME: should we check we're visible here? */
|
||||
if ((stage = clutter_actor_get_stage (self)) != NULL)
|
||||
clutter_stage_queue_redraw (CLUTTER_STAGE(stage));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -5728,3 +5732,14 @@ clutter_actor_get_box_from_vertices (ClutterVertex vtx[4],
|
||||
box->y1 = y_1;
|
||||
box->y2 = y_2;
|
||||
}
|
||||
|
||||
ClutterActor*
|
||||
clutter_actor_get_stage (ClutterActor *actor)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), NULL);
|
||||
|
||||
while (actor && !(CLUTTER_PRIVATE_FLAGS (actor) & CLUTTER_ACTOR_IS_TOPLEVEL))
|
||||
actor = clutter_actor_get_parent (actor);
|
||||
|
||||
return actor;
|
||||
}
|
||||
|
@ -487,6 +487,8 @@ gboolean clutter_actor_is_scaled (ClutterActor *self);
|
||||
void clutter_actor_box_get_from_vertices (ClutterVertex vtx[4],
|
||||
ClutterActorBox *box);
|
||||
|
||||
ClutterActor* clutter_actor_get_stage (ClutterActor *actor);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* _HAVE_CLUTTER_ACTOR_H */
|
||||
|
@ -95,14 +95,6 @@ clutter_backend_init (ClutterBackend *backend)
|
||||
priv->resolution = -1.0;
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
_clutter_backend_get_stage (ClutterBackend *backend)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_BACKEND (backend), NULL);
|
||||
|
||||
return CLUTTER_BACKEND_GET_CLASS (backend)->get_stage (backend);
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_backend_add_options (ClutterBackend *backend,
|
||||
GOptionGroup *group)
|
||||
@ -146,31 +138,65 @@ _clutter_backend_post_parse (ClutterBackend *backend,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_clutter_backend_init_stage (ClutterBackend *backend,
|
||||
GError **error)
|
||||
ClutterActor*
|
||||
_clutter_backend_create_stage (ClutterBackend *backend,
|
||||
GError **error)
|
||||
{
|
||||
ClutterMainContext *context;
|
||||
ClutterBackendClass *klass;
|
||||
ClutterActor *stage = NULL;
|
||||
|
||||
g_return_val_if_fail (CLUTTER_IS_BACKEND (backend), FALSE);
|
||||
|
||||
klass = CLUTTER_BACKEND_GET_CLASS (backend);
|
||||
if (klass->init_stage)
|
||||
return klass->init_stage (backend, error);
|
||||
context = clutter_context_get_default ();
|
||||
|
||||
return TRUE;
|
||||
if (!context->stage_manager)
|
||||
context->stage_manager = clutter_stage_manager_get_default ();
|
||||
|
||||
klass = CLUTTER_BACKEND_GET_CLASS (backend);
|
||||
if (klass->create_stage)
|
||||
stage = klass->create_stage (backend, error);
|
||||
|
||||
if (!stage)
|
||||
return NULL;
|
||||
|
||||
_clutter_stage_manager_add_stage (context->stage_manager,
|
||||
CLUTTER_STAGE(stage));
|
||||
return stage;
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_backend_redraw (ClutterBackend *backend)
|
||||
_clutter_backend_redraw (ClutterBackend *backend, ClutterStage *stage)
|
||||
{
|
||||
ClutterBackendClass *klass;
|
||||
|
||||
klass = CLUTTER_BACKEND_GET_CLASS (backend);
|
||||
if (G_LIKELY(klass->redraw))
|
||||
klass->redraw (backend);
|
||||
klass->redraw (backend, stage);
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_backend_ensure_context (ClutterBackend *backend, ClutterStage *stage)
|
||||
{
|
||||
ClutterBackendClass *klass;
|
||||
static ClutterStage *current_context_stage = NULL;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_BACKEND (backend));
|
||||
g_return_if_fail (CLUTTER_IS_STAGE (stage));
|
||||
|
||||
if (stage != current_context_stage)
|
||||
{
|
||||
klass = CLUTTER_BACKEND_GET_CLASS (backend);
|
||||
if (G_LIKELY(klass->ensure_context))
|
||||
klass->ensure_context (backend, stage);
|
||||
|
||||
current_context_stage = stage;
|
||||
|
||||
CLUTTER_SET_PRIVATE_FLAGS (stage, CLUTTER_ACTOR_SYNC_MATRICES);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ClutterFeatureFlags
|
||||
_clutter_backend_get_features (ClutterBackend *backend)
|
||||
{
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <clutter/clutter-actor.h>
|
||||
#include <clutter/clutter-stage.h>
|
||||
#include <clutter/clutter-event.h>
|
||||
#include <clutter/clutter-feature.h>
|
||||
|
||||
@ -60,15 +61,17 @@ struct _ClutterBackendClass
|
||||
GError **error);
|
||||
gboolean (* post_parse) (ClutterBackend *backend,
|
||||
GError **error);
|
||||
gboolean (* init_stage) (ClutterBackend *backend,
|
||||
ClutterActor *(* create_stage) (ClutterBackend *backend,
|
||||
GError **error);
|
||||
void (* init_events) (ClutterBackend *backend);
|
||||
void (* init_features) (ClutterBackend *backend);
|
||||
ClutterActor *(* get_stage) (ClutterBackend *backend);
|
||||
void (* add_options) (ClutterBackend *backend,
|
||||
GOptionGroup *group);
|
||||
ClutterFeatureFlags (* get_features) (ClutterBackend *backend);
|
||||
void (* redraw) (ClutterBackend *backend);
|
||||
void (* redraw) (ClutterBackend *backend,
|
||||
ClutterStage *stage);
|
||||
void (* ensure_context) (ClutterBackend *backend,
|
||||
ClutterStage *stage);
|
||||
};
|
||||
|
||||
GType clutter_backend_get_type (void) G_GNUC_CONST;
|
||||
|
@ -19,7 +19,8 @@ typedef enum {
|
||||
CLUTTER_DEBUG_BACKEND = 1 << 9,
|
||||
CLUTTER_DEBUG_SCHEDULER = 1 << 10,
|
||||
CLUTTER_DEBUG_SCRIPT = 1 << 11,
|
||||
CLUTTER_DEBUG_SHADER = 1 << 12
|
||||
CLUTTER_DEBUG_SHADER = 1 << 12,
|
||||
CLUTTER_DEBUG_MULTISTAGE = 1 << 13
|
||||
} ClutterDebugFlag;
|
||||
|
||||
#ifdef CLUTTER_ENABLE_DEBUG
|
||||
|
@ -180,6 +180,25 @@ clutter_event_get_source (ClutterEvent *event)
|
||||
return event->any.source;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_event_get_stage:
|
||||
* @event: a #ClutterEvent
|
||||
*
|
||||
* Retrieves the source #ClutterStage the event originated for, or
|
||||
* NULL if the event has no stage.
|
||||
*
|
||||
* Return value: a #ClutterStage
|
||||
*
|
||||
* Since: 0.8
|
||||
*/
|
||||
ClutterStage*
|
||||
clutter_event_get_stage (ClutterEvent *event)
|
||||
{
|
||||
g_return_val_if_fail (event != NULL, NULL);
|
||||
|
||||
return event->any.stage;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_button_event_button:
|
||||
* @buttev: a #ClutterButtonEvent
|
||||
|
@ -200,6 +200,7 @@ struct _ClutterAnyEvent
|
||||
ClutterEventType type;
|
||||
guint32 time;
|
||||
ClutterEventFlags flags;
|
||||
ClutterStage *stage;
|
||||
ClutterActor *source;
|
||||
};
|
||||
|
||||
@ -223,6 +224,7 @@ struct _ClutterKeyEvent
|
||||
ClutterEventType type;
|
||||
guint32 time;
|
||||
ClutterEventFlags flags;
|
||||
ClutterStage *stage;
|
||||
ClutterActor *source;
|
||||
ClutterModifierType modifier_state;
|
||||
guint keyval;
|
||||
@ -254,6 +256,7 @@ struct _ClutterButtonEvent
|
||||
ClutterEventType type;
|
||||
guint32 time;
|
||||
ClutterEventFlags flags;
|
||||
ClutterStage *stage;
|
||||
ClutterActor *source;
|
||||
gint x;
|
||||
gint y;
|
||||
@ -269,6 +272,7 @@ struct _ClutterCrossingEvent
|
||||
ClutterEventType type;
|
||||
guint32 time;
|
||||
ClutterEventFlags flags;
|
||||
ClutterStage *stage;
|
||||
ClutterActor *source;
|
||||
gint x;
|
||||
gint y;
|
||||
@ -281,6 +285,7 @@ struct _ClutterMotionEvent
|
||||
ClutterEventType type;
|
||||
guint32 time;
|
||||
ClutterEventFlags flags;
|
||||
ClutterStage *stage;
|
||||
ClutterActor *source;
|
||||
gint x;
|
||||
gint y;
|
||||
@ -294,6 +299,7 @@ struct _ClutterScrollEvent
|
||||
ClutterEventType type;
|
||||
guint32 time;
|
||||
ClutterEventFlags flags;
|
||||
ClutterStage *stage;
|
||||
ClutterActor *source;
|
||||
gint x;
|
||||
gint y;
|
||||
@ -308,6 +314,7 @@ struct _ClutterStageStateEvent
|
||||
ClutterEventType type;
|
||||
guint32 time;
|
||||
ClutterEventFlags flags;
|
||||
ClutterStage *stage;
|
||||
ClutterActor *source; /* unused XXX: should probably be the stage itself */
|
||||
ClutterStageState changed_mask;
|
||||
ClutterStageState new_state;
|
||||
@ -351,6 +358,7 @@ guint32 clutter_button_event_button (ClutterButtonEvent *buttev);
|
||||
|
||||
guint32 clutter_keysym_to_unicode (guint keyval);
|
||||
|
||||
ClutterStage* clutter_event_get_stage (ClutterEvent *event);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
@ -48,6 +48,7 @@ G_BEGIN_DECLS
|
||||
* @CLUTTER_FEATURE_STAGE_CURSOR: Set if stage has a graphical cursor.
|
||||
* @CLUTTER_FEATURE_SHADERS_GLSL: Set if the backend supports GLSL shaders.
|
||||
* @CLUTTER_FEATURE_OFFSCREEN: Set if the backend supports offscreen rendering.
|
||||
* @CLUTTER_FEATURE_STAGE_MULTIPLE: Set if multiple stages are supported.
|
||||
*
|
||||
* Runtime flags indicating specific features available via Clutter window
|
||||
* sysytem and graphics backend.
|
||||
@ -64,7 +65,8 @@ typedef enum
|
||||
CLUTTER_FEATURE_STAGE_USER_RESIZE = (1 << 6),
|
||||
CLUTTER_FEATURE_STAGE_CURSOR = (1 << 7),
|
||||
CLUTTER_FEATURE_SHADERS_GLSL = (1 << 8),
|
||||
CLUTTER_FEATURE_OFFSCREEN = (1 << 9)
|
||||
CLUTTER_FEATURE_OFFSCREEN = (1 << 9),
|
||||
CLUTTER_FEATURE_STAGE_MULTIPLE = (1 << 10)
|
||||
} ClutterFeatureFlags;
|
||||
|
||||
gboolean clutter_feature_available (ClutterFeatureFlags feature);
|
||||
|
@ -27,6 +27,7 @@
|
||||
#define __CLUTTER_GROUP_H__
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <clutter/clutter-types.h>
|
||||
#include <clutter/clutter-actor.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
@ -82,6 +82,7 @@ static const GDebugKey clutter_debug_keys[] = {
|
||||
{ "scheduler", CLUTTER_DEBUG_SCHEDULER },
|
||||
{ "script", CLUTTER_DEBUG_SCRIPT },
|
||||
{ "shader", CLUTTER_DEBUG_SHADER },
|
||||
{ "multistage", CLUTTER_DEBUG_MULTISTAGE },
|
||||
};
|
||||
#endif /* CLUTTER_ENABLE_DEBUG */
|
||||
|
||||
@ -111,22 +112,21 @@ clutter_get_show_fps (void)
|
||||
* function, but queue a redraw using clutter_actor_queue_redraw().
|
||||
*/
|
||||
void
|
||||
clutter_redraw (void)
|
||||
clutter_redraw (ClutterStage *stage)
|
||||
{
|
||||
ClutterMainContext *ctx;
|
||||
ClutterActor *stage;
|
||||
static GTimer *timer = NULL;
|
||||
static guint timer_n_frames = 0;
|
||||
|
||||
ctx = clutter_context_get_default ();
|
||||
|
||||
stage = _clutter_backend_get_stage (ctx->backend);
|
||||
CLUTTER_TIMESTAMP (SCHEDULER, "Redraw start for stage:%p", stage);
|
||||
CLUTTER_NOTE (PAINT, " Redraw enter for stage:%p", stage);
|
||||
CLUTTER_NOTE (MULTISTAGE, "redraw called for stage:%p", stage);
|
||||
|
||||
CLUTTER_TIMESTAMP (SCHEDULER, "Redraw start");
|
||||
_clutter_backend_ensure_context (ctx->backend, stage);
|
||||
|
||||
CLUTTER_NOTE (PAINT, " Redraw enter");
|
||||
|
||||
/* Setup FPS count */
|
||||
/* Setup FPS count - not currently across *all* stages rather than per */
|
||||
if (clutter_get_show_fps ())
|
||||
{
|
||||
if (!timer)
|
||||
@ -142,8 +142,8 @@ clutter_redraw (void)
|
||||
|
||||
clutter_stage_get_perspectivex (CLUTTER_STAGE (stage), &perspective);
|
||||
|
||||
cogl_setup_viewport (clutter_actor_get_width (stage),
|
||||
clutter_actor_get_height (stage),
|
||||
cogl_setup_viewport (clutter_actor_get_width (CLUTTER_ACTOR(stage)),
|
||||
clutter_actor_get_height (CLUTTER_ACTOR(stage)),
|
||||
perspective.fovy,
|
||||
perspective.aspect,
|
||||
perspective.z_near,
|
||||
@ -156,7 +156,7 @@ clutter_redraw (void)
|
||||
* the stage. It will likely need to swap buffers, vblank sync etc
|
||||
* which will be windowing system dependant.
|
||||
*/
|
||||
_clutter_backend_redraw (ctx->backend);
|
||||
_clutter_backend_redraw (ctx->backend, stage);
|
||||
|
||||
/* Complete FPS info */
|
||||
if (clutter_get_show_fps ())
|
||||
@ -171,9 +171,8 @@ clutter_redraw (void)
|
||||
}
|
||||
}
|
||||
|
||||
CLUTTER_NOTE (PAINT, " Redraw leave");
|
||||
|
||||
CLUTTER_TIMESTAMP (SCHEDULER, "Redraw finish");
|
||||
CLUTTER_NOTE (PAINT, " Redraw leave for stage:%p", stage);
|
||||
CLUTTER_TIMESTAMP (SCHEDULER, "Redraw finish for stage:%p", stage);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -233,6 +232,27 @@ _clutter_do_pick (ClutterStage *stage,
|
||||
|
||||
context = clutter_context_get_default ();
|
||||
|
||||
_clutter_backend_ensure_context (context->backend, stage);
|
||||
|
||||
/* FIXME: needed for when a context switch happens - probably
|
||||
* should put into its own function somewhere..
|
||||
*/
|
||||
if (CLUTTER_PRIVATE_FLAGS (stage) & CLUTTER_ACTOR_SYNC_MATRICES)
|
||||
{
|
||||
ClutterPerspective perspective;
|
||||
|
||||
clutter_stage_get_perspectivex (CLUTTER_STAGE (stage), &perspective);
|
||||
|
||||
cogl_setup_viewport (clutter_actor_get_width (CLUTTER_ACTOR(stage)),
|
||||
clutter_actor_get_height (CLUTTER_ACTOR(stage)),
|
||||
perspective.fovy,
|
||||
perspective.aspect,
|
||||
perspective.z_near,
|
||||
perspective.z_far);
|
||||
|
||||
CLUTTER_UNSET_PRIVATE_FLAGS (stage, CLUTTER_ACTOR_SYNC_MATRICES);
|
||||
}
|
||||
|
||||
cogl_paint_init (&white);
|
||||
cogl_enable (0);
|
||||
|
||||
@ -259,7 +279,7 @@ _clutter_do_pick (ClutterStage *stage,
|
||||
glReadPixels(x, viewport[3] - y -1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
|
||||
|
||||
if (pixel[0] == 0xff && pixel[1] == 0xff && pixel[2] == 0xff)
|
||||
return CLUTTER_ACTOR (stage);
|
||||
return CLUTTER_ACTOR (stage);
|
||||
|
||||
cogl_get_bitmasks (&r, &g, &b, NULL);
|
||||
|
||||
@ -969,6 +989,7 @@ clutter_init_with_args (int *argc,
|
||||
GOptionGroup *group;
|
||||
gboolean res;
|
||||
GError *stage_error;
|
||||
ClutterActor *stage;
|
||||
|
||||
if (clutter_is_initialized)
|
||||
return CLUTTER_INIT_SUCCESS;
|
||||
@ -998,7 +1019,10 @@ clutter_init_with_args (int *argc,
|
||||
clutter_context = clutter_context_get_default ();
|
||||
|
||||
stage_error = NULL;
|
||||
if (!_clutter_backend_init_stage (clutter_context->backend, &stage_error))
|
||||
stage = _clutter_backend_create_stage (clutter_context->backend,
|
||||
&stage_error);
|
||||
|
||||
if (!stage)
|
||||
{
|
||||
g_propagate_error (error, stage_error);
|
||||
return CLUTTER_INIT_ERROR_INTERNAL;
|
||||
@ -1064,6 +1088,7 @@ clutter_init (int *argc,
|
||||
char ***argv)
|
||||
{
|
||||
ClutterMainContext *context;
|
||||
ClutterActor *stage;
|
||||
GError *stage_error;
|
||||
|
||||
if (clutter_is_initialized)
|
||||
@ -1091,7 +1116,10 @@ clutter_init (int *argc,
|
||||
|
||||
/* Stage will give us a GL Context etc */
|
||||
stage_error = NULL;
|
||||
if (!_clutter_backend_init_stage (context->backend, &stage_error))
|
||||
|
||||
stage = _clutter_backend_create_stage (context->backend, &stage_error);
|
||||
|
||||
if (!stage)
|
||||
{
|
||||
CLUTTER_NOTE (MISC, "stage failed to initialise.");
|
||||
g_critical (stage_error->message);
|
||||
@ -1165,7 +1193,9 @@ event_click_count_generate (ClutterEvent *event)
|
||||
previous_button_number = event->button.button;
|
||||
}
|
||||
|
||||
/* store time and position for this click for comparison with next event */
|
||||
/* store time and position for this click for comparison with
|
||||
* next event
|
||||
*/
|
||||
previous_time = event->button.time;
|
||||
previous_x = event->button.x;
|
||||
previous_y = event->button.y;
|
||||
@ -1301,6 +1331,7 @@ generate_enter_leave_events (ClutterEvent *event)
|
||||
cev.crossing.x = event->motion.x;
|
||||
cev.crossing.y = event->motion.y;
|
||||
cev.crossing.source = context->motion_last_actor;
|
||||
cev.crossing.stage = event->any.stage;
|
||||
/* unref in free */
|
||||
cev.crossing.related = motion_current_actor;
|
||||
|
||||
@ -1314,6 +1345,7 @@ generate_enter_leave_events (ClutterEvent *event)
|
||||
cev.crossing.x = event->motion.x;
|
||||
cev.crossing.y = event->motion.y;
|
||||
cev.crossing.source = motion_current_actor;
|
||||
cev.crossing.stage = event->any.stage;
|
||||
|
||||
if (context->motion_last_actor)
|
||||
cev.crossing.related = context->motion_last_actor;
|
||||
@ -1371,7 +1403,7 @@ clutter_do_event (ClutterEvent *event)
|
||||
|
||||
context = clutter_context_get_default ();
|
||||
backend = context->backend;
|
||||
stage = _clutter_backend_get_stage (backend);
|
||||
stage = CLUTTER_ACTOR(event->any.stage);
|
||||
|
||||
if (!stage)
|
||||
return;
|
||||
@ -1394,7 +1426,13 @@ clutter_do_event (ClutterEvent *event)
|
||||
event->any.source = stage;
|
||||
/* the stage did not handle the event, so we just quit */
|
||||
if (!clutter_stage_event (CLUTTER_STAGE (stage), event))
|
||||
clutter_main_quit ();
|
||||
{
|
||||
if (stage == clutter_stage_get_default())
|
||||
clutter_main_quit ();
|
||||
else
|
||||
clutter_actor_destroy (stage);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case CLUTTER_KEY_PRESS:
|
||||
|
@ -72,7 +72,7 @@ void clutter_main (void);
|
||||
void clutter_main_quit (void);
|
||||
gint clutter_main_level (void);
|
||||
|
||||
void clutter_redraw (void);
|
||||
void clutter_redraw (ClutterStage *stage);
|
||||
|
||||
void clutter_do_event (ClutterEvent *event);
|
||||
|
||||
|
@ -40,6 +40,7 @@
|
||||
|
||||
#include <pango/pangoft2.h>
|
||||
|
||||
#include "clutter-stage-manager.h"
|
||||
#include "clutter-event.h"
|
||||
#include "clutter-backend.h"
|
||||
#include "clutter-stage.h"
|
||||
@ -72,28 +73,33 @@ struct _ClutterMainContext
|
||||
{
|
||||
ClutterBackend *backend; /* holds a pointer to the windowing
|
||||
system backend */
|
||||
ClutterStageManager *stage_manager; /* stages */
|
||||
GQueue *events_queue; /* the main event queue */
|
||||
PangoFT2FontMap *font_map;
|
||||
guint update_idle; /* repaint idler id */
|
||||
|
||||
guint is_initialized : 1;
|
||||
GTimer *timer; /* Used for debugging scheduler */
|
||||
|
||||
ClutterPickMode pick_mode; /* Indicates pick render mode */
|
||||
guint motion_events_per_actor : 1;/* set for enter/leave events */
|
||||
|
||||
guint motion_events_per_actor : 1;/* set f
|
||||
or enter/leave events */
|
||||
|
||||
guint motion_frequency; /* Motion events per second */
|
||||
gint num_reactives; /* Num of reactive actors */
|
||||
|
||||
ClutterIDPool *id_pool; /* mapping between reused integer ids and actors */
|
||||
|
||||
ClutterIDPool *id_pool; /* mapping between reused integer ids
|
||||
* and actors
|
||||
*/
|
||||
guint frame_rate; /* Default FPS */
|
||||
|
||||
ClutterActor *pointer_grab_actor; /* The actor having the pointer grab
|
||||
(or NULL if there is no pointer grab)
|
||||
* (or NULL if there is no pointer grab
|
||||
*/
|
||||
ClutterActor *keyboard_grab_actor; /* The actor having the pointer grab
|
||||
(or NULL if there is no pointer grab)
|
||||
*/
|
||||
* (or NULL if there is no pointer
|
||||
* grab)
|
||||
*/
|
||||
GSList *shaders; /* stack of overridden shaders */
|
||||
|
||||
ClutterActor *motion_last_actor;
|
||||
@ -115,13 +121,32 @@ ClutterMainContext *clutter_context_get_default (void);
|
||||
|
||||
#define I_(str) (g_intern_static_string ((str)))
|
||||
|
||||
/* stage manager */
|
||||
|
||||
struct _ClutterStageManager
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
||||
GSList *stages;
|
||||
};
|
||||
|
||||
void _clutter_stage_manager_add_stage (ClutterStageManager *stage_manager,
|
||||
ClutterStage *stage);
|
||||
void _clutter_stage_manager_remove_stage (ClutterStageManager *stage_manager,
|
||||
ClutterStage *stage);
|
||||
|
||||
/* vfuncs implemnted by backend */
|
||||
|
||||
GType _clutter_backend_impl_get_type (void);
|
||||
|
||||
ClutterActor *_clutter_backend_get_stage (ClutterBackend *backend);
|
||||
void _clutter_backend_redraw (ClutterBackend *backend,
|
||||
ClutterStage *stage);
|
||||
|
||||
void _clutter_backend_redraw (ClutterBackend *backend);
|
||||
ClutterActor* _clutter_backend_create_stage (ClutterBackend *backend,
|
||||
GError **error);
|
||||
|
||||
void _clutter_backend_redraw (ClutterBackend *backend,
|
||||
ClutterStage *stage);
|
||||
|
||||
void _clutter_backend_add_options (ClutterBackend *backend,
|
||||
GOptionGroup *group);
|
||||
@ -129,10 +154,11 @@ gboolean _clutter_backend_pre_parse (ClutterBackend *backend,
|
||||
GError **error);
|
||||
gboolean _clutter_backend_post_parse (ClutterBackend *backend,
|
||||
GError **error);
|
||||
gboolean _clutter_backend_init_stage (ClutterBackend *backend,
|
||||
GError **error);
|
||||
void _clutter_backend_init_events (ClutterBackend *backend);
|
||||
|
||||
void _clutter_backend_ensure_context (ClutterBackend *backend,
|
||||
ClutterStage *stage);
|
||||
|
||||
ClutterFeatureFlags _clutter_backend_get_features (ClutterBackend *backend);
|
||||
|
||||
void _clutter_feature_init (void);
|
||||
|
282
clutter/clutter-stage-manager.c
Normal file
282
clutter/clutter-stage-manager.c
Normal file
@ -0,0 +1,282 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
|
||||
#include "clutter-marshal.h"
|
||||
#include "clutter-debug.h"
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-version.h"
|
||||
#include "clutter-stage-manager.h"
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_DEFAULT_STAGE
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
STAGE_ADDED,
|
||||
STAGE_REMOVED,
|
||||
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
static guint manager_signals[LAST_SIGNAL] = { 0, };
|
||||
static ClutterStage *default_stage = NULL;
|
||||
|
||||
G_DEFINE_TYPE (ClutterStageManager, clutter_stage_manager, G_TYPE_OBJECT);
|
||||
|
||||
static void
|
||||
clutter_stage_manager_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_DEFAULT_STAGE:
|
||||
clutter_stage_manager_set_default_stage (CLUTTER_STAGE_MANAGER (gobject),
|
||||
g_value_get_object (value));
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_manager_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_DEFAULT_STAGE:
|
||||
g_value_set_object (value, default_stage);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_manager_dispose (GObject *gobject)
|
||||
{
|
||||
ClutterStageManager *stage_manager;
|
||||
GSList *l;
|
||||
|
||||
stage_manager = CLUTTER_STAGE_MANAGER (gobject);
|
||||
|
||||
for (l = stage_manager->stages; l; l = l->next)
|
||||
{
|
||||
ClutterActor *stage = l->data;
|
||||
|
||||
if (stage)
|
||||
clutter_actor_destroy (stage);
|
||||
}
|
||||
|
||||
g_slist_free (stage_manager->stages);
|
||||
stage_manager->stages = NULL;
|
||||
|
||||
G_OBJECT_CLASS (clutter_stage_manager_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_manager_class_init (ClutterStageManagerClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
|
||||
gobject_class->dispose = clutter_stage_manager_dispose;
|
||||
gobject_class->set_property = clutter_stage_manager_set_property;
|
||||
gobject_class->get_property = clutter_stage_manager_get_property;
|
||||
|
||||
/**
|
||||
* ClutterStageManager:default-stage:
|
||||
*
|
||||
* The default stage used by Clutter.
|
||||
*
|
||||
* Since: 0.8
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_DEFAULT_STAGE,
|
||||
g_param_spec_object ("default-stage",
|
||||
"Default Stage",
|
||||
"The default stage",
|
||||
CLUTTER_TYPE_STAGE,
|
||||
CLUTTER_PARAM_READWRITE));
|
||||
|
||||
/**
|
||||
* ClutterStageManager:stage-added:
|
||||
* @stage_manager: the object which received the signal
|
||||
* @stage: the added stage
|
||||
*
|
||||
* The ::stage-added signal is emitted each time a new #ClutterStage
|
||||
* has been added to the stage manager.
|
||||
*
|
||||
* Since: 0.8
|
||||
*/
|
||||
manager_signals[STAGE_ADDED] =
|
||||
g_signal_new ("stage-added",
|
||||
G_OBJECT_CLASS_TYPE (gobject_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (ClutterStageManagerClass, stage_added),
|
||||
NULL, NULL,
|
||||
clutter_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE, 1,
|
||||
CLUTTER_TYPE_STAGE);
|
||||
/**
|
||||
* ClutterStageManager::stage-removed:
|
||||
* @stage_manager: the object which received the signal
|
||||
* @stage: the removed stage
|
||||
*
|
||||
* The ::stage-removed signal is emitted each time a #ClutterStage
|
||||
* has been removed from the stage manager.
|
||||
*
|
||||
* Since: 0.8
|
||||
*/
|
||||
manager_signals[STAGE_REMOVED] =
|
||||
g_signal_new ("stage-removed",
|
||||
G_OBJECT_CLASS_TYPE (gobject_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (ClutterStageManagerClass, stage_removed),
|
||||
NULL, NULL,
|
||||
clutter_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE, 1,
|
||||
CLUTTER_TYPE_STAGE);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_stage_manager_init (ClutterStageManager *stage_manager)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_stage_manager_get_default:
|
||||
*
|
||||
* Returns the default #ClutterStageManager.
|
||||
*
|
||||
* Return value: the default stage manager instance. The returned object
|
||||
* is owned by Clutter and you should not reference or unreference it.
|
||||
*
|
||||
* Since: 0.8
|
||||
*/
|
||||
ClutterStageManager *
|
||||
clutter_stage_manager_get_default (void)
|
||||
{
|
||||
static ClutterStageManager *stage_manager = NULL;
|
||||
|
||||
if (G_UNLIKELY (stage_manager == NULL))
|
||||
stage_manager = g_object_new (CLUTTER_TYPE_STAGE_MANAGER, NULL);
|
||||
|
||||
return stage_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_stage_manager_set_default_stage:
|
||||
* @stage_manager: a #ClutterStageManager
|
||||
* @stage: a #ClutterStage
|
||||
*
|
||||
* Sets @stage as the default stage.
|
||||
*
|
||||
* Since: 0.8
|
||||
*/
|
||||
void
|
||||
clutter_stage_manager_set_default_stage (ClutterStageManager *stage_manager,
|
||||
ClutterStage *stage)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_STAGE_MANAGER (stage_manager));
|
||||
g_return_if_fail (CLUTTER_IS_STAGE (stage));
|
||||
|
||||
if (!g_slist_find (stage_manager->stages, stage))
|
||||
_clutter_stage_manager_add_stage (stage_manager, stage);
|
||||
|
||||
default_stage = stage;
|
||||
|
||||
g_object_notify (G_OBJECT (stage_manager), "default-stage");
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_stage_manager_get_default_stage:
|
||||
* @stage_manager: a #ClutterStageManager
|
||||
*
|
||||
* Returns the default #ClutterStage.
|
||||
*
|
||||
* Return value: the default stage. The returned object is owned by
|
||||
* Clutter and you should never reference or unreference it
|
||||
*
|
||||
* Since: 0.8
|
||||
*/
|
||||
ClutterStage *
|
||||
clutter_stage_manager_get_default_stage (ClutterStageManager *stage_manager)
|
||||
{
|
||||
return default_stage;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_stage_manager_list_stage:
|
||||
* @stage_manager: a #ClutterStageManager
|
||||
*
|
||||
* Lists all currently used stages.
|
||||
*
|
||||
* Return value: a newly allocated list of #ClutterStage objects. Use
|
||||
* g_slist_free() to deallocate it when done.
|
||||
*
|
||||
* Since: 0.8
|
||||
*/
|
||||
GSList *
|
||||
clutter_stage_manager_list_stages (ClutterStageManager *stage_manager)
|
||||
{
|
||||
return g_slist_copy (stage_manager->stages);
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_stage_manager_add_stage (ClutterStageManager *stage_manager,
|
||||
ClutterStage *stage)
|
||||
{
|
||||
if (g_slist_find (stage_manager->stages, stage))
|
||||
{
|
||||
g_warning ("Trying to add a stage to the list of managed stages, "
|
||||
"but it is already in it, aborting.");
|
||||
return;
|
||||
}
|
||||
|
||||
g_object_ref_sink (stage);
|
||||
stage_manager->stages = g_slist_append (stage_manager->stages, stage);
|
||||
|
||||
if (!default_stage)
|
||||
{
|
||||
default_stage = stage;
|
||||
|
||||
g_object_notify (G_OBJECT (stage_manager), "default-stage");
|
||||
}
|
||||
|
||||
g_signal_emit (stage_manager, manager_signals[STAGE_ADDED], 0, stage);
|
||||
}
|
||||
|
||||
void
|
||||
_clutter_stage_manager_remove_stage (ClutterStageManager *stage_manager,
|
||||
ClutterStage *stage)
|
||||
{
|
||||
if (!g_slist_find (stage_manager->stages, stage))
|
||||
{
|
||||
g_warning ("Trying to remove an unknown stage from the list "
|
||||
"of managed stages, aborting.");
|
||||
return;
|
||||
}
|
||||
|
||||
stage_manager->stages = g_slist_remove (stage_manager->stages, stage);
|
||||
|
||||
/* if it's the default stage, get the first available from the list */
|
||||
if (default_stage == stage)
|
||||
default_stage = stage_manager->stages ? stage_manager->stages->data
|
||||
: NULL;
|
||||
|
||||
g_signal_emit (stage_manager, manager_signals[STAGE_REMOVED], 0, stage);
|
||||
|
||||
g_object_unref (stage);
|
||||
}
|
65
clutter/clutter-stage-manager.h
Normal file
65
clutter/clutter-stage-manager.h
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Authored By Matthew Allum <mallum@openedhand.com>
|
||||
*
|
||||
* Copyright (C) 2008 OpenedHand
|
||||
*
|
||||
* 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_MANAGER_H__
|
||||
#define __CLUTTER_STAGE_MANAGER_H__
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib-object.h>
|
||||
#include <clutter/clutter-stage.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_STAGE_MANAGER (clutter_stage_manager_get_type ())
|
||||
#define CLUTTER_STAGE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_STAGE_MANAGER, ClutterStageManager))
|
||||
#define CLUTTER_IS_STAGE_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_STAGE_MANAGER))
|
||||
#define CLUTTER_STAGE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_STAGE_MANAGER, ClutterStageManagerClass))
|
||||
#define CLUTTER_IS_STAGE_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_STAGE_MANAGER))
|
||||
#define CLUTTER_STAGE_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_STAGE_MANAGER, ClutterStageManagerClass))
|
||||
|
||||
typedef struct _ClutterStageManager ClutterStageManager;
|
||||
typedef struct _ClutterStageManagerClass ClutterStageManagerClass;
|
||||
|
||||
struct _ClutterStageManagerClass
|
||||
{
|
||||
GObjectClass parent_class;
|
||||
|
||||
void (* stage_added) (ClutterStageManager *stage_manager,
|
||||
ClutterStage *stage);
|
||||
void (* stage_removed) (ClutterStageManager *stage_manager,
|
||||
ClutterStage *stage);
|
||||
};
|
||||
|
||||
GType clutter_stage_manager_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ClutterStageManager *clutter_stage_manager_get_default (void);
|
||||
void clutter_stage_manager_set_default_stage (ClutterStageManager *stage_manager,
|
||||
ClutterStage *stage);
|
||||
ClutterStage * clutter_stage_manager_get_default_stage (ClutterStageManager *stage_manager);
|
||||
GSList * clutter_stage_manager_list_stages (ClutterStageManager *stage_manager);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_STAGE_MANAGER_H__ */
|
@ -44,7 +44,9 @@
|
||||
#include "clutter-enum-types.h"
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-debug.h"
|
||||
#include "clutter-stage-manager.h"
|
||||
#include "clutter-version.h" /* For flavour */
|
||||
#include "clutter-id-pool.h"
|
||||
|
||||
#include "cogl.h"
|
||||
|
||||
@ -67,6 +69,8 @@ struct _ClutterStagePrivate
|
||||
|
||||
gchar *title;
|
||||
ClutterActor *key_focused_actor;
|
||||
|
||||
guint update_idle; /* repaint idler id */
|
||||
};
|
||||
|
||||
enum
|
||||
@ -469,12 +473,9 @@ clutter_stage_init (ClutterStage *self)
|
||||
ClutterActor *
|
||||
clutter_stage_get_default (void)
|
||||
{
|
||||
ClutterMainContext *context;
|
||||
ClutterStageManager *stage_manager = clutter_stage_manager_get_default ();
|
||||
|
||||
context = clutter_context_get_default ();
|
||||
g_assert (context != NULL);
|
||||
|
||||
return _clutter_backend_get_stage (context->backend);
|
||||
return CLUTTER_ACTOR(clutter_stage_manager_get_default_stage(stage_manager));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1349,3 +1350,115 @@ clutter_fog_get_type (void)
|
||||
|
||||
return our_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_stage_create_new:
|
||||
*
|
||||
* Creates a new, non-default stage. A non-default stage is a new
|
||||
* top-level actor which can be used as another container. It works
|
||||
* exactly like the default stage, but while clutter_stage_get_default()
|
||||
* will always return the same instance, you will have to keep a pointer
|
||||
* to any #ClutterStage returned by clutter_stage_create().
|
||||
*
|
||||
* The ability to support multiple stages depends on the current
|
||||
* backend. Use clutter_feature_available() and
|
||||
* %CLUTTER_FEATURE_STAGE_MULTIPLE to check at runtime whether a
|
||||
* backend supports multiple stages.
|
||||
*
|
||||
* Return value: a new stage, or %NULL if the default backend does
|
||||
* not support multiple stages. Use clutter_actor_destroy() to
|
||||
* close the returned stage.
|
||||
*
|
||||
* Since: 0.8
|
||||
*/
|
||||
ClutterActor*
|
||||
clutter_stage_create_new (void)
|
||||
{
|
||||
ClutterBackend *backend = clutter_get_default_backend ();
|
||||
GError *error = NULL;
|
||||
ClutterActor *retval;
|
||||
|
||||
if (!clutter_feature_available (CLUTTER_FEATURE_STAGE_MULTIPLE))
|
||||
{
|
||||
g_warning ("Unable to create a new stage: the %s backend does not "
|
||||
"support multiple stages.",
|
||||
CLUTTER_FLAVOUR);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
retval = _clutter_backend_create_stage (backend, &error);
|
||||
if (error)
|
||||
{
|
||||
g_warning ("Unable to create a secondary stage: %s", error->message);
|
||||
g_error_free (error);
|
||||
retval = NULL;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_stage_ensure_current:
|
||||
* @stage: the #ClutterStage
|
||||
*
|
||||
* This function essentially makes sure the right GL context is
|
||||
* current for the passed stage. It is not intended to
|
||||
* be used by applications.
|
||||
*
|
||||
* Since: 0.8
|
||||
*/
|
||||
void
|
||||
clutter_stage_ensure_current (ClutterStage *stage)
|
||||
{
|
||||
ClutterMainContext *ctx;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_STAGE (stage));
|
||||
|
||||
ctx = clutter_context_get_default ();
|
||||
|
||||
_clutter_backend_ensure_context (ctx->backend, stage);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
redraw_update_idle (gpointer data)
|
||||
{
|
||||
ClutterStage *stage = CLUTTER_STAGE(data);
|
||||
|
||||
if (stage->priv->update_idle)
|
||||
{
|
||||
g_source_remove (stage->priv->update_idle);
|
||||
stage->priv->update_idle = 0;
|
||||
}
|
||||
|
||||
CLUTTER_NOTE (MULTISTAGE, "redrawing via idle for stage:%p", stage);
|
||||
clutter_redraw (stage);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_stage_queue_redraw:
|
||||
* @stage: the #ClutterStage
|
||||
*
|
||||
* Queues a redraw for the passed stage. Note applications should call
|
||||
* #clutter_actor_queue_redraw over this.
|
||||
*
|
||||
* Since: 0.8
|
||||
*/
|
||||
void
|
||||
clutter_stage_queue_redraw (ClutterStage *stage)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_STAGE (stage));
|
||||
|
||||
if (!stage->priv->update_idle)
|
||||
{
|
||||
CLUTTER_TIMESTAMP (SCHEDULER, "Adding idle source for stage: %p", stage);
|
||||
|
||||
/* FIXME: weak_ref self in case we dissapear before paint? */
|
||||
stage->priv->update_idle =
|
||||
clutter_threads_add_idle_full (G_PRIORITY_DEFAULT + 10,
|
||||
redraw_update_idle,
|
||||
stage,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
#ifndef __CLUTTER_STAGE_H__
|
||||
#define __CLUTTER_STAGE_H__
|
||||
|
||||
#include <clutter/clutter-types.h>
|
||||
#include <clutter/clutter-group.h>
|
||||
#include <clutter/clutter-color.h>
|
||||
#include <clutter/clutter-event.h>
|
||||
@ -80,7 +81,7 @@ G_BEGIN_DECLS
|
||||
typedef struct _ClutterPerspective ClutterPerspective;
|
||||
typedef struct _ClutterFog ClutterFog;
|
||||
|
||||
typedef struct _ClutterStage ClutterStage;
|
||||
|
||||
typedef struct _ClutterStageClass ClutterStageClass;
|
||||
typedef struct _ClutterStagePrivate ClutterStagePrivate;
|
||||
|
||||
@ -237,6 +238,12 @@ void clutter_stage_set_key_focus (ClutterStage *stage,
|
||||
ClutterActor *actor);
|
||||
ClutterActor * clutter_stage_get_key_focus (ClutterStage *stage);
|
||||
|
||||
ClutterActor* clutter_stage_create_new (void);
|
||||
|
||||
void clutter_stage_ensure_current (ClutterStage *stage);
|
||||
|
||||
void clutter_stage_queue_redraw (ClutterStage *stage);
|
||||
|
||||
/* Commodity macro */
|
||||
#define clutter_stage_add(stage,actor) G_STMT_START { \
|
||||
if (CLUTTER_IS_STAGE ((stage)) && CLUTTER_IS_ACTOR ((actor))) \
|
||||
|
@ -39,6 +39,7 @@ G_BEGIN_DECLS
|
||||
|
||||
/* Forward delarations to avoid header catch 22's */
|
||||
typedef struct _ClutterActor ClutterActor;
|
||||
typedef struct _ClutterStage ClutterStage;
|
||||
|
||||
/**
|
||||
* ClutterGravity:
|
||||
|
@ -213,7 +213,7 @@ clutter_backend_glx_get_features (ClutterBackend *backend)
|
||||
{
|
||||
ClutterBackendGLX *backend_glx = CLUTTER_BACKEND_GLX (backend);
|
||||
const gchar *glx_extensions = NULL;
|
||||
ClutterFeatureFlags flags = 0;
|
||||
ClutterFeatureFlags flags = CLUTTER_FEATURE_STAGE_MULTIPLE;
|
||||
|
||||
/* FIXME: we really need to check if gl context is set */
|
||||
|
||||
@ -343,14 +343,32 @@ clutter_backend_glx_get_features (ClutterBackend *backend)
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_backend_glx_redraw (ClutterBackend *backend)
|
||||
clutter_backend_glx_ensure_context (ClutterBackend *backend,
|
||||
ClutterStage *stage)
|
||||
{
|
||||
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||
ClutterBackendGLX *backend_glx;
|
||||
ClutterStageGLX *stage_glx;
|
||||
ClutterStageX11 *stage_x11;
|
||||
|
||||
stage_x11 = CLUTTER_STAGE_X11(backend_x11->stage);
|
||||
stage_glx = CLUTTER_STAGE_GLX(backend_x11->stage);
|
||||
stage_x11 = CLUTTER_STAGE_X11(stage);
|
||||
stage_glx = CLUTTER_STAGE_GLX(stage);
|
||||
backend_glx = CLUTTER_BACKEND_GLX(backend);
|
||||
|
||||
CLUTTER_NOTE (MULTISTAGE, "setting context for stage:%p", stage );
|
||||
|
||||
glXMakeCurrent (stage_x11->xdpy,
|
||||
stage_x11->xwin,
|
||||
backend_glx->gl_context);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_backend_glx_redraw (ClutterBackend *backend, ClutterStage *stage)
|
||||
{
|
||||
ClutterStageGLX *stage_glx;
|
||||
ClutterStageX11 *stage_x11;
|
||||
|
||||
stage_x11 = CLUTTER_STAGE_X11(stage);
|
||||
stage_glx = CLUTTER_STAGE_GLX(stage);
|
||||
|
||||
clutter_actor_paint (CLUTTER_ACTOR (stage_glx));
|
||||
|
||||
@ -370,47 +388,42 @@ clutter_backend_glx_redraw (ClutterBackend *backend)
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
clutter_backend_glx_init_stage (ClutterBackend *backend,
|
||||
GError **error)
|
||||
ClutterActor*
|
||||
clutter_backend_glx_create_stage (ClutterBackend *backend,
|
||||
GError **error)
|
||||
{
|
||||
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||
ClutterStageX11 *stage_x11;
|
||||
ClutterActor *stage;
|
||||
|
||||
if (!backend_x11->stage)
|
||||
{
|
||||
ClutterStageX11 *stage_x11;
|
||||
ClutterActor *stage;
|
||||
stage = g_object_new (CLUTTER_TYPE_STAGE_GLX, NULL);
|
||||
|
||||
stage = g_object_new (CLUTTER_TYPE_STAGE_GLX, NULL);
|
||||
/* copy backend data into the stage */
|
||||
stage_x11 = CLUTTER_STAGE_X11 (stage);
|
||||
stage_x11->xdpy = backend_x11->xdpy;
|
||||
stage_x11->xwin_root = backend_x11->xwin_root;
|
||||
stage_x11->xscreen = backend_x11->xscreen_num;
|
||||
stage_x11->backend = backend_x11;
|
||||
|
||||
/* copy backend data into the stage */
|
||||
stage_x11 = CLUTTER_STAGE_X11 (stage);
|
||||
stage_x11->xdpy = backend_x11->xdpy;
|
||||
stage_x11->xwin_root = backend_x11->xwin_root;
|
||||
stage_x11->xscreen = backend_x11->xscreen_num;
|
||||
stage_x11->backend = backend_x11;
|
||||
CLUTTER_NOTE (MISC, "X11 stage created (display:%p, screen:%d, root:%u)",
|
||||
stage_x11->xdpy,
|
||||
stage_x11->xscreen,
|
||||
(unsigned int) stage_x11->xwin_root);
|
||||
|
||||
CLUTTER_NOTE (MISC, "X11 stage created (display:%p, screen:%d, root:%u)",
|
||||
stage_x11->xdpy,
|
||||
stage_x11->xscreen,
|
||||
(unsigned int) stage_x11->xwin_root);
|
||||
/* needed ? */
|
||||
g_object_set_data (G_OBJECT (stage), "clutter-backend", backend);
|
||||
|
||||
g_object_set_data (G_OBJECT (stage), "clutter-backend", backend);
|
||||
clutter_actor_realize (stage);
|
||||
|
||||
backend_x11->stage = g_object_ref_sink (stage);
|
||||
}
|
||||
|
||||
clutter_actor_realize (backend_x11->stage);
|
||||
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (backend_x11->stage))
|
||||
if (!CLUTTER_ACTOR_IS_REALIZED (stage))
|
||||
{
|
||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||
CLUTTER_INIT_ERROR_INTERNAL,
|
||||
"Unable to realize the main stage");
|
||||
return FALSE;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return stage;
|
||||
}
|
||||
|
||||
|
||||
@ -421,15 +434,16 @@ clutter_backend_glx_class_init (ClutterBackendGLXClass *klass)
|
||||
ClutterBackendClass *backend_class = CLUTTER_BACKEND_CLASS (klass);
|
||||
|
||||
gobject_class->constructor = clutter_backend_glx_constructor;
|
||||
gobject_class->dispose = clutter_backend_glx_dispose;
|
||||
gobject_class->finalize = clutter_backend_glx_finalize;
|
||||
gobject_class->dispose = clutter_backend_glx_dispose;
|
||||
gobject_class->finalize = clutter_backend_glx_finalize;
|
||||
|
||||
backend_class->pre_parse = clutter_backend_glx_pre_parse;
|
||||
backend_class->post_parse = clutter_backend_glx_post_parse;
|
||||
backend_class->init_stage = clutter_backend_glx_init_stage;
|
||||
backend_class->create_stage = clutter_backend_glx_create_stage;
|
||||
backend_class->add_options = clutter_backend_glx_add_options;
|
||||
backend_class->get_features = clutter_backend_glx_get_features;
|
||||
backend_class->redraw = clutter_backend_glx_redraw;
|
||||
backend_class->ensure_context = clutter_backend_glx_ensure_context;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -72,6 +72,9 @@ struct _ClutterBackendGLX
|
||||
{
|
||||
ClutterBackendX11 parent_instance;
|
||||
|
||||
/* Single context for all wins */
|
||||
GLXContext gl_context;
|
||||
|
||||
/* Vblank stuff */
|
||||
GetVideoSyncProc get_video_sync;
|
||||
WaitVideoSyncProc wait_video_sync;
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "../clutter-shader.h"
|
||||
#include "../clutter-group.h"
|
||||
#include "../clutter-container.h"
|
||||
#include "../clutter-stage.h"
|
||||
|
||||
#include "cogl.h"
|
||||
|
||||
@ -98,12 +99,6 @@ clutter_stage_glx_unrealize (ClutterActor *actor)
|
||||
|
||||
glXMakeCurrent (stage_x11->xdpy, None, NULL);
|
||||
|
||||
if (stage_glx->gl_context != None)
|
||||
{
|
||||
glXDestroyContext (stage_x11->xdpy, stage_glx->gl_context);
|
||||
stage_glx->gl_context = None;
|
||||
}
|
||||
|
||||
XSync (stage_x11->xdpy, False);
|
||||
|
||||
clutter_x11_untrap_x_errors ();
|
||||
@ -116,12 +111,15 @@ clutter_stage_glx_realize (ClutterActor *actor)
|
||||
{
|
||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (actor);
|
||||
ClutterStageGLX *stage_glx = CLUTTER_STAGE_GLX (actor);
|
||||
gboolean is_offscreen;
|
||||
ClutterBackendGLX *backend_glx;
|
||||
gboolean is_offscreen;
|
||||
|
||||
CLUTTER_NOTE (MISC, "Realizing main stage");
|
||||
|
||||
g_object_get (actor, "offscreen", &is_offscreen, NULL);
|
||||
|
||||
backend_glx = CLUTTER_BACKEND_GLX(clutter_get_default_backend());
|
||||
|
||||
if (G_LIKELY (!is_offscreen))
|
||||
{
|
||||
int gl_attributes[] =
|
||||
@ -142,7 +140,7 @@ clutter_stage_glx_realize (ClutterActor *actor)
|
||||
/* The following check seems strange */
|
||||
if (stage_x11->xvisinfo == None)
|
||||
stage_x11->xvisinfo = glXChooseVisual (stage_x11->xdpy,
|
||||
stage_x11->xscreen,
|
||||
stage_x11->xscreen,
|
||||
gl_attributes);
|
||||
if (!stage_x11->xvisinfo)
|
||||
{
|
||||
@ -195,26 +193,27 @@ clutter_stage_glx_realize (ClutterActor *actor)
|
||||
|
||||
clutter_stage_x11_set_wm_protocols (stage_x11);
|
||||
|
||||
if (stage_glx->gl_context)
|
||||
glXDestroyContext (stage_x11->xdpy, stage_glx->gl_context);
|
||||
|
||||
CLUTTER_NOTE (GL, "Creating GL Context");
|
||||
stage_glx->gl_context = glXCreateContext (stage_x11->xdpy,
|
||||
stage_x11->xvisinfo,
|
||||
0,
|
||||
True);
|
||||
|
||||
if (stage_glx->gl_context == None)
|
||||
if (backend_glx->gl_context == None)
|
||||
{
|
||||
g_critical ("Unable to create suitable GL context.");
|
||||
CLUTTER_NOTE (GL, "Creating GL Context");
|
||||
backend_glx->gl_context = glXCreateContext (stage_x11->xdpy,
|
||||
stage_x11->xvisinfo,
|
||||
0,
|
||||
True);
|
||||
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
||||
if (backend_glx->gl_context == None)
|
||||
{
|
||||
g_critical ("Unable to create suitable GL context.");
|
||||
|
||||
return;
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
CLUTTER_NOTE (GL, "glXMakeCurrent");
|
||||
glXMakeCurrent (stage_x11->xdpy, stage_x11->xwin, stage_glx->gl_context);
|
||||
|
||||
clutter_stage_ensure_current (CLUTTER_STAGE(stage_glx));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -244,8 +243,6 @@ clutter_stage_glx_realize (ClutterActor *actor)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (stage_glx->gl_context)
|
||||
glXDestroyContext (stage_x11->xdpy, stage_glx->gl_context);
|
||||
|
||||
stage_x11->xpixmap = XCreatePixmap (stage_x11->xdpy,
|
||||
stage_x11->xwin_root,
|
||||
@ -258,17 +255,34 @@ clutter_stage_glx_realize (ClutterActor *actor)
|
||||
stage_x11->xvisinfo,
|
||||
stage_x11->xpixmap);
|
||||
|
||||
/* indirect */
|
||||
stage_glx->gl_context = glXCreateContext (stage_x11->xdpy,
|
||||
stage_x11->xvisinfo,
|
||||
0,
|
||||
False);
|
||||
if (backend_glx->gl_context == None)
|
||||
{
|
||||
CLUTTER_NOTE (GL, "Creating GL Context");
|
||||
|
||||
/* FIXME: we probably need a seperate offscreen context here
|
||||
* - though it likely makes most sense to drop offscreen stages
|
||||
* and rely on FBO's instead and GLXPixmaps seems mostly broken
|
||||
* anyway..
|
||||
*/
|
||||
backend_glx->gl_context = glXCreateContext (stage_x11->xdpy,
|
||||
stage_x11->xvisinfo,
|
||||
0,
|
||||
False);
|
||||
|
||||
if (backend_glx->gl_context == None)
|
||||
{
|
||||
g_critical ("Unable to create suitable GL context.");
|
||||
|
||||
CLUTTER_ACTOR_UNSET_FLAGS (actor, CLUTTER_ACTOR_REALIZED);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
clutter_x11_trap_x_errors ();
|
||||
|
||||
glXMakeCurrent (stage_x11->xdpy,
|
||||
stage_glx->glxpixmap,
|
||||
stage_glx->gl_context);
|
||||
/* below will call glxMakeCurrent */
|
||||
clutter_stage_ensure_current (CLUTTER_STAGE(stage_glx));
|
||||
|
||||
if (clutter_x11_untrap_x_errors ())
|
||||
{
|
||||
|
@ -49,7 +49,6 @@ struct _ClutterStageGLX
|
||||
ClutterStageX11 parent_instance;
|
||||
|
||||
GLXPixmap glxpixmap;
|
||||
GLXContext gl_context;
|
||||
};
|
||||
|
||||
struct _ClutterStageGLXClass
|
||||
|
@ -192,14 +192,6 @@ clutter_backend_x11_init_events (ClutterBackend *backend)
|
||||
_clutter_backend_x11_events_init (backend);
|
||||
}
|
||||
|
||||
ClutterActor *
|
||||
clutter_backend_x11_get_stage (ClutterBackend *backend)
|
||||
{
|
||||
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||
|
||||
return backend_x11->stage;
|
||||
}
|
||||
|
||||
static const GOptionEntry entries[] =
|
||||
{
|
||||
{
|
||||
@ -247,19 +239,20 @@ clutter_backend_x11_finalize (GObject *gobject)
|
||||
static void
|
||||
clutter_backend_x11_dispose (GObject *gobject)
|
||||
{
|
||||
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (gobject);
|
||||
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (gobject);
|
||||
ClutterMainContext *context;
|
||||
ClutterStageManager *stage_manager;
|
||||
GSList *l;
|
||||
|
||||
if (backend_x11->stage)
|
||||
CLUTTER_NOTE (BACKEND, "Disposing the of stages");
|
||||
|
||||
context = clutter_context_get_default ();
|
||||
stage_manager = context->stage_manager;
|
||||
|
||||
for (l = stage_manager->stages; l; l = l->next)
|
||||
{
|
||||
CLUTTER_NOTE (BACKEND, "Disposing the main stage");
|
||||
|
||||
/* we unset the private flag on the stage so we can safely
|
||||
* destroy it without a warning from clutter_actor_destroy()
|
||||
*/
|
||||
CLUTTER_UNSET_PRIVATE_FLAGS (backend_x11->stage,
|
||||
CLUTTER_ACTOR_IS_TOPLEVEL);
|
||||
clutter_actor_destroy (backend_x11->stage);
|
||||
backend_x11->stage = NULL;
|
||||
ClutterActor *stage = CLUTTER_ACTOR (l->data);
|
||||
clutter_actor_destroy (stage);
|
||||
}
|
||||
|
||||
CLUTTER_NOTE (BACKEND, "Removing the event source");
|
||||
@ -314,10 +307,9 @@ clutter_backend_x11_class_init (ClutterBackendX11Class *klass)
|
||||
gobject_class->dispose = clutter_backend_x11_dispose;
|
||||
gobject_class->finalize = clutter_backend_x11_finalize;
|
||||
|
||||
backend_class->pre_parse = clutter_backend_x11_pre_parse;
|
||||
backend_class->pre_parse = clutter_backend_x11_pre_parse;
|
||||
backend_class->post_parse = clutter_backend_x11_post_parse;
|
||||
backend_class->init_events = clutter_backend_x11_init_events;
|
||||
backend_class->get_stage = clutter_backend_x11_get_stage;
|
||||
backend_class->add_options = clutter_backend_x11_add_options;
|
||||
backend_class->get_features = clutter_backend_x11_get_features;
|
||||
}
|
||||
|
@ -53,9 +53,6 @@ struct _ClutterBackendX11
|
||||
{
|
||||
ClutterBackend parent_instance;
|
||||
|
||||
/* main stage singleton */
|
||||
ClutterActor *stage;
|
||||
|
||||
Display *xdpy;
|
||||
Window xwin_root;
|
||||
Screen *xscreen;
|
||||
|
@ -158,7 +158,6 @@ void
|
||||
_clutter_backend_x11_events_init (ClutterBackend *backend)
|
||||
{
|
||||
ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||
ClutterStage *stage = CLUTTER_STAGE (backend_x11->stage);
|
||||
GSource *source;
|
||||
ClutterEventSource *event_source;
|
||||
int connection_number;
|
||||
@ -182,9 +181,6 @@ _clutter_backend_x11_events_init (ClutterBackend *backend)
|
||||
g_source_set_can_recurse (source, TRUE);
|
||||
g_source_attach (source, NULL);
|
||||
|
||||
xembed_set_info (backend_x11,
|
||||
clutter_x11_get_stage_window (stage),
|
||||
0);
|
||||
}
|
||||
|
||||
void
|
||||
@ -243,14 +239,13 @@ translate_key_event (ClutterBackend *backend,
|
||||
|
||||
static gboolean
|
||||
handle_wm_protocols_event (ClutterBackendX11 *backend_x11,
|
||||
Window window,
|
||||
XEvent *xevent)
|
||||
{
|
||||
Atom atom = (Atom) xevent->xclient.data.l[0];
|
||||
ClutterStage *stage = CLUTTER_STAGE (backend_x11->stage);
|
||||
Window stage_xwindow = clutter_x11_get_stage_window (stage);
|
||||
|
||||
if (atom == backend_x11->atom_WM_DELETE_WINDOW &&
|
||||
xevent->xany.window == stage_xwindow)
|
||||
xevent->xany.window == window)
|
||||
{
|
||||
/* the WM_DELETE_WINDOW is a request: we do not destroy
|
||||
* the window right away, as it might contain vital data;
|
||||
@ -261,13 +256,13 @@ handle_wm_protocols_event (ClutterBackendX11 *backend_x11,
|
||||
xevent->xclient.window);
|
||||
|
||||
set_user_time (backend_x11,
|
||||
&stage_xwindow,
|
||||
&window,
|
||||
xevent->xclient.data.l[1]);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
else if (atom == backend_x11->atom_NET_WM_PING &&
|
||||
xevent->xany.window == stage_xwindow)
|
||||
xevent->xany.window == window)
|
||||
{
|
||||
XClientMessageEvent xclient = xevent->xclient;
|
||||
|
||||
@ -289,7 +284,7 @@ handle_xembed_event (ClutterBackendX11 *backend_x11,
|
||||
{
|
||||
ClutterActor *stage;
|
||||
|
||||
stage = _clutter_backend_get_stage (CLUTTER_BACKEND (backend_x11));
|
||||
stage = clutter_stage_get_default ();
|
||||
|
||||
switch (xevent->xclient.data.l[1])
|
||||
{
|
||||
@ -340,9 +335,6 @@ event_translate (ClutterBackend *backend,
|
||||
Window xwindow, stage_xwindow;
|
||||
|
||||
backend_x11 = CLUTTER_BACKEND_X11 (backend);
|
||||
stage = CLUTTER_STAGE (_clutter_backend_get_stage (backend));
|
||||
stage_x11 = CLUTTER_STAGE_X11 (stage);
|
||||
stage_xwindow = clutter_x11_get_stage_window (stage);
|
||||
|
||||
xwindow = xevent->xany.window;
|
||||
|
||||
@ -378,9 +370,16 @@ event_translate (ClutterBackend *backend,
|
||||
* (the x11 filters might be getting events for other windows, so do not
|
||||
* mess them about.
|
||||
*/
|
||||
if (xwindow != stage_xwindow)
|
||||
stage = clutter_x11_get_stage_from_window (xwindow);
|
||||
|
||||
if (stage == NULL)
|
||||
return FALSE;
|
||||
|
||||
stage_x11 = CLUTTER_STAGE_X11 (stage);
|
||||
stage_xwindow = xwindow; /* clutter_x11_get_stage_window (stage); */
|
||||
|
||||
event->any.stage = stage;
|
||||
|
||||
res = TRUE;
|
||||
|
||||
switch (xevent->type)
|
||||
@ -514,7 +513,8 @@ event_translate (ClutterBackend *backend,
|
||||
/* FIXME: need to make stage an 'actor' so can que
|
||||
* a paint direct from there rather than hack here...
|
||||
*/
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
|
||||
CLUTTER_NOTE (MULTISTAGE, "expose for stage:%p, redrawing", stage);
|
||||
clutter_redraw (stage);
|
||||
res = FALSE;
|
||||
}
|
||||
break;
|
||||
@ -614,7 +614,7 @@ event_translate (ClutterBackend *backend,
|
||||
res = handle_xembed_event (backend_x11, xevent);
|
||||
else if (xevent->xclient.message_type == backend_x11->atom_WM_PROTOCOLS)
|
||||
{
|
||||
res = handle_wm_protocols_event (backend_x11, xevent);
|
||||
res = handle_wm_protocols_event (backend_x11, stage_xwindow, xevent);
|
||||
event->type = event->any.type = CLUTTER_DELETE;
|
||||
}
|
||||
break;
|
||||
|
@ -117,7 +117,7 @@ clutter_stage_x11_show (ClutterActor *actor)
|
||||
/* Fire off a redraw to avoid flicker on first map.
|
||||
* Appears not to work perfectly on intel drivers at least.
|
||||
*/
|
||||
clutter_redraw();
|
||||
clutter_redraw(CLUTTER_STAGE(actor));
|
||||
|
||||
XSync (stage_x11->xdpy, FALSE);
|
||||
XMapWindow (stage_x11->xdpy, stage_x11->xwin);
|
||||
@ -447,6 +447,39 @@ clutter_x11_get_stage_window (ClutterStage *stage)
|
||||
return CLUTTER_STAGE_X11 (stage)->xwin;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_x11_get_stage_from_window:
|
||||
* @win: an X Window ID
|
||||
*
|
||||
* Gets the stage for a particular X window.
|
||||
*
|
||||
* Return value: The stage or NULL if a stage does not exist for the window.
|
||||
*
|
||||
* Since: 0.8
|
||||
*/
|
||||
ClutterStage*
|
||||
clutter_x11_get_stage_from_window (Window win)
|
||||
{
|
||||
ClutterMainContext *context;
|
||||
ClutterStageManager *stage_manager;
|
||||
GSList *l;
|
||||
|
||||
context = clutter_context_get_default ();
|
||||
|
||||
stage_manager = context->stage_manager;
|
||||
|
||||
/* FIXME: use a hash here for performance resaon */
|
||||
for (l = stage_manager->stages; l; l = l->next)
|
||||
{
|
||||
ClutterStageX11 *stage_x11 = CLUTTER_STAGE_X11 (l->data);
|
||||
|
||||
if (stage_x11->xwin == win)
|
||||
return CLUTTER_STAGE(stage_x11);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_x11_get_stage_visual:
|
||||
* @stage: a #ClutterStage
|
||||
|
@ -101,6 +101,8 @@ ClutterX11FilterReturn clutter_x11_handle_event (XEvent *xevent);
|
||||
|
||||
void clutter_x11_disable_event_retrieval (void);
|
||||
|
||||
ClutterStage *clutter_x11_get_stage_from_window (Window win);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_X11_H__ */
|
||||
|
@ -7,7 +7,7 @@ noinst_PROGRAMS = test-textures test-events test-offscreen test-scale \
|
||||
test-threads test-timeline test-score test-script \
|
||||
test-model test-grab test-effects test-fullscreen \
|
||||
test-shader test-unproject test-viewport test-fbo \
|
||||
test-opacity
|
||||
test-opacity test-multistage
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/
|
||||
LDADD = $(top_builddir)/clutter/libclutter-@CLUTTER_FLAVOUR@-@CLUTTER_MAJORMINOR@.la
|
||||
@ -43,5 +43,6 @@ test_fullscreen_SOURCES = test-fullscreen.c
|
||||
test_viewport_SOURCES = test-viewport.c
|
||||
test_fbo_SOURCES = test-fbo.c
|
||||
test_opacity_SOURCES = test-opacity.c
|
||||
test_multistage_SOURCES = test-multistage.c
|
||||
|
||||
EXTRA_DIST = redhand.png test-script.json
|
||||
|
129
tests/test-multistage.c
Normal file
129
tests/test-multistage.c
Normal file
@ -0,0 +1,129 @@
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
static gint n_stages = 1;
|
||||
|
||||
static gboolean
|
||||
tex_button_cb (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer data)
|
||||
{
|
||||
clutter_actor_hide (actor);
|
||||
}
|
||||
|
||||
static void
|
||||
on_button_press (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer data)
|
||||
{
|
||||
ClutterActor *new_stage;
|
||||
ClutterActor *label, *tex;
|
||||
gint width, height;
|
||||
gchar *stage_label, *win_title;
|
||||
ClutterColor color = { 0xdd, 0x33, 0xdd, 0xff };
|
||||
ClutterColor white = { 0x99, 0x99, 0x99, 0xff };
|
||||
GdkPixbuf *pixb;
|
||||
ClutterTimeline *timeline;
|
||||
ClutterAlpha *alpha;
|
||||
ClutterBehaviour *r_behave;
|
||||
|
||||
new_stage = clutter_stage_create_new ();
|
||||
|
||||
/* FIXME: below should really be automatic */
|
||||
/* clutter_stage_ensure_cogl_context (CLUTTER_STAGE(new_stage)); */
|
||||
|
||||
clutter_stage_set_color (CLUTTER_STAGE (new_stage), &color);
|
||||
clutter_actor_set_size (new_stage, 320, 240);
|
||||
|
||||
pixb = gdk_pixbuf_new_from_file ("redhand.png", NULL);
|
||||
|
||||
if (!pixb)
|
||||
g_error("pixbuf load failed");
|
||||
|
||||
tex = clutter_texture_new_from_pixbuf (pixb);
|
||||
clutter_actor_set_reactive (tex, TRUE);
|
||||
g_signal_connect (tex, "button-press-event",
|
||||
G_CALLBACK (tex_button_cb), NULL);
|
||||
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (new_stage), tex);
|
||||
|
||||
stage_label = g_strdup_printf ("<b>Stage: %d</b>", ++n_stages);
|
||||
label = clutter_label_new_with_text ("Mono 12", stage_label);
|
||||
|
||||
clutter_label_set_color (CLUTTER_LABEL (label), &white);
|
||||
clutter_label_set_use_markup (CLUTTER_LABEL (label), TRUE);
|
||||
width = (clutter_actor_get_width (new_stage)
|
||||
- clutter_actor_get_width (label)) / 2;
|
||||
height = (clutter_actor_get_height (new_stage)
|
||||
- clutter_actor_get_height (label)) / 2;
|
||||
clutter_actor_set_position (label, width, height);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (new_stage), label);
|
||||
clutter_actor_show (label);
|
||||
g_free (stage_label);
|
||||
|
||||
/*
|
||||
g_signal_connect (new_stage, "button-press-event",
|
||||
G_CALLBACK (clutter_actor_destroy),
|
||||
NULL);
|
||||
*/
|
||||
|
||||
win_title = g_strdup_printf ("Stage:%p", new_stage);
|
||||
clutter_stage_set_title (CLUTTER_STAGE(new_stage), win_title);
|
||||
|
||||
timeline = clutter_timeline_new_for_duration (2000);
|
||||
g_object_set (timeline, "loop", TRUE, NULL);
|
||||
|
||||
alpha = clutter_alpha_new_full (timeline,
|
||||
CLUTTER_ALPHA_RAMP_INC,
|
||||
NULL, NULL);
|
||||
|
||||
r_behave = clutter_behaviour_rotate_new (alpha,
|
||||
CLUTTER_Y_AXIS,
|
||||
CLUTTER_ROTATE_CW,
|
||||
0.0, 360.0);
|
||||
|
||||
clutter_behaviour_rotate_set_center (CLUTTER_BEHAVIOUR_ROTATE (r_behave),
|
||||
clutter_actor_get_width (label)/2,
|
||||
0,
|
||||
0);
|
||||
|
||||
clutter_behaviour_apply (r_behave, label);
|
||||
clutter_timeline_start (timeline);
|
||||
|
||||
clutter_actor_show_all (new_stage);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage_default;
|
||||
ClutterActor *label;
|
||||
gint width, height;
|
||||
gchar *win_title;
|
||||
|
||||
clutter_init (&argc, &argv);
|
||||
|
||||
stage_default = clutter_stage_get_default ();
|
||||
g_signal_connect (stage_default, "button-press-event",
|
||||
G_CALLBACK (on_button_press),
|
||||
NULL);
|
||||
|
||||
label = clutter_label_new_with_text ("Mono 16", "Default stage");
|
||||
width = (clutter_actor_get_width (stage_default)
|
||||
- clutter_actor_get_width (label))
|
||||
/ 2;
|
||||
height = (clutter_actor_get_height (stage_default)
|
||||
- clutter_actor_get_height (label))
|
||||
/ 2;
|
||||
clutter_actor_set_position (label, width, height);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage_default), label);
|
||||
clutter_actor_show (label);
|
||||
|
||||
win_title = g_strdup_printf ("Stage:%p", stage_default);
|
||||
clutter_stage_set_title (CLUTTER_STAGE(stage_default), win_title);
|
||||
|
||||
clutter_actor_show (stage_default);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user